From 5877a214b6fd4c9dfad0b0349d9aaacbd9723ab3 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 9 Jul 2007 15:33:33 -0700 Subject: [PATCH] --- yaml --- r: 58717 b: refs/heads/master c: c59697e06058fc2361da8cefcfa3de85ac107582 h: refs/heads/master i: 58715: 702004b5dd591f6cc5510d65391fda1d108ff71b v: v3 --- [refs] | 2 +- trunk/Documentation/DocBook/kernel-api.tmpl | 11 - trunk/Documentation/block/barrier.txt | 16 +- trunk/Documentation/power_supply_class.txt | 167 - trunk/MAINTAINERS | 2 +- trunk/arch/mips/Kconfig | 198 +- trunk/arch/mips/Makefile | 84 +- trunk/arch/mips/au1000/common/gpio.c | 124 +- trunk/arch/mips/au1000/common/platform.c | 2 +- trunk/arch/mips/configs/atlas_defconfig | 4 + trunk/arch/mips/configs/bigsur_defconfig | 4 + trunk/arch/mips/configs/capcella_defconfig | 4 + trunk/arch/mips/configs/cobalt_defconfig | 502 +- trunk/arch/mips/configs/db1000_defconfig | 4 + trunk/arch/mips/configs/db1100_defconfig | 4 + trunk/arch/mips/configs/db1200_defconfig | 4 + trunk/arch/mips/configs/db1500_defconfig | 4 + trunk/arch/mips/configs/db1550_defconfig | 4 + trunk/arch/mips/configs/ddb5477_defconfig | 4 + trunk/arch/mips/configs/decstation_defconfig | 4 + trunk/arch/mips/configs/e55_defconfig | 4 + trunk/arch/mips/configs/emma2rh_defconfig | 4 + trunk/arch/mips/configs/ev64120_defconfig | 985 +++ trunk/arch/mips/configs/excite_defconfig | 4 + trunk/arch/mips/configs/fulong_defconfig | 1765 ----- trunk/arch/mips/configs/ip22_defconfig | 4 + trunk/arch/mips/configs/ip27_defconfig | 4 + trunk/arch/mips/configs/ip32_defconfig | 4 + trunk/arch/mips/configs/jazz_defconfig | 4 + trunk/arch/mips/configs/jmr3927_defconfig | 4 + trunk/arch/mips/configs/lasat200_defconfig | 1118 +++ trunk/arch/mips/configs/malta_defconfig | 4 + trunk/arch/mips/configs/mipssim_defconfig | 37 +- trunk/arch/mips/configs/mpc30x_defconfig | 4 + .../{msp71xx_defconfig => ocelot_3_defconfig} | 972 ++- trunk/arch/mips/configs/ocelot_c_defconfig | 982 +++ trunk/arch/mips/configs/ocelot_defconfig | 4 + trunk/arch/mips/configs/pb1100_defconfig | 4 + trunk/arch/mips/configs/pb1500_defconfig | 4 + trunk/arch/mips/configs/pb1550_defconfig | 4 + trunk/arch/mips/configs/pnx8550-jbs_defconfig | 4 + .../mips/configs/pnx8550-stb810_defconfig | 4 + trunk/arch/mips/configs/qemu_defconfig | 4 + trunk/arch/mips/configs/rbhma4200_defconfig | 4 + trunk/arch/mips/configs/rbhma4500_defconfig | 945 ++- trunk/arch/mips/configs/rm200_defconfig | 4 + .../arch/mips/configs/sb1250-swarm_defconfig | 4 + trunk/arch/mips/configs/sead_defconfig | 4 + trunk/arch/mips/configs/tb0219_defconfig | 4 + trunk/arch/mips/configs/tb0226_defconfig | 4 + trunk/arch/mips/configs/tb0287_defconfig | 4 + trunk/arch/mips/configs/workpad_defconfig | 4 + trunk/arch/mips/configs/wrppmc_defconfig | 4 + trunk/arch/mips/configs/yosemite_defconfig | 4 + trunk/arch/mips/ddb5xxx/ddb5477/Makefile | 3 +- .../mips/ddb5xxx/ddb5477/ddb5477-platform.c | 49 - trunk/arch/mips/dec/prom/console.c | 32 +- trunk/arch/mips/dec/prom/init.c | 5 +- trunk/arch/mips/dec/reset.c | 10 +- trunk/arch/mips/defconfig | 4 + trunk/arch/mips/gt64120/ev64120/Kconfig | 3 + trunk/arch/mips/gt64120/ev64120/Makefile | 9 + trunk/arch/mips/gt64120/ev64120/irq.c | 116 + trunk/arch/mips/gt64120/ev64120/promcon.c | 48 + trunk/arch/mips/gt64120/ev64120/reset.c | 45 + trunk/arch/mips/gt64120/ev64120/serialGT.c | 212 + trunk/arch/mips/gt64120/ev64120/setup.c | 99 + .../arch/mips/gt64120/momenco_ocelot/Makefile | 2 +- .../gt64120/momenco_ocelot/ocelot-platform.c | 46 - trunk/arch/mips/gt64120/wrppmc/setup.c | 4 +- trunk/arch/mips/jazz/Makefile | 2 +- trunk/arch/mips/jazz/jazz-platform.c | 60 - trunk/arch/mips/kernel/8250-platform.c | 47 - trunk/arch/mips/kernel/Makefile | 17 +- trunk/arch/mips/kernel/cpu-probe.c | 30 - trunk/arch/mips/kernel/head.S | 10 +- trunk/arch/mips/kernel/irq-mv6434x.c | 111 + trunk/arch/mips/kernel/mips-mt-fpaff.c | 176 - trunk/arch/mips/kernel/mips-mt.c | 205 +- trunk/arch/mips/kernel/proc.c | 2 +- trunk/arch/mips/kernel/process.c | 4 +- trunk/arch/mips/kernel/setup.c | 16 - trunk/arch/mips/kernel/smp.c | 2 +- trunk/arch/mips/kernel/smtc.c | 2 +- trunk/arch/mips/kernel/syscall.c | 5 +- trunk/arch/mips/kernel/traps.c | 77 +- trunk/arch/mips/kernel/unaligned.c | 41 +- trunk/arch/mips/lasat/Kconfig | 15 + trunk/arch/mips/lasat/Makefile | 14 + trunk/arch/mips/lasat/at93c.c | 148 + trunk/arch/mips/lasat/at93c.h | 18 + trunk/arch/mips/lasat/ds1603.c | 183 + trunk/arch/mips/lasat/ds1603.h | 33 + trunk/arch/mips/lasat/image/Makefile | 53 + trunk/arch/mips/lasat/image/head.S | 31 + trunk/arch/mips/lasat/image/romscript.normal | 23 + trunk/arch/mips/lasat/interrupt.c | 130 + trunk/arch/mips/lasat/lasat_board.c | 279 + trunk/arch/mips/lasat/lasat_models.h | 63 + trunk/arch/mips/lasat/picvue.c | 240 + trunk/arch/mips/lasat/picvue.h | 48 + trunk/arch/mips/lasat/picvue_proc.c | 186 + trunk/arch/mips/lasat/prom.c | 117 + trunk/arch/mips/lasat/prom.h | 5 + trunk/arch/mips/lasat/reset.c | 69 + trunk/arch/mips/lasat/setup.c | 182 + trunk/arch/mips/lasat/sysctl.c | 441 ++ trunk/arch/mips/lasat/sysctl.h | 24 + trunk/arch/mips/lemote/lm2e/Makefile | 7 - trunk/arch/mips/lemote/lm2e/bonito-irq.c | 74 - trunk/arch/mips/lemote/lm2e/dbg_io.c | 146 - trunk/arch/mips/lemote/lm2e/irq.c | 145 - trunk/arch/mips/lemote/lm2e/mem.c | 23 - trunk/arch/mips/lemote/lm2e/pci.c | 93 - trunk/arch/mips/lemote/lm2e/prom.c | 104 - trunk/arch/mips/lemote/lm2e/reset.c | 41 - trunk/arch/mips/lemote/lm2e/setup.c | 134 - trunk/arch/mips/lib-32/Makefile | 23 + trunk/arch/mips/lib-32/dump_tlb.c | 242 + trunk/arch/mips/lib-32/r3k_dump_tlb.c | 182 + trunk/arch/mips/lib-32/watch.S | 60 + trunk/arch/mips/lib-64/Makefile | 23 + trunk/arch/mips/lib-64/dump_tlb.c | 216 + trunk/arch/mips/lib-64/watch.S | 57 + trunk/arch/mips/lib/Makefile | 19 - trunk/arch/mips/lib/dump_tlb.c | 100 - trunk/arch/mips/lib/r3k_dump_tlb.c | 62 - trunk/arch/mips/math-emu/cp1emu.c | 34 - trunk/arch/mips/mips-boards/malta/Makefile | 3 +- .../mips/mips-boards/malta/malta_platform.c | 65 - .../{mipssim => mips-boards/sim}/Makefile | 0 .../sim}/sim_cmdline.c | 0 .../sim}/sim_console.c | 2 +- .../{mipssim => mips-boards/sim}/sim_mem.c | 2 +- .../sim}/sim_platform.c | 0 .../{mipssim => mips-boards/sim}/sim_setup.c | 8 +- .../{mipssim => mips-boards/sim}/sim_smp.c | 18 +- .../{mipssim => mips-boards/sim}/sim_time.c | 30 +- trunk/arch/mips/mipssim/sim_int.c | 88 - trunk/arch/mips/mm/Makefile | 1 - trunk/arch/mips/mm/c-r4k.c | 54 - trunk/arch/mips/mm/c-sb1.c | 2 +- trunk/arch/mips/mm/cache.c | 10 - trunk/arch/mips/mm/tlb-r4k.c | 23 +- trunk/arch/mips/mm/tlbex.c | 8 +- trunk/arch/mips/momentum/ocelot_3/Makefile | 8 + trunk/arch/mips/momentum/ocelot_3/irq.c | 109 + .../ocelot_3/ocelot_3_fpga.h} | 57 +- trunk/arch/mips/momentum/ocelot_3/platform.c | 208 + trunk/arch/mips/momentum/ocelot_3/prom.c | 189 + trunk/arch/mips/momentum/ocelot_3/reset.c | 59 + trunk/arch/mips/momentum/ocelot_3/setup.c | 398 ++ trunk/arch/mips/momentum/ocelot_c/Makefile | 8 + trunk/arch/mips/momentum/ocelot_c/cpci-irq.c | 100 + trunk/arch/mips/momentum/ocelot_c/dbg_io.c | 121 + trunk/arch/mips/momentum/ocelot_c/irq.c | 107 + .../ocelot_c/ocelot_c_fpga.h} | 53 +- trunk/arch/mips/momentum/ocelot_c/platform.c | 183 + trunk/arch/mips/momentum/ocelot_c/prom.c | 183 + trunk/arch/mips/momentum/ocelot_c/reset.c | 58 + trunk/arch/mips/momentum/ocelot_c/setup.c | 362 + trunk/arch/mips/momentum/ocelot_c/uart-irq.c | 91 + trunk/arch/mips/pci/Makefile | 10 +- trunk/arch/mips/pci/fixup-atlas.c | 2 +- trunk/arch/mips/pci/fixup-au1000.c | 2 +- trunk/arch/mips/pci/fixup-capcella.c | 2 +- trunk/arch/mips/pci/fixup-cobalt.c | 2 +- trunk/arch/mips/pci/fixup-emma2rh.c | 2 +- trunk/arch/mips/pci/fixup-excite.c | 2 +- trunk/arch/mips/pci/fixup-ip32.c | 2 +- trunk/arch/mips/pci/fixup-jmr3927.c | 2 +- trunk/arch/mips/pci/fixup-lm2e.c | 242 - trunk/arch/mips/pci/fixup-malta.c | 2 +- trunk/arch/mips/pci/fixup-mpc30x.c | 2 +- trunk/arch/mips/pci/fixup-ocelot-c.c | 41 + trunk/arch/mips/pci/fixup-ocelot3.c | 41 + trunk/arch/mips/pci/fixup-pmcmsp.c | 216 - trunk/arch/mips/pci/fixup-pnx8550.c | 2 +- trunk/arch/mips/pci/fixup-rbtx4927.c | 2 +- trunk/arch/mips/pci/fixup-sni.c | 2 +- trunk/arch/mips/pci/fixup-tb0219.c | 2 +- trunk/arch/mips/pci/fixup-tb0226.c | 2 +- trunk/arch/mips/pci/fixup-tb0287.c | 2 +- trunk/arch/mips/pci/fixup-tx4938.c | 2 +- trunk/arch/mips/pci/fixup-vr4133.c | 2 +- trunk/arch/mips/pci/fixup-wrppmc.c | 2 +- trunk/arch/mips/pci/fixup-yosemite.c | 2 +- trunk/arch/mips/pci/ops-bonito64.c | 88 +- trunk/arch/mips/pci/ops-marvell.c | 93 + trunk/arch/mips/pci/ops-nile4.c | 147 + trunk/arch/mips/pci/ops-pmcmsp.c | 994 --- trunk/arch/mips/pci/ops-tx4938.c | 80 +- trunk/arch/mips/pci/pci-bcm1480.c | 3 +- trunk/arch/mips/pci/pci-ddb5477.c | 2 +- trunk/arch/mips/pci/pci-ev64120.c | 22 + trunk/arch/mips/pci/pci-ip27.c | 2 +- trunk/arch/mips/pci/pci-lasat.c | 91 + trunk/arch/mips/pci/pci-ocelot-c.c | 145 + trunk/arch/mips/pci/pci-sb1250.c | 2 +- .../mips/philips/pnx8550/common/platform.c | 2 +- trunk/arch/mips/philips/pnx8550/common/proc.c | 30 +- trunk/arch/mips/pmc-sierra/Kconfig | 46 - trunk/arch/mips/pmc-sierra/msp71xx/Makefile | 11 - .../mips/pmc-sierra/msp71xx/msp_hwbutton.c | 179 - trunk/arch/mips/pmc-sierra/msp71xx/msp_irq.c | 124 - .../mips/pmc-sierra/msp71xx/msp_irq_cic.c | 134 - .../mips/pmc-sierra/msp71xx/msp_irq_slp.c | 109 - trunk/arch/mips/pmc-sierra/msp71xx/msp_prom.c | 566 -- .../arch/mips/pmc-sierra/msp71xx/msp_setup.c | 256 - trunk/arch/mips/pmc-sierra/msp71xx/msp_time.c | 94 - trunk/arch/mips/pmc-sierra/msp71xx/msp_usb.c | 150 - trunk/arch/mips/pmc-sierra/yosemite/smp.c | 2 +- trunk/arch/mips/sgi-ip22/ip22-reset.c | 6 +- trunk/arch/mips/sgi-ip27/ip27-berr.c | 1 + trunk/arch/mips/sgi-ip32/ip32-platform.c | 52 - trunk/arch/mips/sgi-ip32/ip32-setup.c | 36 + trunk/arch/mips/sibyte/cfe/setup.c | 6 +- trunk/arch/mips/sni/Makefile | 2 +- trunk/arch/mips/sni/a20r.c | 31 +- trunk/arch/mips/sni/ds1216.c | 81 + trunk/arch/mips/sni/pcimt.c | 26 +- trunk/arch/mips/sni/pcit.c | 26 +- trunk/arch/mips/sni/rm200.c | 32 +- trunk/arch/mips/sni/sniprom.c | 5 +- trunk/arch/mips/tx4938/common/Makefile | 2 +- trunk/arch/mips/tx4938/common/rtc_rx5c348.c | 192 + .../mips/tx4938/toshiba_rbtx4938/Makefile | 2 +- trunk/arch/mips/tx4938/toshiba_rbtx4938/irq.c | 6 + .../arch/mips/tx4938/toshiba_rbtx4938/setup.c | 306 +- .../mips/tx4938/toshiba_rbtx4938/spi_eeprom.c | 261 +- .../mips/tx4938/toshiba_rbtx4938/spi_txx9.c | 164 + trunk/arch/s390/crypto/crypt_s390.h | 2 +- trunk/arch/s390/kernel/early.c | 45 +- trunk/arch/s390/kernel/entry.S | 7 +- trunk/arch/s390/kernel/entry64.S | 7 +- trunk/arch/s390/kernel/ipl.c | 17 +- trunk/arch/s390/kernel/process.c | 6 +- trunk/arch/s390/kernel/smp.c | 63 +- trunk/arch/s390/kernel/time.c | 4 +- trunk/arch/s390/kernel/vtime.c | 4 +- trunk/arch/s390/lib/Makefile | 4 +- trunk/block/Kconfig | 4 +- trunk/block/cfq-iosched.c | 39 +- trunk/block/elevator.c | 13 +- trunk/block/ll_rw_blk.c | 13 +- trunk/drivers/Kconfig | 4 +- trunk/drivers/Makefile | 1 - trunk/drivers/acorn/block/fd1772.c | 2 +- trunk/drivers/acorn/block/mfmhd.c | 13 +- trunk/drivers/ata/ahci.c | 159 +- trunk/drivers/ata/ata_generic.c | 4 +- trunk/drivers/ata/ata_piix.c | 35 +- trunk/drivers/ata/libata-acpi.c | 914 +-- trunk/drivers/ata/libata-core.c | 105 +- trunk/drivers/ata/libata-eh.c | 11 +- trunk/drivers/ata/libata-scsi.c | 2 +- trunk/drivers/ata/libata.h | 18 +- trunk/drivers/ata/pata_ali.c | 22 +- trunk/drivers/ata/pata_amd.c | 38 +- trunk/drivers/ata/pata_artop.c | 6 +- trunk/drivers/ata/pata_atiixp.c | 3 +- trunk/drivers/ata/pata_cmd640.c | 2 +- trunk/drivers/ata/pata_cmd64x.c | 12 +- trunk/drivers/ata/pata_cs5520.c | 4 +- trunk/drivers/ata/pata_cs5530.c | 8 +- trunk/drivers/ata/pata_cs5535.c | 4 +- trunk/drivers/ata/pata_cypress.c | 2 +- trunk/drivers/ata/pata_efar.c | 2 +- trunk/drivers/ata/pata_hpt366.c | 4 +- trunk/drivers/ata/pata_hpt37x.c | 20 +- trunk/drivers/ata/pata_hpt3x2n.c | 4 +- trunk/drivers/ata/pata_hpt3x3.c | 2 +- trunk/drivers/ata/pata_icside.c | 2 +- trunk/drivers/ata/pata_it8213.c | 4 +- trunk/drivers/ata/pata_it821x.c | 6 +- trunk/drivers/ata/pata_ixp4xx_cf.c | 76 +- trunk/drivers/ata/pata_jmicron.c | 4 +- trunk/drivers/ata/pata_marvell.c | 8 +- trunk/drivers/ata/pata_netcell.c | 4 +- trunk/drivers/ata/pata_ns87410.c | 2 +- trunk/drivers/ata/pata_oldpiix.c | 2 +- trunk/drivers/ata/pata_opti.c | 2 +- trunk/drivers/ata/pata_optidma.c | 4 +- trunk/drivers/ata/pata_pdc202xx_old.c | 6 +- trunk/drivers/ata/pata_platform.c | 6 +- trunk/drivers/ata/pata_radisys.c | 2 +- trunk/drivers/ata/pata_rz1000.c | 2 +- trunk/drivers/ata/pata_sc1200.c | 6 +- trunk/drivers/ata/pata_serverworks.c | 12 +- trunk/drivers/ata/pata_sil680.c | 21 +- trunk/drivers/ata/pata_sis.c | 14 +- trunk/drivers/ata/pata_sl82c105.c | 4 +- trunk/drivers/ata/pata_triflex.c | 2 +- trunk/drivers/ata/pata_via.c | 8 +- trunk/drivers/ata/pdc_adma.c | 20 +- trunk/drivers/ata/sata_inic162x.c | 6 +- trunk/drivers/ata/sata_mv.c | 31 +- trunk/drivers/ata/sata_promise.c | 78 +- trunk/drivers/ata/sata_qstor.c | 2 +- trunk/drivers/ata/sata_sil.c | 13 +- trunk/drivers/ata/sata_sil24.c | 8 +- trunk/drivers/ata/sata_sis.c | 2 +- trunk/drivers/ata/sata_svw.c | 15 +- trunk/drivers/ata/sata_sx4.c | 168 +- trunk/drivers/ata/sata_uli.c | 2 +- trunk/drivers/ata/sata_via.c | 10 +- trunk/drivers/ata/sata_vsc.c | 2 +- trunk/drivers/block/Kconfig | 44 +- trunk/drivers/block/Makefile | 1 + trunk/drivers/block/acsi.c | 1825 +++++ trunk/drivers/block/amiflop.c | 2 +- trunk/drivers/block/cciss.c | 2 - trunk/drivers/block/loop.c | 64 +- trunk/drivers/block/nbd.c | 2 +- trunk/drivers/cdrom/Kconfig | 213 + trunk/drivers/cdrom/Makefile | 10 + trunk/drivers/cdrom/aztcd.c | 2492 +++++++ trunk/drivers/cdrom/aztcd.h | 162 + trunk/drivers/cdrom/cdrom.c | 216 +- trunk/drivers/cdrom/cdu31a.c | 3251 +++++++++ trunk/drivers/cdrom/cdu31a.h | 411 ++ trunk/drivers/cdrom/cm206.c | 1594 +++++ trunk/drivers/cdrom/cm206.h | 171 + trunk/drivers/cdrom/gscd.c | 1029 +++ trunk/drivers/cdrom/gscd.h | 108 + trunk/drivers/cdrom/isp16.c | 374 ++ trunk/drivers/cdrom/isp16.h | 72 + trunk/drivers/cdrom/mcdx.c | 1943 ++++++ trunk/drivers/cdrom/mcdx.h | 185 + trunk/drivers/cdrom/optcd.c | 2105 ++++++ trunk/drivers/cdrom/optcd.h | 52 + trunk/drivers/cdrom/sbpcd.c | 5966 +++++++++++++++++ trunk/drivers/cdrom/sbpcd.h | 839 +++ trunk/drivers/cdrom/sjcd.c | 1815 +++++ trunk/drivers/cdrom/sjcd.h | 181 + trunk/drivers/cdrom/sonycd535.c | 1689 +++++ trunk/drivers/cdrom/sonycd535.h | 183 + trunk/drivers/char/keyboard.c | 4 +- trunk/drivers/char/mem.c | 9 +- trunk/drivers/ide/legacy/hd.c | 3 +- trunk/drivers/input/evdev.c | 84 +- trunk/drivers/input/input.c | 136 +- trunk/drivers/input/joydev.c | 84 +- trunk/drivers/input/joystick/Kconfig | 7 - trunk/drivers/input/joystick/grip_mp.c | 4 +- trunk/drivers/input/joystick/xpad.c | 281 +- trunk/drivers/input/keyboard/atkbd.c | 4 +- .../drivers/input/keyboard/pxa27x_keyboard.c | 2 +- trunk/drivers/input/misc/Kconfig | 6 +- trunk/drivers/input/misc/wistron_btns.c | 359 +- trunk/drivers/input/mouse/Kconfig | 16 - trunk/drivers/input/mouse/Makefile | 1 - trunk/drivers/input/mouse/gpio_mouse.c | 196 - trunk/drivers/input/mouse/psmouse-base.c | 29 - trunk/drivers/input/mouse/psmouse.h | 1 - trunk/drivers/input/mousedev.c | 242 +- trunk/drivers/input/serio/serio_raw.c | 2 +- trunk/drivers/input/tablet/aiptek.c | 991 ++- trunk/drivers/input/tablet/wacom.h | 8 +- trunk/drivers/input/tablet/wacom_sys.c | 6 - trunk/drivers/input/tablet/wacom_wac.c | 47 +- trunk/drivers/input/tablet/wacom_wac.h | 1 - trunk/drivers/input/touchscreen/Kconfig | 6 - .../input/touchscreen/usbtouchscreen.c | 33 - trunk/drivers/input/tsdev.c | 90 +- trunk/drivers/mtd/devices/docprobe.c | 2 +- trunk/drivers/mtd/maps/Kconfig | 6 + trunk/drivers/mtd/maps/Makefile | 1 + trunk/drivers/mtd/maps/lasat.c | 103 + trunk/drivers/mtd/nand/diskonchip.c | 2 +- trunk/drivers/net/Kconfig | 2 +- trunk/drivers/net/sky2.c | 9 +- trunk/drivers/net/tc35815.c | 50 +- trunk/drivers/power/Kconfig | 51 - trunk/drivers/power/Makefile | 22 - trunk/drivers/power/apm_power.c | 243 - trunk/drivers/power/ds2760_battery.c | 470 -- trunk/drivers/power/olpc_battery.c | 352 - trunk/drivers/power/pda_power.c | 261 - trunk/drivers/power/pmu_battery.c | 215 - trunk/drivers/power/power_supply.h | 42 - trunk/drivers/power/power_supply_core.c | 168 - trunk/drivers/power/power_supply_leds.c | 176 - trunk/drivers/power/power_supply_sysfs.c | 299 - trunk/drivers/s390/block/dasd_proc.c | 4 - trunk/drivers/s390/char/sclp.h | 12 - trunk/drivers/s390/char/sclp_chp.c | 4 - trunk/drivers/s390/char/sclp_info.c | 117 +- trunk/drivers/s390/char/vmcp.c | 13 +- trunk/drivers/s390/char/vmlogrdr.c | 4 +- trunk/drivers/s390/char/zcore.c | 2 +- trunk/drivers/s390/cio/device_id.c | 22 +- trunk/drivers/s390/crypto/ap_bus.c | 98 +- trunk/drivers/s390/crypto/ap_bus.h | 11 - trunk/drivers/s390/crypto/zcrypt_cex2a.c | 27 +- trunk/drivers/s390/crypto/zcrypt_pcica.c | 27 +- trunk/drivers/s390/crypto/zcrypt_pcicc.c | 27 +- trunk/drivers/s390/crypto/zcrypt_pcixcc.c | 40 +- trunk/drivers/tc/zs.c | 6 +- trunk/drivers/w1/slaves/Kconfig | 13 - trunk/drivers/w1/slaves/Makefile | 1 - trunk/drivers/w1/slaves/w1_ds2760.c | 213 - trunk/drivers/w1/slaves/w1_ds2760.h | 50 - trunk/drivers/w1/w1_family.h | 1 - trunk/fs/adfs/file.c | 2 +- trunk/fs/affs/file.c | 2 +- trunk/fs/afs/file.c | 2 +- trunk/fs/bad_inode.c | 7 + trunk/fs/bfs/file.c | 2 +- trunk/fs/bio.c | 2 + trunk/fs/block_dev.c | 1 + trunk/fs/cifs/cifsfs.c | 8 +- trunk/fs/coda/file.c | 11 +- trunk/fs/dlm/Makefile | 1 - trunk/fs/dlm/config.c | 25 +- trunk/fs/dlm/config.h | 1 - trunk/fs/dlm/debug_fs.c | 186 +- trunk/fs/dlm/dlm_internal.h | 17 - trunk/fs/dlm/lock.c | 470 +- trunk/fs/dlm/lock.h | 13 +- trunk/fs/dlm/lockspace.c | 86 +- trunk/fs/dlm/lowcomms.c | 23 +- trunk/fs/dlm/main.c | 11 +- trunk/fs/dlm/member.c | 11 +- trunk/fs/dlm/netlink.c | 153 - trunk/fs/dlm/rcom.c | 13 +- trunk/fs/dlm/recoverd.c | 4 +- trunk/fs/dlm/user.c | 129 +- trunk/fs/ecryptfs/file.c | 15 +- trunk/fs/ext2/file.c | 2 + trunk/fs/ext3/file.c | 1 + trunk/fs/ext4/file.c | 1 + trunk/fs/fat/file.c | 2 +- trunk/fs/fuse/file.c | 4 +- trunk/fs/gfs2/Makefile | 2 +- trunk/fs/gfs2/bmap.c | 23 +- trunk/fs/gfs2/daemon.c | 11 - trunk/fs/gfs2/dir.c | 69 +- trunk/fs/gfs2/dir.h | 9 +- trunk/fs/gfs2/eattr.c | 14 +- trunk/fs/gfs2/glock.c | 123 +- trunk/fs/gfs2/glock.h | 1 - trunk/fs/gfs2/glops.c | 2 +- trunk/fs/gfs2/incore.h | 81 +- trunk/fs/gfs2/inode.c | 288 +- trunk/fs/gfs2/inode.h | 30 +- trunk/fs/gfs2/locking/dlm/lock.c | 11 +- trunk/fs/gfs2/locking/dlm/lock_dlm.h | 2 +- trunk/fs/gfs2/locking/dlm/mount.c | 2 +- trunk/fs/gfs2/locking/dlm/plock.c | 8 +- trunk/fs/gfs2/locking/dlm/thread.c | 11 +- trunk/fs/gfs2/log.c | 129 +- trunk/fs/gfs2/lops.c | 49 +- trunk/fs/gfs2/lops.h | 23 - trunk/fs/gfs2/meta_io.c | 8 +- trunk/fs/gfs2/meta_io.h | 2 +- trunk/fs/gfs2/mount.c | 25 +- trunk/fs/gfs2/ondisk.c | 251 + trunk/fs/gfs2/ops_address.c | 69 +- trunk/fs/gfs2/ops_address.h | 2 +- trunk/fs/gfs2/ops_dentry.c | 24 +- trunk/fs/gfs2/ops_export.c | 65 +- trunk/fs/gfs2/ops_export.h | 22 + trunk/fs/gfs2/ops_file.c | 5 +- trunk/fs/gfs2/ops_fstype.c | 33 +- trunk/fs/gfs2/ops_fstype.h | 1 - trunk/fs/gfs2/ops_inode.c | 30 +- trunk/fs/gfs2/ops_super.c | 8 +- trunk/fs/gfs2/ops_vm.c | 2 +- trunk/fs/gfs2/quota.c | 57 +- trunk/fs/gfs2/recovery.c | 22 +- trunk/fs/gfs2/rgrp.c | 377 +- trunk/fs/gfs2/rgrp.h | 1 - trunk/fs/gfs2/super.c | 79 +- trunk/fs/gfs2/super.h | 2 +- trunk/fs/gfs2/util.c | 6 +- trunk/fs/hfs/inode.c | 2 +- trunk/fs/hfsplus/inode.c | 2 +- trunk/fs/hostfs/hostfs_kern.c | 2 +- trunk/fs/hpfs/file.c | 2 +- trunk/fs/jffs2/file.c | 2 +- trunk/fs/jfs/file.c | 1 + trunk/fs/minix/file.c | 2 +- trunk/fs/nfs/file.c | 15 +- trunk/fs/nfsd/vfs.c | 47 +- trunk/fs/ntfs/file.c | 2 +- trunk/fs/ocfs2/file.c | 18 +- trunk/fs/partitions/ibm.c | 167 +- trunk/fs/pipe.c | 70 +- trunk/fs/qnx4/file.c | 2 +- trunk/fs/ramfs/file-mmu.c | 2 +- trunk/fs/ramfs/file-nommu.c | 2 +- trunk/fs/read_write.c | 20 +- trunk/fs/reiserfs/file.c | 1 + trunk/fs/smbfs/file.c | 9 +- trunk/fs/splice.c | 413 +- trunk/fs/sysv/file.c | 2 +- trunk/fs/udf/file.c | 2 +- trunk/fs/ufs/file.c | 2 +- trunk/fs/xfs/linux-2.6/xfs_file.c | 26 + trunk/fs/xfs/linux-2.6/xfs_linux.h | 1 + trunk/fs/xfs/linux-2.6/xfs_lrw.c | 44 + trunk/fs/xfs/linux-2.6/xfs_lrw.h | 3 + trunk/fs/xfs/linux-2.6/xfs_vnode.h | 6 + trunk/fs/xfs/xfs_vnodeops.c | 3 + trunk/include/asm-mips/addrspace.h | 29 +- trunk/include/asm-mips/bootinfo.h | 36 +- trunk/include/asm-mips/cacheops.h | 4 - trunk/include/asm-mips/cpu-features.h | 4 - trunk/include/asm-mips/cpu.h | 10 +- trunk/include/asm-mips/div64.h | 9 +- trunk/include/asm-mips/gpio.h | 6 - trunk/include/asm-mips/io.h | 8 - trunk/include/asm-mips/lasat/ds1603.h | 18 + trunk/include/asm-mips/lasat/eeprom.h | 17 + trunk/include/asm-mips/lasat/head.h | 22 + trunk/include/asm-mips/lasat/lasat.h | 253 + trunk/include/asm-mips/lasat/lasatint.h | 12 + trunk/include/asm-mips/lasat/picvue.h | 15 + trunk/include/asm-mips/lasat/serial.h | 13 + .../asm-mips/mach-au1x00/au1xxx_gpio.h | 20 + trunk/include/asm-mips/mach-au1x00/gpio.h | 69 - trunk/include/asm-mips/mach-au1x00/ioremap.h | 11 - trunk/include/asm-mips/mach-cobalt/cobalt.h | 5 + .../asm-mips/mach-ev64120/mach-gt64120.h | 62 + trunk/include/asm-mips/mach-generic/gpio.h | 15 - trunk/include/asm-mips/mach-generic/ioremap.h | 11 - trunk/include/asm-mips/mach-generic/spaces.h | 64 +- trunk/include/asm-mips/mach-ip22/spaces.h | 33 +- trunk/include/asm-mips/mach-ip27/spaces.h | 9 +- trunk/include/asm-mips/mach-ip32/spaces.h | 36 + trunk/include/asm-mips/mach-jmr3927/ioremap.h | 38 - .../asm-mips/mach-lasat/mach-gt64120.h | 27 + .../asm-mips/mach-lemote/dma-coherence.h | 42 - .../asm-mips/mach-lemote/mc146818rtc.h | 36 - .../asm-mips/mach-mips/kernel-entry-init.h | 52 - .../mach-ocelot3/cpu-feature-overrides.h | 48 + .../cpu-feature-overrides.h | 0 trunk/include/asm-mips/mach-tx49xx/ioremap.h | 42 - trunk/include/asm-mips/mips-boards/bonito64.h | 7 +- trunk/include/asm-mips/mipsregs.h | 39 +- trunk/include/asm-mips/module.h | 2 - trunk/include/asm-mips/nile4.h | 310 + trunk/include/asm-mips/page.h | 21 +- trunk/include/asm-mips/pci.h | 2 +- .../asm-mips/pmc-sierra/msp71xx/msp_cic_int.h | 151 - .../asm-mips/pmc-sierra/msp71xx/msp_int.h | 43 - .../asm-mips/pmc-sierra/msp71xx/msp_pci.h | 205 - .../asm-mips/pmc-sierra/msp71xx/msp_prom.h | 176 - .../asm-mips/pmc-sierra/msp71xx/msp_regops.h | 236 - .../asm-mips/pmc-sierra/msp71xx/msp_regs.h | 667 -- .../asm-mips/pmc-sierra/msp71xx/msp_slp_int.h | 141 - trunk/include/asm-mips/processor.h | 92 +- trunk/include/asm-mips/serial.h | 155 + trunk/include/asm-mips/smp.h | 7 + trunk/include/asm-mips/sni.h | 3 + trunk/include/asm-mips/system.h | 14 +- trunk/include/asm-mips/tx4938/rbtx4938.h | 6 + trunk/include/asm-mips/tx4938/spi.h | 56 +- trunk/include/asm-mips/war.h | 25 +- trunk/include/asm-mips/watch.h | 35 + trunk/include/asm-s390/atomic.h | 4 +- trunk/include/asm-s390/cmb.h | 1 + trunk/include/asm-s390/processor.h | 4 +- trunk/include/asm-s390/sclp.h | 47 +- trunk/include/asm-s390/sfp-machine.h | 6 +- trunk/include/asm-s390/sfp-util.h | 11 - trunk/include/linux/Kbuild | 1 - trunk/include/linux/ata.h | 1 - trunk/include/linux/blkdev.h | 5 + trunk/include/linux/dlm.h | 14 +- trunk/include/linux/dlm_device.h | 22 +- trunk/include/linux/dlm_netlink.h | 56 - trunk/include/linux/fs.h | 7 +- trunk/include/linux/gfs2_ondisk.h | 142 +- trunk/include/linux/gpio_mouse.h | 61 - trunk/include/linux/input.h | 20 +- trunk/include/linux/ioprio.h | 6 +- trunk/include/linux/libata.h | 30 +- trunk/include/linux/mv643xx.h | 4 + trunk/include/linux/pata_platform.h | 5 - trunk/include/linux/pda_power.h | 31 - trunk/include/linux/pipe_fs_i.h | 117 +- trunk/include/linux/power_supply.h | 180 - trunk/include/linux/splice.h | 73 - trunk/include/linux/sunrpc/svc.h | 2 +- trunk/include/linux/usb.h | 16 - trunk/init/Kconfig | 2 + trunk/kernel/relay.c | 205 +- trunk/mm/filemap.c | 20 + trunk/mm/filemap_xip.c | 22 + trunk/mm/shmem.c | 42 +- trunk/net/sunrpc/auth_gss/svcauth_gss.c | 2 +- trunk/net/sunrpc/svc.c | 2 +- trunk/sound/ppc/beep.c | 10 +- 595 files changed, 44980 insertions(+), 20164 deletions(-) delete mode 100644 trunk/Documentation/power_supply_class.txt create mode 100644 trunk/arch/mips/configs/ev64120_defconfig delete mode 100644 trunk/arch/mips/configs/fulong_defconfig create mode 100644 trunk/arch/mips/configs/lasat200_defconfig rename trunk/arch/mips/configs/{msp71xx_defconfig => ocelot_3_defconfig} (51%) create mode 100644 trunk/arch/mips/configs/ocelot_c_defconfig delete mode 100644 trunk/arch/mips/ddb5xxx/ddb5477/ddb5477-platform.c create mode 100644 trunk/arch/mips/gt64120/ev64120/Kconfig create mode 100644 trunk/arch/mips/gt64120/ev64120/Makefile create mode 100644 trunk/arch/mips/gt64120/ev64120/irq.c create mode 100644 trunk/arch/mips/gt64120/ev64120/promcon.c create mode 100644 trunk/arch/mips/gt64120/ev64120/reset.c create mode 100644 trunk/arch/mips/gt64120/ev64120/serialGT.c create mode 100644 trunk/arch/mips/gt64120/ev64120/setup.c delete mode 100644 trunk/arch/mips/gt64120/momenco_ocelot/ocelot-platform.c delete mode 100644 trunk/arch/mips/jazz/jazz-platform.c delete mode 100644 trunk/arch/mips/kernel/8250-platform.c create mode 100644 trunk/arch/mips/kernel/irq-mv6434x.c delete mode 100644 trunk/arch/mips/kernel/mips-mt-fpaff.c create mode 100644 trunk/arch/mips/lasat/Kconfig create mode 100644 trunk/arch/mips/lasat/Makefile create mode 100644 trunk/arch/mips/lasat/at93c.c create mode 100644 trunk/arch/mips/lasat/at93c.h create mode 100644 trunk/arch/mips/lasat/ds1603.c create mode 100644 trunk/arch/mips/lasat/ds1603.h create mode 100644 trunk/arch/mips/lasat/image/Makefile create mode 100644 trunk/arch/mips/lasat/image/head.S create mode 100644 trunk/arch/mips/lasat/image/romscript.normal create mode 100644 trunk/arch/mips/lasat/interrupt.c create mode 100644 trunk/arch/mips/lasat/lasat_board.c create mode 100644 trunk/arch/mips/lasat/lasat_models.h create mode 100644 trunk/arch/mips/lasat/picvue.c create mode 100644 trunk/arch/mips/lasat/picvue.h create mode 100644 trunk/arch/mips/lasat/picvue_proc.c create mode 100644 trunk/arch/mips/lasat/prom.c create mode 100644 trunk/arch/mips/lasat/prom.h create mode 100644 trunk/arch/mips/lasat/reset.c create mode 100644 trunk/arch/mips/lasat/setup.c create mode 100644 trunk/arch/mips/lasat/sysctl.c create mode 100644 trunk/arch/mips/lasat/sysctl.h delete mode 100644 trunk/arch/mips/lemote/lm2e/Makefile delete mode 100644 trunk/arch/mips/lemote/lm2e/bonito-irq.c delete mode 100644 trunk/arch/mips/lemote/lm2e/dbg_io.c delete mode 100644 trunk/arch/mips/lemote/lm2e/irq.c delete mode 100644 trunk/arch/mips/lemote/lm2e/mem.c delete mode 100644 trunk/arch/mips/lemote/lm2e/pci.c delete mode 100644 trunk/arch/mips/lemote/lm2e/prom.c delete mode 100644 trunk/arch/mips/lemote/lm2e/reset.c delete mode 100644 trunk/arch/mips/lemote/lm2e/setup.c create mode 100644 trunk/arch/mips/lib-32/Makefile create mode 100644 trunk/arch/mips/lib-32/dump_tlb.c create mode 100644 trunk/arch/mips/lib-32/r3k_dump_tlb.c create mode 100644 trunk/arch/mips/lib-32/watch.S create mode 100644 trunk/arch/mips/lib-64/Makefile create mode 100644 trunk/arch/mips/lib-64/dump_tlb.c create mode 100644 trunk/arch/mips/lib-64/watch.S delete mode 100644 trunk/arch/mips/lib/dump_tlb.c delete mode 100644 trunk/arch/mips/lib/r3k_dump_tlb.c delete mode 100644 trunk/arch/mips/mips-boards/malta/malta_platform.c rename trunk/arch/mips/{mipssim => mips-boards/sim}/Makefile (100%) rename trunk/arch/mips/{mipssim => mips-boards/sim}/sim_cmdline.c (100%) rename trunk/arch/mips/{mipssim => mips-boards/sim}/sim_console.c (98%) rename trunk/arch/mips/{mipssim => mips-boards/sim}/sim_mem.c (99%) rename trunk/arch/mips/{mipssim => mips-boards/sim}/sim_platform.c (100%) rename trunk/arch/mips/{mipssim => mips-boards/sim}/sim_setup.c (95%) rename trunk/arch/mips/{mipssim => mips-boards/sim}/sim_smp.c (89%) rename trunk/arch/mips/{mipssim => mips-boards/sim}/sim_time.c (91%) delete mode 100644 trunk/arch/mips/mipssim/sim_int.c create mode 100644 trunk/arch/mips/momentum/ocelot_3/Makefile create mode 100644 trunk/arch/mips/momentum/ocelot_3/irq.c rename trunk/arch/mips/{pmc-sierra/msp71xx/msp_pci.c => momentum/ocelot_3/ocelot_3_fpga.h} (53%) create mode 100644 trunk/arch/mips/momentum/ocelot_3/platform.c create mode 100644 trunk/arch/mips/momentum/ocelot_3/prom.c create mode 100644 trunk/arch/mips/momentum/ocelot_3/reset.c create mode 100644 trunk/arch/mips/momentum/ocelot_3/setup.c create mode 100644 trunk/arch/mips/momentum/ocelot_c/Makefile create mode 100644 trunk/arch/mips/momentum/ocelot_c/cpci-irq.c create mode 100644 trunk/arch/mips/momentum/ocelot_c/dbg_io.c create mode 100644 trunk/arch/mips/momentum/ocelot_c/irq.c rename trunk/arch/mips/{pmc-sierra/msp71xx/msp_elb.c => momentum/ocelot_c/ocelot_c_fpga.h} (53%) create mode 100644 trunk/arch/mips/momentum/ocelot_c/platform.c create mode 100644 trunk/arch/mips/momentum/ocelot_c/prom.c create mode 100644 trunk/arch/mips/momentum/ocelot_c/reset.c create mode 100644 trunk/arch/mips/momentum/ocelot_c/setup.c create mode 100644 trunk/arch/mips/momentum/ocelot_c/uart-irq.c delete mode 100644 trunk/arch/mips/pci/fixup-lm2e.c create mode 100644 trunk/arch/mips/pci/fixup-ocelot-c.c create mode 100644 trunk/arch/mips/pci/fixup-ocelot3.c delete mode 100644 trunk/arch/mips/pci/fixup-pmcmsp.c create mode 100644 trunk/arch/mips/pci/ops-marvell.c create mode 100644 trunk/arch/mips/pci/ops-nile4.c delete mode 100644 trunk/arch/mips/pci/ops-pmcmsp.c create mode 100644 trunk/arch/mips/pci/pci-ev64120.c create mode 100644 trunk/arch/mips/pci/pci-lasat.c create mode 100644 trunk/arch/mips/pci/pci-ocelot-c.c delete mode 100644 trunk/arch/mips/pmc-sierra/msp71xx/Makefile delete mode 100644 trunk/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c delete mode 100644 trunk/arch/mips/pmc-sierra/msp71xx/msp_irq.c delete mode 100644 trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c delete mode 100644 trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c delete mode 100644 trunk/arch/mips/pmc-sierra/msp71xx/msp_prom.c delete mode 100644 trunk/arch/mips/pmc-sierra/msp71xx/msp_setup.c delete mode 100644 trunk/arch/mips/pmc-sierra/msp71xx/msp_time.c delete mode 100644 trunk/arch/mips/pmc-sierra/msp71xx/msp_usb.c create mode 100644 trunk/arch/mips/sni/ds1216.c create mode 100644 trunk/arch/mips/tx4938/common/rtc_rx5c348.c create mode 100644 trunk/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c create mode 100644 trunk/drivers/block/acsi.c create mode 100644 trunk/drivers/cdrom/Kconfig create mode 100644 trunk/drivers/cdrom/aztcd.c create mode 100644 trunk/drivers/cdrom/aztcd.h create mode 100644 trunk/drivers/cdrom/cdu31a.c create mode 100644 trunk/drivers/cdrom/cdu31a.h create mode 100644 trunk/drivers/cdrom/cm206.c create mode 100644 trunk/drivers/cdrom/cm206.h create mode 100644 trunk/drivers/cdrom/gscd.c create mode 100644 trunk/drivers/cdrom/gscd.h create mode 100644 trunk/drivers/cdrom/isp16.c create mode 100644 trunk/drivers/cdrom/isp16.h create mode 100644 trunk/drivers/cdrom/mcdx.c create mode 100644 trunk/drivers/cdrom/mcdx.h create mode 100644 trunk/drivers/cdrom/optcd.c create mode 100644 trunk/drivers/cdrom/optcd.h create mode 100644 trunk/drivers/cdrom/sbpcd.c create mode 100644 trunk/drivers/cdrom/sbpcd.h create mode 100644 trunk/drivers/cdrom/sjcd.c create mode 100644 trunk/drivers/cdrom/sjcd.h create mode 100644 trunk/drivers/cdrom/sonycd535.c create mode 100644 trunk/drivers/cdrom/sonycd535.h delete mode 100644 trunk/drivers/input/mouse/gpio_mouse.c create mode 100644 trunk/drivers/mtd/maps/lasat.c delete mode 100644 trunk/drivers/power/Kconfig delete mode 100644 trunk/drivers/power/Makefile delete mode 100644 trunk/drivers/power/apm_power.c delete mode 100644 trunk/drivers/power/ds2760_battery.c delete mode 100644 trunk/drivers/power/olpc_battery.c delete mode 100644 trunk/drivers/power/pda_power.c delete mode 100644 trunk/drivers/power/pmu_battery.c delete mode 100644 trunk/drivers/power/power_supply.h delete mode 100644 trunk/drivers/power/power_supply_core.c delete mode 100644 trunk/drivers/power/power_supply_leds.c delete mode 100644 trunk/drivers/power/power_supply_sysfs.c delete mode 100644 trunk/drivers/w1/slaves/w1_ds2760.c delete mode 100644 trunk/drivers/w1/slaves/w1_ds2760.h delete mode 100644 trunk/fs/dlm/netlink.c create mode 100644 trunk/fs/gfs2/ondisk.c create mode 100644 trunk/fs/gfs2/ops_export.h delete mode 100644 trunk/include/asm-mips/gpio.h create mode 100644 trunk/include/asm-mips/lasat/ds1603.h create mode 100644 trunk/include/asm-mips/lasat/eeprom.h create mode 100644 trunk/include/asm-mips/lasat/head.h create mode 100644 trunk/include/asm-mips/lasat/lasat.h create mode 100644 trunk/include/asm-mips/lasat/lasatint.h create mode 100644 trunk/include/asm-mips/lasat/picvue.h create mode 100644 trunk/include/asm-mips/lasat/serial.h create mode 100644 trunk/include/asm-mips/mach-au1x00/au1xxx_gpio.h delete mode 100644 trunk/include/asm-mips/mach-au1x00/gpio.h create mode 100644 trunk/include/asm-mips/mach-ev64120/mach-gt64120.h delete mode 100644 trunk/include/asm-mips/mach-generic/gpio.h create mode 100644 trunk/include/asm-mips/mach-ip32/spaces.h delete mode 100644 trunk/include/asm-mips/mach-jmr3927/ioremap.h create mode 100644 trunk/include/asm-mips/mach-lasat/mach-gt64120.h delete mode 100644 trunk/include/asm-mips/mach-lemote/dma-coherence.h delete mode 100644 trunk/include/asm-mips/mach-lemote/mc146818rtc.h delete mode 100644 trunk/include/asm-mips/mach-mips/kernel-entry-init.h create mode 100644 trunk/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h rename trunk/include/asm-mips/{mach-mipssim => mach-sim}/cpu-feature-overrides.h (100%) delete mode 100644 trunk/include/asm-mips/mach-tx49xx/ioremap.h create mode 100644 trunk/include/asm-mips/nile4.h delete mode 100644 trunk/include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h delete mode 100644 trunk/include/asm-mips/pmc-sierra/msp71xx/msp_int.h delete mode 100644 trunk/include/asm-mips/pmc-sierra/msp71xx/msp_pci.h delete mode 100644 trunk/include/asm-mips/pmc-sierra/msp71xx/msp_prom.h delete mode 100644 trunk/include/asm-mips/pmc-sierra/msp71xx/msp_regops.h delete mode 100644 trunk/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h delete mode 100644 trunk/include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h create mode 100644 trunk/include/asm-mips/watch.h delete mode 100644 trunk/include/linux/dlm_netlink.h delete mode 100644 trunk/include/linux/gpio_mouse.h delete mode 100644 trunk/include/linux/pda_power.h delete mode 100644 trunk/include/linux/power_supply.h delete mode 100644 trunk/include/linux/splice.h diff --git a/[refs] b/[refs] index 83e45a2ed390..c2a1229f5dea 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 64b853aa328f34dd58e4e617cded91e2ddbcac13 +refs/heads/master: c59697e06058fc2361da8cefcfa3de85ac107582 diff --git a/trunk/Documentation/DocBook/kernel-api.tmpl b/trunk/Documentation/DocBook/kernel-api.tmpl index 8c5698a8c2e1..38f88b6ae405 100644 --- a/trunk/Documentation/DocBook/kernel-api.tmpl +++ b/trunk/Documentation/DocBook/kernel-api.tmpl @@ -643,15 +643,4 @@ X!Idrivers/video/console/fonts.c !Edrivers/spi/spi.c - - splice API - ) - splice is a method for moving blocks of data around inside the - kernel, without continually transferring it between the kernel - and user space. - -!Iinclude/linux/splice.h -!Ffs/splice.c - - diff --git a/trunk/Documentation/block/barrier.txt b/trunk/Documentation/block/barrier.txt index 7d279f2f5bb2..a272c3db8094 100644 --- a/trunk/Documentation/block/barrier.txt +++ b/trunk/Documentation/block/barrier.txt @@ -82,12 +82,23 @@ 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); + 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. @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. @@ -95,10 +106,9 @@ following. static void sd_prepare_flush(request_queue_t *q, struct request *rq) { memset(rq->cmd, 0, sizeof(rq->cmd)); - rq->cmd_type = REQ_TYPE_BLOCK_PC; + rq->flags |= REQ_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/trunk/Documentation/power_supply_class.txt b/trunk/Documentation/power_supply_class.txt deleted file mode 100644 index 9758cf433c06..000000000000 --- a/trunk/Documentation/power_supply_class.txt +++ /dev/null @@ -1,167 +0,0 @@ -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/trunk/MAINTAINERS b/trunk/MAINTAINERS index bc272bf0ff97..2c1dfb271613 100644 --- a/trunk/MAINTAINERS +++ b/trunk/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, TOUCHSCREEN) DRIVERS +INPUT (KEYBOARD, MOUSE, JOYSTICK) DRIVERS P: Dmitry Torokhov M: dmitry.torokhov@gmail.com M: dtor@mail.ru diff --git a/trunk/arch/mips/Kconfig b/trunk/arch/mips/Kconfig index a00fabe2e4e0..73455389257a 100644 --- a/trunk/arch/mips/Kconfig +++ b/trunk/arch/mips/Kconfig @@ -15,29 +15,6 @@ 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" @@ -86,7 +63,7 @@ config MACH_DECSTATION bool "DECstations" select BOOT_ELF32 select DMA_NONCOHERENT - select NO_IOPORT + select SYS_HAS_EARLY_PRINTK select IRQ_CPU select SYS_HAS_CPU_R3000 select SYS_HAS_CPU_R4X00 @@ -111,6 +88,24 @@ 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 + . Say Y here if you wish to build a + kernel for this platform. + config MACH_JAZZ bool "Jazz family of machines" select ARC @@ -131,6 +126,20 @@ 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 @@ -164,6 +173,7 @@ 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 @@ -236,13 +246,11 @@ 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 @@ -266,6 +274,43 @@ config MOMENCO_OCELOT The Ocelot is a MIPS-based Single Board Computer (SBC) made by Momentum Computer . +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 . + config PNX8550_JBS bool "Philips PNX8550 based JBS board" select PNX8550 @@ -301,27 +346,6 @@ 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 @@ -426,7 +450,8 @@ config SGI_IP27 here. config SGI_IP32 - bool "SGI IP32 (O2)" + bool "SGI IP32 (O2) (EXPERIMENTAL)" + depends on EXPERIMENTAL select ARC select ARC32 select BOOT_ELF32 @@ -627,7 +652,6 @@ 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 @@ -636,7 +660,9 @@ 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" @@ -695,9 +721,6 @@ config ARC config ARCH_MAY_HAVE_PC_FDC bool -config BOOT_RAW - bool - config DMA_COHERENT bool @@ -745,19 +768,16 @@ config MIPS_BONITO64 config MIPS_MSC bool -config MIPS_DISABLE_OBSOLETE_IDE +config MIPS_NILE4 bool -config NO_IOPORT - def_bool n +config MIPS_DISABLE_OBSOLETE_IDE + bool 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 @@ -801,10 +821,7 @@ config IRQ_CPU_RM7K config IRQ_CPU_RM9K bool -config IRQ_MSP_SLP - bool - -config IRQ_MSP_CIC +config IRQ_MV64340 bool config DDB5XXX_COMMON @@ -817,9 +834,6 @@ config MIPS_BOARDS_GEN config PCI_GT64XXX_PCI0 bool -config NO_EXCEPT_FILL - bool - config MIPS_TX3927 bool select HAS_TXX9_SERIAL @@ -827,6 +841,14 @@ 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 @@ -841,7 +863,6 @@ 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 @@ -854,17 +875,31 @@ 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" - depends on MOMENCO_OCELOT + #default SYSCLK_83 if MIPS_EV64120 + depends on MIPS_EV64120 || MOMENCO_OCELOT + default SYSCLK_83 if MIPS_EV64120 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 MOMENCO_OCELOT + bool "100" if MIPS_EV64120 || MOMENCO_OCELOT endchoice @@ -876,9 +911,8 @@ config BOOT_ELF32 config MIPS_L1_CACHE_SHIFT int - default "4" if MACH_DECSTATION - default "7" if SGI_IP27 || SNI_RM - default "4" if PMC_MSP4200_EVAL + default "4" if MACH_DECSTATION || SNI_RM + default "7" if SGI_IP27 default "5" config HAVE_STD_PC_SERIAL_PORT @@ -910,16 +944,6 @@ 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 @@ -1130,9 +1154,6 @@ config CPU_SB1 endchoice -config SYS_HAS_CPU_LOONGSON2 - bool - config SYS_HAS_CPU_MIPS32_R1 bool @@ -1467,15 +1488,6 @@ 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/trunk/arch/mips/Makefile b/trunk/arch/mips/Makefile index 20d19c9b7761..f450066b6241 100644 --- a/trunk/arch/mips/Makefile +++ b/trunk/arch/mips/Makefile @@ -118,7 +118,6 @@ 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,6 +282,14 @@ libs-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/prom/ 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) # @@ -290,13 +297,6 @@ core-$(CONFIG_WR_PPMC) += arch/mips/gt64120/wrppmc/ 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 # @@ -327,7 +327,7 @@ load-$(CONFIG_MIPS_SEAD) += 0xffffffff80100000 # # MIPS SIM # -core-$(CONFIG_MIPS_SIM) += arch/mips/mipssim/ +core-$(CONFIG_MIPS_SIM) += arch/mips/mips-boards/sim/ 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 # -# PMC-Sierra MSP SOCs +# Momentum Ocelot-C and -CS boards # -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 +# 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 # # PMC-Sierra Yosemite @@ -364,6 +364,13 @@ core-$(CONFIG_QEMU) += arch/mips/qemu/ 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 # @@ -382,6 +389,10 @@ 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 # @@ -569,7 +580,6 @@ 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 # @@ -577,7 +587,6 @@ 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 @@ -594,8 +603,7 @@ JIFFIES = jiffies_64 endif AFLAGS += $(cflags-y) -CFLAGS += $(cflags-y) \ - -D"VMLINUX_LOAD_ADDRESS=$(load-y)" +CFLAGS += $(cflags-y) LDFLAGS += -m $(ld-emul) @@ -625,11 +633,18 @@ 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 @@ -687,19 +702,32 @@ 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/trunk/arch/mips/au1000/common/gpio.c b/trunk/arch/mips/au1000/common/gpio.c index 7abe42099439..ce55297dcb8c 100644 --- a/trunk/arch/mips/au1000/common/gpio.c +++ b/trunk/arch/mips/au1000/common/gpio.c @@ -1,7 +1,4 @@ /* - * Copyright (C) 2007, OpenWrt.org, Florian Fainelli - * 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 @@ -21,136 +18,101 @@ * 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 -#include -#include -#include #include - -#include - -#include -#include +#include +#include #define gpio1 sys #if !defined(CONFIG_SOC_AU1000) +static AU1X00_GPIO2 * const gpio2 = (AU1X00_GPIO2 *)GPIO2_BASE; -static struct au1x00_gpio2 *const gpio2 = (struct au1x00_gpio2 *) GPIO2_BASE; -#define GPIO2_OUTPUT_ENABLE_MASK 0x00010000 +#define GPIO2_OUTPUT_ENABLE_MASK 0x00010000 -static int au1xxx_gpio2_read(unsigned gpio) +int au1xxx_gpio2_read(int signal) { - gpio -= AU1XXX_GPIO_BASE; - return ((gpio2->pinstate >> gpio) & 0x01); + signal -= 200; +/* gpio2->dir &= ~(0x01 << signal); //Set GPIO to input */ + return ((gpio2->pinstate >> signal) & 0x01); } -static void au1xxx_gpio2_write(unsigned gpio, int value) +void au1xxx_gpio2_write(int signal, int value) { - gpio -= AU1XXX_GPIO_BASE; + signal -= 200; - gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | (value << gpio); + gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << signal) | + (value << signal); } -static int au1xxx_gpio2_direction_input(unsigned gpio) +void au1xxx_gpio2_tristate(int signal) { - gpio -= AU1XXX_GPIO_BASE; - gpio2->dir &= ~(0x01 << gpio); - return 0; + signal -= 200; + gpio2->dir &= ~(0x01 << signal); /* Set GPIO to input */ } +#endif -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) +int au1xxx_gpio1_read(int signal) { - return ((gpio1->pinstaterd >> gpio) & 0x01); +/* gpio1->trioutclr |= (0x01 << signal); */ + return ((gpio1->pinstaterd >> signal) & 0x01); } -static void au1xxx_gpio1_write(unsigned gpio, int value) +void au1xxx_gpio1_write(int signal, int value) { - if (value) - gpio1->outputset = (0x01 << gpio); + if(value) + gpio1->outputset = (0x01 << signal); else - /* Output a zero */ - gpio1->outputclr = (0x01 << gpio); + gpio1->outputclr = (0x01 << signal); /* Output a Zero */ } -static int au1xxx_gpio1_direction_input(unsigned gpio) +void au1xxx_gpio1_tristate(int signal) { - gpio1->pininputen = (0x01 << gpio); - return 0; + gpio1->trioutclr = (0x01 << signal); /* Tristate signal */ } -static int au1xxx_gpio1_direction_output(unsigned gpio, int value) -{ - gpio1->trioutclr = (0x01 & gpio); - return 0; -} -int au1xxx_gpio_get_value(unsigned gpio) +int au1xxx_gpio_read(int signal) { - if (gpio >= AU1XXX_GPIO_BASE) + if(signal >= 200) #if defined(CONFIG_SOC_AU1000) return 0; #else - return au1xxx_gpio2_read(gpio); + return au1xxx_gpio2_read(signal); #endif else - return au1xxx_gpio1_read(gpio); + return au1xxx_gpio1_read(signal); } -EXPORT_SYMBOL(au1xxx_gpio_get_value); - -void au1xxx_gpio_set_value(unsigned gpio, int value) +void au1xxx_gpio_write(int signal, int value) { - if (gpio >= AU1XXX_GPIO_BASE) + if(signal >= 200) #if defined(CONFIG_SOC_AU1000) ; #else - au1xxx_gpio2_write(gpio, value); + au1xxx_gpio2_write(signal, value); #endif else - au1xxx_gpio1_write(gpio, value); + au1xxx_gpio1_write(signal, value); } -EXPORT_SYMBOL(au1xxx_gpio_set_value); - -int au1xxx_gpio_direction_input(unsigned gpio) +void au1xxx_gpio_tristate(int signal) { - if (gpio >= AU1XXX_GPIO_BASE) + if(signal >= 200) #if defined(CONFIG_SOC_AU1000) ; #else - return au1xxx_gpio2_direction_input(gpio); + au1xxx_gpio2_tristate(signal); #endif else - return au1xxx_gpio1_direction_input(gpio); + au1xxx_gpio1_tristate(signal); } -EXPORT_SYMBOL(au1xxx_gpio_direction_input); - -int au1xxx_gpio_direction_output(unsigned gpio, int value) +void au1xxx_gpio1_set_inputs(void) { - 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); + gpio1->pininputen = 0; } -EXPORT_SYMBOL(au1xxx_gpio_direction_output); +EXPORT_SYMBOL(au1xxx_gpio1_set_inputs); +EXPORT_SYMBOL(au1xxx_gpio_tristate); +EXPORT_SYMBOL(au1xxx_gpio_write); +EXPORT_SYMBOL(au1xxx_gpio_read); diff --git a/trunk/arch/mips/au1000/common/platform.c b/trunk/arch/mips/au1000/common/platform.c index d51e18fb789b..8fd203d4a339 100644 --- a/trunk/arch/mips/au1000/common/platform.c +++ b/trunk/arch/mips/au1000/common/platform.c @@ -289,7 +289,7 @@ static struct platform_device *au1xxx_platform_devices[] __initdata = { #endif }; -int __init au1xxx_platform_init(void) +int au1xxx_platform_init(void) { return platform_add_devices(au1xxx_platform_devices, ARRAY_SIZE(au1xxx_platform_devices)); } diff --git a/trunk/arch/mips/configs/atlas_defconfig b/trunk/arch/mips/configs/atlas_defconfig index 129e2c961fec..39e251300c64 100644 --- a/trunk/arch/mips/configs/atlas_defconfig +++ b/trunk/arch/mips/configs/atlas_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/bigsur_defconfig b/trunk/arch/mips/configs/bigsur_defconfig index dc3e1bf4e42e..4713a13211ce 100644 --- a/trunk/arch/mips/configs/bigsur_defconfig +++ b/trunk/arch/mips/configs/bigsur_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/capcella_defconfig b/trunk/arch/mips/configs/capcella_defconfig index 4c7031222e64..5e7ae56b1f3c 100644 --- a/trunk/arch/mips/configs/capcella_defconfig +++ b/trunk/arch/mips/configs/capcella_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/cobalt_defconfig b/trunk/arch/mips/configs/cobalt_defconfig index c8c05785a86d..631b2138ad68 100644 --- a/trunk/arch/mips/configs/cobalt_defconfig +++ b/trunk/arch/mips/configs/cobalt_defconfig @@ -1,24 +1,44 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.22-rc2 -# Fri May 25 11:17:29 2007 +# Linux kernel version: 2.6.21-rc7 +# Wed Apr 18 14:25:45 2007 # CONFIG_MIPS=y # # Machine selection # -# CONFIG_MACH_ALCHEMY is not set +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=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 @@ -118,7 +138,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=0 +CONFIG_ZONE_DMA_FLAG=1 # CONFIG_HZ_48 is not set # CONFIG_HZ_100 is not set # CONFIG_HZ_128 is not set @@ -158,7 +178,6 @@ 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 @@ -174,19 +193,14 @@ 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_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 @@ -219,13 +233,16 @@ 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 # @@ -251,6 +268,7 @@ CONFIG_NET=y # # Networking options # +# CONFIG_NETDEBUG is not set CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -282,11 +300,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 is not set +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 is not set +CONFIG_NETWORK_SECMARK=y # CONFIG_NETFILTER is not set # @@ -327,16 +345,13 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # 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 is not set -# CONFIG_MAC80211 is not set -# CONFIG_IEEE80211 is not set -# CONFIG_RFKILL 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 @@ -355,6 +370,10 @@ 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 @@ -399,6 +418,7 @@ 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 @@ -425,13 +445,16 @@ 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 # -# UBI - Unsorted block images +# OneNAND Flash Device Drivers # -# CONFIG_MTD_UBI is not set +# CONFIG_MTD_ONENAND is not set # # Parallel port support @@ -456,145 +479,87 @@ 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 is not set -# CONFIG_ATA_OVER_ETH 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_PHANTOM is not set -# CONFIG_SGI_IOC4 is not set +CONFIG_SGI_IOC4=y # CONFIG_TIFM_CORE is not set -# CONFIG_BLINK is not set -# CONFIG_IDE 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 # # SCSI device support # CONFIG_RAID_ATTRS=y -CONFIG_SCSI=y -# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI 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 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 + +# +# Serial ATA (prod) and Parallel ATA (experimental) drivers +# +# CONFIG_ATA is not set # # Multi-device support (RAID and LVM) @@ -605,14 +570,10 @@ CONFIG_PATA_VIA=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 # @@ -633,7 +594,24 @@ CONFIG_NETDEVICES=y # ARCnet devices # # CONFIG_ARCNET is not set -# CONFIG_PHYLIB 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) @@ -661,8 +639,35 @@ CONFIG_TULIP=y # CONFIG_ULI526X is not set # CONFIG_HP100 is not set # CONFIG_NET_PCI is not set -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 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 # # Token Ring devices @@ -670,16 +675,18 @@ CONFIG_TULIP=y # CONFIG_TR is not set # -# Wireless LAN +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces # -# 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 @@ -704,7 +711,10 @@ CONFIG_INPUT=y # # Userland interfaces # -# CONFIG_INPUT_MOUSEDEV is not set +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 @@ -716,23 +726,18 @@ CONFIG_INPUT=y # 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=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 +# CONFIG_INPUT_MISC is not set # # Hardware I/O ports # -# CONFIG_SERIO is not set +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 # @@ -749,7 +754,7 @@ CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_PCI is not set +CONFIG_SERIAL_8250_PCI=y CONFIG_SERIAL_8250_NR_UARTS=4 CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set @@ -768,11 +773,16 @@ 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 @@ -782,7 +792,10 @@ CONFIG_COBALT_LCD=y # TPM devices # # CONFIG_TCG_TPM is not set -CONFIG_DEVPORT=y + +# +# I2C support +# # CONFIG_I2C is not set # @@ -795,7 +808,12 @@ CONFIG_DEVPORT=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 @@ -806,19 +824,16 @@ CONFIG_DEVPORT=y # Multimedia devices # # CONFIG_VIDEO_DEV is not set -# CONFIG_DVB_CORE is not set -# CONFIG_DAB is not set # -# Graphics support +# Digital Video Broadcasting Devices # -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_DVB is not set # -# Display device support +# Graphics support # -# CONFIG_DISPLAY_SUPPORT is not set -# CONFIG_VGASTATE is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # CONFIG_FB is not set # @@ -853,6 +868,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y # USB Gadget Support # # CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# # CONFIG_MMC is not set # @@ -893,29 +912,17 @@ 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 # -# I2C RTC drivers -# - -# -# SPI RTC drivers -# - -# -# Platform RTC drivers +# 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 # @@ -929,6 +936,14 @@ CONFIG_RTC_DRV_CMOS=y # DMA Devices # +# +# Auxiliary Display support +# + +# +# Virtualization +# + # # File systems # @@ -937,13 +952,8 @@ 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=y -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y +# CONFIG_EXT3_FS is not set # 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 @@ -959,7 +969,7 @@ CONFIG_INOTIFY_USER=y CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set +CONFIG_FUSE_FS=y CONFIG_GENERIC_ACL=y # @@ -993,6 +1003,7 @@ 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 @@ -1010,23 +1021,13 @@ CONFIG_CONFIGFS_FS=y # Network File Systems # CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -CONFIG_NFS_V3_ACL=y +# CONFIG_NFS_V3 is not set # CONFIG_NFS_V4 is not set # CONFIG_NFS_DIRECTIO 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_NFSD is not set 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 @@ -1050,7 +1051,10 @@ CONFIG_MSDOS_PARTITION=y # # Distributed Lock Manager # -# CONFIG_DLM is not set +CONFIG_DLM=y +CONFIG_DLM_TCP=y +# CONFIG_DLM_SCTP is not set +# CONFIG_DLM_DEBUG is not set # # Profiling support @@ -1068,30 +1072,72 @@ 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 is not set +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set # # Cryptographic options # -# CONFIG_CRYPTO is not set +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 is not set -# CONFIG_CRC_ITU_T 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 -CONFIG_HAS_DMA=y diff --git a/trunk/arch/mips/configs/db1000_defconfig b/trunk/arch/mips/configs/db1000_defconfig index ec60beb888b2..10f6af43753d 100644 --- a/trunk/arch/mips/configs/db1000_defconfig +++ b/trunk/arch/mips/configs/db1000_defconfig @@ -26,7 +26,9 @@ 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 @@ -34,6 +36,8 @@ 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/trunk/arch/mips/configs/db1100_defconfig b/trunk/arch/mips/configs/db1100_defconfig index f3c25f08bfad..4b0862927748 100644 --- a/trunk/arch/mips/configs/db1100_defconfig +++ b/trunk/arch/mips/configs/db1100_defconfig @@ -26,7 +26,9 @@ 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 @@ -34,6 +36,8 @@ 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/trunk/arch/mips/configs/db1200_defconfig b/trunk/arch/mips/configs/db1200_defconfig index 6d400befbacc..820659e810dc 100644 --- a/trunk/arch/mips/configs/db1200_defconfig +++ b/trunk/arch/mips/configs/db1200_defconfig @@ -26,7 +26,9 @@ 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 @@ -34,6 +36,8 @@ 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/trunk/arch/mips/configs/db1500_defconfig b/trunk/arch/mips/configs/db1500_defconfig index 82aea6e08823..4050b9b91bcb 100644 --- a/trunk/arch/mips/configs/db1500_defconfig +++ b/trunk/arch/mips/configs/db1500_defconfig @@ -26,7 +26,9 @@ 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 @@ -34,6 +36,8 @@ 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/trunk/arch/mips/configs/db1550_defconfig b/trunk/arch/mips/configs/db1550_defconfig index 82697714a9e3..7b3519058ab8 100644 --- a/trunk/arch/mips/configs/db1550_defconfig +++ b/trunk/arch/mips/configs/db1550_defconfig @@ -26,7 +26,9 @@ 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 @@ -34,6 +36,8 @@ 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/trunk/arch/mips/configs/ddb5477_defconfig b/trunk/arch/mips/configs/ddb5477_defconfig index a42ab9ae7d4b..5b502a2013fb 100644 --- a/trunk/arch/mips/configs/ddb5477_defconfig +++ b/trunk/arch/mips/configs/ddb5477_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/decstation_defconfig b/trunk/arch/mips/configs/decstation_defconfig index d6e3fffbc80d..4bbdab078ff1 100644 --- a/trunk/arch/mips/configs/decstation_defconfig +++ b/trunk/arch/mips/configs/decstation_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/e55_defconfig b/trunk/arch/mips/configs/e55_defconfig index 78f5004fb721..b5714a6a5398 100644 --- a/trunk/arch/mips/configs/e55_defconfig +++ b/trunk/arch/mips/configs/e55_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/emma2rh_defconfig b/trunk/arch/mips/configs/emma2rh_defconfig index b29bff0f56c3..2e3e155b4c55 100644 --- a/trunk/arch/mips/configs/emma2rh_defconfig +++ b/trunk/arch/mips/configs/emma2rh_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/ev64120_defconfig b/trunk/arch/mips/configs/ev64120_defconfig new file mode 100644 index 000000000000..c10e4e063226 --- /dev/null +++ b/trunk/arch/mips/configs/ev64120_defconfig @@ -0,0 +1,985 @@ +# +# 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/trunk/arch/mips/configs/excite_defconfig b/trunk/arch/mips/configs/excite_defconfig index 69810592aa6b..460d7a26a8ba 100644 --- a/trunk/arch/mips/configs/excite_defconfig +++ b/trunk/arch/mips/configs/excite_defconfig @@ -26,7 +26,9 @@ 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 @@ -34,6 +36,8 @@ 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/trunk/arch/mips/configs/fulong_defconfig b/trunk/arch/mips/configs/fulong_defconfig deleted file mode 100644 index 6ab94d8cf08b..000000000000 --- a/trunk/arch/mips/configs/fulong_defconfig +++ /dev/null @@ -1,1765 +0,0 @@ -# -# 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/trunk/arch/mips/configs/ip22_defconfig b/trunk/arch/mips/configs/ip22_defconfig index 405c9f505a77..7ec618f3c8b9 100644 --- a/trunk/arch/mips/configs/ip22_defconfig +++ b/trunk/arch/mips/configs/ip22_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/ip27_defconfig b/trunk/arch/mips/configs/ip27_defconfig index a9dcbcf563cb..9ddc3eff4793 100644 --- a/trunk/arch/mips/configs/ip27_defconfig +++ b/trunk/arch/mips/configs/ip27_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/ip32_defconfig b/trunk/arch/mips/configs/ip32_defconfig index a040459bec11..8fc18809d5ff 100644 --- a/trunk/arch/mips/configs/ip32_defconfig +++ b/trunk/arch/mips/configs/ip32_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/jazz_defconfig b/trunk/arch/mips/configs/jazz_defconfig index dd04eece9fd3..9331cb0a19b1 100644 --- a/trunk/arch/mips/configs/jazz_defconfig +++ b/trunk/arch/mips/configs/jazz_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/jmr3927_defconfig b/trunk/arch/mips/configs/jmr3927_defconfig index 9a25e770abd8..1b364cf69140 100644 --- a/trunk/arch/mips/configs/jmr3927_defconfig +++ b/trunk/arch/mips/configs/jmr3927_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/lasat200_defconfig b/trunk/arch/mips/configs/lasat200_defconfig new file mode 100644 index 000000000000..fd4272c1458a --- /dev/null +++ b/trunk/arch/mips/configs/lasat200_defconfig @@ -0,0 +1,1118 @@ +# +# 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/trunk/arch/mips/configs/malta_defconfig b/trunk/arch/mips/configs/malta_defconfig index 546cb243fd09..1f64d7632a03 100644 --- a/trunk/arch/mips/configs/malta_defconfig +++ b/trunk/arch/mips/configs/malta_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/mipssim_defconfig b/trunk/arch/mips/configs/mipssim_defconfig index 6abad6f88313..a2db5c201216 100644 --- a/trunk/arch/mips/configs/mipssim_defconfig +++ b/trunk/arch/mips/configs/mipssim_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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 @@ -492,23 +496,36 @@ CONFIG_NETDEVICES=y # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set -# CONFIG_PHYLIB is not set + +# +# PHY device support +# # # Ethernet (10 or 100Mbit) # -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 +# 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 # -# Wireless LAN +# Wan interfaces # -# 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/trunk/arch/mips/configs/mpc30x_defconfig b/trunk/arch/mips/configs/mpc30x_defconfig index 4981ce425d82..ad5c0bf87b2b 100644 --- a/trunk/arch/mips/configs/mpc30x_defconfig +++ b/trunk/arch/mips/configs/mpc30x_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/msp71xx_defconfig b/trunk/arch/mips/configs/ocelot_3_defconfig similarity index 51% rename from trunk/arch/mips/configs/msp71xx_defconfig rename to trunk/arch/mips/configs/ocelot_3_defconfig index adca5f7ba533..28547313ce13 100644 --- a/trunk/arch/mips/configs/msp71xx_defconfig +++ b/trunk/arch/mips/configs/ocelot_3_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.21-rc4 -# Thu Apr 26 18:11:29 2007 +# Linux kernel version: 2.6.20 +# Tue Feb 20 21:47:35 2007 # CONFIG_MIPS=y @@ -25,7 +25,9 @@ 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 @@ -33,13 +35,14 @@ 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 @@ -59,16 +62,6 @@ CONFIG_PMC_MSP=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 @@ -78,24 +71,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_MSP_CIC=y -CONFIG_MSP_USB=y +CONFIG_IRQ_CPU_RM7K=y +CONFIG_IRQ_MV64340=y +CONFIG_PCI_MARVELL=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=y +# 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 @@ -111,14 +104,14 @@ CONFIG_CPU_MIPS32_R2=y # 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_RM9000=y # CONFIG_CPU_SB1 is not set -CONFIG_SYS_HAS_CPU_MIPS32_R1=y -CONFIG_SYS_HAS_CPU_MIPS32_R2=y -CONFIG_CPU_MIPS32=y -CONFIG_CPU_MIPSR2=y +CONFIG_SYS_HAS_CPU_RM9000=y +CONFIG_WEAK_ORDERING=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 @@ -129,12 +122,13 @@ 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 @@ -155,16 +149,15 @@ 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=y +# CONFIG_HZ_250 is not set # CONFIG_HZ_256 is not set -# CONFIG_HZ_1000 is not set +CONFIG_HZ_1000=y # CONFIG_HZ_1024 is not set CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_HZ=250 -# CONFIG_PREEMPT_NONE is not set +CONFIG_HZ=1000 +CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set -CONFIG_PREEMPT=y -# CONFIG_PREEMPT_BKL is not set +# CONFIG_PREEMPT is not set # CONFIG_KEXEC is not set CONFIG_LOCKDEP_SUPPORT=y CONFIG_STACKTRACE_SUPPORT=y @@ -175,15 +168,14 @@ 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="-pmc" +CONFIG_LOCALVERSION="" CONFIG_LOCALVERSION_AUTO=y -# CONFIG_SWAP is not set +CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_IPC_NS is not set CONFIG_SYSVIPC_SYSCTL=y @@ -192,16 +184,15 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_TASKSTATS is not set # CONFIG_UTS_NS is not set # CONFIG_AUDIT is not set -# CONFIG_IKCONFIG is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y CONFIG_SYSFS_DEPRECATED=y -# CONFIG_RELAY is not set -# CONFIG_BLK_DEV_INITRD is not set +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_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y CONFIG_PRINTK=y @@ -210,11 +201,11 @@ CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y -# CONFIG_SHMEM is not set +CONFIG_SHMEM=y CONFIG_SLAB=y CONFIG_VM_EVENT_COUNTERS=y CONFIG_RT_MUTEXES=y -CONFIG_TINY_SHMEM=y +# CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 # CONFIG_SLOB is not set @@ -241,8 +232,8 @@ CONFIG_BLOCK=y # CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_DEADLINE is not set # CONFIG_DEFAULT_CFQ is not set @@ -254,7 +245,6 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_HW_HAS_PCI=y CONFIG_PCI=y -# CONFIG_PCI_DEBUG is not set CONFIG_MMU=y # @@ -277,7 +267,10 @@ CONFIG_TRAD_SIGNALS=y # # Power management options # -# CONFIG_PM is not set +CONFIG_PM=y +# CONFIG_PM_LEGACY is not set +# CONFIG_PM_DEBUG is not set +# CONFIG_PM_SYSFS_DEPRECATED is not set # # Networking @@ -288,16 +281,17 @@ CONFIG_NET=y # Networking options # # CONFIG_NETDEBUG is not set -# CONFIG_PACKET is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y -CONFIG_XFRM_USER=y +# CONFIG_XFRM_USER is not set # CONFIG_XFRM_SUB_POLICY is not set -# CONFIG_XFRM_MIGRATE is not set +CONFIG_XFRM_MIGRATE=y CONFIG_NET_KEY=y -# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_NET_KEY_MIGRATE=y CONFIG_INET=y -CONFIG_IP_MULTICAST=y +# CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_FIB_HASH=y CONFIG_IP_PNP=y @@ -306,92 +300,122 @@ 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=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_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_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 is not set +CONFIG_TCP_MD5SIG=y # # IP: Virtual Server Configuration # # CONFIG_IP_VS is not set -# CONFIG_IPV6 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_INET6_XFRM_TUNNEL is not set # CONFIG_INET6_TUNNEL is not set -# CONFIG_NETWORK_SECMARK 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 -CONFIG_BRIDGE_NETFILTER=y # # Core Netfilter Configuration # -# 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 +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 # # 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=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_IPTABLES is not set # CONFIG_IP_NF_ARPTABLES is not set # -# Bridge: Netfilter Configuration +# IPv6: Netfilter Configuration (EXPERIMENTAL) # -# CONFIG_BRIDGE_NF_EBTABLES is not set +CONFIG_NF_CONNTRACK_IPV6=m +# CONFIG_IP6_NF_QUEUE is not set +# CONFIG_IP6_NF_IPTABLES is not set # # DCCP Configuration (EXPERIMENTAL) @@ -408,10 +432,9 @@ CONFIG_IP_NF_TARGET_REJECT=y # # CONFIG_TIPC is not set # CONFIG_ATM is not set -CONFIG_BRIDGE=y +# CONFIG_BRIDGE is not set # 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 @@ -424,6 +447,7 @@ CONFIG_LLC=y # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +CONFIG_NET_CLS_ROUTE=y # # Network testing @@ -432,8 +456,14 @@ CONFIG_LLC=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set -# CONFIG_IEEE80211 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 +CONFIG_FIB_RULES=y # # Device Drivers @@ -443,101 +473,19 @@ CONFIG_WIRELESS_EXT=y # Generic Driver Options # CONFIG_STANDALONE=y -# 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_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_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=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 +# CONFIG_MTD is not set # # Parallel port support @@ -557,21 +505,19 @@ CONFIG_MTD_PMC_MSP_RAMROOT=y # 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_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set # 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=4096 -CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set # CONFIG_CDROM_PKTCDVD is not set -# CONFIG_ATA_OVER_ETH is not set +CONFIG_ATA_OVER_ETH=m # # Misc devices # -# CONFIG_SGI_IOC4 is not set +CONFIG_SGI_IOC4=m # CONFIG_TIFM_CORE is not set # @@ -582,16 +528,16 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 # # 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_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_TGT=m +CONFIG_SCSI_NETLINK=y CONFIG_SCSI_PROC_FS=y # # SCSI support type (disk, tape, CD-ROM) # -CONFIG_BLK_DEV_SD=y +# CONFIG_BLK_DEV_SD is not set # CONFIG_CHR_DEV_ST is not set # CONFIG_CHR_DEV_OSST is not set # CONFIG_BLK_DEV_SR is not set @@ -604,21 +550,22 @@ CONFIG_BLK_DEV_SD=y # 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 +CONFIG_SCSI_SCAN_ASYNC=y # # 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 +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 # # SCSI low-level drivers # -# CONFIG_ISCSI_TCP is not set +CONFIG_ISCSI_TCP=m # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set @@ -626,7 +573,8 @@ CONFIG_BLK_DEV_SD=y # 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_AIC94XX=m +# CONFIG_AIC94XX_DEBUG is not set # CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ARCMSR is not set # CONFIG_MEGARAID_NEWGEN is not set @@ -682,10 +630,10 @@ CONFIG_BLK_DEV_SD=y # Network device support # CONFIG_NETDEVICES=y -CONFIG_DUMMY=y +# CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set +CONFIG_TUN=m # # ARCnet devices @@ -695,16 +643,26 @@ CONFIG_DUMMY=y # # PHY device support # -# CONFIG_PHYLIB 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=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=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 @@ -716,7 +674,26 @@ CONFIG_MSPETH_NAPI=y # # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set -# CONFIG_NET_PCI 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 # # Ethernet (1000 Mbit) @@ -732,20 +709,22 @@ CONFIG_MSPETH_NAPI=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_QLA3XXX is not set +CONFIG_MV643XX_ETH=y +CONFIG_QLA3XXX=m # CONFIG_ATL1 is not set # # Ethernet (10000 Mbit) # # CONFIG_CHELSIO_T1 is not set -# CONFIG_CHELSIO_T3 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 is not set +CONFIG_NETXEN_NIC=m # # Token Ring devices @@ -755,29 +734,7 @@ CONFIG_MSPETH_NAPI=y # # 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 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 +# CONFIG_NET_RADIO is not set # # Wan interfaces @@ -785,17 +742,17 @@ CONFIG_NET_WIRELESS=y # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set -CONFIG_PPP=y +CONFIG_PPP=m # CONFIG_PPP_MULTILINK is not set # CONFIG_PPP_FILTER is not set -# CONFIG_PPP_ASYNC is not set -# CONFIG_PPP_SYNC_TTY is not set -# CONFIG_PPP_DEFLATE 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 is not set -# CONFIG_PPPOE is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m # CONFIG_SLIP is not set -CONFIG_SLHC=y +CONFIG_SLHC=m # CONFIG_NET_FC is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set @@ -839,24 +796,31 @@ CONFIG_INPUT=y # # Hardware I/O ports # -# CONFIG_SERIO is not set +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_GAMEPORT is not set # # Character devices # -# CONFIG_VT is not set +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y # 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 is not set -CONFIG_SERIAL_8250_NR_UARTS=2 -CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set # @@ -866,7 +830,8 @@ CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y -# CONFIG_LEGACY_PTYS is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 # # IPMI @@ -878,8 +843,7 @@ CONFIG_UNIX98_PTYS=y # # CONFIG_WATCHDOG is not set # CONFIG_HW_RANDOM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set +CONFIG_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -894,58 +858,7 @@ CONFIG_UNIX98_PTYS=y # # I2C support # -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 +# CONFIG_I2C is not set # # SPI support @@ -961,57 +874,8 @@ CONFIG_PMCTWILED=y # # Hardware Monitoring support # -CONFIG_HWMON=y +# CONFIG_HWMON is not set # 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 @@ -1022,13 +886,62 @@ CONFIG_HWMON=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 @@ -1047,133 +960,12 @@ 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=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 +# 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_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 # @@ -1238,22 +1030,37 @@ CONFIG_USB_MON=y 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_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set # CONFIG_EXT4DEV_FS is not set -# CONFIG_REISERFS_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_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set -# CONFIG_XFS_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_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 is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set -# CONFIG_DNOTIFY is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m +CONFIG_GENERIC_ACL=y # # CD-ROM/DVD Filesystems @@ -1264,25 +1071,22 @@ CONFIG_EXT2_FS=y # # DOS/FAT/NT Filesystems # -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# 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 is not set +CONFIG_PROC_KCORE=y CONFIG_PROC_SYSCTL=y CONFIG_SYSFS=y CONFIG_TMPFS=y -# CONFIG_TMPFS_POSIX_ACL is not set +CONFIG_TMPFS_POSIX_ACL=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -# CONFIG_CONFIGFS_FS is not set +CONFIG_CONFIGFS_FS=m # # Miscellaneous filesystems @@ -1293,21 +1097,8 @@ CONFIG_RAMFS=y # 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=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_EFS_FS=y +CONFIG_CRAMFS=y # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set @@ -1317,9 +1108,26 @@ CONFIG_SQUASHFS_VMALLOC=y # # Network File Systems # -# CONFIG_NFS_FS is not set -# CONFIG_NFSD is not set -# CONFIG_SMB_FS is not set +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_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1335,9 +1143,9 @@ CONFIG_MSDOS_PARTITION=y # # Native Language Support # -CONFIG_NLS=y +CONFIG_NLS=m CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=y +# 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 @@ -1361,7 +1169,7 @@ CONFIG_NLS_CODEPAGE_437=y # 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_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 @@ -1379,7 +1187,10 @@ CONFIG_NLS_ISO8859_1=y # # Distributed Lock Manager # -# CONFIG_DLM is not set +CONFIG_DLM=m +CONFIG_DLM_TCP=y +# CONFIG_DLM_SCTP is not set +# CONFIG_DLM_DEBUG is not set # # Profiling support @@ -1392,40 +1203,14 @@ CONFIG_NLS_ISO8859_1=y CONFIG_TRACE_IRQFLAGS_SUPPORT=y # CONFIG_PRINTK_TIME is not set CONFIG_ENABLE_MUST_CHECK=y -CONFIG_MAGIC_SYSRQ=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=y -# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_DEBUG_KERNEL 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="" -# 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 +CONFIG_CMDLINE="ip=any root=nfs" # # Security options @@ -1438,40 +1223,41 @@ CONFIG_SYS_SUPPORTS_KGDB=y # CONFIG_CRYPTO=y CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_BLKCIPHER=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=y -# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=y -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_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 # @@ -1482,12 +1268,16 @@ CONFIG_CRYPTO_DEFLATE=y # Library routines # CONFIG_BITREVERSE=y -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m CONFIG_CRC32=y -# CONFIG_LIBCRC32C is not set +CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y +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 diff --git a/trunk/arch/mips/configs/ocelot_c_defconfig b/trunk/arch/mips/configs/ocelot_c_defconfig new file mode 100644 index 000000000000..82ff6fc0cd41 --- /dev/null +++ b/trunk/arch/mips/configs/ocelot_c_defconfig @@ -0,0 +1,982 @@ +# +# 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/trunk/arch/mips/configs/ocelot_defconfig b/trunk/arch/mips/configs/ocelot_defconfig index e1db1fb80cd0..15a027e00eec 100644 --- a/trunk/arch/mips/configs/ocelot_defconfig +++ b/trunk/arch/mips/configs/ocelot_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/pb1100_defconfig b/trunk/arch/mips/configs/pb1100_defconfig index 0028aef0af9d..37d696c64541 100644 --- a/trunk/arch/mips/configs/pb1100_defconfig +++ b/trunk/arch/mips/configs/pb1100_defconfig @@ -26,7 +26,9 @@ 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 @@ -34,6 +36,8 @@ 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/trunk/arch/mips/configs/pb1500_defconfig b/trunk/arch/mips/configs/pb1500_defconfig index 8a1d5888739c..b11f0e8b6059 100644 --- a/trunk/arch/mips/configs/pb1500_defconfig +++ b/trunk/arch/mips/configs/pb1500_defconfig @@ -26,7 +26,9 @@ 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 @@ -34,6 +36,8 @@ 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/trunk/arch/mips/configs/pb1550_defconfig b/trunk/arch/mips/configs/pb1550_defconfig index 5581ad2ca411..2927f38f4907 100644 --- a/trunk/arch/mips/configs/pb1550_defconfig +++ b/trunk/arch/mips/configs/pb1550_defconfig @@ -26,7 +26,9 @@ 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 @@ -34,6 +36,8 @@ 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/trunk/arch/mips/configs/pnx8550-jbs_defconfig b/trunk/arch/mips/configs/pnx8550-jbs_defconfig index 821c1cee5639..fae16c5ec521 100644 --- a/trunk/arch/mips/configs/pnx8550-jbs_defconfig +++ b/trunk/arch/mips/configs/pnx8550-jbs_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/pnx8550-stb810_defconfig b/trunk/arch/mips/configs/pnx8550-stb810_defconfig index 0e8bd92b38cf..cd821e52181d 100644 --- a/trunk/arch/mips/configs/pnx8550-stb810_defconfig +++ b/trunk/arch/mips/configs/pnx8550-stb810_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/qemu_defconfig b/trunk/arch/mips/configs/qemu_defconfig index 6cca105832ca..8e8d03157954 100644 --- a/trunk/arch/mips/configs/qemu_defconfig +++ b/trunk/arch/mips/configs/qemu_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/rbhma4200_defconfig b/trunk/arch/mips/configs/rbhma4200_defconfig index 20a38526d483..35d64260917e 100644 --- a/trunk/arch/mips/configs/rbhma4200_defconfig +++ b/trunk/arch/mips/configs/rbhma4200_defconfig @@ -24,13 +24,17 @@ 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/trunk/arch/mips/configs/rbhma4500_defconfig b/trunk/arch/mips/configs/rbhma4500_defconfig index 5dbb250f71c7..41011f770a67 100644 --- a/trunk/arch/mips/configs/rbhma4500_defconfig +++ b/trunk/arch/mips/configs/rbhma4500_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.22-rc5 -# Fri Jun 22 21:39:45 2007 +# Linux kernel version: 2.6.20 +# Tue Feb 20 21:47:39 2007 # CONFIG_MIPS=y @@ -9,23 +9,40 @@ CONFIG_MIPS=y # Machine selection # CONFIG_ZONE_DMA=y -# CONFIG_LEMOTE_FULONG is not set -# CONFIG_MACH_ALCHEMY is not set +# 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 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 @@ -65,8 +82,6 @@ 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 @@ -78,7 +93,6 @@ 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 @@ -135,12 +149,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=y +# CONFIG_HZ_250 is not set # CONFIG_HZ_256 is not set -# CONFIG_HZ_1000 is not set +CONFIG_HZ_1000=y # CONFIG_HZ_1024 is not set CONFIG_SYS_SUPPORTS_ARBIT_HZ=y -CONFIG_HZ=250 +CONFIG_HZ=1000 CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set @@ -172,35 +186,28 @@ 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 is not set -CONFIG_BLK_DEV_INITRD=y +CONFIG_RELAY=y CONFIG_INITRAMFS_SOURCE="" -CONFIG_CC_OPTIMIZE_FOR_SIZE=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 is not set +CONFIG_HOTPLUG=y 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_VM_EVENT_COUNTERS=y CONFIG_SLAB=y -# CONFIG_SLUB is not set -# CONFIG_SLOB is not set +CONFIG_VM_EVENT_COUNTERS=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set # # Loadable module support @@ -237,12 +244,17 @@ 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 @@ -254,7 +266,10 @@ CONFIG_TRAD_SIGNALS=y # # Power management options # -# CONFIG_PM is not set +CONFIG_PM=y +# CONFIG_PM_LEGACY is not set +# CONFIG_PM_DEBUG is not set +# CONFIG_PM_SYSFS_DEPRECATED is not set # # Networking @@ -264,9 +279,14 @@ 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 @@ -274,7 +294,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 is not set +CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set @@ -285,23 +305,130 @@ CONFIG_IP_PNP=y # 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 is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET 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_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 is not set -# CONFIG_IPV6 is not set +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_INET6_XFRM_TUNNEL is not set # CONFIG_INET6_TUNNEL is not set -# CONFIG_NETWORK_SECMARK is not set -# CONFIG_NETFILTER 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_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 @@ -319,6 +446,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +CONFIG_NET_CLS_ROUTE=y # # Network testing @@ -327,16 +455,15 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # 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 is not set -# CONFIG_MAC80211 is not set -# CONFIG_IEEE80211 is not set -# CONFIG_RFKILL 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 # # Device Drivers @@ -347,13 +474,94 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # 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 is not set +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 # # Parallel port support @@ -375,30 +583,93 @@ CONFIG_PREVENT_FIRMWARE_BUILD=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 is not set +CONFIG_BLK_DEV_NBD=m # 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_PHANTOM is not set -# CONFIG_SGI_IOC4 is not set +CONFIG_SGI_IOC4=m # CONFIG_TIFM_CORE is not set -# CONFIG_BLINK is not set -# CONFIG_IDE 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 # # SCSI device support # -# CONFIG_RAID_ATTRS is not set +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 # @@ -414,7 +685,6 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 # # IEEE 1394 (FireWire) support # -# CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set # @@ -429,15 +699,36 @@ CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set +CONFIG_TUN=m + +# +# ARCnet devices +# # CONFIG_ARCNET is not set -# CONFIG_PHYLIB 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=y +# CONFIG_MII is not set # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set # CONFIG_CASSINI is not set @@ -456,7 +747,6 @@ 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 @@ -471,20 +761,91 @@ CONFIG_TC35815=y # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # CONFIG_SC92031 is not set -# CONFIG_NETDEV_1000 is not set -# CONFIG_NETDEV_10000 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_TR is not set # -# Wireless LAN +# 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 # -# 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_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_SLIP is not set +CONFIG_SLHC=m # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set @@ -503,18 +864,57 @@ CONFIG_TC35815=y # # Input device support # -# CONFIG_INPUT is not set +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 # # Hardware I/O ports # -# CONFIG_SERIO is not set +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 is not set +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y # CONFIG_SERIAL_NONSTANDARD is not set # @@ -526,12 +926,11 @@ CONFIG_TC35815=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=y -CONFIG_SERIAL_TXX9_STDSERIAL=y +# CONFIG_SERIAL_TXX9_CONSOLE is not set +# CONFIG_SERIAL_TXX9_STDSERIAL is not set # CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y @@ -541,10 +940,15 @@ 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 @@ -554,143 +958,258 @@ 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 # -# SPI Master Controller Drivers +# I2C support # -# CONFIG_SPI_BITBANG is not set -CONFIG_SPI_TXX9=y +# CONFIG_I2C is not set # -# SPI Protocol Masters +# SPI support # -CONFIG_SPI_AT25=y -# CONFIG_SPI_SPIDEV is not set +# 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 +# Hardware Monitoring support # -# CONFIG_MFD_SM501 is not set +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 # # Multimedia devices # # CONFIG_VIDEO_DEV is not set -# CONFIG_DVB_CORE is not set -# CONFIG_DAB is not set # -# Graphics support +# Digital Video Broadcasting Devices # -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set # -# Display device support +# Graphics support # -# CONFIG_DISPLAY_SUPPORT is not set -# CONFIG_VGASTATE is not set -# CONFIG_FB is not set +# 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 # # CONFIG_SOUND is not set +# +# HID Devices +# +CONFIG_HID=y +# CONFIG_HID_DEBUG 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 +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 # # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' # # -# USB Gadget Support +# may also be needed; see USB_STORAGE Help for more information # -# CONFIG_USB_GADGET is not set -# CONFIG_MMC is not set +# CONFIG_USB_LIBUSUAL is not set # -# LED devices +# USB Input Devices # -# CONFIG_NEW_LEDS is not set +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 # -# LED drivers +# USB Imaging devices # +# CONFIG_USB_MDC800 is not set # -# LED Triggers +# 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 # -# InfiniBand support +# USB port drivers # -# CONFIG_INFINIBAND is not set # -# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# USB Serial Converter support # +# CONFIG_USB_SERIAL is not set # -# Real Time Clock +# 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_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set + +# +# USB DSL modem support # -CONFIG_RTC_LIB=y -CONFIG_RTC_CLASS=y -CONFIG_RTC_HCTOSYS=y -CONFIG_RTC_HCTOSYS_DEVICE="rtc0" -# CONFIG_RTC_DEBUG is not set # -# RTC interfaces +# USB Gadget Support # -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 +# CONFIG_USB_GADGET is not set # -# I2C RTC drivers +# MMC/SD Card support # +# CONFIG_MMC is not set # -# SPI RTC drivers +# LED devices # -CONFIG_RTC_DRV_RS5C348=y -# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_NEW_LEDS is not set # -# Platform RTC drivers +# LED 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 # -# on-CPU RTC 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 # @@ -704,16 +1223,39 @@ CONFIG_RTC_DRV_RS5C348=y # DMA Devices # +# +# Auxiliary Display support +# + +# +# Virtualization +# + # # File systems # -# CONFIG_EXT2_FS is not set -# CONFIG_EXT3_FS is not set +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_EXT4DEV_FS is not set -# CONFIG_REISERFS_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_JFS_FS is not set CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set +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_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set @@ -723,21 +1265,26 @@ CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set # CONFIG_DNOTIFY is not set # CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m CONFIG_GENERIC_ACL=y # # CD-ROM/DVD Filesystems # -# CONFIG_ISO9660_FS is not set +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS 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 is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_NTFS_FS is not set # @@ -751,7 +1298,7 @@ CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -# CONFIG_CONFIGFS_FS is not set +CONFIG_CONFIGFS_FS=m # # Miscellaneous filesystems @@ -763,7 +1310,16 @@ CONFIG_RAMFS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_CRAMFS 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_VXFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set @@ -778,16 +1334,19 @@ 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_NFSD=m +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP 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 is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -803,12 +1362,54 @@ CONFIG_MSDOS_PARTITION=y # # Native Language Support # -# CONFIG_NLS is not set +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 # # Distributed Lock Manager # -# CONFIG_DLM is not set +CONFIG_DLM=m +CONFIG_DLM_TCP=y +# CONFIG_DLM_SCTP is not set +# CONFIG_DLM_DEBUG is not set # # Profiling support @@ -826,6 +1427,7 @@ 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 @@ -839,17 +1441,62 @@ CONFIG_SYS_SUPPORTS_KGDB=y # # Cryptographic options # -# CONFIG_CRYPTO is not set +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 is not set -# CONFIG_CRC_ITU_T is not set +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m CONFIG_CRC32=y -# CONFIG_LIBCRC32C is not set +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_HAS_IOMEM=y CONFIG_HAS_IOPORT=y -CONFIG_HAS_DMA=y diff --git a/trunk/arch/mips/configs/rm200_defconfig b/trunk/arch/mips/configs/rm200_defconfig index 1a67a85aabbb..5593cde9f74c 100644 --- a/trunk/arch/mips/configs/rm200_defconfig +++ b/trunk/arch/mips/configs/rm200_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/sb1250-swarm_defconfig b/trunk/arch/mips/configs/sb1250-swarm_defconfig index 98a914092258..6c4f09a381e2 100644 --- a/trunk/arch/mips/configs/sb1250-swarm_defconfig +++ b/trunk/arch/mips/configs/sb1250-swarm_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/sead_defconfig b/trunk/arch/mips/configs/sead_defconfig index 69c08b24c82a..988b9cdef01f 100644 --- a/trunk/arch/mips/configs/sead_defconfig +++ b/trunk/arch/mips/configs/sead_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/tb0219_defconfig b/trunk/arch/mips/configs/tb0219_defconfig index 5d4fc0e4f729..8b1675c07ec4 100644 --- a/trunk/arch/mips/configs/tb0219_defconfig +++ b/trunk/arch/mips/configs/tb0219_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/tb0226_defconfig b/trunk/arch/mips/configs/tb0226_defconfig index 1b92b48de051..b5be8b74d896 100644 --- a/trunk/arch/mips/configs/tb0226_defconfig +++ b/trunk/arch/mips/configs/tb0226_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/tb0287_defconfig b/trunk/arch/mips/configs/tb0287_defconfig index 5b77c7a5d83a..8bb6be4342b6 100644 --- a/trunk/arch/mips/configs/tb0287_defconfig +++ b/trunk/arch/mips/configs/tb0287_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/workpad_defconfig b/trunk/arch/mips/configs/workpad_defconfig index 94a4f94a8b24..8f019ffcc71b 100644 --- a/trunk/arch/mips/configs/workpad_defconfig +++ b/trunk/arch/mips/configs/workpad_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/wrppmc_defconfig b/trunk/arch/mips/configs/wrppmc_defconfig index e38bd9b0eadc..52b48c0715d3 100644 --- a/trunk/arch/mips/configs/wrppmc_defconfig +++ b/trunk/arch/mips/configs/wrppmc_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/configs/yosemite_defconfig b/trunk/arch/mips/configs/yosemite_defconfig index f1cdb12f7925..6824606309e5 100644 --- a/trunk/arch/mips/configs/yosemite_defconfig +++ b/trunk/arch/mips/configs/yosemite_defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/ddb5xxx/ddb5477/Makefile b/trunk/arch/mips/ddb5xxx/ddb5477/Makefile index 4864b8a659c7..23fd3b81fe1a 100644 --- a/trunk/arch/mips/ddb5xxx/ddb5477/Makefile +++ b/trunk/arch/mips/ddb5xxx/ddb5477/Makefile @@ -2,8 +2,7 @@ # Makefile for NEC DDB-Vrc5477 board # -obj-y += ddb5477-platform.o irq.o irq_5477.o setup.o \ - lcd44780.o +obj-y += irq.o irq_5477.o setup.o lcd44780.o obj-$(CONFIG_RUNTIME_DEBUG) += debug.o obj-$(CONFIG_KGDB) += kgdb_io.o diff --git a/trunk/arch/mips/ddb5xxx/ddb5477/ddb5477-platform.c b/trunk/arch/mips/ddb5xxx/ddb5477/ddb5477-platform.c deleted file mode 100644 index c16020ad54c2..000000000000 --- a/trunk/arch/mips/ddb5xxx/ddb5477/ddb5477-platform.c +++ /dev/null @@ -1,49 +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) 2007 Ralf Baechle (ralf@linux-mips.org) - */ -#include -#include -#include - -#include - -#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 "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("8250 UART probe driver for the NEC DDB5477"); diff --git a/trunk/arch/mips/dec/prom/console.c b/trunk/arch/mips/dec/prom/console.c index 078e1a12421d..65419bf32441 100644 --- a/trunk/arch/mips/dec/prom/console.c +++ b/trunk/arch/mips/dec/prom/console.c @@ -3,7 +3,7 @@ * * DECstation PROM-based early console support. * - * Copyright (C) 2004, 2007 Maciej W. Rozycki + * Copyright (C) 2004 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,35 +13,15 @@ #include #include #include -#include #include -static void __init prom_console_write(struct console *con, const char *s, - unsigned int c) +void prom_putchar(char c) { - char buf[81]; - unsigned int chunk = sizeof(buf) - 1; + char s[2]; - 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, -}; + s[0] = c; + s[1] = '\0'; -void __init register_prom_console(void) -{ - register_console(&promcons); + prom_printf( s); } diff --git a/trunk/arch/mips/dec/prom/init.c b/trunk/arch/mips/dec/prom/init.c index 808c182fd3fa..a217aafe59f6 100644 --- a/trunk/arch/mips/dec/prom/init.c +++ b/trunk/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 dec_machine_halt(void); + extern void ATTRIB_NORET 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,9 +103,6 @@ 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/trunk/arch/mips/dec/reset.c b/trunk/arch/mips/dec/reset.c index c15a879046e5..56397227adb0 100644 --- a/trunk/arch/mips/dec/reset.c +++ b/trunk/arch/mips/dec/reset.c @@ -9,26 +9,26 @@ #include -typedef void __noreturn (* noret_func_t)(void); +typedef void ATTRIB_NORET (* noret_func_t)(void); -static inline void __noreturn back_to_prom(void) +static inline void ATTRIB_NORET back_to_prom(void) { noret_func_t func = (void *)CKSEG1ADDR(0x1fc00000); func(); } -void __noreturn dec_machine_restart(char *command) +void ATTRIB_NORET dec_machine_restart(char *command) { back_to_prom(); } -void __noreturn dec_machine_halt(void) +void ATTRIB_NORET dec_machine_halt(void) { back_to_prom(); } -void __noreturn dec_machine_power_off(void) +void ATTRIB_NORET dec_machine_power_off(void) { /* DECstations don't have a software power switch */ back_to_prom(); diff --git a/trunk/arch/mips/defconfig b/trunk/arch/mips/defconfig index b3b6e58058f6..41211f8b7738 100644 --- a/trunk/arch/mips/defconfig +++ b/trunk/arch/mips/defconfig @@ -25,7 +25,9 @@ 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 @@ -33,6 +35,8 @@ 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/trunk/arch/mips/gt64120/ev64120/Kconfig b/trunk/arch/mips/gt64120/ev64120/Kconfig new file mode 100644 index 000000000000..d691762cb0f7 --- /dev/null +++ b/trunk/arch/mips/gt64120/ev64120/Kconfig @@ -0,0 +1,3 @@ +config EVB_PCI1 + bool "Enable Second PCI (PCI1)" + depends on MIPS_EV64120 diff --git a/trunk/arch/mips/gt64120/ev64120/Makefile b/trunk/arch/mips/gt64120/ev64120/Makefile new file mode 100644 index 000000000000..323b2cebc691 --- /dev/null +++ b/trunk/arch/mips/gt64120/ev64120/Makefile @@ -0,0 +1,9 @@ +# +# 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/trunk/arch/mips/gt64120/ev64120/irq.c b/trunk/arch/mips/gt64120/ev64120/irq.c new file mode 100644 index 000000000000..64e4c80b6139 --- /dev/null +++ b/trunk/arch/mips/gt64120/ev64120/irq.c @@ -0,0 +1,116 @@ +/* + * BRIEF MODULE DESCRIPTION + * Code to handle irqs on GT64120A boards + * Derived from mips/orion and Cort + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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/trunk/arch/mips/gt64120/ev64120/promcon.c b/trunk/arch/mips/gt64120/ev64120/promcon.c new file mode 100644 index 000000000000..6e0ecfed9640 --- /dev/null +++ b/trunk/arch/mips/gt64120/ev64120/promcon.c @@ -0,0 +1,48 @@ +/* + * 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 +#include +#include + +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/trunk/arch/mips/gt64120/ev64120/reset.c b/trunk/arch/mips/gt64120/ev64120/reset.c new file mode 100644 index 000000000000..7b9f5e5bf21f --- /dev/null +++ b/trunk/arch/mips/gt64120/ev64120/reset.c @@ -0,0 +1,45 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +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/trunk/arch/mips/gt64120/ev64120/serialGT.c b/trunk/arch/mips/gt64120/ev64120/serialGT.c new file mode 100644 index 000000000000..8f0d835491ff --- /dev/null +++ b/trunk/arch/mips/gt64120/ev64120/serialGT.c @@ -0,0 +1,212 @@ +/* + * 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/trunk/arch/mips/gt64120/ev64120/setup.c b/trunk/arch/mips/gt64120/ev64120/setup.c new file mode 100644 index 000000000000..477848c22a2c --- /dev/null +++ b/trunk/arch/mips/gt64120/ev64120/setup.c @@ -0,0 +1,99 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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/trunk/arch/mips/gt64120/momenco_ocelot/Makefile b/trunk/arch/mips/gt64120/momenco_ocelot/Makefile index 1df5fe23c642..9f9a33fc76b9 100644 --- a/trunk/arch/mips/gt64120/momenco_ocelot/Makefile +++ b/trunk/arch/mips/gt64120/momenco_ocelot/Makefile @@ -2,6 +2,6 @@ # Makefile for Momentum's Ocelot board. # -obj-y += irq.o ocelot-platform.o prom.o reset.o setup.o +obj-y += irq.o prom.o reset.o setup.o obj-$(CONFIG_KGDB) += dbg_io.o diff --git a/trunk/arch/mips/gt64120/momenco_ocelot/ocelot-platform.c b/trunk/arch/mips/gt64120/momenco_ocelot/ocelot-platform.c deleted file mode 100644 index 81d9031a5a2a..000000000000 --- a/trunk/arch/mips/gt64120/momenco_ocelot/ocelot-platform.c +++ /dev/null @@ -1,46 +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) 2007 Ralf Baechle (ralf@linux-mips.org) - * - * A NS16552 DUART with a 20MHz crystal. - * - */ -#include -#include -#include - -#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 "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("8250 UART probe driver for the Momenco Ocelot"); diff --git a/trunk/arch/mips/gt64120/wrppmc/setup.c b/trunk/arch/mips/gt64120/wrppmc/setup.c index ea965529e5e0..121188d5ec4a 100644 --- a/trunk/arch/mips/gt64120/wrppmc/setup.c +++ b/trunk/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_WINDRIVER; - mips_machtype = MACH_WRPPMC; + mips_machgroup = MACH_GROUP_GALILEO; + mips_machtype = MACH_EV64120A; 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/trunk/arch/mips/jazz/Makefile b/trunk/arch/mips/jazz/Makefile index ae4c402b5004..dd9d99bfcf7a 100644 --- a/trunk/arch/mips/jazz/Makefile +++ b/trunk/arch/mips/jazz/Makefile @@ -2,4 +2,4 @@ # Makefile for the Jazz family specific parts of the kernel # -obj-y := irq.o jazzdma.o jazz-platform.o reset.o setup.o +obj-y := irq.o jazzdma.o reset.o setup.o diff --git a/trunk/arch/mips/jazz/jazz-platform.c b/trunk/arch/mips/jazz/jazz-platform.c deleted file mode 100644 index fd736703eef2..000000000000 --- a/trunk/arch/mips/jazz/jazz-platform.c +++ /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. - * - * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org) - */ -#include -#include -#include - -#include - -/* - * 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 "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("8250 UART probe driver for the Jazz family"); diff --git a/trunk/arch/mips/kernel/8250-platform.c b/trunk/arch/mips/kernel/8250-platform.c deleted file mode 100644 index cbf3fe20ad17..000000000000 --- a/trunk/arch/mips/kernel/8250-platform.c +++ /dev/null @@ -1,47 +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) 2007 Ralf Baechle (ralf@linux-mips.org) - */ -#include -#include -#include - -#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 "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Generic 8250 UART probe driver"); diff --git a/trunk/arch/mips/kernel/Makefile b/trunk/arch/mips/kernel/Makefile index 961594cb5214..49246264cc7c 100644 --- a/trunk/arch/mips/kernel/Makefile +++ b/trunk/arch/mips/kernel/Makefile @@ -14,15 +14,14 @@ 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 @@ -30,14 +29,13 @@ 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_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_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_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 @@ -49,6 +47,7 @@ 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 @@ -69,5 +68,3 @@ 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/trunk/arch/mips/kernel/cpu-probe.c b/trunk/arch/mips/kernel/cpu-probe.c index c6b8b074a81a..b12eeee0e974 100644 --- a/trunk/arch/mips/kernel/cpu-probe.c +++ b/trunk/arch/mips/kernel/cpu-probe.c @@ -186,29 +186,9 @@ static inline void check_wait(void) } } -static inline void check_errata(void) -{ - struct cpuinfo_mips *c = ¤t_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(); } /* @@ -505,14 +485,6 @@ 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; } } @@ -616,8 +588,6 @@ 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/trunk/arch/mips/kernel/head.S b/trunk/arch/mips/kernel/head.S index f78538eceef7..6f57ca44291f 100644 --- a/trunk/arch/mips/kernel/head.S +++ b/trunk/arch/mips/kernel/head.S @@ -16,7 +16,6 @@ #include #include -#include #include #include #include @@ -130,25 +129,24 @@ #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_BOOT_RAW +#ifdef CONFIG_MIPS_SIM /* * 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. */ - __INIT + j kernel_entry #endif + __INIT NESTED(kernel_entry, 16, sp) # kernel entry point @@ -199,7 +197,9 @@ 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/trunk/arch/mips/kernel/irq-mv6434x.c b/trunk/arch/mips/kernel/irq-mv6434x.c new file mode 100644 index 000000000000..3dd561832e4c --- /dev/null +++ b/trunk/arch/mips/kernel/irq-mv6434x.c @@ -0,0 +1,111 @@ +/* + * Copyright 2002 Momentum Computer + * Author: mdharm@momenco.com + * Copyright (C) 2004, 06 Ralf Baechle + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +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/trunk/arch/mips/kernel/mips-mt-fpaff.c b/trunk/arch/mips/kernel/mips-mt-fpaff.c deleted file mode 100644 index ede5d73d652e..000000000000 --- a/trunk/arch/mips/kernel/mips-mt-fpaff.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * General MIPS MT support routines, usable in AP/SP, SMVP, or SMTC kernels - * Copyright (C) 2005 Mips Technologies, Inc - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * 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/trunk/arch/mips/kernel/mips-mt.c b/trunk/arch/mips/kernel/mips-mt.c index 1a7d89231299..ba01800b6018 100644 --- a/trunk/arch/mips/kernel/mips-mt.c +++ b/trunk/arch/mips/kernel/mips-mt.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,149 @@ #include #include +/* + * CPU mask used to set process affinity for MT VPEs/TCs with FPUs + */ + +cpumask_t mt_fpu_cpumask; + +#ifdef CONFIG_MIPS_MT_FPAFF + +#include +#include +#include + +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. @@ -51,31 +195,27 @@ 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 */ @@ -170,6 +310,17 @@ 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; @@ -225,6 +376,20 @@ 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/trunk/arch/mips/kernel/proc.c b/trunk/arch/mips/kernel/proc.c index ec04f5a1a5ea..5ddc2e9deecf 100644 --- a/trunk/arch/mips/kernel/proc.c +++ b/trunk/arch/mips/kernel/proc.c @@ -14,6 +14,7 @@ #include #include #include +#include unsigned int vced_count, vcei_count; @@ -83,7 +84,6 @@ 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/trunk/arch/mips/kernel/process.c b/trunk/arch/mips/kernel/process.c index 8f4cf27c7157..6bdfb5a9fa1a 100644 --- a/trunk/arch/mips/kernel/process.c +++ b/trunk/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) */ -void __noreturn cpu_idle(void) +ATTRIB_NORET void 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 void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *)) +static ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *)) { do_exit(fn(arg)); } diff --git a/trunk/arch/mips/kernel/setup.c b/trunk/arch/mips/kernel/setup.c index 316685fca059..4975da0bfb63 100644 --- a/trunk/arch/mips/kernel/setup.c +++ b/trunk/arch/mips/kernel/setup.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include @@ -575,18 +574,3 @@ __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/trunk/arch/mips/kernel/smp.c b/trunk/arch/mips/kernel/smp.c index be7362bc2c9a..a1b017f2dbb3 100644 --- a/trunk/arch/mips/kernel/smp.c +++ b/trunk/arch/mips/kernel/smp.c @@ -52,7 +52,7 @@ EXPORT_SYMBOL(phys_cpu_present_map); EXPORT_SYMBOL(cpu_online_map); extern void __init calibrate_delay(void); -extern void cpu_idle(void); +extern ATTRIB_NORET void cpu_idle(void); /* * First C code run on the secondary CPUs after being started up by diff --git a/trunk/arch/mips/kernel/smtc.c b/trunk/arch/mips/kernel/smtc.c index 342d873b2ecc..046b03b1705a 100644 --- a/trunk/arch/mips/kernel/smtc.c +++ b/trunk/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 = current_cpu_data.vpe_id; + vpe = cpu_data[smp_processor_id()].vpe_id; for (bit = 0; bit < 8; bit++) { /* * In current prototype, I/O interrupts diff --git a/trunk/arch/mips/kernel/syscall.c b/trunk/arch/mips/kernel/syscall.c index b947c61c0cc8..9dd5a2df8eac 100644 --- a/trunk/arch/mips/kernel/syscall.c +++ b/trunk/arch/mips/kernel/syscall.c @@ -272,8 +272,9 @@ asmlinkage int sys_set_thread_area(unsigned long addr) struct thread_info *ti = task_thread_info(current); ti->tp_value = addr; - if (cpu_has_userlocal) - write_c0_userlocal(addr); + + /* If some future MIPS implementation has this register in hardware, + * we will need to update it here (and in context switches). */ return 0; } diff --git a/trunk/arch/mips/kernel/traps.c b/trunk/arch/mips/kernel/traps.c index 80ea4fa95bd9..3ea7863c4519 100644 --- a/trunk/arch/mips/kernel/traps.c +++ b/trunk/arch/mips/kernel/traps.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -69,7 +70,6 @@ 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); -void __noreturn die(const char * str, struct pt_regs * regs) +NORET_TYPE void ATTRIB_NORET die(const char * str, struct pt_regs * regs) { static int die_counter; #ifdef CONFIG_MIPS_MT_SMTC @@ -753,33 +753,6 @@ 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; @@ -813,8 +786,36 @@ asmlinkage void do_cpu(struct pt_regs *regs) ¤t->thread.fpu, 0); if (sig) force_sig(sig, current); - else - mt_ase_fp_affinity(); +#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 */ } return; @@ -834,11 +835,6 @@ 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. @@ -1347,14 +1343,7 @@ void __init per_cpu_trap_init(void) set_c0_status(ST0_MX); #ifdef CONFIG_CPU_MIPSR2 - if (cpu_has_mips_r2) { - unsigned int enable = 0x0000000f; - - if (cpu_has_userlocal) - enable |= (1 << 29); - - write_c0_hwrena(enable); - } + write_c0_hwrena (0x0000000f); /* Allow rdhwr to all registers */ #endif #ifdef CONFIG_MIPS_MT_SMTC diff --git a/trunk/arch/mips/kernel/unaligned.c b/trunk/arch/mips/kernel/unaligned.c index 8b9c34ffae18..18c4a3c45a31 100644 --- a/trunk/arch/mips/kernel/unaligned.c +++ b/trunk/arch/mips/kernel/unaligned.c @@ -77,7 +77,6 @@ #include #include #include -#include #include #include #include @@ -88,18 +87,9 @@ #define STR(x) __STR(x) #define __STR(x) #x -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 +#ifdef CONFIG_PROC_FS +unsigned long unaligned_instructions; #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, @@ -469,7 +459,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs, goto sigill; } -#ifdef CONFIG_DEBUG_FS +#ifdef CONFIG_PROC_FS unaligned_instructions++; #endif @@ -526,10 +516,6 @@ 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. @@ -560,24 +546,3 @@ asmlinkage void do_ade(struct pt_regs *regs) * 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/trunk/arch/mips/lasat/Kconfig b/trunk/arch/mips/lasat/Kconfig new file mode 100644 index 000000000000..1d2ee8a9be13 --- /dev/null +++ b/trunk/arch/mips/lasat/Kconfig @@ -0,0 +1,15 @@ +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/trunk/arch/mips/lasat/Makefile b/trunk/arch/mips/lasat/Makefile new file mode 100644 index 000000000000..99f5046fdf49 --- /dev/null +++ b/trunk/arch/mips/lasat/Makefile @@ -0,0 +1,14 @@ +# +# 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/trunk/arch/mips/lasat/at93c.c b/trunk/arch/mips/lasat/at93c.c new file mode 100644 index 000000000000..ca26e554615e --- /dev/null +++ b/trunk/arch/mips/lasat/at93c.c @@ -0,0 +1,148 @@ +/* + * Atmel AT93C46 serial eeprom driver + * + * Brian Murphy + * + */ +#include +#include +#include +#include +#include + +#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/trunk/arch/mips/lasat/at93c.h b/trunk/arch/mips/lasat/at93c.h new file mode 100644 index 000000000000..cfe2f99b1d44 --- /dev/null +++ b/trunk/arch/mips/lasat/at93c.h @@ -0,0 +1,18 @@ +/* + * Atmel AT93C46 serial eeprom driver + * + * Brian Murphy + * + */ + +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/trunk/arch/mips/lasat/ds1603.c b/trunk/arch/mips/lasat/ds1603.c new file mode 100644 index 000000000000..7dced67c55eb --- /dev/null +++ b/trunk/arch/mips/lasat/ds1603.c @@ -0,0 +1,183 @@ +/* + * Dallas Semiconductors 1603 RTC driver + * + * Brian Murphy + * + */ +#include +#include +#include +#include +#include + +#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/trunk/arch/mips/lasat/ds1603.h b/trunk/arch/mips/lasat/ds1603.h new file mode 100644 index 000000000000..c2e5c76a379d --- /dev/null +++ b/trunk/arch/mips/lasat/ds1603.h @@ -0,0 +1,33 @@ +/* + * Dallas Semiconductors 1603 RTC driver + * + * Brian Murphy + * + */ +#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/trunk/arch/mips/lasat/image/Makefile b/trunk/arch/mips/lasat/image/Makefile new file mode 100644 index 000000000000..35ecd6483ef6 --- /dev/null +++ b/trunk/arch/mips/lasat/image/Makefile @@ -0,0 +1,53 @@ +# +# MAKEFILE FOR THE MIPS LINUX BOOTLOADER AND ROM DEBUGGER +# +# i-data Networks +# +# Author: Thomas Horsten +# + +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/trunk/arch/mips/lasat/image/head.S b/trunk/arch/mips/lasat/image/head.S new file mode 100644 index 000000000000..efb95f2609c2 --- /dev/null +++ b/trunk/arch/mips/lasat/image/head.S @@ -0,0 +1,31 @@ +#include + + .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/trunk/arch/mips/lasat/image/romscript.normal b/trunk/arch/mips/lasat/image/romscript.normal new file mode 100644 index 000000000000..988f8ad189cb --- /dev/null +++ b/trunk/arch/mips/lasat/image/romscript.normal @@ -0,0 +1,23 @@ +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/trunk/arch/mips/lasat/interrupt.c b/trunk/arch/mips/lasat/interrupt.c new file mode 100644 index 000000000000..9a622b9a1051 --- /dev/null +++ b/trunk/arch/mips/lasat/interrupt.c @@ -0,0 +1,130 @@ +/* + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +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/trunk/arch/mips/lasat/lasat_board.c b/trunk/arch/mips/lasat/lasat_board.c new file mode 100644 index 000000000000..fbe9a87bd0ad --- /dev/null +++ b/trunk/arch/mips/lasat/lasat_board.c @@ -0,0 +1,279 @@ +/* + * Thomas Horsten + * 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 +#include +#include +#include +#include +#include +#include +#include +#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 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/trunk/arch/mips/lasat/lasat_models.h b/trunk/arch/mips/lasat/lasat_models.h new file mode 100644 index 000000000000..ae0c5d0bd403 --- /dev/null +++ b/trunk/arch/mips/lasat/lasat_models.h @@ -0,0 +1,63 @@ +/* + * 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/trunk/arch/mips/lasat/picvue.c b/trunk/arch/mips/lasat/picvue.c new file mode 100644 index 000000000000..9ae82c3ffb07 --- /dev/null +++ b/trunk/arch/mips/lasat/picvue.c @@ -0,0 +1,240 @@ +/* + * Picvue PVC160206 display driver + * + * Brian Murphy + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + * + */ +#include + +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/trunk/arch/mips/lasat/picvue_proc.c b/trunk/arch/mips/lasat/picvue_proc.c new file mode 100644 index 000000000000..cce7cddcdb08 --- /dev/null +++ b/trunk/arch/mips/lasat/picvue_proc.c @@ -0,0 +1,186 @@ +/* + * Picvue PVC160206 display driver + * + * Brian Murphy + * + */ +#include +#include +#include +#include + +#include +#include + +#include + +#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) { + 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; iread_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/trunk/arch/mips/lasat/prom.c b/trunk/arch/mips/lasat/prom.c new file mode 100644 index 000000000000..812c6ac366be --- /dev/null +++ b/trunk/arch/mips/lasat/prom.c @@ -0,0 +1,117 @@ +/* + * PROM interface routines. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "at93c.h" +#include +#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/trunk/arch/mips/lasat/prom.h b/trunk/arch/mips/lasat/prom.h new file mode 100644 index 000000000000..019d45fbd268 --- /dev/null +++ b/trunk/arch/mips/lasat/prom.h @@ -0,0 +1,5 @@ +#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/trunk/arch/mips/lasat/reset.c b/trunk/arch/mips/lasat/reset.c new file mode 100644 index 000000000000..9e22acf03083 --- /dev/null +++ b/trunk/arch/mips/lasat/reset.c @@ -0,0 +1,69 @@ +/* + * Thomas Horsten + * 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 +#include + +#include +#include +#include + +#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/trunk/arch/mips/lasat/setup.c b/trunk/arch/mips/lasat/setup.c new file mode 100644 index 000000000000..488007f13988 --- /dev/null +++ b/trunk/arch/mips/lasat/setup.c @@ -0,0 +1,182 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999 MIPS Technologies, Inc. All rights reserved. + * + * Thomas Horsten + * Copyright (C) 2000 LASAT Networks A/S. + * + * Brian Murphy + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_PICVUE +#include +#endif + +#include "ds1603.h" +#include +#include +#include + +#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/trunk/arch/mips/lasat/sysctl.c b/trunk/arch/mips/lasat/sysctl.c new file mode 100644 index 000000000000..699ab1886ceb --- /dev/null +++ b/trunk/arch/mips/lasat/sysctl.c @@ -0,0 +1,441 @@ +/* + * Thomas Horsten + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/trunk/arch/mips/lasat/sysctl.h b/trunk/arch/mips/lasat/sysctl.h new file mode 100644 index 000000000000..4d139d2adbdf --- /dev/null +++ b/trunk/arch/mips/lasat/sysctl.h @@ -0,0 +1,24 @@ +/* + * 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/trunk/arch/mips/lemote/lm2e/Makefile b/trunk/arch/mips/lemote/lm2e/Makefile deleted file mode 100644 index fb1b48c48cb3..000000000000 --- a/trunk/arch/mips/lemote/lm2e/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# 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/trunk/arch/mips/lemote/lm2e/bonito-irq.c b/trunk/arch/mips/lemote/lm2e/bonito-irq.c deleted file mode 100644 index 8fc3bce7075b..000000000000 --- a/trunk/arch/mips/lemote/lm2e/bonito-irq.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include - -#include - - -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/trunk/arch/mips/lemote/lm2e/dbg_io.c b/trunk/arch/mips/lemote/lm2e/dbg_io.c deleted file mode 100644 index 6c95da3ca76f..000000000000 --- a/trunk/arch/mips/lemote/lm2e/dbg_io.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * 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 -#include -#include - -#include - -#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/trunk/arch/mips/lemote/lm2e/irq.c b/trunk/arch/mips/lemote/lm2e/irq.c deleted file mode 100644 index 05693bceaeaf..000000000000 --- a/trunk/arch/mips/lemote/lm2e/irq.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - -/* - * 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/trunk/arch/mips/lemote/lm2e/mem.c b/trunk/arch/mips/lemote/lm2e/mem.c deleted file mode 100644 index 16cd21587d34..000000000000 --- a/trunk/arch/mips/lemote/lm2e/mem.c +++ /dev/null @@ -1,23 +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. - */ -#include -#include -#include - -/* 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/trunk/arch/mips/lemote/lm2e/pci.c b/trunk/arch/mips/lemote/lm2e/pci.c deleted file mode 100644 index 1ade1cef3899..000000000000 --- a/trunk/arch/mips/lemote/lm2e/pci.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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 -#include -#include -#include -#include - -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/trunk/arch/mips/lemote/lm2e/prom.c b/trunk/arch/mips/lemote/lm2e/prom.c deleted file mode 100644 index 67312d7acf2a..000000000000 --- a/trunk/arch/mips/lemote/lm2e/prom.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 - * - * 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 -#include -#include -#include - -#include -#include - -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/trunk/arch/mips/lemote/lm2e/reset.c b/trunk/arch/mips/lemote/lm2e/reset.c deleted file mode 100644 index 099387a3827a..000000000000 --- a/trunk/arch/mips/lemote/lm2e/reset.c +++ /dev/null @@ -1,41 +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) 2007 Lemote, Inc. & Institute of Computing Technology - * Author: Fuxin Zhang, zhangfx@lemote.com - */ -#include - -#include - -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/trunk/arch/mips/lemote/lm2e/setup.c b/trunk/arch/mips/lemote/lm2e/setup.c deleted file mode 100644 index 0e4d1fa572b5..000000000000 --- a/trunk/arch/mips/lemote/lm2e/setup.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifdef CONFIG_VT -#include -#include -#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/trunk/arch/mips/lib-32/Makefile b/trunk/arch/mips/lib-32/Makefile new file mode 100644 index 000000000000..8b94d4cc5a30 --- /dev/null +++ b/trunk/arch/mips/lib-32/Makefile @@ -0,0 +1,23 @@ +# +# 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/trunk/arch/mips/lib-32/dump_tlb.c b/trunk/arch/mips/lib-32/dump_tlb.c new file mode 100644 index 000000000000..6a68deb51aae --- /dev/null +++ b/trunk/arch/mips/lib-32/dump_tlb.c @@ -0,0 +1,242 @@ +/* + * 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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/trunk/arch/mips/lib-32/r3k_dump_tlb.c b/trunk/arch/mips/lib-32/r3k_dump_tlb.c new file mode 100644 index 000000000000..4f2cb74f0766 --- /dev/null +++ b/trunk/arch/mips/lib-32/r3k_dump_tlb.c @@ -0,0 +1,182 @@ +/* + * 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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/trunk/arch/mips/lib-32/watch.S b/trunk/arch/mips/lib-32/watch.S new file mode 100644 index 000000000000..808b3af1a605 --- /dev/null +++ b/trunk/arch/mips/lib-32/watch.S @@ -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. + * + * 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 +#include +#include + + .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/trunk/arch/mips/lib-64/Makefile b/trunk/arch/mips/lib-64/Makefile new file mode 100644 index 000000000000..8b94d4cc5a30 --- /dev/null +++ b/trunk/arch/mips/lib-64/Makefile @@ -0,0 +1,23 @@ +# +# 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/trunk/arch/mips/lib-64/dump_tlb.c b/trunk/arch/mips/lib-64/dump_tlb.c new file mode 100644 index 000000000000..594df1a05ecc --- /dev/null +++ b/trunk/arch/mips/lib-64/dump_tlb.c @@ -0,0 +1,216 @@ +/* + * 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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/trunk/arch/mips/lib-64/watch.S b/trunk/arch/mips/lib-64/watch.S new file mode 100644 index 000000000000..f91434013695 --- /dev/null +++ b/trunk/arch/mips/lib-64/watch.S @@ -0,0 +1,57 @@ +/* + * 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 +#include +#include + + .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/trunk/arch/mips/lib/Makefile b/trunk/arch/mips/lib/Makefile index 91ed1eb33102..1c1aa9f92f6c 100644 --- a/trunk/arch/mips/lib/Makefile +++ b/trunk/arch/mips/lib/Makefile @@ -8,24 +8,5 @@ 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/trunk/arch/mips/lib/dump_tlb.c b/trunk/arch/mips/lib/dump_tlb.c deleted file mode 100644 index 1a4db7dc77cb..000000000000 --- a/trunk/arch/mips/lib/dump_tlb.c +++ /dev/null @@ -1,100 +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 -#include - -#include -#include -#include - -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/trunk/arch/mips/lib/r3k_dump_tlb.c b/trunk/arch/mips/lib/r3k_dump_tlb.c deleted file mode 100644 index 52f87795ecc3..000000000000 --- a/trunk/arch/mips/lib/r3k_dump_tlb.c +++ /dev/null @@ -1,62 +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 -#include - -#include -#include -#include - -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/trunk/arch/mips/math-emu/cp1emu.c b/trunk/arch/mips/math-emu/cp1emu.c index d7f05b0abe17..80531b35cd61 100644 --- a/trunk/arch/mips/math-emu/cp1emu.c +++ b/trunk/arch/mips/math-emu/cp1emu.c @@ -35,7 +35,6 @@ * better performance by compiling with -msoft-float! */ #include -#include #include #include @@ -1278,36 +1277,3 @@ 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/trunk/arch/mips/mips-boards/malta/Makefile b/trunk/arch/mips/mips-boards/malta/Makefile index a242b0fc377d..377d9e8f250a 100644 --- a/trunk/arch/mips/mips-boards/malta/Makefile +++ b/trunk/arch/mips/mips-boards/malta/Makefile @@ -19,7 +19,6 @@ # under Linux. # -obj-y := malta_int.o malta_platform.o malta_setup.o - +obj-y := malta_int.o malta_setup.o obj-$(CONFIG_MTD) += malta_mtd.o obj-$(CONFIG_MIPS_MT_SMTC) += malta_smtc.o diff --git a/trunk/arch/mips/mips-boards/malta/malta_platform.c b/trunk/arch/mips/mips-boards/malta/malta_platform.c deleted file mode 100644 index 83b9bab3cd3f..000000000000 --- a/trunk/arch/mips/mips-boards/malta/malta_platform.c +++ /dev/null @@ -1,65 +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) 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 -#include -#include - -#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 "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("8250 UART probe driver for the Malta CBUS UART"); diff --git a/trunk/arch/mips/mipssim/Makefile b/trunk/arch/mips/mips-boards/sim/Makefile similarity index 100% rename from trunk/arch/mips/mipssim/Makefile rename to trunk/arch/mips/mips-boards/sim/Makefile diff --git a/trunk/arch/mips/mipssim/sim_cmdline.c b/trunk/arch/mips/mips-boards/sim/sim_cmdline.c similarity index 100% rename from trunk/arch/mips/mipssim/sim_cmdline.c rename to trunk/arch/mips/mips-boards/sim/sim_cmdline.c diff --git a/trunk/arch/mips/mipssim/sim_console.c b/trunk/arch/mips/mips-boards/sim/sim_console.c similarity index 98% rename from trunk/arch/mips/mipssim/sim_console.c rename to trunk/arch/mips/mips-boards/sim/sim_console.c index a2f41672cd5d..de595a9ccb27 100644 --- a/trunk/arch/mips/mipssim/sim_console.c +++ b/trunk/arch/mips/mips-boards/sim/sim_console.c @@ -18,8 +18,8 @@ * written by Ralf Baechle */ #include -#include #include +#include static inline unsigned int serial_in(int offset) { diff --git a/trunk/arch/mips/mipssim/sim_mem.c b/trunk/arch/mips/mips-boards/sim/sim_mem.c similarity index 99% rename from trunk/arch/mips/mipssim/sim_mem.c rename to trunk/arch/mips/mips-boards/sim/sim_mem.c index 2312483eb838..e408ef0bcd6e 100644 --- a/trunk/arch/mips/mipssim/sim_mem.c +++ b/trunk/arch/mips/mips-boards/sim/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/trunk/arch/mips/mipssim/sim_platform.c b/trunk/arch/mips/mips-boards/sim/sim_platform.c similarity index 100% rename from trunk/arch/mips/mipssim/sim_platform.c rename to trunk/arch/mips/mips-boards/sim/sim_platform.c diff --git a/trunk/arch/mips/mipssim/sim_setup.c b/trunk/arch/mips/mips-boards/sim/sim_setup.c similarity index 95% rename from trunk/arch/mips/mipssim/sim_setup.c rename to trunk/arch/mips/mips-boards/sim/sim_setup.c index 3643582bdade..b705f09e57c3 100644 --- a/trunk/arch/mips/mipssim/sim_setup.c +++ b/trunk/arch/mips/mips-boards/sim/sim_setup.c @@ -19,18 +19,18 @@ #include #include #include -#include -#include #include -#include #include #include #include #include #include +#include #include #include +#include +#include #include #include #include @@ -62,7 +62,7 @@ void __init plat_mem_setup(void) #endif } -void __init prom_init(void) +void prom_init(void) { set_io_port_base(0xbfd00000); diff --git a/trunk/arch/mips/mipssim/sim_smp.c b/trunk/arch/mips/mips-boards/sim/sim_smp.c similarity index 89% rename from trunk/arch/mips/mipssim/sim_smp.c rename to trunk/arch/mips/mips-boards/sim/sim_smp.c index 38fa807b99f9..cb47863ecf10 100644 --- a/trunk/arch/mips/mipssim/sim_smp.c +++ b/trunk/arch/mips/mips-boards/sim/sim_smp.c @@ -22,13 +22,13 @@ #include #include #include -#include - #include #include #include #include +#include #include +#include #ifdef CONFIG_MIPS_MT_SMTC #include #endif /* CONFIG_MIPS_MT_SMTC */ @@ -73,19 +73,11 @@ 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 plat_prepare_cpus(unsigned int max_cpus) +void prom_prepare_cpus(unsigned int max_cpus) { #ifdef CONFIG_MIPS_MT_SMTC /* @@ -93,8 +85,8 @@ void plat_prepare_cpus(unsigned int max_cpus) * but it may be multithreaded. */ - if (read_c0_config3() & (1 << 2)) { - mipsmt_prepare_cpus(); + if (read_c0_config3() & (1<<2)) { + mipsmt_prepare_cpus(max_cpus); } #endif /* CONFIG_MIPS_MT_SMTC */ } diff --git a/trunk/arch/mips/mipssim/sim_time.c b/trunk/arch/mips/mips-boards/sim/sim_time.c similarity index 91% rename from trunk/arch/mips/mipssim/sim_time.c rename to trunk/arch/mips/mips-boards/sim/sim_time.c index 874a18e8ac24..7224ffe31d36 100644 --- a/trunk/arch/mips/mipssim/sim_time.c +++ b/trunk/arch/mips/mips-boards/sim/sim_time.c @@ -5,10 +5,10 @@ #include #include #include -#include -#include #include +#include +#include #include #include #include @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -36,7 +37,8 @@ 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 */ /* @@ -74,10 +76,8 @@ 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,8 +85,7 @@ 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); @@ -153,15 +152,17 @@ 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(KERN_INFO "CPU frequency %d.%02d MHz\n", est_freq / 1000000, - (est_freq % 1000000) * 100 / 1000000); + printk("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); } @@ -179,7 +180,8 @@ 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/trunk/arch/mips/mipssim/sim_int.c b/trunk/arch/mips/mipssim/sim_int.c deleted file mode 100644 index d86b37235cf6..000000000000 --- a/trunk/arch/mips/mipssim/sim_int.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include -#include - -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/trunk/arch/mips/mm/Makefile b/trunk/arch/mips/mm/Makefile index 19a0e544c4e9..293697b15603 100644 --- a/trunk/arch/mips/mm/Makefile +++ b/trunk/arch/mips/mm/Makefile @@ -9,7 +9,6 @@ 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/trunk/arch/mips/mm/c-r4k.c b/trunk/arch/mips/mm/c-r4k.c index be96231dccb6..df04a315d830 100644 --- a/trunk/arch/mips/mm/c-r4k.c +++ b/trunk/arch/mips/mm/c-r4k.c @@ -335,10 +335,6 @@ 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(); @@ -852,24 +848,6 @@ 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."); @@ -985,14 +963,6 @@ 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", @@ -1066,24 +1036,6 @@ static int __init probe_scache(void) return 1; } -#if defined(CONFIG_CPU_LOONGSON2) -static void __init loongson2_sc_init(void) -{ - struct cpuinfo_mips *c = ¤t_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); @@ -1133,12 +1085,6 @@ 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/trunk/arch/mips/mm/c-sb1.c b/trunk/arch/mips/mm/c-sb1.c index 6f9bd7fbd481..9ea460b16bda 100644 --- a/trunk/arch/mips/mm/c-sb1.c +++ b/trunk/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 __init sb1_cache_init(void) +void sb1_cache_init(void) { extern char except_vec2_sb1; diff --git a/trunk/arch/mips/mm/cache.c b/trunk/arch/mips/mm/cache.c index 81f925a9a731..abf99b1eba13 100644 --- a/trunk/arch/mips/mm/cache.c +++ b/trunk/arch/mips/mm/cache.c @@ -6,8 +6,6 @@ * Copyright (C) 1994 - 2003, 07 by Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 2007 MIPS Technologies, Inc. */ -#include -#include #include #include #include @@ -166,11 +164,3 @@ 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/trunk/arch/mips/mm/tlb-r4k.c b/trunk/arch/mips/mm/tlb-r4k.c index dcd6913dc1ff..65160d4984d9 100644 --- a/trunk/arch/mips/mm/tlb-r4k.c +++ b/trunk/arch/mips/mm/tlb-r4k.c @@ -48,22 +48,6 @@ 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; @@ -89,7 +73,6 @@ void local_flush_tlb_all(void) } tlbw_use_hazard(); write_c0_entryhi(old_ctx); - FLUSH_ITLB; EXIT_CRITICAL(flags); } @@ -153,7 +136,6 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, } else { drop_mmu_context(mm, cpu); } - FLUSH_ITLB; EXIT_CRITICAL(flags); } } @@ -196,7 +178,6 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) } else { local_flush_tlb_all(); } - FLUSH_ITLB; EXIT_CRITICAL(flags); } @@ -229,7 +210,6 @@ 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); } } @@ -261,7 +241,7 @@ void local_flush_tlb_one(unsigned long page) tlbw_use_hazard(); } write_c0_entryhi(oldpid); - FLUSH_ITLB; + EXIT_CRITICAL(flags); } @@ -313,7 +293,6 @@ 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/trunk/arch/mips/mm/tlbex.c b/trunk/arch/mips/mm/tlbex.c index 4ec0964b8394..e7149290d1cb 100644 --- a/trunk/arch/mips/mm/tlbex.c +++ b/trunk/arch/mips/mm/tlbex.c @@ -893,7 +893,6 @@ 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; @@ -1277,8 +1276,7 @@ static void __init build_r4000_tlb_refill_handler(void) * need three, with the second nop'ed and the third being * unused. */ - /* Loongson2 ebase is different than r4k, we have more space */ -#if defined(CONFIG_32BIT) || defined(CONFIG_CPU_LOONGSON2) +#ifdef CONFIG_32BIT if ((p - tlb_handler) > 64) panic("TLB refill handler space exceeded"); #else @@ -1291,7 +1289,7 @@ static void __init build_r4000_tlb_refill_handler(void) /* * Now fold the handler in the TLB refill handler space. */ -#if defined(CONFIG_32BIT) || defined(CONFIG_CPU_LOONGSON2) +#ifdef CONFIG_32BIT f = final_handler; /* Simplest case, just copy the handler. */ copy_handler(relocs, labels, tlb_handler, p, f); @@ -1338,7 +1336,7 @@ static void __init build_r4000_tlb_refill_handler(void) final_len); f = final_handler; -#if defined(CONFIG_64BIT) && !defined(CONFIG_CPU_LOONGSON2) +#ifdef CONFIG_64BIT if (final_len > 32) final_len = 64; else diff --git a/trunk/arch/mips/momentum/ocelot_3/Makefile b/trunk/arch/mips/momentum/ocelot_3/Makefile new file mode 100644 index 000000000000..d5a090a85a15 --- /dev/null +++ b/trunk/arch/mips/momentum/ocelot_3/Makefile @@ -0,0 +1,8 @@ +# +# 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/trunk/arch/mips/momentum/ocelot_3/irq.c b/trunk/arch/mips/momentum/ocelot_3/irq.c new file mode 100644 index 000000000000..3862d1d1add4 --- /dev/null +++ b/trunk/arch/mips/momentum/ocelot_3/irq.c @@ -0,0 +1,109 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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/trunk/arch/mips/pmc-sierra/msp71xx/msp_pci.c b/trunk/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h similarity index 53% rename from trunk/arch/mips/pmc-sierra/msp71xx/msp_pci.c rename to trunk/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h index f764fe7748d6..5710a9029f1c 100644 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_pci.c +++ b/trunk/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h @@ -1,7 +1,7 @@ /* - * The setup file for PCI related hardware on PMC-Sierra MSP processors. + * Ocelot-3 Board Register Definitions * - * Copyright 2005-2006 PMC-Sierra, Inc. + * (C) 2002 Momentum Computer 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,29 +22,38 @@ * 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 */ -#include - -#include -#include - -extern void msp_pci_init(void); +#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)) -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/trunk/arch/mips/momentum/ocelot_3/platform.c b/trunk/arch/mips/momentum/ocelot_3/platform.c new file mode 100644 index 000000000000..44e4c3fc7403 --- /dev/null +++ b/trunk/arch/mips/momentum/ocelot_3/platform.c @@ -0,0 +1,208 @@ +#include +#include +#include +#include +#include + +#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 = ð0_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 = ð1_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 = ð2_pd, + }, +}; + +static struct platform_device *mv643xx_eth_pd_devs[] __initdata = { + &mv643xx_eth_shared_device, + ð0_device, + ð1_device, + ð2_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/trunk/arch/mips/momentum/ocelot_3/prom.c b/trunk/arch/mips/momentum/ocelot_3/prom.c new file mode 100644 index 000000000000..8e02df63578a --- /dev/null +++ b/trunk/arch/mips/momentum/ocelot_3/prom.c @@ -0,0 +1,189 @@ +/* + * Copyright 2002 Momentum Computer Inc. + * Author: Matthew Dharm + * + * 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 +#include +#include + +#include +#include +#include +#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/trunk/arch/mips/momentum/ocelot_3/reset.c b/trunk/arch/mips/momentum/ocelot_3/reset.c new file mode 100644 index 000000000000..9d86d2468376 --- /dev/null +++ b/trunk/arch/mips/momentum/ocelot_3/reset.c @@ -0,0 +1,59 @@ +/* + * 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 + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +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/trunk/arch/mips/momentum/ocelot_3/setup.c b/trunk/arch/mips/momentum/ocelot_3/setup.c new file mode 100644 index 000000000000..ff0829f81116 --- /dev/null +++ b/trunk/arch/mips/momentum/ocelot_3/setup.c @@ -0,0 +1,398 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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/trunk/arch/mips/momentum/ocelot_c/Makefile b/trunk/arch/mips/momentum/ocelot_c/Makefile new file mode 100644 index 000000000000..d69161aa1675 --- /dev/null +++ b/trunk/arch/mips/momentum/ocelot_c/Makefile @@ -0,0 +1,8 @@ +# +# 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/trunk/arch/mips/momentum/ocelot_c/cpci-irq.c b/trunk/arch/mips/momentum/ocelot_c/cpci-irq.c new file mode 100644 index 000000000000..186a140fd2a9 --- /dev/null +++ b/trunk/arch/mips/momentum/ocelot_c/cpci-irq.c @@ -0,0 +1,100 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#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/trunk/arch/mips/momentum/ocelot_c/dbg_io.c b/trunk/arch/mips/momentum/ocelot_c/dbg_io.c new file mode 100644 index 000000000000..32d6fb4ee679 --- /dev/null +++ b/trunk/arch/mips/momentum/ocelot_c/dbg_io.c @@ -0,0 +1,121 @@ + +#include /* 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/trunk/arch/mips/momentum/ocelot_c/irq.c b/trunk/arch/mips/momentum/ocelot_c/irq.c new file mode 100644 index 000000000000..844d566c9de3 --- /dev/null +++ b/trunk/arch/mips/momentum/ocelot_c/irq.c @@ -0,0 +1,107 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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/trunk/arch/mips/pmc-sierra/msp71xx/msp_elb.c b/trunk/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h similarity index 53% rename from trunk/arch/mips/pmc-sierra/msp71xx/msp_elb.c rename to trunk/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h index 3e9641007216..f0f5581dcb50 100644 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_elb.c +++ b/trunk/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h @@ -1,9 +1,7 @@ /* - * Sets up the proper Chip Select configuration registers. It is assumed that - * PMON sets up the ADDR and MASK registers properly. + * Ocelot-C Board Register Definitions * - * Copyright 2005-2006 PMC-Sierra, Inc. - * Author: Marc St-Jean, Marc_St-Jean@pmc-sierra.com + * (C) 2002 Momentum Computer 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 @@ -24,23 +22,40 @@ * 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] */ -#include -#include -#include +#ifndef __OCELOT_C_FPGA_H__ +#define __OCELOT_C_FPGA_H__ + -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; +#ifdef CONFIG_64BIT +#define OCELOT_C_CS0_ADDR (0xfffffffffc000000) +#else +#define OCELOT_C_CS0_ADDR (0xfc000000) #endif - return 0; -} -subsys_initcall(msp_elb_setup); +#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 diff --git a/trunk/arch/mips/momentum/ocelot_c/platform.c b/trunk/arch/mips/momentum/ocelot_c/platform.c new file mode 100644 index 000000000000..7780aa0c6555 --- /dev/null +++ b/trunk/arch/mips/momentum/ocelot_c/platform.c @@ -0,0 +1,183 @@ +#include +#include +#include +#include +#include + +#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 = ð0_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 = ð1_pd, + }, +}; + +static struct platform_device *mv643xx_eth_pd_devs[] __initdata = { + &mv643xx_eth_shared_device, + ð0_device, + ð1_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/trunk/arch/mips/momentum/ocelot_c/prom.c b/trunk/arch/mips/momentum/ocelot_c/prom.c new file mode 100644 index 000000000000..b689ceea8cfb --- /dev/null +++ b/trunk/arch/mips/momentum/ocelot_c/prom.c @@ -0,0 +1,183 @@ +/* + * Copyright 2002 Momentum Computer Inc. + * Author: Matthew Dharm + * + * 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 +#include +#include +#include +#include + +#include +#include +#include + +#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/trunk/arch/mips/momentum/ocelot_c/reset.c b/trunk/arch/mips/momentum/ocelot_c/reset.c new file mode 100644 index 000000000000..3fdcb64ff1e6 --- /dev/null +++ b/trunk/arch/mips/momentum/ocelot_c/reset.c @@ -0,0 +1,58 @@ +/* + * 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 + * + * Louis Hamilton, Red Hat, Inc. + * hamilton@redhat.com [MIPS64 modifications] + */ +#include +#include +#include +#include +#include +#include +#include +#include + +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/trunk/arch/mips/momentum/ocelot_c/setup.c b/trunk/arch/mips/momentum/ocelot_c/setup.c new file mode 100644 index 000000000000..0b6b2338cfb4 --- /dev/null +++ b/trunk/arch/mips/momentum/ocelot_c/setup.c @@ -0,0 +1,362 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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/trunk/arch/mips/momentum/ocelot_c/uart-irq.c b/trunk/arch/mips/momentum/ocelot_c/uart-irq.c new file mode 100644 index 000000000000..de1a31ee52f3 --- /dev/null +++ b/trunk/arch/mips/momentum/ocelot_c/uart-irq.c @@ -0,0 +1,91 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#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/trunk/arch/mips/pci/Makefile b/trunk/arch/mips/pci/Makefile index f26ede001a0b..aba3dbf47eda 100644 --- a/trunk/arch/mips/pci/Makefile +++ b/trunk/arch/mips/pci/Makefile @@ -9,7 +9,9 @@ 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 @@ -20,17 +22,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_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_MOMENCO_OCELOT_3) += fixup-ocelot3.o +obj-$(CONFIG_MOMENCO_OCELOT_C) += fixup-ocelot-c.o pci-ocelot-c.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/trunk/arch/mips/pci/fixup-atlas.c b/trunk/arch/mips/pci/fixup-atlas.c index 45224fd2c7ba..c6cd6e9cdfbc 100644 --- a/trunk/arch/mips/pci/fixup-atlas.c +++ b/trunk/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(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { return irq_tab[slot][pin]; } diff --git a/trunk/arch/mips/pci/fixup-au1000.c b/trunk/arch/mips/pci/fixup-au1000.c index ca0276c8070a..c2f8304fe55b 100644 --- a/trunk/arch/mips/pci/fixup-au1000.c +++ b/trunk/arch/mips/pci/fixup-au1000.c @@ -35,7 +35,7 @@ extern char irq_tab_alchemy[][5]; -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { return irq_tab_alchemy[slot][pin]; } diff --git a/trunk/arch/mips/pci/fixup-capcella.c b/trunk/arch/mips/pci/fixup-capcella.c index 1416bca6d1a3..1e530751936c 100644 --- a/trunk/arch/mips/pci/fixup-capcella.c +++ b/trunk/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(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { return irq_tab_capcella[slot][pin]; } diff --git a/trunk/arch/mips/pci/fixup-cobalt.c b/trunk/arch/mips/pci/fixup-cobalt.c index 7fc475f7eae5..d57ffd7242ca 100644 --- a/trunk/arch/mips/pci/fixup-cobalt.c +++ b/trunk/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(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { if (cobalt_board_id < COBALT_BRD_ID_QUBE2) return irq_tab_qube1[slot]; diff --git a/trunk/arch/mips/pci/fixup-emma2rh.c b/trunk/arch/mips/pci/fixup-emma2rh.c index a2705895561d..7abcfd175d43 100644 --- a/trunk/arch/mips/pci/fixup-emma2rh.c +++ b/trunk/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(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { return irq_map[slot][pin]; } diff --git a/trunk/arch/mips/pci/fixup-excite.c b/trunk/arch/mips/pci/fixup-excite.c index cd64d9f177c4..1da696d43f00 100644 --- a/trunk/arch/mips/pci/fixup-excite.c +++ b/trunk/arch/mips/pci/fixup-excite.c @@ -21,7 +21,7 @@ #include #include -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { if (pin == 0) return -1; diff --git a/trunk/arch/mips/pci/fixup-ip32.c b/trunk/arch/mips/pci/fixup-ip32.c index 190fffd08d3e..3e66b0aa63ca 100644 --- a/trunk/arch/mips/pci/fixup-ip32.c +++ b/trunk/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(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { return irq_tab_mace[slot][pin]; } diff --git a/trunk/arch/mips/pci/fixup-jmr3927.c b/trunk/arch/mips/pci/fixup-jmr3927.c index e974394be7bc..73d18503517c 100644 --- a/trunk/arch/mips/pci/fixup-jmr3927.c +++ b/trunk/arch/mips/pci/fixup-jmr3927.c @@ -33,7 +33,7 @@ #include -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { unsigned char irq = pin; diff --git a/trunk/arch/mips/pci/fixup-lm2e.c b/trunk/arch/mips/pci/fixup-lm2e.c deleted file mode 100644 index e18ae4f574c1..000000000000 --- a/trunk/arch/mips/pci/fixup-lm2e.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * 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 -#include -#include - -/* 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/trunk/arch/mips/pci/fixup-malta.c b/trunk/arch/mips/pci/fixup-malta.c index 0f48498bc231..bf2c41d1e9c5 100644 --- a/trunk/arch/mips/pci/fixup-malta.c +++ b/trunk/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(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { int virq; virq = irq_tab[slot][pin]; diff --git a/trunk/arch/mips/pci/fixup-mpc30x.c b/trunk/arch/mips/pci/fixup-mpc30x.c index 591159625722..3c9ae41f7517 100644 --- a/trunk/arch/mips/pci/fixup-mpc30x.c +++ b/trunk/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(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { if (slot == 30) return internal_func_irqs[PCI_FUNC(dev->devfn)]; diff --git a/trunk/arch/mips/pci/fixup-ocelot-c.c b/trunk/arch/mips/pci/fixup-ocelot-c.c new file mode 100644 index 000000000000..d45494807a33 --- /dev/null +++ b/trunk/arch/mips/pci/fixup-ocelot-c.c @@ -0,0 +1,41 @@ +/* + * Copyright 2002 Momentum Computer Inc. + * Author: Matthew Dharm + * + * 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 +#include +#include +#include + +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/trunk/arch/mips/pci/fixup-ocelot3.c b/trunk/arch/mips/pci/fixup-ocelot3.c new file mode 100644 index 000000000000..ececc03ec620 --- /dev/null +++ b/trunk/arch/mips/pci/fixup-ocelot3.c @@ -0,0 +1,41 @@ +/* + * 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 +#include +#include +#include + +/* + * 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/trunk/arch/mips/pci/fixup-pmcmsp.c b/trunk/arch/mips/pci/fixup-pmcmsp.c deleted file mode 100644 index 00261211dbfa..000000000000 --- a/trunk/arch/mips/pci/fixup-pmcmsp.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * 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 -#include -#include -#include - -#include - -#include -#include - -/* 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/trunk/arch/mips/pci/fixup-pnx8550.c b/trunk/arch/mips/pci/fixup-pnx8550.c index 96857ac63bf5..50546dab6689 100644 --- a/trunk/arch/mips/pci/fixup-pnx8550.c +++ b/trunk/arch/mips/pci/fixup-pnx8550.c @@ -45,7 +45,7 @@ void __init pcibios_fixup(void) /* nothing to do here */ } -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { return pnx8550_irq_tab[slot][pin]; } diff --git a/trunk/arch/mips/pci/fixup-rbtx4927.c b/trunk/arch/mips/pci/fixup-rbtx4927.c index 3cdbecb8e714..ceeb1860895a 100644 --- a/trunk/arch/mips/pci/fixup-rbtx4927.c +++ b/trunk/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(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { unsigned char irq; diff --git a/trunk/arch/mips/pci/fixup-sni.c b/trunk/arch/mips/pci/fixup-sni.c index a45bedd17233..36e5fb1b3786 100644 --- a/trunk/arch/mips/pci/fixup-sni.c +++ b/trunk/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(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { switch (sni_brd_type) { case SNI_BRD_PCI_TOWER: diff --git a/trunk/arch/mips/pci/fixup-tb0219.c b/trunk/arch/mips/pci/fixup-tb0219.c index 720a2b720c5c..734f2b71e164 100644 --- a/trunk/arch/mips/pci/fixup-tb0219.c +++ b/trunk/arch/mips/pci/fixup-tb0219.c @@ -23,7 +23,7 @@ #include -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { int irq = -1; diff --git a/trunk/arch/mips/pci/fixup-tb0226.c b/trunk/arch/mips/pci/fixup-tb0226.c index e3eedf4bf9bd..c9e7cb4361a1 100644 --- a/trunk/arch/mips/pci/fixup-tb0226.c +++ b/trunk/arch/mips/pci/fixup-tb0226.c @@ -23,7 +23,7 @@ #include #include -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { int irq = -1; diff --git a/trunk/arch/mips/pci/fixup-tb0287.c b/trunk/arch/mips/pci/fixup-tb0287.c index 267ab3dc3d42..fbe6bcb28199 100644 --- a/trunk/arch/mips/pci/fixup-tb0287.c +++ b/trunk/arch/mips/pci/fixup-tb0287.c @@ -22,7 +22,7 @@ #include -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { unsigned char bus; int irq = -1; diff --git a/trunk/arch/mips/pci/fixup-tx4938.c b/trunk/arch/mips/pci/fixup-tx4938.c index 2485f47dfe6f..f455520ada88 100644 --- a/trunk/arch/mips/pci/fixup-tx4938.c +++ b/trunk/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(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { unsigned char irq = 0; diff --git a/trunk/arch/mips/pci/fixup-vr4133.c b/trunk/arch/mips/pci/fixup-vr4133.c index de5e5f6bbf4c..a8d9d22b13df 100644 --- a/trunk/arch/mips/pci/fixup-vr4133.c +++ b/trunk/arch/mips/pci/fixup-vr4133.c @@ -169,7 +169,7 @@ void i8259_init(void) } #endif -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { extern int pci_probe_only; pci_probe_only = 1; diff --git a/trunk/arch/mips/pci/fixup-wrppmc.c b/trunk/arch/mips/pci/fixup-wrppmc.c index 3d277549d5df..3357c1300bb1 100644 --- a/trunk/arch/mips/pci/fixup-wrppmc.c +++ b/trunk/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(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { return pci_irq_tab[slot][pin]; } diff --git a/trunk/arch/mips/pci/fixup-yosemite.c b/trunk/arch/mips/pci/fixup-yosemite.c index fdafb13a793b..81d77a587a51 100644 --- a/trunk/arch/mips/pci/fixup-yosemite.c +++ b/trunk/arch/mips/pci/fixup-yosemite.c @@ -26,7 +26,7 @@ #include #include -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { if (pin == 0) return -1; diff --git a/trunk/arch/mips/pci/ops-bonito64.c b/trunk/arch/mips/pci/ops-bonito64.c index f742c51acf0d..dc35270b65a2 100644 --- a/trunk/arch/mips/pci/ops-bonito64.c +++ b/trunk/arch/mips/pci/ops-bonito64.c @@ -29,60 +29,83 @@ #define PCI_ACCESS_READ 0 #define PCI_ACCESS_WRITE 1 -#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) +/* + * PCI configuration cycle AD bus definition + */ +/* Type 0 */ +#define PCI_CFG_TYPE0_REG_SHF 0 +#define PCI_CFG_TYPE0_FUNC_SHF 8 +/* 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) { - u32 busnum = bus->number; - u32 addr, type; + unsigned char busnum = bus->number; u32 dummy; - void *addrp; - int device = PCI_SLOT(devfn); - int function = PCI_FUNC(devfn); - int reg = where & ~3; + u64 pci_addr; - if (busnum == 0) { - /* Type 0 configuration for onboard PCI bus */ - if (device > MAX_DEV_NUM) - return -1; + /* Algorithmics Bonito64 system controller. */ - addr = (1 << (device + ID_SEL_BEGIN)) | (function << 8) | reg; - type = 0; + 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 { - /* Type 1 configuration for offboard PCI bus */ - addr = (busnum << 16) | (device << 11) | (function << 8) | reg; - type = 0x10000; + /* Bus number */ + pci_addr = busnum << PCI_CFG_TYPE1_BUS_SHF; + + /* Device number */ + pci_addr |= + PCI_SLOT(devfn) << PCI_CFG_TYPE1_DEV_SHF; } - /* Clear aborts */ - BONITO_PCICMD |= BONITO_PCICMD_MABORT_CLR | BONITO_PCICMD_MTABORT_CLR; + /* 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; + + if (busnum == 0) { + /* Type 0 */ + BONITO_PCIMAP_CFG = pci_addr >> 16; + } else { + /* Type 1 */ + BONITO_PCIMAP_CFG = (pci_addr >> 16) | 0x10000; + } - BONITO_PCIMAP_CFG = (addr >> 16) | type; + pci_addr &= 0xffff; /* Flush Bonito register block */ dummy = BONITO_PCIMAP_CFG; - mmiowb(); + iob(); /* sync */ - addrp = CFG_SPACE_REG(addr & 0xffff); + /* Perform access */ if (access_type == PCI_ACCESS_WRITE) { - writel(cpu_to_le32(*data), addrp); -#ifndef CONFIG_LEMOTE_FULONG + *(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr) = *(u32 *) data; + /* Wait till done */ while (BONITO_PCIMSTAT & 0xF); -#endif } else { - *data = le32_to_cpu(readl(addrp)); + *(u32 *) data = *(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr); } /* Detect Master/Target abort */ @@ -98,7 +121,6 @@ static int bonito64_pcibios_config_access(unsigned char access_type, } return 0; - } diff --git a/trunk/arch/mips/pci/ops-marvell.c b/trunk/arch/mips/pci/ops-marvell.c new file mode 100644 index 000000000000..1ac5c59199d1 --- /dev/null +++ b/trunk/arch/mips/pci/ops-marvell.c @@ -0,0 +1,93 @@ +/* + * 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 +#include +#include + +#include + +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/trunk/arch/mips/pci/ops-nile4.c b/trunk/arch/mips/pci/ops-nile4.c new file mode 100644 index 000000000000..a8d38dc8c504 --- /dev/null +++ b/trunk/arch/mips/pci/ops-nile4.c @@ -0,0 +1,147 @@ +#include +#include +#include +#include + +#include +#include +#include + +#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/trunk/arch/mips/pci/ops-pmcmsp.c b/trunk/arch/mips/pci/ops-pmcmsp.c deleted file mode 100644 index 09fa007c1d1b..000000000000 --- a/trunk/arch/mips/pci/ops-pmcmsp.c +++ /dev/null @@ -1,994 +0,0 @@ -/* - * 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 - * - * 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 -#include -#include - -#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS) -#include -#include -#endif /* CONFIG_PROC_FS && PCI_COUNTERS */ - -#include -#include - -#include -#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL) -#include -#endif - -#include -#include -#include -#include -#include - -#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/trunk/arch/mips/pci/ops-tx4938.c b/trunk/arch/mips/pci/ops-tx4938.c index a450c4062031..445007084515 100644 --- a/trunk/arch/mips/pci/ops-tx4938.c +++ b/trunk/arch/mips/pci/ops-tx4938.c @@ -46,63 +46,50 @@ struct resource tx4938_pcic1_pci_mem_resource = { .flags = IORESOURCE_MEM }; -static int mkaddr(int bus, int dev_fn, int where, - struct tx4938_pcic_reg *pcicptr) +static int mkaddr(int bus, int dev_fn, int where, int *flagsp) { if (bus > 0) { /* Type 1 configuration */ - pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) | + tx4938_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 */ - pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) | + tx4938_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) | ((dev_fn & 0xff) << 0x08) | (where & 0xfc); } /* clear M_ABORT and Disable M_ABORT Int. */ - pcicptr->pcistatus = - (pcicptr->pcistatus & 0x0000ffff) | + tx4938_pcicptr->pcistatus = + (tx4938_pcicptr->pcistatus & 0x0000ffff) | (PCI_STATUS_REC_MASTER_ABORT << 16); - pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT; + tx4938_pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT; return 0; } -static int check_abort(struct tx4938_pcic_reg *pcicptr) +static int check_abort(int flags) { int code = PCIBIOS_SUCCESSFUL; /* wait write cycle completion before checking error status */ - while (pcicptr->pcicstatus & TX4938_PCIC_PCICSTATUS_IWB) + while (tx4938_pcicptr->pcicstatus & TX4938_PCIC_PCICSTATUS_IWB) ; - if (pcicptr->pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) { - pcicptr->pcistatus = - (pcicptr-> + if (tx4938_pcicptr->pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) { + tx4938_pcicptr->pcistatus = + (tx4938_pcicptr-> pcistatus & 0x0000ffff) | (PCI_STATUS_REC_MASTER_ABORT << 16); - pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT; + tx4938_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 retval, dev, busno, func; - struct tx4938_pcic_reg *pcicptr = pci_bus_to_pcicptr(bus); - void __iomem *cfgdata = - (void __iomem *)(unsigned long)&pcicptr->g2pcfgdata; + int flags, retval, dev, busno, func; dev = PCI_SLOT(devfn); func = PCI_FUNC(devfn); @@ -114,32 +101,32 @@ static int tx4938_pcibios_read_config(struct pci_bus *bus, unsigned int devfn, busno = 0; } - if (mkaddr(busno, devfn, where, pcicptr)) + if (mkaddr(busno, devfn, where, &flags)) return -1; switch (size) { case 1: + *val = *(volatile u8 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata | #ifdef __BIG_ENDIAN - cfgdata += (where & 3) ^ 3; + ((where & 3) ^ 3)); #else - cfgdata += where & 3; + (where & 3)); #endif - *val = __raw_readb(cfgdata); break; case 2: + *val = *(volatile u16 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata | #ifdef __BIG_ENDIAN - cfgdata += (where & 2) ^ 2; + ((where & 3) ^ 2)); #else - cfgdata += where & 2; + (where & 3)); #endif - *val = __raw_readw(cfgdata); break; case 4: - *val = __raw_readl(cfgdata); + *val = tx4938_pcicptr->g2pcfgdata; break; } - retval = check_abort(pcicptr); + retval = check_abort(flags); if (retval == PCIBIOS_DEVICE_NOT_FOUND) *val = 0xffffffff; @@ -149,10 +136,7 @@ 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 dev, busno, func; - struct tx4938_pcic_reg *pcicptr = pci_bus_to_pcicptr(bus); - void __iomem *cfgdata = - (void __iomem *)(unsigned long)&pcicptr->g2pcfgdata; + int flags, dev, busno, func; busno = bus->number; dev = PCI_SLOT(devfn); @@ -165,32 +149,32 @@ static int tx4938_pcibios_write_config(struct pci_bus *bus, unsigned int devfn, busno = 0; } - if (mkaddr(busno, devfn, where, pcicptr)) + if (mkaddr(busno, devfn, where, &flags)) return -1; switch (size) { case 1: + *(volatile u8 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata | #ifdef __BIG_ENDIAN - cfgdata += (where & 3) ^ 3; + ((where & 3) ^ 3)) = val; #else - cfgdata += where & 3; + (where & 3)) = val; #endif - __raw_writeb(val, cfgdata); break; case 2: + *(volatile u16 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata | #ifdef __BIG_ENDIAN - cfgdata += (where & 2) ^ 2; + ((where & 0x3) ^ 0x2)) = val; #else - cfgdata += where & 2; + (where & 3)) = val; #endif - __raw_writew(val, cfgdata); break; case 4: - __raw_writel(val, cfgdata); + tx4938_pcicptr->g2pcfgdata = val; break; } - return check_abort(pcicptr); + return check_abort(flags); } struct pci_ops tx4938_pci_ops = { diff --git a/trunk/arch/mips/pci/pci-bcm1480.c b/trunk/arch/mips/pci/pci-bcm1480.c index 2b4e30c7d105..d7b9e1349f6d 100644 --- a/trunk/arch/mips/pci/pci-bcm1480.c +++ b/trunk/arch/mips/pci/pci-bcm1480.c @@ -74,9 +74,8 @@ static inline void WRITECFG32(u32 addr, u32 data) *(u32 *)(cfg_space + (addr & ~3)) = data; } -int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - This is b0rked. return dev->irq; } diff --git a/trunk/arch/mips/pci/pci-ddb5477.c b/trunk/arch/mips/pci/pci-ddb5477.c index 7363e1877842..d071bc375b11 100644 --- a/trunk/arch/mips/pci/pci-ddb5477.c +++ b/trunk/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(const struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { int slot_num; unsigned char *slot_irq_map; diff --git a/trunk/arch/mips/pci/pci-ev64120.c b/trunk/arch/mips/pci/pci-ev64120.c new file mode 100644 index 000000000000..a84f594b5a18 --- /dev/null +++ b/trunk/arch/mips/pci/pci-ev64120.c @@ -0,0 +1,22 @@ +#include +#include + +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/trunk/arch/mips/pci/pci-ip27.c b/trunk/arch/mips/pci/pci-ip27.c index a322543ac34e..405ce0152739 100644 --- a/trunk/arch/mips/pci/pci-ip27.c +++ b/trunk/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(const struct pci_dev *dev, u8 slot, u8 pin) +int __devinit pcibios_map_irq(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/trunk/arch/mips/pci/pci-lasat.c b/trunk/arch/mips/pci/pci-lasat.c new file mode 100644 index 000000000000..985784a3e6f8 --- /dev/null +++ b/trunk/arch/mips/pci/pci-lasat.c @@ -0,0 +1,91 @@ +/* + * 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 +#include +#include +#include +#include + +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 = >64xxx_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/trunk/arch/mips/pci/pci-ocelot-c.c b/trunk/arch/mips/pci/pci-ocelot-c.c new file mode 100644 index 000000000000..027759f7c904 --- /dev/null +++ b/trunk/arch/mips/pci/pci-ocelot-c.c @@ -0,0 +1,145 @@ +/* + * 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 +#include +#include + +#include + +#include + +/* + * 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/trunk/arch/mips/pci/pci-sb1250.c b/trunk/arch/mips/pci/pci-sb1250.c index c1ac6493155e..75c1246ced5f 100644 --- a/trunk/arch/mips/pci/pci-sb1250.c +++ b/trunk/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(const struct pci_dev *dev, u8 slot, u8 pin) +int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { return dev->irq; } diff --git a/trunk/arch/mips/philips/pnx8550/common/platform.c b/trunk/arch/mips/philips/pnx8550/common/platform.c index c839436bd012..d43f56e2cd78 100644 --- a/trunk/arch/mips/philips/pnx8550/common/platform.c +++ b/trunk/arch/mips/philips/pnx8550/common/platform.c @@ -123,7 +123,7 @@ static struct platform_device *pnx8550_platform_devices[] __initdata = { &pnx8550_uart_device, }; -static int __init pnx8550_platform_init(void) +int pnx8550_platform_init(void) { return platform_add_devices(pnx8550_platform_devices, ARRAY_SIZE(pnx8550_platform_devices)); diff --git a/trunk/arch/mips/philips/pnx8550/common/proc.c b/trunk/arch/mips/philips/pnx8550/common/proc.c index 92311e95b700..3f097558ef13 100644 --- a/trunk/arch/mips/philips/pnx8550/common/proc.c +++ b/trunk/arch/mips/philips/pnx8550/common/proc.c @@ -78,33 +78,29 @@ static int pnx8550_proc_init( void ) { // Create /proc/pnx8550 - pnx8550_dir = proc_mkdir("pnx8550", NULL); + pnx8550_dir = create_proc_entry("pnx8550", S_IFDIR|S_IRUGO, NULL); if (!pnx8550_dir) { printk(KERN_ERR "Can't create pnx8550 proc dir\n"); return -1; } // Create /proc/pnx8550/timers - pnx8550_timers = create_proc_read_entry( - "timers", - 0, - pnx8550_dir, - pnx8550_timers_read, - NULL); - - if (!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 { printk(KERN_ERR "Can't create pnx8550 timers proc file\n"); + } // Create /proc/pnx8550/registers - pnx8550_registers = create_proc_read_entry( - "registers", - 0, - pnx8550_dir, - pnx8550_registers_read, - NULL); - - if (!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 { printk(KERN_ERR "Can't create pnx8550 registers proc file\n"); + } return 0; } diff --git a/trunk/arch/mips/pmc-sierra/Kconfig b/trunk/arch/mips/pmc-sierra/Kconfig index abbd0bbfabd7..24d514c9dff9 100644 --- a/trunk/arch/mips/pmc-sierra/Kconfig +++ b/trunk/arch/mips/pmc-sierra/Kconfig @@ -1,49 +1,3 @@ -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/trunk/arch/mips/pmc-sierra/msp71xx/Makefile b/trunk/arch/mips/pmc-sierra/msp71xx/Makefile deleted file mode 100644 index 4bba79c1cc79..000000000000 --- a/trunk/arch/mips/pmc-sierra/msp71xx/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# 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/trunk/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c b/trunk/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c deleted file mode 100644 index 6fa85728158b..000000000000 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * 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 -#include -#include - -#include -#include -#include -#ifdef CONFIG_PMCTWILED -#include -#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/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq.c b/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq.c deleted file mode 100644 index 734d598a2e3a..000000000000 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include - -#include - -#include - -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/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c b/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c deleted file mode 100644 index 5175357d0a25..000000000000 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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 -#include -#include -#include - -#include - -#include -#include - -/* - * 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/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c b/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c deleted file mode 100644 index f5f1b8d2bb9a..000000000000 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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 -#include -#include -#include - -#include -#include - -#include -#include - -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/trunk/arch/mips/pmc-sierra/msp71xx/msp_prom.c b/trunk/arch/mips/pmc-sierra/msp71xx/msp_prom.c deleted file mode 100644 index e5bd5481d8db..000000000000 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_prom.c +++ /dev/null @@ -1,566 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include -#ifdef CONFIG_CRAMFS -#include -#endif -#ifdef CONFIG_SQUASHFS -#include -#endif - -#include -#include -#include -#include - -#include -#include - -/* 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/trunk/arch/mips/pmc-sierra/msp71xx/msp_setup.c b/trunk/arch/mips/pmc-sierra/msp71xx/msp_setup.c deleted file mode 100644 index 8f69b789be90..000000000000 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_setup.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * 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 -#include -#include -#include -#include - -#include -#include - -#if defined(CONFIG_PMC_MSP7120_GW) -#include -#include -#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/trunk/arch/mips/pmc-sierra/msp71xx/msp_time.c b/trunk/arch/mips/pmc-sierra/msp71xx/msp_time.c deleted file mode 100644 index 2a2beac5a4f8..000000000000 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_time.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -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/trunk/arch/mips/pmc-sierra/msp71xx/msp_usb.c b/trunk/arch/mips/pmc-sierra/msp71xx/msp_usb.c deleted file mode 100644 index 21f9c70b6923..000000000000 --- a/trunk/arch/mips/pmc-sierra/msp71xx/msp_usb.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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 -#include -#include -#include - -#include - -#include -#include -#include - -#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 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/trunk/arch/mips/pmc-sierra/yosemite/smp.c b/trunk/arch/mips/pmc-sierra/yosemite/smp.c index d83c4ada14f3..305491e74dbe 100644 --- a/trunk/arch/mips/pmc-sierra/yosemite/smp.c +++ b/trunk/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 __init prom_boot_secondary(int cpu, struct task_struct *idle) +void 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/trunk/arch/mips/sgi-ip22/ip22-reset.c b/trunk/arch/mips/sgi-ip22/ip22-reset.c index 63afd7e44428..66df5ac8f089 100644 --- a/trunk/arch/mips/sgi-ip22/ip22-reset.c +++ b/trunk/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 __noreturn sgi_machine_power_off(void) +static void ATTRIB_NORET sgi_machine_power_off(void) { unsigned int tmp; @@ -68,7 +68,7 @@ static void __noreturn sgi_machine_power_off(void) } } -static void __noreturn sgi_machine_restart(char *command) +static void ATTRIB_NORET sgi_machine_restart(char *command) { if (machine_state & MACHINE_SHUTTING_DOWN) sgi_machine_power_off(); @@ -76,7 +76,7 @@ static void __noreturn sgi_machine_restart(char *command) while (1); } -static void __noreturn sgi_machine_halt(void) +static void ATTRIB_NORET sgi_machine_halt(void) { if (machine_state & MACHINE_SHUTTING_DOWN) sgi_machine_power_off(); diff --git a/trunk/arch/mips/sgi-ip27/ip27-berr.c b/trunk/arch/mips/sgi-ip27/ip27-berr.c index 123141ab21a2..ce907eda221b 100644 --- a/trunk/arch/mips/sgi-ip27/ip27-berr.c +++ b/trunk/arch/mips/sgi-ip27/ip27-berr.c @@ -21,6 +21,7 @@ #include #include +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/trunk/arch/mips/sgi-ip32/ip32-platform.c b/trunk/arch/mips/sgi-ip32/ip32-platform.c index ba3697ee7ff6..120b15932caf 100644 --- a/trunk/arch/mips/sgi-ip32/ip32-platform.c +++ b/trunk/arch/mips/sgi-ip32/ip32-platform.c @@ -1,53 +1,5 @@ -/* - * 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 #include #include -#include - -#include -#include - -/* - * .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) { @@ -66,7 +18,3 @@ static __init int meth_devinit(void) } device_initcall(meth_devinit); - -MODULE_AUTHOR("Ralf Baechle "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("8250 UART probe driver for SGI IP32 aka O2"); diff --git a/trunk/arch/mips/sgi-ip32/ip32-setup.c b/trunk/arch/mips/sgi-ip32/ip32-setup.c index bbba066cb405..57708fe28bd7 100644 --- a/trunk/arch/mips/sgi-ip32/ip32-setup.c +++ b/trunk/arch/mips/sgi-ip32/ip32-setup.c @@ -62,6 +62,12 @@ static inline void str2eaddr(unsigned char *ea, unsigned char *str) } #endif +#ifdef CONFIG_SERIAL_8250 +#include +#include +#include +#endif /* CONFIG_SERIAL_8250 */ + /* An arbitrary time; this can be decreased if reliability looks good */ #define WAIT_MS 10 @@ -90,6 +96,36 @@ 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/trunk/arch/mips/sibyte/cfe/setup.c b/trunk/arch/mips/sibyte/cfe/setup.c index 51898dd1304a..ae4a92c3e529 100644 --- a/trunk/arch/mips/sibyte/cfe/setup.c +++ b/trunk/arch/mips/sibyte/cfe/setup.c @@ -62,7 +62,7 @@ extern unsigned long initrd_start, initrd_end; extern int kgdb_port; #endif -static void __noreturn cfe_linux_exit(void *arg) +static void ATTRIB_NORET cfe_linux_exit(void *arg) { int warm = *(int *)arg; @@ -83,14 +83,14 @@ static void __noreturn cfe_linux_exit(void *arg) while (1); } -static void __noreturn cfe_linux_restart(char *command) +static void ATTRIB_NORET cfe_linux_restart(char *command) { static const int zero; cfe_linux_exit((void *)&zero); } -static void __noreturn cfe_linux_halt(void) +static void ATTRIB_NORET cfe_linux_halt(void) { static const int one = 1; diff --git a/trunk/arch/mips/sni/Makefile b/trunk/arch/mips/sni/Makefile index 471418e4f446..e5777b7e2bc9 100644 --- a/trunk/arch/mips/sni/Makefile +++ b/trunk/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 a20r.o rm200.o pcimt.o pcit.o time.o +obj-y += irq.o reset.o setup.o ds1216.o a20r.o rm200.o pcimt.o pcit.o time.o obj-$(CONFIG_CPU_BIG_ENDIAN) += sniprom.o diff --git a/trunk/arch/mips/sni/a20r.c b/trunk/arch/mips/sni/a20r.c index 6850a29defcd..31ab80f1befa 100644 --- a/trunk/arch/mips/sni/a20r.c +++ b/trunk/arch/mips/sni/a20r.c @@ -15,6 +15,7 @@ #include #include +#include #define PORT(_base,_irq) \ { \ @@ -39,34 +40,20 @@ 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 = 0x18000000, - .end = 0x18000004, + .start = 0xb8000000, + .end = 0xb8000004, .flags = IORESOURCE_MEM }, { - .start = 0x18010000, - .end = 0x18010004, + .start = 0xb8010000, + .end = 0xb8010004, .flags = IORESOURCE_MEM }, { - .start = 0x1ff00000, - .end = 0x1ff00020, + .start = 0xbff00000, + .end = 0xbff00020, .flags = IORESOURCE_MEM }, { @@ -218,7 +205,8 @@ void __init sni_a20r_irq_init(void) void sni_a20r_init(void) { - /* FIXME, remove if not needed */ + ds1216_base = (volatile unsigned char *) SNI_DS1216_A20R_BASE; + rtc_mips_get_time = ds1216_get_cmos_time; } static int __init snirm_a20r_setup_devinit(void) @@ -230,7 +218,6 @@ 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/trunk/arch/mips/sni/ds1216.c b/trunk/arch/mips/sni/ds1216.c new file mode 100644 index 000000000000..1d92732c14f1 --- /dev/null +++ b/trunk/arch/mips/sni/ds1216.c @@ -0,0 +1,81 @@ + +#include +#include + +#include + +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/trunk/arch/mips/sni/pcimt.c b/trunk/arch/mips/sni/pcimt.c index 44b1ae62aa4a..97b234361b4d 100644 --- a/trunk/arch/mips/sni/pcimt.c +++ b/trunk/arch/mips/sni/pcimt.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -89,26 +90,6 @@ 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, @@ -309,10 +290,12 @@ void __init sni_pcimt_irq_init(void) change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ3); } -void __init sni_pcimt_init(void) +void 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 @@ -329,7 +312,6 @@ 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/trunk/arch/mips/sni/pcit.c b/trunk/arch/mips/sni/pcit.c index 2480c478dcbd..00d151f4d121 100644 --- a/trunk/arch/mips/sni/pcit.c +++ b/trunk/arch/mips/sni/pcit.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -57,25 +58,6 @@ 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, @@ -261,8 +243,10 @@ void __init sni_pcit_cplus_irq_init(void) setup_irq (MIPS_CPU_IRQ_BASE + 3, &sni_isa_irq); } -void __init sni_pcit_init(void) +void 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 @@ -277,12 +261,10 @@ 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/trunk/arch/mips/sni/rm200.c b/trunk/arch/mips/sni/rm200.c index 4bfda020fdc7..b82ff129f5ea 100644 --- a/trunk/arch/mips/sni/rm200.c +++ b/trunk/arch/mips/sni/rm200.c @@ -15,6 +15,7 @@ #include #include +#include #include #define PORT(_base,_irq) \ @@ -40,34 +41,20 @@ 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 = 0x18000000, - .end = 0x180fffff, + .start = 0xb8000000, + .end = 0xb80fffff, .flags = IORESOURCE_MEM }, { - .start = 0x1b000000, - .end = 0x1b000004, + .start = 0xbb000000, + .end = 0xbb000004, .flags = IORESOURCE_MEM }, { - .start = 0x1ff00000, - .end = 0x1ff00020, + .start = 0xbff00000, + .end = 0xbff00020, .flags = IORESOURCE_MEM }, { @@ -109,7 +96,6 @@ 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); } @@ -190,9 +176,11 @@ void __init sni_rm200_irq_init(void) setup_irq (SNI_RM200_INT_START + 0, &sni_isa_irq); } -void __init sni_rm200_init(void) +void 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/trunk/arch/mips/sni/sniprom.c b/trunk/arch/mips/sni/sniprom.c index 00a03a6e8f58..643366eb854a 100644 --- a/trunk/arch/mips/sni/sniprom.c +++ b/trunk/arch/mips/sni/sniprom.c @@ -146,10 +146,7 @@ static void __init sni_console_setup(void) } if (baud) strcpy(options, baud); - if (strncmp (cdev, "tty552", 6) == 0) - add_preferred_console("ttyS", port, baud ? options : NULL); - else - add_preferred_console("ttySC", port, baud ? options : NULL); + add_preferred_console("ttyS", port, baud ? options : NULL); } } diff --git a/trunk/arch/mips/tx4938/common/Makefile b/trunk/arch/mips/tx4938/common/Makefile index 83cda518f204..2033ae77f632 100644 --- a/trunk/arch/mips/tx4938/common/Makefile +++ b/trunk/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 +obj-y += prom.o setup.o irq.o rtc_rx5c348.o obj-$(CONFIG_KGDB) += dbgio.o diff --git a/trunk/arch/mips/tx4938/common/rtc_rx5c348.c b/trunk/arch/mips/tx4938/common/rtc_rx5c348.c new file mode 100644 index 000000000000..07f782fc0725 --- /dev/null +++ b/trunk/arch/mips/tx4938/common/rtc_rx5c348.c @@ -0,0 +1,192 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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/trunk/arch/mips/tx4938/toshiba_rbtx4938/Makefile b/trunk/arch/mips/tx4938/toshiba_rbtx4938/Makefile index 10c94e62bf5b..226941279d75 100644 --- a/trunk/arch/mips/tx4938/toshiba_rbtx4938/Makefile +++ b/trunk/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 +obj-y += prom.o setup.o irq.o spi_eeprom.o spi_txx9.o diff --git a/trunk/arch/mips/tx4938/toshiba_rbtx4938/irq.c b/trunk/arch/mips/tx4938/toshiba_rbtx4938/irq.c index 91aea7aff515..2e96dbb248b1 100644 --- a/trunk/arch/mips/tx4938/toshiba_rbtx4938/irq.c +++ b/trunk/arch/mips/tx4938/toshiba_rbtx4938/irq.c @@ -165,6 +165,8 @@ 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); @@ -183,5 +185,9 @@ 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/trunk/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/trunk/arch/mips/tx4938/toshiba_rbtx4938/setup.c index 6ed39a5aea72..f5d1ce739fcc 100644 --- a/trunk/arch/mips/tx4938/toshiba_rbtx4938/setup.c +++ b/trunk/arch/mips/tx4938/toshiba_rbtx4938/setup.c @@ -14,13 +14,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include #include @@ -35,9 +35,6 @@ #include #include #endif -#include -#include -#include extern void rbtx4938_time_init(void) __init; extern char * __init prom_getcmdline(void); @@ -352,7 +349,7 @@ static struct pci_dev *fake_pci_dev(struct pci_controller *hose, static struct pci_dev dev; static struct pci_bus bus; - dev.sysdata = bus.sysdata = hose; + dev.sysdata = (void *)hose; dev.devfn = devfn; bus.number = busnr; bus.ops = hose->pci_ops; @@ -385,10 +382,8 @@ 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_devfnccfg & 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]); @@ -578,43 +574,82 @@ 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 -static int __init rbtx4938_ethaddr_init(void) +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) { - unsigned char dat[17]; - unsigned char sum; - int i; + struct pci_controller *channel = (struct pci_controller *)dev->bus->sysdata; + static unsigned char dat[17]; + static int read_dat = 0; + int ch = 0; - /* 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"); + 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: 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"); } - 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); + 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"); + } } + 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 */ @@ -622,6 +657,7 @@ 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; @@ -860,8 +896,10 @@ 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; } @@ -978,6 +1016,29 @@ 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[] = { @@ -996,176 +1057,3 @@ 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/trunk/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c b/trunk/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c index 4d6b4ade5e8c..89596e62f909 100644 --- a/trunk/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c +++ b/trunk/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c @@ -10,90 +10,209 @@ * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) */ #include -#include -#include -#include +#include +#include +#include #include +#include -#define AT250X0_PAGE_SIZE 8 +/* 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 -/* register board information for at25 driver */ -int __init spi_eeprom_register(int chipid) +#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) { - 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); + 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]; } -/* simple temporary spi driver to provide early access to seeprom. */ +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; +} -static struct read_param { - int chipid; - int address; - unsigned char *buf; - int len; -} *read_param; +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 int __init early_seeprom_probe(struct spi_device *spi) +int spi_eeprom_write(int chipid, int address, unsigned char *buf, int len) { - 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; + 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); } + 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; } -static struct spi_driver early_seeprom_driver __initdata = { - .driver = { - .name = "at25", - .owner = THIS_MODULE, - }, - .probe = early_seeprom_probe, -}; +#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; +} -int __init spi_eeprom_read(int chipid, int address, - unsigned char *buf, int len) +static int spi_eeprom_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) { - int ret; - struct read_param param = { - .chipid = chipid, - .address = address, - .buf = buf, - .len = len - }; - - read_param = ¶m; - ret = spi_register_driver(&early_seeprom_driver); - if (!ret) - spi_unregister_driver(&early_seeprom_driver); - return ret; + 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; +} + +__init void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid) +{ + 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; + } } +#endif /* CONFIG_PROC_FS */ diff --git a/trunk/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c b/trunk/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c new file mode 100644 index 000000000000..08b20cdfd7b3 --- /dev/null +++ b/trunk/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c @@ -0,0 +1,164 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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/trunk/arch/s390/crypto/crypt_s390.h b/trunk/arch/s390/crypto/crypt_s390.h index 95f5160df27f..2775d2618332 100644 --- a/trunk/arch/s390/crypto/crypt_s390.h +++ b/trunk/arch/s390/crypto/crypt_s390.h @@ -24,7 +24,7 @@ #define CRYPT_S390_PRIORITY 300 #define CRYPT_S390_COMPOSITE_PRIORITY 400 -/* s390 cryptographic operations */ +/* s930 cryptographic operations */ enum crypt_s390_operations { CRYPT_S390_KM = 0x0100, CRYPT_S390_KMC = 0x0200, diff --git a/trunk/arch/s390/kernel/early.c b/trunk/arch/s390/kernel/early.c index e6289ee74ecd..50538e545618 100644 --- a/trunk/arch/s390/kernel/early.c +++ b/trunk/arch/s390/kernel/early.c @@ -171,6 +171,37 @@ 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; @@ -187,7 +218,6 @@ 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) { @@ -263,7 +293,7 @@ static noinline __init void setup_lowcore_early(void) */ void __init startup_init(void) { - unsigned long long memsize; + unsigned long memsize; ipl_save_parameters(); clear_bss_section(); @@ -275,17 +305,8 @@ 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((unsigned long) memsize); + find_memory_chunks(memsize); lockdep_on(); } diff --git a/trunk/arch/s390/kernel/entry.S b/trunk/arch/s390/kernel/entry.S index bc7ff3658c3d..6234c6978a1f 100644 --- a/trunk/arch/s390/kernel/entry.S +++ b/trunk/arch/s390/kernel/entry.S @@ -107,11 +107,6 @@ 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 @@ -223,7 +218,7 @@ system_call: STORE_TIMER __LC_SYNC_ENTER_TIMER sysc_saveall: SAVE_ALL_BASE __LC_SAVE_AREA - SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA + SAVE_ALL_SYNC __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/trunk/arch/s390/kernel/entry64.S b/trunk/arch/s390/kernel/entry64.S index 2a7b1304418b..685f11faa4bc 100644 --- a/trunk/arch/s390/kernel/entry64.S +++ b/trunk/arch/s390/kernel/entry64.S @@ -99,11 +99,6 @@ _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 @@ -212,7 +207,7 @@ system_call: STORE_TIMER __LC_SYNC_ENTER_TIMER sysc_saveall: SAVE_ALL_BASE __LC_SAVE_AREA - SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA + SAVE_ALL_SYNC __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/trunk/arch/s390/kernel/ipl.c b/trunk/arch/s390/kernel/ipl.c index 82b131ddd7ff..367caf92ea78 100644 --- a/trunk/arch/s390/kernel/ipl.c +++ b/trunk/arch/s390/kernel/ipl.c @@ -25,6 +25,10 @@ #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" @@ -142,8 +146,6 @@ 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; @@ -373,9 +375,9 @@ static ssize_t ipl_ccw_loadparm_show(struct kset *kset, char *page) { char loadparm[LOADPARM_LEN + 1] = {}; - if (!sclp_ipl_info.is_valid) + if (!SCCB_VALID) return sprintf(page, "#unknown#\n"); - memcpy(loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN); + memcpy(loadparm, SCCB_LOADPARM, LOADPARM_LEN); EBCASC(loadparm, LOADPARM_LEN); strstrip(loadparm); return sprintf(page, "%s\n", loadparm); @@ -908,9 +910,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 (sclp_ipl_info.is_valid) + if (SCCB_VALID) memcpy(reipl_block_ccw->ipl_info.ccw.load_param, - &sclp_ipl_info.loadparm, LOADPARM_LEN); + SCCB_LOADPARM, LOADPARM_LEN); else /* read scp info failed: set empty loadparm (EBCDIC blanks) */ memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40, @@ -1005,7 +1007,7 @@ static int __init dump_fcp_init(void) { int rc; - if (!sclp_ipl_info.has_dump) + if(!(SCCB_FLAG & 0x2) || !SCCB_VALID) return 0; /* LDIPL DUMP is not installed */ if (!diag308_set_works) return 0; @@ -1086,7 +1088,6 @@ 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/trunk/arch/s390/kernel/process.c b/trunk/arch/s390/kernel/process.c index 441975b796fb..eb43c3b31269 100644 --- a/trunk/arch/s390/kernel/process.c +++ b/trunk/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, S390_CPU_NOT_IDLE, - (void *)(long) smp_processor_id()); + atomic_notifier_call_chain(&idle_chain, 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, - S390_CPU_IDLE, (void *)(long) cpu); + CPU_IDLE, (void *)(long) cpu); if (rc != NOTIFY_OK && rc != NOTIFY_DONE) BUG(); if (rc != NOTIFY_OK) { diff --git a/trunk/arch/s390/kernel/smp.c b/trunk/arch/s390/kernel/smp.c index 182c085ae4dd..8ff2feaf9b00 100644 --- a/trunk/arch/s390/kernel/smp.c +++ b/trunk/arch/s390/kernel/smp.c @@ -410,40 +410,58 @@ EXPORT_SYMBOL(smp_ctl_clear_bit); unsigned int zfcpdump_prefix_array[NR_CPUS + 1] \ __attribute__((__section__(".data"))); -static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) +static void __init smp_get_save_areas(void) { + unsigned int cpu, cpu_num, rc; + __u16 boot_cpu_addr; + if (ipl_info.type != IPL_TYPE_FCP_DUMP) return; - 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]; + 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++; + } } union save_area *zfcpdump_save_areas[NR_CPUS + 1]; EXPORT_SYMBOL_GPL(zfcpdump_save_areas); #else - -static inline void smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) { } - -#endif /* CONFIG_ZFCPDUMP || CONFIG_ZFCPDUMP_MODULE */ +#define smp_get_save_areas() do { } while (0) +#endif /* * Lets check how many CPUs we have. */ + static unsigned int __init smp_count_cpus(void) { unsigned int cpu, num_cpus; @@ -452,6 +470,7 @@ 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; @@ -461,11 +480,12 @@ 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; } @@ -586,6 +606,7 @@ 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/trunk/arch/s390/kernel/time.c b/trunk/arch/s390/kernel/time.c index 48dae49bc1ec..9c2872a7cca7 100644 --- a/trunk/arch/s390/kernel/time.c +++ b/trunk/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 S390_CPU_IDLE: + case CPU_IDLE: stop_hz_timer(); break; - case S390_CPU_NOT_IDLE: + case CPU_NOT_IDLE: start_hz_timer(); break; } diff --git a/trunk/arch/s390/kernel/vtime.c b/trunk/arch/s390/kernel/vtime.c index b6ed143e8597..1e1a6ee2cac1 100644 --- a/trunk/arch/s390/kernel/vtime.c +++ b/trunk/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 S390_CPU_IDLE: + case CPU_IDLE: stop_cpu_timer(); break; - case S390_CPU_NOT_IDLE: + case CPU_NOT_IDLE: start_cpu_timer(); break; } diff --git a/trunk/arch/s390/lib/Makefile b/trunk/arch/s390/lib/Makefile index 52084436ab69..59aea65ce99f 100644 --- a/trunk/arch/s390/lib/Makefile +++ b/trunk/arch/s390/lib/Makefile @@ -4,7 +4,7 @@ EXTRA_AFLAGS := -traditional -lib-y += delay.o string.o uaccess_std.o uaccess_pt.o -obj-$(CONFIG_32BIT) += div64.o qrnnd.o +lib-y += delay.o string.o uaccess_std.o uaccess_pt.o qrnnd.o +obj-$(CONFIG_32BIT) += div64.o lib-$(CONFIG_64BIT) += uaccess_mvcos.o lib-$(CONFIG_SMP) += spinlock.o diff --git a/trunk/block/Kconfig b/trunk/block/Kconfig index 285935134bcd..a50f48111647 100644 --- a/trunk/block/Kconfig +++ b/trunk/block/Kconfig @@ -1,7 +1,7 @@ # # Block layer core configuration # -menuconfig BLOCK +config BLOCK bool "Enable the block layer" if EMBEDDED default y help @@ -49,6 +49,6 @@ config LSF If unsure, say Y. -endif # BLOCK +endif source block/Kconfig.iosched diff --git a/trunk/block/cfq-iosched.c b/trunk/block/cfq-iosched.c index e0aa4dad6742..baef5fc7cff8 100644 --- a/trunk/block/cfq-iosched.c +++ b/trunk/block/cfq-iosched.c @@ -92,8 +92,6 @@ 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; @@ -1353,8 +1351,8 @@ static void cfq_ioc_set_ioprio(struct io_context *ioc) } static struct cfq_queue * -cfq_find_alloc_queue(struct cfq_data *cfqd, int is_sync, - struct task_struct *tsk, gfp_t gfp_mask) +cfq_get_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; @@ -1407,35 +1405,12 @@ cfq_find_alloc_queue(struct cfq_data *cfqd, int is_sync, 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. */ @@ -2044,7 +2019,6 @@ 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); @@ -2061,13 +2035,6 @@ 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/trunk/block/elevator.c b/trunk/block/elevator.c index 4769a25d7037..ce866eb75f6a 100644 --- a/trunk/block/elevator.c +++ b/trunk/block/elevator.c @@ -112,8 +112,12 @@ 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; } @@ -1112,11 +1116,14 @@ ssize_t elv_iosched_show(request_queue_t *q, char *name) { elevator_t *e = q->elevator; struct elevator_type *elv = e->elevator_type; - struct elevator_type *__e; + struct list_head *entry; int len = 0; spin_lock(&elv_list_lock); - list_for_each_entry(__e, &elv_list, list) { + list_for_each(entry, &elv_list) { + struct elevator_type *__e; + + __e = list_entry(entry, struct elevator_type, list); if (!strcmp(elv->elevator_name, __e->elevator_name)) len += sprintf(name+len, "[%s] ", elv->elevator_name); else diff --git a/trunk/block/ll_rw_blk.c b/trunk/block/ll_rw_blk.c index ef42bb2b12b6..c99b46354859 100644 --- a/trunk/block/ll_rw_blk.c +++ b/trunk/block/ll_rw_blk.c @@ -527,6 +527,8 @@ 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 @@ -538,6 +540,13 @@ 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; @@ -1295,9 +1304,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_back_size + nxt->bi_hw_front_size)) + BIOVEC_VIRT_OVERSIZE(bio->bi_hw_front_size + bio->bi_hw_back_size)) return 0; - if (bio->bi_hw_back_size + nxt->bi_hw_front_size > q->max_segment_size) + if (bio->bi_size + nxt->bi_size > q->max_segment_size) return 0; return 1; diff --git a/trunk/drivers/Kconfig b/trunk/drivers/Kconfig index 7916f4b86d23..050323fd79e9 100644 --- a/trunk/drivers/Kconfig +++ b/trunk/drivers/Kconfig @@ -24,6 +24,8 @@ source "drivers/scsi/Kconfig" source "drivers/ata/Kconfig" +source "drivers/cdrom/Kconfig" + source "drivers/md/Kconfig" source "drivers/message/fusion/Kconfig" @@ -52,8 +54,6 @@ source "drivers/spi/Kconfig" source "drivers/w1/Kconfig" -source "drivers/power/Kconfig" - source "drivers/hwmon/Kconfig" source "drivers/mfd/Kconfig" diff --git a/trunk/drivers/Makefile b/trunk/drivers/Makefile index 503d82569449..adad2f3d438a 100644 --- a/trunk/drivers/Makefile +++ b/trunk/drivers/Makefile @@ -61,7 +61,6 @@ 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/trunk/drivers/acorn/block/fd1772.c b/trunk/drivers/acorn/block/fd1772.c index 423ed08fb6f7..674bf81c6e66 100644 --- a/trunk/drivers/acorn/block/fd1772.c +++ b/trunk/drivers/acorn/block/fd1772.c @@ -1246,7 +1246,7 @@ static void redo_fd_request(void) del_timer(&motor_off_timer); ReqCnt = 0; - ReqCmd = rq_data_dir(CURRENT); + ReqCmd = CURRENT->cmd; ReqBlock = CURRENT->sector; ReqBuffer = CURRENT->buffer; setup_req_params(drive); diff --git a/trunk/drivers/acorn/block/mfmhd.c b/trunk/drivers/acorn/block/mfmhd.c index d85520f78e68..689a4c3542ba 100644 --- a/trunk/drivers/acorn/block/mfmhd.c +++ b/trunk/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 (rq_data_dir(CURRENT) == WRITE) { + if (CURRENT->cmd == 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 = rq_data_dir(CURRENT) == WRITE ? CMD_WD : CMD_RD; + raw_cmd.cmdcode = CURRENT->cmd == 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', rq_data_dir(CURRENT) == READ ? "read" : "writ", + raw_cmd.dev + 'a', (CURRENT->cmd == READ) ? "read" : "writ", raw_cmd.cylinder, raw_cmd.head, raw_cmd.sector, nsect, (unsigned long) Copy_buffer, CURRENT); @@ -917,6 +917,13 @@ 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/trunk/drivers/ata/ahci.c b/trunk/drivers/ata/ahci.c index 11e4eb9f304e..ca5229d24d8e 100644 --- a/trunk/drivers/ata/ahci.c +++ b/trunk/drivers/ata/ahci.c @@ -46,7 +46,7 @@ #include #define DRV_NAME "ahci" -#define DRV_VERSION "2.3" +#define DRV_VERSION "2.2" enum { @@ -54,7 +54,7 @@ enum { AHCI_MAX_PORTS = 32, AHCI_MAX_SG = 168, /* hardware max is 64K */ AHCI_DMA_BOUNDARY = 0xffffffff, - AHCI_USE_CLUSTERING = 1, + AHCI_USE_CLUSTERING = 0, AHCI_MAX_CMDS = 32, AHCI_CMD_SZ = 32, AHCI_CMD_SLOT_SZ = AHCI_MAX_CMDS * AHCI_CMD_SZ, @@ -81,7 +81,6 @@ enum { board_ahci_vt8251 = 2, board_ahci_ign_iferr = 3, board_ahci_sb600 = 4, - board_ahci_mv = 5, /* global controller registers */ HOST_CAP = 0x00, /* host capabilities */ @@ -172,8 +171,6 @@ enum { AHCI_FLAG_HONOR_PI = (1 << 26), /* honor PORTS_IMPL */ AHCI_FLAG_IGN_SERR_INTERNAL = (1 << 27), /* ignore SERR_INTERNAL */ AHCI_FLAG_32BIT_ONLY = (1 << 28), /* force 32bit */ - AHCI_FLAG_MV_PATA = (1 << 29), /* PATA port */ - AHCI_FLAG_NO_MSI = (1 << 30), /* no PCI MSI */ AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | @@ -231,12 +228,9 @@ static void ahci_thaw(struct ata_port *ap); static void ahci_error_handler(struct ata_port *ap); static void ahci_vt8251_error_handler(struct ata_port *ap); static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); -static int ahci_port_resume(struct ata_port *ap); -static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl); -static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, - u32 opts); #ifdef CONFIG_PM static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg); +static int ahci_port_resume(struct ata_port *ap); static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); static int ahci_pci_device_resume(struct pci_dev *pdev); #endif @@ -333,14 +327,14 @@ static const struct ata_port_info ahci_port_info[] = { { .flags = AHCI_FLAG_COMMON, .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops, }, /* board_ahci_pi */ { .flags = AHCI_FLAG_COMMON | AHCI_FLAG_HONOR_PI, .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops, }, /* board_ahci_vt8251 */ @@ -348,14 +342,14 @@ static const struct ata_port_info ahci_port_info[] = { .flags = AHCI_FLAG_COMMON | ATA_FLAG_HRST_TO_RESUME | AHCI_FLAG_NO_NCQ, .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_vt8251_ops, }, /* board_ahci_ign_iferr */ { .flags = AHCI_FLAG_COMMON | AHCI_FLAG_IGN_IRQ_IF_ERR, .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops, }, /* board_ahci_sb600 */ @@ -364,19 +358,7 @@ static const struct ata_port_info ahci_port_info[] = { AHCI_FLAG_IGN_SERR_INTERNAL | AHCI_FLAG_32BIT_ONLY, .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA6, - .port_ops = &ahci_ops, - }, - /* board_ahci_mv */ - { - .sht = &ahci_sht, - .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | - ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_HONOR_PI | - AHCI_FLAG_NO_NCQ | AHCI_FLAG_NO_MSI | - AHCI_FLAG_MV_PATA, - .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops, }, }; @@ -474,9 +456,6 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 966 */ { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ - /* Marvell */ - { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ - /* Generic, PCI class code for AHCI */ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, @@ -502,17 +481,11 @@ static inline int ahci_nr_ports(u32 cap) return (cap & 0x1f) + 1; } -static inline void __iomem *__ahci_port_base(struct ata_host *host, - unsigned int port_no) -{ - void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; - - return mmio + 0x100 + (port_no * 0x80); -} - static inline void __iomem *ahci_port_base(struct ata_port *ap) { - return __ahci_port_base(ap->host, ap->port_no); + void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; + + return mmio + 0x100 + (ap->port_no * 0x80); } /** @@ -562,20 +535,6 @@ static void ahci_save_initial_config(struct pci_dev *pdev, hpriv->saved_port_map = port_map; } - /* - * Temporary Marvell 6145 hack: PATA port presence - * is asserted through the standard AHCI port - * presence register, as bit 4 (counting from 0) - */ - if (pi->flags & AHCI_FLAG_MV_PATA) { - dev_printk(KERN_ERR, &pdev->dev, - "MV_AHCI HACK: port_map %x -> %x\n", - hpriv->port_map, - hpriv->port_map & 0xf); - - port_map &= 0xf; - } - /* cross check port_map and cap.n_ports */ if (pi->flags & AHCI_FLAG_HONOR_PI) { u32 tmp_port_map = port_map; @@ -781,7 +740,7 @@ static void ahci_power_down(struct ata_port *ap) } #endif -static void ahci_start_port(struct ata_port *ap) +static void ahci_init_port(struct ata_port *ap) { /* enable FIS reception */ ahci_start_fis_rx(ap); @@ -855,62 +814,39 @@ static int ahci_reset_controller(struct ata_host *host) return 0; } -static void ahci_port_init(struct pci_dev *pdev, struct ata_port *ap, - int port_no, void __iomem *mmio, - void __iomem *port_mmio) -{ - const char *emsg = NULL; - int rc; - u32 tmp; - - /* make sure port is not active */ - rc = ahci_deinit_port(ap, &emsg); - if (rc) - dev_printk(KERN_WARNING, &pdev->dev, - "%s (%d)\n", emsg, rc); - - /* clear SError */ - tmp = readl(port_mmio + PORT_SCR_ERR); - VPRINTK("PORT_SCR_ERR 0x%x\n", tmp); - writel(tmp, port_mmio + PORT_SCR_ERR); - - /* clear port IRQ */ - tmp = readl(port_mmio + PORT_IRQ_STAT); - VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); - if (tmp) - writel(tmp, port_mmio + PORT_IRQ_STAT); - - writel(1 << port_no, mmio + HOST_IRQ_STAT); -} - static void ahci_init_controller(struct ata_host *host) { struct pci_dev *pdev = to_pci_dev(host->dev); void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; - int i; - void __iomem *port_mmio; + int i, rc; u32 tmp; - if (host->ports[0]->flags & AHCI_FLAG_MV_PATA) { - port_mmio = __ahci_port_base(host, 4); + for (i = 0; i < host->n_ports; i++) { + struct ata_port *ap = host->ports[i]; + void __iomem *port_mmio = ahci_port_base(ap); + const char *emsg = NULL; + + if (ata_port_is_dummy(ap)) + continue; + + /* make sure port is not active */ + rc = ahci_deinit_port(ap, &emsg); + if (rc) + dev_printk(KERN_WARNING, &pdev->dev, + "%s (%d)\n", emsg, rc); - writel(0, port_mmio + PORT_IRQ_MASK); + /* clear SError */ + tmp = readl(port_mmio + PORT_SCR_ERR); + VPRINTK("PORT_SCR_ERR 0x%x\n", tmp); + writel(tmp, port_mmio + PORT_SCR_ERR); /* clear port IRQ */ tmp = readl(port_mmio + PORT_IRQ_STAT); VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); if (tmp) writel(tmp, port_mmio + PORT_IRQ_STAT); - } - for (i = 0; i < host->n_ports; i++) { - struct ata_port *ap = host->ports[i]; - - port_mmio = ahci_port_base(ap); - if (ata_port_is_dummy(ap)) - continue; - - ahci_port_init(pdev, ap, i, mmio, port_mmio); + writel(1 << i, mmio + HOST_IRQ_STAT); } tmp = readl(mmio + HOST_CTL); @@ -1296,7 +1232,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) ata_port_abort(ap); } -static void ahci_port_intr(struct ata_port *ap) +static void ahci_host_intr(struct ata_port *ap) { void __iomem *port_mmio = ap->ioaddr.cmd_addr; struct ata_eh_info *ehi = &ap->eh_info; @@ -1422,7 +1358,7 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance) ap = host->ports[i]; if (ap) { - ahci_port_intr(ap); + ahci_host_intr(ap); VPRINTK("port %u\n", i); } else { VPRINTK("port %u (no irq)\n", i); @@ -1530,7 +1466,7 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg) ahci_power_down(ap); else { ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc); - ahci_start_port(ap); + ahci_init_port(ap); } return rc; @@ -1539,7 +1475,7 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg) static int ahci_port_resume(struct ata_port *ap) { ahci_power_up(ap); - ahci_start_port(ap); + ahci_init_port(ap); return 0; } @@ -1637,8 +1573,13 @@ static int ahci_port_start(struct ata_port *ap) ap->private_data = pp; - /* engage engines, captain */ - return ahci_port_resume(ap); + /* power up port */ + ahci_power_up(ap); + + /* initialize port */ + ahci_init_port(ap); + + return 0; } static void ahci_port_stop(struct ata_port *ap) @@ -1783,7 +1724,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) return rc; - if ((pi.flags & AHCI_FLAG_NO_MSI) || pci_enable_msi(pdev)) + if (pci_enable_msi(pdev)) pci_intx(pdev, 1); hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); @@ -1804,18 +1745,14 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) host->private_data = hpriv; for (i = 0; i < host->n_ports; i++) { - struct ata_port *ap = host->ports[i]; - void __iomem *port_mmio = ahci_port_base(ap); - - /* standard SATA port setup */ if (hpriv->port_map & (1 << i)) { + struct ata_port *ap = host->ports[i]; + void __iomem *port_mmio = ahci_port_base(ap); + ap->ioaddr.cmd_addr = port_mmio; ap->ioaddr.scr_addr = port_mmio + PORT_SCR; - } - - /* disabled/not-implemented port */ - else - ap->ops = &ata_dummy_port_ops; + } else + host->ports[i]->ops = &ata_dummy_port_ops; } /* initialize adapter */ diff --git a/trunk/drivers/ata/ata_generic.c b/trunk/drivers/ata/ata_generic.c index 430fcf4f9ef3..4c6e95c95e4a 100644 --- a/trunk/drivers/ata/ata_generic.c +++ b/trunk/drivers/ata/ata_generic.c @@ -143,10 +143,10 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id u16 command; static const struct ata_port_info info = { .sht = &generic_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, + .udma_mask = 0x3f, .port_ops = &generic_port_ops }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/trunk/drivers/ata/ata_piix.c b/trunk/drivers/ata/ata_piix.c index 6a3bfef58e13..9c07b88631be 100644 --- a/trunk/drivers/ata/ata_piix.c +++ b/trunk/drivers/ata/ata_piix.c @@ -200,8 +200,6 @@ static const struct pci_device_id piix_pci_tbl[] = { /* ICH7/7-R (i945, i975) UDMA 100*/ { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_133 }, { 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, - /* ICH8 Mobile PATA Controller */ - { 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, /* NOTE: The following PCI ids must be kept in sync with the * list in drivers/pci/quirks.c. @@ -497,7 +495,7 @@ static struct ata_port_info piix_port_info[] = { .flags = PIIX_SATA_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, }, @@ -507,7 +505,7 @@ static struct ata_port_info piix_port_info[] = { .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, }, @@ -518,7 +516,7 @@ static struct ata_port_info piix_port_info[] = { PIIX_FLAG_AHCI, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, }, @@ -529,7 +527,7 @@ static struct ata_port_info piix_port_info[] = { PIIX_FLAG_AHCI, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, }, @@ -540,7 +538,7 @@ static struct ata_port_info piix_port_info[] = { PIIX_FLAG_AHCI, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, }, @@ -687,14 +685,8 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev) if (adev->class == ATA_DEV_ATA) control |= 4; /* PPE enable */ - /* PIO configuration clears DTE unconditionally. It will be - * programmed in set_dmamode which is guaranteed to be called - * after set_piomode if any DMA mode is available. - */ pci_read_config_word(dev, master_port, &master_data); if (is_slave) { - /* clear TIME1|IE1|PPE1|DTE1 */ - master_data &= 0xff0f; /* Enable SITRE (seperate slave timing register) */ master_data |= 0x4000; /* enable PPE1, IE1 and TIME1 as needed */ @@ -702,14 +694,12 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev) pci_read_config_byte(dev, slave_port, &slave_data); slave_data &= (ap->port_no ? 0x0f : 0xf0); /* Load the timing nibble for this slave */ - slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) - << (ap->port_no ? 4 : 0); + slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0); } else { - /* clear ISP|RCT|TIME0|IE0|PPE0|DTE0 */ - master_data &= 0xccf0; + /* Master keeps the bits in a different format */ + master_data &= 0xccf8; /* Enable PPE, IE and TIME as appropriate */ master_data |= control; - /* load ISP and RCT */ master_data |= (timings[pio][0] << 12) | (timings[pio][1] << 8); @@ -826,7 +816,7 @@ static void do_pata_set_dmamode (struct ata_port *ap, struct ata_device *adev, i master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */ master_data |= control << 4; pci_read_config_byte(dev, 0x44, &slave_data); - slave_data &= (ap->port_no ? 0x0f : 0xf0); + slave_data &= (0x0F + 0xE1 * ap->port_no); /* Load the matching timing */ slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0); pci_write_config_byte(dev, 0x44, slave_data); @@ -838,11 +828,8 @@ static void do_pata_set_dmamode (struct ata_port *ap, struct ata_device *adev, i (timings[pio][0] << 12) | (timings[pio][1] << 8); } - - if (ap->udma_mask) { - udma_enable &= ~(1 << devid); - pci_write_config_word(dev, master_port, master_data); - } + udma_enable &= ~(1 << devid); + pci_write_config_word(dev, master_port, master_data); } /* Don't scribble on 0x48 if the controller does not support UDMA */ if (ap->udma_mask) diff --git a/trunk/drivers/ata/libata-acpi.c b/trunk/drivers/ata/libata-acpi.c index c059f78ad944..02236739b40f 100644 --- a/trunk/drivers/ata/libata-acpi.c +++ b/trunk/drivers/ata/libata-acpi.c @@ -24,13 +24,15 @@ #include #include +#define SATA_ROOT_PORT(x) (((x) >> 16) & 0xffff) +#define SATA_PORT_NUMBER(x) ((x) & 0xffff) /* or NO_PORT_MULT */ #define NO_PORT_MULT 0xffff -#define SATA_ADR(root,pmp) (((root) << 16) | (pmp)) +#define SATA_ADR_RSVD 0xffffffff #define REGS_PER_GTF 7 -struct ata_acpi_gtf { - u8 tf[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */ -} __packed; +struct taskfile_array { + u8 tfa[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */ +}; /* * Helper - belongs in the PCI layer somewhere eventually @@ -40,173 +42,237 @@ static int is_pci_dev(struct device *dev) return (dev->bus == &pci_bus_type); } -static void ata_acpi_associate_sata_port(struct ata_port *ap) -{ - acpi_integer adr = SATA_ADR(ap->port_no, NO_PORT_MULT); - - ap->device->acpi_handle = acpi_get_child(ap->host->acpi_handle, adr); -} - -static void ata_acpi_associate_ide_port(struct ata_port *ap) -{ - int max_devices, i; - - ap->acpi_handle = acpi_get_child(ap->host->acpi_handle, ap->port_no); - if (!ap->acpi_handle) - return; - - max_devices = 1; - if (ap->flags & ATA_FLAG_SLAVE_POSS) - max_devices++; - - for (i = 0; i < max_devices; i++) { - struct ata_device *dev = &ap->device[i]; - - dev->acpi_handle = acpi_get_child(ap->acpi_handle, i); - } -} - /** - * ata_acpi_associate - associate ATA host with ACPI objects - * @host: target ATA host - * - * Look up ACPI objects associated with @host and initialize - * acpi_handle fields of @host, its ports and devices accordingly. + * sata_get_dev_handle - finds acpi_handle and PCI device.function + * @dev: device to locate + * @handle: returned acpi_handle for @dev + * @pcidevfn: return PCI device.func for @dev * - * LOCKING: - * EH context. + * This function is somewhat SATA-specific. Or at least the + * PATA & SATA versions of this function are different, + * so it's not entirely generic code. * - * RETURNS: - * 0 on success, -errno on failure. + * Returns 0 on success, <0 on error. */ -void ata_acpi_associate(struct ata_host *host) +static int sata_get_dev_handle(struct device *dev, acpi_handle *handle, + acpi_integer *pcidevfn) { - int i; - - if (!is_pci_dev(host->dev) || libata_noacpi) - return; - - host->acpi_handle = DEVICE_ACPI_HANDLE(host->dev); - if (!host->acpi_handle) - return; - - for (i = 0; i < host->n_ports; i++) { - struct ata_port *ap = host->ports[i]; - - if (host->ports[0]->flags & ATA_FLAG_ACPI_SATA) - ata_acpi_associate_sata_port(ap); - else - ata_acpi_associate_ide_port(ap); - } + struct pci_dev *pci_dev; + acpi_integer addr; + + if (!is_pci_dev(dev)) + return -ENODEV; + + pci_dev = to_pci_dev(dev); /* NOTE: PCI-specific */ + /* Please refer to the ACPI spec for the syntax of _ADR. */ + addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn); + *pcidevfn = addr; + *handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr); + if (!*handle) + return -ENODEV; + return 0; } /** - * ata_acpi_gtm - execute _GTM - * @ap: target ATA port - * @gtm: out parameter for _GTM result - * - * Evaluate _GTM and store the result in @gtm. + * pata_get_dev_handle - finds acpi_handle and PCI device.function + * @dev: device to locate + * @handle: returned acpi_handle for @dev + * @pcidevfn: return PCI device.func for @dev * - * LOCKING: - * EH context. + * The PATA and SATA versions of this function are different. * - * RETURNS: - * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure. + * Returns 0 on success, <0 on error. */ -static int ata_acpi_gtm(const struct ata_port *ap, struct ata_acpi_gtm *gtm) +static int pata_get_dev_handle(struct device *dev, acpi_handle *handle, + acpi_integer *pcidevfn) { - struct acpi_buffer output = { .length = ACPI_ALLOCATE_BUFFER }; - union acpi_object *out_obj; + unsigned int bus, devnum, func; + acpi_integer addr; + acpi_handle dev_handle, parent_handle; + struct acpi_buffer buffer = {.length = ACPI_ALLOCATE_BUFFER, + .pointer = NULL}; acpi_status status; - int rc = 0; - - status = acpi_evaluate_object(ap->acpi_handle, "_GTM", NULL, &output); - - rc = -ENOENT; - if (status == AE_NOT_FOUND) - goto out_free; - - rc = -EINVAL; - if (ACPI_FAILURE(status)) { - ata_port_printk(ap, KERN_ERR, - "ACPI get timing mode failed (AE 0x%x)\n", - status); - goto out_free; + struct acpi_device_info *dinfo = NULL; + int ret = -ENODEV; + struct pci_dev *pdev; + + if (!is_pci_dev(dev)) + return -ENODEV; + + pdev = to_pci_dev(dev); + + bus = pdev->bus->number; + devnum = PCI_SLOT(pdev->devfn); + func = PCI_FUNC(pdev->devfn); + + dev_handle = DEVICE_ACPI_HANDLE(dev); + parent_handle = DEVICE_ACPI_HANDLE(dev->parent); + + status = acpi_get_object_info(parent_handle, &buffer); + if (ACPI_FAILURE(status)) + goto err; + + dinfo = buffer.pointer; + if (dinfo && (dinfo->valid & ACPI_VALID_ADR) && + dinfo->address == bus) { + /* ACPI spec for _ADR for PCI bus: */ + addr = (acpi_integer)(devnum << 16 | func); + *pcidevfn = addr; + *handle = dev_handle; + } else { + goto err; } - out_obj = output.pointer; - if (out_obj->type != ACPI_TYPE_BUFFER) { - ata_port_printk(ap, KERN_WARNING, - "_GTM returned unexpected object type 0x%x\n", - out_obj->type); + if (!*handle) + goto err; + ret = 0; +err: + kfree(dinfo); + return ret; +} - goto out_free; +struct walk_info { /* can be trimmed some */ + struct device *dev; + struct acpi_device *adev; + acpi_handle handle; + acpi_integer pcidevfn; + unsigned int drivenum; + acpi_handle obj_handle; + struct ata_port *ataport; + struct ata_device *atadev; + u32 sata_adr; + int status; + char basepath[ACPI_PATHNAME_MAX]; + int basepath_len; +}; + +static acpi_status get_devices(acpi_handle handle, + u32 level, void *context, void **return_value) +{ + acpi_status status; + struct walk_info *winfo = context; + struct acpi_buffer namebuf = {ACPI_ALLOCATE_BUFFER, NULL}; + char *pathname; + struct acpi_buffer buffer; + struct acpi_device_info *dinfo; + + status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &namebuf); + if (status) + goto ret; + pathname = namebuf.pointer; + + buffer.length = ACPI_ALLOCATE_BUFFER; + buffer.pointer = NULL; + status = acpi_get_object_info(handle, &buffer); + if (ACPI_FAILURE(status)) + goto out2; + + dinfo = buffer.pointer; + + /* find full device path name for pcidevfn */ + if (dinfo && (dinfo->valid & ACPI_VALID_ADR) && + dinfo->address == winfo->pcidevfn) { + if (ata_msg_probe(winfo->ataport)) + ata_dev_printk(winfo->atadev, KERN_DEBUG, + ":%s: matches pcidevfn (0x%llx)\n", + pathname, winfo->pcidevfn); + strlcpy(winfo->basepath, pathname, + sizeof(winfo->basepath)); + winfo->basepath_len = strlen(pathname); + goto out; } - if (out_obj->buffer.length != sizeof(struct ata_acpi_gtm)) { - ata_port_printk(ap, KERN_ERR, - "_GTM returned invalid length %d\n", - out_obj->buffer.length); - goto out_free; + /* if basepath is not yet known, ignore this object */ + if (!winfo->basepath_len) + goto out; + + /* if this object is in scope of basepath, maybe use it */ + if (strncmp(pathname, winfo->basepath, + winfo->basepath_len) == 0) { + if (!(dinfo->valid & ACPI_VALID_ADR)) + goto out; + if (ata_msg_probe(winfo->ataport)) + ata_dev_printk(winfo->atadev, KERN_DEBUG, + "GOT ONE: (%s) root_port = 0x%llx," + " port_num = 0x%llx\n", pathname, + SATA_ROOT_PORT(dinfo->address), + SATA_PORT_NUMBER(dinfo->address)); + /* heuristics: */ + if (SATA_PORT_NUMBER(dinfo->address) != NO_PORT_MULT) + if (ata_msg_probe(winfo->ataport)) + ata_dev_printk(winfo->atadev, + KERN_DEBUG, "warning: don't" + " know how to handle SATA port" + " multiplier\n"); + if (SATA_ROOT_PORT(dinfo->address) == + winfo->ataport->port_no && + SATA_PORT_NUMBER(dinfo->address) == NO_PORT_MULT) { + if (ata_msg_probe(winfo->ataport)) + ata_dev_printk(winfo->atadev, + KERN_DEBUG, + "THIS ^^^^^ is the requested" + " SATA drive (handle = 0x%p)\n", + handle); + winfo->sata_adr = dinfo->address; + winfo->obj_handle = handle; + } } +out: + kfree(dinfo); +out2: + kfree(pathname); - memcpy(gtm, out_obj->buffer.pointer, sizeof(struct ata_acpi_gtm)); - rc = 0; - out_free: - kfree(output.pointer); - return rc; +ret: + return status; } -/** - * ata_acpi_stm - execute _STM - * @ap: target ATA port - * @stm: timing parameter to _STM - * - * Evaluate _STM with timing parameter @stm. - * - * LOCKING: - * EH context. - * - * RETURNS: - * 0 on success, -ENOENT if _STM doesn't exist, -errno on failure. - */ -static int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm) +/* Get the SATA drive _ADR object. */ +static int get_sata_adr(struct device *dev, acpi_handle handle, + acpi_integer pcidevfn, unsigned int drive, + struct ata_port *ap, + struct ata_device *atadev, u32 *dev_adr) { - acpi_status status; - struct acpi_object_list input; - union acpi_object in_params[3]; - - in_params[0].type = ACPI_TYPE_BUFFER; - in_params[0].buffer.length = sizeof(struct ata_acpi_gtm); - in_params[0].buffer.pointer = (u8 *)stm; - /* Buffers for id may need byteswapping ? */ - in_params[1].type = ACPI_TYPE_BUFFER; - in_params[1].buffer.length = 512; - in_params[1].buffer.pointer = (u8 *)ap->device[0].id; - in_params[2].type = ACPI_TYPE_BUFFER; - in_params[2].buffer.length = 512; - in_params[2].buffer.pointer = (u8 *)ap->device[1].id; - - input.count = 3; - input.pointer = in_params; - - status = acpi_evaluate_object(ap->acpi_handle, "_STM", &input, NULL); + acpi_status status; + struct walk_info *winfo; + int err = -ENOMEM; + + winfo = kzalloc(sizeof(struct walk_info), GFP_KERNEL); + if (!winfo) + goto out; + + winfo->dev = dev; + winfo->atadev = atadev; + winfo->ataport = ap; + if (acpi_bus_get_device(handle, &winfo->adev) < 0) + if (ata_msg_probe(ap)) + ata_dev_printk(winfo->atadev, KERN_DEBUG, + "acpi_bus_get_device failed\n"); + winfo->handle = handle; + winfo->pcidevfn = pcidevfn; + winfo->drivenum = drive; - if (status == AE_NOT_FOUND) - return -ENOENT; + status = acpi_get_devices(NULL, get_devices, winfo, NULL); if (ACPI_FAILURE(status)) { - ata_port_printk(ap, KERN_ERR, - "ACPI set timing mode failed (status=0x%x)\n", status); - return -EINVAL; + if (ata_msg_probe(ap)) + ata_dev_printk(winfo->atadev, KERN_DEBUG, + "%s: acpi_get_devices failed\n", + __FUNCTION__); + err = -ENODEV; + } else { + *dev_adr = winfo->sata_adr; + atadev->obj_handle = winfo->obj_handle; + err = 0; } - return 0; + kfree(winfo); +out: + return err; } /** - * ata_dev_get_GTF - get the drive bootup default taskfile settings + * do_drive_get_GTF - get the drive bootup default taskfile settings * @dev: target ATA device - * @gtf: output parameter for buffer containing _GTF taskfile arrays - * @ptr_to_free: pointer which should be freed + * @gtf_length: number of bytes of _GTF data returned at @gtf_address + * @gtf_address: buffer containing _GTF taskfile arrays * * This applies to both PATA and SATA drives. * @@ -216,41 +282,121 @@ static int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm) * The is not known in advance, so have ACPI-CA * allocate the buffer as needed and return it, then free it later. * - * LOCKING: - * EH context. - * - * RETURNS: - * Number of taskfiles on success, 0 if _GTF doesn't exist or doesn't - * contain valid data. -errno on other errors. + * The returned @gtf_length and @gtf_address are only valid if the + * function return value is 0. */ -static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, - void **ptr_to_free) +static int do_drive_get_GTF(struct ata_device *dev, unsigned int *gtf_length, + unsigned long *gtf_address, unsigned long *obj_loc) { struct ata_port *ap = dev->ap; acpi_status status; + acpi_handle dev_handle = NULL; + acpi_handle chan_handle, drive_handle; + acpi_integer pcidevfn = 0; + u32 dev_adr; struct acpi_buffer output; union acpi_object *out_obj; - int rc = 0; + struct device *gdev = ap->host->dev; + int err = -ENODEV; - /* set up output buffer */ - output.length = ACPI_ALLOCATE_BUFFER; - output.pointer = NULL; /* ACPI-CA sets this; save/free it later */ + *gtf_length = 0; + *gtf_address = 0UL; + *obj_loc = 0UL; + + if (libata_noacpi) + return 0; if (ata_msg_probe(ap)) ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n", __FUNCTION__, ap->port_no); - /* _GTF has no input parameters */ - status = acpi_evaluate_object(dev->acpi_handle, "_GTF", NULL, &output); + if (!ata_dev_enabled(dev) || (ap->flags & ATA_FLAG_DISABLED)) { + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, "%s: ERR: " + "ata_dev_present: %d, PORT_DISABLED: %lu\n", + __FUNCTION__, ata_dev_enabled(dev), + ap->flags & ATA_FLAG_DISABLED); + goto out; + } - if (ACPI_FAILURE(status)) { - if (status != AE_NOT_FOUND) { - ata_dev_printk(dev, KERN_WARNING, - "_GTF evaluation failed (AE 0x%x)\n", - status); - rc = -EIO; + /* Don't continue if device has no _ADR method. + * _GTF is intended for known motherboard devices. */ + if (!(ap->flags & ATA_FLAG_ACPI_SATA)) { + err = pata_get_dev_handle(gdev, &dev_handle, &pcidevfn); + if (err < 0) { + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, + "%s: pata_get_dev_handle failed (%d)\n", + __FUNCTION__, err); + goto out; } - goto out_free; + } else { + err = sata_get_dev_handle(gdev, &dev_handle, &pcidevfn); + if (err < 0) { + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, + "%s: sata_get_dev_handle failed (%d\n", + __FUNCTION__, err); + goto out; + } + } + + /* Get this drive's _ADR info. if not already known. */ + if (!dev->obj_handle) { + if (!(ap->flags & ATA_FLAG_ACPI_SATA)) { + /* get child objects of dev_handle == channel objects, + * + _their_ children == drive objects */ + /* channel is ap->port_no */ + chan_handle = acpi_get_child(dev_handle, + ap->port_no); + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, + "%s: chan adr=%d: chan_handle=0x%p\n", + __FUNCTION__, ap->port_no, + chan_handle); + if (!chan_handle) { + err = -ENODEV; + goto out; + } + /* TBD: could also check ACPI object VALID bits */ + drive_handle = acpi_get_child(chan_handle, dev->devno); + if (!drive_handle) { + err = -ENODEV; + goto out; + } + dev_adr = dev->devno; + dev->obj_handle = drive_handle; + } else { /* for SATA mode */ + dev_adr = SATA_ADR_RSVD; + err = get_sata_adr(gdev, dev_handle, pcidevfn, 0, + ap, dev, &dev_adr); + } + if (err < 0 || dev_adr == SATA_ADR_RSVD || + !dev->obj_handle) { + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, + "%s: get_sata/pata_adr failed: " + "err=%d, dev_adr=%u, obj_handle=0x%p\n", + __FUNCTION__, err, dev_adr, + dev->obj_handle); + goto out; + } + } + + /* Setting up output buffer */ + output.length = ACPI_ALLOCATE_BUFFER; + output.pointer = NULL; /* ACPI-CA sets this; save/free it later */ + + /* _GTF has no input parameters */ + err = -EIO; + status = acpi_evaluate_object(dev->obj_handle, "_GTF", + NULL, &output); + if (ACPI_FAILURE(status)) { + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, + "%s: Run _GTF error: status = 0x%x\n", + __FUNCTION__, status); + goto out; } if (!output.length || !output.pointer) { @@ -260,39 +406,43 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, __FUNCTION__, (unsigned long long)output.length, output.pointer); - goto out_free; + kfree(output.pointer); + goto out; } out_obj = output.pointer; if (out_obj->type != ACPI_TYPE_BUFFER) { - ata_dev_printk(dev, KERN_WARNING, - "_GTF unexpected object type 0x%x\n", - out_obj->type); - rc = -EINVAL; - goto out_free; + kfree(output.pointer); + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, "%s: Run _GTF: " + "error: expected object type of " + " ACPI_TYPE_BUFFER, got 0x%x\n", + __FUNCTION__, out_obj->type); + err = -ENOENT; + goto out; } - if (out_obj->buffer.length % REGS_PER_GTF) { - ata_dev_printk(dev, KERN_WARNING, - "unexpected _GTF length (%d)\n", - out_obj->buffer.length); - rc = -EINVAL; - goto out_free; + if (!out_obj->buffer.length || !out_obj->buffer.pointer || + out_obj->buffer.length % REGS_PER_GTF) { + if (ata_msg_drv(ap)) + ata_dev_printk(dev, KERN_ERR, + "%s: unexpected GTF length (%d) or addr (0x%p)\n", + __FUNCTION__, out_obj->buffer.length, + out_obj->buffer.pointer); + err = -ENOENT; + goto out; } - *ptr_to_free = out_obj; - *gtf = (void *)out_obj->buffer.pointer; - rc = out_obj->buffer.length / REGS_PER_GTF; - + *gtf_length = out_obj->buffer.length; + *gtf_address = (unsigned long)out_obj->buffer.pointer; + *obj_loc = (unsigned long)out_obj; if (ata_msg_probe(ap)) ata_dev_printk(dev, KERN_DEBUG, "%s: returning " - "gtf=%p, gtf_count=%d, ptr_to_free=%p\n", - __FUNCTION__, *gtf, rc, *ptr_to_free); - return rc; - - out_free: - kfree(output.pointer); - return rc; + "gtf_length=%d, gtf_address=0x%lx, obj_loc=0x%lx\n", + __FUNCTION__, *gtf_length, *gtf_address, *obj_loc); + err = 0; +out: + return err; } /** @@ -311,99 +461,154 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf, * function also waits for idle after writing control and before * writing the remaining registers. * - * LOCKING: - * EH context. - * - * RETURNS: - * 0 on success, -errno on failure. + * LOCKING: TBD: + * Inherited from caller. */ -static int taskfile_load_raw(struct ata_device *dev, - const struct ata_acpi_gtf *gtf) +static void taskfile_load_raw(struct ata_device *dev, + const struct taskfile_array *gtf) { struct ata_port *ap = dev->ap; - struct ata_taskfile tf, rtf; - unsigned int err_mask; + struct ata_taskfile tf; + unsigned int err; - if ((gtf->tf[0] == 0) && (gtf->tf[1] == 0) && (gtf->tf[2] == 0) - && (gtf->tf[3] == 0) && (gtf->tf[4] == 0) && (gtf->tf[5] == 0) - && (gtf->tf[6] == 0)) - return 0; + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, "%s: (0x1f1-1f7): hex: " + "%02x %02x %02x %02x %02x %02x %02x\n", + __FUNCTION__, + gtf->tfa[0], gtf->tfa[1], gtf->tfa[2], + gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]); + + if ((gtf->tfa[0] == 0) && (gtf->tfa[1] == 0) && (gtf->tfa[2] == 0) + && (gtf->tfa[3] == 0) && (gtf->tfa[4] == 0) && (gtf->tfa[5] == 0) + && (gtf->tfa[6] == 0)) + return; ata_tf_init(dev, &tf); /* convert gtf to tf */ tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */ tf.protocol = ATA_PROT_NODATA; - tf.feature = gtf->tf[0]; /* 0x1f1 */ - tf.nsect = gtf->tf[1]; /* 0x1f2 */ - tf.lbal = gtf->tf[2]; /* 0x1f3 */ - tf.lbam = gtf->tf[3]; /* 0x1f4 */ - tf.lbah = gtf->tf[4]; /* 0x1f5 */ - tf.device = gtf->tf[5]; /* 0x1f6 */ - tf.command = gtf->tf[6]; /* 0x1f7 */ + tf.feature = gtf->tfa[0]; /* 0x1f1 */ + tf.nsect = gtf->tfa[1]; /* 0x1f2 */ + tf.lbal = gtf->tfa[2]; /* 0x1f3 */ + tf.lbam = gtf->tfa[3]; /* 0x1f4 */ + tf.lbah = gtf->tfa[4]; /* 0x1f5 */ + tf.device = gtf->tfa[5]; /* 0x1f6 */ + tf.command = gtf->tfa[6]; /* 0x1f7 */ + + err = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0); + if (err && ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_ERR, + "%s: ata_exec_internal failed: %u\n", + __FUNCTION__, err); +} + +/** + * do_drive_set_taskfiles - write the drive taskfile settings from _GTF + * @dev: target ATA device + * @gtf_length: total number of bytes of _GTF taskfiles + * @gtf_address: location of _GTF taskfile arrays + * + * This applies to both PATA and SATA drives. + * + * Write {gtf_address, length gtf_length} in groups of + * REGS_PER_GTF bytes. + */ +static int do_drive_set_taskfiles(struct ata_device *dev, + unsigned int gtf_length, + unsigned long gtf_address) +{ + struct ata_port *ap = dev->ap; + int err = -ENODEV; + int gtf_count = gtf_length / REGS_PER_GTF; + int ix; + struct taskfile_array *gtf; if (ata_msg_probe(ap)) - ata_dev_printk(dev, KERN_DEBUG, "executing ACPI cmd " - "%02x/%02x:%02x:%02x:%02x:%02x:%02x\n", - tf.command, tf.feature, tf.nsect, - tf.lbal, tf.lbam, tf.lbah, tf.device); - - rtf = tf; - err_mask = ata_exec_internal(dev, &rtf, NULL, DMA_NONE, NULL, 0); - if (err_mask) { - ata_dev_printk(dev, KERN_ERR, - "ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x failed " - "(Emask=0x%x Stat=0x%02x Err=0x%02x)\n", - tf.command, tf.feature, tf.nsect, tf.lbal, tf.lbam, - tf.lbah, tf.device, err_mask, rtf.command, rtf.feature); - return -EIO; + ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n", + __FUNCTION__, ap->port_no); + + if (libata_noacpi || !(ap->flags & ATA_FLAG_ACPI_SATA)) + return 0; + + if (!ata_dev_enabled(dev) || (ap->flags & ATA_FLAG_DISABLED)) + goto out; + if (!gtf_count) /* shouldn't be here */ + goto out; + + if (gtf_length % REGS_PER_GTF) { + if (ata_msg_drv(ap)) + ata_dev_printk(dev, KERN_ERR, + "%s: unexpected GTF length (%d)\n", + __FUNCTION__, gtf_length); + goto out; } - return 0; + for (ix = 0; ix < gtf_count; ix++) { + gtf = (struct taskfile_array *) + (gtf_address + ix * REGS_PER_GTF); + + /* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */ + taskfile_load_raw(dev, gtf); + } + + err = 0; +out: + return err; } /** * ata_acpi_exec_tfs - get then write drive taskfile settings - * @dev: target ATA device + * @ap: the ata_port for the drive * - * Evaluate _GTF and excute returned taskfiles. - * - * LOCKING: - * EH context. - * - * RETURNS: - * Number of executed taskfiles on success, 0 if _GTF doesn't exist or - * doesn't contain valid data. -errno on other errors. + * This applies to both PATA and SATA drives. */ -static int ata_acpi_exec_tfs(struct ata_device *dev) +int ata_acpi_exec_tfs(struct ata_port *ap) { - struct ata_acpi_gtf *gtf = NULL; - void *ptr_to_free = NULL; - int gtf_count, i, rc; - - /* get taskfiles */ - rc = ata_dev_get_GTF(dev, >f, &ptr_to_free); - if (rc < 0) - return rc; - gtf_count = rc; - - /* execute them */ - for (i = 0, rc = 0; i < gtf_count; i++) { - int tmp; - - /* ACPI errors are eventually ignored. Run till the - * end even after errors. - */ - tmp = taskfile_load_raw(dev, gtf++); - if (!rc) - rc = tmp; - } + int ix; + int ret = 0; + unsigned int gtf_length; + unsigned long gtf_address; + unsigned long obj_loc; - kfree(ptr_to_free); + if (libata_noacpi) + return 0; + /* + * TBD - implement PATA support. For now, + * we should not run GTF on PATA devices since some + * PATA require execution of GTM/STM before GTF. + */ + if (!(ap->flags & ATA_FLAG_ACPI_SATA)) + return 0; - if (rc == 0) - return gtf_count; - return rc; + for (ix = 0; ix < ATA_MAX_DEVICES; ix++) { + struct ata_device *dev = &ap->device[ix]; + + if (!ata_dev_enabled(dev)) + continue; + + ret = do_drive_get_GTF(dev, >f_length, >f_address, + &obj_loc); + if (ret < 0) { + if (ata_msg_probe(ap)) + ata_port_printk(ap, KERN_DEBUG, + "%s: get_GTF error (%d)\n", + __FUNCTION__, ret); + break; + } + + ret = do_drive_set_taskfiles(dev, gtf_length, gtf_address); + kfree((void *)obj_loc); + if (ret < 0) { + if (ata_msg_probe(ap)) + ata_port_printk(ap, KERN_DEBUG, + "%s: set_taskfiles error (%d)\n", + __FUNCTION__, ret); + break; + } + } + + return ret; } /** @@ -415,25 +620,62 @@ static int ata_acpi_exec_tfs(struct ata_device *dev) * ATM this function never returns a failure. It is an optional * method and if it fails for whatever reason, we should still * just keep going. - * - * LOCKING: - * EH context. - * - * RETURNS: - * 0 on success, -errno on failure. */ -static int ata_acpi_push_id(struct ata_device *dev) +int ata_acpi_push_id(struct ata_device *dev) { struct ata_port *ap = dev->ap; + acpi_handle handle; + acpi_integer pcidevfn; int err; + struct device *gdev = ap->host->dev; + u32 dev_adr; acpi_status status; struct acpi_object_list input; union acpi_object in_params[1]; + if (libata_noacpi) + return 0; + if (ata_msg_probe(ap)) ata_dev_printk(dev, KERN_DEBUG, "%s: ix = %d, port#: %d\n", __FUNCTION__, dev->devno, ap->port_no); + /* Don't continue if not a SATA device. */ + if (!(ap->flags & ATA_FLAG_ACPI_SATA)) { + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, + "%s: Not a SATA device\n", __FUNCTION__); + goto out; + } + + /* Don't continue if device has no _ADR method. + * _SDD is intended for known motherboard devices. */ + err = sata_get_dev_handle(gdev, &handle, &pcidevfn); + if (err < 0) { + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, + "%s: sata_get_dev_handle failed (%d\n", + __FUNCTION__, err); + goto out; + } + + /* Get this drive's _ADR info, if not already known */ + if (!dev->obj_handle) { + dev_adr = SATA_ADR_RSVD; + err = get_sata_adr(gdev, handle, pcidevfn, dev->devno, ap, dev, + &dev_adr); + if (err < 0 || dev_adr == SATA_ADR_RSVD || + !dev->obj_handle) { + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, + "%s: get_sata_adr failed: " + "err=%d, dev_adr=%u, obj_handle=0x%p\n", + __FUNCTION__, err, dev_adr, + dev->obj_handle); + goto out; + } + } + /* Give the drive Identify data to the drive via the _SDD method */ /* _SDD: set up input parameters */ input.count = 1; @@ -445,150 +687,20 @@ static int ata_acpi_push_id(struct ata_device *dev) /* It's OK for _SDD to be missing too. */ swap_buf_le16(dev->id, ATA_ID_WORDS); - status = acpi_evaluate_object(dev->acpi_handle, "_SDD", &input, NULL); + status = acpi_evaluate_object(dev->obj_handle, "_SDD", &input, NULL); swap_buf_le16(dev->id, ATA_ID_WORDS); err = ACPI_FAILURE(status) ? -EIO : 0; - if (err < 0) - ata_dev_printk(dev, KERN_WARNING, - "ACPI _SDD failed (AE 0x%x)\n", status); - - return err; -} - -/** - * ata_acpi_on_suspend - ATA ACPI hook called on suspend - * @ap: target ATA port - * - * This function is called when @ap is about to be suspended. All - * devices are already put to sleep but the port_suspend() callback - * hasn't been executed yet. Error return from this function aborts - * suspend. - * - * LOCKING: - * EH context. - * - * RETURNS: - * 0 on success, -errno on failure. - */ -int ata_acpi_on_suspend(struct ata_port *ap) -{ - unsigned long flags; - int rc; - - /* proceed iff per-port acpi_handle is valid */ - if (!ap->acpi_handle) - return 0; - BUG_ON(ap->flags & ATA_FLAG_ACPI_SATA); - - /* store timing parameters */ - rc = ata_acpi_gtm(ap, &ap->acpi_gtm); - - spin_lock_irqsave(ap->lock, flags); - if (rc == 0) - ap->pflags |= ATA_PFLAG_GTM_VALID; - else - ap->pflags &= ~ATA_PFLAG_GTM_VALID; - spin_unlock_irqrestore(ap->lock, flags); - - if (rc == -ENOENT) - rc = 0; - return rc; -} - -/** - * ata_acpi_on_resume - ATA ACPI hook called on resume - * @ap: target ATA port - * - * This function is called when @ap is resumed - right after port - * itself is resumed but before any EH action is taken. - * - * LOCKING: - * EH context. - */ -void ata_acpi_on_resume(struct ata_port *ap) -{ - int i; - - if (ap->acpi_handle && (ap->pflags & ATA_PFLAG_GTM_VALID)) { - BUG_ON(ap->flags & ATA_FLAG_ACPI_SATA); - - /* restore timing parameters */ - ata_acpi_stm(ap, &ap->acpi_gtm); - } - - /* schedule _GTF */ - for (i = 0; i < ATA_MAX_DEVICES; i++) - ap->device[i].flags |= ATA_DFLAG_ACPI_PENDING; -} - -/** - * ata_acpi_on_devcfg - ATA ACPI hook called on device donfiguration - * @dev: target ATA device - * - * This function is called when @dev is about to be configured. - * IDENTIFY data might have been modified after this hook is run. - * - * LOCKING: - * EH context. - * - * RETURNS: - * Positive number if IDENTIFY data needs to be refreshed, 0 if not, - * -errno on failure. - */ -int ata_acpi_on_devcfg(struct ata_device *dev) -{ - struct ata_port *ap = dev->ap; - struct ata_eh_context *ehc = &ap->eh_context; - int acpi_sata = ap->flags & ATA_FLAG_ACPI_SATA; - int rc; - - if (!dev->acpi_handle) - return 0; - - /* do we need to do _GTF? */ - if (!(dev->flags & ATA_DFLAG_ACPI_PENDING) && - !(acpi_sata && (ehc->i.flags & ATA_EHI_DID_HARDRESET))) - return 0; - - /* do _SDD if SATA */ - if (acpi_sata) { - rc = ata_acpi_push_id(dev); - if (rc) - goto acpi_err; - } - - /* do _GTF */ - rc = ata_acpi_exec_tfs(dev); - if (rc < 0) - goto acpi_err; - - dev->flags &= ~ATA_DFLAG_ACPI_PENDING; - - /* refresh IDENTIFY page if any _GTF command has been executed */ - if (rc > 0) { - rc = ata_dev_reread_id(dev, 0); - if (rc < 0) { - ata_dev_printk(dev, KERN_ERR, "failed to IDENTIFY " - "after ACPI commands\n"); - return rc; - } + if (err < 0) { + if (ata_msg_probe(ap)) + ata_dev_printk(dev, KERN_DEBUG, + "%s _SDD error: status = 0x%x\n", + __FUNCTION__, status); } + /* always return success */ +out: return 0; +} - acpi_err: - /* let EH retry on the first failure, disable ACPI on the second */ - if (dev->flags & ATA_DFLAG_ACPI_FAILED) { - ata_dev_printk(dev, KERN_WARNING, "ACPI on devcfg failed the " - "second time, disabling (errno=%d)\n", rc); - - dev->acpi_handle = NULL; - /* if port is working, request IDENTIFY reload and continue */ - if (!(ap->pflags & ATA_PFLAG_FROZEN)) - rc = 1; - } - dev->flags |= ATA_DFLAG_ACPI_FAILED; - return rc; -} diff --git a/trunk/drivers/ata/libata-core.c b/trunk/drivers/ata/libata-core.c index 5b25311ba885..981b397cb46b 100644 --- a/trunk/drivers/ata/libata-core.c +++ b/trunk/drivers/ata/libata-core.c @@ -1845,8 +1845,7 @@ static void ata_dev_config_ncq(struct ata_device *dev, int ata_dev_configure(struct ata_device *dev) { struct ata_port *ap = dev->ap; - struct ata_eh_context *ehc = &ap->eh_context; - int print_info = ehc->i.flags & ATA_EHI_PRINTINFO; + int print_info = ap->eh_context.i.flags & ATA_EHI_PRINTINFO; const u16 *id = dev->id; unsigned int xfer_mask; char revbuf[7]; /* XYZ-99\0 */ @@ -1863,10 +1862,15 @@ int ata_dev_configure(struct ata_device *dev) if (ata_msg_probe(ap)) ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__); - /* let ACPI work its magic */ - rc = ata_acpi_on_devcfg(dev); - if (rc) - return rc; + /* set _SDD */ + rc = ata_acpi_push_id(dev); + if (rc) { + ata_dev_printk(dev, KERN_WARNING, "failed to set _SDD(%d)\n", + rc); + } + + /* retrieve and execute the ATA task file of _GTF */ + ata_acpi_exec_tfs(ap); /* print device capabilities */ if (ata_msg_probe(ap)) @@ -3355,7 +3359,7 @@ int ata_std_prereset(struct ata_port *ap, unsigned long deadline) return 0; /* if SATA, resume phy */ - if (ap->flags & ATA_FLAG_SATA) { + if (ap->cbl == ATA_CBL_SATA) { rc = sata_phy_resume(ap, timing, deadline); /* whine about phy resume failure but proceed */ if (rc && rc != -EOPNOTSUPP) @@ -4102,68 +4106,6 @@ static void ata_fill_sg(struct ata_queued_cmd *qc) ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); } -/** - * ata_fill_sg_dumb - Fill PCI IDE PRD table - * @qc: Metadata associated with taskfile to be transferred - * - * Fill PCI IDE PRD (scatter-gather) table with segments - * associated with the current disk command. Perform the fill - * so that we avoid writing any length 64K records for - * controllers that don't follow the spec. - * - * LOCKING: - * spin_lock_irqsave(host lock) - * - */ -static void ata_fill_sg_dumb(struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - struct scatterlist *sg; - unsigned int idx; - - WARN_ON(qc->__sg == NULL); - WARN_ON(qc->n_elem == 0 && qc->pad_len == 0); - - idx = 0; - ata_for_each_sg(sg, qc) { - u32 addr, offset; - u32 sg_len, len, blen; - - /* determine if physical DMA addr spans 64K boundary. - * Note h/w doesn't support 64-bit, so we unconditionally - * truncate dma_addr_t to u32. - */ - addr = (u32) sg_dma_address(sg); - sg_len = sg_dma_len(sg); - - while (sg_len) { - offset = addr & 0xffff; - len = sg_len; - if ((offset + sg_len) > 0x10000) - len = 0x10000 - offset; - - blen = len & 0xffff; - ap->prd[idx].addr = cpu_to_le32(addr); - if (blen == 0) { - /* Some PATA chipsets like the CS5530 can't - cope with 0x0000 meaning 64K as the spec says */ - ap->prd[idx].flags_len = cpu_to_le32(0x8000); - blen = 0x8000; - ap->prd[++idx].addr = cpu_to_le32(addr + 0x8000); - } - ap->prd[idx].flags_len = cpu_to_le32(blen); - VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len); - - idx++; - sg_len -= len; - addr += len; - } - } - - if (idx) - ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); -} - /** * ata_check_atapi_dma - Check whether ATAPI DMA can be supported * @qc: Metadata associated with taskfile to check @@ -4211,23 +4153,6 @@ void ata_qc_prep(struct ata_queued_cmd *qc) ata_fill_sg(qc); } -/** - * ata_dumb_qc_prep - Prepare taskfile for submission - * @qc: Metadata associated with taskfile to be prepared - * - * Prepare ATA taskfile for submission. - * - * LOCKING: - * spin_lock_irqsave(host lock) - */ -void ata_dumb_qc_prep(struct ata_queued_cmd *qc) -{ - if (!(qc->flags & ATA_QCFLAG_DMAMAP)) - return; - - ata_fill_sg_dumb(qc); -} - void ata_noop_qc_prep(struct ata_queued_cmd *qc) { } /** @@ -5735,7 +5660,7 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance) */ int sata_scr_valid(struct ata_port *ap) { - return (ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read; + return ap->cbl == ATA_CBL_SATA && ap->ops->scr_read; } /** @@ -6368,9 +6293,6 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) if (rc) return rc; - /* associate with ACPI nodes */ - ata_acpi_associate(host); - /* set cable, sata_spd_limit and report */ for (i = 0; i < host->n_ports; i++) { struct ata_port *ap = host->ports[i]; @@ -6402,7 +6324,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) if (!ata_port_is_dummy(ap)) ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%p " "ctl 0x%p bmdma 0x%p irq %d\n", - (ap->flags & ATA_FLAG_SATA) ? 'S' : 'P', + ap->cbl == ATA_CBL_SATA ? 'S' : 'P', ata_mode_string(xfer_mask), ap->ioaddr.cmd_addr, ap->ioaddr.ctl_addr, @@ -6900,7 +6822,6 @@ EXPORT_SYMBOL_GPL(ata_do_set_mode); EXPORT_SYMBOL_GPL(ata_data_xfer); EXPORT_SYMBOL_GPL(ata_data_xfer_noirq); EXPORT_SYMBOL_GPL(ata_qc_prep); -EXPORT_SYMBOL_GPL(ata_dumb_qc_prep); EXPORT_SYMBOL_GPL(ata_noop_qc_prep); EXPORT_SYMBOL_GPL(ata_bmdma_setup); EXPORT_SYMBOL_GPL(ata_bmdma_start); diff --git a/trunk/drivers/ata/libata-eh.c b/trunk/drivers/ata/libata-eh.c index 9ee0a8c08d96..f7582c9c320e 100644 --- a/trunk/drivers/ata/libata-eh.c +++ b/trunk/drivers/ata/libata-eh.c @@ -2154,25 +2154,19 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap) WARN_ON(ap->pflags & ATA_PFLAG_SUSPENDED); - /* tell ACPI we're suspending */ - rc = ata_acpi_on_suspend(ap); - if (rc) - goto out; - /* suspend */ ata_eh_freeze_port(ap); if (ap->ops->port_suspend) rc = ap->ops->port_suspend(ap, ap->pm_mesg); - out: /* report result */ spin_lock_irqsave(ap->lock, flags); ap->pflags &= ~ATA_PFLAG_PM_PENDING; if (rc == 0) ap->pflags |= ATA_PFLAG_SUSPENDED; - else if (ap->pflags & ATA_PFLAG_FROZEN) + else ata_port_schedule_eh(ap); if (ap->pm_result) { @@ -2213,9 +2207,6 @@ static void ata_eh_handle_port_resume(struct ata_port *ap) if (ap->ops->port_resume) rc = ap->ops->port_resume(ap); - /* tell ACPI that we're resuming */ - ata_acpi_on_resume(ap); - /* report result */ spin_lock_irqsave(ap->lock, flags); ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED); diff --git a/trunk/drivers/ata/libata-scsi.c b/trunk/drivers/ata/libata-scsi.c index cfde22da07ac..4ddf00c8c5f5 100644 --- a/trunk/drivers/ata/libata-scsi.c +++ b/trunk/drivers/ata/libata-scsi.c @@ -2620,7 +2620,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) ata_dev_printk(dev, KERN_WARNING, "invalid multi_count %u ignored\n", multi_count); - } + } /* READ/WRITE LONG use a non-standard sect_size */ qc->sect_size = ATA_SECT_SIZE; diff --git a/trunk/drivers/ata/libata.h b/trunk/drivers/ata/libata.h index ba17fc5f2e99..5e2466658420 100644 --- a/trunk/drivers/ata/libata.h +++ b/trunk/drivers/ata/libata.h @@ -98,15 +98,17 @@ extern struct ata_port *ata_port_alloc(struct ata_host *host); /* libata-acpi.c */ #ifdef CONFIG_ATA_ACPI -extern void ata_acpi_associate(struct ata_host *host); -extern int ata_acpi_on_suspend(struct ata_port *ap); -extern void ata_acpi_on_resume(struct ata_port *ap); -extern int ata_acpi_on_devcfg(struct ata_device *adev); +extern int ata_acpi_exec_tfs(struct ata_port *ap); +extern int ata_acpi_push_id(struct ata_device *dev); #else -static inline void ata_acpi_associate(struct ata_host *host) { } -static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; } -static inline void ata_acpi_on_resume(struct ata_port *ap) { } -static inline int ata_acpi_on_devcfg(struct ata_device *adev) { return 0; } +static inline int ata_acpi_exec_tfs(struct ata_port *ap) +{ + return 0; +} +static inline int ata_acpi_push_id(struct ata_device *dev) +{ + return 0; +} #endif /* libata-scsi.c */ diff --git a/trunk/drivers/ata/pata_ali.c b/trunk/drivers/ata/pata_ali.c index 30c4276ec882..75e95bdbe02f 100644 --- a/trunk/drivers/ata/pata_ali.c +++ b/trunk/drivers/ata/pata_ali.c @@ -520,14 +520,14 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { static const struct ata_port_info info_early = { .sht = &ali_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .port_ops = &ali_early_port_ops }; /* Revision 0x20 added DMA */ static const struct ata_port_info info_20 = { .sht = &ali_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, .pio_mask = 0x1f, .mwdma_mask = 0x07, .port_ops = &ali_20_port_ops @@ -535,7 +535,7 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) /* Revision 0x20 with support logic added UDMA */ static const struct ata_port_info info_20_udma = { .sht = &ali_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, .pio_mask = 0x1f, .mwdma_mask = 0x07, .udma_mask = 0x07, /* UDMA33 */ @@ -544,37 +544,37 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) /* Revision 0xC2 adds UDMA66 */ static const struct ata_port_info info_c2 = { .sht = &ali_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA4, + .udma_mask = 0x1f, .port_ops = &ali_c2_port_ops }; /* Revision 0xC3 is UDMA66 for now */ static const struct ata_port_info info_c3 = { .sht = &ali_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA4, + .udma_mask = 0x1f, .port_ops = &ali_c2_port_ops }; /* Revision 0xC4 is UDMA100 */ static const struct ata_port_info info_c4 = { .sht = &ali_sht, - .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, + .udma_mask = 0x3f, .port_ops = &ali_c2_port_ops }; /* Revision 0xC5 is UDMA133 with LBA48 DMA */ static const struct ata_port_info info_c5 = { .sht = &ali_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, .port_ops = &ali_c5_port_ops }; diff --git a/trunk/drivers/ata/pata_amd.c b/trunk/drivers/ata/pata_amd.c index b9c44c575ce3..a16f629b7b38 100644 --- a/trunk/drivers/ata/pata_amd.c +++ b/trunk/drivers/ata/pata_amd.c @@ -541,7 +541,7 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) static const struct ata_port_info info[10] = { { /* 0: AMD 7401 */ .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, /* No SWDMA */ .udma_mask = 0x07, /* UDMA 33 */ @@ -549,74 +549,74 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) }, { /* 1: Early AMD7409 - no swdma */ .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA4, /* UDMA 66 */ + .udma_mask = 0x1f, /* UDMA 66 */ .port_ops = &amd66_port_ops }, { /* 2: AMD 7409, no swdma errata */ .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA4, /* UDMA 66 */ + .udma_mask = 0x1f, /* UDMA 66 */ .port_ops = &amd66_port_ops }, { /* 3: AMD 7411 */ .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, /* UDMA 100 */ + .udma_mask = 0x3f, /* UDMA 100 */ .port_ops = &amd100_port_ops }, { /* 4: AMD 7441 */ .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, /* UDMA 100 */ + .udma_mask = 0x3f, /* UDMA 100 */ .port_ops = &amd100_port_ops }, { /* 5: AMD 8111*/ .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA6, /* UDMA 133, no swdma */ + .udma_mask = 0x7f, /* UDMA 133, no swdma */ .port_ops = &amd133_port_ops }, { /* 6: AMD 8111 UDMA 100 (Serenade) */ .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, /* UDMA 100, no swdma */ + .udma_mask = 0x3f, /* UDMA 100, no swdma */ .port_ops = &amd133_port_ops }, { /* 7: Nvidia Nforce */ .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, /* UDMA 100 */ + .udma_mask = 0x3f, /* UDMA 100 */ .port_ops = &nv100_port_ops }, { /* 8: Nvidia Nforce2 and later */ .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA6, /* UDMA 133, no swdma */ + .udma_mask = 0x7f, /* UDMA 133, no swdma */ .port_ops = &nv133_port_ops }, { /* 9: AMD CS5536 (Geode companion) */ .sht = &amd_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, /* UDMA 100 */ + .udma_mask = 0x3f, /* UDMA 100 */ .port_ops = &amd100_port_ops } }; diff --git a/trunk/drivers/ata/pata_artop.c b/trunk/drivers/ata/pata_artop.c index ce589d96ca42..03b6ddd2abd2 100644 --- a/trunk/drivers/ata/pata_artop.c +++ b/trunk/drivers/ata/pata_artop.c @@ -416,7 +416,7 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id) static int printed_version; static const struct ata_port_info info_6210 = { .sht = &artop_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = ATA_UDMA2, @@ -424,7 +424,7 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id) }; static const struct ata_port_info info_626x = { .sht = &artop_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = ATA_UDMA4, @@ -432,7 +432,7 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id) }; static const struct ata_port_info info_626x_fast = { .sht = &artop_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = ATA_UDMA5, diff --git a/trunk/drivers/ata/pata_atiixp.c b/trunk/drivers/ata/pata_atiixp.c index 80509be49e7a..844914681a2a 100644 --- a/trunk/drivers/ata/pata_atiixp.c +++ b/trunk/drivers/ata/pata_atiixp.c @@ -270,7 +270,7 @@ static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info = { .sht = &atiixp_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x06, /* No MWDMA0 support */ .udma_mask = 0x3F, @@ -285,7 +285,6 @@ static const struct pci_device_id atiixp[] = { { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP300_IDE), }, { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP400_IDE), }, { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP600_IDE), }, - { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP700_IDE), }, { }, }; diff --git a/trunk/drivers/ata/pata_cmd640.c b/trunk/drivers/ata/pata_cmd640.c index 0feb5ae8c486..31cbf8daa299 100644 --- a/trunk/drivers/ata/pata_cmd640.c +++ b/trunk/drivers/ata/pata_cmd640.c @@ -251,7 +251,7 @@ static int cmd640_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { static const struct ata_port_info info = { .sht = &cmd640_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .port_ops = &cmd640_port_ops }; diff --git a/trunk/drivers/ata/pata_cmd64x.c b/trunk/drivers/ata/pata_cmd64x.c index dc443e7dc37c..320a5b10aa98 100644 --- a/trunk/drivers/ata/pata_cmd64x.c +++ b/trunk/drivers/ata/pata_cmd64x.c @@ -380,21 +380,21 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) static const struct ata_port_info cmd_info[6] = { { /* CMD 643 - no UDMA */ .sht = &cmd64x_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .port_ops = &cmd64x_port_ops }, { /* CMD 646 with broken UDMA */ .sht = &cmd64x_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .port_ops = &cmd64x_port_ops }, { /* CMD 646 with working UDMA */ .sht = &cmd64x_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .udma_mask = ATA_UDMA1, @@ -402,14 +402,14 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) }, { /* CMD 646 rev 1 */ .sht = &cmd64x_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .port_ops = &cmd646r1_port_ops }, { /* CMD 648 */ .sht = &cmd64x_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .udma_mask = ATA_UDMA2, @@ -417,7 +417,7 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) }, { /* CMD 649 */ .sht = &cmd64x_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .udma_mask = ATA_UDMA3, diff --git a/trunk/drivers/ata/pata_cs5520.c b/trunk/drivers/ata/pata_cs5520.c index 6bf037d82b5a..00cf0134079c 100644 --- a/trunk/drivers/ata/pata_cs5520.c +++ b/trunk/drivers/ata/pata_cs5520.c @@ -146,7 +146,7 @@ static struct scsi_host_template cs5520_sht = { .queuecommand = ata_scsi_queuecmd, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_DUMB_MAX_PRD, + .sg_tablesize = LIBATA_MAX_PRD, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, @@ -178,7 +178,7 @@ static struct ata_port_operations cs5520_port_ops = { .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, .bmdma_status = ata_bmdma_status, - .qc_prep = ata_dumb_qc_prep, + .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, .data_xfer = ata_data_xfer, diff --git a/trunk/drivers/ata/pata_cs5530.c b/trunk/drivers/ata/pata_cs5530.c index 3fca5898642b..848f0309bf03 100644 --- a/trunk/drivers/ata/pata_cs5530.c +++ b/trunk/drivers/ata/pata_cs5530.c @@ -167,7 +167,7 @@ static struct scsi_host_template cs5530_sht = { .queuecommand = ata_scsi_queuecmd, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_DUMB_MAX_PRD, + .sg_tablesize = LIBATA_MAX_PRD, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, @@ -201,7 +201,7 @@ static struct ata_port_operations cs5530_port_ops = { .post_internal_cmd = ata_bmdma_post_internal_cmd, .cable_detect = ata_cable_40wire, - .qc_prep = ata_dumb_qc_prep, + .qc_prep = ata_qc_prep, .qc_issue = cs5530_qc_issue_prot, .data_xfer = ata_data_xfer, @@ -337,7 +337,7 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { static const struct ata_port_info info = { .sht = &cs5530_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .udma_mask = 0x07, @@ -346,7 +346,7 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id) /* The docking connector doesn't do UDMA, and it seems not MWDMA */ static const struct ata_port_info info_palmax_secondary = { .sht = &cs5530_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, .port_ops = &cs5530_port_ops }; diff --git a/trunk/drivers/ata/pata_cs5535.c b/trunk/drivers/ata/pata_cs5535.c index 360b6f32e17e..aa3256fb9f7a 100644 --- a/trunk/drivers/ata/pata_cs5535.c +++ b/trunk/drivers/ata/pata_cs5535.c @@ -225,10 +225,10 @@ static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info = { .sht = &cs5535_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA4, + .udma_mask = 0x1f, .port_ops = &cs5535_port_ops }; const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; diff --git a/trunk/drivers/ata/pata_cypress.c b/trunk/drivers/ata/pata_cypress.c index 6cbc8778bf4f..d41a7691dd8e 100644 --- a/trunk/drivers/ata/pata_cypress.c +++ b/trunk/drivers/ata/pata_cypress.c @@ -167,7 +167,7 @@ static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *i { static const struct ata_port_info info = { .sht = &cy82c693_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .port_ops = &cy82c693_port_ops diff --git a/trunk/drivers/ata/pata_efar.c b/trunk/drivers/ata/pata_efar.c index c8ba59c56114..079248a9b460 100644 --- a/trunk/drivers/ata/pata_efar.c +++ b/trunk/drivers/ata/pata_efar.c @@ -303,7 +303,7 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) static int printed_version; static const struct ata_port_info info = { .sht = &efar_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma1-2 */ .udma_mask = 0x0f, /* UDMA 66 */ diff --git a/trunk/drivers/ata/pata_hpt366.c b/trunk/drivers/ata/pata_hpt366.c index 6f7d34ad19ef..0c9cb6090711 100644 --- a/trunk/drivers/ata/pata_hpt366.c +++ b/trunk/drivers/ata/pata_hpt366.c @@ -393,10 +393,10 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info_hpt366 = { .sht = &hpt36x_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA4, + .udma_mask = 0x1f, .port_ops = &hpt366_port_ops }; struct ata_port_info info = info_hpt366; diff --git a/trunk/drivers/ata/pata_hpt37x.c b/trunk/drivers/ata/pata_hpt37x.c index b0af65aadde3..a8c0cbeca399 100644 --- a/trunk/drivers/ata/pata_hpt37x.c +++ b/trunk/drivers/ata/pata_hpt37x.c @@ -889,25 +889,25 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) /* HPT370 - UDMA100 */ static const struct ata_port_info info_hpt370 = { .sht = &hpt37x_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, + .udma_mask = 0x3f, .port_ops = &hpt370_port_ops }; /* HPT370A - UDMA100 */ static const struct ata_port_info info_hpt370a = { .sht = &hpt37x_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, + .udma_mask = 0x3f, .port_ops = &hpt370a_port_ops }; /* HPT370 - UDMA100 */ static const struct ata_port_info info_hpt370_33 = { .sht = &hpt37x_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .udma_mask = 0x0f, @@ -916,7 +916,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) /* HPT370A - UDMA100 */ static const struct ata_port_info info_hpt370a_33 = { .sht = &hpt37x_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .udma_mask = 0x0f, @@ -925,19 +925,19 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) /* HPT371, 372 and friends - UDMA133 */ static const struct ata_port_info info_hpt372 = { .sht = &hpt37x_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, .port_ops = &hpt372_port_ops }; /* HPT374 - UDMA100 */ static const struct ata_port_info info_hpt374 = { .sht = &hpt37x_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, + .udma_mask = 0x3f, .port_ops = &hpt374_port_ops }; diff --git a/trunk/drivers/ata/pata_hpt3x2n.c b/trunk/drivers/ata/pata_hpt3x2n.c index aa29cde09f8b..e947433cb37d 100644 --- a/trunk/drivers/ata/pata_hpt3x2n.c +++ b/trunk/drivers/ata/pata_hpt3x2n.c @@ -490,10 +490,10 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) /* HPT372N and friends - UDMA133 */ static const struct ata_port_info info = { .sht = &hpt3x2n_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, .port_ops = &hpt3x2n_port_ops }; struct ata_port_info port = info; diff --git a/trunk/drivers/ata/pata_hpt3x3.c b/trunk/drivers/ata/pata_hpt3x3.c index d928c9105034..8ce5e23a5f75 100644 --- a/trunk/drivers/ata/pata_hpt3x3.c +++ b/trunk/drivers/ata/pata_hpt3x3.c @@ -173,7 +173,7 @@ static int hpt3x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info = { .sht = &hpt3x3_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .udma_mask = 0x07, diff --git a/trunk/drivers/ata/pata_icside.c b/trunk/drivers/ata/pata_icside.c index 321d98b0bed2..c791a46df461 100644 --- a/trunk/drivers/ata/pata_icside.c +++ b/trunk/drivers/ata/pata_icside.c @@ -530,7 +530,7 @@ static int __devinit pata_icside_add_ports(struct pata_icside_info *info) ap->pio_mask = 0x1f; ap->mwdma_mask = info->mwdma_mask; - ap->flags |= ATA_FLAG_SLAVE_POSS; + ap->flags |= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST; ap->ops = &pata_icside_port_ops; pata_icside_setup_ioaddr(&ap->ioaddr, info->base, info->port[i]); diff --git a/trunk/drivers/ata/pata_it8213.c b/trunk/drivers/ata/pata_it8213.c index b8af55e89156..95b0bb61788b 100644 --- a/trunk/drivers/ata/pata_it8213.c +++ b/trunk/drivers/ata/pata_it8213.c @@ -313,10 +313,10 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en static int printed_version; static const struct ata_port_info info = { .sht = &it8213_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA4, /* FIXME: want UDMA 100? */ + .udma_mask = 0x1f, /* UDMA 100 */ .port_ops = &it8213_ops, }; /* Current IT8213 stuff is single port */ diff --git a/trunk/drivers/ata/pata_it821x.c b/trunk/drivers/ata/pata_it821x.c index b67bbf6516ba..12c6e08cc4d1 100644 --- a/trunk/drivers/ata/pata_it821x.c +++ b/trunk/drivers/ata/pata_it821x.c @@ -714,17 +714,17 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) static const struct ata_port_info info_smart = { .sht = &it821x_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .port_ops = &it821x_smart_port_ops }; static const struct ata_port_info info_passthru = { .sht = &it821x_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, .port_ops = &it821x_passthru_port_ops }; diff --git a/trunk/drivers/ata/pata_ixp4xx_cf.c b/trunk/drivers/ata/pata_ixp4xx_cf.c index 4ca7fd6118d5..8d2bc1e9e871 100644 --- a/trunk/drivers/ata/pata_ixp4xx_cf.c +++ b/trunk/drivers/ata/pata_ixp4xx_cf.c @@ -1,14 +1,13 @@ /* * ixp4xx PATA/Compact Flash driver - * Copyright (C) 2006-07 Tower Technologies + * Copyright (c) 2006 Tower Technologies * Author: Alessandro Zummo * * An ATA driver to handle a Compact Flash connected * to the ixp4xx expansion bus in TrueIDE mode. The CF * must have it chip selects connected to two CS lines - * on the ixp4xx. In the irq is not available, you might - * want to modify both this driver and libata to run in - * polling mode. + * on the ixp4xx. The interrupt line is optional, if not + * specified the driver will run in polling mode. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -24,7 +23,7 @@ #include #define DRV_NAME "pata_ixp4xx_cf" -#define DRV_VERSION "0.2" +#define DRV_VERSION "0.1.3" static int ixp4xx_set_mode(struct ata_port *ap, struct ata_device **error) { @@ -43,6 +42,13 @@ static int ixp4xx_set_mode(struct ata_port *ap, struct ata_device **error) return 0; } +static void ixp4xx_phy_reset(struct ata_port *ap) +{ + ap->cbl = ATA_CBL_PATA40; + ata_port_probe(ap); + ata_bus_reset(ap); +} + static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data) { @@ -50,7 +56,7 @@ static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int words = buflen >> 1; u16 *buf16 = (u16 *) buf; struct ata_port *ap = adev->ap; - void __iomem *mmio = ap->ioaddr.data_addr; + void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr; struct ixp4xx_pata_data *data = ap->host->dev->platform_data; /* set the expansion bus in 16bit mode and restore @@ -86,6 +92,10 @@ static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf, *data->cs0_cfg |= 0x01; } +static void ixp4xx_irq_clear(struct ata_port *ap) +{ +} + static struct scsi_host_template ixp4xx_sht = { .module = THIS_MODULE, .name = DRV_NAME, @@ -105,32 +115,29 @@ static struct scsi_host_template ixp4xx_sht = { }; static struct ata_port_operations ixp4xx_port_ops = { - .set_mode = ixp4xx_set_mode, - .mode_filter = ata_pci_default_filter, - - .port_disable = ata_port_disable, - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .exec_command = ata_exec_command, - .check_status = ata_check_status, - .dev_select = ata_std_dev_select, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = ata_bmdma_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .data_xfer = ixp4xx_mmio_data_xfer, - .cable_detect = ata_cable_40wire, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - .irq_on = ata_irq_on, - .irq_ack = ata_dummy_irq_ack, - - .port_start = ata_port_start, + .set_mode = ixp4xx_set_mode, + .mode_filter = ata_pci_default_filter, + + .port_disable = ata_port_disable, + .tf_load = ata_tf_load, + .tf_read = ata_tf_read, + .check_status = ata_check_status, + .exec_command = ata_exec_command, + .dev_select = ata_std_dev_select, + + .qc_prep = ata_qc_prep, + .qc_issue = ata_qc_issue_prot, + .eng_timeout = ata_eng_timeout, + .data_xfer = ixp4xx_mmio_data_xfer, + .cable_detect = ata_cable_40wire, + + .irq_clear = ixp4xx_irq_clear, + .irq_on = ata_irq_on, + .irq_ack = ata_irq_ack, + + .port_start = ata_port_start, + + .phy_reset = ixp4xx_phy_reset, }; static void ixp4xx_setup_port(struct ata_ioports *ioaddr, @@ -171,6 +178,7 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev) struct ata_host *host; struct ata_port *ap; struct ixp4xx_pata_data *data = pdev->dev.platform_data; + int rc; cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); @@ -203,6 +211,10 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev) ap->pio_mask = 0x1f; /* PIO4 */ ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_NO_ATAPI; + /* run in polling mode if no irq has been assigned */ + if (!irq) + ap->flags |= ATA_FLAG_PIO_POLLING; + ixp4xx_setup_port(&ap->ioaddr, data); dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); diff --git a/trunk/drivers/ata/pata_jmicron.c b/trunk/drivers/ata/pata_jmicron.c index 4d67f238eee2..2af7ff8256ca 100644 --- a/trunk/drivers/ata/pata_jmicron.c +++ b/trunk/drivers/ata/pata_jmicron.c @@ -193,11 +193,11 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i { static const struct ata_port_info info = { .sht = &jmicron_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, + .udma_mask = 0x3f, .port_ops = &jmicron_ops, }; diff --git a/trunk/drivers/ata/pata_marvell.c b/trunk/drivers/ata/pata_marvell.c index 87594c04d3a3..edbfe0dbbf78 100644 --- a/trunk/drivers/ata/pata_marvell.c +++ b/trunk/drivers/ata/pata_marvell.c @@ -163,22 +163,22 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i { static const struct ata_port_info info = { .sht = &marvell_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, + .udma_mask = 0x3f, .port_ops = &marvell_ops, }; static const struct ata_port_info info_sata = { .sht = &marvell_sht, /* Slave possible as its magically mapped not real */ - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, .port_ops = &marvell_ops, }; diff --git a/trunk/drivers/ata/pata_netcell.c b/trunk/drivers/ata/pata_netcell.c index 40eb574828bf..81f563458666 100644 --- a/trunk/drivers/ata/pata_netcell.c +++ b/trunk/drivers/ata/pata_netcell.c @@ -94,12 +94,12 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e static int printed_version; static const struct ata_port_info info = { .sht = &netcell_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, /* Actually we don't really care about these as the firmware deals with it */ .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, /* UDMA 133 */ + .udma_mask = 0x3f, /* UDMA 133 */ .port_ops = &netcell_ops, }; const struct ata_port_info *port_info[] = { &info, NULL }; diff --git a/trunk/drivers/ata/pata_ns87410.c b/trunk/drivers/ata/pata_ns87410.c index 2f5d714ebfc4..ea70ec744879 100644 --- a/trunk/drivers/ata/pata_ns87410.c +++ b/trunk/drivers/ata/pata_ns87410.c @@ -193,7 +193,7 @@ static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info = { .sht = &ns87410_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x0F, .port_ops = &ns87410_port_ops }; diff --git a/trunk/drivers/ata/pata_oldpiix.c b/trunk/drivers/ata/pata_oldpiix.c index 091a70a0ef1c..29c23ddd6550 100644 --- a/trunk/drivers/ata/pata_oldpiix.c +++ b/trunk/drivers/ata/pata_oldpiix.c @@ -291,7 +291,7 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e static int printed_version; static const struct ata_port_info info = { .sht = &oldpiix_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma1-2 */ .port_ops = &oldpiix_pata_ops, diff --git a/trunk/drivers/ata/pata_opti.c b/trunk/drivers/ata/pata_opti.c index 458bf67f766f..1c44653e1e06 100644 --- a/trunk/drivers/ata/pata_opti.c +++ b/trunk/drivers/ata/pata_opti.c @@ -218,7 +218,7 @@ static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info = { .sht = &opti_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .port_ops = &opti_port_ops }; diff --git a/trunk/drivers/ata/pata_optidma.c b/trunk/drivers/ata/pata_optidma.c index f89bdfde16d0..3093b02286ce 100644 --- a/trunk/drivers/ata/pata_optidma.c +++ b/trunk/drivers/ata/pata_optidma.c @@ -484,14 +484,14 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info_82c700 = { .sht = &optidma_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .port_ops = &optidma_port_ops }; static const struct ata_port_info info_82c700_udma = { .sht = &optidma_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .udma_mask = 0x07, diff --git a/trunk/drivers/ata/pata_pdc202xx_old.c b/trunk/drivers/ata/pata_pdc202xx_old.c index 92447bed5e77..d277246b7337 100644 --- a/trunk/drivers/ata/pata_pdc202xx_old.c +++ b/trunk/drivers/ata/pata_pdc202xx_old.c @@ -320,7 +320,7 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id static const struct ata_port_info info[3] = { { .sht = &pdc202xx_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .udma_mask = ATA_UDMA2, @@ -328,7 +328,7 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id }, { .sht = &pdc202xx_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .udma_mask = ATA_UDMA4, @@ -336,7 +336,7 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id }, { .sht = &pdc202xx_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .udma_mask = ATA_UDMA5, diff --git a/trunk/drivers/ata/pata_platform.c b/trunk/drivers/ata/pata_platform.c index 79f841bca593..cbb7866940d6 100644 --- a/trunk/drivers/ata/pata_platform.c +++ b/trunk/drivers/ata/pata_platform.c @@ -139,7 +139,6 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) struct resource *io_res, *ctl_res; struct ata_host *host; struct ata_port *ap; - struct pata_platform_info *pp_info; unsigned int mmio; /* @@ -209,12 +208,11 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr; - pp_info = (struct pata_platform_info *)(pdev->dev.platform_data); - pata_platform_setup_port(&ap->ioaddr, pp_info); + pata_platform_setup_port(&ap->ioaddr, pdev->dev.platform_data); /* activate */ return ata_host_activate(host, platform_get_irq(pdev, 0), ata_interrupt, - pp_info->irq_flags, &pata_platform_sht); + 0, &pata_platform_sht); } /** diff --git a/trunk/drivers/ata/pata_radisys.c b/trunk/drivers/ata/pata_radisys.c index 7d1aabed422d..ba96b54f5b87 100644 --- a/trunk/drivers/ata/pata_radisys.c +++ b/trunk/drivers/ata/pata_radisys.c @@ -257,7 +257,7 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e static int printed_version; static const struct ata_port_info info = { .sht = &radisys_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma1-2 */ .udma_mask = 0x14, /* UDMA33/66 only */ diff --git a/trunk/drivers/ata/pata_rz1000.c b/trunk/drivers/ata/pata_rz1000.c index 7632fcb070ca..a3488b41ad26 100644 --- a/trunk/drivers/ata/pata_rz1000.c +++ b/trunk/drivers/ata/pata_rz1000.c @@ -133,7 +133,7 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en static int printed_version; static const struct ata_port_info info = { .sht = &rz1000_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .port_ops = &rz1000_port_ops }; diff --git a/trunk/drivers/ata/pata_sc1200.c b/trunk/drivers/ata/pata_sc1200.c index b8b2d11e4180..1233063ab9a8 100644 --- a/trunk/drivers/ata/pata_sc1200.c +++ b/trunk/drivers/ata/pata_sc1200.c @@ -185,7 +185,7 @@ static struct scsi_host_template sc1200_sht = { .queuecommand = ata_scsi_queuecmd, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_DUMB_MAX_PRD, + .sg_tablesize = LIBATA_MAX_PRD, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, @@ -219,7 +219,7 @@ static struct ata_port_operations sc1200_port_ops = { .bmdma_stop = ata_bmdma_stop, .bmdma_status = ata_bmdma_status, - .qc_prep = ata_dumb_qc_prep, + .qc_prep = ata_qc_prep, .qc_issue = sc1200_qc_issue_prot, .data_xfer = ata_data_xfer, @@ -245,7 +245,7 @@ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info = { .sht = &sc1200_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .udma_mask = 0x07, diff --git a/trunk/drivers/ata/pata_serverworks.c b/trunk/drivers/ata/pata_serverworks.c index 0231aba51ca4..1e8f421963c7 100644 --- a/trunk/drivers/ata/pata_serverworks.c +++ b/trunk/drivers/ata/pata_serverworks.c @@ -478,31 +478,31 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id static const struct ata_port_info info[4] = { { /* OSB4 */ .sht = &serverworks_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .udma_mask = 0x07, .port_ops = &serverworks_osb4_port_ops }, { /* OSB4 no UDMA */ .sht = &serverworks_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .udma_mask = 0x00, .port_ops = &serverworks_osb4_port_ops }, { /* CSB5 */ .sht = &serverworks_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA4, + .udma_mask = 0x1f, .port_ops = &serverworks_csb_port_ops }, { /* CSB5 - later revisions*/ .sht = &serverworks_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, + .udma_mask = 0x3f, .port_ops = &serverworks_csb_port_ops } }; diff --git a/trunk/drivers/ata/pata_sil680.c b/trunk/drivers/ata/pata_sil680.c index b0cd52d6e3fb..440e2cb6ee75 100644 --- a/trunk/drivers/ata/pata_sil680.c +++ b/trunk/drivers/ata/pata_sil680.c @@ -35,8 +35,6 @@ #define DRV_NAME "pata_sil680" #define DRV_VERSION "0.4.6" -#define SIL680_MMIO_BAR 5 - /** * sil680_selreg - return register base * @hwif: interface @@ -295,8 +293,8 @@ static u8 sil680_init_chip(struct pci_dev *pdev) pci_read_config_byte(pdev, 0x8A, &tmpbyte); - dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n", - tmpbyte & 1, tmpbyte & 0x30); + printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n", + tmpbyte & 1, tmpbyte & 0x30); switch(tmpbyte & 0x30) { case 0x00: @@ -317,8 +315,8 @@ static u8 sil680_init_chip(struct pci_dev *pdev) } pci_read_config_byte(pdev, 0x8A, &tmpbyte); - dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n", - tmpbyte & 1, tmpbyte & 0x30); + printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n", + tmpbyte & 1, tmpbyte & 0x30); pci_write_config_byte(pdev, 0xA1, 0x72); pci_write_config_word(pdev, 0xA2, 0x328A); @@ -341,23 +339,22 @@ static u8 sil680_init_chip(struct pci_dev *pdev) return tmpbyte & 0x30; } -static int __devinit sil680_init_one(struct pci_dev *pdev, - const struct pci_device_id *id) +static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { static const struct ata_port_info info = { .sht = &sil680_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, .port_ops = &sil680_port_ops }; static const struct ata_port_info info_slow = { .sht = &sil680_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, + .udma_mask = 0x3f, .port_ops = &sil680_port_ops }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/trunk/drivers/ata/pata_sis.c b/trunk/drivers/ata/pata_sis.c index 2b4508206a6c..cfe4ec6eb3d5 100644 --- a/trunk/drivers/ata/pata_sis.c +++ b/trunk/drivers/ata/pata_sis.c @@ -732,7 +732,7 @@ static const struct ata_port_operations sis_old_ops = { static const struct ata_port_info sis_info = { .sht = &sis_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, .udma_mask = 0, @@ -740,7 +740,7 @@ static const struct ata_port_info sis_info = { }; static const struct ata_port_info sis_info33 = { .sht = &sis_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, .udma_mask = ATA_UDMA2, /* UDMA 33 */ @@ -748,28 +748,28 @@ static const struct ata_port_info sis_info33 = { }; static const struct ata_port_info sis_info66 = { .sht = &sis_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA4, /* UDMA 66 */ .port_ops = &sis_66_ops, }; static const struct ata_port_info sis_info100 = { .sht = &sis_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA5, .port_ops = &sis_100_ops, }; static const struct ata_port_info sis_info100_early = { .sht = &sis_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .udma_mask = ATA_UDMA5, .pio_mask = 0x1f, /* pio0-4 */ .port_ops = &sis_66_ops, }; static const struct ata_port_info sis_info133 = { .sht = &sis_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &sis_133_ops, @@ -783,7 +783,7 @@ const struct ata_port_info sis_info133_for_sata = { }; static const struct ata_port_info sis_info133_early = { .sht = &sis_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &sis_133_early_ops, diff --git a/trunk/drivers/ata/pata_sl82c105.c b/trunk/drivers/ata/pata_sl82c105.c index bde734189623..e5aaec43694d 100644 --- a/trunk/drivers/ata/pata_sl82c105.c +++ b/trunk/drivers/ata/pata_sl82c105.c @@ -303,14 +303,14 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id { static const struct ata_port_info info_dma = { .sht = &sl82c105_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .port_ops = &sl82c105_port_ops }; static const struct ata_port_info info_early = { .sht = &sl82c105_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .port_ops = &sl82c105_port_ops }; diff --git a/trunk/drivers/ata/pata_triflex.c b/trunk/drivers/ata/pata_triflex.c index af21f443db6e..b1d3076dfe51 100644 --- a/trunk/drivers/ata/pata_triflex.c +++ b/trunk/drivers/ata/pata_triflex.c @@ -235,7 +235,7 @@ static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info = { .sht = &triflex_sht, - .flags = ATA_FLAG_SLAVE_POSS, + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, .pio_mask = 0x1f, .mwdma_mask = 0x07, .port_ops = &triflex_port_ops diff --git a/trunk/drivers/ata/pata_via.c b/trunk/drivers/ata/pata_via.c index f0cadbe6aa11..63eca299c62b 100644 --- a/trunk/drivers/ata/pata_via.c +++ b/trunk/drivers/ata/pata_via.c @@ -471,7 +471,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA2, + .udma_mask = 0x7, .port_ops = &via_port_ops }; /* VIA UDMA 66 devices */ @@ -480,7 +480,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA4, + .udma_mask = 0x1f, .port_ops = &via_port_ops }; /* VIA UDMA 100 devices */ @@ -489,7 +489,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, + .udma_mask = 0x3f, .port_ops = &via_port_ops }; /* UDMA133 with bad AST (All current 133) */ @@ -498,7 +498,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA6, /* FIXME: should check north bridge */ + .udma_mask = 0x7f, /* FIXME: should check north bridge */ .port_ops = &via_port_ops }; struct ata_port_info type; diff --git a/trunk/drivers/ata/pdc_adma.c b/trunk/drivers/ata/pdc_adma.c index bec1de594de8..f12c2b6ac08e 100644 --- a/trunk/drivers/ata/pdc_adma.c +++ b/trunk/drivers/ata/pdc_adma.c @@ -145,32 +145,32 @@ static struct scsi_host_template adma_ata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .slave_configure = ata_scsi_slave_config, - .slave_destroy = ata_scsi_slave_destroy, - .bios_param = ata_std_bios_param, - .proc_name = DRV_NAME, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, - .dma_boundary = ADMA_DMA_BOUNDARY, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, - .use_clustering = ENABLE_CLUSTERING, .emulated = ATA_SHT_EMULATED, + .use_clustering = ENABLE_CLUSTERING, + .proc_name = DRV_NAME, + .dma_boundary = ADMA_DMA_BOUNDARY, + .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, + .bios_param = ata_std_bios_param, }; static const struct ata_port_operations adma_ata_ops = { .port_disable = ata_port_disable, .tf_load = ata_tf_load, .tf_read = ata_tf_read, - .exec_command = ata_exec_command, .check_status = ata_check_status, + .check_atapi_dma = adma_check_atapi_dma, + .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, .phy_reset = adma_phy_reset, - .check_atapi_dma = adma_check_atapi_dma, - .data_xfer = ata_data_xfer, .qc_prep = adma_qc_prep, .qc_issue = adma_qc_issue, .eng_timeout = adma_eng_timeout, + .data_xfer = ata_data_xfer, .irq_clear = adma_irq_clear, .irq_on = ata_irq_on, .irq_ack = ata_irq_ack, @@ -188,7 +188,7 @@ static struct ata_port_info adma_port_info[] = { ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, .pio_mask = 0x10, /* pio4 */ - .udma_mask = ATA_UDMA4, + .udma_mask = 0x1f, /* udma0-4 */ .port_ops = &adma_ata_ops, }, }; diff --git a/trunk/drivers/ata/sata_inic162x.c b/trunk/drivers/ata/sata_inic162x.c index 3de183461c3c..dc3bbce04676 100644 --- a/trunk/drivers/ata/sata_inic162x.c +++ b/trunk/drivers/ata/sata_inic162x.c @@ -192,7 +192,7 @@ static void inic_reset_port(void __iomem *port_base) static u32 inic_scr_read(struct ata_port *ap, unsigned sc_reg) { - void __iomem *scr_addr = ap->ioaddr.scr_addr; + void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr; void __iomem *addr; u32 val; @@ -210,7 +210,7 @@ static u32 inic_scr_read(struct ata_port *ap, unsigned sc_reg) static void inic_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val) { - void __iomem *scr_addr = ap->ioaddr.scr_addr; + void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr; void __iomem *addr; if (unlikely(sc_reg >= ARRAY_SIZE(scr_map))) @@ -594,7 +594,7 @@ static struct ata_port_info inic_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &inic_port_ops }; diff --git a/trunk/drivers/ata/sata_mv.c b/trunk/drivers/ata/sata_mv.c index 3873b29c80d6..590f2f92b4e0 100644 --- a/trunk/drivers/ata/sata_mv.c +++ b/trunk/drivers/ata/sata_mv.c @@ -526,44 +526,44 @@ static const struct ata_port_info mv_port_info[] = { { /* chip_504x */ .flags = MV_COMMON_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &mv5_ops, }, { /* chip_508x */ .flags = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC), .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &mv5_ops, }, { /* chip_5080 */ .flags = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC), .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &mv5_ops, }, { /* chip_604x */ .flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS), .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &mv6_ops, }, { /* chip_608x */ .flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS | MV_FLAG_DUAL_HC), .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &mv6_ops, }, { /* chip_6042 */ .flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS), .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &mv_iie_ops, }, { /* chip_7042 */ .flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS), .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &mv_iie_ops, }, }; @@ -2338,7 +2338,7 @@ static void mv_print_info(struct ata_host *host) struct pci_dev *pdev = to_pci_dev(host->dev); struct mv_host_priv *hpriv = host->private_data; u8 rev_id, scc; - const char *scc_s, *gen; + const char *scc_s; /* Use this to determine the HW stepping of the chip so we know * what errata to workaround @@ -2351,20 +2351,11 @@ static void mv_print_info(struct ata_host *host) else if (scc == 0x01) scc_s = "RAID"; else - scc_s = "?"; - - if (IS_GEN_I(hpriv)) - gen = "I"; - else if (IS_GEN_II(hpriv)) - gen = "II"; - else if (IS_GEN_IIE(hpriv)) - gen = "IIE"; - else - gen = "?"; + scc_s = "unknown"; dev_printk(KERN_INFO, &pdev->dev, - "Gen-%s %u slots %u ports %s mode IRQ via %s\n", - gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports, + "%u slots %u ports %s mode IRQ via %s\n", + (unsigned)MV_MAX_Q_DEPTH, host->n_ports, scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx"); } diff --git a/trunk/drivers/ata/sata_promise.c b/trunk/drivers/ata/sata_promise.c index 2ad5872fe90c..6dc0b011a6b7 100644 --- a/trunk/drivers/ata/sata_promise.c +++ b/trunk/drivers/ata/sata_promise.c @@ -45,7 +45,8 @@ #include "sata_promise.h" #define DRV_NAME "sata_promise" -#define DRV_VERSION "2.08" +#define DRV_VERSION "2.07" + enum { PDC_MAX_PORTS = 4, @@ -93,7 +94,7 @@ enum { board_20319 = 2, /* FastTrak S150 TX4 */ board_20619 = 3, /* FastTrak TX4000 */ board_2057x = 4, /* SATAII150 Tx2plus */ - board_2057x_pata = 5, /* SATAII150 Tx2plus PATA port */ + board_2057x_pata = 5, /* SATAII150 Tx2plus */ board_40518 = 6, /* SATAII150 Tx4 */ PDC_HAS_PATA = (1 << 1), /* PDC20375/20575 has PATA */ @@ -123,6 +124,7 @@ enum { PDC_FLAG_4_PORTS = (1 << 26), /* 4 ports */ }; + struct pdc_port_priv { u8 *pkt; dma_addr_t pkt_dma; @@ -250,7 +252,7 @@ static const struct ata_port_info pdc_port_info[] = { PDC_FLAG_SATA_PATA, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &pdc_old_sata_ops, }, @@ -259,7 +261,7 @@ static const struct ata_port_info pdc_port_info[] = { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &pdc_pata_ops, }, @@ -269,7 +271,7 @@ static const struct ata_port_info pdc_port_info[] = { PDC_FLAG_4_PORTS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &pdc_old_sata_ops, }, @@ -279,7 +281,7 @@ static const struct ata_port_info pdc_port_info[] = { PDC_FLAG_4_PORTS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &pdc_pata_ops, }, @@ -289,7 +291,7 @@ static const struct ata_port_info pdc_port_info[] = { PDC_FLAG_GEN_II | PDC_FLAG_SATA_PATA, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &pdc_sata_ops, }, @@ -299,7 +301,7 @@ static const struct ata_port_info pdc_port_info[] = { PDC_FLAG_GEN_II, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &pdc_pata_ops, }, @@ -309,7 +311,7 @@ static const struct ata_port_info pdc_port_info[] = { PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &pdc_sata_ops, }, }; @@ -338,6 +340,7 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = { { } /* terminate list */ }; + static struct pci_driver pdc_ata_pci_driver = { .name = DRV_NAME, .id_table = pdc_ata_pci_tbl, @@ -345,6 +348,7 @@ static struct pci_driver pdc_ata_pci_driver = { .remove = ata_pci_remove_one, }; + static int pdc_common_port_start(struct ata_port *ap) { struct device *dev = ap->host->dev; @@ -378,7 +382,7 @@ static int pdc_sata_port_start(struct ata_port *ap) /* fix up PHYMODE4 align timing */ if (ap->flags & PDC_FLAG_GEN_II) { - void __iomem *mmio = ap->ioaddr.scr_addr; + void __iomem *mmio = (void __iomem *) ap->ioaddr.scr_addr; unsigned int tmp; tmp = readl(mmio + 0x014); @@ -414,7 +418,7 @@ static void pdc_reset_port(struct ata_port *ap) static int pdc_pata_cable_detect(struct ata_port *ap) { u8 tmp; - void __iomem *mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03; + void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03; tmp = readb(mmio); if (tmp & 0x01) @@ -434,6 +438,7 @@ static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg) return readl(ap->ioaddr.scr_addr + (sc_reg * 4)); } + static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) { @@ -568,7 +573,7 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc) static void pdc_freeze(struct ata_port *ap) { - void __iomem *mmio = ap->ioaddr.cmd_addr; + void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr; u32 tmp; tmp = readl(mmio + PDC_CTLSTAT); @@ -580,7 +585,7 @@ static void pdc_freeze(struct ata_port *ap) static void pdc_thaw(struct ata_port *ap) { - void __iomem *mmio = ap->ioaddr.cmd_addr; + void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr; u32 tmp; /* clear IRQ */ @@ -652,8 +657,8 @@ static void pdc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc, ata_port_abort(ap); } -static inline unsigned int pdc_host_intr(struct ata_port *ap, - struct ata_queued_cmd *qc) +static inline unsigned int pdc_host_intr( struct ata_port *ap, + struct ata_queued_cmd *qc) { unsigned int handled = 0; void __iomem *port_mmio = ap->ioaddr.cmd_addr; @@ -680,10 +685,10 @@ static inline unsigned int pdc_host_intr(struct ata_port *ap, handled = 1; break; - default: + default: ap->stats.idle_irq++; break; - } + } return handled; } @@ -696,18 +701,6 @@ static void pdc_irq_clear(struct ata_port *ap) readl(mmio + PDC_INT_SEQMASK); } -static inline int pdc_is_sataii_tx4(unsigned long flags) -{ - const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS; - return (flags & mask) == mask; -} - -static inline unsigned int pdc_port_no_to_ata_no(unsigned int port_no, int is_sataii_tx4) -{ - static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2}; - return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no; -} - static irqreturn_t pdc_interrupt (int irq, void *dev_instance) { struct ata_host *host = dev_instance; @@ -814,6 +807,7 @@ static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf) ata_tf_load(ap, tf); } + static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf) { WARN_ON (tf->protocol == ATA_PROT_DMA || @@ -873,6 +867,7 @@ static void pdc_ata_setup_port(struct ata_port *ap, ap->ioaddr.scr_addr = scr_addr; } + static void pdc_host_init(struct ata_host *host) { void __iomem *mmio = host->iomap[PDC_MMIO_BAR]; @@ -960,8 +955,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e if (pi->flags & PDC_FLAG_SATA_PATA) { u8 tmp = readb(base + PDC_FLASH_CTL+1); - if (!(tmp & 0x80)) + if (!(tmp & 0x80)) { ppi[n_ports++] = pi + 1; + dev_printk(KERN_INFO, &pdev->dev, "PATA port found\n"); + } } host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); @@ -971,12 +968,22 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e } host->iomap = pcim_iomap_table(pdev); - is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags); + is_sataii_tx4 = 0; + if ((pi->flags & (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS)) == (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS)) { + is_sataii_tx4 = 1; + dev_printk(KERN_INFO, &pdev->dev, "applying SATAII TX4 port numbering workaround\n"); + } for (i = 0; i < host->n_ports; i++) { - unsigned int ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4); + static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2}; + int ata_nr; + + ata_nr = i; + if (is_sataii_tx4) + ata_nr = sataii_tx4_port_remap[i]; + pdc_ata_setup_port(host->ports[i], - base + 0x200 + ata_no * 0x80, - base + 0x400 + ata_no * 0x100); + base + 0x200 + ata_nr * 0x80, + base + 0x400 + ata_nr * 0x100); } /* initialize adapter */ @@ -995,16 +1002,19 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e &pdc_ata_sht); } + static int __init pdc_ata_init(void) { return pci_register_driver(&pdc_ata_pci_driver); } + static void __exit pdc_ata_exit(void) { pci_unregister_driver(&pdc_ata_pci_driver); } + MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("Promise ATA TX2/TX4/TX4000 low-level driver"); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/ata/sata_qstor.c b/trunk/drivers/ata/sata_qstor.c index 9ab554da89bf..6688ccb66320 100644 --- a/trunk/drivers/ata/sata_qstor.c +++ b/trunk/drivers/ata/sata_qstor.c @@ -176,7 +176,7 @@ static const struct ata_port_info qs_port_info[] = { //FIXME ATA_FLAG_SRST | ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, .pio_mask = 0x10, /* pio4 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &qs_ata_ops, }, }; diff --git a/trunk/drivers/ata/sata_sil.c b/trunk/drivers/ata/sata_sil.c index 2a86dc4598d0..a3b339bcf3cf 100644 --- a/trunk/drivers/ata/sata_sil.c +++ b/trunk/drivers/ata/sata_sil.c @@ -218,7 +218,7 @@ static const struct ata_port_info sil_port_info[] = { .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, + .udma_mask = 0x3f, /* udma0-5 */ .port_ops = &sil_ops, }, /* sil_3112_no_sata_irq */ @@ -227,7 +227,7 @@ static const struct ata_port_info sil_port_info[] = { SIL_FLAG_NO_SATA_IRQ, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, + .udma_mask = 0x3f, /* udma0-5 */ .port_ops = &sil_ops, }, /* sil_3512 */ @@ -235,7 +235,7 @@ static const struct ata_port_info sil_port_info[] = { .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, + .udma_mask = 0x3f, /* udma0-5 */ .port_ops = &sil_ops, }, /* sil_3114 */ @@ -243,7 +243,7 @@ static const struct ata_port_info sil_port_info[] = { .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, + .udma_mask = 0x3f, /* udma0-5 */ .port_ops = &sil_ops, }, }; @@ -262,9 +262,8 @@ static const struct { unsigned long sfis_cfg; /* SATA FIS reception config register */ } sil_port[] = { /* port 0 ... */ - /* tf ctl bmdma bmdma2 fifo scr sien mode sfis */ - { 0x80, 0x8A, 0x0, 0x10, 0x40, 0x100, 0x148, 0xb4, 0x14c }, - { 0xC0, 0xCA, 0x8, 0x18, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc }, + { 0x80, 0x8A, 0x00, 0x10, 0x40, 0x100, 0x148, 0xb4, 0x14c }, + { 0xC0, 0xCA, 0x08, 0x18, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc }, { 0x280, 0x28A, 0x200, 0x210, 0x240, 0x300, 0x348, 0x2b4, 0x34c }, { 0x2C0, 0x2CA, 0x208, 0x218, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc }, /* ... port 3 */ diff --git a/trunk/drivers/ata/sata_sil24.c b/trunk/drivers/ata/sata_sil24.c index ac43a30ebe29..0ddfae9911cd 100644 --- a/trunk/drivers/ata/sata_sil24.c +++ b/trunk/drivers/ata/sata_sil24.c @@ -426,7 +426,7 @@ static const struct ata_port_info sil24_port_info[] = { SIL24_FLAG_PCIX_IRQ_WOC, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, /* udma0-5 */ + .udma_mask = 0x3f, /* udma0-5 */ .port_ops = &sil24_ops, }, /* sil_3132 */ @@ -434,7 +434,7 @@ static const struct ata_port_info sil24_port_info[] = { .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2), .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, /* udma0-5 */ + .udma_mask = 0x3f, /* udma0-5 */ .port_ops = &sil24_ops, }, /* sil_3131/sil_3531 */ @@ -442,7 +442,7 @@ static const struct ata_port_info sil24_port_info[] = { .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1), .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, /* udma0-5 */ + .udma_mask = 0x3f, /* udma0-5 */ .port_ops = &sil24_ops, }, }; @@ -888,7 +888,7 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance) if (status & (1 << i)) { struct ata_port *ap = host->ports[i]; if (ap && !(ap->flags & ATA_FLAG_DISABLED)) { - sil24_host_intr(ap); + sil24_host_intr(host->ports[i]); handled++; } else printk(KERN_ERR DRV_NAME diff --git a/trunk/drivers/ata/sata_sis.c b/trunk/drivers/ata/sata_sis.c index fd80bcf1b236..f111c984a359 100644 --- a/trunk/drivers/ata/sata_sis.c +++ b/trunk/drivers/ata/sata_sis.c @@ -133,7 +133,7 @@ static const struct ata_port_info sis_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, .pio_mask = 0x1f, .mwdma_mask = 0x7, - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, .port_ops = &sis_ops, }; diff --git a/trunk/drivers/ata/sata_svw.c b/trunk/drivers/ata/sata_svw.c index 63fe99afd59f..bcb2cd8b063d 100644 --- a/trunk/drivers/ata/sata_svw.c +++ b/trunk/drivers/ata/sata_svw.c @@ -107,7 +107,7 @@ static u32 k2_sata_scr_read (struct ata_port *ap, unsigned int sc_reg) { if (sc_reg > SCR_CONTROL) return 0xffffffffU; - return readl(ap->ioaddr.scr_addr + (sc_reg * 4)); + return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4)); } @@ -116,7 +116,7 @@ static void k2_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, { if (sc_reg > SCR_CONTROL) return; - writel(val, ap->ioaddr.scr_addr + (sc_reg * 4)); + writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4)); } @@ -197,8 +197,7 @@ static void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc) struct ata_port *ap = qc->ap; unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); u8 dmactl; - void __iomem *mmio = ap->ioaddr.bmdma_addr; - + void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; /* load PRD table addr. */ mb(); /* make sure PRD table writes are visible to controller */ writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS); @@ -226,7 +225,7 @@ static void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc) static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - void __iomem *mmio = ap->ioaddr.bmdma_addr; + void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr; u8 dmactl; /* start host DMA transaction */ @@ -254,7 +253,7 @@ static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc) static u8 k2_stat_check_status(struct ata_port *ap) { - return readl(ap->ioaddr.status_addr); + return readl((void __iomem *) ap->ioaddr.status_addr); } #ifdef CONFIG_PPC_OF @@ -361,7 +360,7 @@ static const struct ata_port_info k2_port_info[] = { ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, .port_ops = &k2_sata_ops, }, /* board_svw8 */ @@ -371,7 +370,7 @@ static const struct ata_port_info k2_port_info[] = { K2_FLAG_SATA_8_PORTS, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, .port_ops = &k2_sata_ops, }, }; diff --git a/trunk/drivers/ata/sata_sx4.c b/trunk/drivers/ata/sata_sx4.c index 5193bd8647ba..2d14f3d56d92 100644 --- a/trunk/drivers/ata/sata_sx4.c +++ b/trunk/drivers/ata/sata_sx4.c @@ -30,54 +30,6 @@ * */ -/* - Theory of operation - ------------------- - - The SX4 (PDC20621) chip features a single Host DMA (HDMA) copy - engine, DIMM memory, and four ATA engines (one per SATA port). - Data is copied to/from DIMM memory by the HDMA engine, before - handing off to one (or more) of the ATA engines. The ATA - engines operate solely on DIMM memory. - - The SX4 behaves like a PATA chip, with no SATA controls or - knowledge whatsoever, leading to the presumption that - PATA<->SATA bridges exist on SX4 boards, external to the - PDC20621 chip itself. - - The chip is quite capable, supporting an XOR engine and linked - hardware commands (permits a string to transactions to be - submitted and waited-on as a single unit), and an optional - microprocessor. - - The limiting factor is largely software. This Linux driver was - written to multiplex the single HDMA engine to copy disk - transactions into a fixed DIMM memory space, from where an ATA - engine takes over. As a result, each WRITE looks like this: - - submit HDMA packet to hardware - hardware copies data from system memory to DIMM - hardware raises interrupt - - submit ATA packet to hardware - hardware executes ATA WRITE command, w/ data in DIMM - hardware raises interrupt - - and each READ looks like this: - - submit ATA packet to hardware - hardware executes ATA READ command, w/ data in DIMM - hardware raises interrupt - - submit HDMA packet to hardware - hardware copies data from DIMM to system memory - hardware raises interrupt - - This is a very slow, lock-step way of doing things that can - certainly be improved by motivated kernel hackers. - - */ - #include #include #include @@ -106,8 +58,6 @@ enum { PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */ PDC_HDMA_CTLSTAT = 0x12C, /* Host DMA control / status */ - PDC_CTLSTAT = 0x60, /* IDEn control / status */ - PDC_20621_SEQCTL = 0x400, PDC_20621_SEQMASK = 0x480, PDC_20621_GENERAL_CTL = 0x484, @@ -137,60 +87,48 @@ enum { board_20621 = 0, /* FastTrak S150 SX4 */ - PDC_MASK_INT = (1 << 10), /* HDMA/ATA mask int */ - PDC_RESET = (1 << 11), /* HDMA/ATA reset */ - PDC_DMA_ENABLE = (1 << 7), /* DMA start/stop */ + PDC_RESET = (1 << 11), /* HDMA reset */ PDC_MAX_HDMA = 32, PDC_HDMA_Q_MASK = (PDC_MAX_HDMA - 1), - PDC_DIMM0_SPD_DEV_ADDRESS = 0x50, - PDC_DIMM1_SPD_DEV_ADDRESS = 0x51, - PDC_I2C_CONTROL = 0x48, - PDC_I2C_ADDR_DATA = 0x4C, - PDC_DIMM0_CONTROL = 0x80, - PDC_DIMM1_CONTROL = 0x84, - PDC_SDRAM_CONTROL = 0x88, - PDC_I2C_WRITE = 0, /* master -> slave */ - PDC_I2C_READ = (1 << 6), /* master <- slave */ - PDC_I2C_START = (1 << 7), /* start I2C proto */ - PDC_I2C_MASK_INT = (1 << 5), /* mask I2C interrupt */ - PDC_I2C_COMPLETE = (1 << 16), /* I2C normal compl. */ - PDC_I2C_NO_ACK = (1 << 20), /* slave no-ack addr */ - PDC_DIMM_SPD_SUBADDRESS_START = 0x00, - PDC_DIMM_SPD_SUBADDRESS_END = 0x7F, - PDC_DIMM_SPD_ROW_NUM = 3, - PDC_DIMM_SPD_COLUMN_NUM = 4, - PDC_DIMM_SPD_MODULE_ROW = 5, - PDC_DIMM_SPD_TYPE = 11, - PDC_DIMM_SPD_FRESH_RATE = 12, - PDC_DIMM_SPD_BANK_NUM = 17, - PDC_DIMM_SPD_CAS_LATENCY = 18, - PDC_DIMM_SPD_ATTRIBUTE = 21, - PDC_DIMM_SPD_ROW_PRE_CHARGE = 27, - PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28, - PDC_DIMM_SPD_RAS_CAS_DELAY = 29, - PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30, - PDC_DIMM_SPD_SYSTEM_FREQ = 126, - PDC_CTL_STATUS = 0x08, - PDC_DIMM_WINDOW_CTLR = 0x0C, - PDC_TIME_CONTROL = 0x3C, - PDC_TIME_PERIOD = 0x40, - PDC_TIME_COUNTER = 0x44, - PDC_GENERAL_CTLR = 0x484, - PCI_PLL_INIT = 0x8A531824, - PCI_X_TCOUNT = 0xEE1E5CFF, - - /* PDC_TIME_CONTROL bits */ - PDC_TIMER_BUZZER = (1 << 10), - PDC_TIMER_MODE_PERIODIC = 0, /* bits 9:8 == 00 */ - PDC_TIMER_MODE_ONCE = (1 << 8), /* bits 9:8 == 01 */ - PDC_TIMER_ENABLE = (1 << 7), - PDC_TIMER_MASK_INT = (1 << 5), - PDC_TIMER_SEQ_MASK = 0x1f, /* SEQ ID for timer */ - PDC_TIMER_DEFAULT = PDC_TIMER_MODE_ONCE | - PDC_TIMER_ENABLE | - PDC_TIMER_MASK_INT, + PDC_DIMM0_SPD_DEV_ADDRESS = 0x50, + PDC_DIMM1_SPD_DEV_ADDRESS = 0x51, + PDC_MAX_DIMM_MODULE = 0x02, + PDC_I2C_CONTROL_OFFSET = 0x48, + PDC_I2C_ADDR_DATA_OFFSET = 0x4C, + PDC_DIMM0_CONTROL_OFFSET = 0x80, + PDC_DIMM1_CONTROL_OFFSET = 0x84, + PDC_SDRAM_CONTROL_OFFSET = 0x88, + PDC_I2C_WRITE = 0x00000000, + PDC_I2C_READ = 0x00000040, + PDC_I2C_START = 0x00000080, + PDC_I2C_MASK_INT = 0x00000020, + PDC_I2C_COMPLETE = 0x00010000, + PDC_I2C_NO_ACK = 0x00100000, + PDC_DIMM_SPD_SUBADDRESS_START = 0x00, + PDC_DIMM_SPD_SUBADDRESS_END = 0x7F, + PDC_DIMM_SPD_ROW_NUM = 3, + PDC_DIMM_SPD_COLUMN_NUM = 4, + PDC_DIMM_SPD_MODULE_ROW = 5, + PDC_DIMM_SPD_TYPE = 11, + PDC_DIMM_SPD_FRESH_RATE = 12, + PDC_DIMM_SPD_BANK_NUM = 17, + PDC_DIMM_SPD_CAS_LATENCY = 18, + PDC_DIMM_SPD_ATTRIBUTE = 21, + PDC_DIMM_SPD_ROW_PRE_CHARGE = 27, + PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28, + PDC_DIMM_SPD_RAS_CAS_DELAY = 29, + PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30, + PDC_DIMM_SPD_SYSTEM_FREQ = 126, + PDC_CTL_STATUS = 0x08, + PDC_DIMM_WINDOW_CTLR = 0x0C, + PDC_TIME_CONTROL = 0x3C, + PDC_TIME_PERIOD = 0x40, + PDC_TIME_COUNTER = 0x44, + PDC_GENERAL_CTLR = 0x484, + PCI_PLL_INIT = 0x8A531824, + PCI_X_TCOUNT = 0xEE1E5CFF }; @@ -279,7 +217,7 @@ static const struct ata_port_info pdc_port_info[] = { ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &pdc_20621_ops, }, @@ -1061,17 +999,17 @@ static unsigned int pdc20621_i2c_read(struct ata_host *host, u32 device, i2creg |= subaddr << 16; /* Set the device and subaddress */ - writel(i2creg, mmio + PDC_I2C_ADDR_DATA); - readl(mmio + PDC_I2C_ADDR_DATA); + writel(i2creg, mmio + PDC_I2C_ADDR_DATA_OFFSET); + readl(mmio + PDC_I2C_ADDR_DATA_OFFSET); /* Write Control to perform read operation, mask int */ writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT, - mmio + PDC_I2C_CONTROL); + mmio + PDC_I2C_CONTROL_OFFSET); for (count = 0; count <= 1000; count ++) { - status = readl(mmio + PDC_I2C_CONTROL); + status = readl(mmio + PDC_I2C_CONTROL_OFFSET); if (status & PDC_I2C_COMPLETE) { - status = readl(mmio + PDC_I2C_ADDR_DATA); + status = readl(mmio + PDC_I2C_ADDR_DATA_OFFSET); break; } else if (count == 1000) return 0; @@ -1161,8 +1099,8 @@ static int pdc20621_prog_dimm0(struct ata_host *host) data |= (((size / 16) - 1) << 16); data |= (0 << 23); data |= 8; - writel(data, mmio + PDC_DIMM0_CONTROL); - readl(mmio + PDC_DIMM0_CONTROL); + writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET); + readl(mmio + PDC_DIMM0_CONTROL_OFFSET); return size; } @@ -1184,27 +1122,27 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_host *host) */ data = 0x022259F1; - writel(data, mmio + PDC_SDRAM_CONTROL); - readl(mmio + PDC_SDRAM_CONTROL); + writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET); + readl(mmio + PDC_SDRAM_CONTROL_OFFSET); /* Turn on for ECC */ pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS, PDC_DIMM_SPD_TYPE, &spd0); if (spd0 == 0x02) { data |= (0x01 << 16); - writel(data, mmio + PDC_SDRAM_CONTROL); - readl(mmio + PDC_SDRAM_CONTROL); + writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET); + readl(mmio + PDC_SDRAM_CONTROL_OFFSET); printk(KERN_ERR "Local DIMM ECC Enabled\n"); } /* DIMM Initialization Select/Enable (bit 18/19) */ data &= (~(1<<18)); data |= (1<<19); - writel(data, mmio + PDC_SDRAM_CONTROL); + writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET); error = 1; for (i = 1; i <= 10; i++) { /* polling ~5 secs */ - data = readl(mmio + PDC_SDRAM_CONTROL); + data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET); if (!(data & (1<<19))) { error = 0; break; @@ -1238,7 +1176,7 @@ static unsigned int pdc20621_dimm_init(struct ata_host *host) VPRINTK("Time Period Register (0x40): 0x%x\n", time_period); /* Enable timer */ - writel(PDC_TIMER_DEFAULT, mmio + PDC_TIME_CONTROL); + writel(0x00001a0, mmio + PDC_TIME_CONTROL); readl(mmio + PDC_TIME_CONTROL); /* Wait 3 seconds */ diff --git a/trunk/drivers/ata/sata_uli.c b/trunk/drivers/ata/sata_uli.c index aca71819f6e8..6815de7cca79 100644 --- a/trunk/drivers/ata/sata_uli.c +++ b/trunk/drivers/ata/sata_uli.c @@ -129,7 +129,7 @@ static const struct ata_port_info uli_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_IGN_SIMPLEX, .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &uli_ops, }; diff --git a/trunk/drivers/ata/sata_via.c b/trunk/drivers/ata/sata_via.c index a4c0832033d8..e8b90e7b42dd 100644 --- a/trunk/drivers/ata/sata_via.c +++ b/trunk/drivers/ata/sata_via.c @@ -223,7 +223,7 @@ static const struct ata_port_info vt6420_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, .port_ops = &vt6420_sata_ops, }; @@ -231,7 +231,7 @@ static struct ata_port_info vt6421_sport_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, .port_ops = &vt6421_sata_ops, }; @@ -239,7 +239,7 @@ static struct ata_port_info vt6421_pport_info = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY, .pio_mask = 0x1f, .mwdma_mask = 0, - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, .port_ops = &vt6421_pata_ops, }; @@ -303,7 +303,9 @@ static int vt6420_prereset(struct ata_port *ap, unsigned long deadline) if (!(ap->pflags & ATA_PFLAG_LOADING)) goto skip_scr; - /* Resume phy. This is the old SATA resume sequence */ + /* Resume phy. This is the old resume sequence from + * __sata_phy_reset(). + */ svia_scr_write(ap, SCR_CONTROL, 0x300); svia_scr_read(ap, SCR_CONTROL); /* flush */ diff --git a/trunk/drivers/ata/sata_vsc.c b/trunk/drivers/ata/sata_vsc.c index 1b5d81faa102..81330175fc89 100644 --- a/trunk/drivers/ata/sata_vsc.c +++ b/trunk/drivers/ata/sata_vsc.c @@ -371,7 +371,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d ATA_FLAG_MMIO, .pio_mask = 0x1f, .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA6, + .udma_mask = 0x7f, .port_ops = &vsc_sata_ops, }; const struct ata_port_info *ppi[] = { &pi, NULL }; diff --git a/trunk/drivers/block/Kconfig b/trunk/drivers/block/Kconfig index 6e23af1ecbdb..b4c8319138b2 100644 --- a/trunk/drivers/block/Kconfig +++ b/trunk/drivers/block/Kconfig @@ -2,12 +2,9 @@ # Block device driver configuration # -menuconfig BLK_DEV - bool "Block devices" - depends on BLOCK - default y +if BLOCK -if BLK_DEV +menu "Block devices" config BLK_DEV_FD tristate "Normal floppy disk support" @@ -59,9 +56,40 @@ 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 + depends on ATARI && ATARI_ACSI!=n 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 @@ -425,4 +453,6 @@ config ATA_OVER_ETH source "drivers/s390/block/Kconfig" -endif # BLK_DEV +endmenu + +endif diff --git a/trunk/drivers/block/Makefile b/trunk/drivers/block/Makefile index e5f98acc5d52..dd88e33c1eb1 100644 --- a/trunk/drivers/block/Makefile +++ b/trunk/drivers/block/Makefile @@ -9,6 +9,7 @@ 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/trunk/drivers/block/acsi.c b/trunk/drivers/block/acsi.c new file mode 100644 index 000000000000..e3d9152e231a --- /dev/null +++ b/trunk/drivers/block/acsi.c @@ -0,0 +1,1825 @@ +/* + * acsi.c -- Device driver for Atari ACSI hard disks + * + * Copyright 1994 Roman Hodek + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for SCSI_IOCTL_GET_IDLUN */ +#include +#include /* for HDIO_GETGEO */ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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/trunk/drivers/block/amiflop.c b/trunk/drivers/block/amiflop.c index 6ce8b897e262..27a139025ced 100644 --- a/trunk/drivers/block/amiflop.c +++ b/trunk/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, - (rq_data_dir(CURRENT) == READ) ? "read" : "write"); + (CURRENT->cmd==READ)?"read":"write"); #endif block = CURRENT->sector + cnt; if ((int)block > floppy->blocks) { diff --git a/trunk/drivers/block/cciss.c b/trunk/drivers/block/cciss.c index 0fcad430474e..5acc6c44aead 100644 --- a/trunk/drivers/block/cciss.c +++ b/trunk/drivers/block/cciss.c @@ -87,7 +87,6 @@ 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,} @@ -120,7 +119,6 @@ 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/trunk/drivers/block/loop.c b/trunk/drivers/block/loop.c index 4503290da407..0ed5470d2533 100644 --- a/trunk/drivers/block/loop.c +++ b/trunk/drivers/block/loop.c @@ -74,7 +74,6 @@ #include #include #include -#include #include @@ -402,73 +401,50 @@ struct lo_read_data { }; static int -lo_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf, - struct splice_desc *sd) +lo_read_actor(read_descriptor_t *desc, struct page *page, + unsigned long offset, unsigned long size) { - struct lo_read_data *p = sd->u.data; + unsigned long count = desc->count; + struct lo_read_data *p = desc->arg.data; struct loop_device *lo = p->lo; - struct page *page = buf->page; sector_t IV; - size_t size; - int ret; - ret = buf->ops->confirm(pipe, buf); - if (unlikely(ret)) - return ret; + IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - 9))+(offset >> 9); - IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - 9)) + - (buf->offset >> 9); - size = sd->len; - if (size > p->bsize) - size = p->bsize; + if (size > count) + size = count; - if (lo_do_transfer(lo, READ, page, buf->offset, p->page, p->offset, size, IV)) { + if (lo_do_transfer(lo, READ, page, offset, p->page, p->offset, size, IV)) { + size = 0; printk(KERN_ERR "loop: transfer error block %ld\n", page->index); - size = -EINVAL; + desc->error = -EINVAL; } flush_dcache_page(p->page); - if (size > 0) - p->offset += size; - + desc->count = count - size; + desc->written += size; + 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; - long retval; + int 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 = splice_direct_to_actor(file, &sd, lo_direct_splice_actor); - - if (retval < 0) - return retval; - - return 0; + retval = file->f_op->sendfile(file, &pos, bvec->bv_len, + lo_read_actor, &cookie); + return (retval < 0)? retval: 0; } static int @@ -703,8 +679,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 splice_read) */ - if (!inode->i_fop->splice_read) + /* new backing store needs to support loop (eg sendfile) */ + if (!inode->i_fop->sendfile) goto out_putf; /* size of the new backing store needs to be the same */ @@ -784,7 +760,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->splice_read) + if (!file->f_op->sendfile) goto out_putf; if (aops->prepare_write && aops->commit_write) lo_flags |= LO_FLAGS_USE_AOPS; diff --git a/trunk/drivers/block/nbd.c b/trunk/drivers/block/nbd.c index c575fb1d585f..069ae39a9cd9 100644 --- a/trunk/drivers/block/nbd.c +++ b/trunk/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 ((rq_data_dir(req) == WRITE) && (lo->flags & NBD_WRITE_NOCHK)) + * if ((req->cmd == WRITE) && (lo->flags & NBD_WRITE_NOCHK)) * { printk( "Warning: Ignoring result!\n"); nbd_end_request( req ); } */ diff --git a/trunk/drivers/cdrom/Kconfig b/trunk/drivers/cdrom/Kconfig new file mode 100644 index 000000000000..4b12e9031fb3 --- /dev/null +++ b/trunk/drivers/cdrom/Kconfig @@ -0,0 +1,213 @@ +# +# 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 + . + + 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 + 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 + . + + 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 + , you might have to change a setting + in the file before compiling the + kernel. Please read the file . + + 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 + . + + 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 + 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 . + + 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 . + + 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 + . + + 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 + . 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 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 or fill + in your parameters into . 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 . + + 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/trunk/drivers/cdrom/Makefile b/trunk/drivers/cdrom/Makefile index 774c180a4e11..d1d1e5a4be73 100644 --- a/trunk/drivers/cdrom/Makefile +++ b/trunk/drivers/cdrom/Makefile @@ -10,4 +10,14 @@ 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/trunk/drivers/cdrom/aztcd.c b/trunk/drivers/cdrom/aztcd.c new file mode 100644 index 000000000000..1f9fb7a96703 --- /dev/null +++ b/trunk/drivers/cdrom/aztcd.c @@ -0,0 +1,2492 @@ +#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 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 +*/ + +#include +#include "aztcd.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +/*########################################################################### + 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 /* */ +#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(¬Used)) + 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(¬Used) < 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=" + ",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=,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/trunk/drivers/cdrom/aztcd.h b/trunk/drivers/cdrom/aztcd.h new file mode 100644 index 000000000000..057501e31628 --- /dev/null +++ b/trunk/drivers/cdrom/aztcd.h @@ -0,0 +1,162 @@ +/* $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/trunk/drivers/cdrom/cdrom.c b/trunk/drivers/cdrom/cdrom.c index aa5468f487ba..3625a05bc3d3 100644 --- a/trunk/drivers/cdrom/cdrom.c +++ b/trunk/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_MUTEX(cdrom_mutex); +static DEFINE_SPINLOCK(cdrom_lock); 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); - mutex_lock(&cdrom_mutex); + spin_lock(&cdrom_lock); cdi->next = topCdromPtr; topCdromPtr = cdi; - mutex_unlock(&cdrom_mutex); + spin_unlock(&cdrom_lock); 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; - mutex_lock(&cdrom_mutex); + spin_lock(&cdrom_lock); cdi = topCdromPtr; while (cdi && cdi != unreg) { prev = cdi; @@ -460,7 +460,7 @@ int unregister_cdrom(struct cdrom_device_info *unreg) } if (cdi == NULL) { - mutex_unlock(&cdrom_mutex); + spin_unlock(&cdrom_lock); return -2; } if (prev) @@ -468,7 +468,7 @@ int unregister_cdrom(struct cdrom_device_info *unreg) else topCdromPtr = cdi->next; - mutex_unlock(&cdrom_mutex); + spin_unlock(&cdrom_lock); if (cdi->exit) cdi->exit(cdi); @@ -3289,137 +3289,103 @@ 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; + int pos; + struct cdrom_device_info *cdi; 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"); - 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; + 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); } /* Unfortunately, per device settings are not implemented through diff --git a/trunk/drivers/cdrom/cdu31a.c b/trunk/drivers/cdrom/cdu31a.c new file mode 100644 index 000000000000..2157c58755e0 --- /dev/null +++ b/trunk/drivers/cdrom/cdu31a.c @@ -0,0 +1,3251 @@ +/* +* 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) && (! + * 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 with additional + * changes by Erik Andersen + * + * 24 January 1998 -- Removed the scd_disc_status() function, which was now + * just dead code left over from the port. + * Erik Andersen + * + * 16 July 1998 -- Drive donated to Erik Andersen by John Kodis + * . 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 + * + * 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 +*/ + +#define DEBUG 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "cdu31a.h" + +#define MAJOR_NR CDU31A_CDROM_MAJOR +#include + +#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, ¶ms[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/trunk/drivers/cdrom/cdu31a.h b/trunk/drivers/cdrom/cdu31a.h new file mode 100644 index 000000000000..61d4768c412e --- /dev/null +++ b/trunk/drivers/cdrom/cdu31a.h @@ -0,0 +1,411 @@ +/* + * 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/trunk/drivers/cdrom/cm206.c b/trunk/drivers/cdrom/cm206.c new file mode 100644 index 000000000000..230131163240 --- /dev/null +++ b/trunk/drivers/cdrom/cm206.c @@ -0,0 +1,1594 @@ +/* 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 + 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 . + +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 + * + * 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 + +#include /* These include what we really need */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* #include */ + +#include + +#define MAJOR_NR CM206_CDROM_MAJOR + +#include + +#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/trunk/drivers/cdrom/cm206.h b/trunk/drivers/cdrom/cm206.h new file mode 100644 index 000000000000..0ae51c1a0dac --- /dev/null +++ b/trunk/drivers/cdrom/cm206.h @@ -0,0 +1,171 @@ +/* cm206.h Header file for cm206.c. + Copyright (c) 1995 David van Leeuwen +*/ + +#ifndef LINUX_CM206_H +#define LINUX_CM206_H + +#include + +/* 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/trunk/drivers/cdrom/gscd.c b/trunk/drivers/cdrom/gscd.c new file mode 100644 index 000000000000..b3ab6e9b8df1 --- /dev/null +++ b/trunk/drivers/cdrom/gscd.c @@ -0,0 +1,1029 @@ +#define GSCD_VERSION "0.4a Oliver Raupach " + +/* + linux/drivers/block/gscd.c - GoldStar R420 CDROM driver + + Copyright (C) 1995 Oliver Raupach + based upon pre-works by Eberhard Moenkeberg + + + 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 + +*/ + +/* 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define MAJOR_NR GOLDSTAR_CDROM_MAJOR +#include +#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 "); +MODULE_LICENSE("GPL"); +module_init(gscd_init); +module_exit(gscd_exit); +MODULE_ALIAS_BLOCKDEV_MAJOR(GOLDSTAR_CDROM_MAJOR); diff --git a/trunk/drivers/cdrom/gscd.h b/trunk/drivers/cdrom/gscd.h new file mode 100644 index 000000000000..a41e64bfc061 --- /dev/null +++ b/trunk/drivers/cdrom/gscd.h @@ -0,0 +1,108 @@ +/* + * Definitions for a GoldStar R420 CD-ROM interface + * + * Copyright (C) 1995 Oliver Raupach + * Eberhard Moenkeberg + * + * 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/trunk/drivers/cdrom/isp16.c b/trunk/drivers/cdrom/isp16.c new file mode 100644 index 000000000000..db0fd9a240e3 --- /dev/null +++ b/trunk/drivers/cdrom/isp16.c @@ -0,0 +1,374 @@ +/* -- ISP16 cdrom detection and configuration + * + * Copyright (c) 1995,1996 Eric van der Maarel + * + * 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 + * + * 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 + +#include +#include +#include +#include +#include +#include +#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/trunk/drivers/cdrom/isp16.h b/trunk/drivers/cdrom/isp16.h new file mode 100644 index 000000000000..5bd22c8f7a96 --- /dev/null +++ b/trunk/drivers/cdrom/isp16.h @@ -0,0 +1,72 @@ +/* -- 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/trunk/drivers/cdrom/mcdx.c b/trunk/drivers/cdrom/mcdx.c new file mode 100644 index 000000000000..4310cc84dfed --- /dev/null +++ b/trunk/drivers/cdrom/mcdx.c @@ -0,0 +1,1943 @@ +/* + * The Mitsumi CDROM interface + * Copyright (C) 1995 1996 Heiko Schlittermann + * 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 + */ + + +#ifdef RCS +static const char *mcdx_c_version + = "$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $"; +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#define MAJOR_NR MITSUMI_X_CDROM_MAJOR +#include + +#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/trunk/drivers/cdrom/mcdx.h b/trunk/drivers/cdrom/mcdx.h new file mode 100644 index 000000000000..83c364a74dc4 --- /dev/null +++ b/trunk/drivers/cdrom/mcdx.h @@ -0,0 +1,185 @@ +/* + * Definitions for the Mitsumi CDROM interface + * Copyright (C) 1995 1996 Heiko Schlittermann + * 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/trunk/drivers/cdrom/optcd.c b/trunk/drivers/cdrom/optcd.c new file mode 100644 index 000000000000..3541690a77d4 --- /dev/null +++ b/trunk/drivers/cdrom/optcd.c @@ -0,0 +1,2105 @@ +/* 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 +*/ + +/* Includes */ + + +#include +#include +#include +#include + +#include +#include + +#include +#include "optcd.h" + +#include + +#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/trunk/drivers/cdrom/optcd.h b/trunk/drivers/cdrom/optcd.h new file mode 100644 index 000000000000..1911bb92ee28 --- /dev/null +++ b/trunk/drivers/cdrom/optcd.h @@ -0,0 +1,52 @@ +/* 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='. 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/trunk/drivers/cdrom/sbpcd.c b/trunk/drivers/cdrom/sbpcd.c new file mode 100644 index 000000000000..a1283b1ef989 --- /dev/null +++ b/trunk/drivers/cdrom/sbpcd.c @@ -0,0 +1,5966 @@ +/* + * 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 Wed Jul 26 04:24:10 EDT 2000" + +/* Copyright (C) 1993, 1994, 1995 Eberhard 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, 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 + * 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 (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 . 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 with additional + * changes by Erik Andersen + * + * 4.62 Fix a bug where playing audio left the drive in an unusable state. + * Heiko Eissfeldt + * + * 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 + * + * 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 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "sbpcd.h" + +#define MAJOR_NR MATSUSHITA_CDROM_MAJOR +#include + +/*==========================================================================*/ +#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<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<>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;i0) msg(DBG_INF,"ResponseInfo: got %d trailing bytes.\n",j); +#endif /* 000 */ + for (j=0;j0) 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;j1) 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_typedrv_typedrv_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;iSubQ_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;idiskstate_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_typedrv_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)&&(ixa_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;countmsf_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)&&(iTocEnt_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;iTocEnt_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>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 (ifirst_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;ilba_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;j0;i--) OUT(port+0,0); + for (k=0;k0;i--) + { + if (inb(port+1)&s_not_result_ready) continue; + response[k]=inb(port+0); + break; + } + } + for (i=0;i0;i--) OUT(port+0,0); + for (k=0;k0;i--) + { + if (inb(port+1)&s_not_result_ready) continue; + response[k]=inb(port+0); + break; + } + } + for (i=0;i0;i--) OUT(port+0,0); + for (k=0;k0;i--) + { + if (inb(port+1)&s_not_result_ready) continue; + response[k]=inb(port+0); + break; + } + } + for (i=0;i0;i--) OUT(port+0,0); + for (k=0;k0;i--) + { + if (inb(port+1)&s_not_result_ready) continue; + response[k]=inb(port+0); + break; + } + } + for (i=0;idrv_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;jpos_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=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_trk0n_first_track) RETURN_UP(-EINVAL); + if (ti.cdti_trk0>current_drive->n_last_track) RETURN_UP(-EINVAL); + if (ti.cdti_trk1current_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 (in_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 + * + * 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_typesbp_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;framesbp_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= 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;j1) 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=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;jdrv_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;jdrv_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;j0) + 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/trunk/drivers/cdrom/sbpcd.h b/trunk/drivers/cdrom/sbpcd.h new file mode 100644 index 000000000000..2f2225f13c6f --- /dev/null +++ b/trunk/drivers/cdrom/sbpcd.h @@ -0,0 +1,839 @@ +/* + * 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/trunk/drivers/cdrom/sjcd.c b/trunk/drivers/cdrom/sjcd.c new file mode 100644 index 000000000000..5409fca5bbfc --- /dev/null +++ b/trunk/drivers/cdrom/sjcd.c @@ -0,0 +1,1815 @@ +/* -- 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=,, + * 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= + * 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 + */ + +#define SJCD_VERSION_MAJOR 1 +#define SJCD_VERSION_MINOR 7 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#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/trunk/drivers/cdrom/sjcd.h b/trunk/drivers/cdrom/sjcd.h new file mode 100644 index 000000000000..0aa5e714659d --- /dev/null +++ b/trunk/drivers/cdrom/sjcd.h @@ -0,0 +1,181 @@ +/* + * 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/trunk/drivers/cdrom/sonycd535.c b/trunk/drivers/cdrom/sonycd535.c new file mode 100644 index 000000000000..f77ada933ea0 --- /dev/null +++ b/trunk/drivers/cdrom/sonycd535.c @@ -0,0 +1,1689 @@ +/* + * 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 ) + * + * 1995-05-20 + * Modified to support CDU-510/515 series + * (Claudio Porfiri) + * Fixed to report verify_area() failures + * (Heiko Eissfeldt ) + * + * 1995-06-01 + * More changes to support CDU-510/515 series + * (Claudio Porfiri) + * + * 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 + * + * September 2003 - Fix SMP support by removing cli/sti calls. + * Using spinlocks with a wait_queue instead. + * Felipe Damasio + * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REALLY_SLOW_IO +#include +#include +#include + +#include + +#define MAJOR_NR CDU535_CDROM_MAJOR +#include + +#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, ¶ms[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 + * . + */ + /* + * 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/trunk/drivers/cdrom/sonycd535.h b/trunk/drivers/cdrom/sonycd535.h new file mode 100644 index 000000000000..5dea1ef168d6 --- /dev/null +++ b/trunk/drivers/cdrom/sonycd535.h @@ -0,0 +1,183 @@ +#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/trunk/drivers/char/keyboard.c b/trunk/drivers/char/keyboard.c index 90965b4def5c..1b094509b1d2 100644 --- a/trunk/drivers/char/keyboard.c +++ b/trunk/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,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, + 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, 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/trunk/drivers/char/mem.c b/trunk/drivers/char/mem.c index bbee97ff355f..cc9a9d0df979 100644 --- a/trunk/drivers/char/mem.c +++ b/trunk/drivers/char/mem.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include @@ -75,13 +75,6 @@ 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/trunk/drivers/ide/legacy/hd.c b/trunk/drivers/ide/legacy/hd.c index 7f4c0a5050a1..661c12f6dda6 100644 --- a/trunk/drivers/ide/legacy/hd.c +++ b/trunk/drivers/ide/legacy/hd.c @@ -623,8 +623,7 @@ static void hd_request(void) cyl = track / disk->head; #ifdef DEBUG printk("%s: %sing: CHS=%d/%d/%d, sectors=%d, buffer=%p\n", - req->rq_disk->disk_name, - req_data_dir(req) == READ ? "read" : "writ", + req->rq_disk->disk_name, (req->cmd == READ)?"read":"writ", cyl, head, sec, nsect, req->buffer); #endif if (blk_fs_request(req)) { diff --git a/trunk/drivers/input/evdev.c b/trunk/drivers/input/evdev.c index ab4b2d9b5327..be6b93c20f60 100644 --- a/trunk/drivers/input/evdev.c +++ b/trunk/drivers/input/evdev.c @@ -30,7 +30,6 @@ struct evdev { wait_queue_head_t wait; struct evdev_client *grab; struct list_head client_list; - struct device dev; }; struct evdev_client { @@ -95,10 +94,8 @@ static int evdev_flush(struct file *file, fl_owner_t id) return input_flush_device(&evdev->handle, file); } -static void evdev_free(struct device *dev) +static void evdev_free(struct evdev *evdev) { - struct evdev *evdev = container_of(dev, struct evdev, dev); - evdev_table[evdev->minor] = NULL; kfree(evdev); } @@ -117,10 +114,12 @@ static int evdev_release(struct inode *inode, struct file *file) list_del(&client->node); kfree(client); - if (!--evdev->open && evdev->exist) - input_close_device(&evdev->handle); - - put_device(&evdev->dev); + if (!--evdev->open) { + if (evdev->exist) + input_close_device(&evdev->handle); + else + evdev_free(evdev); + } return 0; } @@ -140,32 +139,24 @@ 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) { - error = -ENOMEM; - goto err_put_evdev; - } + if (!client) + return -ENOMEM; client->evdev = evdev; list_add_tail(&client->node, &evdev->client_list); if (!evdev->open++ && evdev->exist) { error = input_open_device(&evdev->handle); - if (error) - goto err_free_client; + if (error) { + list_del(&client->node); + kfree(client); + return error; + } } 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 @@ -634,6 +625,8 @@ 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; @@ -656,32 +649,38 @@ 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; - snprintf(evdev->name, sizeof(evdev->name), "event%d", 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); + sprintf(evdev->name, "event%d", minor); evdev_table[minor] = evdev; - error = device_add(&evdev->dev); - if (error) + devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor), + + 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; + } + + /* temporary symlink to keep userspace happy */ + error = sysfs_create_link(&input_class.subsys.kobj, + &cdev->kobj, evdev->name); + if (error) + goto err_cdev_destroy; error = input_register_handle(&evdev->handle); if (error) - goto err_delete_evdev; + goto err_remove_link; return 0; - err_delete_evdev: - device_del(&evdev->dev); + err_remove_link: + sysfs_remove_link(&input_class.subsys.kobj, evdev->name); + err_cdev_destroy: + class_device_destroy(&input_class, devt); err_free_evdev: - put_device(&evdev->dev); + kfree(evdev); + evdev_table[minor] = NULL; return error; } @@ -691,8 +690,10 @@ 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) { @@ -701,9 +702,8 @@ 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); - } - - put_device(&evdev->dev); + } else + evdev_free(evdev); } static const struct input_device_id evdev_ids[] = { diff --git a/trunk/drivers/input/input.c b/trunk/drivers/input/input.c index 75b4d2a83dd9..ccd8abafcb70 100644 --- a/trunk/drivers/input/input.c +++ b/trunk/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->dev.kobj), error); + handler->name, kobject_name(&dev->cdev.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->dev.kobj, GFP_KERNEL); + const char *path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL); struct input_handle *handle; seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n", @@ -682,17 +682,15 @@ 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 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) +#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); INPUT_DEV_STRING_ATTR_SHOW(name); INPUT_DEV_STRING_ATTR_SHOW(phys); @@ -746,9 +744,7 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id, return len; } -static ssize_t input_dev_show_modalias(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf) { struct input_dev *id = to_input_dev(dev); ssize_t len; @@ -757,13 +753,13 @@ static ssize_t input_dev_show_modalias(struct device *dev, return min_t(int, len, PAGE_SIZE); } -static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); +static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); static struct attribute *input_dev_attrs[] = { - &dev_attr_name.attr, - &dev_attr_phys.attr, - &dev_attr_uniq.attr, - &dev_attr_modalias.attr, + &class_device_attr_name.attr, + &class_device_attr_phys.attr, + &class_device_attr_uniq.attr, + &class_device_attr_modalias.attr, NULL }; @@ -771,15 +767,13 @@ 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 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) +#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); INPUT_DEV_ID_ATTR(bustype); INPUT_DEV_ID_ATTR(vendor); @@ -787,10 +781,10 @@ INPUT_DEV_ID_ATTR(product); INPUT_DEV_ID_ATTR(version); static struct attribute *input_dev_id_attrs[] = { - &dev_attr_bustype.attr, - &dev_attr_vendor.attr, - &dev_attr_product.attr, - &dev_attr_version.attr, + &class_device_attr_bustype.attr, + &class_device_attr_vendor.attr, + &class_device_attr_product.attr, + &class_device_attr_version.attr, NULL }; @@ -819,17 +813,15 @@ 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 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) +#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); INPUT_DEV_CAP_ATTR(EV, ev); INPUT_DEV_CAP_ATTR(KEY, key); @@ -842,15 +834,15 @@ INPUT_DEV_CAP_ATTR(FF, ff); INPUT_DEV_CAP_ATTR(SW, sw); static struct attribute *input_dev_caps_attrs[] = { - &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, + &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, NULL }; @@ -866,9 +858,9 @@ static struct attribute_group *input_dev_attr_groups[] = { NULL }; -static void input_dev_release(struct device *device) +static void input_dev_release(struct class_device *class_dev) { - struct input_dev *dev = to_input_dev(device); + struct input_dev *dev = to_input_dev(class_dev); input_ff_destroy(dev); kfree(dev); @@ -955,10 +947,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 device *device, char **envp, +static int input_dev_uevent(struct class_device *cdev, char **envp, int num_envp, char *buffer, int buffer_size) { - struct input_dev *dev = to_input_dev(device); + struct input_dev *dev = to_input_dev(cdev); int i = 0; int len = 0; @@ -996,14 +988,10 @@ static int input_dev_uevent(struct device *device, 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", + .name = "input", + .release = input_dev_release, + .uevent = input_dev_uevent, }; EXPORT_SYMBOL_GPL(input_class); @@ -1022,9 +1010,9 @@ struct input_dev *input_allocate_device(void) dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL); if (dev) { - dev->dev.type = &input_dev_type; - dev->dev.class = &input_class; - device_initialize(&dev->dev); + dev->cdev.class = &input_class; + dev->cdev.groups = input_dev_attr_groups; + class_device_initialize(&dev->cdev); mutex_init(&dev->mutex); INIT_LIST_HEAD(&dev->h_list); INIT_LIST_HEAD(&dev->node); @@ -1143,17 +1131,17 @@ int input_register_device(struct input_dev *dev) list_add_tail(&dev->node, &input_dev_list); - snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), + snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id), "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); - if (dev->cdev.dev) - dev->dev.parent = dev->cdev.dev; + if (!dev->cdev.dev) + dev->cdev.dev = dev->dev.parent; - error = device_add(&dev->dev); + error = class_device_add(&dev->cdev); if (error) return error; - path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); + path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL); printk(KERN_INFO "input: %s as %s\n", dev->name ? dev->name : "Unspecified device", path ? path : "N/A"); kfree(path); @@ -1185,7 +1173,7 @@ void input_unregister_device(struct input_dev *dev) list_del_init(&dev->node); - device_unregister(&dev->dev); + class_device_unregister(&dev->cdev); input_wakeup_procfs_readers(); } diff --git a/trunk/drivers/input/joydev.c b/trunk/drivers/input/joydev.c index a9a0180bfd46..10e3b7bc925f 100644 --- a/trunk/drivers/input/joydev.c +++ b/trunk/drivers/input/joydev.c @@ -43,8 +43,6 @@ 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; @@ -140,10 +138,8 @@ static int joydev_fasync(int fd, struct file *file, int on) return retval < 0 ? retval : 0; } -static void joydev_free(struct device *dev) +static void joydev_free(struct joydev *joydev) { - struct joydev *joydev = container_of(dev, struct joydev, dev); - joydev_table[joydev->minor] = NULL; kfree(joydev); } @@ -158,10 +154,12 @@ static int joydev_release(struct inode *inode, struct file *file) list_del(&client->node); kfree(client); - if (!--joydev->open && joydev->exist) - input_close_device(&joydev->handle); - - put_device(&joydev->dev); + if (!--joydev->open) { + if (joydev->exist) + input_close_device(&joydev->handle); + else + joydev_free(joydev); + } return 0; } @@ -180,32 +178,24 @@ 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) { - error = -ENOMEM; - goto err_put_joydev; - } + if (!client) + return -ENOMEM; client->joydev = joydev; list_add_tail(&client->node, &joydev->client_list); if (!joydev->open++ && joydev->exist) { error = input_open_device(&joydev->handle); - if (error) - goto err_free_client; + if (error) { + list_del(&client->node); + kfree(client); + return error; + } } 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) @@ -491,6 +481,8 @@ 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; @@ -513,7 +505,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; - snprintf(joydev->name, sizeof(joydev->name), "js%d", minor); + sprintf(joydev->name, "js%d", minor); for (i = 0; i < ABS_MAX + 1; i++) if (test_bit(i, dev->absbit)) { @@ -555,30 +547,36 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i); } - 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); - joydev_table[minor] = joydev; - error = device_add(&joydev->dev); - if (error) + devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor), + + 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; + } + + /* temporary symlink to keep userspace happy */ + error = sysfs_create_link(&input_class.subsys.kobj, + &cdev->kobj, joydev->name); + if (error) + goto err_cdev_destroy; error = input_register_handle(&joydev->handle); if (error) - goto err_delete_joydev; + goto err_remove_link; return 0; - err_delete_joydev: - device_del(&joydev->dev); + err_remove_link: + sysfs_remove_link(&input_class.subsys.kobj, joydev->name); + err_cdev_destroy: + class_device_destroy(&input_class, devt); err_free_joydev: - put_device(&joydev->dev); + joydev_table[minor] = NULL; + kfree(joydev); return error; } @@ -589,8 +587,9 @@ 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) { @@ -598,9 +597,8 @@ 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); - } - - put_device(&joydev->dev); + } else + joydev_free(joydev); } static const struct input_device_id joydev_blacklist[] = { diff --git a/trunk/drivers/input/joystick/Kconfig b/trunk/drivers/input/joystick/Kconfig index 12db72d83ea0..b0023452ec90 100644 --- a/trunk/drivers/input/joystick/Kconfig +++ b/trunk/drivers/input/joystick/Kconfig @@ -268,11 +268,4 @@ 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/trunk/drivers/input/joystick/grip_mp.c b/trunk/drivers/input/joystick/grip_mp.c index 4ed3a3eadf19..555319e6378c 100644 --- a/trunk/drivers/input/joystick/grip_mp.c +++ b/trunk/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; + int i, seq_len = sizeof(init_seq)/sizeof(int); int flags, tries = 0, bads = 0; - for (i = 0; i < ARRAY_SIZE(init_seq); i++) { /* Send magic sequence */ + for (i = 0; i < seq_len; i++) { /* Send magic sequence */ if (init_seq[i]) gameport_trigger(gameport); udelay(GRIP_INIT_DELAY); diff --git a/trunk/drivers/input/joystick/xpad.c b/trunk/drivers/input/joystick/xpad.c index 244089c52650..8c8cd95a6989 100644 --- a/trunk/drivers/input/joystick/xpad.c +++ b/trunk/drivers/input/joystick/xpad.c @@ -8,7 +8,6 @@ * Ivan Hawkes * 2005 Dominic Cerquetti * 2006 Adam Buchbinder - * 2007 Jan Kratochvil * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -29,7 +28,6 @@ * - 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 @@ -90,9 +88,6 @@ #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"); @@ -102,42 +97,40 @@ 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, 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 } + { 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 } }; static const signed short xpad_btn[] = { @@ -153,12 +146,6 @@ 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 */ @@ -172,12 +159,8 @@ 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 */ { } }; @@ -191,16 +174,9 @@ 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 */ }; /* @@ -236,8 +212,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 */ @@ -259,64 +235,6 @@ 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; @@ -337,10 +255,7 @@ static void xpad_irq_in(struct urb *urb) goto exit; } - if (xpad->xtype == XTYPE_XBOX360) - xpad360_process_packet(xpad, 0, xpad->idata); - else - xpad_process_packet(xpad, 0, xpad->idata); + xpad_process_packet(xpad, 0, xpad->idata); exit: retval = usb_submit_urb (urb, GFP_ATOMIC); @@ -349,114 +264,7 @@ static void xpad_irq_in(struct urb *urb) __FUNCTION__, retval); } -#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) +static int xpad_open (struct input_dev *dev) { struct usb_xpad *xpad = input_get_drvdata(dev); @@ -467,12 +275,11 @@ 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) @@ -528,7 +335,6 @@ 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; @@ -550,9 +356,6 @@ 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); @@ -564,10 +367,6 @@ 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), @@ -597,10 +396,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(xpad->udev, XPAD_PKT_LEN, + usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); kfree(xpad); } diff --git a/trunk/drivers/input/keyboard/atkbd.c b/trunk/drivers/input/keyboard/atkbd.c index 41fc3d03b6eb..9950fcb33650 100644 --- a/trunk/drivers/input/keyboard/atkbd.c +++ b/trunk/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,172,166, 0, 0, 0,142, + 159, 0,115, 0,164, 0, 0,116,158, 0,150,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,172,163,165,115,152,172,166,140,160,154,113,114,167,168, + 0,139,150,163,165,115,152,150,166,140,160,154,113,114,167,168, 148,149,147,140 }; diff --git a/trunk/drivers/input/keyboard/pxa27x_keyboard.c b/trunk/drivers/input/keyboard/pxa27x_keyboard.c index ebe5eacf2990..f9e82c9ca421 100644 --- a/trunk/drivers/input/keyboard/pxa27x_keyboard.c +++ b/trunk/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(CKEN_KEYPAD, 1); + pxa_set_cken(CKEN19_KEYPAD, 1); } mutex_unlock(&input_dev->mutex); diff --git a/trunk/drivers/input/misc/Kconfig b/trunk/drivers/input/misc/Kconfig index 9b26574f1466..88e29074ac90 100644 --- a/trunk/drivers/input/misc/Kconfig +++ b/trunk/drivers/input/misc/Kconfig @@ -65,13 +65,9 @@ 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. If - available, mail and wifi leds will be controlable via /sys/class/leds. + laptops of various brands, including Acer and Fujitsu-Siemens. To compile this driver as a module, choose M here: the module will be called wistron_btns. diff --git a/trunk/drivers/input/misc/wistron_btns.c b/trunk/drivers/input/misc/wistron_btns.c index 60121f10f8d9..961aad7a0476 100644 --- a/trunk/drivers/input/misc/wistron_btns.c +++ b/trunk/drivers/input/misc/wistron_btns.c @@ -20,31 +20,37 @@ #include #include #include -#include +#include #include -#include #include #include #include #include #include +#include #include #include -#include -/* How often we poll keys - msecs */ -#define POLL_INTERVAL_DEFAULT 500 /* when idle */ -#define POLL_INTERVAL_BURST 100 /* when a key was recently pressed */ +/* + * 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 /* BIOS subsystem IDs */ #define WIFI 0x35 #define BLUETOOTH 0x34 -#define MAIL_LED 0x31 MODULE_AUTHOR("Miloslav Trmac "); MODULE_DESCRIPTION("Wistron laptop button driver"); MODULE_LICENSE("GPL v2"); -MODULE_VERSION("0.3"); +MODULE_VERSION("0.2"); static int force; /* = 0; */ module_param(force, bool, 0); @@ -242,10 +248,9 @@ enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH }; #define FE_WIFI_LED 0x02 #define FE_UNTESTED 0x80 -static struct key_entry *keymap; /* = NULL; Current key map */ +static const 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) { @@ -258,8 +263,6 @@ 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; } @@ -963,163 +966,118 @@ static int __init select_keymap(void) /* Input layer interface */ -static struct input_polled_dev *wistron_idev; -static unsigned long jiffies_last_press; -static int wifi_enabled; -static int bluetooth_enabled; +static struct input_dev *input_dev; -static void report_key(struct input_dev *dev, unsigned int keycode) -{ - input_report_key(dev, keycode, 1); - input_sync(dev); - input_report_key(dev, keycode, 0); - input_sync(dev); -} - -static void report_switch(struct input_dev *dev, unsigned int code, int value) +static int __devinit setup_input_dev(void) { - input_report_switch(dev, code, value); - input_sync(dev); -} - + const struct key_entry *key; + int error; - /* 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); -} + input_dev = input_allocate_device(); + if (!input_dev) + return -ENOMEM; -/* 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); -} + input_dev->name = "Wistron laptop buttons"; + input_dev->phys = "wistron/input0"; + input_dev->id.bustype = BUS_HOST; + input_dev->cdev.dev = &wistron_device->dev; -static struct led_classdev wistron_mail_led = { - .name = "mail:green", - .brightness_set = wistron_mail_led_set, -}; + 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; -static struct led_classdev wistron_wifi_led = { - .name = "wifi:red", - .brightness_set = wistron_wifi_led_set, -}; + case KE_SW: + set_bit(EV_SW, input_dev->evbit); + set_bit(key->sw.code, input_dev->swbit); + break; -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; + default: + ; + } } - 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); - } -} + /* 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 void __devexit wistron_led_remove(void) -{ - if (have_leds & FE_MAIL_LED) - led_classdev_unregister(&wistron_mail_led); + error = input_register_device(input_dev); + if (error) { + input_free_device(input_dev); + return error; + } - if (have_leds & FE_WIFI_LED) - led_classdev_unregister(&wistron_wifi_led); + return 0; } -static inline void wistron_led_suspend(void) +static void report_key(unsigned keycode) { - if (have_leds & FE_MAIL_LED) - led_classdev_suspend(&wistron_mail_led); - - if (have_leds & FE_WIFI_LED) - led_classdev_suspend(&wistron_wifi_led); + input_report_key(input_dev, keycode, 1); + input_sync(input_dev); + input_report_key(input_dev, keycode, 0); + input_sync(input_dev); } -static inline void wistron_led_resume(void) +static void report_switch(unsigned code, int value) { - if (have_leds & FE_MAIL_LED) - led_classdev_resume(&wistron_mail_led); - - if (have_leds & FE_WIFI_LED) - led_classdev_resume(&wistron_wifi_led); + input_report_switch(input_dev, code, value); + input_sync(input_dev); } -static struct key_entry *wistron_get_entry_by_scancode(int code) -{ - struct key_entry *key; - - for (key = keymap; key->type != KE_END; key++) - if (code == key->code) - return key; - - return NULL; -} + /* Driver core */ -static struct key_entry *wistron_get_entry_by_keycode(int keycode) -{ - struct key_entry *key; +static int wifi_enabled; +static int bluetooth_enabled; - for (key = keymap; key->type != KE_END; key++) - if (key->type == KE_KEY && keycode == key->keycode) - return key; +static void poll_bios(unsigned long); - return NULL; -} +static struct timer_list poll_timer = TIMER_INITIALIZER(poll_bios, 0, 0); static void handle_key(u8 code) { - const struct key_entry *key = wistron_get_entry_by_scancode(code); + const struct key_entry *key; - if (key) { - switch (key->type) { - case KE_KEY: - report_key(wistron_idev->input, key->keycode); - break; + for (key = keymap; key->type != KE_END; key++) { + if (code == key->code) { + switch (key->type) { + case KE_KEY: + report_key(key->keycode); + break; - case KE_SW: - report_switch(wistron_idev->input, - key->sw.code, key->sw.value); - break; + case KE_SW: + report_switch(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_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); - } - break; + case KE_BLUETOOTH: + if (have_bluetooth) { + bluetooth_enabled = !bluetooth_enabled; + bios_set_state(BLUETOOTH, bluetooth_enabled); + } + break; - default: - BUG(); + case KE_END: + break; + default: + BUG(); + } + return; } - jiffies_last_press = jiffies; - } else - printk(KERN_NOTICE - "wistron_btns: Unknown key code %02X\n", code); + } + printk(KERN_NOTICE "wistron_btns: Unknown key code %02X\n", code); } -static void poll_bios(bool discard) +static void poll_bios(unsigned long discard) { u8 qlen; u16 val; @@ -1132,118 +1090,15 @@ static void poll_bios(bool 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; - } - return -EINVAL; + mod_timer(&poll_timer, jiffies + HZ / POLL_FREQUENCY); } -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; + int err = setup_input_dev(); + if (err) + return err; bios_attach(); cmos_address = bios_get_cmos_address(); @@ -1270,21 +1125,15 @@ static int __devinit wistron_probe(struct platform_device *dev) bios_set_state(BLUETOOTH, bluetooth_enabled); } - wistron_led_init(&dev->dev); - err = setup_input_dev(); - if (err) { - bios_detach(); - return err; - } + poll_bios(1); /* Flush stale event queue and arm timer */ return 0; } static int __devexit wistron_remove(struct platform_device *dev) { - wistron_led_remove(); - input_unregister_polled_device(wistron_idev); - input_free_polled_device(wistron_idev); + del_timer_sync(&poll_timer); + input_unregister_device(input_dev); bios_detach(); return 0; @@ -1293,13 +1142,14 @@ 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; } @@ -1311,8 +1161,7 @@ static int wistron_resume(struct platform_device *dev) if (have_bluetooth) bios_set_state(BLUETOOTH, bluetooth_enabled); - wistron_led_resume(); - poll_bios(true); + poll_bios(1); return 0; } diff --git a/trunk/drivers/input/mouse/Kconfig b/trunk/drivers/input/mouse/Kconfig index 7bbea097cda2..50e06e8dd05d 100644 --- a/trunk/drivers/input/mouse/Kconfig +++ b/trunk/drivers/input/mouse/Kconfig @@ -216,20 +216,4 @@ 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/trunk/drivers/input/mouse/Makefile b/trunk/drivers/input/mouse/Makefile index 9e6e36330820..aa4ba878533f 100644 --- a/trunk/drivers/input/mouse/Makefile +++ b/trunk/drivers/input/mouse/Makefile @@ -15,7 +15,6 @@ 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/trunk/drivers/input/mouse/gpio_mouse.c b/trunk/drivers/input/mouse/gpio_mouse.c deleted file mode 100644 index 0936d6ba015c..000000000000 --- a/trunk/drivers/input/mouse/gpio_mouse.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include - -#include - -/* - * 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 "); -MODULE_DESCRIPTION("GPIO mouse driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/input/mouse/psmouse-base.c b/trunk/drivers/input/mouse/psmouse-base.c index b9f0fb2530e2..f15f695777f8 100644 --- a/trunk/drivers/input/mouse/psmouse-base.c +++ b/trunk/drivers/input/mouse/psmouse-base.c @@ -177,15 +177,6 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse) packet[1] |= (packet[0] & 0x40) << 1; } -/* - * 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 */ @@ -548,20 +539,6 @@ 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 @@ -762,12 +739,6 @@ static const struct psmouse_protocol psmouse_protocols[] = { .detect = touchkit_ps2_detect, }, #endif - { - .type = PSMOUSE_CORTRON, - .name = "CortronPS/2", - .alias = "cortps", - .detect = cortron_detect, - }, { .type = PSMOUSE_AUTO, .name = "auto", diff --git a/trunk/drivers/input/mouse/psmouse.h b/trunk/drivers/input/mouse/psmouse.h index 27a68835b5ba..3964e8acbc54 100644 --- a/trunk/drivers/input/mouse/psmouse.h +++ b/trunk/drivers/input/mouse/psmouse.h @@ -88,7 +88,6 @@ enum psmouse_type { PSMOUSE_LIFEBOOK, PSMOUSE_TRACKPOINT, PSMOUSE_TOUCHKIT_PS2, - PSMOUSE_CORTRON, PSMOUSE_AUTO /* This one should always be last */ }; diff --git a/trunk/drivers/input/mousedev.c b/trunk/drivers/input/mousedev.c index 9173916b8be5..3f4866d8d18c 100644 --- a/trunk/drivers/input/mousedev.c +++ b/trunk/drivers/input/mousedev.c @@ -64,7 +64,6 @@ 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; @@ -113,7 +112,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]) @@ -219,10 +218,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); } } @@ -288,11 +287,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; @@ -344,7 +343,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; @@ -363,10 +362,8 @@ static int mousedev_fasync(int fd, struct file *file, int on) return retval < 0 ? retval : 0; } -static void mousedev_free(struct device *dev) +static void mousedev_free(struct mousedev *mousedev) { - struct mousedev *mousedev = container_of(dev, struct mousedev, dev); - mousedev_table[mousedev->minor] = NULL; kfree(mousedev); } @@ -375,16 +372,15 @@ 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 = 1; + mousedev->mixdev_open++; } - get_device(&mousedev->dev); list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list); return 0; @@ -399,40 +395,36 @@ 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->mixdev_open) { - if (!mousedev->open && mousedev->exist) - if (input_open_device(&mousedev->handle)) - continue; + if (mousedev->exist && !mousedev->open) { + if (input_open_device(&mousedev->handle)) + continue; mousedev->open++; - mousedev->mixdev_open = 1; + mousedev->mixdev_open++; } } } static void mixdev_close_devices(void) { - struct mousedev *mousedev; + struct mousedev *mousedev, *next; - if (--mousedev_mix->open) - return; - - list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { + list_for_each_entry_safe(mousedev, next, &mousedev_mix_list, mixdev_node) { if (mousedev->mixdev_open) { mousedev->mixdev_open = 0; - if (!--mousedev->open && mousedev->exist) - input_close_device(&mousedev->handle); + if (!--mousedev->open) { + if (mousedev->exist) + input_close_device(&mousedev->handle); + else + mousedev_free(mousedev); + } } } } @@ -447,12 +439,14 @@ static int mousedev_release(struct inode *inode, struct file *file) list_del(&client->node); kfree(client); - if (mousedev->minor == MOUSEDEV_MIX) - mixdev_close_devices(); - else if (!--mousedev->open && mousedev->exist) - input_close_device(&mousedev->handle); - - put_device(&mousedev->dev); + if (!--mousedev->open) { + if (mousedev->minor == MOUSEDEV_MIX) + mixdev_close_devices(); + else if (mousedev->exist) + input_close_device(&mousedev->handle); + else + mousedev_free(mousedev); + } return 0; } @@ -479,13 +473,9 @@ 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) { - error = -ENOMEM; - goto err_put_mousedev; - } + if (!client) + return -ENOMEM; spin_lock_init(&client->packet_lock); client->pos_x = xres / 2; @@ -493,23 +483,21 @@ static int mousedev_open(struct inode *inode, struct file *file) client->mousedev = mousedev; list_add_tail(&client->node, &mousedev->client_list); - 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; + 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; + } + } } 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) @@ -692,96 +680,57 @@ static const struct file_operations mousedev_fops = { .fasync = mousedev_fasync, }; -static struct mousedev *mousedev_create(struct input_dev *dev, - struct input_handler *handler, - int minor) +static int mousedev_connect(struct input_handler *handler, struct input_dev *dev, + const struct input_device_id *id) { struct mousedev *mousedev; + struct class_device *cdev; + dev_t devt; + int minor; int error; - mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL); - if (!mousedev) { - error = -ENOMEM; - goto err_out; + 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; + 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; - - 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); + sprintf(mousedev->name, "mouse%d", minor); mousedev_table[minor] = mousedev; - 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; + devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor), - 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); - } - - 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; + cdev = class_device_create(&input_class, &dev->cdev, devt, + dev->cdev.dev, mousedev->name); + if (IS_ERR(cdev)) { + error = PTR_ERR(cdev); + goto err_free_mousedev; } - mousedev = mousedev_create(dev, handler, minor); - if (IS_ERR(mousedev)) - return PTR_ERR(mousedev); + /* temporary symlink to keep userspace happy */ + error = sysfs_create_link(&input_class.subsys.kobj, + &cdev->kobj, mousedev->name); + if (error) + goto err_cdev_destroy; error = input_register_handle(&mousedev->handle); if (error) - goto err_delete_mousedev; + goto err_remove_link; error = mixdev_add_device(mousedev); if (error) @@ -791,18 +740,37 @@ static int mousedev_connect(struct input_handler *handler, struct input_dev *dev err_unregister_handle: input_unregister_handle(&mousedev->handle); - err_delete_mousedev: - device_unregister(&mousedev->dev); + 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); return error; } static void mousedev_disconnect(struct input_handle *handle) { struct mousedev *mousedev = handle->private; + struct mousedev_client *client; - mixdev_remove_device(mousedev); input_unregister_handle(handle); - mousedev_destroy(mousedev); + + 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); } static const struct input_device_id mousedev_ids[] = { @@ -854,16 +822,25 @@ 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) { - mousedev_destroy(mousedev_mix); + if (error) 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 @@ -886,8 +863,9 @@ 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/trunk/drivers/input/serio/serio_raw.c b/trunk/drivers/input/serio/serio_raw.c index 0403622ae267..887357666c68 100644 --- a/trunk/drivers/input/serio/serio_raw.c +++ b/trunk/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 uninitialized_var(c); + char c; ssize_t retval = 0; if (!serio_raw->serio) diff --git a/trunk/drivers/input/tablet/aiptek.c b/trunk/drivers/input/tablet/aiptek.c index 94683f58c9e1..cc0a498763d8 100644 --- a/trunk/drivers/input/tablet/aiptek.c +++ b/trunk/drivers/input/tablet/aiptek.c @@ -82,8 +82,8 @@ /* * Version Information */ -#define DRIVER_VERSION "v2.3 (May 2, 2007)" -#define DRIVER_AUTHOR "Bryan W. Headley/Chris Atenasio/Cedric Brun/Rene van Paassen" +#define DRIVER_VERSION "v1.5 (May-15-2004)" +#define DRIVER_AUTHOR "Bryan W. Headley/Chris Atenasio" #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 1 + * byte0 0 0 0 0 0 0 1 0 * 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 1 + * byte0 0 0 0 0 0 1 0 0 * 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,9 +218,15 @@ #define AIPTEK_WHEEL_DISABLE (-10101) /* ToolCode values, which BTW are 0x140 .. 0x14f - * We have things set up such that if the tool button has changed, - * the tools get reset. + * 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. */ +#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 @@ -258,9 +264,9 @@ /* Mouse button programming */ -#define AIPTEK_MOUSE_LEFT_BUTTON 0x04 -#define AIPTEK_MOUSE_RIGHT_BUTTON 0x08 -#define AIPTEK_MOUSE_MIDDLE_BUTTON 0x10 +#define AIPTEK_MOUSE_LEFT_BUTTON 0x01 +#define AIPTEK_MOUSE_RIGHT_BUTTON 0x02 +#define AIPTEK_MOUSE_MIDDLE_BUTTON 0x04 /* Stylus button programming */ @@ -288,6 +294,7 @@ 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 { @@ -320,32 +327,9 @@ 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 @@ -361,39 +345,23 @@ static const int macroKeyEvents[] = { }; /*********************************************************************** - * Map values to strings and back. Every map shoudl have the following - * as its last element: { NULL, AIPTEK_INVALID_VALUE }. + * Relative reports deliver values in 2's complement format to + * deal with negative offsets. */ -#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) -{ - const struct aiptek_map *p; - - 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) +static int aiptek_convert_from_2s_complement(unsigned char c) { - const struct aiptek_map *p; - - for (p = map; p->value != AIPTEK_INVALID_VALUE; p++) - if (val == p->value) - return p->string; + int ret; + unsigned char b = c; + int negate = 0; - return "unknown"; + if ((b & 0x80) != 0) { + b = ~b; + b--; + negate = 1; + } + ret = b; + ret = (negate == 1) ? -ret : ret; + return ret; } /*********************************************************************** @@ -417,9 +385,6 @@ static const char *map_val_to_str(const struct aiptek_map *map, int val) * 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 @@ -476,8 +441,8 @@ static void aiptek_irq(struct urb *urb) aiptek->diagnostic = AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE; } else { - x = (signed char) data[2]; - y = (signed char) data[3]; + x = aiptek_convert_from_2s_complement(data[2]); + y = aiptek_convert_from_2s_complement(data[3]); /* jitterable keeps track of whether any button has been pressed. * We're also using it to remap the physical mouse button mask @@ -486,20 +451,18 @@ static void aiptek_irq(struct urb *urb) * that a non-zero value indicates that one or more * mouse button was pressed.) */ - jitterable = data[1] & 0x07; + jitterable = data[5] & 0x07; - 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; + 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; 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. @@ -509,11 +472,6 @@ 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); } } @@ -531,8 +489,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))); - dv = (data[5] & 0x01) != 0 ? 1 : 0; - p = (data[5] & 0x02) != 0 ? 1 : 0; + p = (data[5] & 0x01) != 0 ? 1 : 0; + dv = (data[5] & 0x02) != 0 ? 1 : 0; tip = (data[5] & 0x04) != 0 ? 1 : 0; /* Use jitterable to re-arrange button masks @@ -547,18 +505,16 @@ static void aiptek_irq(struct urb *urb) * all 'bad' reports... */ if (dv != 0) { - /* If the selected tool changed, reset the old - * tool key, and set the new one. + /* 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 (aiptek->previousToolMode != - aiptek->curSetting.toolMode) { - input_report_key(inputdev, - aiptek->previousToolMode, 0); + if (TOOL_BUTTON_FIRED + (aiptek->curSetting.toolMode) == 0) { input_report_key(inputdev, - aiptek->curSetting.toolMode, + TOOL_BUTTON(aiptek->curSetting.toolMode), 1); - aiptek->previousToolMode = - aiptek->curSetting.toolMode; + aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; } if (p != 0) { @@ -594,11 +550,6 @@ 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); } } @@ -617,25 +568,23 @@ static void aiptek_irq(struct urb *urb) jitterable = data[5] & 0x1c; - dv = (data[5] & 0x01) != 0 ? 1 : 0; - p = (data[5] & 0x02) != 0 ? 1 : 0; + p = (data[5] & 0x01) != 0 ? 1 : 0; + dv = (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 the selected tool changed, reset the old - * tool key, and set the new one. + /* 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 (aiptek->previousToolMode != - aiptek->curSetting.toolMode) { - input_report_key(inputdev, - aiptek->previousToolMode, 0); + if (TOOL_BUTTON_FIRED + (aiptek->curSetting.toolMode) == 0) { input_report_key(inputdev, - aiptek->curSetting.toolMode, + TOOL_BUTTON(aiptek->curSetting.toolMode), 1); - aiptek->previousToolMode = - aiptek->curSetting.toolMode; + aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; } if (p != 0) { @@ -656,12 +605,7 @@ static void aiptek_irq(struct urb *urb) aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE; } } - 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_report_rel(inputdev, REL_MISC, p | AIPTEK_REPORT_TOOL_MOUSE); input_sync(inputdev); } } @@ -671,83 +615,98 @@ static void aiptek_irq(struct urb *urb) else if (data[0] == 4) { jitterable = data[1] & 0x18; - dv = (data[1] & 0x01) != 0 ? 1 : 0; - p = (data[1] & 0x02) != 0 ? 1 : 0; + p = (data[1] & 0x01) != 0 ? 1 : 0; + dv = (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 = dv && p && tip && !(data[3] & 1) ? (data[3] >> 1) : -1; + macro = data[3]; z = le16_to_cpu(get_unaligned((__le16 *) (data + 4))); - if (dv) { - /* If the selected tool changed, reset the old - * tool key, and set the new one. + 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 (aiptek->previousToolMode != - aiptek->curSetting.toolMode) { - input_report_key(inputdev, - aiptek->previousToolMode, 0); + if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) { input_report_key(inputdev, - aiptek->curSetting.toolMode, + TOOL_BUTTON(aiptek->curSetting.toolMode), 1); - aiptek->previousToolMode = - aiptek->curSetting.toolMode; + aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; } - } - if (aiptek->lastMacro != -1 && aiptek->lastMacro != macro) { - input_report_key(inputdev, macroKeyEvents[aiptek->lastMacro], 0); - aiptek->lastMacro = -1; - } + 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 (macro != -1 && macro != aiptek->lastMacro) { - input_report_key(inputdev, macroKeyEvents[macro], 1); - aiptek->lastMacro = macro; + /* 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); } - 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; - dv = (data[1] & 0x01) != 0 ? 1 : 0; - p = (data[1] & 0x02) != 0 ? 1 : 0; + p = (data[1] & 0x01) != 0 ? 1 : 0; + dv = (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 = dv && p && left && !(data[3] & 1) ? (data[3] >> 1) : 0; + macro = data[3]; - if (dv) { - /* If the selected tool changed, reset the old - * tool key, and set the new one. + 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 (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; + 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 (aiptek->lastMacro != -1 && aiptek->lastMacro != macro) { - input_report_key(inputdev, macroKeyEvents[aiptek->lastMacro], 0); - aiptek->lastMacro = -1; - } + if (p != 0) { + input_report_key(inputdev, BTN_LEFT, left); + input_report_key(inputdev, BTN_MIDDLE, middle); + input_report_key(inputdev, BTN_RIGHT, right); + } + + /* 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 (macro != -1 && macro != aiptek->lastMacro) { input_report_key(inputdev, macroKeyEvents[macro], 1); - aiptek->lastMacro = macro; + input_report_rel(inputdev, ABS_MISC, + p | AIPTEK_REPORT_TOOL_MOUSE); + input_sync(inputdev); } - - 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. @@ -766,18 +725,15 @@ static void aiptek_irq(struct urb *urb) 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); + /* 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) { input_report_key(inputdev, - aiptek->curSetting.toolMode, - 1); - aiptek->previousToolMode = - aiptek->curSetting.toolMode; + TOOL_BUTTON(aiptek->curSetting. + toolMode), 1); + aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT; } input_report_key(inputdev, macroKeyEvents[macro], 1); @@ -1051,6 +1007,9 @@ 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); @@ -1064,36 +1023,118 @@ 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; - return snprintf(buf, PAGE_SIZE, "%s\n", - map_val_to_str(pointer_mode_map, - aiptek->curSetting.pointerMode)); + default: + s = "unknown"; + break; + } + return snprintf(buf, PAGE_SIZE, "%s\n", s); } 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); - int new_mode = map_str_to_val(pointer_mode_map, buf, count); - - if (new_mode == AIPTEK_INVALID_VALUE) - return -EINVAL; + if (aiptek == NULL) + return 0; - aiptek->newSetting.pointerMode = new_mode; + 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; + } return count; } @@ -1105,32 +1146,44 @@ 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; - return snprintf(buf, PAGE_SIZE, "%s\n", - map_val_to_str(coordinate_mode_map, - aiptek->curSetting.coordinateMode)); + 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); } 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); - int new_mode = map_str_to_val(coordinate_mode_map, buf, count); - - if (new_mode == AIPTEK_INVALID_VALUE) - return -EINVAL; + if (aiptek == NULL) + return 0; - aiptek->newSetting.coordinateMode = new_mode; + 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; + } return count; } @@ -1142,37 +1195,73 @@ 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; - return snprintf(buf, PAGE_SIZE, "%s\n", - map_val_to_str(tool_mode_map, - aiptek->curSetting.toolMode)); + default: + s = "unknown"; + break; + } + return snprintf(buf, PAGE_SIZE, "%s\n", s); } 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); - int new_mode = map_str_to_val(tool_mode_map, buf, count); + if (aiptek == NULL) + return 0; - if (new_mode == AIPTEK_INVALID_VALUE) - return -EINVAL; + 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; + } - aiptek->newSetting.toolMode = new_mode; return count; } @@ -1188,6 +1277,9 @@ 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 { @@ -1202,6 +1294,9 @@ 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 { @@ -1224,6 +1319,9 @@ 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 { @@ -1238,6 +1336,9 @@ 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 { @@ -1260,6 +1361,9 @@ 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); } @@ -1268,6 +1372,9 @@ 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; } @@ -1284,6 +1391,9 @@ 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); } @@ -1293,6 +1403,9 @@ 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; } @@ -1301,6 +1414,23 @@ static DEVICE_ATTR(delay, S_IRUGO | S_IWUGO, 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. @@ -1309,6 +1439,9 @@ 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); } @@ -1323,6 +1456,9 @@ 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"; @@ -1357,32 +1493,45 @@ 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; - return snprintf(buf, PAGE_SIZE, "%s\n", - map_val_to_str(stylus_button_map, - aiptek->curSetting.stylusButtonUpper)); + default: + s = "unknown"; + break; + } + return snprintf(buf, PAGE_SIZE, "%s\n", s); } 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 (new_button == AIPTEK_INVALID_VALUE) - return -EINVAL; + if (aiptek == NULL) + return 0; - aiptek->newSetting.stylusButtonUpper = new_button; + 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; + } return count; } @@ -1394,26 +1543,45 @@ 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; - return snprintf(buf, PAGE_SIZE, "%s\n", - map_val_to_str(stylus_button_map, - aiptek->curSetting.stylusButtonLower)); + default: + s = "unknown"; + break; + } + return snprintf(buf, PAGE_SIZE, "%s\n", s); } 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 (new_button == AIPTEK_INVALID_VALUE) - return -EINVAL; + if (aiptek == NULL) + return 0; - aiptek->newSetting.stylusButtonLower = new_button; + 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; + } return count; } @@ -1425,33 +1593,49 @@ 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; - return snprintf(buf, PAGE_SIZE, "%s\n", - map_val_to_str(mouse_button_map, - aiptek->curSetting.mouseButtonLeft)); + default: + s = "unknown"; + break; + } + return snprintf(buf, PAGE_SIZE, "%s\n", s); } 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 (new_button == AIPTEK_INVALID_VALUE) - return -EINVAL; + if (aiptek == NULL) + return 0; - aiptek->newSetting.mouseButtonLeft = new_button; + 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; + } return count; } @@ -1466,22 +1650,48 @@ 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; - return snprintf(buf, PAGE_SIZE, "%s\n", - map_val_to_str(mouse_button_map, - aiptek->curSetting.mouseButtonMiddle)); + 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); } 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 (new_button == AIPTEK_INVALID_VALUE) - return -EINVAL; + if (aiptek == NULL) + return 0; - aiptek->newSetting.mouseButtonMiddle = new_button; + 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; + } return count; } @@ -1496,22 +1706,47 @@ 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; - return snprintf(buf, PAGE_SIZE, "%s\n", - map_val_to_str(mouse_button_map, - aiptek->curSetting.mouseButtonRight)); + case AIPTEK_MOUSE_RIGHT_BUTTON: + s = "right"; + break; + + default: + s = "unknown"; + break; + } + return snprintf(buf, PAGE_SIZE, "%s\n", s); } 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 (new_button == AIPTEK_INVALID_VALUE) - return -EINVAL; + if (aiptek == NULL) + return 0; - aiptek->newSetting.mouseButtonRight = new_button; + 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; + } return count; } @@ -1527,6 +1762,9 @@ 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 { @@ -1540,6 +1778,9 @@ 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; } @@ -1553,6 +1794,11 @@ 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... */ @@ -1565,6 +1811,9 @@ 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. */ @@ -1588,6 +1837,9 @@ 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); } @@ -1601,6 +1853,9 @@ 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); } @@ -1614,39 +1869,86 @@ 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); -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 -}; +/*********************************************************************** + * 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); +} -static struct attribute_group aiptek_attribute_group = { - .attrs = aiptek_attributes, -}; +/*********************************************************************** + * This routine creates the sysfs files managed by this device + * driver. + */ +static int aiptek_add_files(struct device *dev) +{ + int ret; + + 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; +} /*********************************************************************** * This routine is called when a tablet has been identified. It basically @@ -1659,6 +1961,8 @@ 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, @@ -1680,23 +1984,17 @@ 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) { - warn("aiptek: cannot allocate memory or input device"); + if (!aiptek || !inputdev) goto fail1; - } aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH, GFP_ATOMIC, &aiptek->data_dma); - if (!aiptek->data) { - warn("aiptek: cannot allocate usb buffer"); + if (!aiptek->data) goto fail1; - } aiptek->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!aiptek->urb) { - warn("aiptek: cannot allocate urb"); + if (!aiptek->urb) goto fail2; - } aiptek->inputdev = inputdev; aiptek->usbdev = usbdev; @@ -1704,7 +2002,6 @@ 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 @@ -1757,23 +2054,36 @@ 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. */ - for (i = 0; i < ARRAY_SIZE(eventTypes); ++i) - __set_bit(eventTypes[i], inputdev->evbit); + 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(absEvents); ++i) - __set_bit(absEvents[i], inputdev->absbit); + inputdev->relbit[0] |= + (BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL) | BIT(REL_MISC)); - for (i = 0; i < ARRAY_SIZE(relEvents); ++i) - __set_bit(relEvents[i], inputdev->relbit); + inputdev->keybit[LONG(BTN_LEFT)] |= + (BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE)); - __set_bit(MSC_SERIAL, inputdev->mscbit); + 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 up key and button codes */ - for (i = 0; i < ARRAY_SIZE(buttonEvents); ++i) - __set_bit(buttonEvents[i], inputdev->keybit); + inputdev->mscbit[0] = BIT(MSC_SERIAL); + /* 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 @@ -1824,11 +2134,25 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) } } - /* 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"); + /* Register the tablet as an Input Device + */ + err = input_register_device(aiptek->inputdev); + if (err) 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. @@ -1837,27 +2161,18 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) /* Set up the sysfs files */ - err = sysfs_create_group(&intf->dev.kobj, &aiptek_attribute_group); - if (err) { - warn("aiptek: cannot create sysfs group err: %d", err); - goto fail3; - } + aiptek_add_files(&intf->dev); - /* Register the tablet as an Input Device + /* Make sure the evdev module is loaded. Assuming evdev IS a module :-) */ - err = input_register_device(aiptek->inputdev); - if (err) { - warn("aiptek: input_register_device returned err: %d", err); - goto fail4; - } + if (request_module("evdev") != 0) + info("aiptek: error loading 'evdev' module"); + 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: usb_set_intfdata(intf, NULL); - input_free_device(inputdev); + fail1: input_free_device(inputdev); kfree(aiptek); return err; } @@ -1877,7 +2192,7 @@ static void aiptek_disconnect(struct usb_interface *intf) */ usb_kill_urb(aiptek->urb); input_unregister_device(aiptek->inputdev); - sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group); + aiptek_delete_files(&intf->dev); usb_free_urb(aiptek->urb); usb_buffer_free(interface_to_usbdev(intf), AIPTEK_PACKET_LENGTH, diff --git a/trunk/drivers/input/tablet/wacom.h b/trunk/drivers/input/tablet/wacom.h index 6542edb6f76e..ef01a807ec0f 100644 --- a/trunk/drivers/input/tablet/wacom.h +++ b/trunk/drivers/input/tablet/wacom.h @@ -11,7 +11,7 @@ * Copyright (c) 2000 Daniel Egger * Copyright (c) 2001 Frederic Lepied * Copyright (c) 2004 Panagiotis Issaris - * Copyright (c) 2002-2007 Ping Cheng + * Copyright (c) 2002-2006 Ping Cheng * * ChangeLog: * v0.1 (vp) - Initial release @@ -62,9 +62,8 @@ * - 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 */ /* @@ -85,7 +84,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.47" +#define DRIVER_VERSION "v1.46" #define DRIVER_AUTHOR "Vojtech Pavlik " #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" #define DRIVER_LICENSE "GPL" @@ -124,7 +123,6 @@ 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/trunk/drivers/input/tablet/wacom_sys.c b/trunk/drivers/input/tablet/wacom_sys.c index 064e123c9b76..83bddef66067 100644 --- a/trunk/drivers/input/tablet/wacom_sys.c +++ b/trunk/drivers/input/tablet/wacom_sys.c @@ -138,12 +138,6 @@ 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/trunk/drivers/input/tablet/wacom_wac.c b/trunk/drivers/input/tablet/wacom_wac.c index fc03ba256f4c..7661f03a2db2 100644 --- a/trunk/drivers/input/tablet/wacom_wac.c +++ b/trunk/drivers/input/tablet/wacom_wac.c @@ -178,8 +178,7 @@ 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 || - wacom->features->type == WACOM_MO) { + if (wacom->features->type == WACOM_G4) { rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03); wacom_report_rel(wcombo, REL_WHEEL, -rw); } else @@ -191,8 +190,7 @@ 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 || - wacom->features->type == WACOM_MO) + if (wacom->features->type == WACOM_G4) wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); else wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); @@ -228,8 +226,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) } /* send pad data */ - switch (wacom->features->type) { - case WACOM_G4: + if (wacom->features->type == WACOM_G4) { if (data[7] & 0xf8) { wacom_input_sync(wcombo); /* sync last event */ wacom->id[1] = 1; @@ -250,33 +247,6 @@ 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; } @@ -361,7 +331,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); @@ -453,9 +423,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 */ @@ -547,7 +517,6 @@ 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: @@ -569,8 +538,6 @@ 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 */ @@ -612,7 +579,6 @@ 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 }, @@ -661,7 +627,6 @@ 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/trunk/drivers/input/tablet/wacom_wac.h b/trunk/drivers/input/tablet/wacom_wac.h index a302e229bb8a..a5e12e8756de 100644 --- a/trunk/drivers/input/tablet/wacom_wac.h +++ b/trunk/drivers/input/tablet/wacom_wac.h @@ -25,7 +25,6 @@ enum { INTUOS3, INTUOS3L, CINTIQ, - WACOM_MO, MAX_TYPE }; diff --git a/trunk/drivers/input/touchscreen/Kconfig b/trunk/drivers/input/touchscreen/Kconfig index 69371779806a..e5cca9bd0406 100644 --- a/trunk/drivers/input/touchscreen/Kconfig +++ b/trunk/drivers/input/touchscreen/Kconfig @@ -177,7 +177,6 @@ config TOUCHSCREEN_USB_COMPOSITE - some other eTurboTouch - Gunze AHL61 - DMC TSC-10/25 - - IRTOUCHSYSTEMS/UNITOP Have a look at for a usage description and the required user-space stuff. @@ -220,9 +219,4 @@ 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/trunk/drivers/input/touchscreen/usbtouchscreen.c b/trunk/drivers/input/touchscreen/usbtouchscreen.c index b407028ffc59..e3f22852bd09 100644 --- a/trunk/drivers/input/touchscreen/usbtouchscreen.c +++ b/trunk/drivers/input/touchscreen/usbtouchscreen.c @@ -9,7 +9,6 @@ * - eTurboTouch * - Gunze AHL61 * - DMC TSC-10/25 - * - IRTOUCHSYSTEMS/UNITOP * * Copyright (C) 2004-2006 by Daniel Ritz * Copyright (C) by Todd E. Johnson (mtouchusb.c) @@ -111,7 +110,6 @@ enum { DEVTYPE_ETURBO, DEVTYPE_GUNZE, DEVTYPE_DMC_TSC10, - DEVTYPE_IRTOUCH, }; static struct usb_device_id usbtouch_devices[] = { @@ -152,11 +150,6 @@ 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 - {} }; @@ -422,21 +415,6 @@ static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt) #endif -/***************************************************************************** - * 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 */ @@ -526,17 +504,6 @@ 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/trunk/drivers/input/tsdev.c b/trunk/drivers/input/tsdev.c index d2f882e98e5e..2db364898e15 100644 --- a/trunk/drivers/input/tsdev.c +++ b/trunk/drivers/input/tsdev.c @@ -109,11 +109,9 @@ struct tsdev { int open; int minor; char name[8]; - struct input_handle handle; wait_queue_head_t wait; struct list_head client_list; - struct device dev; - + struct input_handle handle; int x, y, pressure; struct ts_calibration cal; }; @@ -165,13 +163,9 @@ 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) { - error = -ENOMEM; - goto err_put_tsdev; - } + if (!client) + return -ENOMEM; client->tsdev = tsdev; client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0; @@ -179,25 +173,19 @@ static int tsdev_open(struct inode *inode, struct file *file) if (!tsdev->open++ && tsdev->exist) { error = input_open_device(&tsdev->handle); - if (error) - goto err_free_client; + if (error) { + list_del(&client->node); + kfree(client); + return error; + } } 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 device *dev) +static void tsdev_free(struct tsdev *tsdev) { - struct tsdev *tsdev = container_of(dev, struct tsdev, dev); - tsdev_table[tsdev->minor] = NULL; kfree(tsdev); } @@ -212,10 +200,12 @@ static int tsdev_release(struct inode *inode, struct file *file) list_del(&client->node); kfree(client); - if (!--tsdev->open && tsdev->exist) - input_close_device(&tsdev->handle); - - put_device(&tsdev->dev); + if (!--tsdev->open) { + if (tsdev->exist) + input_close_device(&tsdev->handle); + else + tsdev_free(tsdev); + } return 0; } @@ -371,7 +361,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 / 1000; + client->event[client->head].millisecs = time.tv_usec / 100; client->event[client->head].pressure = tsdev->pressure; x = tsdev->x; @@ -398,6 +388,8 @@ 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; @@ -415,13 +407,14 @@ 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; @@ -436,30 +429,36 @@ 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); - 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); - tsdev_table[minor] = tsdev; - error = device_add(&tsdev->dev); - if (error) + devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor), + + 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; + } + + /* temporary symlink to keep userspace happy */ + error = sysfs_create_link(&input_class.subsys.kobj, + &cdev->kobj, tsdev->name); + if (error) + goto err_cdev_destroy; error = input_register_handle(&tsdev->handle); if (error) - goto err_delete_tsdev; + goto err_remove_link; return 0; - err_delete_tsdev: - device_del(&tsdev->dev); + err_remove_link: + sysfs_remove_link(&input_class.subsys.kobj, tsdev->name); + err_cdev_destroy: + class_device_destroy(&input_class, devt); err_free_tsdev: - put_device(&tsdev->dev); + tsdev_table[minor] = NULL; + kfree(tsdev); return error; } @@ -469,8 +468,10 @@ 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) { @@ -478,9 +479,8 @@ 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); - } - - put_device(&tsdev->dev); + } else + tsdev_free(tsdev); } static const struct input_device_id tsdev_ids[] = { diff --git a/trunk/drivers/mtd/devices/docprobe.c b/trunk/drivers/mtd/devices/docprobe.c index b96ac8e119dc..78872c3f3760 100644 --- a/trunk/drivers/mtd/devices/docprobe.c +++ b/trunk/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) +#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C) 0xff000000, ##else #warning Unknown architecture for DiskOnChip. No default probe locations defined diff --git a/trunk/drivers/mtd/maps/Kconfig b/trunk/drivers/mtd/maps/Kconfig index f88ebc5b685e..b665e4ac2208 100644 --- a/trunk/drivers/mtd/maps/Kconfig +++ b/trunk/drivers/mtd/maps/Kconfig @@ -258,6 +258,12 @@ 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/trunk/drivers/mtd/maps/Makefile b/trunk/drivers/mtd/maps/Makefile index 970b189271a2..3acbb5d01ca4 100644 --- a/trunk/drivers/mtd/maps/Makefile +++ b/trunk/drivers/mtd/maps/Makefile @@ -47,6 +47,7 @@ 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/trunk/drivers/mtd/maps/lasat.c b/trunk/drivers/mtd/maps/lasat.c new file mode 100644 index 000000000000..e34376321050 --- /dev/null +++ b/trunk/drivers/mtd/maps/lasat.c @@ -0,0 +1,103 @@ +/* + * Flash device on Lasat 100 and 200 boards + * + * (C) 2002 Brian Murphy + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +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 "); +MODULE_DESCRIPTION("Lasat Safepipe/Masquerade MTD map driver"); diff --git a/trunk/drivers/mtd/nand/diskonchip.c b/trunk/drivers/mtd/nand/diskonchip.c index 17c868034aad..595208f965a5 100644 --- a/trunk/drivers/mtd/nand/diskonchip.c +++ b/trunk/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) +#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C) 0xff000000, #else #warning Unknown architecture for DiskOnChip. No default probe locations defined diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig index 627316db3744..5cc3d517e39b 100644 --- a/trunk/drivers/net/Kconfig +++ b/trunk/drivers/net/Kconfig @@ -2307,7 +2307,7 @@ config UGETH_TX_ON_DEMAND config MV643XX_ETH tristate "MV-643XX Ethernet support" - depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32) + depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MV64X60 || MOMENCO_OCELOT_3 || (PPC_MULTIPLATFORM && PPC32) select MII help This driver supports the gigabit Ethernet on the Marvell MV643XX diff --git a/trunk/drivers/net/sky2.c b/trunk/drivers/net/sky2.c index b51d73c8f817..77abf892e4f3 100644 --- a/trunk/drivers/net/sky2.c +++ b/trunk/drivers/net/sky2.c @@ -96,7 +96,7 @@ static int disable_msi = 0; module_param(disable_msi, int, 0); MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); -static int idle_timeout = 0; +static int idle_timeout = 100; module_param(idle_timeout, int, 0); MODULE_PARM_DESC(idle_timeout, "Watchdog timer for lost interrupts (ms)"); @@ -2490,6 +2490,13 @@ static int sky2_poll(struct net_device *dev0, int *budget) work_done = sky2_status_intr(hw, work_limit); if (work_done < work_limit) { + /* Bug/Errata workaround? + * Need to kick the TX irq moderation timer. + */ + if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) { + sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP); + sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START); + } netif_rx_complete(dev0); /* end of interrupt, re-enables also acts as I/O synchronization */ diff --git a/trunk/drivers/net/tc35815.c b/trunk/drivers/net/tc35815.c index 75655add3f34..463d600ed83d 100644 --- a/trunk/drivers/net/tc35815.c +++ b/trunk/drivers/net/tc35815.c @@ -23,9 +23,9 @@ */ #ifdef TC35815_NAPI -#define DRV_VERSION "1.36-NAPI" +#define DRV_VERSION "1.35-NAPI" #else -#define DRV_VERSION "1.36" +#define DRV_VERSION "1.35" #endif static const char *version = "tc35815.c:v" DRV_VERSION "\n"; #define MODNAME "tc35815" @@ -49,7 +49,6 @@ static const char *version = "tc35815.c:v" DRV_VERSION "\n"; #include #include #include -#include #include #include @@ -598,46 +597,13 @@ 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); -#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) +static void __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) { @@ -649,9 +615,6 @@ static int __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, @@ -761,10 +724,7 @@ static int __devinit tc35815_init_one (struct pci_dev *pdev, tc35815_chip_reset(dev); /* Retrieve the ethernet address. */ - if (tc35815_init_dev_addr(dev)) { - dev_warn(&pdev->dev, "not valid ether addr\n"); - random_ether_addr(dev->dev_addr); - } + tc35815_init_dev_addr(dev); rc = register_netdev (dev); if (rc) diff --git a/trunk/drivers/power/Kconfig b/trunk/drivers/power/Kconfig deleted file mode 100644 index ab9c3e5a7c1d..000000000000 --- a/trunk/drivers/power/Kconfig +++ /dev/null @@ -1,51 +0,0 @@ -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/trunk/drivers/power/Makefile b/trunk/drivers/power/Makefile deleted file mode 100644 index 6413ded5fe5f..000000000000 --- a/trunk/drivers/power/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -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/trunk/drivers/power/apm_power.c b/trunk/drivers/power/apm_power.c deleted file mode 100644 index 042bd950d036..000000000000 --- a/trunk/drivers/power/apm_power.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright © 2007 Anton Vorontsov - * Copyright © 2007 Eugeny Boger - * - * Author: Eugeny Boger - * - * 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 -#include -#include - -#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 "); -MODULE_DESCRIPTION("APM emulation driver for battery monitoring class"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/power/ds2760_battery.c b/trunk/drivers/power/ds2760_battery.c deleted file mode 100644 index 00e1ea6f1de2..000000000000 --- a/trunk/drivers/power/ds2760_battery.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - * 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 - * February 2007 - * - * Matt Reimer - * April 2004, 2005, 2007 - * - * Szabolcs Gyurko - * September 2004 - */ - -#include -#include -#include -#include -#include -#include -#include - -#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 , " - "Matt Reimer , " - "Anton Vorontsov "); -MODULE_DESCRIPTION("ds2760 battery driver"); diff --git a/trunk/drivers/power/olpc_battery.c b/trunk/drivers/power/olpc_battery.c deleted file mode 100644 index 878684df7667..000000000000 --- a/trunk/drivers/power/olpc_battery.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Battery driver for One Laptop Per Child board. - * - * Copyright © 2006 David Woodhouse - * - * 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 -#include -#include -#include -#include -#include -#include - - -#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 "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Battery driver for One Laptop Per Child 'XO' machine"); diff --git a/trunk/drivers/power/pda_power.c b/trunk/drivers/power/pda_power.c deleted file mode 100644 index 4e1eb040e148..000000000000 --- a/trunk/drivers/power/pda_power.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * 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 - * - * 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 -#include -#include -#include -#include -#include -#include - -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 "); diff --git a/trunk/drivers/power/pmu_battery.c b/trunk/drivers/power/pmu_battery.c deleted file mode 100644 index 2fea4af0e40a..000000000000 --- a/trunk/drivers/power/pmu_battery.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Battery class driver for Apple PMU - * - * Copyright © 2006 David Woodhouse - * - * 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 -#include -#include -#include -#include -#include - -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 "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("PMU battery driver"); diff --git a/trunk/drivers/power/power_supply.h b/trunk/drivers/power/power_supply.h deleted file mode 100644 index a9880d468ee4..000000000000 --- a/trunk/drivers/power/power_supply.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Functions private to power supply class - * - * Copyright © 2007 Anton Vorontsov - * Copyright © 2004 Szabolcs Gyurko - * Copyright © 2003 Ian Molton - * - * 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/trunk/drivers/power/power_supply_core.c b/trunk/drivers/power/power_supply_core.c deleted file mode 100644 index e87ea5156755..000000000000 --- a/trunk/drivers/power/power_supply_core.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Universal power supply monitor class - * - * Copyright © 2007 Anton Vorontsov - * Copyright © 2004 Szabolcs Gyurko - * Copyright © 2003 Ian Molton - * - * Modified: 2004, Oct Szabolcs Gyurko - * - * You may use this code as per GPL version 2 - */ - -#include -#include -#include -#include -#include -#include -#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 , " - "Szabolcs Gyurko, " - "Anton Vorontsov "); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/power/power_supply_leds.c b/trunk/drivers/power/power_supply_leds.c deleted file mode 100644 index 7232490bb595..000000000000 --- a/trunk/drivers/power/power_supply_leds.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * LEDs triggers for power supply class - * - * Copyright © 2007 Anton Vorontsov - * Copyright © 2004 Szabolcs Gyurko - * Copyright © 2003 Ian Molton - * - * Modified: 2004, Oct Szabolcs Gyurko - * - * You may use this code as per GPL version 2 - */ - -#include - -/* 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/trunk/drivers/power/power_supply_sysfs.c b/trunk/drivers/power/power_supply_sysfs.c deleted file mode 100644 index c07d4258d347..000000000000 --- a/trunk/drivers/power/power_supply_sysfs.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Sysfs interface for the universal power supply monitor class - * - * Copyright © 2007 David Woodhouse - * Copyright © 2007 Anton Vorontsov - * Copyright © 2004 Szabolcs Gyurko - * Copyright © 2003 Ian Molton - * - * Modified: 2004, Oct Szabolcs Gyurko - * - * You may use this code as per GPL version 2 - */ - -#include -#include - -/* - * 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/trunk/drivers/s390/block/dasd_proc.c b/trunk/drivers/s390/block/dasd_proc.c index ac7e8ef504cb..8b3b0f4a157c 100644 --- a/trunk/drivers/s390/block/dasd_proc.c +++ b/trunk/drivers/s390/block/dasd_proc.c @@ -28,7 +28,6 @@ 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) { @@ -48,7 +47,6 @@ 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) @@ -169,7 +167,6 @@ 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) { @@ -183,7 +180,6 @@ 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/trunk/drivers/s390/char/sclp.h b/trunk/drivers/s390/char/sclp.h index c7318a125852..dbb99d1b6f57 100644 --- a/trunk/drivers/s390/char/sclp.h +++ b/trunk/drivers/s390/char/sclp.h @@ -72,18 +72,6 @@ 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/trunk/drivers/s390/char/sclp_chp.c b/trunk/drivers/s390/char/sclp_chp.c index c68f5e7e63a0..a66b914519b5 100644 --- a/trunk/drivers/s390/char/sclp_chp.c +++ b/trunk/drivers/s390/char/sclp_chp.c @@ -55,8 +55,6 @@ 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) @@ -154,8 +152,6 @@ 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/trunk/drivers/s390/char/sclp_info.c b/trunk/drivers/s390/char/sclp_info.c index a1136e052750..7bcbe643b087 100644 --- a/trunk/drivers/s390/char/sclp_info.c +++ b/trunk/drivers/s390/char/sclp_info.c @@ -11,106 +11,47 @@ #include #include "sclp.h" -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; +struct sclp_readinfo_sccb s390_readinfo_sccb; 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}; - /* 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); + __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; - 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); -} -void __init sclp_facilities_detect(void) -{ - if (!early_readinfo_sccb_valid) - return; - sclp_facilities = early_readinfo_sccb.facilities; -} - -unsigned long long __init sclp_memory_detect(void) -{ - unsigned long long memsize; - struct sclp_readinfo_sccb *sccb; + response = sccb->response_code; - 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; -} + if (response == 0x10) + break; -/* - * 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 (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO) + break; - 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); + command = SCLP_CMDW_READ_SCP_INFO; + } +out: + __ctl_clear_bit(0, 9); /* disable service signal subclass mask */ } diff --git a/trunk/drivers/s390/char/vmcp.c b/trunk/drivers/s390/char/vmcp.c index 82e6a6b253eb..fce3dac5cb3e 100644 --- a/trunk/drivers/s390/char/vmcp.c +++ b/trunk/drivers/s390/char/vmcp.c @@ -175,12 +175,13 @@ 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, - .write = vmcp_write, - .unlocked_ioctl = vmcp_ioctl, - .compat_ioctl = vmcp_ioctl + .open = &vmcp_open, + .release = &vmcp_release, + .read = &vmcp_read, + .llseek = &no_llseek, + .write = &vmcp_write, + .unlocked_ioctl = &vmcp_ioctl, + .compat_ioctl = &vmcp_ioctl }; static struct miscdevice vmcp_dev = { diff --git a/trunk/drivers/s390/char/vmlogrdr.c b/trunk/drivers/s390/char/vmlogrdr.c index 12f7a4ce82c1..a5a00e9ae4d0 100644 --- a/trunk/drivers/s390/char/vmlogrdr.c +++ b/trunk/drivers/s390/char/vmlogrdr.c @@ -835,7 +835,7 @@ static void vmlogrdr_cleanup(void) } -static int __init vmlogrdr_init(void) +static int vmlogrdr_init(void) { int rc; int i; @@ -885,7 +885,7 @@ static int __init vmlogrdr_init(void) } -static void __exit vmlogrdr_exit(void) +static void vmlogrdr_exit(void) { vmlogrdr_cleanup(); printk (KERN_INFO "vmlogrdr: driver unloaded\n"); diff --git a/trunk/drivers/s390/char/zcore.c b/trunk/drivers/s390/char/zcore.c index 3712ede16723..4e711a985d59 100644 --- a/trunk/drivers/s390/char/zcore.c +++ b/trunk/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(void __user *dest, unsigned long src, size_t count) +static int memcpy_real_user(__user void *dest, unsigned long src, size_t count) { static char buf[4096]; int offs = 0, size; diff --git a/trunk/drivers/s390/cio/device_id.c b/trunk/drivers/s390/cio/device_id.c index 60b9347f7c92..997f46874537 100644 --- a/trunk/drivers/s390/cio/device_id.c +++ b/trunk/drivers/s390/cio/device_id.c @@ -27,6 +27,7 @@ /* * diag210 is used under VM to get information about a virtual device */ +#ifdef CONFIG_64BIT int diag210(struct diag210 * addr) { @@ -42,7 +43,6 @@ 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,8 +51,19 @@ diag210(struct diag210 * addr) " srl %0,28\n" "1: sam64\n" EX_TABLE(0b,1b) - : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory"); + : "=&d" (ccode) : "a" (__pa(&diag210_tmp)) : "cc", "memory"); + + *addr = diag210_tmp; + spin_unlock_irqrestore(&diag210_lock, flags); + + return ccode; +} #else +int +diag210(struct diag210 * addr) +{ + int ccode; + asm volatile( " lhi %0,-1\n" " diag %1,0,0x210\n" @@ -60,14 +71,11 @@ diag210(struct diag210 * addr) " srl %0,28\n" "1:\n" EX_TABLE(0b,1b) - : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory"); -#endif - - *addr = diag210_tmp; - spin_unlock_irqrestore(&diag210_lock, flags); + : "=&d" (ccode) : "a" (__pa(addr)) : "cc", "memory"); return ccode; } +#endif /* * Input : diff --git a/trunk/drivers/s390/crypto/ap_bus.c b/trunk/drivers/s390/crypto/ap_bus.c index 90bd22014513..5aac0ec36368 100644 --- a/trunk/drivers/s390/crypto/ap_bus.c +++ b/trunk/drivers/s390/crypto/ap_bus.c @@ -43,7 +43,6 @@ 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. @@ -190,7 +189,6 @@ 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; @@ -254,8 +252,6 @@ 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; } @@ -330,12 +326,11 @@ 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 && rc != -EBUSY) + if (rc != -ENODEV) break; if (i < AP_MAX_RESET - 1) { udelay(5); @@ -345,40 +340,6 @@ static int ap_init_queue(ap_qid_t qid) return rc; } -/** - * 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. */ @@ -537,7 +498,6 @@ 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); @@ -799,21 +759,17 @@ 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); - device_unregister(dev); put_device(dev); + device_unregister(dev); continue; - } - spin_unlock_bh(&ap_dev->lock); + } else + spin_unlock_bh(&ap_dev->lock); + } + if (dev) { put_device(dev); continue; } @@ -832,8 +788,6 @@ 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 @@ -899,7 +853,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_decrease_queue_count(ap_dev); + ap_dev->queue_count--; list_for_each_entry(ap_msg, &ap_dev->pendingq, list) { if (ap_msg->psmid != ap_dev->reply->psmid) continue; @@ -950,7 +904,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_increase_queue_count(ap_dev); + ap_dev->queue_count++; list_move_tail(&ap_msg->list, &ap_dev->pendingq); ap_dev->requestq_count--; ap_dev->pendingq_count++; @@ -960,7 +914,6 @@ 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: @@ -1007,11 +960,10 @@ 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_increase_queue_count(ap_dev); + ap_dev->queue_count++; 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++; @@ -1093,25 +1045,6 @@ static void ap_poll_timeout(unsigned long unused) tasklet_schedule(&ap_tasklet); } -/** - * 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 @@ -1123,8 +1056,6 @@ 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; @@ -1216,17 +1147,6 @@ 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/trunk/drivers/s390/crypto/ap_bus.h b/trunk/drivers/s390/crypto/ap_bus.h index 87c2d6442875..008559ea742b 100644 --- a/trunk/drivers/s390/crypto/ap_bus.h +++ b/trunk/drivers/s390/crypto/ap_bus.h @@ -33,7 +33,6 @@ #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. */ @@ -84,13 +83,6 @@ 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; @@ -103,7 +95,6 @@ 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) @@ -121,8 +112,6 @@ 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/trunk/drivers/s390/crypto/zcrypt_cex2a.c b/trunk/drivers/s390/crypto/zcrypt_cex2a.c index 08657f604b8c..5bb13a9d0898 100644 --- a/trunk/drivers/s390/crypto/zcrypt_cex2a.c +++ b/trunk/drivers/s390/crypto/zcrypt_cex2a.c @@ -70,7 +70,6 @@ static struct ap_driver zcrypt_cex2a_driver = { .remove = zcrypt_cex2a_remove, .receive = zcrypt_cex2a_receive, .ids = zcrypt_cex2a_ids, - .request_timeout = CEX2A_CLEANUP_TIME, }; /** @@ -307,13 +306,18 @@ 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(&work); - if (rc == 0) + rc = wait_for_completion_interruptible_timeout( + &work, CEX2A_CLEANUP_TIME); + if (rc > 0) rc = convert_response(zdev, &ap_msg, mex->outputdata, mex->outputdatalength); - else - /* Signal pending. */ + else { + /* Signal pending or message timed out. */ ap_cancel_message(zdev->ap_dev, &ap_msg); + if (rc == 0) + /* Message timed out. */ + rc = -ETIME; + } out_free: kfree(ap_msg.message); return rc; @@ -344,13 +348,18 @@ 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(&work); - if (rc == 0) + rc = wait_for_completion_interruptible_timeout( + &work, CEX2A_CLEANUP_TIME); + if (rc > 0) rc = convert_response(zdev, &ap_msg, crt->outputdata, crt->outputdatalength); - else - /* Signal pending. */ + else { + /* Signal pending or message timed out. */ 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/trunk/drivers/s390/crypto/zcrypt_pcica.c b/trunk/drivers/s390/crypto/zcrypt_pcica.c index 6e93b4751782..818ffe05ac00 100644 --- a/trunk/drivers/s390/crypto/zcrypt_pcica.c +++ b/trunk/drivers/s390/crypto/zcrypt_pcica.c @@ -70,7 +70,6 @@ static struct ap_driver zcrypt_pcica_driver = { .remove = zcrypt_pcica_remove, .receive = zcrypt_pcica_receive, .ids = zcrypt_pcica_ids, - .request_timeout = PCICA_CLEANUP_TIME, }; /** @@ -291,13 +290,18 @@ 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(&work); - if (rc == 0) + rc = wait_for_completion_interruptible_timeout( + &work, PCICA_CLEANUP_TIME); + if (rc > 0) rc = convert_response(zdev, &ap_msg, mex->outputdata, mex->outputdatalength); - else - /* Signal pending. */ + else { + /* Signal pending or message timed out. */ ap_cancel_message(zdev->ap_dev, &ap_msg); + if (rc == 0) + /* Message timed out. */ + rc = -ETIME; + } out_free: kfree(ap_msg.message); return rc; @@ -328,13 +332,18 @@ 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(&work); - if (rc == 0) + rc = wait_for_completion_interruptible_timeout( + &work, PCICA_CLEANUP_TIME); + if (rc > 0) rc = convert_response(zdev, &ap_msg, crt->outputdata, crt->outputdatalength); - else - /* Signal pending. */ + else { + /* Signal pending or message timed out. */ 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/trunk/drivers/s390/crypto/zcrypt_pcicc.c b/trunk/drivers/s390/crypto/zcrypt_pcicc.c index d6d59bf9ac38..f295a403b29a 100644 --- a/trunk/drivers/s390/crypto/zcrypt_pcicc.c +++ b/trunk/drivers/s390/crypto/zcrypt_pcicc.c @@ -82,7 +82,6 @@ static struct ap_driver zcrypt_pcicc_driver = { .remove = zcrypt_pcicc_remove, .receive = zcrypt_pcicc_receive, .ids = zcrypt_pcicc_ids, - .request_timeout = PCICC_CLEANUP_TIME, }; /** @@ -502,13 +501,18 @@ 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(&work); - if (rc == 0) + rc = wait_for_completion_interruptible_timeout( + &work, PCICC_CLEANUP_TIME); + if (rc > 0) rc = convert_response(zdev, &ap_msg, mex->outputdata, mex->outputdatalength); - else - /* Signal pending. */ + else { + /* Signal pending or message timed out. */ 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; @@ -540,13 +544,18 @@ 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(&work); - if (rc == 0) + rc = wait_for_completion_interruptible_timeout( + &work, PCICC_CLEANUP_TIME); + if (rc > 0) rc = convert_response(zdev, &ap_msg, crt->outputdata, crt->outputdatalength); - else - /* Signal pending. */ + else { + /* Signal pending or message timed out. */ 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/trunk/drivers/s390/crypto/zcrypt_pcixcc.c b/trunk/drivers/s390/crypto/zcrypt_pcixcc.c index 64948788d301..252443b6bd1b 100644 --- a/trunk/drivers/s390/crypto/zcrypt_pcixcc.c +++ b/trunk/drivers/s390/crypto/zcrypt_pcixcc.c @@ -93,7 +93,6 @@ static struct ap_driver zcrypt_pcixcc_driver = { .remove = zcrypt_pcixcc_remove, .receive = zcrypt_pcixcc_receive, .ids = zcrypt_pcixcc_ids, - .request_timeout = PCIXCC_CLEANUP_TIME, }; /** @@ -642,13 +641,18 @@ 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(&resp_type.work); - if (rc == 0) + rc = wait_for_completion_interruptible_timeout( + &resp_type.work, PCIXCC_CLEANUP_TIME); + if (rc > 0) rc = convert_response_ica(zdev, &ap_msg, mex->outputdata, mex->outputdatalength); - else - /* Signal pending. */ + else { + /* Signal pending or message timed out. */ 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; @@ -681,13 +685,18 @@ 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(&resp_type.work); - if (rc == 0) + rc = wait_for_completion_interruptible_timeout( + &resp_type.work, PCIXCC_CLEANUP_TIME); + if (rc > 0) rc = convert_response_ica(zdev, &ap_msg, crt->outputdata, crt->outputdatalength); - else - /* Signal pending. */ + else { + /* Signal pending or message timed out. */ 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; @@ -720,12 +729,17 @@ 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(&resp_type.work); - if (rc == 0) + rc = wait_for_completion_interruptible_timeout( + &resp_type.work, PCIXCC_CLEANUP_TIME); + if (rc > 0) rc = convert_response_xcrb(zdev, &ap_msg, xcRB); - else - /* Signal pending. */ + else { + /* Signal pending or message timed out. */ 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/trunk/drivers/tc/zs.c b/trunk/drivers/tc/zs.c index 4fff61b32dcb..61de78a9f6ee 100644 --- a/trunk/drivers/tc/zs.c +++ b/trunk/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] = { +static unsigned char zs_init_regs[16] __initdata = { 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 probe_sccs(void) +static void __init 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 serial_console_setup(struct console *co, char *options) +static int __init serial_console_setup(struct console *co, char *options) { struct dec_serial *info; int baud = 9600; diff --git a/trunk/drivers/w1/slaves/Kconfig b/trunk/drivers/w1/slaves/Kconfig index df95d6c2cefa..904e5aeb696c 100644 --- a/trunk/drivers/w1/slaves/Kconfig +++ b/trunk/drivers/w1/slaves/Kconfig @@ -35,17 +35,4 @@ 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/trunk/drivers/w1/slaves/Makefile b/trunk/drivers/w1/slaves/Makefile index a8eb7524df1d..725dcfdfddb4 100644 --- a/trunk/drivers/w1/slaves/Makefile +++ b/trunk/drivers/w1/slaves/Makefile @@ -5,5 +5,4 @@ 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/trunk/drivers/w1/slaves/w1_ds2760.c b/trunk/drivers/w1/slaves/w1_ds2760.c deleted file mode 100644 index 88a37fbccc3f..000000000000 --- a/trunk/drivers/w1/slaves/w1_ds2760.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * 1-Wire implementation for the ds2760 chip - * - * Copyright © 2004-2005, 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. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#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 "); -MODULE_DESCRIPTION("1-wire Driver Dallas 2760 battery monitor chip"); diff --git a/trunk/drivers/w1/slaves/w1_ds2760.h b/trunk/drivers/w1/slaves/w1_ds2760.h deleted file mode 100644 index f1302429cb02..000000000000 --- a/trunk/drivers/w1/slaves/w1_ds2760.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 1-Wire implementation for the ds2760 chip - * - * Copyright © 2004-2005, 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. - * - */ - -#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/trunk/drivers/w1/w1_family.h b/trunk/drivers/w1/w1_family.h index ef1e1dafa19a..1e2ac40c2c14 100644 --- a/trunk/drivers/w1/w1_family.h +++ b/trunk/drivers/w1/w1_family.h @@ -33,7 +33,6 @@ #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/trunk/fs/adfs/file.c b/trunk/fs/adfs/file.c index 36e381c6a99a..f544a2855923 100644 --- a/trunk/fs/adfs/file.c +++ b/trunk/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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, }; const struct inode_operations adfs_file_inode_operations = { diff --git a/trunk/fs/affs/file.c b/trunk/fs/affs/file.c index c314a35f0918..c8796906f584 100644 --- a/trunk/fs/affs/file.c +++ b/trunk/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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, }; const struct inode_operations affs_file_inode_operations = { diff --git a/trunk/fs/afs/file.c b/trunk/fs/afs/file.c index aede7eb66dd4..9c0e721d9fc2 100644 --- a/trunk/fs/afs/file.c +++ b/trunk/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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, .fsync = afs_fsync, }; diff --git a/trunk/fs/bad_inode.c b/trunk/fs/bad_inode.c index 521ff7caadbd..329ee473eede 100644 --- a/trunk/fs/bad_inode.c +++ b/trunk/fs/bad_inode.c @@ -114,6 +114,12 @@ 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) { @@ -176,6 +182,7 @@ 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/trunk/fs/bfs/file.c b/trunk/fs/bfs/file.c index 24310e9ee05a..ef4d1fa04e65 100644 --- a/trunk/fs/bfs/file.c +++ b/trunk/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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, }; static int bfs_move_block(unsigned long from, unsigned long to, struct super_block *sb) diff --git a/trunk/fs/bio.c b/trunk/fs/bio.c index 33e46340a766..093345f00128 100644 --- a/trunk/fs/bio.c +++ b/trunk/fs/bio.c @@ -1223,6 +1223,8 @@ 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/trunk/fs/block_dev.c b/trunk/fs/block_dev.c index b3e9bfa748cf..ea1480a16f51 100644 --- a/trunk/fs/block_dev.c +++ b/trunk/fs/block_dev.c @@ -1346,6 +1346,7 @@ 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/trunk/fs/cifs/cifsfs.c b/trunk/fs/cifs/cifsfs.c index 8b0cbf4a4ad0..7c04752b76cb 100644 --- a/trunk/fs/cifs/cifsfs.c +++ b/trunk/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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, .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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, /* BB removeme BB */ #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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, .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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, /* BB removeme BB */ #ifdef CONFIG_CIFS_POSIX .ioctl = cifs_ioctl, #endif /* CONFIG_CIFS_POSIX */ diff --git a/trunk/fs/coda/file.c b/trunk/fs/coda/file.c index 99dbe866816d..5ef2b609ec7d 100644 --- a/trunk/fs/coda/file.c +++ b/trunk/fs/coda/file.c @@ -47,9 +47,8 @@ coda_file_read(struct file *coda_file, char __user *buf, size_t count, loff_t *p } static ssize_t -coda_file_splice_read(struct file *coda_file, loff_t *ppos, - struct pipe_inode_info *pipe, size_t count, - unsigned int flags) +coda_file_sendfile(struct file *coda_file, loff_t *ppos, size_t count, + read_actor_t actor, void *target) { struct coda_file_info *cfi; struct file *host_file; @@ -58,10 +57,10 @@ coda_file_splice_read(struct file *coda_file, loff_t *ppos, BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); host_file = cfi->cfi_container; - if (!host_file->f_op || !host_file->f_op->splice_read) + if (!host_file->f_op || !host_file->f_op->sendfile) return -EINVAL; - return host_file->f_op->splice_read(host_file, ppos, pipe, count,flags); + return host_file->f_op->sendfile(host_file, ppos, count, actor, target); } static ssize_t @@ -296,6 +295,6 @@ const struct file_operations coda_file_operations = { .flush = coda_flush, .release = coda_release, .fsync = coda_fsync, - .splice_read = coda_file_splice_read, + .sendfile = coda_file_sendfile, }; diff --git a/trunk/fs/dlm/Makefile b/trunk/fs/dlm/Makefile index d248e60951ba..604cf7dc5f39 100644 --- a/trunk/fs/dlm/Makefile +++ b/trunk/fs/dlm/Makefile @@ -8,7 +8,6 @@ dlm-y := ast.o \ member.o \ memory.o \ midcomms.o \ - netlink.o \ lowcomms.o \ rcom.o \ recover.o \ diff --git a/trunk/fs/dlm/config.c b/trunk/fs/dlm/config.c index 5069b2cb5a1f..822abdcd1434 100644 --- a/trunk/fs/dlm/config.c +++ b/trunk/fs/dlm/config.c @@ -90,7 +90,6 @@ struct cluster { unsigned int cl_scan_secs; unsigned int cl_log_debug; unsigned int cl_protocol; - unsigned int cl_timewarn_cs; }; enum { @@ -104,7 +103,6 @@ enum { CLUSTER_ATTR_SCAN_SECS, CLUSTER_ATTR_LOG_DEBUG, CLUSTER_ATTR_PROTOCOL, - CLUSTER_ATTR_TIMEWARN_CS, }; struct cluster_attribute { @@ -164,7 +162,6 @@ 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, @@ -177,7 +174,6 @@ 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, }; @@ -433,8 +429,6 @@ 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; @@ -754,16 +748,9 @@ 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; - - 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); + return to_space(config_group_find_obj(space_list, name)); } static void put_space(struct space *sp) @@ -789,20 +776,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) + if (found) + config_item_get(i); + else cm = NULL; return cm; } @@ -922,7 +909,6 @@ 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, @@ -934,7 +920,6 @@ 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_timewarn_cs = DEFAULT_TIMEWARN_CS + .ci_protocol = DEFAULT_PROTOCOL }; diff --git a/trunk/fs/dlm/config.h b/trunk/fs/dlm/config.h index a3170fe22090..967cc3d72e5e 100644 --- a/trunk/fs/dlm/config.h +++ b/trunk/fs/dlm/config.h @@ -27,7 +27,6 @@ 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/trunk/fs/dlm/debug_fs.c b/trunk/fs/dlm/debug_fs.c index 12c3bfd5e660..61ba670b9e02 100644 --- a/trunk/fs/dlm/debug_fs.c +++ b/trunk/fs/dlm/debug_fs.c @@ -17,7 +17,6 @@ #include #include "dlm_internal.h" -#include "lock.h" #define DLM_DEBUG_BUF_LEN 4096 static char debug_buf[DLM_DEBUG_BUF_LEN]; @@ -27,8 +26,6 @@ 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; @@ -60,8 +57,8 @@ static char *print_lockmode(int mode) } } -static void print_resource_lock(struct seq_file *s, struct dlm_lkb *lkb, - struct dlm_rsb *res) +static void print_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)); @@ -88,8 +85,6 @@ 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])) @@ -134,15 +129,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_resource_lock(s, lkb, res); + print_lock(s, lkb, res); seq_printf(s, "Conversion Queue\n"); list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) - print_resource_lock(s, lkb, res); + print_lock(s, lkb, res); seq_printf(s, "Waiting Queue\n"); list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) - print_resource_lock(s, lkb, res); + print_lock(s, lkb, res); if (list_empty(&res->res_lookup)) goto out; @@ -156,61 +151,6 @@ 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; } @@ -226,9 +166,6 @@ 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; } @@ -239,7 +176,6 @@ 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; @@ -248,14 +184,11 @@ 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; } @@ -269,7 +202,7 @@ static struct rsb_iter *rsb_iter_init(struct dlm_ls *ls) { struct rsb_iter *ri; - ri = kzalloc(sizeof *ri, GFP_KERNEL); + ri = kmalloc(sizeof *ri, GFP_KERNEL); if (!ri) return NULL; @@ -327,17 +260,7 @@ static int rsb_seq_show(struct seq_file *file, void *iter_ptr) { struct rsb_iter *ri = iter_ptr; - 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); - } + print_resource(ri->rsb, file); return 0; } @@ -372,83 +295,6 @@ static const struct file_operations rsb_fops = { .release = seq_release }; -/* - * 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 */ @@ -516,20 +362,6 @@ 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; } @@ -539,8 +371,6 @@ 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/trunk/fs/dlm/dlm_internal.h b/trunk/fs/dlm/dlm_internal.h index 74901e981e10..30994d68f6a0 100644 --- a/trunk/fs/dlm/dlm_internal.h +++ b/trunk/fs/dlm/dlm_internal.h @@ -151,7 +151,6 @@ struct dlm_args { void *bastaddr; int mode; struct dlm_lksb *lksb; - unsigned long timeout; }; @@ -214,9 +213,6 @@ 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 @@ -247,9 +243,6 @@ 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 */ @@ -454,16 +447,12 @@ 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 */ @@ -471,12 +460,9 @@ 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; @@ -486,7 +472,6 @@ 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; @@ -516,7 +501,6 @@ 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 */ @@ -534,7 +518,6 @@ 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/trunk/fs/dlm/lock.c b/trunk/fs/dlm/lock.c index b455919c1998..d8d6e729f96b 100644 --- a/trunk/fs/dlm/lock.c +++ b/trunk/fs/dlm/lock.c @@ -82,13 +82,10 @@ 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 @@ -197,17 +194,17 @@ void dlm_dump_rsb(struct dlm_rsb *r) /* Threads cannot use the lockspace while it's being recovered */ -static inline void dlm_lock_recovery(struct dlm_ls *ls) +static inline void lock_recovery(struct dlm_ls *ls) { down_read(&ls->ls_in_recovery); } -void dlm_unlock_recovery(struct dlm_ls *ls) +static inline void unlock_recovery(struct dlm_ls *ls) { up_read(&ls->ls_in_recovery); } -int dlm_lock_recovery_try(struct dlm_ls *ls) +static inline int lock_recovery_try(struct dlm_ls *ls) { return down_read_trylock(&ls->ls_in_recovery); } @@ -289,22 +286,8 @@ 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; @@ -598,7 +581,6 @@ 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); @@ -1003,136 +985,15 @@ 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) @@ -1414,8 +1275,10 @@ 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 an earlier lkb in the - * convert queue from being granted, then deadlk/demote lkb. + * 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(). * * Example: * Granted Queue: empty @@ -1424,52 +1287,41 @@ 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 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. + * list. We demote the granted mode of the second lock (the lkb passed to this + * function). * - * 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. + * 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. */ -static int conversion_deadlock_detect(struct dlm_rsb *r, struct dlm_lkb *lkb2) +static int conversion_deadlock_detect(struct dlm_rsb *rsb, struct dlm_lkb *lkb) { - struct dlm_lkb *lkb1; - int lkb_is_ahead = 0; + struct dlm_lkb *this, *first = NULL, *self = NULL; - list_for_each_entry(lkb1, &r->res_convertqueue, lkb_statequeue) { - if (lkb1 == lkb2) { - lkb_is_ahead = 1; + list_for_each_entry(this, &rsb->res_convertqueue, lkb_statequeue) { + if (!first) + first = this; + if (this == lkb) { + self = lkb; continue; } - if (!lkb_is_ahead) { - if (!modes_compat(lkb2, lkb1)) - return 1; - } else { - if (!modes_compat(lkb2, lkb1) && - !modes_compat(lkb1, lkb2)) - return 1; - } + 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; } + return 0; } @@ -1598,57 +1450,42 @@ 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; } -static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now, - int *err) +/* + * 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) { + 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; - /* - * 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); - } - } + if (lkb->lkb_sbflags & DLM_SBF_DEMOTED) goto out; - } - /* - * 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)) + if (rqmode != DLM_LOCK_PR && flags & DLM_LKF_ALTPR) alt = DLM_LOCK_PR; - else if (rqmode != DLM_LOCK_CW && (lkb->lkb_exflags & DLM_LKF_ALTCW)) + else if (rqmode != DLM_LOCK_CW && flags & DLM_LKF_ALTCW) alt = DLM_LOCK_CW; if (alt) { @@ -1663,20 +1500,10 @@ 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: @@ -1686,29 +1513,14 @@ 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); - deadlk = 0; - - if (can_be_granted(r, lkb, 0, &deadlk)) { + if (can_be_granted(r, lkb, 0)) { grant_lock_pending(r, lkb); grant_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; + } else { + hi = max_t(int, lkb->lkb_rqmode, hi); + if (!demoted && is_demoted(lkb)) + demote_restart = 1; } - - hi = max_t(int, lkb->lkb_rqmode, hi); } if (grant_restart) @@ -1726,7 +1538,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, NULL)) + if (can_be_granted(r, lkb, 0)) grant_lock_pending(r, lkb); else high = max_t(int, lkb->lkb_rqmode, high); @@ -1921,7 +1733,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, unsigned long timeout_cs, void *ast, + int namelen, uint32_t parent_lkid, void *ast, void *astarg, void *bast, struct dlm_args *args) { int rv = -EINVAL; @@ -1964,6 +1776,10 @@ 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; @@ -1975,7 +1791,6 @@ 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; @@ -2030,7 +1845,6 @@ 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; @@ -2089,9 +1903,6 @@ 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; @@ -2123,9 +1934,6 @@ 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; @@ -2176,7 +1984,7 @@ static int do_request(struct dlm_rsb *r, struct dlm_lkb *lkb) { int error = 0; - if (can_be_granted(r, lkb, 1, NULL)) { + if (can_be_granted(r, lkb, 1)) { grant_lock(r, lkb); queue_cast(r, lkb, 0); goto out; @@ -2186,7 +1994,6 @@ 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; } @@ -2202,32 +2009,16 @@ 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, &deadlk)) { + if (can_be_granted(r, lkb, 1)) { 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 @@ -2250,7 +2041,6 @@ 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; } @@ -2484,7 +2274,7 @@ int dlm_lock(dlm_lockspace_t *lockspace, if (!ls) return -EINVAL; - dlm_lock_recovery(ls); + lock_recovery(ls); if (convert) error = find_lkb(ls, lksb->sb_lkid, &lkb); @@ -2494,7 +2284,7 @@ int dlm_lock(dlm_lockspace_t *lockspace, if (error) goto out; - error = set_lock_args(mode, lksb, flags, namelen, 0, ast, + error = set_lock_args(mode, lksb, flags, namelen, parent_lkid, ast, astarg, bast, &args); if (error) goto out_put; @@ -2509,10 +2299,10 @@ int dlm_lock(dlm_lockspace_t *lockspace, out_put: if (convert || error) __put_lkb(ls, lkb); - if (error == -EAGAIN || error == -EDEADLK) + if (error == -EAGAIN) error = 0; out: - dlm_unlock_recovery(ls); + unlock_recovery(ls); dlm_put_lockspace(ls); return error; } @@ -2532,7 +2322,7 @@ int dlm_unlock(dlm_lockspace_t *lockspace, if (!ls) return -EINVAL; - dlm_lock_recovery(ls); + lock_recovery(ls); error = find_lkb(ls, lkid, &lkb); if (error) @@ -2554,7 +2344,7 @@ int dlm_unlock(dlm_lockspace_t *lockspace, out_put: dlm_put_lkb(lkb); out: - dlm_unlock_recovery(ls); + unlock_recovery(ls); dlm_put_lockspace(ls); return error; } @@ -2594,7 +2384,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, ls->ls_allocation, &mb); + mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_KERNEL, &mb); if (!mh) return -ENOBUFS; @@ -3321,10 +3111,9 @@ 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); - add_timeout(lkb); - } else { + else { grant_lock_pc(r, lkb, ms); queue_cast(r, lkb, 0); } @@ -3383,12 +3172,6 @@ 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); @@ -3396,7 +3179,6 @@ 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: @@ -3516,7 +3298,8 @@ 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); - queue_cast(r, lkb, -DLM_ECANCEL); + if (ms->m_result) + queue_cast(r, lkb, -DLM_ECANCEL); break; case 0: break; @@ -3641,7 +3424,7 @@ int dlm_receive_message(struct dlm_header *hd, int nodeid, int recovery) } } - if (dlm_lock_recovery_try(ls)) + if (lock_recovery_try(ls)) break; schedule(); } @@ -3720,7 +3503,7 @@ int dlm_receive_message(struct dlm_header *hd, int nodeid, int recovery) log_error(ls, "unknown message type %d", ms->m_type); } - dlm_unlock_recovery(ls); + unlock_recovery(ls); out: dlm_put_lockspace(ls); dlm_astd_wake(); @@ -4251,13 +4034,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, - unsigned long timeout_cs) + uint32_t parent_lkid) { struct dlm_lkb *lkb; struct dlm_args args; int error; - dlm_lock_recovery(ls); + lock_recovery(ls); error = create_lkb(ls, &lkb); if (error) { @@ -4279,7 +4062,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, timeout_cs, + error = set_lock_args(mode, &ua->lksb, flags, namelen, parent_lkid, DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args); lkb->lkb_flags |= DLM_IFL_USER; ua->old_mode = DLM_LOCK_IV; @@ -4311,20 +4094,19 @@ 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: - dlm_unlock_recovery(ls); + 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, - unsigned long timeout_cs) + int mode, uint32_t flags, uint32_t lkid, char *lvb_in) { struct dlm_lkb *lkb; struct dlm_args args; struct dlm_user_args *ua; int error; - dlm_lock_recovery(ls); + lock_recovery(ls); error = find_lkb(ls, lkid, &lkb); if (error) @@ -4345,7 +4127,6 @@ 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; @@ -4353,19 +4134,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, timeout_cs, - DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args); + error = set_lock_args(mode, &ua->lksb, flags, 0, 0, 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 || error == -EDEADLK) + if (error == -EINPROGRESS || error == -EAGAIN) error = 0; out_put: dlm_put_lkb(lkb); out: - dlm_unlock_recovery(ls); + unlock_recovery(ls); kfree(ua_tmp); return error; } @@ -4378,7 +4159,7 @@ int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, struct dlm_user_args *ua; int error; - dlm_lock_recovery(ls); + lock_recovery(ls); error = find_lkb(ls, lkid, &lkb); if (error) @@ -4413,7 +4194,7 @@ int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, out_put: dlm_put_lkb(lkb); out: - dlm_unlock_recovery(ls); + unlock_recovery(ls); kfree(ua_tmp); return error; } @@ -4426,7 +4207,7 @@ int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, struct dlm_user_args *ua; int error; - dlm_lock_recovery(ls); + lock_recovery(ls); error = find_lkb(ls, lkid, &lkb); if (error) @@ -4450,59 +4231,11 @@ int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, out_put: dlm_put_lkb(lkb); out: - dlm_unlock_recovery(ls); + 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 */ @@ -4581,13 +4314,12 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc) { struct dlm_lkb *lkb, *safe; - dlm_lock_recovery(ls); + 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 @@ -4615,7 +4347,7 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc) } mutex_unlock(&ls->ls_clear_proc_locks); - dlm_unlock_recovery(ls); + unlock_recovery(ls); } static void purge_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc) @@ -4697,12 +4429,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 { - dlm_lock_recovery(ls); + lock_recovery(ls); if (pid == current->pid) purge_proc_locks(ls, proc); else do_purge(ls, nodeid, pid); - dlm_unlock_recovery(ls); + unlock_recovery(ls); } return error; } diff --git a/trunk/fs/dlm/lock.h b/trunk/fs/dlm/lock.h index 1720313c22df..64fc4ec40668 100644 --- a/trunk/fs/dlm/lock.h +++ b/trunk/fs/dlm/lock.h @@ -1,7 +1,7 @@ /****************************************************************************** ******************************************************************************* ** -** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved. +** Copyright (C) 2005 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,10 +24,6 @@ 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); @@ -38,18 +34,15 @@ 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, - unsigned long timeout_cs); + uint32_t flags, void *name, unsigned int namelen, uint32_t parent_lkid); 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, - unsigned long timeout_cs); + int mode, uint32_t flags, uint32_t lkid, char *lvb_in); 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/trunk/fs/dlm/lockspace.c b/trunk/fs/dlm/lockspace.c index 1dc72105ab12..a677b2a5eed4 100644 --- a/trunk/fs/dlm/lockspace.c +++ b/trunk/fs/dlm/lockspace.c @@ -197,24 +197,13 @@ 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; } @@ -245,13 +234,8 @@ static int dlm_scand(void *data) struct dlm_ls *ls; while (!kthread_should_stop()) { - 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); - } - } + list_for_each_entry(ls, &lslist, ls_list) + dlm_scan_rsbs(ls); schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ); } return 0; @@ -411,7 +395,6 @@ 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; @@ -434,22 +417,11 @@ 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; @@ -489,8 +461,6 @@ 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); @@ -507,8 +477,6 @@ 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); @@ -545,49 +513,32 @@ 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_delist; + goto out_rcomfree; } + dlm_create_debug_file(ls); + error = kobject_setup(ls); if (error) - goto out_stop; + goto out_del; error = kobject_register(&ls->ls_kobj); if (error) - 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(). */ + goto out_del; error = do_uevent(ls, 1); if (error) - 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"); + goto out_unreg; *lockspace = ls; return 0; - out_members: - do_uevent(ls, 0); - dlm_clear_members(ls); - kfree(ls->ls_node_array); - out_stop: + out_unreg: + kobject_unregister(&ls->ls_kobj); + out_del: + dlm_delete_debug_file(ls); dlm_recoverd_stop(ls); - out_delist: + out_rcomfree: spin_lock(&lslist_lock); list_del(&ls->ls_list); spin_unlock(&lslist_lock); @@ -599,10 +550,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace, out_rsbfree: kfree(ls->ls_rsbtbl); out_lsfree: - if (do_unreg) - kobject_unregister(&ls->ls_kobj); - else - kfree(ls); + kfree(ls); out: module_put(THIS_MODULE); return error; @@ -622,8 +570,6 @@ 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; @@ -750,7 +696,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/trunk/fs/dlm/lowcomms.c b/trunk/fs/dlm/lowcomms.c index 0553a6158dcb..27970a58d29b 100644 --- a/trunk/fs/dlm/lowcomms.c +++ b/trunk/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 (con && !test_and_set_bit(CF_READ_PENDING, &con->flags)) + if (!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 (con && !test_and_set_bit(CF_WRITE_PENDING, &con->flags)) + if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags)) queue_work(send_workqueue, &con->swork); } @@ -720,17 +720,11 @@ 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; @@ -1406,11 +1400,8 @@ 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/trunk/fs/dlm/main.c b/trunk/fs/dlm/main.c index eca2907f2386..162fbae58fe5 100644 --- a/trunk/fs/dlm/main.c +++ b/trunk/fs/dlm/main.c @@ -2,7 +2,7 @@ ******************************************************************************* ** ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. -** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. +** Copyright (C) 2004-2005 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,8 +25,6 @@ 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) { @@ -52,16 +50,10 @@ 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: @@ -76,7 +68,6 @@ 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/trunk/fs/dlm/member.c b/trunk/fs/dlm/member.c index 073599dced2a..85e2897bd740 100644 --- a/trunk/fs/dlm/member.c +++ b/trunk/fs/dlm/member.c @@ -1,7 +1,7 @@ /****************************************************************************** ******************************************************************************* ** -** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved. +** Copyright (C) 2005 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,12 +233,6 @@ 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; @@ -290,9 +284,6 @@ 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/trunk/fs/dlm/netlink.c b/trunk/fs/dlm/netlink.c deleted file mode 100644 index 863b87d0dc71..000000000000 --- a/trunk/fs/dlm/netlink.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * 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 -#include -#include - -#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/trunk/fs/dlm/rcom.c b/trunk/fs/dlm/rcom.c index e3a1527cbdbe..6bfbd6153809 100644 --- a/trunk/fs/dlm/rcom.c +++ b/trunk/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, ls->ls_allocation, &mb); + mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_KERNEL, &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 -EPROTO; + return -EINVAL; } 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 -EPROTO; + return -EINVAL; } return 0; } @@ -386,8 +386,7 @@ 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(struct dlm_ls *ls, int nodeid, - struct dlm_rcom *rc_in) +static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in) { struct dlm_rcom *rc; struct rcom_config *rf; @@ -395,7 +394,7 @@ static int send_ls_not_ready(struct dlm_ls *ls, int nodeid, char *mb; int mb_len = sizeof(struct dlm_rcom) + sizeof(struct rcom_config); - mh = dlm_lowcomms_get_buffer(nodeid, mb_len, ls->ls_allocation, &mb); + mh = dlm_lowcomms_get_buffer(nodeid, mb_len, GFP_KERNEL, &mb); if (!mh) return -ENOBUFS; memset(mb, 0, mb_len); @@ -465,7 +464,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(ls, nodeid, rc); + send_ls_not_ready(nodeid, rc); return; } diff --git a/trunk/fs/dlm/recoverd.c b/trunk/fs/dlm/recoverd.c index 66575997861c..3cb636d60249 100644 --- a/trunk/fs/dlm/recoverd.c +++ b/trunk/fs/dlm/recoverd.c @@ -2,7 +2,7 @@ ******************************************************************************* ** ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. -** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. +** Copyright (C) 2004-2005 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,8 +190,6 @@ 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/trunk/fs/dlm/user.c b/trunk/fs/dlm/user.c index 6438941ab1f8..b0201ec325a7 100644 --- a/trunk/fs/dlm/user.c +++ b/trunk/fs/dlm/user.c @@ -33,17 +33,16 @@ static const struct file_operations device_fops; struct dlm_lock_params32 { __u8 mode; __u8 namelen; - __u16 unused; - __u32 flags; + __u16 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]; }; @@ -69,7 +68,6 @@ struct dlm_lksb32 { }; struct dlm_lock_result32 { - __u32 version[3]; __u32 length; __u32 user_astaddr; __u32 user_astparam; @@ -104,8 +102,6 @@ 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; @@ -119,10 +115,6 @@ 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; @@ -138,36 +130,6 @@ 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 */ @@ -214,7 +176,25 @@ 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); - eol = lkb_is_endoflife(lkb, ua->lksb.sb_status, type); + /* 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; if (eol) { lkb->lkb_ast_type &= ~AST_BAST; lkb->lkb_flags |= DLM_IFL_ENDOFLIFE; @@ -272,18 +252,16 @@ 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, - (unsigned long) params->timeout); + params->lkid, params->lvb); else { error = dlm_user_request(ls, ua, params->mode, params->flags, params->name, params->namelen, - (unsigned long) params->timeout); + params->parent); if (!error) error = ua->lksb.sb_lkid; } @@ -321,22 +299,6 @@ 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; @@ -386,7 +348,7 @@ static int device_create_lockspace(struct dlm_lspace_params *params) return -EPERM; error = dlm_new_lockspace(params->name, strlen(params->name), - &lockspace, params->flags, DLM_USER_LVB_LEN); + &lockspace, 0, DLM_USER_LVB_LEN); if (error) return error; @@ -562,14 +524,6 @@ 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"); @@ -687,9 +641,6 @@ 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; @@ -748,20 +699,6 @@ 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, @@ -773,16 +710,6 @@ 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 @@ -820,6 +747,11 @@ 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 */ @@ -891,7 +823,6 @@ 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/trunk/fs/ecryptfs/file.c b/trunk/fs/ecryptfs/file.c index 94f456fe4d9b..59288d817078 100644 --- a/trunk/fs/ecryptfs/file.c +++ b/trunk/fs/ecryptfs/file.c @@ -338,17 +338,16 @@ static int ecryptfs_fasync(int fd, struct file *file, int flag) return rc; } -static ssize_t ecryptfs_splice_read(struct file *file, loff_t * ppos, - struct pipe_inode_info *pipe, size_t count, - unsigned int flags) +static ssize_t ecryptfs_sendfile(struct file *file, loff_t * ppos, + size_t count, read_actor_t actor, void *target) { struct file *lower_file = NULL; int rc = -EINVAL; lower_file = ecryptfs_file_to_lower(file); - if (lower_file->f_op && lower_file->f_op->splice_read) - rc = lower_file->f_op->splice_read(lower_file, ppos, pipe, - count, flags); + if (lower_file->f_op && lower_file->f_op->sendfile) + rc = lower_file->f_op->sendfile(lower_file, ppos, count, + actor, target); return rc; } @@ -365,7 +364,7 @@ const struct file_operations ecryptfs_dir_fops = { .release = ecryptfs_release, .fsync = ecryptfs_fsync, .fasync = ecryptfs_fasync, - .splice_read = ecryptfs_splice_read, + .sendfile = ecryptfs_sendfile, }; const struct file_operations ecryptfs_main_fops = { @@ -382,7 +381,7 @@ const struct file_operations ecryptfs_main_fops = { .release = ecryptfs_release, .fsync = ecryptfs_fsync, .fasync = ecryptfs_fasync, - .splice_read = ecryptfs_splice_read, + .sendfile = ecryptfs_sendfile, }; static int diff --git a/trunk/fs/ext2/file.c b/trunk/fs/ext2/file.c index 04afeecaaef3..566d4e2d3852 100644 --- a/trunk/fs/ext2/file.c +++ b/trunk/fs/ext2/file.c @@ -53,6 +53,7 @@ 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, }; @@ -70,6 +71,7 @@ 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/trunk/fs/ext3/file.c b/trunk/fs/ext3/file.c index acc4913d3019..1e6f13864536 100644 --- a/trunk/fs/ext3/file.c +++ b/trunk/fs/ext3/file.c @@ -120,6 +120,7 @@ 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/trunk/fs/ext4/file.c b/trunk/fs/ext4/file.c index d4c8186aed64..3c6c1fd2be90 100644 --- a/trunk/fs/ext4/file.c +++ b/trunk/fs/ext4/file.c @@ -120,6 +120,7 @@ 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/trunk/fs/fat/file.c b/trunk/fs/fat/file.c index 69a83b59dce8..55d3c7461c5b 100644 --- a/trunk/fs/fat/file.c +++ b/trunk/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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, }; static int fat_cont_expand(struct inode *inode, loff_t size) diff --git a/trunk/fs/fuse/file.c b/trunk/fs/fuse/file.c index f79de7c8cdfa..adf7995232b8 100644 --- a/trunk/fs/fuse/file.c +++ b/trunk/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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, }; 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 splice_read */ + /* no mmap and sendfile */ }; static const struct address_space_operations fuse_file_aops = { diff --git a/trunk/fs/gfs2/Makefile b/trunk/fs/gfs2/Makefile index 04ad0caebedb..e3f1ada643ac 100644 --- a/trunk/fs/gfs2/Makefile +++ b/trunk/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 ops_address.o ops_dentry.o ops_export.o ops_file.o \ + mount.o ondisk.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/trunk/fs/gfs2/bmap.c b/trunk/fs/gfs2/bmap.c index cd805a66880d..c53a5d2d0590 100644 --- a/trunk/fs/gfs2/bmap.c +++ b/trunk/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_length; + rg_blocks += rgd->rd_ri.ri_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; + ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; 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_length + + sdp->sd_max_height + al->al_rgd->rd_ri.ri_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; + ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; error = gfs2_meta_inode_buffer(ip, &dibh); if (error) @@ -885,6 +885,7 @@ 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); @@ -927,13 +928,15 @@ 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); - zero_user_page(page, offset, length, KM_USER0); + kaddr = kmap_atomic(page, KM_USER0); + memset(kaddr + offset, 0, length); + flush_dcache_page(page); + kunmap_atomic(kaddr, KM_USER0); unlock: unlock_page(page); @@ -959,7 +962,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; + ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; 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); @@ -971,7 +974,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; + ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; 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); @@ -1041,10 +1044,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_no_addr; + ip->i_num.no_addr; gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); } - ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; + ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; ip->i_di.di_flags &= ~GFS2_DIF_TRUNC_IN_PROG; gfs2_trans_add_bh(ip->i_gl, dibh, 1); diff --git a/trunk/fs/gfs2/daemon.c b/trunk/fs/gfs2/daemon.c index 3548d9f31e0d..683cb5bda870 100644 --- a/trunk/fs/gfs2/daemon.c +++ b/trunk/fs/gfs2/daemon.c @@ -16,7 +16,6 @@ #include #include #include -#include #include "gfs2.h" #include "incore.h" @@ -50,8 +49,6 @@ 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); } @@ -77,8 +74,6 @@ 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; @@ -98,8 +93,6 @@ 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); } @@ -148,8 +141,6 @@ int gfs2_logd(void *data) } t = gfs2_tune_get(sdp, gt_logd_secs) * HZ; - if (freezing(current)) - refrigerator(); schedule_timeout_interruptible(t); } @@ -200,8 +191,6 @@ 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/trunk/fs/gfs2/dir.c b/trunk/fs/gfs2/dir.c index 2beb2f401aa2..a96fa07b3f3b 100644 --- a/trunk/fs/gfs2/dir.c +++ b/trunk/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; + ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -228,7 +228,7 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf, 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; + ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; 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_no_addr, + (unsigned long long)dip->i_num.no_addr, dip->i_di.di_entries, g.offset); error = -EIO; @@ -1488,55 +1488,24 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, * Returns: errno */ -struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name) +int gfs2_dir_search(struct inode *dir, const struct qstr *name, + struct gfs2_inum_host *inum, unsigned int *type) { 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 (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: + if (inum) + gfs2_inum_in(inum, (char *)&dent->de_inum); + if (type) + *type = be16_to_cpu(dent->de_type); brelse(bh); + return 0; } - return ret; + return -ENOENT; } static int dir_new_leaf(struct inode *inode, const struct qstr *name) @@ -1596,7 +1565,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_inode *nip, unsigned type) + const struct gfs2_inum_host *inum, unsigned type) { struct gfs2_inode *ip = GFS2_I(inode); struct buffer_head *bh; @@ -1611,7 +1580,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(nip, dent); + gfs2_inum_out(inum, (char *)&dent->de_inum); dent->de_type = cpu_to_be16(type); if (ip->i_di.di_flags & GFS2_DIF_EXHASH) { leaf = (struct gfs2_leaf *)bh->b_data; @@ -1623,7 +1592,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; + ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC; gfs2_dinode_out(ip, bh->b_data); brelse(bh); error = 0; @@ -1709,7 +1678,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; + dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC; gfs2_dinode_out(dip, bh->b_data); brelse(bh); mark_inode_dirty(&dip->i_inode); @@ -1731,7 +1700,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, - const struct gfs2_inode *nip, unsigned int new_type) + struct gfs2_inum_host *inum, unsigned int new_type) { struct buffer_head *bh; struct gfs2_dirent *dent; @@ -1746,7 +1715,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(nip, dent); + gfs2_inum_out(inum, (char *)&dent->de_inum); dent->de_type = cpu_to_be16(new_type); if (dip->i_di.di_flags & GFS2_DIF_EXHASH) { @@ -1757,7 +1726,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; + dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC; gfs2_dinode_out(dip, bh->b_data); brelse(bh); return 0; @@ -1898,7 +1867,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_length; + rg_blocks += rgd->rd_ri.ri_length; } error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs); diff --git a/trunk/fs/gfs2/dir.h b/trunk/fs/gfs2/dir.h index 8a468cac9328..48fe89046bba 100644 --- a/trunk/fs/gfs2/dir.h +++ b/trunk/fs/gfs2/dir.h @@ -16,16 +16,15 @@ struct inode; struct gfs2_inode; struct gfs2_inum; -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_search(struct inode *dir, const struct qstr *filename, + struct gfs2_inum_host *inum, unsigned int *type); int gfs2_dir_add(struct inode *inode, const struct qstr *filename, - const struct gfs2_inode *ip, unsigned int type); + const struct gfs2_inum_host *inum, 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, - const struct gfs2_inode *nip, unsigned int new_type); + struct gfs2_inum_host *new_inum, unsigned int new_type); int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip); diff --git a/trunk/fs/gfs2/eattr.c b/trunk/fs/gfs2/eattr.c index 2a7435b5c4dc..5b83ca6acab1 100644 --- a/trunk/fs/gfs2/eattr.c +++ b/trunk/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_length + RES_DINODE + + error = gfs2_trans_begin(sdp, rgd->rd_ri.ri_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; + ip->i_inode.i_ctime = CURRENT_TIME_SEC; 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_length + + blks + al->al_rgd->rd_ri.ri_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; + ip->i_inode.i_ctime = CURRENT_TIME_SEC; 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; + ip->i_inode.i_ctime = CURRENT_TIME_SEC; 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; + ip->i_inode.i_ctime = CURRENT_TIME_SEC; 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_length; + rg_blocks += rgd->rd_ri.ri_length; } error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs); diff --git a/trunk/fs/gfs2/glock.c b/trunk/fs/gfs2/glock.c index 3f0974e1afef..1815429a2978 100644 --- a/trunk/fs/gfs2/glock.c +++ b/trunk/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__after_clear_bit(); + smp_mb(); wake_up_bit(&gh->gh_iflags, HIF_WAIT); } -static int just_schedule(void *word) +static int holder_wait(void *word) { schedule(); return 0; @@ -435,20 +435,7 @@ static int just_schedule(void *word) static void wait_on_holder(struct gfs2_holder *gh) { might_sleep(); - 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); + wait_on_bit(&gh->gh_iflags, HIF_WAIT, holder_wait, TASK_UNINTERRUPTIBLE); } /** @@ -541,7 +528,7 @@ static int rq_demote(struct gfs2_glock *gl) if (gl->gl_state == gl->gl_demote_state || gl->gl_state == LM_ST_UNLOCKED) { - gfs2_demote_wake(gl); + clear_bit(GLF_DEMOTE, &gl->gl_flags); return 0; } set_bit(GLF_LOCK, &gl->gl_flags); @@ -679,22 +666,12 @@ 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, int remote) +static void handle_callback(struct gfs2_glock *gl, unsigned int state) { 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; } @@ -763,7 +740,7 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret) if (ret & LM_OUT_CANCELED) op_done = 0; else - gfs2_demote_wake(gl); + clear_bit(GLF_DEMOTE, &gl->gl_flags); } else { spin_lock(&gl->gl_spin); list_del_init(&gh->gh_list); @@ -871,7 +848,7 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret) gfs2_assert_warn(sdp, !ret); state_change(gl, LM_ST_UNLOCKED); - gfs2_demote_wake(gl); + clear_bit(GLF_DEMOTE, &gl->gl_flags); if (glops->go_inval) glops->go_inval(gl, DIO_METADATA); @@ -1197,7 +1174,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, 0); + handle_callback(gl, LM_ST_UNLOCKED); gfs2_glmutex_lock(gl); @@ -1219,13 +1196,6 @@ 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 @@ -1327,6 +1297,10 @@ 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) @@ -1334,28 +1308,62 @@ 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) { - struct gfs2_holder *tmp[4]; - struct gfs2_holder **pph = tmp; + int *e; + unsigned int x; + int borked = 0, serious = 0; int error = 0; - switch(num_gh) { - case 0: + if (!num_gh) return 0; - case 1: + + if (num_gh == 1) { ghs->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC); return gfs2_glock_nq(ghs); - default: - if (num_gh <= 4) + } + + 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; break; - pph = kmalloc(num_gh * sizeof(struct gfs2_holder *), GFP_NOFS); - if (!pph) - return -ENOMEM; + } + } + + 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; + } } - error = nq_m_sync(num_gh, ghs, pph); + 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); + } - if (pph != tmp) - kfree(pph); + kfree(e); return error; } @@ -1448,7 +1456,7 @@ static void blocking_cb(struct gfs2_sbd *sdp, struct lm_lockname *name, if (!gl) return; - handle_callback(gl, state, 1); + handle_callback(gl, state); spin_lock(&gl->gl_spin); run_queue(gl); @@ -1588,7 +1596,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, 0); + handle_callback(gl, LM_ST_UNLOCKED); gfs2_glmutex_unlock(gl); } @@ -1701,7 +1709,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, 0); + handle_callback(gl, LM_ST_UNLOCKED); gfs2_glmutex_unlock(gl); } } @@ -1815,8 +1823,7 @@ static int dump_inode(struct glock_iter *gi, struct gfs2_inode *ip) print_dbg(gi, " Inode:\n"); print_dbg(gi, " num = %llu/%llu\n", - (unsigned long long)ip->i_no_formal_ino, - (unsigned long long)ip->i_no_addr); + ip->i_num.no_formal_ino, ip->i_num.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++) @@ -1902,8 +1909,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, (unsigned long long) - (jiffies - gl->gl_demote_time)*(1000000/HZ)); + gl->gl_demote_state, + (u64)(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/trunk/fs/gfs2/glock.h b/trunk/fs/gfs2/glock.h index 7721ca3fff9e..b3e152db70c8 100644 --- a/trunk/fs/gfs2/glock.h +++ b/trunk/fs/gfs2/glock.h @@ -87,7 +87,6 @@ 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/trunk/fs/gfs2/glops.c b/trunk/fs/gfs2/glops.c index 777ca46010e8..7b82657a9910 100644 --- a/trunk/fs/gfs2/glops.c +++ b/trunk/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/trunk/fs/gfs2/incore.h b/trunk/fs/gfs2/incore.h index 170ba93829c0..d995441373ab 100644 --- a/trunk/fs/gfs2/incore.h +++ b/trunk/fs/gfs2/incore.h @@ -28,14 +28,6 @@ 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. @@ -68,23 +60,12 @@ 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 */ - 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_rindex_host rd_ri; struct gfs2_rgrp_host rd_rg; u64 rd_rg_vn; struct gfs2_bitmap *rd_bits; @@ -95,8 +76,6 @@ 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 { @@ -232,24 +211,10 @@ 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; - u64 i_no_addr; - u64 i_no_formal_ino; + struct gfs2_inum_host i_num; + unsigned long i_flags; /* GIF_... */ struct gfs2_dinode_host i_di; /* To be replaced by ref to block */ @@ -310,6 +275,14 @@ 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; @@ -354,9 +327,7 @@ 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; @@ -383,12 +354,6 @@ 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 @@ -461,28 +426,6 @@ 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; @@ -601,7 +544,6 @@ 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; @@ -610,6 +552,7 @@ 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/trunk/fs/gfs2/inode.c b/trunk/fs/gfs2/inode.c index 34f7bcdea1e9..df0b8b3018b9 100644 --- a/trunk/fs/gfs2/inode.c +++ b/trunk/fs/gfs2/inode.c @@ -38,17 +38,12 @@ #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); - u64 *no_addr = opaque; + struct gfs2_inum_host *inum = opaque; - if (ip->i_no_addr == *no_addr && + if (ip->i_num.no_addr == inum->no_addr && inode->i_private != NULL) return 1; @@ -58,70 +53,37 @@ 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); - u64 *no_addr = opaque; + struct gfs2_inum_host *inum = opaque; - inode->i_ino = (unsigned long)*no_addr; - ip->i_no_addr = *no_addr; + ip->i_num = *inum; + inode->i_ino = inum->no_addr; return 0; } -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) +struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum) { - unsigned long hash = (unsigned long)no_addr; - return iget5_locked(sb, hash, iget_test, iget_set, &no_addr); + return ilookup5(sb, (unsigned long)inum->no_addr, + iget_test, 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) +static struct inode *gfs2_iget(struct super_block *sb, struct gfs2_inum_host *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); + return iget5_locked(sb, (unsigned long)inum->no_addr, + iget_test, iget_set, inum); } /** * gfs2_inode_lookup - Lookup an inode * @sb: The super block - * @no_addr: The inode number + * @inum: 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, - unsigned int type, - u64 no_addr, - u64 no_formal_ino) +struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *inum, unsigned int type) { - struct inode *inode = gfs2_iget(sb, no_addr); + struct inode *inode = gfs2_iget(sb, inum); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_glock *io_gl; int error; @@ -131,15 +93,29 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, if (inode->i_state & I_NEW) { struct gfs2_sbd *sdp = GFS2_SB(inode); + umode_t mode = DT2IF(type); inode->i_private = ip; - ip->i_no_formal_ino = no_formal_ino; + 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; + } - error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl); + error = gfs2_glock_get(sdp, inum->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, no_addr, &gfs2_iopen_glops, CREATE, &io_gl); + error = gfs2_glock_get(sdp, inum->no_addr, &gfs2_iopen_glops, CREATE, &io_gl); if (unlikely(error)) goto fail_put; @@ -147,38 +123,12 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, 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); - - 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); + unlock_new_inode(inode); } -gfs2_nfsbypass: return inode; -fail_glock: - gfs2_glock_dq(&ip->i_iopen_gh); fail_iopen: gfs2_glock_put(io_gl); fail_put: @@ -194,12 +144,14 @@ 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_no_addr != be64_to_cpu(str->di_num.no_addr)) { + if (ip->i_num.no_addr != be64_to_cpu(str->di_num.no_addr)) { if (gfs2_consist_inode(ip)) gfs2_dinode_print(ip); return -EIO; } - ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino); + if (ip->i_num.no_formal_ino != be64_to_cpu(str->di_num.no_formal_ino)) + return -ESTALE; + 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) { @@ -223,11 +175,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 = be32_to_cpu(str->di_atime_nsec); + ip->i_inode.i_atime.tv_nsec = 0; ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime); - ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec); + ip->i_inode.i_mtime.tv_nsec = 0; ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime); - ip->i_inode.i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec); + ip->i_inode.i_ctime.tv_nsec = 0; di->di_goal_meta = be64_to_cpu(str->di_goal_meta); di->di_goal_data = be64_to_cpu(str->di_goal_data); @@ -295,7 +247,7 @@ int gfs2_dinode_dealloc(struct gfs2_inode *ip) if (error) goto out_qs; - rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr); + rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr); if (!rgd) { gfs2_consist_inode(ip); error = -EIO; @@ -362,7 +314,7 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff) else drop_nlink(&ip->i_inode); - ip->i_inode.i_ctime = CURRENT_TIME; + ip->i_inode.i_ctime = CURRENT_TIME_SEC; gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); @@ -414,7 +366,9 @@ 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; - int error = 0; + struct gfs2_inum_host inum; + unsigned int type; + int error; struct inode *inode = NULL; int unlock = 0; @@ -441,9 +395,12 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, goto out; } - inode = gfs2_dir_search(dir, name); - if (IS_ERR(inode)) - error = PTR_ERR(inode); + error = gfs2_dir_search(dir, name, &inum, &type); + if (error) + goto out; + + inode = gfs2_inode_lookup(sb, &inum, type); + out: if (unlock) gfs2_glock_dq_uninit(&d_gh); @@ -452,22 +409,6 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, 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); @@ -607,7 +548,7 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name, if (!dip->i_inode.i_nlink) return -EPERM; - error = gfs2_dir_check(&dip->i_inode, name, NULL); + error = gfs2_dir_search(&dip->i_inode, name, NULL, NULL); switch (error) { case -ENOENT: error = 0; @@ -647,7 +588,8 @@ static void munge_mode_uid_gid(struct gfs2_inode *dip, unsigned int *mode, *gid = current->fsgid; } -static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation) +static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum_host *inum, + u64 *generation) { struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); int error; @@ -663,7 +605,7 @@ static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation) if (error) goto out_ipreserv; - *no_addr = gfs2_alloc_di(dip, generation); + inum->no_addr = gfs2_alloc_di(dip, generation); gfs2_trans_end(sdp); @@ -693,7 +635,6 @@ 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); @@ -709,7 +650,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(tv.tv_sec); + di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(get_seconds()); 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); @@ -739,9 +680,6 @@ 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); @@ -811,7 +749,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_length + + al->al_rgd->rd_ri.ri_length + 2 * RES_DINODE + RES_STATFS + RES_QUOTA, 0); if (error) @@ -822,7 +760,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, IF2DT(ip->i_inode.i_mode)); + error = gfs2_dir_add(&dip->i_inode, name, &ip->i_num, IF2DT(ip->i_inode.i_mode)); if (error) goto fail_end_trans; @@ -902,11 +840,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 = NULL; + struct inode *inode; 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 = { .no_addr = 0, .no_formal_ino = 0 }; + struct gfs2_inum_host inum; int error; u64 generation; @@ -926,7 +864,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, if (error) goto fail_gunlock; - error = alloc_dinode(dip, &inum.no_addr, &generation); + error = alloc_dinode(dip, &inum, &generation); if (error) goto fail_gunlock; @@ -939,36 +877,34 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, if (error) goto fail_gunlock2; - inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode), - inum.no_addr, - inum.no_formal_ino); + inode = gfs2_inode_lookup(dir->i_sb, &inum, IF2DT(mode)); if (IS_ERR(inode)) goto fail_gunlock2; error = gfs2_inode_refresh(GFS2_I(inode)); if (error) - goto fail_gunlock2; + goto fail_iput; error = gfs2_acl_create(dip, GFS2_I(inode)); if (error) - goto fail_gunlock2; + goto fail_iput; error = gfs2_security_init(dip, GFS2_I(inode)); if (error) - goto fail_gunlock2; + goto fail_iput; error = link_dinode(dip, name, GFS2_I(inode)); if (error) - goto fail_gunlock2; + goto fail_iput; 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: @@ -1040,8 +976,10 @@ int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name, */ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, - const struct gfs2_inode *ip) + 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)) @@ -1059,10 +997,18 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, if (error) return error; - error = gfs2_dir_check(&dip->i_inode, name, ip); + error = gfs2_dir_search(&dip->i_inode, name, &inum, &type); 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; } @@ -1186,11 +1132,10 @@ 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 quantum = gfs2_tune_get(sdp, gt_atime_quantum); + s64 curtime, 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)) || @@ -1208,7 +1153,8 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh) (sdp->sd_vfs->s_flags & MS_RDONLY)) return 0; - if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) { + curtime = get_seconds(); + if (curtime - 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); @@ -1219,8 +1165,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. */ - tv = CURRENT_TIME; - if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) { + curtime = get_seconds(); + if (curtime - ip->i_inode.i_atime.tv_sec >= quantum) { struct buffer_head *dibh; struct gfs2_dinode *di; @@ -1234,12 +1180,11 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh) if (error) goto fail_end_trans; - ip->i_inode.i_atime = tv; + ip->i_inode.i_atime.tv_sec = curtime; 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); @@ -1307,66 +1252,3 @@ 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/trunk/fs/gfs2/inode.h b/trunk/fs/gfs2/inode.h index 4517ac82c01c..b57f448b15bc 100644 --- a/trunk/fs/gfs2/inode.h +++ b/trunk/fs/gfs2/inode.h @@ -10,17 +10,17 @@ #ifndef __INODE_DOT_H__ #define __INODE_DOT_H__ -static inline int gfs2_is_stuffed(const struct gfs2_inode *ip) +static inline int gfs2_is_stuffed(struct gfs2_inode *ip) { return !ip->i_di.di_height; } -static inline int gfs2_is_jdata(const struct gfs2_inode *ip) +static inline int gfs2_is_jdata(struct gfs2_inode *ip) { return ip->i_di.di_flags & GFS2_DIF_JDATA; } -static inline int gfs2_is_dir(const struct gfs2_inode *ip) +static inline int gfs2_is_dir(struct gfs2_inode *ip) { return S_ISDIR(ip->i_inode.i_mode); } @@ -32,25 +32,9 @@ 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); -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); +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); int gfs2_inode_refresh(struct gfs2_inode *ip); @@ -63,14 +47,12 @@ 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, - const struct gfs2_inode *ip); + 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/trunk/fs/gfs2/locking/dlm/lock.c b/trunk/fs/gfs2/locking/dlm/lock.c index 542a797ac89a..c305255bfe8a 100644 --- a/trunk/fs/gfs2/locking/dlm/lock.c +++ b/trunk/fs/gfs2/locking/dlm/lock.c @@ -174,6 +174,7 @@ 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); @@ -398,12 +399,6 @@ 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). */ @@ -429,10 +424,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_on_bit(&lpn->flags, LFL_AST_WAIT, gdlm_ast_wait, TASK_UNINTERRUPTIBLE); + wait_for_completion(&lpn->ast_wait); error = lpn->lksb.sb_status; if (error) { printk(KERN_INFO "lock_dlm: hold_null_lock dlm error %d\n", diff --git a/trunk/fs/gfs2/locking/dlm/lock_dlm.h b/trunk/fs/gfs2/locking/dlm/lock_dlm.h index 24d70f73b651..d074c6e6f9bf 100644 --- a/trunk/fs/gfs2/locking/dlm/lock_dlm.h +++ b/trunk/fs/gfs2/locking/dlm/lock_dlm.h @@ -101,7 +101,6 @@ enum { LFL_NOBAST = 10, LFL_HEADQUE = 11, LFL_UNLOCK_DELETE = 12, - LFL_AST_WAIT = 13, }; struct gdlm_lock { @@ -118,6 +117,7 @@ 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/trunk/fs/gfs2/locking/dlm/mount.c b/trunk/fs/gfs2/locking/dlm/mount.c index 41c5b04caaba..1d8faa3da8af 100644 --- a/trunk/fs/gfs2/locking/dlm/mount.c +++ b/trunk/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, - DLM_LSFL_FS | (nodir ? DLM_LSFL_NODIR : 0), + nodir ? DLM_LSFL_NODIR : 0, GDLM_LVB_SIZE); if (error) { log_error("dlm_new_lockspace error %d", error); diff --git a/trunk/fs/gfs2/locking/dlm/plock.c b/trunk/fs/gfs2/locking/dlm/plock.c index fba1f1d87e4f..f82495e18c2d 100644 --- a/trunk/fs/gfs2/locking/dlm/plock.c +++ b/trunk/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,20 +254,16 @@ 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) { + else if (rv == 0 && op->info.pid != fl->fl_pid) { 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/trunk/fs/gfs2/locking/dlm/thread.c b/trunk/fs/gfs2/locking/dlm/thread.c index 1aca51e45092..9cf1f168eaf8 100644 --- a/trunk/fs/gfs2/locking/dlm/thread.c +++ b/trunk/fs/gfs2/locking/dlm/thread.c @@ -44,13 +44,6 @@ 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; @@ -143,7 +136,7 @@ static void process_complete(struct gdlm_lock *lp) */ if (test_and_clear_bit(LFL_SYNC_LVB, &lp->flags)) { - wake_up_ast(lp); + complete(&lp->ast_wait); return; } @@ -221,7 +214,7 @@ static void process_complete(struct gdlm_lock *lp) if (test_bit(LFL_INLOCK, &lp->flags)) { clear_bit(LFL_NOBLOCK, &lp->flags); lp->cur = lp->req; - wake_up_ast(lp); + complete(&lp->ast_wait); return; } diff --git a/trunk/fs/gfs2/log.c b/trunk/fs/gfs2/log.c index f49a12e24086..291415ddfe51 100644 --- a/trunk/fs/gfs2/log.c +++ b/trunk/fs/gfs2/log.c @@ -83,11 +83,6 @@ 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); @@ -130,11 +125,6 @@ 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)) { @@ -272,8 +262,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 few blocks of the journal. Thats - * due to the fact that there is a small number of header blocks + * 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 * 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. @@ -284,7 +274,6 @@ 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)) @@ -292,7 +281,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 + reserved_blks)) { + while(sdp->sd_log_blks_free <= (blks + 6)) { gfs2_log_unlock(sdp); gfs2_ail1_empty(sdp, 0); gfs2_log_flush(sdp, NULL); @@ -368,58 +357,6 @@ 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; @@ -510,14 +447,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) +static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail, int pull) { 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; + sdp->sd_log_blks_free += dist - (pull ? 1 : 0); gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks); gfs2_log_unlock(sdp); @@ -567,7 +504,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); + log_pull_tail(sdp, tail, pull); else gfs2_assert_withdraw(sdp, !pull); @@ -580,7 +517,6 @@ 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); @@ -597,20 +533,9 @@ static void log_flush_commit(struct gfs2_sbd *sdp) } else brelse(bh); kfree(lb); - flushcount++; } - /* 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); - } + log_write_header(sdp, 0, 0); } /** @@ -640,10 +565,7 @@ 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_num_jdata == - sdp->sd_log_commited_buf + - sdp->sd_log_commited_databuf); + gfs2_assert_withdraw(sdp, sdp->sd_log_num_buf == sdp->sd_log_commited_buf); gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke); @@ -654,19 +576,16 @@ 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){ - gfs2_log_lock(sdp); - sdp->sd_log_blks_free--; /* Adjust for unreserved buffer */ - gfs2_log_unlock(sdp); + else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle) 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_commited_databuf = 0; + sdp->sd_log_num_hdrs = 0; sdp->sd_log_commited_revoke = 0; if (!list_empty(&ai->ai_ail1_list)) { @@ -683,26 +602,32 @@ 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; + unsigned int reserved = 0; unsigned int old; gfs2_log_lock(sdp); sdp->sd_log_commited_buf += tr->tr_num_buf_new - tr->tr_num_buf_rm; - 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)); + gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_buf) >= 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); - reserved = calc_reserved(sdp); + + 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++; + 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); + gfs2_assert_withdraw(sdp, + sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks + + sdp->sd_log_num_hdrs); sdp->sd_log_blks_reserved = reserved; @@ -748,13 +673,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, - (sdp->sd_log_tail == current_tail(sdp)) ? 0 : PULL); + log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT, 0); 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/trunk/fs/gfs2/lops.c b/trunk/fs/gfs2/lops.c index aff70f0698fd..f82d84d05d23 100644 --- a/trunk/fs/gfs2/lops.c +++ b/trunk/fs/gfs2/lops.c @@ -17,7 +17,6 @@ #include "gfs2.h" #include "incore.h" -#include "inode.h" #include "glock.h" #include "log.h" #include "lops.h" @@ -118,13 +117,15 @@ 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 = BUF_OFFSET; + unsigned int offset = sizeof(struct gfs2_log_descriptor); unsigned int limit; unsigned int num; unsigned n; __be64 *ptr; - limit = buf_limit(sdp); + offset += sizeof(__be64) - 1; + offset &= ~(sizeof(__be64) - 1); + limit = (sdp->sd_sb.sb_bsize - offset)/sizeof(__be64); /* for 4k blocks, limit = 503 */ bd1 = bd2 = list_prepare_entry(bd1, &sdp->sd_log_le_buf, bd_le.le_list); @@ -133,6 +134,7 @@ 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); @@ -467,28 +469,25 @@ 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 (gfs2_is_jdata(ip)) { + if (list_empty(&bd->bd_list_tr) && + (ip->i_di.di_flags & GFS2_DIF_JDATA)) { tr->tr_num_buf++; list_add(&bd->bd_list_tr, &tr->tr_list_buf); - } - gfs2_log_unlock(sdp); - if (!list_empty(&le->le_list)) - return; - - gfs2_trans_add_gl(bd->bd_gl); - if (gfs2_is_jdata(ip)) { - sdp->sd_log_num_jdata++; + gfs2_log_unlock(sdp); gfs2_pin(sdp, bd->bd_bh); - tr->tr_num_databuf_new++; + tr->tr_num_buf_new++; + } else { + gfs2_log_unlock(sdp); } - sdp->sd_log_num_databuf++; + gfs2_trans_add_gl(bd->bd_gl); gfs2_log_lock(sdp); - list_add(&le->le_list, &sdp->sd_log_le_databuf); + 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); + } gfs2_log_unlock(sdp); } @@ -521,6 +520,7 @@ 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,7 +528,9 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp) unsigned int num, n; __be64 *ptr = NULL; - limit = databuf_limit(sdp); + offset += 2*sizeof(__be64) - 1; + offset &= ~(2*sizeof(__be64) - 1); + limit = (sdp->sd_sb.sb_bsize - offset)/sizeof(__be64); /* * Start writing ordered buffers, write journaled buffers @@ -579,10 +581,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 + - DATABUF_OFFSET); + ptr = (__be64 *)(bh->b_data + offset); ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC); ld->ld_header.mh_type = @@ -603,7 +605,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--; @@ -620,7 +622,6 @@ 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/trunk/fs/gfs2/lops.h b/trunk/fs/gfs2/lops.h index 41a00df75587..965bc65c7c64 100644 --- a/trunk/fs/gfs2/lops.h +++ b/trunk/fs/gfs2/lops.h @@ -13,13 +13,6 @@ #include #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; @@ -28,22 +21,6 @@ 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/trunk/fs/gfs2/meta_io.c b/trunk/fs/gfs2/meta_io.c index 8da343b34ae7..e62d4f620c58 100644 --- a/trunk/fs/gfs2/meta_io.c +++ b/trunk/fs/gfs2/meta_io.c @@ -387,18 +387,12 @@ 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); - if (bh_ip->i_inode.i_private != NULL) - tr->tr_num_databuf_rm++; - else - tr->tr_num_buf_rm++; + tr->tr_num_buf_rm++; brelse(bh); } if (bd) { diff --git a/trunk/fs/gfs2/meta_io.h b/trunk/fs/gfs2/meta_io.h index 527bf19d9690..e037425bc042 100644 --- a/trunk/fs/gfs2/meta_io.h +++ b/trunk/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_no_addr, 0, bhp); + return gfs2_meta_indirect_buffer(ip, 0, ip->i_num.no_addr, 0, bhp); } struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen); diff --git a/trunk/fs/gfs2/mount.c b/trunk/fs/gfs2/mount.c index 6f006a804db3..4864659555d4 100644 --- a/trunk/fs/gfs2/mount.c +++ b/trunk/fs/gfs2/mount.c @@ -82,19 +82,20 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount) char *options, *o, *v; int error = 0; - /* 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); + 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 */ - 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; + /* Set some defaults */ + 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/trunk/fs/gfs2/ondisk.c b/trunk/fs/gfs2/ondisk.c new file mode 100644 index 000000000000..d9ecfd23a49e --- /dev/null +++ b/trunk/fs/gfs2/ondisk.c @@ -0,0 +1,251 @@ +/* + * 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 +#include +#include +#include + +#include "gfs2.h" +#include +#include +#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/trunk/fs/gfs2/ops_address.c b/trunk/fs/gfs2/ops_address.c index 26c888890c24..30c15622174f 100644 --- a/trunk/fs/gfs2/ops_address.c +++ b/trunk/fs/gfs2/ops_address.c @@ -1,6 +1,6 @@ /* * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. - * Copyright (C) 2004-2007 Red Hat, Inc. 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 @@ -32,7 +32,6 @@ #include "trans.h" #include "rgrp.h" #include "ops_file.h" -#include "super.h" #include "util.h" #include "glops.h" @@ -50,8 +49,6 @@ 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); } } @@ -137,9 +134,7 @@ 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)) && - PageChecked(page)) { - ClearPageChecked(page); + if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) { error = gfs2_trans_begin(sdp, RES_DINODE + 1, 0); if (error) goto out_ignore; @@ -208,7 +203,11 @@ 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)) { - zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0); + kaddr = kmap_atomic(page, KM_USER0); + memset(kaddr, 0, PAGE_CACHE_SIZE); + kunmap_atomic(kaddr, KM_USER0); + flush_dcache_page(page); + SetPageUptodate(page); return 0; } @@ -450,31 +449,6 @@ static int gfs2_prepare_write(struct file *file, struct page *page, return error; } -/** - * 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 @@ -537,9 +511,6 @@ 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) { @@ -571,23 +542,6 @@ static int gfs2_commit_write(struct file *file, struct page *page, return error; } -/** - * 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 @@ -624,8 +578,6 @@ 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); @@ -646,8 +598,6 @@ 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; @@ -778,8 +728,8 @@ static unsigned limit = 0; return; fs_warn(sdp, "ip = %llu %llu\n", - (unsigned long long)ip->i_no_formal_ino, - (unsigned long long)ip->i_no_addr); + (unsigned long long)ip->i_num.no_formal_ino, + (unsigned long long)ip->i_num.no_addr); for (x = 0; x < GFS2_MAX_META_HEIGHT; x++) fs_warn(sdp, "ip->i_cache[%u] = %s\n", @@ -860,7 +810,6 @@ 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/trunk/fs/gfs2/ops_address.h b/trunk/fs/gfs2/ops_address.h index fa1b5b3d28b9..35aaee4aa7e1 100644 --- a/trunk/fs/gfs2/ops_address.h +++ b/trunk/fs/gfs2/ops_address.h @@ -1,6 +1,6 @@ /* * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. - * Copyright (C) 2004-2007 Red Hat, Inc. 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 diff --git a/trunk/fs/gfs2/ops_dentry.c b/trunk/fs/gfs2/ops_dentry.c index 793e334d098e..a6fdc52f554a 100644 --- a/trunk/fs/gfs2/ops_dentry.c +++ b/trunk/fs/gfs2/ops_dentry.c @@ -21,7 +21,6 @@ #include "glock.h" #include "ops_dentry.h" #include "util.h" -#include "inode.h" /** * gfs2_drevalidate - Check directory lookup consistency @@ -41,15 +40,14 @@ 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 = NULL; + struct gfs2_inode *ip; + struct gfs2_inum_host inum; + unsigned int type; int error; int had_lock=0; - if (inode) { - if (is_bad_inode(inode)) - goto invalid; - ip = GFS2_I(inode); - } + if (inode && is_bad_inode(inode)) + goto invalid; if (sdp->sd_args.ar_localcaching) goto valid; @@ -61,7 +59,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) goto fail; } - error = gfs2_dir_check(parent->d_inode, &dentry->d_name, ip); + error = gfs2_dir_search(parent->d_inode, &dentry->d_name, &inum, &type); switch (error) { case 0: if (!inode) @@ -75,6 +73,16 @@ 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/trunk/fs/gfs2/ops_export.c b/trunk/fs/gfs2/ops_export.c index 99ea5659bc2c..aad918337a46 100644 --- a/trunk/fs/gfs2/ops_export.c +++ b/trunk/fs/gfs2/ops_export.c @@ -22,14 +22,10 @@ #include "glops.h" #include "inode.h" #include "ops_dentry.h" -#include "ops_fstype.h" +#include "ops_export.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, @@ -39,28 +35,31 @@ static struct dentry *gfs2_decode_fh(struct super_block *sb, void *context) { __be32 *fh = (__force __be32 *)p; - struct gfs2_inum_host inum, parent; + struct gfs2_fh_obj fh_obj; + struct gfs2_inum_host *this, 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: - 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]); + 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]); break; default: return NULL; } - return gfs2_export_ops.find_exported_dentry(sb, &inum, &parent, + return gfs2_export_ops.find_exported_dentry(sb, &fh_obj, &parent, acceptable, context); } @@ -76,10 +75,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_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); + 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); *len = GFS2_SMALL_FH_SIZE; if (!connectable || inode == sb->s_root->d_inode) @@ -91,10 +90,13 @@ 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_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); + 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 */ *len = GFS2_LARGE_FH_SIZE; iput(inode); @@ -142,8 +144,7 @@ static int gfs2_get_name(struct dentry *parent, char *name, ip = GFS2_I(inode); *name = 0; - gnfd.inum.no_addr = ip->i_no_addr; - gnfd.inum.no_formal_ino = ip->i_no_formal_ino; + gnfd.inum = ip->i_num; gnfd.name = name; error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh); @@ -191,7 +192,8 @@ 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_inum_host *inum = inum_obj; + struct gfs2_fh_obj *fh_obj = (struct gfs2_fh_obj *)inum_obj; + struct gfs2_inum_host *inum = &fh_obj->this; struct gfs2_holder i_gh, ri_gh, rgd_gh; struct gfs2_rgrpd *rgd; struct inode *inode; @@ -200,9 +202,9 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj) /* System files? */ - inode = gfs2_ilookup(sb, inum->no_addr); + inode = gfs2_ilookup(sb, inum); if (inode) { - if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) { + if (GFS2_I(inode)->i_num.no_formal_ino != inum->no_formal_ino) { iput(inode); return ERR_PTR(-ESTALE); } @@ -234,9 +236,7 @@ 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, DT_UNKNOWN, - inum->no_addr, - 0); + inode = gfs2_inode_lookup(sb, inum, fh_obj->imode); if (!inode) goto fail; if (IS_ERR(inode)) { @@ -250,15 +250,6 @@ 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/trunk/fs/gfs2/ops_export.h b/trunk/fs/gfs2/ops_export.h new file mode 100644 index 000000000000..f925a955b3b8 --- /dev/null +++ b/trunk/fs/gfs2/ops_export.h @@ -0,0 +1,22 @@ +/* + * 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/trunk/fs/gfs2/ops_file.c b/trunk/fs/gfs2/ops_file.c index 196d83266e34..064df8804582 100644 --- a/trunk/fs/gfs2/ops_file.c +++ b/trunk/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_no_addr, + { .ln_number = ip->i_num.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_no_addr, &gfs2_flock_glops, + ip->i_num.no_addr, &gfs2_flock_glops, CREATE, &gl); if (error) goto out; @@ -635,6 +635,7 @@ 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/trunk/fs/gfs2/ops_fstype.c b/trunk/fs/gfs2/ops_fstype.c index cf5aa5050548..2c5f8e7def0d 100644 --- a/trunk/fs/gfs2/ops_fstype.c +++ b/trunk/fs/gfs2/ops_fstype.c @@ -27,6 +27,7 @@ #include "inode.h" #include "lm.h" #include "mount.h" +#include "ops_export.h" #include "ops_fstype.h" #include "ops_super.h" #include "recovery.h" @@ -104,7 +105,6 @@ 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,6 +116,7 @@ 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; @@ -125,9 +126,14 @@ static int init_names(struct gfs2_sbd *sdp, int silent) /* Try to autodetect */ if (!proto[0] || !table[0]) { - error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift); - if (error) - return error; + 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_check_sb(sdp, &sdp->sd_sb, silent); if (error) @@ -145,9 +151,6 @@ 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; } @@ -233,17 +236,17 @@ static int init_locking(struct gfs2_sbd *sdp, struct gfs2_holder *mount_gh, return error; } -static inline struct inode *gfs2_lookup_root(struct super_block *sb, - u64 no_addr) +static struct inode *gfs2_lookup_root(struct super_block *sb, + struct gfs2_inum_host *inum) { - return gfs2_inode_lookup(sb, DT_DIR, no_addr, 0); + return gfs2_inode_lookup(sb, inum, DT_DIR); } static int init_sb(struct gfs2_sbd *sdp, int silent, int undo) { struct super_block *sb = sdp->sd_vfs; struct gfs2_holder sb_gh; - u64 no_addr; + struct gfs2_inum_host *inum; struct inode *inode; int error = 0; @@ -286,10 +289,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 */ - no_addr = sdp->sd_sb.sb_root_dir.no_addr; + inum = &sdp->sd_sb.sb_root_dir; if (sb->s_type == &gfs2meta_fs_type) - no_addr = sdp->sd_sb.sb_master_dir.no_addr; - inode = gfs2_lookup_root(sb, no_addr); + inum = &sdp->sd_sb.sb_master_dir; + inode = gfs2_lookup_root(sb, inum); if (IS_ERR(inode)) { error = PTR_ERR(inode); fs_err(sdp, "can't read in root inode: %d\n", error); @@ -446,7 +449,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.no_addr); + inode = gfs2_lookup_root(sdp->sd_vfs, &sdp->sd_sb.sb_master_dir); if (IS_ERR(inode)) { error = PTR_ERR(inode); fs_err(sdp, "can't read in master directory: %d\n", error); diff --git a/trunk/fs/gfs2/ops_fstype.h b/trunk/fs/gfs2/ops_fstype.h index 407029b3b2b3..7cc2c296271b 100644 --- a/trunk/fs/gfs2/ops_fstype.h +++ b/trunk/fs/gfs2/ops_fstype.h @@ -14,6 +14,5 @@ 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/trunk/fs/gfs2/ops_inode.c b/trunk/fs/gfs2/ops_inode.c index 911c115b5c6c..d85f6e05cb95 100644 --- a/trunk/fs/gfs2/ops_inode.c +++ b/trunk/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_check(dir, &dentry->d_name, NULL); + error = gfs2_dir_search(dir, &dentry->d_name, NULL, 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_length + + al->al_rgd->rd_ri.ri_length + 2 * RES_DINODE + RES_STATFS + RES_QUOTA, 0); if (error) @@ -217,7 +217,8 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, goto out_ipres; } - error = gfs2_dir_add(dir, &dentry->d_name, ip, IF2DT(inode->i_mode)); + error = gfs2_dir_add(dir, &dentry->d_name, &ip->i_num, + IF2DT(inode->i_mode)); if (error) goto out_end_trans; @@ -274,7 +275,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_no_addr); + rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr); gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2); @@ -419,7 +420,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, dent); + gfs2_inum_out(&dip->i_num, &dent->de_inum); dent->de_type = cpu_to_be16(DT_DIR); gfs2_dinode_out(ip, di); @@ -471,7 +472,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_no_addr); + rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr); gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2); error = gfs2_glock_nq_m(3, ghs); @@ -613,7 +614,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_no_addr); + nrgd = gfs2_blk2rgrpd(sdp, nip->i_num.no_addr); if (nrgd) gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++); } @@ -652,7 +653,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, if (error) goto out_gunlock; - error = gfs2_dir_check(ndir, &ndentry->d_name, NULL); + error = gfs2_dir_search(ndir, &ndentry->d_name, NULL, NULL); switch (error) { case -ENOENT: error = 0; @@ -711,7 +712,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_length + + al->al_rgd->rd_ri.ri_length + 4 * RES_DINODE + 4 * RES_LEAF + RES_STATFS + RES_QUOTA + 4, 0); if (error) @@ -749,7 +750,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, if (error) goto out_end_trans; - error = gfs2_dir_mvino(ip, &name, ndip, DT_DIR); + error = gfs2_dir_mvino(ip, &name, &ndip->i_num, DT_DIR); if (error) goto out_end_trans; } else { @@ -757,7 +758,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; + ip->i_inode.i_ctime = CURRENT_TIME_SEC; gfs2_trans_add_bh(ip->i_gl, dibh, 1); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -767,7 +768,8 @@ 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, IF2DT(ip->i_inode.i_mode)); + error = gfs2_dir_add(ndir, &ndentry->d_name, &ip->i_num, + IF2DT(ip->i_inode.i_mode)); if (error) goto out_end_trans; @@ -903,8 +905,8 @@ static int setattr_size(struct inode *inode, struct iattr *attr) } error = gfs2_truncatei(ip, attr->ia_size); - if (error && (inode->i_size != ip->i_di.di_size)) - i_size_write(inode, ip->i_di.di_size); + if (error) + return error; return error; } diff --git a/trunk/fs/gfs2/ops_super.c b/trunk/fs/gfs2/ops_super.c index 603d940f1159..485ce3d49923 100644 --- a/trunk/fs/gfs2/ops_super.c +++ b/trunk/fs/gfs2/ops_super.c @@ -326,10 +326,8 @@ 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) { - ip->i_iopen_gh.gh_gl->gl_object = NULL; + if (ip->i_iopen_gh.gh_gl) gfs2_glock_dq_uninit(&ip->i_iopen_gh); - } } } @@ -424,13 +422,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, 0, &gh); + error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB, &gh); if (unlikely(error)) { gfs2_glock_dq_uninit(&ip->i_iopen_gh); goto out; } - gfs2_glock_dq_wait(&ip->i_iopen_gh); + gfs2_glock_dq(&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/trunk/fs/gfs2/ops_vm.c b/trunk/fs/gfs2/ops_vm.c index 404b7cc9f8c4..aa0dbd2aac1b 100644 --- a/trunk/fs/gfs2/ops_vm.c +++ b/trunk/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_length + + error = gfs2_trans_begin(sdp, al->al_rgd->rd_ri.ri_length + ind_blocks + RES_DINODE + RES_STATFS + RES_QUOTA, 0); if (error) diff --git a/trunk/fs/gfs2/quota.c b/trunk/fs/gfs2/quota.c index 6e546ee8f3d4..c186857e48a8 100644 --- a/trunk/fs/gfs2/quota.c +++ b/trunk/fs/gfs2/quota.c @@ -66,18 +66,6 @@ #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; @@ -573,25 +561,6 @@ 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 * @@ -604,13 +573,12 @@ 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_SIZE - 1); + unsigned offset = loc & (PAGE_CACHE_SHIFT - 1); unsigned blocksize, iblock, pos; struct buffer_head *bh; struct page *page; void *kaddr; - char *ptr; - struct gfs2_quota_host qp; + __be64 *ptr; s64 value; int err = -EIO; @@ -652,17 +620,13 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, kaddr = kmap_atomic(page, KM_USER0); ptr = kaddr + offset; - gfs2_quota_in(&qp, ptr); - qp.qu_value += change; - value = qp.qu_value; - gfs2_quota_out(&qp, ptr); + value = (s64)be64_to_cpu(*ptr) + change; + *ptr = cpu_to_be64(value); 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); @@ -725,7 +689,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_length + + al->al_rgd->rd_ri.ri_length + num_qd * data_blocks + nalloc * ind_blocks + RES_DINODE + num_qd + @@ -745,7 +709,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->qd_gl->gl_lvb); if (error) goto out_end_trans; @@ -1086,15 +1050,6 @@ 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/trunk/fs/gfs2/recovery.c b/trunk/fs/gfs2/recovery.c index 5ada38c99a2c..8bc182c7e2ef 100644 --- a/trunk/fs/gfs2/recovery.c +++ b/trunk/fs/gfs2/recovery.c @@ -116,22 +116,6 @@ 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 @@ -163,10 +147,12 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk, sizeof(u32)); hash = crc32_le(hash, (unsigned char const *)¬hing, sizeof(nothing)); hash ^= (u32)~0; - error = gfs2_log_header_in(&lh, bh->b_data); + gfs2_log_header_in(&lh, bh->b_data); brelse(bh); - if (error || lh.lh_blkno != blk || lh.lh_hash != hash) + if (lh.lh_header.mh_magic != GFS2_MAGIC || + lh.lh_header.mh_type != GFS2_METATYPE_LH || + lh.lh_blkno != blk || lh.lh_hash != hash) return 1; *head = lh; diff --git a/trunk/fs/gfs2/rgrp.c b/trunk/fs/gfs2/rgrp.c index e4e040625153..1727f5012efe 100644 --- a/trunk/fs/gfs2/rgrp.c +++ b/trunk/fs/gfs2/rgrp.c @@ -1,6 +1,6 @@ /* * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. - * Copyright (C) 2004-2007 Red Hat, Inc. 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 @@ -28,7 +28,6 @@ #include "ops_file.h" #include "util.h" #include "log.h" -#include "inode.h" #define BFITNOENT ((u32)~0) @@ -51,9 +50,6 @@ 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 @@ -208,7 +204,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_length; + u32 length = rgd->rd_ri.ri_length; u32 count[4], tmp; int buf, x; @@ -231,7 +227,7 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd) return; } - tmp = rgd->rd_data - + tmp = rgd->rd_ri.ri_data - rgd->rd_rg.rg_free - rgd->rd_rg.rg_dinodes; if (count[1] + count[2] != tmp) { @@ -257,10 +253,10 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd) } -static inline int rgrp_contains_block(struct gfs2_rgrpd *rgd, u64 block) +static inline int rgrp_contains_block(struct gfs2_rindex_host *ri, u64 block) { - u64 first = rgd->rd_data0; - u64 last = first + rgd->rd_data; + u64 first = ri->ri_data0; + u64 last = first + ri->ri_data; return first <= block && block < last; } @@ -279,7 +275,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, blk)) { + if (rgrp_contains_block(&rgd->rd_ri, blk)) { list_move(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list); spin_unlock(&sdp->sd_rindex_spin); return rgd; @@ -358,15 +354,6 @@ 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 @@ -380,7 +367,7 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd) { struct gfs2_sbd *sdp = rgd->rd_sbd; struct gfs2_bitmap *bi; - u32 length = rgd->rd_length; /* # blocks in hdr & bitmap */ + u32 length = rgd->rd_ri.ri_length; /* # blocks in hdr & bitmap */ u32 bytes_left, bytes; int x; @@ -391,7 +378,7 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd) if (!rgd->rd_bits) return -ENOMEM; - bytes_left = rgd->rd_bitbytes; + bytes_left = rgd->rd_ri.ri_bitbytes; for (x = 0; x < length; x++) { bi = rgd->rd_bits + x; @@ -412,14 +399,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_bitbytes - bytes_left; + bi->bi_start = rgd->rd_ri.ri_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_bitbytes - bytes_left; + bi->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left; bi->bi_len = bytes; } @@ -431,9 +418,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_data) { + if ((bi->bi_start + bi->bi_len) * GFS2_NBBY != rgd->rd_ri.ri_data) { if (gfs2_consist_rgrpd(rgd)) { - gfs2_rindex_print(rgd); + gfs2_rindex_print(&rgd->rd_ri); fs_err(sdp, "start=%u len=%u offset=%u\n", bi->bi_start, bi->bi_len, bi->bi_offset); } @@ -443,104 +430,9 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd) return 0; } -/** - * 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 + * @gl: The glock covering the rindex inode * * Returns: 0 on successful update, error code otherwise */ @@ -549,11 +441,13 @@ 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 rgrp_count = ip->i_di.di_size; + u64 junk = ip->i_di.di_size; int error; - if (do_div(rgrp_count, sizeof(struct gfs2_rindex))) { + if (do_div(junk, sizeof(struct gfs2_rindex))) { gfs2_consist_inode(ip); return -EIO; } @@ -561,50 +455,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 < rgrp_count; sdp->sd_rgrps++) { - error = read_rindex_entry(ip, &ra_state); - if (error) { - clear_rgrpdi(sdp); - return error; + 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; } - } - sdp->sd_rindex_vn = ip->i_gl->gl_vn; - return 0; -} + rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS); + error = -ENOMEM; + if (!rgd) + 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; + mutex_init(&rgd->rd_mutex); + lops_init_le(&rgd->rd_le, &gfs2_rg_lops); + rgd->rd_sbd = sdp; - 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; - } + 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; + + error = gfs2_glock_get(sdp, rgd->rd_ri.ri_addr, + &gfs2_rgrp_glops, CREATE, &rgd->rd_gl); + if (error) + goto fail; + + rgd->rd_gl->gl_object = rgd; + rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1; } sdp->sd_rindex_vn = ip->i_gl->gl_vn; return 0; + +fail: + clear_rgrpdi(sdp); + return error; } /** @@ -649,28 +543,6 @@ 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 @@ -685,7 +557,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_length; + unsigned int length = rgd->rd_ri.ri_length; struct gfs2_bitmap *bi; unsigned int x, y; int error; @@ -703,7 +575,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_addr + x, 0, &bi->bi_bh); + error = gfs2_meta_read(gl, rgd->rd_ri.ri_addr + x, 0, &bi->bi_bh); if (error) goto fail; } @@ -765,7 +637,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_length; + int x, length = rgd->rd_ri.ri_length; spin_lock(&sdp->sd_rindex_spin); gfs2_assert_warn(rgd->rd_sbd, rgd->rd_bh_count); @@ -788,7 +660,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_length; + unsigned int length = rgd->rd_ri.ri_length; unsigned int x; for (x = 0; x < length; x++) { @@ -849,38 +721,6 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al) return ret; } -/** - * 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 @@ -903,7 +743,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_addr == rglast) + if (rgd->rd_ri.ri_addr == rglast) goto out; } @@ -1042,9 +882,8 @@ static void forward_rgrp_set(struct gfs2_sbd *sdp, struct gfs2_rgrpd *rgd) * Returns: errno */ -static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) +static int get_local_rgrp(struct gfs2_inode *ip) { - 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; @@ -1064,11 +903,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) 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; @@ -1077,7 +912,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) break; default: - return ERR_PTR(error); + return error; } } @@ -1092,11 +927,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) 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: @@ -1104,7 +935,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) break; default: - return ERR_PTR(error); + return error; } rgd = gfs2_rgrpd_get_next(rgd); @@ -1113,7 +944,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) if (rgd == begin) { if (++loops >= 3) - return ERR_PTR(-ENOSPC); + return -ENOSPC; if (!skipped) loops++; flags = 0; @@ -1123,7 +954,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) } out: - ip->i_last_rg_alloc = rgd->rd_addr; + ip->i_last_rg_alloc = rgd->rd_ri.ri_addr; if (begin) { recent_rgrp_add(rgd); @@ -1133,7 +964,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) forward_rgrp_set(sdp, rgd); } - return NULL; + return 0; } /** @@ -1147,33 +978,19 @@ 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; - struct inode *inode; - int error = 0; - u64 last_unlinked = 0; + int error; if (gfs2_assert_warn(sdp, al->al_requested)) return -EINVAL; -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); - + error = gfs2_rindex_hold(sdp, &al->al_ri_gh); if (error) 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; + error = get_local_rgrp(ip); + if (error) { + gfs2_glock_dq_uninit(&al->al_ri_gh); + return error; } al->al_file = file; @@ -1202,8 +1019,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip) al->al_rgd = NULL; gfs2_glock_dq_uninit(&al->al_rgd_gh); - if (ip != GFS2_I(sdp->sd_rindex)) - gfs2_glock_dq_uninit(&al->al_ri_gh); + gfs2_glock_dq_uninit(&al->al_ri_gh); } /** @@ -1221,8 +1037,8 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block) unsigned int buf; unsigned char type; - length = rgd->rd_length; - rgrp_block = block - rgd->rd_data0; + length = rgd->rd_ri.ri_length; + rgrp_block = block - rgd->rd_ri.ri_data0; for (buf = 0; buf < length; buf++) { bi = rgd->rd_bits + buf; @@ -1261,10 +1077,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_length; + u32 length = rgd->rd_ri.ri_length; u32 blk = 0; unsigned int buf, x; @@ -1302,18 +1118,17 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, goal = 0; } - if (old_state != new_state) { - gfs2_assert_withdraw(rgd->rd_sbd, blk != BFITNOENT); + if (gfs2_assert_withdraw(rgd->rd_sbd, x <= length)) + blk = 0; - gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); - gfs2_setbit(rgd, bi->bi_bh->b_data + 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); - if (bi->bi_clone) - gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset, - bi->bi_len, blk, new_state); - } - return (blk == BFITNOENT) ? 0 : (bi->bi_start * GFS2_NBBY) + blk; + return bi->bi_start * GFS2_NBBY + blk; } /** @@ -1341,9 +1156,9 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart, return NULL; } - length = rgd->rd_length; + length = rgd->rd_ri.ri_length; - rgrp_blk = bstart - rgd->rd_data0; + rgrp_blk = bstart - rgd->rd_ri.ri_data0; while (blen--) { for (buf = 0; buf < length; buf++) { @@ -1387,15 +1202,15 @@ u64 gfs2_alloc_data(struct gfs2_inode *ip) u32 goal, blk; u64 block; - if (rgrp_contains_block(rgd, ip->i_di.di_goal_data)) - goal = ip->i_di.di_goal_data - rgd->rd_data0; + 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; 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_data0 + blk; + block = rgd->rd_ri.ri_data0 + blk; ip->i_di.di_goal_data = block; gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free); @@ -1431,15 +1246,15 @@ u64 gfs2_alloc_meta(struct gfs2_inode *ip) u32 goal, blk; u64 block; - if (rgrp_contains_block(rgd, ip->i_di.di_goal_meta)) - goal = ip->i_di.di_goal_meta - rgd->rd_data0; + 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; 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_data0 + blk; + block = rgd->rd_ri.ri_data0 + blk; ip->i_di.di_goal_meta = block; gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free); @@ -1481,7 +1296,7 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation) rgd->rd_last_alloc_meta = blk; - block = rgd->rd_data0 + blk; + block = rgd->rd_ri.ri_data0 + blk; gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free); rgd->rd_rg.rg_free--; @@ -1564,7 +1379,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_no_addr; + u64 blkno = ip->i_num.no_addr; rgd = rgblk_free(sdp, blkno, 1, GFS2_BLKST_UNLINKED); if (!rgd) @@ -1599,9 +1414,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_no_addr); + gfs2_free_uninit_di(rgd, ip->i_num.no_addr); gfs2_quota_change(ip, -1, ip->i_inode.i_uid, ip->i_inode.i_gid); - gfs2_meta_wipe(ip, ip->i_no_addr, 1); + gfs2_meta_wipe(ip, ip->i_num.no_addr, 1); } /** diff --git a/trunk/fs/gfs2/rgrp.h b/trunk/fs/gfs2/rgrp.h index b4c6adfc6f2e..b01e0cfc99b5 100644 --- a/trunk/fs/gfs2/rgrp.h +++ b/trunk/fs/gfs2/rgrp.h @@ -65,6 +65,5 @@ 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/trunk/fs/gfs2/super.c b/trunk/fs/gfs2/super.c index f916b9740c75..4fdda974dc83 100644 --- a/trunk/fs/gfs2/super.c +++ b/trunk/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_magic != GFS2_MAGIC || - sb->sb_type != GFS2_METATYPE_SB) { + if (sb->sb_header.mh_magic != GFS2_MAGIC || + sb->sb_header.mh_type != GFS2_METATYPE_SB) { if (!silent) printk(KERN_WARNING "GFS2: not a GFS2 filesystem\n"); return -EINVAL; @@ -174,31 +174,10 @@ 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 - * @sdp: The GFS2 super block + * @sb: The VFS 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. @@ -210,19 +189,17 @@ static void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf) * the master directory (contains pointers to journals etc) and the * root directory. * - * Returns: 0 on success or error + * Returns: A page containing the sb or NULL */ -int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector) +struct page *gfs2_read_super(struct super_block *sb, 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 -ENOBUFS; + return NULL; ClearPageUptodate(page); ClearPageDirty(page); @@ -231,7 +208,7 @@ int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector) bio = bio_alloc(GFP_KERNEL, 1); if (unlikely(!bio)) { __free_page(page); - return -ENOBUFS; + return NULL; } bio->bi_sector = sector * (sb->s_blocksize >> 9); @@ -245,13 +222,9 @@ int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector) bio_put(bio); if (!PageUptodate(page)) { __free_page(page); - return -EIO; + return NULL; } - p = kmap(page); - gfs2_sb_in(&sdp->sd_sb, p); - kunmap(page); - __free_page(page); - return 0; + return page; } /** @@ -268,13 +241,19 @@ 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; - error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift); - if (error) { + page = gfs2_read_super(sdp->sd_vfs, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift); + if (!page) { if (!silent) fs_err(sdp, "can't read superblock\n"); - return error; + return -EIO; } + 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) @@ -381,7 +360,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_check(sdp->sd_jindex, &name, NULL); + error = gfs2_dir_search(sdp->sd_jindex, &name, NULL, NULL); if (error == -ENOENT) { error = 0; break; @@ -614,24 +593,6 @@ 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); @@ -811,7 +772,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_data; + sc->sc_total += rgd->rd_ri.ri_data; sc->sc_free += rgd->rd_rg.rg_free; sc->sc_dinodes += rgd->rd_rg.rg_dinodes; return 0; diff --git a/trunk/fs/gfs2/super.h b/trunk/fs/gfs2/super.h index 60a870e430be..e590b2df11dc 100644 --- a/trunk/fs/gfs2/super.h +++ b/trunk/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); -int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector); +struct page *gfs2_read_super(struct super_block *sb, sector_t sector); static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp) { diff --git a/trunk/fs/gfs2/util.c b/trunk/fs/gfs2/util.c index 424a0774eda8..601eaa1b9ed6 100644 --- a/trunk/fs/gfs2/util.c +++ b/trunk/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_no_formal_ino, - (unsigned long long)ip->i_no_addr, + sdp->sd_fsname, (unsigned long long)ip->i_num.no_formal_ino, + (unsigned long long)ip->i_num.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_addr, + sdp->sd_fsname, (unsigned long long)rgd->rd_ri.ri_addr, sdp->sd_fsname, function, file, line); return rv; } diff --git a/trunk/fs/hfs/inode.c b/trunk/fs/hfs/inode.c index bc835f272a6e..9a934db0bd8a 100644 --- a/trunk/fs/hfs/inode.c +++ b/trunk/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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, .fsync = file_fsync, .open = hfs_file_open, .release = hfs_file_release, diff --git a/trunk/fs/hfsplus/inode.c b/trunk/fs/hfsplus/inode.c index 409ce5429c91..45dab5d6cc10 100644 --- a/trunk/fs/hfsplus/inode.c +++ b/trunk/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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, .fsync = file_fsync, .open = hfsplus_file_open, .release = hfsplus_file_release, diff --git a/trunk/fs/hostfs/hostfs_kern.c b/trunk/fs/hostfs/hostfs_kern.c index c77862032e84..8286491dbf31 100644 --- a/trunk/fs/hostfs/hostfs_kern.c +++ b/trunk/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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, .aio_read = generic_file_aio_read, .aio_write = generic_file_aio_write, .write = do_sync_write, diff --git a/trunk/fs/hpfs/file.c b/trunk/fs/hpfs/file.c index 5b53e5c5d8df..b4eafc0f1e54 100644 --- a/trunk/fs/hpfs/file.c +++ b/trunk/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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, }; const struct inode_operations hpfs_file_iops = diff --git a/trunk/fs/jffs2/file.c b/trunk/fs/jffs2/file.c index c2530197be0c..99871279a1ed 100644 --- a/trunk/fs/jffs2/file.c +++ b/trunk/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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile }; /* jffs2_file_inode_operations */ diff --git a/trunk/fs/jfs/file.c b/trunk/fs/jfs/file.c index 87eb93694af7..f7f8eff19b7b 100644 --- a/trunk/fs/jfs/file.c +++ b/trunk/fs/jfs/file.c @@ -108,6 +108,7 @@ 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/trunk/fs/minix/file.c b/trunk/fs/minix/file.c index 17765f697e50..f92baa1d7570 100644 --- a/trunk/fs/minix/file.c +++ b/trunk/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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, }; const struct inode_operations minix_file_inode_operations = { diff --git a/trunk/fs/nfs/file.c b/trunk/fs/nfs/file.c index 8689b736fdd9..9eb8eb4e4a08 100644 --- a/trunk/fs/nfs/file.c +++ b/trunk/fs/nfs/file.c @@ -41,9 +41,7 @@ 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_splice_read(struct file *filp, loff_t *ppos, - struct pipe_inode_info *pipe, - size_t count, unsigned int flags); +static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); 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, @@ -67,7 +65,7 @@ const struct file_operations nfs_file_operations = { .fsync = nfs_fsync, .lock = nfs_lock, .flock = nfs_flock, - .splice_read = nfs_file_splice_read, + .sendfile = nfs_file_sendfile, .check_flags = nfs_check_flags, }; @@ -226,21 +224,20 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov, } static ssize_t -nfs_file_splice_read(struct file *filp, loff_t *ppos, - struct pipe_inode_info *pipe, size_t count, - unsigned int flags) +nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count, + read_actor_t actor, void *target) { struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; ssize_t res; - dfprintk(VFS, "nfs: splice_read(%s/%s, %lu@%Lu)\n", + dfprintk(VFS, "nfs: sendfile(%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_splice_read(filp, ppos, pipe, count, flags); + res = generic_file_sendfile(filp, ppos, count, actor, target); return res; } diff --git a/trunk/fs/nfsd/vfs.c b/trunk/fs/nfsd/vfs.c index 8604e35bd48e..7e6aa245b5d5 100644 --- a/trunk/fs/nfsd/vfs.c +++ b/trunk/fs/nfsd/vfs.c @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include @@ -801,32 +801,26 @@ nfsd_get_raparms(dev_t dev, ino_t ino) } /* - * 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. + * 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. */ static int -nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf, - struct splice_desc *sd) +nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset , unsigned long size) { - struct svc_rqst *rqstp = sd->u.data; + unsigned long count = desc->count; + struct svc_rqst *rqstp = desc->arg.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; - size = sd->len; + if (size > count) + size = count; if (rqstp->rq_res.page_len == 0) { get_page(page); put_page(*pp); *pp = page; rqstp->rq_resused++; - rqstp->rq_res.page_base = buf->offset; + rqstp->rq_res.page_base = offset; rqstp->rq_res.page_len = size; } else if (page != pp[-1]) { get_page(page); @@ -838,15 +832,11 @@ nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf, } 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) @@ -871,15 +861,10 @@ 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->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); + 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); } else { oldfs = get_fs(); set_fs(KERNEL_DS); diff --git a/trunk/fs/ntfs/file.c b/trunk/fs/ntfs/file.c index ffcc504a1667..7ed56390b582 100644 --- a/trunk/fs/ntfs/file.c +++ b/trunk/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. */ - .splice_read = generic_file_splice_read /* Zero-copy data send with + .sendfile = generic_file_sendfile, /* Zero-copy data send with the data source being on the ntfs partition. We do not need to care about the diff --git a/trunk/fs/ocfs2/file.c b/trunk/fs/ocfs2/file.c index 4979b6675717..ac6c96431bbc 100644 --- a/trunk/fs/ocfs2/file.c +++ b/trunk/fs/ocfs2/file.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include @@ -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->confirm(pipe, buf); + ret = buf->ops->pin(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->u.file, + copied = ocfs2_buffered_write_cluster(sd->file, (loff_t)sd->pos + total, count, ocfs2_map_and_write_splice_data, @@ -1636,14 +1636,9 @@ 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; - struct splice_desc sd = { - .total_len = len, - .flags = flags, - .pos = *ppos, - .u.file = out, - }; - - ret = __splice_from_pipe(pipe, &sd, ocfs2_splice_write_actor); + + ret = __splice_from_pipe(pipe, out, ppos, len, flags, + ocfs2_splice_write_actor); if (ret > 0) { *ppos += ret; @@ -1822,6 +1817,7 @@ 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/trunk/fs/partitions/ibm.c b/trunk/fs/partitions/ibm.c index 1e064c4a4f86..9f7ad4244f63 100644 --- a/trunk/fs/partitions/ibm.c +++ b/trunk/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_information2_t *info; + dasd_information_t *info; struct hd_geometry *geo; char type[5] = {0,}; char name[7] = {0,}; @@ -64,17 +64,14 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) if (i_size == 0) goto out_exit; - info = kmalloc(sizeof(dasd_information2_t), GFP_KERNEL); - if (info == NULL) + if ((info = kmalloc(sizeof(dasd_information_t), GFP_KERNEL)) == NULL) goto out_exit; - geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL); - if (geo == NULL) + if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL) goto out_nogeo; - label = kmalloc(sizeof(union label_t), GFP_KERNEL); - if (label == NULL) + if ((label = kmalloc(sizeof(union label_t), GFP_KERNEL)) == NULL) goto out_nolab; - if (ioctl_by_bdev(bdev, BIODASDINFO2, (unsigned long)info) != 0 || + if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)info) != 0 || ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0) goto out_freeall; @@ -99,108 +96,84 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) res = 1; /* - * Three different formats: LDL, CDL and unformated disk - * - * identified by info->format - * - * unformated disks we do not have to care about + * Three different types: CMS1, VOL1 and LNX1/unlabeled */ - 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; - } + 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 { - /* - * Old style LNX1 or unlabeled disk - */ - if (strncmp(type, "LNX1", 4) == 0) - printk ("LNX1/%8s:", name); - else - printk("(nonl)"); + printk("CMS1/%8s:", name); offset = (info->label_block + 1); size = i_size >> 9; } put_partition(state, 1, offset*(blocksize >> 9), - size-offset*(blocksize >> 9)); - } else if (info->format == DASD_FORMAT_CDL) { + size-offset*(blocksize >> 9)); + } else if ((strncmp(type, "VOL1", 4) == 0) && + (!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) { /* - * New style CDL formatted disk + * New style VOL1 labeled disk */ unsigned int blk; int counter; - /* - * check if VOL1 label is available - * if not, something is wrong, skipping partition detection - */ - 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), - §); - 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), - §); - 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), - §); - } + 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), + §)) != NULL) { + struct vtoc_format1_label f1; - 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"); + 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 + */ + 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)); } printk("\n"); diff --git a/trunk/fs/pipe.c b/trunk/fs/pipe.c index d007830d9c87..3a89592bdf57 100644 --- a/trunk/fs/pipe.c +++ b/trunk/fs/pipe.c @@ -164,20 +164,6 @@ 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) { @@ -189,15 +175,6 @@ 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) { @@ -208,28 +185,11 @@ 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; @@ -238,32 +198,12 @@ int generic_pipe_buf_steal(struct pipe_inode_info *pipe, return 1; } -/** - * 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) +void generic_pipe_buf_get(struct pipe_inode_info *info, struct pipe_buffer *buf) { page_cache_get(buf->page); } -/** - * 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) +int generic_pipe_buf_pin(struct pipe_inode_info *info, struct pipe_buffer *buf) { return 0; } @@ -272,7 +212,7 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = { .can_merge = 1, .map = generic_pipe_buf_map, .unmap = generic_pipe_buf_unmap, - .confirm = generic_pipe_buf_confirm, + .pin = generic_pipe_buf_pin, .release = anon_pipe_buf_release, .steal = generic_pipe_buf_steal, .get = generic_pipe_buf_get, @@ -312,7 +252,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, if (chars > total_len) chars = total_len; - error = ops->confirm(pipe, buf); + error = ops->pin(pipe, buf); if (error) { if (!ret) error = ret; @@ -433,7 +373,7 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov, int error, atomic = 1; void *addr; - error = ops->confirm(pipe, buf); + error = ops->pin(pipe, buf); if (error) goto out; diff --git a/trunk/fs/qnx4/file.c b/trunk/fs/qnx4/file.c index 867f42b02035..44649981bbc8 100644 --- a/trunk/fs/qnx4/file.c +++ b/trunk/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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, #ifdef CONFIG_QNX4FS_RW .write = do_sync_write, .aio_write = generic_file_aio_write, diff --git a/trunk/fs/ramfs/file-mmu.c b/trunk/fs/ramfs/file-mmu.c index 97bdc0b2f9d2..2f14774a124f 100644 --- a/trunk/fs/ramfs/file-mmu.c +++ b/trunk/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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, .llseek = generic_file_llseek, }; diff --git a/trunk/fs/ramfs/file-nommu.c b/trunk/fs/ramfs/file-nommu.c index cad2b7ace630..5d258c40a2fd 100644 --- a/trunk/fs/ramfs/file-nommu.c +++ b/trunk/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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, .llseek = generic_file_llseek, }; diff --git a/trunk/fs/read_write.c b/trunk/fs/read_write.c index 507ddff48a9a..4d03008f015b 100644 --- a/trunk/fs/read_write.c +++ b/trunk/fs/read_write.c @@ -15,7 +15,6 @@ #include #include #include -#include #include "read_write.h" #include @@ -26,7 +25,7 @@ const struct file_operations generic_ro_fops = { .read = do_sync_read, .aio_read = generic_file_aio_read, .mmap = generic_file_readonly_mmap, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, }; EXPORT_SYMBOL(generic_ro_fops); @@ -709,7 +708,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, fl; + int fput_needed_in, fput_needed_out; /* * Get input file, and verify that it is ok.. @@ -724,7 +723,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->splice_read) + if (!in_file->f_op || !in_file->f_op->sendfile) goto fput_in; retval = -ESPIPE; if (!ppos) @@ -777,18 +776,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, count = max - pos; } - 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); + retval = in_file->f_op->sendfile(in_file, ppos, count, file_send_actor, out_file); if (retval > 0) { add_rchar(current, retval); diff --git a/trunk/fs/reiserfs/file.c b/trunk/fs/reiserfs/file.c index 30eebfb1b2d8..9e451a68580f 100644 --- a/trunk/fs/reiserfs/file.c +++ b/trunk/fs/reiserfs/file.c @@ -1531,6 +1531,7 @@ 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/trunk/fs/smbfs/file.c b/trunk/fs/smbfs/file.c index c5d78a7e492b..aea3f8aa54c0 100644 --- a/trunk/fs/smbfs/file.c +++ b/trunk/fs/smbfs/file.c @@ -262,9 +262,8 @@ smb_file_mmap(struct file * file, struct vm_area_struct * vma) } static ssize_t -smb_file_splice_read(struct file *file, loff_t *ppos, - struct pipe_inode_info *pipe, size_t count, - unsigned int flags) +smb_file_sendfile(struct file *file, loff_t *ppos, + size_t count, read_actor_t actor, void *target) { struct dentry *dentry = file->f_path.dentry; ssize_t status; @@ -278,7 +277,7 @@ smb_file_splice_read(struct file *file, loff_t *ppos, DENTRY_PATH(dentry), status); goto out; } - status = generic_file_splice_read(file, ppos, pipe, count, flags); + status = generic_file_sendfile(file, ppos, count, actor, target); out: return status; } @@ -417,7 +416,7 @@ const struct file_operations smb_file_operations = .open = smb_file_open, .release = smb_file_release, .fsync = smb_fsync, - .splice_read = smb_file_splice_read, + .sendfile = smb_file_sendfile, }; const struct inode_operations smb_file_inode_operations = diff --git a/trunk/fs/splice.c b/trunk/fs/splice.c index ed2ce995475c..e7d7080de2f9 100644 --- a/trunk/fs/splice.c +++ b/trunk/fs/splice.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -29,6 +29,22 @@ #include #include +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 @@ -85,12 +101,8 @@ static void page_cache_pipe_buf_release(struct pipe_inode_info *pipe, buf->flags &= ~PIPE_BUF_FLAG_LRU; } -/* - * 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) +static int page_cache_pipe_buf_pin(struct pipe_inode_info *pipe, + struct pipe_buffer *buf) { struct page *page = buf->page; int err; @@ -131,7 +143,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, - .confirm = page_cache_pipe_buf_confirm, + .pin = page_cache_pipe_buf_pin, .release = page_cache_pipe_buf_release, .steal = page_cache_pipe_buf_steal, .get = generic_pipe_buf_get, @@ -151,25 +163,18 @@ static const struct pipe_buf_operations user_page_pipe_buf_ops = { .can_merge = 0, .map = generic_pipe_buf_map, .unmap = generic_pipe_buf_unmap, - .confirm = generic_pipe_buf_confirm, + .pin = generic_pipe_buf_pin, .release = page_cache_pipe_buf_release, .steal = user_page_pipe_buf_steal, .get = generic_pipe_buf_get, }; -/** - * 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. - * +/* + * Pipe output worker. This sets up our pipe format with the page cache + * pipe buffer operations. Otherwise very similar to the regular pipe_writev(). */ -ssize_t splice_to_pipe(struct pipe_inode_info *pipe, - struct splice_pipe_desc *spd) +static 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; @@ -196,7 +201,6 @@ 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; @@ -291,6 +295,11 @@ __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. */ @@ -298,9 +307,8 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, /* * If find_get_pages_contig() returned fewer pages than we needed, - * allocate the rest and fill in the holes. + * allocate the rest. */ - error = 0; index += spd.nr_pages; while (spd.nr_pages < nr_pages) { /* @@ -462,16 +470,11 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, /** * 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 * - * 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. - * + * Will read pages from given file and fill them into a pipe. */ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, @@ -525,11 +528,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->u.file; + struct file *file = sd->file; loff_t pos = sd->pos; int ret, more; - ret = buf->ops->confirm(pipe, buf); + ret = buf->ops->pin(pipe, buf); if (!ret) { more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len; @@ -563,7 +566,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->u.file; + struct file *file = sd->file; struct address_space *mapping = file->f_mapping; unsigned int offset, this_len; struct page *page; @@ -573,7 +576,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->confirm(pipe, buf); + ret = buf->ops->pin(pipe, buf); if (unlikely(ret)) return ret; @@ -660,37 +663,36 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf, return ret; } -/** - * __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. - * +/* + * 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. */ -ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd, - splice_actor *actor) +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) { 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; @@ -702,10 +704,10 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd, 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) { @@ -717,7 +719,7 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd, do_wakeup = 1; } - if (!sd->total_len) + if (!sd.total_len) break; } @@ -730,7 +732,7 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd, break; } - if (sd->flags & SPLICE_F_NONBLOCK) { + if (flags & SPLICE_F_NONBLOCK) { if (!ret) ret = -EAGAIN; break; @@ -764,32 +766,12 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd, } 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 @@ -798,7 +780,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, &sd, actor); + ret = __splice_from_pipe(pipe, out, ppos, len, flags, actor); inode_double_unlock(inode, pipe->inode); return ret; @@ -808,14 +790,12 @@ 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 * - * 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. + * 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 @@ -824,12 +804,6 @@ 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; @@ -837,7 +811,7 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out, if (unlikely(err)) return err; - ret = __splice_from_pipe(pipe, &sd, pipe_to_file); + ret = __splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); if (ret > 0) { unsigned long nr_pages; @@ -867,13 +841,11 @@ 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 * - * Description: - * Will either move or copy pages (determined by @flags options) from - * the given pipe inode to the given file. + * Will either move or copy pages (determined by @flags options) from + * the given pipe inode to the given file. * */ ssize_t @@ -924,15 +896,13 @@ EXPORT_SYMBOL(generic_file_splice_write); /** * generic_splice_sendpage - splice data from a pipe to a socket - * @pipe: pipe to splice from + * @inode: pipe inode * @out: socket to write to - * @ppos: position in @out * @len: number of bytes to splice * @flags: splice modifier flags * - * Description: - * Will send @len bytes from the pipe to a network socket. No data copying - * is involved. + * 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, @@ -986,27 +956,14 @@ static long do_splice_to(struct file *in, loff_t *ppos, return in->f_op->splice_read(in, ppos, pipe, len, 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) +long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, + size_t len, unsigned int flags) { struct pipe_inode_info *pipe; long ret, bytes; + loff_t out_off; umode_t i_mode; - size_t len; - int i, flags; + int i; /* * We require the input being a regular file, as we don't want to @@ -1042,13 +999,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, */ ret = 0; bytes = 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; + out_off = 0; while (len) { size_t read_len, max_read_len; @@ -1058,19 +1009,19 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, */ max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE)); - ret = do_splice_to(in, &sd->pos, pipe, max_read_len, flags); + ret = do_splice_to(in, ppos, 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 = actor(pipe, sd); + ret = do_splice_from(pipe, out, &out_off, read_len, + flags & ~SPLICE_F_NONBLOCK); if (unlikely(ret < 0)) goto out_release; @@ -1115,48 +1066,6 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, 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; } /* @@ -1339,131 +1248,28 @@ 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 vmsplice_to_pipe(struct file *file, const struct iovec __user *iov, - unsigned long nr_segs, unsigned int flags) +static long do_vmsplice(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]; @@ -1478,6 +1284,10 @@ static long vmsplice_to_pipe(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); @@ -1487,22 +1297,6 @@ static long vmsplice_to_pipe(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) { @@ -1510,18 +1304,11 @@ 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 = vmsplice_to_pipe(file, iov, nr_segs, flags); - else if (file->f_mode & FMODE_READ) - error = vmsplice_to_user(file, iov, nr_segs, flags); + error = do_vmsplice(file, iov, nr_segs, flags); fput_light(file, fput); } diff --git a/trunk/fs/sysv/file.c b/trunk/fs/sysv/file.c index 589be21d884e..0732ddb9020b 100644 --- a/trunk/fs/sysv/file.c +++ b/trunk/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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, }; const struct inode_operations sysv_file_inode_operations = { diff --git a/trunk/fs/udf/file.c b/trunk/fs/udf/file.c index df070bee8d4f..51b5764685e7 100644 --- a/trunk/fs/udf/file.c +++ b/trunk/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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, }; const struct inode_operations udf_file_inode_operations = { diff --git a/trunk/fs/ufs/file.c b/trunk/fs/ufs/file.c index 6705d74c6d2d..1e096323bad4 100644 --- a/trunk/fs/ufs/file.c +++ b/trunk/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, - .splice_read = generic_file_splice_read, + .sendfile = generic_file_sendfile, }; diff --git a/trunk/fs/xfs/linux-2.6/xfs_file.c b/trunk/fs/xfs/linux-2.6/xfs_file.c index 8c43cd2e237a..cb51dc961355 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_file.c +++ b/trunk/fs/xfs/linux-2.6/xfs_file.c @@ -123,6 +123,30 @@ xfs_file_aio_write_invis( return __xfs_file_write(iocb, iov, nr_segs, IO_ISAIO|IO_INVIS, pos); } +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, @@ -428,6 +452,7 @@ 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, @@ -450,6 +475,7 @@ 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/trunk/fs/xfs/linux-2.6/xfs_linux.h b/trunk/fs/xfs/linux-2.6/xfs_linux.h index af24a457d3a3..715adad7dd4d 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_linux.h +++ b/trunk/fs/xfs/linux-2.6/xfs_linux.h @@ -101,6 +101,7 @@ * 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/trunk/fs/xfs/linux-2.6/xfs_lrw.c b/trunk/fs/xfs/linux-2.6/xfs_lrw.c index 765ec16a6e39..ed90403f0ee7 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_lrw.c +++ b/trunk/fs/xfs/linux-2.6/xfs_lrw.c @@ -286,6 +286,50 @@ xfs_read( return ret; } +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, diff --git a/trunk/fs/xfs/linux-2.6/xfs_lrw.h b/trunk/fs/xfs/linux-2.6/xfs_lrw.h index 7c60a1eed88b..7ac51b1d2161 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_lrw.h +++ b/trunk/fs/xfs/linux-2.6/xfs_lrw.h @@ -90,6 +90,9 @@ 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/trunk/fs/xfs/linux-2.6/xfs_vnode.h b/trunk/fs/xfs/linux-2.6/xfs_vnode.h index 013048a92643..d1b2d01843d1 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_vnode.h +++ b/trunk/fs/xfs/linux-2.6/xfs_vnode.h @@ -139,6 +139,9 @@ 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 *); @@ -203,6 +206,7 @@ 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; @@ -250,6 +254,8 @@ 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/trunk/fs/xfs/xfs_vnodeops.c b/trunk/fs/xfs/xfs_vnodeops.c index 70bc82f65311..de17aed578f0 100644 --- a/trunk/fs/xfs/xfs_vnodeops.c +++ b/trunk/fs/xfs/xfs_vnodeops.c @@ -4680,6 +4680,9 @@ 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/trunk/include/asm-mips/addrspace.h b/trunk/include/asm-mips/addrspace.h index 0b3ff9c48409..964c5eddc21b 100644 --- a/trunk/include/asm-mips/addrspace.h +++ b/trunk/include/asm-mips/addrspace.h @@ -129,12 +129,29 @@ #define PHYS_TO_XKPHYS(cm,a) (_CONST64_(0x8000000000000000) | \ ((cm)<<59) | (a)) -/* - * 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 */ +#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 #ifndef CONFIG_CPU_R8000 diff --git a/trunk/include/asm-mips/bootinfo.h b/trunk/include/asm-mips/bootinfo.h index 087126a5faf9..b0c329783ac5 100644 --- a/trunk/include/asm-mips/bootinfo.h +++ b/trunk/include/asm-mips/bootinfo.h @@ -108,13 +108,19 @@ #define MACH_GROUP_COSINE 10 /* CoSine Orion */ #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 /* no more supported (jun 2007) */ +#define MACH_MOMENCO_OCELOT_C 2 #define MACH_MOMENCO_JAGUAR_ATX 3 /* no more supported (may 2007) */ #define MACH_MOMENCO_OCELOT_3 4 @@ -187,6 +193,13 @@ #define MACH_GROUP_HP_LJ 20 /* Hewlett Packard LaserJet */ #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 */ @@ -200,27 +213,6 @@ #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/trunk/include/asm-mips/cacheops.h b/trunk/include/asm-mips/cacheops.h index df7f2deb3b56..c4a1ec31ff6a 100644 --- a/trunk/include/asm-mips/cacheops.h +++ b/trunk/include/asm-mips/cacheops.h @@ -20,11 +20,7 @@ #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/trunk/include/asm-mips/cpu-features.h b/trunk/include/asm-mips/cpu-features.h index d95a83e3e1d7..5e4bed123b48 100644 --- a/trunk/include/asm-mips/cpu-features.h +++ b/trunk/include/asm-mips/cpu-features.h @@ -150,10 +150,6 @@ #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/trunk/include/asm-mips/cpu.h b/trunk/include/asm-mips/cpu.h index 3857358fb6de..2924069075e0 100644 --- a/trunk/include/asm-mips/cpu.h +++ b/trunk/include/asm-mips/cpu.h @@ -89,8 +89,6 @@ #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 @@ -109,7 +107,6 @@ * Definitions for 7:0 on legacy processors */ -#define PRID_REV_MASK 0x00ff #define PRID_REV_TX4927 0x0022 #define PRID_REV_TX4937 0x0030 @@ -126,7 +123,6 @@ #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 @@ -215,10 +211,7 @@ #define CPU_SB1A 62 #define CPU_74K 63 #define CPU_R14000 64 -#define CPU_LOONGSON1 65 -#define CPU_LOONGSON2 66 - -#define CPU_LAST 66 +#define CPU_LAST 64 /* * ISA Level encodings @@ -264,7 +257,6 @@ #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/trunk/include/asm-mips/div64.h b/trunk/include/asm-mips/div64.h index 716371bd0980..66189f5f6399 100644 --- a/trunk/include/asm-mips/div64.h +++ b/trunk/include/asm-mips/div64.h @@ -20,7 +20,7 @@ */ #define do_div64_32(res, high, low, base) ({ \ - unsigned long __quot32, __mod32; \ + unsigned long __quot, __mod; \ unsigned long __cf, __tmp, __tmp2, __i; \ \ __asm__(".set push\n\t" \ @@ -48,13 +48,12 @@ "bnez %4, 0b\n\t" \ " srl %5, %1, 0x1f\n\t" \ ".set pop" \ - : "=&r" (__mod32), "=&r" (__tmp), \ - "=&r" (__quot32), "=&r" (__cf), \ + : "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \ "=&r" (__i), "=&r" (__tmp2) \ : "Jr" (base), "0" (high), "1" (low)); \ \ - (res) = __quot32; \ - __mod32; }) + (res) = __quot; \ + __mod; }) #define do_div(n, base) ({ \ unsigned long long __quot; \ diff --git a/trunk/include/asm-mips/gpio.h b/trunk/include/asm-mips/gpio.h deleted file mode 100644 index 06e46faf862d..000000000000 --- a/trunk/include/asm-mips/gpio.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_MIPS_GPIO_H -#define __ASM_MIPS_GPIO_H - -#include - -#endif /* __ASM_MIPS_GPIO_H */ diff --git a/trunk/include/asm-mips/io.h b/trunk/include/asm-mips/io.h index 12bcc1f9fba9..92ec2618560c 100644 --- a/trunk/include/asm-mips/io.h +++ b/trunk/include/asm-mips/io.h @@ -178,11 +178,6 @@ 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) { @@ -287,9 +282,6 @@ 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/trunk/include/asm-mips/lasat/ds1603.h b/trunk/include/asm-mips/lasat/ds1603.h new file mode 100644 index 000000000000..edcd7544b358 --- /dev/null +++ b/trunk/include/asm-mips/lasat/ds1603.h @@ -0,0 +1,18 @@ +#include + +/* 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/trunk/include/asm-mips/lasat/eeprom.h b/trunk/include/asm-mips/lasat/eeprom.h new file mode 100644 index 000000000000..7b53edd5cd5f --- /dev/null +++ b/trunk/include/asm-mips/lasat/eeprom.h @@ -0,0 +1,17 @@ +#include + +/* 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/trunk/include/asm-mips/lasat/head.h b/trunk/include/asm-mips/lasat/head.h new file mode 100644 index 000000000000..f5589f31a197 --- /dev/null +++ b/trunk/include/asm-mips/lasat/head.h @@ -0,0 +1,22 @@ +/* + * 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 +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/trunk/include/asm-mips/lasat/lasat.h b/trunk/include/asm-mips/lasat/lasat.h new file mode 100644 index 000000000000..42077e367a5b --- /dev/null +++ b/trunk/include/asm-mips/lasat/lasat.h @@ -0,0 +1,253 @@ +/* + * lasat.h + * + * Thomas Horsten + * 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 + +#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 +/* 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/trunk/include/asm-mips/lasat/lasatint.h b/trunk/include/asm-mips/lasat/lasatint.h new file mode 100644 index 000000000000..065474feeccc --- /dev/null +++ b/trunk/include/asm-mips/lasat/lasatint.h @@ -0,0 +1,12 @@ +#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/trunk/include/asm-mips/lasat/picvue.h b/trunk/include/asm-mips/lasat/picvue.h new file mode 100644 index 000000000000..42a492edc40e --- /dev/null +++ b/trunk/include/asm-mips/lasat/picvue.h @@ -0,0 +1,15 @@ +/* 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/trunk/include/asm-mips/lasat/serial.h b/trunk/include/asm-mips/lasat/serial.h new file mode 100644 index 000000000000..9e88c7669c7a --- /dev/null +++ b/trunk/include/asm-mips/lasat/serial.h @@ -0,0 +1,13 @@ +#include + +/* 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/trunk/include/asm-mips/mach-au1x00/au1xxx_gpio.h b/trunk/include/asm-mips/mach-au1x00/au1xxx_gpio.h new file mode 100644 index 000000000000..27911e054ffc --- /dev/null +++ b/trunk/include/asm-mips/mach-au1x00/au1xxx_gpio.h @@ -0,0 +1,20 @@ +#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/trunk/include/asm-mips/mach-au1x00/gpio.h b/trunk/include/asm-mips/mach-au1x00/gpio.h deleted file mode 100644 index 2dc61e009a08..000000000000 --- a/trunk/include/asm-mips/mach-au1x00/gpio.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef _AU1XXX_GPIO_H_ -#define _AU1XXX_GPIO_H_ - -#include - -#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 - -#endif /* _AU1XXX_GPIO_H_ */ diff --git a/trunk/include/asm-mips/mach-au1x00/ioremap.h b/trunk/include/asm-mips/mach-au1x00/ioremap.h index 364cea2dc71f..098fca4289bb 100644 --- a/trunk/include/asm-mips/mach-au1x00/ioremap.h +++ b/trunk/include/asm-mips/mach-au1x00/ioremap.h @@ -28,15 +28,4 @@ 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/trunk/include/asm-mips/mach-cobalt/cobalt.h b/trunk/include/asm-mips/mach-cobalt/cobalt.h index 9c9d2b998ca4..684a501c04cf 100644 --- a/trunk/include/asm-mips/mach-cobalt/cobalt.h +++ b/trunk/include/asm-mips/mach-cobalt/cobalt.h @@ -30,6 +30,7 @@ #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) @@ -70,6 +71,10 @@ 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/trunk/include/asm-mips/mach-ev64120/mach-gt64120.h b/trunk/include/asm-mips/mach-ev64120/mach-gt64120.h new file mode 100644 index 000000000000..7e272ce57ea3 --- /dev/null +++ b/trunk/include/asm-mips/mach-ev64120/mach-gt64120.h @@ -0,0 +1,62 @@ +/* + * 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/trunk/include/asm-mips/mach-generic/gpio.h b/trunk/include/asm-mips/mach-generic/gpio.h deleted file mode 100644 index 6eaf5efedf3a..000000000000 --- a/trunk/include/asm-mips/mach-generic/gpio.h +++ /dev/null @@ -1,15 +0,0 @@ -#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 /* cansleep wrappers */ - -#endif /* __ASM_MACH_GENERIC_GPIO_H */ diff --git a/trunk/include/asm-mips/mach-generic/ioremap.h b/trunk/include/asm-mips/mach-generic/ioremap.h index b379938d47f0..9b64ff6e485d 100644 --- a/trunk/include/asm-mips/mach-generic/ioremap.h +++ b/trunk/include/asm-mips/mach-generic/ioremap.h @@ -20,15 +20,4 @@ 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/trunk/include/asm-mips/mach-generic/spaces.h b/trunk/include/asm-mips/mach-generic/spaces.h index c9fa4b14968d..0ae9997bc9a8 100644 --- a/trunk/include/asm-mips/mach-generic/spaces.h +++ b/trunk/include/asm-mips/mach-generic/spaces.h @@ -10,54 +10,38 @@ #ifndef _ASM_MACH_GENERIC_SPACES_H #define _ASM_MACH_GENERIC_SPACES_H -#include - -/* - * This gives the physical RAM offset. - */ -#ifndef PHYS_OFFSET -#define PHYS_OFFSET _AC(0, UL) -#endif #ifdef CONFIG_32BIT -#define CAC_BASE _AC(0x80000000, UL) -#define IO_BASE _AC(0xa0000000, UL) -#define UNCAC_BASE _AC(0xa0000000, UL) +#define CAC_BASE 0x80000000 +#define IO_BASE 0xa0000000 +#define UNCAC_BASE 0xa0000000 +#define MAP_BASE 0xc0000000 -#ifndef MAP_BASE -#define MAP_BASE _AC(0xc0000000, UL) -#endif +/* + * 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 _AC(0x20000000, UL) +#define HIGHMEM_START 0x20000000UL #endif #endif /* CONFIG_32BIT */ #ifdef CONFIG_64BIT -#ifndef CAC_BASE +/* + * This handles the memory map. + */ #ifdef CONFIG_DMA_NONCOHERENT -#define CAC_BASE _AC(0x9800000000000000, UL) +#define PAGE_OFFSET 0x9800000000000000UL #else -#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) +#define PAGE_OFFSET 0xa800000000000000UL #endif /* @@ -66,20 +50,22 @@ * in the distant future. Nobody will care for a few years :-) */ #ifndef HIGHMEM_START -#define HIGHMEM_START (_AC(1, UL) << _AC(59, UL)) +#define HIGHMEM_START (1UL << 59UL) #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/trunk/include/asm-mips/mach-ip22/spaces.h b/trunk/include/asm-mips/mach-ip22/spaces.h index 7f9fa6f66059..ab20c026fd19 100644 --- a/trunk/include/asm-mips/mach-ip22/spaces.h +++ b/trunk/include/asm-mips/mach-ip22/spaces.h @@ -11,17 +11,44 @@ #define _ASM_MACH_IP22_SPACES_H -#ifdef CONFIG_64BIT +#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 CAC_BASE 0xffffffff80000000 #define IO_BASE 0xffffffffa0000000 #define UNCAC_BASE 0xffffffffa0000000 #define MAP_BASE 0xc000000000000000 -#endif /* CONFIG_64BIT */ +#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)) -#include +#endif /* CONFIG_64BIT */ #endif /* __ASM_MACH_IP22_SPACES_H */ diff --git a/trunk/include/asm-mips/mach-ip27/spaces.h b/trunk/include/asm-mips/mach-ip27/spaces.h index b18802a0b17e..45e61785ef42 100644 --- a/trunk/include/asm-mips/mach-ip27/spaces.h +++ b/trunk/include/asm-mips/mach-ip27/spaces.h @@ -14,17 +14,22 @@ * 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 HIGHMEM_START (~0UL) +#define PAGE_OFFSET CAC_BASE -#include +#define HIGHMEM_START (~0UL) #endif /* _ASM_MACH_IP27_SPACES_H */ diff --git a/trunk/include/asm-mips/mach-ip32/spaces.h b/trunk/include/asm-mips/mach-ip32/spaces.h new file mode 100644 index 000000000000..44abe5c02389 --- /dev/null +++ b/trunk/include/asm-mips/mach-ip32/spaces.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) 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/trunk/include/asm-mips/mach-jmr3927/ioremap.h b/trunk/include/asm-mips/mach-jmr3927/ioremap.h deleted file mode 100644 index aa131ad7f717..000000000000 --- a/trunk/include/asm-mips/mach-jmr3927/ioremap.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 - -/* - * 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/trunk/include/asm-mips/mach-lasat/mach-gt64120.h b/trunk/include/asm-mips/mach-lasat/mach-gt64120.h new file mode 100644 index 000000000000..1a9ad45cc135 --- /dev/null +++ b/trunk/include/asm-mips/mach-lasat/mach-gt64120.h @@ -0,0 +1,27 @@ +/* + * 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/trunk/include/asm-mips/mach-lemote/dma-coherence.h b/trunk/include/asm-mips/mach-lemote/dma-coherence.h deleted file mode 100644 index 7e914777ebc4..000000000000 --- a/trunk/include/asm-mips/mach-lemote/dma-coherence.h +++ /dev/null @@ -1,42 +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) 2006, 07 Ralf Baechle - * 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/trunk/include/asm-mips/mach-lemote/mc146818rtc.h b/trunk/include/asm-mips/mach-lemote/mc146818rtc.h deleted file mode 100644 index ed5147e11085..000000000000 --- a/trunk/include/asm-mips/mach-lemote/mc146818rtc.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) 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 - -#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/trunk/include/asm-mips/mach-mips/kernel-entry-init.h b/trunk/include/asm-mips/mach-mips/kernel-entry-init.h deleted file mode 100644 index 0b793e7bf67e..000000000000 --- a/trunk/include/asm-mips/mach-mips/kernel-entry-init.h +++ /dev/null @@ -1,52 +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. - * - * 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/trunk/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h b/trunk/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h new file mode 100644 index 000000000000..57a12ded0613 --- /dev/null +++ b/trunk/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h @@ -0,0 +1,48 @@ +/* + * 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/trunk/include/asm-mips/mach-mipssim/cpu-feature-overrides.h b/trunk/include/asm-mips/mach-sim/cpu-feature-overrides.h similarity index 100% rename from trunk/include/asm-mips/mach-mipssim/cpu-feature-overrides.h rename to trunk/include/asm-mips/mach-sim/cpu-feature-overrides.h diff --git a/trunk/include/asm-mips/mach-tx49xx/ioremap.h b/trunk/include/asm-mips/mach-tx49xx/ioremap.h deleted file mode 100644 index 88cf546719b8..000000000000 --- a/trunk/include/asm-mips/mach-tx49xx/ioremap.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 - -/* - * 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/trunk/include/asm-mips/mips-boards/bonito64.h b/trunk/include/asm-mips/mips-boards/bonito64.h index dc3fc32eedd8..cd7125610100 100644 --- a/trunk/include/asm-mips/mips-boards/bonito64.h +++ b/trunk/include/asm-mips/mips-boards/bonito64.h @@ -26,12 +26,7 @@ /* offsets from base register */ #define BONITO(x) (x) -#elif defined(CONFIG_LEMOTE_FULONG) - -#define BONITO(x) (*(volatile u32 *)((char *)CKSEG1ADDR(BONITO_REG_BASE) + (x))) -#define BONITO_IRQ_BASE 32 - -#else +#else /* !__ASSEMBLY__ */ /* * Algorithmics Bonito64 system controller register base. diff --git a/trunk/include/asm-mips/mipsregs.h b/trunk/include/asm-mips/mipsregs.h index 706b3691f57e..89c81922d47c 100644 --- a/trunk/include/asm-mips/mipsregs.h +++ b/trunk/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, 07 MIPS Technologies, Inc. + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. * Copyright (C) 2003, 2004 Maciej W. Rozycki */ #ifndef _ASM_MIPSREGS_H @@ -15,7 +15,6 @@ #include #include -#include /* * The following macros are especially useful for __asm__ @@ -534,13 +533,9 @@ #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. */ @@ -777,9 +772,6 @@ 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) @@ -1302,39 +1294,10 @@ 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/trunk/include/asm-mips/module.h b/trunk/include/asm-mips/module.h index de6d09ebbd80..c5ef324fd69f 100644 --- a/trunk/include/asm-mips/module.h +++ b/trunk/include/asm-mips/module.h @@ -112,8 +112,6 @@ 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/trunk/include/asm-mips/nile4.h b/trunk/include/asm-mips/nile4.h new file mode 100644 index 000000000000..c3ca959aa4d9 --- /dev/null +++ b/trunk/include/asm-mips/nile4.h @@ -0,0 +1,310 @@ +/* + * asm-mips/nile4.h -- NEC Vrc-5074 Nile 4 definitions + * + * Copyright (C) 2000 Geert Uytterhoeven + * 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/trunk/include/asm-mips/page.h b/trunk/include/asm-mips/page.h index b92dd8c760da..5c3239dad0f2 100644 --- a/trunk/include/asm-mips/page.h +++ b/trunk/include/asm-mips/page.h @@ -34,8 +34,12 @@ #ifndef __ASSEMBLY__ -#include -#include +/* + * This gives the physical RAM offset. + */ +#ifndef PHYS_OFFSET +#define PHYS_OFFSET 0UL +#endif /* * It's normally defined only for FLATMEM config but it's @@ -44,6 +48,9 @@ */ #define ARCH_PFN_OFFSET PFN_UP(PHYS_OFFSET) +#include +#include + extern void clear_page(void * page); extern void copy_page(void * to, void * from); @@ -143,15 +150,11 @@ 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(x) \ -({ \ - unsigned long __x = (unsigned long)(x); \ - __x < CKSEG0 ? XPHYSADDR(__x) : CPHYSADDR(__x); \ -}) +#define __pa_page_offset(x) ((unsigned long)(x) < CKSEG0 ? PAGE_OFFSET : CKSEG0) #else -#define __pa(x) \ - ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET) +#define __pa_page_offset(x) PAGE_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/trunk/include/asm-mips/pci.h b/trunk/include/asm-mips/pci.h index a59d54749eef..3eea3ba0fca5 100644 --- a/trunk/include/asm-mips/pci.h +++ b/trunk/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(const struct pci_dev *dev, u8 slot, u8 pin); +extern int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin); /* Can be used to override the logic in pci_scan_bus for skipping diff --git a/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h b/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h deleted file mode 100644 index c84bcf9570b1..000000000000 --- a/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_int.h b/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_int.h deleted file mode 100644 index 1d9f05474820..000000000000 --- a/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_int.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_pci.h b/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_pci.h deleted file mode 100644 index 415606903617..000000000000 --- a/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_pci.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * 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/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_prom.h b/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_prom.h deleted file mode 100644 index 14ca7dc382a8..000000000000 --- a/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_prom.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * 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 - -#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/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_regops.h b/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_regops.h deleted file mode 100644 index 60a5a38dd5b2..000000000000 --- a/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_regops.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - * 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 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 - -#include - -#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/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h b/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h deleted file mode 100644 index 0b56f55206c6..000000000000 --- a/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h +++ /dev/null @@ -1,667 +0,0 @@ -/* - * 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 -#include - -#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/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h b/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h deleted file mode 100644 index 96d4c8ce8c83..000000000000 --- a/trunk/include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * 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/trunk/include/asm-mips/processor.h b/trunk/include/asm-mips/processor.h index 1d8b9a8ae324..5f80ba71ab92 100644 --- a/trunk/include/asm-mips/processor.h +++ b/trunk/include/asm-mips/processor.h @@ -82,6 +82,10 @@ struct mips_fpu_struct { unsigned int fcr31; }; +#define INIT_FPU { \ + {0,} \ +} + #define NUM_DSP_REGS 6 typedef __u32 dspreg_t; @@ -91,6 +95,8 @@ struct mips_dsp_state { unsigned int dspcontrol; }; +#define INIT_DSP {{0,},} + #define INIT_CPUMASK { \ {0,} \ } @@ -149,63 +155,41 @@ struct thread_struct { #define MF_N64 0 #ifdef CONFIG_MIPS_MT_FPAFF -#define FPAFF_INIT \ - .emulated_fp = 0, \ - .user_cpus_allowed = INIT_CPUMASK, +#define FPAFF_INIT 0, INIT_CPUMASK, #else #define FPAFF_INIT #endif /* CONFIG_MIPS_MT_FPAFF */ -#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, \ +#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 \ } struct task_struct; @@ -253,7 +237,7 @@ unsigned long get_wchan(struct task_struct *p); #define ARCH_HAS_PREFETCH -static inline void prefetch(const void *addr) +extern inline void prefetch(const void *addr) { __asm__ __volatile__( " .set mips4 \n" diff --git a/trunk/include/asm-mips/serial.h b/trunk/include/asm-mips/serial.h index c07ebd8eb9e7..ce51213d84f9 100644 --- a/trunk/include/asm-mips/serial.h +++ b/trunk/include/asm-mips/serial.h @@ -19,4 +19,159 @@ */ #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 + +#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 +#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 +#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/trunk/include/asm-mips/smp.h b/trunk/include/asm-mips/smp.h index 13aef6af422c..1608fd71d6f7 100644 --- a/trunk/include/asm-mips/smp.h +++ b/trunk/include/asm-mips/smp.h @@ -49,6 +49,13 @@ 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/trunk/include/asm-mips/sni.h b/trunk/include/asm-mips/sni.h index ddaf36a1e389..f257509b914f 100644 --- a/trunk/include/asm-mips/sni.h +++ b/trunk/include/asm-mips/sni.h @@ -146,6 +146,9 @@ 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/trunk/include/asm-mips/system.h b/trunk/include/asm-mips/system.h index 46bdb3f566f9..bb0b289dbc9e 100644 --- a/trunk/include/asm-mips/system.h +++ b/trunk/include/asm-mips/system.h @@ -44,7 +44,7 @@ struct task_struct; * different thread. */ -#define __mips_mt_fpaff_switch_to(prev) \ +#define switch_to(prev,next,last) \ 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/trunk/include/asm-mips/tx4938/rbtx4938.h b/trunk/include/asm-mips/tx4938/rbtx4938.h index 74e7d8061e58..0fbedafdcea8 100644 --- a/trunk/include/asm-mips/tx4938/rbtx4938.h +++ b/trunk/include/asm-mips/tx4938/rbtx4938.h @@ -105,6 +105,12 @@ #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/trunk/include/asm-mips/tx4938/spi.h b/trunk/include/asm-mips/tx4938/spi.h index 6a60c83e152b..0dbbab820a5a 100644 --- a/trunk/include/asm-mips/tx4938/spi.h +++ b/trunk/include/asm-mips/tx4938/spi.h @@ -14,7 +14,61 @@ #ifndef __ASM_TX_BOARDS_TX4938_SPI_H #define __ASM_TX_BOARDS_TX4938_SPI_H -extern int spi_eeprom_register(int chipid); +/* 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_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/trunk/include/asm-mips/war.h b/trunk/include/asm-mips/war.h index 9de52a5b0f3d..ec0eeebd8802 100644 --- a/trunk/include/asm-mips/war.h +++ b/trunk/include/asm-mips/war.h @@ -169,9 +169,10 @@ /* * On the RM9000 there is a problem which makes the CreateDirtyExclusive - * eache operation unusable on SMP systems. + * cache operation unusable on SMP systems. */ -#if defined(CONFIG_PMC_YOSEMITE) || defined(CONFIG_BASLER_EXCITE) +#if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_PMC_YOSEMITE) || \ + defined(CONFIG_BASLER_EXCITE) #define RM9000_CDEX_SMP_WAR 1 #endif @@ -181,10 +182,11 @@ * I-cache line worth of instructions being fetched may case spurious * exceptions. */ -#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) +#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) #define ICACHE_REFILLS_WORKAROUND_WAR 1 #endif @@ -197,14 +199,6 @@ #define R10000_LLSC_WAR 1 #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 */ @@ -244,8 +238,5 @@ #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/trunk/include/asm-mips/watch.h b/trunk/include/asm-mips/watch.h new file mode 100644 index 000000000000..6aa90cae1114 --- /dev/null +++ b/trunk/include/asm-mips/watch.h @@ -0,0 +1,35 @@ +/* + * 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 + +/* + * 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/trunk/include/asm-s390/atomic.h b/trunk/include/asm-s390/atomic.h index ea486952f778..c17bdbf22067 100644 --- a/trunk/include/asm-s390/atomic.h +++ b/trunk/include/asm-s390/atomic.h @@ -24,7 +24,7 @@ */ typedef struct { - int counter; + volatile 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 { - long long counter; + volatile long long counter; } __attribute__ ((aligned (8))) atomic64_t; #define ATOMIC64_INIT(i) { (i) } diff --git a/trunk/include/asm-s390/cmb.h b/trunk/include/asm-s390/cmb.h index 021e7c3223ec..241756f80df3 100644 --- a/trunk/include/asm-s390/cmb.h +++ b/trunk/include/asm-s390/cmb.h @@ -88,6 +88,7 @@ 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/trunk/include/asm-s390/processor.h b/trunk/include/asm-s390/processor.h index 3b972d4c6b29..5cb480af65d5 100644 --- a/trunk/include/asm-s390/processor.h +++ b/trunk/include/asm-s390/processor.h @@ -357,8 +357,8 @@ extern void (*s390_base_ext_handler_fn)(void); /* * CPU idle notifier chain. */ -#define S390_CPU_IDLE 0 -#define S390_CPU_NOT_IDLE 1 +#define CPU_IDLE 0 +#define CPU_NOT_IDLE 1 struct notifier_block; int register_idle_notifier(struct notifier_block *nb); diff --git a/trunk/include/asm-s390/sclp.h b/trunk/include/asm-s390/sclp.h index cb9faf1ea5cf..21ed64773210 100644 --- a/trunk/include/asm-s390/sclp.h +++ b/trunk/include/asm-s390/sclp.h @@ -11,6 +11,29 @@ #include #include +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 { @@ -19,22 +42,12 @@ struct sclp_chp_info { u8 configured[SCLP_CHP_INFO_MASK_SIZE]; }; -#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); +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); #endif /* _ASM_S390_SCLP_H */ diff --git a/trunk/include/asm-s390/sfp-machine.h b/trunk/include/asm-s390/sfp-machine.h index 4e16aede4b06..8ca8c77b2d04 100644 --- a/trunk/include/asm-s390/sfp-machine.h +++ b/trunk/include/asm-s390/sfp-machine.h @@ -27,9 +27,9 @@ #define _FP_W_TYPE_SIZE 32 -#define _FP_W_TYPE unsigned int -#define _FP_WS_TYPE signed int -#define _FP_I_TYPE int +#define _FP_W_TYPE unsigned long +#define _FP_WS_TYPE signed long +#define _FP_I_TYPE long #define _FP_MUL_MEAT_S(R,X,Y) \ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm) diff --git a/trunk/include/asm-s390/sfp-util.h b/trunk/include/asm-s390/sfp-util.h index 0addc6466d95..8cabcd23d976 100644 --- a/trunk/include/asm-s390/sfp-util.h +++ b/trunk/include/asm-s390/sfp-util.h @@ -51,16 +51,6 @@ 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)); \ @@ -68,7 +58,6 @@ } while (0) extern unsigned long __udiv_qrnnd (unsigned int *, unsigned int, unsigned int , unsigned int); -#endif #define UDIV_NEEDS_NORMALIZATION 0 diff --git a/trunk/include/linux/Kbuild b/trunk/include/linux/Kbuild index afae306b177c..f317c270d4bf 100644 --- a/trunk/include/linux/Kbuild +++ b/trunk/include/linux/Kbuild @@ -49,7 +49,6 @@ 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/trunk/include/linux/ata.h b/trunk/include/linux/ata.h index 407dc7e098bc..703febb2df31 100644 --- a/trunk/include/linux/ata.h +++ b/trunk/include/linux/ata.h @@ -126,7 +126,6 @@ enum { ATA_REG_IRQ = ATA_REG_NSECT, /* ATA device commands */ - ATA_CMD_DEV_RESET = 0x08, /* ATAPI device reset */ ATA_CMD_CHK_POWER = 0xE5, /* check power mode */ ATA_CMD_STANDBY = 0xE2, /* place in standby power mode */ ATA_CMD_IDLE = 0xE3, /* place in idle power mode */ diff --git a/trunk/include/linux/blkdev.h b/trunk/include/linux/blkdev.h index fae138bd2207..db5b00a792f5 100644 --- a/trunk/include/linux/blkdev.h +++ b/trunk/include/linux/blkdev.h @@ -868,6 +868,11 @@ 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/trunk/include/linux/dlm.h b/trunk/include/linux/dlm.h index be9d278761e0..1b1dcb9a40bb 100644 --- a/trunk/include/linux/dlm.h +++ b/trunk/include/linux/dlm.h @@ -2,7 +2,7 @@ ******************************************************************************* ** ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. -** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. +** Copyright (C) 2004-2005 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,11 +85,7 @@ * Only relevant to locks originating in userspace. A persistent lock will not * be removed if the process holding the lock exits. * - * 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_NODLKWT * DLM_LKF_NODLCKBLK * * net yet implemented @@ -153,7 +149,6 @@ #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 @@ -204,12 +199,11 @@ 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/trunk/include/linux/dlm_device.h b/trunk/include/linux/dlm_device.h index 9642277a152a..c2735cab2ebf 100644 --- a/trunk/include/linux/dlm_device.h +++ b/trunk/include/linux/dlm_device.h @@ -2,7 +2,7 @@ ******************************************************************************* ** ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. -** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. +** Copyright (C) 2004-2005 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,24 +18,21 @@ #define DLM_USER_LVB_LEN 32 /* Version of the device interface */ -#define DLM_DEVICE_VERSION_MAJOR 6 -#define DLM_DEVICE_VERSION_MINOR 0 +#define DLM_DEVICE_VERSION_MAJOR 5 +#define DLM_DEVICE_VERSION_MINOR 1 #define DLM_DEVICE_VERSION_PATCH 0 /* struct passed to the lock write */ struct dlm_lock_params { __u8 mode; __u8 namelen; - __u16 unused; - __u32 flags; + __u16 flags; __u32 lkid; __u32 parent; - __u64 xid; - __u64 timeout; - void __user *castparam; + 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]; @@ -65,15 +62,9 @@ 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; @@ -92,7 +83,6 @@ 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/trunk/include/linux/dlm_netlink.h b/trunk/include/linux/dlm_netlink.h deleted file mode 100644 index 19276332707a..000000000000 --- a/trunk/include/linux/dlm_netlink.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index 4f0b3bf5983c..6a41f4cab14c 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -1054,7 +1054,7 @@ struct block_device_operations { }; /* - * "descriptor" for what we're up to with a read. + * "descriptor" for what we're up to with a read for sendfile(). * This allows us to use the same read code yet * have multiple different users of the data that * we read from a file. @@ -1105,6 +1105,7 @@ 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); @@ -1761,6 +1762,7 @@ 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); @@ -1790,6 +1792,9 @@ 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/trunk/include/linux/gfs2_ondisk.h b/trunk/include/linux/gfs2_ondisk.h index a44a6a078f0a..8b7e4c1e32ae 100644 --- a/trunk/include/linux/gfs2_ondisk.h +++ b/trunk/include/linux/gfs2_ondisk.h @@ -54,6 +54,18 @@ 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. @@ -82,6 +94,12 @@ 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 * @@ -121,6 +139,23 @@ 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 */ @@ -138,6 +173,14 @@ 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 */ @@ -169,6 +212,13 @@ 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 */ @@ -180,6 +230,12 @@ struct gfs2_quota { __u8 qu_reserved[64]; }; +struct gfs2_quota_host { + __u64 qu_limit; + __u64 qu_warn; + __u64 qu_value; +}; + /* * dinode structure */ @@ -259,11 +315,29 @@ 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[44]; + __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 */ }; /* @@ -340,6 +414,16 @@ 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 */ @@ -380,6 +464,11 @@ 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 @@ -392,6 +481,12 @@ 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 @@ -406,12 +501,39 @@ struct gfs2_quota_change { __be32 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 */ +struct gfs2_quota_change_host { + __u64 qc_change; + __u32 qc_flags; /* GFS2_QCF_... */ + __u32 qc_id; }; +#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/trunk/include/linux/gpio_mouse.h b/trunk/include/linux/gpio_mouse.h deleted file mode 100644 index 44ed7aa14d85..000000000000 --- a/trunk/include/linux/gpio_mouse.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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/trunk/include/linux/input.h b/trunk/include/linux/input.h index 18c98b543030..d8521c72f69f 100644 --- a/trunk/include/linux/input.h +++ b/trunk/include/linux/input.h @@ -981,15 +981,15 @@ struct input_dev { struct mutex mutex; /* serializes open and close operations */ unsigned int users; - struct device dev; + struct class_device cdev; union { /* temporarily so while we switching to struct device */ - struct device *dev; - } cdev; + struct device *parent; + } dev; struct list_head h_list; struct list_head node; }; -#define to_input_dev(d) container_of(d, struct input_dev, dev) +#define to_input_dev(d) container_of(d, struct input_dev, cdev) /* * 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(get_device(&dev->dev)); + return to_input_dev(class_device_get(&dev->cdev)); } static inline void input_put_device(struct input_dev *dev) { - put_device(&dev->dev); + class_device_put(&dev->cdev); } static inline void *input_get_drvdata(struct input_dev *dev) diff --git a/trunk/include/linux/ioprio.h b/trunk/include/linux/ioprio.h index 2eaa142cd061..8e2042b9d471 100644 --- a/trunk/include/linux/ioprio.h +++ b/trunk/include/linux/ioprio.h @@ -47,10 +47,8 @@ enum { #define IOPRIO_NORM (4) static inline int task_ioprio(struct task_struct *task) { - if (ioprio_valid(task->ioprio)) - return IOPRIO_PRIO_DATA(task->ioprio); - - return IOPRIO_NORM; + WARN_ON(!ioprio_valid(task->ioprio)); + return IOPRIO_PRIO_DATA(task->ioprio); } static inline int task_nice_ioprio(struct task_struct *task) diff --git a/trunk/include/linux/libata.h b/trunk/include/linux/libata.h index a3df64677ac3..620da7be07b7 100644 --- a/trunk/include/linux/libata.h +++ b/trunk/include/linux/libata.h @@ -116,7 +116,6 @@ static inline struct device *pci_dev_to_dev(struct pci_dev *pdev) enum { /* various global constants */ LIBATA_MAX_PRD = ATA_MAX_PRD / 2, - LIBATA_DUMB_MAX_PRD = ATA_MAX_PRD / 4, /* Worst case */ ATA_MAX_PORTS = 8, ATA_DEF_QUEUE = 1, /* tag ATA_MAX_QUEUE - 1 is reserved for internal commands */ @@ -137,8 +136,6 @@ enum { ATA_DFLAG_CDB_INTR = (1 << 2), /* device asserts INTRQ when ready for CDB */ ATA_DFLAG_NCQ = (1 << 3), /* device supports NCQ */ ATA_DFLAG_FLUSH_EXT = (1 << 4), /* do FLUSH_EXT instead of FLUSH */ - ATA_DFLAG_ACPI_PENDING = (1 << 5), /* ACPI resume action pending */ - ATA_DFLAG_ACPI_FAILED = (1 << 6), /* ACPI on devcfg has failed */ ATA_DFLAG_CFG_MASK = (1 << 8) - 1, ATA_DFLAG_PIO = (1 << 8), /* device limited to PIO mode */ @@ -199,7 +196,6 @@ enum { ATA_PFLAG_FLUSH_PORT_TASK = (1 << 16), /* flush port task */ ATA_PFLAG_SUSPENDED = (1 << 17), /* port is suspended (power) */ ATA_PFLAG_PM_PENDING = (1 << 18), /* PM operation pending */ - ATA_PFLAG_GTM_VALID = (1 << 19), /* acpi_gtm data valid */ /* struct ata_queued_cmd flags */ ATA_QCFLAG_ACTIVE = (1 << 0), /* cmd not yet ack'd to scsi lyer */ @@ -367,9 +363,6 @@ struct ata_host { void *private_data; const struct ata_port_operations *ops; unsigned long flags; -#ifdef CONFIG_ATA_ACPI - acpi_handle acpi_handle; -#endif struct ata_port *simplex_claimed; /* channel owning the DMA */ struct ata_port *ports[0]; }; @@ -436,9 +429,6 @@ struct ata_device { unsigned int devno; /* 0 or 1 */ unsigned long flags; /* ATA_DFLAG_xxx */ struct scsi_device *sdev; /* attached SCSI device */ -#ifdef CONFIG_ATA_ACPI - acpi_handle acpi_handle; -#endif /* n_sector is used as CLEAR_OFFSET, read comment above CLEAR_OFFSET */ u64 n_sectors; /* size of device, if ATA */ unsigned int class; /* ATA_DEV_xxx */ @@ -467,6 +457,10 @@ struct ata_device { struct ata_ering ering; int spdn_cnt; unsigned int horkage; /* List of broken features */ +#ifdef CONFIG_ATA_ACPI + /* ACPI objects info */ + acpi_handle obj_handle; +#endif }; /* Offset into struct ata_device. Fields above it are maintained @@ -495,17 +489,6 @@ struct ata_eh_context { unsigned int did_probe_mask; }; -struct ata_acpi_drive -{ - u32 pio; - u32 dma; -} __packed; - -struct ata_acpi_gtm { - struct ata_acpi_drive drive[2]; - u32 flags; -} __packed; - struct ata_port { struct Scsi_Host *scsi_host; /* our co-allocated scsi host */ const struct ata_port_operations *ops; @@ -566,10 +549,6 @@ struct ata_port { void *private_data; -#ifdef CONFIG_ATA_ACPI - acpi_handle acpi_handle; - struct ata_acpi_gtm acpi_gtm; -#endif u8 sector_buf[ATA_SECT_SIZE]; /* owned by EH */ }; @@ -779,7 +758,6 @@ extern void ata_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data); extern void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data); -extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc); extern void ata_qc_prep(struct ata_queued_cmd *qc); extern void ata_noop_qc_prep(struct ata_queued_cmd *qc); extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc); diff --git a/trunk/include/linux/mv643xx.h b/trunk/include/linux/mv643xx.h index b021b3a2b65a..c6d4ab86b83c 100644 --- a/trunk/include/linux/mv643xx.h +++ b/trunk/include/linux/mv643xx.h @@ -13,6 +13,10 @@ #ifndef __ASM_MV643XX_H #define __ASM_MV643XX_H +#ifdef __mips__ +#include +#include +#endif #include /****************************************/ diff --git a/trunk/include/linux/pata_platform.h b/trunk/include/linux/pata_platform.h index 5799e8d50623..2d5fd647e0e9 100644 --- a/trunk/include/linux/pata_platform.h +++ b/trunk/include/linux/pata_platform.h @@ -8,11 +8,6 @@ struct pata_platform_info { * spacing used by ata_std_ports(). */ unsigned int ioport_shift; - /* - * Indicate platform specific irq types and initial - * IRQ flags when call request_irq() - */ - unsigned int irq_flags; }; #endif /* __LINUX_PATA_PLATFORM_H */ diff --git a/trunk/include/linux/pda_power.h b/trunk/include/linux/pda_power.h deleted file mode 100644 index 1375f15797e7..000000000000 --- a/trunk/include/linux/pda_power.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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 - * - * 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/trunk/include/linux/pipe_fs_i.h b/trunk/include/linux/pipe_fs_i.h index 8e4120285f72..c8884f971228 100644 --- a/trunk/include/linux/pipe_fs_i.h +++ b/trunk/include/linux/pipe_fs_i.h @@ -9,39 +9,13 @@ #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; @@ -60,73 +34,22 @@ struct pipe_inode_info { /* * Note on the nesting of these functions: * - * ->confirm() + * ->pin() * ->steal() * ... * ->map() * ... * ->unmap() * - * 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. + * That is, ->map() must be called on a pinned buffer, same goes for ->steal(). */ 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 *); - - /* - * ->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. - */ + int (*pin)(struct pipe_inode_info *, struct pipe_buffer *); 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 *); }; @@ -145,7 +68,39 @@ 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_confirm(struct pipe_inode_info *, struct pipe_buffer *); +int generic_pipe_buf_pin(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/trunk/include/linux/power_supply.h b/trunk/include/linux/power_supply.h deleted file mode 100644 index 606c0957997f..000000000000 --- a/trunk/include/linux/power_supply.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Universal power supply monitor class - * - * Copyright © 2007 Anton Vorontsov - * Copyright © 2004 Szabolcs Gyurko - * Copyright © 2003 Ian Molton - * - * 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 -#include -#include - -/* - * 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/trunk/include/linux/splice.h b/trunk/include/linux/splice.h deleted file mode 100644 index 33e447f98a54..000000000000 --- a/trunk/include/linux/splice.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Function declerations and data structures related to the splice - * implementation. - * - * Copyright (C) 2007 Jens Axboe - * - */ -#ifndef SPLICE_H -#define SPLICE_H - -#include - -/* - * 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/trunk/include/linux/sunrpc/svc.h b/trunk/include/linux/sunrpc/svc.h index 129d50f2225c..4a7ae8ab6eb8 100644 --- a/trunk/include/linux/sunrpc/svc.h +++ b/trunk/include/linux/sunrpc/svc.h @@ -253,7 +253,7 @@ struct svc_rqst { * determine what device number * to report (real or virtual) */ - int rq_splice_ok; /* turned off in gss privacy + int rq_sendfile_ok; /* turned off in gss privacy * to prevent encrypting page * cache pages */ wait_queue_head_t rq_wait; /* synchronization */ diff --git a/trunk/include/linux/usb.h b/trunk/include/linux/usb.h index 56aa2ee21f1b..94bd38a6d947 100644 --- a/trunk/include/linux/usb.h +++ b/trunk/include/linux/usb.h @@ -728,22 +728,6 @@ static inline int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor .idVendor = (vend), .idProduct = (prod), \ .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 diff --git a/trunk/init/Kconfig b/trunk/init/Kconfig index d9d878a3bb46..a9e99f8328ff 100644 --- a/trunk/init/Kconfig +++ b/trunk/init/Kconfig @@ -686,4 +686,6 @@ config STOP_MACHINE Need stop_machine() primitive. endmenu +menu "Block layer" source "block/Kconfig" +endmenu diff --git a/trunk/kernel/relay.c b/trunk/kernel/relay.c index 3b299fb3855c..95db8c79fe8f 100644 --- a/trunk/kernel/relay.c +++ b/trunk/kernel/relay.c @@ -21,7 +21,6 @@ #include #include #include -#include /* list of open channels, for cpu hotplug */ static DEFINE_MUTEX(relay_channels_mutex); @@ -122,7 +121,6 @@ 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) @@ -972,6 +970,43 @@ 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, @@ -1032,159 +1067,19 @@ static ssize_t relay_file_read(struct file *filp, NULL, &desc); } -static void relay_consume_bytes(struct rchan_buf *rbuf, int bytes_consumed) -{ - 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) +static ssize_t relay_file_sendfile(struct file *filp, + loff_t *ppos, + size_t count, + read_actor_t actor, + void *target) { - 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; + 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); } const struct file_operations relay_file_operations = { @@ -1194,7 +1089,7 @@ const struct file_operations relay_file_operations = { .read = relay_file_read, .llseek = no_llseek, .release = relay_file_release, - .splice_read = relay_file_splice_read, + .sendfile = relay_file_sendfile, }; EXPORT_SYMBOL_GPL(relay_file_operations); diff --git a/trunk/mm/filemap.c b/trunk/mm/filemap.c index c6ebd9f912ab..d1d9814f99dd 100644 --- a/trunk/mm/filemap.c +++ b/trunk/mm/filemap.c @@ -1245,6 +1245,26 @@ 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/trunk/mm/filemap_xip.c b/trunk/mm/filemap_xip.c index 65ffc321f0c0..fa360e566d88 100644 --- a/trunk/mm/filemap_xip.c +++ b/trunk/mm/filemap_xip.c @@ -159,6 +159,28 @@ 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/trunk/mm/shmem.c b/trunk/mm/shmem.c index 0493e4d0bcaa..b6aae2b33393 100644 --- a/trunk/mm/shmem.c +++ b/trunk/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_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. + * 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. */ repeat: if (!filepage) @@ -1485,18 +1485,9 @@ static const struct inode_operations shmem_symlink_inode_operations; static const struct inode_operations shmem_symlink_inline_operations; /* - * 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. + * Normally tmpfs makes no use of shmem_prepare_write, but it + * lets a tmpfs file be used read-write below the loop driver. */ -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) { @@ -1720,6 +1711,25 @@ 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); @@ -2376,7 +2386,6 @@ 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 @@ -2390,8 +2399,7 @@ static const struct file_operations shmem_file_operations = { .read = shmem_file_read, .write = shmem_file_write, .fsync = simple_sync_file, - .splice_read = generic_file_splice_read, - .splice_write = generic_file_splice_write, + .sendfile = shmem_file_sendfile, #endif }; diff --git a/trunk/net/sunrpc/auth_gss/svcauth_gss.c b/trunk/net/sunrpc/auth_gss/svcauth_gss.c index c094583386fd..099a983797da 100644 --- a/trunk/net/sunrpc/auth_gss/svcauth_gss.c +++ b/trunk/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_splice_ok = 0; + rqstp->rq_sendfile_ok = 0; priv_len = svc_getnl(&buf->head[0]); if (rqstp->rq_deferred) { diff --git a/trunk/net/sunrpc/svc.c b/trunk/net/sunrpc/svc.c index 55ea6df069de..e673ef993904 100644 --- a/trunk/net/sunrpc/svc.c +++ b/trunk/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_splice_ok = 1; + rqstp->rq_sendfile_ok = 1; /* tcp needs a space for the record length... */ if (rqstp->rq_prot == IPPROTO_TCP) svc_putnl(resv, 0); diff --git a/trunk/sound/ppc/beep.c b/trunk/sound/ppc/beep.c index a1aa89f2faf3..5f38f670102c 100644 --- a/trunk/sound/ppc/beep.c +++ b/trunk/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 = input_get_drvdata(dev); + chip = dev->private; 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->dev.parent = &chip->pdev->dev; - input_set_drvdata(input_dev, chip); + input_dev->private = chip; + input_dev->cdev.dev = &chip->pdev->dev; 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)