# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet v2.6.0-test1 -> 1.1534 # drivers/pci/hotplug/acpiphp_pci.c 1.7 -> 1.8 # arch/sparc64/kernel/pci.c 1.30 -> 1.31 # sound/oss/ac97_plugin_ad1980.c 1.1 -> 1.2 # drivers/scsi/arm/oak.c 1.20 -> 1.22 # arch/ia64/kernel/fsys.S 1.16 -> 1.17 # drivers/scsi/megaraid.c 1.50 -> 1.51 # drivers/block/ps2esdi.c 1.65 -> 1.66 # drivers/input/keyboard/sunkbd.c 1.12 -> 1.13 # drivers/scsi/imm.h 1.10 -> 1.11 # drivers/ide/legacy/hd.c 1.20 -> 1.21 # include/asm-ppc/hardirq.h 1.21 -> 1.22 # drivers/media/common/saa7146_vbi.c 1.3 -> 1.5 # drivers/block/swim_iop.c 1.24 -> 1.25 # include/linux/dm-ioctl.h 1.2 -> 1.3 # drivers/block/as-iosched.c 1.5 -> 1.8 # drivers/scsi/ips.c 1.60 -> 1.61 # arch/mips64/kernel/setup.c 1.7 -> 1.8 # drivers/usb/misc/usblcd.c 1.10 -> 1.11 # include/asm-ppc/processor.h 1.31 -> 1.32 # drivers/media/dvb/frontends/Makefile 1.5 -> 1.7 # drivers/media/dvb/ttpci/av7110.h 1.2 -> 1.3 # drivers/usb/storage/protocol.c 1.11 -> 1.12 # include/asm-v850/teg.h 1.2 -> 1.4 # drivers/mtd/mtd_blkdevs.c 1.4 -> 1.5 # sound/oss/emu10k1/8010.h 1.3 -> 1.4 # net/atm/signaling.h 1.1 -> 1.2 # drivers/s390/net/qeth.h 1.1 -> 1.2 # drivers/scsi/pas16.c 1.11 -> 1.13 # include/asm-generic/sections.h 1.1 -> 1.2 # include/net/ip_vs.h 1.3 -> 1.4 # kernel/ksyms.c 1.209 -> 1.210 # drivers/cdrom/gscd.c 1.33 -> 1.34 # include/asm-ppc/uaccess.h 1.8 -> 1.9 # drivers/char/watchdog/i810-tco.c 1.17 -> 1.19 # include/linux/nfs_mount.h 1.3 -> 1.4 # arch/sparc/kernel/setup.c 1.19 -> 1.20 # drivers/usb/serial/ipaq.h 1.8 -> 1.9 # arch/parisc/kernel/ioctl32.c 1.12 -> 1.13 # include/media/saa7146.h 1.3 -> 1.4 # drivers/pci/quirks.c 1.29 -> 1.30 # drivers/scsi/pci2220i.c 1.23 -> 1.24 # arch/ppc/mm/mem_pieces.c 1.6 -> 1.7 # include/linux/elevator.h 1.25 -> 1.26 # drivers/net/irda/vlsi_ir.c 1.17 -> 1.18 # drivers/scsi/scsi_pc98.c 1.3 -> 1.4 # include/scsi/scsi_device.h 1.2 -> 1.3 # drivers/usb/storage/jumpshot.c 1.18 -> 1.19 # drivers/message/fusion/mptctl.c 1.15 -> 1.16 # arch/ia64/Makefile 1.55 -> 1.56 # drivers/scsi/oktagon_esp.c 1.10 -> 1.11 # drivers/telephony/ixj.c 1.24 -> 1.25 # arch/i386/kernel/cpu/mtrr/main.c 1.28 -> 1.29 # drivers/scsi/aha152x.c 1.32 -> 1.34 # drivers/block/ioctl.c 1.55 -> 1.57 # drivers/scsi/fcal.c 1.11 -> 1.12 # drivers/scsi/hosts.c 1.80 -> 1.83 # drivers/scsi/cpqfcTSinit.c 1.39 -> 1.40 # drivers/scsi/aacraid/comminit.c 1.5 -> 1.6 # sound/oss/emu10k1/efxmgr.c 1.5 -> 1.6 # drivers/media/video/mxb.c 1.5 -> 1.7 # drivers/scsi/pc980155.c 1.1 -> 1.2 # drivers/scsi/mac53c94.c 1.5 -> 1.6 # drivers/usb/gadget/net2280.c 1.11 -> 1.12 # drivers/scsi/scsi_proc.c 1.28 -> 1.29 # drivers/scsi/aic7xxx/aic7xxx_osm.c 1.43 -> 1.45 # drivers/char/watchdog/pcwd.c 1.23 -> 1.24 # include/linux/times.h 1.3 -> 1.4 # include/media/saa7146_vv.h 1.3 -> 1.5 # drivers/scsi/jazz_esp.c 1.8 -> 1.9 # drivers/video/vesafb.c 1.32 -> 1.33 # init/do_mounts_initrd.c 1.1 -> 1.2 # drivers/scsi/mac_scsi.c 1.6 -> 1.7 # drivers/scsi/sun3_scsi.c 1.17 -> 1.18 # drivers/scsi/cpqfcTScontrol.c 1.8 -> 1.9 # include/linux/ext3_jbd.h 1.13 -> 1.14 # drivers/usb/host/ohci-hcd.c 1.43 -> 1.44 # arch/s390/kernel/setup.c 1.23 -> 1.24 # drivers/media/dvb/dvb-core/dvb_net.h 1.4 -> 1.5 # drivers/scsi/arm/cumana_1.c 1.19 -> 1.21 # drivers/video/pvr2fb.c 1.14 -> 1.15 # arch/v850/kernel/rte_cb.c 1.4 -> 1.6 # drivers/scsi/lasi700.c 1.12 -> 1.14 # sound/oss/emu10k1/audio.c 1.17 -> 1.18 # drivers/net/wan/comx-hw-comx.c 1.11 -> 1.12 # fs/partitions/nec98.c 1.2 -> 1.3 # fs/umsdos/ioctl.c 1.5 -> 1.6 # kernel/fork.c 1.131 -> 1.134 # include/linux/sched.h 1.155 -> 1.156 # include/asm-v850/ma.h 1.1 -> 1.3 # drivers/block/ll_rw_blk.c 1.192 -> 1.194 # kernel/sys.c 1.50 -> 1.52 # drivers/scsi/ibmmca.c 1.21 -> 1.22 # drivers/scsi/arm/queue.c 1.10 -> 1.11 # drivers/scsi/bvme6000.c 1.6 -> 1.7 # include/linux/hfs_sysdep.h 1.9 -> 1.10 # drivers/video/Makefile 1.85 -> 1.86 # drivers/acpi/utilities/utglobal.c 1.27 -> 1.28 # drivers/md/Kconfig 1.3 -> 1.4 # include/asm-ia64/mmu_context.h 1.13 -> 1.14 # drivers/media/dvb/frontends/alps_bsrv2.c 1.6 -> 1.7 # drivers/media/dvb/ttpci/budget-ci.c 1.3 -> 1.4 # include/linux/serial_core.h 1.24 -> 1.25 # arch/v850/kernel/head.S 1.3 -> 1.4 # drivers/scsi/NCR_Q720.c 1.1 -> 1.3 # arch/h8300/kernel/setup.c 1.1 -> 1.2 # drivers/ieee1394/sbp2.c 1.37 -> 1.38 # include/asm-i386/thread_info.h 1.12 -> 1.13 # arch/sparc64/prom/bootstr.c 1.3 -> 1.4 # drivers/media/dvb/frontends/grundig_29504-401.c 1.5 -> 1.6 # arch/ia64/kernel/setup.c 1.52 -> 1.53 # Documentation/pnp.txt 1.3 -> 1.4 # sound/oss/emu10k1/cardmo.c 1.4 -> 1.5 # fs/proc/proc_misc.c 1.81 -> 1.84 # drivers/media/dvb/ttpci/budget-patch.c 1.3 -> 1.5 # drivers/scsi/NCR_D700.c 1.14 -> 1.16 # sound/isa/cmi8330.c 1.15 -> 1.16 # drivers/media/dvb/ttpci/Makefile 1.1 -> 1.2 # arch/sparc/kernel/process.c 1.28 -> 1.29 # drivers/scsi/dc395x.c 1.8 -> 1.10 # drivers/scsi/sym53c416.c 1.18 -> 1.19 # drivers/block/cpqarray.c 1.77 -> 1.78 # include/asm-v850/nb85e_timer_c.h 1.1 -> 1.2 include/asm-v850/v850e_timer_c.h (moved) # sound/oss/dmasound/dmasound_core.c 1.12 -> 1.13 # drivers/block/floppy.c 1.79 -> 1.80 # drivers/media/dvb/frontends/Kconfig 1.5 -> 1.7 # include/scsi/scsi_host.h 1.2 -> 1.5 # drivers/block/ataflop.c 1.40 -> 1.41 # drivers/cdrom/cdrom.c 1.37 -> 1.38 # drivers/scsi/53c700.c 1.37 -> 1.39 # drivers/pci/hotplug/cpci_hotplug.h 1.2 -> 1.3 # arch/v850/kernel/ma.c 1.3 -> 1.4 # drivers/sbus/char/envctrl.c 1.15 -> 1.16 # drivers/media/dvb/dvb-core/dvb_demux.c 1.6 -> 1.8 # drivers/cdrom/sbpcd.c 1.45 -> 1.46 # include/asm-v850/rte_ma1_cb.h 1.2 -> 1.4 # fs/devfs/base.c 1.95 -> 1.97 # init/main.c 1.104 -> 1.105 # fs/intermezzo/sysctl.c 1.9 -> 1.10 # drivers/scsi/g_NCR5380.c 1.20 -> 1.21 # drivers/usb/class/usblp.c 1.50 -> 1.52 # arch/s390/kernel/entry.S 1.30 -> 1.31 # arch/s390/kernel/entry64.S 1.3 -> 1.4 # arch/mips/momentum/ocelot_c/setup.c 1.1 -> 1.2 # drivers/char/watchdog/machzwd.c 1.18 -> 1.19 # arch/arm26/kernel/setup.c 1.2 -> 1.3 # drivers/media/dvb/dvb-core/dvb_net.c 1.5 -> 1.7 # include/asm-ppc/unistd.h 1.24 -> 1.25 # include/asm-ia64/atomic.h 1.6 -> 1.7 # drivers/scsi/i91uscsi.c 1.5 -> 1.6 # arch/v850/kernel/nb85e_utils.c 1.2 -> 1.3 arch/v850/kernel/v850e_utils.c (moved) # drivers/scsi/scsi_sysfs.c 1.24 -> 1.26 # drivers/acpi/executer/exutils.c 1.20 -> 1.21 # fs/cifs/cifsglob.h 1.11 -> 1.12 # drivers/serial/sunsu.c 1.36 -> 1.37 # arch/ppc/platforms/residual.c 1.10 -> 1.11 # arch/x86_64/mm/init.c 1.20 -> 1.21 # drivers/media/dvb/dvb-core/dvbdev.c 1.12 -> 1.13 # drivers/telephony/Kconfig 1.2 -> 1.3 # sound/oss/emu10k1/midi.h 1.2 -> 1.3 # arch/ia64/kernel/time.c 1.27.1.1 -> 1.29 # drivers/acorn/block/mfmhd.c 1.50 -> 1.51 # include/asm-v850/sim85e2c.h 1.2 -> 1.3 # drivers/block/Kconfig 1.6 -> 1.8 # include/linux/blkdev.h 1.116 -> 1.118 # drivers/scsi/NCR53C9x.c 1.25 -> 1.26 # net/ipv6/xfrm6_policy.c 1.9 -> 1.10 # kernel/time.c 1.15 -> 1.16 # drivers/net/fc/iph5526.c 1.26 -> 1.27 # include/acpi/platform/acenv.h 1.17 -> 1.18 # drivers/block/nbd.c 1.64 -> 1.66 # drivers/media/dvb/dvb-core/dvb_frontend.c 1.6 -> 1.7 # drivers/usb/net/ax8817x.c 1.2 -> 1.3 # drivers/block/cciss_scsi.c 1.16 -> 1.17 # drivers/acpi/tables/tbinstal.c 1.19 -> 1.20 # fs/jffs2/Makefile 1.7 -> 1.8 # sound/oss/emu10k1/irqmgr.h 1.3 -> 1.4 # sound/oss/btaudio.c 1.16 -> 1.17 # drivers/serial/core.c 1.67 -> 1.68 # drivers/net/wan/sdladrv.c 1.8 -> 1.9 # drivers/scsi/ips.h 1.29 -> 1.30 # arch/mips/sibyte/cfe/setup.c 1.1 -> 1.2 # drivers/cdrom/optcd.c 1.29 -> 1.30 # drivers/scsi/sr.c 1.85 -> 1.87 # drivers/scsi/aha1740.c 1.22 -> 1.26 # drivers/media/dvb/frontends/alps_tdlb7.c 1.5 -> 1.6 # drivers/char/ftape/lowlevel/fdc-io.c 1.9 -> 1.10 # kernel/suspend.c 1.41 -> 1.42 # drivers/scsi/scsi.h 1.88 -> 1.89 # include/asm-generic/percpu.h 1.7 -> 1.9 # arch/arm/mach-clps711x/autcpu12.c 1.4 -> 1.5 # arch/ia64/kernel/entry.S 1.44 -> 1.46 # drivers/usb/storage/usb.c 1.73 -> 1.74 # drivers/scsi/ini9100u.c 1.16 -> 1.17 # drivers/net/wan/syncppp.c 1.13 -> 1.14 # include/asm-v850/processor.h 1.5 -> 1.6 # drivers/char/nwbutton.h 1.2 -> 1.3 # arch/m68k/mm/sun3mmu.c 1.6 -> 1.7 # net/ipv4/ipvs/Kconfig 1.2 -> 1.3 # drivers/md/dm-ioctl.c 1.27 -> 1.30 # arch/mips/mm/fault.c 1.6 -> 1.7 # drivers/usb/image/scanner.c 1.62 -> 1.65 # drivers/net/ni65.c 1.16 -> 1.17 # drivers/scsi/scsi_module.c 1.4 -> 1.5 # drivers/scsi/mvme147.c 1.6 -> 1.7 # drivers/pci/pci.c 1.57 -> 1.58 # arch/mips/momentum/ocelot_g/setup.c 1.1 -> 1.2 # drivers/scsi/mca_53c9x.c 1.8 -> 1.9 # sound/oss/Makefile 1.22 -> 1.24 # drivers/char/ftape/lowlevel/ftape-calibr.c 1.4 -> 1.5 # fs/cifs/transport.c 1.13 -> 1.14 # net/atm/proc.c 1.20 -> 1.21 # drivers/md/md.c 1.173 -> 1.174 # drivers/scsi/ncr53c8xx.c 1.31 -> 1.32 # drivers/scsi/advansys.c 1.34 -> 1.35 # include/asm-v850/anna.h 1.2 -> 1.5 # drivers/scsi/inia100.c 1.24 -> 1.25 # drivers/char/watchdog/shwdt.c 1.13 -> 1.15 # fs/jbd/transaction.c 1.70 -> 1.73 # net/atm/pvc.c 1.13 -> 1.14 # drivers/parisc/led.c 1.9 -> 1.10 # arch/v850/kernel/nb85e_intc.c 1.3 -> 1.4 arch/v850/kernel/v850e_intc.c (moved) # mm/bootmem.c 1.18 -> 1.19 # drivers/usb/serial/visor.c 1.63 -> 1.64 # drivers/scsi/u14-34f.c 1.29 -> 1.30 # drivers/media/dvb/Kconfig 1.2 -> 1.3 # drivers/media/dvb/dvb-core/dvbdev.h 1.6 -> 1.8 # sound/oss/emu10k1/hwaccess.c 1.4 -> 1.5 # include/asm-v850/nb85e_timer_d.h 1.2 -> 1.3 include/asm-v850/v850e_timer_d.h (moved) # fs/intermezzo/vfs.c 1.22 -> 1.23 # drivers/media/dvb/ttpci/budget-core.c 1.3 -> 1.4 # kernel/extable.c 1.7 -> 1.8 # drivers/pci/hotplug/acpiphp_glue.c 1.15 -> 1.16 # arch/i386/kernel/io_apic.c 1.75 -> 1.76 # fs/ext3/acl.c 1.12 -> 1.13 # arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c 1.1 -> 1.2 # drivers/acorn/block/fd1772.c 1.36 -> 1.37 # drivers/usb/storage/sddr55.c 1.8 -> 1.9 # drivers/scsi/pluto.c 1.12 -> 1.13 # drivers/cdrom/sonycd535.c 1.35 -> 1.36 # arch/sparc64/kernel/setup.c 1.38 -> 1.39 # include/asm-v850/machdep.h 1.2 -> 1.4 # sound/oss/ad1889.c 1.3 -> 1.4 # include/asm-v850/cacheflush.h 1.2 -> 1.3 # include/asm-ia64/processor.h 1.47 -> 1.48 # drivers/pcmcia/ti113x.h 1.11 -> 1.12 # include/linux/nfs_fs.h 1.46 -> 1.47 # drivers/scsi/aacraid/commctrl.c 1.2 -> 1.3 # drivers/scsi/aic7xxx/aic7xxx_osm.h 1.49 -> 1.50 # drivers/block/swim3.c 1.28 -> 1.29 # drivers/media/video/Makefile 1.18 -> 1.19 # sound/oss/emu10k1/hwaccess.h 1.8 -> 1.9 # drivers/block/floppy98.c 1.8 -> 1.9 # arch/sparc64/mm/init.c 1.46 -> 1.48 # drivers/scsi/fd_mcs.c 1.17 -> 1.18 # drivers/scsi/amiga7xx.c 1.6 -> 1.7 # drivers/scsi/fastlane.c 1.10 -> 1.11 # include/linux/ide.h 1.60 -> 1.61 # drivers/scsi/nsp32.c 1.15 -> 1.17 # arch/sparc64/kernel/head.S 1.17 -> 1.18 # net/sunrpc/clnt.c 1.39 -> 1.40 # drivers/scsi/arm/fas216.c 1.21 -> 1.23 # drivers/scsi/aacraid/linit.c 1.19 -> 1.20 # drivers/char/ftape/zftape/zftape-init.c 1.18 -> 1.19 # drivers/net/wireless/ray_cs.c 1.18 -> 1.19 # drivers/acpi/tables.c 1.13 -> 1.14 # drivers/usb/storage/transport.h 1.28 -> 1.29 # drivers/usb/image/scanner.h 1.36 -> 1.38 # drivers/acpi/tables/tbconvrt.c 1.23 -> 1.24 # drivers/scsi/atp870u.c 1.23 -> 1.24 # net/atm/br2684.c 1.3 -> 1.4 # drivers/message/fusion/mptscsih.c 1.24 -> 1.25 # net/netsyms.c 1.87 -> 1.88 # drivers/media/video/dpc7146.c 1.3 -> 1.5 # net/ipv6/xfrm6_state.c 1.6 -> 1.7 # drivers/pci/hotplug/Kconfig 1.9 -> 1.10 # drivers/usb/serial/usb-serial.c 1.83 -> 1.84 # drivers/scsi/aic7xxx_old.c 1.50 -> 1.51 # include/asm-ia64/system.h 1.39 -> 1.40 # include/asm-ia64/tlb.h 1.15 -> 1.16 # sound/isa/es18xx.c 1.18 -> 1.19 # arch/ia64/kernel/module.c 1.7 -> 1.8 # drivers/usb/gadget/zero.c 1.6 -> 1.7 # drivers/char/watchdog/softdog.c 1.17 -> 1.18 # drivers/fc4/fcp_impl.h 1.2 -> 1.3 # include/linux/usb.h 1.81 -> 1.82 # drivers/pci/hotplug/cpci_hotplug_core.c 1.7 -> 1.8 # drivers/scsi/aacraid/aachba.c 1.19 -> 1.20 # drivers/usb/storage/protocol.h 1.6 -> 1.7 # drivers/scsi/seagate.c 1.20 -> 1.21 # include/asm-v850/rte_cb.h 1.3 -> 1.4 # include/asm-v850/asm.h 1.3 -> 1.4 # arch/ia64/pci/pci.c 1.35 -> 1.36 # arch/ia64/hp/sim/simscsi.c 1.14 -> 1.15 # fs/binfmt_elf.c 1.49 -> 1.50 # drivers/scsi/blz2060.c 1.9 -> 1.10 # drivers/s390/block/dasd.c 1.63 -> 1.64 # arch/v850/Kconfig 1.15 -> 1.16 # drivers/scsi/sg.c 1.59 -> 1.60 # arch/ia64/kernel/ia64_ksyms.c 1.32 -> 1.33 # drivers/scsi/aacraid/dpcsup.c 1.3 -> 1.4 # drivers/sbus/char/jsflash.c 1.30 -> 1.31 # drivers/usb/usb-skeleton.c 1.39 -> 1.40 # drivers/pcmcia/ricoh.h 1.7 -> 1.8 # drivers/md/dm.h 1.7 -> 1.9 # net/sunrpc/auth_gss/auth_gss.c 1.9 -> 1.10 # drivers/char/ip2/i2os.h 1.2 -> 1.3 # drivers/scsi/sr_vendor.c 1.11 -> 1.12 # drivers/ide/Kconfig 1.16 -> 1.17 # drivers/usb/net/catc.c 1.27 -> 1.28 # drivers/block/amiflop.c 1.41 -> 1.42 # drivers/cdrom/mcdx.c 1.32 -> 1.33 # sound/oss/emu10k1/passthrough.c 1.8 -> 1.9 # arch/s390/kernel/s390_ext.c 1.4 -> 1.5 # drivers/block/genhd.c 1.90 -> 1.91 # include/linux/pci.h 1.99 -> 1.102 # drivers/s390/net/qeth_mpc.h 1.1 -> 1.2 # arch/ia64/kernel/iosapic.c 1.28 -> 1.29 # drivers/scsi/osst.c 1.47 -> 1.48 # arch/i386/kernel/setup.c 1.86 -> 1.88 # drivers/char/watchdog/sc520_wdt.c 1.9 -> 1.10 # drivers/usb/core/hcd-pci.c 1.15 -> 1.17 # drivers/scsi/NCR53c406a.c 1.23 -> 1.24 # drivers/scsi/AM53C974.c 1.15 -> 1.16 # arch/um/drivers/ubd_kern.c 1.32 -> 1.33 # drivers/char/ip2.c 1.6 -> 1.7 # include/asm-v850/nb85e_utils.h 1.1 -> 1.2 include/asm-v850/v850e_utils.h (moved) # arch/mips/sibyte/swarm/setup.c 1.1 -> 1.2 # drivers/serial/Makefile 1.17 -> 1.18 # arch/ia64/kernel/acpi.c 1.43 -> 1.44 # drivers/scsi/mac_esp.c 1.12 -> 1.13 # include/asm-v850/nb85e_cache.h 1.4 -> 1.5 include/asm-v850/v850e_cache.h (moved) # fs/nfs/nfs3proc.c 1.25 -> 1.26 # include/asm-v850/nb85e.h 1.1 -> 1.2 include/asm-v850/v850e.h (moved) # drivers/scsi/scsi_syms.c 1.42 -> 1.44 # drivers/usb/storage/isd200.c 1.31 -> 1.32 # arch/ppc64/kernel/XmPciLpEvent.c 1.2 -> 1.3 # drivers/char/ftape/lowlevel/ftape-format.c 1.1 -> 1.2 # arch/sparc64/kernel/time.c 1.42 -> 1.43 # drivers/usb/storage/scsiglue.c 1.49 -> 1.50 # drivers/scsi/scsi_lib.c 1.99 -> 1.104 # include/linux/tty.h 1.18 -> 1.19 # net/xfrm/xfrm_policy.c 1.39 -> 1.40 # kernel/compat.c 1.18 -> 1.19 # net/core/dev.c 1.89 -> 1.90 # drivers/ide/ide-dma.c 1.17 -> 1.18 # drivers/media/common/saa7146_fops.c 1.4 -> 1.5 # arch/v850/kernel/nb85e_timer_d.c 1.1 -> 1.2 arch/v850/kernel/v850e_timer_d.c (moved) # drivers/usb/core/usb.c 1.127 -> 1.128 # drivers/media/dvb/frontends/ves1820.c 1.6 -> 1.7 # arch/v850/kernel/anna.c 1.3 -> 1.6 # sound/oss/emu10k1/passthrough.h 1.4 -> 1.5 # drivers/s390/cio/device_fsm.c 1.6 -> 1.7 # arch/h8300/mm/init.c 1.1 -> 1.2 # drivers/media/dvb/dvb-core/dvb_functions.h 1.1 -> 1.2 # drivers/scsi/aha1542.c 1.29 -> 1.30 # drivers/scsi/arm/arxescsi.c 1.21 -> 1.22 # drivers/scsi/arm/acornscsi.c 1.32 -> 1.34 # drivers/scsi/ultrastor.c 1.19 -> 1.20 # arch/v850/kernel/intv.S 1.3 -> 1.4 # drivers/scsi/pcmcia/qlogic_stub.c 1.15 -> 1.17 # include/linux/namespace.h 1.5 -> 1.7 # drivers/scsi/aic7xxx/aiclib.c 1.5 -> 1.6 # sound/oss/emu10k1/cardmi.c 1.5 -> 1.6 # drivers/scsi/a2091.c 1.10 -> 1.11 # drivers/usb/net/usbnet.c 1.58 -> 1.59 # drivers/usb/storage/scsiglue.h 1.6 -> 1.7 # arch/i386/kernel/cpu/mtrr/cyrix.c 1.3 -> 1.4 # arch/v850/kernel/sim85e2c.c 1.2 -> 1.3 arch/v850/kernel/sim85e2.c (moved) # fs/cifs/cifsfs.c 1.22 -> 1.23 # drivers/pnp/isapnp/core.c 1.39 -> 1.40 # drivers/s390/cio/chsc.c 1.12 -> 1.13 # include/asm-v850/fpga85e2c.h 1.2 -> 1.4 # usr/Makefile 1.8 -> 1.9 # fs/nfsd/nfssvc.c 1.40 -> 1.41 # drivers/media/dvb/ttpci/budget.c 1.3 -> 1.5 # drivers/scsi/aic7xxx/aic79xx_osm.c 1.47 -> 1.48 # net/ipv6/tcp_ipv6.c 1.64 -> 1.66 # arch/ppc/platforms/4xx/beech.c 1.1 -> 1.2 # fs/ext3/xattr.c 1.22 -> 1.24 # net/xfrm/xfrm_user.c 1.31 -> 1.32 # arch/mips/vr41xx/tanbac-tb0229/setup.c 1.1 -> 1.2 # drivers/usb/media/dabusb.c 1.29 -> 1.30 # drivers/pcmcia/hd64465_ss.c 1.13 -> 1.14 # drivers/fc4/fc.c 1.11 -> 1.12 # arch/sparc/mm/srmmu.c 1.34 -> 1.35 # drivers/s390/block/dasd_ioctl.c 1.17 -> 1.18 # arch/ppc/platforms/pmac_cpufreq.c 1.4 -> 1.5 # Documentation/magic-number.txt 1.4 -> 1.6 # drivers/usb/core/hcd.c 1.67 -> 1.68 # drivers/scsi/dmx3191d.c 1.13 -> 1.14 # drivers/media/dvb/Makefile 1.3 -> 1.4 # arch/ppc/platforms/4xx/walnut.c 1.8 -> 1.9 # arch/ppc64/mm/init.c 1.47 -> 1.48 # drivers/scsi/aacraid/sa.c 1.4 -> 1.5 # arch/m68k/mm/motorola.c 1.6 -> 1.7 # drivers/scsi/ppa.c 1.24 -> 1.25 # sound/oss/emu10k1/voicemgr.c 1.4 -> 1.5 # sound/oss/emu10k1/voicemgr.h 1.4 -> 1.5 # drivers/scsi/scsicam.c 1.13 -> 1.14 # drivers/char/agp/i460-agp.c 1.25 -> 1.26 # drivers/scsi/pcmcia/fdomain_stub.c 1.16 -> 1.18 # drivers/char/pcxx.c 1.16 -> 1.17 # fs/bio.c 1.48 -> 1.49 # MAINTAINERS 1.155 -> 1.156 # drivers/ieee1394/amdtp.c 1.14 -> 1.15 # drivers/usb/net/rtl8150.c 1.28 -> 1.29 # drivers/pcmcia/yenta_socket.c 1.33 -> 1.34 # drivers/s390/cio/qdio.c 1.7 -> 1.8 # drivers/media/common/saa7146_hlp.c 1.3 -> 1.5 # drivers/scsi/scsi_debug.c 1.39 -> 1.42 # include/asm-v850/ma1.h 1.1 -> 1.2 # drivers/block/cryptoloop.c 1.1 -> 1.2 # net/atm/lec.c 1.29 -> 1.31 # drivers/char/istallion.c 1.29 -> 1.30 # drivers/scsi/aic7xxx/aic79xx_osm.h 1.33 -> 1.34 # drivers/cdrom/mcd.c 1.32 -> 1.33 # drivers/acpi/tables/tbrsdt.c 1.10 -> 1.11 # drivers/scsi/gdth.c 1.30 -> 1.31 # arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c 1.1 -> 1.2 # drivers/char/watchdog/acquirewdt.c 1.21 -> 1.22 # scripts/ver_linux 1.10 -> 1.11 # fs/lockd/svc.c 1.22 -> 1.23 # arch/v850/vmlinux.lds.S 1.11 -> 1.13 # net/ipv6/esp6.c 1.17 -> 1.18 # drivers/char/watchdog/wdt_pci.c 1.22 -> 1.23 # arch/ppc/platforms/4xx/sycamore.c 1.3 -> 1.4 # drivers/pci/hotplug/cpci_hotplug_pci.c 1.11 -> 1.13 # drivers/usb/class/cdc-acm.c 1.46 -> 1.47 # fs/vfat/namei.c 1.34 -> 1.35 # drivers/scsi/st.c 1.66 -> 1.67 # drivers/scsi/ide-scsi.c 1.26 -> 1.27 # drivers/block/z2ram.c 1.25 -> 1.26 # drivers/usb/storage/usb.h 1.34 -> 1.36 # drivers/media/common/saa7146_video.c 1.4 -> 1.6 # drivers/scsi/eata_pio.c 1.19 -> 1.20 # drivers/acpi/tables/tbget.c 1.19 -> 1.20 # fs/namespace.c 1.48 -> 1.49 # drivers/atm/atmtcp.c 1.10 -> 1.12 # net/atm/svc.c 1.15 -> 1.18 # drivers/scsi/arm/powertec.c 1.28 -> 1.29 # arch/m68knommu/kernel/setup.c 1.5 -> 1.6 # init/do_mounts.h 1.4 -> 1.5 # drivers/scsi/sr_ioctl.c 1.29 -> 1.30 # drivers/scsi/mesh.c 1.9 -> 1.10 # arch/m68k/apollo/dn_ints.c 1.8 -> 1.9 # drivers/media/dvb/ttpci/av7110.c 1.3 -> 1.5 # drivers/scsi/pci2000.c 1.18 -> 1.19 # net/atm/pppoatm.c 1.7 -> 1.8 # arch/m68knommu/mm/init.c 1.1 -> 1.2 # Makefile 1.417 -> 1.418 # arch/s390/kernel/compat_ioctl.c 1.4 -> 1.5 # arch/mips/ramdisk/Makefile 1.1 -> 1.2 # arch/v850/kernel/teg.c 1.1 -> 1.2 # drivers/cdrom/sjcd.c 1.26 -> 1.27 # drivers/scsi/zalon.c 1.4 -> 1.6 # drivers/scsi/sym53c8xx.c 1.37 -> 1.39 # drivers/block/paride/pf.c 1.40 -> 1.42 # net/sunrpc/xprt.c 1.62 -> 1.63 # drivers/scsi/blz1230.c 1.10 -> 1.11 # drivers/scsi/wd33c93.c 1.14 -> 1.15 # drivers/scsi/qlogicpti.c 1.18 -> 1.19 # net/ipv6/ah6.c 1.18 -> 1.19 # drivers/scsi/psi240i.c 1.12 -> 1.13 # drivers/acpi/processor.c 1.39 -> 1.40 # include/asm-ia64/elf.h 1.12 -> 1.13 # drivers/scsi/scsi_priv.h 1.15 -> 1.17 # net/wanrouter/wanmain.c 1.16 -> 1.17 # drivers/scsi/aha1542.h 1.8 -> 1.9 # drivers/char/watchdog/sbc60xxwdt.c 1.24 -> 1.25 # drivers/cdrom/cdu31a.c 1.36 -> 1.37 # drivers/char/watchdog/i810-tco.h 1.4 -> 1.6 # drivers/scsi/sun3x_esp.c 1.11 -> 1.12 # arch/v850/kernel/nb85e_cache.c 1.1 -> 1.2 arch/v850/kernel/v850e_cache.c (moved) # include/asm-v850/stat.h 1.4 -> 1.5 # sound/oss/emu10k1/mixer.c 1.9 -> 1.10 # drivers/scsi/dec_esp.c 1.8 -> 1.9 # drivers/scsi/fdomain.c 1.23 -> 1.24 # init/do_mounts_rd.c 1.5 -> 1.6 # fs/partitions/efi.h 1.4 -> 1.5 # drivers/scsi/constants.c 1.11 -> 1.12 # drivers/scsi/aacraid/commsup.c 1.5 -> 1.6 # drivers/message/i2o/i2o_block.c 1.54 -> 1.55 # drivers/media/common/saa7146_core.c 1.4 -> 1.5 # drivers/media/dvb/frontends/nxt6000.c 1.2 -> 1.3 # drivers/ide/legacy/hd98.c 1.4 -> 1.5 # drivers/usb/net/kaweth.c 1.49 -> 1.50 # arch/ppc64/kernel/prom.c 1.29 -> 1.30 # drivers/scsi/arm/cumana_2.c 1.29 -> 1.30 # drivers/scsi/dtc.c 1.11 -> 1.12 # net/xfrm/xfrm_state.c 1.32 -> 1.33 # kernel/module.c 1.87 -> 1.90 # arch/s390/mm/init.c 1.16 -> 1.17 # drivers/scsi/qlogicfc.c 1.33 -> 1.34 # drivers/scsi/in2000.c 1.21 -> 1.22 # drivers/usb/gadget/net2280.h 1.2 -> 1.3 # include/asm-ppc/pci.h 1.19 -> 1.20 # drivers/net/wan/sdlamain.c 1.18 -> 1.19 # net/atm/common.h 1.9 -> 1.12 # drivers/scsi/a3000.c 1.9 -> 1.10 # drivers/net/pcmcia/Kconfig 1.5 -> 1.6 # arch/i386/pci/visws.c 1.10 -> 1.12 # net/ipv4/ip_gre.c 1.27 -> 1.28 # drivers/s390/cio/device.c 1.8 -> 1.9 # drivers/s390/block/xpram.c 1.42 -> 1.43 # arch/ia64/ia32/ia32_ioctl.c 1.12 -> 1.13 # drivers/acpi/tables/tbxfroot.c 1.17 -> 1.18 # arch/ppc64/kernel/iSeries_irq.c 1.2 -> 1.3 # net/ipv6/route.c 1.50 -> 1.51 # net/ipv4/tcp_input.c 1.44 -> 1.45 # include/acpi/acconfig.h 1.40 -> 1.41 # drivers/usb/class/bluetty.c 1.46 -> 1.47 # drivers/char/stallion.c 1.31 -> 1.32 # include/asm-ia64/percpu.h 1.8 -> 1.11 # drivers/scsi/sd.c 1.126 -> 1.129 # drivers/s390/char/tape_block.c 1.5 -> 1.6 # drivers/net/seeq8005.c 1.11 -> 1.12 # arch/m68k/atari/stram.c 1.24 -> 1.25 # arch/ppc/kernel/time.c 1.22 -> 1.23 # arch/i386/mm/init.c 1.50 -> 1.52 # include/asm-v850/system.h 1.4 -> 1.5 # arch/mips/sibyte/sb1250/prom.c 1.1 -> 1.2 # drivers/block/DAC960.c 1.60 -> 1.61 # drivers/s390/block/dasd_genhd.c 1.25 -> 1.27 # drivers/usb/storage/unusual_devs.h 1.48 -> 1.49 # net/atm/signaling.c 1.13 -> 1.17 # fs/nfs/inode.c 1.82 -> 1.84 # drivers/block/elevator.c 1.46 -> 1.48 # mm/slab.c 1.93 -> 1.95 # drivers/md/dm.c 1.24 -> 1.27 # include/linux/module.h 1.66 -> 1.68 # arch/alpha/kernel/irq.c 1.22 -> 1.23 # drivers/scsi/cpqfcTSworker.c 1.16 -> 1.17 # drivers/usb/serial/ftdi_sio.c 1.44 -> 1.45 # drivers/message/i2o/i2o_scsi.c 1.20 -> 1.21 # drivers/media/dvb/ttpci/budget-av.c 1.3 -> 1.5 # include/asm-v850/nb85e_intc.h 1.2 -> 1.3 include/asm-v850/v850e_intc.h (moved) # drivers/scsi/cyberstorm.c 1.9 -> 1.10 # drivers/scsi/scsi_scan.c 1.97 -> 1.99 # drivers/s390/cio/device.h 1.4 -> 1.5 # kernel/sched.c 1.202 -> 1.203 # arch/s390/kernel/compat_linux.c 1.4 -> 1.5 # drivers/block/deadline-iosched.c 1.21 -> 1.22 # drivers/block/paride/pd.c 1.49 -> 1.50 # include/asm-v850/rte_nb85e_cb.h 1.2 -> 1.4 # drivers/char/watchdog/wdt977.c 1.15 -> 1.17 # arch/sh/mm/init.c 1.13 -> 1.14 # drivers/acpi/osl.c 1.40 -> 1.41 # drivers/usb/storage/sddr09.c 1.24 -> 1.25 # sound/oss/emu10k1/cardwo.c 1.10 -> 1.11 # drivers/scsi/sim710.c 1.16 -> 1.18 # arch/v850/kernel/rte_ma1_cb.c 1.4 -> 1.5 # drivers/block/xd.c 1.54 -> 1.55 # drivers/char/busmouse.c 1.8 -> 1.9 # drivers/ide/ide-io.c 1.13 -> 1.15 # drivers/media/dvb/frontends/grundig_29504-491.c 1.5 -> 1.6 # net/atm/mpc.c 1.20 -> 1.22 # drivers/scsi/dpt_i2o.c 1.32 -> 1.33 # arch/ppc/kernel/irq.c 1.29 -> 1.30 # arch/x86_64/mm/numa.c 1.4 -> 1.5 # include/linux/atmdev.h 1.18 -> 1.21 # drivers/scsi/mvme16x.c 1.6 -> 1.7 # drivers/usb/serial/ipaq.c 1.30 -> 1.31 # drivers/scsi/cyberstormII.c 1.9 -> 1.10 # include/asm-v850/as85ep1.h 1.1 -> 1.4 # sound/oss/Kconfig 1.9 -> 1.11 # arch/sparc64/kernel/sparc64_ksyms.c 1.50 -> 1.51 # arch/i386/pci/legacy.c 1.11 -> 1.12 # drivers/media/video/pms.c 1.11 -> 1.12 # drivers/media/dvb/dvb-core/dvb_functions.c 1.2 -> 1.3 # drivers/media/common/Makefile 1.1 -> 1.2 # include/linux/blk.h 1.36 -> 1.37 # drivers/acpi/hardware/hwregs.c 1.24 -> 1.25 # drivers/serial/nb85e_uart.c 1.12 -> 1.13 drivers/serial/v850e_uart.c (moved) # drivers/scsi/ppa.h 1.9 -> 1.10 # include/asm-s390/irq.h 1.9 -> 1.10 # arch/s390/defconfig 1.25 -> 1.26 # drivers/usb/serial/ftdi_sio.h 1.6 -> 1.7 # drivers/net/Kconfig 1.35 -> 1.36 # arch/m68k/mm/init.c 1.10 -> 1.11 # arch/ppc64/boot/Makefile 1.14 -> 1.15 # drivers/scsi/eata.c 1.34 -> 1.35 # drivers/pci/setup-res.c 1.18 -> 1.19 # arch/mips/mm/init.c 1.9 -> 1.10 # drivers/acpi/thermal.c 1.24 -> 1.25 # fs/cifs/CHANGES 1.23 -> 1.24 # arch/m68k/q40/q40ints.c 1.12 -> 1.13 # drivers/net/eql.c 1.9 -> 1.10 # include/asm-s390/siginfo.h 1.5 -> 1.6 # drivers/usb/host/uhci-hcd.c 1.36 -> 1.37 # include/asm-s390/dma.h 1.3 -> 1.4 # drivers/scsi/pcmcia/aha152x_stub.c 1.15 -> 1.17 # arch/sparc64/lib/atomic.S 1.2 -> 1.3 # drivers/scsi/t128.c 1.12 -> 1.13 # sound/oss/ad1816.c 1.11 -> 1.12 # arch/v850/kernel/fpga85e2c.c 1.2 -> 1.4 # net/ipv4/ipvs/ip_vs_ctl.c 1.1 -> 1.2 # fs/cifs/connect.c 1.26 -> 1.27 # drivers/cdrom/cm206.c 1.33 -> 1.34 # arch/alpha/mm/init.c 1.17 -> 1.18 # net/ipv4/ipvs/ip_vs_conn.c 1.3 -> 1.4 # drivers/pci/Makefile 1.33 -> 1.34 # fs/partitions/check.c 1.114 -> 1.116 # arch/ppc/kernel/misc.S 1.44 -> 1.45 # drivers/char/watchdog/ib700wdt.c 1.14 -> 1.15 # drivers/serial/Kconfig 1.12 -> 1.13 # drivers/pci/hotplug.c 1.18 -> 1.20 # drivers/scsi/gvp11.c 1.10 -> 1.11 # drivers/cdrom/aztcd.c 1.29 -> 1.30 # net/ipv6/sit.c 1.26 -> 1.27 # drivers/media/video/Kconfig 1.7 -> 1.8 # net/atm/raw.c 1.4 -> 1.7 # include/asm-sparc64/atomic.h 1.3 -> 1.4 # net/ipv6/addrconf.c 1.57 -> 1.58 # arch/ia64/kernel/perfmon.c 1.52 -> 1.53 # drivers/char/moxa.c 1.24 -> 1.25 # drivers/usb/host/ohci-q.c 1.41 -> 1.42 # drivers/pci/pool.c 1.14 -> 1.15 # drivers/scsi/3w-xxxx.c 1.34 -> 1.35 # fs/lockd/clntlock.c 1.7 -> 1.8 # arch/arm26/mm/init.c 1.3 -> 1.4 # drivers/char/watchdog/indydog.c 1.6 -> 1.7 # include/asm-v850/highres_timer.h 1.1 -> 1.2 # include/linux/netdevice.h 1.45 -> 1.46 # kernel/profile.c 1.4 -> 1.5 # fs/compat_ioctl.c 1.3 -> 1.4 # drivers/scsi/BusLogic.c 1.21 -> 1.22 # drivers/scsi/sgiwd93.c 1.8 -> 1.9 # include/pcmcia/ss.h 1.23 -> 1.24 # arch/ppc/kernel/syscalls.c 1.11 -> 1.12 # arch/v850/kernel/rte_nb85e_cb.c 1.2 -> 1.3 # drivers/usb/misc/usbtest.c 1.16 -> 1.17 # drivers/scsi/arm/ecoscsi.c 1.19 -> 1.21 # include/linux/kernel_stat.h 1.11 -> 1.12 # fs/cifs/TODO 1.6 -> 1.7 # arch/v850/kernel/as85ep1.c 1.2 -> 1.5 # arch/v850/sim85e2c.ld 1.3 -> 1.4 arch/v850/sim85e2.ld (moved) # fs/cifs/misc.c 1.9 -> 1.10 # net/ipv4/ipvs/ip_vs_xmit.c 1.1 -> 1.2 # drivers/scsi/scsi_ioctl.c 1.20 -> 1.21 # drivers/media/common/saa7146_i2c.c 1.3 -> 1.5 # arch/sparc64/mm/fault.c 1.16 -> 1.17 # arch/ia64/scripts/toolchain-flags 1.2 -> 1.3 # drivers/ide/ppc/mpc8xx.c 1.5 -> 1.6 # drivers/block/cciss.c 1.83 -> 1.84 # drivers/parport/parport_pc.c 1.39 -> 1.40 # sound/oss/emu10k1/main.c 1.16 -> 1.18 # drivers/usb/gadget/ether.c 1.5 -> 1.7 # drivers/block/paride/pcd.c 1.34 -> 1.35 # net/atm/clip.c 1.18 -> 1.20 # drivers/pci/setup-bus.c 1.17 -> 1.18 # drivers/net/ni65.h 1.2 -> 1.3 # sound/oss/emu10k1/efxmgr.h 1.5 -> 1.6 # include/scsi/scsi_request.h 1.3 -> 1.4 # drivers/scsi/qlogicisp.c 1.21 -> 1.22 # drivers/md/dm-table.c 1.19 -> 1.20 # arch/ia64/kernel/ptrace.c 1.29 -> 1.30 # drivers/scsi/esp.c 1.30 -> 1.31 # drivers/usb/net/pegasus.c 1.50 -> 1.51 # drivers/scsi/pcmcia/nsp_cs.c 1.23 -> 1.25 # drivers/s390/cio/cio.c 1.14 -> 1.16 # drivers/scsi/wd7000.c 1.27 -> 1.28 # include/asm-v850/nb85e_uart.h 1.2 -> 1.3 include/asm-v850/v850e_uart.h (moved) # drivers/serial/sunzilog.c 1.32 -> 1.33 # arch/ia64/kernel/init_task.c 1.10 -> 1.11 # drivers/scsi/arm/eesox.c 1.29 -> 1.30 # arch/ia64/kernel/smp.c 1.25 -> 1.26 # include/asm-i386/hw_irq.h 1.21 -> 1.23 # drivers/usb/image/hpusbscsi.c 1.31 -> 1.33 # drivers/scsi/imm.c 1.23 -> 1.24 # arch/v850/kernel/gbus_int.c 1.6 -> 1.8 # drivers/block/acsi.c 1.51 -> 1.52 # drivers/char/ip2/i2lib.c 1.7 -> 1.8 # include/linux/elfcore.h 1.3 -> 1.4 # drivers/block/umem.c 1.39 -> 1.40 # drivers/scsi/sym53c8xx_2/sym_glue.h 1.9 -> 1.10 # drivers/scsi/qla1280.c 1.38 -> 1.40 # include/linux/loop.h 1.16 -> 1.17 # drivers/scsi/qlogicfas.c 1.22 -> 1.24 # drivers/scsi/atari_scsi.c 1.9 -> 1.10 # net/ipv6/xfrm6_input.c 1.11 -> 1.12 # arch/v850/kernel/Makefile 1.7 -> 1.8 # include/asm-v850/ptrace.h 1.2 -> 1.3 # fs/nfs/nfs3xdr.c 1.25 -> 1.26 # include/asm-ppc/ipc.h 1.4 -> 1.5 # drivers/usb/image/microtek.c 1.32 -> 1.34 # net/ipv4/ipip.c 1.30 -> 1.31 # drivers/s390/net/qeth.c 1.1 -> 1.2 # drivers/char/ip2main.c 1.39 -> 1.40 # include/linux/nfs_fs_sb.h 1.10 -> 1.11 # drivers/scsi/aacraid/rx.c 1.3 -> 1.4 # sound/oss/emu10k1/recmgr.c 1.4 -> 1.5 # arch/v850/kernel/highres_timer.c 1.1 -> 1.2 # drivers/scsi/53c7xx.c 1.18 -> 1.19 # drivers/scsi/sun3_scsi_vme.c 1.6 -> 1.7 # include/asm-v850/entry.h 1.2 -> 1.3 # include/asm-s390/dma-mapping.h 1.1 -> 1.2 # drivers/usb/storage/debug.h 1.6 -> 1.7 # drivers/scsi/sym53c8xx_2/sym_glue.c 1.26 -> 1.27 # net/atm/common.c 1.32 -> 1.38 # drivers/scsi/tmscsim.c 1.21 -> 1.22 # (new) -> 1.1 drivers/media/video/hexium_orion.c # (new) -> 1.1 drivers/media/dvb/ttusb-budget/Kconfig # (new) -> 1.1 drivers/media/dvb/frontends/tda1004x.c # (new) -> 1.1 include/asm-v850/v850e2.h # (new) -> 1.1 drivers/media/dvb/ttusb-dec/ttusb_dec.h # (new) -> 1.1 drivers/md/dm-ioctl-v4.c # (new) -> 1.1 drivers/media/dvb/frontends/mt312.h # (new) -> 1.1 include/asm-v850/sim85e2s.h # (new) -> 1.1 include/linux/dm-ioctl-v4.h # (new) -> 1.2 drivers/media/dvb/frontends/mt312.c # (new) -> 1.2 drivers/media/dvb/b2c2/Makefile # (new) -> 1.1 drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h # (new) -> 1.1 include/asm-v850/v850e_uartb.h # (new) -> 1.1 drivers/media/dvb/ttpci/ttpci-eeprom.h # (new) -> 1.1 drivers/media/dvb/ttusb-dec/Kconfig # (new) -> 1.1 drivers/pci/remove.c # (new) -> 1.1 include/asm-sparc64/sections.h # (new) -> 1.1 sound/oss/hal2.h # (new) -> 1.1 drivers/media/video/hexium_gemini.c # (new) -> 1.1 include/asm-v850/serial.h # (new) -> 1.1 include/asm-v850/rte_me2_cb.h # (new) -> 1.1 arch/v850/rte_me2_cb.ld # (new) -> 1.1 drivers/media/video/hexium_gemini.h # (new) -> 1.1 arch/ia64/scripts/check-model.c # (new) -> 1.1 arch/v850/kernel/me2.c # (new) -> 1.1 include/asm-i386/local.h # (new) -> 1.1 drivers/media/dvb/ttusb-dec/fdump.c # (new) -> 1.1 arch/v850/kernel/rte_me2_cb.c # (new) -> 1.1 drivers/media/dvb/ttusb-dec/Makefile # (new) -> 1.1 include/asm-sparc64/local.h # (new) -> 1.1 drivers/media/dvb/b2c2/Kconfig # (new) -> 1.1 arch/v850/kernel/v850e2_cache.c # (new) -> 1.1 include/asm-v850/v850e2_cache.h # (new) -> 1.1 drivers/media/dvb/ttpci/ttpci-eeprom.c # (new) -> 1.1 drivers/media/common/saa7146_vv_ksyms.c # (new) -> 1.2 drivers/media/dvb/b2c2/skystar2.c # (new) -> 1.1 sound/oss/hal2.c # (new) -> 1.2 sound/oss/harmony.c # (new) -> 1.1 drivers/media/video/hexium_orion.h # (new) -> 1.1 include/asm-generic/local.h # (new) -> 1.1 include/asm-v850/sim85e2.h # (new) -> 1.1 include/asm-v850/v850e_uarta.h # (new) -> 1.2 include/asm-ia64/local.h # (new) -> 1.2 sound/oss/kahlua.c # (new) -> 1.1 drivers/media/dvb/ttusb-dec/ttusb_dec.c # (new) -> 1.1 drivers/media/video/hexium.h # (new) -> 1.1 include/asm-v850/me2.h # (new) -> 1.1 drivers/media/dvb/ttusb-dec/dec2000_frontend.c # (new) -> 1.1 drivers/md/dm-ioctl-v1.c # (new) -> 1.1 drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c # (new) -> 1.1 drivers/media/dvb/ttusb-budget/Makefile # (new) -> 1.1 include/linux/dm-ioctl-v1.h # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/07/13 torvalds@home.osdl.org 1.1455.2.4 # Linux 2.6.0-test1 # # First "test" kernel. Same naming we used for 2.4.0 - there it took # from May to December to get to the real version. Let's see if we # can do it faster this time. # -------------------------------------------- # 03/07/13 davem@kernel.bkbits.net 1.1455.1.3 # Merge davem@nuts.ninka.net:/home/davem/src/BK/net-2.5 # into kernel.bkbits.net:/home/davem/net-2.5 # -------------------------------------------- # 03/07/13 david@csse.uwa.edu.au 1.1455.2.5 # [PATCH] USB: Adding DSS-20 SyncStation to ftdi_sio # # Patch for 2.4.22 ftdi_sio to add DSS-20 SyncStation to ftdi_sio - the # SyncStation is the usb cradle for the Sony Ericsson P800 phone. # -------------------------------------------- # 03/07/13 greg@kroah.com 1.1455.3.1 # Merge bk://soma.bkbits.net/linux-2.5-cpci # into kroah.com:/home/linux/BK/pci-2.5 # -------------------------------------------- # 03/07/13 ganesh@vxindia.veritas.com 1.1455.2.6 # [PATCH] USB: more ids for ipaq # # 3 more device ids added to ipaq.c/ipaq.h # # Added ids for the Rover P5, Toshiba E310 and E335. Thanks to # Matthijs van der Molen, Pavel Stoliarov, Tod B. Schmidt and # Matt Hartley. # -------------------------------------------- # 03/07/13 nkiesel@tbdnetworks.com 1.1455.3.2 # [PATCH] PCI: fixup for compile error in pci/legacy.c # # the last patch forgot to fix the debug code. # -------------------------------------------- # 03/07/13 greg@kroah.com 1.1455.3.3 # PCI: fix up error for when CONFIG_PCI=n and scsi.h is included. # -------------------------------------------- # 03/07/14 maneesh@in.ibm.com 1.1455.1.4 # [PATCH] vfsmount_lock-fix # # This fixes one place where I missed the replacing dcache_lock with # vfsmount_lock in put_namespace(). # # Tested with CLONE_NEWNS flag also. # -------------------------------------------- # 03/07/14 randy.dunlap@verizon.net 1.1455.1.5 # [PATCH] syncppp: incomplete function prototype # # This fixes this warning: # # syncppp.c:165: warning: function declaration isn't a prototype # # by adding "void" as the function parameter list. # -------------------------------------------- # 03/07/14 randy.dunlap@verizon.net 1.1455.1.6 # [PATCH] reduce stack usage in wanrouter # # From Jorn Engel and Randy Dunlap. # # It reduces stack usage in the WAN router by about 0x500 bytes # (from 0x520 to 0x24 when I did it in April). # -------------------------------------------- # 03/07/14 randy.dunlap@verizon.net 1.1455.1.7 # [PATCH] unchecked return code of copy_to_user in read_profile # # From Daniele Bellucci . # # Check the copy_to_user() return code in read_profile(). # -------------------------------------------- # 03/07/14 randy.dunlap@verizon.net 1.1455.1.8 # [PATCH] busmouse: fix memory leak and misc_register failure # # From Flavio B. Leitner. # # Fix a memory leak and an unchecked return code in the busmouse driver. # -------------------------------------------- # 03/07/14 alex@ssi.bg 1.1455.1.9 # [PATCH] Fix irq handling of IO-APIC edge IRQs on UP # # send_IPI_self is needed to resend irqs with IRQ_PENDING status when # enabled. # # Checked with Ingo, and it's in 2.4-ac for some time. # # This should fix ide lost interrupts on UP with IO-APIC # # Ide trigers it this way: # - disable_irq # - do stuff that triggers IRQ. # - irq is IRQ_PENDING # - enable_irq # - IRQ is lost, needs to be resend. # # I'll send the patch to fixup IDE disable_irq logic to Bart. # -------------------------------------------- # 03/07/14 chyang@clusterfs.com 1.1455.1.10 # [PATCH] unresolved symbol with moduled intermezzo # # This solves the unresolved symbol problem with modular intermezzo. Also # update the MAINTAINERS entry. # -------------------------------------------- # 03/07/14 jgarzik@pobox.com 1.1455.1.11 # [PATCH] Large PCI bus numbers # # ppc64 machines can have PCI bus numbers larger than 8 bits, but it looks # like pci_device_to_OF_node already handles this case, in both 2.4 and # 2.5. # # We just need the space to store them. # -------------------------------------------- # 03/07/14 lethal@linux-sh.org 1.1455.1.12 # [PATCH] pvr2fb update # # Here's an update for pvr2fb (with a patch this time), which makes it compile # again. # -------------------------------------------- # 03/07/14 lethal@linux-sh.org 1.1455.1.13 # [PATCH] PCMCIA: Update hd64465 driver # # This patch updates the sh-specific hd64465 pcmcia driver for the new API, as # well as fixing up some other issues (such as remap_page_range() abuse -- we # remap through P3 area instead) which caused it not to compile. Changes by # Dominik Brodowski and myself. # -------------------------------------------- # 03/07/14 lethal@linux-sh.org 1.1455.1.14 # [PATCH] shwdt update # # This patch includes quite a few changes and updates for the shwdt driver (which # brings it in sync with LinuxSH CVS HEAD). This fixes up support for the SH-2, # and also fixes up some timer brain-damage. # -------------------------------------------- # 03/07/14 agrover@groveronline.com 1.1461 # ACPI: Dynamically allocate SDT list (suggested by Andi Kleen) # -------------------------------------------- # 03/07/14 agrover@groveronline.com 1.1462 # Merge groveronline.com:/root/bk/linux-2.5 # into groveronline.com:/root/bk/linux-acpi # -------------------------------------------- # 03/07/14 agrover@groveronline.com 1.1463 # ACPI: Update version, and other trivialities # -------------------------------------------- # 03/07/14 greg@kroah.com 1.1455.2.7 # [PATCH] USB: fixed up pci slot_name accesses in usb code # -------------------------------------------- # 03/07/14 greg@kroah.com 1.1455.2.8 # [PATCH] USB: fixed up pci slot_name accesses in usb gadget code # -------------------------------------------- # 03/07/14 willy@debian.org 1.1388.5.3 # [PATCH] ia64: Add some devinits to pci.c # # These functions can all be devinit as they're all called from functions # which are themselves devinit. # -------------------------------------------- # 03/07/14 greg@kroah.com 1.1455.3.4 # [PATCH] PCI: remove usages of pci slot_name from the pci core code. # -------------------------------------------- # 03/07/14 greg@kroah.com 1.1455.3.5 # [PATCH] PCI: remove usages of pci slot_name from acpi pci hotplug driver # -------------------------------------------- # 03/07/14 greg@kroah.com 1.1455.1.15 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/gregkh-2.5 # -------------------------------------------- # 03/07/14 greg@kroah.com 1.1455.4.1 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/pci-2.5 # -------------------------------------------- # 03/07/14 davidm@tiger.hpl.hp.com 1.1455.5.1 # Merge tiger.hpl.hp.com:/data1/bk/vanilla/linux-2.5 # into tiger.hpl.hp.com:/data1/bk/lia64/to-linus-2.5 # -------------------------------------------- # 03/07/14 mdharm-usb@one-eyed-alien.net 1.1455.1.16 # [PATCH] USB: convert ISD200 and Jumpshot to DMA-safe buffer # # This patch converts the ISD200 and Jumpshot drivers to use the new DMA-safe # buffer. # # # I'd also like to take a moment to thank Alan Stern, who writes many of # these patches. Without his help, many of the improvements everyone has # seen over the 2.5.x series would not have been possible. # -------------------------------------------- # 03/07/14 mdharm-usb@one-eyed-alien.net 1.1455.1.17 # [PATCH] USB: remove now-dead mode-translation code # # This patch removes all of the mode-translation logic. It's no longer # needed, as the upper-level drivers now all issue the proper 10-byte # commands. This is a large patch, but what it's doing is removing a great # deal of unneeded code -- about 650+ lines removed, according to diffstat. # # Those of you who are having some trouble getting your DVD-RAMs detected # properly should have all your problems solved by an upcoming patch from the # SCSI folks. It may look like that problem is related to this patch, but it # isn't -- it's a side-effect of another SCSI patch to consolidate code. # # Special thanks to James Bottomley for being patient enough to work with me # on these issues on the SCSI layer. # # This, BTW, makes US_FL_MODE_XLATE a NOP. The symbol is kept for the # purpose of allowing unusual_devs.h to be consistent between 2.4 and 2.5 # # There are still a few places where more code could (potentially) be # removed. I need to mull over the UFI specification to be sure, tho. # -------------------------------------------- # 03/07/14 albertogli@telpin.com.ar 1.1455.6.1 # [IPVS]: Fix typo in Kconfig file. # -------------------------------------------- # 03/07/14 ak@muc.de 1.1455.6.2 # [NET]: Turn softnet_data into per-cpu data. # -------------------------------------------- # 03/07/14 chas@cmf.nrl.navy.mil 1.1455.6.3 # [ATM]: Cleanup pppoatm_ioctl_hook. # -------------------------------------------- # 03/07/14 chas@cmf.nrl.navy.mil 1.1455.6.4 # [ATM]: Cleanup br2684_ioctl_hook. # -------------------------------------------- # 03/07/14 kunihiro@ipinfusion.com 1.1455.6.5 # [IPSEC/IPV6]: Add missing email address to my copyrights. # -------------------------------------------- # 03/07/14 willy@debian.org 1.1455.5.2 # [PATCH] ia64: use has_8259 in acpi_register_irq() # # acpi_madt is marked as __initdata, so an attempt to use # acpi_register_irq() after we discarded init sections would cause us to # dereference a random location. Everywhere else uses has_8259 anyway. # -------------------------------------------- # 03/07/15 paulus@samba.org 1.1455.7.1 # Merge samba.org:/home/paulus/kernel/linux-2.5 # into samba.org:/home/paulus/kernel/for-linus-ppc # -------------------------------------------- # 03/07/14 davidm@tiger.hpl.hp.com 1.1455.5.3 # ia64: Set the PRT entry's irq member in iosapic_parse_prt(). # -------------------------------------------- # 03/07/14 davidm@tiger.hpl.hp.com 1.1455.5.4 # ia64: Small fixes for 2.6.0-test1 merge. # -------------------------------------------- # 03/07/15 davem@nuts.ninka.net 1.1455.6.6 # [TCP/IPV6]: Check for anycast where we check for multicast. # -------------------------------------------- # 03/07/15 paulus@samba.org 1.1455.7.2 # PPC32: Add some more system calls - tgkill, utimes, [f]statfs64. # # Patch from Anton Blanchard. Also reserves a syscall for swapcontext # and updates the _syscallN macros. # -------------------------------------------- # 03/07/15 paulus@samba.org 1.1455.7.3 # PPC32: Add SEMTIMEDOP. Patch from Anton Blanchard. # -------------------------------------------- # 03/07/15 paulus@samba.org 1.1455.7.4 # PPC32: Eliminate duplicate variable declarations in arch/ppc/kernel/time.c # -------------------------------------------- # 03/07/15 paulus@samba.org 1.1455.7.5 # PPC32: Fix compilation of powermac CPU frequency switching support. # -------------------------------------------- # 03/07/15 greg@kroah.com 1.1455.4.2 # [PATCH] PCI: fix problem with pci remove functions not being built if CONFIG_HOTPLUG was not set # # This fixes a build problem on sparc, and hopefully will prevent this from # happening in the future... # -------------------------------------------- # 03/07/15 greg@kroah.com 1.1455.1.18 # [PATCH] USB: remove some warnings when building the documentation. # -------------------------------------------- # 03/07/15 greg@kroah.com 1.1455.1.19 # [PATCH] USB: flush all in-flight urbs _before_ disconnect() is called. # # This solves the module unload problem for some usb-serial drivers # (like visor.c and ftdi_sio.c), and makes usb drivers much simpler. # -------------------------------------------- # 03/07/15 greg@kroah.com 1.1455.1.20 # [PATCH] USB: fix up bluetty driver's tty and devfs names. # -------------------------------------------- # 03/07/15 greg@kroah.com 1.1455.1.21 # [PATCH] USB: fix up cdc-acm driver's tty and devfs names. # -------------------------------------------- # 03/07/15 davidm@tiger.hpl.hp.com 1.1455.5.5 # ia64: Change per-CPU implementation so that __get_cpu_var() returns the # canonical address (l-value). To get the virtually mapped # alias (which is more efficient), use __ia64_per_cpu_var(). The # latter is safe only if the address of the l-value is never passed # to another CPU (i.e., not stored in any global place). # For extremely efficient, portable per-CPU variables, there is # now a new API local.h which was introduced by Rusty Russell. # To use this, declare a variable of type local_t as a per-CPU # variable and then use {__,}cpu_local_FOO() to manipulate such # variables. This patch also updated the atomic interface with # a 64-bit counter. # -------------------------------------------- # 03/07/15 david-b@pacbell.net 1.1455.1.22 # [PATCH] USB: ohci minor tweaks # # Two small updates: # # - Report short control reads correctly in an exotic case # that our regression tests cover. (Haven't run them with # ohci for a long time, it seems...) # # - IRQ non-delivery bugs (ACPI, APIC, etc) can prevent urbs # from unlinking. This prints a warning when that sort of # non-USB bug is biting. # -------------------------------------------- # 03/07/15 david-b@pacbell.net 1.1455.1.23 # [PATCH] USB: usb net drivers SET_NETDEV_DEV # # I noticed that Viro's "use alloc_etherdev" patch left a # small problem: only "usbnet" did SET_NETDEV_DEV, and # that used the wrong driver model device. # # This has all the usb network drivers use SET_NETDEV_DEV, # so the /sys/class/net/*/{device,driver} files link to the # relevant usb interface and to its device driver. # -------------------------------------------- # 03/07/15 david-b@pacbell.net 1.1455.1.24 # [PATCH] USB: ethernet gadget learns about pxa2xx udc # # The original code needed some updates to work properly with # the USB Device Controller found in Intel's PXA 2xx processors. # # - SET_INTERFACE is effectively unusable. So the driver # now has a "minimalist" mode, with none of the bells and # whistles of CDC. # # - The config symbol will be CONFIG_USB_PXA2XX, since the # same controller (modulo errata) is in several processors # other than the "older" pxa250. # # For the record, that "minimalist" mode was the original idea # behind this driver ... implementing CDC was a win for interop # since most non-MSFT host operating systems support it already, # without needing a new driver. # # There were also a few other minor updates: # # - Net2280: queue depth shrank a bit, don't use the same # endpoint numbers for the IN and OUT sides. (CATC doesn't # let filters consider direction, just numbers.) # # - Join the Jihad! Abolish register_netdev()!! This just # nests the gadget-private data structures inside the # netdev data structure, instead of the other way around. # # - Minor cleanups. # -------------------------------------------- # 03/07/15 david-b@pacbell.net 1.1455.1.25 # [PATCH] USB: usbtest, autoconfigure from descriptors # # Not all gadget controllers support ep2in-bulk and ep2out-bulk, # unlike the EZ-USB (non-FX2) devices or the net2280. # # So this patch teaches "usbtest" how to look at the descriptors # it's given, and use the appropriate endpoints. This helps # support Linux test devices using hardware like the pxa2xx UDC, # and other controllers. # -------------------------------------------- # 03/07/15 david-b@pacbell.net 1.1455.1.26 # [PATCH] USB: gadget zero learns about pxa2xx udc # # The original code needed some updates to work properly with # the USB Device Controller found in Intel's PXA 2xx processors. # # - SET_INTERFACE and SET_CONFIGURATION involve hardware # automagic: all endpoints get reset. This is a PITA, # and will likely get more work. (Seems like the reset # is only partial, hosts need to CLEAR_HALT themselves...) # # What this does is to handle -ECONNABORTED notifications # from pxa2xx_udc, in those cases. In general, gadget # drivers need to reset endpoints themselves, since the # lower levels (hardware!) won't know how the endpoints # are allocated between interfaces and altsettings. # # - The config symbol will be CONFIG_USB_PXA2XX, since the # same controller (modulo errata) is in several processors # other than the "older" pxa250. # # - This also adds an "i/o pattern" parameter, so that it # can continue to use the "all zeroes" pattern or switch # to something else. The initial "something else" is an # easily predicted "mod63" pattern. # -------------------------------------------- # 03/07/15 henning@meier-geinitz.de 1.1455.1.27 # [PATCH] USB: fix open/probe race in scanner driver # # This patch from Oliver Neukum fixes a race between open and # probe. # -------------------------------------------- # 03/07/15 henning@meier-geinitz.de 1.1455.1.28 # [PATCH] USB: New vendor/product ids for scanner driver # # this patch adds new vendor/product ids for Avision, Canon, HP, # Microtek and Relisys scanners. # -------------------------------------------- # 03/07/15 davidm@tiger.hpl.hp.com 1.1455.5.6 # Fix patch breakage. # -------------------------------------------- # 03/07/15 oliver@neukum.org 1.1455.1.29 # [PATCH] USB: fix race between open() and probe() # # registering the device before setting the interface data can lead # to a null pointer being followed in open(). This patch fixes that. # -------------------------------------------- # 03/07/15 oliver@neukum.org 1.1455.1.30 # [PATCH] USB: fix layering violation in usblp # # writing urb->status is a no go area for drivers. # -------------------------------------------- # 03/07/15 stern@rowland.harvard.edu 1.1455.1.31 # [PATCH] USB: More unusual_devs.h entry updates # # Here are more user-reported updates for unusual_devs.h. # -------------------------------------------- # 03/07/15 greg@kroah.com 1.1455.1.32 # [PATCH] USB: fix a nasty use-after-free bug in the usb-serial core. # -------------------------------------------- # 03/07/15 davidm@wailua.hpl.hp.com 1.1455.5.7 # ia64: Patch by Arun Sharma: Make execve()ing of ia32 tasks work again. # The impact on native ia64 fork+execve performance as measured by # LMbench is in the noise range (plus or minus 0.1%). The first two # hunks in the patch are not together because we wanted to hide the # memory latency. # -------------------------------------------- # 03/07/15 kuznet@ms2.inr.ac.ru 1.1455.6.7 # [TCP/IPV6]: Another anycast check. # -------------------------------------------- # 03/07/15 ja@ssi.bg 1.1455.6.8 # [IPV4/IPV6]: Fix use-after-free bugs in tunneling drivers. # -------------------------------------------- # 03/07/15 shemminger@osdl.org 1.1455.6.9 # [NET]: Dynamic net_device for serial eql balancer. # -------------------------------------------- # 03/07/15 chas@cmf.nrl.navy.mil 1.1455.6.10 # [ATM]: Use sk_state_change() and eliminate vcc->callback(). # -------------------------------------------- # 03/07/15 chas@cmf.nrl.navy.mil 1.1455.6.11 # [ATM]: Eliminate vcc->sleep in favor of sk->sk_sleep. # -------------------------------------------- # 03/07/15 chas@cmf.nrl.navy.mil 1.1455.6.12 # [ATM]: Use sk_data_ready and sk_change_state instead of wake_up. # -------------------------------------------- # 03/07/15 chas@cmf.nrl.navy.mil 1.1455.6.13 # [ATM]: Replace vcc->reply with sk->sk_err; implement sk_write_space. # -------------------------------------------- # 03/07/15 greg@kroah.com 1.1455.1.33 # [PATCH] USB: fix memory leak in the visor driver. # -------------------------------------------- # 03/07/15 rob@osinvestor.com 1.1455.8.1 # [SERIAL]: Do not use serio->private to track serio open status in sun drivers. # # Issue discovered by Ricky Beam (jfbeam@bluetronic.net). # -------------------------------------------- # 03/07/15 jfbeam@bluetronic.net 1.1455.8.2 # [SUNKBD]: Mark reset/layout as volatile. # -------------------------------------------- # 03/07/16 davidm@tiger.hpl.hp.com 1.1455.5.8 # ia64: Put per-CPU data into .data.percpu section both for UP and MP. # This ensures that per-CPU data is "addl"-addressable even # on UP. # -------------------------------------------- # 03/07/16 davem@cheetah.ninka.net 1.1455.9.1 # [SPARC64]: Fix pbus->sysdata interpretation in pci_domain_nr(). # -------------------------------------------- # 03/07/16 davem@nuts.ninka.net 1.1455.8.3 # [SPARC64]: Fix assumptions about data section ordering and objects ending up in .data vs .bss # -------------------------------------------- # 03/07/16 davem@nuts.ninka.net 1.1455.8.4 # Merge cheetah:src/BK/sparc-2.5 # into nuts.ninka.net:/home/davem/src/BK/sparc-2.5 # -------------------------------------------- # 03/07/16 yoshfuji@linux-ipv6.org 1.1455.6.14 # [IPV6]: Get reference to neigh/dev when building ndisc DST. # -------------------------------------------- # 03/07/16 wensong@linux-vs.org 1.1455.6.15 # [IPV4]: Add the defense timer for IPVS. # -------------------------------------------- # 03/07/16 wensong@linux-vs.org 1.1455.6.16 # [IPV4]: Remove the unnecessay del_timer_sync call in IPVS connection expire. # -------------------------------------------- # 03/07/16 wensong@linux-vs.org 1.1455.6.17 # [IPV4]: Do not use proto for route output in IPVS. # -------------------------------------------- # 03/07/16 oliver@neukum.org 1.1455.1.34 # [PATCH] USB: fix irq urb in hpusbscsi # # this fixes the completion handler for the interrupt urb in hpusbscsi. # -------------------------------------------- # 03/07/16 oliver@neukum.org 1.1455.1.35 # [PATCH] USB: fix race between probe and open in skeleton # # registering a device only partially initialised is quite bad an # idea. # -------------------------------------------- # 03/07/16 david-b@pacbell.net 1.1455.1.36 # [PATCH] USB: ethernet gadget, another pxa update # # - #ifdefs out some code that never runs on the pxa # - catches "alloc_etherdev Jihad" changes I somehow missed # -------------------------------------------- # 03/07/16 oliver@neukum.org 1.1455.1.37 # [PATCH] USB: usblcd: race between open and read/write # # usblcd registers a device before all buffers are allocated leading # to a race resulting in NULL pointers being followed. # This fixes it. # -------------------------------------------- # 03/07/16 stern@rowland.harvard.edu 1.1455.1.38 # [PATCH] USB: I/O buffering for sddr09 # # This patch makes the sddr09 subdriver use proper DMA I/O buffering. # -------------------------------------------- # 03/07/16 stern@rowland.harvard.edu 1.1455.1.39 # [PATCH] USB: Make sddr55 use proper I/O buffering # # This patch makes the sddr55 subdriver use proper DMA I/O buffering. # -------------------------------------------- # 03/07/16 jbarnes@sgi.com 1.1455.5.9 # [PATCH] ia64: fix GENERIC compile # # This will fix the generic compile by removing sn2 from the list of # targets, since it depends on the new discontig code, which hasn't gone # in yet. # -------------------------------------------- # 03/07/16 stevef@steveft21.ltcsamba 1.1444.8.1 # Fix inverted kmalloc parm ordering (noticed by Zwane) that caused oops on mounts of long server names (reported on bugzilla). Fix multiuser mount option. # -------------------------------------------- # 03/07/16 stevef@steveft21.ltcsamba 1.1455.10.1 # Merge bk://cifs.bkbits.net/linux-2.5cifs # into steveft21.ltcsamba:/usr/src/bk/linux-2.5cifs # -------------------------------------------- # 03/07/16 davidm@tiger.hpl.hp.com 1.1455.5.10 # ia64: If the compiler supports it, use attribute (model (small)) to # tell the compiler that per-CPU variables can be addressed # with "addl". # # On the simulator kernel, this saves about 2776 bytes in the # kernel image. On a zx1 kernel, it saves about 5593 bytes. # As per-CPU variables are used more, these savings will # increase, of course. # -------------------------------------------- # 03/07/17 paulus@samba.org 1.1455.7.6 # PPC32: Remove unused fields from irq_cpustat_t. # -------------------------------------------- # 03/07/17 paulus@samba.org 1.1455.7.7 # PPC32: PCI mapping fixes for non-cache-coherent PPC machines. # -------------------------------------------- # 03/07/17 paulus@samba.org 1.1455.7.8 # PPC32: Make FP exceptions enabled by default. # -------------------------------------------- # 03/07/17 paulus@samba.org 1.1455.7.9 # PPC32: Change mm_segment_t definitions to simplify the code. # -------------------------------------------- # 03/07/17 anton@samba.org 1.1358.11.10 # [PATCH] sym2 error handler sleeps with irqs off # # The scsi error handler calls driver error handlers with the host_lock # taken. We need to drop it before calling down() in the sym2 driver. # -------------------------------------------- # 03/07/17 axboe@suse.de 1.1358.11.11 # [PATCH] Consolidate SCSI requeueing and add blk elevator hook # # This patch removes the scsi mid layer dependency on __elv_add_request # and introduces a new blk_requeue_request() function so the block # layer specificially knows a requeue is in progress. # # It also adds an elevator hook for elevators like AS which need to # hook into the requeue for correct adjustment of internal counters. # -------------------------------------------- # 03/07/17 torvalds@home.osdl.org 1.1455.11.1 # Revert PCI bus number size increase - it isn't even needed # on 2.5+, since ppc64 can (and does) use the PCI domain numbers # for this instead. # # The PCI domain support should be back-ported to 2.4.x rather # than having bigger PCI bus numbers. # # Cset exclude: jgarzik@pobox.com|ChangeSet|20030714162217|61624 # -------------------------------------------- # 03/07/17 torvalds@home.osdl.org 1.1464 # Merge http://linux-acpi.bkbits.net/linux-acpi # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/07/17 B.Zolnierkiewicz@elka.pw.edu.pl 1.1465 # [PATCH] fix IDE irq disable logic # # Since the IO-APIC irq disable fix went in we can now enable # the proper IRQ disabling in the IDE driver again. That had # been disabled due to the problems with UP IO-APIC. # -------------------------------------------- # 03/07/17 B.Zolnierkiewicz@elka.pw.edu.pl 1.1466 # [PATCH] Fix dma timeout bugs # # From Alexander Atanasov # # Fix DMA I/O and state machine fixes, error recovery # -------------------------------------------- # 03/07/17 torvalds@home.osdl.org 1.1467 # Merge bk://kernel.bkbits.net/gregkh/linux/pci-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/07/17 thomr9am@ss1000.ms.mff.cuni.cz 1.1468 # [PATCH] fix emu10k1 removal oops # # All of the cleanup functions in sound/oss/emu10k1/main.c were incorrectly # marked as __devinit. This little one fixes it, so that the module no longer # oopses when being removed. # -------------------------------------------- # 03/07/17 torvalds@home.osdl.org 1.1469 # Merge bk://kernel.bkbits.net/davem/sparc-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/07/17 torvalds@home.osdl.org 1.1470 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/07/17 torvalds@home.osdl.org 1.1471 # Add "clock_t_to_jiffies()" conversion function with # some rather minimal overflow protection. # -------------------------------------------- # 03/07/17 mikpe@csd.uu.se 1.1472 # [PATCH] make clean should remove usr/initramfs_data.S # # The kernel build leaves a temp file in linux/usr/ that make clean # doesn't remove. Fixed in the patch below. # -------------------------------------------- # 03/07/17 petero2@telia.com 1.1473 # [PATCH] Incorrect timeout in CDROM_SEND_PACKET ioctl # # The CDROM_SEND_PACKET ioctl passes a struct cdrom_generic_command from # user space, which contains a timeout field. # # The timeout is measured in jiffies, but the conversion from user to # kernel jiffies is missing, which makes the timeout 10 times shorter than # it should be in 2.5 kernels on x86. This causes CDRW formatting with # cdrwtool to fail. The following patch fixes this problem. # -------------------------------------------- # 03/07/17 hunold@convergence.de 1.1474 # [PATCH] Update the saa7146 driver core # # - fix WRITE_RPS0 and WRITE_RPS1 inlines, fix usage in mxb and budget # drivers # - export "saa7146_start_preview" and "saa7146_stop_preview" to allow # drivers to start and stop video overlay (necessary for analog module # support in the av7110 driver) # - fix i2c implementation: some frontend drivers transfer a huge amount # of firmware data (> 30kB), speed up the transmission by busy waiting # between byte transfers for bigger transmissions # - change ioctl function in various driver to accept a saa7146 # filehandle instead of a saa714 device structure # -------------------------------------------- # 03/07/17 hunold@convergence.de 1.1475 # [PATCH] Various small fixes in dvb-core # # - indentation fixes in dvb_demux.c # - include cleanup in various files # - simplify dvb/ttpci/Makefile # -------------------------------------------- # 03/07/17 hunold@convergence.de 1.1476 # [PATCH] Major dvb net code cleanup, many fixes # # - code review and fix the old race condition in dev->set_multicast_list # - use tq_schedule instead of tq_immediate # - remove card_num and dev_num from struct dvb_net (now obsolete) # - prevent interface from being removed while it is in use # - allow add/remove only for the superuser # - set check-CRC flag on section filter to drop broken packets # - some more debug printfs in filter handling code # - cleaned up and commented packet reception handler # - fix formatting # -------------------------------------------- # 03/07/17 hunold@convergence.de 1.1477 # [PATCH] Update dvb frontend drivers # # - grundig_29504-401.c: fix charge pump and band switch setting bug, # caught by Robert Schlabbach # - grundig_29504-401.c: pass apply_frontend_param() return value to # upper layers # - grundig_29504-401.c: try to make a more specific detection mechanism # - grundig_29504-491.c:remove bogus out-of-range check, FEC table index # is limited to 0...7 due to &= ~0x03 anyway... # - nxt6000.c: Patch by Paul Andreassen: Add Support for Comtech # DVBT-6k07 (PLL IC: SP5730) # - ves1820.c: use Robert Schlabbach's suggestions for CLKCONF (0x03) and # CARCONF (0x04) # - alps_bsrv2.c: don't enable voltage on init + inversion bugfix # -------------------------------------------- # 03/07/17 hunold@convergence.de 1.1478 # [PATCH] Add Zarlink MT312 DVB-T frontend driver # # - Zarlink MT312 satellite channel decoder driver contributed by Andreas # Oberritter # -------------------------------------------- # 03/07/17 hunold@convergence.de 1.1479 # [PATCH] Update the DVB budget drivers # # - follow changes in dvb_net, use new eeprom parse code to properly # detect the mac # - add new subvendor/subystem id pair # -------------------------------------------- # 03/07/17 hunold@convergence.de 1.1480 # [PATCH] Update the DVB av7110 driver # # - Fix to 'Sharing SDRAM between TT re-insertion and OSD...' - OSD # didn't get the maximum available memory in one piece; needs new # firmware version 0x2616 # - Improved performance when setting palette with full 256 color OSD # - read MAC from EEPROM if available, contributed by Michael Glaum # # - add some MODULE_PARM_DESC for modinfo # - add support for the "analog module" available for DVB-C cards: the # saa7113 is initialized and some more v4l2 ioctls are available. you # can use "xawtv" now to switch between "dvb" and "analog" input. when # you are one the "analog" input, you can tune in analog channels. # -------------------------------------------- # 03/07/17 hunold@convergence.de 1.1481 # [PATCH] More saa7146 driver core updates # # - separate all EXPORT_SYMBOL stuff to saa7146_ksyms.c # - properly stop capturing when no more buffers are available (missing # register upload) # - make extension data a per-device member, not a per-extension member, # so that every device can have it's own private data (necessary for # DVB drivers which handle more than one device) # - implement field based capturing, ie. capturing fields to different # capture buffers # - change default old of capture fields for ALTERNATE mode (comply with # bttv) # - follow these changes in various analog saa7146 based cards drivers # (mxb.c and dpc7146.c) # - follow these changes in various saa7146 based budget card drivers # -------------------------------------------- # 03/07/17 hunold@convergence.de 1.1482 # [PATCH] Various kconfig and Makefile updates # -------------------------------------------- # 03/07/17 hunold@convergence.de 1.1483 # [PATCH] Add a driver for the Technisat Skystar2 DVB card # # - add DVB driver for Technisat Skystar2 card, which is based on the # FlexCop2 chipset by B2C2 # -------------------------------------------- # 03/07/17 hunold@convergence.de 1.1484 # [PATCH] Add two drivers for Hexium frame grabber cards # # - add drivers for the Orion and Gemini frame grabber cards, based on # the saa7146. For details, see http://www.hexium.hu/. Thanks to # Michael Hunold . # -------------------------------------------- # 03/07/17 hunold@convergence.de 1.1485 # [PATCH] More updates for the dvb core # -------------------------------------------- # 03/07/17 hunold@convergence.de 1.1486 # [PATCH] Add TDA14500x DVB-T frontend driver # # - tda1004x DVB-T driver contributed by Andrew de Quincy and Robert # Schlalach # -------------------------------------------- # 03/07/17 hunold@convergence.de 1.1487 # [PATCH] Update various other frontend drivers # # - In alps_tdlb7.c read SP8870 status reg to clear pending irqs in # FE_SET_FRONTEND, as suggested by Ragnar Sundblad to avoid frontend # hang-ups. # - the vp310 support in mt312.c support should be configured to 90Mhz, # too. skystar2 driver with bugfixed master_xfer() should probably # work now. # -------------------------------------------- # 03/07/17 hunold@convergence.de 1.1488 # [PATCH] Update the av7110 DVB driver # # - fix DMX_GET_STC to get the msb right # - follow changes in saa7146 driver core, separate some data for DVB-C # and DVB-S cards # -------------------------------------------- # 03/07/17 hunold@convergence.de 1.1489 # [PATCH] Add two drivers for USB based DVB-T adapters # # - add two new usb dvb drivers: # o dvb-ttusb-budget.c for Technotrend/Hauppauge Nova-USB devices # (Thanks to Holger Waechtler and elix Domke # ) # o dvb-ttusb-dec.c for Technotrend/Hauppauge USB DEC2000-T devices # (Thanks to Alex Woods ) # -------------------------------------------- # 03/07/17 hunold@convergence.de 1.1490 # [PATCH] Update Technisat Skystar2 DVB driver # # This is a follow-up patch to my latest patch series. It fixes the # problems and flaws Greg KH pointed out. # # There was a typo in the Makefile, so the driver was never compiled. But # I assumed that it built without errors. Doh! # # - update the Technisat Skystar2 driver: # - follow kernel coding rules, change comments # - change function return values from u32 to int where possible # - make all functions static # - comment out unused functions # - fix return values of functions to follow kernel rules # - removed bogus delay, read and write functions # -------------------------------------------- # 03/07/17 torvalds@home.osdl.org 1.1491 # Merge bk://ppc.bkbits.net/for-linus-ppc # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/07/17 torvalds@home.osdl.org 1.1492 # Merge http://lia64.bkbits.net/to-linus-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/07/17 fcusack@fcusack.com 1.1493 # [PATCH] rpcsec_gss compatibility # # start gss seq no at 1; netapp doesn't accept seq no 0. # # Just as a data point, Solaris 9 client uses initial seq. no. 2. # -------------------------------------------- # 03/07/17 fcusack@fcusack.com 1.1494 # [PATCH] Fix rpc_setbufsize() usage # # - fix null dereference on xprt->inet if (!connected), which happens if # a rpc cred wasn't available (root+auth_gss case) # - set bufsize on reconnect # -------------------------------------------- # 03/07/17 fcusack@fcusack.com 1.1495 # [PATCH] Allow unattended nfs3/krb5 mounts # # The comment in nfs_get_root() basically describes the patch: # # Some authentication types (gss/krb5, most notably) # are such that root won't be able to present a # credential for GETATTR (ie, getroot()). # # An easy way (ie, without this patch) to have unattended mounts is to # have a root/host@REALM (or similar) principal stashed in a keytab, which # root (rather, gssd) can use. However, this might not be desirable for # many sites. In any case, RFC2623 specifically describes the problem # addressed here. # # Notes: # # - Root inode gets inum of 1. This doesn't seem to matter, but may be # aesthetically unpleasing. I wanted to choose an inum unlikely to # conflict with an existing inum (although NFS has specific support # for that). It looks like more work than it's worth to change the # inum after the info is available. AFAICT it's not critical info. # # - Solaris has this "wierd" (but understandable) behavior that after # mounting without a credential, the mount point is not visible at all # until an access is attempted with a credential. This now-you-see-it- # now-you-don't behavior doesn't seem worthwhile to reproduce here. # # - Unfortunately, MOUNT_VERSION must go to 5. Some kernels with ver 4 # do not understand pseudoflavor. Keeping it at 4 means that the # userland mount can't know for sure whether the kernel accepted the # option or not. (Unless I'm missing some hack that could be done.) # # It works in my environment, against a netapp server (with the rpcsec_gss # patch I provided earlier). # -------------------------------------------- # 03/07/17 schwidefsky@de.ibm.com 1.1496 # [PATCH] s390: arch update # # - New default configuration. # - Fix get_tv32/put_tv32. # - Replace generic dma-mapping file with empty one. # - Remove wrong comment from dma.h. # -------------------------------------------- # 03/07/17 schwidefsky@de.ibm.com 1.1497 # [PATCH] s390: irq stats. # # Enable irq statistics for s390*. We defined NR_IRQS to 2, one for all i/o # interrupts and one for all external interrupts. # -------------------------------------------- # 03/07/17 schwidefsky@de.ibm.com 1.1498 # [PATCH] s390: dasd driver. # # Remove put_disk from dasd_destroy_partitions. This is done in dasd_free_device. # -------------------------------------------- # 03/07/17 schwidefsky@de.ibm.com 1.1499 # [PATCH] s390: common i/o layer. # # - Fix two memory leaks. # - Clear pending status in cio_enable_subchannel. # - Don't call device_unregister from interrupt context. # - Fix refcounting problems on static device structures for the ccw console. # - Delete timeouts for qdio after successful startup. # -------------------------------------------- # 03/07/17 schwidefsky@de.ibm.com 1.1500 # [PATCH] s390: qeth network driver. # # - Reset netdevice to defaults in offline processing. # - Fix checksumming. # - Fix routing status display. # - Get rid of _ccw_device_get_device_number in qeth. # - Inline some functions to save stack space. # -------------------------------------------- # 03/07/17 schwidefsky@de.ibm.com 1.1501 # [PATCH] s390: siginfo_t for s390x. # # Correct size of siginfo_t for s390x (from 136 to 128). # -------------------------------------------- # 03/07/17 bunk@fs.tum.de 1.1502 # [PATCH] remove all #include 's # # This causes blk.h to print a warning and removes all uses of blk.h. # I've tested the compilation in 2.6.0-test1 with a .config that tries to # compile as many drivers as possible. # -------------------------------------------- # 03/07/17 linux@thorsten-knabe.de 1.1503 # [PATCH] sound/oss/ad1816.c update # # This fixes various problems with the AD1816 sound driver: # # - Compilation errors with CONFIG_PNP enabled fixed. # - PNP specific code rewritten. # - SMP fixes. # - DMA resource handling fixes. # - Other minor code cleanup. # -------------------------------------------- # 03/07/17 torvalds@home.osdl.org 1.1504 # Merge bk://cifs.bkbits.net/linux-2.5cifs # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/07/17 jasper@vs19.net 1.1505 # [PATCH] Fix up unattended nfs3/krb5 mounts # # The patch from Frank was missing the auth flavor argument to # nfs_sb_init(). Trivial fix follows. # # [ Side note: the code mixes the spellings 'flavor' and 'flavour', which # is somewhat confusing. That should probably be fixed to avoid confusion. ] # -------------------------------------------- # 03/07/17 stern@rowland.harvard.edu 1.1455.1.40 # [PATCH] USB: Handle over current inputs on all Intel controllers # # This patch for the UHCI driver changes the test for over current inputs, # which can cause false Resume indications with some of Intel's USB # controllers. Previously the code only checked for one specific controller # chip, but now another one has turned up that exhibits the same flaw. It # seems best just to check for Intel being the manufacturer, especially # since it doesn't hurt to check for the condition when it isn't present or # is only temporary. # -------------------------------------------- # 03/07/17 henning@meier-geinitz.de 1.1455.1.41 # [PATCH] USB: unlink interrupt URBs in scanner driver # # Clean up irq urb when not enough memory is available. # -------------------------------------------- # 03/07/17 oliver@neukum.org 1.1455.1.42 # [PATCH] USB: fix race between probe and open in dabusb # # the driver is registering the device too early, so that open may # see a partially initialised device. # -------------------------------------------- # 03/07/17 david-b@pacbell.net 1.1455.1.43 # [PATCH] USB: better locking in hcd_endpoint_disable() # # You'll recall there was a change to the locking in that code after # it was submitted. This is a better fix to that issue. # # "Obviously correct", though I've not run with this in ages. # -------------------------------------------- # 03/07/17 greg@kroah.com 1.1506 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/gregkh-2.5 # -------------------------------------------- # 03/07/18 jejb@jet.(none) 1.1507 # Merge jet.(none):/home1/jejb/BK/scsi-misc-2.5 # into jet.(none):/home1/jejb/BK/scsi-for-linus-2.5 # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.1 # [PATCH] Allow LBD on architectures that support it # # From: Milton Miller # # Enable the CONFIG_LBD option for the architectures which appear to support # it. # # It is not actually tested for those architectures, but it's not likely to # be unless we do this... # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.2 # [PATCH] misc fixes # # - i460-agp linkage fix ("Luck, Tony" ) # # - Don't reimplement offsetof() in hfs # # - NBD warning fix # # - Remove unneeded null-pointer test in journal_stop (Andreas Gruenbacher) # # - remove debug stuff in journal_dirty_metadata() # # - slab.c typo fixes (Lev Makhlis ) # # - In devfs_mk_cdev() error path, don't print `buf' until we've written # something into it. (Reported by Gergely Nagy ) # # - Two ISA sound drivers had their kmalloc() args reversed (Spotted by Steve # French) # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.3 # [PATCH] parport_pc.c compile warning # # From: Shane Shrybman # # This fixes the following warning: # # drivers/parport/parport_pc.c:98: warning: `verbose_probing' defined but # not used # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.4 # [PATCH] ext3 extended attribute fixes # # From: Andreas Gruenbacher # # - Fix transaction credit exhaustion BUG. # # - ext3_journal_get_write_access_credits failures break out of the loop in # 1058, so is not released properly. # # - must be reset after journal_release_buffer() in line 1072. # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.5 # [PATCH] Ext3 xattr credits fix for quotas # # From: Andreas Gruenbacher # # The xattr and acl code are not properly reserving credits for quotas. # EXT3_DATA_TRANS_BLOCKS is an overestimate of the credits required including # quotas. Make it a little more tight, and use it in the xattr and acl code # to be quota safe. # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.6 # [PATCH] ioctl(BLKBSZSET) fix and cleanup # # From: Lou Langholtz # # - set_blocksize() already does those size checks. # # - test the set_blocksize() return value: it can fail if the requested # blocksize is less that the hard sector size. # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.7 # [PATCH] pass regs into dump_fpu() in elf coredump # # From: Pete Zaitcev # # sparc32 needs the registers passed into dump_fpu(). # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.8 # [PATCH] is_devfsd_or_child() deadlock fix # # From: Andrey Borzenkov # # The code that did proper check existed in 2.4 and was removed in 2.5 for # whatever reason. The patch restores it slightly modified as below. # # 2.4 code looks somewhat unclean in that # # - it traverses task list without lock. # # - it starts from current->real_parent but nothing prevents current be # init_task itself. This hung for me on 2.5 during boot. May be 2.4 does # something differently. # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.9 # [PATCH] remove task_cache entirely # # From: Manfred Spraul # # kernel/fork.c contains a disabled cache for task stuctures. task # structures are placed into the task cache only if "tsk==current", and # "tsk==current" is impossible. There is even a WARN_ON against that in # __put_task_struct(). # # So remove it entirely - it's dead code. # # One problem is that order-1 allocations are not cached per-cpu - we can # use kmalloc for the stack. # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.10 # [PATCH] use kmalloc for ia32 stacks # # From: William Lee Irwin III # # I've been slab allocating the stack on i386 for some time, and it has gone # without incident in pgcl, -wli, -mjb (?), and so on. kmalloc() is fine; # there isn't any particularly compelling reason for a dedicated slab as # there's no preconstruction to do, though it can be arranged. # # Basically, it works, there's no obvious reason not to, and (even better) # it's not totally invisible to the VM and even makes overhead reportable. # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.11 # [PATCH] fix removable partitioned media with devfs # # From: Andrey Borzenkov # # Current 2.5 does not register any device node in devfs for empty media # (capacity == 0) case. This makes removables unusable with devfs. # Partition rescan is done only on bdev open, but without any device node for # device it is impossible to open it. # # In 2.4 it was finally solved by always registering .../disc node as # representation for "whole" disk and using devfsd action to force partition # rescan on access to (non-existing) partition name. For primary names it # was handled internally by devfs - it kept track of removable devices in # directory and initiated partition rescan when name was not found. # # Both are obviously broken now. You can't do partition rescan because no # node is registered at all and internal handling was removed. Very nice. # # The attached patch makes resgister_disk always register at least disc node. # This now works for old and new compat names as per devfsd configuration; # canonical names are still broken: # # {pts/3}% ll /dev/scsi/host1/bus0/target4/lun0/part4 # ls: /dev/scsi/host1/bus0/target4/lun0/part4: No such file or directory # # but it can be fixed using the same technique as above so I won't push it. # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.12 # [PATCH] fix return of compat_sys_sched_getaffinity # # From: Anton Blanchard # # On success getaffinity should return the size of mask. It looks like # Randy's patch (which fixed a bogus return) missed this bit. # # In reality I'm not sure if we care, and with cpu bitmasks this stuff is # going to break. # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.13 # [PATCH] Fix two bugs with process limits (RLIMIT_NPROC) # # From: Neil Brown # # 1/ If a setuid process swaps it's real and effective uids and then forks, # the fork fails if the new realuid has more processes # than the original process was limited to. # This is particularly a problem if a user with a process limit # (e.g. 256) runs a setuid-root program which does setuid() + fork() # (e.g. lprng) while root already has more than 256 process (which # is quite possible). # # The root problem here is that a limit which should be a per-user # limit is being implemented as a per-process limit with # per-process (e.g. CAP_SYS_RESOURCE) controls. # Being a per-user limit, it should be that the root-user can over-ride # it, not just some process with CAP_SYS_RESOURCE. # # This patch adds a test to ignore process limits if the real user is root. # # 2/ When a root-owned process (e.g. cgiwrap) sets up process limits and then # calls setuid, the setuid should fail if the user would then be running # more than rlim_cur[RLIMIT_NPROC] processes, but it doesn't. This patch # adds an appropriate test. With this patch, and per-user process limit # imposed in cgiwrap really works. # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.14 # [PATCH] unline most of put_namespace() # # It has five callsites, and is big. # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.15 # [PATCH] CONFIG_BLK_DEV_CRYPTOLOOP needs CONFIG_CRYPTO # # From: Brett # # CONFIG_BLK_DEV_CRYPTOLOOP needs CONFIG_CRYPTO # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.16 # [PATCH] slab: print stuff when the wrong cache is used # # From: Manfred Spraul # # Some extra diagnostics when someone passes the wrong object type # into kmem_cache_free(). To help some bug which Manfred is chasing. # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.17 # [PATCH] settimeofday() fixes # # From: davem # # - sys_stime() takes an int*, but it should be a time_t*: they have different # sizes on (for example) sparc64. # # - sys_settimeofday() is confusing timevals with timespecs. They have # different sizes on sparc64 and the time keeps on getting set to epoch. # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.18 # [PATCH] visws: fix PCI breakage # # From: Andrey Panin # # This fixes Visws PCI code which was broken since 2.5.73. # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.19 # [PATCH] vesafb fix # # From: Gerd Knorr # # The patch below fixes some vesafb issues. Changes: # # * fixed struct screen_info in tty.h to use portable types. "unsigned # long" for 32bit values doesn't work on hammer machines ... # # * limited the framebuffer memory used by vesafb to 16 MB. This avoids # that vesafb's ioremap() eats plenty of kernel address space for no real # benefit if the gfx card has very much memory (some have 128 MB or more, # ia32 has 128 MB address space for vmalloc and ioremap ...). # # * mtrr is enabled by default. That should improve the vesafb performance # a lot. Also added a option to disable mtrr. # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.20 # [PATCH] watchdog: i810-tco support # # From: Wim Van Sebroeck # # Adds support for the 82801EB and 82801ER I/O Controller Hub's (ICH5 & # ICH5R). This will add watchdog support for the i865 and i875 motherboard # chipsets. It also removes some extra trailing spaces in the source files. # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.21 # [PATCH] CLONE_STOPPED # # From: Ulrich Drepper # # CLONE_STOPPED: start a thread in a stopped state. Required for NTPL. # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.22 # [PATCH] dm: 'wait for event' race # # From: Joe Thornber # # There was a race associated with the 'wait for a significant event' # functionality. # # Basically userland could read the status table, then wait for another # event, but the event it was waiting for could have occurred in the gap # between reading and waiting. # # To solve this we assign identifiers to events, in order to successfully # wait for an event both userland and the kernel driver must be in agreement # about what the last event identifier was. If they don't agree the wait # call will return immediately, allowing userland to re-read the status and # see what it missed. # # The new ioctl interface will use this properly. # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.23 # [PATCH] dm: v4 ioctl interface # # From: Joe Thornber # # v4 of the ioctl interface. Note there never was a v2 or a v3 except in an # unofficial EVMS way. # # This works correctly with the 64-bit dev_t patches in -mm kernels. # # There is now a config option to allow the user to select v1 or v4, it # defaults to v1. dm-ioctl.[hc] just #includes dm-ioctl-v[14].[hc] depending # on the config option. # # If you want to use v4 you will have to update your tools # (libdevmapper/lvm). The latest tools at the time of writing are: # # dmsetup + libdevmapper + replacement kernel patches for 2.4.20 & 2.4.21: # # ftp://ftp.sistina.com/pub/LVM2/device-mapper/device-mapper-testing-new-version4-interface.tgz # # Updated LVM2 tools to work with the above: # # ftp://ftp.sistina.com/pub/LVM2/tools/LVM2.0-testing.tgz # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.24 # [PATCH] fix bootmem allocator on machines with holes in # # From: Anton Blanchard # # If the memory we are trying to allocate is too large to fit in the current # region, we should skip to the end. We currently search the available # bitmap, find the area is too small, increment the start by incr and try # again. This resulted in an apparent lockup on a 64GB machine that had a # 3GB IO hole starting at 1GB (and the mem_map array would not fit in the # first region). # # Also use ALIGN macro instead of an open coded version. # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.25 # [PATCH] Update Documentation/magic-numbers.txt # # From: # # Update Documentation/magic-numbers.txt # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.26 # [PATCH] fix as-iosched do_div() # # For CONFIG_LBD=n case it was passing a u32 into do_div(). # -------------------------------------------- # 03/07/18 akpm@osdl.org 1.1506.1.27 # [PATCH] "Fix" AS i/o hang with aacraid driver # # From: Mark Haverkamp # # Mark says: # # "Daniel McNeil and I have been debugging a hang with the aacraid driver # using the as I/O scheduler." # # We found that scsi_request_fn would de-queue a request and later # re-queued it. This left the as_data->nr_dispatched variable in an # inconsistent state (it was never being decremented back to zero). # # We added a call to elv_completed_request to clean up the state before # re-adding the request. This has fixed our hang problem." # # It affects other SCSI drivers, but less frequently. We're assuming this is # the cause of several "everything got stuck in D state" reports. # # A very long design discussion has ensued. We don't have a suitably tested fix # ready so I think it is best to put Mark's one-liner in there for now, fix it # for real when everyone gets back from OLS. # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.1 # [PATCH] alpha illegal->invalid # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.2 # [PATCH] mtrr printk levels # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.3 # [PATCH] mtrr fixes # # Fix cyrix mtrr ((Zoltán Böszörményi) # Back port 2.4 handling for the Intel bug # Add printk levels # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.4 # [PATCH] fix visws pci (visws specific code) # # (Andrey Panin) # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.5 # [PATCH] another batch of "invalid" not "illegal" fixes # # (Steven Cole) # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.6 # [PATCH] POSIX doesnt guarantee head -2, only head -n 2 # # (and some build environments are set up to be poxixly correct) # # (Teemu Tervo) # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.7 # [PATCH] head -n 2 for ppc64 # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.8 # [PATCH] updated magic number tables # # (Fabian Frederick) # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.9 # [PATCH] pnp layer seems to document wrong file name # # (Jochen Hein) # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.10 # [PATCH] first cut ftape conversion # # (Paulo Andre) # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.11 # [PATCH] clean up ip2 glue (not yet ported tho) # # (Adriank Bunk) # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.12 # [PATCH] move watchdogs to __module_get now it exists # # (Jan Dittmer) # # Also add the 82801EB/ER (Wim Van Sebroeck) # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.13 # [PATCH] fix all the paths in ide Kconfig docs # # (Helge Hafting) # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.14 # [PATCH] convert ewrk3 for new locking etc # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.15 # [PATCH] clarify AXNET kconfig as per 2.4 # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.16 # [PATCH] use cpu_relax in seq8005 # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.17 # [PATCH] re-enable seq8005 # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.18 # [PATCH] forward port 2.4 Zoom video support # # Also apply the right fix to the yenta hang problem # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.19 # [PATCH] make isapnp request its port properly # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.20 # [PATCH] function is long gone, kill prototype # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.21 # [PATCH] pas16 build fix # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.22 # [PATCH] fix qlogicfas build warning # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.23 # [PATCH] undefined shifts in qla1280 # # C doesn't define >> by 32 for 32bit systems, and on some gcc leaves # you with the original value... # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.24 # [PATCH] sym53c8xxx wasnt updated to new irq code etc # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.25 # [PATCH] serial proc gives info on keycounts which can sometiems be abused # # For 2.4.x we made the file r-------- but for 2.6 we can do a nicer job # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.26 # [PATCH] xjack pcmcia needs .. pcmcia # # (Taral) # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.27 # [PATCH] restore console log level when jbd raises it # # (Vita Samel) # # maybe the set function should return the old value instead ? # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.28 # [PATCH] fix jffs2 build # # (Jamie Hicks) # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.29 # [PATCH] fix a doc error and misleading printk # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.30 # [PATCH] remove a now false comment # # (Frank Cusack) # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.31 # [PATCH] fix a copy_user return # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.32 # [PATCH] fix failed sethostname corrupting the data # # (Stephan Maciej) # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.33 # [PATCH] correct author of ad1980 plugin # # (Overzealous C&P of Red Hat license template 8)) # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.34 # [PATCH] fix make rpm versioning # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.35 # [PATCH] fix ver_linux for 2.6 # # (Steven Cole) # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.36 # [PATCH] fix unused symbol in ad1889 # # (Francois Romieu) # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.37 # [PATCH] btaudio uses memset so should be strlcpy # # (I've got a patch pending from someone to redo the lot using memset so # its safe from padding suprises) # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.38 # [PATCH] illegal->invalid for dmasound # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.39 # [PATCH] emu10k further updates/bug fixes # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.40 # [PATCH] Add HAL2 driver # # (Ladislav Michl) # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.41 # [PATCH] Add Harmony OSS driver # # (Jean-Christoph Vaugeois, Matthieu Delahaye,Helge Deller, Alex deVries) # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.42 # [PATCH] Kahlua audio driver # -------------------------------------------- # 03/07/18 alan@lxorguk.ukuu.org.uk 1.1455.12.43 # [PATCH] Makefile bits for audio resync # -------------------------------------------- # 03/07/18 torvalds@home.osdl.org 1.1506.1.28 # Manual merge # -------------------------------------------- # 03/07/18 miles@lsi.nec.co.jp 1.1506.1.29 # [PATCH] Rename `nb85e' to `v850e' on v850 # # The term `nb85e' is incorrect (caused by my confusion when starting the # v850 port), so this renames all occurances to `v850e'. # # Because this change renames some files too, it contains a number of # whole-file add/removes. # -------------------------------------------- # 03/07/18 miles@lsi.nec.co.jp 1.1506.1.30 # [PATCH] Refactor v850 UART driver # # The v850 family contains several related-but-not-identical on-chip # UARTs. This patch factors out the common code and uses it to implement # both types (only one was supported before). # # Also, this patch changes the way the v850 UART is initialized, to use # the same method as other linux serial drivers. # # This patch renames the UART code to be `v850e_uart' rather than # `nb85e_uart', as the former is more correct. As this change renames # some files too, the patch contains a number of whole-file add/removes. # -------------------------------------------- # 03/07/18 miles@lsi.nec.co.jp 1.1506.1.31 # [PATCH] Cleanup v850 cache-flushing code a bit # # (1) Add support for the V850E/ME2 processor # # (2) Clean up the cache-flushing function naming a bit # # (3) Similar to previous patches, rename everything from `nb85e' to `v850e'. # This patch renames some files, and so contains a number of whole-file # add/removes. # -------------------------------------------- # 03/07/18 miles@lsi.nec.co.jp 1.1506.1.32 # [PATCH] Add another layer of indirection for irq numbering with v850 `gbus' irqs # # This allows ports that support the v850 RTE-CB `GBUS' interrupts to use # both them and processor-board-specific interrupts at the same time. # -------------------------------------------- # 03/07/18 miles@lsi.nec.co.jp 1.1506.1.33 # [PATCH] Add v850 RTE-V850E/ME2-CB port # # This adds a port to the V850E/ME2 processor, and the `SolutionGear mini' # RTE-V850E/ME2-CB evaluation board. # -------------------------------------------- # 03/07/18 miles@lsi.nec.co.jp 1.1506.1.34 # [PATCH] Add v850 `sim85e2s' port, and cleanup v850e2 code # # This patch adds support for the `sim85e2s' simulation of the NA85E2S # processor implementation. As part of this, cache-flushing support for # the common v850e2 cache implementation is added. # # It also cleans up a bunch of code that was duplicated between different # v850e2 processors. # -------------------------------------------- # 03/07/18 miles@lsi.nec.co.jp 1.1506.1.35 # [PATCH] Update v850 config/makefile # # This updates the v850 Kconfig and kernel/Makefile to reflect preceding # changes. # -------------------------------------------- # 03/07/18 miles@lsi.nec.co.jp 1.1506.1.36 # [PATCH] v850 miscellanea # # Some updated copyright noticed and an unnecessary variable deleted. # -------------------------------------------- # 03/07/18 miles@lsi.nec.co.jp 1.1506.1.37 # [PATCH] Rename config option CONFIG_V850E_MA1_HIGHRES_TIMER on v850 # # This feature is not actually MA1-specific, so get rid of the `MA1' in # the name. # -------------------------------------------- # 03/07/18 miles@lsi.nec.co.jp 1.1506.1.38 # [PATCH] Update AS85EP1 port on v850 # -------------------------------------------- # 03/07/18 miles@lsi.nec.co.jp 1.1506.1.39 # [PATCH] On v850, use a long jump to start_kernel # # This allows the low-level start code to be located far away from the # rest of the kernel, which is sometimes necessary. # -------------------------------------------- # 03/07/18 jejb@jet.(none) 1.1508 # back out akpm's "fix" for AS # -------------------------------------------- # 03/07/18 jejb@jet.(none) 1.1509 # Put the requeue hack back into as-iosched.c # -------------------------------------------- # 03/07/18 torvalds@home.osdl.org 1.1510 # Merge bk://linux-scsi.bkbits.net/scsi-for-linus-2.6 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/07/18 romieu@fr.zoreil.com 1.1511 # [PATCH] Fix error path in kahlua driver # # Memory leak fix: hw_config is allocated before the call to sb_dsp_detect. # -------------------------------------------- # 03/07/18 romieu@fr.zoreil.com 1.1512 # [PATCH] Unchecked copy_to_user disturb harmony # # Fix an assortment of unchecked copy_to_user(). # -------------------------------------------- # 03/07/18 romieu@fr.zoreil.com 1.1513 # [PATCH] add new sound drivers to Makefile/Kconfig # # Adds kahlua, harmony and hal2 drivers to the build options. # -------------------------------------------- # 03/07/18 torvalds@home.osdl.org 1.1514 # Fix vfat shortname character logic that had wrong signedness # tests. # # From Dennis Vshivkov: # # "whenever I was trying to create a file using only national # characters for its name, it was always created with an # uppercased shortname (provided that the name was not too # long for 8.3, of course). Everything was fine with latin # filenames, though." # # The bug is that we check "buf[0]" as an unsigned character, but # "buf" is just "char *", which (depending on architecture and # compiler options) tends to be signed. # -------------------------------------------- # 03/07/18 rusty@rustcorp.com.au 1.1515 # [PATCH] Allow struct members inside percpu macros # # The current percpu macros do not allow __get_cpu_var(foo.val1) # which makes building macros on top of them really difficult. The # reason for this is the __per_cpu postfix appended to per-cpu # variables, designed to catch direct uses. Prepend it instead. # -------------------------------------------- # 03/07/18 rusty@rustcorp.com.au 1.1516 # [PATCH] Centralize Linker Symbols # # Richard Henderson point out a while back that linker generated symbols # should be declared as: "char _text[]" so that the compiler can't make # assumptions about them sitting in small sections, etc. # # Centralize these defintions in asm/sections.h (where some already # are on x86). # -------------------------------------------- # 03/07/18 rusty@rustcorp.com.au 1.1517 # [PATCH] introduce "local_t" - cpu-local atomic variables # # Introduces local_t, a type which is like atomic_t, but the # operations are only atomic from a single CPU's point of view # (ie. atomic against interrupts and softirqs). Some architectures # (eg. i386) can implement these very efficiently. # # There are special operations for the case of a local operation on a # per-cpu variable (which is common), which some architectures can # implement efficiently (eg. IA64 keeps all per-cpu variables mapped # at the same address, so no address arithmetic is needed). # # The generic implementation given here simply uses atomics on 32-bit # archs, three variables on others. x86 is already implemented specially. # -------------------------------------------- # 03/07/18 rusty@rustcorp.com.au 1.1518 # [PATCH] Resolve module local_t conflict # # Uses local_t for module reference counts. # -------------------------------------------- # 03/07/18 rusty@rustcorp.com.au 1.1519 # [PATCH] Sparc64 local_t support # # These are the local_t bits for sparc64. # # Other platforms such as PPC64 and Alpha (and in fact any "load locked/ # store conditional" like platform other than IA64), probably want to do # something similar. # -------------------------------------------- # 03/07/18 rusty@rustcorp.com.au 1.1520 # [PATCH] Make rmmod -f taint kernel. # # Somehow, the code which taints the kernel when rmmod -f is used got # lost. Restore it. # -------------------------------------------- # 03/07/18 rusty@rustcorp.com.au 1.1521 # [PATCH] module_put_and_exit # # Author: Neil Brown # # Define module_put_and_exit() and use it for nfsd/lockd # # Both nfsd and lockd have threads which expect to hold a reference # to the module while the thread is running. In order for the thread # to be able to put_module() the module before exiting, the # put_module code must be call from outside the module. # # This patch provides module_put_and_exit in non-modular code which a # thread-in-a-module can call. It also gets nfsd and lockd to use it # as appropriate. # # Note that in lockd, we can __get_module in the thread itself as the # creator of the thread is waiting for the thread to startup. # # In nfsd and for the 'reclaimer' threaded started by locked, we # __get_module first and put_module if the thread failed to start. # -------------------------------------------- # 03/07/18 rusty@rustcorp.com.au 1.1522 # [PATCH] Delete init/cleanup_module prototypes in obscure places. # # A few places pre-declare "int module_init(void);" and "void # module_cleanup(void);". Other than being obsolete, this is # unneccessary (it's in init.h anyway). # # There are still about 100 places which still use the # obsolete-since-2.2 "a function named module_init() magically gets # called": this change frees us up implement that via a macro. # -------------------------------------------- # 03/07/18 rusty@rustcorp.com.au 1.1523 # [PATCH] Make percpu_modcopy a macro # # davidm@hpl.hp.com writes: # "I'm working on updating the ia64 tree with local_t etc. One # thing that would really help me: could you make # asm-generic/percpu_modcopy() a macro? The routine depends on # cpu_possible(), but I can't including smp.h in percpu.h since # that would lead to recusive header-file dependencies (and in my # opinion, percpu.h should be more "primitive" than smp.h, so that # it can be included virtually everywhere)." # -------------------------------------------- # 03/07/18 hch@infradead.org 1.1524 # [PATCH] Use before initialisation in devfs_mk_cdev() # # As noted by Gergely Nagy: # # "devfs_mk_cdev() first checks the mode passed to it, and if it thinks # it is not a char device, it prints a warning and aborts. Now, this # printing involves the local variable `buf' (char buf[64]), which is # not initialised at that point." # # The same problem also affects devfs_mk_bdev. # # Fixed thus. # -------------------------------------------- # 03/07/19 rddunlap@osdl.org 1.1525 # [PATCH] janitor: drivers/telephony/ixj # # From: Daniele Bellucci # # This is an audit (copy_*_user), cleanup, and coding-style fix # for this driver. # -------------------------------------------- # 03/07/19 randy.dunlap@verizon.net 1.1526 # [PATCH] janitor: audit misc_register in wdt977 # # From: Daniele Bellucci # # Add a check to misc_register() in the wdt977 driver. # -------------------------------------------- # 03/07/19 randy.dunlap@verizon.net 1.1527 # [PATCH] janitor: copy_to_user in media/video/pms # # From: Daniele Bellucci # # Add a status check to copy_to_user() in a media/video driver. # -------------------------------------------- # 03/07/19 randy.dunlap@verizon.net 1.1528 # [PATCH] janitor: copy_to_user in net/irda/vlsi_ir # # From: Matthew Wilcox and Daniele Bellucci # # Fix an unchecked copy_to_user() in net/irda/vlsi_ir.c. # -------------------------------------------- # 03/07/19 rddunlap@osdl.org 1.1529 # [PATCH] janitor: copy_to_user in wireless/ray_cs ioctl # # From: Daniele Bellucci # # Fix an unchecked copy_to_user in ray_cs ioctl. # -------------------------------------------- # 03/07/19 rddunlap@osdl.org 1.1530 # [PATCH] janitor: unchecked copy/put_user in umsdos ioctl # # author: Daniele Bellucci # # Fix a series of unchecked copy/put_user()s in umsdos ioctl. # -------------------------------------------- # 03/07/19 rddunlap@osdl.org 1.1531 # [PATCH] janitor: unchecked copy_to_user in drivers/sbus/char/envctrl # # author: Daniele Bellucci # # Fix several unchecked copy_to_user()s in sbus/char/envctrl # -------------------------------------------- # 03/07/19 rddunlap@osdl.org 1.1532 # [PATCH] janitor: unchecked copy_from_user in ieee1394/amdtp # # author: Daniele Bellucci # # Fix an unchecked copy_from_user in ieee1394/amdtp. # -------------------------------------------- # 03/07/19 rddunlap@osdl.org 1.1533 # [PATCH] janitor: unchecked copy_from_user in parisc/led.c # # author: Daniele Bellucci # -------------------------------------------- # 03/07/19 rddunlap@osdl.org 1.1534 # [PATCH] janitor: mem leak and copy_from_user in wan/comx driver # # author: Daniele Bellucci # # Fix a memory leak and checks a copy_from_user in wan/comx driver. # -------------------------------------------- # diff -Nru a/Documentation/magic-number.txt b/Documentation/magic-number.txt --- a/Documentation/magic-number.txt Sat Jul 19 12:54:25 2003 +++ b/Documentation/magic-number.txt Sat Jul 19 12:54:25 2003 @@ -51,6 +51,13 @@ 03 Nov 2002 +Updated the magic table to Linux 2.5.74. + + Fabian Frederick + + 09 Jul 2003 + + Magic Name Number Structure File =========================================================================== PG_MAGIC 'P' pg_{read,write}_hdr include/linux/pg.h @@ -62,10 +69,12 @@ HDLC_MAGIC 0x239e n_hdlc drivers/char/n_hdlc.c APM_BIOS_MAGIC 0x4101 apm_user arch/i386/kernel/apm.c CYCLADES_MAGIC 0x4359 cyclades_port include/linux/cyclades.h +DB_MAGIC 0x4442 fc_info drivers/net/iph5526_novram.c +DL_MAGIC 0x444d fc_info drivers/net/iph5526_novram.c FASYNC_MAGIC 0x4601 fasync_struct include/linux/fs.h +FF_MAGIC 0x4646 fc_info drivers/net/iph5526_novram.c ISICOM_MAGIC 0x4d54 isi_port include/linux/isicom.h -PTY_MAGIC 0x5001 (none at the moment) - drivers/char/pty.c +PTY_MAGIC 0x5001 drivers/char/pty.c PPP_MAGIC 0x5002 ppp include/linux/if_pppvar.h SERIAL_MAGIC 0x5301 async_struct include/linux/serial.h SSTATE_MAGIC 0x5302 serial_state include/linux/serial.h @@ -81,9 +90,9 @@ MGSLPC_MAGIC 0x5402 mgslpc_info drivers/char/pcmcia/synclink_cs.c TTY_LDISC_MAGIC 0x5403 tty_ldisc include/linux/tty_ldisc.h USB_SERIAL_MAGIC 0x6702 usb_serial drivers/usb/serial/usb-serial.h +FULL_DUPLEX_MAGIC 0x6969 drivers/net/tulip/de2104x.c USB_BLUETOOTH_MAGIC 0x6d02 usb_bluetooth drivers/usb/class/bluetty.c -RFCOMM_TTY_MAGIC 0x6d02 (note at the moment) - net/bluetooth/rfcomm/tty.c +RFCOMM_TTY_MAGIC 0x6d02 net/bluetooth/rfcomm/tty.c USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port drivers/usb/serial/usb-serial.h CG_MAGIC 0x00090255 ufs_cylinder_group include/linux/ufs_fs.h A2232_MAGIC 0x000a2232 gs_port drivers/char/ser_a2232.h @@ -91,6 +100,7 @@ RPORT_MAGIC 0x00525001 r_port drivers/char/rocket_int.h LSEMAGIC 0x05091998 lse drivers/fc4/fc.c GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str drivers/scsi/gdth_ioctl.h +RIEBL_MAGIC 0x09051990 drivers/net/atarilance.c RIO_MAGIC 0x12345678 gs_port drivers/char/rio/rio_linux.c SX_MAGIC 0x12345678 gs_port drivers/char/sx.h NBD_REQUEST_MAGIC 0x12560953 nbd_request include/linux/nbd.h @@ -120,6 +130,7 @@ GDA_MAGIC 0x58464552 gda include/asm-mips64/sn/gda.h RED_MAGIC1 0x5a2cf071 (any) mm/slab.c STL_PORTMAGIC 0x5a7182c9 stlport include/linux/stallion.h +EEPROM_MAGIC_VALUE 0X5ab478d2 lanai_dev drivers/atm/lanai.c HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state include/linux/hdlcdrv.h EPCA_MAGIC 0x5c6df104 channel include/linux/epca.h PCXX_MAGIC 0x5c6df104 channel drivers/char/pcxx.h @@ -127,9 +138,11 @@ I810_STATE_MAGIC 0x63657373 i810_state sound/oss/i810_audio.c TRIDENT_STATE_MAGIC 0x63657373 trient_state sound/oss/trident.c M3_CARD_MAGIC 0x646e6f50 m3_card sound/oss/maestro3.c +FW_HEADER_MAGIC 0x65726F66 fw_header drivers/atm/fore200e.h SLOT_MAGIC 0x67267321 slot drivers/hotplug/cpqphp.h SLOT_MAGIC 0x67267322 slot drivers/hotplug/acpiphp.h LO_MAGIC 0x68797548 nbd_device include/linux/nbd.h +OPROFILE_MAGIC 0x6f70726f super_block drivers/oprofile/oprofilefs.h M3_STATE_MAGIC 0x734d724d m3_state sound/oss/maestro3.c STL_PANELMAGIC 0x7ef621a1 stlpanel include/linux/stallion.h VMALLOC_MAGIC 0x87654320 snd_alloc_track sound/core/memory.c @@ -137,11 +150,15 @@ PWC_MAGIC 0x89DC10AB pwc_device drivers/usb/media/pwc.h NBD_REPLY_MAGIC 0x96744668 nbd_reply include/linux/nbd.h STL_BOARDMAGIC 0xa2267f52 stlbrd include/linux/stallion.h +ENI155_MAGIC 0xa54b872d midway_eprom drivers/atm/eni.h SCI_MAGIC 0xbabeface gs_port drivers/char/sh-sci.h CODA_MAGIC 0xC0DAC0DA coda_file_info include/linux/coda_fs_i.h +DPMEM_MAGIC 0xc0ffee11 gdt_pci_sram drivers/scsi/gdth.h STLI_PORTMAGIC 0xe671c7a1 stliport include/linux/istallion.h YAM_MAGIC 0xF10A7654 yam_port drivers/net/hamradio/yam.c CCB_MAGIC 0xf2691ad2 ccb drivers/scsi/ncr53c8xx.c +QUEUE_MAGIC_FREE 0xf7e1c9a3 queue_entry drivers/scsi/arm/queue.c +QUEUE_MAGIC_USED 0xf7e1cc33 queue_entry drivers/scsi/arm/queue.c HTB_CMAGIC 0xFEFAFEF1 htb_class net/sched/sch_htb.c NMI_MAGIC 0x48414d4d455201 nmi_s include/asm-mips64/sn/nmi.h diff -Nru a/Documentation/pnp.txt b/Documentation/pnp.txt --- a/Documentation/pnp.txt Sat Jul 19 12:54:23 2003 +++ b/Documentation/pnp.txt Sat Jul 19 12:54:23 2003 @@ -22,7 +22,7 @@ In addition to the standard driverfs file the following are created in each device's directory: id - displays a list of support EISA IDs -possible - displays possible resource configurations +options - displays possible resource configurations resources - displays currently allocated resources and allows resource changes -activating a device @@ -60,7 +60,7 @@ - Notice the string "DISABLED". THis means the device is not active. 3.) check the device's possible configurations (optional) -# cat possible +# cat options Dependent: 01 - Priority acceptable port 0x3f0-0x3f0, align 0x7, size 0x6, 16-bit address decoding port 0x3f7-0x3f7, align 0x0, size 0x1, 16-bit address decoding diff -Nru a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS Sat Jul 19 12:54:25 2003 +++ b/MAINTAINERS Sat Jul 19 12:54:25 2003 @@ -973,7 +973,7 @@ S: Supported INTERMEZZO FILE SYSTEM -P: Chen Yang +P: Cluster File Systems M: intermezzo-devel@lists.sf.net W: http://www.inter-mezzo.org/ L: intermezzo-discuss@lists.sourceforge.net diff -Nru a/Makefile b/Makefile --- a/Makefile Sat Jul 19 12:54:26 2003 +++ b/Makefile Sat Jul 19 12:54:26 2003 @@ -781,7 +781,8 @@ tar -cvz $(RCS_TAR_IGNORE) -f $(KERNELPATH).tar.gz $(KERNELPATH)/. ; \ rm $(KERNELPATH) ; \ cd $(TOPDIR) ; \ - $(CONFIG_SHELL) $(srctree)/scripts/mkversion > .version ; \ + $(CONFIG_SHELL) $(srctree)/scripts/mkversion > .tmp_version ; \ + mv -f .tmp_version .version; \ $(RPM) -ta $(TOPDIR)/../$(KERNELPATH).tar.gz ; \ rm $(TOPDIR)/../$(KERNELPATH).tar.gz diff -Nru a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c --- a/arch/alpha/kernel/irq.c Sat Jul 19 12:54:26 2003 +++ b/arch/alpha/kernel/irq.c Sat Jul 19 12:54:26 2003 @@ -601,7 +601,7 @@ if ((unsigned) irq > ACTUAL_NR_IRQS && illegal_count < MAX_ILLEGAL_IRQS ) { irq_err_count++; illegal_count++; - printk(KERN_CRIT "device_interrupt: illegal interrupt %d\n", + printk(KERN_CRIT "device_interrupt: invalid interrupt %d\n", irq); return; } diff -Nru a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c --- a/arch/alpha/mm/init.c Sat Jul 19 12:54:28 2003 +++ b/arch/alpha/mm/init.c Sat Jul 19 12:54:28 2003 @@ -20,9 +20,6 @@ #include #include /* max_low_pfn */ #include -#ifdef CONFIG_BLK_DEV_INITRD -#include -#endif #include #include diff -Nru a/arch/arm/mach-clps711x/autcpu12.c b/arch/arm/mach-clps711x/autcpu12.c --- a/arch/arm/mach-clps711x/autcpu12.c Sat Jul 19 12:54:24 2003 +++ b/arch/arm/mach-clps711x/autcpu12.c Sat Jul 19 12:54:24 2003 @@ -21,7 +21,6 @@ #include #include #include -#include #include #include diff -Nru a/arch/arm26/kernel/setup.c b/arch/arm26/kernel/setup.c --- a/arch/arm26/kernel/setup.c Sat Jul 19 12:54:23 2003 +++ b/arch/arm26/kernel/setup.c Sat Jul 19 12:54:23 2003 @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/arch/arm26/mm/init.c b/arch/arm26/mm/init.c --- a/arch/arm26/mm/init.c Sat Jul 19 12:54:29 2003 +++ b/arch/arm26/mm/init.c Sat Jul 19 12:54:29 2003 @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c --- a/arch/h8300/kernel/setup.c Sat Jul 19 12:54:23 2003 +++ b/arch/h8300/kernel/setup.c Sat Jul 19 12:54:23 2003 @@ -35,7 +35,6 @@ #include #ifdef CONFIG_BLK_DEV_INITRD -#include #include #endif diff -Nru a/arch/h8300/mm/init.c b/arch/h8300/mm/init.c --- a/arch/h8300/mm/init.c Sat Jul 19 12:54:25 2003 +++ b/arch/h8300/mm/init.c Sat Jul 19 12:54:25 2003 @@ -23,9 +23,6 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_RAM -#include -#endif #include #include #include diff -Nru a/arch/i386/kernel/cpu/mtrr/cyrix.c b/arch/i386/kernel/cpu/mtrr/cyrix.c --- a/arch/i386/kernel/cpu/mtrr/cyrix.c Sat Jul 19 12:54:25 2003 +++ b/arch/i386/kernel/cpu/mtrr/cyrix.c Sat Jul 19 12:54:25 2003 @@ -330,16 +330,16 @@ set_mtrr_done(&ctxt); /* flush cache and disable MAPEN */ if (ccrc[5]) - printk("mtrr: ARR usage was not enabled, enabled manually\n"); + printk(KERN_INFO "mtrr: ARR usage was not enabled, enabled manually\n"); if (ccrc[3]) - printk("mtrr: ARR3 cannot be changed\n"); + printk(KERN_INFO "mtrr: ARR3 cannot be changed\n"); /* if ( ccrc[1] & 0x80) printk ("mtrr: SMM memory access through ARR3 disabled\n"); if ( ccrc[1] & 0x04) printk ("mtrr: SMM memory access disabled\n"); if ( ccrc[1] & 0x02) printk ("mtrr: SMM mode disabled\n"); */ if (ccrc[6]) - printk("mtrr: ARR3 was write protected, unprotected\n"); + printk(KERN_INFO "mtrr: ARR3 was write protected, unprotected\n"); } static struct mtrr_ops cyrix_mtrr_ops = { diff -Nru a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c --- a/arch/i386/kernel/cpu/mtrr/main.c Sat Jul 19 12:54:22 2003 +++ b/arch/i386/kernel/cpu/mtrr/main.c Sat Jul 19 12:54:22 2003 @@ -64,7 +64,7 @@ static void set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type type); -static unsigned int arr3_protected; +extern int arr3_protected; void set_mtrr_ops(struct mtrr_ops * ops) { @@ -75,23 +75,25 @@ /* Returns non-zero if we have the write-combining memory type */ static int have_wrcomb(void) { - struct pci_dev *dev = NULL; - - /* WTF is this? - * Someone, please shoot me. - */ - - /* ServerWorks LE chipsets have problems with write-combining - Don't allow it and leave room for other chipsets to be tagged */ - + struct pci_dev *dev; + if ((dev = pci_find_class(PCI_CLASS_BRIDGE_HOST << 8, NULL)) != NULL) { - if ((dev->vendor == PCI_VENDOR_ID_SERVERWORKS) && - (dev->device == PCI_DEVICE_ID_SERVERWORKS_LE)) { - printk(KERN_INFO - "mtrr: Serverworks LE detected. Write-combining disabled.\n"); + /* ServerWorks LE chipsets have problems with write-combining + Don't allow it and leave room for other chipsets to be tagged */ + if (dev->vendor == PCI_VENDOR_ID_SERVERWORKS && + dev->device == PCI_DEVICE_ID_SERVERWORKS_LE) { + printk(KERN_INFO "mtrr: Serverworks LE detected. Write-combining disabled.\n"); return 0; } - } + /* Intel 450NX errata # 23. Non ascending cachline evictions to + write combining memory may resulting in data corruption */ + if (dev->vendor == PCI_VENDOR_ID_INTEL && + dev->device == PCI_DEVICE_ID_INTEL_82451NX) + { + printk(KERN_INFO "mtrr: Intel 450NX MMC detected. Write-combining disabled.\n"); + return 0; + } + } return (mtrr_if->have_wrcomb ? mtrr_if->have_wrcomb() : 0); } @@ -121,7 +123,7 @@ max = num_var_ranges; if ((usage_table = kmalloc(max * sizeof *usage_table, GFP_KERNEL)) == NULL) { - printk("mtrr: could not allocate\n"); + printk(KERN_ERR "mtrr: could not allocate\n"); return; } for (i = 0; i < max; i++) @@ -310,7 +312,7 @@ return error; if (type >= MTRR_NUM_TYPES) { - printk("mtrr: type: %u illegal\n", type); + printk(KERN_WARNING "mtrr: type: %u invalid\n", type); return -EINVAL; } @@ -322,7 +324,7 @@ } if (base & size_or_mask || size & size_or_mask) { - printk("mtrr: base or size exceeds the MTRR width\n"); + printk(KERN_WARNING "mtrr: base or size exceeds the MTRR width\n"); return -EINVAL; } @@ -348,7 +350,7 @@ if (ltype != type) { if (type == MTRR_TYPE_UNCACHABLE) continue; - printk ("mtrr: type mismatch for %lx000,%lx000 old: %s new: %s\n", + printk (KERN_WARNING "mtrr: type mismatch for %lx000,%lx000 old: %s new: %s\n", base, size, attrib_to_str(ltype), attrib_to_str(type)); goto out; @@ -364,7 +366,7 @@ set_mtrr(i, base, size, type); usage_table[i] = 1; } else - printk("mtrr: no more MTRRs available\n"); + printk(KERN_INFO "mtrr: no more MTRRs available\n"); error = i; out: up(&main_lock); @@ -412,8 +414,8 @@ char increment) { if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) { - printk("mtrr: size and base must be multiples of 4 kiB\n"); - printk("mtrr: size: 0x%lx base: 0x%lx\n", size, base); + printk(KERN_WARNING "mtrr: size and base must be multiples of 4 kiB\n"); + printk(KERN_DEBUG "mtrr: size: 0x%lx base: 0x%lx\n", size, base); return -EINVAL; } return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type, @@ -458,28 +460,28 @@ } } if (reg < 0) { - printk("mtrr: no MTRR for %lx000,%lx000 found\n", base, + printk(KERN_DEBUG "mtrr: no MTRR for %lx000,%lx000 found\n", base, size); goto out; } } if (reg >= max) { - printk("mtrr: register: %d too big\n", reg); + printk(KERN_WARNING "mtrr: register: %d too big\n", reg); goto out; } if (is_cpu(CYRIX) && !use_intel()) { if ((reg == 3) && arr3_protected) { - printk("mtrr: ARR3 cannot be changed\n"); + printk(KERN_WARNING "mtrr: ARR3 cannot be changed\n"); goto out; } } mtrr_if->get(reg, &lbase, &lsize, <ype); if (lsize < 1) { - printk("mtrr: MTRR %d not used\n", reg); + printk(KERN_WARNING "mtrr: MTRR %d not used\n", reg); goto out; } if (usage_table[reg] < 1) { - printk("mtrr: reg: %d has count=0\n", reg); + printk(KERN_WARNING "mtrr: reg: %d has count=0\n", reg); goto out; } if (--usage_table[reg] < 1) @@ -508,8 +510,8 @@ mtrr_del(int reg, unsigned long base, unsigned long size) { if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) { - printk("mtrr: size and base must be multiples of 4 kiB\n"); - printk("mtrr: size: 0x%lx base: 0x%lx\n", size, base); + printk(KERN_INFO "mtrr: size and base must be multiples of 4 kiB\n"); + printk(KERN_DEBUG "mtrr: size: 0x%lx base: 0x%lx\n", size, base); return -EINVAL; } return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT); @@ -677,7 +679,7 @@ break; } } - printk("mtrr: v%s\n",MTRR_VERSION); + printk(KERN_INFO "mtrr: v%s\n",MTRR_VERSION); if (mtrr_if) { set_num_var_ranges(); diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c --- a/arch/i386/kernel/io_apic.c Sat Jul 19 12:54:24 2003 +++ b/arch/i386/kernel/io_apic.c Sat Jul 19 12:54:24 2003 @@ -682,6 +682,21 @@ #else /* !SMP */ static inline void move_irq(int irq) { } + +void send_IPI_self(int vector) +{ + unsigned int cfg; + + /* + * Wait for idle. + */ + apic_wait_icr_idle(); + cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL; + /* + * Send the IPI. The write to APIC_ICR fires this off. + */ + apic_write_around(APIC_ICR, cfg); +} #endif /* defined(CONFIG_SMP) */ diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c --- a/arch/i386/kernel/setup.c Sat Jul 19 12:54:25 2003 +++ b/arch/i386/kernel/setup.c Sat Jul 19 12:54:25 2003 @@ -42,6 +42,7 @@ #include #include #include +#include #include "setup_arch_pre.h" #include "mach_resources.h" @@ -100,7 +101,7 @@ extern void dmi_scan_machine(void); extern void generic_apic_probe(char *); extern int root_mountflags; -extern char _text, _etext, _edata, _end; +extern char _end[]; unsigned long saved_videomode; @@ -520,7 +521,7 @@ acpi_disabled = 1; /* "acpismp=force" turns on ACPI again */ - else if (!memcmp(from, "acpismp=force", 14)) + if (c == ' ' && !memcmp(from, "acpismp=force", 13)) acpi_disabled = 0; /* @@ -676,7 +677,7 @@ * partially used pages are not usable - thus * we are rounding upwards: */ - start_pfn = PFN_UP(__pa(&_end)); + start_pfn = PFN_UP(__pa(_end)); find_max_pfn(); @@ -947,15 +948,15 @@ if (!MOUNT_ROOT_RDONLY) root_mountflags &= ~MS_RDONLY; - init_mm.start_code = (unsigned long) &_text; - init_mm.end_code = (unsigned long) &_etext; - init_mm.end_data = (unsigned long) &_edata; - init_mm.brk = (unsigned long) &_end; - - code_resource.start = virt_to_phys(&_text); - code_resource.end = virt_to_phys(&_etext)-1; - data_resource.start = virt_to_phys(&_etext); - data_resource.end = virt_to_phys(&_edata)-1; + init_mm.start_code = (unsigned long) _text; + init_mm.end_code = (unsigned long) _etext; + init_mm.end_data = (unsigned long) _edata; + init_mm.brk = (unsigned long) _end; + + code_resource.start = virt_to_phys(_text); + code_resource.end = virt_to_phys(_etext)-1; + data_resource.start = virt_to_phys(_etext); + data_resource.end = virt_to_phys(_edata)-1; parse_cmdline_early(cmdline_p); @@ -977,7 +978,7 @@ generic_apic_probe(*cmdline_p); #endif -#ifdef CONFIG_ACPI_BOOT +#ifdef CONFIG_ACPI /* * Parse the ACPI tables for possible boot-time SMP configuration. */ diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c --- a/arch/i386/mm/init.c Sat Jul 19 12:54:26 2003 +++ b/arch/i386/mm/init.c Sat Jul 19 12:54:26 2003 @@ -20,9 +20,6 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_INITRD -#include -#endif #include #include #include @@ -565,7 +562,7 @@ free_page(addr); totalram_pages++; } - printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10); + printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (__init_end - __init_begin) >> 10); } #ifdef CONFIG_BLK_DEV_INITRD diff -Nru a/arch/i386/pci/legacy.c b/arch/i386/pci/legacy.c --- a/arch/i386/pci/legacy.c Sat Jul 19 12:54:27 2003 +++ b/arch/i386/pci/legacy.c Sat Jul 19 12:54:27 2003 @@ -24,7 +24,7 @@ for (devfn = 0; devfn < 256; devfn += 8) { if (!raw_pci_ops->read(0, n, devfn, PCI_VENDOR_ID, 2, &l) && l != 0x0000 && l != 0xffff) { - DBG("Found device at %02x:%02x [%04x]\n", n, dev->devfn, l); + DBG("Found device at %02x:%02x [%04x]\n", n, devfn, l); printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n); pci_scan_bus(n, &pci_root_ops, NULL); break; diff -Nru a/arch/i386/pci/visws.c b/arch/i386/pci/visws.c --- a/arch/i386/pci/visws.c Sat Jul 19 12:54:26 2003 +++ b/arch/i386/pci/visws.c Sat Jul 19 12:54:26 2003 @@ -17,7 +17,7 @@ int broken_hp_bios_irq9; -extern struct pci_ops pci_direct_conf1; +extern struct pci_raw_ops pci_direct_conf1; static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; } @@ -101,8 +101,9 @@ printk(KERN_INFO "PCI: Lithium bridge A bus: %u, " "bridge B (PIIX4) bus: %u\n", pci_bus1, pci_bus0); - pci_scan_bus(pci_bus0, &pci_direct_conf1, NULL); - pci_scan_bus(pci_bus1, &pci_direct_conf1, NULL); + raw_pci_ops = &pci_direct_conf1; + pci_scan_bus(pci_bus0, &pci_root_ops, NULL); + pci_scan_bus(pci_bus1, &pci_root_ops, NULL); pci_fixup_irqs(visws_swizzle, visws_map_irq); pcibios_resource_survey(); return 0; diff -Nru a/arch/ia64/Makefile b/arch/ia64/Makefile --- a/arch/ia64/Makefile Sat Jul 19 12:54:21 2003 +++ b/arch/ia64/Makefile Sat Jul 19 12:54:21 2003 @@ -66,8 +66,7 @@ drivers-$(CONFIG_PCI) += arch/ia64/pci/ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ -drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ \ - arch/ia64/sn/ +drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ boot := arch/ia64/boot diff -Nru a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c --- a/arch/ia64/hp/sim/simscsi.c Sat Jul 19 12:54:25 2003 +++ b/arch/ia64/hp/sim/simscsi.c Sat Jul 19 12:54:25 2003 @@ -9,7 +9,7 @@ * 99/12/18 David Mosberger Added support for READ10/WRITE10 needed by linux v2.3.33 */ #include -#include +#include #include #include #include diff -Nru a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c --- a/arch/ia64/ia32/ia32_ioctl.c Sat Jul 19 12:54:26 2003 +++ b/arch/ia64/ia32/ia32_ioctl.c Sat Jul 19 12:54:26 2003 @@ -52,7 +52,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c --- a/arch/ia64/kernel/acpi.c Sat Jul 19 12:54:25 2003 +++ b/arch/ia64/kernel/acpi.c Sat Jul 19 12:54:25 2003 @@ -720,7 +720,7 @@ { int vector = 0; - if (acpi_madt->flags.pcat_compat && (gsi < 16)) + if (has_8259 && (gsi < 16)) return isa_irq_to_vector(gsi); if (!iosapic_register_intr) diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S --- a/arch/ia64/kernel/entry.S Sat Jul 19 12:54:24 2003 +++ b/arch/ia64/kernel/entry.S Sat Jul 19 12:54:24 2003 @@ -61,7 +61,17 @@ mov out2=in2 // envp add out3=16,sp // regs br.call.sptk.many rp=sys_execve -.ret0: cmp4.ge p6,p7=r8,r0 +.ret0: +#ifdef CONFIG_IA32_SUPPORT + /* + * Check if we're returning to ia32 mode. If so, we need to restore ia32 registers + * from pt_regs. + */ + adds r16=PT(CR_IPSR)+16,sp + ;; + ld8 r16=[r16] +#endif + cmp4.ge p6,p7=r8,r0 mov ar.pfs=loc1 // restore ar.pfs sxt4 r8=r8 // return 64-bit result ;; @@ -89,6 +99,12 @@ ldf.fill f23=[sp]; ldf.fill f24=[sp]; mov f25=f0 ldf.fill f26=[sp]; ldf.fill f27=[sp]; mov f28=f0 ldf.fill f29=[sp]; ldf.fill f30=[sp]; mov f31=f0 +#ifdef CONFIG_IA32_SUPPORT + tbit.nz p6,p0=r16, IA64_PSR_IS_BIT + movl loc0=ia64_ret_from_ia32_execve + ;; +(p6) mov rp=loc0 +#endif br.ret.sptk.many rp END(ia64_execve) @@ -688,7 +704,7 @@ mov b7=r0 // clear b7 ;; (pUStk) st1 [r14]=r3 - movl r17=THIS_CPU(ia64_phys_stacked_size_p8) + addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0 ;; mov r16=ar.bsp // get existing backing store pointer srlz.i // ensure interruption collection is off @@ -701,6 +717,19 @@ br.cond.sptk.many rbs_switch END(ia64_leave_syscall) +#ifdef CONFIG_IA32_SUPPORT +GLOBAL_ENTRY(ia64_ret_from_ia32_execve) + PT_REGS_UNWIND_INFO(0) + adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8 + adds r3=PT(R10)+16,sp // r3 = &pt_regs.r10 + ;; + .mem.offset 0,0 + st8.spill [r2]=r8 // store return value in slot for r8 and set unat bit + .mem.offset 8,0 + st8.spill [r3]=r0 // clear error indication in slot for r10 and set unat bit +END(ia64_ret_from_ia32_execve_syscall) + // fall through +#endif /* CONFIG_IA32_SUPPORT */ GLOBAL_ENTRY(ia64_leave_kernel) PT_REGS_UNWIND_INFO(0) /* @@ -841,7 +870,7 @@ shr.u r18=r19,16 // get byte size of existing "dirty" partition ;; mov r16=ar.bsp // get existing backing store pointer - movl r17=THIS_CPU(ia64_phys_stacked_size_p8) + addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0 ;; ld4 r17=[r17] // r17 = cpu_data->phys_stacked_size_p8 (pKStk) br.cond.dpnt skip_rbs_switch diff -Nru a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S --- a/arch/ia64/kernel/fsys.S Sat Jul 19 12:54:21 2003 +++ b/arch/ia64/kernel/fsys.S Sat Jul 19 12:54:21 2003 @@ -165,7 +165,7 @@ .altrp b6 .body add r9=TI_FLAGS+IA64_TASK_SIZE,r16 - movl r3=THIS_CPU(cpu_info) + addl r3=THIS_CPU(cpu_info),r0 mov.m r31=ar.itc // put time stamp into r31 (ITC) == now (35 cyc) #ifdef CONFIG_SMP @@ -177,7 +177,7 @@ movl r19=xtime // xtime is a timespec struct ld8 r10=[r10] // r10 <- __per_cpu_offset[0] - movl r21=THIS_CPU(cpu_info) + addl r21=THIS_CPU(cpu_info),r0 ;; add r10=r21, r10 // r10 <- &cpu_data(time_keeper_id) tbit.nz p8,p0 = r2, IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT_BIT diff -Nru a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c --- a/arch/ia64/kernel/ia64_ksyms.c Sat Jul 19 12:54:25 2003 +++ b/arch/ia64/kernel/ia64_ksyms.c Sat Jul 19 12:54:25 2003 @@ -64,9 +64,10 @@ #endif #include -EXPORT_SYMBOL(cpu_info__per_cpu); +EXPORT_SYMBOL(per_cpu__cpu_info); #ifdef CONFIG_SMP EXPORT_SYMBOL(__per_cpu_offset); +EXPORT_SYMBOL(per_cpu__local_per_cpu_offset); #endif EXPORT_SYMBOL(kernel_thread); diff -Nru a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c --- a/arch/ia64/kernel/init_task.c Sat Jul 19 12:54:30 2003 +++ b/arch/ia64/kernel/init_task.c Sat Jul 19 12:54:30 2003 @@ -2,7 +2,7 @@ * This is where we statically allocate and initialize the initial * task. * - * Copyright (C) 1999, 2002 Hewlett-Packard Co + * Copyright (C) 1999, 2002-2003 Hewlett-Packard Co * David Mosberger-Tang */ @@ -34,7 +34,7 @@ struct thread_info thread_info; } s; unsigned long stack[KERNEL_STACK_SIZE/sizeof (unsigned long)]; -} init_task_mem __attribute__((section(".data.init_task"))) = {{ +} init_task_mem asm ("init_task_mem") __attribute__((section(".data.init_task"))) = {{ .task = INIT_TASK(init_task_mem.s.task), .thread_info = INIT_THREAD_INFO(init_task_mem.s.task) }}; diff -Nru a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c --- a/arch/ia64/kernel/iosapic.c Sat Jul 19 12:54:25 2003 +++ b/arch/ia64/kernel/iosapic.c Sat Jul 19 12:54:25 2003 @@ -717,6 +717,7 @@ register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, IOSAPIC_LEVEL); } + entry->irq = vector; snprintf(pci_id, sizeof(pci_id), "%02x:%02x:%02x[%c]", entry->id.segment, entry->id.bus, entry->id.device, 'A' + entry->pin); diff -Nru a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c --- a/arch/ia64/kernel/module.c Sat Jul 19 12:54:24 2003 +++ b/arch/ia64/kernel/module.c Sat Jul 19 12:54:24 2003 @@ -164,7 +164,7 @@ apply_imm64 (struct module *mod, struct insn *insn, uint64_t val) { if (slot(insn) != 2) { - printk(KERN_ERR "%s: illegal slot number %d for IMM64\n", + printk(KERN_ERR "%s: invalid slot number %d for IMM64\n", mod->name, slot(insn)); return 0; } @@ -176,7 +176,7 @@ apply_imm60 (struct module *mod, struct insn *insn, uint64_t val) { if (slot(insn) != 2) { - printk(KERN_ERR "%s: illegal slot number %d for IMM60\n", + printk(KERN_ERR "%s: invalid slot number %d for IMM60\n", mod->name, slot(insn)); return 0; } diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c --- a/arch/ia64/kernel/perfmon.c Sat Jul 19 12:54:29 2003 +++ b/arch/ia64/kernel/perfmon.c Sat Jul 19 12:54:29 2003 @@ -566,7 +566,7 @@ #define pfm_wait_task_inactive(t) wait_task_inactive(t) -#define pfm_get_cpu_var(v) __get_cpu_var(v) +#define pfm_get_cpu_var(v) __ia64_per_cpu_var(v) #define pfm_get_cpu_data(a,b) per_cpu(a, b) typedef irqreturn_t pfm_irq_handler_t; #define PFM_IRQ_HANDLER_RET(v) do { \ diff -Nru a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c --- a/arch/ia64/kernel/ptrace.c Sat Jul 19 12:54:30 2003 +++ b/arch/ia64/kernel/ptrace.c Sat Jul 19 12:54:30 2003 @@ -42,7 +42,7 @@ (IA64_PSR_UM | IA64_PSR_DB | IA64_PSR_IS | IA64_PSR_ID | IA64_PSR_DD | IA64_PSR_RI) #define IPSR_READ_MASK IPSR_WRITE_MASK -#define PTRACE_DEBUG 1 +#define PTRACE_DEBUG 0 #if PTRACE_DEBUG # define dprintk(format...) printk(format) diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c --- a/arch/ia64/kernel/setup.c Sat Jul 19 12:54:23 2003 +++ b/arch/ia64/kernel/setup.c Sat Jul 19 12:54:23 2003 @@ -56,6 +56,7 @@ #endif DEFINE_PER_CPU(struct cpuinfo_ia64, cpu_info); +DEFINE_PER_CPU(unsigned long, local_per_cpu_offset); DEFINE_PER_CPU(unsigned long, ia64_phys_stacked_size_p8); unsigned long ia64_cycles_per_usec; struct ia64_boot_param *ia64_boot_param; @@ -709,6 +710,8 @@ memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start); __per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start; cpu_data += PERCPU_PAGE_SIZE; + + per_cpu(local_per_cpu_offset, cpu) = __per_cpu_offset[cpu]; } } cpu_data = __per_cpu_start + __per_cpu_offset[smp_processor_id()]; @@ -716,19 +719,18 @@ cpu_data = __phys_per_cpu_start; #endif /* !CONFIG_SMP */ - cpu_info = cpu_data + ((char *) &__get_cpu_var(cpu_info) - __per_cpu_start); -#ifdef CONFIG_NUMA - cpu_info->node_data = get_node_data_ptr(); -#endif - get_max_cacheline_size(); /* * We can't pass "local_cpu_data" to identify_cpu() because we haven't called * ia64_mmu_init() yet. And we can't call ia64_mmu_init() first because it * depends on the data returned by identify_cpu(). We break the dependency by - * accessing cpu_data() the old way, through identity mapped space. + * accessing cpu_data() through the canonical per-CPU address. */ + cpu_info = cpu_data + ((char *) &__ia64_per_cpu_var(cpu_info) - __per_cpu_start); +#ifdef CONFIG_NUMA + cpu_info->node_data = get_node_data_ptr(); +#endif identify_cpu(cpu_info); #ifdef CONFIG_MCKINLEY diff -Nru a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c --- a/arch/ia64/kernel/smp.c Sat Jul 19 12:54:30 2003 +++ b/arch/ia64/kernel/smp.c Sat Jul 19 12:54:30 2003 @@ -72,7 +72,7 @@ #define IPI_CPU_STOP 1 /* This needs to be cacheline aligned because it is written to by *other* CPUs. */ -static DEFINE_PER_CPU(__u64, ipi_operation) ____cacheline_aligned; +static DEFINE_PER_CPU(u64, ipi_operation) ____cacheline_aligned; static void stop_this_cpu (void) @@ -91,7 +91,7 @@ handle_IPI (int irq, void *dev_id, struct pt_regs *regs) { int this_cpu = get_cpu(); - unsigned long *pending_ipis = &__get_cpu_var(ipi_operation); + unsigned long *pending_ipis = &__ia64_per_cpu_var(ipi_operation); unsigned long ops; /* Count this now; we may make a call that never returns. */ diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c --- a/arch/ia64/kernel/time.c Sat Jul 19 12:54:23 2003 +++ b/arch/ia64/kernel/time.c Sat Jul 19 12:54:23 2003 @@ -83,12 +83,11 @@ itc_get_offset (void) { unsigned long elapsed_cycles, lost = jiffies - wall_jiffies; - unsigned long now, last_tick; + unsigned long now = ia64_get_itc(), last_tick; last_tick = (cpu_data(TIME_KEEPER_ID)->itm_next - (lost + 1)*cpu_data(TIME_KEEPER_ID)->itm_delta); - now = ia64_get_itc(); if (unlikely((long) (now - last_tick) < 0)) { printk(KERN_ERR "CPU %d: now < last_tick (now=0x%lx,last_tick=0x%lx)!\n", smp_processor_id(), now, last_tick); diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c --- a/arch/ia64/pci/pci.c Sat Jul 19 12:54:25 2003 +++ b/arch/ia64/pci/pci.c Sat Jul 19 12:54:25 2003 @@ -124,7 +124,7 @@ /* Called by ACPI when it finds a new root bus. */ -static struct pci_controller * +static struct pci_controller * __devinit alloc_pci_controller (int seg) { struct pci_controller *controller; @@ -138,7 +138,7 @@ return controller; } -static int +static int __devinit alloc_resource (char *name, struct resource *root, unsigned long start, unsigned long end, unsigned long flags) { struct resource *res; @@ -159,7 +159,7 @@ return 0; } -static u64 +static u64 __devinit add_io_space (struct acpi_resource_address64 *addr) { u64 offset; @@ -190,7 +190,7 @@ return IO_SPACE_BASE(i); } -static acpi_status +static acpi_status __devinit count_window (struct acpi_resource *resource, void *data) { unsigned int *windows = (unsigned int *) data; @@ -211,7 +211,7 @@ char *name; }; -static acpi_status +static acpi_status __devinit add_window (struct acpi_resource *res, void *data) { struct pci_root_info *info = (struct pci_root_info *) data; @@ -252,7 +252,7 @@ return AE_OK; } -struct pci_bus * +struct pci_bus * __devinit pci_acpi_scan_root (struct acpi_device *device, int domain, int bus) { struct pci_root_info info; diff -Nru a/arch/ia64/scripts/check-model.c b/arch/ia64/scripts/check-model.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/scripts/check-model.c Sat Jul 19 12:54:30 2003 @@ -0,0 +1 @@ +int __attribute__ ((__model__ (__small__))) x; diff -Nru a/arch/ia64/scripts/toolchain-flags b/arch/ia64/scripts/toolchain-flags --- a/arch/ia64/scripts/toolchain-flags Sat Jul 19 12:54:29 2003 +++ b/arch/ia64/scripts/toolchain-flags Sat Jul 19 12:54:29 2003 @@ -2,6 +2,7 @@ # # Check whether linker can handle cross-segment @segrel(): # +CPPFLAGS="" CC=$1 OBJDUMP=$2 dir=$(dirname $0) @@ -11,10 +12,17 @@ res=$($OBJDUMP --full --section .rodata $out | fgrep 000 | cut -f3 -d' ') rm -f $out if [ $res != 00000a00 ]; then - echo " -DHAVE_BUGGY_SEGREL" + CPPFLAGS="$CPPFLAGS -DHAVE_BUGGY_SEGREL" cat >&2 <15)) { - printk("Trying to request illegal IRQ\n"); + printk("Trying to request invalid IRQ\n"); return -ENXIO; } @@ -72,7 +72,7 @@ void dn_free_irq(unsigned int irq, void *dev_id) { if((irq<0) || (irq>15)) { - printk("Trying to free illegal IRQ\n"); + printk("Trying to free invalid IRQ\n"); return ; } diff -Nru a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c --- a/arch/m68k/atari/stram.c Sat Jul 19 12:54:26 2003 +++ b/arch/m68k/atari/stram.c Sat Jul 19 12:54:26 2003 @@ -37,7 +37,6 @@ #define MAJOR_NR Z2RAM_MAJOR #define do_z2_request do_stram_request #define DEVICE_NR(device) (minor(device)) -#include #endif #undef DEBUG diff -Nru a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c --- a/arch/m68k/mm/init.c Sat Jul 19 12:54:27 2003 +++ b/arch/m68k/mm/init.c Sat Jul 19 12:54:27 2003 @@ -17,9 +17,6 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_RAM -#include -#endif #include #include diff -Nru a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c --- a/arch/m68k/mm/motorola.c Sat Jul 19 12:54:25 2003 +++ b/arch/m68k/mm/motorola.c Sat Jul 19 12:54:25 2003 @@ -18,9 +18,6 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_RAM -#include -#endif #include #include diff -Nru a/arch/m68k/mm/sun3mmu.c b/arch/m68k/mm/sun3mmu.c --- a/arch/m68k/mm/sun3mmu.c Sat Jul 19 12:54:24 2003 +++ b/arch/m68k/mm/sun3mmu.c Sat Jul 19 12:54:24 2003 @@ -16,9 +16,6 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_RAM -#include -#endif #include #include diff -Nru a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c --- a/arch/m68k/q40/q40ints.c Sat Jul 19 12:54:27 2003 +++ b/arch/m68k/q40/q40ints.c Sat Jul 19 12:54:27 2003 @@ -171,7 +171,7 @@ { case 1: case 2: case 8: case 9: case 12: case 13: - printk("%s: ISA IRQ %d from %x illegal\n", __FUNCTION__, irq, (unsigned)dev_id); + printk("%s: ISA IRQ %d from %x invalid\n", __FUNCTION__, irq, (unsigned)dev_id); return; case 11: irq=10; default: diff -Nru a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c --- a/arch/m68knommu/kernel/setup.c Sat Jul 19 12:54:26 2003 +++ b/arch/m68knommu/kernel/setup.c Sat Jul 19 12:54:26 2003 @@ -37,7 +37,6 @@ #include #ifdef CONFIG_BLK_DEV_INITRD -#include #include #endif diff -Nru a/arch/m68knommu/mm/init.c b/arch/m68knommu/mm/init.c --- a/arch/m68knommu/mm/init.c Sat Jul 19 12:54:26 2003 +++ b/arch/m68knommu/mm/init.c Sat Jul 19 12:54:26 2003 @@ -27,9 +27,6 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_RAM -#include -#endif #include #include #include diff -Nru a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c --- a/arch/mips/mm/fault.c Sat Jul 19 12:54:24 2003 +++ b/arch/mips/mm/fault.c Sat Jul 19 12:54:24 2003 @@ -162,7 +162,7 @@ tsk->thread.cp0_badvaddr = address; tsk->thread.error_code = write; #if 0 - printk("do_page_fault() #2: sending SIGSEGV to %s for illegal %s\n" + printk("do_page_fault() #2: sending SIGSEGV to %s for invalid %s\n" "%08lx (epc == %08lx, ra == %08lx)\n", tsk->comm, write ? "write access to" : "read access from", diff -Nru a/arch/mips/mm/init.c b/arch/mips/mm/init.c --- a/arch/mips/mm/init.c Sat Jul 19 12:54:27 2003 +++ b/arch/mips/mm/init.c Sat Jul 19 12:54:27 2003 @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c --- a/arch/mips/momentum/ocelot_c/setup.c Sat Jul 19 12:54:23 2003 +++ b/arch/mips/momentum/ocelot_c/setup.c Sat Jul 19 12:54:23 2003 @@ -63,7 +63,7 @@ #include #include #include -#include +#include #include #include "ocelot_c_fpga.h" diff -Nru a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c --- a/arch/mips/momentum/ocelot_g/setup.c Sat Jul 19 12:54:24 2003 +++ b/arch/mips/momentum/ocelot_g/setup.c Sat Jul 19 12:54:24 2003 @@ -64,7 +64,7 @@ #include #include #include -#include +#include #include "gt64240.h" #include "ocelot_pld.h" diff -Nru a/arch/mips/ramdisk/Makefile b/arch/mips/ramdisk/Makefile --- a/arch/mips/ramdisk/Makefile Sat Jul 19 12:54:26 2003 +++ b/arch/mips/ramdisk/Makefile Sat Jul 19 12:54:26 2003 @@ -2,7 +2,7 @@ # Makefile for a ramdisk image # -O_FORMAT = $(shell $(OBJDUMP) -i | head -2 | grep elf32) +O_FORMAT = $(shell $(OBJDUMP) -i | head -n 2 | grep elf32) img = $(CONFIG_EMBEDDED_RAMDISK_IMAGE) ramdisk.o: $(subst ",,$(img)) ld.script echo "O_FORMAT: " $(O_FORMAT) diff -Nru a/arch/mips/sibyte/cfe/setup.c b/arch/mips/sibyte/cfe/setup.c --- a/arch/mips/sibyte/cfe/setup.c Sat Jul 19 12:54:23 2003 +++ b/arch/mips/sibyte/cfe/setup.c Sat Jul 19 12:54:23 2003 @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/arch/mips/sibyte/sb1250/prom.c b/arch/mips/sibyte/sb1250/prom.c --- a/arch/mips/sibyte/sb1250/prom.c Sat Jul 19 12:54:26 2003 +++ b/arch/mips/sibyte/sb1250/prom.c Sat Jul 19 12:54:26 2003 @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c --- a/arch/mips/sibyte/swarm/setup.c Sat Jul 19 12:54:25 2003 +++ b/arch/mips/sibyte/swarm/setup.c Sat Jul 19 12:54:25 2003 @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c Sat Jul 19 12:54:24 2003 +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c Sat Jul 19 12:54:24 2003 @@ -134,7 +134,7 @@ #include #include #include -#include +#include #ifdef CONFIG_RTC_DS1742 #include #endif diff -Nru a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c Sat Jul 19 12:54:25 2003 +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c Sat Jul 19 12:54:25 2003 @@ -62,7 +62,7 @@ #include #include #include -#include +#include #include #ifdef CONFIG_RTC_DS1742 #include diff -Nru a/arch/mips/vr41xx/tanbac-tb0229/setup.c b/arch/mips/vr41xx/tanbac-tb0229/setup.c --- a/arch/mips/vr41xx/tanbac-tb0229/setup.c Sat Jul 19 12:54:25 2003 +++ b/arch/mips/vr41xx/tanbac-tb0229/setup.c Sat Jul 19 12:54:25 2003 @@ -18,7 +18,7 @@ * option) any later version. */ #include -#include +#include #include #include #include diff -Nru a/arch/mips64/kernel/setup.c b/arch/mips64/kernel/setup.c --- a/arch/mips64/kernel/setup.c Sat Jul 19 12:54:21 2003 +++ b/arch/mips64/kernel/setup.c Sat Jul 19 12:54:21 2003 @@ -28,9 +28,6 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_RAM -#include -#endif #include #include #include diff -Nru a/arch/parisc/kernel/ioctl32.c b/arch/parisc/kernel/ioctl32.c --- a/arch/parisc/kernel/ioctl32.c Sat Jul 19 12:54:21 2003 +++ b/arch/parisc/kernel/ioctl32.c Sat Jul 19 12:54:21 2003 @@ -48,7 +48,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c --- a/arch/ppc/kernel/irq.c Sat Jul 19 12:54:27 2003 +++ b/arch/ppc/kernel/irq.c Sat Jul 19 12:54:27 2003 @@ -420,10 +420,9 @@ { int status; struct irqaction *action; - int cpu = smp_processor_id(); irq_desc_t *desc = irq_desc + irq; - kstat_cpu(cpu).irqs[irq]++; + kstat_this_cpu.irqs[irq]++; spin_lock(&desc->lock); ack_irq(irq); /* diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S --- a/arch/ppc/kernel/misc.S Sat Jul 19 12:54:28 2003 +++ b/arch/ppc/kernel/misc.S Sat Jul 19 12:54:28 2003 @@ -1375,3 +1375,8 @@ .long sys_clock_gettime .long sys_clock_getres .long sys_clock_nanosleep + .long sys_ni_syscall /* reserved for swapcontext */ + .long sys_tgkill /* 250 */ + .long sys_utimes + .long sys_statfs64 + .long sys_fstatfs64 diff -Nru a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c --- a/arch/ppc/kernel/syscalls.c Sat Jul 19 12:54:29 2003 +++ b/arch/ppc/kernel/syscalls.c Sat Jul 19 12:54:29 2003 @@ -20,7 +20,6 @@ * */ -#include #include #include #include @@ -59,10 +58,15 @@ version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; - ret = -EINVAL; + ret = -ENOSYS; switch (call) { case SEMOP: - ret = sys_semop (first, (struct sembuf __user *)ptr, second); + ret = sys_semtimedop (first, (struct sembuf __user *)ptr, + second, NULL); + break; + case SEMTIMEDOP: + ret = sys_semtimedop (first, (struct sembuf __user *)ptr, + second, (const struct timespec *) fifth); break; case SEMGET: ret = sys_semget (first, second, third); @@ -258,6 +262,4 @@ return error; } -cond_syscall(sys_pciconfig_read); -cond_syscall(sys_pciconfig_write); cond_syscall(sys_pciconfig_iobase); diff -Nru a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c --- a/arch/ppc/kernel/time.c Sat Jul 19 12:54:26 2003 +++ b/arch/ppc/kernel/time.c Sat Jul 19 12:54:26 2003 @@ -244,7 +244,7 @@ time_t wtm_sec, new_sec = tv->tv_sec; long wtm_nsec, new_nsec = tv->tv_nsec; unsigned long flags; - int tb_delta, new_nsec, new_sec; + int tb_delta; if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) return -EINVAL; diff -Nru a/arch/ppc/mm/mem_pieces.c b/arch/ppc/mm/mem_pieces.c --- a/arch/ppc/mm/mem_pieces.c Sat Jul 19 12:54:21 2003 +++ b/arch/ppc/mm/mem_pieces.c Sat Jul 19 12:54:21 2003 @@ -17,7 +17,6 @@ #include #include #include -#include #include #include "mem_pieces.h" diff -Nru a/arch/ppc/platforms/4xx/beech.c b/arch/ppc/platforms/4xx/beech.c --- a/arch/ppc/platforms/4xx/beech.c Sat Jul 19 12:54:25 2003 +++ b/arch/ppc/platforms/4xx/beech.c Sat Jul 19 12:54:25 2003 @@ -25,7 +25,6 @@ * */ -#include #include #include #include diff -Nru a/arch/ppc/platforms/4xx/sycamore.c b/arch/ppc/platforms/4xx/sycamore.c --- a/arch/ppc/platforms/4xx/sycamore.c Sat Jul 19 12:54:25 2003 +++ b/arch/ppc/platforms/4xx/sycamore.c Sat Jul 19 12:54:25 2003 @@ -17,7 +17,6 @@ #include #include #include -#include #include #include diff -Nru a/arch/ppc/platforms/4xx/walnut.c b/arch/ppc/platforms/4xx/walnut.c --- a/arch/ppc/platforms/4xx/walnut.c Sat Jul 19 12:54:25 2003 +++ b/arch/ppc/platforms/4xx/walnut.c Sat Jul 19 12:54:25 2003 @@ -19,7 +19,6 @@ #include #include #include -#include #include #include diff -Nru a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c --- a/arch/ppc/platforms/pmac_cpufreq.c Sat Jul 19 12:54:25 2003 +++ b/arch/ppc/platforms/pmac_cpufreq.c Sat Jul 19 12:54:25 2003 @@ -176,7 +176,7 @@ freqs.old = cur_freq; freqs.new = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq; - freqs.cpu = CPUFREQ_ALL_CPUS; + freqs.cpu = smp_processor_id(); cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); if (cpufreq_uses_pmu) diff -Nru a/arch/ppc/platforms/residual.c b/arch/ppc/platforms/residual.c --- a/arch/ppc/platforms/residual.c Sat Jul 19 12:54:23 2003 +++ b/arch/ppc/platforms/residual.c Sat Jul 19 12:54:23 2003 @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ppc64/boot/Makefile b/arch/ppc64/boot/Makefile --- a/arch/ppc64/boot/Makefile Sat Jul 19 12:54:27 2003 +++ b/arch/ppc64/boot/Makefile Sat Jul 19 12:54:27 2003 @@ -118,7 +118,7 @@ ls -l vmlinux | \ awk '{printf "/* generated -- do not edit! */\n" \ "unsigned long vmlinux_filesize = %d;\n", $$5}' > $(obj)/imagesize.c - $(CROSS_COMPILE)nm -n vmlinux | tail -1 | \ + $(CROSS_COMPILE)nm -n vmlinux | tail -n 1 | \ awk '{printf "unsigned long vmlinux_memsize = 0x%s;\n", substr($$1,8)}' \ >> $(obj)/imagesize.c diff -Nru a/arch/ppc64/kernel/XmPciLpEvent.c b/arch/ppc64/kernel/XmPciLpEvent.c --- a/arch/ppc64/kernel/XmPciLpEvent.c Sat Jul 19 12:54:25 2003 +++ b/arch/ppc64/kernel/XmPciLpEvent.c Sat Jul 19 12:54:25 2003 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include diff -Nru a/arch/ppc64/kernel/iSeries_irq.c b/arch/ppc64/kernel/iSeries_irq.c --- a/arch/ppc64/kernel/iSeries_irq.c Sat Jul 19 12:54:26 2003 +++ b/arch/ppc64/kernel/iSeries_irq.c Sat Jul 19 12:54:26 2003 @@ -29,7 +29,6 @@ #include #include #include -#include #include #include diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c --- a/arch/ppc64/kernel/prom.c Sat Jul 19 12:54:26 2003 +++ b/arch/ppc64/kernel/prom.c Sat Jul 19 12:54:26 2003 @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c --- a/arch/ppc64/mm/init.c Sat Jul 19 12:54:25 2003 +++ b/arch/ppc64/mm/init.c Sat Jul 19 12:54:25 2003 @@ -37,9 +37,6 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_INITRD -#include /* for initrd_* */ -#endif #include #include diff -Nru a/arch/s390/defconfig b/arch/s390/defconfig --- a/arch/s390/defconfig Sat Jul 19 12:54:27 2003 +++ b/arch/s390/defconfig Sat Jul 19 12:54:27 2003 @@ -20,6 +20,7 @@ CONFIG_SYSCTL=y CONFIG_LOG_BUF_SHIFT=17 # CONFIG_EMBEDDED is not set +# CONFIG_KALLSYMS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -169,7 +170,7 @@ # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set -CONFIG_IPV6=m +CONFIG_IPV6=y # CONFIG_IPV6_PRIVACY is not set # CONFIG_INET6_AH is not set # CONFIG_INET6_ESP is not set @@ -180,7 +181,7 @@ # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IPV6_SCTP__=m +CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set # CONFIG_VLAN_8021Q is not set @@ -383,7 +384,6 @@ CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y # CONFIG_DEBUG_SLAB is not set -# CONFIG_KALLSYMS is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # diff -Nru a/arch/s390/kernel/compat_ioctl.c b/arch/s390/kernel/compat_ioctl.c --- a/arch/s390/kernel/compat_ioctl.c Sat Jul 19 12:54:26 2003 +++ b/arch/s390/kernel/compat_ioctl.c Sat Jul 19 12:54:26 2003 @@ -23,7 +23,6 @@ #include #include -#include #include #include #include diff -Nru a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c --- a/arch/s390/kernel/compat_linux.c Sat Jul 19 12:54:27 2003 +++ b/arch/s390/kernel/compat_linux.c Sat Jul 19 12:54:27 2003 @@ -250,14 +250,14 @@ static inline long get_tv32(struct timeval *o, struct compat_timeval *i) { return (!access_ok(VERIFY_READ, tv32, sizeof(*tv32)) || - (__get_user(o->tv_sec, &i->tv_sec) | + (__get_user(o->tv_sec, &i->tv_sec) || __get_user(o->tv_usec, &i->tv_usec))); } static inline long put_tv32(struct compat_timeval *o, struct timeval *i) { return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || - (__put_user(i->tv_sec, &o->tv_sec) | + (__put_user(i->tv_sec, &o->tv_sec) || __put_user(i->tv_usec, &o->tv_usec))); } diff -Nru a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S --- a/arch/s390/kernel/entry.S Sat Jul 19 12:54:23 2003 +++ b/arch/s390/kernel/entry.S Sat Jul 19 12:54:23 2003 @@ -606,6 +606,8 @@ SAVE_ALL_BASE SAVE_ALL __LC_EXT_OLD_PSW,0 GET_THREAD_INFO # load pointer to task_struct to R9 + l %r1,BASED(.Ldo_extint) + basr %r14,%r1 lh %r6,__LC_EXT_INT_CODE # get interruption code lr %r1,%r6 # calculate index = code & 0xff n %r1,BASED(.Lc0xff) @@ -694,6 +696,7 @@ */ .Ls390_mcck: .long s390_do_machine_check .Ldo_IRQ: .long do_IRQ +.Ldo_extint: .long do_extint .Ldo_signal: .long do_signal .Ldo_softirq: .long do_softirq .Lentry_base: .long entry_base diff -Nru a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S --- a/arch/s390/kernel/entry64.S Sat Jul 19 12:54:23 2003 +++ b/arch/s390/kernel/entry64.S Sat Jul 19 12:54:23 2003 @@ -637,6 +637,7 @@ ext_int_handler: SAVE_ALL __LC_EXT_OLD_PSW,0 GET_THREAD_INFO # load pointer to task_struct to R9 + brasl %r14,do_extint llgh %r6,__LC_EXT_INT_CODE # get interruption code lgr %r1,%r6 # calculate index = code & 0xff nill %r1,0xff diff -Nru a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c --- a/arch/s390/kernel/s390_ext.c Sat Jul 19 12:54:25 2003 +++ b/arch/s390/kernel/s390_ext.c Sat Jul 19 12:54:25 2003 @@ -11,8 +11,11 @@ #include #include #include +#include + #include #include +#include /* * Simple hash strategy: index = code & 0xff; @@ -96,6 +99,11 @@ } else ext_int_hash[index] = p->next; return 0; +} + +void do_extint(void) +{ + kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++; } EXPORT_SYMBOL(register_external_interrupt); diff -Nru a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c --- a/arch/s390/kernel/setup.c Sat Jul 19 12:54:22 2003 +++ b/arch/s390/kernel/setup.c Sat Jul 19 12:54:22 2003 @@ -34,12 +34,15 @@ #include #include #include +#include + #include #include #include #include #include #include +#include /* * Machine setup.. @@ -600,3 +603,40 @@ .stop = c_stop, .show = show_cpuinfo, }; + +/* + * show_interrupts is needed by /proc/interrupts. + */ + +static const char *intrclass_names[] = { + "EXT", + "I/O", +}; + +int show_interrupts(struct seq_file *p, void *v) +{ + int i, j; + + seq_puts(p, " "); + + for (j=0; j #include #include -#ifdef CONFIG_BLK_DEV_INITRD -#include -#endif #include #include diff -Nru a/arch/sh/mm/init.c b/arch/sh/mm/init.c --- a/arch/sh/mm/init.c Sat Jul 19 12:54:27 2003 +++ b/arch/sh/mm/init.c Sat Jul 19 12:54:27 2003 @@ -22,9 +22,6 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_INITRD -#include -#endif #include #include diff -Nru a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c --- a/arch/sparc/kernel/process.c Sat Jul 19 12:54:23 2003 +++ b/arch/sparc/kernel/process.c Sat Jul 19 12:54:23 2003 @@ -590,16 +590,20 @@ put_psr(get_psr() | PSR_EF); fpsave(¤t->thread.float_regs[0], ¤t->thread.fsr, ¤t->thread.fpqueue[0], ¤t->thread.fpqdepth); - regs->psr &= ~(PSR_EF); - current->flags &= ~(PF_USEDFPU); + if (regs != NULL) { + regs->psr &= ~(PSR_EF); + current->flags &= ~(PF_USEDFPU); + } } #else if (current == last_task_used_math) { put_psr(get_psr() | PSR_EF); fpsave(¤t->thread.float_regs[0], ¤t->thread.fsr, ¤t->thread.fpqueue[0], ¤t->thread.fpqdepth); - last_task_used_math = 0; - regs->psr &= ~(PSR_EF); + if (regs != NULL) { + regs->psr &= ~(PSR_EF); + last_task_used_math = 0; + } } #endif memcpy(&fpregs->pr_fr.pr_regs[0], diff -Nru a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c --- a/arch/sparc/kernel/setup.c Sat Jul 19 12:54:21 2003 +++ b/arch/sparc/kernel/setup.c Sat Jul 19 12:54:21 2003 @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c --- a/arch/sparc/mm/srmmu.c Sat Jul 19 12:54:25 2003 +++ b/arch/sparc/mm/srmmu.c Sat Jul 19 12:54:25 2003 @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S --- a/arch/sparc64/kernel/head.S Sat Jul 19 12:54:24 2003 +++ b/arch/sparc64/kernel/head.S Sat Jul 19 12:54:24 2003 @@ -66,7 +66,7 @@ sparc_ramdisk_size: .word 0 .xword reboot_command - .xword bootstr_len + .xword bootstr_info .word _end /* We must be careful, 32-bit OpenBOOT will get confused if it @@ -740,8 +740,9 @@ .data .align 8 - .globl prom_tba + .globl prom_tba, tlb_type prom_tba: .xword 0 +tlb_type: .word 0 /* Must NOT end up in BSS */ .section ".fixup",#alloc,#execinstr .globl __ret_efault __ret_efault: diff -Nru a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c --- a/arch/sparc64/kernel/pci.c Sat Jul 19 12:54:21 2003 +++ b/arch/sparc64/kernel/pci.c Sat Jul 19 12:54:21 2003 @@ -804,25 +804,20 @@ /* Return the domain nuber for this pci bus */ -int pci_domain_nr(struct pci_bus *bus) +int pci_domain_nr(struct pci_bus *pbus) { - struct pcidev_cookie *cookie = bus->sysdata; + struct pci_pbm_info *pbm = pbus->sysdata; int ret; - if (cookie != NULL) { - struct pci_pbm_info *pbm = cookie->pbm; - if (pbm == NULL || pbm->parent == NULL) { - ret = -ENXIO; - } else { - struct pci_controller_info *p = pbm->parent; - - ret = p->index; - if (p->pbms_same_domain == 0) - ret = ((ret << 1) + - ((pbm == &pbm->parent->pbm_B) ? 1 : 0)); - } - } else { + if (pbm == NULL || pbm->parent == NULL) { ret = -ENXIO; + } else { + struct pci_controller_info *p = pbm->parent; + + ret = p->index; + if (p->pbms_same_domain == 0) + ret = ((ret << 1) + + ((pbm == &pbm->parent->pbm_B) ? 1 : 0)); } return ret; diff -Nru a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c --- a/arch/sparc64/kernel/setup.c Sat Jul 19 12:54:24 2003 +++ b/arch/sparc64/kernel/setup.c Sat Jul 19 12:54:24 2003 @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c --- a/arch/sparc64/kernel/sparc64_ksyms.c Sat Jul 19 12:54:27 2003 +++ b/arch/sparc64/kernel/sparc64_ksyms.c Sat Jul 19 12:54:27 2003 @@ -176,6 +176,8 @@ /* Atomic counter implementation. */ EXPORT_SYMBOL(__atomic_add); EXPORT_SYMBOL(__atomic_sub); +EXPORT_SYMBOL(__atomic64_add); +EXPORT_SYMBOL(__atomic64_sub); #ifdef CONFIG_SMP EXPORT_SYMBOL(atomic_dec_and_lock); #endif diff -Nru a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c --- a/arch/sparc64/kernel/time.c Sat Jul 19 12:54:25 2003 +++ b/arch/sparc64/kernel/time.c Sat Jul 19 12:54:25 2003 @@ -41,6 +41,7 @@ #include #include #include +#include spinlock_t mostek_lock = SPIN_LOCK_UNLOCKED; spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; @@ -449,7 +450,6 @@ return; { - extern int _stext; extern int rwlock_impl_begin, rwlock_impl_end; extern int atomic_impl_begin, atomic_impl_end; extern int __memcpy_begin, __memcpy_end; @@ -468,7 +468,7 @@ pc < (unsigned long) &__bitops_end)) pc = o7; - pc -= (unsigned long) &_stext; + pc -= (unsigned long) _stext; pc >>= prof_shift; if(pc >= prof_len) diff -Nru a/arch/sparc64/lib/atomic.S b/arch/sparc64/lib/atomic.S --- a/arch/sparc64/lib/atomic.S Sat Jul 19 12:54:27 2003 +++ b/arch/sparc64/lib/atomic.S Sat Jul 19 12:54:27 2003 @@ -33,4 +33,27 @@ membar #StoreLoad | #StoreStore retl sub %g7, %o0, %o0 + + .globl __atomic64_add +__atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */ + ldx [%o1], %g5 + add %g5, %o0, %g7 + casx [%o1], %g5, %g7 + cmp %g5, %g7 + bne,pn %xcc, __atomic64_add + membar #StoreLoad | #StoreStore + retl + add %g7, %o0, %o0 + + .globl __atomic64_sub +__atomic64_sub: /* %o0 = increment, %o1 = atomic_ptr */ + ldx [%o1], %g5 + sub %g5, %o0, %g7 + casx [%o1], %g5, %g7 + cmp %g5, %g7 + bne,pn %xcc, __atomic64_sub + membar #StoreLoad | #StoreStore + retl + sub %g7, %o0, %o0 + atomic_impl_end: diff -Nru a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c --- a/arch/sparc64/mm/fault.c Sat Jul 19 12:54:29 2003 +++ b/arch/sparc64/mm/fault.c Sat Jul 19 12:54:29 2003 @@ -26,6 +26,7 @@ #include #include #include +#include #define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0])) @@ -320,10 +321,9 @@ if (regs->tstate & TSTATE_PRIV) { unsigned long tpc = regs->tpc; - extern unsigned int _etext; /* Sanity check the PC. */ - if ((tpc >= KERNBASE && tpc < (unsigned long) &_etext) || + if ((tpc >= KERNBASE && tpc < (unsigned long) _etext) || (tpc >= MODULES_VADDR && tpc < MODULES_END)) { /* Valid, no problems... */ } else { diff -Nru a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c --- a/arch/sparc64/mm/init.c Sat Jul 19 12:54:24 2003 +++ b/arch/sparc64/mm/init.c Sat Jul 19 12:54:24 2003 @@ -35,6 +35,7 @@ #include #include #include +#include DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); @@ -48,16 +49,14 @@ unsigned long phys_base; unsigned long pfn_base; -enum ultra_tlb_layout tlb_type = spitfire; - /* get_new_mmu_context() uses "cache + 1". */ spinlock_t ctx_alloc_lock = SPIN_LOCK_UNLOCKED; unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1; #define CTX_BMAP_SLOTS (1UL << (CTX_VERSION_SHIFT - 6)) unsigned long mmu_context_bmap[CTX_BMAP_SLOTS]; -/* References to section boundaries */ -extern char __init_begin, __init_end, _start, _end, etext, edata; +/* References to special section boundaries */ +extern char _start[], _end[]; /* Initial ramdisk setup */ extern unsigned int sparc_ramdisk_image; @@ -1333,7 +1332,7 @@ * image. The kernel is hard mapped below PAGE_OFFSET in a * 4MB locked TLB translation. */ - start_pfn = PAGE_ALIGN((unsigned long) &_end) - + start_pfn = PAGE_ALIGN((unsigned long) _end) - ((unsigned long) KERNBASE); /* Adjust up to the physical address where the kernel begins. */ @@ -1349,7 +1348,7 @@ #ifdef CONFIG_BLK_DEV_INITRD /* Now have to check initial ramdisk, so that bootmap does not overwrite it */ if (sparc_ramdisk_image) { - if (sparc_ramdisk_image >= (unsigned long)&_end - 2 * PAGE_SIZE) + if (sparc_ramdisk_image >= (unsigned long)_end - 2 * PAGE_SIZE) sparc_ramdisk_image -= KERNBASE; initrd_start = sparc_ramdisk_image + phys_base; initrd_end = initrd_start + sparc_ramdisk_size; @@ -1426,7 +1425,7 @@ set_bit(0, mmu_context_bmap); - real_end = (unsigned long)&_end; + real_end = (unsigned long)_end; if ((real_end > ((unsigned long)KERNBASE + 0x400000))) bigkernel = 1; #ifdef CONFIG_BLK_DEV_INITRD @@ -1718,7 +1717,7 @@ memset(sparc64_valid_addr_bitmap, 0, i << 3); addr = PAGE_OFFSET + phys_base; - last = PAGE_ALIGN((unsigned long)&_end) - + last = PAGE_ALIGN((unsigned long)_end) - ((unsigned long) KERNBASE); last += PAGE_OFFSET + phys_base; while (addr < last) { @@ -1745,11 +1744,11 @@ SetPageReserved(mem_map_zero); clear_page(page_address(mem_map_zero)); - codepages = (((unsigned long) &etext) - ((unsigned long)&_start)); + codepages = (((unsigned long) _etext) - ((unsigned long) _start)); codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT; - datapages = (((unsigned long) &edata) - ((unsigned long)&etext)); + datapages = (((unsigned long) _edata) - ((unsigned long) _etext)); datapages = PAGE_ALIGN(datapages) >> PAGE_SHIFT; - initpages = (((unsigned long) &__init_end) - ((unsigned long) &__init_begin)); + initpages = (((unsigned long) __init_end) - ((unsigned long) __init_begin)); initpages = PAGE_ALIGN(initpages) >> PAGE_SHIFT; #ifndef CONFIG_SMP @@ -1812,8 +1811,8 @@ /* * The init section is aligned to 8k in vmlinux.lds. Page align for >8k pagesizes. */ - addr = PAGE_ALIGN((unsigned long)(&__init_begin)); - initend = (unsigned long)(&__init_end) & PAGE_MASK; + addr = PAGE_ALIGN((unsigned long)(__init_begin)); + initend = (unsigned long)(__init_end) & PAGE_MASK; for (; addr < initend; addr += PAGE_SIZE) { unsigned long page; struct page *p; diff -Nru a/arch/sparc64/prom/bootstr.c b/arch/sparc64/prom/bootstr.c --- a/arch/sparc64/prom/bootstr.c Sat Jul 19 12:54:23 2003 +++ b/arch/sparc64/prom/bootstr.c Sat Jul 19 12:54:23 2003 @@ -15,16 +15,22 @@ */ #define BARG_LEN 256 -int bootstr_len = BARG_LEN; -static int bootstr_valid = 0; -static char bootstr_buf[BARG_LEN] = { 0 }; +struct { + int bootstr_len; + int bootstr_valid; + char bootstr_buf[BARG_LEN]; +} bootstr_info = { + .bootstr_len = BARG_LEN, +}; char * __init prom_getbootargs(void) { /* This check saves us from a panic when bootfd patches args. */ - if (bootstr_valid) return bootstr_buf; - prom_getstring(prom_chosen_node, "bootargs", bootstr_buf, BARG_LEN); - bootstr_valid = 1; - return bootstr_buf; + if (bootstr_info.bootstr_valid) + return bootstr_info.bootstr_buf; + prom_getstring(prom_chosen_node, "bootargs", + bootstr_info.bootstr_buf, BARG_LEN); + bootstr_info.bootstr_valid = 1; + return bootstr_info.bootstr_buf; } diff -Nru a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c --- a/arch/um/drivers/ubd_kern.c Sat Jul 19 12:54:25 2003 +++ b/arch/um/drivers/ubd_kern.c Sat Jul 19 12:54:25 2003 @@ -15,7 +15,6 @@ #include "linux/config.h" #include "linux/module.h" -#include "linux/blk.h" #include "linux/blkdev.h" #include "linux/hdreg.h" #include "linux/init.h" diff -Nru a/arch/v850/Kconfig b/arch/v850/Kconfig --- a/arch/v850/Kconfig Sat Jul 19 12:54:25 2003 +++ b/arch/v850/Kconfig Sat Jul 19 12:54:25 2003 @@ -48,20 +48,24 @@ choice prompt "Platform" default GDB + config V850E_SIM + bool "GDB" config RTE_CB_MA1 bool "RTE-V850E/MA1-CB" config RTE_CB_NB85E bool "RTE-V850E/NB85E-CB" - config V850E_SIM - bool "GDB" + config RTE_CB_ME2 + bool "RTE-V850E/ME2-CB" + config V850E_AS85EP1 + bool "AS85EP1" config V850E2_SIM85E2C bool "sim85e2c" + config V850E2_SIM85E2S + bool "sim85e2s" config V850E2_FPGA85E2C bool "NA85E2C-FPGA" config V850E2_ANNA bool "Anna" - config V850E_AS85EP1 - bool "AS85EP1" endchoice @@ -78,41 +82,32 @@ bool depends RTE_CB_MA1 default y - # Similarly for the RTE-V850E/MA1-CB - V850E/TEG + # Similarly for the RTE-V850E/NB85E-CB - V850E/TEG config V850E_TEG bool depends RTE_CB_NB85E default y - - # NB85E processor core - config V850E_NB85E + # ... and the RTE-V850E/ME2-CB - V850E/ME2 + config V850E_ME2 bool - depends V850E_MA1 || V850E_TEG + depends RTE_CB_ME2 default y - config V850E_MA1_HIGHRES_TIMER - bool "High resolution timer support" - depends V850E_MA1 - - #### V850E2 processor-specific config + #### sim85e2-specific config - # V850E2 processors - config V850E2 + config V850E2_SIM85E2 bool - depends V850E2_SIM85E2C || V850E2_FPGA85E2C || V850E2_ANNA + depends V850E2_SIM85E2C || V850E2_SIM85E2S default y - # Processors based on the NA85E2A core - config V850E2_NA85E2A - bool - depends V850E2_ANNA - default y - # Processors based on the NA85E2C core - config V850E2_NA85E2C + #### V850E2 processor-specific config + + # V850E2 processors + config V850E2 bool - depends V850E2_SIM85E2C || V850E2_FPGA85E2C + depends V850E2_SIM85E2 || V850E2_FPGA85E2C || V850E2_ANNA default y @@ -121,7 +116,7 @@ # Boards in the RTE-x-CB series config RTE_CB bool - depends RTE_CB_MA1 || RTE_CB_NB85E + depends RTE_CB_MA1 || RTE_CB_NB85E || RTE_CB_ME2 default y config RTE_CB_MULTI @@ -129,7 +124,7 @@ # RTE_CB_NB85E can either have multi ROM support or not, but # other platforms (currently only RTE_CB_MA1) require it. prompt "Multi monitor ROM support" if RTE_CB_NB85E - depends RTE_CB + depends RTE_CB_MA1 || RTE_CB_NB85E default y config RTE_CB_MULTI_DBTRAP @@ -156,14 +151,42 @@ # The only PCI bus we support is on the RTE-MOTHER-A board config PCI bool - default y if RTE_MB_A_PCI + default RTE_MB_A_PCI + + + #### Some feature-specific configs + + # Everything except for the GDB simulator uses the same interrupt controller + config V850E_INTC + bool + default !V850E_SIM + + # Everything except for the various simulators uses the "Timer D" unit + config V850E_TIMER_D + bool + default !V850E_SIM && !V850E2_SIM85E2 + + # Cache control used on some v850e1 processors + config V850E_CACHE + bool + default V850E_TEG || V850E_ME2 + + # Cache control used on v850e2 processors; I think this should + # actually apply to more, but currently only the SIM85E2S uses it + config V850E2_CACHE + bool + default V850E2_SIM85E2S + + config NO_CACHE + bool + default !V850E_CACHE && !V850E2_CACHE #### Misc config config ROM_KERNEL bool "Kernel in ROM" - depends V850E2_ANNA || (RTE_CB && !RTE_CB_MULTI) + depends V850E2_ANNA || V850E_AS85EP1 || RTE_CB_ME2 # Some platforms pre-zero memory, in which case the kernel doesn't need to config ZERO_BSS @@ -177,9 +200,12 @@ int default 8 if V850E2_SIM85E2C || V850E2_FPGA85E2C + config V850E_HIGHRES_TIMER + bool "High resolution timer support" + depends V850E_TIMER_D config TIME_BOOTUP bool "Time bootup" - depends V850E_MA1_HIGHRES_TIMER + depends V850E_HIGHRES_TIMER config RESET_GUARD bool "Reset Guard" @@ -241,6 +267,7 @@ default y config KCORE_ELF + bool default y source "fs/Kconfig.binfmt" diff -Nru a/arch/v850/kernel/Makefile b/arch/v850/kernel/Makefile --- a/arch/v850/kernel/Makefile Sat Jul 19 12:54:30 2003 +++ b/arch/v850/kernel/Makefile Sat Jul 19 12:54:30 2003 @@ -15,24 +15,26 @@ signal.o irq.o mach.o ptrace.o bug.o obj-$(CONFIG_MODULES) += module.o v850_ksyms.o # chip-specific code -obj-$(CONFIG_V850E_NB85E) += nb85e_intc.o -obj-$(CONFIG_V850E_MA1) += ma.o nb85e_utils.o nb85e_timer_d.o -obj-$(CONFIG_V850E_TEG) += teg.o nb85e_utils.o nb85e_cache.o \ - nb85e_timer_d.o -obj-$(CONFIG_V850E2_ANNA) += anna.o nb85e_intc.o nb85e_utils.o \ - nb85e_timer_d.o -obj-$(CONFIG_V850E_AS85EP1) += as85ep1.o nb85e_intc.o nb85e_utils.o \ - nb85e_timer_d.o +obj-$(CONFIG_V850E_MA1) += ma.o +obj-$(CONFIG_V850E_ME2) += me2.o +obj-$(CONFIG_V850E_TEG) += teg.o +obj-$(CONFIG_V850E_AS85EP1) += as85ep1.o +obj-$(CONFIG_V850E2_ANNA) += anna.o # platform-specific code obj-$(CONFIG_V850E_SIM) += sim.o simcons.o -obj-$(CONFIG_V850E2_SIM85E2C) += sim85e2c.o nb85e_intc.o memcons.o -obj-$(CONFIG_V850E2_FPGA85E2C) += fpga85e2c.o nb85e_intc.o memcons.o +obj-$(CONFIG_V850E2_SIM85E2) += sim85e2.o memcons.o +obj-$(CONFIG_V850E2_FPGA85E2C) += fpga85e2c.o memcons.o obj-$(CONFIG_RTE_CB) += rte_cb.o rte_cb_leds.o obj-$(CONFIG_RTE_CB_MA1) += rte_ma1_cb.o +obj-$(CONFIG_RTE_CB_ME2) += rte_me2_cb.o obj-$(CONFIG_RTE_CB_NB85E) += rte_nb85e_cb.o obj-$(CONFIG_RTE_CB_MULTI) += rte_cb_multi.o obj-$(CONFIG_RTE_MB_A_PCI) += rte_mb_a_pci.o obj-$(CONFIG_RTE_GBUS_INT) += gbus_int.o # feature-specific code -obj-$(CONFIG_V850E_MA1_HIGHRES_TIMER) += highres_timer.o +obj-$(CONFIG_V850E_INTC) += v850e_intc.o +obj-$(CONFIG_V850E_TIMER_D) += v850e_timer_d.o v850e_utils.o +obj-$(CONFIG_V850E_CACHE) += v850e_cache.o +obj-$(CONFIG_V850E2_CACHE) += v850e2_cache.o +obj-$(CONFIG_V850E_HIGHRES_TIMER) += highres_timer.o obj-$(CONFIG_PROC_FS) += procfs.o diff -Nru a/arch/v850/kernel/anna.c b/arch/v850/kernel/anna.c --- a/arch/v850/kernel/anna.c Sat Jul 19 12:54:25 2003 +++ b/arch/v850/kernel/anna.c Sat Jul 19 12:54:25 2003 @@ -1,8 +1,8 @@ /* * arch/v850/kernel/anna.c -- Anna V850E2 evaluation chip/board * - * Copyright (C) 2002 NEC Corporation - * Copyright (C) 2002 Miles Bader + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader * * 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 @@ -21,8 +21,8 @@ #include #include #include -#include -#include +#include +#include #include "mach.h" @@ -41,32 +41,34 @@ void __init mach_early_init (void) { - ANNA_ILBEN = 0; - ANNA_CSC(0) = 0x402F; - ANNA_CSC(1) = 0x4000; - ANNA_BPC = 0; - ANNA_BSC = 0xAAAA; - ANNA_BEC = 0; - ANNA_BHC = 0xFFFF; /* icache all memory, dcache all */ - ANNA_BCT(0) = 0xB088; - ANNA_BCT(1) = 0x0008; - ANNA_DWC(0) = 0x0027; - ANNA_DWC(1) = 0; - ANNA_BCC = 0x0006; - ANNA_ASC = 0; - ANNA_LBS = 0x0089; - ANNA_SCR3 = 0x21A9; - ANNA_RFS3 = 0x8121; + ANNA_ILBEN = 0; - nb85e_intc_disable_irqs (); + V850E2_CSC(0) = 0x402F; + V850E2_CSC(1) = 0x4000; + V850E2_BPC = 0; + V850E2_BSC = 0xAAAA; + V850E2_BEC = 0; + +#if 0 + V850E2_BHC = 0xFFFF; /* icache all memory, dcache all */ +#else + V850E2_BHC = 0; /* cache no memory */ +#endif + V850E2_BCT(0) = 0xB088; + V850E2_BCT(1) = 0x0008; + V850E2_DWC(0) = 0x0027; + V850E2_DWC(1) = 0; + V850E2_BCC = 0x0006; + V850E2_ASC = 0; + V850E2_LBS = 0x0089; + V850E2_SCR(3) = 0x21A9; + V850E2_RFS(3) = 0x8121; + + v850e_intc_disable_irqs (); } void __init mach_setup (char **cmdline) { -#ifdef CONFIG_V850E_NB85E_UART_CONSOLE - nb85e_uart_cons_init (1); -#endif - ANNA_PORT_PM (LEDS_PORT) = 0; /* Make all LED pins output pins. */ mach_tick = anna_led_tick; } @@ -95,12 +97,12 @@ void __init mach_sched_init (struct irqaction *timer_action) { /* Start hardware timer. */ - nb85e_timer_d_configure (0, HZ); + v850e_timer_d_configure (0, HZ); /* Install timer interrupt handler. */ setup_irq (IRQ_INTCMD(0), timer_action); } -static struct nb85e_intc_irq_init irq_inits[] = { +static struct v850e_intc_irq_init irq_inits[] = { { "IRQ", 0, NUM_MACH_IRQS, 1, 7 }, { "PIN", IRQ_INTP(0), IRQ_INTP_NUM, 1, 4 }, { "CCC", IRQ_INTCCC(0), IRQ_INTCCC_NUM, 1, 5 }, @@ -118,7 +120,7 @@ void __init mach_init_irqs (void) { - nb85e_intc_init_irq_types (irq_inits, hw_itypes); + v850e_intc_init_irq_types (irq_inits, hw_itypes); } void machine_restart (char *__unused) diff -Nru a/arch/v850/kernel/as85ep1.c b/arch/v850/kernel/as85ep1.c --- a/arch/v850/kernel/as85ep1.c Sat Jul 19 12:54:29 2003 +++ b/arch/v850/kernel/as85ep1.c Sat Jul 19 12:54:29 2003 @@ -1,8 +1,8 @@ /* * arch/v850/kernel/as85ep1.c -- AS85EP1 V850E evaluation chip/board * - * Copyright (C) 2002 NEC Corporation - * Copyright (C) 2002 Miles Bader + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader * * 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 @@ -21,8 +21,8 @@ #include #include #include -#include -#include +#include +#include #include "mach.h" @@ -90,20 +90,14 @@ AS85EP1_IRAMM = 0x0; /* $BFbB"L?Na(BRAM$B$O!V(Bread-mode$B!W$K$J$j$^$9(B */ #endif /* !CONFIG_ROM_KERNEL */ - nb85e_intc_disable_irqs (); + v850e_intc_disable_irqs (); } void __init mach_setup (char **cmdline) { -#ifdef CONFIG_V850E_NB85E_UART_CONSOLE - nb85e_uart_cons_init (1); -#endif - AS85EP1_PORT_PMC (LEDS_PORT) = 0; /* Make the LEDs port an I/O port. */ AS85EP1_PORT_PM (LEDS_PORT) = 0; /* Make all the bits output pins. */ mach_tick = as85ep1_led_tick; - - ROOT_DEV = MKDEV (BLKMEM_MAJOR, 0); } void __init mach_get_physical_ram (unsigned long *ram_start, @@ -137,21 +131,21 @@ root_fs_image_end - root_fs_image_start); } -void mach_gettimeofday (struct timeval *tv) +void mach_gettimeofday (struct timespec *tv) { tv->tv_sec = 0; - tv->tv_usec = 0; + tv->tv_nsec = 0; } void __init mach_sched_init (struct irqaction *timer_action) { /* Start hardware timer. */ - nb85e_timer_d_configure (0, HZ); + v850e_timer_d_configure (0, HZ); /* Install timer interrupt handler. */ setup_irq (IRQ_INTCMD(0), timer_action); } -static struct nb85e_intc_irq_init irq_inits[] = { +static struct v850e_intc_irq_init irq_inits[] = { { "IRQ", 0, NUM_MACH_IRQS, 1, 7 }, { "CCC", IRQ_INTCCC(0), IRQ_INTCCC_NUM, 1, 5 }, { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 }, @@ -166,7 +160,7 @@ void __init mach_init_irqs (void) { - nb85e_intc_init_irq_types (irq_inits, hw_itypes); + v850e_intc_init_irq_types (irq_inits, hw_itypes); } void machine_restart (char *__unused) diff -Nru a/arch/v850/kernel/fpga85e2c.c b/arch/v850/kernel/fpga85e2c.c --- a/arch/v850/kernel/fpga85e2c.c Sat Jul 19 12:54:28 2003 +++ b/arch/v850/kernel/fpga85e2c.c Sat Jul 19 12:54:28 2003 @@ -2,8 +2,8 @@ * arch/v850/kernel/fpga85e2c.h -- Machine-dependent defs for * FPGA implementation of V850E2/NA85E2C * - * Copyright (C) 2002 NEC Corporation - * Copyright (C) 2002 Miles Bader + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader * * 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 @@ -46,7 +46,7 @@ /* Set bus sizes: CS0 32-bit, CS1 16-bit, CS7 8-bit, everything else 32-bit. */ - BSC = 0x2AA6; + V850E2_BSC = 0x2AA6; for (i = 2; i <= 6; i++) CSDEV(i) = 0; /* 32 bit */ @@ -134,7 +134,7 @@ /* Interrupts */ -struct nb85e_intc_irq_init irq_inits[] = { +struct v850e_intc_irq_init irq_inits[] = { { "IRQ", 0, NUM_MACH_IRQS, 1, 7 }, { "RPU", IRQ_RPU(0), IRQ_RPU_NUM, 1, 6 }, { 0 } @@ -146,7 +146,7 @@ /* Initialize interrupts. */ void __init mach_init_irqs (void) { - nb85e_intc_init_irq_types (irq_inits, hw_itypes); + v850e_intc_init_irq_types (irq_inits, hw_itypes); } diff -Nru a/arch/v850/kernel/gbus_int.c b/arch/v850/kernel/gbus_int.c --- a/arch/v850/kernel/gbus_int.c Sat Jul 19 12:54:30 2003 +++ b/arch/v850/kernel/gbus_int.c Sat Jul 19 12:54:30 2003 @@ -113,9 +113,7 @@ /* Only pay attention to enabled interrupts. */ status &= enable; if (status) { - unsigned base_irq - = IRQ_GBUS_INT (w * GBUS_INT_BITS_PER_WORD); - irq = base_irq; + irq = IRQ_GBUS_INT (w * GBUS_INT_BITS_PER_WORD); do { /* There's an active interrupt in word W, find out which one, and call its @@ -247,7 +245,7 @@ /* First initialize the shared gint interrupts. */ for (i = 0; i < NUM_USED_GINTS; i++) { unsigned gint = used_gint[i].gint; - struct nb85e_intc_irq_init gint_irq_init[2]; + struct v850e_intc_irq_init gint_irq_init[2]; /* We initialize one GINT interrupt at a time. */ gint_irq_init[0].name = "GINT"; @@ -258,7 +256,7 @@ gint_irq_init[1].name = 0; /* Terminate the vector. */ - nb85e_intc_init_irq_types (gint_irq_init, gint_hw_itypes); + v850e_intc_init_irq_types (gint_irq_init, gint_hw_itypes); } /* Then the GBUS interrupts. */ diff -Nru a/arch/v850/kernel/head.S b/arch/v850/kernel/head.S --- a/arch/v850/kernel/head.S Sat Jul 19 12:54:23 2003 +++ b/arch/v850/kernel/head.S Sat Jul 19 12:54:23 2003 @@ -1,8 +1,8 @@ /* * arch/v850/kernel/head.S -- Lowest-level startup code * - * Copyright (C) 2001,02 NEC Corporation - * Copyright (C) 2001,02 Miles Bader + * Copyright (C) 2001,02,03 NEC Electronics Corporation + * Copyright (C) 2001,02,03 Miles Bader * * 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 @@ -115,7 +115,14 @@ jarl CSYM(memset), lp #endif - // Start Linux kernel. + // What happens if the main kernel function returns (it shouldn't) mov hilo(CSYM(machine_halt)), lp - jr CSYM(start_kernel) + + // Start the linux kernel. We use an indirect jump to get extra + // range, because on some platforms this initial startup code + // (and the associated platform-specific code in mach_early_init) + // are located far away from the main kernel, e.g. so that they + // can initialize RAM first and copy the kernel or something. + mov hilo(CSYM(start_kernel)), r12 + jmp [r12] C_END(start) diff -Nru a/arch/v850/kernel/highres_timer.c b/arch/v850/kernel/highres_timer.c --- a/arch/v850/kernel/highres_timer.c Sat Jul 19 12:54:30 2003 +++ b/arch/v850/kernel/highres_timer.c Sat Jul 19 12:54:30 2003 @@ -1,8 +1,8 @@ /* * arch/v850/kernel/highres_timer.c -- High resolution timing routines * - * Copyright (C) 2001,02 NEC Corporation - * Copyright (C) 2001,02 Miles Bader + * Copyright (C) 2001,02,03 NEC Electronics Corporation + * Copyright (C) 2001,02,03 Miles Bader * * 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 @@ -12,7 +12,7 @@ */ #include -#include +#include #include #define HIGHRES_TIMER_USEC_SHIFT 12 @@ -42,7 +42,7 @@ void highres_timer_reset (void) { - NB85E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT) = 0; + V850E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT) = 0; HIGHRES_TIMER_SLOW_TICKS = 0; } @@ -51,12 +51,12 @@ u32 fast_tick_rate; /* Start hardware timer. */ - nb85e_timer_d_configure (HIGHRES_TIMER_TIMER_D_UNIT, + v850e_timer_d_configure (HIGHRES_TIMER_TIMER_D_UNIT, HIGHRES_TIMER_SLOW_TICK_RATE); fast_tick_rate = - (NB85E_TIMER_D_BASE_FREQ - >> NB85E_TIMER_D_DIVLOG2 (HIGHRES_TIMER_TIMER_D_UNIT)); + (V850E_TIMER_D_BASE_FREQ + >> V850E_TIMER_D_DIVLOG2 (HIGHRES_TIMER_TIMER_D_UNIT)); /* The obvious way of calculating microseconds from fast ticks is to do: @@ -77,16 +77,16 @@ /* Enable the interrupt (which is hardwired to this use), and give it the highest priority. */ - NB85E_INTC_IC (IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT)) = 0; + V850E_INTC_IC (IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT)) = 0; } void highres_timer_stop (void) { /* Stop the timer. */ - NB85E_TIMER_D_TMCD (HIGHRES_TIMER_TIMER_D_UNIT) = - NB85E_TIMER_D_TMCD_CAE; + V850E_TIMER_D_TMCD (HIGHRES_TIMER_TIMER_D_UNIT) = + V850E_TIMER_D_TMCD_CAE; /* Disable its interrupt, just in case. */ - nb85e_intc_disable_irq (IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT)); + v850e_intc_disable_irq (IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT)); } inline void highres_timer_read_ticks (u32 *slow_ticks, u32 *fast_ticks) @@ -95,9 +95,9 @@ u32 fast_ticks_1, fast_ticks_2, _slow_ticks; local_irq_save (flags); - fast_ticks_1 = NB85E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT); + fast_ticks_1 = V850E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT); _slow_ticks = HIGHRES_TIMER_SLOW_TICKS; - fast_ticks_2 = NB85E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT); + fast_ticks_2 = V850E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT); local_irq_restore (flags); if (fast_ticks_2 < fast_ticks_1) diff -Nru a/arch/v850/kernel/intv.S b/arch/v850/kernel/intv.S --- a/arch/v850/kernel/intv.S Sat Jul 19 12:54:25 2003 +++ b/arch/v850/kernel/intv.S Sat Jul 19 12:54:25 2003 @@ -16,7 +16,7 @@ #include #include -#ifdef CONFIG_V850E_MA1_HIGHRES_TIMER +#ifdef CONFIG_V850E_HIGHRES_TIMER #include #endif @@ -59,7 +59,7 @@ .section .intv.mach, "ax" .org 0x0 -#if defined (CONFIG_V850E_MA1_HIGHRES_TIMER) && defined (IRQ_INTCMD) +#if defined (CONFIG_V850E_HIGHRES_TIMER) && defined (IRQ_INTCMD) /* Interrupts before the highres timer interrupt. */ .rept IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT) diff -Nru a/arch/v850/kernel/ma.c b/arch/v850/kernel/ma.c --- a/arch/v850/kernel/ma.c Sat Jul 19 12:54:23 2003 +++ b/arch/v850/kernel/ma.c Sat Jul 19 12:54:23 2003 @@ -22,19 +22,19 @@ #include #include #include -#include +#include #include "mach.h" void __init mach_sched_init (struct irqaction *timer_action) { /* Start hardware timer. */ - nb85e_timer_d_configure (0, HZ); + v850e_timer_d_configure (0, HZ); /* Install timer interrupt handler. */ setup_irq (IRQ_INTCMD(0), timer_action); } -static struct nb85e_intc_irq_init irq_inits[] = { +static struct v850e_intc_irq_init irq_inits[] = { { "IRQ", 0, NUM_MACH_IRQS, 1, 7 }, { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 }, { "DMA", IRQ_INTDMA(0), IRQ_INTDMA_NUM, 1, 2 }, @@ -51,7 +51,7 @@ /* Initialize MA chip interrupts. */ void __init ma_init_irqs (void) { - nb85e_intc_init_irq_types (irq_inits, hw_itypes); + v850e_intc_init_irq_types (irq_inits, hw_itypes); } /* Called before configuring an on-chip UART. */ diff -Nru a/arch/v850/kernel/me2.c b/arch/v850/kernel/me2.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/v850/kernel/me2.c Sat Jul 19 12:54:30 2003 @@ -0,0 +1,74 @@ +/* + * arch/v850/kernel/me2.c -- V850E/ME2 chip-specific support + * + * Copyright (C) 2003 NEC Corporation + * Copyright (C) 2003 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "mach.h" + +void __init mach_sched_init (struct irqaction *timer_action) +{ + /* Start hardware timer. */ + v850e_timer_d_configure (0, HZ); + /* Install timer interrupt handler. */ + setup_irq (IRQ_INTCMD(0), timer_action); +} + +static struct v850e_intc_irq_init irq_inits[] = { + { "IRQ", 0, NUM_CPU_IRQS, 1, 7 }, + { "INTP", IRQ_INTP(0), IRQ_INTP_NUM, 1, 5 }, + { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 3 }, + { "UBTIRE", IRQ_INTUBTIRE(0), IRQ_INTUBTIRE_NUM, 5, 4 }, + { "UBTIR", IRQ_INTUBTIR(0), IRQ_INTUBTIR_NUM, 5, 4 }, + { "UBTIT", IRQ_INTUBTIT(0), IRQ_INTUBTIT_NUM, 5, 4 }, + { "UBTIF", IRQ_INTUBTIF(0), IRQ_INTUBTIF_NUM, 5, 4 }, + { "UBTITO", IRQ_INTUBTITO(0), IRQ_INTUBTITO_NUM, 5, 4 }, + { 0 } +}; +#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1) + +static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS]; + +/* Initialize V850E/ME2 chip interrupts. */ +void __init me2_init_irqs (void) +{ + v850e_intc_init_irq_types (irq_inits, hw_itypes); +} + +/* Called before configuring an on-chip UART. */ +void me2_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud) +{ + if (chan == 0) { + /* Specify that the relevent pins on the chip should do + serial I/O, not direct I/O. */ + ME2_PORT1_PMC |= 0xC; + /* Specify that we're using the UART, not the CSI device. */ + ME2_PORT1_PFC |= 0xC; + } else if (chan == 1) { + /* Specify that the relevent pins on the chip should do + serial I/O, not direct I/O. */ + ME2_PORT2_PMC |= 0x6; + /* Specify that we're using the UART, not the CSI device. */ + ME2_PORT2_PFC |= 0x6; + } +} diff -Nru a/arch/v850/kernel/nb85e_cache.c b/arch/v850/kernel/nb85e_cache.c --- a/arch/v850/kernel/nb85e_cache.c Sat Jul 19 12:54:26 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,178 +0,0 @@ -/* - * arch/v850/kernel/nb85e_cache.c -- Cache control for NB85E_CACHE212 and - * NB85E_CACHE213 cache memories - * - * Copyright (C) 2003 NEC Electronics Corporation - * Copyright (C) 2003 Miles Bader - * - * 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. - * - * Written by Miles Bader - */ - -#include -#include - -#define WAIT_UNTIL_CLEAR(value) while (value) {} - -/* Set caching params via the BHC and DCC registers. */ -void nb85e_cache_enable (u16 bhc, u16 dcc) -{ - unsigned long *r0_ram = (unsigned long *)R0_RAM_ADDR; - register u16 bhc_val asm ("r6") = bhc; - - /* Configure data-cache. */ - NB85E_CACHE_DCC = dcc; - - /* Configure caching for various memory regions by writing the BHC - register. The documentation says that an instruction _cannot_ - enable/disable caching for the memory region in which the - instruction itself exists; to work around this, we store - appropriate instructions into the on-chip RAM area (which is never - cached), and briefly jump there to do the work. */ - r0_ram[0] = 0xf0720760; /* st.h r0, 0xfffff072[r0] */ - r0_ram[1] = 0xf06a3760; /* st.h r6, 0xfffff06a[r0] */ - r0_ram[2] = 0x5640006b; /* jmp [r11] */ - asm ("mov hilo(1f), r11; jmp [%1]; 1:;" - :: "r" (bhc_val), "r" (R0_RAM_ADDR) : "r11"); -} - -static void clear_icache (void) -{ - /* 1. Read the instruction cache control register (ICC) and confirm - that bits 0 and 1 (TCLR0, TCLR1) are all cleared. */ - WAIT_UNTIL_CLEAR (NB85E_CACHE_ICC & 0x3); - - /* 2. Read the ICC register and confirm that bit 12 (LOCK0) is - cleared. Bit 13 of the ICC register is always cleared. */ - WAIT_UNTIL_CLEAR (NB85E_CACHE_ICC & 0x1000); - - /* 3. Set the TCLR0 and TCLR1 bits of the ICC register as follows, - when clearing way 0 and way 1 at the same time: - (a) Set the TCLR0 and TCLR1 bits. - (b) Read the TCLR0 and TCLR1 bits to confirm that these bits - are cleared. - (c) Perform (a) and (b) above again. */ - NB85E_CACHE_ICC |= 0x3; - WAIT_UNTIL_CLEAR (NB85E_CACHE_ICC & 0x3); - /* Do it again. */ - NB85E_CACHE_ICC |= 0x3; - WAIT_UNTIL_CLEAR (NB85E_CACHE_ICC & 0x3); -} - -/* Flush or clear (or both) the data cache, depending on the value of FLAGS; - the procedure is the same for both, just the control bits used differ (and - both may be performed simultaneously). */ -static void dcache_op (unsigned short flags) -{ - /* 1. Read the data cache control register (DCC) and confirm that bits - 0, 1, 4, and 5 (DC00, DC01, DC04, DC05) are all cleared. */ - WAIT_UNTIL_CLEAR (NB85E_CACHE_DCC & 0x33); - - /* 2. Clear DCC register bit 12 (DC12), bit 13 (DC13), or both - depending on the way for which tags are to be cleared. */ - NB85E_CACHE_DCC &= ~0xC000; - - /* 3. Set DCC register bit 0 (DC00), bit 1 (DC01) or both depending on - the way for which tags are to be cleared. - ... - Set DCC register bit 4 (DC04), bit 5 (DC05), or both depending - on the way to be data flushed. */ - NB85E_CACHE_DCC |= flags; - - /* 4. Read DCC register bit DC00, DC01 [DC04, DC05], or both depending - on the way for which tags were cleared [flushed] and confirm - that that bit is cleared. */ - WAIT_UNTIL_CLEAR (NB85E_CACHE_DCC & flags); -} - -/* Flushes the contents of the dcache to memory. */ -static inline void flush_dcache (void) -{ - /* We only need to do something if in write-back mode. */ - if (NB85E_CACHE_DCC & 0x0400) - dcache_op (0x30); -} - -/* Flushes the contents of the dcache to memory, and then clears it. */ -static inline void clear_dcache (void) -{ - /* We only need to do something if the dcache is enabled. */ - if (NB85E_CACHE_DCC & 0x0C00) - dcache_op (0x33); -} - -/* Clears the dcache without flushing to memory first. */ -static inline void clear_dcache_no_flush (void) -{ - /* We only need to do something if the dcache is enabled. */ - if (NB85E_CACHE_DCC & 0x0C00) - dcache_op (0x3); -} - -static inline void cache_exec_after_store (void) -{ - flush_dcache (); - clear_icache (); -} - - -/* Exported functions. */ - -void inline nb85e_cache_flush_all (void) -{ - clear_icache (); - clear_dcache (); -} - -void nb85e_cache_flush_mm (struct mm_struct *mm) -{ - /* nothing */ -} - -void nb85e_cache_flush_range (struct mm_struct *mm, - unsigned long start, unsigned long end) -{ - /* nothing */ -} - -void nb85e_cache_flush_page (struct vm_area_struct *vma, - unsigned long page_addr) -{ - /* nothing */ -} - -void nb85e_cache_flush_dcache_page (struct page *page) -{ - /* nothing */ -} - -void nb85e_cache_flush_icache (void) -{ - cache_exec_after_store (); -} - -void nb85e_cache_flush_icache_range (unsigned long start, unsigned long end) -{ - cache_exec_after_store (); -} - -void nb85e_cache_flush_icache_page (struct vm_area_struct *vma, - struct page *page) -{ - cache_exec_after_store (); -} - -void nb85e_cache_flush_icache_user_range (struct vm_area_struct *vma, - struct page *page, - unsigned long adr, int len) -{ - cache_exec_after_store (); -} - -void nb85e_cache_flush_sigtramp (unsigned long addr) -{ - cache_exec_after_store (); -} diff -Nru a/arch/v850/kernel/nb85e_intc.c b/arch/v850/kernel/nb85e_intc.c --- a/arch/v850/kernel/nb85e_intc.c Sat Jul 19 12:54:24 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,104 +0,0 @@ -/* - * arch/v850/kernel/nb85e_intc.c -- NB85E cpu core interrupt controller (INTC) - * - * Copyright (C) 2001,02,03 NEC Electronics Corporation - * Copyright (C) 2001,02,03 Miles Bader - * - * 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. - * - * Written by Miles Bader - */ - -#include -#include -#include - -#include - -static void irq_nop (unsigned irq) { } - -static unsigned nb85e_intc_irq_startup (unsigned irq) -{ - nb85e_intc_clear_pending_irq (irq); - nb85e_intc_enable_irq (irq); - return 0; -} - -static void nb85e_intc_end_irq (unsigned irq) -{ - unsigned long psw, temp; - - /* Clear the highest-level bit in the In-service priority register - (ISPR), to allow this interrupt (or another of the same or - lesser priority) to happen again. - - The `reti' instruction normally does this automatically when the - PSW bits EP and NP are zero, but we can't always rely on reti - being used consistently to return after an interrupt (another - process can be scheduled, for instance, which can delay the - associated reti for a long time, or this process may be being - single-stepped, which uses the `dbret' instruction to return - from the kernel). - - We also set the PSW EP bit, which prevents reti from also - trying to modify the ISPR itself. */ - - /* Get PSW and disable interrupts. */ - asm volatile ("stsr psw, %0; di" : "=r" (psw)); - /* We don't want to do anything for NMIs (they don't use the ISPR). */ - if (! (psw & 0xC0)) { - /* Transition to `trap' state, so that an eventual real - reti instruction won't modify the ISPR. */ - psw |= 0x40; - /* Fake an interrupt return, which automatically clears the - appropriate bit in the ISPR. */ - asm volatile ("mov hilo(1f), %0;" - "ldsr %0, eipc; ldsr %1, eipsw;" - "reti;" - "1:" - : "=&r" (temp) : "r" (psw)); - } -} - -/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array - INITS (which is terminated by an entry with the name field == 0). */ -void __init nb85e_intc_init_irq_types (struct nb85e_intc_irq_init *inits, - struct hw_interrupt_type *hw_irq_types) -{ - struct nb85e_intc_irq_init *init; - for (init = inits; init->name; init++) { - unsigned i; - struct hw_interrupt_type *hwit = hw_irq_types++; - - hwit->typename = init->name; - - hwit->startup = nb85e_intc_irq_startup; - hwit->shutdown = nb85e_intc_disable_irq; - hwit->enable = nb85e_intc_enable_irq; - hwit->disable = nb85e_intc_disable_irq; - hwit->ack = irq_nop; - hwit->end = nb85e_intc_end_irq; - - /* Initialize kernel IRQ infrastructure for this interrupt. */ - init_irq_handlers(init->base, init->num, init->interval, hwit); - - /* Set the interrupt priorities. */ - for (i = 0; i < init->num; i++) { - unsigned irq = init->base + i * init->interval; - - /* If the interrupt is currently enabled (all - interrupts are initially disabled), then - assume whoever enabled it has set things up - properly, and avoid messing with it. */ - if (! nb85e_intc_irq_enabled (irq)) - /* This write also (1) disables the - interrupt, and (2) clears any pending - interrupts. */ - NB85E_INTC_IC (irq) - = (NB85E_INTC_IC_PR (init->priority) - | NB85E_INTC_IC_MK); - } - } -} diff -Nru a/arch/v850/kernel/nb85e_timer_d.c b/arch/v850/kernel/nb85e_timer_d.c --- a/arch/v850/kernel/nb85e_timer_d.c Sat Jul 19 12:54:25 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,54 +0,0 @@ -/* - * include/asm-v850/nb85e_timer_d.c -- `Timer D' component often used - * with the NB85E cpu core - * - * Copyright (C) 2001,02 NEC Corporation - * Copyright (C) 2001,02 Miles Bader - * - * 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. - * - * Written by Miles Bader - */ - -#include - -#include -#include - -/* Start interval timer TIMER (0-3). The timer will issue the - corresponding INTCMD interrupt RATE times per second. - This function does not enable the interrupt. */ -void nb85e_timer_d_configure (unsigned timer, unsigned rate) -{ - unsigned divlog2, count; - - /* Calculate params for timer. */ - if (! calc_counter_params ( - NB85E_TIMER_D_BASE_FREQ, rate, - NB85E_TIMER_D_TMCD_CS_MIN, NB85E_TIMER_D_TMCD_CS_MAX, 16, - &divlog2, &count)) - printk (KERN_WARNING - "Cannot find interval timer %d setting suitable" - " for rate of %dHz.\n" - "Using rate of %dHz instead.\n", - timer, rate, - (NB85E_TIMER_D_BASE_FREQ >> divlog2) >> 16); - - /* Do the actual hardware timer initialization: */ - - /* Enable timer. */ - NB85E_TIMER_D_TMCD(timer) = NB85E_TIMER_D_TMCD_CAE; - /* Set clock divider. */ - NB85E_TIMER_D_TMCD(timer) - = NB85E_TIMER_D_TMCD_CAE - | NB85E_TIMER_D_TMCD_CS(divlog2); - /* Set timer compare register. */ - NB85E_TIMER_D_CMD(timer) = count; - /* Start counting. */ - NB85E_TIMER_D_TMCD(timer) - = NB85E_TIMER_D_TMCD_CAE - | NB85E_TIMER_D_TMCD_CS(divlog2) - | NB85E_TIMER_D_TMCD_CE; -} diff -Nru a/arch/v850/kernel/nb85e_utils.c b/arch/v850/kernel/nb85e_utils.c --- a/arch/v850/kernel/nb85e_utils.c Sat Jul 19 12:54:23 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,65 +0,0 @@ -/* - * include/asm-v850/nb85e_utils.h -- Utility functions associated with - * the NB85E cpu core - * - * Copyright (C) 2001,02 NEC Corporation - * Copyright (C) 2001,02 Miles Bader - * - * 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. - * - * Written by Miles Bader - */ - -/* Note: these functions are often associated with the N85E cpu core, - but not always, which is why they're not in `nb85e.c'. */ - -#include - -/* Calculate counter clock-divider and count values to attain the - desired frequency RATE from the base frequency BASE_FREQ. The - counter is expected to have a clock-divider, which can divide the - system cpu clock by a power of two value from MIN_DIVLOG2 to - MAX_DIV_LOG2, and a word-size of COUNTER_SIZE bits (the counter - counts up and resets whenever it's equal to the compare register, - generating an interrupt or whatever when it does so). The returned - values are: *DIVLOG2 -- log2 of the desired clock divider and *COUNT - -- the counter compare value to use. Returns true if it was possible - to find a reasonable value, otherwise false (and the other return - values will be set to be as good as possible). */ -int calc_counter_params (unsigned long base_freq, - unsigned long rate, - unsigned min_divlog2, unsigned max_divlog2, - unsigned counter_size, - unsigned *divlog2, unsigned *count) -{ - unsigned _divlog2; - int ok = 0; - - /* Find the lowest clock divider setting that can represent RATE. */ - for (_divlog2 = min_divlog2; _divlog2 <= max_divlog2; _divlog2++) { - /* Minimum interrupt rate possible using this divider. */ - unsigned min_int_rate - = (base_freq >> _divlog2) >> counter_size; - - if (min_int_rate <= rate) { - /* This setting is the highest resolution - setting that's slow enough enough to attain - RATE interrupts per second, so use it. */ - ok = 1; - break; - } - } - - if (_divlog2 > max_divlog2) - /* Can't find correct setting. */ - _divlog2 = max_divlog2; - - if (divlog2) - *divlog2 = _divlog2; - if (count) - *count = ((base_freq >> _divlog2) + rate/2) / rate; - - return ok; -} diff -Nru a/arch/v850/kernel/rte_cb.c b/arch/v850/kernel/rte_cb.c --- a/arch/v850/kernel/rte_cb.c Sat Jul 19 12:54:22 2003 +++ b/arch/v850/kernel/rte_cb.c Sat Jul 19 12:54:22 2003 @@ -17,7 +17,7 @@ #include #include -#include +#include #include "mach.h" @@ -34,7 +34,7 @@ void __init rte_cb_early_init (void) { - nb85e_intc_disable_irqs (); + v850e_intc_disable_irqs (); #ifdef CONFIG_RTE_CB_MULTI multi_init (); @@ -43,6 +43,7 @@ void __init mach_setup (char **cmdline) { +#ifdef CONFIG_RTE_MB_A_PCI /* Probe for Mother-A, and print a message if we find it. */ *(volatile unsigned long *)MB_A_SRAM_ADDR = 0xDEADBEEF; if (*(volatile unsigned long *)MB_A_SRAM_ADDR == 0xDEADBEEF) { @@ -52,23 +53,11 @@ " NEC SolutionGear/Midas lab" " RTE-MOTHER-A motherboard\n"); } - -#if defined (CONFIG_V850E_NB85E_UART_CONSOLE) && !defined (CONFIG_TIME_BOOTUP) - nb85e_uart_cons_init (0); -#endif +#endif /* CONFIG_RTE_MB_A_PCI */ mach_tick = led_tick; } -#ifdef CONFIG_TIME_BOOTUP -void initial_boot_done (void) -{ -#ifdef CONFIG_V850E_NB85E_UART_CONSOLE - nb85e_uart_cons_init (0); -#endif -} -#endif - void machine_restart (char *__unused) { #ifdef CONFIG_RESET_GUARD @@ -193,6 +182,7 @@ static struct hw_interrupt_type gbus_hw_itypes[NUM_GBUS_IRQ_INITS]; #endif /* CONFIG_RTE_GBUS_INT */ + void __init rte_cb_init_irqs (void) { diff -Nru a/arch/v850/kernel/rte_ma1_cb.c b/arch/v850/kernel/rte_ma1_cb.c --- a/arch/v850/kernel/rte_ma1_cb.c Sat Jul 19 12:54:27 2003 +++ b/arch/v850/kernel/rte_ma1_cb.c Sat Jul 19 12:54:27 2003 @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include "mach.h" @@ -89,14 +89,14 @@ rte_cb_init_irqs (); /* Use falling-edge-sensitivity for interrupts . */ - NB85E_TIMER_C_SESC (0) &= ~0xC; - NB85E_TIMER_C_SESC (1) &= ~0xF; + V850E_TIMER_C_SESC (0) &= ~0xC; + V850E_TIMER_C_SESC (1) &= ~0xF; /* INTP000-INTP011 are shared with `Timer C', so we have to set up Timer C to pass them through as raw interrupts. */ for (tc = 0; tc < 2; tc++) /* Turn on the timer. */ - NB85E_TIMER_C_TMCC0 (tc) |= NB85E_TIMER_C_TMCC0_CAE; + V850E_TIMER_C_TMCC0 (tc) |= V850E_TIMER_C_TMCC0_CAE; /* Make sure the relevant port0/port1 pins are assigned interrupt duty. We used INTP001-INTP011 (don't screw with diff -Nru a/arch/v850/kernel/rte_me2_cb.c b/arch/v850/kernel/rte_me2_cb.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/v850/kernel/rte_me2_cb.c Sat Jul 19 12:54:30 2003 @@ -0,0 +1,308 @@ +/* + * arch/v850/kernel/rte_me2_cb.c -- Midas labs RTE-V850E/ME2-CB board + * + * Copyright (C) 2001,02,03 NEC Electronics Corporation + * Copyright (C) 2001,02,03 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mach.h" + +extern unsigned long *_intv_start; +extern unsigned long *_intv_end; + +/* LED access routines. */ +extern unsigned read_leds (int pos, char *buf, int len); +extern unsigned write_leds (int pos, const char *buf, int len); + + +/* SDRAM are almost contiguous (with a small hole in between; + see mach_reserve_bootmem for details), so just use both as one big area. */ +#define RAM_START SDRAM_ADDR +#define RAM_END (SDRAM_ADDR + SDRAM_SIZE) + + +void __init mach_get_physical_ram (unsigned long *ram_start, + unsigned long *ram_len) +{ + *ram_start = RAM_START; + *ram_len = RAM_END - RAM_START; +} + +void __init mach_reserve_bootmem () +{ + extern char _root_fs_image_start, _root_fs_image_end; + u32 root_fs_image_start = (u32)&_root_fs_image_start; + u32 root_fs_image_end = (u32)&_root_fs_image_end; + + /* Reserve the memory used by the root filesystem image if it's + in RAM. */ + if (root_fs_image_start >= RAM_START && root_fs_image_start < RAM_END) + reserve_bootmem (root_fs_image_start, + root_fs_image_end - root_fs_image_start); +} + +void mach_gettimeofday (struct timespec *tv) +{ + tv->tv_sec = 0; + tv->tv_nsec = 0; +} + +/* Called before configuring an on-chip UART. */ +void rte_me2_cb_uart_pre_configure (unsigned chan, + unsigned cflags, unsigned baud) +{ + /* The RTE-V850E/ME2-CB connects some general-purpose I/O + pins on the CPU to the RTS/CTS lines of UARTB channel 0's + serial connection. + I/O pins P21 and P22 are RTS and CTS respectively. */ + if (chan == 0) { + /* Put P21 & P22 in I/O port mode. */ + ME2_PORT2_PMC &= ~0x6; + /* Make P21 and output, and P22 an input. */ + ME2_PORT2_PM = (ME2_PORT2_PM & ~0xC) | 0x4; + } + + me2_uart_pre_configure (chan, cflags, baud); +} + +void __init mach_init_irqs (void) +{ + /* Initialize interrupts. */ + me2_init_irqs (); + rte_me2_cb_init_irqs (); +} + +#ifdef CONFIG_ROM_KERNEL +/* Initialization for kernel in ROM. */ +static inline rom_kernel_init (void) +{ + /* If the kernel is in ROM, we have to copy any initialized data + from ROM into RAM. */ + extern unsigned long _data_load_start, _sdata, _edata; + register unsigned long *src = &_data_load_start; + register unsigned long *dst = &_sdata, *end = &_edata; + + while (dst != end) + *dst++ = *src++; +} +#endif /* CONFIG_ROM_KERNEL */ + +static void install_interrupt_vectors (void) +{ + unsigned long *p1, *p2; + + ME2_IRAMM = 0x03; /* V850E/ME2 iRAM write mode */ + + /* vector copy to iRAM */ + p1 = (unsigned long *)0; /* v85x vector start */ + p2 = (unsigned long *)&_intv_start; + while (p2 < (unsigned long *)&_intv_end) + *p1++ = *p2++; + + ME2_IRAMM = 0x00; /* V850E/ME2 iRAM read mode */ +} + +/* CompactFlash */ + +static void cf_power_on (void) +{ + /* CF card detected? */ + if (CB_CF_STS0 & 0x0030) + return; + + CB_CF_REG0 = 0x0002; /* reest on */ + mdelay (10); + CB_CF_REG0 = 0x0003; /* power on */ + mdelay (10); + CB_CF_REG0 = 0x0001; /* reset off */ + mdelay (10); +} + +static void cf_power_off (void) +{ + CB_CF_REG0 = 0x0003; /* power on */ + mdelay (10); + CB_CF_REG0 = 0x0002; /* reest on */ + mdelay (10); +} + +void __init mach_early_init (void) +{ + install_interrupt_vectors (); + + /* CS1 SDRAM instruction cache enable */ + v850e_cache_enable (0x04, 0x03, 0); + + rte_cb_early_init (); + + /* CompactFlash power on */ + cf_power_on (); + +#if defined (CONFIG_ROM_KERNEL) + rom_kernel_init (); +#endif +} + + +/* RTE-V850E/ME2-CB Programmable Interrupt Controller. */ + +static struct cb_pic_irq_init cb_pic_irq_inits[] = { + { "CB_EXTTM0", IRQ_CB_EXTTM0, 1, 1, 6 }, + { "CB_EXTSIO", IRQ_CB_EXTSIO, 1, 1, 6 }, + { "CB_TOVER", IRQ_CB_TOVER, 1, 1, 6 }, + { "CB_GINT0", IRQ_CB_GINT0, 1, 1, 6 }, + { "CB_USB", IRQ_CB_USB, 1, 1, 6 }, + { "CB_LANC", IRQ_CB_LANC, 1, 1, 6 }, + { "CB_USB_VBUS_ON", IRQ_CB_USB_VBUS_ON, 1, 1, 6 }, + { "CB_USB_VBUS_OFF", IRQ_CB_USB_VBUS_OFF, 1, 1, 6 }, + { "CB_EXTTM1", IRQ_CB_EXTTM1, 1, 1, 6 }, + { "CB_EXTTM2", IRQ_CB_EXTTM2, 1, 1, 6 }, + { 0 } +}; +#define NUM_CB_PIC_IRQ_INITS \ + ((sizeof cb_pic_irq_inits / sizeof cb_pic_irq_inits[0]) - 1) + +static struct hw_interrupt_type cb_pic_hw_itypes[NUM_CB_PIC_IRQ_INITS]; +static unsigned char cb_pic_active_irqs = 0; + +void __init rte_me2_cb_init_irqs (void) +{ + cb_pic_init_irq_types (cb_pic_irq_inits, cb_pic_hw_itypes); + + /* Initalize on board PIC1 (not PIC0) enable */ + CB_PIC_INT0M = 0x0000; + CB_PIC_INT1M = 0x0000; + CB_PIC_INTR = 0x0000; + CB_PIC_INTEN |= CB_PIC_INT1EN; + + ME2_PORT2_PMC |= 0x08; /* INTP23/SCK1 mode */ + ME2_PORT2_PFC &= ~0x08; /* INTP23 mode */ + ME2_INTR(2) &= ~0x08; /* INTP23 falling-edge detect */ + ME2_INTF(2) &= ~0x08; /* " */ + + rte_cb_init_irqs (); /* gbus &c */ +} + + +/* Enable interrupt handling for interrupt IRQ. */ +void cb_pic_enable_irq (unsigned irq) +{ + CB_PIC_INT1M |= 1 << (irq - CB_PIC_BASE_IRQ); +} + +void cb_pic_disable_irq (unsigned irq) +{ + CB_PIC_INT1M &= ~(1 << (irq - CB_PIC_BASE_IRQ)); +} + +void cb_pic_shutdown_irq (unsigned irq) +{ + cb_pic_disable_irq (irq); + + if (--cb_pic_active_irqs == 0) + free_irq (IRQ_CB_PIC, 0); + + CB_PIC_INT1M &= ~(1 << (irq - CB_PIC_BASE_IRQ)); +} + +static void cb_pic_handle_irq (int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned status = CB_PIC_INTR; + unsigned enable = CB_PIC_INT1M; + + /* Only pay attention to enabled interrupts. */ + status &= enable; + + CB_PIC_INTEN &= ~CB_PIC_INT1EN; + + if (status) { + unsigned mask = 1; + + irq = CB_PIC_BASE_IRQ; + do { + /* There's an active interrupt, find out which one, + and call its handler. */ + while (! (status & mask)) { + irq++; + mask <<= 1; + } + status &= ~mask; + + CB_PIC_INTR = mask; + + /* Recursively call handle_irq to handle it. */ + handle_irq (irq, regs); + } while (status); + } + + CB_PIC_INTEN |= CB_PIC_INT1EN; +} + + +static void irq_nop (unsigned irq) { } + +static unsigned cb_pic_startup_irq (unsigned irq) +{ + int rval; + + if (cb_pic_active_irqs == 0) { + rval = request_irq (IRQ_CB_PIC, cb_pic_handle_irq, + SA_INTERRUPT, "cb_pic_handler", 0); + if (rval != 0) + return rval; + } + + cb_pic_active_irqs++; + + cb_pic_enable_irq (irq); + + return 0; +} + +/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array + INITS (which is terminated by an entry with the name field == 0). */ +void __init cb_pic_init_irq_types (struct cb_pic_irq_init *inits, + struct hw_interrupt_type *hw_irq_types) +{ + struct cb_pic_irq_init *init; + for (init = inits; init->name; init++) { + struct hw_interrupt_type *hwit = hw_irq_types++; + + hwit->typename = init->name; + + hwit->startup = cb_pic_startup_irq; + hwit->shutdown = cb_pic_shutdown_irq; + hwit->enable = cb_pic_enable_irq; + hwit->disable = cb_pic_disable_irq; + hwit->ack = irq_nop; + hwit->end = irq_nop; + + /* Initialize kernel IRQ infrastructure for this interrupt. */ + init_irq_handlers(init->base, init->num, init->interval, hwit); + } +} diff -Nru a/arch/v850/kernel/rte_nb85e_cb.c b/arch/v850/kernel/rte_nb85e_cb.c --- a/arch/v850/kernel/rte_nb85e_cb.c Sat Jul 19 12:54:29 2003 +++ b/arch/v850/kernel/rte_nb85e_cb.c Sat Jul 19 12:54:29 2003 @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include "mach.h" @@ -41,7 +41,7 @@ Unfortunately, the dcache seems to be buggy, so we only use the icache for now. */ - nb85e_cache_enable (0x0040 /* BHC */, 0x0000 /* DCC */); + v850e_cache_enable (0x0040 /*BHC*/, 0x0003 /*ICC*/, 0x0000 /*DCC*/); rte_cb_early_init (); } diff -Nru a/arch/v850/kernel/sim85e2.c b/arch/v850/kernel/sim85e2.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/v850/kernel/sim85e2.c Sat Jul 19 12:54:25 2003 @@ -0,0 +1,211 @@ +/* + * arch/v850/kernel/sim85e2.c -- Machine-specific stuff for + * V850E2 RTL simulator + * + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "mach.h" + + +/* There are 4 possible areas we can use: + + IRAM (1MB) is fast for instruction fetches, but slow for data + DRAM (1020KB) is fast for data, but slow for instructions + ERAM is cached, so should be fast for both insns and data + SDRAM is external DRAM, similar to ERAM +*/ + +#define INIT_MEMC_FOR_SDRAM +#define USE_SDRAM_AREA +#define KERNEL_IN_SDRAM_AREA + +#define DCACHE_MODE V850E2_CACHE_BTSC_DCM_WT +/*#define DCACHE_MODE V850E2_CACHE_BTSC_DCM_WB_ALLOC*/ + +#ifdef USE_SDRAM_AREA +#define RAM_START SDRAM_ADDR +#define RAM_END (SDRAM_ADDR + SDRAM_SIZE) +#else +/* When we use DRAM, we need to account for the fact that the end of it is + used for R0_RAM. */ +#define RAM_START DRAM_ADDR +#define RAM_END R0_RAM_ADDR +#endif + + +extern void memcons_setup (void); + + +#ifdef KERNEL_IN_SDRAM_AREA +#define EARLY_INIT_SECTION_ATTR __attribute__ ((section (".early.text"))) +#else +#define EARLY_INIT_SECTION_ATTR __init +#endif + +void EARLY_INIT_SECTION_ATTR mach_early_init (void) +{ + extern int panic_timeout; + + /* The sim85e2 simulator tracks `undefined' values, so to make + debugging easier, we begin by zeroing out all otherwise + undefined registers. This is not strictly necessary. + + The registers we zero are: + Every GPR except: + stack-pointer (r3) + task-pointer (r16) + our return addr (r31) + Every system register (SPR) that we know about except for + the PSW (SPR 5), which we zero except for the + disable-interrupts bit. + */ + + /* GPRs */ + asm volatile (" mov r0, r1 ; mov r0, r2 "); + asm volatile ("mov r0, r4 ; mov r0, r5 ; mov r0, r6 ; mov r0, r7 "); + asm volatile ("mov r0, r8 ; mov r0, r9 ; mov r0, r10; mov r0, r11"); + asm volatile ("mov r0, r12; mov r0, r13; mov r0, r14; mov r0, r15"); + asm volatile (" mov r0, r17; mov r0, r18; mov r0, r19"); + asm volatile ("mov r0, r20; mov r0, r21; mov r0, r22; mov r0, r23"); + asm volatile ("mov r0, r24; mov r0, r25; mov r0, r26; mov r0, r27"); + asm volatile ("mov r0, r28; mov r0, r29; mov r0, r30"); + + /* SPRs */ + asm volatile ("ldsr r0, 0; ldsr r0, 1; ldsr r0, 2; ldsr r0, 3"); + asm volatile ("ldsr r0, 4"); + asm volatile ("addi 0x20, r0, r1; ldsr r1, 5"); /* PSW */ + asm volatile ("ldsr r0, 16; ldsr r0, 17; ldsr r0, 18; ldsr r0, 19"); + asm volatile ("ldsr r0, 20"); + + +#ifdef INIT_MEMC_FOR_SDRAM + /* Settings for SDRAM controller. */ + V850E2_VSWC = 0x0042; + V850E2_BSC = 0x9286; + V850E2_BCT(0) = 0xb000; /* was: 0 */ + V850E2_BCT(1) = 0x000b; + V850E2_ASC = 0; + V850E2_LBS = 0xa9aa; /* was: 0xaaaa */ + V850E2_LBC(0) = 0; + V850E2_LBC(1) = 0; /* was: 0x3 */ + V850E2_BCC = 0; + V850E2_RFS(4) = 0x800a; /* was: 0xf109 */ + V850E2_SCR(4) = 0x2091; /* was: 0x20a1 */ + V850E2_RFS(3) = 0x800c; + V850E2_SCR(3) = 0x20a1; + V850E2_DWC(0) = 0; + V850E2_DWC(1) = 0; +#endif + +#if 0 +#ifdef CONFIG_V850E2_SIM85E2S + /* Turn on the caches. */ + V850E2_CACHE_BTSC = V850E2_CACHE_BTSC_ICM | DCACHE_MODE; + V850E2_BHC = 0x1010; +#elif CONFIG_V850E2_SIM85E2C + V850E2_CACHE_BTSC |= (V850E2_CACHE_BTSC_ICM | V850E2_CACHE_BTSC_DCM0); + V850E2_BUSM_BHC = 0xFFFF; +#endif +#else + V850E2_BHC = 0; +#endif + + /* Don't stop the simulator at `halt' instructions. */ + SIM85E2_NOTHAL = 1; + + /* Ensure that the simulator halts on a panic, instead of going + into an infinite loop inside the panic function. */ + panic_timeout = -1; +} + +void __init mach_setup (char **cmdline) +{ + memcons_setup (); +} + +void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len) +{ + *ram_start = RAM_START; + *ram_len = RAM_END - RAM_START; +} + +void __init mach_reserve_bootmem () +{ + extern char _root_fs_image_start, _root_fs_image_end; + u32 root_fs_image_start = (u32)&_root_fs_image_start; + u32 root_fs_image_end = (u32)&_root_fs_image_end; + + /* Reserve the memory used by the root filesystem image if it's + in RAM. */ + if (root_fs_image_end > root_fs_image_start + && root_fs_image_start >= RAM_START + && root_fs_image_start < RAM_END) + reserve_bootmem (root_fs_image_start, + root_fs_image_end - root_fs_image_start); +} + +void __init mach_sched_init (struct irqaction *timer_action) +{ + /* The simulator actually cycles through all interrupts + periodically. We just pay attention to IRQ0, which gives us + 1/64 the rate of the periodic interrupts. */ + setup_irq (0, timer_action); +} + +void mach_gettimeofday (struct timespec *tv) +{ + tv->tv_sec = 0; + tv->tv_nsec = 0; +} + +/* Interrupts */ + +struct v850e_intc_irq_init irq_inits[] = { + { "IRQ", 0, NUM_MACH_IRQS, 1, 7 }, + { 0 } +}; +struct hw_interrupt_type hw_itypes[1]; + +/* Initialize interrupts. */ +void __init mach_init_irqs (void) +{ + v850e_intc_init_irq_types (irq_inits, hw_itypes); +} + + +void machine_halt (void) __attribute__ ((noreturn)); +void machine_halt (void) +{ + SIM85E2_SIMFIN = 0; /* Halt immediately. */ + for (;;) {} +} + +void machine_restart (char *__unused) +{ + machine_halt (); +} + +void machine_power_off (void) +{ + machine_halt (); +} diff -Nru a/arch/v850/kernel/sim85e2c.c b/arch/v850/kernel/sim85e2c.c --- a/arch/v850/kernel/sim85e2c.c Sat Jul 19 12:54:25 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,145 +0,0 @@ -/* - * arch/v850/kernel/sim85e2c.c -- Machine-specific stuff for - * V850E2 RTL simulator - * - * Copyright (C) 2002 NEC Corporation - * Copyright (C) 2002 Miles Bader - * - * 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. - * - * Written by Miles Bader - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "mach.h" - -extern void memcons_setup (void); - - -void __init mach_early_init (void) -{ - extern int panic_timeout; - - /* Don't stop the simulator at `halt' instructions. */ - NOTHAL = 1; - - /* The sim85e2c simulator tracks `undefined' values, so to make - debugging easier, we begin by zeroing out all otherwise - undefined registers. This is not strictly necessary. - - The registers we zero are: - Every GPR except: - stack-pointer (r3) - task-pointer (r16) - our return addr (r31) - Every system register (SPR) that we know about except for - the PSW (SPR 5), which we zero except for the - disable-interrupts bit. - */ - - /* GPRs */ - asm volatile (" mov r0, r1 ; mov r0, r2 "); - asm volatile ("mov r0, r4 ; mov r0, r5 ; mov r0, r6 ; mov r0, r7 "); - asm volatile ("mov r0, r8 ; mov r0, r9 ; mov r0, r10; mov r0, r11"); - asm volatile ("mov r0, r12; mov r0, r13; mov r0, r14; mov r0, r15"); - asm volatile (" mov r0, r17; mov r0, r18; mov r0, r19"); - asm volatile ("mov r0, r20; mov r0, r21; mov r0, r22; mov r0, r23"); - asm volatile ("mov r0, r24; mov r0, r25; mov r0, r26; mov r0, r27"); - asm volatile ("mov r0, r28; mov r0, r29; mov r0, r30"); - - /* SPRs */ - asm volatile ("ldsr r0, 0; ldsr r0, 1; ldsr r0, 2; ldsr r0, 3"); - asm volatile ("ldsr r0, 4"); - asm volatile ("addi 0x20, r0, r1; ldsr r1, 5"); /* PSW */ - asm volatile ("ldsr r0, 16; ldsr r0, 17; ldsr r0, 18; ldsr r0, 19"); - asm volatile ("ldsr r0, 20"); - - /* Turn on the caches. */ - NA85E2C_CACHE_BTSC - |= (NA85E2C_CACHE_BTSC_ICM | NA85E2C_CACHE_BTSC_DCM0); - NA85E2C_BUSM_BHC = 0xFFFF; - - /* Ensure that the simulator halts on a panic, instead of going - into an infinite loop inside the panic function. */ - panic_timeout = -1; -} - -void __init mach_setup (char **cmdline) -{ - memcons_setup (); -} - -void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len) -{ - /* There are 3 possible areas we can use: - IRAM (1MB) is fast for instruction fetches, but slow for data - DRAM (1020KB) is fast for data, but slow for instructions - ERAM is cached, so should be fast for both insns and data, - _but_ currently only supports write-through caching, so - writes are slow. - Since there's really no area that's good for general kernel - use, we use DRAM -- it won't be good for user programs - (which will be loaded into kernel allocated memory), but - currently we're more concerned with testing the kernel. */ - *ram_start = DRAM_ADDR; - *ram_len = R0_RAM_ADDR - DRAM_ADDR; -} - -void __init mach_sched_init (struct irqaction *timer_action) -{ - /* The simulator actually cycles through all interrupts - periodically. We just pay attention to IRQ0, which gives us - 1/64 the rate of the periodic interrupts. */ - setup_irq (0, timer_action); -} - -void mach_gettimeofday (struct timespec *tv) -{ - tv->tv_sec = 0; - tv->tv_nsec = 0; -} - -/* Interrupts */ - -struct nb85e_intc_irq_init irq_inits[] = { - { "IRQ", 0, NUM_MACH_IRQS, 1, 7 }, - { 0 } -}; -struct hw_interrupt_type hw_itypes[1]; - -/* Initialize interrupts. */ -void __init mach_init_irqs (void) -{ - nb85e_intc_init_irq_types (irq_inits, hw_itypes); -} - - -void machine_halt (void) __attribute__ ((noreturn)); -void machine_halt (void) -{ - SIMFIN = 0; /* Halt immediately. */ - for (;;) {} -} - -void machine_restart (char *__unused) -{ - machine_halt (); -} - -void machine_power_off (void) -{ - machine_halt (); -} diff -Nru a/arch/v850/kernel/teg.c b/arch/v850/kernel/teg.c --- a/arch/v850/kernel/teg.c Sat Jul 19 12:54:26 2003 +++ b/arch/v850/kernel/teg.c Sat Jul 19 12:54:26 2003 @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include "mach.h" @@ -31,12 +31,12 @@ /* Select timer interrupt instead of external pin. */ TEG_ISS |= 0x1; /* Start hardware timer. */ - nb85e_timer_d_configure (0, HZ); + v850e_timer_d_configure (0, HZ); /* Install timer interrupt handler. */ setup_irq (IRQ_INTCMD(0), timer_action); } -static struct nb85e_intc_irq_init irq_inits[] = { +static struct v850e_intc_irq_init irq_inits[] = { { "IRQ", 0, NUM_CPU_IRQS, 1, 7 }, { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 }, { "SER", IRQ_INTSER(0), IRQ_INTSER_NUM, 1, 3 }, @@ -51,7 +51,7 @@ /* Initialize MA chip interrupts. */ void __init teg_init_irqs (void) { - nb85e_intc_init_irq_types (irq_inits, hw_itypes); + v850e_intc_init_irq_types (irq_inits, hw_itypes); } /* Called before configuring an on-chip UART. */ diff -Nru a/arch/v850/kernel/v850e2_cache.c b/arch/v850/kernel/v850e2_cache.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/v850/kernel/v850e2_cache.c Sat Jul 19 12:54:30 2003 @@ -0,0 +1,127 @@ +/* + * arch/v850/kernel/v850e2_cache.c -- Cache control for V850E2 cache + * memories + * + * Copyright (C) 2003 NEC Electronics Corporation + * Copyright (C) 2003 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include + +#include + +/* Cache operations we can do. The encoding corresponds directly to the + value we need to write into the COPR register. */ +enum cache_op { + OP_SYNC_IF_DIRTY = V850E2_CACHE_COPR_CFC(0), /* 000 */ + OP_SYNC_IF_VALID = V850E2_CACHE_COPR_CFC(1), /* 001 */ + OP_SYNC_IF_VALID_AND_CLEAR = V850E2_CACHE_COPR_CFC(3), /* 011 */ + OP_WAY_CLEAR = V850E2_CACHE_COPR_CFC(4), /* 100 */ + OP_FILL = V850E2_CACHE_COPR_CFC(5), /* 101 */ + OP_CLEAR = V850E2_CACHE_COPR_CFC(6), /* 110 */ + OP_CREATE_DIRTY = V850E2_CACHE_COPR_CFC(7) /* 111 */ +}; + +/* Which cache to use. This encoding also corresponds directly to the + value we need to write into the COPR register. */ +enum cache { + ICACHE = 0, + DCACHE = V850E2_CACHE_COPR_LBSL +}; + +/* Returns ADDR rounded down to the beginning of its cache-line. */ +#define CACHE_LINE_ADDR(addr) \ + ((addr) & ~(V850E2_CACHE_LINE_SIZE - 1)) +/* Returns END_ADDR rounded up to the `limit' of its cache-line. */ +#define CACHE_LINE_END_ADDR(end_addr) \ + CACHE_LINE_ADDR(end_addr + (V850E2_CACHE_LINE_SIZE - 1)) + + +/* Low-level cache ops. */ + +/* Apply cache-op OP to all entries in CACHE. */ +static inline void cache_op_all (enum cache_op op, enum cache cache) +{ + int cmd = op | cache | V850E2_CACHE_COPR_WSLE | V850E2_CACHE_COPR_STRT; + + if (op != OP_WAY_CLEAR) { + /* The WAY_CLEAR operation does the whole way, but other + ops take begin-index and count params; we just indicate + the entire cache. */ + V850E2_CACHE_CADL = 0; + V850E2_CACHE_CADH = 0; + V850E2_CACHE_CCNT = V850E2_CACHE_WAY_SIZE - 1; + } + + V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(0); /* way 0 */ + V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(1); /* way 1 */ + V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(2); /* way 2 */ + V850E2_CACHE_COPR = cmd | V850E2_CACHE_COPR_WSL(3); /* way 3 */ +} + +/* Apply cache-op OP to all entries in CACHE covering addresses ADDR + through ADDR+LEN. */ +static inline void cache_op_range (enum cache_op op, u32 addr, u32 len, + enum cache cache) +{ + u32 start = CACHE_LINE_ADDR (addr); + u32 end = CACHE_LINE_END_ADDR (addr + len); + u32 num_lines = (end - start) >> V850E2_CACHE_LINE_SIZE_BITS; + + V850E2_CACHE_CADL = start & 0xFFFF; + V850E2_CACHE_CADH = start >> 16; + V850E2_CACHE_CCNT = num_lines - 1; + + V850E2_CACHE_COPR = op | cache | V850E2_CACHE_COPR_STRT; +} + + +/* High-level ops. */ + +static void cache_exec_after_store_all (void) +{ + cache_op_all (OP_SYNC_IF_DIRTY, DCACHE); + cache_op_all (OP_WAY_CLEAR, ICACHE); +} + +static void cache_exec_after_store_range (u32 start, u32 len) +{ + cache_op_range (OP_SYNC_IF_DIRTY, start, len, DCACHE); + cache_op_range (OP_CLEAR, start, len, ICACHE); +} + + +/* Exported functions. */ + +void flush_icache (void) +{ + cache_exec_after_store_all (); +} + +void flush_icache_range (unsigned long start, unsigned long end) +{ + cache_exec_after_store_range (start, end - start); +} + +void flush_icache_page (struct vm_area_struct *vma, struct page *page) +{ + cache_exec_after_store_range (page_to_virt (page), PAGE_SIZE); +} + +void flush_icache_user_range (struct vm_area_struct *vma, struct page *page, + unsigned long addr, int len) +{ + cache_exec_after_store_range (addr, len); +} + +void flush_cache_sigtramp (unsigned long addr) +{ + /* For the exact size, see signal.c, but 16 bytes should be enough. */ + cache_exec_after_store_range (addr, 16); +} diff -Nru a/arch/v850/kernel/v850e_cache.c b/arch/v850/kernel/v850e_cache.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/v850/kernel/v850e_cache.c Sat Jul 19 12:54:26 2003 @@ -0,0 +1,173 @@ +/* + * arch/v850/kernel/v850e_cache.c -- Cache control for V850E cache memories + * + * Copyright (C) 2003 NEC Electronics Corporation + * Copyright (C) 2003 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +/* This file implements cache control for the rather simple cache used on + some V850E CPUs, specifically the NB85E/TEG CPU-core and the V850E/ME2 + CPU. V850E2 processors have their own (better) cache + implementation. */ + +#include +#include + +#define WAIT_UNTIL_CLEAR(value) while (value) {} + +/* Set caching params via the BHC and DCC registers. */ +void v850e_cache_enable (u16 bhc, u16 icc, u16 dcc) +{ + unsigned long *r0_ram = (unsigned long *)R0_RAM_ADDR; + register u16 bhc_val asm ("r6") = bhc; + + /* Read the instruction cache control register (ICC) and confirm + that bits 0 and 1 (TCLR0, TCLR1) are all cleared. */ + WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3); + V850E_CACHE_ICC = icc; + +#ifdef V850E_CACHE_DCC + /* Configure data-cache. */ + V850E_CACHE_DCC = dcc; +#endif /* V850E_CACHE_DCC */ + + /* Configure caching for various memory regions by writing the BHC + register. The documentation says that an instruction _cannot_ + enable/disable caching for the memory region in which the + instruction itself exists; to work around this, we store + appropriate instructions into the on-chip RAM area (which is never + cached), and briefly jump there to do the work. */ +#ifdef V850E_CACHE_WRITE_IBS + *r0_ram++ = 0xf0720760; /* st.h r0, 0xfffff072[r0] */ +#endif + *r0_ram++ = 0xf06a3760; /* st.h r6, 0xfffff06a[r0] */ + *r0_ram = 0x5640006b; /* jmp [r11] */ + + asm ("mov hilo(1f), r11; jmp [%1]; 1:;" + :: "r" (bhc_val), "r" (R0_RAM_ADDR) : "r11"); +} + +static void clear_icache (void) +{ + /* 1. Read the instruction cache control register (ICC) and confirm + that bits 0 and 1 (TCLR0, TCLR1) are all cleared. */ + WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3); + + /* 2. Read the ICC register and confirm that bit 12 (LOCK0) is + cleared. Bit 13 of the ICC register is always cleared. */ + WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x1000); + + /* 3. Set the TCLR0 and TCLR1 bits of the ICC register as follows, + when clearing way 0 and way 1 at the same time: + (a) Set the TCLR0 and TCLR1 bits. + (b) Read the TCLR0 and TCLR1 bits to confirm that these bits + are cleared. + (c) Perform (a) and (b) above again. */ + V850E_CACHE_ICC |= 0x3; + WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3); + +#ifdef V850E_CACHE_REPEAT_ICC_WRITE + /* Do it again. */ + V850E_CACHE_ICC |= 0x3; + WAIT_UNTIL_CLEAR (V850E_CACHE_ICC & 0x3); +#endif +} + +#ifdef V850E_CACHE_DCC +/* Flush or clear (or both) the data cache, depending on the value of FLAGS; + the procedure is the same for both, just the control bits used differ (and + both may be performed simultaneously). */ +static void dcache_op (unsigned short flags) +{ + /* 1. Read the data cache control register (DCC) and confirm that bits + 0, 1, 4, and 5 (DC00, DC01, DC04, DC05) are all cleared. */ + WAIT_UNTIL_CLEAR (V850E_CACHE_DCC & 0x33); + + /* 2. Clear DCC register bit 12 (DC12), bit 13 (DC13), or both + depending on the way for which tags are to be cleared. */ + V850E_CACHE_DCC &= ~0xC000; + + /* 3. Set DCC register bit 0 (DC00), bit 1 (DC01) or both depending on + the way for which tags are to be cleared. + ... + Set DCC register bit 4 (DC04), bit 5 (DC05), or both depending + on the way to be data flushed. */ + V850E_CACHE_DCC |= flags; + + /* 4. Read DCC register bit DC00, DC01 [DC04, DC05], or both depending + on the way for which tags were cleared [flushed] and confirm + that that bit is cleared. */ + WAIT_UNTIL_CLEAR (V850E_CACHE_DCC & flags); +} +#endif /* V850E_CACHE_DCC */ + +/* Flushes the contents of the dcache to memory. */ +static inline void flush_dcache (void) +{ +#ifdef V850E_CACHE_DCC + /* We only need to do something if in write-back mode. */ + if (V850E_CACHE_DCC & 0x0400) + dcache_op (0x30); +#endif /* V850E_CACHE_DCC */ +} + +/* Flushes the contents of the dcache to memory, and then clears it. */ +static inline void clear_dcache (void) +{ +#ifdef V850E_CACHE_DCC + /* We only need to do something if the dcache is enabled. */ + if (V850E_CACHE_DCC & 0x0C00) + dcache_op (0x33); +#endif /* V850E_CACHE_DCC */ +} + +/* Clears the dcache without flushing to memory first. */ +static inline void clear_dcache_no_flush (void) +{ +#ifdef V850E_CACHE_DCC + /* We only need to do something if the dcache is enabled. */ + if (V850E_CACHE_DCC & 0x0C00) + dcache_op (0x3); +#endif /* V850E_CACHE_DCC */ +} + +static inline void cache_exec_after_store (void) +{ + flush_dcache (); + clear_icache (); +} + + +/* Exported functions. */ + +void flush_icache (void) +{ + cache_exec_after_store (); +} + +void flush_icache_range (unsigned long start, unsigned long end) +{ + cache_exec_after_store (); +} + +void flush_icache_page (struct vm_area_struct *vma, struct page *page) +{ + cache_exec_after_store (); +} + +void flush_icache_user_range (struct vm_area_struct *vma, struct page *page, + unsigned long adr, int len) +{ + cache_exec_after_store (); +} + +void flush_cache_sigtramp (unsigned long addr) +{ + cache_exec_after_store (); +} diff -Nru a/arch/v850/kernel/v850e_intc.c b/arch/v850/kernel/v850e_intc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/v850/kernel/v850e_intc.c Sat Jul 19 12:54:24 2003 @@ -0,0 +1,104 @@ +/* + * arch/v850/kernel/v850e_intc.c -- V850E interrupt controller (INTC) + * + * Copyright (C) 2001,02,03 NEC Electronics Corporation + * Copyright (C) 2001,02,03 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include + +#include + +static void irq_nop (unsigned irq) { } + +static unsigned v850e_intc_irq_startup (unsigned irq) +{ + v850e_intc_clear_pending_irq (irq); + v850e_intc_enable_irq (irq); + return 0; +} + +static void v850e_intc_end_irq (unsigned irq) +{ + unsigned long psw, temp; + + /* Clear the highest-level bit in the In-service priority register + (ISPR), to allow this interrupt (or another of the same or + lesser priority) to happen again. + + The `reti' instruction normally does this automatically when the + PSW bits EP and NP are zero, but we can't always rely on reti + being used consistently to return after an interrupt (another + process can be scheduled, for instance, which can delay the + associated reti for a long time, or this process may be being + single-stepped, which uses the `dbret' instruction to return + from the kernel). + + We also set the PSW EP bit, which prevents reti from also + trying to modify the ISPR itself. */ + + /* Get PSW and disable interrupts. */ + asm volatile ("stsr psw, %0; di" : "=r" (psw)); + /* We don't want to do anything for NMIs (they don't use the ISPR). */ + if (! (psw & 0xC0)) { + /* Transition to `trap' state, so that an eventual real + reti instruction won't modify the ISPR. */ + psw |= 0x40; + /* Fake an interrupt return, which automatically clears the + appropriate bit in the ISPR. */ + asm volatile ("mov hilo(1f), %0;" + "ldsr %0, eipc; ldsr %1, eipsw;" + "reti;" + "1:" + : "=&r" (temp) : "r" (psw)); + } +} + +/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array + INITS (which is terminated by an entry with the name field == 0). */ +void __init v850e_intc_init_irq_types (struct v850e_intc_irq_init *inits, + struct hw_interrupt_type *hw_irq_types) +{ + struct v850e_intc_irq_init *init; + for (init = inits; init->name; init++) { + unsigned i; + struct hw_interrupt_type *hwit = hw_irq_types++; + + hwit->typename = init->name; + + hwit->startup = v850e_intc_irq_startup; + hwit->shutdown = v850e_intc_disable_irq; + hwit->enable = v850e_intc_enable_irq; + hwit->disable = v850e_intc_disable_irq; + hwit->ack = irq_nop; + hwit->end = v850e_intc_end_irq; + + /* Initialize kernel IRQ infrastructure for this interrupt. */ + init_irq_handlers(init->base, init->num, init->interval, hwit); + + /* Set the interrupt priorities. */ + for (i = 0; i < init->num; i++) { + unsigned irq = init->base + i * init->interval; + + /* If the interrupt is currently enabled (all + interrupts are initially disabled), then + assume whoever enabled it has set things up + properly, and avoid messing with it. */ + if (! v850e_intc_irq_enabled (irq)) + /* This write also (1) disables the + interrupt, and (2) clears any pending + interrupts. */ + V850E_INTC_IC (irq) + = (V850E_INTC_IC_PR (init->priority) + | V850E_INTC_IC_MK); + } + } +} diff -Nru a/arch/v850/kernel/v850e_timer_d.c b/arch/v850/kernel/v850e_timer_d.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/v850/kernel/v850e_timer_d.c Sat Jul 19 12:54:25 2003 @@ -0,0 +1,54 @@ +/* + * include/asm-v850/v850e_timer_d.c -- `Timer D' component often used + * with V850E CPUs + * + * Copyright (C) 2001,02,03 NEC Electronics Corporation + * Copyright (C) 2001,02,03 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include + +#include +#include + +/* Start interval timer TIMER (0-3). The timer will issue the + corresponding INTCMD interrupt RATE times per second. + This function does not enable the interrupt. */ +void v850e_timer_d_configure (unsigned timer, unsigned rate) +{ + unsigned divlog2, count; + + /* Calculate params for timer. */ + if (! calc_counter_params ( + V850E_TIMER_D_BASE_FREQ, rate, + V850E_TIMER_D_TMCD_CS_MIN, V850E_TIMER_D_TMCD_CS_MAX, 16, + &divlog2, &count)) + printk (KERN_WARNING + "Cannot find interval timer %d setting suitable" + " for rate of %dHz.\n" + "Using rate of %dHz instead.\n", + timer, rate, + (V850E_TIMER_D_BASE_FREQ >> divlog2) >> 16); + + /* Do the actual hardware timer initialization: */ + + /* Enable timer. */ + V850E_TIMER_D_TMCD(timer) = V850E_TIMER_D_TMCD_CAE; + /* Set clock divider. */ + V850E_TIMER_D_TMCD(timer) + = V850E_TIMER_D_TMCD_CAE + | V850E_TIMER_D_TMCD_CS(divlog2); + /* Set timer compare register. */ + V850E_TIMER_D_CMD(timer) = count; + /* Start counting. */ + V850E_TIMER_D_TMCD(timer) + = V850E_TIMER_D_TMCD_CAE + | V850E_TIMER_D_TMCD_CS(divlog2) + | V850E_TIMER_D_TMCD_CE; +} diff -Nru a/arch/v850/kernel/v850e_utils.c b/arch/v850/kernel/v850e_utils.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/v850/kernel/v850e_utils.c Sat Jul 19 12:54:23 2003 @@ -0,0 +1,62 @@ +/* + * include/asm-v850/v850e_utils.h -- Utility functions associated with + * V850E CPUs + * + * Copyright (C) 2001,02,03 NEC Electronics Corporation + * Copyright (C) 2001,02,03 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include + +/* Calculate counter clock-divider and count values to attain the + desired frequency RATE from the base frequency BASE_FREQ. The + counter is expected to have a clock-divider, which can divide the + system cpu clock by a power of two value from MIN_DIVLOG2 to + MAX_DIV_LOG2, and a word-size of COUNTER_SIZE bits (the counter + counts up and resets whenever it's equal to the compare register, + generating an interrupt or whatever when it does so). The returned + values are: *DIVLOG2 -- log2 of the desired clock divider and *COUNT + -- the counter compare value to use. Returns true if it was possible + to find a reasonable value, otherwise false (and the other return + values will be set to be as good as possible). */ +int calc_counter_params (unsigned long base_freq, + unsigned long rate, + unsigned min_divlog2, unsigned max_divlog2, + unsigned counter_size, + unsigned *divlog2, unsigned *count) +{ + unsigned _divlog2; + int ok = 0; + + /* Find the lowest clock divider setting that can represent RATE. */ + for (_divlog2 = min_divlog2; _divlog2 <= max_divlog2; _divlog2++) { + /* Minimum interrupt rate possible using this divider. */ + unsigned min_int_rate + = (base_freq >> _divlog2) >> counter_size; + + if (min_int_rate <= rate) { + /* This setting is the highest resolution + setting that's slow enough enough to attain + RATE interrupts per second, so use it. */ + ok = 1; + break; + } + } + + if (_divlog2 > max_divlog2) + /* Can't find correct setting. */ + _divlog2 = max_divlog2; + + if (divlog2) + *divlog2 = _divlog2; + if (count) + *count = ((base_freq >> _divlog2) + rate/2) / rate; + + return ok; +} diff -Nru a/arch/v850/rte_me2_cb.ld b/arch/v850/rte_me2_cb.ld --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/v850/rte_me2_cb.ld Sat Jul 19 12:54:30 2003 @@ -0,0 +1,30 @@ +/* Linker script for the Midas labs RTE-V850E/ME2-CB evaluation board + (CONFIG_RTE_CB_ME2), with kernel in SDRAM. */ + +MEMORY { + /* 128Kbyte of IRAM */ + IRAM : ORIGIN = 0x00000000, LENGTH = 0x00020000 + + /* 32MB of SDRAM. */ + SDRAM : ORIGIN = 0x00800000, LENGTH = 0x02000000 +} + +#define KRAM SDRAM + +SECTIONS { + .text : { + __kram_start = . ; + TEXT_CONTENTS + INTV_CONTENTS /* copy to iRAM (0x0-0x620) */ + } > KRAM + + .data : { + DATA_CONTENTS + BSS_CONTENTS + RAMK_INIT_CONTENTS + __kram_end = . ; + BOOTMAP_CONTENTS + } > KRAM + + .root ALIGN (4096) : { ROOT_FS_CONTENTS } > SDRAM +} diff -Nru a/arch/v850/sim85e2.ld b/arch/v850/sim85e2.ld --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/v850/sim85e2.ld Sat Jul 19 12:54:29 2003 @@ -0,0 +1,44 @@ +/* Linker script for the sim85e2c simulator, which is a verilog simulation of + the V850E2 NA85E2C cpu core (CONFIG_V850E2_SIM85E2C). */ + +MEMORY { + /* 1MB of `instruction RAM', starting at 0. + Instruction fetches are much faster from IRAM than from DRAM. + This should match IRAM_ADDR in "include/asm-v580/sim85e2c.h". */ + IRAM : ORIGIN = 0x00000000, LENGTH = 0x00100000 + + /* 1MB of `data RAM', below and contiguous with the I/O space. + Data fetches are much faster from DRAM than from IRAM. + This should match DRAM_ADDR in "include/asm-v580/sim85e2c.h". */ + DRAM : ORIGIN = 0xfff00000, LENGTH = 0x000ff000 + /* We have to load DRAM at a mirror-address of 0x1ff00000, + because the simulator's preprocessing script isn't smart + enough to deal with the above LMA. */ + DRAM_LOAD : ORIGIN = 0x1ff00000, LENGTH = 0x000ff000 + + /* `external ram' (CS1 area), comes after IRAM. + This should match ERAM_ADDR in "include/asm-v580/sim85e2c.h". */ + ERAM : ORIGIN = 0x00100000, LENGTH = 0x07f00000 + + /* Dynamic RAM; uses memory controller. */ + /* SDRAM : ORIGIN = 0x10000000, LENGTH = 0x01000000 */ + SDRAM : ORIGIN = 0x10000000, LENGTH = 0x00200000/*use 2MB*/ +} + +SECTIONS { + .iram : { + INTV_CONTENTS + *arch/v850/kernel/head.o + *(.early.text) + } > IRAM + .dram : { + _memcons_output = . ; + . = . + 0x8000 ; + _memcons_output_end = . ; + } > DRAM + .sdram : { + /* We stick console output into a buffer here. */ + RAMK_KRAM_CONTENTS + ROOT_FS_CONTENTS + } > SDRAM +} diff -Nru a/arch/v850/sim85e2c.ld b/arch/v850/sim85e2c.ld --- a/arch/v850/sim85e2c.ld Sat Jul 19 12:54:29 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,44 +0,0 @@ -/* Linker script for the sim85e2c simulator, which is a verilog simulation of - the V850E2 NA85E2C cpu core (CONFIG_V850E2_SIM85E2C). */ - -MEMORY { - /* 1MB of `instruction RAM', starting at 0. - Instruction fetches are much faster from IRAM than from DRAM. - This should match IRAM_ADDR in "include/asm-v580/sim85e2c.h". */ - IRAM : ORIGIN = 0x00000000, LENGTH = 0x00100000 - - /* 1MB of `data RAM', below and contiguous with the I/O space. - Data fetches are much faster from DRAM than from IRAM. - This should match DRAM_ADDR in "include/asm-v580/sim85e2c.h". */ - DRAM : ORIGIN = 0xfff00000, LENGTH = 0x000ff000 - /* We have to load DRAM at a mirror-address of 0x1ff00000, - because the simulator's preprocessing script isn't smart - enough to deal with the above LMA. */ - DRAM_LOAD : ORIGIN = 0x1ff00000, LENGTH = 0x000ff000 - - /* `external ram' (CS1 area), comes after IRAM. - This should match ERAM_ADDR in "include/asm-v580/sim85e2c.h". */ - ERAM : ORIGIN = 0x00100000, LENGTH = 0x07f00000 -} - -SECTIONS { - .iram : { - INTV_CONTENTS - TEXT_CONTENTS - RAMK_INIT_CONTENTS - } > IRAM - .data : { - __kram_start = . ; - DATA_CONTENTS - BSS_CONTENTS - ROOT_FS_CONTENTS - - /* We stick console output into a buffer here. */ - _memcons_output = . ; - . = . + 0x8000 ; - _memcons_output_end = . ; - - __kram_end = . ; - BOOTMAP_CONTENTS - } > DRAM AT> DRAM_LOAD -} diff -Nru a/arch/v850/vmlinux.lds.S b/arch/v850/vmlinux.lds.S --- a/arch/v850/vmlinux.lds.S Sat Jul 19 12:54:25 2003 +++ b/arch/v850/vmlinux.lds.S Sat Jul 19 12:54:25 2003 @@ -206,8 +206,8 @@ # include "sim.ld" #endif -#ifdef CONFIG_V850E2_SIM85E2C -# include "sim85e2c.ld" +#ifdef CONFIG_V850E2_SIM85E2 +# include "sim85e2.ld" #endif #ifdef CONFIG_V850E2_FPGA85E2C @@ -247,3 +247,8 @@ # include "rte_nb85e_cb.ld" # endif #endif + +#ifdef CONFIG_RTE_CB_ME2 +# include "rte_me2_cb.ld" +#endif + diff -Nru a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c --- a/arch/x86_64/mm/init.c Sat Jul 19 12:54:23 2003 +++ b/arch/x86_64/mm/init.c Sat Jul 19 12:54:23 2003 @@ -19,9 +19,6 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_INITRD -#include -#endif #include #include #include diff -Nru a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c --- a/arch/x86_64/mm/numa.c Sat Jul 19 12:54:27 2003 +++ b/arch/x86_64/mm/numa.c Sat Jul 19 12:54:27 2003 @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c --- a/drivers/acorn/block/fd1772.c Sat Jul 19 12:54:24 2003 +++ b/drivers/acorn/block/fd1772.c Sat Jul 19 12:54:24 2003 @@ -152,8 +152,6 @@ #include -#include - /* Note: FD_MAX_UNITS could be redefined to 2 for the Atari (with * little additional rework in this file). But I'm not yet sure if * some other code depends on the number of floppies... (It is defined diff -Nru a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c --- a/drivers/acorn/block/mfmhd.c Sat Jul 19 12:54:23 2003 +++ b/drivers/acorn/block/mfmhd.c Sat Jul 19 12:54:23 2003 @@ -111,7 +111,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c --- a/drivers/acpi/executer/exutils.c Sat Jul 19 12:54:23 2003 +++ b/drivers/acpi/executer/exutils.c Sat Jul 19 12:54:23 2003 @@ -290,7 +290,7 @@ * acpi_integer is unsigned, so we don't worry about a '-' */ if ((current_value = value) == 0) { - return_VALUE (1); + return_VALUE (1); } num_digits = 0; diff -Nru a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c --- a/drivers/acpi/hardware/hwregs.c Sat Jul 19 12:54:27 2003 +++ b/drivers/acpi/hardware/hwregs.c Sat Jul 19 12:54:27 2003 @@ -357,9 +357,9 @@ /* * Decode the Register ID - * Register id = Register block id | bit id + * Register ID = [Register block ID] | [bit ID] * - * Check bit id to fine locate Register offset. + * Check bit ID to fine locate Register offset. * Check Mask to determine Register offset, and then read-write. */ switch (bit_reg_info->parent_register) { @@ -367,9 +367,9 @@ /* * Status Registers are different from the rest. Clear by - * writing 1, writing 0 has no effect. So, the only relevant + * writing 1, and writing 0 has no effect. So, the only relevant * information is the single bit we're interested in, all others should - * be written as 0 so they will be left unchanged + * be written as 0 so they will be left unchanged. */ value = ACPI_REGISTER_PREPARE_BITS (value, bit_reg_info->bit_position, bit_reg_info->access_bit_mask); @@ -394,17 +394,17 @@ case ACPI_REGISTER_PM1_CONTROL: /* - * Read the PM1 Control register. + * Write the PM1 Control register. * Note that at this level, the fact that there are actually TWO - * registers (A and B - and that B may not exist) is abstracted. + * registers (A and B - and B may not exist) is abstracted. */ ACPI_DEBUG_PRINT ((ACPI_DB_IO, "PM1 control: Read %X\n", register_value)); ACPI_REGISTER_INSERT_VALUE (register_value, bit_reg_info->bit_position, bit_reg_info->access_bit_mask, value); - status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, register_id, - (u16) register_value); + status = acpi_hw_register_write (ACPI_MTX_DO_NOT_LOCK, + ACPI_REGISTER_PM1_CONTROL, (u16) register_value); break; @@ -724,7 +724,7 @@ /* * Three address spaces supported: - * Memory, Io, or PCI config. + * Memory, IO, or PCI_Config. */ switch (reg->address_space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: @@ -808,9 +808,10 @@ (!reg->address)) { return (AE_OK); } + /* * Three address spaces supported: - * Memory, Io, or PCI config. + * Memory, IO, or PCI_Config. */ switch (reg->address_space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: diff -Nru a/drivers/acpi/osl.c b/drivers/acpi/osl.c --- a/drivers/acpi/osl.c Sat Jul 19 12:54:27 2003 +++ b/drivers/acpi/osl.c Sat Jul 19 12:54:27 2003 @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -291,11 +292,14 @@ void acpi_os_stall(u32 us) { - if (us > 10000) { - mdelay(us / 1000); - } - else { - udelay(us); + while (us) { + u32 delay = 1000; + + if (delay > us) + delay = us; + udelay(delay); + touch_nmi_watchdog(); + us -= delay; } } diff -Nru a/drivers/acpi/processor.c b/drivers/acpi/processor.c --- a/drivers/acpi/processor.c Sat Jul 19 12:54:26 2003 +++ b/drivers/acpi/processor.c Sat Jul 19 12:54:26 2003 @@ -1351,7 +1351,7 @@ PDE(inode)->data); } -static int +static ssize_t acpi_processor_write_throttling ( struct file *file, const char *buffer, @@ -1414,7 +1414,7 @@ PDE(inode)->data); } -static int +static ssize_t acpi_processor_write_limit ( struct file *file, const char *buffer, diff -Nru a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c --- a/drivers/acpi/tables/tbconvrt.c Sat Jul 19 12:54:24 2003 +++ b/drivers/acpi/tables/tbconvrt.c Sat Jul 19 12:54:24 2003 @@ -75,14 +75,10 @@ ACPI_FUNCTION_ENTRY (); -#if ACPI_MACHINE_WIDTH != 64 - if (RSDP->revision < 2) { pointer_size = sizeof (u32); } - else -#endif - { + else { pointer_size = sizeof (u64); } diff -Nru a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c --- a/drivers/acpi/tables/tbget.c Sat Jul 19 12:54:26 2003 +++ b/drivers/acpi/tables/tbget.c Sat Jul 19 12:54:26 2003 @@ -145,7 +145,7 @@ /* Create a logical address for the physical pointer*/ status = acpi_os_map_memory (address->pointer.physical, sizeof (struct acpi_table_header), - (void **) &header); + (void *) &header); if (ACPI_FAILURE (status)) { ACPI_REPORT_ERROR (("Could not map memory at %8.8X%8.8X for length %X\n", ACPI_HIDWORD (address->pointer.physical), @@ -361,7 +361,7 @@ * into our address space. */ status = acpi_os_map_memory (address->pointer.physical, (acpi_size) header->length, - (void **) &full_table); + (void *) &full_table); if (ACPI_FAILURE (status)) { ACPI_REPORT_ERROR (("Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X\n", header->signature, diff -Nru a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c --- a/drivers/acpi/tables/tbinstal.c Sat Jul 19 12:54:23 2003 +++ b/drivers/acpi/tables/tbinstal.c Sat Jul 19 12:54:23 2003 @@ -271,22 +271,40 @@ if (list_head->next) { return_ACPI_STATUS (AE_ALREADY_EXISTS); } - } - /* - * Link the new table in to the list of tables of this type. - * Just insert at the start of the list, order unimportant. - * - * table_desc->Prev is already NULL from calloc() - */ - table_desc->next = list_head->next; - list_head->next = table_desc; + table_desc->next = list_head->next; + list_head->next = table_desc; + + if (table_desc->next) { + table_desc->next->prev = table_desc; + } - if (table_desc->next) { - table_desc->next->prev = table_desc; + list_head->count++; } + else { + /* + * Link the new table in to the list of tables of this type. + * Insert at the end of the list, order IS IMPORTANT. + * + * table_desc->Prev & Next are already NULL from calloc() + */ + list_head->count++; + + if (!list_head->next) { + list_head->next = table_desc; + } + else { + table_desc->next = list_head->next; - list_head->count++; + while (table_desc->next->next) { + table_desc->next = table_desc->next->next; + } + + table_desc->next->next = table_desc; + table_desc->prev = table_desc->next; + table_desc->next = NULL; + } + } /* Finish initialization of the table descriptor */ diff -Nru a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c --- a/drivers/acpi/tables/tbrsdt.c Sat Jul 19 12:54:25 2003 +++ b/drivers/acpi/tables/tbrsdt.c Sat Jul 19 12:54:25 2003 @@ -85,7 +85,7 @@ * Obtain access to the RSDP structure */ status = acpi_os_map_memory (address->pointer.physical, sizeof (struct rsdp_descriptor), - (void **) &rsdp); + (void *) &rsdp); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } diff -Nru a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c --- a/drivers/acpi/tables/tbxfroot.c Sat Jul 19 12:54:26 2003 +++ b/drivers/acpi/tables/tbxfroot.c Sat Jul 19 12:54:26 2003 @@ -179,7 +179,7 @@ if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { status = acpi_os_map_memory (rsdp_address.pointer.physical, sizeof (struct rsdp_descriptor), - (void **) &acpi_gbl_RSDP); + (void *) &acpi_gbl_RSDP); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -423,7 +423,7 @@ * 1) Search EBDA (low memory) paragraphs */ status = acpi_os_map_memory ((u64) ACPI_LO_RSDP_WINDOW_BASE, ACPI_LO_RSDP_WINDOW_SIZE, - (void **) &table_ptr); + (void *) &table_ptr); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n", ACPI_LO_RSDP_WINDOW_BASE, ACPI_LO_RSDP_WINDOW_SIZE)); @@ -447,7 +447,7 @@ * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h */ status = acpi_os_map_memory ((u64) ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE, - (void **) &table_ptr); + (void *) &table_ptr); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n", ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE)); diff -Nru a/drivers/acpi/tables.c b/drivers/acpi/tables.c --- a/drivers/acpi/tables.c Sat Jul 19 12:54:24 2003 +++ b/drivers/acpi/tables.c Sat Jul 19 12:54:24 2003 @@ -33,6 +33,7 @@ #include #include #include +#include #define PREFIX "ACPI: " @@ -61,16 +62,14 @@ /* System Description Table (RSDT/XSDT) */ struct acpi_table_sdt { - unsigned long pa; /* Physical Address */ - unsigned long count; /* Table count */ - struct { - unsigned long pa; - enum acpi_table_id id; - unsigned long size; - } entry[ACPI_MAX_TABLES]; + unsigned long pa; + enum acpi_table_id id; + unsigned long size; } __attribute__ ((packed)); -static struct acpi_table_sdt sdt; +static unsigned long sdt_pa; /* Physical Address */ +static unsigned long sdt_count; /* Table count */ +static struct acpi_table_sdt *sdt_entry; void acpi_table_print ( @@ -236,11 +235,11 @@ /* Locate the table. */ - for (i = 0; i < sdt.count; i++) { - if (sdt.entry[i].id != temp_id) + for (i = 0; i < sdt_count; i++) { + if (sdt_entry[i].id != temp_id) continue; *header = (void *) - __acpi_map_table(sdt.entry[i].pa, sdt.entry[i].size); + __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size); if (!*header) { printk(KERN_WARNING PREFIX "Unable to map %s\n", acpi_table_signatures[temp_id]); @@ -289,11 +288,11 @@ /* Locate the MADT (if exists). There should only be one. */ - for (i = 0; i < sdt.count; i++) { - if (sdt.entry[i].id != id) + for (i = 0; i < sdt_count; i++) { + if (sdt_entry[i].id != id) continue; madt = (void *) - __acpi_map_table(sdt.entry[i].pa, sdt.entry[i].size); + __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size); if (!madt) { printk(KERN_WARNING PREFIX "Unable to map %s\n", acpi_table_signatures[id]); @@ -308,7 +307,7 @@ return -ENODEV; } - madt_end = (unsigned long) madt + sdt.entry[i].size; + madt_end = (unsigned long) madt + sdt_entry[i].size; /* Parse all entries looking for a match. */ @@ -349,10 +348,10 @@ if (!handler) return -EINVAL; - for (i = 0; i < sdt.count; i++) { - if (sdt.entry[i].id != id) + for (i = 0; i < sdt_count; i++) { + if (sdt_entry[i].id != id) continue; - handler(sdt.entry[i].pa, sdt.entry[i].size); + handler(sdt_entry[i].pa, sdt_entry[i].size); count++; } @@ -377,11 +376,11 @@ struct acpi_table_xsdt *mapped_xsdt = NULL; - sdt.pa = ((struct acpi20_table_rsdp*)rsdp)->xsdt_address; + sdt_pa = ((struct acpi20_table_rsdp*)rsdp)->xsdt_address; /* map in just the header */ header = (struct acpi_table_header *) - __acpi_map_table(sdt.pa, sizeof(struct acpi_table_header)); + __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header)); if (!header) { printk(KERN_WARNING PREFIX "Unable to map XSDT header\n"); @@ -390,7 +389,7 @@ /* remap in the entire table before processing */ mapped_xsdt = (struct acpi_table_xsdt *) - __acpi_map_table(sdt.pa, header->length); + __acpi_map_table(sdt_pa, header->length); if (!mapped_xsdt) { printk(KERN_WARNING PREFIX "Unable to map XSDT\n"); return -ENODEV; @@ -407,15 +406,21 @@ return -ENODEV; } - sdt.count = (header->length - sizeof(struct acpi_table_header)) >> 3; - if (sdt.count > ACPI_MAX_TABLES) { + sdt_count = (header->length - sizeof(struct acpi_table_header)) >> 3; + if (sdt_count > ACPI_MAX_TABLES) { printk(KERN_WARNING PREFIX "Truncated %lu XSDT entries\n", - (sdt.count - ACPI_MAX_TABLES)); - sdt.count = ACPI_MAX_TABLES; + (sdt_count - ACPI_MAX_TABLES)); + sdt_count = ACPI_MAX_TABLES; } - for (i = 0; i < sdt.count; i++) - sdt.entry[i].pa = (unsigned long) mapped_xsdt->entry[i]; + sdt_entry = alloc_bootmem(sdt_count * sizeof(struct acpi_table_sdt)); + if (!sdt_entry) { + printk(KERN_ERR "ACPI: Could not allocate mem for SDT entries!\n"); + return -ENOMEM; + } + + for (i = 0; i < sdt_count; i++) + sdt_entry[i].pa = (unsigned long) mapped_xsdt->entry[i]; } /* Then check RSDT */ @@ -424,11 +429,11 @@ struct acpi_table_rsdt *mapped_rsdt = NULL; - sdt.pa = rsdp->rsdt_address; + sdt_pa = rsdp->rsdt_address; /* map in just the header */ header = (struct acpi_table_header *) - __acpi_map_table(sdt.pa, sizeof(struct acpi_table_header)); + __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header)); if (!header) { printk(KERN_WARNING PREFIX "Unable to map RSDT header\n"); return -ENODEV; @@ -436,7 +441,7 @@ /* remap in the entire table before processing */ mapped_rsdt = (struct acpi_table_rsdt *) - __acpi_map_table(sdt.pa, header->length); + __acpi_map_table(sdt_pa, header->length); if (!mapped_rsdt) { printk(KERN_WARNING PREFIX "Unable to map RSDT\n"); return -ENODEV; @@ -453,15 +458,21 @@ return -ENODEV; } - sdt.count = (header->length - sizeof(struct acpi_table_header)) >> 2; - if (sdt.count > ACPI_MAX_TABLES) { + sdt_count = (header->length - sizeof(struct acpi_table_header)) >> 2; + if (sdt_count > ACPI_MAX_TABLES) { printk(KERN_WARNING PREFIX "Truncated %lu RSDT entries\n", - (sdt.count - ACPI_TABLE_COUNT)); - sdt.count = ACPI_MAX_TABLES; + (sdt_count - ACPI_MAX_TABLES)); + sdt_count = ACPI_MAX_TABLES; } - for (i = 0; i < sdt.count; i++) - sdt.entry[i].pa = (unsigned long) mapped_rsdt->entry[i]; + sdt_entry = alloc_bootmem(sdt_count * sizeof(struct acpi_table_sdt)); + if (!sdt_entry) { + printk(KERN_ERR "ACPI: Could not allocate mem for SDT entries!\n"); + return -ENOMEM; + } + + for (i = 0; i < sdt_count; i++) + sdt_entry[i].pa = (unsigned long) mapped_rsdt->entry[i]; } else { @@ -469,38 +480,38 @@ return -ENODEV; } - acpi_table_print(header, sdt.pa); + acpi_table_print(header, sdt_pa); - for (i = 0; i < sdt.count; i++) { + for (i = 0; i < sdt_count; i++) { /* map in just the header */ header = (struct acpi_table_header *) - __acpi_map_table(sdt.entry[i].pa, + __acpi_map_table(sdt_entry[i].pa, sizeof(struct acpi_table_header)); if (!header) continue; /* remap in the entire table before processing */ header = (struct acpi_table_header *) - __acpi_map_table(sdt.entry[i].pa, + __acpi_map_table(sdt_entry[i].pa, header->length); if (!header) continue; - acpi_table_print(header, sdt.entry[i].pa); + acpi_table_print(header, sdt_entry[i].pa); if (acpi_table_compute_checksum(header, header->length)) { printk(KERN_WARNING " >>> ERROR: Invalid checksum\n"); continue; } - sdt.entry[i].size = header->length; + sdt_entry[i].size = header->length; for (id = 0; id < ACPI_TABLE_COUNT; id++) { if (!strncmp((char *) &header->signature, acpi_table_signatures[id], sizeof(header->signature))) { - sdt.entry[i].id = id; + sdt_entry[i].id = id; } } } @@ -524,8 +535,6 @@ struct acpi_table_rsdp *rsdp = NULL; unsigned long rsdp_phys = 0; int result = 0; - - memset(&sdt, 0, sizeof(struct acpi_table_sdt)); /* Locate and map the Root System Description Table (RSDP) */ diff -Nru a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c --- a/drivers/acpi/thermal.c Sat Jul 19 12:54:27 2003 +++ b/drivers/acpi/thermal.c Sat Jul 19 12:54:27 2003 @@ -84,11 +84,11 @@ static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file); static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file); static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file); -static int acpi_thermal_write_trip_points (struct file*,const char *,size_t,loff_t *); +static ssize_t acpi_thermal_write_trip_points (struct file*,const char *,size_t,loff_t *); static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file); -static int acpi_thermal_write_cooling_mode (struct file*,const char *,size_t,loff_t *); +static ssize_t acpi_thermal_write_cooling_mode (struct file*,const char *,size_t,loff_t *); static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file); -static int acpi_thermal_write_polling(struct file*,const char *,size_t,loff_t *); +static ssize_t acpi_thermal_write_polling(struct file*,const char *,size_t,loff_t *); static struct acpi_driver acpi_thermal_driver = { .name = ACPI_THERMAL_DRIVER_NAME, @@ -881,7 +881,7 @@ return single_open(file, acpi_thermal_trip_seq_show, PDE(inode)->data); } -static int +static ssize_t acpi_thermal_write_trip_points ( struct file *file, const char *buffer, @@ -950,7 +950,7 @@ PDE(inode)->data); } -static int +static ssize_t acpi_thermal_write_cooling_mode ( struct file *file, const char *buffer, @@ -1011,7 +1011,7 @@ PDE(inode)->data); } -static int +static ssize_t acpi_thermal_write_polling ( struct file *file, const char *buffer, diff -Nru a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c --- a/drivers/acpi/utilities/utglobal.c Sat Jul 19 12:54:23 2003 +++ b/drivers/acpi/utilities/utglobal.c Sat Jul 19 12:54:23 2003 @@ -307,9 +307,9 @@ /*********** Name, Signature, Global typed pointer Signature size, Type How many allowed?, Contains valid AML? */ /* RSDP 0 */ {RSDP_NAME, RSDP_SIG, NULL, sizeof (RSDP_SIG)-1, ACPI_TABLE_ROOT | ACPI_TABLE_SINGLE}, - /* DSDT 1 */ {DSDT_SIG, DSDT_SIG, (void **) &acpi_gbl_DSDT, sizeof (DSDT_SIG)-1, ACPI_TABLE_SECONDARY| ACPI_TABLE_SINGLE | ACPI_TABLE_EXECUTABLE}, - /* FADT 2 */ {FADT_SIG, FADT_SIG, (void **) &acpi_gbl_FADT, sizeof (FADT_SIG)-1, ACPI_TABLE_PRIMARY | ACPI_TABLE_SINGLE}, - /* FACS 3 */ {FACS_SIG, FACS_SIG, (void **) &acpi_gbl_FACS, sizeof (FACS_SIG)-1, ACPI_TABLE_SECONDARY| ACPI_TABLE_SINGLE}, + /* DSDT 1 */ {DSDT_SIG, DSDT_SIG, (void *) &acpi_gbl_DSDT, sizeof (DSDT_SIG)-1, ACPI_TABLE_SECONDARY| ACPI_TABLE_SINGLE | ACPI_TABLE_EXECUTABLE}, + /* FADT 2 */ {FADT_SIG, FADT_SIG, (void *) &acpi_gbl_FADT, sizeof (FADT_SIG)-1, ACPI_TABLE_PRIMARY | ACPI_TABLE_SINGLE}, + /* FACS 3 */ {FACS_SIG, FACS_SIG, (void *) &acpi_gbl_FACS, sizeof (FACS_SIG)-1, ACPI_TABLE_SECONDARY| ACPI_TABLE_SINGLE}, /* PSDT 4 */ {PSDT_SIG, PSDT_SIG, NULL, sizeof (PSDT_SIG)-1, ACPI_TABLE_PRIMARY | ACPI_TABLE_MULTIPLE | ACPI_TABLE_EXECUTABLE}, /* SSDT 5 */ {SSDT_SIG, SSDT_SIG, NULL, sizeof (SSDT_SIG)-1, ACPI_TABLE_PRIMARY | ACPI_TABLE_MULTIPLE | ACPI_TABLE_EXECUTABLE}, /* XSDT 6 */ {XSDT_SIG, XSDT_SIG, NULL, sizeof (RSDT_SIG)-1, ACPI_TABLE_ROOT | ACPI_TABLE_SINGLE}, diff -Nru a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c --- a/drivers/atm/atmtcp.c Sat Jul 19 12:54:26 2003 +++ b/drivers/atm/atmtcp.c Sat Jul 19 12:54:26 2003 @@ -66,7 +66,7 @@ *(struct atm_vcc **) &new_msg->vcc = vcc; old_test = test_bit(flag,&vcc->flags); out_vcc->push(out_vcc,skb); - add_wait_queue(&vcc->sleep,&wait); + add_wait_queue(vcc->sk->sk_sleep, &wait); while (test_bit(flag,&vcc->flags) == old_test) { mb(); out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL; @@ -78,7 +78,7 @@ schedule(); } current->state = TASK_RUNNING; - remove_wait_queue(&vcc->sleep,&wait); + remove_wait_queue(vcc->sk->sk_sleep, &wait); return error; } @@ -90,7 +90,7 @@ vcc->vpi = msg->addr.sap_addr.vpi; vcc->vci = msg->addr.sap_addr.vci; vcc->qos = msg->qos; - vcc->reply = msg->result; + vcc->sk->sk_err = -msg->result; switch (msg->type) { case ATMTCP_CTRL_OPEN: change_bit(ATM_VF_READY,&vcc->flags); @@ -103,7 +103,7 @@ msg->type); return -EINVAL; } - wake_up(&vcc->sleep); + wake_up(vcc->sk->sk_sleep); return 0; } @@ -134,7 +134,7 @@ clear_bit(ATM_VF_READY,&vcc->flags); /* just in case ... */ error = atmtcp_send_control(vcc,ATMTCP_CTRL_OPEN,&msg,ATM_VF_READY); if (error) return error; - return vcc->reply; + return -vcc->sk->sk_err; } @@ -257,7 +257,7 @@ walk = atm_sk(s); if (walk->dev != atmtcp_dev) continue; - wake_up(&walk->sleep); + wake_up(walk->sk->sk_sleep); } read_unlock(&vcc_sklist_lock); } diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c --- a/drivers/block/DAC960.c Sat Jul 19 12:54:26 2003 +++ b/drivers/block/DAC960.c Sat Jul 19 12:54:26 2003 @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/block/Kconfig b/drivers/block/Kconfig --- a/drivers/block/Kconfig Sat Jul 19 12:54:23 2003 +++ b/drivers/block/Kconfig Sat Jul 19 12:54:23 2003 @@ -264,6 +264,7 @@ config BLK_DEV_CRYPTOLOOP tristate "Cryptoloop Support" + select CRYPTO depends on BLK_DEV_LOOP ---help--- Say Y here if you want to be able to use the ciphers that are @@ -339,7 +340,7 @@ config LBD bool "Support for Large Block Devices" - depends on X86 + depends on X86 || MIPS32 || PPC32 || ARCH_S390_31 || SUPERH help Say Y here if you want to attach large (bigger than 2TB) discs to your machine, or if you want to have a raid or loopback device diff -Nru a/drivers/block/acsi.c b/drivers/block/acsi.c --- a/drivers/block/acsi.c Sat Jul 19 12:54:30 2003 +++ b/drivers/block/acsi.c Sat Jul 19 12:54:30 2003 @@ -55,7 +55,6 @@ #include #include #include -#include #include #include #include /* for SCSI_IOCTL_GET_IDLUN */ diff -Nru a/drivers/block/amiflop.c b/drivers/block/amiflop.c --- a/drivers/block/amiflop.c Sat Jul 19 12:54:25 2003 +++ b/drivers/block/amiflop.c Sat Jul 19 12:54:25 2003 @@ -79,7 +79,6 @@ #include #include #include -#include #undef DEBUG /* print _LOTS_ of infos */ diff -Nru a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c --- a/drivers/block/as-iosched.c Sat Jul 19 12:54:21 2003 +++ b/drivers/block/as-iosched.c Sat Jul 19 12:54:21 2003 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -834,10 +833,11 @@ + 2*1024*64); aic->seek_samples += 256; - aic->seek_total += 256*seek_dist; + aic->seek_total += (u64)256*seek_dist; if (aic->seek_samples) { - aic->seek_mean = aic->seek_total + 128; - sector_div(aic->seek_mean, aic->seek_samples); + u64 total = aic->seek_total + (aic->seek_samples>>1); + do_div(total, aic->seek_samples); + aic->seek_mean = (sector_t)total; } aic->seek_samples = (aic->seek_samples>>1) + (aic->seek_samples>>2); @@ -1306,6 +1306,15 @@ as_update_arq(ad, arq); /* keep state machine up to date */ } +/* + * FIXME: HACK for AS requeue problems + */ +static void as_requeue_request(request_queue_t *q, struct request *rq) +{ + elv_completed_request(q, rq); + __elv_add_request(q, rq, 0, 0); +} + static void as_insert_request(request_queue_t *q, struct request *rq, struct list_head *insert_here) @@ -1821,6 +1830,7 @@ .elevator_next_req_fn = as_next_request, .elevator_add_req_fn = as_insert_request, .elevator_remove_req_fn = as_remove_request, + .elevator_requeue_req_fn = as_requeue_request, .elevator_queue_empty_fn = as_queue_empty, .elevator_completed_req_fn = as_completed_request, .elevator_former_req_fn = as_former_request, diff -Nru a/drivers/block/ataflop.c b/drivers/block/ataflop.c --- a/drivers/block/ataflop.c Sat Jul 19 12:54:23 2003 +++ b/drivers/block/ataflop.c Sat Jul 19 12:54:23 2003 @@ -91,7 +91,6 @@ #include #include #include -#include #include #define FD_MAX_UNITS 2 diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c --- a/drivers/block/cciss.c Sat Jul 19 12:54:29 2003 +++ b/drivers/block/cciss.c Sat Jul 19 12:54:29 2003 @@ -41,7 +41,6 @@ #include #include -#include #include #include #include diff -Nru a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c --- a/drivers/block/cciss_scsi.c Sat Jul 19 12:54:23 2003 +++ b/drivers/block/cciss_scsi.c Sat Jul 19 12:54:23 2003 @@ -712,7 +712,8 @@ sh->hostdata[0] = (unsigned long) hba[ctlr]; sh->irq = hba[ctlr]->intr; sh->unique_id = sh->irq; - scsi_add_host(sh, &hba[ctlr]->pdev->dev); + scsi_add_host(sh, &hba[ctlr]->pdev->dev); /* XXX handle failure */ + scsi_scan_host(sh); return 1; } diff -Nru a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c --- a/drivers/block/cpqarray.c Sat Jul 19 12:54:23 2003 +++ b/drivers/block/cpqarray.c Sat Jul 19 12:54:23 2003 @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c --- a/drivers/block/cryptoloop.c Sat Jul 19 12:54:25 2003 +++ b/drivers/block/cryptoloop.c Sat Jul 19 12:54:25 2003 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c --- a/drivers/block/deadline-iosched.c Sat Jul 19 12:54:27 2003 +++ b/drivers/block/deadline-iosched.c Sat Jul 19 12:54:27 2003 @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/block/elevator.c b/drivers/block/elevator.c --- a/drivers/block/elevator.c Sat Jul 19 12:54:26 2003 +++ b/drivers/block/elevator.c Sat Jul 19 12:54:26 2003 @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -214,6 +213,18 @@ e->elevator_merge_req_fn(q, rq, next); } +void elv_requeue_request(request_queue_t *q, struct request *rq) +{ + /* + * if iosched has an explicit requeue hook, then use that. otherwise + * just put the request at the front of the queue + */ + if (q->elevator.elevator_requeue_req_fn) + q->elevator.elevator_requeue_req_fn(q, rq); + else + __elv_add_request(q, rq, 0, 0); +} + void __elv_add_request(request_queue_t *q, struct request *rq, int at_end, int plug) { @@ -417,6 +428,7 @@ EXPORT_SYMBOL(elv_add_request); EXPORT_SYMBOL(__elv_add_request); +EXPORT_SYMBOL(elv_requeue_request); EXPORT_SYMBOL(elv_next_request); EXPORT_SYMBOL(elv_remove_request); EXPORT_SYMBOL(elv_queue_empty); diff -Nru a/drivers/block/floppy.c b/drivers/block/floppy.c --- a/drivers/block/floppy.c Sat Jul 19 12:54:23 2003 +++ b/drivers/block/floppy.c Sat Jul 19 12:54:23 2003 @@ -242,7 +242,7 @@ #define LOCAL_END_REQUEST #define DEVICE_NAME "floppy" -#include +#include #include #include /* for the compatibility eject ioctl */ #include diff -Nru a/drivers/block/floppy98.c b/drivers/block/floppy98.c --- a/drivers/block/floppy98.c Sat Jul 19 12:54:24 2003 +++ b/drivers/block/floppy98.c Sat Jul 19 12:54:24 2003 @@ -277,7 +277,6 @@ #define LOCAL_END_REQUEST #define DEVICE_NAME "floppy" -#include #include #include /* for the compatibility eject ioctl */ #include diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c --- a/drivers/block/genhd.c Sat Jul 19 12:54:25 2003 +++ b/drivers/block/genhd.c Sat Jul 19 12:54:25 2003 @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/block/ioctl.c b/drivers/block/ioctl.c --- a/drivers/block/ioctl.c Sat Jul 19 12:54:22 2003 +++ b/drivers/block/ioctl.c Sat Jul 19 12:54:22 2003 @@ -1,5 +1,5 @@ #include /* for capable() */ -#include /* for set_device_ro() */ +#include #include #include #include @@ -166,13 +166,11 @@ return -EINVAL; if (get_user(n, (int *) arg)) return -EFAULT; - if (n > PAGE_SIZE || n < 512 || (n & (n - 1))) - return -EINVAL; if (bd_claim(bdev, &holder) < 0) return -EBUSY; - set_blocksize(bdev, n); + ret = set_blocksize(bdev, n); bd_release(bdev); - return 0; + return ret; case BLKPG: return blkpg_ioctl(bdev, (struct blkpg_ioctl_arg *) arg); case BLKRRPART: diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c --- a/drivers/block/ll_rw_blk.c Sat Jul 19 12:54:22 2003 +++ b/drivers/block/ll_rw_blk.c Sat Jul 19 12:54:22 2003 @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -1494,6 +1494,23 @@ return rq; } +/** + * blk_requeue_request - put a request back on queue + * @q: request queue where request should be inserted + * @rq: request to be inserted + * + * Description: + * Drivers often keep queueing requests until the hardware cannot accept + * more, when that condition happens we need to put the request back + * on the queue. Must be called with queue lock held. + */ +void blk_requeue_request(request_queue_t *q, struct request *rq) +{ + if (blk_rq_tagged(rq)) + blk_queue_end_tag(q, rq); + + elv_requeue_request(q, rq); +} /** * blk_insert_request - insert a special request in to a request queue @@ -2730,6 +2747,7 @@ EXPORT_SYMBOL(blk_get_request); EXPORT_SYMBOL(blk_put_request); EXPORT_SYMBOL(blk_insert_request); +EXPORT_SYMBOL(blk_requeue_request); EXPORT_SYMBOL(blk_queue_prep_rq); EXPORT_SYMBOL(blk_queue_merge_bvec); diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c --- a/drivers/block/nbd.c Sat Jul 19 12:54:23 2003 +++ b/drivers/block/nbd.c Sat Jul 19 12:54:23 2003 @@ -44,7 +44,6 @@ #include -#include #include #include #include @@ -55,8 +54,6 @@ #include #include #include -#include -#include #include #include @@ -261,7 +258,8 @@ dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%luB)\n", lo->disk->disk_name, req, nbdcmd_to_ascii(nbd_cmd(req)), - req->sector << 9, req->nr_sectors << 9); + (unsigned long long)req->sector << 9, + req->nr_sectors << 9); result = sock_xmit(sock, 1, &request, sizeof(request), (nbd_cmd(req) == NBD_CMD_WRITE)? MSG_MORE: 0); if (result <= 0) { diff -Nru a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c --- a/drivers/block/paride/pcd.c Sat Jul 19 12:54:29 2003 +++ b/drivers/block/paride/pcd.c Sat Jul 19 12:54:30 2003 @@ -137,7 +137,7 @@ #include #include #include -#include +#include #include static spinlock_t pcd_lock; diff -Nru a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c --- a/drivers/block/paride/pd.c Sat Jul 19 12:54:27 2003 +++ b/drivers/block/paride/pd.c Sat Jul 19 12:54:27 2003 @@ -150,7 +150,7 @@ #include #include #include /* for the eject ioctl */ -#include +#include #include #include diff -Nru a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c --- a/drivers/block/paride/pf.c Sat Jul 19 12:54:26 2003 +++ b/drivers/block/paride/pf.c Sat Jul 19 12:54:26 2003 @@ -150,7 +150,7 @@ #include #include #include -#include +#include #include #include @@ -222,9 +222,6 @@ #define ATAPI_READ_10 0x28 #define ATAPI_WRITE_10 0x2a -#ifdef MODULE -void cleanup_module(void); -#endif static int pf_open(struct inode *inode, struct file *file); static void do_pf_request(request_queue_t * q); static int pf_ioctl(struct inode *inode, struct file *file, diff -Nru a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c --- a/drivers/block/ps2esdi.c Sat Jul 19 12:54:21 2003 +++ b/drivers/block/ps2esdi.c Sat Jul 19 12:54:21 2003 @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/block/swim3.c b/drivers/block/swim3.c --- a/drivers/block/swim3.c Sat Jul 19 12:54:24 2003 +++ b/drivers/block/swim3.c Sat Jul 19 12:54:24 2003 @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c --- a/drivers/block/swim_iop.c Sat Jul 19 12:54:21 2003 +++ b/drivers/block/swim_iop.c Sat Jul 19 12:54:21 2003 @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/block/umem.c b/drivers/block/umem.c --- a/drivers/block/umem.c Sat Jul 19 12:54:30 2003 +++ b/drivers/block/umem.c Sat Jul 19 12:54:30 2003 @@ -99,7 +99,7 @@ static int major_nr; -#include +#include #include struct cardinfo { diff -Nru a/drivers/block/xd.c b/drivers/block/xd.c --- a/drivers/block/xd.c Sat Jul 19 12:54:27 2003 +++ b/drivers/block/xd.c Sat Jul 19 12:54:27 2003 @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/drivers/block/z2ram.c b/drivers/block/z2ram.c --- a/drivers/block/z2ram.c Sat Jul 19 12:54:26 2003 +++ b/drivers/block/z2ram.c Sat Jul 19 12:54:26 2003 @@ -30,7 +30,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c --- a/drivers/cdrom/aztcd.c Sat Jul 19 12:54:28 2003 +++ b/drivers/cdrom/aztcd.c Sat Jul 19 12:54:28 2003 @@ -166,7 +166,7 @@ */ #include -#include +#include #include "aztcd.h" #include diff -Nru a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c --- a/drivers/cdrom/cdrom.c Sat Jul 19 12:54:23 2003 +++ b/drivers/cdrom/cdrom.c Sat Jul 19 12:54:23 2003 @@ -268,6 +268,7 @@ #include #include #include +#include #include @@ -2171,6 +2172,7 @@ return -ENOSYS; cdinfo(CD_DO_IOCTL, "entering CDROM_SEND_PACKET\n"); IOCTL_IN(arg, struct cdrom_generic_command, cgc); + cgc.timeout = clock_t_to_jiffies(cgc.timeout); return cdrom_do_cmd(cdi, &cgc); } case CDROM_NEXT_WRITABLE: { diff -Nru a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c --- a/drivers/cdrom/cdu31a.c Sat Jul 19 12:54:26 2003 +++ b/drivers/cdrom/cdu31a.c Sat Jul 19 12:54:26 2003 @@ -177,7 +177,7 @@ #include "cdu31a.h" #define MAJOR_NR CDU31A_CDROM_MAJOR -#include +#include #define CDU31A_READAHEAD 4 /* 128 sector, 64kB, 32 reads read-ahead */ #define CDU31A_MAX_CONSECUTIVE_ATTENTIONS 10 diff -Nru a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c --- a/drivers/cdrom/cm206.c Sat Jul 19 12:54:28 2003 +++ b/drivers/cdrom/cm206.c Sat Jul 19 12:54:28 2003 @@ -199,7 +199,7 @@ #define MAJOR_NR CM206_CDROM_MAJOR -#include +#include #undef DEBUG #define STATISTICS /* record times and frequencies of events */ diff -Nru a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c --- a/drivers/cdrom/gscd.c Sat Jul 19 12:54:21 2003 +++ b/drivers/cdrom/gscd.c Sat Jul 19 12:54:21 2003 @@ -69,7 +69,7 @@ #include #define MAJOR_NR GOLDSTAR_CDROM_MAJOR -#include +#include #define gscd_port gscd /* for compatible parameter passing with "insmod" */ #include "gscd.h" diff -Nru a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c --- a/drivers/cdrom/mcd.c Sat Jul 19 12:54:25 2003 +++ b/drivers/cdrom/mcd.c Sat Jul 19 12:54:25 2003 @@ -101,7 +101,7 @@ #include #include #include -#include +#include #define mcd_port mcd /* for compatible parameter passing with "insmod" */ #include "mcd.h" diff -Nru a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c --- a/drivers/cdrom/mcdx.c Sat Jul 19 12:54:25 2003 +++ b/drivers/cdrom/mcdx.c Sat Jul 19 12:54:25 2003 @@ -74,7 +74,7 @@ #include #define MAJOR_NR MITSUMI_X_CDROM_MAJOR -#include +#include #include /* for compatible parameter passing with "insmod" */ diff -Nru a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c --- a/drivers/cdrom/optcd.c Sat Jul 19 12:54:23 2003 +++ b/drivers/cdrom/optcd.c Sat Jul 19 12:54:23 2003 @@ -73,7 +73,7 @@ #include #include -#include +#include #include #include "optcd.h" diff -Nru a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c --- a/drivers/cdrom/sbpcd.c Sat Jul 19 12:54:23 2003 +++ b/drivers/cdrom/sbpcd.c Sat Jul 19 12:54:23 2003 @@ -387,7 +387,7 @@ #include "sbpcd.h" #define MAJOR_NR MATSUSHITA_CDROM_MAJOR -#include +#include /*==========================================================================*/ #if SBPCD_DIS_IRQ diff -Nru a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c --- a/drivers/cdrom/sjcd.c Sat Jul 19 12:54:26 2003 +++ b/drivers/cdrom/sjcd.c Sat Jul 19 12:54:26 2003 @@ -74,7 +74,7 @@ #include #include #include -#include +#include #include "sjcd.h" static int sjcd_present = 0; diff -Nru a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c --- a/drivers/cdrom/sonycd535.c Sat Jul 19 12:54:24 2003 +++ b/drivers/cdrom/sonycd535.c Sat Jul 19 12:54:24 2003 @@ -134,7 +134,7 @@ #include #define MAJOR_NR CDU535_CDROM_MAJOR -#include +#include #define sony535_cd_base_io sonycd535 /* for compatible parameter passing with "insmod" */ #include "sonycd535.h" diff -Nru a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c --- a/drivers/char/agp/i460-agp.c Sat Jul 19 12:54:25 2003 +++ b/drivers/char/agp/i460-agp.c Sat Jul 19 12:54:25 2003 @@ -608,7 +608,7 @@ .name = "agpgart-intel-i460", .id_table = agp_intel_i460_pci_table, .probe = agp_intel_i460_probe, - .remove = agp_intel_i460_remove, + .remove = __devexit_p(agp_intel_i460_remove), }; static int __init agp_intel_i460_init(void) diff -Nru a/drivers/char/busmouse.c b/drivers/char/busmouse.c --- a/drivers/char/busmouse.c Sat Jul 19 12:54:27 2003 +++ b/drivers/char/busmouse.c Sat Jul 19 12:54:27 2003 @@ -357,25 +357,23 @@ { unsigned int msedev = MINOR_TO_MOUSE(ops->minor); struct busmouse_data *mse; - int ret; + int ret = -EINVAL; if (msedev >= NR_MICE) { printk(KERN_ERR "busmouse: trying to allocate mouse on minor %d\n", ops->minor); - return -EINVAL; + goto out; } + ret = -ENOMEM; mse = kmalloc(sizeof(*mse), GFP_KERNEL); if (!mse) - return -ENOMEM; + goto out; down(&mouse_sem); + ret = -EBUSY; if (busmouse_data[msedev]) - { - up(&mouse_sem); - kfree(mse); - return -EBUSY; - } + goto freemem; memset(mse, 0, sizeof(*mse)); @@ -386,14 +384,22 @@ mse->lock = (spinlock_t)SPIN_LOCK_UNLOCKED; init_waitqueue_head(&mse->wait); - busmouse_data[msedev] = mse; ret = misc_register(&mse->miscdev); - if (!ret) - ret = msedev; + + if (ret < 0) + goto freemem; + + busmouse_data[msedev] = mse; + ret = msedev; +out: up(&mouse_sem); - return ret; + + +freemem: + kfree(mse); + goto out; } /** diff -Nru a/drivers/char/ftape/lowlevel/fdc-io.c b/drivers/char/ftape/lowlevel/fdc-io.c --- a/drivers/char/ftape/lowlevel/fdc-io.c Sat Jul 19 12:54:23 2003 +++ b/drivers/char/ftape/lowlevel/fdc-io.c Sat Jul 19 12:54:23 2003 @@ -66,6 +66,7 @@ /* Local vars. */ +static spinlock_t fdc_io_lock; static unsigned int fdc_calibr_count; static unsigned int fdc_calibr_time; static int fdc_status; @@ -89,14 +90,13 @@ { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&fdc_io_lock, flags); if (count == 0) { ft_expected_stray_interrupts = 0; } else { ft_expected_stray_interrupts += count; } - restore_flags(flags); + spin_unlock_irqrestore(&fdc_io_lock, flags); } /* Wait during a timeout period for a given FDC status. @@ -194,8 +194,7 @@ TRACE_FUN(ft_t_any); fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */ - save_flags(flags); - cli(); + spin_lock_irqsave(&fdc_io_lock, flags); if (!in_interrupt()) /* Yes, I know, too much comments inside this function * ... @@ -242,12 +241,11 @@ } fdc_usec_wait(FT_RQM_DELAY); /* wait for valid RQM status */ - save_flags(flags); - cli(); + spin_lock_irqsave(&fdc_io_lock, flags); } fdc_status = inb(fdc.msr); if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_IN_READY) { - restore_flags(flags); + spin_unlock_irqrestore(&fdc_io_lock, flags); TRACE_ABORT(-EBUSY, ft_t_err, "fdc not ready"); } fdc_mode = *cmd_data; /* used by isr */ @@ -289,7 +287,7 @@ last_time = ftape_timestamp(); } #endif - restore_flags(flags); + spin_unlock_irqrestore(&fdc_io_lock, flags); TRACE_EXIT result; } @@ -305,15 +303,14 @@ int retry = 0; TRACE_FUN(ft_t_any); - save_flags(flags); - cli(); + spin_lock_irqsave(&fdc_io_lock, flags); fdc_status = inb(fdc.msr); if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_OUT_READY) { TRACE(ft_t_err, "fdc not ready"); result = -EBUSY; } else while (count) { if (!(fdc_status & FDC_BUSY)) { - restore_flags(flags); + spin_unlock_irqrestore(&fdc_io_lock, flags); TRACE_ABORT(-EIO, ft_t_err, "premature end of result phase"); } result = fdc_read(res_data); @@ -336,7 +333,7 @@ ++res_data; } } - restore_flags(flags); + spin_unlock_irqrestore(&fdc_io_lock, flags); fdc_usec_wait(FT_RQM_DELAY); /* allow FDC to negate BSY */ TRACE_EXIT result; } @@ -609,8 +606,7 @@ unsigned long flags; TRACE_FUN(ft_t_any); - save_flags(flags); - cli(); + spin_lock_irqsave(&fdc_io_lock, flags); fdc_dor_reset(1); /* keep unit selected */ @@ -629,7 +625,7 @@ */ fdc_update_dsr(); /* restore data rate and precomp */ - restore_flags(flags); + spin_unlock_irqrestore(&fdc_io_lock, flags); /* * Wait for first polling cycle to complete @@ -928,8 +924,7 @@ */ TRACE(ft_t_fdc_dma, "phys. addr. = %lx", virt_to_bus((void*) buff->ptr)); - save_flags(flags); - cli(); /* could be called from ISR ! */ + spin_lock_irqsave(&fdc_io_lock, flags); fdc_setup_dma(DMA_MODE_WRITE, buff->ptr, FT_SECTORS_PER_SEGMENT * 4); /* Issue FDC command to start reading/writing. */ @@ -937,7 +932,7 @@ out[4] = buff->gap3; TRACE_CATCH(fdc_setup_error = fdc_command(out, sizeof(out)), restore_flags(flags); fdc_mode = fdc_idle); - restore_flags(flags); + spin_unlock_irqrestore(&fdc_io_lock, flags); TRACE_EXIT 0; } @@ -977,11 +972,10 @@ break; default: TRACE_ABORT(-EIO, - ft_t_bug, "bug: illegal operation parameter"); + ft_t_bug, "bug: invalid operation parameter"); } TRACE(ft_t_fdc_dma, "phys. addr. = %lx",virt_to_bus((void*)buff->ptr)); - save_flags(flags); - cli(); /* could be called from ISR ! */ + spin_lock_irqsave(&fdc_io_lock, flags); if (operation != FDC_VERIFY) { fdc_setup_dma(dma_mode, buff->ptr, FT_SECTOR_SIZE * buff->sector_count); @@ -999,7 +993,7 @@ out[8] = 0xff; /* No limit to transfer size. */ TRACE(ft_t_fdc_dma, "C: 0x%02x, H: 0x%02x, R: 0x%02x, cnt: 0x%02x", out[2], out[3], out[4], out[6] - out[4] + 1); - restore_flags(flags); + spin_unlock_irqrestore(&fdc_io_lock, flags); TRACE_CATCH(fdc_setup_error = fdc_command(out, 9),fdc_mode = fdc_idle); TRACE_EXIT 0; } diff -Nru a/drivers/char/ftape/lowlevel/ftape-calibr.c b/drivers/char/ftape/lowlevel/ftape-calibr.c --- a/drivers/char/ftape/lowlevel/ftape-calibr.c Sat Jul 19 12:54:24 2003 +++ b/drivers/char/ftape/lowlevel/ftape-calibr.c Sat Jul 19 12:54:24 2003 @@ -49,6 +49,8 @@ static unsigned long ps_per_cycle = 0; #endif +static spinlock_t calibr_lock; + /* * Note: On Intel PCs, the clock ticks at 100 Hz (HZ==100) which is * too slow for certain timeouts (and that clock doesn't even tick @@ -75,13 +77,12 @@ __u16 lo; __u16 hi; - save_flags(flags); - cli(); + spin_lock_irqsave(&calibr_lock, flags); outb_p(0x00, 0x43); /* latch the count ASAP */ lo = inb_p(0x40); /* read the latched count */ lo |= inb(0x40) << 8; hi = jiffies; - restore_flags(flags); + spin_unlock_irqrestore(&calibr_lock, flags); return ((hi + 1) * (unsigned int) LATCH) - lo; /* downcounter ! */ #endif } @@ -94,12 +95,11 @@ unsigned int count; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&calibr_lock, flags); outb_p(0x00, 0x43); /* latch the count ASAP */ count = inb_p(0x40); /* read the latched count */ count |= inb(0x40) << 8; - restore_flags(flags); + spin_unlock_irqrestore(&calibr_lock, flags); return (LATCH - count); /* normal: downcounter */ #endif } @@ -150,14 +150,13 @@ int status; TRACE_FUN(ft_t_any); - save_flags(flags); - cli(); + spin_lock_irqsave(&calibr_lock, flags); t0 = short_ftape_timestamp(); for (i = 0; i < 1000; ++i) { status = inb(fdc.msr); } t1 = short_ftape_timestamp(); - restore_flags(flags); + spin_unlock_irqrestore(&calibr_lock, flags); TRACE(ft_t_info, "inb() duration: %d nsec", ftape_timediff(t0, t1)); TRACE_EXIT; } @@ -241,8 +240,7 @@ *calibr_count = *calibr_time = count; /* set TC to 1 */ - save_flags(flags); - cli(); + spin_lock_irqsave(&calibr_lock, flags); fun(0); /* dummy, get code into cache */ t0 = short_ftape_timestamp(); fun(0); /* overhead + one test */ @@ -252,7 +250,7 @@ fun(count); /* overhead + count tests */ t1 = short_ftape_timestamp(); multiple = diff(t0, t1); - restore_flags(flags); + spin_unlock_irqrestore(&calibr_lock, flags); time = ftape_timediff(0, multiple - once); tc = (1000 * time) / (count - 1); TRACE(ft_t_any, "once:%3d us,%6d times:%6d us, TC:%5d ns", diff -Nru a/drivers/char/ftape/lowlevel/ftape-format.c b/drivers/char/ftape/lowlevel/ftape-format.c --- a/drivers/char/ftape/lowlevel/ftape-format.c Sat Jul 19 12:54:25 2003 +++ b/drivers/char/ftape/lowlevel/ftape-format.c Sat Jul 19 12:54:25 2003 @@ -44,6 +44,8 @@ #define FT_FMT_SEGS_PER_BUF (FT_BUFF_SIZE/(4*FT_SECTORS_PER_SEGMENT)) #endif +static spinlock_t ftape_format_lock; + /* * first segment of the new buffer */ @@ -129,9 +131,9 @@ head->status = formatting; TRACE_CATCH(ftape_seek_head_to_track(track),); TRACE_CATCH(ftape_command(QIC_LOGICAL_FORWARD),); - save_flags(flags); cli(); + spin_lock_irqsave(&ftape_format_lock, flags); TRACE_CATCH(fdc_setup_formatting(head), restore_flags(flags)); - restore_flags(flags); + spin_unlock_irqrestore(&ftape_format_lock, flags); TRACE_EXIT 0; } diff -Nru a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c --- a/drivers/char/ftape/zftape/zftape-init.c Sat Jul 19 12:54:24 2003 +++ b/drivers/char/ftape/zftape/zftape-init.c Sat Jul 19 12:54:24 2003 @@ -118,7 +118,7 @@ > FTAPE_SEL_D) { clear_bit(0,&busy_flag); - TRACE_ABORT(-ENXIO, ft_t_err, "failed: illegal unit nr"); + TRACE_ABORT(-ENXIO, ft_t_err, "failed: invalid unit nr"); } orig_sigmask = current->blocked; sigfillset(¤t->blocked); diff -Nru a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c --- a/drivers/char/ip2/i2lib.c Sat Jul 19 12:54:30 2003 +++ b/drivers/char/ip2/i2lib.c Sat Jul 19 12:54:30 2003 @@ -1089,7 +1089,7 @@ // Move the data if ( user ) { - COPY_FROM_USER(rc, (char*)(DATA_OF(pInsert)), pSource, + rc = copy_from_user((char*)(DATA_OF(pInsert)), pSource, amountToMove ); } else { memcpy( (char*)(DATA_OF(pInsert)), pSource, amountToMove ); diff -Nru a/drivers/char/ip2/i2os.h b/drivers/char/ip2/i2os.h --- a/drivers/char/ip2/i2os.h Sat Jul 19 12:54:25 2003 +++ b/drivers/char/ip2/i2os.h Sat Jul 19 12:54:25 2003 @@ -19,8 +19,6 @@ #ifndef I2OS_H /* To prevent multiple includes */ #define I2OS_H 1 -#define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq)) - //------------------------------------------------- // Required Includes //------------------------------------------------- @@ -45,22 +43,6 @@ //-------------------------------------------- // Interrupt control //-------------------------------------------- - -#if LINUX_VERSION_CODE < 0x00020100 -typedef int spinlock_t; -#define spin_lock_init() -#define spin_lock(a) -#define spin_unlock(a) -#define spin_lock_irqsave(a,b) {save_flags((b));cli();} -#define spin_unlock_irqrestore(a,b) {restore_flags((b));} -#define write_lock_irqsave(a,b) spin_lock_irqsave(a,b) -#define write_unlock_irqrestore(a,b) spin_unlock_irqrestore(a,b) -#define read_lock_irqsave(a,b) spin_lock_irqsave(a,b) -#define read_unlock_irqrestore(a,b) spin_unlock_irqrestore(a,b) -#endif - -//#define SAVE_AND_DISABLE_INTS(a,b) spin_lock_irqsave(a,b) -//#define RESTORE_INTS(a,b) spin_unlock_irqrestore(a,b) #define LOCK_INIT(a) rwlock_init(a) diff -Nru a/drivers/char/ip2.c b/drivers/char/ip2.c --- a/drivers/char/ip2.c Sat Jul 19 12:54:25 2003 +++ b/drivers/char/ip2.c Sat Jul 19 12:54:25 2003 @@ -38,16 +38,14 @@ static int poll_only = 0; -# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) - MODULE_AUTHOR("Doug McNash"); - MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); - MODULE_PARM(irq,"1-"__MODULE_STRING(IP2_MAX_BOARDS) "i"); - MODULE_PARM_DESC(irq,"Interrupts for IntelliPort Cards"); - MODULE_PARM(io,"1-"__MODULE_STRING(IP2_MAX_BOARDS) "i"); - MODULE_PARM_DESC(io,"I/O ports for IntelliPort Cards"); - MODULE_PARM(poll_only,"1i"); - MODULE_PARM_DESC(poll_only,"Do not use card interrupts"); -# endif /* LINUX_VERSION */ +MODULE_AUTHOR("Doug McNash"); +MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); +MODULE_PARM(irq,"1-"__MODULE_STRING(IP2_MAX_BOARDS) "i"); +MODULE_PARM_DESC(irq,"Interrupts for IntelliPort Cards"); +MODULE_PARM(io,"1-"__MODULE_STRING(IP2_MAX_BOARDS) "i"); +MODULE_PARM_DESC(io,"I/O ports for IntelliPort Cards"); +MODULE_PARM(poll_only,"1i"); +MODULE_PARM_DESC(poll_only,"Do not use card interrupts"); //====================================================================== diff -Nru a/drivers/char/ip2main.c b/drivers/char/ip2main.c --- a/drivers/char/ip2main.c Sat Jul 19 12:54:30 2003 +++ b/drivers/char/ip2main.c Sat Jul 19 12:54:30 2003 @@ -83,7 +83,6 @@ /* Includes */ /************/ #include -// Uncomment the following if you want it compiled with modversions #include @@ -120,82 +119,11 @@ #include #include -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq)) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) -# include -# include -# include -#else -# include -#endif +#include +#include +#include -// These VERSION switches maybe inexact because I simply don't know -// when the various features appeared in the 2.1.XX kernels. -// They are good enough for 2.0 vs 2.2 and if you are fooling with -// the 2.1.XX stuff then it would be trivial for you to fix. -// Most of these macros were stolen from some other drivers -// so blame them. - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,4) -# define GET_USER(error,value,addr) error = get_user(value,addr) -# define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0 -# define PUT_USER(error,value,addr) error = put_user(value,addr) -# define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0 - -# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,5) -# include -# define pcibios_strerror(status) \ - printk( KERN_ERR "IP2: PCI error 0x%x \n", status ); -# endif - -#else /* 2.0.x and 2.1.x before 2.1.4 */ - -# define proc_register_dynamic(a,b) proc_register(a,b) - -# define GET_USER(error,value,addr) \ - do { \ - error = verify_area (VERIFY_READ, (void *) addr, sizeof (value)); \ - if (error == 0) \ - value = get_user(addr); \ - } while (0) - -# define COPY_FROM_USER(error,dest,src,size) \ - do { \ - error = verify_area (VERIFY_READ, (void *) src, size); \ - if (error == 0) \ - memcpy_fromfs (dest, src, size); \ - } while (0) - -# define PUT_USER(error,value,addr) \ - do { \ - error = verify_area (VERIFY_WRITE, (void *) addr, sizeof (value)); \ - if (error == 0) \ - put_user (value, addr); \ - } while (0) - -# define COPY_TO_USER(error,dest,src,size) \ - do { \ - error = verify_area (VERIFY_WRITE, (void *) dest, size); \ - if (error == 0) \ - memcpy_tofs (dest, src, size); \ - } while (0) - -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) -#define __init -#define __initfunc(a) a -#define __initdata -#define ioremap(a,b) vremap((a),(b)) -#define iounmap(a) vfree((a)) -#define SERIAL_TYPE_NORMAL 1 -#define schedule_timeout(a){current->timeout = jiffies + (a); schedule();} -#define signal_pending(a) ((a)->signal & ~(a)->blocked) -#define in_interrupt() intr_count -#endif +#include #include "./ip2/ip2types.h" #include "./ip2/ip2trace.h" @@ -276,11 +204,7 @@ static int get_serial_info(i2ChanStrPtr, struct serial_struct *); static int set_serial_info(i2ChanStrPtr, struct serial_struct *); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) -static int ip2_ipl_read(struct inode *, char *, size_t , loff_t *); -#else -static ssize_t ip2_ipl_read(struct file *, char *, size_t, loff_t *) ; -#endif +static ssize_t ip2_ipl_read(struct file *, char *, size_t, loff_t *); static ssize_t ip2_ipl_write(struct file *, const char *, size_t, loff_t *); static int ip2_ipl_ioctl(struct inode *, struct file *, UINT, ULONG); static int ip2_ipl_open(struct inode *, struct file *); @@ -354,9 +278,6 @@ #define DBG_CNT(s) #endif -#define MIN(a,b) ( ( (a) < (b) ) ? (a) : (b) ) -#define MAX(a,b) ( ( (a) > (b) ) ? (a) : (b) ) - /********/ /* Code */ /********/ @@ -366,12 +287,9 @@ #include "./ip2/i2lib.c" /* High level interface services */ /* Configuration area for modprobe */ -#ifdef MODULE -# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) - MODULE_AUTHOR("Doug McNash"); - MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); -# endif /* LINUX_VERSION */ -#endif /* MODULE */ + +MODULE_AUTHOR("Doug McNash"); +MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); static int poll_only = 0; @@ -660,53 +578,6 @@ break; case PCI: #ifdef CONFIG_PCI -#if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 */ - if (pcibios_present()) { - unsigned char pci_bus, pci_devfn; - int Pci_index = 0; - status = pcibios_find_device(PCI_VENDOR_ID_COMPUTONE, - PCI_DEVICE_ID_COMPUTONE_IP2EX, Pci_index, - &pci_bus, &pci_devfn); - if (status == 0) { - unsigned int addr; - unsigned char pci_irq; - - ip2config.type[i] = PCI; - /* - * Update Pci_index, so that the next time we go - * searching for a PCI board we find a different - * one. - */ - ++Pci_index; - - pcibios_read_config_dword(pci_bus, pci_devfn, - PCI_BASE_ADDRESS_1, &addr); - if ( addr & 1 ) { - ip2config.addr[i]=(USHORT)(addr&0xfffe); - } else { - printk( KERN_ERR "IP2: PCI I/O address error\n"); - } - pcibios_read_config_byte(pci_bus, pci_devfn, - PCI_INTERRUPT_LINE, &pci_irq); - -// If the PCI BIOS assigned it, lets try and use it. If we -// can't acquire it or it screws up, deal with it then. - -// if (!is_valid_irq(pci_irq)) { -// printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq); -// pci_irq = 0; -// } - ip2config.irq[i] = pci_irq; - } else { // ann error - ip2config.addr[i] = 0; - if (status == PCIBIOS_DEVICE_NOT_FOUND) { - printk( KERN_ERR "IP2: PCI board %d not found\n", i ); - } else { - pcibios_strerror(status); - } - } - } -#else /* LINUX_VERSION_CODE > 2.1.99 */ { struct pci_dev *pci_dev_i = NULL; pci_dev_i = pci_find_device(PCI_VENDOR_ID_COMPUTONE, @@ -739,11 +610,10 @@ if (status == PCIBIOS_DEVICE_NOT_FOUND) { printk( KERN_ERR "IP2: PCI board %d not found\n", i ); } else { - pcibios_strerror(status); + printk( KERN_ERR "IP2: PCI error 0x%x \n", status ); } } } -#endif /* ! 2_0_X */ #else printk( KERN_ERR "IP2: PCI card specified but PCI support not\n"); printk( KERN_ERR "IP2: configured in this kernel.\n"); @@ -2193,7 +2063,7 @@ ip2trace (CHANN, ITRC_IOCTL, 6, 1, rc ); - PUT_USER(rc,C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg); + rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg); if (rc) return rc; break; @@ -2202,7 +2072,7 @@ ip2trace (CHANN, ITRC_IOCTL, 7, 1, rc ); - GET_USER(rc,arg,(unsigned long *) arg); + rc = get_user(arg,(unsigned long *) arg); if (rc) return rc; tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) @@ -2243,7 +2113,7 @@ return -EINTR; } #endif - PUT_USER(rc, + rc = put_user( ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0) | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0) | ((pCh->dataSetIn & I2_DCD) ? TIOCM_CAR : 0) @@ -2333,17 +2203,17 @@ cnow = pCh->icount; restore_flags(flags); p_cuser = (struct serial_icounter_struct *) arg; - PUT_USER(rc,cnow.cts, &p_cuser->cts); - PUT_USER(rc,cnow.dsr, &p_cuser->dsr); - PUT_USER(rc,cnow.rng, &p_cuser->rng); - PUT_USER(rc,cnow.dcd, &p_cuser->dcd); - PUT_USER(rc,cnow.rx, &p_cuser->rx); - PUT_USER(rc,cnow.tx, &p_cuser->tx); - PUT_USER(rc,cnow.frame, &p_cuser->frame); - PUT_USER(rc,cnow.overrun, &p_cuser->overrun); - PUT_USER(rc,cnow.parity, &p_cuser->parity); - PUT_USER(rc,cnow.brk, &p_cuser->brk); - PUT_USER(rc,cnow.buf_overrun, &p_cuser->buf_overrun); + rc = put_user(cnow.cts, &p_cuser->cts); + rc = put_user(cnow.dsr, &p_cuser->dsr); + rc = put_user(cnow.rng, &p_cuser->rng); + rc = put_user(cnow.dcd, &p_cuser->dcd); + rc = put_user(cnow.rx, &p_cuser->rx); + rc = put_user(cnow.tx, &p_cuser->tx); + rc = put_user(cnow.frame, &p_cuser->frame); + rc = put_user(cnow.overrun, &p_cuser->overrun); + rc = put_user(cnow.parity, &p_cuser->parity); + rc = put_user(cnow.brk, &p_cuser->brk); + rc = put_user(cnow.buf_overrun, &p_cuser->buf_overrun); break; /* @@ -2387,7 +2257,7 @@ int rc; unsigned int arg; - GET_USER(rc,arg,value); + rc = get_user(arg,value); if (rc) return rc; switch(cmd) { @@ -2469,7 +2339,7 @@ tmp.close_delay = pCh->ClosingDelay; tmp.closing_wait = pCh->ClosingWaitTime; tmp.custom_divisor = pCh->BaudDivisor; - COPY_TO_USER(rc,retinfo,&tmp,sizeof(*retinfo)); + rc = copy_to_user(retinfo,&tmp,sizeof(*retinfo)); return rc; } @@ -2489,15 +2359,15 @@ { struct serial_struct ns; int old_flags, old_baud_divisor; - int rc = 0; if ( !new_info ) { return -EFAULT; } - COPY_FROM_USER(rc, &ns, new_info, sizeof (ns) ); - if (rc) { - return rc; + + if (copy_from_user(&ns, new_info, sizeof (ns))) { + return -EFAULT; } + /* * We don't allow setserial to change IRQ, board address, type or baud * base. Also line nunber as such is meaningless but we use it for our @@ -2537,7 +2407,7 @@ set_params( pCh, NULL ); } - return rc; + return 0; } /******************************************************************************/ @@ -2860,16 +2730,10 @@ /******************************************************************************/ static -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) -int -ip2_ipl_read(struct inode *pInode, char *pData, size_t count, loff_t *off ) - unsigned int minor = minor( pInode->i_rdev ); -#else ssize_t ip2_ipl_read(struct file *pFile, char *pData, size_t count, loff_t *off ) { unsigned int minor = minor( pFile->f_dentry->d_inode->i_rdev ); -#endif int rc = 0; #ifdef IP2DEBUG_IPL @@ -2904,7 +2768,7 @@ { #ifdef DEBUG_FIFO int rc; - COPY_TO_USER(rc, pData, DBGBuf, count); + rc = copy_to_user(pData, DBGBuf, count); printk(KERN_DEBUG "Last index %d\n", I ); @@ -2925,10 +2789,10 @@ if ( count < (sizeof(int) * 6) ) { return -EIO; } - PUT_USER(rc, tracewrap, pIndex ); - PUT_USER(rc, TRACEMAX, ++pIndex ); - PUT_USER(rc, tracestrip, ++pIndex ); - PUT_USER(rc, tracestuff, ++pIndex ); + rc = put_user(tracewrap, pIndex ); + rc = put_user(TRACEMAX, ++pIndex ); + rc = put_user(tracestrip, ++pIndex ); + rc = put_user(tracestuff, ++pIndex ); pData += sizeof(int) * 6; count -= sizeof(int) * 6; @@ -2941,7 +2805,7 @@ } chunk = TRACEMAX - tracestrip; if ( dumpcount > chunk ) { - COPY_TO_USER(rc, pData, &tracebuf[tracestrip], + rc = copy_to_user(pData, &tracebuf[tracestrip], chunk * sizeof(tracebuf[0]) ); pData += chunk * sizeof(tracebuf[0]); tracestrip = 0; @@ -2949,13 +2813,13 @@ } else { chunk = dumpcount; } - COPY_TO_USER(rc, pData, &tracebuf[tracestrip], + rc = copy_to_user(pData, &tracebuf[tracestrip], chunk * sizeof(tracebuf[0]) ); tracestrip += chunk; tracewrap = 0; - PUT_USER(rc, tracestrip, ++pIndex ); - PUT_USER(rc, tracestuff, ++pIndex ); + rc = put_user(tracestrip, ++pIndex ); + rc = put_user(tracestuff, ++pIndex ); return dumpcount; #else @@ -3019,15 +2883,15 @@ case 13: switch ( cmd ) { case 64: /* Driver - ip2stat */ - PUT_USER(rc, ip2_tty_driver->refcount, pIndex++ ); - PUT_USER(rc, irq_counter, pIndex++ ); - PUT_USER(rc, bh_counter, pIndex++ ); + rc = put_user(ip2_tty_driver->refcount, pIndex++ ); + rc = put_user(irq_counter, pIndex++ ); + rc = put_user(bh_counter, pIndex++ ); break; case 65: /* Board - ip2stat */ if ( pB ) { - COPY_TO_USER(rc, (char*)arg, (char*)pB, sizeof(i2eBordStr) ); - PUT_USER(rc, INB(pB->i2eStatus), + rc = copy_to_user((char*)arg, (char*)pB, sizeof(i2eBordStr) ); + rc = put_user(INB(pB->i2eStatus), (ULONG*)(arg + (ULONG)(&pB->i2eStatus) - (ULONG)pB ) ); } else { rc = -ENODEV; @@ -3039,7 +2903,7 @@ pCh = DevTable[cmd]; if ( pCh ) { - COPY_TO_USER(rc, (char*)arg, (char*)pCh, sizeof(i2ChanStr) ); + rc = copy_to_user((char*)arg, (char*)pCh, sizeof(i2ChanStr) ); } else { rc = -ENODEV; } @@ -3054,60 +2918,60 @@ break; case 3: // Trace device if ( cmd == 1 ) { - PUT_USER(rc, iiSendPendingMail, pIndex++ ); - PUT_USER(rc, i2InitChannels, pIndex++ ); - PUT_USER(rc, i2QueueNeeds, pIndex++ ); - PUT_USER(rc, i2QueueCommands, pIndex++ ); - PUT_USER(rc, i2GetStatus, pIndex++ ); - PUT_USER(rc, i2Input, pIndex++ ); - PUT_USER(rc, i2InputFlush, pIndex++ ); - PUT_USER(rc, i2Output, pIndex++ ); - PUT_USER(rc, i2FlushOutput, pIndex++ ); - PUT_USER(rc, i2DrainWakeup, pIndex++ ); - PUT_USER(rc, i2DrainOutput, pIndex++ ); - PUT_USER(rc, i2OutputFree, pIndex++ ); - PUT_USER(rc, i2StripFifo, pIndex++ ); - PUT_USER(rc, i2StuffFifoBypass, pIndex++ ); - PUT_USER(rc, i2StuffFifoFlow, pIndex++ ); - PUT_USER(rc, i2StuffFifoInline, pIndex++ ); - PUT_USER(rc, i2ServiceBoard, pIndex++ ); - PUT_USER(rc, serviceOutgoingFifo, pIndex++ ); - // PUT_USER(rc, ip2_init, pIndex++ ); - PUT_USER(rc, ip2_init_board, pIndex++ ); - PUT_USER(rc, find_eisa_board, pIndex++ ); - PUT_USER(rc, set_irq, pIndex++ ); - PUT_USER(rc, ip2_interrupt, pIndex++ ); - PUT_USER(rc, ip2_poll, pIndex++ ); - PUT_USER(rc, service_all_boards, pIndex++ ); - PUT_USER(rc, do_input, pIndex++ ); - PUT_USER(rc, do_status, pIndex++ ); + rc = put_user(iiSendPendingMail, pIndex++ ); + rc = put_user(i2InitChannels, pIndex++ ); + rc = put_user(i2QueueNeeds, pIndex++ ); + rc = put_user(i2QueueCommands, pIndex++ ); + rc = put_user(i2GetStatus, pIndex++ ); + rc = put_user(i2Input, pIndex++ ); + rc = put_user(i2InputFlush, pIndex++ ); + rc = put_user(i2Output, pIndex++ ); + rc = put_user(i2FlushOutput, pIndex++ ); + rc = put_user(i2DrainWakeup, pIndex++ ); + rc = put_user(i2DrainOutput, pIndex++ ); + rc = put_user(i2OutputFree, pIndex++ ); + rc = put_user(i2StripFifo, pIndex++ ); + rc = put_user(i2StuffFifoBypass, pIndex++ ); + rc = put_user(i2StuffFifoFlow, pIndex++ ); + rc = put_user(i2StuffFifoInline, pIndex++ ); + rc = put_user(i2ServiceBoard, pIndex++ ); + rc = put_user(serviceOutgoingFifo, pIndex++ ); + // rc = put_user(ip2_init, pIndex++ ); + rc = put_user(ip2_init_board, pIndex++ ); + rc = put_user(find_eisa_board, pIndex++ ); + rc = put_user(set_irq, pIndex++ ); + rc = put_user(ip2_interrupt, pIndex++ ); + rc = put_user(ip2_poll, pIndex++ ); + rc = put_user(service_all_boards, pIndex++ ); + rc = put_user(do_input, pIndex++ ); + rc = put_user(do_status, pIndex++ ); #ifndef IP2DEBUG_OPEN - PUT_USER(rc, 0, pIndex++ ); + rc = put_user(0, pIndex++ ); #else - PUT_USER(rc, open_sanity_check, pIndex++ ); + rc = put_user(open_sanity_check, pIndex++ ); #endif - PUT_USER(rc, ip2_open, pIndex++ ); - PUT_USER(rc, ip2_close, pIndex++ ); - PUT_USER(rc, ip2_hangup, pIndex++ ); - PUT_USER(rc, ip2_write, pIndex++ ); - PUT_USER(rc, ip2_putchar, pIndex++ ); - PUT_USER(rc, ip2_flush_chars, pIndex++ ); - PUT_USER(rc, ip2_write_room, pIndex++ ); - PUT_USER(rc, ip2_chars_in_buf, pIndex++ ); - PUT_USER(rc, ip2_flush_buffer, pIndex++ ); - - //PUT_USER(rc, ip2_wait_until_sent, pIndex++ ); - PUT_USER(rc, 0, pIndex++ ); - - PUT_USER(rc, ip2_throttle, pIndex++ ); - PUT_USER(rc, ip2_unthrottle, pIndex++ ); - PUT_USER(rc, ip2_ioctl, pIndex++ ); - PUT_USER(rc, set_modem_info, pIndex++ ); - PUT_USER(rc, get_serial_info, pIndex++ ); - PUT_USER(rc, set_serial_info, pIndex++ ); - PUT_USER(rc, ip2_set_termios, pIndex++ ); - PUT_USER(rc, ip2_set_line_discipline, pIndex++ ); - PUT_USER(rc, set_params, pIndex++ ); + rc = put_user(ip2_open, pIndex++ ); + rc = put_user(ip2_close, pIndex++ ); + rc = put_user(ip2_hangup, pIndex++ ); + rc = put_user(ip2_write, pIndex++ ); + rc = put_user(ip2_putchar, pIndex++ ); + rc = put_user(ip2_flush_chars, pIndex++ ); + rc = put_user(ip2_write_room, pIndex++ ); + rc = put_user(ip2_chars_in_buf, pIndex++ ); + rc = put_user(ip2_flush_buffer, pIndex++ ); + + //rc = put_user(ip2_wait_until_sent, pIndex++ ); + rc = put_user(0, pIndex++ ); + + rc = put_user(ip2_throttle, pIndex++ ); + rc = put_user(ip2_unthrottle, pIndex++ ); + rc = put_user(ip2_ioctl, pIndex++ ); + rc = put_user(set_modem_info, pIndex++ ); + rc = put_user(get_serial_info, pIndex++ ); + rc = put_user(set_serial_info, pIndex++ ); + rc = put_user(ip2_set_termios, pIndex++ ); + rc = put_user(ip2_set_line_discipline, pIndex++ ); + rc = put_user(set_params, pIndex++ ); } else { rc = -EINVAL; } diff -Nru a/drivers/char/istallion.c b/drivers/char/istallion.c --- a/drivers/char/istallion.c Sat Jul 19 12:54:25 2003 +++ b/drivers/char/istallion.c Sat Jul 19 12:54:25 2003 @@ -650,8 +650,6 @@ */ #ifdef MODULE -int init_module(void); -void cleanup_module(void); static void stli_argbrds(void); static int stli_parsebrd(stlconf_t *confp, char **argp); diff -Nru a/drivers/char/moxa.c b/drivers/char/moxa.c --- a/drivers/char/moxa.c Sat Jul 19 12:54:29 2003 +++ b/drivers/char/moxa.c Sat Jul 19 12:54:29 2003 @@ -216,10 +216,7 @@ static struct semaphore moxaBuffSem; int moxa_init(void); -#ifdef MODULE -int init_module(void); -void cleanup_module(void); -#endif + /* * static functions: */ diff -Nru a/drivers/char/nwbutton.h b/drivers/char/nwbutton.h --- a/drivers/char/nwbutton.h Sat Jul 19 12:54:24 2003 +++ b/drivers/char/nwbutton.h Sat Jul 19 12:54:24 2003 @@ -32,10 +32,6 @@ int button_add_callback (void (*callback) (void), int count); int button_del_callback (void (*callback) (void)); static void button_consume_callbacks (int bpcount); -#ifdef MODULE -int init_module (void); -void cleanup_module (void); -#endif /* MODULE */ #else /* Not compiling the driver itself */ diff -Nru a/drivers/char/pcxx.c b/drivers/char/pcxx.c --- a/drivers/char/pcxx.c Sat Jul 19 12:54:25 2003 +++ b/drivers/char/pcxx.c Sat Jul 19 12:54:25 2003 @@ -209,17 +209,9 @@ #ifdef MODULE -/* - * pcxe_init() is our init_module(): - */ -#define pcxe_init init_module - -void cleanup_module(void); - - /*****************************************************************************/ -void cleanup_module() +static void pcxe_cleanup() { unsigned long flags; @@ -240,6 +232,12 @@ kfree(digi_channels); restore_flags(flags); } + +/* + * pcxe_init() is our init_module(): + */ +module_init(pcxe_init); +module_cleanup(pcxe_cleanup); #endif static inline struct channel *chan(register struct tty_struct *tty) diff -Nru a/drivers/char/stallion.c b/drivers/char/stallion.c --- a/drivers/char/stallion.c Sat Jul 19 12:54:26 2003 +++ b/drivers/char/stallion.c Sat Jul 19 12:54:26 2003 @@ -472,8 +472,6 @@ */ #ifdef MODULE -int init_module(void); -void cleanup_module(void); static void stl_argbrds(void); static int stl_parsebrd(stlconf_t *confp, char **argp); diff -Nru a/drivers/char/watchdog/acquirewdt.c b/drivers/char/watchdog/acquirewdt.c --- a/drivers/char/watchdog/acquirewdt.c Sat Jul 19 12:54:25 2003 +++ b/drivers/char/watchdog/acquirewdt.c Sat Jul 19 12:54:25 2003 @@ -143,7 +143,7 @@ return -EBUSY; } if (nowayout) - MOD_INC_USE_COUNT; + __module_get(THIS_MODULE); /* Activate */ acq_is_open=1; diff -Nru a/drivers/char/watchdog/i810-tco.c b/drivers/char/watchdog/i810-tco.c --- a/drivers/char/watchdog/i810-tco.c Sat Jul 19 12:54:21 2003 +++ b/drivers/char/watchdog/i810-tco.c Sat Jul 19 12:54:21 2003 @@ -25,7 +25,8 @@ * 82801AA & 82801AB chip : document number 290655-003, 290677-004, * 82801BA & 82801BAM chip : document number 290687-002, 298242-005, * 82801CA & 82801CAM chip : document number 290716-001, 290718-001, - * 82801DB & 82801E chip : document number 290744-001, 273599-001 + * 82801DB & 82801E chip : document number 290744-001, 273599-001, + * 82801EB & 82801ER chip : document number 252516-001 * * 20000710 Nils Faerber * Initial Version 0.01 @@ -42,9 +43,11 @@ * clean up ioctls (WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS and * WDIOC_SETOPTIONS), made i810tco_getdevice __init, * removed boot_status, removed tco_timer_read, - * added support for 82801DB and 82801E chipset, general cleanup. + * added support for 82801DB and 82801E chipset, + * added support for 82801EB and 8280ER chipset, + * general cleanup. */ - + #include #include #include @@ -164,7 +167,7 @@ * Reload (trigger) the timer. Lock is needed so we don't reload it during * a reprogramming event */ - + static void tco_timer_reload (void) { spin_lock(&tco_lock); @@ -307,6 +310,7 @@ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, }, { 0, }, }; MODULE_DEVICE_TABLE (pci, i810tco_pci_tbl); diff -Nru a/drivers/char/watchdog/i810-tco.h b/drivers/char/watchdog/i810-tco.h --- a/drivers/char/watchdog/i810-tco.h Sat Jul 19 12:54:26 2003 +++ b/drivers/char/watchdog/i810-tco.h Sat Jul 19 12:54:26 2003 @@ -1,5 +1,5 @@ /* - * i810-tco 0.05: TCO timer driver for i8xx chipsets + * i810-tco: TCO timer driver for i8xx chipsets * * (c) Copyright 2000 kernel concepts , All Rights Reserved. * http://www.kernelconcepts.de @@ -8,7 +8,7 @@ * 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. - * + * * Neither kernel concepts nor Nils Faerber admit liability nor provide * warranty for any of this software. This material is provided * "AS-IS" and at no charge. diff -Nru a/drivers/char/watchdog/ib700wdt.c b/drivers/char/watchdog/ib700wdt.c --- a/drivers/char/watchdog/ib700wdt.c Sat Jul 19 12:54:28 2003 +++ b/drivers/char/watchdog/ib700wdt.c Sat Jul 19 12:54:28 2003 @@ -230,7 +230,7 @@ return -EBUSY; } if (nowayout) - MOD_INC_USE_COUNT; + __module_get(THIS_MODULE); /* Activate */ ibwdt_is_open = 1; diff -Nru a/drivers/char/watchdog/indydog.c b/drivers/char/watchdog/indydog.c --- a/drivers/char/watchdog/indydog.c Sat Jul 19 12:54:29 2003 +++ b/drivers/char/watchdog/indydog.c Sat Jul 19 12:54:29 2003 @@ -54,7 +54,7 @@ return -EBUSY; if (nowayout) - MOD_INC_USE_COUNT; + __module_get(THIS_MODULE); /* * Activate timer diff -Nru a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c --- a/drivers/char/watchdog/machzwd.c Sat Jul 19 12:54:23 2003 +++ b/drivers/char/watchdog/machzwd.c Sat Jul 19 12:54:23 2003 @@ -392,7 +392,7 @@ } if (nowayout) - MOD_INC_USE_COUNT; + __module_get(THIS_MODULE); zf_is_open = 1; diff -Nru a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c --- a/drivers/char/watchdog/pcwd.c Sat Jul 19 12:54:22 2003 +++ b/drivers/char/watchdog/pcwd.c Sat Jul 19 12:54:22 2003 @@ -431,7 +431,7 @@ atomic_inc( &open_allowed ); return -EBUSY; } - MOD_INC_USE_COUNT; + __module_get(THIS_MODULE); /* Enable the port */ if (revision == PCWD_REVISION_C) { spin_lock(&io_lock); diff -Nru a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c --- a/drivers/char/watchdog/sbc60xxwdt.c Sat Jul 19 12:54:26 2003 +++ b/drivers/char/watchdog/sbc60xxwdt.c Sat Jul 19 12:54:26 2003 @@ -207,9 +207,8 @@ /* Just in case we're already talking to someone... */ if(wdt_is_open) return -EBUSY; - if (nowayout) { - MOD_INC_USE_COUNT; - } + if (nowayout) + __module_get(THIS_MODULE); /* Good, fire up the show */ wdt_is_open = 1; wdt_startup(); diff -Nru a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c --- a/drivers/char/watchdog/sc520_wdt.c Sat Jul 19 12:54:25 2003 +++ b/drivers/char/watchdog/sc520_wdt.c Sat Jul 19 12:54:25 2003 @@ -231,7 +231,7 @@ /* Good, fire up the show */ wdt_startup(); if (nowayout) - MOD_INC_USE_COUNT; + __module_get(THIS_MODULE); return 0; default: diff -Nru a/drivers/char/watchdog/shwdt.c b/drivers/char/watchdog/shwdt.c --- a/drivers/char/watchdog/shwdt.c Sat Jul 19 12:54:24 2003 +++ b/drivers/char/watchdog/shwdt.c Sat Jul 19 12:54:24 2003 @@ -3,7 +3,7 @@ * * Watchdog driver for integrated watchdog in the SuperH processors. * - * Copyright (C) 2001, 2002 Paul Mundt + * Copyright (C) 2001, 2002, 2003 Paul Mundt * * 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 @@ -12,6 +12,10 @@ * * 14-Dec-2001 Matt Domsch * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT + * + * 19-Apr-2002 Rob Radez + * Added expect close support, made emulated timeout runtime changeable + * general cleanups, add some ioctls */ #include #include @@ -22,76 +26,50 @@ #include #include #include +#include #include #include - -#if defined(CONFIG_CPU_SH5) - #define WTCNT CPRC_BASE + 0x10 - #define WTCSR CPRC_BASE + 0x18 -#elif defined(CONFIG_CPU_SH4) - #define WTCNT 0xffc00008 - #define WTCSR 0xffc0000c -#elif defined(CONFIG_CPU_SH3) - #define WTCNT 0xffffff84 - #define WTCSR 0xffffff86 -#else - #error "Can't use SuperH watchdog on this platform" -#endif - -#define WTCNT_HIGH 0x5a00 -#define WTCSR_HIGH 0xa500 - -#define WTCSR_TME 0x80 -#define WTCSR_WT 0x40 -#define WTCSR_RSTS 0x20 -#define WTCSR_WOVF 0x10 -#define WTCSR_IOVF 0x08 -#define WTCSR_CKS2 0x04 -#define WTCSR_CKS1 0x02 -#define WTCSR_CKS0 0x01 - -/* - * CKS0-2 supports a number of clock division ratios. At the time the watchdog - * is enabled, it defaults to a 41 usec overflow period .. we overload this to - * something a little more reasonable, and really can't deal with anything - * lower than WTCSR_CKS_1024, else we drop back into the usec range. - * - * Clock Division Ratio Overflow Period - * -------------------------------------------- - * 1/32 (initial value) 41 usecs - * 1/64 82 usecs - * 1/128 164 usecs - * 1/256 328 usecs - * 1/512 656 usecs - * 1/1024 1.31 msecs - * 1/2048 2.62 msecs - * 1/4096 5.25 msecs - */ -#define WTCSR_CKS_32 0x00 -#define WTCSR_CKS_64 0x01 -#define WTCSR_CKS_128 0x02 -#define WTCSR_CKS_256 0x03 -#define WTCSR_CKS_512 0x04 -#define WTCSR_CKS_1024 0x05 -#define WTCSR_CKS_2048 0x06 -#define WTCSR_CKS_4096 0x07 +#include /* - * Default clock division ratio is 5.25 msecs. Overload this at module load - * time. Any value not in the msec range will default to a timeout of one - * jiffy, which exceeds the usec overflow periods. + * Default clock division ratio is 5.25 msecs. For an additional table of + * values, consult the asm-sh/watchdog.h. Overload this at module load + * time. + * + * In order for this to work reliably we need to have HZ set to 1000 or + * something quite higher than 100 (or we need a proper high-res timer + * implementation that will deal with this properly), otherwise the 10ms + * resolution of a jiffy is enough to trigger the overflow. For things like + * the SH-4 and SH-5, this isn't necessarily that big of a problem, though + * for the SH-2 and SH-3, this isn't recommended unless the WDT is absolutely + * necssary. + * + * As a result of this timing problem, the only modes that are particularly + * feasible are the 4096 and the 2048 divisors, which yeild 5.25 and 2.62ms + * overflow periods respectively. + * + * Also, since we can't really expect userspace to be responsive enough + * before the overflow happens, we maintain two seperate timers .. One in + * the kernel for clearing out WOVF every 2ms or so (again, this depends on + * HZ == 1000), and another for monitoring userspace writes to the WDT device. + * + * As such, we currently use a configurable heartbeat interval which defaults + * to 30s. In this case, the userspace daemon is only responsible for periodic + * writes to the device before the next heartbeat is scheduled. If the daemon + * misses its deadline, the kernel timer will allow the WDT to overflow. */ static int clock_division_ratio = WTCSR_CKS_4096; -#define msecs_to_jiffies(msecs) (jiffies + ((HZ * msecs + 999) / 1000)) +#define msecs_to_jiffies(msecs) (jiffies + (HZ * msecs + 9999) / 10000) #define next_ping_period(cks) msecs_to_jiffies(cks - 4) -#define user_ping_period(cks) (next_ping_period(cks) * 10) -static unsigned long sh_is_open = 0; +static unsigned long shwdt_is_open; static struct watchdog_info sh_wdt_info; +static char shwdt_expect_close; static struct timer_list timer; static unsigned long next_heartbeat; +static int heartbeat = 30; #ifdef CONFIG_WATCHDOG_NOWAYOUT static int nowayout = 1; @@ -99,35 +77,6 @@ static int nowayout = 0; #endif -MODULE_PARM(nowayout,"i"); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); - -/** - * sh_wdt_write_cnt - Write to Counter - * - * @val: Value to write - * - * Writes the given value @val to the lower byte of the timer counter. - * The upper byte is set manually on each write. - */ -static void sh_wdt_write_cnt(__u8 val) -{ - ctrl_outw(WTCNT_HIGH | (__u16)val, WTCNT); -} - -/** - * sh_wdt_write_csr - Write to Control/Status Register - * - * @val: Value to write - * - * Writes the given value @val to the lower byte of the control/status - * register. The upper byte is set manually on each write. - */ -static void sh_wdt_write_csr(__u8 val) -{ - ctrl_outw(WTCSR_HIGH | (__u16)val, WTCSR); -} - /** * sh_wdt_start - Start the Watchdog * @@ -135,13 +84,44 @@ */ static void sh_wdt_start(void) { - timer.expires = next_ping_period(clock_division_ratio); - next_heartbeat = user_ping_period(clock_division_ratio); - add_timer(&timer); + __u8 csr; + + mod_timer(&timer, next_ping_period(clock_division_ratio)); + next_heartbeat = jiffies + (heartbeat * HZ); + + csr = sh_wdt_read_csr(); + csr |= WTCSR_WT | clock_division_ratio; + sh_wdt_write_csr(csr); - sh_wdt_write_csr(WTCSR_WT | WTCSR_CKS_4096); sh_wdt_write_cnt(0); - sh_wdt_write_csr((ctrl_inb(WTCSR) | WTCSR_TME)); + + /* + * These processors have a bit of an inconsistent initialization + * process.. starting with SH-3, RSTS was moved to WTCSR, and the + * RSTCSR register was removed. + * + * On the SH-2 however, in addition with bits being in different + * locations, we must deal with RSTCSR outright.. + */ + csr = sh_wdt_read_csr(); + csr |= WTCSR_TME; + csr &= ~WTCSR_RSTS; + sh_wdt_write_csr(csr); + +#ifdef CONFIG_CPU_SH2 + /* + * Whoever came up with the RSTCSR semantics must've been smoking + * some of the good stuff, since in addition to the WTCSR/WTCNT write + * brain-damage, it's managed to fuck things up one step further.. + * + * If we need to clear the WOVF bit, the upper byte has to be 0xa5.. + * but if we want to touch RSTE or RSTS, the upper byte has to be + * 0x5a.. + */ + csr = sh_wdt_read_rstcsr(); + csr &= ~RSTCSR_RSTS; + sh_wdt_write_rstcsr(csr); +#endif } /** @@ -151,9 +131,13 @@ */ static void sh_wdt_stop(void) { + __u8 csr; + del_timer(&timer); - sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_TME)); + csr = sh_wdt_read_csr(); + csr &= ~WTCSR_TME; + sh_wdt_write_csr(csr); } /** @@ -166,11 +150,15 @@ static void sh_wdt_ping(unsigned long data) { if (time_before(jiffies, next_heartbeat)) { - sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_IOVF)); + __u8 csr; + + csr = sh_wdt_read_csr(); + csr &= ~WTCSR_IOVF; + sh_wdt_write_csr(csr); + sh_wdt_write_cnt(0); - timer.expires = next_ping_period(clock_division_ratio); - add_timer(&timer); + mod_timer(&timer, next_ping_period(clock_division_ratio)); } } @@ -184,21 +172,12 @@ */ static int sh_wdt_open(struct inode *inode, struct file *file) { - switch (minor(inode->i_rdev)) { - case WATCHDOG_MINOR: - if (test_and_set_bit(0, &sh_is_open)) - return -EBUSY; + if (test_and_set_bit(0, &shwdt_is_open)) + return -EBUSY; + if (nowayout) + __module_get(THIS_MODULE); - if (nowayout) { - MOD_INC_USE_COUNT; - } - - sh_wdt_start(); - - break; - default: - return -ENODEV; - } + sh_wdt_start(); return 0; } @@ -213,33 +192,20 @@ */ static int sh_wdt_close(struct inode *inode, struct file *file) { - if (minor(inode->i_rdev) == WATCHDOG_MINOR) { - if (!nowayout) { - sh_wdt_stop(); - } - clear_bit(0, &sh_is_open); + if (!nowayout && shwdt_expect_close == 42) { + sh_wdt_stop(); + } else { + printk(KERN_CRIT "shwdt: Unexpected close, not stopping watchdog!\n"); + next_heartbeat = jiffies + (heartbeat * HZ); } + + clear_bit(0, &shwdt_is_open); + shwdt_expect_close = 0; return 0; } /** - * sh_wdt_read - Read from Device - * - * @file: file handle of device - * @buf: buffer to write to - * @count: length of buffer - * @ppos: offset - * - * Unsupported. - */ -static ssize_t sh_wdt_read(struct file *file, char *buf, - size_t count, loff_t *ppos) -{ - return -EINVAL; -} - -/** * sh_wdt_write - Write to Device * * @file: file handle of device @@ -257,11 +223,21 @@ return -ESPIPE; if (count) { - next_heartbeat = user_ping_period(clock_division_ratio); - return 1; + size_t i; + + shwdt_expect_close = 0; + + for (i = 0; i != count; i++) { + char c; + if (get_user(c, buf + i)) + return -EFAULT; + if (c == 'V') + shwdt_expect_close = 42; + } + next_heartbeat = jiffies + (heartbeat * HZ); } - return 0; + return count; } /** @@ -278,6 +254,8 @@ static int sh_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + int new_timeout; + switch (cmd) { case WDIOC_GETSUPPORT: if (copy_to_user((struct watchdog_info *)arg, @@ -288,17 +266,41 @@ break; case WDIOC_GETSTATUS: - if (copy_to_user((int *)arg, - &sh_is_open, - sizeof(int))) { + case WDIOC_GETBOOTSTATUS: + return put_user(0, (int *)arg); + case WDIOC_KEEPALIVE: + next_heartbeat = jiffies + (heartbeat * HZ); + + break; + case WDIOC_SETTIMEOUT: + if (get_user(new_timeout, (int *)arg)) return -EFAULT; + if (new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */ + return -EINVAL; + heartbeat = new_timeout; + next_heartbeat = jiffies + (heartbeat * HZ); + /* Fall */ + case WDIOC_GETTIMEOUT: + return put_user(heartbeat, (int *)arg); + case WDIOC_SETOPTIONS: + { + int options, retval = -EINVAL; + + if (get_user(options, (int *)arg)) + return -EFAULT; + + if (options & WDIOS_DISABLECARD) { + sh_wdt_stop(); + retval = 0; } - break; - case WDIOC_KEEPALIVE: - next_heartbeat = user_ping_period(clock_division_ratio); + if (options & WDIOS_ENABLECARD) { + sh_wdt_start(); + retval = 0; + } - break; + return retval; + } default: return -ENOTTY; } @@ -328,7 +330,7 @@ static struct file_operations sh_wdt_fops = { .owner = THIS_MODULE, - .read = sh_wdt_read, + .llseek = no_llseek, .write = sh_wdt_write, .ioctl = sh_wdt_ioctl, .open = sh_wdt_open, @@ -336,21 +338,20 @@ }; static struct watchdog_info sh_wdt_info = { - .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, - .firmware_version = 1, - .identity = "SH WDT", + .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, + .firmware_version = 1, + .identity = "SH WDT", }; static struct notifier_block sh_wdt_notifier = { - .notifier_call = sh_wdt_notify_sys, - .next = NULL, - .priority = 0 + .notifier_call = sh_wdt_notify_sys, + .priority = 0, }; static struct miscdevice sh_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops &sh_wdt_fops, + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &sh_wdt_fops, }; /** @@ -366,23 +367,8 @@ return -EINVAL; } - if (!request_region(WTCNT, 1, "shwdt")) { - printk(KERN_ERR "shwdt: Can't request WTCNT region\n"); - misc_deregister(&sh_wdt_miscdev); - return -ENXIO; - } - - if (!request_region(WTCSR, 1, "shwdt")) { - printk(KERN_ERR "shwdt: Can't request WTCSR region\n"); - release_region(WTCNT, 1); - misc_deregister(&sh_wdt_miscdev); - return -ENXIO; - } - if (register_reboot_notifier(&sh_wdt_notifier)) { printk(KERN_ERR "shwdt: Can't register reboot notifier\n"); - release_region(WTCSR, 1); - release_region(WTCNT, 1); misc_deregister(&sh_wdt_miscdev); return -EINVAL; } @@ -403,16 +389,16 @@ static void __exit sh_wdt_exit(void) { unregister_reboot_notifier(&sh_wdt_notifier); - release_region(WTCSR, 1); - release_region(WTCNT, 1); misc_deregister(&sh_wdt_miscdev); } -MODULE_AUTHOR("Paul Mundt "); +MODULE_AUTHOR("Paul Mundt "); MODULE_DESCRIPTION("SuperH watchdog driver"); MODULE_LICENSE("GPL"); MODULE_PARM(clock_division_ratio, "i"); MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). Defaults to 0x7."); +MODULE_PARM(nowayout,"i"); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); module_init(sh_wdt_init); module_exit(sh_wdt_exit); diff -Nru a/drivers/char/watchdog/softdog.c b/drivers/char/watchdog/softdog.c --- a/drivers/char/watchdog/softdog.c Sat Jul 19 12:54:24 2003 +++ b/drivers/char/watchdog/softdog.c Sat Jul 19 12:54:24 2003 @@ -104,9 +104,8 @@ { if(test_and_set_bit(0, &timer_alive)) return -EBUSY; - if (nowayout) { - MOD_INC_USE_COUNT; - } + if (nowayout) + __module_get(THIS_MODULE); /* * Activate timer */ diff -Nru a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c --- a/drivers/char/watchdog/wdt977.c Sat Jul 19 12:54:27 2003 +++ b/drivers/char/watchdog/wdt977.c Sat Jul 19 12:54:27 2003 @@ -16,6 +16,8 @@ * 19-Dec-2001 Woody Suwalski: Netwinder fixes, ioctl interface * 06-Jan-2002 Woody Suwalski: For compatibility, convert all timeouts * from minutes to seconds. + * 07-Jul-2003 Daniele Bellucci: Audit return code of misc_register in + * nwwatchdog_init. */ #include @@ -99,7 +101,7 @@ if (nowayout) { - MOD_INC_USE_COUNT; + __module_get(THIS_MODULE); /* do not permit disabling the watchdog by writing 0 to reg. 0xF2 */ if (!timeoutM) timeoutM = DEFAULT_TIMEOUT; @@ -343,12 +345,14 @@ static int __init nwwatchdog_init(void) { + int retval; if (!machine_is_netwinder()) return -ENODEV; - misc_register(&wdt977_miscdev); - printk(KERN_INFO "Wdt977 Watchdog sleeping.\n"); - return 0; + retval = misc_register(&wdt977_miscdev); + if (!retval) + printk(KERN_INFO "Wdt977 Watchdog sleeping.\n"); + return retval; } static void __exit nwwatchdog_exit(void) diff -Nru a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c --- a/drivers/char/watchdog/wdt_pci.c Sat Jul 19 12:54:25 2003 +++ b/drivers/char/watchdog/wdt_pci.c Sat Jul 19 12:54:25 2003 @@ -367,7 +367,7 @@ return -EBUSY; if (nowayout) { - MOD_INC_USE_COUNT; + __module_get(THIS_MODULE); } /* * Activate diff -Nru a/drivers/fc4/fc.c b/drivers/fc4/fc.c --- a/drivers/fc4/fc.c Sat Jul 19 12:54:25 2003 +++ b/drivers/fc4/fc.c Sat Jul 19 12:54:25 2003 @@ -33,7 +33,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/fc4/fcp_impl.h b/drivers/fc4/fcp_impl.h --- a/drivers/fc4/fcp_impl.h Sat Jul 19 12:54:24 2003 +++ b/drivers/fc4/fcp_impl.h Sat Jul 19 12:54:24 2003 @@ -8,7 +8,6 @@ #define _FCP_SCSI_H #include -#include #include "../scsi/scsi.h" #include "fc.h" diff -Nru a/drivers/ide/Kconfig b/drivers/ide/Kconfig --- a/drivers/ide/Kconfig Sat Jul 19 12:54:25 2003 +++ b/drivers/ide/Kconfig Sat Jul 19 12:54:25 2003 @@ -521,7 +521,7 @@ If you say Y here, you also need to say Y to "Use DMA by default when available", above. Please read the comments at the top of - . + . If unsure, say N. @@ -608,7 +608,7 @@ depends on BLK_DEV_HPT34X && IDEDMA_PCI_WIP help This is a dangerous thing to attempt currently! Please read the - comments at the top of . If you say Y + comments at the top of . If you say Y here, then say Y to "Use DMA by default when available" as well. If unsure, say N. @@ -670,14 +670,14 @@ This driver adds detection and support for the NS87415 chip (used in SPARC64, among others). - Please read the comments at the top of . + Please read the comments at the top of . config BLK_DEV_OPTI621 tristate "OPTi 82C621 chipset enhanced support (EXPERIMENTAL)" depends on PCI && BLK_DEV_IDEPCI && EXPERIMENTAL help This is a driver for the OPTi 82C621 EIDE controller. - Please read the comments at the top of . + Please read the comments at the top of . config BLK_DEV_PDC202XX_OLD tristate "PROMISE PDC202{46|62|65|67} support" @@ -696,7 +696,7 @@ when the PDC20265 BIOS has been disabled (for faster boot up). Please read the comments at the top of - . + . If unsure, say N. @@ -754,7 +754,7 @@ If you say Y here, you need to say Y to "Use DMA by default when available" as well. - Please read the comments at the top of . + Please read the comments at the top of . config BLK_DEV_SLC90E66 tristate "SLC90E66 chipset support" @@ -770,7 +770,7 @@ available" as well. Please read the comments at the top of - drivers/ide/slc90e66.c. + drivers/ide/pci/slc90e66.c. config BLK_DEV_TRM290 tristate "Tekram TRM290 chipset support" @@ -779,7 +779,7 @@ This driver adds support for bus master DMA transfers using the Tekram TRM290 PCI IDE chip. Volunteers are needed for further tweaking and development. - Please read the comments at the top of . + Please read the comments at the top of . config BLK_DEV_VIA82CXXX tristate "VIA82CXXX chipset support" @@ -1010,7 +1010,7 @@ boot parameter. It enables support for the secondary IDE interface of the ALI M1439/1443/1445/1487/1489 chipsets, and permits faster I/O speeds to be set as well. See the files - and for + and for more info. config BLK_DEV_DTC2278 @@ -1021,7 +1021,7 @@ boot parameter. It enables support for the secondary IDE interface of the DTC-2278 card, and permits faster I/O speeds to be set as well. See the and - files for more info. + files for more info. config BLK_DEV_HT6560B tristate "Holtek HT6560B support" @@ -1031,7 +1031,7 @@ boot parameter. It enables support for the secondary IDE interface of the Holtek card, and permits faster I/O speeds to be set as well. See the and - files for more info. + files for more info. config BLK_DEV_PDC4030 tristate "PROMISE DC4030 support (EXPERIMENTAL)" @@ -1044,7 +1044,7 @@ supported (and probably never will be since I don't think the cards support them). This driver is enabled at runtime using the "ide0=dc4030" or "ide1=dc4030" kernel boot parameter. See the - file for more info. + file for more info. config BLK_DEV_QD65XX tristate "QDI QD65xx support" @@ -1052,7 +1052,7 @@ help This driver is enabled at runtime using the "ide0=qd65xx" kernel boot parameter. It permits faster I/O speeds to be set. See the - and for + and for more info. config BLK_DEV_UMC8672 @@ -1063,7 +1063,7 @@ boot parameter. It enables support for the secondary IDE interface of the UMC-8672, and permits faster I/O speeds to be set as well. See the files and - for more info. + for more info. config BLK_DEV_HD_ONLY bool "Old hard disk (MFM/RLL/IDE) driver" @@ -1132,7 +1132,7 @@ available" as well. Please read the comments at the top of - . + . If unsure, say N. diff -Nru a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c --- a/drivers/ide/ide-dma.c Sat Jul 19 12:54:25 2003 +++ b/drivers/ide/ide-dma.c Sat Jul 19 12:54:25 2003 @@ -442,9 +442,10 @@ * the driver to resolve the problem, if a DMA transfer is still * in progress we continue to wait (arguably we need to add a * secondary 'I don't care what the drive thinks' timeout here) - * Finally if we have an interrupt but for some reason got the - * timeout first we complete the I/O. This can occur if an - * interrupt is lost or due to bugs. + * Finally if we have an interrupt we let it complete the I/O. + * But only one time - we clear expiry and if it's still not + * completed after WAIT_CMD, we error and retry in PIO. + * This can occur if an interrupt is lost or due to hang or bugs. */ static int dma_timer_expiry (ide_drive_t *drive) @@ -461,19 +462,16 @@ HWGROUP(drive)->expiry = NULL; /* one free ride for now */ /* 1 dmaing, 2 error, 4 intr */ - - if (dma_stat & 2) { /* ERROR */ - (void) hwif->ide_dma_end(drive); - return DRIVER(drive)->error(drive, - "dma_timer_expiry", hwif->INB(IDE_STATUS_REG)); - } + if (dma_stat & 2) /* ERROR */ + return -1; + if (dma_stat & 1) /* DMAing */ return WAIT_CMD; if (dma_stat & 4) /* Got an Interrupt */ - HWGROUP(drive)->handler(drive); + return WAIT_CMD; - return 0; + return 0; /* Status is unknown -- reset the bus */ } /** diff -Nru a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c --- a/drivers/ide/ide-io.c Sat Jul 19 12:54:27 2003 +++ b/drivers/ide/ide-io.c Sat Jul 19 12:54:27 2003 @@ -949,14 +949,14 @@ * happens anyway when any interrupt comes in, IDE or otherwise * -- the kernel masks the IRQ while it is being handled. */ - if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq) + if (hwif->irq != masked_irq) disable_irq_nosync(hwif->irq); spin_unlock(&ide_lock); local_irq_enable(); /* allow other IRQs while we start this request */ startstop = start_request(drive, rq); spin_lock_irq(&ide_lock); - if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq) + if (hwif->irq != masked_irq) enable_irq(hwif->irq); if (startstop == ide_released) goto queue_next; @@ -980,21 +980,25 @@ * retry the current request in pio mode instead of risking tossing it * all away */ -void ide_dma_timeout_retry(ide_drive_t *drive) +static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) { ide_hwif_t *hwif = HWIF(drive); struct request *rq; + ide_startstop_t ret = ide_stopped; /* * end current dma transaction */ - (void) hwif->ide_dma_end(drive); - /* - * complain a little, later we might remove some of this verbosity - */ - printk(KERN_WARNING "%s: timeout waiting for DMA\n", drive->name); - (void) hwif->ide_dma_timeout(drive); + if (error < 0) { + printk(KERN_WARNING "%s: DMA timeout error\n", drive->name); + (void)HWIF(drive)->ide_dma_end(drive); + ret = DRIVER(drive)->error(drive, "dma timeout error", + hwif->INB(IDE_STATUS_REG)); + } else { + printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name); + (void) hwif->ide_dma_timeout(drive); + } /* * disable dma for now, but remember that we did so because of @@ -1018,9 +1022,9 @@ rq->hard_cur_sectors = rq->current_nr_sectors; if (rq->bio) rq->buffer = NULL; -} -EXPORT_SYMBOL(ide_dma_timeout_retry); + return ret; +} /** * ide_timer_expiry - handle lack of an IDE interrupt @@ -1041,11 +1045,10 @@ ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data; ide_handler_t *handler; ide_expiry_t *expiry; - unsigned long flags; - unsigned long wait; + unsigned long flags; + unsigned long wait = -1; spin_lock_irqsave(&ide_lock, flags); - del_timer(&hwgroup->timer); if ((handler = hwgroup->handler) == NULL) { /* @@ -1072,7 +1075,7 @@ } if ((expiry = hwgroup->expiry) != NULL) { /* continue */ - if ((wait = expiry(drive)) != 0) { + if ((wait = expiry(drive)) > 0) { /* reset timer */ hwgroup->timer.expires = jiffies + wait; add_timer(&hwgroup->timer); @@ -1107,15 +1110,15 @@ startstop = handler(drive); } else { if (drive->waiting_for_dma) { - startstop = ide_stopped; - ide_dma_timeout_retry(drive); + startstop = ide_dma_timeout_retry(drive, wait); } else - startstop = DRIVER(drive)->error(drive, "irq timeout", hwif->INB(IDE_STATUS_REG)); + startstop = + DRIVER(drive)->error(drive, "irq timeout", hwif->INB(IDE_STATUS_REG)); } set_recovery_timer(hwif); drive->service_time = jiffies - drive->service_start; - enable_irq(hwif->irq); spin_lock_irq(&ide_lock); + enable_irq(hwif->irq); if (startstop == ide_stopped) hwgroup->busy = 0; } diff -Nru a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c --- a/drivers/ide/legacy/hd.c Sat Jul 19 12:54:21 2003 +++ b/drivers/ide/legacy/hd.c Sat Jul 19 12:54:21 2003 @@ -26,7 +26,7 @@ /* Uncomment the following if you want verbose error reports. */ /* #define VERBOSE_ERRORS */ -#include +#include #include #include #include diff -Nru a/drivers/ide/legacy/hd98.c b/drivers/ide/legacy/hd98.c --- a/drivers/ide/legacy/hd98.c Sat Jul 19 12:54:26 2003 +++ b/drivers/ide/legacy/hd98.c Sat Jul 19 12:54:26 2003 @@ -46,8 +46,6 @@ #include #include -#include - #include "io_ports.h" #ifdef __arm__ diff -Nru a/drivers/ide/ppc/mpc8xx.c b/drivers/ide/ppc/mpc8xx.c --- a/drivers/ide/ppc/mpc8xx.c Sat Jul 19 12:54:29 2003 +++ b/drivers/ide/ppc/mpc8xx.c Sat Jul 19 12:54:29 2003 @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c --- a/drivers/ieee1394/amdtp.c Sat Jul 19 12:54:25 2003 +++ b/drivers/ieee1394/amdtp.c Sat Jul 19 12:54:25 2003 @@ -62,6 +62,12 @@ * - Maybe make an ALSA interface, that is, create a file_ops * implementation that recognizes ALSA ioctls and uses defaults for * things that can't be controlled through ALSA (iso channel). + * + * Changes: + * + * - Audit copy_from_user in amdtp_write. + * Daniele Bellucci + * */ #include @@ -1112,7 +1118,8 @@ for (i = 0; i < count; i += length) { p = buffer_put_bytes(s->input, count - i, &length); - copy_from_user(p, buffer + i, length); + if (copy_from_user(p, buffer + i, length)) + return -EFAULT; if (s->input->length < s->input->size) continue; diff -Nru a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c --- a/drivers/ieee1394/sbp2.c Sat Jul 19 12:54:23 2003 +++ b/drivers/ieee1394/sbp2.c Sat Jul 19 12:54:23 2003 @@ -52,7 +52,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c --- a/drivers/input/keyboard/sunkbd.c Sat Jul 19 12:54:21 2003 +++ b/drivers/input/keyboard/sunkbd.c Sat Jul 19 12:54:21 2003 @@ -80,8 +80,8 @@ char name[64]; char phys[32]; char type; - char reset; - char layout; + volatile char reset; + volatile char layout; }; /* diff -Nru a/drivers/md/Kconfig b/drivers/md/Kconfig --- a/drivers/md/Kconfig Sat Jul 19 12:54:23 2003 +++ b/drivers/md/Kconfig Sat Jul 19 12:54:23 2003 @@ -145,5 +145,12 @@ If unsure, say N. +config DM_IOCTL_V4 + bool "ioctl interface version 4" + depends on BLK_DEV_DM + ---help--- + Recent tools use a new version of the ioctl interface, only + select this option if you intend using such tools. + endmenu diff -Nru a/drivers/md/dm-ioctl-v1.c b/drivers/md/dm-ioctl-v1.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/md/dm-ioctl-v1.c Sat Jul 19 12:54:30 2003 @@ -0,0 +1,1160 @@ +/* + * Copyright (C) 2001, 2002 Sistina Software (UK) Limited. + * + * This file is released under the GPL. + */ + +#include "dm.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DM_DRIVER_EMAIL "dm@uk.sistina.com" + +/*----------------------------------------------------------------- + * The ioctl interface needs to be able to look up devices by + * name or uuid. + *---------------------------------------------------------------*/ +struct hash_cell { + struct list_head name_list; + struct list_head uuid_list; + + char *name; + char *uuid; + struct mapped_device *md; +}; + +#define NUM_BUCKETS 64 +#define MASK_BUCKETS (NUM_BUCKETS - 1) +static struct list_head _name_buckets[NUM_BUCKETS]; +static struct list_head _uuid_buckets[NUM_BUCKETS]; + +void dm_hash_remove_all(void); + +/* + * Guards access to all three tables. + */ +static DECLARE_RWSEM(_hash_lock); + +static void init_buckets(struct list_head *buckets) +{ + unsigned int i; + + for (i = 0; i < NUM_BUCKETS; i++) + INIT_LIST_HEAD(buckets + i); +} + +int dm_hash_init(void) +{ + init_buckets(_name_buckets); + init_buckets(_uuid_buckets); + devfs_mk_dir(DM_DIR); + return 0; +} + +void dm_hash_exit(void) +{ + dm_hash_remove_all(); + devfs_remove(DM_DIR); +} + +/*----------------------------------------------------------------- + * Hash function: + * We're not really concerned with the str hash function being + * fast since it's only used by the ioctl interface. + *---------------------------------------------------------------*/ +static unsigned int hash_str(const char *str) +{ + const unsigned int hash_mult = 2654435387U; + unsigned int h = 0; + + while (*str) + h = (h + (unsigned int) *str++) * hash_mult; + + return h & MASK_BUCKETS; +} + +/*----------------------------------------------------------------- + * Code for looking up a device by name + *---------------------------------------------------------------*/ +static struct hash_cell *__get_name_cell(const char *str) +{ + struct list_head *tmp; + struct hash_cell *hc; + unsigned int h = hash_str(str); + + list_for_each (tmp, _name_buckets + h) { + hc = list_entry(tmp, struct hash_cell, name_list); + if (!strcmp(hc->name, str)) + return hc; + } + + return NULL; +} + +static struct hash_cell *__get_uuid_cell(const char *str) +{ + struct list_head *tmp; + struct hash_cell *hc; + unsigned int h = hash_str(str); + + list_for_each (tmp, _uuid_buckets + h) { + hc = list_entry(tmp, struct hash_cell, uuid_list); + if (!strcmp(hc->uuid, str)) + return hc; + } + + return NULL; +} + +/*----------------------------------------------------------------- + * Inserting, removing and renaming a device. + *---------------------------------------------------------------*/ +static inline char *kstrdup(const char *str) +{ + char *r = kmalloc(strlen(str) + 1, GFP_KERNEL); + if (r) + strcpy(r, str); + return r; +} + +static struct hash_cell *alloc_cell(const char *name, const char *uuid, + struct mapped_device *md) +{ + struct hash_cell *hc; + + hc = kmalloc(sizeof(*hc), GFP_KERNEL); + if (!hc) + return NULL; + + hc->name = kstrdup(name); + if (!hc->name) { + kfree(hc); + return NULL; + } + + if (!uuid) + hc->uuid = NULL; + + else { + hc->uuid = kstrdup(uuid); + if (!hc->uuid) { + kfree(hc->name); + kfree(hc); + return NULL; + } + } + + INIT_LIST_HEAD(&hc->name_list); + INIT_LIST_HEAD(&hc->uuid_list); + hc->md = md; + return hc; +} + +static void free_cell(struct hash_cell *hc) +{ + if (hc) { + kfree(hc->name); + kfree(hc->uuid); + kfree(hc); + } +} + +/* + * devfs stuff. + */ +static int register_with_devfs(struct hash_cell *hc) +{ + struct gendisk *disk = dm_disk(hc->md); + + devfs_mk_bdev(MKDEV(disk->major, disk->first_minor), + S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP, + DM_DIR "/%s", hc->name); + return 0; +} + +static int unregister_with_devfs(struct hash_cell *hc) +{ + devfs_remove(DM_DIR"/%s", hc->name); + return 0; +} + +/* + * The kdev_t and uuid of a device can never change once it is + * initially inserted. + */ +int dm_hash_insert(const char *name, const char *uuid, struct mapped_device *md) +{ + struct hash_cell *cell; + + /* + * Allocate the new cells. + */ + cell = alloc_cell(name, uuid, md); + if (!cell) + return -ENOMEM; + + /* + * Insert the cell into all three hash tables. + */ + down_write(&_hash_lock); + if (__get_name_cell(name)) + goto bad; + + list_add(&cell->name_list, _name_buckets + hash_str(name)); + + if (uuid) { + if (__get_uuid_cell(uuid)) { + list_del(&cell->name_list); + goto bad; + } + list_add(&cell->uuid_list, _uuid_buckets + hash_str(uuid)); + } + register_with_devfs(cell); + dm_get(md); + up_write(&_hash_lock); + + return 0; + + bad: + up_write(&_hash_lock); + free_cell(cell); + return -EBUSY; +} + +void __hash_remove(struct hash_cell *hc) +{ + /* remove from the dev hash */ + list_del(&hc->uuid_list); + list_del(&hc->name_list); + unregister_with_devfs(hc); + dm_put(hc->md); + free_cell(hc); +} + +void dm_hash_remove_all(void) +{ + int i; + struct hash_cell *hc; + struct list_head *tmp, *n; + + down_write(&_hash_lock); + for (i = 0; i < NUM_BUCKETS; i++) { + list_for_each_safe (tmp, n, _name_buckets + i) { + hc = list_entry(tmp, struct hash_cell, name_list); + __hash_remove(hc); + } + } + up_write(&_hash_lock); +} + +int dm_hash_rename(const char *old, const char *new) +{ + char *new_name, *old_name; + struct hash_cell *hc; + + /* + * duplicate new. + */ + new_name = kstrdup(new); + if (!new_name) + return -ENOMEM; + + down_write(&_hash_lock); + + /* + * Is new free ? + */ + hc = __get_name_cell(new); + if (hc) { + DMWARN("asked to rename to an already existing name %s -> %s", + old, new); + up_write(&_hash_lock); + kfree(new_name); + return -EBUSY; + } + + /* + * Is there such a device as 'old' ? + */ + hc = __get_name_cell(old); + if (!hc) { + DMWARN("asked to rename a non existent device %s -> %s", + old, new); + up_write(&_hash_lock); + kfree(new_name); + return -ENXIO; + } + + /* + * rename and move the name cell. + */ + unregister_with_devfs(hc); + + list_del(&hc->name_list); + old_name = hc->name; + hc->name = new_name; + list_add(&hc->name_list, _name_buckets + hash_str(new_name)); + + /* rename the device node in devfs */ + register_with_devfs(hc); + + up_write(&_hash_lock); + kfree(old_name); + return 0; +} + + +/*----------------------------------------------------------------- + * Implementation of the ioctl commands + *---------------------------------------------------------------*/ + +/* + * All the ioctl commands get dispatched to functions with this + * prototype. + */ +typedef int (*ioctl_fn)(struct dm_ioctl *param, struct dm_ioctl *user); + +/* + * Check a string doesn't overrun the chunk of + * memory we copied from userland. + */ +static int valid_str(char *str, void *begin, void *end) +{ + while (((void *) str >= begin) && ((void *) str < end)) + if (!*str++) + return 0; + + return -EINVAL; +} + +static int next_target(struct dm_target_spec *last, uint32_t next, + void *begin, void *end, + struct dm_target_spec **spec, char **params) +{ + *spec = (struct dm_target_spec *) + ((unsigned char *) last + next); + *params = (char *) (*spec + 1); + + if (*spec < (last + 1) || ((void *) *spec > end)) + return -EINVAL; + + return valid_str(*params, begin, end); +} + +static int populate_table(struct dm_table *table, struct dm_ioctl *args) +{ + int r, first = 1; + unsigned int i = 0; + struct dm_target_spec *spec; + char *params; + void *begin, *end; + + if (!args->target_count) { + DMWARN("populate_table: no targets specified"); + return -EINVAL; + } + + begin = (void *) args; + end = begin + args->data_size; + + for (i = 0; i < args->target_count; i++) { + + if (first) + r = next_target((struct dm_target_spec *) args, + args->data_start, + begin, end, &spec, ¶ms); + else + r = next_target(spec, spec->next, begin, end, + &spec, ¶ms); + + if (r) { + DMWARN("unable to find target"); + return -EINVAL; + } + + r = dm_table_add_target(table, spec->target_type, + (sector_t) spec->sector_start, + (sector_t) spec->length, + params); + if (r) { + DMWARN("internal error adding target to table"); + return -EINVAL; + } + + first = 0; + } + + return dm_table_complete(table); +} + +/* + * Round up the ptr to the next 'align' boundary. Obviously + * 'align' must be a power of 2. + */ +static inline void *align_ptr(void *ptr, unsigned int align) +{ + align--; + return (void *) (((unsigned long) (ptr + align)) & ~align); +} + +/* + * Copies a dm_ioctl and an optional additional payload to + * userland. + */ +static int results_to_user(struct dm_ioctl *user, struct dm_ioctl *param, + void *data, uint32_t len) +{ + int r; + void *ptr = NULL; + + if (data) { + ptr = align_ptr(user + 1, sizeof(unsigned long)); + param->data_start = ptr - (void *) user; + } + + /* + * The version number has already been filled in, so we + * just copy later fields. + */ + r = copy_to_user(&user->data_size, ¶m->data_size, + sizeof(*param) - sizeof(param->version)); + if (r) + return -EFAULT; + + if (data) { + if (param->data_start + len > param->data_size) + return -ENOSPC; + + if (copy_to_user(ptr, data, len)) + r = -EFAULT; + } + + return r; +} + +/* + * Fills in a dm_ioctl structure, ready for sending back to + * userland. + */ +static int __info(struct mapped_device *md, struct dm_ioctl *param) +{ + struct dm_table *table; + struct block_device *bdev; + struct gendisk *disk = dm_disk(md); + + param->flags = DM_EXISTS_FLAG; + if (dm_suspended(md)) + param->flags |= DM_SUSPEND_FLAG; + + bdev = bdget_disk(disk, 0); + if (!bdev) + return -ENXIO; + + param->dev = bdev->bd_dev; + param->open_count = bdev->bd_openers; + bdput(bdev); + + if (disk->policy) + param->flags |= DM_READONLY_FLAG; + + table = dm_get_table(md); + param->target_count = dm_table_get_num_targets(table); + dm_table_put(table); + + return 0; +} + +/* + * Always use UUID for lookups if it's present, otherwise use name. + */ +static inline struct mapped_device *find_device(struct dm_ioctl *param) +{ + struct hash_cell *hc; + struct mapped_device *md = NULL; + + down_read(&_hash_lock); + hc = *param->uuid ? __get_uuid_cell(param->uuid) : + __get_name_cell(param->name); + if (hc) { + md = hc->md; + + /* + * Sneakily write in both the name and the uuid + * while we have the cell. + */ + strlcpy(param->name, hc->name, sizeof(param->name)); + if (hc->uuid) + strlcpy(param->uuid, hc->uuid, sizeof(param->uuid)); + else + param->uuid[0] = '\0'; + + dm_get(md); + } + up_read(&_hash_lock); + + return md; +} + +#define ALIGNMENT sizeof(int) +static void *_align(void *ptr, unsigned int a) +{ + register unsigned long align = --a; + + return (void *) (((unsigned long) ptr + align) & ~align); +} + +/* + * Copies device info back to user space, used by + * the create and info ioctls. + */ +static int info(struct dm_ioctl *param, struct dm_ioctl *user) +{ + struct mapped_device *md; + + param->flags = 0; + + md = find_device(param); + if (!md) + /* + * Device not found - returns cleared exists flag. + */ + goto out; + + __info(md, param); + dm_put(md); + + out: + return results_to_user(user, param, NULL, 0); +} + +static inline int get_mode(struct dm_ioctl *param) +{ + int mode = FMODE_READ | FMODE_WRITE; + + if (param->flags & DM_READONLY_FLAG) + mode = FMODE_READ; + + return mode; +} + +static int check_name(const char *name) +{ + if (name[0] == '/') { + DMWARN("invalid device name"); + return -EINVAL; + } + + return 0; +} + +static int create(struct dm_ioctl *param, struct dm_ioctl *user) +{ + int r; + struct dm_table *t; + struct mapped_device *md; + + r = check_name(param->name); + if (r) + return r; + + r = dm_table_create(&t, get_mode(param)); + if (r) + return r; + + r = populate_table(t, param); + if (r) { + dm_table_put(t); + return r; + } + + if (param->flags & DM_PERSISTENT_DEV_FLAG) + r = dm_create_with_minor(minor(to_kdev_t(param->dev)), &md); + else + r = dm_create(&md); + + if (r) { + dm_table_put(t); + return r; + } + + /* suspend the device */ + r = dm_suspend(md); + if (r) { + DMWARN("suspend failed"); + dm_table_put(t); + dm_put(md); + return r; + } + /* swap in the table */ + r = dm_swap_table(md, t); + if (r) { + DMWARN("table swap failed"); + dm_table_put(t); + dm_put(md); + return r; + } + + /* resume the device */ + r = dm_resume(md); + if (r) { + DMWARN("resume failed"); + dm_table_put(t); + dm_put(md); + return r; + } + + dm_table_put(t); /* md will have grabbed its own reference */ + + set_disk_ro(dm_disk(md), (param->flags & DM_READONLY_FLAG) ? 1 : 0); + r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md); + dm_put(md); + + return r ? r : info(param, user); +} + +/* + * Build up the status struct for each target + */ +static int __status(struct mapped_device *md, struct dm_ioctl *param, + char *outbuf, size_t *len) +{ + unsigned int i, num_targets; + struct dm_target_spec *spec; + char *outptr; + status_type_t type; + struct dm_table *table = dm_get_table(md); + + if (param->flags & DM_STATUS_TABLE_FLAG) + type = STATUSTYPE_TABLE; + else + type = STATUSTYPE_INFO; + + outptr = outbuf; + + /* Get all the target info */ + num_targets = dm_table_get_num_targets(table); + for (i = 0; i < num_targets; i++) { + struct dm_target *ti = dm_table_get_target(table, i); + + if (outptr - outbuf + + sizeof(struct dm_target_spec) > param->data_size) { + dm_table_put(table); + return -ENOMEM; + } + + spec = (struct dm_target_spec *) outptr; + + spec->status = 0; + spec->sector_start = ti->begin; + spec->length = ti->len; + strlcpy(spec->target_type, ti->type->name, + sizeof(spec->target_type)); + + outptr += sizeof(struct dm_target_spec); + + /* Get the status/table string from the target driver */ + if (ti->type->status) + ti->type->status(ti, type, outptr, + outbuf + param->data_size - outptr); + else + outptr[0] = '\0'; + + outptr += strlen(outptr) + 1; + _align(outptr, ALIGNMENT); + spec->next = outptr - outbuf; + } + + param->target_count = num_targets; + *len = outptr - outbuf; + dm_table_put(table); + + return 0; +} + +/* + * Return the status of a device as a text string for each + * target. + */ +static int get_status(struct dm_ioctl *param, struct dm_ioctl *user) +{ + struct mapped_device *md; + size_t len = 0; + int ret; + char *outbuf = NULL; + + md = find_device(param); + if (!md) + /* + * Device not found - returns cleared exists flag. + */ + goto out; + + /* We haven't a clue how long the resultant data will be so + just allocate as much as userland has allowed us and make sure + we don't overun it */ + outbuf = kmalloc(param->data_size, GFP_KERNEL); + if (!outbuf) + goto out; + /* + * Get the status of all targets + */ + __status(md, param, outbuf, &len); + + /* + * Setup the basic dm_ioctl structure. + */ + __info(md, param); + + out: + if (md) + dm_put(md); + + ret = results_to_user(user, param, outbuf, len); + + if (outbuf) + kfree(outbuf); + + return ret; +} + +/* + * Wait for a device to report an event + */ +static int wait_device_event(struct dm_ioctl *param, struct dm_ioctl *user) +{ + struct mapped_device *md; + DECLARE_WAITQUEUE(wq, current); + + md = find_device(param); + if (!md) + /* + * Device not found - returns cleared exists flag. + */ + goto out; + + /* + * Setup the basic dm_ioctl structure. + */ + __info(md, param); + + /* + * Wait for a notification event + */ + set_current_state(TASK_INTERRUPTIBLE); + if (!dm_add_wait_queue(md, &wq, dm_get_event_nr(md))) { + schedule(); + dm_remove_wait_queue(md, &wq); + } + set_current_state(TASK_RUNNING); + dm_put(md); + + out: + return results_to_user(user, param, NULL, 0); +} + +/* + * Retrieves a list of devices used by a particular dm device. + */ +static int dep(struct dm_ioctl *param, struct dm_ioctl *user) +{ + int r; + unsigned int count; + struct mapped_device *md; + struct list_head *tmp; + size_t len = 0; + struct dm_target_deps *deps = NULL; + struct dm_table *table; + + md = find_device(param); + if (!md) + goto out; + table = dm_get_table(md); + + /* + * Setup the basic dm_ioctl structure. + */ + __info(md, param); + + /* + * Count the devices. + */ + count = 0; + list_for_each(tmp, dm_table_get_devices(table)) + count++; + + /* + * Allocate a kernel space version of the dm_target_status + * struct. + */ + if (array_too_big(sizeof(*deps), sizeof(*deps->dev), count)) { + dm_table_put(table); + dm_put(md); + return -ENOMEM; + } + + len = sizeof(*deps) + (sizeof(*deps->dev) * count); + deps = kmalloc(len, GFP_KERNEL); + if (!deps) { + dm_table_put(table); + dm_put(md); + return -ENOMEM; + } + + /* + * Fill in the devices. + */ + deps->count = count; + count = 0; + list_for_each(tmp, dm_table_get_devices(table)) { + struct dm_dev *dd = list_entry(tmp, struct dm_dev, list); + deps->dev[count++] = dd->bdev->bd_dev; + } + dm_table_put(table); + dm_put(md); + + out: + r = results_to_user(user, param, deps, len); + + kfree(deps); + return r; +} + +static int remove(struct dm_ioctl *param, struct dm_ioctl *user) +{ + struct hash_cell *hc; + + down_write(&_hash_lock); + hc = *param->uuid ? __get_uuid_cell(param->uuid) : + __get_name_cell(param->name); + if (!hc) { + DMWARN("device doesn't appear to be in the dev hash table."); + up_write(&_hash_lock); + return -EINVAL; + } + + /* + * You may ask the interface to drop its reference to an + * in use device. This is no different to unlinking a + * file that someone still has open. The device will not + * actually be destroyed until the last opener closes it. + * The name and uuid of the device (both are interface + * properties) will be available for reuse immediately. + * + * You don't want to drop a _suspended_ device from the + * interface, since that will leave you with no way of + * resuming it. + */ + if (dm_suspended(hc->md)) { + DMWARN("refusing to remove a suspended device."); + up_write(&_hash_lock); + return -EPERM; + } + + __hash_remove(hc); + up_write(&_hash_lock); + return 0; +} + +static int remove_all(struct dm_ioctl *param, struct dm_ioctl *user) +{ + dm_hash_remove_all(); + return 0; +} + +static int suspend(struct dm_ioctl *param, struct dm_ioctl *user) +{ + int r; + struct mapped_device *md; + + md = find_device(param); + if (!md) + return -ENXIO; + + if (param->flags & DM_SUSPEND_FLAG) + r = dm_suspend(md); + else + r = dm_resume(md); + + dm_put(md); + return r; +} + +static int reload(struct dm_ioctl *param, struct dm_ioctl *user) +{ + int r; + struct mapped_device *md; + struct dm_table *t; + + r = dm_table_create(&t, get_mode(param)); + if (r) + return r; + + r = populate_table(t, param); + if (r) { + dm_table_put(t); + return r; + } + + md = find_device(param); + if (!md) { + dm_table_put(t); + return -ENXIO; + } + + r = dm_swap_table(md, t); + if (r) { + dm_put(md); + dm_table_put(t); + return r; + } + dm_table_put(t); /* md will have taken its own reference */ + + set_disk_ro(dm_disk(md), (param->flags & DM_READONLY_FLAG) ? 1 : 0); + dm_put(md); + + r = info(param, user); + return r; +} + +static int rename(struct dm_ioctl *param, struct dm_ioctl *user) +{ + int r; + char *new_name = (char *) param + param->data_start; + + if (valid_str(new_name, (void *) param, + (void *) param + param->data_size)) { + DMWARN("Invalid new logical volume name supplied."); + return -EINVAL; + } + + r = check_name(new_name); + if (r) + return r; + + return dm_hash_rename(param->name, new_name); +} + + +/*----------------------------------------------------------------- + * Implementation of open/close/ioctl on the special char + * device. + *---------------------------------------------------------------*/ +static ioctl_fn lookup_ioctl(unsigned int cmd) +{ + static struct { + int cmd; + ioctl_fn fn; + } _ioctls[] = { + {DM_VERSION_CMD, NULL}, /* version is dealt with elsewhere */ + {DM_REMOVE_ALL_CMD, remove_all}, + {DM_DEV_CREATE_CMD, create}, + {DM_DEV_REMOVE_CMD, remove}, + {DM_DEV_RELOAD_CMD, reload}, + {DM_DEV_RENAME_CMD, rename}, + {DM_DEV_SUSPEND_CMD, suspend}, + {DM_DEV_DEPS_CMD, dep}, + {DM_DEV_STATUS_CMD, info}, + {DM_TARGET_STATUS_CMD, get_status}, + {DM_TARGET_WAIT_CMD, wait_device_event}, + }; + + return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn; +} + +/* + * As well as checking the version compatibility this always + * copies the kernel interface version out. + */ +static int check_version(unsigned int cmd, struct dm_ioctl *user) +{ + uint32_t version[3]; + int r = 0; + + if (copy_from_user(version, user->version, sizeof(version))) + return -EFAULT; + + if ((DM_VERSION_MAJOR != version[0]) || + (DM_VERSION_MINOR < version[1])) { + DMWARN("ioctl interface mismatch: " + "kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)", + DM_VERSION_MAJOR, DM_VERSION_MINOR, + DM_VERSION_PATCHLEVEL, + version[0], version[1], version[2], cmd); + r = -EINVAL; + } + + /* + * Fill in the kernel version. + */ + version[0] = DM_VERSION_MAJOR; + version[1] = DM_VERSION_MINOR; + version[2] = DM_VERSION_PATCHLEVEL; + if (copy_to_user(user->version, version, sizeof(version))) + return -EFAULT; + + return r; +} + +static void free_params(struct dm_ioctl *param) +{ + vfree(param); +} + +static int copy_params(struct dm_ioctl *user, struct dm_ioctl **param) +{ + struct dm_ioctl tmp, *dmi; + + if (copy_from_user(&tmp, user, sizeof(tmp))) + return -EFAULT; + + if (tmp.data_size < sizeof(tmp)) + return -EINVAL; + + dmi = (struct dm_ioctl *) vmalloc(tmp.data_size); + if (!dmi) + return -ENOMEM; + + if (copy_from_user(dmi, user, tmp.data_size)) { + vfree(dmi); + return -EFAULT; + } + + *param = dmi; + return 0; +} + +static int validate_params(uint cmd, struct dm_ioctl *param) +{ + /* Ignores parameters */ + if (cmd == DM_REMOVE_ALL_CMD) + return 0; + + /* Unless creating, either name of uuid but not both */ + if (cmd != DM_DEV_CREATE_CMD) { + if ((!*param->uuid && !*param->name) || + (*param->uuid && *param->name)) { + DMWARN("one of name or uuid must be supplied"); + return -EINVAL; + } + } + + /* Ensure strings are terminated */ + param->name[DM_NAME_LEN - 1] = '\0'; + param->uuid[DM_UUID_LEN - 1] = '\0'; + + return 0; +} + +static int ctl_ioctl(struct inode *inode, struct file *file, + uint command, ulong u) +{ + int r = 0; + unsigned int cmd; + struct dm_ioctl *param; + struct dm_ioctl *user = (struct dm_ioctl *) u; + ioctl_fn fn = NULL; + + /* only root can play with this */ + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (_IOC_TYPE(command) != DM_IOCTL) + return -ENOTTY; + + cmd = _IOC_NR(command); + + /* + * Check the interface version passed in. This also + * writes out the kernels interface version. + */ + r = check_version(cmd, user); + if (r) + return r; + + /* + * Nothing more to do for the version command. + */ + if (cmd == DM_VERSION_CMD) + return 0; + + fn = lookup_ioctl(cmd); + if (!fn) { + DMWARN("dm_ctl_ioctl: unknown command 0x%x", command); + return -ENOTTY; + } + + /* + * Copy the parameters into kernel space. + */ + r = copy_params(user, ¶m); + if (r) + return r; + + r = validate_params(cmd, param); + if (r) { + free_params(param); + return r; + } + + r = fn(param, user); + free_params(param); + return r; +} + +static struct file_operations _ctl_fops = { + .ioctl = ctl_ioctl, + .owner = THIS_MODULE, +}; + +static struct miscdevice _dm_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = DM_NAME, + .devfs_name = "mapper/control", + .fops = &_ctl_fops +}; + +/* + * Create misc character device and link to DM_DIR/control. + */ +int __init dm_interface_init(void) +{ + int r; + + r = dm_hash_init(); + if (r) + return r; + + r = misc_register(&_dm_misc); + if (r) { + DMERR("misc_register failed for control device"); + dm_hash_exit(); + return r; + } + + DMINFO("%d.%d.%d%s initialised: %s", DM_VERSION_MAJOR, + DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL, DM_VERSION_EXTRA, + DM_DRIVER_EMAIL); + return 0; + + if (misc_deregister(&_dm_misc) < 0) + DMERR("misc_deregister failed for control device"); + dm_hash_exit(); + return r; +} + +void dm_interface_exit(void) +{ + if (misc_deregister(&_dm_misc) < 0) + DMERR("misc_deregister failed for control device"); + dm_hash_exit(); +} diff -Nru a/drivers/md/dm-ioctl-v4.c b/drivers/md/dm-ioctl-v4.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/md/dm-ioctl-v4.c Sat Jul 19 12:54:30 2003 @@ -0,0 +1,1252 @@ +/* + * Copyright (C) 2001, 2002 Sistina Software (UK) Limited. + * + * This file is released under the GPL. + */ + +#include "dm.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DM_DRIVER_EMAIL "dm@uk.sistina.com" + +/*----------------------------------------------------------------- + * The ioctl interface needs to be able to look up devices by + * name or uuid. + *---------------------------------------------------------------*/ +struct hash_cell { + struct list_head name_list; + struct list_head uuid_list; + + char *name; + char *uuid; + struct mapped_device *md; + struct dm_table *new_map; +}; + +#define NUM_BUCKETS 64 +#define MASK_BUCKETS (NUM_BUCKETS - 1) +static struct list_head _name_buckets[NUM_BUCKETS]; +static struct list_head _uuid_buckets[NUM_BUCKETS]; + +void dm_hash_remove_all(void); + +/* + * Guards access to both hash tables. + */ +static DECLARE_RWSEM(_hash_lock); + +static void init_buckets(struct list_head *buckets) +{ + unsigned int i; + + for (i = 0; i < NUM_BUCKETS; i++) + INIT_LIST_HEAD(buckets + i); +} + +int dm_hash_init(void) +{ + init_buckets(_name_buckets); + init_buckets(_uuid_buckets); + devfs_mk_dir(DM_DIR); + return 0; +} + +void dm_hash_exit(void) +{ + dm_hash_remove_all(); + devfs_remove(DM_DIR); +} + +/*----------------------------------------------------------------- + * Hash function: + * We're not really concerned with the str hash function being + * fast since it's only used by the ioctl interface. + *---------------------------------------------------------------*/ +static unsigned int hash_str(const char *str) +{ + const unsigned int hash_mult = 2654435387U; + unsigned int h = 0; + + while (*str) + h = (h + (unsigned int) *str++) * hash_mult; + + return h & MASK_BUCKETS; +} + +/*----------------------------------------------------------------- + * Code for looking up a device by name + *---------------------------------------------------------------*/ +static struct hash_cell *__get_name_cell(const char *str) +{ + struct list_head *tmp; + struct hash_cell *hc; + unsigned int h = hash_str(str); + + list_for_each (tmp, _name_buckets + h) { + hc = list_entry(tmp, struct hash_cell, name_list); + if (!strcmp(hc->name, str)) + return hc; + } + + return NULL; +} + +static struct hash_cell *__get_uuid_cell(const char *str) +{ + struct list_head *tmp; + struct hash_cell *hc; + unsigned int h = hash_str(str); + + list_for_each (tmp, _uuid_buckets + h) { + hc = list_entry(tmp, struct hash_cell, uuid_list); + if (!strcmp(hc->uuid, str)) + return hc; + } + + return NULL; +} + +/*----------------------------------------------------------------- + * Inserting, removing and renaming a device. + *---------------------------------------------------------------*/ +static inline char *kstrdup(const char *str) +{ + char *r = kmalloc(strlen(str) + 1, GFP_KERNEL); + if (r) + strcpy(r, str); + return r; +} + +static struct hash_cell *alloc_cell(const char *name, const char *uuid, + struct mapped_device *md) +{ + struct hash_cell *hc; + + hc = kmalloc(sizeof(*hc), GFP_KERNEL); + if (!hc) + return NULL; + + hc->name = kstrdup(name); + if (!hc->name) { + kfree(hc); + return NULL; + } + + if (!uuid) + hc->uuid = NULL; + + else { + hc->uuid = kstrdup(uuid); + if (!hc->uuid) { + kfree(hc->name); + kfree(hc); + return NULL; + } + } + + INIT_LIST_HEAD(&hc->name_list); + INIT_LIST_HEAD(&hc->uuid_list); + hc->md = md; + hc->new_map = NULL; + return hc; +} + +static void free_cell(struct hash_cell *hc) +{ + if (hc) { + kfree(hc->name); + kfree(hc->uuid); + kfree(hc); + } +} + +/* + * devfs stuff. + */ +static int register_with_devfs(struct hash_cell *hc) +{ + struct gendisk *disk = dm_disk(hc->md); + + devfs_mk_bdev(MKDEV(disk->major, disk->first_minor), + S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP, + DM_DIR "/%s", hc->name); + return 0; +} + +static int unregister_with_devfs(struct hash_cell *hc) +{ + devfs_remove(DM_DIR"/%s", hc->name); + return 0; +} + +/* + * The kdev_t and uuid of a device can never change once it is + * initially inserted. + */ +int dm_hash_insert(const char *name, const char *uuid, struct mapped_device *md) +{ + struct hash_cell *cell; + + /* + * Allocate the new cells. + */ + cell = alloc_cell(name, uuid, md); + if (!cell) + return -ENOMEM; + + /* + * Insert the cell into both hash tables. + */ + down_write(&_hash_lock); + if (__get_name_cell(name)) + goto bad; + + list_add(&cell->name_list, _name_buckets + hash_str(name)); + + if (uuid) { + if (__get_uuid_cell(uuid)) { + list_del(&cell->name_list); + goto bad; + } + list_add(&cell->uuid_list, _uuid_buckets + hash_str(uuid)); + } + register_with_devfs(cell); + dm_get(md); + up_write(&_hash_lock); + + return 0; + + bad: + up_write(&_hash_lock); + free_cell(cell); + return -EBUSY; +} + +void __hash_remove(struct hash_cell *hc) +{ + /* remove from the dev hash */ + list_del(&hc->uuid_list); + list_del(&hc->name_list); + unregister_with_devfs(hc); + dm_put(hc->md); + if (hc->new_map) + dm_table_put(hc->new_map); + free_cell(hc); +} + +void dm_hash_remove_all(void) +{ + int i; + struct hash_cell *hc; + struct list_head *tmp, *n; + + down_write(&_hash_lock); + for (i = 0; i < NUM_BUCKETS; i++) { + list_for_each_safe (tmp, n, _name_buckets + i) { + hc = list_entry(tmp, struct hash_cell, name_list); + __hash_remove(hc); + } + } + up_write(&_hash_lock); +} + +int dm_hash_rename(const char *old, const char *new) +{ + char *new_name, *old_name; + struct hash_cell *hc; + + /* + * duplicate new. + */ + new_name = kstrdup(new); + if (!new_name) + return -ENOMEM; + + down_write(&_hash_lock); + + /* + * Is new free ? + */ + hc = __get_name_cell(new); + if (hc) { + DMWARN("asked to rename to an already existing name %s -> %s", + old, new); + up_write(&_hash_lock); + kfree(new_name); + return -EBUSY; + } + + /* + * Is there such a device as 'old' ? + */ + hc = __get_name_cell(old); + if (!hc) { + DMWARN("asked to rename a non existent device %s -> %s", + old, new); + up_write(&_hash_lock); + kfree(new_name); + return -ENXIO; + } + + /* + * rename and move the name cell. + */ + unregister_with_devfs(hc); + + list_del(&hc->name_list); + old_name = hc->name; + hc->name = new_name; + list_add(&hc->name_list, _name_buckets + hash_str(new_name)); + + /* rename the device node in devfs */ + register_with_devfs(hc); + + up_write(&_hash_lock); + kfree(old_name); + return 0; +} + +/*----------------------------------------------------------------- + * Implementation of the ioctl commands + *---------------------------------------------------------------*/ +/* + * All the ioctl commands get dispatched to functions with this + * prototype. + */ +typedef int (*ioctl_fn)(struct dm_ioctl *param, size_t param_size); + +static int remove_all(struct dm_ioctl *param, size_t param_size) +{ + dm_hash_remove_all(); + param->data_size = 0; + return 0; +} + +/* + * Round up the ptr to an 8-byte boundary. + */ +#define ALIGN_MASK 7 +static inline void *align_ptr(void *ptr) +{ + return (void *) (((size_t) (ptr + ALIGN_MASK)) & ~ALIGN_MASK); +} + +/* + * Retrieves the data payload buffer from an already allocated + * struct dm_ioctl. + */ +static void *get_result_buffer(struct dm_ioctl *param, size_t param_size, + size_t *len) +{ + param->data_start = align_ptr(param + 1) - (void *) param; + + if (param->data_start < param_size) + *len = param_size - param->data_start; + else + *len = 0; + + return ((void *) param) + param->data_start; +} + +static int list_devices(struct dm_ioctl *param, size_t param_size) +{ + unsigned int i; + struct hash_cell *hc; + size_t len, needed = 0; + struct gendisk *disk; + struct dm_name_list *nl, *old_nl = NULL; + + down_write(&_hash_lock); + + /* + * Loop through all the devices working out how much + * space we need. + */ + for (i = 0; i < NUM_BUCKETS; i++) { + list_for_each_entry (hc, _name_buckets + i, name_list) { + needed += sizeof(struct dm_name_list); + needed += strlen(hc->name); + needed += ALIGN_MASK; + } + } + + /* + * Grab our output buffer. + */ + nl = get_result_buffer(param, param_size, &len); + if (len < needed) { + param->flags |= DM_BUFFER_FULL_FLAG; + goto out; + } + param->data_size = param->data_start + needed; + + nl->dev = 0; /* Flags no data */ + + /* + * Now loop through filling out the names. + */ + for (i = 0; i < NUM_BUCKETS; i++) { + list_for_each_entry (hc, _name_buckets + i, name_list) { + if (old_nl) + old_nl->next = (uint32_t) ((void *) nl - + (void *) old_nl); + disk = dm_disk(hc->md); + nl->dev = MKDEV(disk->major, disk->first_minor); + nl->next = 0; + strcpy(nl->name, hc->name); + + old_nl = nl; + nl = align_ptr(((void *) ++nl) + strlen(hc->name) + 1); + } + } + + out: + up_write(&_hash_lock); + return 0; +} + +static int check_name(const char *name) +{ + if (strchr(name, '/')) { + DMWARN("invalid device name"); + return -EINVAL; + } + + return 0; +} + +/* + * Fills in a dm_ioctl structure, ready for sending back to + * userland. + */ +static int __dev_status(struct mapped_device *md, struct dm_ioctl *param) +{ + struct gendisk *disk = dm_disk(md); + struct dm_table *table; + struct block_device *bdev; + + param->flags &= ~(DM_SUSPEND_FLAG | DM_READONLY_FLAG | + DM_ACTIVE_PRESENT_FLAG); + + if (dm_suspended(md)) + param->flags |= DM_SUSPEND_FLAG; + + bdev = bdget_disk(disk, 0); + if (!bdev) + return -ENXIO; + + param->dev = MKDEV(disk->major, disk->first_minor); + + /* + * Yes, this will be out of date by the time it gets back + * to userland, but it is still very useful ofr + * debugging. + */ + param->open_count = bdev->bd_openers; + bdput(bdev); + + if (disk->policy) + param->flags |= DM_READONLY_FLAG; + + param->event_nr = dm_get_event_nr(md); + + table = dm_get_table(md); + if (table) { + param->flags |= DM_ACTIVE_PRESENT_FLAG; + param->target_count = dm_table_get_num_targets(table); + dm_table_put(table); + } else + param->target_count = 0; + + return 0; +} + +static int dev_create(struct dm_ioctl *param, size_t param_size) +{ + int r; + struct mapped_device *md; + + r = check_name(param->name); + if (r) + return r; + + if (param->flags & DM_PERSISTENT_DEV_FLAG) + r = dm_create_with_minor(minor(to_kdev_t(param->dev)), &md); + else + r = dm_create(&md); + + if (r) + return r; + + r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md); + if (r) { + dm_put(md); + return r; + } + + param->flags &= ~DM_INACTIVE_PRESENT_FLAG; + + r = __dev_status(md, param); + dm_put(md); + + return r; +} + +/* + * Always use UUID for lookups if it's present, otherwise use name. + */ +static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) +{ + return *param->uuid ? + __get_uuid_cell(param->uuid) : __get_name_cell(param->name); +} + +static inline struct mapped_device *find_device(struct dm_ioctl *param) +{ + struct hash_cell *hc; + struct mapped_device *md = NULL; + + down_read(&_hash_lock); + hc = __find_device_hash_cell(param); + if (hc) { + md = hc->md; + + /* + * Sneakily write in both the name and the uuid + * while we have the cell. + */ + strncpy(param->name, hc->name, sizeof(param->name)); + if (hc->uuid) + strncpy(param->uuid, hc->uuid, sizeof(param->uuid)-1); + else + param->uuid[0] = '\0'; + + if (hc->new_map) + param->flags |= DM_INACTIVE_PRESENT_FLAG; + else + param->flags &= ~DM_INACTIVE_PRESENT_FLAG; + + dm_get(md); + } + up_read(&_hash_lock); + + return md; +} + +static int dev_remove(struct dm_ioctl *param, size_t param_size) +{ + struct hash_cell *hc; + + down_write(&_hash_lock); + hc = __find_device_hash_cell(param); + + if (!hc) { + DMWARN("device doesn't appear to be in the dev hash table."); + up_write(&_hash_lock); + return -ENXIO; + } + + __hash_remove(hc); + up_write(&_hash_lock); + param->data_size = 0; + return 0; +} + +/* + * Check a string doesn't overrun the chunk of + * memory we copied from userland. + */ +static int invalid_str(char *str, void *end) +{ + while ((void *) str < end) + if (!*str++) + return 0; + + return -EINVAL; +} + +static int dev_rename(struct dm_ioctl *param, size_t param_size) +{ + int r; + char *new_name = (char *) param + param->data_start; + + if (new_name < (char *) (param + 1) || + invalid_str(new_name, (void *) param + param_size)) { + DMWARN("Invalid new logical volume name supplied."); + return -EINVAL; + } + + r = check_name(new_name); + if (r) + return r; + + param->data_size = 0; + return dm_hash_rename(param->name, new_name); +} + +static int suspend(struct dm_ioctl *param) +{ + int r = 0; + struct mapped_device *md; + + md = find_device(param); + if (!md) + return -ENXIO; + + if (!dm_suspended(md)) + r = dm_suspend(md); + + if (!r) + r = __dev_status(md, param); + + dm_put(md); + return r; +} + +static int resume(struct dm_ioctl *param) +{ + int r = 0; + struct hash_cell *hc; + struct mapped_device *md; + struct dm_table *new_map; + + down_write(&_hash_lock); + + hc = __find_device_hash_cell(param); + if (!hc) { + DMWARN("device doesn't appear to be in the dev hash table."); + up_write(&_hash_lock); + return -ENXIO; + } + + md = hc->md; + dm_get(md); + + new_map = hc->new_map; + hc->new_map = NULL; + param->flags &= ~DM_INACTIVE_PRESENT_FLAG; + + up_write(&_hash_lock); + + /* Do we need to load a new map ? */ + if (new_map) { + /* Suspend if it isn't already suspended */ + if (!dm_suspended(md)) + dm_suspend(md); + + r = dm_swap_table(md, new_map); + if (r) { + dm_put(md); + dm_table_put(new_map); + return r; + } + + if (dm_table_get_mode(new_map) & FMODE_WRITE) + set_disk_ro(dm_disk(md), 0); + else + set_disk_ro(dm_disk(md), 1); + + dm_table_put(new_map); + } + + if (dm_suspended(md)) + r = dm_resume(md); + + if (!r) + r = __dev_status(md, param); + + dm_put(md); + return r; +} + +/* + * Set or unset the suspension state of a device. + * If the device already is in the requested state we just return its status. + */ +static int dev_suspend(struct dm_ioctl *param, size_t param_size) +{ + if (param->flags & DM_SUSPEND_FLAG) + return suspend(param); + + return resume(param); +} + +/* + * Copies device info back to user space, used by + * the create and info ioctls. + */ +static int dev_status(struct dm_ioctl *param, size_t param_size) +{ + int r; + struct mapped_device *md; + + md = find_device(param); + if (!md) + return -ENXIO; + + r = __dev_status(md, param); + dm_put(md); + return r; +} + +/* + * Wait for a device to report an event + */ +static int dev_wait(struct dm_ioctl *param, size_t param_size) +{ + int r; + struct mapped_device *md; + DECLARE_WAITQUEUE(wq, current); + + md = find_device(param); + if (!md) + return -ENXIO; + + /* + * Wait for a notification event + */ + set_current_state(TASK_INTERRUPTIBLE); + if (!dm_add_wait_queue(md, &wq, param->event_nr)) { + schedule(); + dm_remove_wait_queue(md, &wq); + } + set_current_state(TASK_RUNNING); + + /* + * The userland program is going to want to know what + * changed to trigger the event, so we may as well tell + * him and save an ioctl. + */ + r = __dev_status(md, param); + + dm_put(md); + return r; +} + +static inline int get_mode(struct dm_ioctl *param) +{ + int mode = FMODE_READ | FMODE_WRITE; + + if (param->flags & DM_READONLY_FLAG) + mode = FMODE_READ; + + return mode; +} + +static int next_target(struct dm_target_spec *last, uint32_t next, void *end, + struct dm_target_spec **spec, char **target_params) +{ + *spec = (struct dm_target_spec *) ((unsigned char *) last + next); + *target_params = (char *) (*spec + 1); + + if (*spec < (last + 1)) + return -EINVAL; + + return invalid_str(*target_params, end); +} + +static int populate_table(struct dm_table *table, + struct dm_ioctl *param, size_t param_size) +{ + int r; + unsigned int i = 0; + struct dm_target_spec *spec = (struct dm_target_spec *) param; + uint32_t next = param->data_start; + void *end = (void *) param + param_size; + char *target_params; + + if (!param->target_count) { + DMWARN("populate_table: no targets specified"); + return -EINVAL; + } + + for (i = 0; i < param->target_count; i++) { + + r = next_target(spec, next, end, &spec, &target_params); + if (r) { + DMWARN("unable to find target"); + return r; + } + + r = dm_table_add_target(table, spec->target_type, + (sector_t) spec->sector_start, + (sector_t) spec->length, + target_params); + if (r) { + DMWARN("error adding target to table"); + return r; + } + + next = spec->next; + } + + return dm_table_complete(table); +} + +static int table_load(struct dm_ioctl *param, size_t param_size) +{ + int r; + struct hash_cell *hc; + struct dm_table *t; + + r = dm_table_create(&t, get_mode(param)); + if (r) + return r; + + r = populate_table(t, param, param_size); + if (r) { + dm_table_put(t); + return r; + } + + down_write(&_hash_lock); + hc = __find_device_hash_cell(param); + if (!hc) { + DMWARN("device doesn't appear to be in the dev hash table."); + up_write(&_hash_lock); + return -ENXIO; + } + + hc->new_map = t; + param->flags |= DM_INACTIVE_PRESENT_FLAG; + + r = __dev_status(hc->md, param); + up_write(&_hash_lock); + return r; +} + +static int table_clear(struct dm_ioctl *param, size_t param_size) +{ + int r; + struct hash_cell *hc; + + down_write(&_hash_lock); + + hc = __find_device_hash_cell(param); + if (!hc) { + DMWARN("device doesn't appear to be in the dev hash table."); + up_write(&_hash_lock); + return -ENXIO; + } + + if (hc->new_map) { + dm_table_put(hc->new_map); + hc->new_map = NULL; + } + + param->flags &= ~DM_INACTIVE_PRESENT_FLAG; + + r = __dev_status(hc->md, param); + up_write(&_hash_lock); + return r; +} + +/* + * Retrieves a list of devices used by a particular dm device. + */ +static void retrieve_deps(struct dm_table *table, + struct dm_ioctl *param, size_t param_size) +{ + unsigned int count = 0; + struct list_head *tmp; + size_t len, needed; + struct dm_target_deps *deps; + + deps = get_result_buffer(param, param_size, &len); + + /* + * Count the devices. + */ + list_for_each(tmp, dm_table_get_devices(table)) + count++; + + /* + * Check we have enough space. + */ + needed = sizeof(*deps) + (sizeof(*deps->dev) * count); + if (len < needed) { + param->flags |= DM_BUFFER_FULL_FLAG; + return; + } + + /* + * Fill in the devices. + */ + deps->count = count; + count = 0; + list_for_each(tmp, dm_table_get_devices(table)) { + struct dm_dev *dd = list_entry(tmp, struct dm_dev, list); + deps->dev[count++] = dd->bdev->bd_dev; + } + + param->data_size = param->data_start + needed; +} + +static int table_deps(struct dm_ioctl *param, size_t param_size) +{ + int r = 0; + struct mapped_device *md; + struct dm_table *table; + + md = find_device(param); + if (!md) + return -ENXIO; + + r = __dev_status(md, param); + if (r) + goto out; + + table = dm_get_table(md); + if (table) { + retrieve_deps(table, param, param_size); + dm_table_put(table); + } + + out: + dm_put(md); + return r; +} + +/* + * Build up the status struct for each target + */ +static void retrieve_status(struct dm_table *table, + struct dm_ioctl *param, size_t param_size) +{ + unsigned int i, num_targets; + struct dm_target_spec *spec; + char *outbuf, *outptr; + status_type_t type; + size_t remaining, len, used = 0; + + outptr = outbuf = get_result_buffer(param, param_size, &len); + + if (param->flags & DM_STATUS_TABLE_FLAG) + type = STATUSTYPE_TABLE; + else + type = STATUSTYPE_INFO; + + /* Get all the target info */ + num_targets = dm_table_get_num_targets(table); + for (i = 0; i < num_targets; i++) { + struct dm_target *ti = dm_table_get_target(table, i); + + remaining = len - (outptr - outbuf); + if (remaining < sizeof(struct dm_target_spec)) { + param->flags |= DM_BUFFER_FULL_FLAG; + break; + } + + spec = (struct dm_target_spec *) outptr; + + spec->status = 0; + spec->sector_start = ti->begin; + spec->length = ti->len; + strncpy(spec->target_type, ti->type->name, + sizeof(spec->target_type)); + + outptr += sizeof(struct dm_target_spec); + remaining = len - (outptr - outbuf); + + /* Get the status/table string from the target driver */ + if (ti->type->status) { + if (ti->type->status(ti, type, outptr, remaining)) { + param->flags |= DM_BUFFER_FULL_FLAG; + break; + } + } else + outptr[0] = '\0'; + + outptr += strlen(outptr) + 1; + used = param->data_start + (outptr - outbuf); + + align_ptr(outptr); + spec->next = outptr - outbuf; + } + + if (used) + param->data_size = used; + + param->target_count = num_targets; +} + +/* + * Return the status of a device as a text string for each + * target. + */ +static int table_status(struct dm_ioctl *param, size_t param_size) +{ + int r; + struct mapped_device *md; + struct dm_table *table; + + md = find_device(param); + if (!md) + return -ENXIO; + + r = __dev_status(md, param); + if (r) + goto out; + + table = dm_get_table(md); + if (table) { + retrieve_status(table, param, param_size); + dm_table_put(table); + } + + out: + dm_put(md); + return r; +} + +/*----------------------------------------------------------------- + * Implementation of open/close/ioctl on the special char + * device. + *---------------------------------------------------------------*/ +static ioctl_fn lookup_ioctl(unsigned int cmd) +{ + static struct { + int cmd; + ioctl_fn fn; + } _ioctls[] = { + {DM_VERSION_CMD, NULL}, /* version is dealt with elsewhere */ + {DM_REMOVE_ALL_CMD, remove_all}, + {DM_LIST_DEVICES_CMD, list_devices}, + + {DM_DEV_CREATE_CMD, dev_create}, + {DM_DEV_REMOVE_CMD, dev_remove}, + {DM_DEV_RENAME_CMD, dev_rename}, + {DM_DEV_SUSPEND_CMD, dev_suspend}, + {DM_DEV_STATUS_CMD, dev_status}, + {DM_DEV_WAIT_CMD, dev_wait}, + + {DM_TABLE_LOAD_CMD, table_load}, + {DM_TABLE_CLEAR_CMD, table_clear}, + {DM_TABLE_DEPS_CMD, table_deps}, + {DM_TABLE_STATUS_CMD, table_status} + }; + + return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn; +} + +/* + * As well as checking the version compatibility this always + * copies the kernel interface version out. + */ +static int check_version(unsigned int cmd, struct dm_ioctl *user) +{ + uint32_t version[3]; + int r = 0; + + if (copy_from_user(version, user->version, sizeof(version))) + return -EFAULT; + + if ((DM_VERSION_MAJOR != version[0]) || + (DM_VERSION_MINOR < version[1])) { + DMWARN("ioctl interface mismatch: " + "kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)", + DM_VERSION_MAJOR, DM_VERSION_MINOR, + DM_VERSION_PATCHLEVEL, + version[0], version[1], version[2], cmd); + r = -EINVAL; + } + + /* + * Fill in the kernel version. + */ + version[0] = DM_VERSION_MAJOR; + version[1] = DM_VERSION_MINOR; + version[2] = DM_VERSION_PATCHLEVEL; + if (copy_to_user(user->version, version, sizeof(version))) + return -EFAULT; + + return r; +} + +static void free_params(struct dm_ioctl *param) +{ + vfree(param); +} + +static int copy_params(struct dm_ioctl *user, struct dm_ioctl **param) +{ + struct dm_ioctl tmp, *dmi; + + if (copy_from_user(&tmp, user, sizeof(tmp))) + return -EFAULT; + + if (tmp.data_size < sizeof(tmp)) + return -EINVAL; + + dmi = (struct dm_ioctl *) vmalloc(tmp.data_size); + if (!dmi) + return -ENOMEM; + + if (copy_from_user(dmi, user, tmp.data_size)) { + vfree(dmi); + return -EFAULT; + } + + *param = dmi; + return 0; +} + +static int validate_params(uint cmd, struct dm_ioctl *param) +{ + /* Always clear this flag */ + param->flags &= ~DM_BUFFER_FULL_FLAG; + + /* Ignores parameters */ + if (cmd == DM_REMOVE_ALL_CMD || cmd == DM_LIST_DEVICES_CMD) + return 0; + + /* Unless creating, either name or uuid but not both */ + if (cmd != DM_DEV_CREATE_CMD) { + if ((!*param->uuid && !*param->name) || + (*param->uuid && *param->name)) { + DMWARN("one of name or uuid must be supplied, cmd(%u)", + cmd); + return -EINVAL; + } + } + + /* Ensure strings are terminated */ + param->name[DM_NAME_LEN - 1] = '\0'; + param->uuid[DM_UUID_LEN - 1] = '\0'; + + return 0; +} + +static int ctl_ioctl(struct inode *inode, struct file *file, + uint command, ulong u) +{ + int r = 0; + unsigned int cmd; + struct dm_ioctl *param; + struct dm_ioctl *user = (struct dm_ioctl *) u; + ioctl_fn fn = NULL; + size_t param_size; + + /* only root can play with this */ + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (_IOC_TYPE(command) != DM_IOCTL) + return -ENOTTY; + + cmd = _IOC_NR(command); + + /* + * Check the interface version passed in. This also + * writes out the kernel's interface version. + */ + r = check_version(cmd, user); + if (r) + return r; + + /* + * Nothing more to do for the version command. + */ + if (cmd == DM_VERSION_CMD) + return 0; + + fn = lookup_ioctl(cmd); + if (!fn) { + DMWARN("dm_ctl_ioctl: unknown command 0x%x", command); + return -ENOTTY; + } + + /* + * Trying to avoid low memory issues when a device is + * suspended. + */ + current->flags |= PF_MEMALLOC; + + /* + * Copy the parameters into kernel space. + */ + r = copy_params(user, ¶m); + if (r) { + current->flags &= ~PF_MEMALLOC; + return r; + } + + /* + * FIXME: eventually we will remove the PF_MEMALLOC flag + * here. However the tools still do nasty things like + * 'load' while a device is suspended. + */ + + r = validate_params(cmd, param); + if (r) + goto out; + + param_size = param->data_size; + param->data_size = sizeof(*param); + r = fn(param, param_size); + + /* + * Copy the results back to userland. + */ + if (!r && copy_to_user(user, param, param->data_size)) + r = -EFAULT; + + out: + free_params(param); + current->flags &= ~PF_MEMALLOC; + return r; +} + +static struct file_operations _ctl_fops = { + .ioctl = ctl_ioctl, + .owner = THIS_MODULE, +}; + +static struct miscdevice _dm_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = DM_NAME, + .devfs_name = "mapper/control", + .fops = &_ctl_fops +}; + +/* + * Create misc character device and link to DM_DIR/control. + */ +int __init dm_interface_init(void) +{ + int r; + + r = dm_hash_init(); + if (r) + return r; + + r = misc_register(&_dm_misc); + if (r) { + DMERR("misc_register failed for control device"); + dm_hash_exit(); + return r; + } + + DMINFO("%d.%d.%d%s initialised: %s", DM_VERSION_MAJOR, + DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL, DM_VERSION_EXTRA, + DM_DRIVER_EMAIL); + return 0; +} + +void dm_interface_exit(void) +{ + if (misc_deregister(&_dm_misc) < 0) + DMERR("misc_deregister failed for control device"); + + dm_hash_exit(); +} diff -Nru a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c --- a/drivers/md/dm-ioctl.c Sat Jul 19 12:54:24 2003 +++ b/drivers/md/dm-ioctl.c Sat Jul 19 12:54:24 2003 @@ -1,1134 +1,13 @@ /* - * Copyright (C) 2001, 2002 Sistina Software (UK) Limited. + * Copyright (C) 2003 Sistina Software (UK) Limited. * * This file is released under the GPL. */ -#include "dm.h" - -#include -#include -#include #include -#include -#include -#include -#include -#include - -#include - -#define DM_DRIVER_EMAIL "dm@uk.sistina.com" - -/*----------------------------------------------------------------- - * The ioctl interface needs to be able to look up devices by - * name or uuid. - *---------------------------------------------------------------*/ -struct hash_cell { - struct list_head name_list; - struct list_head uuid_list; - - char *name; - char *uuid; - struct mapped_device *md; -}; - -#define NUM_BUCKETS 64 -#define MASK_BUCKETS (NUM_BUCKETS - 1) -static struct list_head _name_buckets[NUM_BUCKETS]; -static struct list_head _uuid_buckets[NUM_BUCKETS]; - -void dm_hash_remove_all(void); - -/* - * Guards access to all three tables. - */ -static DECLARE_RWSEM(_hash_lock); - -static void init_buckets(struct list_head *buckets) -{ - unsigned int i; - - for (i = 0; i < NUM_BUCKETS; i++) - INIT_LIST_HEAD(buckets + i); -} - -int dm_hash_init(void) -{ - init_buckets(_name_buckets); - init_buckets(_uuid_buckets); - devfs_mk_dir(DM_DIR); - return 0; -} - -void dm_hash_exit(void) -{ - dm_hash_remove_all(); - devfs_remove(DM_DIR); -} - -/*----------------------------------------------------------------- - * Hash function: - * We're not really concerned with the str hash function being - * fast since it's only used by the ioctl interface. - *---------------------------------------------------------------*/ -static unsigned int hash_str(const char *str) -{ - const unsigned int hash_mult = 2654435387U; - unsigned int h = 0; - - while (*str) - h = (h + (unsigned int) *str++) * hash_mult; - - return h & MASK_BUCKETS; -} - -/*----------------------------------------------------------------- - * Code for looking up a device by name - *---------------------------------------------------------------*/ -static struct hash_cell *__get_name_cell(const char *str) -{ - struct list_head *tmp; - struct hash_cell *hc; - unsigned int h = hash_str(str); - - list_for_each (tmp, _name_buckets + h) { - hc = list_entry(tmp, struct hash_cell, name_list); - if (!strcmp(hc->name, str)) - return hc; - } - - return NULL; -} - -static struct hash_cell *__get_uuid_cell(const char *str) -{ - struct list_head *tmp; - struct hash_cell *hc; - unsigned int h = hash_str(str); - - list_for_each (tmp, _uuid_buckets + h) { - hc = list_entry(tmp, struct hash_cell, uuid_list); - if (!strcmp(hc->uuid, str)) - return hc; - } - - return NULL; -} - -/*----------------------------------------------------------------- - * Inserting, removing and renaming a device. - *---------------------------------------------------------------*/ -static inline char *kstrdup(const char *str) -{ - char *r = kmalloc(strlen(str) + 1, GFP_KERNEL); - if (r) - strcpy(r, str); - return r; -} - -static struct hash_cell *alloc_cell(const char *name, const char *uuid, - struct mapped_device *md) -{ - struct hash_cell *hc; - - hc = kmalloc(sizeof(*hc), GFP_KERNEL); - if (!hc) - return NULL; - - hc->name = kstrdup(name); - if (!hc->name) { - kfree(hc); - return NULL; - } - - if (!uuid) - hc->uuid = NULL; - - else { - hc->uuid = kstrdup(uuid); - if (!hc->uuid) { - kfree(hc->name); - kfree(hc); - return NULL; - } - } - - INIT_LIST_HEAD(&hc->name_list); - INIT_LIST_HEAD(&hc->uuid_list); - hc->md = md; - return hc; -} - -static void free_cell(struct hash_cell *hc) -{ - if (hc) { - kfree(hc->name); - kfree(hc->uuid); - kfree(hc); - } -} - -/* - * devfs stuff. - */ -static int register_with_devfs(struct hash_cell *hc) -{ - struct gendisk *disk = dm_disk(hc->md); - - devfs_mk_bdev(MKDEV(disk->major, disk->first_minor), - S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP, - DM_DIR "/%s", hc->name); - return 0; -} - -static int unregister_with_devfs(struct hash_cell *hc) -{ - devfs_remove(DM_DIR"/%s", hc->name); - return 0; -} - -/* - * The kdev_t and uuid of a device can never change once it is - * initially inserted. - */ -int dm_hash_insert(const char *name, const char *uuid, struct mapped_device *md) -{ - struct hash_cell *cell; - - /* - * Allocate the new cells. - */ - cell = alloc_cell(name, uuid, md); - if (!cell) - return -ENOMEM; - - /* - * Insert the cell into all three hash tables. - */ - down_write(&_hash_lock); - if (__get_name_cell(name)) - goto bad; - - list_add(&cell->name_list, _name_buckets + hash_str(name)); - - if (uuid) { - if (__get_uuid_cell(uuid)) { - list_del(&cell->name_list); - goto bad; - } - list_add(&cell->uuid_list, _uuid_buckets + hash_str(uuid)); - } - register_with_devfs(cell); - dm_get(md); - up_write(&_hash_lock); - - return 0; - - bad: - up_write(&_hash_lock); - free_cell(cell); - return -EBUSY; -} - -void __hash_remove(struct hash_cell *hc) -{ - /* remove from the dev hash */ - list_del(&hc->uuid_list); - list_del(&hc->name_list); - unregister_with_devfs(hc); - dm_put(hc->md); - free_cell(hc); -} - -void dm_hash_remove_all(void) -{ - int i; - struct hash_cell *hc; - struct list_head *tmp, *n; - - down_write(&_hash_lock); - for (i = 0; i < NUM_BUCKETS; i++) { - list_for_each_safe (tmp, n, _name_buckets + i) { - hc = list_entry(tmp, struct hash_cell, name_list); - __hash_remove(hc); - } - } - up_write(&_hash_lock); -} - -int dm_hash_rename(const char *old, const char *new) -{ - char *new_name, *old_name; - struct hash_cell *hc; - - /* - * duplicate new. - */ - new_name = kstrdup(new); - if (!new_name) - return -ENOMEM; - - down_write(&_hash_lock); - - /* - * Is new free ? - */ - hc = __get_name_cell(new); - if (hc) { - DMWARN("asked to rename to an already existing name %s -> %s", - old, new); - up_write(&_hash_lock); - kfree(new_name); - return -EBUSY; - } - - /* - * Is there such a device as 'old' ? - */ - hc = __get_name_cell(old); - if (!hc) { - DMWARN("asked to rename a non existent device %s -> %s", - old, new); - up_write(&_hash_lock); - kfree(new_name); - return -ENXIO; - } - - /* - * rename and move the name cell. - */ - unregister_with_devfs(hc); - - list_del(&hc->name_list); - old_name = hc->name; - hc->name = new_name; - list_add(&hc->name_list, _name_buckets + hash_str(new_name)); - - /* rename the device node in devfs */ - register_with_devfs(hc); - - up_write(&_hash_lock); - kfree(old_name); - return 0; -} - - -/*----------------------------------------------------------------- - * Implementation of the ioctl commands - *---------------------------------------------------------------*/ - -/* - * All the ioctl commands get dispatched to functions with this - * prototype. - */ -typedef int (*ioctl_fn)(struct dm_ioctl *param, struct dm_ioctl *user); - -/* - * Check a string doesn't overrun the chunk of - * memory we copied from userland. - */ -static int valid_str(char *str, void *begin, void *end) -{ - while (((void *) str >= begin) && ((void *) str < end)) - if (!*str++) - return 0; - - return -EINVAL; -} - -static int next_target(struct dm_target_spec *last, uint32_t next, - void *begin, void *end, - struct dm_target_spec **spec, char **params) -{ - *spec = (struct dm_target_spec *) - ((unsigned char *) last + next); - *params = (char *) (*spec + 1); - - if (*spec < (last + 1) || ((void *) *spec > end)) - return -EINVAL; - - return valid_str(*params, begin, end); -} - -static int populate_table(struct dm_table *table, struct dm_ioctl *args) -{ - int r, first = 1; - unsigned int i = 0; - struct dm_target_spec *spec; - char *params; - void *begin, *end; - - if (!args->target_count) { - DMWARN("populate_table: no targets specified"); - return -EINVAL; - } - - begin = (void *) args; - end = begin + args->data_size; - - for (i = 0; i < args->target_count; i++) { - - if (first) - r = next_target((struct dm_target_spec *) args, - args->data_start, - begin, end, &spec, ¶ms); - else - r = next_target(spec, spec->next, begin, end, - &spec, ¶ms); - - if (r) { - DMWARN("unable to find target"); - return -EINVAL; - } - - r = dm_table_add_target(table, spec->target_type, - (sector_t) spec->sector_start, - (sector_t) spec->length, - params); - if (r) { - DMWARN("internal error adding target to table"); - return -EINVAL; - } - - first = 0; - } - - return dm_table_complete(table); -} - -/* - * Round up the ptr to the next 'align' boundary. Obviously - * 'align' must be a power of 2. - */ -static inline void *align_ptr(void *ptr, unsigned int align) -{ - align--; - return (void *) (((unsigned long) (ptr + align)) & ~align); -} - -/* - * Copies a dm_ioctl and an optional additional payload to - * userland. - */ -static int results_to_user(struct dm_ioctl *user, struct dm_ioctl *param, - void *data, uint32_t len) -{ - int r; - void *ptr = NULL; - - if (data) { - ptr = align_ptr(user + 1, sizeof(unsigned long)); - param->data_start = ptr - (void *) user; - } - - /* - * The version number has already been filled in, so we - * just copy later fields. - */ - r = copy_to_user(&user->data_size, ¶m->data_size, - sizeof(*param) - sizeof(param->version)); - if (r) - return -EFAULT; - - if (data) { - if (param->data_start + len > param->data_size) - return -ENOSPC; - - if (copy_to_user(ptr, data, len)) - r = -EFAULT; - } - - return r; -} - -/* - * Fills in a dm_ioctl structure, ready for sending back to - * userland. - */ -static int __info(struct mapped_device *md, struct dm_ioctl *param) -{ - struct dm_table *table; - struct block_device *bdev; - struct gendisk *disk = dm_disk(md); - - param->flags = DM_EXISTS_FLAG; - if (dm_suspended(md)) - param->flags |= DM_SUSPEND_FLAG; - - bdev = bdget_disk(disk, 0); - if (!bdev) - return -ENXIO; - - param->dev = bdev->bd_dev; - param->open_count = bdev->bd_openers; - bdput(bdev); - - if (disk->policy) - param->flags |= DM_READONLY_FLAG; - - table = dm_get_table(md); - param->target_count = dm_table_get_num_targets(table); - dm_table_put(table); - - return 0; -} - -/* - * Always use UUID for lookups if it's present, otherwise use name. - */ -static inline struct mapped_device *find_device(struct dm_ioctl *param) -{ - struct hash_cell *hc; - struct mapped_device *md = NULL; - - down_read(&_hash_lock); - hc = *param->uuid ? __get_uuid_cell(param->uuid) : - __get_name_cell(param->name); - if (hc) { - md = hc->md; - - /* - * Sneakily write in both the name and the uuid - * while we have the cell. - */ - strlcpy(param->name, hc->name, sizeof(param->name)); - if (hc->uuid) - strlcpy(param->uuid, hc->uuid, sizeof(param->uuid)); - else - param->uuid[0] = '\0'; - - dm_get(md); - } - up_read(&_hash_lock); - - return md; -} - -#define ALIGNMENT sizeof(int) -static void *_align(void *ptr, unsigned int a) -{ - register unsigned long align = --a; - - return (void *) (((unsigned long) ptr + align) & ~align); -} - -/* - * Copies device info back to user space, used by - * the create and info ioctls. - */ -static int info(struct dm_ioctl *param, struct dm_ioctl *user) -{ - struct mapped_device *md; - - param->flags = 0; - - md = find_device(param); - if (!md) - /* - * Device not found - returns cleared exists flag. - */ - goto out; - - __info(md, param); - dm_put(md); - - out: - return results_to_user(user, param, NULL, 0); -} - -static inline int get_mode(struct dm_ioctl *param) -{ - int mode = FMODE_READ | FMODE_WRITE; - - if (param->flags & DM_READONLY_FLAG) - mode = FMODE_READ; - - return mode; -} - -static int check_name(const char *name) -{ - if (name[0] == '/') { - DMWARN("invalid device name"); - return -EINVAL; - } - - return 0; -} - -static int create(struct dm_ioctl *param, struct dm_ioctl *user) -{ - int r; - struct dm_table *t; - struct mapped_device *md; - - r = check_name(param->name); - if (r) - return r; - - r = dm_table_create(&t, get_mode(param)); - if (r) - return r; - - r = populate_table(t, param); - if (r) { - dm_table_put(t); - return r; - } - - if (param->flags & DM_PERSISTENT_DEV_FLAG) - r = dm_create_with_minor(minor(to_kdev_t(param->dev)), t, &md); - else - r = dm_create(t, &md); - - if (r) { - dm_table_put(t); - return r; - } - dm_table_put(t); /* md will have grabbed its own reference */ - - set_disk_ro(dm_disk(md), (param->flags & DM_READONLY_FLAG) ? 1 : 0); - r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md); - dm_put(md); - - return r ? r : info(param, user); -} - -/* - * Build up the status struct for each target - */ -static int __status(struct mapped_device *md, struct dm_ioctl *param, - char *outbuf, size_t *len) -{ - unsigned int i, num_targets; - struct dm_target_spec *spec; - char *outptr; - status_type_t type; - struct dm_table *table = dm_get_table(md); - - if (param->flags & DM_STATUS_TABLE_FLAG) - type = STATUSTYPE_TABLE; - else - type = STATUSTYPE_INFO; - - outptr = outbuf; - - /* Get all the target info */ - num_targets = dm_table_get_num_targets(table); - for (i = 0; i < num_targets; i++) { - struct dm_target *ti = dm_table_get_target(table, i); - - if (outptr - outbuf + - sizeof(struct dm_target_spec) > param->data_size) { - dm_table_put(table); - return -ENOMEM; - } - - spec = (struct dm_target_spec *) outptr; - - spec->status = 0; - spec->sector_start = ti->begin; - spec->length = ti->len; - strlcpy(spec->target_type, ti->type->name, - sizeof(spec->target_type)); - - outptr += sizeof(struct dm_target_spec); - - /* Get the status/table string from the target driver */ - if (ti->type->status) - ti->type->status(ti, type, outptr, - outbuf + param->data_size - outptr); - else - outptr[0] = '\0'; - - outptr += strlen(outptr) + 1; - _align(outptr, ALIGNMENT); - spec->next = outptr - outbuf; - } - - param->target_count = num_targets; - *len = outptr - outbuf; - dm_table_put(table); - - return 0; -} - -/* - * Return the status of a device as a text string for each - * target. - */ -static int get_status(struct dm_ioctl *param, struct dm_ioctl *user) -{ - struct mapped_device *md; - size_t len = 0; - int ret; - char *outbuf = NULL; - - md = find_device(param); - if (!md) - /* - * Device not found - returns cleared exists flag. - */ - goto out; - - /* We haven't a clue how long the resultant data will be so - just allocate as much as userland has allowed us and make sure - we don't overun it */ - outbuf = kmalloc(param->data_size, GFP_KERNEL); - if (!outbuf) - goto out; - /* - * Get the status of all targets - */ - __status(md, param, outbuf, &len); - - /* - * Setup the basic dm_ioctl structure. - */ - __info(md, param); - - out: - if (md) - dm_put(md); - - ret = results_to_user(user, param, outbuf, len); - - if (outbuf) - kfree(outbuf); - - return ret; -} - -/* - * Wait for a device to report an event - */ -static int wait_device_event(struct dm_ioctl *param, struct dm_ioctl *user) -{ - struct mapped_device *md; - struct dm_table *table; - DECLARE_WAITQUEUE(wq, current); - - md = find_device(param); - if (!md) - /* - * Device not found - returns cleared exists flag. - */ - goto out; - - /* - * Setup the basic dm_ioctl structure. - */ - __info(md, param); - - /* - * Wait for a notification event - */ - set_current_state(TASK_INTERRUPTIBLE); - table = dm_get_table(md); - dm_table_add_wait_queue(table, &wq); - dm_table_put(table); - dm_put(md); - - schedule(); - - out: - return results_to_user(user, param, NULL, 0); -} - -/* - * Retrieves a list of devices used by a particular dm device. - */ -static int dep(struct dm_ioctl *param, struct dm_ioctl *user) -{ - int r; - unsigned int count; - struct mapped_device *md; - struct list_head *tmp; - size_t len = 0; - struct dm_target_deps *deps = NULL; - struct dm_table *table; - - md = find_device(param); - if (!md) - goto out; - table = dm_get_table(md); - - /* - * Setup the basic dm_ioctl structure. - */ - __info(md, param); - - /* - * Count the devices. - */ - count = 0; - list_for_each(tmp, dm_table_get_devices(table)) - count++; - - /* - * Allocate a kernel space version of the dm_target_status - * struct. - */ - if (array_too_big(sizeof(*deps), sizeof(*deps->dev), count)) { - dm_table_put(table); - dm_put(md); - return -ENOMEM; - } - - len = sizeof(*deps) + (sizeof(*deps->dev) * count); - deps = kmalloc(len, GFP_KERNEL); - if (!deps) { - dm_table_put(table); - dm_put(md); - return -ENOMEM; - } - - /* - * Fill in the devices. - */ - deps->count = count; - count = 0; - list_for_each(tmp, dm_table_get_devices(table)) { - struct dm_dev *dd = list_entry(tmp, struct dm_dev, list); - deps->dev[count++] = dd->bdev->bd_dev; - } - dm_table_put(table); - dm_put(md); - - out: - r = results_to_user(user, param, deps, len); - - kfree(deps); - return r; -} - -static int remove(struct dm_ioctl *param, struct dm_ioctl *user) -{ - struct hash_cell *hc; - - down_write(&_hash_lock); - hc = *param->uuid ? __get_uuid_cell(param->uuid) : - __get_name_cell(param->name); - if (!hc) { - DMWARN("device doesn't appear to be in the dev hash table."); - up_write(&_hash_lock); - return -EINVAL; - } - - /* - * You may ask the interface to drop its reference to an - * in use device. This is no different to unlinking a - * file that someone still has open. The device will not - * actually be destroyed until the last opener closes it. - * The name and uuid of the device (both are interface - * properties) will be available for reuse immediately. - * - * You don't want to drop a _suspended_ device from the - * interface, since that will leave you with no way of - * resuming it. - */ - if (dm_suspended(hc->md)) { - DMWARN("refusing to remove a suspended device."); - up_write(&_hash_lock); - return -EPERM; - } - - __hash_remove(hc); - up_write(&_hash_lock); - return 0; -} - -static int remove_all(struct dm_ioctl *param, struct dm_ioctl *user) -{ - dm_hash_remove_all(); - return 0; -} - -static int suspend(struct dm_ioctl *param, struct dm_ioctl *user) -{ - int r; - struct mapped_device *md; - - md = find_device(param); - if (!md) - return -ENXIO; - - if (param->flags & DM_SUSPEND_FLAG) - r = dm_suspend(md); - else - r = dm_resume(md); - - dm_put(md); - return r; -} - -static int reload(struct dm_ioctl *param, struct dm_ioctl *user) -{ - int r; - struct mapped_device *md; - struct dm_table *t; - - r = dm_table_create(&t, get_mode(param)); - if (r) - return r; - - r = populate_table(t, param); - if (r) { - dm_table_put(t); - return r; - } - - md = find_device(param); - if (!md) { - dm_table_put(t); - return -ENXIO; - } - - r = dm_swap_table(md, t); - if (r) { - dm_put(md); - dm_table_put(t); - return r; - } - dm_table_put(t); /* md will have taken its own reference */ - - set_disk_ro(dm_disk(md), (param->flags & DM_READONLY_FLAG) ? 1 : 0); - dm_put(md); - - r = info(param, user); - return r; -} - -static int rename(struct dm_ioctl *param, struct dm_ioctl *user) -{ - int r; - char *new_name = (char *) param + param->data_start; - - if (valid_str(new_name, (void *) param, - (void *) param + param->data_size)) { - DMWARN("Invalid new logical volume name supplied."); - return -EINVAL; - } - - r = check_name(new_name); - if (r) - return r; - - return dm_hash_rename(param->name, new_name); -} - - -/*----------------------------------------------------------------- - * Implementation of open/close/ioctl on the special char - * device. - *---------------------------------------------------------------*/ -static ioctl_fn lookup_ioctl(unsigned int cmd) -{ - static struct { - int cmd; - ioctl_fn fn; - } _ioctls[] = { - {DM_VERSION_CMD, NULL}, /* version is dealt with elsewhere */ - {DM_REMOVE_ALL_CMD, remove_all}, - {DM_DEV_CREATE_CMD, create}, - {DM_DEV_REMOVE_CMD, remove}, - {DM_DEV_RELOAD_CMD, reload}, - {DM_DEV_RENAME_CMD, rename}, - {DM_DEV_SUSPEND_CMD, suspend}, - {DM_DEV_DEPS_CMD, dep}, - {DM_DEV_STATUS_CMD, info}, - {DM_TARGET_STATUS_CMD, get_status}, - {DM_TARGET_WAIT_CMD, wait_device_event}, - }; - - return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn; -} - -/* - * As well as checking the version compatibility this always - * copies the kernel interface version out. - */ -static int check_version(unsigned int cmd, struct dm_ioctl *user) -{ - uint32_t version[3]; - int r = 0; - - if (copy_from_user(version, user->version, sizeof(version))) - return -EFAULT; - - if ((DM_VERSION_MAJOR != version[0]) || - (DM_VERSION_MINOR < version[1])) { - DMWARN("ioctl interface mismatch: " - "kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)", - DM_VERSION_MAJOR, DM_VERSION_MINOR, - DM_VERSION_PATCHLEVEL, - version[0], version[1], version[2], cmd); - r = -EINVAL; - } - - /* - * Fill in the kernel version. - */ - version[0] = DM_VERSION_MAJOR; - version[1] = DM_VERSION_MINOR; - version[2] = DM_VERSION_PATCHLEVEL; - if (copy_to_user(user->version, version, sizeof(version))) - return -EFAULT; - - return r; -} - -static void free_params(struct dm_ioctl *param) -{ - vfree(param); -} - -static int copy_params(struct dm_ioctl *user, struct dm_ioctl **param) -{ - struct dm_ioctl tmp, *dmi; - - if (copy_from_user(&tmp, user, sizeof(tmp))) - return -EFAULT; - - if (tmp.data_size < sizeof(tmp)) - return -EINVAL; - - dmi = (struct dm_ioctl *) vmalloc(tmp.data_size); - if (!dmi) - return -ENOMEM; - - if (copy_from_user(dmi, user, tmp.data_size)) { - vfree(dmi); - return -EFAULT; - } - - *param = dmi; - return 0; -} - -static int validate_params(uint cmd, struct dm_ioctl *param) -{ - /* Ignores parameters */ - if (cmd == DM_REMOVE_ALL_CMD) - return 0; - - /* Unless creating, either name of uuid but not both */ - if (cmd != DM_DEV_CREATE_CMD) { - if ((!*param->uuid && !*param->name) || - (*param->uuid && *param->name)) { - DMWARN("one of name or uuid must be supplied"); - return -EINVAL; - } - } - - /* Ensure strings are terminated */ - param->name[DM_NAME_LEN - 1] = '\0'; - param->uuid[DM_UUID_LEN - 1] = '\0'; - - return 0; -} - -static int ctl_ioctl(struct inode *inode, struct file *file, - uint command, ulong u) -{ - int r = 0; - unsigned int cmd; - struct dm_ioctl *param; - struct dm_ioctl *user = (struct dm_ioctl *) u; - ioctl_fn fn = NULL; - - /* only root can play with this */ - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - if (_IOC_TYPE(command) != DM_IOCTL) - return -ENOTTY; - - cmd = _IOC_NR(command); - - /* - * Check the interface version passed in. This also - * writes out the kernels interface version. - */ - r = check_version(cmd, user); - if (r) - return r; - - /* - * Nothing more to do for the version command. - */ - if (cmd == DM_VERSION_CMD) - return 0; - - fn = lookup_ioctl(cmd); - if (!fn) { - DMWARN("dm_ctl_ioctl: unknown command 0x%x", command); - return -ENOTTY; - } - - /* - * Copy the parameters into kernel space. - */ - r = copy_params(user, ¶m); - if (r) - return r; - - r = validate_params(cmd, param); - if (r) { - free_params(param); - return r; - } - - r = fn(param, user); - free_params(param); - return r; -} - -static struct file_operations _ctl_fops = { - .ioctl = ctl_ioctl, - .owner = THIS_MODULE, -}; - -static struct miscdevice _dm_misc = { - .minor = MISC_DYNAMIC_MINOR, - .name = DM_NAME, - .devfs_name = "mapper/control", - .fops = &_ctl_fops -}; - -/* - * Create misc character device and link to DM_DIR/control. - */ -int __init dm_interface_init(void) -{ - int r; - - r = dm_hash_init(); - if (r) - return r; - - r = misc_register(&_dm_misc); - if (r) { - DMERR("misc_register failed for control device"); - dm_hash_exit(); - return r; - } - - DMINFO("%d.%d.%d%s initialised: %s", DM_VERSION_MAJOR, - DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL, DM_VERSION_EXTRA, - DM_DRIVER_EMAIL); - return 0; - - if (misc_deregister(&_dm_misc) < 0) - DMERR("misc_deregister failed for control device"); - dm_hash_exit(); - return r; -} -void dm_interface_exit(void) -{ - if (misc_deregister(&_dm_misc) < 0) - DMERR("misc_deregister failed for control device"); - dm_hash_exit(); -} +#ifdef CONFIG_DM_IOCTL_V4 +#include "dm-ioctl-v4.c" +#else +#include "dm-ioctl-v1.c" +#endif diff -Nru a/drivers/md/dm-table.c b/drivers/md/dm-table.c --- a/drivers/md/dm-table.c Sat Jul 19 12:54:30 2003 +++ b/drivers/md/dm-table.c Sat Jul 19 12:54:30 2003 @@ -48,11 +48,9 @@ */ struct io_restrictions limits; - /* - * A waitqueue for processes waiting for something - * interesting to happen to this table. - */ - wait_queue_head_t eventq; + /* events get handed up using this callback */ + void (*event_fn)(void *); + void *event_context; }; /* @@ -222,7 +220,6 @@ return -ENOMEM; } - init_waitqueue_head(&t->eventq); t->mode = mode; *result = t; return 0; @@ -243,9 +240,6 @@ { unsigned int i; - /* destroying the table counts as an event */ - dm_table_event(t); - /* free the indexes (see dm_table_complete) */ if (t->depth >= 2) vfree(t->index[t->depth - 2]); @@ -694,9 +688,22 @@ return r; } +static spinlock_t _event_lock = SPIN_LOCK_UNLOCKED; +void dm_table_event_callback(struct dm_table *t, + void (*fn)(void *), void *context) +{ + spin_lock_irq(&_event_lock); + t->event_fn = fn; + t->event_context = context; + spin_unlock_irq(&_event_lock); +} + void dm_table_event(struct dm_table *t) { - wake_up_interruptible(&t->eventq); + spin_lock(&_event_lock); + if (t->event_fn) + t->event_fn(t->event_context); + spin_unlock(&_event_lock); } sector_t dm_table_get_size(struct dm_table *t) @@ -759,11 +766,6 @@ int dm_table_get_mode(struct dm_table *t) { return t->mode; -} - -void dm_table_add_wait_queue(struct dm_table *t, wait_queue_t *wq) -{ - add_wait_queue(&t->eventq, wq); } void dm_table_suspend_targets(struct dm_table *t) diff -Nru a/drivers/md/dm.c b/drivers/md/dm.c --- a/drivers/md/dm.c Sat Jul 19 12:54:26 2003 +++ b/drivers/md/dm.c Sat Jul 19 12:54:26 2003 @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -63,6 +62,12 @@ * io objects are allocated from here. */ mempool_t *io_pool; + + /* + * Event handling. + */ + uint32_t event_nr; + wait_queue_head_t eventq; }; #define MIN_IOS 256 @@ -510,6 +515,11 @@ down_read(&md->lock); } + if (!md->map) { + bio_io_error(bio, bio->bi_size); + return 0; + } + __split_bio(md, bio); up_read(&md->lock); return 0; @@ -619,6 +629,8 @@ atomic_set(&md->pending, 0); init_waitqueue_head(&md->wait); + init_waitqueue_head(&md->eventq); + return md; } @@ -634,6 +646,16 @@ /* * Bind a table to the device. */ +static void event_callback(void *context) +{ + struct mapped_device *md = (struct mapped_device *) context; + + down_write(&md->lock); + md->event_nr++; + wake_up_interruptible(&md->eventq); + up_write(&md->lock); +} + static int __bind(struct mapped_device *md, struct dm_table *t) { request_queue_t *q = &md->queue; @@ -645,6 +667,8 @@ if (size == 0) return 0; + dm_table_event_callback(md->map, event_callback, md); + dm_table_get(t); dm_table_set_restrictions(t, q); return 0; @@ -652,6 +676,10 @@ static void __unbind(struct mapped_device *md) { + if (!md->map) + return; + + dm_table_event_callback(md->map, NULL, NULL); dm_table_put(md->map); md->map = NULL; set_capacity(md->disk, 0); @@ -661,35 +689,26 @@ * Constructor for a new device. */ static int create_aux(unsigned int minor, int persistent, - struct dm_table *table, struct mapped_device **result) + struct mapped_device **result) { - int r; struct mapped_device *md; md = alloc_dev(minor, persistent); if (!md) return -ENXIO; - r = __bind(md, table); - if (r) { - free_dev(md); - return r; - } - dm_table_resume_targets(md->map); - *result = md; return 0; } -int dm_create(struct dm_table *table, struct mapped_device **result) +int dm_create(struct mapped_device **result) { - return create_aux(0, 0, table, result); + return create_aux(0, 0, result); } -int dm_create_with_minor(unsigned int minor, - struct dm_table *table, struct mapped_device **result) +int dm_create_with_minor(unsigned int minor, struct mapped_device **result) { - return create_aux(minor, 1, table, result); + return create_aux(minor, 1, result); } void dm_get(struct mapped_device *md) @@ -700,7 +719,7 @@ void dm_put(struct mapped_device *md) { if (atomic_dec_and_test(&md->holders)) { - if (!test_bit(DMF_SUSPENDED, &md->flags)) + if (!test_bit(DMF_SUSPENDED, &md->flags) && md->map) dm_table_suspend_targets(md->map); __unbind(md); free_dev(md); @@ -790,7 +809,8 @@ down_write(&md->lock); remove_wait_queue(&md->wait, &wait); set_bit(DMF_SUSPENDED, &md->flags); - dm_table_suspend_targets(md->map); + if (md->map) + dm_table_suspend_targets(md->map); up_write(&md->lock); return 0; @@ -801,7 +821,8 @@ struct deferred_io *def; down_write(&md->lock); - if (!test_bit(DMF_SUSPENDED, &md->flags) || + if (!md->map || + !test_bit(DMF_SUSPENDED, &md->flags) || !dm_table_get_size(md->map)) { up_write(&md->lock); return -EINVAL; @@ -820,6 +841,42 @@ return 0; } +/*----------------------------------------------------------------- + * Event notification. + *---------------------------------------------------------------*/ +uint32_t dm_get_event_nr(struct mapped_device *md) +{ + uint32_t r; + + down_read(&md->lock); + r = md->event_nr; + up_read(&md->lock); + + return r; +} + +int dm_add_wait_queue(struct mapped_device *md, wait_queue_t *wq, + uint32_t event_nr) +{ + down_write(&md->lock); + if (event_nr != md->event_nr) { + up_write(&md->lock); + return 1; + } + + add_wait_queue(&md->eventq, wq); + up_write(&md->lock); + + return 0; +} + +void dm_remove_wait_queue(struct mapped_device *md, wait_queue_t *wq) +{ + down_write(&md->lock); + remove_wait_queue(&md->eventq, wq); + up_write(&md->lock); +} + /* * The gendisk is only valid as long as you have a reference * count on 'md'. @@ -835,7 +892,8 @@ down_read(&md->lock); t = md->map; - dm_table_get(t); + if (t) + dm_table_get(t); up_read(&md->lock); return t; diff -Nru a/drivers/md/dm.h b/drivers/md/dm.h --- a/drivers/md/dm.h Sat Jul 19 12:54:25 2003 +++ b/drivers/md/dm.h Sat Jul 19 12:54:25 2003 @@ -51,9 +51,8 @@ * Functions for manipulating a struct mapped_device. * Drop the reference with dm_put when you finish with the object. *---------------------------------------------------------------*/ -int dm_create(struct dm_table *table, struct mapped_device **md); -int dm_create_with_minor(unsigned int minor, struct dm_table *table, - struct mapped_device **md); +int dm_create(struct mapped_device **md); +int dm_create_with_minor(unsigned int minor, struct mapped_device **md); /* * Reference counting for md. @@ -79,6 +78,14 @@ struct dm_table *dm_get_table(struct mapped_device *md); /* + * Event functions. + */ +uint32_t dm_get_event_nr(struct mapped_device *md); +int dm_add_wait_queue(struct mapped_device *md, wait_queue_t *wq, + uint32_t event_nr); +void dm_remove_wait_queue(struct mapped_device *md, wait_queue_t *wq); + +/* * Info functions. */ struct gendisk *dm_disk(struct mapped_device *md); @@ -96,6 +103,8 @@ int dm_table_add_target(struct dm_table *t, const char *type, sector_t start, sector_t len, char *params); int dm_table_complete(struct dm_table *t); +void dm_table_event_callback(struct dm_table *t, + void (*fn)(void *), void *context); void dm_table_event(struct dm_table *t); sector_t dm_table_get_size(struct dm_table *t); struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index); @@ -104,7 +113,6 @@ unsigned int dm_table_get_num_targets(struct dm_table *t); struct list_head *dm_table_get_devices(struct dm_table *t); int dm_table_get_mode(struct dm_table *t); -void dm_table_add_wait_queue(struct dm_table *t, wait_queue_t *wq); void dm_table_suspend_targets(struct dm_table *t); void dm_table_resume_targets(struct dm_table *t); diff -Nru a/drivers/md/md.c b/drivers/md/md.c --- a/drivers/md/md.c Sat Jul 19 12:54:24 2003 +++ b/drivers/md/md.c Sat Jul 19 12:54:24 2003 @@ -52,8 +52,6 @@ #define MD_DRIVER #define DEVICE_NR(device) (minor(device)) -#include - #define DEBUG 0 #define dprintk(x...) ((void)(DEBUG && printk(x))) diff -Nru a/drivers/media/common/Makefile b/drivers/media/common/Makefile --- a/drivers/media/common/Makefile Sat Jul 19 12:54:27 2003 +++ b/drivers/media/common/Makefile Sat Jul 19 12:54:27 2003 @@ -1,5 +1,5 @@ saa7146-objs := saa7146_i2c.o saa7146_core.o -saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o +saa7146_vv-objs := saa7146_vv_ksyms.o saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o saa7146_vv.o diff -Nru a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c --- a/drivers/media/common/saa7146_core.c Sat Jul 19 12:54:26 2003 +++ b/drivers/media/common/saa7146_core.c Sat Jul 19 12:54:26 2003 @@ -373,6 +373,9 @@ dev->module = THIS_MODULE; init_waitqueue_head(&dev->i2c_wq); + /* set some default values */ + saa7146_write(dev, BCS_CTRL, 0x80400040); + if( 0 != ext->probe) { if( 0 != ext->probe(dev) ) { DEB_D(("ext->probe() failed for %p. skipping device.\n",dev)); @@ -390,9 +393,6 @@ INIT_LIST_HEAD(&dev->item); list_add_tail(&dev->item,&saa7146_devices); saa7146_num++; - - /* set some default values */ - saa7146_write(dev, BCS_CTRL, 0x80400040); err = 0; goto out; diff -Nru a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c --- a/drivers/media/common/saa7146_fops.c Sat Jul 19 12:54:25 2003 +++ b/drivers/media/common/saa7146_fops.c Sat Jul 19 12:54:25 2003 @@ -106,10 +106,21 @@ // fixme: fix this for vflip != 0 saa7146_write(dev, PROT_ADDR1, 0); + saa7146_write(dev, MC2, (MASK_02|MASK_18)); + /* write the address of the rps-program */ saa7146_write(dev, RPS_ADDR0, dev->d_rps0.dma_handle); /* turn on rps */ saa7146_write(dev, MC1, (MASK_12 | MASK_28)); + +/* + printk("vdma%d.base_even: 0x%08x\n", 1,saa7146_read(dev,BASE_EVEN1)); + printk("vdma%d.base_odd: 0x%08x\n", 1,saa7146_read(dev,BASE_ODD1)); + printk("vdma%d.prot_addr: 0x%08x\n", 1,saa7146_read(dev,PROT_ADDR1)); + printk("vdma%d.base_page: 0x%08x\n", 1,saa7146_read(dev,BASE_PAGE1)); + printk("vdma%d.pitch: 0x%08x\n", 1,saa7146_read(dev,PITCH1)); + printk("vdma%d.num_line_byte: 0x%08x\n", 1,saa7146_read(dev,NUM_LINE_BYTE1)); +*/ } del_timer(&q->timeout); } @@ -374,7 +385,7 @@ .minor = -1, }; -int saa7146_vv_init(struct saa7146_dev* dev) +int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) { struct saa7146_vv *vv = kmalloc (sizeof(struct saa7146_vv),GFP_KERNEL); if( NULL == vv ) { @@ -385,6 +396,11 @@ DEB_EE(("dev:%p\n",dev)); + /* save per-device extension data (one extension can + handle different devices that might need different + configuration data) */ + dev->ext_vv_data = ext_vv; + vv->video_minor = -1; vv->vbi_minor = -1; @@ -474,13 +490,6 @@ module_init(saa7146_vv_init_module); module_exit(saa7146_vv_cleanup_module); - -EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync); -EXPORT_SYMBOL_GPL(saa7146_register_device); -EXPORT_SYMBOL_GPL(saa7146_unregister_device); - -EXPORT_SYMBOL_GPL(saa7146_vv_init); -EXPORT_SYMBOL_GPL(saa7146_vv_release); MODULE_AUTHOR("Michael Hunold "); MODULE_DESCRIPTION("video4linux driver for saa7146-based hardware"); diff -Nru a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c --- a/drivers/media/common/saa7146_hlp.c Sat Jul 19 12:54:25 2003 +++ b/drivers/media/common/saa7146_hlp.c Sat Jul 19 12:54:25 2003 @@ -242,7 +242,9 @@ if( 2*out_y >= in_y) { lpi = 1; } - } else if (field == V4L2_FIELD_TOP || field == V4L2_FIELD_BOTTOM) { + } else if (field == V4L2_FIELD_TOP + || field == V4L2_FIELD_ALTERNATE + || field == V4L2_FIELD_BOTTOM) { if( 4*out_y >= in_y ) { lpi = 1; } @@ -468,9 +470,7 @@ *clip_format &= 0xfffffff7; if (V4L2_FIELD_HAS_BOTH(field)) { *clip_format |= 0x00000008; - } else if (field == V4L2_FIELD_TOP) { - *clip_format |= 0x00000000; - } else if (field == V4L2_FIELD_BOTTOM) { + } else { *clip_format |= 0x00000000; } } @@ -593,6 +593,10 @@ } if (V4L2_FIELD_HAS_BOTH(field)) { + } else if (field == V4L2_FIELD_ALTERNATE) { + /* fixme */ + vdma1.base_odd = vdma1.prot_addr; + vdma1.pitch /= 2; } else if (field == V4L2_FIELD_TOP) { vdma1.base_odd = vdma1.prot_addr; vdma1.pitch /= 2; @@ -706,7 +710,7 @@ /* calculate starting address */ where = (which-1)*0x18; - if( 0 != (dev->ext->ext_vv_data->flags & SAA7146_EXT_SWAP_ODD_EVEN)) { + if( 0 != (dev->ext_vv_data->flags & SAA7146_EXT_SWAP_ODD_EVEN)) { saa7146_write(dev, where, vdma->base_even); saa7146_write(dev, where+0x04, vdma->base_odd); } else { @@ -760,6 +764,16 @@ } if (V4L2_FIELD_HAS_BOTH(field)) { + } else if (field == V4L2_FIELD_ALTERNATE) { + /* fixme */ + if ( vv->last_field == V4L2_FIELD_TOP ) { + vdma1.base_odd = vdma1.prot_addr; + vdma1.pitch /= 2; + } else if ( vv->last_field == V4L2_FIELD_BOTTOM ) { + vdma1.base_odd = vdma1.base_even; + vdma1.base_even = vdma1.prot_addr; + vdma1.pitch /= 2; + } } else if (field == V4L2_FIELD_TOP) { vdma1.base_odd = vdma1.prot_addr; vdma1.pitch /= 2; @@ -896,6 +910,14 @@ } if (V4L2_FIELD_HAS_BOTH(field)) { + } else if (field == V4L2_FIELD_ALTERNATE) { + /* fixme */ + vdma1.base_odd = vdma1.prot_addr; + vdma1.pitch /= 2; + vdma2.base_odd = vdma2.prot_addr; + vdma2.pitch /= 2; + vdma3.base_odd = vdma3.prot_addr; + vdma3.pitch /= 2; } else if (field == V4L2_FIELD_TOP) { vdma1.base_odd = vdma1.prot_addr; vdma1.pitch /= 2; @@ -935,21 +957,22 @@ static void program_capture_engine(struct saa7146_dev *dev, int planar) { struct saa7146_vv *vv = dev->vv_data; + int count = 0; unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B; unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B; - if( 0 != (dev->ext->ext_vv_data->flags & SAA7146_EXT_SWAP_ODD_EVEN)) { + if( 0 != (dev->ext_vv_data->flags & SAA7146_EXT_SWAP_ODD_EVEN)) { unsigned long tmp = e_wait; e_wait = o_wait; o_wait = tmp; } - /* wait for o_fid_a/b / e_fid_a/b toggle only if bit 0 is not set*/ - WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | e_wait); + /* wait for o_fid_a/b / e_fid_a/b toggle only if rps register 0 is not set*/ WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | o_wait); + WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | e_wait); - /* set bit 0 */ + /* set rps register 0 */ WRITE_RPS0(CMD_WR_REG | (1 << 8) | (MC2/4)); WRITE_RPS0(MASK_27 | MASK_11); @@ -970,8 +993,14 @@ } /* wait for o_fid_a/b / e_fid_a/b toggle */ + if ( vv->last_field == V4L2_FIELD_INTERLACED ) { + WRITE_RPS0(CMD_PAUSE | o_wait); WRITE_RPS0(CMD_PAUSE | e_wait); + } else if ( vv->last_field == V4L2_FIELD_TOP ) { WRITE_RPS0(CMD_PAUSE | o_wait); + } else if ( vv->last_field == V4L2_FIELD_BOTTOM ) { + WRITE_RPS0(CMD_PAUSE | e_wait); + } /* turn off video-dma1 */ WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4)); @@ -999,12 +1028,38 @@ void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next) { struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); + struct saa7146_vv *vv = dev->vv_data; + u32 vdma1_prot_addr; DEB_CAP(("buf:%p, next:%p\n",buf,next)); +/* + printk("vdma%d.base_even: 0x%08x\n", 1,saa7146_read(dev,BASE_EVEN1)); + printk("vdma%d.base_odd: 0x%08x\n", 1,saa7146_read(dev,BASE_ODD1)); + printk("vdma%d.prot_addr: 0x%08x\n", 1,saa7146_read(dev,PROT_ADDR1)); + printk("vdma%d.base_page: 0x%08x\n", 1,saa7146_read(dev,BASE_PAGE1)); + printk("vdma%d.pitch: 0x%08x\n", 1,saa7146_read(dev,PITCH1)); + printk("vdma%d.num_line_byte: 0x%08x\n", 1,saa7146_read(dev,NUM_LINE_BYTE1)); + printk("vdma%d => vptr : 0x%08x\n", 1,saa7146_read(dev,PCI_VDP1)); +*/ + + vdma1_prot_addr = saa7146_read(dev, PROT_ADDR1); + if( 0 == vdma1_prot_addr ) { + /* clear out beginning of streaming bit (rps register 0)*/ + DEB_CAP(("forcing sync to new frame\n")); + saa7146_write(dev, MC2, MASK_27 ); + } + saa7146_set_window(dev, buf->fmt->width, buf->fmt->height, buf->fmt->field); saa7146_set_output_format(dev, sfmt->trans); saa7146_disable_clipping(dev); + + if ( vv->last_field == V4L2_FIELD_INTERLACED ) { + } else if ( vv->last_field == V4L2_FIELD_TOP ) { + vv->last_field = V4L2_FIELD_BOTTOM; + } else if ( vv->last_field == V4L2_FIELD_BOTTOM ) { + vv->last_field = V4L2_FIELD_TOP; + } if( 0 != IS_PLANAR(sfmt->trans)) { calculate_video_dma_grab_planar(dev, buf); diff -Nru a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c --- a/drivers/media/common/saa7146_i2c.c Sat Jul 19 12:54:29 2003 +++ b/drivers/media/common/saa7146_i2c.c Sat Jul 19 12:54:29 2003 @@ -181,9 +181,10 @@ /* this functions writes out the data-byte 'dword' to the i2c-device. it returns 0 if ok, -1 if the transfer failed, -2 if the transfer failed badly (e.g. address error) */ -static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword) +static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_delay) { u32 status = 0, mc2 = 0; + int trial = 0; int timeout; /* write out i2c-command */ @@ -224,10 +225,13 @@ /* wait until we get a transfer done or error */ timeout = jiffies + HZ/100 + 1; /* 10ms */ while(1) { + /** + * first read usually delivers bogus results... + */ + saa7146_i2c_status(dev); status = saa7146_i2c_status(dev); - if( (0x3 == (status & 0x3)) || (0 == (status & 0x1)) ) { + if ((status & 0x3) != 1) break; - } if (jiffies > timeout) { /* this is normal when probing the bus * (no answer from nonexisistant device...) @@ -235,6 +239,9 @@ DEB_I2C(("saa7146_i2c_writeout: timed out waiting for end of xfer\n")); return -EIO; } + if ((++trial < 20) && short_delay) + udelay(10); + else my_wait(dev,1); } } @@ -277,6 +284,7 @@ u32* buffer = dev->d_i2c.cpu_addr; int err = 0; int address_err = 0; + int short_delay = 0; if (down_interruptible (&dev->i2c_lock)) return -ERESTARTSYS; @@ -292,6 +300,8 @@ goto out; } + if (count > 3) short_delay = 1; + do { /* reset the i2c-device if necessary */ err = saa7146_i2c_reset(dev); @@ -302,7 +312,7 @@ /* write out the u32s one after another */ for(i = 0; i < count; i++) { - err = saa7146_i2c_writeout(dev, &buffer[i] ); + err = saa7146_i2c_writeout(dev, &buffer[i], short_delay); if ( 0 != err) { /* this one is unsatisfying: some i2c slaves on some dvb cards don't acknowledge correctly, so the saa7146 @@ -357,7 +367,7 @@ if( 0 == dev->revision ) { u32 zero = 0; saa7146_i2c_reset(dev); - if( 0 != saa7146_i2c_writeout(dev, &zero)) { + if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) { INFO(("revision 0 error. this should never happen.\n")); } } @@ -397,8 +407,13 @@ if( NULL != i2c_adapter ) { memset(i2c_adapter,0,sizeof(struct i2c_adapter)); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) + strcpy(i2c_adapter->name, dev->name); + i2c_adapter->data = dev; +#else strcpy(i2c_adapter->dev.name, dev->name); i2c_set_adapdata(i2c_adapter,dev); +#endif i2c_adapter->algo = &saa7146_algo; i2c_adapter->algo_data = NULL; i2c_adapter->id = I2C_ALGO_SAA7146; diff -Nru a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c --- a/drivers/media/common/saa7146_vbi.c Sat Jul 19 12:54:21 2003 +++ b/drivers/media/common/saa7146_vbi.c Sat Jul 19 12:54:21 2003 @@ -9,6 +9,7 @@ u32 *cpu; dma_addr_t dma_addr; + int count = 0; int i; DECLARE_WAITQUEUE(wait, current); @@ -443,5 +444,3 @@ .irq_done = vbi_irq_done, .read = vbi_read, }; - -EXPORT_SYMBOL_GPL(saa7146_vbi_uops); diff -Nru a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c --- a/drivers/media/common/saa7146_video.c Sat Jul 19 12:54:26 2003 +++ b/drivers/media/common/saa7146_video.c Sat Jul 19 12:54:26 2003 @@ -137,6 +137,7 @@ switch (field) { case V4L2_FIELD_TOP: case V4L2_FIELD_BOTTOM: + case V4L2_FIELD_ALTERNATE: maxh = maxh / 2; break; case V4L2_FIELD_INTERLACED: @@ -186,11 +187,18 @@ : V4L2_FIELD_BOTTOM; } switch (field) { + case V4L2_FIELD_ALTERNATE: { + vv->last_field = V4L2_FIELD_TOP; + maxh = maxh / 2; + break; + } case V4L2_FIELD_TOP: case V4L2_FIELD_BOTTOM: + vv->last_field = V4L2_FIELD_INTERLACED; maxh = maxh / 2; break; case V4L2_FIELD_INTERLACED: + vv->last_field = V4L2_FIELD_INTERLACED; break; default: { DEB_D(("no known field mode '%d'.\n",field)); @@ -220,7 +228,7 @@ } } -static int start_preview(struct saa7146_fh *fh) +int saa7146_start_preview(struct saa7146_fh *fh) { struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; @@ -266,12 +274,12 @@ return 0; } -static int stop_preview(struct saa7146_fh *fh) +int saa7146_stop_preview(struct saa7146_fh *fh) { struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; - DEB_EE(("saa7146.o: stop_preview()\n")); + DEB_EE(("saa7146.o: saa7146_stop_preview()\n")); /* check if overlay is running */ if( 0 == vv->ov_data ) { @@ -333,8 +341,8 @@ if( vv->ov_data != NULL ) { if( fh == vv->ov_data->fh) { spin_lock_irqsave(&dev->slock,flags); - stop_preview(fh); - start_preview(fh); + saa7146_stop_preview(fh); + saa7146_start_preview(fh); spin_unlock_irqrestore(&dev->slock,flags); } } @@ -522,8 +530,8 @@ if( 0 != vv->ov_data ) { if( fh == vv->ov_data->fh ) { spin_lock_irqsave(&dev->slock,flags); - stop_preview(fh); - start_preview(fh); + saa7146_stop_preview(fh); + saa7146_start_preview(fh); spin_unlock_irqrestore(&dev->slock,flags); } } @@ -561,7 +569,7 @@ m3 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1; o1 = size%PAGE_SIZE; o2 = (size+(size/4))%PAGE_SIZE; - printk("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2); + DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2)); break; } case 16: { @@ -571,7 +579,7 @@ m3 = ((2*size+PAGE_SIZE)/PAGE_SIZE)-1; o1 = size%PAGE_SIZE; o2 = (size+(size/2))%PAGE_SIZE; - printk("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2); + DEB_CAP(("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",size,m1,m2,m3,o1,o2)); break; } default: { @@ -674,7 +682,7 @@ spin_lock_irqsave(&dev->slock,flags); - /* clear out beginning of streaming bit */ + /* clear out beginning of streaming bit (rps register 0)*/ saa7146_write(dev, MC2, MASK_27 ); /* enable rps0 irqs */ @@ -740,19 +748,19 @@ struct videobuf_queue *q; /* check if extension handles the command */ - for(ee = 0; dev->ext->ext_vv_data->ioctls[ee].flags != 0; ee++) { - if( cmd == dev->ext->ext_vv_data->ioctls[ee].cmd ) + for(ee = 0; dev->ext_vv_data->ioctls[ee].flags != 0; ee++) { + if( cmd == dev->ext_vv_data->ioctls[ee].cmd ) break; } - if( 0 != (dev->ext->ext_vv_data->ioctls[ee].flags & SAA7146_EXCLUSIVE) ) { + if( 0 != (dev->ext_vv_data->ioctls[ee].flags & SAA7146_EXCLUSIVE) ) { DEB_D(("extension handles ioctl exclusive.\n")); - result = dev->ext->ext_vv_data->ioctl(dev, cmd, arg); + result = dev->ext_vv_data->ioctl(fh, cmd, arg); return result; } - if( 0 != (dev->ext->ext_vv_data->ioctls[ee].flags & SAA7146_BEFORE) ) { + if( 0 != (dev->ext_vv_data->ioctls[ee].flags & SAA7146_BEFORE) ) { DEB_D(("extension handles ioctl before.\n")); - result = dev->ext->ext_vv_data->ioctl(dev, cmd, arg); + result = dev->ext_vv_data->ioctl(fh, cmd, arg); if( -EAGAIN != result ) { return result; } @@ -793,7 +801,7 @@ V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; - cap->capabilities |= dev->ext->ext_vv_data->capabilities; + cap->capabilities |= dev->ext_vv_data->capabilities; return 0; } case VIDIOC_G_FBUF: @@ -942,9 +950,10 @@ struct v4l2_standard *e = arg; if (e->index < 0 ) return -EINVAL; - if( e->index < dev->ext->ext_vv_data->num_stds ) { + if( e->index < dev->ext_vv_data->num_stds ) { DEB_EE(("VIDIOC_ENUMSTD: index:%d\n",e->index)); - return v4l2_video_std_construct(e, dev->ext->ext_vv_data->stds[e->index].id, dev->ext->ext_vv_data->stds[e->index].name); + v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name); + return 0; } return -EINVAL; } @@ -968,22 +977,22 @@ if( vv->ov_data != NULL ) { ov_fh = vv->ov_data->fh; - stop_preview(ov_fh); + saa7146_stop_preview(ov_fh); restart_overlay = 1; } - for(i = 0; i < dev->ext->ext_vv_data->num_stds; i++) - if (*id & dev->ext->ext_vv_data->stds[i].id) + for(i = 0; i < dev->ext_vv_data->num_stds; i++) + if (*id & dev->ext_vv_data->stds[i].id) break; - if (i != dev->ext->ext_vv_data->num_stds) { - vv->standard = &dev->ext->ext_vv_data->stds[i]; - if( NULL != dev->ext->ext_vv_data->std_callback ) - dev->ext->ext_vv_data->std_callback(dev, vv->standard); + if (i != dev->ext_vv_data->num_stds) { + vv->standard = &dev->ext_vv_data->stds[i]; + if( NULL != dev->ext_vv_data->std_callback ) + dev->ext_vv_data->std_callback(dev, vv->standard); found = 1; } if( 0 != restart_overlay ) { - start_preview(ov_fh); + saa7146_start_preview(ov_fh); } up(&dev->lock); @@ -1000,7 +1009,7 @@ int on = *(int *)arg; int err = 0; - if( NULL == vv->ov_fmt ) { + if( NULL == vv->ov_fmt && on != 0 ) { DEB_D(("VIDIOC_OVERLAY: no framebuffer informations. call S_FBUF first!\n")); return -EAGAIN; } @@ -1013,7 +1022,7 @@ } } spin_lock_irqsave(&dev->slock,flags); - err = start_preview(fh); + err = saa7146_start_preview(fh); spin_unlock_irqrestore(&dev->slock,flags); } else { if( vv->ov_data != NULL ) { @@ -1022,7 +1031,7 @@ } } spin_lock_irqsave(&dev->slock,flags); - err = stop_preview(fh); + err = saa7146_stop_preview(fh); spin_unlock_irqrestore(&dev->slock,flags); } return err; @@ -1036,12 +1045,18 @@ return videobuf_querybuf(q,arg); } case VIDIOC_QBUF: { - DEB_D(("VIDIOC_QBUF \n")); - return videobuf_qbuf(file,q,arg); + struct v4l2_buffer *b = arg; + int ret = 0; + ret = videobuf_qbuf(file,q,b); + DEB_D(("VIDIOC_QBUF: ret:%d, index:%d\n",ret,b->index)); + return ret; } case VIDIOC_DQBUF: { - DEB_D(("VIDIOC_DQBUF \n")); - return videobuf_dqbuf(file,q,arg); + struct v4l2_buffer *b = arg; + int ret = 0; + ret = videobuf_dqbuf(file,q,b); + DEB_D(("VIDIOC_DQBUF: ret:%d, index:%d\n",ret,b->index)); + return ret; } case VIDIOC_STREAMON: { DEB_D(("VIDIOC_STREAMON \n")); @@ -1075,7 +1090,7 @@ q = &fh->video_q; down(&q->lock); - err = videobuf_mmap_setup(file,q,gbuffers,gbufsize); + err = videobuf_mmap_setup(file,q,gbuffers,gbufsize); // ,V4L2_MEMORY_MMAP); if (err < 0) { up(&q->lock); return err; @@ -1250,7 +1265,7 @@ vv->video_q.dev = dev; /* set some default values */ - vv->standard = &dev->ext->ext_vv_data->stds[0]; + vv->standard = &dev->ext_vv_data->stds[0]; /* FIXME: what's this? */ vv->current_hps_source = SAA7146_HPS_SOURCE_PORT_A; @@ -1287,7 +1302,7 @@ if( 0 != vv->ov_data ) { if( fh == vv->ov_data->fh ) { spin_lock_irqsave(&dev->slock,flags); - stop_preview(fh); + saa7146_stop_preview(fh); spin_unlock_irqrestore(&dev->slock,flags); } } @@ -1331,7 +1346,7 @@ if( vv->ov_data != NULL ) { ov_fh = vv->ov_data->fh; - stop_preview(ov_fh); + saa7146_stop_preview(ov_fh); restart_overlay = 1; } @@ -1343,7 +1358,7 @@ /* restart overlay if it was active before */ if( 0 != restart_overlay ) { - start_preview(ov_fh); + saa7146_start_preview(ov_fh); } return ret; @@ -1358,5 +1373,3 @@ .capture_begin = video_begin, .capture_end = video_end, }; - -EXPORT_SYMBOL_GPL(saa7146_video_uops); diff -Nru a/drivers/media/common/saa7146_vv_ksyms.c b/drivers/media/common/saa7146_vv_ksyms.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/common/saa7146_vv_ksyms.c Sat Jul 19 12:54:30 2003 @@ -0,0 +1,15 @@ +#include +#include + +EXPORT_SYMBOL_GPL(saa7146_vbi_uops); +EXPORT_SYMBOL_GPL(saa7146_video_uops); + +EXPORT_SYMBOL_GPL(saa7146_start_preview); +EXPORT_SYMBOL_GPL(saa7146_stop_preview); + +EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync); +EXPORT_SYMBOL_GPL(saa7146_register_device); +EXPORT_SYMBOL_GPL(saa7146_unregister_device); + +EXPORT_SYMBOL_GPL(saa7146_vv_init); +EXPORT_SYMBOL_GPL(saa7146_vv_release); diff -Nru a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig --- a/drivers/media/dvb/Kconfig Sat Jul 19 12:54:24 2003 +++ b/drivers/media/dvb/Kconfig Sat Jul 19 12:54:24 2003 @@ -33,9 +33,19 @@ source "drivers/media/dvb/frontends/Kconfig" comment "Supported SAA7146 based PCI Adapters" - depends on DVB + depends on DVB && PCI source "drivers/media/dvb/ttpci/Kconfig" + +comment "Supported USB Adapters" + depends on DVB && USB + +source "drivers/media/dvb/ttusb-budget/Kconfig" +source "drivers/media/dvb/ttusb-dec/Kconfig" + +comment "Supported FlexCopII (B2C2) Adapters" + depends on DVB && PCI +source "drivers/media/dvb/b2c2/Kconfig" endmenu diff -Nru a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile --- a/drivers/media/dvb/Makefile Sat Jul 19 12:54:25 2003 +++ b/drivers/media/dvb/Makefile Sat Jul 19 12:54:25 2003 @@ -2,4 +2,5 @@ # Makefile for the kernel multimedia device drivers. # -obj-y := dvb-core/ frontends/ ttpci/ # ttusb-budget/ +obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ + diff -Nru a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/b2c2/Kconfig Sat Jul 19 12:54:30 2003 @@ -0,0 +1,8 @@ +config DVB_B2C2_SKYSTAR + tristate "Technisat Skystar2 PCI" + depends on DVB_CORE + help + Support for the Skystar2 PCI DVB card by Technisat, which + is equipped with the FlexCopII chipset by B2C2. + + Say Y if you own such a device and want to use it. diff -Nru a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/b2c2/Makefile Sat Jul 19 12:54:30 2003 @@ -0,0 +1,3 @@ +obj-$(CONFIG_DVB_B2C2_SKYSTAR) += skystar2.o + +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ diff -Nru a/drivers/media/dvb/b2c2/skystar2.c b/drivers/media/dvb/b2c2/skystar2.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/b2c2/skystar2.c Sat Jul 19 12:54:30 2003 @@ -0,0 +1,2506 @@ +/* + * skystar2.c - driver for the Technisat SkyStar2 PCI DVB card + * based on the FlexCopII by B2C2,Inc. + * + * Copyright (C) 2003 V.C. , skystar@moldova.cc + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * 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 Lesser 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 "dvb_i2c.h" +#include "dvb_frontend.h" +#include "dvb_functions.h" + +#include +#include +#include "dvb_demux.h" +#include "dmxdev.h" +#include "dvb_filter.h" +#include "dvbdev.h" +#include "demux.h" +#include "dvb_net.h" + +static int debug = 0; +#define dprintk(x...) do { if (debug) printk(x); } while (0) + +#define SizeOfBufDMA1 0x3AC00 +#define SizeOfBufDMA2 0x758 + +struct dmaq { + + u32 bus_addr; + u32 head; + u32 tail; + u32 buffer_size; + u8 *buffer; +}; + +struct packet_header { + + u32 sync_byte; + u32 transport_error_indicator; + u32 payload_unit_start_indicator; + u32 transport_priority; + u32 pid; + u32 transport_scrambling_control; + u32 adaptation_field_control; + u32 continuity_counter; +}; + +struct adapter { + + struct pci_dev *pdev; + + u8 card_revision; + u32 b2c2_revision; + u32 PidFilterMax; + u32 MacFilterMax; + u32 irq; + u32 io_mem; + u32 io_port; + u8 mac_addr[8]; + u32 dwSramType; + + struct dvb_adapter *dvb_adapter; + struct dvb_demux demux; + struct dmxdev dmxdev; + struct dmx_frontend hw_frontend; + struct dmx_frontend mem_frontend; + struct dvb_i2c_bus *i2c_bus; + struct dvb_net dvbnet; + + struct semaphore i2c_sem; + + struct dmaq dmaq1; + struct dmaq dmaq2; + + u32 dma_ctrl; + u32 dma_status; + + u32 capturing; + + spinlock_t lock; + + u16 pids[0x27]; + u32 mac_filter; +}; + +#define WriteRegDW(adapter,reg,value) writel(value, adapter->io_mem + reg) +#define ReadRegDW(adapter,reg) readl(adapter->io_mem + reg) + +static void WriteRegOp(struct adapter *adapter, u32 reg, u32 operation, u32 andvalue, u32 orvalue) +{ + u32 tmp; + + tmp = ReadRegDW(adapter, reg); + + if (operation == 1) + tmp = tmp | orvalue; + if (operation == 2) + tmp = tmp & andvalue; + if (operation == 3) + tmp = (tmp & andvalue) | orvalue; + + WriteRegDW(adapter, reg, tmp); +} + +/* i2c functions */ +static int i2cMainWriteForFlex2(struct adapter * adapter, u32 command, u8 * buf, u32 retries) +{ + u32 i; + u32 value; + + WriteRegDW(adapter, 0x100, 0); + WriteRegDW(adapter, 0x100, command); + + for (i = 0; i < retries; i++) { + value = ReadRegDW(adapter, 0x100); + + if ((value & 0x40000000) == 0) { + if ((value & 0x81000000) == 0x80000000) { + if (buf != 0) + *buf = (value >> 0x10) & 0xff; + + return 1; + } + + } else { + + WriteRegDW(adapter, 0x100, 0); + WriteRegDW(adapter, 0x100, command); + } + } + + return 0; +} + +/* device = 0x10000000 for tuner, 0x20000000 for eeprom */ +static void i2cMainSetup(u32 device, u32 chip_addr, u8 op, u8 addr, u32 value, u32 len, u32 *command) +{ + *command = device | ((len - 1) << 26) | (value << 16) | (addr << 8) | chip_addr; + + if (op != 0) + *command = *command | 0x03000000; + else + *command = *command | 0x01000000; +} + +static int FlexI2cRead4(struct adapter * adapter, u32 device, u32 chip_addr, u16 addr, u8 * buf, u8 len) +{ + u32 command; + u32 value; + + int result, i; + + i2cMainSetup(device, chip_addr, 1, addr, 0, len, &command); + + result = i2cMainWriteForFlex2(adapter, command, buf, 100000); + + if ((result & 0xff) != 0) { + if (len > 1) { + value = ReadRegDW(adapter, 0x104); + + for (i = 1; i < len; i++) { + buf[i] = value & 0xff; + value = value >> 8; + } + } + } + + return result; +} + +static int FlexI2cWrite4(struct adapter * adapter, u32 device, u32 chip_addr, u32 addr, u8 * buf, u8 len) +{ + u32 command; + u32 value; + int i; + + if (len > 1) { + value = 0; + + for (i = len; i > 1; i--) { + value = value << 8; + value = value | buf[i - 1]; + } + + WriteRegDW(adapter, 0x104, value); + } + + i2cMainSetup(device, chip_addr, 0, addr, buf[0], len, &command); + + return i2cMainWriteForFlex2(adapter, command, 0, 100000); +} + +static void fixchipaddr(u32 device, u32 bus, u32 addr, u32 *ret) +{ + if (device == 0x20000000) + *ret = bus | ((addr >> 8) & 3); + + *ret = bus; +} + +static u32 FLEXI2C_read(struct adapter * adapter, u32 device, u32 bus, u32 addr, u8 * buf, u32 len) +{ + u32 chipaddr; + u32 bytes_to_transfer; + u8 *start; + +// dprintk("%s:\n", __FUNCTION__); + + start = buf; + + while (len != 0) { + bytes_to_transfer = len; + + if (bytes_to_transfer > 4) + bytes_to_transfer = 4; + + fixchipaddr(device, bus, addr, &chipaddr); + + if (FlexI2cRead4(adapter, device, chipaddr, addr, buf, bytes_to_transfer) == 0) + return buf - start; + + buf = buf + bytes_to_transfer; + addr = addr + bytes_to_transfer; + len = len - bytes_to_transfer; + }; + + return buf - start; +} + +static u32 FLEXI2C_write(struct adapter * adapter, u32 device, u32 bus, u32 addr, u8 * buf, u32 len) +{ + u32 chipaddr; + u32 bytes_to_transfer; + u8 *start; + +// dprintk("%s:\n", __FUNCTION__); + + start = buf; + + while (len != 0) { + bytes_to_transfer = len; + + if (bytes_to_transfer > 4) + bytes_to_transfer = 4; + + fixchipaddr(device, bus, addr, &chipaddr); + + if (FlexI2cWrite4(adapter, device, chipaddr, addr, buf, bytes_to_transfer) == 0) + return buf - start; + + buf = buf + bytes_to_transfer; + addr = addr + bytes_to_transfer; + len = len - bytes_to_transfer; + } + + return buf - start; +} + +static int master_xfer(struct dvb_i2c_bus *i2c, const struct i2c_msg *msgs, int num) +{ + struct adapter *tmp = i2c->data; + int i, ret = 0; + + if (down_interruptible(&tmp->i2c_sem)) + return -ERESTARTSYS; + + if (0) { + dprintk("%s:\n", __FUNCTION__); + + for (i = 0; i < num; i++) { + printk("message %d: flags=%x, addr=0x%04x, buf=%x, len=%d \n", i, msgs[i].flags, msgs[i].addr, (u32) msgs[i].buf, msgs[i].len); + } + } + + /* allow only the vp310 frontend to access the bus */ + if ((msgs[0].addr != 0x0E) && (msgs[0].addr != 0x61)) { + up(&tmp->i2c_sem); + + return -EREMOTEIO; + } + + if ((num == 1) && (msgs[0].buf != NULL)) { + if (msgs[0].flags == I2C_M_RD) { + ret = -EINVAL; + + } else { + + // single writes do have the reg addr in buf[0] and data in buf[1] to buf[n] + ret = FLEXI2C_write(tmp, 0x10000000, msgs[0].addr, msgs[0].buf[0], &msgs[0].buf[1], msgs[0].len - 1); + + if (ret != msgs[0].len - 1) + ret = -EREMOTEIO; + else + ret = num; + } + + } else if ((num == 2) && (msgs[1].buf != NULL)) { + + // i2c reads consist of a reg addr _write_ followed by a data read, so msg[1].flags has to be examined + if (msgs[1].flags == I2C_M_RD) { + ret = FLEXI2C_read(tmp, 0x10000000, msgs[0].addr, msgs[0].buf[0], msgs[1].buf, msgs[1].len); + + } else { + + ret = FLEXI2C_write(tmp, 0x10000000, msgs[0].addr, msgs[0].buf[0], msgs[1].buf, msgs[1].len); + } + + if (ret != msgs[1].len) + ret = -EREMOTEIO; + else + ret = num; + } + + up(&tmp->i2c_sem); + + /* master xfer functions always return the number of successfully + transmitted messages, not the number of transmitted bytes. + return -EREMOTEIO in case of failure. */ + return ret; +} + +/* SRAM (Skystar2 rev2.3 has one "ISSI IS61LV256" chip on board, + but it seems that FlexCopII can work with more than one chip) */ +static void SRAMSetNetDest(struct adapter * adapter, u8 dest) +{ + u32 tmp; + + udelay(1000); + + tmp = (ReadRegDW(adapter, 0x714) & 0xFFFFFFFC) | (dest & 3); + + udelay(1000); + + WriteRegDW(adapter, 0x714, tmp); + WriteRegDW(adapter, 0x714, tmp); + + udelay(1000); + + /* return value is never used? */ +/* return tmp; */ +} + +static void SRAMSetCaiDest(struct adapter * adapter, u8 dest) +{ + u32 tmp; + + udelay(1000); + + tmp = (ReadRegDW(adapter, 0x714) & 0xFFFFFFF3) | ((dest & 3) << 2); + + udelay(1000); + udelay(1000); + + WriteRegDW(adapter, 0x714, tmp); + WriteRegDW(adapter, 0x714, tmp); + + udelay(1000); + + /* return value is never used? */ +/* return tmp; */ +} + +static void SRAMSetCaoDest(struct adapter * adapter, u8 dest) +{ + u32 tmp; + + udelay(1000); + + tmp = (ReadRegDW(adapter, 0x714) & 0xFFFFFFCF) | ((dest & 3) << 4); + + udelay(1000); + udelay(1000); + + WriteRegDW(adapter, 0x714, tmp); + WriteRegDW(adapter, 0x714, tmp); + + udelay(1000); + + /* return value is never used? */ +/* return tmp; */ +} + +static void SRAMSetMediaDest(struct adapter * adapter, u8 dest) +{ + u32 tmp; + + udelay(1000); + + tmp = (ReadRegDW(adapter, 0x714) & 0xFFFFFF3F) | ((dest & 3) << 6); + + udelay(1000); + udelay(1000); + + WriteRegDW(adapter, 0x714, tmp); + WriteRegDW(adapter, 0x714, tmp); + + udelay(1000); + + /* return value is never used? */ +/* return tmp; */ +} + +/* SRAM memory is accessed through a buffer register in the FlexCop + chip (0x700). This register has the following structure: + bits 0-14 : address + bit 15 : read/write flag + bits 16-23 : 8-bit word to write + bits 24-27 : = 4 + bits 28-29 : memory bank selector + bit 31 : busy flag +*/ +static void FlexSramWrite(struct adapter *adapter, u32 bank, u32 addr, u8 * buf, u32 len) +{ + u32 i, command, retries; + + for (i = 0; i < len; i++) { + command = bank | addr | 0x04000000 | (*buf << 0x10); + + retries = 2; + + while (((ReadRegDW(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) { + mdelay(1); + retries--; + }; + + if (retries == 0) + printk("%s: SRAM timeout\n", __FUNCTION__); + + WriteRegDW(adapter, 0x700, command); + + buf++; + addr++; + } +} + +static void FlexSramRead(struct adapter *adapter, u32 bank, u32 addr, u8 * buf, u32 len) +{ + u32 i, command, value, retries; + + for (i = 0; i < len; i++) { + command = bank | addr | 0x04008000; + + retries = 10000; + + while (((ReadRegDW(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) { + mdelay(1); + retries--; + }; + + if (retries == 0) + printk("%s: SRAM timeout\n", __FUNCTION__); + + WriteRegDW(adapter, 0x700, command); + + retries = 10000; + + while (((ReadRegDW(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) { + mdelay(1); + retries--; + }; + + if (retries == 0) + printk("%s: SRAM timeout\n", __FUNCTION__); + + value = ReadRegDW(adapter, 0x700) >> 0x10; + + *buf = (value & 0xff); + + addr++; + buf++; + } +} + +static void SRAM_writeChunk(struct adapter *adapter, u32 addr, u8 * buf, u16 len) +{ + u32 bank; + + bank = 0; + + if (adapter->dwSramType == 0x20000) { + bank = (addr & 0x18000) << 0x0D; + } + + if (adapter->dwSramType == 0x00000) { + if ((addr >> 0x0F) == 0) + bank = 0x20000000; + else + bank = 0x10000000; + } + + FlexSramWrite(adapter, bank, addr & 0x7FFF, buf, len); +} + +static void SRAM_readChunk(struct adapter *adapter, u32 addr, u8 * buf, u16 len) +{ + u32 bank; + + bank = 0; + + if (adapter->dwSramType == 0x20000) { + bank = (addr & 0x18000) << 0x0D; + } + + if (adapter->dwSramType == 0x00000) { + if ((addr >> 0x0F) == 0) + bank = 0x20000000; + else + bank = 0x10000000; + } + + FlexSramRead(adapter, bank, addr & 0x7FFF, buf, len); +} + +static void SRAM_read(struct adapter *adapter, u32 addr, u8 * buf, u32 len) +{ + u32 length; + + while (len != 0) { + length = len; + + // check if the address range belongs to the same + // 32K memory chip. If not, the data is read from + // one chip at a time. + if ((addr >> 0x0F) != ((addr + len - 1) >> 0x0F)) { + length = (((addr >> 0x0F) + 1) << 0x0F) - addr; + } + + SRAM_readChunk(adapter, addr, buf, length); + + addr = addr + length; + buf = buf + length; + len = len - length; + } +} + +static void SRAM_write(struct adapter *adapter, u32 addr, u8 * buf, u32 len) +{ + u32 length; + + while (len != 0) { + length = len; + + // check if the address range belongs to the same + // 32K memory chip. If not, the data is written to + // one chip at a time. + if ((addr >> 0x0F) != ((addr + len - 1) >> 0x0F)) { + length = (((addr >> 0x0F) + 1) << 0x0F) - addr; + } + + SRAM_writeChunk(adapter, addr, buf, length); + + addr = addr + length; + buf = buf + length; + len = len - length; + } +} + +static void SRAM_setSize(struct adapter *adapter, u32 mask) +{ + WriteRegDW(adapter, 0x71C, (mask | (~0x30000 & ReadRegDW(adapter, 0x71C)))); +} + +static void SRAM_init(struct adapter *adapter) +{ + u32 tmp; + + tmp = ReadRegDW(adapter, 0x71C); + + WriteRegDW(adapter, 0x71C, 1); + + if (ReadRegDW(adapter, 0x71C) != 0) { + WriteRegDW(adapter, 0x71C, tmp); + + adapter->dwSramType = tmp & 0x30000; + + dprintk("%s: dwSramType = %x\n", __FUNCTION__, adapter->dwSramType); + + } else { + + adapter->dwSramType = 0x10000; + + dprintk("%s: dwSramType = %x\n", __FUNCTION__, adapter->dwSramType); + } + + /* return value is never used? */ +/* return adapter->dwSramType; */ +} + +static int SRAM_testLocation(struct adapter *adapter, u32 mask, u32 addr) +{ + u8 tmp1, tmp2; + + dprintk("%s: mask = %x, addr = %x\n", __FUNCTION__, mask, addr); + + SRAM_setSize(adapter, mask); + SRAM_init(adapter); + + tmp2 = 0xA5; + tmp1 = 0x4F; + + SRAM_write(adapter, addr, &tmp2, 1); + SRAM_write(adapter, addr + 4, &tmp1, 1); + + tmp2 = 0; + + mdelay(20); + + SRAM_read(adapter, addr, &tmp2, 1); + SRAM_read(adapter, addr, &tmp2, 1); + + dprintk("%s: wrote 0xA5, read 0x%2x\n", __FUNCTION__, tmp2); + + if (tmp2 != 0xA5) + return 0; + + tmp2 = 0x5A; + tmp1 = 0xF4; + + SRAM_write(adapter, addr, &tmp2, 1); + SRAM_write(adapter, addr + 4, &tmp1, 1); + + tmp2 = 0; + + mdelay(20); + + SRAM_read(adapter, addr, &tmp2, 1); + SRAM_read(adapter, addr, &tmp2, 1); + + dprintk("%s: wrote 0x5A, read 0x%2x\n", __FUNCTION__, tmp2); + + if (tmp2 != 0x5A) + return 0; + + return 1; +} + +static u32 SRAM_length(struct adapter * adapter) +{ + if (adapter->dwSramType == 0x10000) + return 32768; // 32K + if (adapter->dwSramType == 0x00000) + return 65536; // 64K + if (adapter->dwSramType == 0x20000) + return 131072; // 128K + + return 32768; // 32K +} + +/* FlexcopII can work with 32K, 64K or 128K of external SRAM memory. + - for 128K there are 4x32K chips at bank 0,1,2,3. + - for 64K there are 2x32K chips at bank 1,2. + - for 32K there is one 32K chip at bank 0. + + FlexCop works only with one bank at a time. The bank is selected + by bits 28-29 of the 0x700 register. + + bank 0 covers addresses 0x00000-0x07FFF + bank 1 covers addresses 0x08000-0x0FFFF + bank 2 covers addresses 0x10000-0x17FFF + bank 3 covers addresses 0x18000-0x1FFFF +*/ +static int SramDetectForFlex2(struct adapter *adapter) +{ + u32 tmp, tmp2, tmp3; + + dprintk("%s:\n", __FUNCTION__); + + tmp = ReadRegDW(adapter, 0x208); + WriteRegDW(adapter, 0x208, 0); + + tmp2 = ReadRegDW(adapter, 0x71C); + + dprintk("%s: tmp2 = %x\n", __FUNCTION__, tmp2); + + WriteRegDW(adapter, 0x71C, 1); + + tmp3 = ReadRegDW(adapter, 0x71C); + + dprintk("%s: tmp3 = %x\n", __FUNCTION__, tmp3); + + WriteRegDW(adapter, 0x71C, tmp2); + + // check for internal SRAM ??? + tmp3--; + if (tmp3 != 0) { + SRAM_setSize(adapter, 0x10000); + SRAM_init(adapter); + WriteRegDW(adapter, 0x208, tmp); + + dprintk("%s: sram size = 32K\n", __FUNCTION__); + + return 32; + } + + if (SRAM_testLocation(adapter, 0x20000, 0x18000) != 0) { + SRAM_setSize(adapter, 0x20000); + SRAM_init(adapter); + WriteRegDW(adapter, 0x208, tmp); + + dprintk("%s: sram size = 128K\n", __FUNCTION__); + + return 128; + } + + if (SRAM_testLocation(adapter, 0x00000, 0x10000) != 0) { + SRAM_setSize(adapter, 0x00000); + SRAM_init(adapter); + WriteRegDW(adapter, 0x208, tmp); + + dprintk("%s: sram size = 64K\n", __FUNCTION__); + + return 64; + } + + if (SRAM_testLocation(adapter, 0x10000, 0x00000) != 0) { + SRAM_setSize(adapter, 0x10000); + SRAM_init(adapter); + WriteRegDW(adapter, 0x208, tmp); + + dprintk("%s: sram size = 32K\n", __FUNCTION__); + + return 32; + } + + SRAM_setSize(adapter, 0x10000); + SRAM_init(adapter); + WriteRegDW(adapter, 0x208, tmp); + + dprintk("%s: SRAM detection failed. Set to 32K \n", __FUNCTION__); + + return 0; +} + +static void SLL_detectSramSize(struct adapter *adapter) +{ + SramDetectForFlex2(adapter); +} +/* EEPROM (Skystar2 has one "24LC08B" chip on board) */ +/* +static int EEPROM_write(struct adapter *adapter, u16 addr, u8 * buf, u16 len) +{ + return FLEXI2C_write(adapter, 0x20000000, 0x50, addr, buf, len); +} +*/ + +static int EEPROM_read(struct adapter *adapter, u16 addr, u8 * buf, u16 len) +{ + return FLEXI2C_read(adapter, 0x20000000, 0x50, addr, buf, len); +} + +u8 calc_LRC(u8 * buf, u32 len) +{ + u32 i; + u8 sum; + + sum = 0; + + for (i = 0; i < len; i++) + sum = sum ^ buf[i]; + + return sum; +} + +static int EEPROM_LRC_read(struct adapter *adapter, u32 addr, u32 len, u8 * buf, u32 retries) +{ + int i; + + for (i = 0; i < retries; i++) { + if (EEPROM_read(adapter, addr, buf, len) == len) { + if (calc_LRC(buf, len - 1) == buf[len - 1]) + return 1; + } + } + + return 0; +} + +/* +static int EEPROM_LRC_write(struct adapter *adapter, u32 addr, u32 len, u8 * wbuf, u8 * rbuf, u32 retries) +{ + int i; + + for (i = 0; i < retries; i++) { + if (EEPROM_write(adapter, addr, wbuf, len) == len) { + if (EEPROM_LRC_read(adapter, addr, len, rbuf, retries) == 1) + return 1; + } + } + + return 0; +} +*/ + +/* These functions could be called from the initialization routine + to unlock SkyStar2 cards, locked by "Europe On Line". + + in cards from "Europe On Line" the key is: + + u8 key[20] = { + 0xB2, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + }; + + LRC = 0xB3; + + in unlocked cards the key is: + + u8 key[20] = { + 0xB2, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + }; + + LRC = 0xB2; +*/ +/* +static int EEPROM_writeKey(struct adapter *adapter, u8 * key, u32 len) +{ + u8 rbuf[20]; + u8 wbuf[20]; + + if (len != 16) + return 0; + + memcpy(wbuf, key, len); + + wbuf[16] = 0; + wbuf[17] = 0; + wbuf[18] = 0; + wbuf[19] = calc_LRC(wbuf, 19); + + return EEPROM_LRC_write(adapter, 0x3E4, 20, wbuf, rbuf, 4); +} +*/ +static int EEPROM_readKey(struct adapter *adapter, u8 * key, u32 len) +{ + u8 buf[20]; + + if (len != 16) + return 0; + + if (EEPROM_LRC_read(adapter, 0x3E4, 20, buf, 4) == 0) + return 0; + + memcpy(key, buf, len); + + return 1; +} + +static int EEPROM_getMacAddr(struct adapter *adapter, char type, u8 * mac) +{ + u8 tmp[8]; + + if (EEPROM_LRC_read(adapter, 0x3F8, 8, tmp, 4) != 0) { + if (type != 0) { + mac[0] = tmp[0]; + mac[1] = tmp[1]; + mac[2] = tmp[2]; + mac[3] = 0xFE; + mac[4] = 0xFF; + mac[5] = tmp[3]; + mac[6] = tmp[4]; + mac[7] = tmp[5]; + + } else { + + mac[0] = tmp[0]; + mac[1] = tmp[1]; + mac[2] = tmp[2]; + mac[3] = tmp[3]; + mac[4] = tmp[4]; + mac[5] = tmp[5]; + } + + return 1; + + } else { + + if (type == 0) { + memset(mac, 0, 6); + + } else { + + memset(mac, 0, 8); + } + + return 0; + } +} + +/* +static char EEPROM_setMacAddr(struct adapter *adapter, char type, u8 * mac) +{ + u8 tmp[8]; + + if (type != 0) { + tmp[0] = mac[0]; + tmp[1] = mac[1]; + tmp[2] = mac[2]; + tmp[3] = mac[5]; + tmp[4] = mac[6]; + tmp[5] = mac[7]; + + } else { + + tmp[0] = mac[0]; + tmp[1] = mac[1]; + tmp[2] = mac[2]; + tmp[3] = mac[3]; + tmp[4] = mac[4]; + tmp[5] = mac[5]; + } + + tmp[6] = 0; + tmp[7] = calc_LRC(tmp, 7); + + if (EEPROM_write(adapter, 0x3F8, tmp, 8) == 8) + return 1; + + return 0; +} +*/ + +/* PID filter */ +static void FilterEnableStream1Filter(struct adapter *adapter, u32 op) +{ + dprintk("%s: op=%x\n", __FUNCTION__, op); + + if (op == 0) { + WriteRegOp(adapter, 0x208, 2, ~0x00000001, 0); + + } else { + + WriteRegOp(adapter, 0x208, 1, 0, 0x00000001); + } +} + +static void FilterEnableStream2Filter(struct adapter *adapter, u32 op) +{ + dprintk("%s: op=%x\n", __FUNCTION__, op); + + if (op == 0) { + WriteRegOp(adapter, 0x208, 2, ~0x00000002, 0); + + } else { + + WriteRegOp(adapter, 0x208, 1, 0, 0x00000002); + } +} + +static void FilterEnablePcrFilter(struct adapter *adapter, u32 op) +{ + dprintk("%s: op=%x\n", __FUNCTION__, op); + + if (op == 0) { + WriteRegOp(adapter, 0x208, 2, ~0x00000004, 0); + + } else { + + WriteRegOp(adapter, 0x208, 1, 0, 0x00000004); + } +} + +static void FilterEnablePmtFilter(struct adapter *adapter, u32 op) +{ + dprintk("%s: op=%x\n", __FUNCTION__, op); + + if (op == 0) { + WriteRegOp(adapter, 0x208, 2, ~0x00000008, 0); + + } else { + + WriteRegOp(adapter, 0x208, 1, 0, 0x00000008); + } +} + +static void FilterEnableEmmFilter(struct adapter *adapter, u32 op) +{ + dprintk("%s: op=%x\n", __FUNCTION__, op); + + if (op == 0) { + WriteRegOp(adapter, 0x208, 2, ~0x00000010, 0); + + } else { + + WriteRegOp(adapter, 0x208, 1, 0, 0x00000010); + } +} + +static void FilterEnableEcmFilter(struct adapter *adapter, u32 op) +{ + dprintk("%s: op=%x\n", __FUNCTION__, op); + + if (op == 0) { + WriteRegOp(adapter, 0x208, 2, ~0x00000020, 0); + + } else { + + WriteRegOp(adapter, 0x208, 1, 0, 0x00000020); + } +} + +/* +static void FilterEnableNullFilter(struct adapter *adapter, u32 op) +{ + dprintk("%s: op=%x\n", __FUNCTION__, op); + + if (op == 0) { + WriteRegOp(adapter, 0x208, 2, ~0x00000040, 0); + + } else { + + WriteRegOp(adapter, 0x208, 1, 0, 0x00000040); + } +} +*/ + +static void FilterEnableMaskFilter(struct adapter *adapter, u32 op) +{ + dprintk("%s: op=%x\n", __FUNCTION__, op); + + if (op == 0) { + WriteRegOp(adapter, 0x208, 2, ~0x00000080, 0); + + } else { + + WriteRegOp(adapter, 0x208, 1, 0, 0x00000080); + } +} + + +static void CtrlEnableMAC(struct adapter *adapter, u32 op) +{ + if (op == 0) { + WriteRegOp(adapter, 0x208, 2, ~0x00004000, 0); + + } else { + + WriteRegOp(adapter, 0x208, 1, 0, 0x00004000); + } +} + +static int CASetMacDstAddrFilter(struct adapter *adapter, u8 * mac) +{ + u32 tmp1, tmp2; + + tmp1 = (mac[3] << 0x18) | (mac[2] << 0x10) | (mac[1] << 0x08) | mac[0]; + tmp2 = (mac[5] << 0x08) | mac[4]; + + WriteRegDW(adapter, 0x418, tmp1); + WriteRegDW(adapter, 0x41C, tmp2); + + return 0; +} + +/* +static void SetIgnoreMACFilter(struct adapter *adapter, u8 op) +{ + if (op != 0) { + WriteRegOp(adapter, 0x208, 2, ~0x00004000, 0); + + adapter->mac_filter = 1; + + } else { + + if (adapter->mac_filter != 0) { + adapter->mac_filter = 0; + + WriteRegOp(adapter, 0x208, 1, 0, 0x00004000); + } + } +} +*/ + +/* +static void CheckNullFilterEnable(struct adapter *adapter) +{ + FilterEnableNullFilter(adapter, 1); + FilterEnableMaskFilter(adapter, 1); +} +*/ + +static void InitPIDsInfo(struct adapter *adapter) +{ + int i; + + for (i = 0; i < 0x27; i++) + adapter->pids[i] = 0x1FFF; +} + +static int CheckPID(struct adapter *adapter, u16 pid) +{ + u32 i; + + if (pid == 0x1FFF) + return 0; + + for (i = 0; i < 0x27; i++) { + if (adapter->pids[i] == pid) + return 1; + } + + return 0; +} + +static void PidSetGroupPID(struct adapter * adapter, u32 pid) +{ + u32 value; + + dprintk("%s: pid=%x\n", __FUNCTION__, pid); + + value = (pid & 0x3FFF) | (ReadRegDW(adapter, 0x30C) & 0xFFFF0000); + + WriteRegDW(adapter, 0x30C, value); + + /* return value is never used? */ +/* return value; */ +} + +static void PidSetGroupMASK(struct adapter * adapter, u32 pid) +{ + u32 value; + + dprintk("%s: pid=%x\n", __FUNCTION__, pid); + + value = ((pid & 0x3FFF) << 0x10) | (ReadRegDW(adapter, 0x30C) & 0xFFFF); + + WriteRegDW(adapter, 0x30C, value); + + /* return value is never used? */ +/* return value; */ +} + +static void PidSetStream1PID(struct adapter * adapter, u32 pid) +{ + u32 value; + + dprintk("%s: pid=%x\n", __FUNCTION__, pid); + + value = (pid & 0x3FFF) | (ReadRegDW(adapter, 0x300) & 0xFFFFC000); + + WriteRegDW(adapter, 0x300, value); + + /* return value is never used? */ +/* return value; */ +} + +static void PidSetStream2PID(struct adapter * adapter, u32 pid) +{ + u32 value; + + dprintk("%s: pid=%x\n", __FUNCTION__, pid); + + value = ((pid & 0x3FFF) << 0x10) | (ReadRegDW(adapter, 0x300) & 0xFFFF); + + WriteRegDW(adapter, 0x300, value); + + /* return value is never used? */ +/* return value; */ +} + +static void PidSetPcrPID(struct adapter * adapter, u32 pid) +{ + u32 value; + + dprintk("%s: pid=%x\n", __FUNCTION__, pid); + + value = (pid & 0x3FFF) | (ReadRegDW(adapter, 0x304) & 0xFFFFC000); + + WriteRegDW(adapter, 0x304, value); + + /* return value is never used? */ +/* return value; */ +} + +static void PidSetPmtPID(struct adapter * adapter, u32 pid) +{ + u32 value; + + dprintk("%s: pid=%x\n", __FUNCTION__, pid); + + value = ((pid & 0x3FFF) << 0x10) | (ReadRegDW(adapter, 0x304) & 0x3FFF); + + WriteRegDW(adapter, 0x304, value); + + /* return value is never used? */ +/* return value; */ +} + +static void PidSetEmmPID(struct adapter * adapter, u32 pid) +{ + u32 value; + + dprintk("%s: pid=%x\n", __FUNCTION__, pid); + + value = (pid & 0xFFFF) | (ReadRegDW(adapter, 0x308) & 0xFFFF0000); + + WriteRegDW(adapter, 0x308, value); + + /* return value is never used? */ +/* return value; */ +} + +static void PidSetEcmPID(struct adapter * adapter, u32 pid) +{ + u32 value; + + dprintk("%s: pid=%x\n", __FUNCTION__, pid); + + value = (pid << 0x10) | (ReadRegDW(adapter, 0x308) & 0xFFFF); + + WriteRegDW(adapter, 0x308, value); + + /* return value is never used? */ +/* return value; */ +} + +static int PidGetStream1PID(struct adapter * adapter) +{ + return ReadRegDW(adapter, 0x300) & 0x00001FFF; +} + +static int PidGetStream2PID(struct adapter * adapter) +{ + return (ReadRegDW(adapter, 0x300) >> 0x10)& 0x00001FFF; +} + +static int PidGetPcrPID(struct adapter * adapter) +{ + return ReadRegDW(adapter, 0x304) & 0x00001FFF; +} + +static int PidGetPmtPID(struct adapter * adapter) +{ + return (ReadRegDW(adapter, 0x304) >> 0x10)& 0x00001FFF; +} + +static int PidGetEmmPID(struct adapter * adapter) +{ + return ReadRegDW(adapter, 0x308) & 0x00001FFF; +} + +static int PidGetEcmPID(struct adapter * adapter) +{ + return (ReadRegDW(adapter, 0x308) >> 0x10)& 0x00001FFF; +} + +static int PidGetGroupPID(struct adapter * adapter) +{ + return ReadRegDW(adapter, 0x30C) & 0x00001FFF; +} + +static int PidGetGroupMASK(struct adapter * adapter) +{ + return (ReadRegDW(adapter, 0x30C) >> 0x10)& 0x00001FFF; +} + +/* +static void ResetHardwarePIDFilter(struct adapter *adapter) +{ + PidSetStream1PID(adapter, 0x1FFF); + + PidSetStream2PID(adapter, 0x1FFF); + FilterEnableStream2Filter(adapter, 0); + + PidSetPcrPID(adapter, 0x1FFF); + FilterEnablePcrFilter(adapter, 0); + + PidSetPmtPID(adapter, 0x1FFF); + FilterEnablePmtFilter(adapter, 0); + + PidSetEcmPID(adapter, 0x1FFF); + FilterEnableEcmFilter(adapter, 0); + + PidSetEmmPID(adapter, 0x1FFF); + FilterEnableEmmFilter(adapter, 0); +} +*/ + +static void OpenWholeBandwidth(struct adapter *adapter) +{ + PidSetGroupPID(adapter, 0); + + PidSetGroupMASK(adapter, 0); + + FilterEnableMaskFilter(adapter, 1); +} + +static int AddHwPID(struct adapter *adapter, u32 pid) +{ + dprintk("%s: pid=%d\n", __FUNCTION__, pid); + + if (pid <= 0x1F) + return 1; + + if ((PidGetGroupMASK(adapter) == 0) && (PidGetGroupPID(adapter) == 0)) + return 0; + + if (PidGetStream1PID(adapter) == 0x1FFF) { + PidSetStream1PID(adapter, pid & 0xFFFF); + + FilterEnableStream1Filter(adapter, 1); + + return 1; + } + + if (PidGetStream2PID(adapter) == 0x1FFF) { + PidSetStream2PID(adapter, (pid & 0xFFFF)); + + FilterEnableStream2Filter(adapter, 1); + + return 1; + } + + if (PidGetPcrPID(adapter) == 0x1FFF) { + PidSetPcrPID(adapter, (pid & 0xFFFF)); + + FilterEnablePcrFilter(adapter, 1); + + return 1; + } + + if ((PidGetPmtPID(adapter) & 0x1FFF) == 0x1FFF) { + PidSetPmtPID(adapter, (pid & 0xFFFF)); + + FilterEnablePmtFilter(adapter, 1); + + return 1; + } + + if ((PidGetEmmPID(adapter) & 0x1FFF) == 0x1FFF) { + PidSetEmmPID(adapter, (pid & 0xFFFF)); + + FilterEnableEmmFilter(adapter, 1); + + return 1; + } + + if ((PidGetEcmPID(adapter) & 0x1FFF) == 0x1FFF) { + PidSetEcmPID(adapter, (pid & 0xFFFF)); + + FilterEnableEcmFilter(adapter, 1); + + return 1; + } + + return -1; +} + +static int RemoveHwPID(struct adapter *adapter, u32 pid) +{ + dprintk("%s: pid=%d\n", __FUNCTION__, pid); + + if (pid <= 0x1F) + return 1; + + if (PidGetStream1PID(adapter) == pid) { + PidSetStream1PID(adapter, 0x1FFF); + + return 1; + } + + if (PidGetStream2PID(adapter) == pid) { + PidSetStream2PID(adapter, 0x1FFF); + + FilterEnableStream2Filter(adapter, 0); + + return 1; + } + + if (PidGetPcrPID(adapter) == pid) { + PidSetPcrPID(adapter, 0x1FFF); + + FilterEnablePcrFilter(adapter, 0); + + return 1; + } + + if (PidGetPmtPID(adapter) == pid) { + PidSetPmtPID(adapter, 0x1FFF); + + FilterEnablePmtFilter(adapter, 0); + + return 1; + } + + if (PidGetEmmPID(adapter) == pid) { + PidSetEmmPID(adapter, 0x1FFF); + + FilterEnableEmmFilter(adapter, 0); + + return 1; + } + + if (PidGetEcmPID(adapter) == pid) { + PidSetEcmPID(adapter, 0x1FFF); + + FilterEnableEcmFilter(adapter, 0); + + return 1; + } + + return -1; +} + +static int AddPID(struct adapter *adapter, u32 pid) +{ + int i; + + dprintk("%s: pid=%d\n", __FUNCTION__, pid); + + if (pid > 0x1FFE) + return -1; + + if (CheckPID(adapter, pid) == 1) + return 1; + + for (i = 0; i < 0x27; i++) { + if (adapter->pids[i] == 0x1FFF) // find free pid filter + { + adapter->pids[i] = pid; + + if (AddHwPID(adapter, pid) < 0) + OpenWholeBandwidth(adapter); + + return 1; + } + } + + return -1; +} + +static int RemovePID(struct adapter *adapter, u32 pid) +{ + u32 i; + + dprintk("%s: pid=%d\n", __FUNCTION__, pid); + + if (pid > 0x1FFE) + return -1; + + for (i = 0; i < 0x27; i++) { + if (adapter->pids[i] == pid) { + adapter->pids[i] = 0x1FFF; + + RemoveHwPID(adapter, pid); + + return 1; + } + } + + return -1; +} + +/* dma & irq */ +static void CtrlEnableSmc(struct adapter *adapter, u32 op) +{ + if (op == 0) { + WriteRegOp(adapter, 0x208, 2, ~0x00000800, 0); + + } else { + + WriteRegOp(adapter, 0x208, 1, 0, 0x00000800); + } +} + +static void DmaEnableDisableIrq(struct adapter *adapter, u32 flag1, u32 flag2, u32 flag3) +{ + adapter->dma_ctrl = adapter->dma_ctrl & 0x000F0000; + + if (flag1 == 0) { + if (flag2 == 0) + adapter->dma_ctrl = adapter->dma_ctrl & ~0x00010000; + else + adapter->dma_ctrl = adapter->dma_ctrl | 0x00010000; + + if (flag3 == 0) + adapter->dma_ctrl = adapter->dma_ctrl & ~0x00020000; + else + adapter->dma_ctrl = adapter->dma_ctrl | 0x00020000; + + } else { + + if (flag2 == 0) + adapter->dma_ctrl = adapter->dma_ctrl & ~0x00040000; + else + adapter->dma_ctrl = adapter->dma_ctrl | 0x00040000; + + if (flag3 == 0) + adapter->dma_ctrl = adapter->dma_ctrl & ~0x00080000; + else + adapter->dma_ctrl = adapter->dma_ctrl | 0x00080000; + } +} + +static void IrqDmaEnableDisableIrq(struct adapter * adapter, u32 op) +{ + u32 value; + + value = ReadRegDW(adapter, 0x208) & 0xFFF0FFFF; + + if (op != 0) + value = value | (adapter->dma_ctrl & 0x000F0000); + + WriteRegDW(adapter, 0x208, value); +} + +/* FlexCopII has 2 dma channels. DMA1 is used to transfer TS data to + system memory. + + The DMA1 buffer is divided in 2 subbuffers of equal size. + FlexCopII will transfer TS data to one subbuffer, signal an interrupt + when the subbuffer is full and continue fillig the second subbuffer. + + For DMA1: + subbuffer size in 32-bit words is stored in the first 24 bits of + register 0x004. The last 8 bits of register 0x004 contain the number + of subbuffers. + + the first 30 bits of register 0x000 contain the address of the first + subbuffer. The last 2 bits contain 0, when dma1 is disabled and 1, + when dma1 is enabled. + + the first 30 bits of register 0x00C contain the address of the second + subbuffer. the last 2 bits contain 1. + + register 0x008 will contain the address of the subbuffer that was filled + with TS data, when FlexCopII will generate an interrupt. + + For DMA2: + subbuffer size in 32-bit words is stored in the first 24 bits of + register 0x014. The last 8 bits of register 0x014 contain the number + of subbuffers. + + the first 30 bits of register 0x010 contain the address of the first + subbuffer. The last 2 bits contain 0, when dma1 is disabled and 1, + when dma1 is enabled. + + the first 30 bits of register 0x01C contain the address of the second + subbuffer. the last 2 bits contain 1. + + register 0x018 contains the address of the subbuffer that was filled + with TS data, when FlexCopII generates an interrupt. +*/ +static int DmaInitDMA(struct adapter *adapter, u32 dma_channel) +{ + u32 subbuffers, subbufsize, subbuf0, subbuf1; + + if (dma_channel == 0) { + dprintk("%s: Initializing DMA1 channel\n", __FUNCTION__); + + subbuffers = 2; + + subbufsize = (((adapter->dmaq1.buffer_size / 2) / 4) << 8) | subbuffers; + + subbuf0 = adapter->dmaq1.bus_addr & 0xFFFFFFFC; + + subbuf1 = ((adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) & 0xFFFFFFFC) | 1; + + dprintk("%s: first subbuffer address = 0x%x\n", __FUNCTION__, subbuf0); + udelay(1000); + WriteRegDW(adapter, 0x000, subbuf0); + + dprintk("%s: subbuffer size = 0x%x\n", __FUNCTION__, (subbufsize >> 8) * 4); + udelay(1000); + WriteRegDW(adapter, 0x004, subbufsize); + + dprintk("%s: second subbuffer address = 0x%x\n", __FUNCTION__, subbuf1); + udelay(1000); + WriteRegDW(adapter, 0x00C, subbuf1); + + dprintk("%s: counter = 0x%x\n", __FUNCTION__, adapter->dmaq1.bus_addr & 0xFFFFFFFC); + WriteRegDW(adapter, 0x008, adapter->dmaq1.bus_addr & 0xFFFFFFFC); + udelay(1000); + + if (subbuffers == 0) + DmaEnableDisableIrq(adapter, 0, 1, 0); + else + DmaEnableDisableIrq(adapter, 0, 1, 1); + + IrqDmaEnableDisableIrq(adapter, 1); + + SRAMSetMediaDest(adapter, 1); + SRAMSetNetDest(adapter, 1); + SRAMSetCaiDest(adapter, 2); + SRAMSetCaoDest(adapter, 2); + } + + if (dma_channel == 1) { + dprintk("%s: Initializing DMA2 channel\n", __FUNCTION__); + + subbuffers = 2; + + subbufsize = (((adapter->dmaq2.buffer_size / 2) / 4) << 8) | subbuffers; + + subbuf0 = adapter->dmaq2.bus_addr & 0xFFFFFFFC; + + subbuf1 = ((adapter->dmaq2.bus_addr + adapter->dmaq2.buffer_size / 2) & 0xFFFFFFFC) | 1; + + dprintk("%s: first subbuffer address = 0x%x\n", __FUNCTION__, subbuf0); + udelay(1000); + WriteRegDW(adapter, 0x010, subbuf0); + + dprintk("%s: subbuffer size = 0x%x\n", __FUNCTION__, (subbufsize >> 8) * 4); + udelay(1000); + WriteRegDW(adapter, 0x014, subbufsize); + + dprintk("%s: second buffer address = 0x%x\n", __FUNCTION__, subbuf1); + udelay(1000); + WriteRegDW(adapter, 0x01C, subbuf1); + + SRAMSetCaiDest(adapter, 2); + } + + return 0; +} + +static void CtrlEnableReceiveData(struct adapter *adapter, u32 op) +{ + if (op == 0) { + WriteRegOp(adapter, 0x208, 2, ~0x00008000, 0); + + adapter->dma_status = adapter->dma_status & ~0x00000004; + + } else { + + WriteRegOp(adapter, 0x208, 1, 0, 0x00008000); + + adapter->dma_status = adapter->dma_status | 0x00000004; + } +} + +/* bit 0 of dma_mask is set to 1 if dma1 channel has to be enabled/disabled + bit 1 of dma_mask is set to 1 if dma2 channel has to be enabled/disabled +*/ +static void DmaStartStop0x2102(struct adapter *adapter, u32 dma_mask, u32 start_stop) +{ + u32 dma_enable, dma1_enable, dma2_enable; + + dprintk("%s: dma_mask=%x\n", __FUNCTION__, dma_mask); + + if (start_stop == 1) { + dprintk("%s: starting dma\n", __FUNCTION__); + + dma1_enable = 0; + dma2_enable = 0; + + if (((dma_mask & 1) != 0) && ((adapter->dma_status & 1) == 0) && (adapter->dmaq1.bus_addr != 0)) { + adapter->dma_status = adapter->dma_status | 1; + dma1_enable = 1; + } + + if (((dma_mask & 2) != 0) && ((adapter->dma_status & 2) == 0) && (adapter->dmaq2.bus_addr != 0)) { + adapter->dma_status = adapter->dma_status | 2; + dma2_enable = 1; + } + // enable dma1 and dma2 + if ((dma1_enable == 1) && (dma2_enable == 1)) { + WriteRegDW(adapter, 0x000, adapter->dmaq1.bus_addr | 1); + WriteRegDW(adapter, 0x00C, (adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) | 1); + WriteRegDW(adapter, 0x010, adapter->dmaq2.bus_addr | 1); + + CtrlEnableReceiveData(adapter, 1); + + return; + } + // enable dma1 + if ((dma1_enable == 1) && (dma2_enable == 0)) { + WriteRegDW(adapter, 0x000, adapter->dmaq1.bus_addr | 1); + WriteRegDW(adapter, 0x00C, (adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) | 1); + + CtrlEnableReceiveData(adapter, 1); + + return; + } + // enable dma2 + if ((dma1_enable == 0) && (dma2_enable == 1)) { + WriteRegDW(adapter, 0x010, adapter->dmaq2.bus_addr | 1); + + CtrlEnableReceiveData(adapter, 1); + + return; + } + // start dma + if ((dma1_enable == 0) && (dma2_enable == 0)) { + CtrlEnableReceiveData(adapter, 1); + + return; + } + + } else { + + dprintk("%s: stoping dma\n", __FUNCTION__); + + dma_enable = adapter->dma_status & 0x00000003; + + if (((dma_mask & 1) != 0) && ((adapter->dma_status & 1) != 0)) { + dma_enable = dma_enable & 0xFFFFFFFE; + } + + if (((dma_mask & 2) != 0) && ((adapter->dma_status & 2) != 0)) { + dma_enable = dma_enable & 0xFFFFFFFD; + } + //stop dma + if ((dma_enable == 0) && ((adapter->dma_status & 4) != 0)) { + CtrlEnableReceiveData(adapter, 0); + + udelay(3000); + } + //disable dma1 + if (((dma_mask & 1) != 0) && ((adapter->dma_status & 1) != 0) && (adapter->dmaq1.bus_addr != 0)) { + WriteRegDW(adapter, 0x000, adapter->dmaq1.bus_addr); + WriteRegDW(adapter, 0x00C, (adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) | 1); + + adapter->dma_status = adapter->dma_status & ~0x00000001; + } + //disable dma2 + if (((dma_mask & 2) != 0) && ((adapter->dma_status & 2) != 0) && (adapter->dmaq2.bus_addr != 0)) { + WriteRegDW(adapter, 0x010, adapter->dmaq2.bus_addr); + + adapter->dma_status = adapter->dma_status & ~0x00000002; + } + } +} + +static void OpenStream(struct adapter *adapter, u32 pid) +{ + u32 dma_mask; + + if (adapter->capturing == 0) + adapter->capturing = 1; + + FilterEnableMaskFilter(adapter, 1); + + AddPID(adapter, pid); + + dprintk("%s: adapter->dma_status=%x\n", __FUNCTION__, adapter->dma_status); + + if ((adapter->dma_status & 7) != 7) { + dma_mask = 0; + + if (((adapter->dma_status & 0x10000000) != 0) && ((adapter->dma_status & 1) == 0)) { + dma_mask = dma_mask | 1; + + adapter->dmaq1.head = 0; + adapter->dmaq1.tail = 0; + + memset(adapter->dmaq1.buffer, 0, adapter->dmaq1.buffer_size); + } + + if (((adapter->dma_status & 0x20000000) != 0) && ((adapter->dma_status & 2) == 0)) { + dma_mask = dma_mask | 2; + + adapter->dmaq2.head = 0; + adapter->dmaq2.tail = 0; + } + + if (dma_mask != 0) { + IrqDmaEnableDisableIrq(adapter, 1); + + DmaStartStop0x2102(adapter, dma_mask, 1); + } + } +} + +static void CloseStream(struct adapter *adapter, u32 pid) +{ + u32 dma_mask; + + if (adapter->capturing != 0) + adapter->capturing = 0; + + dprintk("%s: dma_status=%x\n", __FUNCTION__, adapter->dma_status); + + dma_mask = 0; + + if ((adapter->dma_status & 1) != 0) + dma_mask = dma_mask | 0x00000001; + if ((adapter->dma_status & 2) != 0) + dma_mask = dma_mask | 0x00000002; + + if (dma_mask != 0) { + DmaStartStop0x2102(adapter, dma_mask, 0); + } + + RemovePID(adapter, pid); +} + +static void InterruptServiceDMA1(struct adapter *adapter) +{ + struct dvb_demux *dvbdmx = &adapter->demux; + struct packet_header packet_header; + + int nCurDmaCounter; + u32 nNumBytesParsed; + u32 nNumNewBytesTransferred; + u32 dwDefaultPacketSize = 188; + u8 gbTmpBuffer[188]; + u8 *pbDMABufCurPos; + + nCurDmaCounter = readl(adapter->io_mem + 0x008) - adapter->dmaq1.bus_addr; + nCurDmaCounter = (nCurDmaCounter / dwDefaultPacketSize) * dwDefaultPacketSize; + + if ((nCurDmaCounter < 0) || (nCurDmaCounter > adapter->dmaq1.buffer_size)) { + dprintk("%s: dma counter outside dma buffer\n", __FUNCTION__); + return; + } + + adapter->dmaq1.head = nCurDmaCounter; + + if (adapter->dmaq1.tail <= nCurDmaCounter) { + nNumNewBytesTransferred = nCurDmaCounter - adapter->dmaq1.tail; + + } else { + + nNumNewBytesTransferred = (adapter->dmaq1.buffer_size - adapter->dmaq1.tail) + nCurDmaCounter; + } + +// dprintk("%s: nCurDmaCounter = %d\n" , __FUNCTION__, nCurDmaCounter); +// dprintk("%s: dmaq1.tail = %d\n" , __FUNCTION__, adapter->dmaq1.tail): +// dprintk("%s: BytesTransferred = %d\n" , __FUNCTION__, nNumNewBytesTransferred); + + if (nNumNewBytesTransferred < dwDefaultPacketSize) + return; + + nNumBytesParsed = 0; + + while (nNumBytesParsed < nNumNewBytesTransferred) { + pbDMABufCurPos = adapter->dmaq1.buffer + adapter->dmaq1.tail; + + if (adapter->dmaq1.buffer + adapter->dmaq1.buffer_size < adapter->dmaq1.buffer + adapter->dmaq1.tail + 188) { + memcpy(gbTmpBuffer, adapter->dmaq1.buffer + adapter->dmaq1.tail, adapter->dmaq1.buffer_size - adapter->dmaq1.tail); + memcpy(gbTmpBuffer + (adapter->dmaq1.buffer_size - adapter->dmaq1.tail), adapter->dmaq1.buffer, (188 - (adapter->dmaq1.buffer_size - adapter->dmaq1.tail))); + + pbDMABufCurPos = gbTmpBuffer; + } + + if (adapter->capturing != 0) { + u32 *dq = (u32 *) pbDMABufCurPos; + + packet_header.sync_byte = *dq & 0x000000FF; + packet_header.transport_error_indicator = *dq & 0x00008000; + packet_header.payload_unit_start_indicator = *dq & 0x00004000; + packet_header.transport_priority = *dq & 0x00002000; + packet_header.pid = ((*dq & 0x00FF0000) >> 0x10) | (*dq & 0x00001F00); + packet_header.transport_scrambling_control = *dq >> 0x1E; + packet_header.adaptation_field_control = (*dq & 0x30000000) >> 0x1C; + packet_header.continuity_counter = (*dq & 0x0F000000) >> 0x18; + + if ((packet_header.sync_byte == 0x47) && (packet_header.transport_error_indicator == 0) && (packet_header.pid != 0x1FFF)) { + if (CheckPID(adapter, packet_header.pid & 0x0000FFFF) != 0) { + dvb_dmx_swfilter_packets(dvbdmx, pbDMABufCurPos, dwDefaultPacketSize / 188); + + } else { + +// dprintk("%s: pid=%x\n", __FUNCTION__, packet_header.pid); + } + } + } + + nNumBytesParsed = nNumBytesParsed + dwDefaultPacketSize; + + adapter->dmaq1.tail = adapter->dmaq1.tail + dwDefaultPacketSize; + + if (adapter->dmaq1.tail >= adapter->dmaq1.buffer_size) + adapter->dmaq1.tail = adapter->dmaq1.tail - adapter->dmaq1.buffer_size; + }; +} + +static void InterruptServiceDMA2(struct adapter *adapter) +{ + printk("%s:\n", __FUNCTION__); +} + +static irqreturn_t isr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct adapter *tmp = dev_id; + + u32 value; + +// dprintk("%s:\n", __FUNCTION__); + + spin_lock_irq(&tmp->lock); + + if (0 == ((value = ReadRegDW(tmp, 0x20C)) & 0x0F)) { + spin_unlock_irq(&tmp->lock); + return IRQ_NONE; + } + + while (value != 0) { + if ((value & 0x03) != 0) + InterruptServiceDMA1(tmp); + if ((value & 0x0C) != 0) + InterruptServiceDMA2(tmp); + value = ReadRegDW(tmp, 0x20C) & 0x0F; + } + + spin_unlock_irq(&tmp->lock); + return IRQ_HANDLED; +} + +static void Initdmaqueue(struct adapter *adapter) +{ + dma_addr_t dma_addr; + + if (adapter->dmaq1.buffer != 0) + return; + + adapter->dmaq1.head = 0; + adapter->dmaq1.tail = 0; + adapter->dmaq1.buffer = 0; + + adapter->dmaq1.buffer = pci_alloc_consistent(adapter->pdev, SizeOfBufDMA1 + 0x80, &dma_addr); + + if (adapter->dmaq1.buffer != 0) { + memset(adapter->dmaq1.buffer, 0, SizeOfBufDMA1); + + adapter->dmaq1.bus_addr = dma_addr; + adapter->dmaq1.buffer_size = SizeOfBufDMA1; + + DmaInitDMA(adapter, 0); + + adapter->dma_status = adapter->dma_status | 0x10000000; + + dprintk("%s: allocated dma buffer at 0x%x, length=%d\n", __FUNCTION__, (int) adapter->dmaq1.buffer, SizeOfBufDMA1); + + } else { + + adapter->dma_status = adapter->dma_status & ~0x10000000; + } + + if (adapter->dmaq2.buffer != 0) + return; + + adapter->dmaq2.head = 0; + adapter->dmaq2.tail = 0; + adapter->dmaq2.buffer = 0; + + adapter->dmaq2.buffer = pci_alloc_consistent(adapter->pdev, SizeOfBufDMA2 + 0x80, &dma_addr); + + if (adapter->dmaq2.buffer != 0) { + memset(adapter->dmaq2.buffer, 0, SizeOfBufDMA2); + + adapter->dmaq2.bus_addr = dma_addr; + adapter->dmaq2.buffer_size = SizeOfBufDMA2; + + DmaInitDMA(adapter, 1); + + adapter->dma_status = adapter->dma_status | 0x20000000; + + dprintk("%s: allocated dma buffer at 0x%x, length=%d\n", __FUNCTION__, (int) adapter->dmaq2.buffer, (int) SizeOfBufDMA2); + + } else { + + adapter->dma_status = adapter->dma_status & ~0x20000000; + } +} + +static void Freedmaqueue(struct adapter *adapter) +{ + if (adapter->dmaq1.buffer != 0) { + pci_free_consistent(adapter->pdev, SizeOfBufDMA1 + 0x80, adapter->dmaq1.buffer, adapter->dmaq1.bus_addr); + + adapter->dmaq1.bus_addr = 0; + adapter->dmaq1.head = 0; + adapter->dmaq1.tail = 0; + adapter->dmaq1.buffer_size = 0; + adapter->dmaq1.buffer = 0; + } + + if (adapter->dmaq2.buffer != 0) { + pci_free_consistent(adapter->pdev, SizeOfBufDMA2 + 0x80, adapter->dmaq2.buffer, adapter->dmaq2.bus_addr); + + adapter->dmaq2.bus_addr = 0; + adapter->dmaq2.head = 0; + adapter->dmaq2.tail = 0; + adapter->dmaq2.buffer_size = 0; + adapter->dmaq2.buffer = 0; + } +} + +static void FreeAdapterObject(struct adapter *adapter) +{ + dprintk("%s:\n", __FUNCTION__); + + CloseStream(adapter, 0); + + if (adapter->irq != 0) + free_irq(adapter->irq, adapter); + + Freedmaqueue(adapter); + + if (adapter->io_mem != 0) + iounmap((void *) adapter->io_mem); + + if (adapter != 0) + kfree(adapter); +} + +static struct pci_driver skystar2_pci_driver; + +static int ClaimAdapter(struct adapter *adapter) +{ + struct pci_dev *pdev = adapter->pdev; + + u16 var; + + if (!request_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1), skystar2_pci_driver.name)) + return -EBUSY; + + if (!request_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0), skystar2_pci_driver.name)) + return -EBUSY; + + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &adapter->card_revision); + + dprintk("%s: card revision %x \n", __FUNCTION__, adapter->card_revision); + + if (pci_enable_device(pdev)) + return -EIO; + + pci_read_config_word(pdev, 4, &var); + + if ((var & 4) == 0) + pci_set_master(pdev); + + adapter->io_port = pdev->resource[1].start; + + adapter->io_mem = (u32) ioremap(pdev->resource[0].start, 0x800); + + if (adapter->io_mem == 0) { + dprintk("%s: can not map io memory\n", __FUNCTION__); + + return 2; + } + + dprintk("%s: io memory maped at %x\n", __FUNCTION__, adapter->io_mem); + + return 1; +} + +/* +static int SLL_reset_FlexCOP(struct adapter *adapter) +{ + WriteRegDW(adapter, 0x208, 0); + WriteRegDW(adapter, 0x210, 0xB2FF); + + return 0; +} +*/ + +static int DriverInitialize(struct pci_dev * pdev) +{ + struct adapter *adapter; + u32 tmp; + u8 key[16]; + + if (!(adapter = kmalloc(sizeof(struct adapter), GFP_KERNEL))) { + dprintk("%s: out of memory!\n", __FUNCTION__); + + return -ENOMEM; + } + + memset(adapter, 0, sizeof(struct adapter)); + + pci_set_drvdata(pdev,adapter); + + adapter->pdev = pdev; + adapter->irq = pdev->irq; + + if ((ClaimAdapter(adapter)) != 1) { + FreeAdapterObject(adapter); + + return -ENODEV; + } + + IrqDmaEnableDisableIrq(adapter, 0); + + if (request_irq(pdev->irq, isr, 0x4000000, "Skystar2", adapter) != 0) { + dprintk("%s: unable to allocate irq=%d !\n", __FUNCTION__, pdev->irq); + + FreeAdapterObject(adapter); + + return -ENODEV; + } + + ReadRegDW(adapter, 0x208); + WriteRegDW(adapter, 0x208, 0); + WriteRegDW(adapter, 0x210, 0xB2FF); + WriteRegDW(adapter, 0x208, 0x40); + + InitPIDsInfo(adapter); + + PidSetGroupPID(adapter, 0); + PidSetGroupMASK(adapter, 0x1FE0); + PidSetStream1PID(adapter, 0x1FFF); + PidSetStream2PID(adapter, 0x1FFF); + PidSetPmtPID(adapter, 0x1FFF); + PidSetPcrPID(adapter, 0x1FFF); + PidSetEcmPID(adapter, 0x1FFF); + PidSetEmmPID(adapter, 0x1FFF); + + Initdmaqueue(adapter); + + if ((adapter->dma_status & 0x30000000) == 0) { + FreeAdapterObject(adapter); + + return -ENODEV; + } + + adapter->b2c2_revision = (ReadRegDW(adapter, 0x204) >> 0x18); + + if ((adapter->b2c2_revision != 0x82) && (adapter->b2c2_revision != 0xC3)) + if (adapter->b2c2_revision != 0x82) { + dprintk("%s: The revision of the FlexCopII chip on your card is - %d\n", __FUNCTION__, adapter->b2c2_revision); + dprintk("%s: This driver works now only with FlexCopII(rev.130) and FlexCopIIB(rev.195).\n", __FUNCTION__); + + FreeAdapterObject(adapter); + + return -ENODEV; + } + + tmp = ReadRegDW(adapter, 0x204); + + WriteRegDW(adapter, 0x204, 0); + mdelay(20); + + WriteRegDW(adapter, 0x204, tmp); + mdelay(10); + + tmp = ReadRegDW(adapter, 0x308); + WriteRegDW(adapter, 0x308, 0x4000 | tmp); + + adapter->dwSramType = 0x10000; + + SLL_detectSramSize(adapter); + + dprintk("%s sram length = %d, sram type= %x\n", __FUNCTION__, SRAM_length(adapter), adapter->dwSramType); + + SRAMSetMediaDest(adapter, 1); + SRAMSetNetDest(adapter, 1); + + CtrlEnableSmc(adapter, 0); + + SRAMSetCaiDest(adapter, 2); + SRAMSetCaoDest(adapter, 2); + + DmaEnableDisableIrq(adapter, 1, 0, 0); + + if (EEPROM_getMacAddr(adapter, 0, adapter->mac_addr) != 0) { + printk("%s MAC address = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x \n", __FUNCTION__, adapter->mac_addr[0], adapter->mac_addr[1], adapter->mac_addr[2], adapter->mac_addr[3], adapter->mac_addr[4], adapter->mac_addr[5], adapter->mac_addr[6], adapter->mac_addr[7] + ); + + CASetMacDstAddrFilter(adapter, adapter->mac_addr); + CtrlEnableMAC(adapter, 1); + } + + EEPROM_readKey(adapter, key, 16); + + printk("%s key = \n %02x %02x %02x %02x \n %02x %02x %02x %02x \n %02x %02x %02x %02x \n %02x %02x %02x %02x \n", __FUNCTION__, key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7], key[8], key[9], key[10], key[11], key[12], key[13], key[14], key[15]); + + adapter->lock = SPIN_LOCK_UNLOCKED; + + return 0; +} + +static void DriverHalt(struct pci_dev *pdev) +{ + struct adapter *adapter; + + adapter = pci_get_drvdata(pdev); + + IrqDmaEnableDisableIrq(adapter, 0); + + CtrlEnableReceiveData(adapter, 0); + + FreeAdapterObject(adapter); + + pci_set_drvdata(pdev, NULL); + + release_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1)); + + release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); +} + +static int dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + struct adapter *adapter = (struct adapter *) dvbdmx->priv; + + dprintk("%s: PID=%d, type=%d\n", __FUNCTION__, dvbdmxfeed->pid, dvbdmxfeed->type); + + OpenStream(adapter, dvbdmxfeed->pid); + + return 0; +} + +static int dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + struct adapter *adapter = (struct adapter *) dvbdmx->priv; + + dprintk("%s: PID=%d, type=%d\n", __FUNCTION__, dvbdmxfeed->pid, dvbdmxfeed->type); + + CloseStream(adapter, dvbdmxfeed->pid); + + return 0; +} + +/* lnb control */ +static void set_tuner_tone(struct adapter *adapter, u8 tone) +{ + u16 wzHalfPeriodFor45MHz[] = { 0x01FF, 0x0154, 0x00FF, 0x00CC }; + u16 ax; + + dprintk("%s: %u\n", __FUNCTION__, tone); + + switch (tone) { + case 1: + ax = wzHalfPeriodFor45MHz[0]; + break; + case 2: + ax = wzHalfPeriodFor45MHz[1]; + break; + case 3: + ax = wzHalfPeriodFor45MHz[2]; + break; + case 4: + ax = wzHalfPeriodFor45MHz[3]; + break; + + default: + ax = 0; + } + + if (ax != 0) { + WriteRegDW(adapter, 0x200, ((ax << 0x0F) + (ax & 0x7FFF)) | 0x40000000); + + } else { + + WriteRegDW(adapter, 0x200, 0x40FF8000); + } +} + +static void set_tuner_polarity(struct adapter *adapter, u8 polarity) +{ + u32 var; + + dprintk("%s : polarity = %u \n", __FUNCTION__, polarity); + + var = ReadRegDW(adapter, 0x204); + + if (polarity == 0) { + dprintk("%s: LNB power off\n", __FUNCTION__); + var = var | 1; + }; + + if (polarity == 1) { + var = var & ~1; + var = var & ~4; + }; + + if (polarity == 2) { + var = var & ~1; + var = var | 4; + } + + WriteRegDW(adapter, 0x204, var); +} + +static int flexcop_diseqc_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) +{ + struct adapter *adapter = fe->before_after_data; + + switch (cmd) { + case FE_SLEEP: + { + printk("%s: FE_SLEEP\n", __FUNCTION__); + + set_tuner_polarity(adapter, 0); + + // return -EOPNOTSUPP, to make DVB core also send "FE_SLEEP" command to frontend. + return -EOPNOTSUPP; + } + + case FE_SET_VOLTAGE: + { + dprintk("%s: FE_SET_VOLTAGE\n", __FUNCTION__); + + switch ((fe_sec_voltage_t) arg) { + case SEC_VOLTAGE_13: + + printk("%s: SEC_VOLTAGE_13, %x\n", __FUNCTION__, SEC_VOLTAGE_13); + + set_tuner_polarity(adapter, 1); + + break; + + case SEC_VOLTAGE_18: + + printk("%s: SEC_VOLTAGE_18, %x\n", __FUNCTION__, SEC_VOLTAGE_18); + + set_tuner_polarity(adapter, 2); + + break; + + default: + + return -EINVAL; + }; + + break; + } + + case FE_SET_TONE: + { + dprintk("%s: FE_SET_TONE\n", __FUNCTION__); + + switch ((fe_sec_tone_mode_t) arg) { + case SEC_TONE_ON: + + printk("%s: SEC_TONE_ON, %x\n", __FUNCTION__, SEC_TONE_ON); + + set_tuner_tone(adapter, 1); + + break; + + case SEC_TONE_OFF: + + printk("%s: SEC_TONE_OFF, %x\n", __FUNCTION__, SEC_TONE_OFF); + + set_tuner_tone(adapter, 0); + + break; + + default: + + return -EINVAL; + }; + + break; + } + + default: + + return -EOPNOTSUPP; + }; + + return 0; +} + +static int skystar2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + struct adapter *adapter; + struct dvb_adapter *dvb_adapter; + struct dvb_demux *dvbdemux; + + int ret; + + if (pdev == NULL) + return -ENODEV; + + if (DriverInitialize(pdev) != 0) + return -ENODEV; + + dvb_register_adapter(&dvb_adapter, skystar2_pci_driver.name); + + if (dvb_adapter == NULL) { + printk("%s: Error registering DVB adapter\n", __FUNCTION__); + + DriverHalt(pdev); + + return -ENODEV; + } + + adapter = (struct adapter *) pci_get_drvdata(pdev); + + adapter->dvb_adapter = dvb_adapter; + + init_MUTEX(&adapter->i2c_sem); + + adapter->i2c_bus = dvb_register_i2c_bus(master_xfer, adapter, adapter->dvb_adapter, 0); + + if (!adapter->i2c_bus) + return -ENOMEM; + + dvb_add_frontend_ioctls(adapter->dvb_adapter, flexcop_diseqc_ioctl, NULL, adapter); + + dvbdemux = &adapter->demux; + + dvbdemux->priv = (void *) adapter; + dvbdemux->filternum = 32; + dvbdemux->feednum = 32; + dvbdemux->start_feed = dvb_start_feed; + dvbdemux->stop_feed = dvb_stop_feed; + dvbdemux->write_to_decoder = 0; + dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING); + + dvb_dmx_init(&adapter->demux); + + adapter->hw_frontend.source = DMX_FRONTEND_0; + + adapter->dmxdev.filternum = 32; + adapter->dmxdev.demux = &dvbdemux->dmx; + adapter->dmxdev.capabilities = 0; + + dvb_dmxdev_init(&adapter->dmxdev, adapter->dvb_adapter); + + ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &adapter->hw_frontend); + if (ret < 0) + return ret; + + adapter->mem_frontend.source = DMX_MEMORY_FE; + + ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &adapter->mem_frontend); + if (ret < 0) + return ret; + + ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, &adapter->hw_frontend); + if (ret < 0) + return ret; + + dvb_net_init(adapter->dvb_adapter, &adapter->dvbnet, &dvbdemux->dmx); + return 0; +} + +static void skystar2_remove(struct pci_dev *pdev) +{ + struct adapter *adapter; + struct dvb_demux *dvbdemux; + + if (pdev == NULL) + return; + + adapter = pci_get_drvdata(pdev); + + if (adapter != NULL) { + dvb_net_release(&adapter->dvbnet); + dvbdemux = &adapter->demux; + + dvbdemux->dmx.close(&dvbdemux->dmx); + dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &adapter->hw_frontend); + dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &adapter->mem_frontend); + + dvb_dmxdev_release(&adapter->dmxdev); + dvb_dmx_release(&adapter->demux); + + if (adapter->dvb_adapter != NULL) { + dvb_remove_frontend_ioctls(adapter->dvb_adapter, flexcop_diseqc_ioctl, NULL); + + if (adapter->i2c_bus != NULL) + dvb_unregister_i2c_bus(master_xfer, adapter->i2c_bus->adapter, adapter->i2c_bus->id); + + dvb_unregister_adapter(adapter->dvb_adapter); + } + + DriverHalt(pdev); + } +} + +static struct pci_device_id skystar2_pci_tbl[] = { + {0x000013D0, 0x00002103, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000}, + {0,}, +}; + +static struct pci_driver skystar2_pci_driver = { + .name = "Technisat SkyStar2 driver", + .id_table = skystar2_pci_tbl, + .probe = skystar2_probe, + .remove = skystar2_remove, +}; + +static int skystar2_init(void) +{ + return pci_module_init(&skystar2_pci_driver); +} + +static void skystar2_cleanup(void) +{ + pci_unregister_driver(&skystar2_pci_driver); +} + +module_init(skystar2_init); +module_exit(skystar2_cleanup); + +MODULE_DESCRIPTION("Technisat SkyStar2 DVB PCI Driver"); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c --- a/drivers/media/dvb/dvb-core/dvb_demux.c Sat Jul 19 12:54:23 2003 +++ b/drivers/media/dvb/dvb-core/dvb_demux.c Sat Jul 19 12:54:23 2003 @@ -403,13 +403,16 @@ { int p = 0,i, j; + spin_lock(&demux->lock); + if ((i = demux->tsbufp)) { if (count < (j=188-i)) { memcpy(&demux->tsbuf[i], buf, count); demux->tsbufp += count; - return; + goto bailout; } memcpy(&demux->tsbuf[i], buf, j); + if (demux->tsbuf[0] == 0x47) dvb_dmx_swfilter_packet(demux, demux->tsbuf); demux->tsbufp = 0; p += j; @@ -424,11 +427,14 @@ i = count-p; memcpy(demux->tsbuf, buf+p, i); demux->tsbufp=i; - return; + goto bailout; } } else p++; } + +bailout: + spin_unlock(&demux->lock); } @@ -1030,9 +1036,11 @@ if (down_interruptible (&dvbdemux->mutex)) return -ERESTARTSYS; - dvb_dmx_swfilter(dvbdemux, buf, count); up(&dvbdemux->mutex); + + if (signal_pending(current)) + return -EINTR; return count; } @@ -1110,8 +1118,8 @@ return 0; } -int -dvb_dmx_init(struct dvb_demux *dvbdemux) + +int dvb_dmx_init(struct dvb_demux *dvbdemux) { int i, err; struct dmx_demux *dmx = &dvbdemux->dmx; @@ -1181,8 +1189,8 @@ return 0; } -int -dvb_dmx_release(struct dvb_demux *dvbdemux) + +int dvb_dmx_release(struct dvb_demux *dvbdemux) { struct dmx_demux *dmx = &dvbdemux->dmx; diff -Nru a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c --- a/drivers/media/dvb/dvb-core/dvb_frontend.c Sat Jul 19 12:54:23 2003 +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c Sat Jul 19 12:54:23 2003 @@ -263,8 +263,14 @@ if (flags & O_NONBLOCK) return -EWOULDBLOCK; + up(&fe->sem); + ret = wait_event_interruptible (events->wait_queue, events->eventw != events->eventr); + + if (down_interruptible (&fe->sem)) + return -ERESTARTSYS; + if (ret < 0) return ret; } diff -Nru a/drivers/media/dvb/dvb-core/dvb_functions.c b/drivers/media/dvb/dvb-core/dvb_functions.c --- a/drivers/media/dvb/dvb-core/dvb_functions.c Sat Jul 19 12:54:27 2003 +++ b/drivers/media/dvb/dvb-core/dvb_functions.c Sat Jul 19 12:54:27 2003 @@ -1,11 +1,11 @@ #include -#include -#include -#include #include +#include +#include #include #include #include +#include #include void dvb_kernel_thread_setup (const char *thread_name) diff -Nru a/drivers/media/dvb/dvb-core/dvb_functions.h b/drivers/media/dvb/dvb-core/dvb_functions.h --- a/drivers/media/dvb/dvb-core/dvb_functions.h Sat Jul 19 12:54:25 2003 +++ b/drivers/media/dvb/dvb-core/dvb_functions.h Sat Jul 19 12:54:25 2003 @@ -1,6 +1,8 @@ #ifndef __DVB_FUNCTIONS_H__ #define __DVB_FUNCTIONS_H__ +#include + /** * a sleeping delay function, waits i ms * diff -Nru a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c --- a/drivers/media/dvb/dvb-core/dvb_net.c Sat Jul 19 12:54:23 2003 +++ b/drivers/media/dvb/dvb-core/dvb_net.c Sat Jul 19 12:54:23 2003 @@ -24,22 +24,25 @@ * */ -#include -#include -#include -#include -#include -#include - #include +#include #include "dvb_demux.h" #include "dvb_net.h" #include "dvb_functions.h" + +#if 1 +#define dprintk(x...) printk(x) +#else +#define dprintk(x...) +#endif + + #define DVB_NET_MULTICAST_MAX 10 struct dvb_net_priv { + int in_use; struct net_device_stats stats; char name[6]; u16 pid; @@ -49,10 +52,17 @@ int multi_num; struct dmx_section_filter *multi_secfilter[DVB_NET_MULTICAST_MAX]; unsigned char multi_macs[DVB_NET_MULTICAST_MAX][6]; - int mode; + int rx_mode; +#define RX_MODE_UNI 0 +#define RX_MODE_MULTI 1 +#define RX_MODE_ALL_MULTI 2 +#define RX_MODE_PROMISC 3 + struct work_struct set_multicast_list_wq; + struct work_struct restart_net_feed_wq; }; -/* + +/** * Determine the packet's protocol ID. The rule here is that we * assume 802.3 if the type field is short enough to be a length. * This is normal practice and works for any 'now in use' protocol. @@ -60,8 +70,8 @@ * stolen from eth.c out of the linux kernel, hacked for dvb-device * by Michael Holzt */ - -unsigned short my_eth_type_trans(struct sk_buff *skb, struct net_device *dev) +static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb, + struct net_device *dev) { struct ethhdr *eth; unsigned char *rawp; @@ -70,8 +80,7 @@ skb_pull(skb,dev->hard_header_len); eth= skb->mac.ethernet; - if(*eth->h_dest&1) - { + if (*eth->h_dest & 1) { if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0) skb->pkt_type=PACKET_BROADCAST; else @@ -83,7 +92,7 @@ rawp = skb->data; - /* + /** * This is a magic hack to spot IPX packets. Older Novell breaks * the protocol design and runs IPX over 802.3 without an 802.2 LLC * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This @@ -92,42 +101,73 @@ if (*(unsigned short *)rawp == 0xFFFF) return htons(ETH_P_802_3); - /* + /** * Real 802.2 LLC */ return htons(ETH_P_802_2); } -static void dvb_net_sec(struct net_device *dev, const u8 *pkt, int pkt_len) + +static void dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len) { u8 *eth; struct sk_buff *skb; - if (pkt_len<13) { - printk("%s: IP/MPE packet length = %d too small.\n", dev->name, pkt_len); + /* note: pkt_len includes a 32bit checksum */ + if (pkt_len < 16) { + printk("%s: IP/MPE packet length = %d too small.\n", + dev->name, pkt_len); + ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; + ((struct dvb_net_priv *) dev->priv)->stats.rx_length_errors++; + return; + } + if ((pkt[5] & 0xfd) != 0xc1) { + /* drop scrambled or broken packets */ + ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; + ((struct dvb_net_priv *) dev->priv)->stats.rx_crc_errors++; return; } - skb = dev_alloc_skb(pkt_len+2); - if (skb == NULL) { - printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", - dev->name); + if (pkt[5] & 0x02) { + //FIXME: handle LLC/SNAP ((struct dvb_net_priv *)dev->priv)->stats.rx_dropped++; return; } - eth=(u8 *) skb_put(skb, pkt_len+2); - memcpy(eth+14, (void*)pkt+12, pkt_len-12); + if (pkt[7]) { + /* FIXME: assemble datagram from multiple sections */ + ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; + ((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++; + return; + } + /* we have 14 byte ethernet header (ip header follows); + * 12 byte MPE header; 4 byte checksum; + 2 byte alignment + */ + if (!(skb = dev_alloc_skb(pkt_len - 4 - 12 + 14 + 2))) { + //printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); + ((struct dvb_net_priv *) dev->priv)->stats.rx_dropped++; + return; + } + skb_reserve(skb, 2); /* longword align L3 header */ + skb->dev = dev; + + /* copy L3 payload */ + eth = (u8 *) skb_put(skb, pkt_len - 12 - 4 + 14); + memcpy(eth + 14, pkt + 12, pkt_len - 12 - 4); + + /* create ethernet header: */ eth[0]=pkt[0x0b]; eth[1]=pkt[0x0a]; eth[2]=pkt[0x09]; eth[3]=pkt[0x08]; eth[4]=pkt[0x04]; eth[5]=pkt[0x03]; + eth[6]=eth[7]=eth[8]=eth[9]=eth[10]=eth[11]=0; - eth[12]=0x08; eth[13]=0x00; - skb->protocol=my_eth_type_trans(skb,dev); - skb->dev=dev; + eth[12] = 0x08; /* ETH_P_IP */ + eth[13] = 0x00; + + skb->protocol = dvb_net_eth_type_trans(skb, dev); ((struct dvb_net_priv *)dev->priv)->stats.rx_packets++; ((struct dvb_net_priv *)dev->priv)->stats.rx_bytes+=skb->len; @@ -141,9 +181,11 @@ { struct net_device *dev=(struct net_device *) filter->priv; - /* FIXME: this only works if exactly one complete section is - delivered in buffer1 only */ - dvb_net_sec(dev, buffer1, buffer1_len); + /** + * we rely on the DVB API definition where exactly one complete + * section is delivered in buffer1 + */ + dvb_net_sec (dev, (u8*) buffer1, buffer1_len); return 0; } @@ -178,24 +220,27 @@ memset((*secfilter)->filter_mode, 0xff, DMX_MAX_FILTER_SIZE); (*secfilter)->filter_value[0]=0x3e; - (*secfilter)->filter_mask[0]=0xff; - (*secfilter)->filter_value[3]=mac[5]; - (*secfilter)->filter_mask[3]=mac_mask[5]; (*secfilter)->filter_value[4]=mac[4]; - (*secfilter)->filter_mask[4]=mac_mask[4]; (*secfilter)->filter_value[8]=mac[3]; - (*secfilter)->filter_mask[8]=mac_mask[3]; (*secfilter)->filter_value[9]=mac[2]; - (*secfilter)->filter_mask[9]=mac_mask[2]; - (*secfilter)->filter_value[10]=mac[1]; - (*secfilter)->filter_mask[10]=mac_mask[1]; (*secfilter)->filter_value[11]=mac[0]; + + (*secfilter)->filter_mask[0] = 0xff; + (*secfilter)->filter_mask[3] = mac_mask[5]; + (*secfilter)->filter_mask[4] = mac_mask[4]; + (*secfilter)->filter_mask[8] = mac_mask[3]; + (*secfilter)->filter_mask[9] = mac_mask[2]; + (*secfilter)->filter_mask[10] = mac_mask[1]; (*secfilter)->filter_mask[11]=mac_mask[0]; - printk("%s: filter mac=%02x %02x %02x %02x %02x %02x\n", + dprintk("%s: filter mac=%02x %02x %02x %02x %02x %02x\n", dev->name, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + dprintk("%s: filter mask=%02x %02x %02x %02x %02x %02x\n", + dev->name, mac_mask[0], mac_mask[1], mac_mask[2], + mac_mask[3], mac_mask[4], mac_mask[5]); + return 0; } @@ -206,46 +251,57 @@ struct dmx_demux *demux = priv->demux; unsigned char *mac = (unsigned char *) dev->dev_addr; + dprintk("%s: rx_mode %i\n", __FUNCTION__, priv->rx_mode); + if (priv->secfeed || priv->secfilter || priv->multi_secfilter[0]) + printk("%s: BUG %d\n", __FUNCTION__, __LINE__); + priv->secfeed=0; priv->secfilter=0; + dprintk("%s: alloc secfeed\n", __FUNCTION__); ret=demux->allocate_section_feed(demux, &priv->secfeed, dvb_net_callback); if (ret<0) { - printk("%s: could not get section feed\n", dev->name); + printk("%s: could not allocate section feed\n", dev->name); return ret; } - ret=priv->secfeed->set(priv->secfeed, priv->pid, 32768, 0, 0); + ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 0, 1); + if (ret<0) { printk("%s: could not set section feed\n", dev->name); - priv->demux-> - release_section_feed(priv->demux, priv->secfeed); + priv->demux->release_section_feed(priv->demux, priv->secfeed); priv->secfeed=0; return ret; } - /* fixme: is this correct? */ - try_module_get(THIS_MODULE); - if (priv->mode<3) + if (priv->rx_mode != RX_MODE_PROMISC) { + dprintk("%s: set secfilter\n", __FUNCTION__); dvb_net_filter_set(dev, &priv->secfilter, mac, mask_normal); + } - switch (priv->mode) { - case 1: - for (i=0; imulti_num; i++) + switch (priv->rx_mode) { + case RX_MODE_MULTI: + for (i = 0; i < priv->multi_num; i++) { + dprintk("%s: set multi_secfilter[%d]\n", __FUNCTION__, i); dvb_net_filter_set(dev, &priv->multi_secfilter[i], priv->multi_macs[i], mask_normal); + } break; - case 2: + case RX_MODE_ALL_MULTI: priv->multi_num=1; - dvb_net_filter_set(dev, &priv->multi_secfilter[0], mac_allmulti, mask_allmulti); + dprintk("%s: set multi_secfilter[0]\n", __FUNCTION__); + dvb_net_filter_set(dev, &priv->multi_secfilter[0], + mac_allmulti, mask_allmulti); break; - case 3: + case RX_MODE_PROMISC: priv->multi_num=0; + dprintk("%s: set secfilter\n", __FUNCTION__); dvb_net_filter_set(dev, &priv->secfilter, mac, mask_promisc); break; } + dprintk("%s: start filtering\n", __FUNCTION__); priv->secfeed->start_filtering(priv->secfeed); return 0; } @@ -255,89 +311,93 @@ struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv; int i; + dprintk("%s\n", __FUNCTION__); if (priv->secfeed) { - if (priv->secfeed->is_filtering) + if (priv->secfeed->is_filtering) { + dprintk("%s: stop secfeed\n", __FUNCTION__); priv->secfeed->stop_filtering(priv->secfeed); - if (priv->secfilter) - priv->secfeed-> - release_filter(priv->secfeed, + } + + if (priv->secfilter) { + dprintk("%s: release secfilter\n", __FUNCTION__); + priv->secfeed->release_filter(priv->secfeed, priv->secfilter); priv->secfilter=0; + } for (i=0; imulti_num; i++) { - if (priv->multi_secfilter[i]) - priv->secfeed-> - release_filter(priv->secfeed, + if (priv->multi_secfilter[i]) { + dprintk("%s: release multi_filter[%d]\n", __FUNCTION__, i); + priv->secfeed->release_filter(priv->secfeed, priv->multi_secfilter[i]); priv->multi_secfilter[i]=0; } - priv->demux-> - release_section_feed(priv->demux, priv->secfeed); + } + + priv->demux->release_section_feed(priv->demux, priv->secfeed); priv->secfeed=0; - /* fixme: is this correct? */ - module_put(THIS_MODULE); } else printk("%s: no feed to stop\n", dev->name); } -static int dvb_add_mc_filter(struct net_device *dev, struct dev_mc_list *mc) + +static int dvb_set_mc_filter (struct net_device *dev, struct dev_mc_list *mc) { struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv; - int ret; - if (priv->multi_num >= DVB_NET_MULTICAST_MAX) + if (priv->multi_num == DVB_NET_MULTICAST_MAX) return -ENOMEM; - ret = memcmp(priv->multi_macs[priv->multi_num], mc->dmi_addr, 6); memcpy(priv->multi_macs[priv->multi_num], mc->dmi_addr, 6); priv->multi_num++; - - return ret; + return 0; } -static void dvb_net_set_multi(struct net_device *dev) + +static void wq_set_multicast_list (void *data) { + struct net_device *dev = data; struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv; - struct dev_mc_list *mc; - int mci; - int update = 0; + + dvb_net_feed_stop(dev); + + priv->rx_mode = RX_MODE_UNI; if(dev->flags & IFF_PROMISC) { -// printk("%s: promiscuous mode\n", dev->name); - if(priv->mode != 3) - update = 1; - priv->mode = 3; - } else if(dev->flags & IFF_ALLMULTI) { -// printk("%s: allmulti mode\n", dev->name); - if(priv->mode != 2) - update = 1; - priv->mode = 2; - } else if(dev->mc_count > 0) { -// printk("%s: set_mc_list, %d entries\n", -// dev->name, dev->mc_count); - if(priv->mode != 1) - update = 1; - priv->mode = 1; + dprintk("%s: promiscuous mode\n", dev->name); + priv->rx_mode = RX_MODE_PROMISC; + } else if ((dev->flags & IFF_ALLMULTI)) { + dprintk("%s: allmulti mode\n", dev->name); + priv->rx_mode = RX_MODE_ALL_MULTI; + } else if (dev->mc_count) { + int mci; + struct dev_mc_list *mc; + + dprintk("%s: set_mc_list, %d entries\n", + dev->name, dev->mc_count); + + priv->rx_mode = RX_MODE_MULTI; priv->multi_num = 0; + for (mci = 0, mc=dev->mc_list; mci < dev->mc_count; - mc=mc->next, mci++) - if(dvb_add_mc_filter(dev, mc) != 0) - update = 1; - } else { - if(priv->mode != 0) - update = 1; - priv->mode = 0; + mc = mc->next, mci++) { + dvb_set_mc_filter(dev, mc); + } } - if(netif_running(dev) != 0 && update > 0) - { - dvb_net_feed_stop(dev); dvb_net_feed_start(dev); } + + +static void dvb_net_set_multicast_list (struct net_device *dev) +{ + struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv; + schedule_work(&priv->set_multicast_list_wq); } + static int dvb_net_set_config(struct net_device *dev, struct ifmap *map) { if (netif_running(dev)) @@ -345,29 +405,47 @@ return 0; } -static int dvb_net_set_mac(struct net_device *dev, void *p) + +static void wq_restart_net_feed (void *data) { - struct sockaddr *addr=p; - int update; + struct net_device *dev = data; - update = memcmp(dev->dev_addr, addr->sa_data, dev->addr_len); - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - if (netif_running(dev) != 0 && update > 0) { + if (netif_running(dev)) { dvb_net_feed_stop(dev); dvb_net_feed_start(dev); } +} + + +static int dvb_net_set_mac (struct net_device *dev, void *p) +{ + struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv; + struct sockaddr *addr=p; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + if (netif_running(dev)) + schedule_work(&priv->restart_net_feed_wq); + return 0; } static int dvb_net_open(struct net_device *dev) { + struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv; + + priv->in_use++; dvb_net_feed_start(dev); return 0; } + static int dvb_net_stop(struct net_device *dev) { + struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv; + + priv->in_use--; dvb_net_feed_stop(dev); return 0; } @@ -386,16 +464,14 @@ dev->stop = dvb_net_stop; dev->hard_start_xmit = dvb_net_tx; dev->get_stats = dvb_net_get_stats; - dev->set_multicast_list = dvb_net_set_multi; + dev->set_multicast_list = dvb_net_set_multicast_list; dev->set_config = dvb_net_set_config; dev->set_mac_address = dvb_net_set_mac; dev->mtu = 4096; dev->mc_count = 0; - - dev->flags |= IFF_NOARP; dev->hard_header_cache = NULL; - //SET_MODULE_OWNER(dev); + dev->flags |= IFF_NOARP; return 0; } @@ -404,18 +480,19 @@ { int i; - for (i=0; idev_num; i++) + for (i=0; istate[i]) break; - if (i==dvbnet->dev_num) + + if (i == DVB_NET_DEVICES_MAX) return -1; + dvbnet->state[i]=1; return i; } -int -dvb_net_add_if(struct dvb_net *dvbnet, u16 pid) +static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid) { struct net_device *net; struct dmx_demux *demux; @@ -423,59 +500,63 @@ int result; int if_num; - if_num=get_if(dvbnet); - if (if_num<0) + if ((if_num = get_if(dvbnet)) < 0) return -EINVAL; net=&dvbnet->device[if_num]; demux=dvbnet->demux; - net->base_addr = 0; - net->irq = 0; - net->dma = 0; - net->mem_start = 0; + memset(net, 0, sizeof(struct net_device)); + memcpy(net->name, "dvb0_0", 7); - net->name[3]=dvbnet->card_num+0x30; - net->name[5]=if_num+0x30; + net->name[3] = dvbnet->dvbdev->adapter->num + '0'; + net->name[5] = if_num + '0'; + net->addr_len = 6; + memcpy(net->dev_addr, dvbnet->dvbdev->adapter->proposed_mac, 6); net->next = NULL; net->init = dvb_net_init_dev; - net->priv = kmalloc(sizeof(struct dvb_net_priv), GFP_KERNEL); - if (net->priv == NULL) + + if (!(net->priv = kmalloc(sizeof(struct dvb_net_priv), GFP_KERNEL))) return -ENOMEM; priv = net->priv; memset(priv, 0, sizeof(struct dvb_net_priv)); priv->demux = demux; priv->pid = pid; - priv->mode = 0; + priv->rx_mode = RX_MODE_UNI; + + INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list, net); + INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed, net); net->base_addr = pid; if ((result = register_netdev(net)) < 0) { return result; } - /* fixme: is this correct? */ - try_module_get(THIS_MODULE); return if_num; } -int -dvb_net_remove_if(struct dvb_net *dvbnet, int num) + +static int dvb_net_remove_if(struct dvb_net *dvbnet, int num) { + struct dvb_net_priv *priv = dvbnet->device[num].priv; + if (!dvbnet->state[num]) return -EINVAL; + if (priv->in_use) + return -EBUSY; + dvb_net_stop(&dvbnet->device[num]); - kfree(dvbnet->device[num].priv); + flush_scheduled_work(); + kfree(priv); unregister_netdev(&dvbnet->device[num]); dvbnet->state[num]=0; - /* fixme: is this correct? */ - module_put(THIS_MODULE); - return 0; } -int dvb_net_do_ioctl(struct inode *inode, struct file *file, + +static int dvb_net_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; @@ -490,6 +571,8 @@ struct dvb_net_if *dvbnetif=(struct dvb_net_if *)parg; int result; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; result=dvb_net_add_if(dvbnet, dvbnetif->pid); if (result<0) return result; @@ -502,7 +585,7 @@ struct dvb_net_priv *priv_data; struct dvb_net_if *dvbnetif=(struct dvb_net_if *)parg; - if (dvbnetif->if_num >= dvbnet->dev_num || + if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX || !dvbnet->state[dvbnetif->if_num]) return -EFAULT; @@ -512,7 +595,9 @@ break; } case NET_REMOVE_IF: - return dvb_net_remove_if(dvbnet, (long) parg); + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + return dvb_net_remove_if(dvbnet, (int) parg); default: return -EINVAL; } @@ -542,28 +627,29 @@ .fops = &dvb_net_fops, }; -void -dvb_net_release(struct dvb_net *dvbnet) + +void dvb_net_release (struct dvb_net *dvbnet) { int i; dvb_unregister_device(dvbnet->dvbdev); - for (i=0; idev_num; i++) { + + for (i=0; istate[i]) continue; dvb_net_remove_if(dvbnet, i); } } -int -dvb_net_init(struct dvb_adapter *adap, struct dvb_net *dvbnet, struct dmx_demux *dmx) + +int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet, + struct dmx_demux *dmx) { int i; dvbnet->demux = dmx; - dvbnet->dev_num = DVB_NET_DEVICES_MAX; - for (i=0; idev_num; i++) + for (i=0; istate[i] = 0; dvb_register_device (adap, &dvbnet->dvbdev, &dvbdev_net, diff -Nru a/drivers/media/dvb/dvb-core/dvb_net.h b/drivers/media/dvb/dvb-core/dvb_net.h --- a/drivers/media/dvb/dvb-core/dvb_net.h Sat Jul 19 12:54:22 2003 +++ b/drivers/media/dvb/dvb-core/dvb_net.h Sat Jul 19 12:54:22 2003 @@ -35,8 +35,6 @@ struct dvb_net { struct dvb_device *dvbdev; - int card_num; - int dev_num; struct net_device device[DVB_NET_DEVICES_MAX]; int state[DVB_NET_DEVICES_MAX]; struct dmx_demux *demux; diff -Nru a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c --- a/drivers/media/dvb/dvb-core/dvbdev.c Sat Jul 19 12:54:23 2003 +++ b/drivers/media/dvb/dvb-core/dvbdev.c Sat Jul 19 12:54:23 2003 @@ -29,8 +29,6 @@ #include #include #include -#include -#include #include "dvbdev.h" #include "dvb_functions.h" diff -Nru a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h --- a/drivers/media/dvb/dvb-core/dvbdev.h Sat Jul 19 12:54:24 2003 +++ b/drivers/media/dvb/dvb-core/dvbdev.h Sat Jul 19 12:54:24 2003 @@ -27,8 +27,9 @@ #include #include #include -#include #include +#include +#include #define DVB_MAJOR 250 @@ -48,6 +49,7 @@ struct list_head list_head; struct list_head device_list; const char *name; + u8 proposed_mac [6]; }; diff -Nru a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig --- a/drivers/media/dvb/frontends/Kconfig Sat Jul 19 12:54:23 2003 +++ b/drivers/media/dvb/frontends/Kconfig Sat Jul 19 12:54:23 2003 @@ -93,6 +93,16 @@ DVB adapter simply enable all supported frontends, the right one will get autodetected. +config DVB_MT312 + tristate "Zarlink MT312 Satellite Channel Decoder (QPSK)" + depends on DVB_CORE + help + A DVB-S tuner module. Say Y when you want to support this frontend. + + If you don't know what tuner module is soldered on your + DVB adapter simply enable all supported frontends, the + right one will get autodetected. + config DVB_VES1820 tristate "Frontends with external VES1820 demodulator (QAM)" depends on DVB_CORE @@ -105,3 +115,23 @@ DVB adapter simply enable all supported frontends, the right one will get autodetected. +config DVB_TDA1004X + tristate "Frontends with external TDA1004X demodulators (OFDM)" + depends on DVB_CORE + help + A DVB-T tuner module. Say Y when you want to support this frontend. + + If you don't know what tuner module is soldered on your + DVB adapter simply enable all supported frontends, the + right one will get autodetected. + +config DVB_TDA1004X_FIRMWARE_FILE + string "Full pathname of tda1004x.bin firmware file" + depends on DVB_TDA1004X + default "/etc/dvb/tda1004x.bin" + help + The TDA1004X requires additional firmware in order to function. + The firmware file can obtained as follows: + wget http://www.technotrend.de/new/215/TTweb_215a_budget_20_05_2003.zip + unzip -j TTweb_215a_budget_20_05_2003.zip Software/Oem/PCI/App/ttlcdacc.dll + mv ttlcdacc.dll /etc/dvb/tda1004x.bin diff -Nru a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile --- a/drivers/media/dvb/frontends/Makefile Sat Jul 19 12:54:21 2003 +++ b/drivers/media/dvb/frontends/Makefile Sat Jul 19 12:54:21 2003 @@ -12,4 +12,6 @@ obj-$(CONFIG_DVB_CX24110) += cx24110.o obj-$(CONFIG_DVB_GRUNDIG_29504_491) += grundig_29504-491.o obj-$(CONFIG_DVB_GRUNDIG_29504_401) += grundig_29504-401.o +obi-$(CONFIG_DVB_MT312) += mt312.o obj-$(CONFIG_DVB_VES1820) += ves1820.o +obj-$(CONFIG_DVB_TDA1004X) += tda1004x.o diff -Nru a/drivers/media/dvb/frontends/alps_bsrv2.c b/drivers/media/dvb/frontends/alps_bsrv2.c --- a/drivers/media/dvb/frontends/alps_bsrv2.c Sat Jul 19 12:54:23 2003 +++ b/drivers/media/dvb/frontends/alps_bsrv2.c Sat Jul 19 12:54:23 2003 @@ -55,7 +55,7 @@ 0x01, 0xA4, 0x35, 0x81, 0x2A, 0x0d, 0x55, 0xC4, 0x09, 0x69, 0x00, 0x86, 0x4c, 0x28, 0x7F, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x31, 0xb0, 0x14, 0x00, 0xDC, 0x20, + 0x80, 0x00, 0x31, 0xb0, 0x14, 0x00, 0xDC, 0x00, 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x7f, 0x00 @@ -158,6 +158,11 @@ { u8 val; + /* + * inversion on/off are interchanged because i and q seem to + * be swapped on the hardware + */ + switch (inversion) { case INVERSION_OFF: val = 0xc0; @@ -166,13 +171,16 @@ val = 0x80; break; case INVERSION_AUTO: - val = 0x40; + val = 0x00; break; default: return -EINVAL; } - return ves1893_writereg (i2c, 0x0c, (init_1893_tab[0x0c] & 0x3f) | val); + /* needs to be saved for FE_GET_FRONTEND */ + init_1893_tab[0x0c] = (init_1893_tab[0x0c] & 0x3f) | val; + + return ves1893_writereg (i2c, 0x0c, init_1893_tab[0x0c]); } @@ -383,8 +391,14 @@ afc = (afc * (int)(p->u.qpsk.symbol_rate/1000/8))/16; p->frequency -= afc; + + /* + * inversion indicator is only valid + * if auto inversion was used + */ + if (!(init_1893_tab[0x0c] & 0x80)) p->inversion = (ves1893_readreg (i2c, 0x0f) & 2) ? - INVERSION_ON : INVERSION_OFF; + INVERSION_OFF : INVERSION_ON; p->u.qpsk.fec_inner = ves1893_get_fec (i2c); /* XXX FIXME: timing offset !! */ break; diff -Nru a/drivers/media/dvb/frontends/alps_tdlb7.c b/drivers/media/dvb/frontends/alps_tdlb7.c --- a/drivers/media/dvb/frontends/alps_tdlb7.c Sat Jul 19 12:54:23 2003 +++ b/drivers/media/dvb/frontends/alps_tdlb7.c Sat Jul 19 12:54:23 2003 @@ -349,6 +349,9 @@ sp5659_set_tv_freq (i2c, p->frequency); + // read status reg in order to clear pending irqs + sp8870_readreg(i2c, 0x200); + // sample rate correction bit [23..17] sp8870_writereg(i2c,0x0319,0x000A); diff -Nru a/drivers/media/dvb/frontends/grundig_29504-401.c b/drivers/media/dvb/frontends/grundig_29504-401.c --- a/drivers/media/dvb/frontends/grundig_29504-401.c Sat Jul 19 12:54:23 2003 +++ b/drivers/media/dvb/frontends/grundig_29504-401.c Sat Jul 19 12:54:23 2003 @@ -37,15 +37,15 @@ struct dvb_frontend_info grundig_29504_401_info = { - .name = "Grundig 29504-401", - .type = FE_OFDM, -/* .frequency_min = ???,*/ -/* .frequency_max = ???,*/ - .frequency_stepsize = 166666, -/* .frequency_tolerance = ???,*/ -/* .symbol_rate_tolerance = ???,*/ - .notifier_delay = 0, - .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + name: "Grundig 29504-401", + type: FE_OFDM, +/* frequency_min: ???,*/ +/* frequency_max: ???,*/ + frequency_stepsize: 166666, +/* frequency_tolerance: ???,*/ +/* symbol_rate_tolerance: ???,*/ + notifier_delay: 0, + caps: FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_MUTE_TS /*| FE_CAN_CLEAN_SETUP*/ @@ -109,15 +109,15 @@ div = (36125000 + freq) / 166666; cfg = 0x88; - cpump = div < 175000000 ? 2 : div < 390000000 ? 1 : - div < 470000000 ? 2 : div < 750000000 ? 1 : 3; + cpump = freq < 175000000 ? 2 : freq < 390000000 ? 1 : + freq < 470000000 ? 2 : freq < 750000000 ? 1 : 3; - band_select = div < 175000000 ? 0x0e : div < 470000000 ? 0x05 : 0x03; + band_select = freq < 175000000 ? 0x0e : freq < 470000000 ? 0x05 : 0x03; buf [0] = (div >> 8) & 0x7f; buf [1] = div & 0xff; buf [2] = ((div >> 10) & 0x60) | cfg; - buf [3] = cpump | band_select; + buf [3] = (cpump << 6) | band_select; return tsa5060_write (i2c, buf); } @@ -267,12 +267,12 @@ } -static void reset_and_configure (struct dvb_i2c_bus *i2c) +static int reset_and_configure (struct dvb_i2c_bus *i2c) { u8 buf [] = { 0x06 }; struct i2c_msg msg = { .addr = 0x00, .flags = 0, .buf = buf, .len = 1 }; - i2c->xfer (i2c, &msg, 1); + return (i2c->xfer (i2c, &msg, 1) == 1) ? 0 : -ENODEV; } @@ -391,7 +391,7 @@ struct dvb_frontend_parameters *p = arg; tsa5060_set_tv_freq (i2c, p->frequency); - apply_frontend_param (i2c, p); + return apply_frontend_param (i2c, p); } case FE_GET_FRONTEND: /* we could correct the frequency here, but... @@ -417,25 +417,61 @@ static int l64781_attach (struct dvb_i2c_bus *i2c) { + u8 reg0x3e; u8 b0 [] = { 0x1a }; u8 b1 [] = { 0x00 }; struct i2c_msg msg [] = { { .addr = 0x55, .flags = 0, .buf = b0, .len = 1 }, { .addr = 0x55, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; - if (i2c->xfer (i2c, msg, 2) == 2) /* probably an EEPROM... */ + /** + * the L64781 won't show up before we send the reset_and_configure() + * broadcast. If nothing responds there is no L64781 on the bus... + */ + if (reset_and_configure(i2c) < 0) { + dprintk("no response on reset_and_configure() broadcast, bailing out...\n"); return -ENODEV; + } - reset_and_configure (i2c); - - if (i2c->xfer (i2c, msg, 2) != 2) /* nothing... */ + /* The chip always responds to reads */ + if (i2c->xfer(i2c, msg, 2) != 2) { + dprintk("no response to read on I2C bus\n"); return -ENODEV; + } - if (b1[0] != 0xa1) + /* Save current register contents for bailout */ + reg0x3e = l64781_readreg(i2c, 0x3e); + + /* Reading the POWER_DOWN register always returns 0 */ + if (reg0x3e != 0) { + dprintk("Device doesn't look like L64781\n"); return -ENODEV; + } + + /* Turn the chip off */ + l64781_writereg (i2c, 0x3e, 0x5a); + + /* Responds to all reads with 0 */ + if (l64781_readreg(i2c, 0x1a) != 0) { + dprintk("Read 1 returned unexpcted value\n"); + goto bailout; + } + + /* Turn the chip on */ + l64781_writereg (i2c, 0x3e, 0xa5); + + /* Responds with register default value */ + if (l64781_readreg(i2c, 0x1a) != 0xa1) { + dprintk("Read 2 returned unexpcted value\n"); + goto bailout; + } dvb_register_frontend (grundig_29504_401_ioctl, i2c, NULL, &grundig_29504_401_info); return 0; + + bailout: + l64781_writereg (i2c, 0x3e, reg0x3e); /* restore reg 0x3e */ + return -ENODEV; } diff -Nru a/drivers/media/dvb/frontends/grundig_29504-491.c b/drivers/media/dvb/frontends/grundig_29504-491.c --- a/drivers/media/dvb/frontends/grundig_29504-491.c Sat Jul 19 12:54:27 2003 +++ b/drivers/media/dvb/frontends/grundig_29504-491.c Sat Jul 19 12:54:27 2003 @@ -179,10 +179,7 @@ static fe_code_rate_t fec_tab [] = { FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4, FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8 }; - index = tda8083_readreg (i2c, 0x0e) & 0x3; - - if (index > 7) - return FEC_NONE; + index = tda8083_readreg(i2c, 0x0e) & 0x07; return fec_tab [index]; } diff -Nru a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/frontends/mt312.c Sat Jul 19 12:54:30 2003 @@ -0,0 +1,749 @@ +/* + Driver for Zarlink MT312 Satellite Channel Decoder + + Copyright (C) 2003 Andreas Oberritter + + 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. + + References: + http://products.zarlink.com/product_profiles/MT312.htm + http://products.zarlink.com/product_profiles/SL1935.htm +*/ + +#include +#include +#include +#include +#include + +#include "dvb_frontend.h" +#include "mt312.h" + +#define I2C_ADDR_MT312 0x0e +#define I2C_ADDR_SL1935 0x61 +#define I2C_ADDR_TSA5059 0x61 + +#define MT312_DEBUG 0 + +#define MT312_SYS_CLK 90000000UL /* 90 MHz */ +#define MT312_PLL_CLK 10000000UL /* 10 MHz */ + +static struct dvb_frontend_info mt312_info = { + .name = "Zarlink MT312", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = (MT312_PLL_CLK / 1000) / 128, + /*.frequency_tolerance = 29500, FIXME: binary compatibility waste? */ + .symbol_rate_min = MT312_SYS_CLK / 128, + .symbol_rate_max = MT312_SYS_CLK / 2, + /*.symbol_rate_tolerance = 500, FIXME: binary compatibility waste? 2% */ + .notifier_delay = 0, + .caps = + FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | + FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | + FE_CAN_FEC_AUTO | FE_CAN_QPSK | FE_CAN_RECOVER | + FE_CAN_CLEAN_SETUP | FE_CAN_MUTE_TS +}; + +static int mt312_read(struct dvb_i2c_bus *i2c, + const enum mt312_reg_addr reg, void *buf, + const size_t count) +{ + int ret; + struct i2c_msg msg[2]; + u8 regbuf[1] = { reg }; + + msg[0].addr = I2C_ADDR_MT312; + msg[0].flags = 0; + msg[0].buf = regbuf; + msg[0].len = 1; + msg[1].addr = I2C_ADDR_MT312; + msg[1].flags = I2C_M_RD; + msg[1].buf = buf; + msg[1].len = count; + + ret = i2c->xfer(i2c, msg, 2); + + if (ret != 2) { + printk(KERN_ERR "%s: ret == %d\n", __FUNCTION__, ret); + return -EREMOTEIO; + } +#ifdef MT312_DEBUG + { + int i; + printk(KERN_INFO "R(%d):", reg & 0x7f); + for (i = 0; i < count; i++) + printk(" %02x", ((const u8 *) buf)[i]); + printk("\n"); + } +#endif + + return 0; +} + +static int mt312_write(struct dvb_i2c_bus *i2c, + const enum mt312_reg_addr reg, const void *src, + const size_t count) +{ + int ret; + u8 buf[count + 1]; + struct i2c_msg msg; + +#ifdef MT312_DEBUG + { + int i; + printk(KERN_INFO "W(%d):", reg & 0x7f); + for (i = 0; i < count; i++) + printk(" %02x", ((const u8 *) src)[i]); + printk("\n"); + } +#endif + + buf[0] = reg; + memcpy(&buf[1], src, count); + + msg.addr = I2C_ADDR_MT312; + msg.flags = 0; + msg.buf = buf; + msg.len = count + 1; + + ret = i2c->xfer(i2c, &msg, 1); + + if (ret != 1) { + printk(KERN_ERR "%s: ret == %d\n", __FUNCTION__, ret); + return -EREMOTEIO; + } + + return 0; +} + +static inline int mt312_readreg(struct dvb_i2c_bus *i2c, + const enum mt312_reg_addr reg, u8 * val) +{ + return mt312_read(i2c, reg, val, 1); +} + +static inline int mt312_writereg(struct dvb_i2c_bus *i2c, + const enum mt312_reg_addr reg, const u8 val) +{ + return mt312_write(i2c, reg, &val, 1); +} + +static int mt312_pll_write(struct dvb_i2c_bus *i2c, const u8 addr, + u8 * buf, const u8 len) +{ + int ret; + struct i2c_msg msg; + + msg.addr = addr; + msg.flags = 0; + msg.buf = buf; + msg.len = len; + + if ((ret = mt312_writereg(i2c, GPP_CTRL, 0x40)) < 0) + return ret; + + if ((ret = i2c->xfer(i2c, &msg, 1)) != 1) + printk(KERN_ERR "%s: i/o error (ret == %d)\n", __FUNCTION__, ret); + + if ((ret = mt312_writereg(i2c, GPP_CTRL, 0x00)) < 0) + return ret; + + return 0; +} + +static inline u32 mt312_div(u32 a, u32 b) +{ + return (a + (b / 2)) / b; +} + +static int sl1935_set_tv_freq(struct dvb_i2c_bus *i2c, u32 freq, u32 sr) +{ + /* 155 uA, Baseband Path B */ + u8 buf[4] = { 0x00, 0x00, 0x80, 0x00 }; + + u8 exp; + u32 ref; + u32 div; + + if (sr < 10000000) { /* 1-10 MSym/s: ratio 2 ^ 3 */ + exp = 3; + buf[2] |= 0x40; /* 690 uA */ + } else if (sr < 15000000) { /* 10-15 MSym/s: ratio 2 ^ 4 */ + exp = 4; + buf[2] |= 0x20; /* 330 uA */ + } else { /* 15-45 MSym/s: ratio 2 ^ 7 */ + exp = 7; + buf[3] |= 0x08; /* Baseband Path A */ + } + + div = mt312_div(MT312_PLL_CLK, 1 << exp); + ref = mt312_div(freq * 1000, div); + mt312_info.frequency_stepsize = mt312_div(div, 1000); + + buf[0] = (ref >> 8) & 0x7f; + buf[1] = (ref >> 0) & 0xff; + buf[2] |= (exp - 1); + + if (freq < 1550000) + buf[3] |= 0x10; + + printk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0], + buf[1], buf[2], buf[3]); + + return mt312_pll_write(i2c, I2C_ADDR_SL1935, buf, sizeof(buf)); +} + +static int tsa5059_set_tv_freq(struct dvb_i2c_bus *i2c, u32 freq, u32 sr) +{ + u8 buf[4]; + + u32 ref = mt312_div(freq, 125); + + buf[0] = (ref >> 8) & 0x7f; + buf[1] = (ref >> 0) & 0xff; + buf[2] = 0x84 | ((ref >> 10) & 0x60); + buf[3] = 0x80; + + if (freq < 1550000) + buf[3] |= 0x02; + + printk(KERN_INFO "synth dword = %02x%02x%02x%02x\n", buf[0], + buf[1], buf[2], buf[3]); + + return mt312_pll_write(i2c, I2C_ADDR_TSA5059, buf, sizeof(buf)); +} + +static int mt312_reset(struct dvb_i2c_bus *i2c, const u8 full) +{ + return mt312_writereg(i2c, RESET, full ? 0x80 : 0x40); +} + +static int mt312_init(struct dvb_i2c_bus *i2c, const long id) +{ + int ret; + u8 buf[2]; + + /* wake up */ + if ((ret = mt312_writereg(i2c, CONFIG, 0x8c)) < 0) + return ret; + + /* wait at least 150 usec */ + udelay(150); + + /* full reset */ + if ((ret = mt312_reset(i2c, 1)) < 0) + return ret; + + /* SYS_CLK */ + buf[0] = mt312_div(MT312_SYS_CLK * 2, 1000000); + + /* DISEQC_RATIO */ + buf[1] = mt312_div(MT312_PLL_CLK, 15000 * 4); + + if ((ret = mt312_write(i2c, SYS_CLK, buf, sizeof(buf))) < 0) + return ret; + + if ((ret = mt312_writereg(i2c, SNR_THS_HIGH, 0x32)) < 0) + return ret; + + if ((ret = mt312_writereg(i2c, OP_CTRL, 0x53)) < 0) + return ret; + + /* TS_SW_LIM */ + buf[0] = 0x8c; + buf[1] = 0x98; + + if ((ret = mt312_write(i2c, TS_SW_LIM_L, buf, sizeof(buf))) < 0) + return ret; + + if ((ret = mt312_writereg(i2c, CS_SW_LIM, 0x69)) < 0) + return ret; + + return 0; +} + +static int mt312_send_master_cmd(struct dvb_i2c_bus *i2c, + const struct dvb_diseqc_master_cmd *c) +{ + int ret; + u8 diseqc_mode; + + if ((c->msg_len == 0) || (c->msg_len > sizeof(c->msg))) + return -EINVAL; + + if ((ret = mt312_readreg(i2c, DISEQC_MODE, &diseqc_mode)) < 0) + return ret; + + if ((ret = + mt312_write(i2c, (0x80 | DISEQC_INSTR), c->msg, c->msg_len)) < 0) + return ret; + + if ((ret = + mt312_writereg(i2c, DISEQC_MODE, + (diseqc_mode & 0x40) | ((c->msg_len - 1) << 3) + | 0x04)) < 0) + return ret; + + /* set DISEQC_MODE[2:0] to zero if a return message is expected */ + if (c->msg[0] & 0x02) + if ((ret = + mt312_writereg(i2c, DISEQC_MODE, (diseqc_mode & 0x40))) < 0) + return ret; + + return 0; +} + +static int mt312_recv_slave_reply(struct dvb_i2c_bus *i2c, + struct dvb_diseqc_slave_reply *r) +{ + /* TODO */ + return -EOPNOTSUPP; +} + +static int mt312_send_burst(struct dvb_i2c_bus *i2c, const fe_sec_mini_cmd_t c) +{ + const u8 mini_tab[2] = { 0x02, 0x03 }; + + int ret; + u8 diseqc_mode; + + if (c > SEC_MINI_B) + return -EINVAL; + + if ((ret = mt312_readreg(i2c, DISEQC_MODE, &diseqc_mode)) < 0) + return ret; + + if ((ret = + mt312_writereg(i2c, DISEQC_MODE, + (diseqc_mode & 0x40) | mini_tab[c])) < 0) + return ret; + + return 0; +} + +static int mt312_set_tone(struct dvb_i2c_bus *i2c, const fe_sec_tone_mode_t t) +{ + const u8 tone_tab[2] = { 0x01, 0x00 }; + + int ret; + u8 diseqc_mode; + + if (t > SEC_TONE_OFF) + return -EINVAL; + + if ((ret = mt312_readreg(i2c, DISEQC_MODE, &diseqc_mode)) < 0) + return ret; + + if ((ret = + mt312_writereg(i2c, DISEQC_MODE, + (diseqc_mode & 0x40) | tone_tab[t])) < 0) + return ret; + + return 0; +} + +static int mt312_set_voltage(struct dvb_i2c_bus *i2c, const fe_sec_voltage_t v) +{ + const u8 volt_tab[3] = { 0x00, 0x40, 0x00 }; + + if (v > SEC_VOLTAGE_OFF) + return -EINVAL; + + return mt312_writereg(i2c, DISEQC_MODE, volt_tab[v]); +} + +static int mt312_read_status(struct dvb_i2c_bus *i2c, fe_status_t * s) +{ + int ret; + u8 status[3]; + + *s = 0; + + if ((ret = mt312_read(i2c, QPSK_STAT_H, status, sizeof(status))) < 0) + return ret; + + if (status[0] & 0xc0) + *s |= FE_HAS_SIGNAL; /* signal noise ratio */ + if (status[0] & 0x04) + *s |= FE_HAS_CARRIER; /* qpsk carrier lock */ + if (status[2] & 0x02) + *s |= FE_HAS_VITERBI; /* viterbi lock */ + if (status[2] & 0x04) + *s |= FE_HAS_SYNC; /* byte align lock */ + if (status[0] & 0x01) + *s |= FE_HAS_LOCK; /* qpsk lock */ + + return 0; +} + +static int mt312_read_bercnt(struct dvb_i2c_bus *i2c, u32 * ber) +{ + int ret; + u8 buf[3]; + + if ((ret = mt312_read(i2c, RS_BERCNT_H, buf, 3)) < 0) + return ret; + + *ber = ((buf[0] << 16) | (buf[1] << 8) | buf[2]) * 64; + + return 0; +} + +static int mt312_read_agc(struct dvb_i2c_bus *i2c, u16 * signal_strength) +{ + int ret; + u8 buf[3]; + u16 agc; + s16 err_db; + + if ((ret = mt312_read(i2c, AGC_H, buf, sizeof(buf))) < 0) + return ret; + + agc = (buf[0] << 6) | (buf[1] >> 2); + err_db = (s16) (((buf[1] & 0x03) << 14) | buf[2] << 6) >> 6; + + *signal_strength = agc; + + printk(KERN_DEBUG "agc=%08x err_db=%hd\n", agc, err_db); + + return 0; +} + +static int mt312_read_snr(struct dvb_i2c_bus *i2c, u16 * snr) +{ + int ret; + u8 buf[2]; + + if ((ret = mt312_read(i2c, M_SNR_H, &buf, sizeof(buf))) < 0) + return ret; + + *snr = 0xFFFF - ((((buf[0] & 0x7f) << 8) | buf[1]) << 1); + + return 0; +} + +static int mt312_read_ubc(struct dvb_i2c_bus *i2c, u32 * ubc) +{ + int ret; + u8 buf[2]; + + if ((ret = mt312_read(i2c, RS_UBC_H, &buf, sizeof(buf))) < 0) + return ret; + + *ubc = (buf[0] << 8) | buf[1]; + + return 0; +} + +static int mt312_set_frontend(struct dvb_i2c_bus *i2c, + const struct dvb_frontend_parameters *p, + const long id) +{ + int ret; + u8 buf[5]; + u16 sr; + + const u8 fec_tab[10] = + { 0x00, 0x01, 0x02, 0x04, 0x3f, 0x08, 0x10, 0x20, 0x3f, 0x3f }; + const u8 inv_tab[3] = { 0x00, 0x40, 0x80 }; + + int (*set_tv_freq)(struct dvb_i2c_bus *i2c, u32 freq, u32 sr); + + if ((p->frequency < mt312_info.frequency_min) + || (p->frequency > mt312_info.frequency_max)) + return -EINVAL; + + if ((p->inversion < INVERSION_OFF) + || (p->inversion > INVERSION_AUTO)) + return -EINVAL; + + if ((p->u.qpsk.symbol_rate < mt312_info.symbol_rate_min) + || (p->u.qpsk.symbol_rate > mt312_info.symbol_rate_max)) + return -EINVAL; + + if ((p->u.qpsk.fec_inner < FEC_NONE) + || (p->u.qpsk.fec_inner > FEC_AUTO)) + return -EINVAL; + + if ((p->u.qpsk.fec_inner == FEC_4_5) + || (p->u.qpsk.fec_inner == FEC_8_9)) + return -EINVAL; + + switch (id) { + case ID_VP310: + set_tv_freq = tsa5059_set_tv_freq; + break; + case ID_MT312: + set_tv_freq = sl1935_set_tv_freq; + break; + default: + return -EINVAL; + } + + if ((ret = set_tv_freq(i2c, p->frequency, p->u.qpsk.symbol_rate)) < 0) + return ret; + + /* sr = (u16)(sr * 256.0 / 1000000.0) */ + sr = mt312_div(p->u.qpsk.symbol_rate * 4, 15625); + + /* SYM_RATE */ + buf[0] = (sr >> 8) & 0x3f; + buf[1] = (sr >> 0) & 0xff; + + /* VIT_MODE */ + buf[2] = inv_tab[p->inversion] | fec_tab[p->u.qpsk.fec_inner]; + + /* QPSK_CTRL */ + buf[3] = 0x40; /* swap I and Q before QPSK demodulation */ + + if (p->u.qpsk.symbol_rate < 10000000) + buf[3] |= 0x04; /* use afc mode */ + + /* GO */ + buf[4] = 0x01; + + if ((ret = mt312_write(i2c, SYM_RATE_H, buf, sizeof(buf))) < 0) + return ret; + + return 0; +} + +static int mt312_get_inversion(struct dvb_i2c_bus *i2c, + fe_spectral_inversion_t * i) +{ + int ret; + u8 vit_mode; + + if ((ret = mt312_readreg(i2c, VIT_MODE, &vit_mode)) < 0) + return ret; + + if (vit_mode & 0x80) /* auto inversion was used */ + *i = (vit_mode & 0x40) ? INVERSION_ON : INVERSION_OFF; + + return 0; +} + +static int mt312_get_symbol_rate(struct dvb_i2c_bus *i2c, u32 * sr) +{ + int ret; + u8 sym_rate_h; + u8 dec_ratio; + u16 sym_rat_op; + u16 monitor; + u8 buf[2]; + + if ((ret = mt312_readreg(i2c, SYM_RATE_H, &sym_rate_h)) < 0) + return ret; + + if (sym_rate_h & 0x80) { /* symbol rate search was used */ + if ((ret = mt312_writereg(i2c, MON_CTRL, 0x03)) < 0) + return ret; + + if ((ret = mt312_read(i2c, MONITOR_H, buf, sizeof(buf))) < 0) + return ret; + + monitor = (buf[0] << 8) | buf[1]; + + printk(KERN_DEBUG "sr(auto) = %u\n", + mt312_div(monitor * 15625, 4)); + } else { + if ((ret = mt312_writereg(i2c, MON_CTRL, 0x05)) < 0) + return ret; + + if ((ret = mt312_read(i2c, MONITOR_H, buf, sizeof(buf))) < 0) + return ret; + + dec_ratio = ((buf[0] >> 5) & 0x07) * 32; + + if ((ret = mt312_read(i2c, SYM_RAT_OP_H, buf, sizeof(buf))) < 0) + return ret; + + sym_rat_op = (buf[0] << 8) | buf[1]; + + printk(KERN_DEBUG "sym_rat_op=%d dec_ratio=%d\n", + sym_rat_op, dec_ratio); + printk(KERN_DEBUG "*sr(manual) = %lu\n", + (((MT312_PLL_CLK * 8192) / (sym_rat_op + 8192)) * + 2) - dec_ratio); + } + + return 0; +} + +static int mt312_get_code_rate(struct dvb_i2c_bus *i2c, fe_code_rate_t * cr) +{ + const fe_code_rate_t fec_tab[8] = + { FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_6_7, FEC_7_8, + FEC_AUTO, FEC_AUTO }; + + int ret; + u8 fec_status; + + if ((ret = mt312_readreg(i2c, FEC_STATUS, &fec_status)) < 0) + return ret; + + *cr = fec_tab[(fec_status >> 4) & 0x07]; + + return 0; +} + +static int mt312_get_frontend(struct dvb_i2c_bus *i2c, + struct dvb_frontend_parameters *p) +{ + int ret; + + if ((ret = mt312_get_inversion(i2c, &p->inversion)) < 0) + return ret; + + if ((ret = mt312_get_symbol_rate(i2c, &p->u.qpsk.symbol_rate)) < 0) + return ret; + + if ((ret = mt312_get_code_rate(i2c, &p->u.qpsk.fec_inner)) < 0) + return ret; + + return 0; +} + +static int mt312_sleep(struct dvb_i2c_bus *i2c) +{ + int ret; + u8 config; + + /* reset all registers to defaults */ + if ((ret = mt312_reset(i2c, 1)) < 0) + return ret; + + if ((ret = mt312_readreg(i2c, CONFIG, &config)) < 0) + return ret; + + /* enter standby */ + if ((ret = mt312_writereg(i2c, CONFIG, config & 0x7f)) < 0) + return ret; + + return 0; +} + +static int mt312_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) +{ + struct dvb_i2c_bus *i2c = fe->i2c; + + switch (cmd) { + case FE_GET_INFO: + memcpy(arg, &mt312_info, sizeof(struct dvb_frontend_info)); + break; + + case FE_DISEQC_RESET_OVERLOAD: + return -EOPNOTSUPP; + + case FE_DISEQC_SEND_MASTER_CMD: + return mt312_send_master_cmd(i2c, arg); + + case FE_DISEQC_RECV_SLAVE_REPLY: + if ((long) fe->data == ID_MT312) + return mt312_recv_slave_reply(i2c, arg); + else + return -EOPNOTSUPP; + + case FE_DISEQC_SEND_BURST: + return mt312_send_burst(i2c, (fe_sec_mini_cmd_t) arg); + + case FE_SET_TONE: + return mt312_set_tone(i2c, (fe_sec_tone_mode_t) arg); + + case FE_SET_VOLTAGE: + return mt312_set_voltage(i2c, (fe_sec_voltage_t) arg); + + case FE_ENABLE_HIGH_LNB_VOLTAGE: + return -EOPNOTSUPP; + + case FE_READ_STATUS: + return mt312_read_status(i2c, arg); + + case FE_READ_BER: + return mt312_read_bercnt(i2c, arg); + + case FE_READ_SIGNAL_STRENGTH: + return mt312_read_agc(i2c, arg); + + case FE_READ_SNR: + return mt312_read_snr(i2c, arg); + + case FE_READ_UNCORRECTED_BLOCKS: + return mt312_read_ubc(i2c, arg); + + case FE_SET_FRONTEND: + return mt312_set_frontend(i2c, arg, (long) fe->data); + + case FE_GET_FRONTEND: + return mt312_get_frontend(i2c, arg); + + case FE_GET_EVENT: + return -EOPNOTSUPP; + + case FE_SLEEP: + return mt312_sleep(i2c); + + case FE_INIT: + return mt312_init(i2c, (long) fe->data); + + case FE_RESET: + return mt312_reset(i2c, 0); + + default: + return -ENOIOCTLCMD; + } + + return 0; +} + +static int mt312_attach(struct dvb_i2c_bus *i2c) +{ + int ret; + u8 id; + + if ((ret = mt312_readreg(i2c, ID, &id)) < 0) + return ret; + + if ((id != ID_VP310) && (id != ID_MT312)) + return -ENODEV; + + return dvb_register_frontend(mt312_ioctl, i2c, (void *) (long) id, + &mt312_info); +} + +static void mt312_detach(struct dvb_i2c_bus *i2c) +{ + dvb_unregister_frontend(mt312_ioctl, i2c); +} + +static int __init mt312_module_init(void) +{ + return dvb_register_i2c_device(THIS_MODULE, mt312_attach, mt312_detach); +} + +static void __exit mt312_module_exit(void) +{ + dvb_unregister_i2c_device(mt312_attach); +} + +module_init(mt312_module_init); +module_exit(mt312_module_exit); + +MODULE_DESCRIPTION("MT312 Satellite Channel Decoder Driver"); +MODULE_AUTHOR("Andreas Oberritter "); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb/frontends/mt312.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/frontends/mt312.h Sat Jul 19 12:54:30 2003 @@ -0,0 +1,162 @@ +/* + Driver for Zarlink MT312 QPSK Frontend + + Copyright (C) 2003 Andreas Oberritter + + 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 _DVB_FRONTENDS_MT312 +#define _DVB_FRONTENDS_MT312 + +enum mt312_reg_addr { + QPSK_INT_H = 0, + QPSK_INT_M = 1, + QPSK_INT_L = 2, + FEC_INT = 3, + QPSK_STAT_H = 4, + QPSK_STAT_L = 5, + FEC_STATUS = 6, + LNB_FREQ_H = 7, + LNB_FREQ_L = 8, + M_SNR_H = 9, + M_SNR_L = 10, + VIT_ERRCNT_H = 11, + VIT_ERRCNT_M = 12, + VIT_ERRCNT_L = 13, + RS_BERCNT_H = 14, + RS_BERCNT_M = 15, + RS_BERCNT_L = 16, + RS_UBC_H = 17, + RS_UBC_L = 18, + SIG_LEVEL = 19, + GPP_CTRL = 20, + RESET = 21, + DISEQC_MODE = 22, + SYM_RATE_H = 23, + SYM_RATE_L = 24, + VIT_MODE = 25, + QPSK_CTRL = 26, + GO = 27, + IE_QPSK_H = 28, + IE_QPSK_M = 29, + IE_QPSK_L = 30, + IE_FEC = 31, + QPSK_STAT_EN = 32, + FEC_STAT_EN = 33, + SYS_CLK = 34, + DISEQC_RATIO = 35, + DISEQC_INSTR = 36, + FR_LIM = 37, + FR_OFF = 38, + AGC_CTRL = 39, + AGC_INIT = 40, + AGC_REF = 41, + AGC_MAX = 42, + AGC_MIN = 43, + AGC_LK_TH = 44, + TS_AGC_LK_TH = 45, + AGC_PWR_SET = 46, + QPSK_MISC = 47, + SNR_THS_LOW = 48, + SNR_THS_HIGH = 49, + TS_SW_RATE = 50, + TS_SW_LIM_L = 51, + TS_SW_LIM_H = 52, + CS_SW_RATE_1 = 53, + CS_SW_RATE_2 = 54, + CS_SW_RATE_3 = 55, + CS_SW_RATE_4 = 56, + CS_SW_LIM = 57, + TS_LPK = 58, + TS_LPK_M = 59, + TS_LPK_L = 60, + CS_KPROP_H = 61, + CS_KPROP_L = 62, + CS_KINT_H = 63, + CS_KINT_L = 64, + QPSK_SCALE = 65, + TLD_OUTCLK_TH = 66, + TLD_INCLK_TH = 67, + FLD_TH = 68, + PLD_OUTLK3 = 69, + PLD_OUTLK2 = 70, + PLD_OUTLK1 = 71, + PLD_OUTLK0 = 72, + PLD_INLK3 = 73, + PLD_INLK2 = 74, + PLD_INLK1 = 75, + PLD_INLK0 = 76, + PLD_ACC_TIME = 77, + SWEEP_PAR = 78, + STARTUP_TIME = 79, + LOSSLOCK_TH = 80, + FEC_LOCK_TM = 81, + LOSSLOCK_TM = 82, + VIT_ERRPER_H = 83, + VIT_ERRPER_M = 84, + VIT_ERRPER_L = 85, + VIT_SETUP = 86, + VIT_REF0 = 87, + VIT_REF1 = 88, + VIT_REF2 = 89, + VIT_REF3 = 90, + VIT_REF4 = 91, + VIT_REF5 = 92, + VIT_REF6 = 93, + VIT_MAXERR = 94, + BA_SETUPT = 95, + OP_CTRL = 96, + FEC_SETUP = 97, + PROG_SYNC = 98, + AFC_SEAR_TH = 99, + CSACC_DIF_TH = 100, + QPSK_LK_CT = 101, + QPSK_ST_CT = 102, + MON_CTRL = 103, + QPSK_RESET = 104, + QPSK_TST_CT = 105, + QPSK_TST_ST = 106, + TEST_R = 107, + AGC_H = 108, + AGC_M = 109, + AGC_L = 110, + FREQ_ERR1_H = 111, + FREQ_ERR1_M = 112, + FREQ_ERR1_L = 113, + FREQ_ERR2_H = 114, + FREQ_ERR2_L = 115, + SYM_RAT_OP_H = 116, + SYM_RAT_OP_L = 117, + DESEQC2_INT = 118, + DISEQC2_STAT = 119, + DISEQC2_FIFO = 120, + DISEQC2_CTRL1 = 121, + DISEQC2_CTRL2 = 122, + MONITOR_H = 123, + MONITOR_L = 124, + TEST_MODE = 125, + ID = 126, + CONFIG = 127 +}; + +enum mt312_model_id { + ID_VP310 = 1, + ID_MT312 = 3 +}; + +#endif /* DVB_FRONTENDS_MT312 */ diff -Nru a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c --- a/drivers/media/dvb/frontends/nxt6000.c Sat Jul 19 12:54:26 2003 +++ b/drivers/media/dvb/frontends/nxt6000.c Sat Jul 19 12:54:26 2003 @@ -6,8 +6,10 @@ Alps TDME7 (Tuner: MITEL SP5659) Alps TDED4 (Tuner: TI ALP510, external Nxt6000) + Comtech DVBT-6k07 (PLL IC: SP5730) Copyright (C) 2002-2003 Florian Schirmer + Copyright (C) 2003 Paul Andreassen 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 @@ -78,6 +80,7 @@ #define TUNER_TYPE_ALP510 0 #define TUNER_TYPE_SP5659 1 +#define TUNER_TYPE_SP5730 2 #define FE2NXT(fe) ((struct nxt6000_config *)&(fe->data)) #define FREQ2DIV(freq) ((freq + 36166667) / 166667) @@ -212,6 +215,39 @@ } +static int sp5730_set_tv_freq(struct dvb_frontend *fe, u32 freq) +{ + + u8 buf[4]; + struct nxt6000_config *nxt = FE2NXT(fe); + + buf[0] = (FREQ2DIV(freq) >> 8) & 0x7F; + buf[1] = FREQ2DIV(freq) & 0xFF; + buf[2] = 0x93; + + if ((freq >= 51000000) && (freq < 132100000)) + buf[3] = 0x05; + else if ((freq >= 132100000) && (freq < 143000000)) + buf[3] = 0x45; + else if ((freq >= 146000000) && (freq < 349100000)) + buf[3] = 0x06; + else if ((freq >= 349100000) && (freq < 397100000)) + buf[3] = 0x46; + else if ((freq >= 397100000) && (freq < 426000000)) + buf[3] = 0x86; + else if ((freq >= 430000000) && (freq < 659100000)) + buf[3] = 0x03; + else if ((freq >= 659100000) && (freq < 759100000)) + buf[3] = 0x43; + else if ((freq >= 759100000) && (freq < 858000000)) + buf[3] = 0x83; + else + return -EINVAL; + + return pll_write(fe->i2c, nxt->demod_addr, nxt->tuner_addr, buf, 4); + +} + static void nxt6000_reset(struct dvb_frontend *fe) { @@ -756,6 +792,13 @@ break; + case TUNER_TYPE_SP5730: + + if ((result = sp5730_set_tv_freq(fe, param->frequency)) < 0) + return result; + + break; + default: return -EFAULT; @@ -815,6 +858,14 @@ nxt.clock_inversion = 0; dprintk("nxt6000: detected MITEL SP5659 tuner at 0x%02X\n", nxt.tuner_addr); + + } else if (pll_write(i2c, demod_addr_tbl[addr_nr], 0xC0, NULL, 0) == 0) { + + nxt.tuner_addr = 0xC0; + nxt.tuner_type = TUNER_TYPE_SP5730; + nxt.clock_inversion = 0; + + dprintk("nxt6000: detected SP5730 tuner at 0x%02X\n", nxt.tuner_addr); } else { diff -Nru a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/frontends/tda1004x.c Sat Jul 19 12:54:30 2003 @@ -0,0 +1,1158 @@ + /* + Driver for Philips tda1004x OFDM Frontend + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + */ + +/* + This driver needs a copy of the DLL "ttlcdacc.dll" from the Haupauge or Technotrend + windows driver saved as '/etc/dvb/tda1004x.mc'. + You can also pass the complete file name with the module parameter 'tda1004x_firmware'. + + Currently the DLL from v2.15a of the technotrend driver is supported. Other versions can + be added reasonably painlessly. + + Windows driver URL: http://www.technotrend.de/ + */ + + +#define __KERNEL_SYSCALLS__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dvb_frontend.h" +#include "dvb_functions.h" + +#ifndef CONFIG_TDA1004X_MC_LOCATION +#define CONFIG_TDA1004X_MC_LOCATION "/etc/dvb/tda1004x.mc" +#endif + +static int tda1004x_debug = 0; +static char *tda1004x_firmware = CONFIG_TDA1004X_MC_LOCATION; + + +#define TDA10045H_ADDRESS 0x08 +#define TD1344_ADDRESS 0x61 +#define TDM1316L_ADDRESS 0x63 +#define MC44BC374_ADDRESS 0x65 + +#define TDA1004X_CHIPID 0x00 +#define TDA1004X_AUTO 0x01 +#define TDA1004X_IN_CONF1 0x02 +#define TDA1004X_IN_CONF2 0x03 +#define TDA1004X_OUT_CONF1 0x04 +#define TDA1004X_OUT_CONF2 0x05 +#define TDA1004X_STATUS_CD 0x06 +#define TDA1004X_CONFC4 0x07 +#define TDA1004X_DSSPARE2 0x0C +#define TDA1004X_CODE_IN 0x0D +#define TDA1004X_FWPAGE 0x0E +#define TDA1004X_SCAN_CPT 0x10 +#define TDA1004X_DSP_CMD 0x11 +#define TDA1004X_DSP_ARG 0x12 +#define TDA1004X_DSP_DATA1 0x13 +#define TDA1004X_DSP_DATA2 0x14 +#define TDA1004X_CONFADC1 0x15 +#define TDA1004X_CONFC1 0x16 +#define TDA1004X_SIGNAL_STRENGTH 0x1a +#define TDA1004X_SNR 0x1c +#define TDA1004X_REG1E 0x1e +#define TDA1004X_REG1F 0x1f +#define TDA1004X_CBER_RESET 0x20 +#define TDA1004X_CBER_MSB 0x21 +#define TDA1004X_CBER_LSB 0x22 +#define TDA1004X_CVBER_LUT 0x23 +#define TDA1004X_VBER_MSB 0x24 +#define TDA1004X_VBER_MID 0x25 +#define TDA1004X_VBER_LSB 0x26 +#define TDA1004X_UNCOR 0x27 +#define TDA1004X_CONFPLL_P 0x2D +#define TDA1004X_CONFPLL_M_MSB 0x2E +#define TDA1004X_CONFPLL_M_LSB 0x2F +#define TDA1004X_CONFPLL_N 0x30 +#define TDA1004X_UNSURW_MSB 0x31 +#define TDA1004X_UNSURW_LSB 0x32 +#define TDA1004X_WREF_MSB 0x33 +#define TDA1004X_WREF_MID 0x34 +#define TDA1004X_WREF_LSB 0x35 +#define TDA1004X_MUXOUT 0x36 +#define TDA1004X_CONFADC2 0x37 +#define TDA1004X_IOFFSET 0x38 + +#define dprintk if (tda1004x_debug) printk + +static struct dvb_frontend_info tda10045h_info = { + .name = "Philips TDA10045H", + .type = FE_OFDM, + .frequency_min = 51000000, + .frequency_max = 858000000, + .frequency_stepsize = 166667, + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO +}; + +#pragma pack(1) +struct tda1004x_state { + u8 tda1004x_address; + u8 tuner_address; + u8 initialised:1; +}; +#pragma pack() + +struct fwinfo { + int file_size; + int fw_offset; + int fw_size; +}; +static struct fwinfo tda10045h_fwinfo[] = { {.file_size = 286720,.fw_offset = 0x34cc5,.fw_size = 30555} }; +static int tda10045h_fwinfo_count = sizeof(tda10045h_fwinfo) / sizeof(struct fwinfo); + +static int errno; + + +static int tda1004x_write_byte(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, int reg, int data) +{ + int ret; + u8 buf[] = { reg, data }; + struct i2c_msg msg = { .addr=0, .flags=0, .buf=buf, .len=2 }; + + dprintk("%s: reg=0x%x, data=0x%x\n", __FUNCTION__, reg, data); + + msg.addr = tda_state->tda1004x_address; + ret = i2c->xfer(i2c, &msg, 1); + + if (ret != 1) + dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n", + __FUNCTION__, reg, data, ret); + + dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __FUNCTION__, + reg, data, ret); + return (ret != 1) ? -1 : 0; +} + +static int tda1004x_read_byte(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, int reg) +{ + int ret; + u8 b0[] = { reg }; + u8 b1[] = { 0 }; + struct i2c_msg msg[] = {{ .addr=0, .flags=0, .buf=b0, .len=1}, + { .addr=0, .flags=I2C_M_RD, .buf=b1, .len = 1}}; + + dprintk("%s: reg=0x%x\n", __FUNCTION__, reg); + + msg[0].addr = tda_state->tda1004x_address; + msg[1].addr = tda_state->tda1004x_address; + ret = i2c->xfer(i2c, msg, 2); + + if (ret != 2) { + dprintk("%s: error reg=0x%x, ret=%i\n", __FUNCTION__, reg, + ret); + return -1; + } + + dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __FUNCTION__, + reg, b1[0], ret); + return b1[0]; +} + +static int tda1004x_write_mask(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, int reg, int mask, int data) +{ + int val; + dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __FUNCTION__, reg, + mask, data); + + // read a byte and check + val = tda1004x_read_byte(i2c, tda_state, reg); + if (val < 0) + return val; + + // mask if off + val = val & ~mask; + val |= data & 0xff; + + // write it out again + return tda1004x_write_byte(i2c, tda_state, reg, val); +} + +static int tda1004x_write_buf(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, int reg, unsigned char *buf, int len) +{ + int i; + int result; + + dprintk("%s: reg=0x%x, len=0x%x\n", __FUNCTION__, reg, len); + + result = 0; + for (i = 0; i < len; i++) { + result = tda1004x_write_byte(i2c, tda_state, reg + i, buf[i]); + if (result != 0) + break; + } + + return result; +} + +static int tda1004x_enable_tuner_i2c(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state) +{ + int result; + dprintk("%s\n", __FUNCTION__); + + result = tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 2, 2); + dvb_delay(1); + return result; +} + +static int tda1004x_disable_tuner_i2c(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state) +{ + + dprintk("%s\n", __FUNCTION__); + + return tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 2, 0); +} + + +static int tda10045h_set_bandwidth(struct dvb_i2c_bus *i2c, + struct tda1004x_state *tda_state, + fe_bandwidth_t bandwidth) +{ + static u8 bandwidth_6mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x60, 0x1e, 0xa7, 0x45, 0x4f }; + static u8 bandwidth_7mhz[] = { 0x02, 0x00, 0x37, 0x00, 0x4a, 0x2f, 0x6d, 0x76, 0xdb }; + static u8 bandwidth_8mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x48, 0x17, 0x89, 0xc7, 0x14 }; + + switch (bandwidth) { + case BANDWIDTH_6_MHZ: + tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0x14); + tda1004x_write_buf(i2c, tda_state, TDA1004X_CONFPLL_P, bandwidth_6mhz, sizeof(bandwidth_6mhz)); + break; + + case BANDWIDTH_7_MHZ: + tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0x80); + tda1004x_write_buf(i2c, tda_state, TDA1004X_CONFPLL_P, bandwidth_7mhz, sizeof(bandwidth_7mhz)); + break; + + case BANDWIDTH_8_MHZ: + tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0x14); + tda1004x_write_buf(i2c, tda_state, TDA1004X_CONFPLL_P, bandwidth_8mhz, sizeof(bandwidth_8mhz)); + break; + + default: + return -EINVAL; + } + + tda1004x_write_byte(i2c, tda_state, TDA1004X_IOFFSET, 0); + + // done + return 0; +} + + +static int tda1004x_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state) +{ + u8 fw_buf[65]; + struct i2c_msg fw_msg = {.addr = 0,.flags = 0,.buf = fw_buf,.len = 0 }; + struct i2c_msg tuner_msg = {.addr = 0,.flags = 0,.buf = 0,.len = 0 }; + unsigned char *firmware = NULL; + int filesize; + int fd; + int fwinfo_idx; + int fw_size = 0; + int fw_pos; + int tx_size; + static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 }; + mm_segment_t fs = get_fs(); + + dprintk("%s\n", __FUNCTION__); + + // Load the firmware + set_fs(get_ds()); + fd = open(tda1004x_firmware, 0, 0); + if (fd < 0) { + printk("%s: Unable to open firmware %s\n", __FUNCTION__, + tda1004x_firmware); + return -EIO; + } + filesize = lseek(fd, 0L, 2); + if (filesize <= 0) { + printk("%s: Firmware %s is empty\n", __FUNCTION__, + tda1004x_firmware); + sys_close(fd); + return -EIO; + } + + // find extraction parameters + for (fwinfo_idx = 0; fwinfo_idx < tda10045h_fwinfo_count; fwinfo_idx++) { + if (tda10045h_fwinfo[fwinfo_idx].file_size == filesize) + break; + } + if (fwinfo_idx >= tda10045h_fwinfo_count) { + printk("%s: Unsupported firmware %s\n", __FUNCTION__, tda1004x_firmware); + sys_close(fd); + return -EIO; + } + fw_size = tda10045h_fwinfo[fwinfo_idx].fw_size; + + // allocate buffer for it + firmware = vmalloc(fw_size); + if (firmware == NULL) { + printk("%s: Out of memory loading firmware\n", + __FUNCTION__); + sys_close(fd); + return -EIO; + } + + // read it! + lseek(fd, tda10045h_fwinfo[fwinfo_idx].fw_offset, 0); + if (read(fd, firmware, fw_size) != fw_size) { + printk("%s: Failed to read firmware\n", __FUNCTION__); + vfree(firmware); + sys_close(fd); + return -EIO; + } + sys_close(fd); + set_fs(fs); + + // Disable the MC44BC374C + tda1004x_enable_tuner_i2c(i2c, tda_state); + tuner_msg.addr = MC44BC374_ADDRESS; + tuner_msg.buf = disable_mc44BC374c; + tuner_msg.len = sizeof(disable_mc44BC374c); + if (i2c->xfer(i2c, &tuner_msg, 1) != 1) { + i2c->xfer(i2c, &tuner_msg, 1); + } + tda1004x_disable_tuner_i2c(i2c, tda_state); + + // set some valid bandwith parameters + switch(tda_state->tda1004x_address) { + case TDA10045H_ADDRESS: + tda10045h_set_bandwidth(i2c, tda_state, BANDWIDTH_8_MHZ); + break; + } + dvb_delay(500); + + // do the firmware upload + tda1004x_write_byte(i2c, tda_state, TDA1004X_FWPAGE, 0); + fw_msg.addr = tda_state->tda1004x_address; + fw_pos = 0; + while (fw_pos != fw_size) { + // work out how much to send this time + tx_size = fw_size - fw_pos; + if (tx_size > 64) { + tx_size = 64; + } + // send the chunk + fw_buf[0] = TDA1004X_CODE_IN; + memcpy(fw_buf + 1, firmware + fw_pos, tx_size); + fw_msg.len = tx_size + 1; + if (i2c->xfer(i2c, &fw_msg, 1) != 1) { + vfree(firmware); + return -EIO; + } + fw_pos += tx_size; + + dprintk("%s: fw_pos=0x%x\n", __FUNCTION__, fw_pos); + } + dvb_delay(100); + vfree(firmware); + + // Initialise the DSP and check upload was OK + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x10, 0); + tda1004x_write_byte(i2c, tda_state, TDA1004X_DSP_CMD, 0x67); + if ((tda1004x_read_byte(i2c, tda_state, TDA1004X_DSP_DATA1) != 0x67) || + (tda1004x_read_byte(i2c, tda_state, TDA1004X_DSP_DATA2) != 0x2c)) { + printk("%s: firmware upload failed!\n", __FUNCTION__); + return -EIO; + } + + // tda setup + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 8, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 0x10, 0x10); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0xC0, 0x0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x20, 0); + tda1004x_write_byte(i2c, tda_state, TDA1004X_CONFADC1, 0x2e); + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x80, 0x80); + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x40, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x10, 0); + tda1004x_write_byte(i2c, tda_state, TDA1004X_REG1E, 0); + tda1004x_write_byte(i2c, tda_state, TDA1004X_REG1F, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_VBER_MSB, 0xe0, 0xa0); + + // done + return 0; +} + +static int tda1004x_encode_fec(int fec) +{ + // convert known FEC values + switch (fec) { + case FEC_1_2: + return 0; + case FEC_2_3: + return 1; + case FEC_3_4: + return 2; + case FEC_5_6: + return 3; + case FEC_7_8: + return 4; + } + + // unsupported + return -EINVAL; +} + +static int tda1004x_decode_fec(int tdafec) +{ + // convert known FEC values + switch (tdafec) { + case 0: + return FEC_1_2; + case 1: + return FEC_2_3; + case 2: + return FEC_3_4; + case 3: + return FEC_5_6; + case 4: + return FEC_7_8; + } + + // unsupported + return -1; +} + +static int tda1004x_set_frequency(struct dvb_i2c_bus *i2c, + struct tda1004x_state *tda_state, + struct dvb_frontend_parameters *fe_params) +{ + u8 tuner_buf[4]; + struct i2c_msg tuner_msg = {.addr=0, .flags=0, .buf=tuner_buf, .len=sizeof(tuner_buf) }; + int tuner_frequency; + u8 band, cp, filter; + int counter, counter2; + + dprintk("%s\n", __FUNCTION__); + + // setup the frequency buffer + switch (tda_state->tuner_address) { + case TD1344_ADDRESS: + + // setup tuner buffer + tuner_frequency = + (((fe_params->frequency / 1000) * 6) + 217502) / 1000; + tuner_buf[0] = tuner_frequency >> 8; + tuner_buf[1] = tuner_frequency & 0xff; + tuner_buf[2] = 0x88; + if (fe_params->frequency < 550000000) { + tuner_buf[3] = 0xab; + } else { + tuner_buf[3] = 0xeb; + } + + // tune it + tda1004x_enable_tuner_i2c(i2c, tda_state); + tuner_msg.addr = tda_state->tuner_address; + tuner_msg.len = 4; + i2c->xfer(i2c, &tuner_msg, 1); + + // wait for it to finish + tuner_msg.len = 1; + tuner_msg.flags = I2C_M_RD; + counter = 0; + counter2 = 0; + while (counter++ < 100) { + if (i2c->xfer(i2c, &tuner_msg, 1) == 1) { + if (tuner_buf[0] & 0x40) { + counter2++; + } else { + counter2 = 0; + } + } + + if (counter2 > 10) { + break; + } + } + tda1004x_disable_tuner_i2c(i2c, tda_state); + break; + + case TDM1316L_ADDRESS: + // determine charge pump + tuner_frequency = fe_params->frequency + 36130000; + if (tuner_frequency < 87000000) { + return -EINVAL; + } else if (tuner_frequency < 130000000) { + cp = 3; + } else if (tuner_frequency < 160000000) { + cp = 5; + } else if (tuner_frequency < 200000000) { + cp = 6; + } else if (tuner_frequency < 290000000) { + cp = 3; + } else if (tuner_frequency < 420000000) { + cp = 5; + } else if (tuner_frequency < 480000000) { + cp = 6; + } else if (tuner_frequency < 620000000) { + cp = 3; + } else if (tuner_frequency < 830000000) { + cp = 5; + } else if (tuner_frequency < 895000000) { + cp = 7; + } else { + return -EINVAL; + } + + // determine band + if (fe_params->frequency < 49000000) { + return -EINVAL; + } else if (fe_params->frequency < 159000000) { + band = 1; + } else if (fe_params->frequency < 444000000) { + band = 2; + } else if (fe_params->frequency < 861000000) { + band = 4; + } else { + return -EINVAL; + } + + // work out filter + switch (fe_params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + // 6 MHz isn't supported directly, but set this to + // the 8 MHz setting in case we can fiddle it later + filter = 1; + break; + + case BANDWIDTH_7_MHZ: + filter = 0; + break; + + case BANDWIDTH_8_MHZ: + filter = 1; + break; + + default: + return -EINVAL; + } + + // calculate tuner parameters + tuner_frequency = + (((fe_params->frequency / 1000) * 6) + 217280) / 1000; + tuner_buf[0] = tuner_frequency >> 8; + tuner_buf[1] = tuner_frequency & 0xff; + tuner_buf[2] = 0xca; + tuner_buf[3] = (cp << 5) | (filter << 3) | band; + + // tune it + tda1004x_enable_tuner_i2c(i2c, tda_state); + tuner_msg.addr = tda_state->tuner_address; + tuner_msg.len = 4; + if (i2c->xfer(i2c, &tuner_msg, 1) != 1) { + return -EIO; + } + dvb_delay(1); + tda1004x_disable_tuner_i2c(i2c, tda_state); + break; + + default: + return -EINVAL; + } + + dprintk("%s: success\n", __FUNCTION__); + + // done + return 0; +} + +static int tda1004x_set_fe(struct dvb_i2c_bus *i2c, + struct tda1004x_state *tda_state, + struct dvb_frontend_parameters *fe_params) +{ + int tmp; + + dprintk("%s\n", __FUNCTION__); + + + // set frequency + tmp = tda1004x_set_frequency(i2c, tda_state, fe_params); + if (tmp < 0) + return tmp; + + // hardcoded to use auto as much as possible + fe_params->u.ofdm.code_rate_HP = FEC_AUTO; + fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_AUTO; + fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; + + // Set standard params.. or put them to auto + if ((fe_params->u.ofdm.code_rate_HP == FEC_AUTO) || + (fe_params->u.ofdm.code_rate_LP == FEC_AUTO) || + (fe_params->u.ofdm.constellation == QAM_AUTO) || + (fe_params->u.ofdm.hierarchy_information == HIERARCHY_AUTO)) { + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 1, 1); // enable auto + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x03, 0); // turn off constellation bits + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 0); // turn off hierarchy bits + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0x3f, 0); // turn off FEC bits + } else { + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 1, 0); // disable auto + + // set HP FEC + tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_HP); + if (tmp < 0) return tmp; + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 7, tmp); + + // set LP FEC + if (fe_params->u.ofdm.code_rate_LP != FEC_NONE) { + tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_LP); + if (tmp < 0) return tmp; + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0x38, tmp << 3); + } + + // set constellation + switch (fe_params->u.ofdm.constellation) { + case QPSK: + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 3, 0); + break; + + case QAM_16: + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 3, 1); + break; + + case QAM_64: + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 3, 2); + break; + + default: + return -EINVAL; + } + + // set hierarchy + switch (fe_params->u.ofdm.hierarchy_information) { + case HIERARCHY_NONE: + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 0 << 5); + break; + + case HIERARCHY_1: + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 1 << 5); + break; + + case HIERARCHY_2: + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 2 << 5); + break; + + case HIERARCHY_4: + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x60, 3 << 5); + break; + + default: + return -EINVAL; + } + } + + // set bandwidth + switch(tda_state->tda1004x_address) { + case TDA10045H_ADDRESS: + tda10045h_set_bandwidth(i2c, tda_state, fe_params->u.ofdm.bandwidth); + break; + } + + // set inversion + switch (fe_params->inversion) { + case INVERSION_OFF: + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x20, 0); + break; + + case INVERSION_ON: + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x20, 0x20); + break; + + default: + return -EINVAL; + } + + // set guard interval + switch (fe_params->u.ofdm.guard_interval) { + case GUARD_INTERVAL_1_32: + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 0 << 2); + break; + + case GUARD_INTERVAL_1_16: + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 1 << 2); + break; + + case GUARD_INTERVAL_1_8: + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 2 << 2); + break; + + case GUARD_INTERVAL_1_4: + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 3 << 2); + break; + + case GUARD_INTERVAL_AUTO: + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 2, 2); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x0c, 0 << 2); + break; + + default: + return -EINVAL; + } + + // set transmission mode + switch (fe_params->u.ofdm.transmission_mode) { + case TRANSMISSION_MODE_2K: + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 4, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x10, 0 << 4); + break; + + case TRANSMISSION_MODE_8K: + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 4, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x10, 1 << 4); + break; + + case TRANSMISSION_MODE_AUTO: + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 4, 4); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x10, 0); + break; + + default: + return -EINVAL; + } + + // reset DSP + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 8); + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 0); + dvb_delay(10); + + // done + return 0; +} + + +static int tda1004x_get_fe(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, struct dvb_frontend_parameters *fe_params) +{ + + dprintk("%s\n", __FUNCTION__); + + // inversion status + fe_params->inversion = INVERSION_OFF; + if (tda1004x_read_byte(i2c, tda_state, TDA1004X_CONFC1) & 0x20) { + fe_params->inversion = INVERSION_ON; + } + + // bandwidth + switch (tda1004x_read_byte(i2c, tda_state, TDA1004X_WREF_LSB)) { + case 0x14: + fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; + break; + case 0xdb: + fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; + break; + case 0x4f: + fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; + break; + } + + // FEC + fe_params->u.ofdm.code_rate_HP = + tda1004x_decode_fec(tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF2) & 7); + fe_params->u.ofdm.code_rate_LP = + tda1004x_decode_fec((tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF2) >> 3) & 7); + + // constellation + switch (tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 3) { + case 0: + fe_params->u.ofdm.constellation = QPSK; + break; + case 1: + fe_params->u.ofdm.constellation = QAM_16; + break; + case 2: + fe_params->u.ofdm.constellation = QAM_64; + break; + } + + // transmission mode + fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; + if (tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 0x10) { + fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; + } + + // guard interval + switch ((tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 0x0c) >> 2) { + case 0: + fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; + break; + case 1: + fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; + break; + case 2: + fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; + break; + case 3: + fe_params->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; + break; + } + + // hierarchy + switch ((tda1004x_read_byte(i2c, tda_state, TDA1004X_OUT_CONF1) & 0x60) >> 5) { + case 0: + fe_params->u.ofdm.hierarchy_information = HIERARCHY_NONE; + break; + case 1: + fe_params->u.ofdm.hierarchy_information = HIERARCHY_1; + break; + case 2: + fe_params->u.ofdm.hierarchy_information = HIERARCHY_2; + break; + case 3: + fe_params->u.ofdm.hierarchy_information = HIERARCHY_4; + break; + } + + // done + return 0; +} + + +static int tda1004x_read_status(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, fe_status_t * fe_status) +{ + int status; + int cber; + int vber; + + dprintk("%s\n", __FUNCTION__); + + // read status + status = tda1004x_read_byte(i2c, tda_state, TDA1004X_STATUS_CD); + if (status == -1) { + return -EIO; + } + + // decode + *fe_status = 0; + if (status & 4) *fe_status |= FE_HAS_SIGNAL; + if (status & 2) *fe_status |= FE_HAS_CARRIER; + if (status & 8) *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; + + // if we don't already have VITERBI (i.e. not LOCKED), see if the viterbi + // is getting anything valid + if (!(*fe_status & FE_HAS_VITERBI)) { + // read the CBER + cber = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_LSB); + if (cber == -1) return -EIO; + status = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_MSB); + if (status == -1) return -EIO; + cber |= (status << 8); + tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_RESET); + + if (cber != 65535) { + *fe_status |= FE_HAS_VITERBI; + } + } + + // if we DO have some valid VITERBI output, but don't already have SYNC + // bytes (i.e. not LOCKED), see if the RS decoder is getting anything valid. + if ((*fe_status & FE_HAS_VITERBI) && (!(*fe_status & FE_HAS_SYNC))) { + // read the VBER + vber = tda1004x_read_byte(i2c, tda_state, TDA1004X_VBER_LSB); + if (vber == -1) return -EIO; + status = tda1004x_read_byte(i2c, tda_state, TDA1004X_VBER_MID); + if (status == -1) return -EIO; + vber |= (status << 8); + status = tda1004x_read_byte(i2c, tda_state, TDA1004X_VBER_MSB); + if (status == -1) return -EIO; + vber |= ((status << 16) & 0x0f); + tda1004x_read_byte(i2c, tda_state, TDA1004X_CVBER_LUT); + + // if RS has passed some valid TS packets, then we must be + // getting some SYNC bytes + if (vber < 16632) { + *fe_status |= FE_HAS_SYNC; + } + } + + // success + dprintk("%s: fe_status=0x%x\n", __FUNCTION__, *fe_status); + return 0; +} + +static int tda1004x_read_signal_strength(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u16 * signal) +{ + int tmp; + + dprintk("%s\n", __FUNCTION__); + + // read it + tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_SIGNAL_STRENGTH); + if (tmp < 0) + return -EIO; + + // done + *signal = (tmp << 8) | tmp; + dprintk("%s: signal=0x%x\n", __FUNCTION__, *signal); + return 0; +} + + +static int tda1004x_read_snr(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u16 * snr) +{ + int tmp; + + dprintk("%s\n", __FUNCTION__); + + // read it + tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_SNR); + if (tmp < 0) + return -EIO; + if (tmp) { + tmp = 255 - tmp; + } + + // done + *snr = ((tmp << 8) | tmp); + dprintk("%s: snr=0x%x\n", __FUNCTION__, *snr); + return 0; +} + +static int tda1004x_read_ucblocks(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u32* ucblocks) +{ + int tmp; + int tmp2; + int counter; + + dprintk("%s\n", __FUNCTION__); + + // read the UCBLOCKS and reset + counter = 0; + tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_UNCOR); + if (tmp < 0) + return -EIO; + tmp &= 0x7f; + while (counter++ < 5) { + tda1004x_write_mask(i2c, tda_state, TDA1004X_UNCOR, 0x80, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_UNCOR, 0x80, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_UNCOR, 0x80, 0); + + tmp2 = tda1004x_read_byte(i2c, tda_state, TDA1004X_UNCOR); + if (tmp2 < 0) + return -EIO; + tmp2 &= 0x7f; + if ((tmp2 < tmp) || (tmp2 == 0)) + break; + } + + // done + if (tmp != 0x7f) { + *ucblocks = tmp; + } else { + *ucblocks = 0xffffffff; + } + dprintk("%s: ucblocks=0x%x\n", __FUNCTION__, *ucblocks); + return 0; +} + +static int tda1004x_read_ber(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u32* ber) +{ + int tmp; + + dprintk("%s\n", __FUNCTION__); + + // read it in + tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_LSB); + if (tmp < 0) return -EIO; + *ber = tmp << 1; + tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_MSB); + if (tmp < 0) return -EIO; + *ber |= (tmp << 9); + tda1004x_read_byte(i2c, tda_state, TDA1004X_CBER_RESET); + + // done + dprintk("%s: ber=0x%x\n", __FUNCTION__, *ber); + return 0; +} + + +static int tda1004x_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) +{ + int status = 0; + struct dvb_i2c_bus *i2c = fe->i2c; + struct tda1004x_state *tda_state = (struct tda1004x_state *) &(fe->data); + + dprintk("%s: cmd=0x%x\n", __FUNCTION__, cmd); + + switch (cmd) { + case FE_GET_INFO: + switch(tda_state->tda1004x_address) { + case TDA10045H_ADDRESS: + memcpy(arg, &tda10045h_info, sizeof(struct dvb_frontend_info)); + break; + } + break; + + case FE_READ_STATUS: + return tda1004x_read_status(i2c, tda_state, (fe_status_t *) arg); + + case FE_READ_BER: + return tda1004x_read_ber(i2c, tda_state, (u32 *) arg); + + case FE_READ_SIGNAL_STRENGTH: + return tda1004x_read_signal_strength(i2c, tda_state, (u16 *) arg); + + case FE_READ_SNR: + return tda1004x_read_snr(i2c, tda_state, (u16 *) arg); + + case FE_READ_UNCORRECTED_BLOCKS: + return tda1004x_read_ucblocks(i2c, tda_state, (u32 *) arg); + + case FE_SET_FRONTEND: + return tda1004x_set_fe(i2c, tda_state, (struct dvb_frontend_parameters*) arg); + + case FE_GET_FRONTEND: + return tda1004x_get_fe(i2c, tda_state, (struct dvb_frontend_parameters*) arg); + + case FE_INIT: + // don't bother reinitialising + if (tda_state->initialised) + return 0; + + // OK, perform initialisation + status = tda1004x_init(i2c, tda_state); + if (status == 0) + tda_state->initialised = 1; + return status; + + default: + return -EOPNOTSUPP; + } + + return 0; +} + + +static int tda1004x_attach(struct dvb_i2c_bus *i2c) +{ + int tda1004x_address = -1; + int tuner_address = -1; + struct tda1004x_state tda_state; + struct i2c_msg tuner_msg = {.addr=0, .flags=0, .buf=0, .len=0 }; + static u8 td1344_init[] = { 0x0b, 0xf5, 0x88, 0xab }; + static u8 tdm1316l_init[] = { 0x0b, 0xf5, 0x85, 0xab }; + + dprintk("%s\n", __FUNCTION__); + + // probe for frontend + tda_state.tda1004x_address = TDA10045H_ADDRESS; + if (tda1004x_read_byte(i2c, &tda_state, TDA1004X_CHIPID) == 0x25) { + tda1004x_address = TDA10045H_ADDRESS; + printk("tda1004x: Detected Philips TDA10045H.\n"); + } + + // did we find a frontend? + if (tda1004x_address == -1) { + return -ENODEV; + } + + // supported tuner? + tda1004x_enable_tuner_i2c(i2c, &tda_state); + tuner_msg.addr = TD1344_ADDRESS; + tuner_msg.buf = td1344_init; + tuner_msg.len = sizeof(td1344_init); + if (i2c->xfer(i2c, &tuner_msg, 1) == 1) { + dvb_delay(1); + tuner_address = TD1344_ADDRESS; + printk("tda1004x: Detected Philips TD1344 tuner. PLEASE CHECK THIS AND REPORT BACK!.\n"); + } else { + tuner_msg.addr = TDM1316L_ADDRESS; + tuner_msg.buf = tdm1316l_init; + tuner_msg.len = sizeof(tdm1316l_init); + if (i2c->xfer(i2c, &tuner_msg, 1) == 1) { + dvb_delay(1); + tuner_address = TDM1316L_ADDRESS; + printk("tda1004x: Detected Philips TDM1316L tuner.\n"); + } + } + tda1004x_disable_tuner_i2c(i2c, &tda_state); + + // did we find a tuner? + if (tuner_address == -1) { + printk("tda1004x: Detected, but with unknown tuner.\n"); + return -ENODEV; + } + + // create state + tda_state.tda1004x_address = tda1004x_address; + tda_state.tuner_address = tuner_address; + tda_state.initialised = 0; + + // register + switch(tda_state.tda1004x_address) { + case TDA10045H_ADDRESS: + dvb_register_frontend(tda1004x_ioctl, i2c, (void *)(*((u32*) &tda_state)), &tda10045h_info); + break; + } + + // success + return 0; +} + + +static +void tda1004x_detach(struct dvb_i2c_bus *i2c) +{ + dprintk("%s\n", __FUNCTION__); + + dvb_unregister_frontend(tda1004x_ioctl, i2c); +} + + +static +int __init init_tda1004x(void) +{ + return dvb_register_i2c_device(THIS_MODULE, tda1004x_attach, tda1004x_detach); +} + + +static +void __exit exit_tda1004x(void) +{ + dvb_unregister_i2c_device(tda1004x_attach); +} + +module_init(init_tda1004x); +module_exit(exit_tda1004x); + +MODULE_DESCRIPTION("Philips TDA10045H DVB-T Frontend"); +MODULE_AUTHOR("Andrew de Quincey & Robert Schlabbach"); +MODULE_LICENSE("GPL"); + +MODULE_PARM(tda1004x_debug, "i"); +MODULE_PARM_DESC(tda1004x_debug, "enable verbose debug messages"); + +MODULE_PARM(tda1004x_firmware, "s"); +MODULE_PARM_DESC(tda1004x_firmware, "Where to find the firmware file"); diff -Nru a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c --- a/drivers/media/dvb/frontends/ves1820.c Sat Jul 19 12:54:25 2003 +++ b/drivers/media/dvb/frontends/ves1820.c Sat Jul 19 12:54:25 2003 @@ -95,7 +95,7 @@ static u8 ves1820_inittab [] = { - 0x69, 0x6A, 0x9B, 0x0A, 0x52, 0x46, 0x26, 0x1A, + 0x69, 0x6A, 0x9B, 0x12, 0x12, 0x46, 0x26, 0x1A, 0x43, 0x6A, 0xAA, 0xAA, 0x1E, 0x85, 0x43, 0x28, 0xE0, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, @@ -109,7 +109,7 @@ { u8 addr = GET_DEMOD_ADDR(fe->data); u8 buf[] = { 0x00, reg, data }; - struct i2c_msg msg = { addr: addr, .flags = 0, .buf = buf, .len = 3 }; + struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 }; struct dvb_i2c_bus *i2c = fe->i2c; int ret; @@ -130,8 +130,8 @@ u8 b0 [] = { 0x00, reg }; u8 b1 [] = { 0 }; u8 addr = GET_DEMOD_ADDR(fe->data); - struct i2c_msg msg [] = { { addr: addr, .flags = 0, .buf = b0, .len = 2 }, - { addr: addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; + struct i2c_msg msg [] = { { .addr = addr, .flags = 0, .buf = b0, .len = 2 }, + { .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; struct dvb_i2c_bus *i2c = fe->i2c; int ret; @@ -147,7 +147,7 @@ static int tuner_write (struct dvb_i2c_bus *i2c, u8 addr, u8 data [4]) { int ret; - struct i2c_msg msg = { addr: addr, .flags = 0, .buf = data, .len = 4 }; + struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 }; ret = i2c->xfer (i2c, &msg, 1); diff -Nru a/drivers/media/dvb/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile --- a/drivers/media/dvb/ttpci/Makefile Sat Jul 19 12:54:23 2003 +++ b/drivers/media/dvb/ttpci/Makefile Sat Jul 19 12:54:23 2003 @@ -3,16 +3,12 @@ # and the AV7110 DVB device driver # -dvb-ttpci-budget-objs := budget.o -dvb-ttpci-budget-av-objs := budget-av.o -dvb-ttpci-budget-ci-objs := budget-ci.o -dvb-ttpci-budget-patch-objs := budget-patch.o dvb-ttpci-objs := av7110.o av7110_ipack.o av7110_ir.o -obj-$(CONFIG_DVB_BUDGET) += budget-core.o dvb-ttpci-budget.o -obj-$(CONFIG_DVB_BUDGET_CI) += budget-core.o dvb-ttpci-budget-ci.o -obj-$(CONFIG_DVB_BUDGET_AV) += budget-core.o dvb-ttpci-budget-av.o -obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-core.o dvb-ttpci-budget-patch.o -obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o +obj-$(CONFIG_DVB_BUDGET) += budget-core.o budget.o ttpci-eeprom.o +obj-$(CONFIG_DVB_BUDGET_AV) += budget-core.o budget-av.o ttpci-eeprom.o +obj-$(CONFIG_DVB_BUDGET_CI) += budget-core.o budget-ci.o ttpci-eeprom.o +obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-core.o budget-patch.o ttpci-eeprom.o +obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o ttpci-eeprom.o EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ diff -Nru a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c --- a/drivers/media/dvb/ttpci/av7110.c Sat Jul 19 12:54:26 2003 +++ b/drivers/media/dvb/ttpci/av7110.c Sat Jul 19 12:54:26 2003 @@ -86,6 +86,7 @@ #define DEB_EE(x) #endif +#include "ttpci-eeprom.h" #include "av7110.h" #include "av7110_ipack.h" @@ -110,7 +111,8 @@ int av7110_num = 0; -#define FW_CI_LL_SUPPORT(arm_app) (((arm_app) >> 16) & 0x8000) +#define FW_CI_LL_SUPPORT(arm_app) ((arm_app) & 0x80000000) +#define FW_VERSION(arm_app) ((arm_app) & 0x0000FFFF) /**************************************************************************** * DEBI functions @@ -1089,7 +1091,7 @@ u32 stat; #endif - DEB_EE(("av7110: %p\n",av7110)); +// DEB_EE(("av7110: %p\n",av7110)); if (!av7110->arm_ready) { DEB_D(("arm not ready.\n")); @@ -1166,7 +1168,7 @@ { int ret; - DEB_EE(("av7110: %p\n",av7110)); +// DEB_EE(("av7110: %p\n",av7110)); if (!av7110->arm_ready) { DEB_D(("arm not ready.\n")); @@ -1190,7 +1192,7 @@ u16 buf[num+2]; int i, ret; - DEB_EE(("av7110: %p\n",av7110)); +// DEB_EE(("av7110: %p\n",av7110)); buf[0]=(( type << 8 ) | com); buf[1]=num; @@ -1332,7 +1334,7 @@ static inline int SendDAC(struct av7110 *av7110, u8 addr, u8 data) { - DEB_EE(("av7110: %p\n",av7110)); +// DEB_EE(("av7110: %p\n",av7110)); return outcom(av7110, COMTYPE_AUDIODAC, AudioDAC, 2, addr, data); } @@ -1659,6 +1661,24 @@ color, ((blend>>4)&0x0f)); } +static int OSDSetPalette(struct av7110 *av7110, u32 *colors, u8 first, u8 last) +{ + int i; + int length = last - first + 1; + + if (length * 4 > DATA_BUFF3_SIZE) + return -1; + + for (i=0; i> 4; + u32 yuv = blend ? RGB2YUV(colors[i] & 0xFF, (colors[i] >> 8) & 0xFF, (colors[i] >> 16) & 0xFF) | blend : 0; + yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16); // TODO kls2003-06-15: not sure if this is endian-proof + wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i*4, yuv, 4); + } + return outcom(av7110, COMTYPE_OSD, Set_Palette, 4, + av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]], first, last); +} + static int OSDSetBlock(struct av7110 *av7110, int x0, int y0, int x1, int y1, int inc, u8 *data) { uint w, h, bpp, bpl, size, lpb, bnum, brest; @@ -1721,6 +1741,9 @@ return 0; case OSD_SetPalette: { + if (FW_VERSION(av7110->arm_app) >= 0x2618) + OSDSetPalette(av7110, (u32 *)dc->data, dc->color, dc->x0); + else { int i, len=dc->x0-dc->color+1; u8 *colors=(u8 *)dc->data; @@ -1728,6 +1751,7 @@ OSDSetColor(av7110, dc->color+i, colors[i*4] , colors[i*4+1], colors[i*4+2], colors[i*4+3]); + } return 0; } case OSD_SetTrans: @@ -2087,28 +2111,28 @@ static inline void TestMode(struct av7110 *av7110, int mode) { - DEB_EE(("av7110: %p\n",av7110)); +// DEB_EE(("av7110: %p\n",av7110)); outcom(av7110, COMTYPE_ENCODER, SetTestMode, 1, mode); } static inline void VidMode(struct av7110 *av7110, int mode) { - DEB_EE(("av7110: %p\n",av7110)); +// DEB_EE(("av7110: %p\n",av7110)); outcom(av7110, COMTYPE_ENCODER, SetVidMode, 1, mode); } -static inline int vidcom(struct av7110 *av7110, u32 com, u32 arg) +static int inline vidcom(struct av7110 *av7110, u32 com, u32 arg) { - DEB_EE(("av7110: %p\n",av7110)); +// DEB_EE(("av7110: %p\n",av7110)); return outcom(av7110, 0x80, 0x02, 4, (com>>16), (com&0xffff), (arg>>16), (arg&0xffff)); } -static inline int audcom(struct av7110 *av7110, u32 com) +static int inline audcom(struct av7110 *av7110, u32 com) { - DEB_EE(("av7110: %p\n",av7110)); +// DEB_EE(("av7110: %p\n",av7110)); return outcom(av7110, 0x80, 0x03, 4, (com>>16), (com&0xffff)); } @@ -2583,38 +2607,274 @@ * V4L SECTION ****************************************************************************/ -int av7110_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) +static struct v4l2_input inputs[2] = { + { 0, "DVB", V4L2_INPUT_TYPE_CAMERA, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { 1, "ANALOG", V4L2_INPUT_TYPE_TUNER, 2, 1, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, +}; + +/* taken from ves1820.c */ +static int ves1820_writereg(struct saa7146_dev *dev, u8 reg, u8 data) +{ + u8 addr = 0x09; + u8 buf[] = { 0x00, reg, data }; + struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 }; + + DEB_EE(("av7710: dev: %p\n",dev)); + + if( 1 != saa7146_i2c_transfer(dev, &msg, 1, 1)) { + return -1; + } + return 0; +} + +static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4]) +{ + struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 }; + + DEB_EE(("av7710: dev: %p\n",dev)); + + if( 1 != saa7146_i2c_transfer(dev, &msg, 1, 1)) { + return -1; + } + return 0; +} + + +/** + * set up the downconverter frequency divisor for a + * reference clock comparision frequency of 62.5 kHz. + */ +static int tuner_set_tv_freq (struct saa7146_dev *dev, u32 freq) +{ + u32 div; + u8 config; + u8 buf [4]; + + DEB_EE(("av7710: freq: 0x%08x\n",freq)); + + /* magic number: 56. tuning with the frequency given by v4l2 + is always off by 56*62.5 kHz...*/ + div = freq + 56; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x8e; + + if (freq < 16*168.25 ) + config = 0xa0; + else if (freq < 16*447.25) + config = 0x90; + else + config = 0x30; + config &= ~0x02; + + buf[3] = config; + + return tuner_write (dev, 0x61, buf); +} + +static struct saa7146_standard analog_standard[]; +static struct saa7146_standard dvb_standard[]; +static struct saa7146_standard standard[]; + +int av7110_dvb_c_switch(struct saa7146_fh *fh) +{ + struct saa7146_dev *dev = fh->dev; + struct saa7146_vv *vv = dev->vv_data; + struct av7110 *av7110 = (struct av7110*)dev->ext_priv; + u16 buf[3] = { ((COMTYPE_AUDIODAC << 8) + ADSwitch), 1, 1 }; + + u8 band = 0; + int source, sync; + struct saa7146_fh *ov_fh = NULL; + int restart_overlay = 0; + + DEB_EE(("av7110: %p\n",av7110)); + + if( vv->ov_data != NULL ) { + ov_fh = vv->ov_data->fh; + saa7146_stop_preview(ov_fh); + restart_overlay = 1; + } + + if( 0 != av7110->current_input ) { + buf[2] = 0; + band = 0x68; /* analog band */ + source = SAA7146_HPS_SOURCE_PORT_B; + sync = SAA7146_HPS_SYNC_PORT_B; + memcpy(standard,analog_standard,sizeof(struct saa7146_standard)*2); + } else { + buf[2] = 1; + band = 0x28; /* digital band */ + source = SAA7146_HPS_SOURCE_PORT_A; + sync = SAA7146_HPS_SYNC_PORT_A; + memcpy(standard,dvb_standard,sizeof(struct saa7146_standard)*2); + } + + /* hmm, this does not do anything!? */ + if (OutCommand(av7110, buf, 3)) { + printk("ADSwitch error\n"); + } + + if( 0 != ves1820_writereg(dev, 0x0f, band )) { + printk("setting band in demodulator failed.\n"); + } + saa7146_set_hps_source_and_sync(dev, source, sync); + + /* restart overlay if it was active before */ + if( 0 != restart_overlay ) { + saa7146_start_preview(ov_fh); + } + + return 0; +} + +int av7110_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { + struct saa7146_dev *dev = fh->dev; + struct av7110 *av7110 = (struct av7110*)dev->ext_priv; DEB_EE(("saa7146_dev: %p\n",dev)); switch(cmd) { + case VIDIOC_G_TUNER: + { + struct v4l2_tuner *t = arg; + + DEB_EE(("VIDIOC_G_TUNER: %d\n", t->index)); + + if( 0 == av7110->has_analog_tuner || av7110->current_input != 1 ) { + return -EINVAL; + } + + memset(t,0,sizeof(*t)); + strcpy(t->name, "Television"); + + t->type = V4L2_TUNER_ANALOG_TV; + t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP; + t->rangelow = 772; /* 48.25 MHZ / 62.5 kHz = 772, see fi1216mk2-specs, page 2 */ + t->rangehigh = 13684; /* 855.25 MHz / 62.5 kHz = 13684 */ + /* FIXME: add the real signal strength here */ + t->signal = 0xffff; + t->afc = 0; + /* fixme: real autodetection here */ + t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO; + + return 0; + } + case VIDIOC_S_TUNER: + { + struct v4l2_tuner *t = arg; + + DEB_EE(("VIDIOC_S_TUNER: %d\n", t->index)); + + if( 0 == av7110->has_analog_tuner || av7110->current_input != 1 ) { + return -EINVAL; + } + + + switch(t->audmode) { + case V4L2_TUNER_MODE_STEREO: { + DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_STEREO\n")); + break; + } + case V4L2_TUNER_MODE_LANG1: { + DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG1\n")); + break; + } + case V4L2_TUNER_MODE_LANG2: { + DEB_D(("VIDIOC_S_TUNER: V4L2_TUNER_MODE_LANG2\n")); + break; + } + default: { /* case V4L2_TUNER_MODE_MONO: {*/ + DEB_D(("VIDIOC_S_TUNER: TDA9840_SET_MONO\n")); + break; + } + } + + return 0; + } + case VIDIOC_G_FREQUENCY: + { + struct v4l2_frequency *f = arg; + + DEB_EE(("VIDIOC_G_FREQ: freq:0x%08x.\n", f->frequency)); + + if( 0 == av7110->has_analog_tuner || av7110->current_input != 1 ) { + return -EINVAL; + } + + memset(f,0,sizeof(*f)); + f->type = V4L2_TUNER_ANALOG_TV; + f->frequency = av7110->current_freq; + + return 0; + } + case VIDIOC_S_FREQUENCY: + { + struct v4l2_frequency *f = arg; + + DEB_EE(("VIDIOC_S_FREQUENCY: freq:0x%08x.\n",f->frequency)); + + if( 0 == av7110->has_analog_tuner || av7110->current_input != 1 ) { + return -EINVAL; + } + + if (V4L2_TUNER_ANALOG_TV != f->type) + return -EINVAL; + + /* tune in desired frequency */ + tuner_set_tv_freq(dev, f->frequency); + av7110->current_freq = f->frequency; + + return 0; + } case VIDIOC_ENUMINPUT: { struct v4l2_input *i = arg; + DEB_EE(("VIDIOC_ENUMINPUT: %d\n", i->index)); + + if( 0 != av7110->has_analog_tuner ) { + if( i->index < 0 || i->index >= 2) { + return -EINVAL; + } + } else { if( i->index != 0 ) { return -EINVAL; } + } - memset(i,0,sizeof(*i)); - i->index = 0; - strcpy(i->name, "DVB"); - i->type = V4L2_INPUT_TYPE_CAMERA; - i->audioset = 1; + memcpy(i, &inputs[i->index], sizeof(struct v4l2_input)); return 0; } case VIDIOC_G_INPUT: { int *input = (int *)arg; - *input = 0; + *input = av7110->current_input; + DEB_EE(("VIDIOC_G_INPUT: %d\n", *input)); return 0; } case VIDIOC_S_INPUT: { + int input = *(int *)arg; + + DEB_EE(("VIDIOC_S_INPUT: %d\n", input)); + + if( 0 == av7110->has_analog_tuner ) { return 0; } + + if( input < 0 || input >= 2) { + return -EINVAL; + } + + /* fixme: switch inputs here */ + av7110->current_input = input; + return av7110_dvb_c_switch(fh); + } default: + printk("no such ioctl\n"); return -ENOIOCTLCMD; } return 0; @@ -2997,7 +3257,7 @@ DEB_EE(("av7110: fwstc = %04hx %04hx %04hx %04hx\n", fwstc[0], fwstc[1], fwstc[2], fwstc[3])); - *stc = (((uint64_t)fwstc[2] & 1) << 32) | + *stc = (((uint64_t)(~fwstc[2]) & 1) << 32) | (((uint64_t)fwstc[1]) << 16) | ((uint64_t)fwstc[0]); *base = 1; @@ -4006,7 +4266,6 @@ #endif // } - av7110->dvb_net.card_num=av7110->dvb_adapter->num; dvb_net_init(av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx); return 0; @@ -4061,9 +4320,16 @@ { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE }, { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE }, { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE }, + { VIDIOC_G_FREQUENCY, SAA7146_EXCLUSIVE }, + { VIDIOC_S_FREQUENCY, SAA7146_EXCLUSIVE }, + { VIDIOC_G_TUNER, SAA7146_EXCLUSIVE }, + { VIDIOC_S_TUNER, SAA7146_EXCLUSIVE }, { 0, 0 } }; +static struct saa7146_ext_vv av7110_vv_data_st; +static struct saa7146_ext_vv av7110_vv_data_c; + static int av7110_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *pci_ext) { struct av7110 *av7110 = NULL; @@ -4081,7 +4347,16 @@ DEB_EE(("dev: %p, av7110: %p\n",dev,av7110)); - if (saa7146_vv_init(dev)) { + /* special case DVB-C: these cards have an analog tuner + plus need some special handling, so we have separate + saa7146_ext_vv data for these... */ + if (dev->pci->subsystem_vendor == 0x110a) { + ret = saa7146_vv_init(dev, &av7110_vv_data_c); + } else { + ret = saa7146_vv_init(dev, &av7110_vv_data_st); + } + + if ( 0 != ret) { ERR(("cannot init capture device. skipping.\n")); kfree(av7110); return -1; @@ -4114,6 +4389,8 @@ return -ENOMEM; } + ttpci_eeprom_parse_mac(av7110->i2c_bus); + saa7146_write(dev, PCI_BT_V1, 0x1c00101f); saa7146_write(dev, BCS_CTRL, 0x80400040); @@ -4186,9 +4463,9 @@ bootarm(av7110); firmversion(av7110); - if ((av7110->arm_app&0xffff)<0x2501) + if (FW_VERSION(av7110->arm_app)<0x2501) printk ("av7110: Warning, firmware version 0x%04x is too old. " - "System might be unstable!\n", av7110->arm_app&0xffff); + "System might be unstable!\n", FW_VERSION(av7110->arm_app)); kernel_thread(arm_thread, (void *) av7110, 0); @@ -4199,6 +4476,8 @@ VidMode(av7110, vidmode); /* remaining inits according to card and frontend type */ + av7110->has_analog_tuner = 0; + av7110->current_input = 0; if (i2c_writereg(av7110, 0x20, 0x00, 0x00)==1) { printk ("av7110(%d): Crystal audio DAC detected\n", av7110->dvb_adapter->num); @@ -4225,6 +4504,31 @@ msp_writereg(av7110, 0x12, 0x000a, 0x0220); // SCART 1 source msp_writereg(av7110, 0x12, 0x0007, 0x7f00); // SCART 1 volume msp_writereg(av7110, 0x12, 0x000d, 0x4800); // prescale SCART + + if (i2c_writereg(av7110, 0x48, 0x01, 0x00)!=1) { + INFO(("saa7113 not accessible.\n")); + } else { + av7110->has_analog_tuner = 1; + /* init the saa7113 */ + i2c_writereg(av7110, 0x48, 0x02, 0xd0); i2c_writereg(av7110, 0x48, 0x03, 0x23); i2c_writereg(av7110, 0x48, 0x04, 0x00); + i2c_writereg(av7110, 0x48, 0x05, 0x00); i2c_writereg(av7110, 0x48, 0x06, 0xe9); i2c_writereg(av7110, 0x48, 0x07, 0x0d); + i2c_writereg(av7110, 0x48, 0x08, 0x98); i2c_writereg(av7110, 0x48, 0x09, 0x02); i2c_writereg(av7110, 0x48, 0x0a, 0x80); + i2c_writereg(av7110, 0x48, 0x0b, 0x40); i2c_writereg(av7110, 0x48, 0x0c, 0x40); i2c_writereg(av7110, 0x48, 0x0d, 0x00); + i2c_writereg(av7110, 0x48, 0x0e, 0x01); i2c_writereg(av7110, 0x48, 0x0f, 0x7c); i2c_writereg(av7110, 0x48, 0x10, 0x48); + i2c_writereg(av7110, 0x48, 0x11, 0x0c); i2c_writereg(av7110, 0x48, 0x12, 0x8b); i2c_writereg(av7110, 0x48, 0x13, 0x10); + i2c_writereg(av7110, 0x48, 0x14, 0x00); i2c_writereg(av7110, 0x48, 0x15, 0x00); i2c_writereg(av7110, 0x48, 0x16, 0x00); + i2c_writereg(av7110, 0x48, 0x17, 0x00); i2c_writereg(av7110, 0x48, 0x18, 0x00); i2c_writereg(av7110, 0x48, 0x19, 0x00); + i2c_writereg(av7110, 0x48, 0x1a, 0x00); i2c_writereg(av7110, 0x48, 0x1b, 0x00); i2c_writereg(av7110, 0x48, 0x1c, 0x00); + i2c_writereg(av7110, 0x48, 0x1d, 0x00); i2c_writereg(av7110, 0x48, 0x1e, 0x00); + } + + memcpy(standard,dvb_standard,sizeof(struct saa7146_standard)*2); + /* set dd1 stream a & b */ + saa7146_write(dev, DD1_STREAM_B, 0x00000000); + saa7146_write(dev, DD1_INIT, 0x0200700); + saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); + + } else if (dev->pci->subsystem_vendor == 0x110a) { printk("av7110(%d): DVB-C w/o analog module detected\n", av7110->dvb_adapter->num); @@ -4330,6 +4634,16 @@ { "NTSC", V4L2_STD_NTSC, 0x10, 244, 480, 0x40, 708, 709, 480, 640 }, }; +static struct saa7146_standard analog_standard[] = { + { "PAL", V4L2_STD_PAL, 0x18, 288, 576, 0x08, 708, 709, 576, 768 }, + { "NTSC", V4L2_STD_NTSC, 0x10, 244, 480, 0x40, 708, 709, 480, 640 }, +}; + +static struct saa7146_standard dvb_standard[] = { + { "PAL", V4L2_STD_PAL, 0x14, 288, 576, 0x4a, 708, 709, 576, 768 }, + { "NTSC", V4L2_STD_NTSC, 0x10, 244, 480, 0x40, 708, 709, 480, 640 }, +}; + static struct saa7146_extension av7110_extension; #define MAKE_AV7110_INFO(x_var,x_name) \ @@ -4387,7 +4701,7 @@ } -static struct saa7146_ext_vv av7110_vv_data = { +static struct saa7146_ext_vv av7110_vv_data_st = { .inputs = 1, .audios = 1, .capabilities = 0, @@ -4401,9 +4715,23 @@ .ioctl = av7110_ioctl, }; +static struct saa7146_ext_vv av7110_vv_data_c = { + .inputs = 1, + .audios = 1, + .capabilities = V4L2_CAP_TUNER, + .flags = 0, + + .stds = &standard[0], + .num_stds = sizeof(standard)/sizeof(struct saa7146_standard), + .std_callback = &std_callback, + + .ioctls = &ioctls[0], + .ioctl = av7110_ioctl, +}; + + static struct saa7146_extension av7110_extension = { .name = "dvb\0", - .ext_vv_data = &av7110_vv_data, .module = THIS_MODULE, .pci_tbl = &pci_tbl[0], @@ -4442,7 +4770,11 @@ MODULE_PARM(av7110_debug,"i"); MODULE_PARM(vidmode,"i"); +MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC"); MODULE_PARM(pids_off,"i"); +MODULE_PARM_DESC(pids_off,"clear video/audio/PCR PID filters when demux is closed"); MODULE_PARM(adac,"i"); +MODULE_PARM_DESC(adac,"audio DAC type: 0 TI, 1 CRYSTAL, 2 MSP (use if autodetection fails)"); MODULE_PARM(hw_sections, "i"); +MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware"); diff -Nru a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h --- a/drivers/media/dvb/ttpci/av7110.h Sat Jul 19 12:54:21 2003 +++ b/drivers/media/dvb/ttpci/av7110.h Sat Jul 19 12:54:21 2003 @@ -153,7 +153,8 @@ BlitBmp, ReleaseBmp, SetWTrans, - SetWNoTrans + SetWNoTrans, + Set_Palette }; enum av7110_pid_command { @@ -405,6 +406,11 @@ struct dvb_i2c_bus *i2c_bus; char *card_name; + /* support for analog module of dvb-c */ + int has_analog_tuner; + int current_input; + u32 current_freq; + struct tasklet_struct debi_tasklet; struct tasklet_struct gpio_tasklet; @@ -571,6 +577,9 @@ #define DATA_BUFF2_BASE (DATA_BUFF1_BASE+DATA_BUFF1_SIZE) #define DATA_BUFF2_SIZE 0x0800 + +#define DATA_BUFF3_BASE (DATA_BUFF2_BASE+DATA_BUFF2_SIZE) +#define DATA_BUFF3_SIZE 0x0400 #define Reserved (DPRAM_BASE + 0x1E00) #define Reserved_SIZE 0x1C0 diff -Nru a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c --- a/drivers/media/dvb/ttpci/budget-av.c Sat Jul 19 12:54:26 2003 +++ b/drivers/media/dvb/ttpci/budget-av.c Sat Jul 19 12:54:26 2003 @@ -170,6 +170,7 @@ return err; } +static struct saa7146_ext_vv vv_data; static int budget_av_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) @@ -207,16 +208,22 @@ dvb_delay(500); if ((err = saa7113_init (budget_av))) { - budget_av_detach(dev); + /* fixme: proper cleanup here */ + ERR(("cannot init saa7113.\n")); + return err; + } + + if ( 0 != saa7146_vv_init(dev,&vv_data)) { + /* fixme: proper cleanup here */ + ERR(("cannot init vv subsystem.\n")); return err; } - saa7146_vv_init(dev); if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) { + /* fixme: proper cleanup here */ ERR(("cannot register capture v4l2 device.\n")); - budget_av_detach(dev); return err; } @@ -256,8 +263,9 @@ }; -static int av_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) +static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { + struct saa7146_dev *dev = fh->dev; struct budget_av *budget_av = (struct budget_av*) dev->ext_priv; /* struct saa7146_vv *vv = dev->vv_data; @@ -299,11 +307,19 @@ } static struct saa7146_standard standard[] = { - { "PAL", V4L2_STD_PAL, SAA7146_PAL_VALUES }, - { "NTSC", V4L2_STD_NTSC, SAA7146_NTSC_VALUES }, + { + .name = "PAL", .id = V4L2_STD_PAL, + .v_offset = 0x17, .v_field = 288, .v_calc = 576, + .h_offset = 0x14, .h_pixels = 680, .h_calc = 680+1, + .v_max_out = 576, .h_max_out = 768, + }, { + .name = "NTSC", .id = V4L2_STD_NTSC, + .v_offset = 0x16, .v_field = 240, .v_calc = 480, + .h_offset = 0x06, .h_pixels = 708, .h_calc = 708+1, + .v_max_out = 480, .h_max_out = 640, + } }; - static struct saa7146_ext_vv vv_data = { .inputs = 2, .capabilities = 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113 @@ -337,8 +353,6 @@ .module = THIS_MODULE, .attach = budget_av_attach, .detach = budget_av_detach, - - .ext_vv_data = &vv_data, .irq_mask = MASK_10, .irq_func = ttpci_budget_irq10_handler, diff -Nru a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c --- a/drivers/media/dvb/ttpci/budget-ci.c Sat Jul 19 12:54:23 2003 +++ b/drivers/media/dvb/ttpci/budget-ci.c Sat Jul 19 12:54:23 2003 @@ -371,7 +371,6 @@ static struct saa7146_extension budget_extension = { .name = "budget_ci dvb\0", .flags = 0, - .ext_vv_data = NULL, .module = THIS_MODULE, .pci_tbl = &pci_tbl[0], diff -Nru a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c --- a/drivers/media/dvb/ttpci/budget-core.c Sat Jul 19 12:54:24 2003 +++ b/drivers/media/dvb/ttpci/budget-core.c Sat Jul 19 12:54:24 2003 @@ -1,4 +1,5 @@ #include "budget.h" +#include "ttpci-eeprom.h" int budget_debug = 0; @@ -165,7 +166,6 @@ if (ret < 0) return ret; - budget->dvb_net.card_num = budget->dvb_adapter->num; dvb_net_init(budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx); return 0; @@ -222,7 +222,7 @@ get recognized before the main driver is loaded */ saa7146_write(dev, GPIO_CTRL, 0x500000); - saa7146_i2c_adapter_prepare(dev, NULL, SAA7146_I2C_BUS_BIT_RATE_3200); + saa7146_i2c_adapter_prepare(dev, NULL, SAA7146_I2C_BUS_BIT_RATE_120); budget->i2c_bus = dvb_register_i2c_bus (master_xfer, dev, budget->dvb_adapter, 0); @@ -231,6 +231,8 @@ dvb_unregister_adapter (budget->dvb_adapter); return -ENOMEM; } + + ttpci_eeprom_parse_mac(budget->i2c_bus); if( NULL == (budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci,length,&budget->pt))) { ret = -ENOMEM; diff -Nru a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c --- a/drivers/media/dvb/ttpci/budget-patch.c Sat Jul 19 12:54:23 2003 +++ b/drivers/media/dvb/ttpci/budget-patch.c Sat Jul 19 12:54:23 2003 @@ -165,6 +165,7 @@ { struct budget_patch *budget; int err; + int count = 0; if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL))) return -ENOMEM; @@ -263,7 +264,6 @@ static struct saa7146_extension budget_extension = { .name = "budget_patch dvb\0", .flags = 0, - .ext_vv_data = NULL, .module = THIS_MODULE, .pci_tbl = pci_tbl, diff -Nru a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c --- a/drivers/media/dvb/ttpci/budget.c Sat Jul 19 12:54:25 2003 +++ b/drivers/media/dvb/ttpci/budget.c Sat Jul 19 12:54:25 2003 @@ -192,6 +192,7 @@ MAKE_BUDGET_INFO(ttbs, "TT-Budget/WinTV-NOVA-S PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttbc, "TT-Budget/WinTV-NOVA-C PCI", BUDGET_TT); MAKE_BUDGET_INFO(ttbt, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT); +MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T PCI", BUDGET_TT); MAKE_BUDGET_INFO(satel, "SATELCO Multimedia PCI", BUDGET_TT_HW_DISEQC); /* Uncomment for Budget Patch */ /*MAKE_BUDGET_INFO(fs_1_3,"Siemens/Technotrend/Hauppauge PCI rev1.3+Budget_Patch", BUDGET_PATCH);*/ @@ -202,6 +203,7 @@ MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003), MAKE_EXTENSION_PCI(ttbc, 0x13c2, 0x1004), MAKE_EXTENSION_PCI(ttbt, 0x13c2, 0x1005), + MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011), MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013), { .vendor = 0, @@ -213,7 +215,6 @@ static struct saa7146_extension budget_extension = { .name = "budget dvb\0", .flags = 0, - .ext_vv_data = NULL, .module = THIS_MODULE, .pci_tbl = pci_tbl, diff -Nru a/drivers/media/dvb/ttpci/ttpci-eeprom.c b/drivers/media/dvb/ttpci/ttpci-eeprom.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/ttpci/ttpci-eeprom.c Sat Jul 19 12:54:30 2003 @@ -0,0 +1,120 @@ +/* + Retrieve encoded MAC address from 24C16 serial 2-wire EEPROM, + decode it and store it in the associated adapter struct for + use by dvb_net.c + + This code was tested on TT-Budget/WinTV-NOVA-CI PCI boards with + Atmel and ST Microelectronics EEPROMs. + + This card appear to have the 24C16 write protect held to ground, + thus permitting normal read/write operation. Theoretically it + would be possible to write routines to burn a different (encoded) + MAC address into the EEPROM. + + Robert Schlabbach GMX + Michael Glaum KVH Industries + Holger Waechtler Convergence + + 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 "dvb_i2c.h" +#include "dvb_functions.h" + +#if 1 +#define dprintk(x...) printk(x) +#else +#define dprintk(x...) +#endif + + +static int ttpci_eeprom_read_encodedMAC(struct dvb_i2c_bus *i2c, u8 * encodedMAC) +{ + int ret; + u8 b0[] = { 0xd4 }; + + struct i2c_msg msg[] = { + {.addr = 0x50,.flags = 0,.buf = b0,.len = 1}, + {.addr = 0x50,.flags = I2C_M_RD,.buf = encodedMAC,.len = 6} + }; + + dprintk("%s\n", __FUNCTION__); + + ret = i2c->xfer(i2c, msg, 2); + + if (ret != 2) /* Assume EEPROM isn't there */ + return (-ENODEV); + + return 0; +} + +static void decodeMAC(u8 * decodedMAC, const u8 * encodedMAC) +{ + u8 ormask0[3] = { 0x54, 0x7B, 0x9E }; + u8 ormask1[3] = { 0xD3, 0xF1, 0x23 }; + u8 low; + u8 high; + u8 shift; + int i; + + decodedMAC[0] = 0x00; + decodedMAC[1] = 0xD0; + decodedMAC[2] = 0x5C; + + for (i = 0; i < 3; i++) { + low = encodedMAC[2 * i] ^ ormask0[i]; + high = encodedMAC[2 * i + 1] ^ ormask1[i]; + shift = (high >> 6) & 0x3; + + decodedMAC[5 - i] = ((high << 8) | low) >> shift; + } + +} + + +int ttpci_eeprom_parse_mac(struct dvb_i2c_bus *i2c) +{ + int ret; + u8 encodedMAC[6]; + u8 decodedMAC[6]; + + ret = ttpci_eeprom_read_encodedMAC(i2c, encodedMAC); + + if (ret != 0) { /* Will only be -ENODEV */ + dprintk("Couldn't read from EEPROM: not there?\n"); + memset(i2c->adapter->proposed_mac, 0, 6); + return ret; + } + + decodeMAC(decodedMAC, encodedMAC); + memcpy(i2c->adapter->proposed_mac, decodedMAC, 6); + + dprintk("%s adapter %i has MAC addr = %02x:%02x:%02x:%02x:%02x:%02x\n", + i2c->adapter->name, i2c->adapter->num, + decodedMAC[0], decodedMAC[1], decodedMAC[2], + decodedMAC[3], decodedMAC[4], decodedMAC[5]); + dprintk("encoded MAC was %02x:%02x:%02x:%02x:%02x:%02x\n", + encodedMAC[0], encodedMAC[1], encodedMAC[2], + encodedMAC[3], encodedMAC[4], encodedMAC[5]); + return 0; +} + +EXPORT_SYMBOL(ttpci_eeprom_parse_mac); diff -Nru a/drivers/media/dvb/ttpci/ttpci-eeprom.h b/drivers/media/dvb/ttpci/ttpci-eeprom.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/ttpci/ttpci-eeprom.h Sat Jul 19 12:54:30 2003 @@ -0,0 +1,32 @@ +/* + Retrieve encoded MAC address from ATMEL ttpci_eeprom serial 2-wire EEPROM, + decode it and store it in associated adapter net device + + Robert Schlabbach GMX + Michael Glaum KVH Industries + Holger Waechtler Convergence + + 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 __TTPCI_EEPROM_H__ +#define __TTPCI_EEPROM_H__ + +#include "dvb_i2c.h" + +extern int ttpci_eeprom_parse_mac(struct dvb_i2c_bus *i2c); + +#endif diff -Nru a/drivers/media/dvb/ttusb-budget/Kconfig b/drivers/media/dvb/ttusb-budget/Kconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/ttusb-budget/Kconfig Sat Jul 19 12:54:30 2003 @@ -0,0 +1,11 @@ +config DVB_TTUSB_BUDGET + tristate "Technotrend/Hauppauge Nova-USB devices" + depends on DVB_CORE && USB + help + Support for external USB adapters designed by Technotrend and + produced by Hauppauge, shipped under the brand name 'Nova-USB'. + + These devices don't have a MPEG decoder built in, so you need + an external software decoder to watch TV. + + Say Y if you own such a device and want to use it. diff -Nru a/drivers/media/dvb/ttusb-budget/Makefile b/drivers/media/dvb/ttusb-budget/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/ttusb-budget/Makefile Sat Jul 19 12:54:30 2003 @@ -0,0 +1,3 @@ +obj-$(CONFIG_DVB_TTUSB_BUDGET) += dvb-ttusb-budget.o + +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ diff -Nru a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c Sat Jul 19 12:54:30 2003 @@ -0,0 +1,1271 @@ +/* + * TTUSB DVB driver + * + * Copyright (c) 2002 Holger Waechtler + * Copyright (c) 2003 Felix Domke + * + * 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 + +#include "dvb_frontend.h" +#include "dmxdev.h" +#include "dvb_demux.h" +#include "dvb_net.h" + +#include +#include +#include +#include + +#include "dvb_functions.h" + +/* + TTUSB_HWSECTIONS: + the DSP supports filtering in hardware, however, since the "muxstream" + is a bit braindead (no matching channel masks or no matching filter mask), + we won't support this - yet. it doesn't event support negative filters, + so the best way is maybe to keep TTUSB_HWSECTIONS undef'd and just + parse TS data. USB bandwith will be a problem when having large + datastreams, especially for dvb-net, but hey, that's not my problem. + + TTUSB_DISEQC, TTUSB_TONE: + let the STC do the diseqc/tone stuff. this isn't supported at least with + my TTUSB, so let it undef'd unless you want to implement another + frontend. never tested. + + DEBUG: + define it to > 3 for really hardcore debugging. you probably don't want + this unless the device doesn't load at all. > 2 for bandwidth statistics. +*/ + +static int debug = 0; + +#define dprintk(x...) do { if (debug) printk(KERN_DEBUG x); } while (0) + +#define ISO_BUF_COUNT 4 +#define FRAMES_PER_ISO_BUF 4 +#define ISO_FRAME_SIZE 912 +#define TTUSB_MAXCHANNEL 32 +#ifdef TTUSB_HWSECTIONS +#define TTUSB_MAXFILTER 16 /* ??? */ +#endif + +#define TTUSB_BUDGET_NAME "ttusb_stc_fw" + +/** + * since we're casting (struct ttusb*) <-> (struct dvb_demux*) around + * the dvb_demux field must be the first in struct!! + */ +struct ttusb { + struct dvb_demux dvb_demux; + struct dmxdev dmxdev; + struct dvb_net dvbnet; + + /* our semaphore, for channel allocation/deallocation */ + struct semaphore sem; + /* and one for USB access. */ + struct semaphore semusb; + + struct dvb_adapter *adapter; + struct usb_device *dev; + + int disconnecting; + int iso_streaming; + + unsigned int bulk_out_pipe; + unsigned int bulk_in_pipe; + unsigned int isoc_in_pipe; + + void *iso_buffer; + dma_addr_t iso_dma_handle; + + struct urb *iso_urb[ISO_BUF_COUNT]; + + int running_feed_count; + int last_channel; + int last_filter; + + u8 c; /* transaction counter, wraps around... */ + fe_sec_tone_mode_t tone; + fe_sec_voltage_t voltage; + + int mux_state; // 0..2 - MuxSyncWord, 3 - nMuxPacks, 4 - muxpack + u8 mux_npacks; + u8 muxpack[256 + 8]; + int muxpack_ptr, muxpack_len; + + int insync; + + u16 cc; /* MuxCounter - will increment on EVERY MUX PACKET */ + /* (including stuffing. yes. really.) */ + + u8 last_result[32]; + + struct ttusb_channel { + struct ttusb *ttusb; + struct dvb_demux_feed *dvbdmxfeed; + + int active; + int id; + int pid; + int type; /* 1 - TS, 2 - Filter */ +#ifdef TTUSB_HWSECTIONS + int filterstate[TTUSB_MAXFILTER]; /* 0: not busy, 1: busy */ +#endif + } channel[TTUSB_MAXCHANNEL]; +#if 0 + devfs_handle_t stc_devfs_handle; +#endif +}; + +/* ugly workaround ... don't know why it's neccessary to read */ +/* all result codes. */ + +#define DEBUG 0 +static int ttusb_cmd(struct ttusb *ttusb, + const u8 * data, int len, int needresult) +{ + int actual_len; + int err; +#if DEBUG >= 3 + int i; + + printk(">"); + for (i = 0; i < len; ++i) + printk(" %02x", data[i]); + printk("\n"); +#endif + + if (down_interruptible(&ttusb->semusb) < 0) + return -EAGAIN; + + err = usb_bulk_msg(ttusb->dev, ttusb->bulk_out_pipe, + (u8 *) data, len, &actual_len, HZ); + if (err != 0) { + dprintk("%s: usb_bulk_msg(send) failed, err == %i!\n", + __FUNCTION__, err); + up(&ttusb->semusb); + return err; + } + if (actual_len != len) { + dprintk("%s: only wrote %d of %d bytes\n", __FUNCTION__, + actual_len, len); + up(&ttusb->semusb); + return -1; + } + + err = usb_bulk_msg(ttusb->dev, ttusb->bulk_in_pipe, + ttusb->last_result, 32, &actual_len, HZ); + + if (err != 0) { + printk("%s: failed, receive error %d\n", __FUNCTION__, + err); + up(&ttusb->semusb); + return err; + } +#if DEBUG >= 3 + actual_len = ttusb->last_result[3] + 4; + printk("<"); + for (i = 0; i < actual_len; ++i) + printk(" %02x", ttusb->last_result[i]); + printk("\n"); +#endif + if (!needresult) + up(&ttusb->semusb); + return 0; +} + +static int ttusb_result(struct ttusb *ttusb, u8 * data, int len) +{ + memcpy(data, ttusb->last_result, len); + up(&ttusb->semusb); + return 0; +} + +static int ttusb_i2c_msg(struct ttusb *ttusb, + u8 addr, u8 * snd_buf, u8 snd_len, u8 * rcv_buf, + u8 rcv_len) +{ + u8 b[0x28]; + u8 id = ++ttusb->c; + int i, err; + + if (snd_len > 0x28 - 7 || rcv_len > 0x20 - 7) + return -EINVAL; + + b[0] = 0xaa; + b[1] = id; + b[2] = 0x31; + b[3] = snd_len + 3; + b[4] = addr << 1; + b[5] = snd_len; + b[6] = rcv_len; + + for (i = 0; i < snd_len; i++) + b[7 + i] = snd_buf[i]; + + err = ttusb_cmd(ttusb, b, snd_len + 7, 1); + + if (err) + return -EREMOTEIO; + + err = ttusb_result(ttusb, b, 0x20); + + if (rcv_len > 0) { + + if (err || b[0] != 0x55 || b[1] != id) { + dprintk + ("%s: usb_bulk_msg(recv) failed, err == %i, id == %02x, b == ", + __FUNCTION__, err, id); + return -EREMOTEIO; + } + + for (i = 0; i < rcv_len; i++) + rcv_buf[i] = b[7 + i]; + } + + return rcv_len; +} + +static int ttusb_i2c_xfer(struct dvb_i2c_bus *i2c, const struct i2c_msg msg[], + int num) +{ + struct ttusb *ttusb = i2c->data; + int i = 0; + int inc; + + if (down_interruptible(&ttusb->sem) < 0) + return -EAGAIN; + + while (i < num) { + u8 addr, snd_len, rcv_len, *snd_buf, *rcv_buf; + int err; + + if (num > i + 1 && (msg[i + 1].flags & I2C_M_RD)) { + addr = msg[i].addr; + snd_buf = msg[i].buf; + snd_len = msg[i].len; + rcv_buf = msg[i + 1].buf; + rcv_len = msg[i + 1].len; + inc = 2; + } else { + addr = msg[i].addr; + snd_buf = msg[i].buf; + snd_len = msg[i].len; + rcv_buf = NULL; + rcv_len = 0; + inc = 1; + } + + err = ttusb_i2c_msg(ttusb, addr, + snd_buf, snd_len, rcv_buf, rcv_len); + + if (err < rcv_len) { + printk("%s: i == %i\n", __FUNCTION__, i); + break; + } + + i += inc; + } + + up(&ttusb->sem); + return i; +} + +#include "dvb-ttusb-dspbootcode.h" + +static int ttusb_boot_dsp(struct ttusb *ttusb) +{ + int i, err; + u8 b[40]; + + /* BootBlock */ + b[0] = 0xaa; + b[2] = 0x13; + b[3] = 28; + + /* upload dsp code in 32 byte steps (36 didn't work for me ...) */ + /* 32 is max packet size, no messages should be splitted. */ + for (i = 0; i < sizeof(dsp_bootcode); i += 28) { + memcpy(&b[4], &dsp_bootcode[i], 28); + + b[1] = ++ttusb->c; + + err = ttusb_cmd(ttusb, b, 32, 0); + if (err) + goto done; + } + + /* last block ... */ + b[1] = ++ttusb->c; + b[2] = 0x13; + b[3] = 0; + + err = ttusb_cmd(ttusb, b, 4, 0); + if (err) + goto done; + + /* BootEnd */ + b[1] = ++ttusb->c; + b[2] = 0x14; + b[3] = 0; + + err = ttusb_cmd(ttusb, b, 4, 0); + + done: + if (err) { + dprintk("%s: usb_bulk_msg() failed, return value %i!\n", + __FUNCTION__, err); + } + + return err; +} + +static int ttusb_set_channel(struct ttusb *ttusb, int chan_id, int filter_type, + int pid) +{ + int err; + /* SetChannel */ + u8 b[] = { 0xaa, ++ttusb->c, 0x22, 4, chan_id, filter_type, + (pid >> 8) & 0xff, pid & 0xff + }; + + err = ttusb_cmd(ttusb, b, sizeof(b), 0); + return err; +} + +static int ttusb_del_channel(struct ttusb *ttusb, int channel_id) +{ + int err; + /* DelChannel */ + u8 b[] = { 0xaa, ++ttusb->c, 0x23, 1, channel_id }; + + err = ttusb_cmd(ttusb, b, sizeof(b), 0); + return err; +} + +#ifdef TTUSB_HWSECTIONS +static int ttusb_set_filter(struct ttusb *ttusb, int filter_id, + int associated_chan, u8 filter[8], u8 mask[8]) +{ + int err; + /* SetFilter */ + u8 b[] = { 0xaa, 0, 0x24, 0x1a, filter_id, associated_chan, + filter[0], filter[1], filter[2], filter[3], + filter[4], filter[5], filter[6], filter[7], + filter[8], filter[9], filter[10], filter[11], + mask[0], mask[1], mask[2], mask[3], + mask[4], mask[5], mask[6], mask[7], + mask[8], mask[9], mask[10], mask[11] + }; + + err = ttusb_cmd(ttusb, b, sizeof(b), 0); + return err; +} + +static int ttusb_del_filter(struct ttusb *ttusb, int filter_id) +{ + int err; + /* DelFilter */ + u8 b[] = { 0xaa, ++ttusb->c, 0x25, 1, filter_id }; + + err = ttusb_cmd(ttusb, b, sizeof(b), 0); + return err; +} +#endif + +static int ttusb_init_controller(struct ttusb *ttusb) +{ + u8 b0[] = { 0xaa, ++ttusb->c, 0x15, 1, 0 }; + u8 b1[] = { 0xaa, ++ttusb->c, 0x15, 1, 1 }; + u8 b2[] = { 0xaa, ++ttusb->c, 0x32, 1, 0 }; + /* i2c write read: 5 bytes, addr 0x10, 0x02 bytes write, 1 bytes read. */ + u8 b3[] = + { 0xaa, ++ttusb->c, 0x31, 5, 0x10, 0x02, 0x01, 0x00, 0x1e }; + u8 b4[] = + { 0x55, ttusb->c, 0x31, 4, 0x10, 0x02, 0x01, 0x00, 0x1e }; + + u8 get_version[] = { 0xaa, ++ttusb->c, 0x17, 5, 0, 0, 0, 0, 0 }; + u8 get_dsp_version[0x20] = + { 0xaa, ++ttusb->c, 0x26, 28, 0, 0, 0, 0, 0 }; + int err; + + /* reset board */ + if ((err = ttusb_cmd(ttusb, b0, sizeof(b0), 0))) + return err; + + /* reset board (again?) */ + if ((err = ttusb_cmd(ttusb, b1, sizeof(b1), 0))) + return err; + + ttusb_boot_dsp(ttusb); + + /* set i2c bit rate */ + if ((err = ttusb_cmd(ttusb, b2, sizeof(b2), 0))) + return err; + + if ((err = ttusb_cmd(ttusb, b3, sizeof(b3), 1))) + return err; + + err = ttusb_result(ttusb, b4, sizeof(b4)); + + if ((err = ttusb_cmd(ttusb, get_version, sizeof(get_version), 1))) + return err; + + if ((err = ttusb_result(ttusb, get_version, sizeof(get_version)))) + return err; + + dprintk("%s: stc-version: %c%c%c%c%c\n", __FUNCTION__, + get_version[4], get_version[5], get_version[6], + get_version[7], get_version[8]); + + if (memcmp(get_version + 4, "V 0.0", 5) && + memcmp(get_version + 4, "V 1.1", 5)) { + printk + ("%s: unknown STC version %c%c%c%c%c, please report!\n", + __FUNCTION__, get_version[4], get_version[5], + get_version[6], get_version[7], get_version[8]); + } + + err = + ttusb_cmd(ttusb, get_dsp_version, sizeof(get_dsp_version), 1); + if (err) + return err; + + err = + ttusb_result(ttusb, get_dsp_version, sizeof(get_dsp_version)); + if (err) + return err; + printk("%s: dsp-version: %c%c%c\n", __FUNCTION__, + get_dsp_version[4], get_dsp_version[5], get_dsp_version[6]); + return 0; +} + +#ifdef TTUSB_DISEQC +static int ttusb_send_diseqc(struct ttusb *ttusb, + const struct dvb_diseqc_master_cmd *cmd) +{ + u8 b[12] = { 0xaa, ++ttusb->c, 0x18 }; + + int err; + + b[3] = 4 + 2 + cmd->msg_len; + b[4] = 0xFF; /* send diseqc master, not burst */ + b[5] = cmd->msg_len; + + memcpy(b + 5, cmd->msg, cmd->msg_len); + + /* Diseqc */ + if ((err = ttusb_cmd(ttusb, b, 4 + b[3], 0))) { + dprintk("%s: usb_bulk_msg() failed, return value %i!\n", + __FUNCTION__, err); + } + + return err; +} +#endif + +static int ttusb_update_lnb(struct ttusb *ttusb) +{ + u8 b[] = { 0xaa, ++ttusb->c, 0x16, 5, /*power: */ 1, + ttusb->voltage == SEC_VOLTAGE_18 ? 0 : 1, + ttusb->tone == SEC_TONE_ON ? 1 : 0, 1, 1 + }; + int err; + + /* SetLNB */ + if ((err = ttusb_cmd(ttusb, b, sizeof(b), 0))) { + dprintk("%s: usb_bulk_msg() failed, return value %i!\n", + __FUNCTION__, err); + } + + return err; +} + +static int ttusb_set_voltage(struct ttusb *ttusb, fe_sec_voltage_t voltage) +{ + ttusb->voltage = voltage; + return ttusb_update_lnb(ttusb); +} + +#ifdef TTUSB_TONE +static int ttusb_set_tone(struct ttusb *ttusb, fe_sec_tone_mode_t tone) +{ + ttusb->tone = tone; + return ttusb_update_lnb(ttusb); +} +#endif + +static int ttusb_lnb_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) +{ + struct ttusb *ttusb = fe->i2c->data; + + switch (cmd) { + case FE_SET_VOLTAGE: + return ttusb_set_voltage(ttusb, (fe_sec_voltage_t) arg); +#ifdef TTUSB_TONE + case FE_SET_TONE: + return ttusb_set_tone(ttusb, (fe_sec_tone_mode_t) arg); +#endif +#ifdef TTUSB_DISEQC + case FE_DISEQC_SEND_MASTER_CMD: + return ttusb_send_diseqc(ttusb, + (struct dvb_diseqc_master_cmd *) + arg); +#endif + default: + return -EOPNOTSUPP; + }; +} + +#if 0 +static void ttusb_set_led_freq(struct ttusb *ttusb, u8 freq) +{ + u8 b[] = { 0xaa, ++ttusb->c, 0x19, 1, freq }; + int err, actual_len; + + err = ttusb_cmd(ttusb, b, sizeof(b), 0); + if (err) { + dprintk("%s: usb_bulk_msg() failed, return value %i!\n", + __FUNCTION__, err); + } +} +#endif + +/*****************************************************************************/ + +#ifdef TTUSB_HWSECTIONS +static void ttusb_handle_ts_data(struct ttusb_channel *channel, + const u8 * data, int len); +static void ttusb_handle_sec_data(struct ttusb_channel *channel, + const u8 * data, int len); +#endif + +int numpkt = 0, lastj, numts, numstuff, numsec, numinvalid; + +static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack, + int len) +{ + u16 csum = 0, cc; + int i; + for (i = 0; i < len; i += 2) + csum ^= le16_to_cpup((u16 *) (muxpack + i)); + if (csum) { + printk("%s: muxpack with incorrect checksum, ignoring\n", + __FUNCTION__); + numinvalid++; + return; + } + + cc = (muxpack[len - 4] << 8) | muxpack[len - 3]; + cc &= 0x7FFF; + if (cc != ttusb->cc) + printk("%s: cc discontinuity (%d frames missing)\n", + __FUNCTION__, (cc - ttusb->cc) & 0x7FFF); + ttusb->cc = (cc + 1) & 0x7FFF; + if (muxpack[0] & 0x80) { +#ifdef TTUSB_HWSECTIONS + /* section data */ + int pusi = muxpack[0] & 0x40; + int channel = muxpack[0] & 0x1F; + int payload = muxpack[1]; + const u8 *data = muxpack + 2; + /* check offset flag */ + if (muxpack[0] & 0x20) + data++; + + ttusb_handle_sec_data(ttusb->channel + channel, data, + payload); + data += payload; + + if ((!!(ttusb->muxpack[0] & 0x20)) ^ + !!(ttusb->muxpack[1] & 1)) + data++; +#warning TODO: pusi + printk("cc: %04x\n", (data[0] << 8) | data[1]); +#endif + numsec++; + } else if (muxpack[0] == 0x47) { +#ifdef TTUSB_HWSECTIONS + /* we have TS data here! */ + int pid = ((muxpack[1] & 0x0F) << 8) | muxpack[2]; + int channel; + for (channel = 0; channel < TTUSB_MAXCHANNEL; ++channel) + if (ttusb->channel[channel].active + && (pid == ttusb->channel[channel].pid)) + ttusb_handle_ts_data(ttusb->channel + + channel, muxpack, + 188); +#endif + numts++; + dvb_dmx_swfilter_packets(&ttusb->dvb_demux, muxpack, 1); + } else if (muxpack[0] != 0) { + numinvalid++; + printk("illegal muxpack type %02x\n", muxpack[0]); + } else + numstuff++; +} + +static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len) +{ + int maxwork = 1024; + while (len) { + if (!(maxwork--)) { + printk("%s: too much work\n", __FUNCTION__); + break; + } + + switch (ttusb->mux_state) { + case 0: + case 1: + case 2: + len--; + if (*data++ == 0xAA) + ++ttusb->mux_state; + else { + ttusb->mux_state = 0; +#if DEBUG > 3 + if (ttusb->insync) + printk("%02x ", data[-1]); +#else + if (ttusb->insync) { + printk("%s: lost sync.\n", + __FUNCTION__); + ttusb->insync = 0; + } +#endif + } + break; + case 3: + ttusb->insync = 1; + len--; + ttusb->mux_npacks = *data++; + ++ttusb->mux_state; + ttusb->muxpack_ptr = 0; + /* maximum bytes, until we know the length */ + ttusb->muxpack_len = 2; + break; + case 4: + { + int avail; + avail = len; + if (avail > + (ttusb->muxpack_len - + ttusb->muxpack_ptr)) + avail = + ttusb->muxpack_len - + ttusb->muxpack_ptr; + memcpy(ttusb->muxpack + ttusb->muxpack_ptr, + data, avail); + ttusb->muxpack_ptr += avail; + if (ttusb->muxpack_ptr > 264) + BUG(); + data += avail; + len -= avail; + /* determine length */ + if (ttusb->muxpack_ptr == 2) { + if (ttusb->muxpack[0] & 0x80) { + ttusb->muxpack_len = + ttusb->muxpack[1] + 2; + if (ttusb-> + muxpack[0] & 0x20) + ttusb-> + muxpack_len++; + if ((!! + (ttusb-> + muxpack[0] & 0x20)) ^ + !!(ttusb-> + muxpack[1] & 1)) + ttusb-> + muxpack_len++; + ttusb->muxpack_len += 4; + } else if (ttusb->muxpack[0] == + 0x47) + ttusb->muxpack_len = + 188 + 4; + else if (ttusb->muxpack[0] == 0x00) + ttusb->muxpack_len = + ttusb->muxpack[1] + 2 + + 4; + else { + dprintk + ("%s: invalid state: first byte is %x\n", + __FUNCTION__, + ttusb->muxpack[0]); + ttusb->mux_state = 0; + } + } + + /** + * if length is valid and we reached the end: + * goto next muxpack + */ + if ((ttusb->muxpack_ptr >= 2) && + (ttusb->muxpack_ptr == + ttusb->muxpack_len)) { + ttusb_process_muxpack(ttusb, + ttusb-> + muxpack, + ttusb-> + muxpack_ptr); + ttusb->muxpack_ptr = 0; + /* maximum bytes, until we know the length */ + ttusb->muxpack_len = 2; + + /** + * no muxpacks left? + * return to search-sync state + */ + if (!ttusb->mux_npacks--) { + ttusb->mux_state = 0; + break; + } + } + break; + } + default: + BUG(); + break; + } + } +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +static void ttusb_iso_irq(struct urb *urb) +#else +static void ttusb_iso_irq(struct urb *urb, struct pt_regs *ptregs) +#endif +{ + struct ttusb *ttusb = urb->context; + + if (!ttusb->iso_streaming) + return; + +#if 0 + printk("%s: status %d, errcount == %d, length == %i\n", + __FUNCTION__, + urb->status, urb->error_count, urb->actual_length); +#endif + + if (!urb->status) { + int i; + for (i = 0; i < urb->number_of_packets; ++i) { + struct usb_iso_packet_descriptor *d; + u8 *data; + int len; + numpkt++; + if ((jiffies - lastj) >= HZ) { +#if DEBUG > 2 + printk + ("frames/s: %d (ts: %d, stuff %d, sec: %d, invalid: %d, all: %d)\n", + numpkt * HZ / (jiffies - lastj), + numts, numstuff, numsec, numinvalid, + numts + numstuff + numsec + + numinvalid); +#endif + numts = numstuff = numsec = numinvalid = 0; + lastj = jiffies; + numpkt = 0; + } + d = &urb->iso_frame_desc[i]; + data = urb->transfer_buffer + d->offset; + len = d->actual_length; + d->actual_length = 0; + d->status = 0; + ttusb_process_frame(ttusb, data, len); + } + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + usb_submit_urb(urb, GFP_KERNEL); +#endif +} + +static void ttusb_free_iso_urbs(struct ttusb *ttusb) +{ + int i; + + for (i = 0; i < ISO_BUF_COUNT; i++) + if (ttusb->iso_urb[i]) + usb_free_urb(ttusb->iso_urb[i]); + + pci_free_consistent(NULL, + ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * + ISO_BUF_COUNT, ttusb->iso_buffer, + ttusb->iso_dma_handle); +} + +static int ttusb_alloc_iso_urbs(struct ttusb *ttusb) +{ + int i; + + ttusb->iso_buffer = pci_alloc_consistent(NULL, + ISO_FRAME_SIZE * + FRAMES_PER_ISO_BUF * + ISO_BUF_COUNT, + &ttusb->iso_dma_handle); + + memset(ttusb->iso_buffer, 0, + ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT); + + for (i = 0; i < ISO_BUF_COUNT; i++) { + struct urb *urb; + + if (! + (urb = + usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_KERNEL))) { + ttusb_free_iso_urbs(ttusb); + return -ENOMEM; + } + + ttusb->iso_urb[i] = urb; + } + + return 0; +} + +static void ttusb_stop_iso_xfer(struct ttusb *ttusb) +{ + int i; + + for (i = 0; i < ISO_BUF_COUNT; i++) + usb_unlink_urb(ttusb->iso_urb[i]); + + ttusb->iso_streaming = 0; +} + +static int ttusb_start_iso_xfer(struct ttusb *ttusb) +{ + int i, j, err, buffer_offset = 0; + + if (ttusb->iso_streaming) { + printk("%s: iso xfer already running!\n", __FUNCTION__); + return 0; + } + + ttusb->insync = 0; + ttusb->mux_state = 0; + + for (i = 0; i < ISO_BUF_COUNT; i++) { + int frame_offset = 0; + struct urb *urb = ttusb->iso_urb[i]; + + urb->dev = ttusb->dev; + urb->context = ttusb; + urb->complete = ttusb_iso_irq; + urb->pipe = ttusb->isoc_in_pipe; + urb->transfer_flags = URB_ISO_ASAP; + urb->number_of_packets = FRAMES_PER_ISO_BUF; + urb->transfer_buffer_length = + ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF; + urb->transfer_buffer = ttusb->iso_buffer + buffer_offset; + buffer_offset += ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF; + + for (j = 0; j < FRAMES_PER_ISO_BUF; j++) { + urb->iso_frame_desc[j].offset = frame_offset; + urb->iso_frame_desc[j].length = ISO_FRAME_SIZE; + frame_offset += ISO_FRAME_SIZE; + } + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + for (i = 0; i < ISO_BUF_COUNT; i++) { + int next = (i + 1) % ISO_BUF_COUNT; + ttusb->iso_urb[i]->next = ttusb->iso_urb[next]; + } +#endif + + for (i = 0; i < ISO_BUF_COUNT; i++) { + if ((err = usb_submit_urb(ttusb->iso_urb[i], GFP_KERNEL))) { + ttusb_stop_iso_xfer(ttusb); + printk + ("%s: failed urb submission (%i: err = %i)!\n", + __FUNCTION__, i, err); + return err; + } + } + + ttusb->iso_streaming = 1; + + return 0; +} + +#ifdef TTUSB_HWSECTIONS +static void ttusb_handle_ts_data(struct ttusb_channel *channel, const u8 * data, + int len) +{ + struct dvb_demux_feed *dvbdmxfeed = channel->dvbdmxfeed; + + dvbdmxfeed->cb.ts(data, len, 0, 0, &dvbdmxfeed->feed.ts, 0); +} + +static void ttusb_handle_sec_data(struct ttusb_channel *channel, const u8 * data, + int len) +{ +// struct dvb_demux_feed *dvbdmxfeed = channel->dvbdmxfeed; +#error TODO: handle ugly stuff +// dvbdmxfeed->cb.sec(data, len, 0, 0, &dvbdmxfeed->feed.sec, 0); +} +#endif + +static struct ttusb_channel *ttusb_channel_allocate(struct ttusb *ttusb) +{ + int i; + + if (down_interruptible(&ttusb->sem)) + return NULL; + + /* lock! */ + for (i = 0; i < TTUSB_MAXCHANNEL; ++i) { + if (!ttusb->channel[i].active) { + ttusb->channel[i].active = 1; + up(&ttusb->sem); + return ttusb->channel + i; + } + } + + up(&ttusb->sem); + + return NULL; +} + +static int ttusb_start_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + struct ttusb *ttusb = (struct ttusb *) dvbdmxfeed->demux; + struct ttusb_channel *channel; + + printk("ttusb_start_feed\n"); + + switch (dvbdmxfeed->type) { + case DMX_TYPE_TS: + break; + case DMX_TYPE_SEC: + break; + default: + return -EINVAL; + } + + if (dvbdmxfeed->type == DMX_TYPE_TS) { + switch (dvbdmxfeed->pes_type) { + case DMX_TS_PES_VIDEO: + case DMX_TS_PES_AUDIO: + case DMX_TS_PES_TELETEXT: + case DMX_TS_PES_PCR: + case DMX_TS_PES_OTHER: + channel = ttusb_channel_allocate(ttusb); + break; + default: + return -EINVAL; + } + } else { + channel = ttusb_channel_allocate(ttusb); + } + + if (!channel) + return -EBUSY; + + dvbdmxfeed->priv = channel; + channel->dvbdmxfeed = dvbdmxfeed; + + channel->pid = dvbdmxfeed->pid; + +#ifdef TTUSB_HWSECTIONS + if (dvbdmxfeed->type == DMX_TYPE_TS) { + channel->type = 1; + } else if (dvbdmxfeed->type == DMX_TYPE_SEC) { + channel->type = 2; +#error TODO: allocate filters + } +#else + channel->type = 1; +#endif + + ttusb_set_channel(ttusb, channel->id, channel->type, channel->pid); + + if (0 == ttusb->running_feed_count++) + ttusb_start_iso_xfer(ttusb); + + return 0; +} + +static int ttusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + struct ttusb_channel *channel = + (struct ttusb_channel *) dvbdmxfeed->priv; + struct ttusb *ttusb = (struct ttusb *) dvbdmxfeed->demux; + + ttusb_del_channel(channel->ttusb, channel->id); + + if (--ttusb->running_feed_count == 0) + ttusb_stop_iso_xfer(ttusb); + + channel->active = 0; + + return 0; +} + +static int ttusb_setup_interfaces(struct ttusb *ttusb) +{ + usb_set_configuration(ttusb->dev, 1); + usb_set_interface(ttusb->dev, 1, 1); + + ttusb->bulk_out_pipe = usb_sndbulkpipe(ttusb->dev, 1); + ttusb->bulk_in_pipe = usb_rcvbulkpipe(ttusb->dev, 1); + ttusb->isoc_in_pipe = usb_rcvisocpipe(ttusb->dev, 2); + + return 0; +} + +#if 0 +static u8 stc_firmware[8192]; + +static int stc_open(struct inode *inode, struct file *file) +{ + struct ttusb *ttusb = file->private_data; + int addr; + + for (addr = 0; addr < 8192; addr += 16) { + u8 snd_buf[2] = { addr >> 8, addr & 0xFF }; + ttusb_i2c_msg(ttusb, 0x50, snd_buf, 2, stc_firmware + addr, + 16); + } + + return 0; +} + +static ssize_t stc_read(struct file *file, char *buf, size_t count, + loff_t * offset) +{ + int tc = count; + + if ((tc + *offset) > 8192) + tc = 8192 - *offset; + + if (tc < 0) + return 0; + + copy_to_user(buf, stc_firmware + *offset, tc); + + *offset += tc; + + return tc; +} + +static int stc_release(struct inode *inode, struct file *file) +{ + return 0; +} + +static struct file_operations stc_fops = { + .owner = THIS_MODULE, + .read = stc_read, + .open = stc_open, + .release = stc_release, +}; +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +static void *ttusb_probe(struct usb_device *udev, unsigned int ifnum, + const struct usb_device_id *id) +{ + struct ttusb *ttusb; + int result, channel; + + if (ifnum != 0) + return NULL; + + dprintk("%s: TTUSB DVB connected\n", __FUNCTION__); + + if (!(ttusb = kmalloc(sizeof(struct ttusb), GFP_KERNEL))) + return NULL; + +#else +static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct usb_device *udev; + struct ttusb *ttusb; + int result, channel; + + dprintk("%s: TTUSB DVB connected\n", __FUNCTION__); + + udev = interface_to_usbdev(intf); + + if (!(ttusb = kmalloc(sizeof(struct ttusb), GFP_KERNEL))) + return -ENOMEM; + +#endif + + memset(ttusb, 0, sizeof(struct ttusb)); + + for (channel = 0; channel < TTUSB_MAXCHANNEL; ++channel) { + ttusb->channel[channel].id = channel; + ttusb->channel[channel].ttusb = ttusb; + } + + ttusb->dev = udev; + ttusb->c = 0; + ttusb->mux_state = 0; + sema_init(&ttusb->sem, 0); + sema_init(&ttusb->semusb, 1); + + ttusb_setup_interfaces(ttusb); + + ttusb_alloc_iso_urbs(ttusb); + if (ttusb_init_controller(ttusb)) + printk("ttusb_init_controller: error\n"); + + up(&ttusb->sem); + + dvb_register_adapter(&ttusb->adapter, + "Technotrend/Hauppauge Nova-USB"); + + dvb_register_i2c_bus(ttusb_i2c_xfer, ttusb, ttusb->adapter, 0); + dvb_add_frontend_ioctls(ttusb->adapter, ttusb_lnb_ioctl, NULL, + ttusb); + + memset(&ttusb->dvb_demux, 0, sizeof(ttusb->dvb_demux)); + + ttusb->dvb_demux.dmx.capabilities = + DMX_TS_FILTERING | DMX_SECTION_FILTERING; + ttusb->dvb_demux.priv = 0; +#ifdef TTUSB_HWSECTIONS + ttusb->dvb_demux.filternum = TTUSB_MAXFILTER; +#else + ttusb->dvb_demux.filternum = 32; +#endif + ttusb->dvb_demux.feednum = TTUSB_MAXCHANNEL; + ttusb->dvb_demux.start_feed = ttusb_start_feed; + ttusb->dvb_demux.stop_feed = ttusb_stop_feed; + ttusb->dvb_demux.write_to_decoder = 0; + + if ((result = dvb_dmx_init(&ttusb->dvb_demux)) < 0) { + printk("ttusb_dvb: dvb_dmx_init failed (errno = %d)\n", + result); + goto err; + } +//FIXME dmxdev (nur WAS?) + ttusb->dmxdev.filternum = ttusb->dvb_demux.filternum; + ttusb->dmxdev.demux = &ttusb->dvb_demux.dmx; + ttusb->dmxdev.capabilities = 0; + + if ((result = dvb_dmxdev_init(&ttusb->dmxdev, ttusb->adapter)) < 0) { + printk("ttusb_dvb: dvb_dmxdev_init failed (errno = %d)\n", + result); + dvb_dmx_release(&ttusb->dvb_demux); + goto err; + } + + if (dvb_net_init + (ttusb->adapter, &ttusb->dvbnet, &ttusb->dvb_demux.dmx)) { + printk("ttusb_dvb: dvb_net_init failed!\n"); + } + + err: +#if 0 + ttusb->stc_devfs_handle = + devfs_register(ttusb->adapter->devfs_handle, TTUSB_BUDGET_NAME, + DEVFS_FL_DEFAULT, 0, 192, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP + | S_IROTH | S_IWOTH, &stc_fops, ttusb); +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + return (void *) ttusb; +#else + usb_set_intfdata(intf, (void *) ttusb); + + return 0; +#endif +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +static void ttusb_disconnect(struct usb_device *udev, void *data) +{ + struct ttusb *ttusb = data; +#else +static void ttusb_disconnect(struct usb_interface *intf) +{ + struct ttusb *ttusb = usb_get_intfdata(intf); + + usb_set_intfdata(intf, NULL); +#endif + + ttusb->disconnecting = 1; + + ttusb_stop_iso_xfer(ttusb); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,69)) +#undef devfs_remove +#define devfs_remove(x) devfs_unregister(ttusb->stc_devfs_handle); +#endif +#if 0 + devfs_remove(TTUSB_BUDGET_NAME); +#endif + ttusb->dvb_demux.dmx.close(&ttusb->dvb_demux.dmx); + dvb_net_release(&ttusb->dvbnet); + dvb_dmxdev_release(&ttusb->dmxdev); + dvb_dmx_release(&ttusb->dvb_demux); + + dvb_unregister_i2c_bus(ttusb_i2c_xfer, ttusb->adapter, 0); + dvb_unregister_adapter(ttusb->adapter); + + ttusb_free_iso_urbs(ttusb); + + kfree(ttusb); + + dprintk("%s: TTUSB DVB disconnected\n", __FUNCTION__); +} + +static struct usb_device_id ttusb_table[] = { + {USB_DEVICE(0xb48, 0x1003)}, + {USB_DEVICE(0xb48, 0x1004)}, /* to be confirmed ???? */ + {USB_DEVICE(0xb48, 0x1005)}, /* to be confirmed ???? */ + {} +}; + +MODULE_DEVICE_TABLE(usb, ttusb_table); + +static struct usb_driver ttusb_driver = { + .name = "Technotrend/Hauppauge USB-Nova", + .probe = ttusb_probe, + .disconnect = ttusb_disconnect, + .id_table = ttusb_table, +}; + +static int __init ttusb_init(void) +{ + int err; + + if ((err = usb_register(&ttusb_driver)) < 0) { + printk("%s: usb_register failed! Error number %d", + __FILE__, err); + return -1; + } + + return 0; +} + +static void __exit ttusb_exit(void) +{ + usb_deregister(&ttusb_driver); +} + +module_init(ttusb_init); +module_exit(ttusb_exit); + +MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "Debug or not"); + +MODULE_AUTHOR("Holger Waechtler "); +MODULE_DESCRIPTION("TTUSB DVB Driver"); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h b/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h Sat Jul 19 12:54:30 2003 @@ -0,0 +1,1644 @@ + +#include + +u8 dsp_bootcode [] __initdata = { + 0x08, 0xaa, 0x00, 0x18, 0x00, 0x03, 0x08, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x01, 0x80, 0x18, 0x5f, + 0x00, 0x00, 0x01, 0x80, 0x77, 0x18, 0x2a, 0xeb, + 0x6b, 0xf8, 0x00, 0x18, 0x03, 0xff, 0x68, 0xf8, + 0x00, 0x18, 0xff, 0xfe, 0xf7, 0xb8, 0xf7, 0xbe, + 0xf6, 0xb9, 0xf4, 0xa0, 0xf6, 0xb7, 0xf6, 0xb5, + 0xf6, 0xb6, 0xf0, 0x20, 0x19, 0xdf, 0xf1, 0x00, + 0x00, 0x01, 0xf8, 0x4d, 0x01, 0xab, 0xf6, 0xb8, + 0xf0, 0x20, 0x19, 0xdf, 0xf0, 0x73, 0x01, 0xa5, + 0x7e, 0xf8, 0x00, 0x12, 0xf0, 0x00, 0x00, 0x01, + 0x47, 0xf8, 0x00, 0x11, 0x7e, 0x92, 0x00, 0xf8, + 0x00, 0x11, 0xf0, 0x00, 0x00, 0x01, 0x7e, 0xf8, + 0x00, 0x11, 0xf0, 0x00, 0x00, 0x01, 0x6c, 0x89, + 0x01, 0x9a, 0xf7, 0xb8, 0xee, 0xfc, 0xf0, 0x20, + 0xff, 0xff, 0xf1, 0x00, 0x00, 0x01, 0xf8, 0x4d, + 0x01, 0xbf, 0xf2, 0x73, 0x01, 0xb9, 0x4e, 0x02, + 0xf4, 0x95, 0xf5, 0xe3, 0x56, 0x02, 0x7e, 0x00, + 0x11, 0x00, 0xfa, 0x4c, 0x01, 0xb7, 0x6b, 0x03, + 0x00, 0x01, 0xf6, 0xb8, 0xee, 0x04, 0xf0, 0x74, + 0x0d, 0xa7, 0xf0, 0x74, 0x01, 0xc5, 0x4a, 0x11, + 0x4a, 0x16, 0x72, 0x11, 0x2a, 0xe6, 0x10, 0xf8, + 0x00, 0x11, 0xfa, 0x45, 0x01, 0xdb, 0xf4, 0x95, + 0xee, 0xff, 0x48, 0x11, 0xf0, 0x00, 0x2a, 0xc6, + 0x88, 0x16, 0xf4, 0x95, 0xf4, 0x95, 0x10, 0xee, + 0xff, 0xff, 0xf4, 0xe3, 0x6c, 0xe9, 0xff, 0xff, + 0x01, 0xd5, 0x10, 0xf8, 0x2a, 0xe7, 0xf8, 0x45, + 0x01, 0xe2, 0x10, 0xf8, 0x2a, 0xe7, 0xf4, 0xe3, + 0xf0, 0x74, 0x01, 0xff, 0xee, 0x01, 0x8a, 0x16, + 0x8a, 0x11, 0xfc, 0x00, 0xf7, 0xb8, 0xe9, 0x20, + 0x4a, 0x11, 0x09, 0xf8, 0x2a, 0xe6, 0xf8, 0x4e, + 0x01, 0xf3, 0xf2, 0x73, 0x01, 0xfd, 0xf4, 0x95, + 0xe8, 0x01, 0x72, 0x11, 0x2a, 0xe6, 0x49, 0x11, + 0x80, 0xe1, 0x2a, 0xc6, 0xf3, 0x00, 0x00, 0x01, + 0xe8, 0x00, 0x81, 0xf8, 0x2a, 0xe6, 0x8a, 0x11, + 0xfc, 0x00, 0xf4, 0x95, 0xf0, 0x73, 0x02, 0x00, + 0x10, 0xf8, 0x2a, 0x0f, 0xfc, 0x00, 0x4a, 0x11, + 0xf0, 0x74, 0x02, 0x02, 0x80, 0xf8, 0x2a, 0x10, + 0x73, 0x08, 0x00, 0x09, 0x40, 0xf8, 0x2a, 0x15, + 0x82, 0xf8, 0x00, 0x11, 0xf4, 0x95, 0x77, 0x10, + 0x03, 0xe8, 0xf5, 0xa9, 0xf8, 0x30, 0x02, 0x21, + 0x71, 0xf8, 0x2a, 0x10, 0x2a, 0x15, 0x56, 0xf8, + 0x2a, 0x0c, 0xf0, 0xe3, 0x4e, 0xf8, 0x2a, 0x16, + 0xe8, 0x00, 0x4e, 0xf8, 0x2a, 0x0c, 0x8a, 0x11, + 0xfc, 0x00, 0x4a, 0x06, 0x4a, 0x07, 0x4a, 0x1d, + 0x68, 0xf8, 0x00, 0x07, 0x7d, 0x3f, 0x69, 0xf8, + 0x00, 0x07, 0x40, 0x00, 0x68, 0xf8, 0x00, 0x1d, + 0xff, 0xfc, 0x6b, 0xf8, 0x2a, 0x0f, 0x00, 0x01, + 0x8a, 0x1d, 0x8a, 0x07, 0x8a, 0x06, 0xf4, 0xeb, + 0xee, 0xfd, 0x76, 0xf8, 0x2a, 0x0f, 0x00, 0x00, + 0x76, 0x00, 0x00, 0x00, 0xfb, 0x80, 0x19, 0x4c, + 0xf4, 0x95, 0xe8, 0x00, 0x80, 0xf8, 0x2a, 0x11, + 0xf9, 0x80, 0x19, 0x07, 0x80, 0xf8, 0x2a, 0x0e, + 0xf9, 0x80, 0x16, 0x66, 0x76, 0x00, 0x2a, 0x12, + 0x10, 0xf8, 0x2a, 0x11, 0xf9, 0x80, 0x18, 0xe3, + 0x10, 0xf8, 0x2a, 0x0e, 0xf9, 0x80, 0x16, 0x66, + 0x10, 0xf8, 0x2a, 0x0e, 0xf9, 0x80, 0x16, 0x87, + 0xee, 0x03, 0xfc, 0x00, 0x4a, 0x11, 0xf6, 0xb8, + 0xf4, 0x95, 0xf0, 0x20, 0x80, 0x00, 0x11, 0xf8, + 0x2a, 0x5a, 0xf8, 0x4d, 0x02, 0x93, 0x11, 0xf8, + 0x2a, 0x9f, 0xf8, 0x4c, 0x02, 0x7c, 0x77, 0x12, + 0x2a, 0x39, 0x49, 0x12, 0x01, 0xf8, 0x2a, 0x9f, + 0x89, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x71, 0x81, + 0x00, 0x11, 0x6c, 0xe1, 0xff, 0xab, 0x02, 0x93, + 0x6b, 0xf8, 0x2a, 0x9f, 0x00, 0x01, 0xe9, 0x05, + 0x01, 0xe2, 0x00, 0x03, 0x81, 0xf8, 0x2a, 0xa0, + 0xf0, 0x73, 0x02, 0x95, 0x72, 0x11, 0x2a, 0x9f, + 0xf4, 0x95, 0x10, 0xe1, 0x2a, 0x39, 0x6b, 0xf8, + 0x2a, 0x9f, 0x00, 0x01, 0x11, 0xf8, 0x2a, 0x9f, + 0x09, 0xf8, 0x2a, 0xa0, 0xf8, 0x4c, 0x02, 0x93, + 0x76, 0xf8, 0x2a, 0x5a, 0x00, 0x00, 0x76, 0xf8, + 0x2a, 0x9f, 0x00, 0x00, 0x76, 0xf8, 0x2a, 0xa0, + 0x00, 0x00, 0x88, 0x11, 0xf4, 0x95, 0x48, 0x11, + 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe, + 0x10, 0xf8, 0x2a, 0x5a, 0xf8, 0x44, 0x02, 0xb2, + 0x76, 0xf8, 0x2a, 0x5a, 0x00, 0x01, 0xf0, 0x74, + 0x02, 0x58, 0x88, 0x11, 0xf4, 0x95, 0x77, 0x10, + 0x80, 0x00, 0xf4, 0xa9, 0xf8, 0x30, 0x02, 0xb2, + 0x48, 0x11, 0xf0, 0x30, 0x00, 0xff, 0x80, 0x00, + 0x10, 0xf8, 0x2a, 0x5b, 0xf9, 0x80, 0x18, 0xd6, + 0xee, 0x02, 0x8a, 0x11, 0xfc, 0x00, 0xf4, 0x95, + 0x4a, 0x08, 0x4a, 0x09, 0x4a, 0x0a, 0x4a, 0x0b, + 0x4a, 0x0c, 0x4a, 0x0d, 0x4a, 0x10, 0x4a, 0x11, + 0x4a, 0x12, 0x4a, 0x13, 0x4a, 0x14, 0x4a, 0x15, + 0x4a, 0x16, 0x4a, 0x17, 0x4a, 0x17, 0x4a, 0x19, + 0x4a, 0x0e, 0x4a, 0x06, 0x4a, 0x07, 0x4a, 0x1a, + 0x4a, 0x1d, 0x4a, 0x1b, 0x4a, 0x1c, 0x68, 0xf8, + 0x00, 0x07, 0x7d, 0x3f, 0x69, 0xf8, 0x00, 0x07, + 0x40, 0x00, 0x68, 0xf8, 0x00, 0x1d, 0xff, 0xfc, + 0x48, 0x18, 0x68, 0xf8, 0x00, 0x18, 0xff, 0xfe, + 0xf4, 0x95, 0xf4, 0x95, 0x4a, 0x08, 0xee, 0xfd, + 0xf0, 0x74, 0x02, 0x58, 0x88, 0x11, 0xf4, 0x95, + 0x77, 0x10, 0x80, 0x00, 0xf4, 0xa9, 0xf8, 0x30, + 0x02, 0xef, 0x48, 0x11, 0xf0, 0x30, 0x00, 0xff, + 0x80, 0x00, 0x10, 0xf8, 0x2a, 0x5b, 0xf9, 0x80, + 0x18, 0xd6, 0xee, 0x03, 0x8a, 0x18, 0xf4, 0x95, + 0x8a, 0x1c, 0x8a, 0x1b, 0x8a, 0x1d, 0x8a, 0x1a, + 0x8a, 0x07, 0x8a, 0x06, 0x8a, 0x0e, 0x8a, 0x19, + 0x8a, 0x17, 0x8a, 0x17, 0x8a, 0x16, 0x8a, 0x15, + 0x8a, 0x14, 0x8a, 0x13, 0x8a, 0x12, 0x8a, 0x11, + 0x8a, 0x10, 0x8a, 0x0d, 0x8a, 0x0c, 0x8a, 0x0b, + 0x8a, 0x0a, 0x8a, 0x09, 0x8a, 0x08, 0xf4, 0xeb, + 0x4a, 0x11, 0x77, 0x11, 0x2a, 0x39, 0x76, 0x81, + 0x00, 0x55, 0x77, 0x12, 0x2a, 0x18, 0x10, 0xe2, + 0x00, 0x01, 0x80, 0xe1, 0x00, 0x01, 0x10, 0xe2, + 0x00, 0x02, 0x80, 0xe1, 0x00, 0x02, 0x76, 0xe1, + 0x00, 0x03, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x04, + 0x00, 0xaa, 0xf0, 0x74, 0x02, 0x98, 0x8a, 0x11, + 0xfc, 0x00, 0x4a, 0x11, 0x88, 0x11, 0xf4, 0x95, + 0xf4, 0x95, 0x10, 0x81, 0x6f, 0xf8, 0x2a, 0x9e, + 0x0c, 0x88, 0xe8, 0xff, 0x18, 0xe1, 0x00, 0x01, + 0x1a, 0xf8, 0x2a, 0x9e, 0xf0, 0x30, 0x1f, 0xff, + 0x80, 0xf8, 0x2a, 0x9e, 0x8a, 0x11, 0xfc, 0x00, + 0x4a, 0x11, 0x77, 0x11, 0x2a, 0x39, 0x76, 0x81, + 0x00, 0x55, 0x77, 0x12, 0x2a, 0x18, 0x11, 0xe2, + 0x00, 0x01, 0x81, 0xe1, 0x00, 0x01, 0x11, 0xe2, + 0x00, 0x02, 0x81, 0xe1, 0x00, 0x02, 0x76, 0xe1, + 0x00, 0x03, 0x00, 0x02, 0x48, 0x08, 0x6f, 0xe1, + 0x00, 0x04, 0x0c, 0x98, 0xf0, 0x30, 0x00, 0xff, + 0x80, 0xe1, 0x00, 0x05, 0x76, 0xe1, 0x00, 0x06, + 0x00, 0xaa, 0xf0, 0x74, 0x02, 0x98, 0x8a, 0x11, + 0xfc, 0x00, 0x4a, 0x11, 0x77, 0x11, 0x2a, 0x39, + 0x76, 0x81, 0x00, 0x55, 0x77, 0x12, 0x2a, 0x18, + 0x10, 0xe2, 0x00, 0x01, 0x80, 0xe1, 0x00, 0x01, + 0x10, 0xe2, 0x00, 0x02, 0x80, 0xe1, 0x00, 0x02, + 0x76, 0xe1, 0x00, 0x03, 0x00, 0x04, 0x48, 0x11, + 0xf0, 0x00, 0x00, 0x04, 0x88, 0x12, 0xf4, 0x95, + 0x77, 0x13, 0x2a, 0x76, 0xe9, 0x00, 0xe5, 0x98, + 0xf3, 0x00, 0x00, 0x01, 0xf6, 0xb8, 0x48, 0x0b, + 0x08, 0xf8, 0x2a, 0x3c, 0xf8, 0x43, 0x03, 0x71, + 0x76, 0x82, 0x00, 0xaa, 0xf0, 0x74, 0x02, 0x98, + 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xf0, + 0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x71, 0x81, + 0x00, 0x14, 0x71, 0xe1, 0x00, 0x01, 0x00, 0x15, + 0x49, 0x11, 0xf3, 0x00, 0x00, 0x02, 0x89, 0x11, + 0xe7, 0x82, 0x6d, 0xea, 0x00, 0x04, 0xe7, 0x83, + 0x6d, 0xeb, 0x00, 0x0a, 0x77, 0x1a, 0x00, 0x05, + 0xf0, 0x72, 0x03, 0xaa, 0x11, 0x81, 0xf2, 0xe8, + 0x80, 0x82, 0xe9, 0xff, 0x19, 0xe1, 0x00, 0x01, + 0xf1, 0xa0, 0x81, 0x92, 0x11, 0xe1, 0x00, 0x0c, + 0xf2, 0xe8, 0x80, 0x83, 0xe9, 0xff, 0x19, 0xe1, + 0x00, 0x0d, 0xf1, 0xa0, 0x81, 0x93, 0x6d, 0xe9, + 0x00, 0x02, 0x48, 0x18, 0x49, 0x18, 0x70, 0x00, + 0x00, 0x15, 0xf0, 0x00, 0x00, 0x04, 0xf3, 0x00, + 0x00, 0x0a, 0x80, 0x01, 0x81, 0x02, 0xf2, 0x74, + 0x0e, 0x54, 0xf4, 0x95, 0x48, 0x14, 0xee, 0x10, + 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xf0, 0x74, + 0x0c, 0x5e, 0x80, 0xf8, 0x2a, 0x5c, 0x77, 0x12, + 0x2a, 0x39, 0x76, 0x82, 0x00, 0x55, 0x77, 0x11, + 0x2a, 0x18, 0x10, 0xe1, 0x00, 0x01, 0x80, 0xe2, + 0x00, 0x01, 0x10, 0xe1, 0x00, 0x02, 0x80, 0xe2, + 0x00, 0x02, 0x76, 0xe2, 0x00, 0x03, 0x00, 0x1c, + 0xf6, 0xb8, 0x56, 0xf8, 0x2a, 0x16, 0xf0, 0xf0, + 0xf0, 0xf8, 0x80, 0xe2, 0x00, 0x07, 0x56, 0xf8, + 0x2a, 0x16, 0xf1, 0xf0, 0xe8, 0xff, 0xf2, 0x80, + 0x80, 0xe2, 0x00, 0x06, 0x56, 0xf8, 0x2a, 0x16, + 0xf1, 0xf8, 0xe8, 0xff, 0xf2, 0x80, 0x80, 0xe2, + 0x00, 0x05, 0x57, 0xf8, 0x2a, 0x16, 0xe8, 0xff, + 0xf2, 0x80, 0x80, 0xe2, 0x00, 0x04, 0x56, 0xf8, + 0x27, 0x6c, 0xf0, 0xf0, 0xf0, 0xf8, 0x80, 0xe2, + 0x00, 0x0b, 0x56, 0xf8, 0x27, 0x6c, 0xf1, 0xf0, + 0xe8, 0xff, 0xf2, 0x80, 0x80, 0xe2, 0x00, 0x0a, + 0x56, 0xf8, 0x27, 0x6c, 0xf1, 0xf8, 0xe8, 0xff, + 0xf2, 0x80, 0x80, 0xe2, 0x00, 0x09, 0xe8, 0xff, + 0x57, 0xf8, 0x27, 0x6c, 0xf2, 0x80, 0x80, 0xe2, + 0x00, 0x08, 0x56, 0xf8, 0x27, 0x6a, 0xf0, 0xf0, + 0xf0, 0xf8, 0x80, 0xe2, 0x00, 0x0f, 0x56, 0xf8, + 0x27, 0x6a, 0xf1, 0xf0, 0xe8, 0xff, 0xf2, 0x80, + 0x80, 0xe2, 0x00, 0x0e, 0x56, 0xf8, 0x27, 0x6a, + 0xf1, 0xf8, 0xe8, 0xff, 0xf2, 0x80, 0x80, 0xe2, + 0x00, 0x0d, 0x57, 0xf8, 0x27, 0x6a, 0xe8, 0xff, + 0xf2, 0x80, 0x80, 0xe2, 0x00, 0x0c, 0x76, 0xe2, + 0x00, 0x13, 0x00, 0x00, 0x76, 0xe2, 0x00, 0x12, + 0x00, 0x00, 0x6f, 0xf8, 0x2a, 0x5c, 0x0c, 0x58, + 0x80, 0xe2, 0x00, 0x11, 0xe8, 0xff, 0x18, 0xf8, + 0x2a, 0x5c, 0x80, 0xe2, 0x00, 0x10, 0x76, 0xe2, + 0x00, 0x17, 0x00, 0x00, 0x76, 0xe2, 0x00, 0x16, + 0x00, 0x00, 0x6f, 0xf8, 0x2a, 0x9e, 0x0c, 0x58, + 0x80, 0xe2, 0x00, 0x15, 0xe8, 0xff, 0x18, 0xf8, + 0x2a, 0x9e, 0x80, 0xe2, 0x00, 0x14, 0x76, 0xe2, + 0x00, 0x1b, 0x00, 0x00, 0x76, 0xe2, 0x00, 0x1a, + 0x00, 0x00, 0x76, 0xe2, 0x00, 0x19, 0x00, 0x00, + 0x70, 0xe2, 0x00, 0x18, 0x27, 0x6e, 0x76, 0xe2, + 0x00, 0x1f, 0x00, 0x00, 0x76, 0xe2, 0x00, 0x1e, + 0x00, 0x00, 0x76, 0xe2, 0x00, 0x1d, 0x00, 0x00, + 0x76, 0xe2, 0x00, 0x1c, 0x00, 0x00, 0x76, 0xe2, + 0x00, 0x20, 0x00, 0xaa, 0xf0, 0x74, 0x02, 0x98, + 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe, + 0x10, 0xf8, 0x2a, 0x38, 0xf8, 0x45, 0x04, 0xed, + 0x77, 0x12, 0x2a, 0x18, 0x10, 0xe2, 0x00, 0x02, + 0x88, 0x11, 0xf4, 0x95, 0x77, 0x10, 0x00, 0x08, + 0x6d, 0xe9, 0xff, 0xdf, 0xf6, 0xa9, 0xf8, 0x20, + 0x04, 0x75, 0xf0, 0x73, 0x04, 0x7d, 0xf0, 0x10, + 0x00, 0x21, 0xf0, 0x00, 0x1a, 0x83, 0x48, 0x08, + 0x7e, 0xf8, 0x00, 0x08, 0xf4, 0xe2, 0xf0, 0x74, + 0x03, 0x0a, 0xf0, 0x73, 0x04, 0xea, 0x48, 0x12, + 0xf2, 0x74, 0x03, 0x23, 0xf0, 0x00, 0x00, 0x04, + 0xf2, 0x74, 0x03, 0x36, 0xf4, 0x95, 0xe8, 0x00, + 0xf0, 0x73, 0x04, 0xea, 0x77, 0x11, 0x2a, 0x18, + 0xe8, 0xff, 0x6f, 0xe1, 0x00, 0x04, 0x0d, 0x48, + 0x18, 0xe1, 0x00, 0x05, 0xf2, 0x74, 0x09, 0x69, + 0xf4, 0x95, 0xf2, 0xa0, 0xf0, 0x74, 0x03, 0x36, + 0xf0, 0x73, 0x04, 0xea, 0x77, 0x11, 0x2a, 0x18, + 0xe8, 0xff, 0x6f, 0xe1, 0x00, 0x04, 0x0d, 0x48, + 0x18, 0xe1, 0x00, 0x05, 0xf2, 0x74, 0x09, 0x41, + 0xf4, 0x95, 0xf2, 0xa0, 0xf0, 0x74, 0x03, 0x36, + 0xf0, 0x73, 0x04, 0xea, 0xf0, 0x74, 0x03, 0x57, + 0xf0, 0x73, 0x04, 0xea, 0x10, 0xf8, 0x2a, 0x1c, + 0xf0, 0x74, 0x12, 0xa4, 0xf2, 0x74, 0x03, 0x36, + 0xf4, 0x95, 0xe8, 0x00, 0xf0, 0x73, 0x04, 0xea, + 0x48, 0x12, 0xf2, 0x74, 0x03, 0x80, 0xf0, 0x00, + 0x00, 0x04, 0xf2, 0x74, 0x03, 0x36, 0xf4, 0x95, + 0xe8, 0x00, 0xf0, 0x73, 0x04, 0xea, 0x10, 0xf8, + 0x2a, 0x1c, 0xf0, 0x74, 0x12, 0xc5, 0xf2, 0x74, + 0x03, 0x36, 0xf4, 0x95, 0xe8, 0x00, 0xf0, 0x73, + 0x04, 0xea, 0x77, 0x11, 0x2a, 0x18, 0xe8, 0xff, + 0x6f, 0xe1, 0x00, 0x06, 0x0d, 0x48, 0x18, 0xe1, + 0x00, 0x07, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, + 0xf2, 0xa0, 0x70, 0x00, 0x00, 0x12, 0x80, 0x01, + 0x10, 0xe1, 0x00, 0x04, 0xf0, 0x74, 0x0e, 0x7a, + 0xf2, 0x74, 0x03, 0x36, 0xf4, 0x95, 0xe8, 0x00, + 0xf0, 0x73, 0x04, 0xea, 0xf0, 0x74, 0x03, 0xbc, + 0x76, 0xf8, 0x2a, 0x38, 0x00, 0x00, 0xee, 0x02, + 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x77, 0x11, + 0x2a, 0x39, 0x76, 0x81, 0x00, 0x55, 0x77, 0x12, + 0x2a, 0x18, 0x10, 0xe2, 0x00, 0x01, 0x80, 0xe1, + 0x00, 0x01, 0x10, 0xe2, 0x00, 0x02, 0x80, 0xe1, + 0x00, 0x02, 0x76, 0xe1, 0x00, 0x03, 0x00, 0x09, + 0x48, 0x11, 0xf0, 0x00, 0x00, 0x04, 0x88, 0x12, + 0xf4, 0x95, 0x77, 0x13, 0x2a, 0x86, 0xe9, 0x00, + 0xe5, 0x98, 0xf3, 0x00, 0x00, 0x01, 0xf6, 0xb8, + 0x48, 0x0b, 0x08, 0xf8, 0x2a, 0x3c, 0xf8, 0x43, + 0x05, 0x0a, 0x76, 0x82, 0x00, 0xaa, 0xf0, 0x74, + 0x02, 0x98, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, + 0x77, 0x11, 0x2a, 0x39, 0x76, 0x81, 0x00, 0x55, + 0x77, 0x13, 0x2a, 0x18, 0x10, 0xe3, 0x00, 0x01, + 0x80, 0xe1, 0x00, 0x01, 0x10, 0xe3, 0x00, 0x02, + 0x80, 0xe1, 0x00, 0x02, 0x13, 0xe3, 0x00, 0x03, + 0x81, 0xe1, 0x00, 0x03, 0x48, 0x11, 0x77, 0x11, + 0x00, 0x00, 0xf8, 0x4d, 0x05, 0x44, 0xf0, 0x00, + 0x00, 0x04, 0x88, 0x12, 0x48, 0x13, 0xf0, 0x00, + 0x00, 0x04, 0x88, 0x13, 0xf4, 0x95, 0xf4, 0x95, + 0xe5, 0x98, 0x6d, 0x91, 0xf6, 0xb8, 0x48, 0x11, + 0x08, 0xf8, 0x2a, 0x3c, 0xf8, 0x43, 0x05, 0x3a, + 0xf0, 0x20, 0x2a, 0x39, 0x49, 0x11, 0xf5, 0x00, + 0x89, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x76, 0xe1, + 0x00, 0x04, 0x00, 0xaa, 0xf0, 0x74, 0x02, 0x98, + 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x77, 0x11, + 0x2a, 0x39, 0x76, 0x81, 0x00, 0x55, 0x77, 0x12, + 0x2a, 0x18, 0x10, 0xe2, 0x00, 0x01, 0x80, 0xe1, + 0x00, 0x01, 0x10, 0xe2, 0x00, 0x02, 0x80, 0xe1, + 0x00, 0x02, 0x76, 0xe1, 0x00, 0x03, 0x00, 0x0c, + 0x48, 0x11, 0xf0, 0x00, 0x00, 0x04, 0x88, 0x12, + 0xf4, 0x95, 0x77, 0x13, 0x2a, 0x7a, 0xe9, 0x00, + 0xe5, 0x98, 0xf3, 0x00, 0x00, 0x01, 0xf6, 0xb8, + 0x48, 0x0b, 0x08, 0xf8, 0x2a, 0x3c, 0xf8, 0x43, + 0x05, 0x6a, 0x76, 0x82, 0x00, 0xaa, 0xf0, 0x74, + 0x02, 0x98, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, + 0x77, 0x11, 0x2a, 0x39, 0x76, 0x81, 0x00, 0x55, + 0x77, 0x12, 0x2a, 0x18, 0x10, 0xe2, 0x00, 0x01, + 0x80, 0xe1, 0x00, 0x01, 0x10, 0xe2, 0x00, 0x02, + 0x80, 0xe1, 0x00, 0x02, 0x76, 0xe1, 0x00, 0x03, + 0x00, 0x19, 0x48, 0x11, 0xf0, 0x00, 0x00, 0x04, + 0x88, 0x12, 0xf4, 0x95, 0x77, 0x13, 0x2a, 0x5d, + 0xe9, 0x00, 0xe5, 0x98, 0xf3, 0x00, 0x00, 0x01, + 0xf6, 0xb8, 0x48, 0x0b, 0x08, 0xf8, 0x2a, 0x3c, + 0xf8, 0x43, 0x05, 0x93, 0x76, 0x82, 0x00, 0xaa, + 0xf0, 0x74, 0x02, 0x98, 0x8a, 0x11, 0xfc, 0x00, + 0x4a, 0x11, 0x88, 0x11, 0x10, 0xf8, 0x2a, 0x38, + 0xf8, 0x44, 0x05, 0xe3, 0x10, 0xf8, 0x2a, 0xa1, + 0xf8, 0x44, 0x05, 0xba, 0x6c, 0xe1, 0xff, 0x56, + 0x05, 0xe3, 0x72, 0x12, 0x2a, 0xa1, 0xf4, 0x95, + 0x70, 0xe2, 0x2a, 0x18, 0x00, 0x11, 0x6b, 0xf8, + 0x2a, 0xa1, 0x00, 0x01, 0xf0, 0x73, 0x05, 0xe3, + 0x72, 0x12, 0x2a, 0xa1, 0xf4, 0x95, 0x70, 0xe2, + 0x2a, 0x18, 0x00, 0x11, 0x10, 0xf8, 0x2a, 0xa1, + 0xf0, 0x00, 0x00, 0x01, 0x88, 0x12, 0xf4, 0x95, + 0xf4, 0x95, 0x6e, 0xe2, 0xff, 0xfc, 0x05, 0xd1, + 0x73, 0x12, 0x2a, 0xa1, 0x48, 0x11, 0xf0, 0x00, + 0x00, 0x05, 0x80, 0xf8, 0x2a, 0xa2, 0x10, 0xf8, + 0x2a, 0xa1, 0x08, 0xf8, 0x2a, 0xa2, 0xf8, 0x44, + 0x05, 0xe3, 0x6c, 0xe1, 0xff, 0xab, 0x05, 0xdd, + 0x76, 0xf8, 0x2a, 0x38, 0x00, 0x01, 0x76, 0xf8, + 0x2a, 0xa1, 0x00, 0x00, 0x76, 0xf8, 0x2a, 0xa2, + 0x00, 0x00, 0x8a, 0x11, 0xfc, 0x00, 0xf4, 0x95, + 0x4a, 0x08, 0x4a, 0x09, 0x4a, 0x0a, 0x4a, 0x0b, + 0x4a, 0x0c, 0x4a, 0x0d, 0x4a, 0x10, 0x4a, 0x11, + 0x4a, 0x12, 0x4a, 0x13, 0x4a, 0x14, 0x4a, 0x15, + 0x4a, 0x16, 0x4a, 0x17, 0x4a, 0x17, 0x4a, 0x19, + 0x4a, 0x0e, 0x4a, 0x06, 0x4a, 0x07, 0x4a, 0x1a, + 0x4a, 0x1d, 0x4a, 0x1b, 0x4a, 0x1c, 0x68, 0xf8, + 0x00, 0x07, 0x7d, 0x3f, 0x69, 0xf8, 0x00, 0x07, + 0x40, 0x00, 0x68, 0xf8, 0x00, 0x1d, 0xff, 0xfc, + 0x48, 0x18, 0x68, 0xf8, 0x00, 0x18, 0xff, 0xfe, + 0xf4, 0x95, 0xf4, 0x95, 0x4a, 0x08, 0xee, 0xff, + 0x10, 0xf8, 0x2a, 0x5b, 0xf9, 0x80, 0x18, 0x04, + 0xf0, 0x74, 0x05, 0xa2, 0xee, 0x01, 0x8a, 0x18, + 0xf4, 0x95, 0x8a, 0x1c, 0x8a, 0x1b, 0x8a, 0x1d, + 0x8a, 0x1a, 0x8a, 0x07, 0x8a, 0x06, 0x8a, 0x0e, + 0x8a, 0x19, 0x8a, 0x17, 0x8a, 0x17, 0x8a, 0x16, + 0x8a, 0x15, 0x8a, 0x14, 0x8a, 0x13, 0x8a, 0x12, + 0x8a, 0x11, 0x8a, 0x10, 0x8a, 0x0d, 0x8a, 0x0c, + 0x8a, 0x0b, 0x8a, 0x0a, 0x8a, 0x09, 0x8a, 0x08, + 0xf4, 0xeb, 0xee, 0xfd, 0x76, 0xf8, 0x2a, 0x38, + 0x00, 0x00, 0x76, 0xf8, 0x2a, 0x5a, 0x00, 0x00, + 0xe8, 0x01, 0x4e, 0x00, 0xfb, 0x80, 0x17, 0xd6, + 0xf4, 0x95, 0xe8, 0x01, 0x80, 0xf8, 0x2a, 0x5b, + 0x76, 0x00, 0x2a, 0x8f, 0xf9, 0x80, 0x16, 0xaa, + 0x10, 0xf8, 0x2a, 0x5b, 0xf9, 0x80, 0x17, 0x5c, + 0x10, 0xf8, 0x2a, 0x5b, 0xf9, 0x80, 0x17, 0x6f, + 0xfb, 0x80, 0x16, 0x66, 0xf4, 0x95, 0xe8, 0x1a, + 0xfb, 0x80, 0x16, 0x87, 0xf4, 0x95, 0xe8, 0x1a, + 0xfb, 0x80, 0x16, 0x66, 0xf4, 0x95, 0xe8, 0x1b, + 0xfb, 0x80, 0x16, 0x87, 0xf4, 0x95, 0xe8, 0x1b, + 0xee, 0x03, 0xfc, 0x00, 0x4a, 0x11, 0xf4, 0x95, + 0x13, 0x02, 0x88, 0x11, 0xe8, 0x00, 0xf8, 0x4d, + 0x06, 0x6a, 0xf3, 0x10, 0x00, 0x01, 0x89, 0x1a, + 0xf4, 0x95, 0xf0, 0x72, 0x06, 0x69, 0x1c, 0x91, + 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x88, 0x11, + 0x12, 0x03, 0x11, 0x02, 0xf8, 0x45, 0x06, 0x79, + 0xf0, 0x10, 0x00, 0x01, 0x88, 0x1a, 0xf4, 0x95, + 0xf0, 0x72, 0x06, 0x78, 0x81, 0x91, 0x8a, 0x11, + 0xfc, 0x00, 0x4a, 0x11, 0xf4, 0x95, 0x71, 0x02, + 0x00, 0x11, 0x11, 0x03, 0x61, 0xf8, 0x00, 0x11, + 0x00, 0x01, 0xf8, 0x30, 0x06, 0x91, 0xf6, 0xb8, + 0x6f, 0xf8, 0x00, 0x11, 0x0c, 0x1f, 0x88, 0x11, + 0xf3, 0xe8, 0xe8, 0xff, 0x18, 0x81, 0xf1, 0xa0, + 0x81, 0x81, 0xf0, 0x73, 0x06, 0x9d, 0xf6, 0xb8, + 0x6f, 0xf8, 0x00, 0x11, 0x0c, 0x1f, 0x88, 0x11, + 0xf3, 0x30, 0x00, 0xff, 0xf0, 0x20, 0xff, 0x00, + 0x18, 0x81, 0xf1, 0xa0, 0x81, 0x81, 0x8a, 0x11, + 0xfc, 0x00, 0x4a, 0x11, 0xf4, 0x95, 0x11, 0x02, + 0x61, 0xf8, 0x00, 0x0b, 0x00, 0x01, 0xf8, 0x20, + 0x06, 0xb1, 0x49, 0x0b, 0xf6, 0x1f, 0x88, 0x11, + 0xf4, 0x95, 0xf4, 0x95, 0x10, 0x81, 0xf2, 0x73, + 0x06, 0xb8, 0xf0, 0x30, 0x00, 0xff, 0x49, 0x0b, + 0xf6, 0x1f, 0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, + 0x12, 0x81, 0xf4, 0x78, 0x8a, 0x11, 0xfc, 0x00, + 0x4a, 0x11, 0xf4, 0x95, 0x71, 0x02, 0x00, 0x12, + 0x13, 0x03, 0x88, 0x11, 0xe8, 0x00, 0xf8, 0x4d, + 0x06, 0xcc, 0xf3, 0x10, 0x00, 0x01, 0x89, 0x1a, + 0xf4, 0x95, 0xf0, 0x72, 0x06, 0xcb, 0x11, 0x92, + 0xf2, 0xc0, 0x81, 0x91, 0x8a, 0x11, 0xfc, 0x00, + 0x88, 0x12, 0x12, 0x02, 0x71, 0x01, 0x00, 0x13, + 0xf8, 0x45, 0x06, 0xdb, 0xf0, 0x10, 0x00, 0x01, + 0x88, 0x1a, 0xf4, 0x95, 0xf0, 0x72, 0x06, 0xda, + 0xe5, 0x98, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe, + 0x88, 0x11, 0x11, 0x04, 0x10, 0x06, 0x71, 0x05, + 0x00, 0x12, 0x61, 0xf8, 0x00, 0x12, 0x00, 0x01, + 0xf8, 0x20, 0x06, 0xea, 0xf0, 0x00, 0x00, 0x01, + 0xf6, 0xb8, 0xf0, 0x00, 0x00, 0x01, 0x6f, 0xf8, + 0x00, 0x12, 0x0f, 0x1f, 0x48, 0x08, 0x81, 0x00, + 0xf4, 0x7f, 0x80, 0x01, 0xf2, 0x74, 0x06, 0xba, + 0xf4, 0x95, 0x48, 0x11, 0xee, 0x02, 0x8a, 0x11, + 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe, 0x88, 0x12, + 0x11, 0x04, 0x10, 0x06, 0x71, 0x05, 0x00, 0x13, + 0x61, 0xf8, 0x00, 0x13, 0x00, 0x01, 0xf8, 0x20, + 0x07, 0x09, 0xf0, 0x00, 0x00, 0x01, 0xf0, 0x00, + 0x00, 0x01, 0x88, 0x11, 0xf6, 0xb8, 0x6f, 0xf8, + 0x00, 0x13, 0x0f, 0x1f, 0x81, 0x00, 0x48, 0x11, + 0xf4, 0x7f, 0x80, 0x01, 0xf2, 0x74, 0x06, 0xce, + 0xf4, 0x95, 0x48, 0x12, 0x48, 0x11, 0xf0, 0x30, + 0xff, 0xfe, 0xee, 0x02, 0x8a, 0x11, 0xfc, 0x00, + 0x4a, 0x11, 0x4a, 0x16, 0x4a, 0x17, 0xee, 0xfc, + 0xf4, 0x95, 0x80, 0x02, 0x71, 0x08, 0x00, 0x16, + 0x10, 0x09, 0x71, 0x0b, 0x00, 0x17, 0x80, 0x03, + 0x71, 0x0a, 0x00, 0x11, 0x48, 0x17, 0xf8, 0x45, + 0x07, 0x3f, 0x70, 0x00, 0x00, 0x11, 0x10, 0x03, + 0xf0, 0x74, 0x06, 0x9f, 0x80, 0x01, 0x70, 0x00, + 0x00, 0x16, 0x10, 0x02, 0xf0, 0x74, 0x06, 0x7b, + 0x6d, 0x91, 0x6d, 0x96, 0x6c, 0xef, 0xff, 0xff, + 0x07, 0x2f, 0xee, 0x04, 0x8a, 0x17, 0x8a, 0x16, + 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe, + 0x10, 0xf8, 0x2a, 0xe8, 0x08, 0xf8, 0x2a, 0xe9, + 0xf8, 0x45, 0x07, 0x64, 0x76, 0x00, 0x00, 0x01, + 0x62, 0xf8, 0x2a, 0xe9, 0x00, 0x5e, 0xf2, 0x74, + 0x12, 0x0b, 0xf0, 0x00, 0x30, 0x40, 0x72, 0x11, + 0x2a, 0xe9, 0x77, 0x10, 0x00, 0x0f, 0xf5, 0xa9, + 0xf8, 0x20, 0x07, 0x61, 0x6b, 0xf8, 0x2a, 0xe9, + 0x00, 0x01, 0xf0, 0x73, 0x07, 0x64, 0x76, 0xf8, + 0x2a, 0xe9, 0x00, 0x00, 0xee, 0x02, 0x8a, 0x11, + 0xfc, 0x00, 0x4a, 0x11, 0x88, 0x11, 0xe8, 0x00, + 0x75, 0xf8, 0x00, 0x08, 0x00, 0x08, 0xe8, 0x00, + 0x75, 0xf8, 0x00, 0x08, 0x00, 0x09, 0xf6, 0xb8, + 0xf4, 0x95, 0xf0, 0x20, 0xfc, 0x3f, 0x75, 0xf8, + 0x00, 0x08, 0x00, 0x0d, 0xf0, 0x20, 0x0c, 0x30, + 0x75, 0xf8, 0x00, 0x08, 0x00, 0x0c, 0x76, 0xf8, + 0x2a, 0xe8, 0x00, 0x00, 0x76, 0xf8, 0x2a, 0xe9, + 0x00, 0x00, 0x6c, 0x81, 0x07, 0x92, 0x76, 0xf8, + 0x2a, 0xea, 0x00, 0x00, 0xfb, 0x80, 0x16, 0x76, + 0xf4, 0x95, 0xe8, 0x10, 0xe8, 0x00, 0x75, 0xf8, + 0x00, 0x08, 0x00, 0x00, 0xf0, 0x73, 0x07, 0xa8, + 0x76, 0xf8, 0x2a, 0xea, 0x00, 0x01, 0xfb, 0x80, + 0x16, 0x66, 0xf4, 0x95, 0xe8, 0x10, 0xfb, 0x80, + 0x16, 0x87, 0xf4, 0x95, 0xe8, 0x10, 0xe8, 0x00, + 0x75, 0xf8, 0x00, 0x08, 0x00, 0x00, 0xf6, 0xb8, + 0xf4, 0x95, 0xf0, 0x20, 0xff, 0xff, 0x75, 0xf8, + 0x00, 0x08, 0x00, 0x00, 0x8a, 0x11, 0xfc, 0x00, + 0xf4, 0x95, 0x4a, 0x08, 0x4a, 0x09, 0x4a, 0x0a, + 0x4a, 0x06, 0x4a, 0x07, 0x4a, 0x1d, 0x68, 0xf8, + 0x00, 0x07, 0x7d, 0x3f, 0x69, 0xf8, 0x00, 0x07, + 0x40, 0x00, 0x68, 0xf8, 0x00, 0x1d, 0xff, 0xfc, + 0x10, 0xf8, 0x2a, 0xea, 0xf8, 0x45, 0x07, 0xe1, + 0x10, 0xf8, 0x2a, 0xe8, 0xf0, 0x00, 0x00, 0x01, + 0xf0, 0x30, 0x00, 0x0f, 0x80, 0xf8, 0x2a, 0xe8, + 0x10, 0xf8, 0x2a, 0xe8, 0xf8, 0x44, 0x07, 0xd6, + 0xf6, 0xb8, 0xf4, 0x95, 0xf0, 0x20, 0xfc, 0x3f, + 0x75, 0xf8, 0x00, 0x08, 0x00, 0x0d, 0xf0, 0x20, + 0x0c, 0x30, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x0c, + 0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x00, + 0xf6, 0xb8, 0xf4, 0x95, 0xf0, 0x20, 0xff, 0xff, + 0x75, 0xf8, 0x00, 0x08, 0x00, 0x00, 0x8a, 0x1d, + 0x8a, 0x07, 0x8a, 0x06, 0x8a, 0x0a, 0x8a, 0x09, + 0x8a, 0x08, 0xf4, 0xeb, 0xee, 0xff, 0xf2, 0x74, + 0x07, 0x67, 0xf4, 0x95, 0xe8, 0x01, 0xee, 0x01, + 0xfc, 0x00, 0x4a, 0x07, 0x4a, 0x1d, 0x68, 0xf8, + 0x00, 0x07, 0x7d, 0x3f, 0x69, 0xf8, 0x00, 0x07, + 0x40, 0x00, 0x68, 0xf8, 0x00, 0x1d, 0xff, 0xfc, + 0x8a, 0x1d, 0x8a, 0x07, 0xf4, 0xeb, 0x4a, 0x11, + 0x77, 0x11, 0x00, 0x28, 0x76, 0x81, 0x24, 0x00, + 0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01, + 0xf2, 0x74, 0x07, 0x67, 0xf4, 0x95, 0xe8, 0x00, + 0x77, 0x11, 0x00, 0x1d, 0x68, 0x81, 0x00, 0x7f, + 0xf6, 0xb8, 0xf4, 0x95, 0xf0, 0x20, 0xff, 0x80, + 0x77, 0x11, 0x00, 0x1d, 0xf0, 0x30, 0x01, 0x00, + 0x1a, 0x81, 0x80, 0x81, 0xf0, 0x74, 0x0a, 0x33, + 0xf0, 0x74, 0x11, 0xac, 0xf9, 0x80, 0x13, 0x25, + 0xf9, 0x80, 0x16, 0x53, 0xf9, 0x80, 0x17, 0x82, + 0xf0, 0x74, 0x06, 0x2f, 0xf9, 0x80, 0x14, 0xb2, + 0xf9, 0x80, 0x19, 0x10, 0xf0, 0x74, 0x0d, 0xe3, + 0xf0, 0x74, 0x07, 0xe8, 0xf0, 0x74, 0x02, 0x36, + 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x60, 0xf8, + 0x27, 0x7b, 0xff, 0xff, 0xf8, 0x30, 0x08, 0x39, + 0x71, 0xf8, 0x27, 0x7b, 0x27, 0x79, 0x60, 0xf8, + 0x27, 0x79, 0xff, 0xff, 0xf8, 0x30, 0x08, 0xb2, + 0x10, 0xf8, 0x29, 0x86, 0x08, 0xf8, 0x27, 0x79, + 0xf0, 0x30, 0x7f, 0xff, 0x88, 0x11, 0xf4, 0x95, + 0x77, 0x10, 0x40, 0x00, 0xf6, 0xa9, 0xf8, 0x30, + 0x08, 0x58, 0x10, 0xf8, 0x27, 0x79, 0x08, 0xf8, + 0x27, 0x7a, 0xf0, 0x30, 0x7f, 0xff, 0x88, 0x11, + 0xf4, 0x95, 0x77, 0x10, 0x40, 0x00, 0xf6, 0xa9, + 0xf8, 0x20, 0x08, 0x63, 0x76, 0xf8, 0x27, 0x79, + 0xff, 0xff, 0x76, 0xf8, 0x27, 0x7b, 0xff, 0xff, + 0xf7, 0xb8, 0xf2, 0x73, 0x08, 0xd9, 0xf0, 0x20, + 0xff, 0xff, 0xf6, 0xb8, 0x56, 0xf8, 0x27, 0x74, + 0xf0, 0xf9, 0x88, 0x11, 0x56, 0xf8, 0x27, 0x72, + 0xf0, 0xf9, 0x88, 0x12, 0xf4, 0x95, 0xf4, 0x95, + 0xe7, 0x20, 0xf4, 0xa9, 0xf8, 0x30, 0x08, 0x8f, + 0xf1, 0x20, 0x27, 0x7c, 0x48, 0x11, 0xf6, 0x00, + 0x88, 0x13, 0xf4, 0x95, 0xf4, 0x95, 0x10, 0x83, + 0x08, 0xf8, 0x27, 0x79, 0xf0, 0x30, 0x7f, 0xff, + 0x88, 0x13, 0xf4, 0x95, 0x77, 0x10, 0x40, 0x00, + 0xf5, 0xab, 0xf8, 0x30, 0x08, 0x8f, 0x6d, 0x91, + 0x48, 0x11, 0xf0, 0x30, 0x01, 0xff, 0x88, 0x11, + 0xf4, 0x95, 0xe7, 0x20, 0xf7, 0xa9, 0xf8, 0x30, + 0x08, 0x74, 0x6d, 0x89, 0x48, 0x11, 0xf0, 0x30, + 0x01, 0xff, 0xf0, 0xe7, 0xf4, 0x95, 0x48, 0x08, + 0x4e, 0xf8, 0x27, 0x74, 0x48, 0x08, 0xf1, 0xf9, + 0x89, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x71, 0xe1, + 0x27, 0x7c, 0x27, 0x7a, 0x60, 0xf8, 0x27, 0x7b, + 0xff, 0xff, 0xf8, 0x30, 0x08, 0xab, 0x48, 0x08, + 0x4e, 0xf8, 0x27, 0x72, 0x76, 0xf8, 0x27, 0x7b, + 0xff, 0xff, 0x76, 0xf8, 0x27, 0x79, 0xff, 0xff, + 0xf2, 0x73, 0x08, 0xd9, 0xf4, 0x95, 0xe8, 0x00, + 0x44, 0xf8, 0x27, 0x73, 0x40, 0xf8, 0x27, 0x75, + 0x82, 0xf8, 0x00, 0x11, 0xf4, 0x95, 0x77, 0x10, + 0x80, 0x00, 0xf6, 0xa9, 0xf8, 0x20, 0x08, 0xd8, + 0xf6, 0xb8, 0x10, 0xf8, 0x27, 0x73, 0xf0, 0x00, + 0x80, 0x00, 0x48, 0x08, 0x4e, 0xf8, 0x27, 0x74, + 0x48, 0x08, 0xf0, 0xf9, 0x88, 0x11, 0xf4, 0x95, + 0xf4, 0x95, 0x71, 0xe1, 0x27, 0x7c, 0x27, 0x7a, + 0xf7, 0xb8, 0x57, 0xf8, 0x27, 0x74, 0xf0, 0x62, + 0xff, 0xff, 0xf0, 0x40, 0xff, 0x80, 0xf2, 0x80, + 0x4e, 0xf8, 0x27, 0x74, 0xe8, 0x00, 0x8a, 0x11, + 0xfc, 0x00, 0x4a, 0x11, 0x4a, 0x16, 0xee, 0xfb, + 0x11, 0xf8, 0x27, 0x71, 0x09, 0xf8, 0x27, 0x73, + 0x89, 0x11, 0x88, 0x10, 0xf4, 0x95, 0xf4, 0x95, + 0xf6, 0xa9, 0xf8, 0x20, 0x08, 0xed, 0xf2, 0x73, + 0x09, 0x0e, 0xf4, 0x95, 0xe8, 0x00, 0xf6, 0x20, + 0x76, 0x00, 0x00, 0x41, 0xf0, 0x74, 0x12, 0xee, + 0x88, 0x16, 0xf4, 0x95, 0xf7, 0xb8, 0x6d, 0x96, + 0x10, 0xf8, 0x00, 0x16, 0xf8, 0x47, 0x09, 0x0a, + 0xe7, 0x61, 0x76, 0x00, 0x00, 0x00, 0x76, 0x01, + 0x00, 0x80, 0x76, 0x02, 0x00, 0xff, 0x76, 0x03, + 0x00, 0x00, 0xf2, 0x74, 0x0c, 0xb9, 0xf4, 0x95, + 0xe8, 0x00, 0x6c, 0xe9, 0xff, 0xff, 0x08, 0xfb, + 0x73, 0x16, 0x00, 0x0e, 0xf0, 0x66, 0x00, 0x41, + 0xee, 0x05, 0x8a, 0x16, 0x8a, 0x11, 0xfc, 0x00, + 0x4a, 0x11, 0xf4, 0x95, 0x71, 0x02, 0x00, 0x13, + 0xf6, 0xb8, 0x77, 0x11, 0x7f, 0xff, 0x57, 0xf8, + 0x27, 0x72, 0x48, 0x11, 0xf2, 0x80, 0xf0, 0x00, + 0x80, 0x00, 0x88, 0x11, 0xf6, 0x40, 0xf0, 0xe0, + 0xf1, 0xf1, 0xe8, 0x01, 0xf2, 0x80, 0x80, 0xf8, + 0x27, 0x78, 0x77, 0x12, 0x80, 0x00, 0x57, 0xf8, + 0x27, 0x72, 0x48, 0x12, 0xf2, 0x80, 0x88, 0x12, + 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x82, 0x09, 0x38, + 0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01, + 0xf0, 0x73, 0x09, 0x3d, 0xf0, 0x20, 0x80, 0x01, + 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01, 0x70, 0x81, + 0x00, 0x13, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, + 0xf0, 0x30, 0x7f, 0xff, 0x11, 0xf8, 0x29, 0x86, + 0xf5, 0x20, 0xf3, 0x30, 0x7f, 0xff, 0x89, 0x11, + 0xf4, 0x95, 0x77, 0x10, 0x40, 0x00, 0xf6, 0xa9, + 0xf8, 0x20, 0x09, 0x54, 0xf2, 0x73, 0x09, 0x67, + 0xf4, 0x95, 0xe8, 0x02, 0x6f, 0xf8, 0x27, 0x7a, + 0x0d, 0x20, 0xf3, 0x30, 0x7f, 0xff, 0x89, 0x11, + 0xf4, 0x95, 0x77, 0x10, 0x40, 0x00, 0xf6, 0xa9, + 0xf8, 0x20, 0x09, 0x64, 0xf2, 0x73, 0x09, 0x67, + 0xf4, 0x95, 0xe8, 0x01, 0x80, 0xf8, 0x27, 0x7b, + 0xe8, 0x00, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, + 0x11, 0xf8, 0x29, 0x86, 0xf5, 0x20, 0xf3, 0x30, + 0x7f, 0xff, 0x89, 0x11, 0xf4, 0x95, 0x77, 0x10, + 0x40, 0x00, 0xf6, 0xa9, 0xf8, 0x20, 0x09, 0x7a, + 0xf2, 0x73, 0x09, 0x8d, 0xf4, 0x95, 0xe8, 0x02, + 0x6f, 0xf8, 0x27, 0x7a, 0x0d, 0x20, 0xf3, 0x30, + 0x7f, 0xff, 0x89, 0x11, 0xf4, 0x95, 0x77, 0x10, + 0x40, 0x00, 0xf6, 0xa9, 0xf8, 0x20, 0x09, 0x8a, + 0xf2, 0x73, 0x09, 0x8d, 0xf4, 0x95, 0xe8, 0x01, + 0x80, 0xf8, 0x27, 0x79, 0xe8, 0x00, 0x8a, 0x11, + 0xfc, 0x00, 0x4a, 0x11, 0xf4, 0x95, 0x71, 0x02, + 0x00, 0x12, 0x88, 0x11, 0xf6, 0xb8, 0x57, 0xf8, + 0x27, 0x72, 0xf0, 0x20, 0x7f, 0xff, 0xf2, 0x80, + 0xf0, 0x00, 0x80, 0x00, 0x80, 0x81, 0x57, 0xf8, + 0x27, 0x72, 0xe8, 0x01, 0xf3, 0xf1, 0xf2, 0x80, + 0x80, 0xf8, 0x27, 0x78, 0x77, 0x11, 0x80, 0x00, + 0x48, 0x11, 0x57, 0xf8, 0x27, 0x72, 0xf2, 0x80, + 0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x81, + 0x09, 0xb5, 0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08, + 0x00, 0x01, 0xf0, 0x73, 0x09, 0xba, 0xf0, 0x20, + 0x80, 0x01, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01, + 0x45, 0xf8, 0x27, 0x71, 0x43, 0xf8, 0x27, 0x73, + 0x83, 0xf8, 0x00, 0x11, 0xf4, 0x95, 0xe7, 0x20, + 0xf6, 0xa9, 0xf8, 0x30, 0x09, 0xc9, 0xf2, 0x73, + 0x09, 0xe4, 0x77, 0x12, 0x00, 0x00, 0x57, 0xf8, + 0x27, 0x72, 0xf0, 0x20, 0x7f, 0xff, 0xf2, 0x80, + 0x49, 0x12, 0xf5, 0x00, 0xf3, 0x00, 0x80, 0x00, + 0x61, 0xf8, 0x00, 0x0b, 0x80, 0x00, 0xf8, 0x30, + 0x09, 0xdc, 0xf1, 0x20, 0x80, 0x00, 0xf5, 0x20, + 0x89, 0x12, 0xf4, 0x95, 0x48, 0x12, 0x6f, 0xf8, + 0x27, 0x73, 0x0d, 0x00, 0xf4, 0x95, 0x49, 0x0b, + 0x4f, 0xf8, 0x27, 0x72, 0x8a, 0x11, 0xfe, 0x00, + 0x48, 0x12, 0xf4, 0x95, 0x4a, 0x11, 0x4a, 0x16, + 0x4a, 0x17, 0xee, 0xfc, 0xf4, 0x95, 0x71, 0x08, + 0x00, 0x16, 0x88, 0x17, 0xf0, 0x74, 0x08, 0x30, + 0x48, 0x18, 0x70, 0x00, 0x00, 0x16, 0xf2, 0x74, + 0x09, 0x8f, 0xf0, 0x00, 0x00, 0x02, 0x88, 0x11, + 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x81, 0x0a, 0x0a, + 0xf2, 0x74, 0x08, 0xdb, 0xf4, 0x95, 0x48, 0x16, + 0x48, 0x18, 0x70, 0x00, 0x00, 0x16, 0xf2, 0x74, + 0x09, 0x8f, 0xf0, 0x00, 0x00, 0x02, 0x88, 0x11, + 0x10, 0x02, 0x70, 0x01, 0x00, 0x11, 0x80, 0x00, + 0xf2, 0x74, 0x06, 0xce, 0xf4, 0x95, 0x48, 0x17, + 0x49, 0x11, 0x48, 0x17, 0xf6, 0x00, 0x88, 0x17, + 0xe7, 0x60, 0xf5, 0xa9, 0xf8, 0x20, 0x0a, 0x2d, + 0x48, 0x16, 0xf6, 0x20, 0x88, 0x11, 0x48, 0x18, + 0x70, 0x00, 0x00, 0x11, 0xf2, 0x74, 0x09, 0x8f, + 0xf0, 0x00, 0x00, 0x02, 0x88, 0x11, 0x70, 0x01, + 0x00, 0x11, 0x10, 0x02, 0x80, 0x00, 0xf2, 0x74, + 0x06, 0xce, 0xf4, 0x95, 0x48, 0x17, 0xee, 0x04, + 0x48, 0x16, 0x8a, 0x17, 0x8a, 0x16, 0x8a, 0x11, + 0xfc, 0x00, 0xee, 0xfd, 0xe8, 0x00, 0x4e, 0xf8, + 0x27, 0x70, 0xe8, 0x00, 0x4e, 0xf8, 0x27, 0x72, + 0xe8, 0x00, 0x4e, 0xf8, 0x27, 0x74, 0xe8, 0x00, + 0x4e, 0xf8, 0x27, 0x76, 0x76, 0xf8, 0x27, 0x79, + 0xff, 0xff, 0x76, 0xf8, 0x27, 0x7a, 0x00, 0x00, + 0x76, 0xf8, 0x27, 0x7b, 0xff, 0xff, 0x76, 0xf8, + 0x27, 0x78, 0x00, 0x00, 0xe8, 0x00, 0x75, 0xf8, + 0x00, 0x08, 0x00, 0x01, 0x76, 0x00, 0x00, 0x00, + 0x76, 0x01, 0x02, 0x00, 0xf2, 0x74, 0x12, 0xdc, + 0xf0, 0x20, 0x27, 0x7c, 0xee, 0x03, 0xfc, 0x00, + 0x4a, 0x11, 0xee, 0xfc, 0xf4, 0x95, 0x4e, 0x00, + 0x77, 0x12, 0x7f, 0xff, 0xf6, 0xb8, 0x49, 0x12, + 0xf1, 0x80, 0xf3, 0x00, 0x80, 0x00, 0x89, 0x12, + 0xf0, 0xe0, 0xf1, 0xf1, 0x4f, 0x02, 0xe9, 0x01, + 0xf4, 0x95, 0x48, 0x0b, 0xf5, 0x40, 0x56, 0x02, + 0xf1, 0x80, 0x81, 0xf8, 0x27, 0x78, 0x77, 0x11, + 0x80, 0x00, 0x56, 0x00, 0x49, 0x11, 0xf1, 0x80, + 0x89, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x81, + 0x0a, 0x81, 0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08, + 0x00, 0x01, 0xf0, 0x73, 0x0a, 0x86, 0xf0, 0x20, + 0x80, 0x01, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01, + 0x10, 0x82, 0xee, 0x04, 0x8a, 0x11, 0xfc, 0x00, + 0x4a, 0x11, 0xee, 0xfe, 0xf4, 0x95, 0x4e, 0x00, + 0x77, 0x11, 0x7f, 0xff, 0xf6, 0xb8, 0x49, 0x11, + 0xf1, 0x80, 0xf3, 0x00, 0x80, 0x00, 0x89, 0x11, + 0xf0, 0xe0, 0xf1, 0xf1, 0xe8, 0x01, 0xf2, 0x80, + 0x80, 0xf8, 0x27, 0x78, 0x56, 0x00, 0xf1, 0x20, + 0x80, 0x00, 0xf1, 0x80, 0xf4, 0x95, 0x49, 0x0b, + 0xf8, 0x4d, 0x0a, 0xab, 0xf0, 0x20, 0x80, 0x01, + 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01, 0xf0, 0x73, + 0x0a, 0xaf, 0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08, + 0x00, 0x01, 0xee, 0x02, 0x48, 0x11, 0x8a, 0x11, + 0xfc, 0x00, 0x4a, 0x11, 0x88, 0x12, 0x13, 0x02, + 0x77, 0x11, 0x00, 0x00, 0xf8, 0x4d, 0x0a, 0xcb, + 0xf3, 0x10, 0x00, 0x01, 0x89, 0x1a, 0xf4, 0x95, + 0xf0, 0x72, 0x0a, 0xca, 0x48, 0x11, 0x1c, 0xf8, + 0x29, 0x7e, 0x88, 0x11, 0x11, 0xf8, 0x29, 0x7e, + 0xf2, 0x00, 0x00, 0x01, 0x80, 0xf8, 0x29, 0x7e, + 0x81, 0x92, 0x48, 0x11, 0x8a, 0x11, 0xfc, 0x00, + 0x4a, 0x11, 0xf4, 0x95, 0x71, 0x02, 0x00, 0x11, + 0x88, 0x12, 0xf6, 0xb8, 0xf0, 0x20, 0x7f, 0xff, + 0x57, 0xf8, 0x27, 0x70, 0xf2, 0x80, 0xf0, 0x00, + 0x80, 0x00, 0x80, 0x82, 0x57, 0xf8, 0x27, 0x70, + 0xe8, 0x01, 0xf3, 0xf1, 0xf2, 0x80, 0x80, 0xf8, + 0x27, 0x78, 0x77, 0x12, 0x80, 0x00, 0x48, 0x12, + 0x57, 0xf8, 0x27, 0x70, 0xf2, 0x80, 0x88, 0x12, + 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x82, 0x0a, 0xf4, + 0xe8, 0x00, 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01, + 0xf0, 0x73, 0x0a, 0xf9, 0xf0, 0x20, 0x80, 0x01, + 0x75, 0xf8, 0x00, 0x08, 0x00, 0x01, 0x45, 0xf8, + 0x27, 0x75, 0xe7, 0x10, 0x43, 0xf8, 0x27, 0x71, + 0x83, 0xf8, 0x00, 0x12, 0x6d, 0xe8, 0x00, 0x04, + 0x6d, 0x8a, 0xf6, 0xaa, 0xf8, 0x30, 0x0b, 0x0a, + 0xf2, 0x73, 0x0b, 0x25, 0x77, 0x11, 0x00, 0x00, + 0x57, 0xf8, 0x27, 0x70, 0xf0, 0x20, 0x7f, 0xff, + 0xf2, 0x80, 0x49, 0x11, 0xf5, 0x00, 0xf3, 0x00, + 0x80, 0x00, 0x61, 0xf8, 0x00, 0x0b, 0x80, 0x00, + 0xf8, 0x30, 0x0b, 0x1d, 0xf1, 0x20, 0x80, 0x00, + 0xf5, 0x20, 0x89, 0x11, 0xf4, 0x95, 0x48, 0x11, + 0x6f, 0xf8, 0x27, 0x71, 0x0d, 0x00, 0xf4, 0x95, + 0x49, 0x0b, 0x4f, 0xf8, 0x27, 0x70, 0x48, 0x11, + 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x4a, 0x16, + 0x4a, 0x17, 0xee, 0xf0, 0x88, 0x17, 0x10, 0x17, + 0x80, 0x05, 0x10, 0x16, 0x80, 0x06, 0x10, 0x15, + 0x80, 0x07, 0x71, 0x14, 0x00, 0x11, 0x10, 0x05, + 0xf0, 0x30, 0x00, 0x01, 0x88, 0x10, 0x10, 0x06, + 0xf0, 0x30, 0x00, 0x01, 0x80, 0x08, 0x49, 0x11, + 0x10, 0x05, 0xf6, 0x01, 0x80, 0x09, 0x10, 0x06, + 0x61, 0xf8, 0x00, 0x08, 0x00, 0x01, 0xf8, 0x20, + 0x0b, 0x4b, 0x10, 0x09, 0xf0, 0x00, 0x00, 0x01, + 0x80, 0x09, 0x71, 0x08, 0x00, 0x12, 0xf4, 0xaa, + 0xf8, 0x30, 0x0b, 0x54, 0x10, 0x09, 0xf0, 0x00, + 0x00, 0x01, 0x80, 0x09, 0x12, 0x09, 0x49, 0x11, + 0xf4, 0x7f, 0x80, 0x09, 0xf6, 0x20, 0x80, 0x0a, + 0x56, 0xf8, 0x27, 0x70, 0x4e, 0x0c, 0x10, 0x09, + 0x80, 0x00, 0x48, 0x18, 0xf2, 0x74, 0x0a, 0xce, + 0xf0, 0x00, 0x00, 0x04, 0x88, 0x16, 0xf4, 0x95, + 0xf4, 0x95, 0x6c, 0x86, 0x0b, 0x6d, 0xf2, 0x73, + 0x0c, 0x59, 0xf4, 0x95, 0xe8, 0x00, 0xf6, 0xb8, + 0xf4, 0x95, 0x56, 0x0c, 0xf0, 0xf9, 0x88, 0x12, + 0xf4, 0x95, 0xf4, 0x95, 0x70, 0xe2, 0x27, 0x7c, + 0x29, 0x86, 0xe8, 0x00, 0x80, 0x0e, 0x48, 0x11, + 0xf8, 0x45, 0x0b, 0xcc, 0x77, 0x10, 0x00, 0x01, + 0xf4, 0xa9, 0xf8, 0x30, 0x0b, 0x89, 0x6c, 0xe1, + 0xff, 0xfd, 0x0b, 0x8b, 0x10, 0xe7, 0x00, 0x02, + 0x80, 0x0e, 0xf0, 0x73, 0x0b, 0x8b, 0x10, 0x87, + 0x80, 0x0e, 0xe7, 0x10, 0xf5, 0xae, 0xf8, 0x20, + 0x0b, 0xb2, 0x70, 0x00, 0x00, 0x17, 0x70, 0x01, + 0x00, 0x16, 0x10, 0x04, 0xf0, 0x74, 0x06, 0xce, + 0x48, 0x17, 0x49, 0x16, 0xf6, 0x00, 0x88, 0x17, + 0x48, 0x11, 0xf6, 0x20, 0x88, 0x11, 0x10, 0x09, + 0xf6, 0x20, 0x80, 0x00, 0x48, 0x18, 0xf2, 0x74, + 0x0a, 0xce, 0xf0, 0x00, 0x00, 0x04, 0x88, 0x16, + 0x10, 0x04, 0x70, 0x00, 0x00, 0x17, 0x70, 0x01, + 0x00, 0x11, 0xf0, 0x74, 0x06, 0xce, 0x48, 0x11, + 0x00, 0x04, 0x80, 0x04, 0xf0, 0x73, 0x0b, 0xbc, + 0x70, 0x00, 0x00, 0x17, 0x70, 0x01, 0x00, 0x11, + 0x10, 0x04, 0xf0, 0x74, 0x06, 0xce, 0x48, 0x11, + 0x00, 0x04, 0x80, 0x04, 0x49, 0x11, 0x48, 0x16, + 0xf6, 0x20, 0x88, 0x16, 0xf4, 0x95, 0xf4, 0x95, + 0x6c, 0x86, 0x0b, 0xcc, 0x10, 0x0a, 0x80, 0x00, + 0x48, 0x18, 0xf2, 0x74, 0x0a, 0xce, 0xf0, 0x00, + 0x00, 0x04, 0x88, 0x16, 0x12, 0x0a, 0xf8, 0x45, + 0x0c, 0x33, 0x71, 0x0a, 0x00, 0x10, 0xf4, 0xae, + 0xf8, 0x30, 0x0c, 0x1c, 0x48, 0x16, 0xf0, 0xe1, + 0x88, 0x11, 0x12, 0x08, 0xf8, 0x45, 0x0b, 0xdb, + 0x6d, 0x89, 0x12, 0x07, 0xf8, 0x45, 0x0b, 0xe9, + 0x10, 0x07, 0x80, 0x00, 0x70, 0x02, 0x00, 0x11, + 0x10, 0x06, 0x80, 0x01, 0x10, 0x04, 0xf0, 0x74, + 0x06, 0xdc, 0xf0, 0x73, 0x0b, 0xef, 0x48, 0x11, + 0x6f, 0x00, 0x0c, 0x9f, 0x10, 0x04, 0xf0, 0x74, + 0x0a, 0xb3, 0x11, 0x0e, 0xf1, 0xc0, 0x81, 0x0e, + 0x10, 0x06, 0x49, 0x11, 0xf6, 0x00, 0x80, 0x06, + 0x10, 0x05, 0xf6, 0x20, 0x88, 0x11, 0xf0, 0x00, + 0x00, 0x01, 0x48, 0x08, 0x6f, 0x00, 0x0c, 0x9f, + 0x48, 0x18, 0xf2, 0x74, 0x0a, 0xce, 0xf0, 0x00, + 0x00, 0x04, 0x12, 0x07, 0xf8, 0x45, 0x0c, 0x11, + 0x10, 0x07, 0x80, 0x00, 0x70, 0x02, 0x00, 0x11, + 0x10, 0x06, 0x80, 0x01, 0x10, 0x04, 0xf0, 0x74, + 0x06, 0xdc, 0xf0, 0x73, 0x0c, 0x17, 0x48, 0x11, + 0x6f, 0x00, 0x0c, 0x9f, 0x10, 0x04, 0xf0, 0x74, + 0x0a, 0xb3, 0x11, 0x0e, 0xf1, 0xc0, 0x81, 0x0e, + 0xf0, 0x73, 0x0c, 0x33, 0x12, 0x07, 0xf8, 0x45, + 0x0c, 0x2a, 0x10, 0x07, 0x80, 0x00, 0x10, 0x06, + 0x80, 0x01, 0x10, 0x05, 0x80, 0x02, 0x10, 0x04, + 0xf0, 0x74, 0x06, 0xdc, 0xf0, 0x73, 0x0c, 0x30, + 0x12, 0x05, 0x6f, 0x00, 0x0c, 0x9f, 0x10, 0x04, + 0xf0, 0x74, 0x0a, 0xb3, 0x11, 0x0e, 0xf1, 0xc0, + 0x81, 0x0e, 0x76, 0x00, 0x00, 0x01, 0x48, 0x18, + 0xf2, 0x74, 0x0a, 0xce, 0xf0, 0x00, 0x00, 0x04, + 0x71, 0x04, 0x00, 0x11, 0x70, 0x81, 0x29, 0x86, + 0x10, 0x0e, 0x1c, 0xf8, 0x29, 0x86, 0x80, 0x0e, + 0x76, 0x00, 0x00, 0x01, 0x48, 0x18, 0xf2, 0x74, + 0x0a, 0xce, 0xf0, 0x00, 0x00, 0x04, 0x10, 0x0e, + 0x71, 0x04, 0x00, 0x11, 0x80, 0x81, 0x10, 0xf8, + 0x29, 0x86, 0xf0, 0x00, 0x00, 0x01, 0xf0, 0x30, + 0x7f, 0xff, 0x80, 0xf8, 0x29, 0x86, 0x10, 0x09, + 0xf0, 0x00, 0x00, 0x02, 0x80, 0x09, 0xee, 0x10, + 0x8a, 0x17, 0x8a, 0x16, 0x8a, 0x11, 0xfc, 0x00, + 0x10, 0xf8, 0x27, 0x75, 0x08, 0xf8, 0x27, 0x71, + 0xf0, 0x10, 0x00, 0x01, 0x48, 0x08, 0xfc, 0x00, + 0x4a, 0x11, 0x4a, 0x16, 0xee, 0xff, 0xf4, 0x95, + 0x71, 0x04, 0x00, 0x16, 0xf0, 0x00, 0x00, 0x01, + 0x48, 0x08, 0x4e, 0xf8, 0x29, 0x7c, 0x6d, 0xee, + 0xff, 0xfd, 0x48, 0x16, 0xf8, 0x45, 0x0c, 0x99, + 0x56, 0xf8, 0x29, 0x7c, 0xf0, 0x74, 0x0a, 0x5a, + 0x88, 0x11, 0x10, 0xf8, 0x29, 0x7d, 0xf0, 0x00, + 0x00, 0x01, 0x48, 0x08, 0x4e, 0xf8, 0x29, 0x7c, + 0x10, 0xf8, 0x29, 0x82, 0xf0, 0x00, 0x00, 0x01, + 0x88, 0x10, 0xf4, 0x95, 0xf4, 0x95, 0xf4, 0xa9, + 0xfa, 0x30, 0x0c, 0x96, 0x80, 0xf8, 0x29, 0x82, + 0x56, 0xf8, 0x29, 0x80, 0xf0, 0x00, 0x00, 0x01, + 0x4e, 0xf8, 0x29, 0x80, 0x73, 0x11, 0x29, 0x82, + 0x6c, 0xee, 0xff, 0xff, 0x0c, 0x76, 0xee, 0x01, + 0x8a, 0x16, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, + 0x76, 0xf8, 0x29, 0x84, 0x00, 0x00, 0x76, 0xf8, + 0x29, 0x85, 0x00, 0x01, 0xe8, 0x00, 0x4e, 0xf8, + 0x2a, 0x0c, 0x76, 0xf8, 0x29, 0x86, 0x00, 0x00, + 0x76, 0xf8, 0x29, 0x87, 0x00, 0x00, 0x77, 0x11, + 0x29, 0x88, 0x76, 0x81, 0xaa, 0xaa, 0x76, 0xe1, + 0x00, 0x01, 0xaa, 0xaa, 0x76, 0xe1, 0x00, 0x02, + 0x00, 0x00, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, + 0xee, 0xfc, 0xf4, 0x95, 0x71, 0x06, 0x00, 0x14, + 0x71, 0x07, 0x00, 0x13, 0x71, 0x08, 0x00, 0x12, + 0x71, 0x09, 0x00, 0x15, 0x77, 0x10, 0x00, 0xff, + 0xf4, 0xaa, 0xf8, 0x30, 0x0d, 0x44, 0x49, 0x13, + 0x53, 0xf8, 0x2a, 0x0c, 0x4f, 0xf8, 0x2a, 0x0c, + 0x73, 0x12, 0x00, 0x0e, 0xf1, 0x66, 0x00, 0x0d, + 0x89, 0x11, 0xf4, 0x95, 0x77, 0x10, 0x00, 0x01, + 0x71, 0xe1, 0x24, 0x00, 0x00, 0x11, 0xf4, 0xa9, + 0xf8, 0x30, 0x0d, 0x17, 0x77, 0x10, 0x00, 0x02, + 0xf4, 0xa9, 0xf8, 0x30, 0x0c, 0xec, 0x77, 0x11, + 0x29, 0x8a, 0x76, 0x81, 0x00, 0x00, 0xe8, 0x00, + 0x77, 0x14, 0x00, 0x00, 0x77, 0x13, 0x00, 0x00, + 0xf0, 0x73, 0x0d, 0x48, 0x6c, 0x83, 0x0c, 0xfa, + 0x77, 0x11, 0x29, 0x8a, 0x48, 0x12, 0xf0, 0xe8, + 0xf0, 0x40, 0x80, 0x00, 0x80, 0x81, 0xe8, 0x00, + 0x77, 0x14, 0x00, 0x00, 0xf0, 0x73, 0x0d, 0x48, + 0x49, 0x13, 0xf3, 0x40, 0x80, 0x00, 0x81, 0xf8, + 0x29, 0x8a, 0x61, 0xf8, 0x00, 0x15, 0x00, 0x01, + 0xf8, 0x20, 0x0d, 0x07, 0x69, 0xf8, 0x29, 0x8a, + 0x40, 0x00, 0x61, 0xf8, 0x00, 0x14, 0x00, 0x01, + 0xf8, 0x20, 0x0d, 0x0f, 0x69, 0xf8, 0x29, 0x8a, + 0x20, 0x00, 0x77, 0x11, 0x29, 0x8a, 0x49, 0x12, + 0xf3, 0xe8, 0x1b, 0x81, 0x81, 0x81, 0xf0, 0x73, + 0x0d, 0x48, 0x11, 0xf8, 0x29, 0x84, 0xf8, 0x4c, + 0x0d, 0x37, 0x77, 0x11, 0x29, 0x88, 0x76, 0x81, + 0xaa, 0xaa, 0x11, 0xf8, 0x29, 0x85, 0xf3, 0x10, + 0x00, 0x01, 0xf3, 0x40, 0xaa, 0x00, 0x81, 0xe1, + 0x00, 0x01, 0x76, 0x00, 0x00, 0x02, 0x80, 0x01, + 0x70, 0x02, 0x00, 0x14, 0x70, 0x03, 0x00, 0x13, + 0xf2, 0x74, 0x0b, 0x28, 0xf4, 0x95, 0x48, 0x11, + 0x71, 0xf8, 0x29, 0x85, 0x29, 0x84, 0xf0, 0x73, + 0x0d, 0x73, 0x76, 0x00, 0x00, 0x00, 0x80, 0x01, + 0x76, 0x02, 0x00, 0x00, 0x70, 0x03, 0x00, 0x13, + 0xf2, 0x74, 0x0b, 0x28, 0xf4, 0x95, 0xe8, 0x00, + 0xf0, 0x73, 0x0d, 0x73, 0x77, 0x11, 0x29, 0x8a, + 0x70, 0x81, 0x00, 0x13, 0x11, 0xf8, 0x29, 0x84, + 0xf8, 0x4c, 0x0d, 0x68, 0x77, 0x11, 0x29, 0x88, + 0x76, 0x81, 0xaa, 0xaa, 0x11, 0xf8, 0x29, 0x85, + 0xf3, 0x10, 0x00, 0x01, 0xf3, 0x40, 0xaa, 0x00, + 0x81, 0xe1, 0x00, 0x01, 0x76, 0x00, 0x00, 0x03, + 0x80, 0x01, 0x70, 0x02, 0x00, 0x14, 0x70, 0x03, + 0x00, 0x13, 0xf2, 0x74, 0x0b, 0x28, 0xf4, 0x95, + 0x48, 0x11, 0x71, 0xf8, 0x29, 0x85, 0x29, 0x84, + 0xf0, 0x73, 0x0d, 0x73, 0x76, 0x00, 0x00, 0x01, + 0x80, 0x01, 0x70, 0x02, 0x00, 0x14, 0x70, 0x03, + 0x00, 0x13, 0xf2, 0x74, 0x0b, 0x28, 0xf4, 0x95, + 0x48, 0x11, 0x6b, 0xf8, 0x29, 0x84, 0xff, 0xff, + 0xee, 0x04, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, + 0xf5, 0x40, 0xf4, 0x95, 0x48, 0x0b, 0xf4, 0x78, + 0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0xe1, + 0xff, 0xb9, 0x0d, 0x88, 0xf2, 0x73, 0x0d, 0xa5, + 0xf4, 0x95, 0xe8, 0x60, 0xf2, 0x00, 0x00, 0x06, + 0x61, 0xf8, 0x00, 0x11, 0x00, 0x20, 0xf8, 0x30, + 0x0d, 0x98, 0x61, 0xf8, 0x00, 0x0b, 0x00, 0x01, + 0xf8, 0x20, 0x0d, 0xa3, 0xf2, 0x00, 0x00, 0x07, + 0xf0, 0x73, 0x0d, 0xa3, 0x61, 0xf8, 0x00, 0x0b, + 0x00, 0x01, 0xf8, 0x20, 0x0d, 0xa1, 0xf2, 0x73, + 0x0d, 0xa3, 0xf0, 0x00, 0x00, 0x01, 0xf0, 0x00, + 0x00, 0x02, 0x48, 0x08, 0xf4, 0x7f, 0x8a, 0x11, + 0xfc, 0x00, 0xee, 0xff, 0xf0, 0x74, 0x07, 0xfd, + 0xf0, 0x74, 0x07, 0x44, 0xf0, 0x74, 0x0d, 0xb4, + 0xf0, 0x74, 0x02, 0x05, 0xf0, 0x74, 0x04, 0x60, + 0xf0, 0x73, 0x0d, 0xaa, 0xee, 0xfd, 0x10, 0xf8, + 0x2a, 0xa3, 0xf8, 0x44, 0x0d, 0xcb, 0x10, 0xf8, + 0x2a, 0xa4, 0xf8, 0x45, 0x0d, 0xd7, 0x76, 0x00, + 0x02, 0x00, 0xf2, 0x74, 0x09, 0xe8, 0xf0, 0x20, + 0x22, 0x00, 0x76, 0xf8, 0x2a, 0xa4, 0x00, 0x00, + 0x76, 0xf8, 0x2a, 0xa7, 0x00, 0x00, 0xf0, 0x73, + 0x0d, 0xd7, 0x76, 0x00, 0x02, 0x00, 0xf2, 0x74, + 0x09, 0xe8, 0xf0, 0x20, 0x20, 0x00, 0x76, 0xf8, + 0x2a, 0xa3, 0x00, 0x00, 0x76, 0xf8, 0x2a, 0xa7, + 0x00, 0x01, 0xf0, 0x74, 0x0c, 0x5e, 0xf0, 0xe0, + 0xf0, 0x10, 0x3a, 0x98, 0xf8, 0x47, 0x0d, 0xe1, + 0x76, 0xf8, 0x27, 0x6e, 0x00, 0x00, 0xee, 0x03, + 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe, 0x77, 0x11, + 0x20, 0x00, 0x76, 0x00, 0xaa, 0xaa, 0x76, 0x01, + 0x02, 0x00, 0xf2, 0x74, 0x06, 0x6c, 0xf4, 0x95, + 0x48, 0x11, 0x76, 0x00, 0x55, 0x55, 0x76, 0x01, + 0x02, 0x00, 0x48, 0x11, 0xf2, 0x74, 0x06, 0x6c, + 0xf0, 0x00, 0x02, 0x00, 0x76, 0xf8, 0x2a, 0xa3, + 0x00, 0x00, 0x76, 0xf8, 0x2a, 0xa4, 0x00, 0x00, + 0xe8, 0x00, 0x4e, 0x00, 0xfb, 0x80, 0x15, 0x3e, + 0xf4, 0x95, 0xe8, 0x04, 0x80, 0xf8, 0x2a, 0xa5, + 0x76, 0x00, 0x2a, 0xa8, 0xf9, 0x80, 0x14, 0x87, + 0x76, 0x00, 0x2a, 0xad, 0xfb, 0x80, 0x13, 0x62, + 0xf4, 0x95, 0xe8, 0x02, 0x10, 0xf8, 0x2a, 0xa5, + 0xf9, 0x80, 0x14, 0x63, 0xfb, 0x80, 0x16, 0x66, + 0xf4, 0x95, 0xe8, 0x1c, 0xfb, 0x80, 0x16, 0x87, + 0xf4, 0x95, 0xe8, 0x1c, 0xe8, 0x01, 0x4e, 0x00, + 0xfb, 0x80, 0x17, 0xd6, 0xf4, 0x95, 0xe8, 0x00, + 0x80, 0xf8, 0x2a, 0xa6, 0x76, 0x00, 0x2a, 0xb7, + 0xf9, 0x80, 0x16, 0xaa, 0x10, 0xf8, 0x2a, 0xa6, + 0xf9, 0x80, 0x17, 0x5c, 0x10, 0xf8, 0x2a, 0xa6, + 0xf9, 0x80, 0x17, 0x6f, 0xee, 0x02, 0x8a, 0x11, + 0xfc, 0x00, 0xf4, 0x95, 0x4a, 0x08, 0x4a, 0x09, + 0x4a, 0x0a, 0x4a, 0x07, 0x4a, 0x1d, 0x68, 0xf8, + 0x00, 0x07, 0x7d, 0x3f, 0x69, 0xf8, 0x00, 0x07, + 0x40, 0x00, 0x68, 0xf8, 0x00, 0x1d, 0xff, 0xfc, + 0x10, 0xf8, 0x2a, 0xa7, 0xf8, 0x44, 0x0e, 0x4b, + 0x76, 0xf8, 0x2a, 0xa3, 0x00, 0x01, 0xf0, 0x73, + 0x0e, 0x4e, 0x76, 0xf8, 0x2a, 0xa4, 0x00, 0x01, + 0x8a, 0x1d, 0x8a, 0x07, 0x8a, 0x0a, 0x8a, 0x09, + 0x8a, 0x08, 0xf4, 0xeb, 0x4a, 0x11, 0x4a, 0x16, + 0x4a, 0x17, 0xee, 0xfe, 0x88, 0x0e, 0x71, 0x08, + 0x00, 0x16, 0x71, 0x06, 0x00, 0x17, 0x11, 0x07, + 0xf0, 0x66, 0x00, 0x0d, 0xf0, 0x00, 0x25, 0xa0, + 0x88, 0x11, 0x76, 0x01, 0x00, 0x06, 0x81, 0x00, + 0xf2, 0x74, 0x06, 0xce, 0xf0, 0x00, 0x00, 0x01, + 0x76, 0x01, 0x00, 0x06, 0x70, 0x00, 0x00, 0x16, + 0x48, 0x11, 0xf2, 0x74, 0x06, 0xce, 0xf0, 0x00, + 0x00, 0x07, 0x70, 0x81, 0x00, 0x17, 0xee, 0x02, + 0x8a, 0x17, 0x8a, 0x16, 0x8a, 0x11, 0xfc, 0x00, + 0x4a, 0x11, 0x88, 0x0e, 0x71, 0x02, 0x00, 0x12, + 0x11, 0x03, 0xf0, 0x66, 0x00, 0x0d, 0xf0, 0x00, + 0x24, 0x00, 0x88, 0x11, 0xf4, 0x95, 0x70, 0x81, + 0x00, 0x12, 0x6e, 0xe2, 0xff, 0xfe, 0x0e, 0x8d, + 0xf4, 0x95, 0xe8, 0x00, 0xe8, 0x01, 0x80, 0xe1, + 0x00, 0x02, 0x76, 0xe1, 0x00, 0x03, 0x00, 0xff, + 0x76, 0xe1, 0x00, 0x04, 0x00, 0x00, 0x76, 0xe1, + 0x00, 0x0b, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x0c, + 0x00, 0x00, 0x81, 0xe1, 0x00, 0x01, 0x8a, 0x11, + 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfc, 0x88, 0x0e, + 0xf4, 0x95, 0xf1, 0x66, 0x00, 0x0d, 0xf3, 0x00, + 0x24, 0x00, 0x89, 0x11, 0xf4, 0x95, 0xf4, 0x95, + 0x76, 0xe1, 0x00, 0x0c, 0x00, 0x00, 0x76, 0xe1, + 0x00, 0x0b, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x02, + 0x00, 0x01, 0x76, 0x00, 0x00, 0x00, 0x76, 0x01, + 0x00, 0x00, 0x80, 0x02, 0x76, 0x03, 0x00, 0x00, + 0xf2, 0x74, 0x0c, 0xb9, 0xf4, 0x95, 0xe8, 0x00, + 0xee, 0x04, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, + 0x88, 0x19, 0xf4, 0x95, 0x73, 0x19, 0x00, 0x0e, + 0xf1, 0x66, 0x00, 0x0d, 0xf2, 0x00, 0x24, 0x00, + 0x77, 0x15, 0x25, 0xa0, 0x77, 0x14, 0x00, 0x00, + 0x77, 0x1a, 0x00, 0x1f, 0xf0, 0x72, 0x0f, 0x14, + 0xf6, 0xb8, 0x49, 0x19, 0x09, 0x85, 0xf8, 0x4c, + 0x0f, 0x13, 0xf1, 0x00, 0x00, 0x05, 0x89, 0x11, + 0x49, 0x15, 0xf3, 0x00, 0x00, 0x01, 0x89, 0x13, + 0x49, 0x15, 0xf3, 0x00, 0x00, 0x07, 0x89, 0x12, + 0x11, 0x93, 0x1d, 0x91, 0x19, 0x92, 0x89, 0x10, + 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x80, 0x0f, 0x13, + 0x11, 0x93, 0x1d, 0x91, 0x19, 0x92, 0x89, 0x10, + 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x80, 0x0f, 0x13, + 0x11, 0x93, 0x1d, 0x91, 0x19, 0x92, 0x89, 0x10, + 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x80, 0x0f, 0x13, + 0x11, 0x93, 0x1d, 0x91, 0x19, 0x92, 0x89, 0x10, + 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x80, 0x0f, 0x13, + 0x11, 0x93, 0x1d, 0x91, 0x19, 0x92, 0x89, 0x10, + 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x80, 0x0f, 0x13, + 0x11, 0x93, 0x1d, 0x91, 0x19, 0x92, 0x89, 0x11, + 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0x81, 0x0f, 0x13, + 0x6d, 0x94, 0x6d, 0xed, 0x00, 0x0d, 0x48, 0x14, + 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x4a, 0x16, + 0x4a, 0x17, 0xee, 0xf8, 0x88, 0x17, 0x10, 0x0d, + 0x80, 0x04, 0x10, 0x0c, 0x80, 0x05, 0x71, 0x0e, + 0x00, 0x16, 0x73, 0x17, 0x00, 0x0e, 0xf0, 0x66, + 0x00, 0x0d, 0xf0, 0x00, 0x24, 0x00, 0x88, 0x11, + 0x10, 0xf8, 0x27, 0x63, 0xf8, 0x45, 0x0f, 0x32, + 0xf2, 0x74, 0x0e, 0x9f, 0xf4, 0x95, 0x48, 0x17, + 0x10, 0xf8, 0x27, 0x60, 0xf8, 0x44, 0x0f, 0x3d, + 0x60, 0xe1, 0x00, 0x02, 0x00, 0x01, 0xf8, 0x20, + 0x0f, 0x6d, 0xf0, 0x73, 0x11, 0x33, 0x10, 0x04, + 0x80, 0x00, 0x10, 0x05, 0xf0, 0x74, 0x06, 0x9f, + 0x11, 0x04, 0xf3, 0x00, 0x00, 0x01, 0x81, 0x04, + 0x6d, 0x8e, 0x77, 0x10, 0x00, 0x01, 0x71, 0xe1, + 0x00, 0x02, 0x00, 0x12, 0xf4, 0xaa, 0xf8, 0x30, + 0x0f, 0x62, 0x77, 0x10, 0x00, 0x02, 0xf4, 0xaa, + 0xf8, 0x30, 0x0f, 0x6d, 0x45, 0xe1, 0x00, 0x0b, + 0x88, 0x10, 0x43, 0xe1, 0x00, 0x0c, 0x83, 0xf8, + 0x00, 0x12, 0xf4, 0x95, 0xf4, 0x95, 0xf4, 0xaa, + 0xf8, 0x30, 0x0f, 0x6d, 0xf0, 0x73, 0x0f, 0x96, + 0xf5, 0x00, 0x81, 0x04, 0x49, 0x16, 0xf5, 0x20, + 0x89, 0x16, 0x76, 0xe1, 0x00, 0x0c, 0x00, 0x00, + 0x76, 0xe1, 0x00, 0x04, 0x00, 0x00, 0x48, 0x16, + 0xf8, 0x45, 0x11, 0x33, 0xf7, 0xb8, 0x71, 0xe1, + 0x00, 0x02, 0x00, 0x12, 0x10, 0xf8, 0x00, 0x12, + 0xf0, 0x10, 0x00, 0x03, 0xf8, 0x46, 0x0f, 0x8c, + 0x10, 0xf8, 0x00, 0x12, 0xf0, 0x10, 0x00, 0x03, + 0xf8, 0x45, 0x10, 0x16, 0x77, 0x10, 0x00, 0x01, + 0xf4, 0xaa, 0xf8, 0x30, 0x0f, 0x9c, 0x77, 0x10, + 0x00, 0x02, 0xf4, 0xaa, 0xf8, 0x30, 0x0f, 0xa8, + 0xf0, 0x73, 0x0f, 0x96, 0x77, 0x10, 0x00, 0x04, + 0xf4, 0xaa, 0xf8, 0x30, 0x10, 0xb7, 0x77, 0x10, + 0x00, 0x05, 0xf4, 0xaa, 0xf8, 0x30, 0x10, 0xbc, + 0xf2, 0x74, 0x0e, 0x9f, 0xf4, 0x95, 0x48, 0x17, + 0xf0, 0x73, 0x11, 0x31, 0x76, 0xe1, 0x00, 0x0c, + 0x00, 0x00, 0x76, 0xe1, 0x00, 0x0b, 0x00, 0x00, + 0x76, 0xe1, 0x00, 0x04, 0x00, 0x00, 0x76, 0xe1, + 0x00, 0x02, 0x00, 0x02, 0x11, 0xe1, 0x00, 0x0c, + 0xe8, 0x03, 0xf6, 0x20, 0x89, 0x12, 0xf4, 0x95, + 0x77, 0x10, 0x00, 0x03, 0xf5, 0xaa, 0xf8, 0x30, + 0x0f, 0xb6, 0x6b, 0xf8, 0x27, 0x6f, 0x00, 0x01, + 0x88, 0x10, 0xf4, 0x95, 0xf4, 0x95, 0xf5, 0xae, + 0xf8, 0x20, 0x0f, 0xbd, 0x48, 0x16, 0x80, 0x06, + 0x88, 0x13, 0xf4, 0x95, 0x77, 0x10, 0x00, 0x03, + 0xf6, 0xab, 0xf8, 0x20, 0x0f, 0xc8, 0x6b, 0xf8, + 0x27, 0x6f, 0x00, 0x01, 0x12, 0x06, 0xf8, 0x45, + 0x10, 0x00, 0x10, 0xe1, 0x00, 0x04, 0x80, 0x00, + 0x10, 0x05, 0x80, 0x01, 0x10, 0x04, 0x80, 0x02, + 0x10, 0x06, 0x80, 0x03, 0x48, 0x11, 0xf2, 0x74, + 0x07, 0x1e, 0xf0, 0x00, 0x00, 0x05, 0x10, 0x06, + 0x00, 0xe1, 0x00, 0x04, 0x80, 0xe1, 0x00, 0x04, + 0x10, 0x06, 0x00, 0xe1, 0x00, 0x0c, 0x80, 0xe1, + 0x00, 0x0c, 0x88, 0x12, 0x11, 0x06, 0x10, 0x04, + 0xf6, 0x00, 0x80, 0x04, 0x48, 0x16, 0xf6, 0x20, + 0x88, 0x16, 0x89, 0x13, 0xf4, 0x95, 0x77, 0x10, + 0x00, 0x03, 0xf6, 0xab, 0xf8, 0x20, 0x0f, 0xf5, + 0x6b, 0xf8, 0x27, 0x6f, 0x00, 0x01, 0x77, 0x10, + 0x00, 0x0c, 0x71, 0xe1, 0x00, 0x04, 0x00, 0x13, + 0xf6, 0xab, 0xf8, 0x20, 0x10, 0x00, 0x6b, 0xf8, + 0x27, 0x6f, 0x00, 0x01, 0x6c, 0xe2, 0xff, 0xfd, + 0x11, 0x31, 0xf6, 0xb8, 0x6f, 0xe1, 0x00, 0x05, + 0x0c, 0x48, 0x6f, 0xe1, 0x00, 0x06, 0x0c, 0x18, + 0xf0, 0x30, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x03, + 0x80, 0xe1, 0x00, 0x0b, 0x76, 0xe1, 0x00, 0x02, + 0x00, 0x03, 0x48, 0x16, 0xf8, 0x45, 0x11, 0x33, + 0x71, 0xe1, 0x00, 0x0c, 0x00, 0x12, 0x10, 0xe1, + 0x00, 0x0b, 0x49, 0x12, 0xf6, 0x20, 0x88, 0x13, + 0xe8, 0x0c, 0xf6, 0x20, 0x88, 0x10, 0xf4, 0x95, + 0xf4, 0x95, 0xf5, 0xab, 0xf8, 0x20, 0x10, 0x27, + 0x48, 0x13, 0x80, 0x06, 0x88, 0x10, 0xf4, 0x95, + 0xf4, 0x95, 0xf5, 0xae, 0xf8, 0x20, 0x10, 0x30, + 0x70, 0x06, 0x00, 0x16, 0x12, 0x06, 0xf8, 0x45, + 0x10, 0x5f, 0x10, 0xe1, 0x00, 0x04, 0x80, 0x00, + 0x10, 0x05, 0x80, 0x01, 0x10, 0x04, 0x80, 0x02, + 0x10, 0x06, 0x80, 0x03, 0x48, 0x11, 0xf2, 0x74, + 0x07, 0x1e, 0xf0, 0x00, 0x00, 0x05, 0x10, 0x06, + 0x00, 0xe1, 0x00, 0x04, 0x80, 0xe1, 0x00, 0x04, + 0x10, 0x06, 0x00, 0xe1, 0x00, 0x0c, 0x80, 0xe1, + 0x00, 0x0c, 0x88, 0x12, 0x11, 0x06, 0x10, 0x04, + 0xf6, 0x00, 0x80, 0x04, 0x48, 0x16, 0xf6, 0x20, + 0x88, 0x16, 0xf4, 0x95, 0x77, 0x10, 0x00, 0x0c, + 0x71, 0xe1, 0x00, 0x04, 0x00, 0x13, 0xf6, 0xab, + 0xf8, 0x20, 0x10, 0x5f, 0x6b, 0xf8, 0x27, 0x6f, + 0x00, 0x01, 0x77, 0x10, 0x00, 0x0c, 0xf6, 0xaa, + 0xf8, 0x20, 0x10, 0x6b, 0xf2, 0x74, 0x0e, 0x9f, + 0xf4, 0x95, 0x48, 0x17, 0x71, 0xe1, 0x00, 0x0c, + 0x00, 0x12, 0x77, 0x10, 0x00, 0x0c, 0xf4, 0xaa, + 0xf8, 0x30, 0x10, 0x7c, 0x77, 0x10, 0x00, 0x0c, + 0x71, 0xe1, 0x00, 0x0b, 0x00, 0x13, 0xf6, 0xab, + 0xf8, 0x30, 0x10, 0xb4, 0xe7, 0x30, 0xf7, 0xaa, + 0xf8, 0x30, 0x10, 0xb4, 0xf2, 0x74, 0x0e, 0xc1, + 0xf4, 0x95, 0x48, 0x17, 0x88, 0x12, 0xf4, 0x95, + 0xf4, 0x95, 0x6c, 0x82, 0x10, 0x8d, 0x76, 0xe1, + 0x00, 0x04, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x02, + 0x00, 0x05, 0xf0, 0x73, 0x10, 0xb4, 0x76, 0xe1, + 0x00, 0x02, 0x00, 0x04, 0x77, 0x10, 0x00, 0x0c, + 0x71, 0xe1, 0x00, 0x0b, 0x00, 0x12, 0xf5, 0xaa, + 0xf8, 0x20, 0x10, 0x9a, 0xf0, 0x73, 0x10, 0x9c, + 0x77, 0x12, 0x00, 0x0c, 0x76, 0x00, 0x00, 0x00, + 0x70, 0x01, 0x00, 0x12, 0x70, 0x02, 0x00, 0x17, + 0x76, 0x03, 0x00, 0x01, 0x48, 0x11, 0xf2, 0x74, + 0x0c, 0xb9, 0xf0, 0x00, 0x00, 0x05, 0x76, 0xe1, + 0x00, 0x04, 0x00, 0x00, 0x77, 0x10, 0x00, 0x0c, + 0x71, 0xe1, 0x00, 0x0b, 0x00, 0x12, 0xf6, 0xaa, + 0xf8, 0x20, 0x11, 0x1c, 0x48, 0x16, 0xf8, 0x45, + 0x11, 0x33, 0x60, 0xe1, 0x00, 0x02, 0x00, 0x05, + 0xf8, 0x20, 0x10, 0xdf, 0x10, 0xe1, 0x00, 0x0b, + 0x08, 0xe1, 0x00, 0x0c, 0x11, 0xe1, 0x00, 0x04, + 0xf8, 0x4d, 0x10, 0xc7, 0x6b, 0xf8, 0x27, 0x6f, + 0x00, 0x01, 0x88, 0x10, 0xf4, 0x95, 0xf4, 0x95, + 0xf5, 0xae, 0xf8, 0x20, 0x10, 0xcf, 0x48, 0x16, + 0xf4, 0x95, 0x48, 0x08, 0xf8, 0x45, 0x11, 0x16, + 0x6f, 0xe1, 0x00, 0x0c, 0x0d, 0x00, 0x81, 0xe1, + 0x00, 0x0c, 0x11, 0x04, 0xf5, 0x00, 0x81, 0x04, + 0x49, 0x16, 0xf5, 0x20, 0x89, 0x16, 0xf0, 0x73, + 0x11, 0x0e, 0x10, 0xe1, 0x00, 0x0b, 0x71, 0xe1, + 0x00, 0x0c, 0x00, 0x12, 0x88, 0x10, 0xf4, 0x95, + 0xf4, 0x95, 0xf6, 0xaa, 0xf8, 0x30, 0x11, 0x16, + 0x49, 0x12, 0xf6, 0x20, 0x88, 0x10, 0xf4, 0x95, + 0xf4, 0x95, 0xf5, 0xae, 0xf8, 0x20, 0x10, 0xf3, + 0x48, 0x16, 0x80, 0x06, 0x48, 0x08, 0xf8, 0x45, + 0x11, 0x16, 0x10, 0x04, 0x70, 0x02, 0x00, 0x17, + 0x80, 0x00, 0x76, 0x03, 0x00, 0x00, 0x10, 0x06, + 0x80, 0x01, 0x10, 0x05, 0xf0, 0x74, 0x0c, 0xb9, + 0x10, 0x06, 0x00, 0xe1, 0x00, 0x0c, 0x80, 0xe1, + 0x00, 0x0c, 0x11, 0x06, 0x10, 0x04, 0xf6, 0x00, + 0x80, 0x04, 0x48, 0x16, 0xf6, 0x20, 0x88, 0x16, + 0x10, 0xe1, 0x00, 0x0c, 0x08, 0xe1, 0x00, 0x0b, + 0xf8, 0x45, 0x11, 0x1c, 0xf0, 0x73, 0x11, 0x31, + 0xf2, 0x74, 0x0e, 0x9f, 0xf4, 0x95, 0x48, 0x17, + 0xf0, 0x73, 0x11, 0x33, 0x76, 0xe1, 0x00, 0x0c, + 0x00, 0x00, 0x76, 0xe1, 0x00, 0x0b, 0x00, 0x00, + 0x76, 0xe1, 0x00, 0x02, 0x00, 0x01, 0x10, 0x04, + 0x80, 0x00, 0x10, 0x05, 0xf0, 0x74, 0x06, 0x9f, + 0x88, 0x12, 0xf4, 0x95, 0x77, 0x10, 0x00, 0xff, + 0xf4, 0xaa, 0xf8, 0x30, 0x11, 0x33, 0x6c, 0x86, + 0x0f, 0x70, 0xee, 0x08, 0x8a, 0x17, 0x8a, 0x16, + 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfc, + 0xf4, 0x95, 0x71, 0x06, 0x00, 0x12, 0x88, 0x11, + 0x73, 0x12, 0x00, 0x0e, 0xf1, 0x66, 0x00, 0x0d, + 0xf3, 0x00, 0x24, 0x00, 0x89, 0x14, 0x13, 0x81, + 0xf7, 0x7a, 0xf3, 0x30, 0x00, 0x01, 0x81, 0xf8, + 0x27, 0x60, 0x13, 0xe1, 0x00, 0x01, 0xf7, 0x7c, + 0xf3, 0x30, 0x00, 0x03, 0x81, 0xf8, 0x27, 0x61, + 0xe9, 0x0f, 0x19, 0xe1, 0x00, 0x01, 0x81, 0xf8, + 0x27, 0x62, 0x71, 0xe4, 0x00, 0x03, 0x00, 0x13, + 0xf6, 0xb8, 0x49, 0x13, 0xf3, 0x00, 0x00, 0x01, + 0xf3, 0x30, 0x00, 0x0f, 0x49, 0x0b, 0x09, 0xf8, + 0x27, 0x62, 0xf8, 0x4d, 0x11, 0x75, 0x77, 0x10, + 0x00, 0xff, 0xf4, 0xab, 0xf8, 0x30, 0x11, 0x75, + 0x57, 0xf8, 0x27, 0x6c, 0xf3, 0x00, 0x00, 0x01, + 0x4f, 0xf8, 0x27, 0x6c, 0x76, 0xf8, 0x27, 0x63, + 0x00, 0x01, 0xf0, 0x73, 0x11, 0x78, 0x76, 0xf8, + 0x27, 0x63, 0x00, 0x00, 0x70, 0xe4, 0x00, 0x03, + 0x27, 0x62, 0x76, 0xf8, 0x27, 0x64, 0x00, 0x00, + 0x11, 0xf8, 0x27, 0x61, 0x61, 0xf8, 0x00, 0x0b, + 0x00, 0x02, 0xf8, 0x20, 0x11, 0x8d, 0xe9, 0x01, + 0x6f, 0xe1, 0x00, 0x02, 0x0f, 0x18, 0x81, 0xf8, + 0x27, 0x64, 0x11, 0xf8, 0x27, 0x61, 0x61, 0xf8, + 0x00, 0x0b, 0x00, 0x01, 0xf8, 0x20, 0x11, 0xa9, + 0x10, 0xf8, 0x27, 0x64, 0xf1, 0x00, 0x00, 0x04, + 0x89, 0x13, 0xe9, 0xb8, 0xf5, 0x20, 0x81, 0xf8, + 0x27, 0x65, 0x60, 0x84, 0x00, 0x02, 0xf8, 0x20, + 0x11, 0xa9, 0x70, 0x00, 0x00, 0x11, 0x70, 0x01, + 0x00, 0x13, 0x70, 0x02, 0x27, 0x65, 0xf2, 0x74, + 0x0f, 0x18, 0xf4, 0x95, 0x48, 0x12, 0xee, 0x04, + 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0x4a, 0x16, + 0x4a, 0x17, 0xee, 0xfc, 0xe8, 0x00, 0x4e, 0xf8, + 0x27, 0x66, 0xe8, 0x00, 0x4e, 0xf8, 0x27, 0x68, + 0xe8, 0x00, 0x4e, 0xf8, 0x27, 0x6c, 0xe8, 0x00, + 0x4e, 0xf8, 0x27, 0x6a, 0x77, 0x12, 0x27, 0x40, + 0x77, 0x11, 0x24, 0x00, 0x77, 0x1a, 0x00, 0x1f, + 0xf0, 0x72, 0x11, 0xdb, 0x70, 0x92, 0x00, 0x11, + 0x76, 0xe1, 0x00, 0x01, 0xff, 0xff, 0x76, 0x81, + 0x00, 0x00, 0x76, 0xe1, 0x00, 0x02, 0x00, 0x00, + 0x76, 0xe1, 0x00, 0x03, 0x00, 0xff, 0x76, 0xe1, + 0x00, 0x0c, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x0b, + 0x00, 0x00, 0x76, 0xe1, 0x00, 0x04, 0x00, 0x00, + 0x6d, 0xe9, 0x00, 0x0d, 0xf0, 0x20, 0x25, 0xa0, + 0xf1, 0x00, 0x00, 0x07, 0x89, 0x11, 0xf1, 0x00, + 0x00, 0x01, 0x81, 0x02, 0x88, 0x16, 0xf4, 0x95, + 0x77, 0x17, 0x00, 0x20, 0x76, 0x86, 0x00, 0xff, + 0x76, 0x00, 0x00, 0x00, 0x76, 0x01, 0x00, 0x06, + 0x10, 0x02, 0xf0, 0x74, 0x06, 0x6c, 0x76, 0x00, + 0x00, 0x00, 0x76, 0x01, 0x00, 0x06, 0xf2, 0x74, + 0x06, 0x6c, 0xf4, 0x95, 0x48, 0x11, 0x10, 0x02, + 0xf0, 0x00, 0x00, 0x0d, 0x80, 0x02, 0x6d, 0xe9, + 0x00, 0x0d, 0x6d, 0xee, 0x00, 0x0d, 0x6c, 0xef, + 0xff, 0xff, 0x11, 0xe8, 0xf0, 0x74, 0x0c, 0x9d, + 0xee, 0x04, 0x8a, 0x17, 0x8a, 0x16, 0x8a, 0x11, + 0xfc, 0x00, 0x4a, 0x11, 0x4a, 0x16, 0x4a, 0x17, + 0xee, 0xfa, 0x88, 0x11, 0x10, 0x0a, 0x49, 0x11, + 0xf8, 0x4d, 0x12, 0x9f, 0x48, 0x08, 0xf8, 0x45, + 0x12, 0x9f, 0x80, 0x04, 0x12, 0x81, 0xf5, 0x78, + 0x89, 0x12, 0xf4, 0x95, 0xf4, 0x95, 0x6c, 0xe2, + 0xff, 0xb9, 0x12, 0x8a, 0x61, 0xf8, 0x00, 0x08, + 0x00, 0x80, 0xf8, 0x30, 0x12, 0x8a, 0x13, 0xe1, + 0x00, 0x01, 0xf0, 0xe8, 0xf7, 0x78, 0xf1, 0xa0, + 0xf2, 0x30, 0x1f, 0xff, 0x88, 0x17, 0xf4, 0x95, + 0x77, 0x12, 0x24, 0x00, 0x77, 0x16, 0x00, 0x00, + 0x77, 0x13, 0x00, 0x20, 0xf6, 0xb8, 0x48, 0x17, + 0x08, 0xe2, 0x00, 0x01, 0xf8, 0x45, 0x12, 0x42, + 0x6d, 0xea, 0x00, 0x0d, 0x6d, 0x96, 0x6c, 0xeb, + 0xff, 0xff, 0x12, 0x34, 0xf0, 0x73, 0x12, 0x90, + 0x56, 0xf8, 0x27, 0x6a, 0xf0, 0x00, 0x00, 0x01, + 0x4e, 0xf8, 0x27, 0x6a, 0x60, 0x82, 0x00, 0x01, + 0xf8, 0x30, 0x12, 0x54, 0x70, 0x00, 0x00, 0x16, + 0xf2, 0x74, 0x11, 0x38, 0xf4, 0x95, 0x48, 0x11, + 0xf0, 0x73, 0x12, 0x90, 0x70, 0x00, 0x00, 0x16, + 0xf2, 0x74, 0x11, 0x38, 0xf4, 0x95, 0x48, 0x11, + 0x72, 0x10, 0x2a, 0x9e, 0xf4, 0x95, 0xf4, 0xaf, + 0xf8, 0x30, 0x12, 0x6e, 0x76, 0x00, 0x00, 0x00, + 0x76, 0x01, 0x00, 0xbc, 0x70, 0x02, 0x00, 0x16, + 0x76, 0x03, 0x00, 0x00, 0xf2, 0x74, 0x0c, 0xb9, + 0xf4, 0x95, 0x48, 0x11, 0xf0, 0x73, 0x12, 0x90, + 0x10, 0xf8, 0x27, 0x6e, 0xf8, 0x44, 0x12, 0x90, + 0x76, 0x00, 0x00, 0x00, 0x76, 0x01, 0x00, 0xbc, + 0x70, 0x02, 0x00, 0x16, 0x76, 0x03, 0x00, 0x00, + 0xf2, 0x74, 0x0c, 0xb9, 0xf4, 0x95, 0x48, 0x11, + 0xf0, 0x74, 0x0c, 0x5e, 0xf0, 0xe0, 0xf0, 0x10, + 0x13, 0x88, 0xf8, 0x42, 0x12, 0x90, 0x76, 0xf8, + 0x27, 0x6e, 0x00, 0x01, 0xf0, 0x73, 0x12, 0x90, + 0x56, 0xf8, 0x27, 0x66, 0xf0, 0x00, 0x00, 0x01, + 0x4e, 0xf8, 0x27, 0x66, 0x6d, 0xe9, 0x00, 0x5e, + 0x56, 0xf8, 0x27, 0x68, 0xf0, 0x00, 0x00, 0x01, + 0x4e, 0xf8, 0x27, 0x68, 0x71, 0x04, 0x00, 0x12, + 0x6e, 0xea, 0xff, 0xff, 0x12, 0x18, 0x70, 0x04, + 0x00, 0x12, 0xee, 0x06, 0x8a, 0x17, 0x8a, 0x16, + 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xee, 0xfe, + 0x88, 0x0e, 0xf4, 0x95, 0xf0, 0x66, 0x00, 0x0d, + 0xf0, 0x00, 0x25, 0xa0, 0x88, 0x11, 0xf4, 0x95, + 0xf4, 0x95, 0x76, 0x81, 0x00, 0xff, 0x76, 0x00, + 0x00, 0x00, 0x76, 0x01, 0x00, 0x06, 0xf2, 0x74, + 0x06, 0x6c, 0xf0, 0x00, 0x00, 0x01, 0x76, 0x00, + 0x00, 0x00, 0x76, 0x01, 0x00, 0x06, 0x48, 0x11, + 0xf2, 0x74, 0x06, 0x6c, 0xf0, 0x00, 0x00, 0x07, + 0xee, 0x02, 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, + 0x88, 0x0e, 0xf4, 0x95, 0xf0, 0x66, 0x00, 0x0d, + 0xf0, 0x00, 0x24, 0x00, 0x88, 0x11, 0xf4, 0x95, + 0xf4, 0x95, 0x76, 0xe1, 0x00, 0x01, 0xff, 0xff, + 0x76, 0x81, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x02, + 0x00, 0x00, 0x76, 0xe1, 0x00, 0x03, 0x00, 0xff, + 0x8a, 0x11, 0xfc, 0x00, 0x4a, 0x11, 0xf4, 0x95, + 0x13, 0x03, 0x88, 0x11, 0xfa, 0x4d, 0x12, 0xec, + 0x71, 0x02, 0x00, 0x12, 0xf3, 0x10, 0x00, 0x01, + 0x89, 0x1a, 0xf4, 0x95, 0xf0, 0x72, 0x12, 0xeb, + 0x70, 0x91, 0x00, 0x12, 0x8a, 0x11, 0xfc, 0x00, + 0xf4, 0x95, 0x4a, 0x0b, 0x4a, 0x0c, 0x4a, 0x0d, + 0xf7, 0xb8, 0xee, 0xfe, 0x10, 0xf8, 0x00, 0x08, + 0x11, 0x06, 0xf1, 0xc0, 0x83, 0x00, 0xf4, 0x85, + 0x11, 0x06, 0xf7, 0x85, 0x81, 0x06, 0xf6, 0xb8, + 0xec, 0x0f, 0x1e, 0x06, 0x61, 0x00, 0x80, 0x00, + 0xf8, 0x20, 0x13, 0x05, 0xf4, 0x84, 0xee, 0x02, + 0x8a, 0x0d, 0x8a, 0x0c, 0x8a, 0x0b, 0xfc, 0x00, + 0xf4, 0x95, 0x4a, 0x0b, 0x4a, 0x0c, 0x4a, 0x0d, + 0xee, 0xfe, 0xf7, 0xb8, 0x80, 0x00, 0x10, 0xf8, + 0x00, 0x08, 0xf4, 0x85, 0x11, 0x06, 0xf7, 0x85, + 0x81, 0x06, 0xf6, 0xb8, 0xec, 0x0f, 0x1e, 0x06, + 0xf0, 0xf0, 0x61, 0x00, 0x80, 0x00, 0xf8, 0x20, + 0x13, 0x20, 0xf4, 0x84, 0xee, 0x02, 0x8a, 0x0d, + 0x8a, 0x0c, 0x8a, 0x0b, 0xfc, 0x00, 0x4a, 0x11, + 0x77, 0x11, 0x00, 0x7b, 0x76, 0x81, 0x2e, 0xec, + 0x77, 0x11, 0x00, 0x7b, 0xee, 0xff, 0x71, 0x81, + 0x00, 0x11, 0xee, 0x01, 0x76, 0xe1, 0x00, 0x01, + 0x00, 0x00, 0x76, 0xe1, 0x00, 0x04, 0x00, 0x00, + 0x76, 0xe1, 0x00, 0x06, 0x00, 0x00, 0x76, 0xe1, + 0x00, 0x62, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x76, + 0x00, 0x00, 0x76, 0xe1, 0x00, 0x92, 0x00, 0x00, + 0x76, 0xe1, 0x00, 0x94, 0x00, 0x00, 0x76, 0xe1, + 0x00, 0xb0, 0x00, 0x00, 0x76, 0xe1, 0x00, 0xb3, + 0x00, 0x00, 0x76, 0xe1, 0x00, 0xbe, 0x00, 0x00, + 0x76, 0xe1, 0x00, 0xbf, 0x00, 0x00, 0x76, 0xe1, + 0x00, 0xc1, 0x00, 0x00, 0x76, 0xe1, 0x00, 0xc3, + 0x00, 0x00, 0x76, 0xe1, 0x00, 0xc5, 0x00, 0x00, + 0x76, 0xe1, 0x00, 0xc7, 0x00, 0x00, 0x76, 0x81, + 0x00, 0x00, 0x8a, 0x11, 0xf4, 0x95, 0xf4, 0xe4, + 0x4a, 0x11, 0x4a, 0x16, 0x4a, 0x17, 0xee, 0xff, + 0xf4, 0x95, 0x71, 0x06, 0x00, 0x16, 0xfb, 0x80, + 0x16, 0xa2, 0x88, 0x17, 0xf4, 0x95, 0xf7, 0xb8, + 0x10, 0xf8, 0x00, 0x17, 0xf0, 0x10, 0x00, 0x02, + 0xfa, 0x46, 0x13, 0x88, 0x77, 0x11, 0x00, 0x00, + 0x10, 0xf8, 0x00, 0x17, 0xf0, 0x10, 0x00, 0x02, + 0xf8, 0x45, 0x13, 0xf9, 0x10, 0xf8, 0x00, 0x17, + 0xf8, 0x45, 0x14, 0x39, 0x10, 0xf8, 0x00, 0x17, + 0xf0, 0x10, 0x00, 0x01, 0xf8, 0x45, 0x14, 0x1f, + 0xf0, 0x73, 0x14, 0x52, 0x10, 0xf8, 0x00, 0x17, + 0xf0, 0x10, 0x00, 0x03, 0xf8, 0x45, 0x13, 0xd3, + 0x10, 0xf8, 0x00, 0x17, 0xf0, 0x10, 0x00, 0x06, + 0xf8, 0x44, 0x14, 0x52, 0x77, 0x12, 0x00, 0x7b, + 0x71, 0x82, 0x00, 0x14, 0x61, 0xe4, 0x00, 0x07, + 0x00, 0x40, 0xf8, 0x30, 0x14, 0x52, 0x49, 0x14, + 0x48, 0x17, 0xf6, 0x00, 0x88, 0x12, 0xf4, 0x95, + 0x77, 0x13, 0x00, 0x55, 0x77, 0x11, 0x00, 0x57, + 0x6d, 0xea, 0x00, 0x3b, 0xe5, 0x01, 0x10, 0xe6, + 0x00, 0x06, 0x80, 0x81, 0x48, 0x14, 0x00, 0xf8, + 0x00, 0x17, 0x88, 0x12, 0xf4, 0x95, 0x77, 0x11, + 0x00, 0x55, 0x10, 0xe2, 0x00, 0x40, 0x80, 0x81, + 0x77, 0x11, 0x00, 0x57, 0x10, 0xe6, 0x00, 0x07, + 0x80, 0x81, 0x77, 0x11, 0x00, 0x55, 0x10, 0xe2, + 0x00, 0x45, 0x80, 0x81, 0x10, 0xe6, 0x00, 0x08, + 0x77, 0x11, 0x00, 0x57, 0x80, 0x81, 0x77, 0x11, + 0x00, 0x55, 0x10, 0xe2, 0x00, 0x4a, 0x80, 0x81, + 0x77, 0x11, 0x00, 0x57, 0x10, 0xe6, 0x00, 0x09, + 0x80, 0x81, 0xf2, 0x73, 0x14, 0x52, 0x77, 0x11, + 0x03, 0xc0, 0x77, 0x12, 0x00, 0x7b, 0x10, 0x82, + 0xf0, 0x00, 0x00, 0x07, 0x88, 0x13, 0xf4, 0x95, + 0xf4, 0x95, 0x96, 0x1b, 0xf8, 0x30, 0x14, 0x52, + 0x10, 0xe3, 0x00, 0x35, 0x77, 0x12, 0x00, 0x55, + 0x80, 0x82, 0x77, 0x12, 0x00, 0x57, 0x10, 0xe6, + 0x00, 0x04, 0x80, 0x82, 0x77, 0x12, 0x00, 0x55, + 0x10, 0xe3, 0x00, 0x37, 0x80, 0x82, 0x77, 0x12, + 0x00, 0x57, 0x10, 0xe6, 0x00, 0x05, 0x80, 0x82, + 0x48, 0x11, 0xf0, 0x40, 0x00, 0x10, 0xf2, 0x73, + 0x14, 0x50, 0xf0, 0x40, 0x00, 0x20, 0x77, 0x12, + 0x00, 0x7b, 0x10, 0x82, 0xf0, 0x00, 0x00, 0x07, + 0x88, 0x12, 0xf4, 0x95, 0xf4, 0x95, 0x96, 0x0d, + 0xf8, 0x30, 0x14, 0x52, 0x10, 0xe2, 0x00, 0x34, + 0x77, 0x13, 0x00, 0x55, 0x80, 0x83, 0x77, 0x13, + 0x00, 0x57, 0x10, 0xe6, 0x00, 0x02, 0x80, 0x83, + 0x10, 0xe2, 0x00, 0x36, 0x77, 0x12, 0x00, 0x55, + 0x80, 0x82, 0x77, 0x12, 0x00, 0x57, 0x10, 0xe6, + 0x00, 0x03, 0x80, 0x82, 0x48, 0x11, 0xf0, 0x40, + 0x00, 0x04, 0xf2, 0x73, 0x14, 0x50, 0xf0, 0x40, + 0x00, 0x08, 0x77, 0x12, 0x00, 0x7b, 0x10, 0x82, + 0xf0, 0x00, 0x00, 0x07, 0x88, 0x12, 0xf4, 0x95, + 0xf4, 0x95, 0x96, 0x0e, 0xf8, 0x30, 0x14, 0x52, + 0x10, 0xe2, 0x00, 0x33, 0x77, 0x12, 0x00, 0x55, + 0x80, 0x82, 0x77, 0x12, 0x00, 0x57, 0x10, 0xe6, + 0x00, 0x01, 0x80, 0x82, 0x48, 0x11, 0xf2, 0x73, + 0x14, 0x50, 0xf0, 0x40, 0x00, 0x02, 0x77, 0x12, + 0x00, 0x7b, 0x10, 0x82, 0xf0, 0x00, 0x00, 0x07, + 0x88, 0x12, 0xf4, 0x95, 0xf4, 0x95, 0x96, 0x0f, + 0xf8, 0x30, 0x14, 0x52, 0x10, 0xe2, 0x00, 0x32, + 0x77, 0x12, 0x00, 0x55, 0x77, 0x13, 0x00, 0x57, + 0x80, 0x82, 0x48, 0x11, 0xe7, 0x62, 0xf0, 0x40, + 0x00, 0x01, 0xe5, 0x01, 0x88, 0x11, 0xf4, 0x95, + 0x77, 0x12, 0x00, 0x7b, 0x48, 0x11, 0x71, 0x82, + 0x00, 0x12, 0x1a, 0xe2, 0x00, 0x07, 0x80, 0xe2, + 0x00, 0x07, 0xf9, 0x80, 0x16, 0x9a, 0xee, 0x01, + 0x8a, 0x17, 0x48, 0x11, 0x8a, 0x16, 0x8a, 0x11, + 0xf4, 0xe4, 0x4a, 0x11, 0x88, 0x11, 0x77, 0x0e, + 0x00, 0x05, 0x77, 0x12, 0x00, 0x55, 0xe8, 0x04, + 0xf6, 0xb8, 0x28, 0xe1, 0x00, 0x02, 0xee, 0xff, + 0x80, 0x82, 0x77, 0x12, 0x00, 0x57, 0xf0, 0x20, + 0x80, 0x00, 0xee, 0x01, 0x1a, 0x82, 0x77, 0x12, + 0x00, 0x57, 0x80, 0x82, 0xe8, 0x01, 0x32, 0xe1, + 0x00, 0x02, 0xf5, 0x82, 0x77, 0x11, 0x00, 0x54, + 0xf6, 0x93, 0x18, 0x81, 0x77, 0x11, 0x00, 0x54, + 0xf2, 0xa0, 0x80, 0x81, 0x8a, 0x11, 0xf4, 0x95, + 0xf4, 0xe4, 0x4a, 0x11, 0x4a, 0x16, 0xf4, 0x95, + 0x71, 0x04, 0x00, 0x11, 0xfb, 0x80, 0x16, 0xa2, + 0x88, 0x16, 0xf4, 0x95, 0x77, 0x12, 0x00, 0x55, + 0x10, 0xe6, 0x00, 0x03, 0x80, 0x82, 0x77, 0x12, + 0x00, 0x56, 0x10, 0xe1, 0x00, 0x02, 0x77, 0x13, + 0x00, 0x56, 0x80, 0x82, 0x77, 0x12, 0x00, 0x56, + 0x10, 0xe1, 0x00, 0x03, 0x80, 0x82, 0x10, 0xe1, + 0x00, 0x04, 0x77, 0x12, 0x00, 0x56, 0x80, 0x82, + 0x77, 0x12, 0x00, 0x56, 0x10, 0xe1, 0x00, 0x01, + 0x80, 0x82, 0xe7, 0x12, 0xe5, 0x01, 0xf9, 0x80, + 0x16, 0x9a, 0x8a, 0x16, 0x8a, 0x11, 0xf4, 0xe4, + 0x4a, 0x11, 0x4a, 0x16, 0x4a, 0x17, 0xee, 0xf9, + 0x77, 0x11, 0x00, 0x7b, 0x76, 0x00, 0x00, 0x16, + 0x76, 0x01, 0x00, 0x17, 0x76, 0x02, 0x00, 0x1a, + 0x76, 0x03, 0x00, 0x1b, 0x76, 0x04, 0x00, 0x1c, + 0x76, 0x05, 0x00, 0x1d, 0x71, 0x81, 0x00, 0x17, + 0x71, 0xe7, 0x00, 0x06, 0x00, 0x11, 0x10, 0x81, + 0xf8, 0x44, 0x14, 0xdf, 0xf9, 0x80, 0x16, 0x53, + 0xf6, 0xb8, 0xfb, 0x80, 0x15, 0x85, 0xf0, 0x20, + 0xff, 0xff, 0xf6, 0xb8, 0xfb, 0x80, 0x16, 0x08, + 0xf0, 0x20, 0xff, 0xff, 0x77, 0x11, 0x00, 0x7b, + 0x71, 0x81, 0x00, 0x17, 0x76, 0xe7, 0x00, 0x06, + 0x00, 0x01, 0x48, 0x17, 0x77, 0x16, 0x00, 0x00, + 0x77, 0x10, 0x00, 0x04, 0x77, 0x15, 0x00, 0x03, + 0x77, 0x14, 0x00, 0x02, 0x77, 0x13, 0x00, 0x01, + 0xf0, 0x00, 0x00, 0x39, 0x76, 0xe7, 0x00, 0x08, + 0x00, 0x1f, 0x76, 0xe7, 0x00, 0x07, 0x00, 0x00, + 0x88, 0x0e, 0x77, 0x1a, 0x00, 0x05, 0x48, 0x17, + 0xf0, 0x00, 0x00, 0x09, 0x88, 0x12, 0x48, 0x18, + 0x88, 0x19, 0xe8, 0x00, 0xf0, 0x72, 0x15, 0x2c, + 0x73, 0x19, 0x00, 0x11, 0x76, 0x82, 0x00, 0x00, + 0x11, 0x91, 0x73, 0x11, 0x00, 0x19, 0x70, 0xe2, + 0x00, 0x03, 0x00, 0x16, 0x70, 0xe2, 0x00, 0x04, + 0x00, 0x13, 0x70, 0xe2, 0x00, 0x05, 0x00, 0x14, + 0x81, 0xe2, 0x00, 0x01, 0x70, 0xe2, 0x00, 0x06, + 0x00, 0x15, 0x70, 0xe2, 0x00, 0x07, 0x00, 0x10, + 0x80, 0xe2, 0x00, 0x02, 0x73, 0x0e, 0x00, 0x11, + 0xf1, 0x00, 0x00, 0x1e, 0x6d, 0xee, 0x00, 0x05, + 0x6d, 0xeb, 0x00, 0x05, 0x6d, 0xec, 0x00, 0x05, + 0x6d, 0xed, 0x00, 0x05, 0x6d, 0xe8, 0x00, 0x05, + 0xf0, 0x00, 0x00, 0x01, 0x81, 0x91, 0x6d, 0xea, + 0x00, 0x08, 0x73, 0x11, 0x00, 0x0e, 0xee, 0x07, + 0x76, 0xe7, 0x00, 0x41, 0x00, 0x24, 0x76, 0xe7, + 0x00, 0x46, 0x00, 0x25, 0x76, 0xe7, 0x00, 0x4b, + 0x00, 0x26, 0x76, 0xe7, 0x00, 0x50, 0x00, 0x27, + 0x8a, 0x17, 0x8a, 0x16, 0x8a, 0x11, 0xf4, 0xe4, + 0x4a, 0x11, 0x4a, 0x16, 0xee, 0xfe, 0x88, 0x11, + 0x56, 0x06, 0x4e, 0x00, 0xf9, 0x80, 0x16, 0xa2, + 0xf7, 0xb8, 0x10, 0xf8, 0x00, 0x11, 0xf0, 0x10, + 0xff, 0xff, 0xfa, 0x45, 0x15, 0x60, 0x77, 0x16, + 0xff, 0xff, 0x77, 0x12, 0x00, 0x7b, 0x49, 0x11, + 0x10, 0x82, 0xf6, 0x03, 0xf0, 0x00, 0x00, 0x09, + 0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x10, 0x81, + 0xf8, 0x44, 0x15, 0x71, 0xf2, 0x73, 0x15, 0x71, + 0xf4, 0x95, 0xe7, 0x16, 0x77, 0x11, 0x00, 0x7b, + 0x10, 0x81, 0xf0, 0x00, 0x00, 0x09, 0x88, 0x11, + 0xf4, 0x95, 0x77, 0x12, 0x00, 0x06, 0x10, 0x81, + 0xf8, 0x45, 0x15, 0x5c, 0x6e, 0xea, 0xff, 0xff, + 0x15, 0x69, 0x6d, 0xe9, 0x00, 0x08, 0x76, 0x86, + 0x00, 0x01, 0xe9, 0x01, 0x56, 0x00, 0xf1, 0x80, + 0x10, 0xf8, 0x00, 0x0b, 0xf8, 0x45, 0x15, 0x7e, + 0xfb, 0x80, 0x15, 0x85, 0xf4, 0x95, 0x48, 0x16, + 0xf9, 0x80, 0x16, 0x9a, 0xee, 0x02, 0x48, 0x16, + 0x8a, 0x16, 0x8a, 0x11, 0xf4, 0xe4, 0x4a, 0x11, + 0xee, 0xff, 0xfb, 0x80, 0x16, 0xa2, 0x88, 0x11, + 0xf4, 0x95, 0x77, 0x10, 0xff, 0xff, 0xf4, 0xa9, + 0xf8, 0x30, 0x15, 0xc4, 0x10, 0xe1, 0x00, 0x03, + 0x77, 0x12, 0x00, 0x55, 0x80, 0x82, 0x77, 0x12, + 0x00, 0x56, 0x76, 0x82, 0x00, 0x00, 0x77, 0x12, + 0x00, 0x56, 0x76, 0x82, 0x00, 0x00, 0x77, 0x12, + 0x00, 0x56, 0x76, 0x82, 0x00, 0x00, 0x77, 0x12, + 0x00, 0x56, 0x76, 0x82, 0x00, 0x00, 0x77, 0x12, + 0x00, 0x56, 0x76, 0x82, 0x00, 0x00, 0x10, 0xe1, + 0x00, 0x02, 0xf0, 0x00, 0x00, 0x08, 0x32, 0xf8, + 0x00, 0x08, 0x77, 0x12, 0x00, 0x54, 0xe8, 0x01, + 0xf4, 0x82, 0xf4, 0x93, 0x18, 0x82, 0x77, 0x12, + 0x00, 0x54, 0xf0, 0x40, 0x00, 0x00, 0x80, 0x82, + 0x10, 0xe1, 0x00, 0x01, 0xf9, 0x80, 0x16, 0x76, + 0x10, 0xe1, 0x00, 0x01, 0xf9, 0x80, 0x16, 0x66, + 0xf0, 0x73, 0x16, 0x03, 0x77, 0x11, 0x00, 0x7b, + 0x71, 0x81, 0x00, 0x11, 0x71, 0xe1, 0x00, 0x07, + 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x10, 0xe1, + 0x00, 0x09, 0xf9, 0x80, 0x15, 0x85, 0x77, 0x11, + 0x00, 0x7b, 0x71, 0x81, 0x00, 0x11, 0x10, 0xe1, + 0x00, 0x09, 0xfb, 0x80, 0x15, 0x85, 0xf0, 0x00, + 0x00, 0x08, 0x77, 0x11, 0x00, 0x7b, 0x71, 0x81, + 0x00, 0x11, 0x10, 0xe1, 0x00, 0x09, 0xfb, 0x80, + 0x15, 0x85, 0xf0, 0x00, 0x00, 0x10, 0x77, 0x11, + 0x00, 0x7b, 0x71, 0x81, 0x00, 0x11, 0x10, 0xe1, + 0x00, 0x09, 0xfb, 0x80, 0x15, 0x85, 0xf0, 0x00, + 0x00, 0x18, 0x77, 0x11, 0x00, 0x7b, 0x71, 0x81, + 0x00, 0x11, 0x10, 0xe1, 0x00, 0x09, 0xfb, 0x80, + 0x15, 0x85, 0xf0, 0x00, 0x00, 0x20, 0x77, 0x11, + 0x00, 0x7b, 0x71, 0x81, 0x00, 0x11, 0x10, 0xe1, + 0x00, 0x09, 0xfb, 0x80, 0x15, 0x85, 0xf0, 0x00, + 0x00, 0x28, 0xf9, 0x80, 0x16, 0x9a, 0xee, 0x01, + 0x8a, 0x11, 0xf4, 0xe4, 0x4a, 0x11, 0xee, 0xff, + 0xfb, 0x80, 0x16, 0xa2, 0x88, 0x11, 0xf4, 0x95, + 0x77, 0x10, 0xff, 0xff, 0xf4, 0xa9, 0xf8, 0x30, + 0x16, 0x41, 0x77, 0x11, 0x00, 0x55, 0x76, 0x81, + 0x00, 0x1e, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81, + 0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81, + 0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81, + 0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81, + 0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81, + 0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81, + 0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81, + 0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81, + 0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0x76, 0x81, + 0x00, 0x00, 0x77, 0x11, 0x00, 0x56, 0xf2, 0x73, + 0x16, 0x4e, 0x76, 0x81, 0x00, 0x00, 0x77, 0x11, + 0x00, 0x7b, 0x71, 0x81, 0x00, 0x11, 0x71, 0xe1, + 0x00, 0x07, 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, + 0x10, 0xe1, 0x00, 0x39, 0xf9, 0x80, 0x16, 0x08, + 0xf9, 0x80, 0x16, 0x9a, 0xee, 0x01, 0x8a, 0x11, + 0xf4, 0xe4, 0x4a, 0x11, 0x77, 0x11, 0x00, 0x7b, + 0x10, 0x81, 0xf0, 0x00, 0x00, 0x04, 0x88, 0x11, + 0xf4, 0x95, 0xf4, 0x95, 0x10, 0x81, 0xfa, 0x44, + 0x16, 0x63, 0xf4, 0x95, 0xee, 0xff, 0x76, 0x81, + 0x00, 0x01, 0xee, 0x01, 0x8a, 0x11, 0xf4, 0xe4, + 0xf0, 0x10, 0x00, 0x10, 0x4a, 0x11, 0x32, 0xf8, + 0x00, 0x08, 0xee, 0xff, 0x77, 0x11, 0x00, 0x01, + 0xe8, 0x01, 0xee, 0x01, 0xf4, 0x82, 0x1a, 0x81, + 0x80, 0x81, 0x8a, 0x11, 0xf4, 0x95, 0xf4, 0xe4, + 0xf0, 0x10, 0x00, 0x10, 0x4a, 0x11, 0x32, 0xf8, + 0x00, 0x08, 0xee, 0xff, 0xe8, 0x01, 0x77, 0x11, + 0x00, 0x00, 0xf4, 0x82, 0xee, 0x01, 0xf4, 0x93, + 0x18, 0x81, 0x80, 0x81, 0x8a, 0x11, 0xf4, 0x95, + 0xf4, 0xe4, 0x4a, 0x11, 0xf0, 0x10, 0x00, 0x10, + 0x77, 0x11, 0x00, 0x00, 0x32, 0xf8, 0x00, 0x08, + 0xee, 0xff, 0x11, 0x81, 0xe8, 0x01, 0xee, 0x01, + 0x77, 0x11, 0x00, 0x00, 0xf4, 0x82, 0xf2, 0xa0, + 0x80, 0x81, 0x8a, 0x11, 0xf4, 0x95, 0xf4, 0xe4, + 0xf2, 0x73, 0x16, 0x9e, 0xf6, 0xbb, 0xf4, 0x95, + 0xf4, 0x95, 0xf4, 0x95, 0xf4, 0x95, 0xf4, 0xe4, + 0xf2, 0x73, 0x16, 0xa6, 0xf7, 0xbb, 0xf4, 0x95, + 0xf4, 0x95, 0xf4, 0x95, 0xf4, 0x95, 0xf4, 0xe4, + 0x4a, 0x11, 0x4a, 0x16, 0xf4, 0x95, 0x71, 0x04, + 0x00, 0x16, 0xfb, 0x80, 0x16, 0xa2, 0x88, 0x11, + 0xf4, 0x95, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, + 0x76, 0x82, 0x00, 0x0e, 0x10, 0xe6, 0x00, 0x0e, + 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x80, 0x82, + 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, + 0x00, 0x0d, 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, + 0x10, 0xe6, 0x00, 0x0d, 0x80, 0x82, 0x71, 0xe1, + 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x0c, + 0x10, 0xe6, 0x00, 0x0c, 0x71, 0xe1, 0x00, 0x06, + 0x00, 0x12, 0x80, 0x82, 0x71, 0xe1, 0x00, 0x05, + 0x00, 0x12, 0x76, 0x82, 0x00, 0x0b, 0x10, 0xe6, + 0x00, 0x0b, 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, + 0x80, 0x82, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, + 0x76, 0x82, 0x00, 0x0a, 0x71, 0xe1, 0x00, 0x06, + 0x00, 0x12, 0x10, 0xe6, 0x00, 0x0a, 0x80, 0x82, + 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, + 0x00, 0x09, 0x10, 0xe6, 0x00, 0x09, 0x71, 0xe1, + 0x00, 0x06, 0x00, 0x12, 0x80, 0x82, 0x71, 0xe1, + 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x08, + 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x10, 0xe6, + 0x00, 0x08, 0x80, 0x82, 0x71, 0xe1, 0x00, 0x05, + 0x00, 0x12, 0x76, 0x82, 0x00, 0x07, 0x10, 0xe6, + 0x00, 0x07, 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, + 0x80, 0x82, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, + 0x76, 0x82, 0x00, 0x06, 0x71, 0xe1, 0x00, 0x06, + 0x00, 0x12, 0x10, 0xe6, 0x00, 0x06, 0x80, 0x82, + 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, + 0x00, 0x05, 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, + 0x10, 0xe6, 0x00, 0x05, 0x80, 0x82, 0x71, 0xe1, + 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x04, + 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x10, 0xe6, + 0x00, 0x04, 0x80, 0x82, 0x71, 0xe1, 0x00, 0x05, + 0x00, 0x12, 0x76, 0x82, 0x00, 0x03, 0x71, 0xe1, + 0x00, 0x06, 0x00, 0x12, 0x10, 0xe6, 0x00, 0x03, + 0x80, 0x82, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, + 0x76, 0x82, 0x00, 0x02, 0x10, 0xe6, 0x00, 0x02, + 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x80, 0x82, + 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, + 0x00, 0x01, 0x10, 0xe6, 0x00, 0x01, 0x71, 0xe1, + 0x00, 0x06, 0x00, 0x12, 0x80, 0x82, 0x71, 0xe1, + 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, + 0x71, 0xe1, 0x00, 0x06, 0x00, 0x13, 0xe7, 0x62, + 0xe5, 0x01, 0xf9, 0x80, 0x16, 0x9a, 0x8a, 0x16, + 0x8a, 0x11, 0xf4, 0xe4, 0x4a, 0x11, 0x88, 0x11, + 0xf4, 0x95, 0xf4, 0x95, 0x71, 0xe1, 0x00, 0x05, + 0x00, 0x12, 0xee, 0xff, 0x76, 0x82, 0x00, 0x00, + 0xee, 0x01, 0x71, 0xe1, 0x00, 0x06, 0x00, 0x11, + 0x69, 0x81, 0x00, 0x01, 0x8a, 0x11, 0xf4, 0x95, + 0xf4, 0xe4, 0x4a, 0x11, 0x88, 0x11, 0xf4, 0x95, + 0xf4, 0x95, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, + 0xee, 0xff, 0x76, 0x82, 0x00, 0x01, 0xee, 0x01, + 0x71, 0xe1, 0x00, 0x06, 0x00, 0x11, 0x69, 0x81, + 0x00, 0x01, 0x8a, 0x11, 0xf4, 0x95, 0xf4, 0xe4, + 0x4a, 0x11, 0x77, 0x11, 0x00, 0x7b, 0x10, 0x81, + 0xf0, 0x00, 0x00, 0x94, 0x88, 0x11, 0xf4, 0x95, + 0xf4, 0x95, 0x10, 0x81, 0xfa, 0x44, 0x17, 0x9c, + 0xf4, 0x95, 0xee, 0xff, 0xf9, 0x80, 0x16, 0x53, + 0x77, 0x11, 0x00, 0x7b, 0x10, 0x81, 0xf0, 0x00, + 0x00, 0x94, 0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, + 0x76, 0x81, 0x00, 0x01, 0xee, 0x01, 0x76, 0xe1, + 0x00, 0x01, 0x00, 0x00, 0x76, 0xe1, 0x00, 0x02, + 0x00, 0x21, 0x76, 0xe1, 0x00, 0x03, 0x00, 0x20, + 0x76, 0xe1, 0x00, 0x04, 0x00, 0x23, 0x76, 0xe1, + 0x00, 0x05, 0x00, 0x22, 0x76, 0xe1, 0x00, 0x06, + 0x00, 0x38, 0x76, 0xe1, 0x00, 0x07, 0x00, 0x39, + 0x76, 0xe1, 0x00, 0x08, 0x00, 0x15, 0x76, 0xe1, + 0x00, 0x09, 0x00, 0x14, 0x76, 0xe1, 0x00, 0x0a, + 0x00, 0x00, 0x76, 0xe1, 0x00, 0x0b, 0x00, 0x41, + 0x76, 0xe1, 0x00, 0x0c, 0x00, 0x40, 0x76, 0xe1, + 0x00, 0x0d, 0x00, 0x43, 0x76, 0xe1, 0x00, 0x0e, + 0x00, 0x42, 0x76, 0xe1, 0x00, 0x0f, 0x00, 0x48, + 0x76, 0xe1, 0x00, 0x10, 0x00, 0x49, 0x76, 0xe1, + 0x00, 0x11, 0x00, 0x1b, 0x76, 0xe1, 0x00, 0x12, + 0x00, 0x1a, 0x8a, 0x11, 0xf4, 0x95, 0xf4, 0xe4, + 0x4a, 0x11, 0xee, 0xfd, 0x88, 0x11, 0x56, 0x06, + 0x4e, 0x00, 0xf9, 0x80, 0x16, 0xa2, 0x77, 0x12, + 0x00, 0x7b, 0x77, 0x0e, 0x00, 0x09, 0x10, 0x82, + 0x28, 0xf8, 0x00, 0x11, 0xf0, 0x00, 0x00, 0x95, + 0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x10, 0x81, + 0xf8, 0x45, 0x17, 0xf0, 0xf2, 0x73, 0x17, 0xfd, + 0x77, 0x11, 0xff, 0xff, 0x76, 0x81, 0x00, 0x01, + 0xe9, 0x01, 0x56, 0x00, 0xf1, 0x80, 0x10, 0xf8, + 0x00, 0x0b, 0xf8, 0x45, 0x17, 0xfd, 0xfb, 0x80, + 0x18, 0x10, 0xf4, 0x95, 0x48, 0x11, 0xf9, 0x80, + 0x16, 0x9a, 0xee, 0x03, 0x48, 0x11, 0x8a, 0x11, + 0xf4, 0x95, 0xf4, 0xe4, 0x4a, 0x11, 0x88, 0x11, + 0xf4, 0x95, 0xee, 0xff, 0x71, 0xe1, 0x00, 0x01, + 0x00, 0x11, 0xee, 0x01, 0x10, 0x81, 0x8a, 0x11, + 0xf4, 0x95, 0xf4, 0xe4, 0x4a, 0x11, 0xee, 0xff, + 0xfb, 0x80, 0x16, 0xa2, 0x88, 0x11, 0xf4, 0x95, + 0x77, 0x10, 0xff, 0xff, 0xf4, 0xa9, 0xf8, 0x30, + 0x18, 0xc3, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, + 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1, 0x00, 0x06, + 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1, + 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x01, + 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82, + 0x00, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, + 0x76, 0x82, 0x00, 0x02, 0x71, 0xe1, 0x00, 0x06, + 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1, + 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x03, + 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82, + 0x00, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, + 0x76, 0x82, 0x00, 0x04, 0x71, 0xe1, 0x00, 0x06, + 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1, + 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x05, + 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82, + 0x00, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, + 0x76, 0x82, 0x00, 0x06, 0x71, 0xe1, 0x00, 0x06, + 0x00, 0x12, 0x76, 0x82, 0x00, 0x01, 0x71, 0xe1, + 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x07, + 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82, + 0x20, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, + 0x76, 0x82, 0x00, 0x08, 0x71, 0xe1, 0x00, 0x06, + 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1, + 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x09, + 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82, + 0x00, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, + 0x76, 0x82, 0x00, 0x0a, 0x71, 0xe1, 0x00, 0x06, + 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1, + 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x0b, + 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82, + 0x00, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, + 0x76, 0x82, 0x00, 0x0c, 0x71, 0xe1, 0x00, 0x06, + 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x71, 0xe1, + 0x00, 0x05, 0x00, 0x12, 0x76, 0x82, 0x00, 0x0d, + 0x71, 0xe1, 0x00, 0x06, 0x00, 0x12, 0x76, 0x82, + 0x00, 0x00, 0x71, 0xe1, 0x00, 0x05, 0x00, 0x12, + 0x76, 0x82, 0x00, 0x0e, 0x71, 0xe1, 0x00, 0x06, + 0x00, 0x12, 0x76, 0x82, 0x00, 0x00, 0x10, 0xe1, + 0x00, 0x07, 0xf9, 0x80, 0x16, 0x76, 0x10, 0xe1, + 0x00, 0x08, 0xf9, 0x80, 0x16, 0x76, 0x10, 0xe1, + 0x00, 0x07, 0xf9, 0x80, 0x16, 0x66, 0x10, 0xe1, + 0x00, 0x08, 0xf9, 0x80, 0x16, 0x66, 0xf0, 0x73, + 0x18, 0xd1, 0x77, 0x11, 0x00, 0x7b, 0x10, 0x81, + 0xfb, 0x80, 0x18, 0x10, 0xf0, 0x00, 0x00, 0x95, + 0x77, 0x11, 0x00, 0x7b, 0x10, 0x81, 0xfb, 0x80, + 0x18, 0x10, 0xf0, 0x00, 0x00, 0x9e, 0xf9, 0x80, + 0x16, 0x9a, 0xee, 0x01, 0x8a, 0x11, 0xf4, 0xe4, + 0x4a, 0x11, 0x88, 0x11, 0xee, 0xff, 0xf4, 0x95, + 0x10, 0x04, 0x71, 0xe1, 0x00, 0x03, 0x00, 0x11, + 0xee, 0x01, 0x80, 0x81, 0x8a, 0x11, 0xf4, 0x95, + 0xf4, 0xe4, 0x4a, 0x11, 0x4a, 0x16, 0xf4, 0x95, + 0x71, 0x04, 0x00, 0x16, 0xfb, 0x80, 0x16, 0xa2, + 0x88, 0x11, 0xf4, 0x95, 0x71, 0xe1, 0x00, 0x02, + 0x00, 0x12, 0x76, 0x82, 0x00, 0x10, 0x10, 0xe6, + 0x00, 0x01, 0x71, 0xe1, 0x00, 0x03, 0x00, 0x12, + 0x80, 0x82, 0x71, 0xe1, 0x00, 0x04, 0x00, 0x12, + 0x10, 0xe6, 0x00, 0x02, 0x80, 0x82, 0xe7, 0x62, + 0x71, 0xe1, 0x00, 0x02, 0x00, 0x13, 0xe5, 0x01, + 0xf9, 0x80, 0x16, 0x9a, 0x8a, 0x16, 0x8a, 0x11, + 0xf4, 0xe4, 0x4a, 0x11, 0x88, 0x11, 0xee, 0xff, + 0xee, 0x01, 0x10, 0xe1, 0x00, 0x01, 0x8a, 0x11, + 0xf4, 0x95, 0xf4, 0xe4, 0x4a, 0x11, 0x77, 0x11, + 0x00, 0x7b, 0x10, 0x81, 0xf0, 0x00, 0x00, 0xb3, + 0x88, 0x11, 0xf4, 0x95, 0xf4, 0x95, 0x10, 0x81, + 0xfa, 0x44, 0x19, 0x2a, 0xf4, 0x95, 0xee, 0xff, + 0xf9, 0x80, 0x16, 0x53, 0x77, 0x11, 0x00, 0x7b, + 0x10, 0x81, 0xf0, 0x00, 0x00, 0xb3, 0x88, 0x11, + 0xf4, 0x95, 0xf4, 0x95, 0x76, 0x81, 0x00, 0x01, + 0xee, 0x01, 0x76, 0xe1, 0x00, 0x01, 0x00, 0x00, + 0x76, 0xe1, 0x00, 0x02, 0x00, 0x13, 0x76, 0xe1, + 0x00, 0x03, 0x00, 0x26, 0x76, 0xe1, 0x00, 0x04, + 0x00, 0x25, 0x76, 0xe1, 0x00, 0x05, 0x00, 0x24, + 0x76, 0xe1, 0x00, 0x06, 0x00, 0x00, 0x76, 0xe1, + 0x00, 0x07, 0x00, 0x17, 0x76, 0xe1, 0x00, 0x08, + 0x00, 0x32, 0x76, 0xe1, 0x00, 0x09, 0x00, 0x31, + 0x76, 0xe1, 0x00, 0x0a, 0x00, 0x30, 0x8a, 0x11, + 0xf4, 0x95, 0xf4, 0xe4, 0x4a, 0x11, 0x4a, 0x16, + 0x4a, 0x17, 0xee, 0xff, 0xf4, 0x95, 0x71, 0x06, + 0x00, 0x17, 0xfb, 0x80, 0x16, 0xa2, 0x88, 0x11, + 0xf4, 0x95, 0xf7, 0xb8, 0x10, 0xf8, 0x00, 0x11, + 0xf0, 0x10, 0xff, 0xff, 0xfa, 0x45, 0x19, 0x73, + 0x77, 0x16, 0xff, 0xff, 0x77, 0x12, 0x00, 0x7b, + 0x77, 0x0e, 0x00, 0x05, 0x10, 0x82, 0x28, 0xf8, + 0x00, 0x11, 0xf0, 0x00, 0x00, 0xb4, 0x88, 0x11, + 0xf4, 0x95, 0xf4, 0x95, 0x10, 0x81, 0xf8, 0x44, + 0x19, 0x84, 0xf2, 0x73, 0x19, 0x84, 0xf4, 0x95, + 0xe7, 0x16, 0x77, 0x11, 0x00, 0x7b, 0x10, 0x81, + 0xf0, 0x00, 0x00, 0xb4, 0x88, 0x11, 0xf4, 0x95, + 0x77, 0x12, 0x00, 0x02, 0x10, 0x81, 0xf8, 0x45, + 0x19, 0x6f, 0x6e, 0xea, 0xff, 0xff, 0x19, 0x7c, + 0x6d, 0xe9, 0x00, 0x05, 0x61, 0xf8, 0x00, 0x17, + 0x00, 0x01, 0xfa, 0x20, 0x19, 0x8f, 0x76, 0x86, + 0x00, 0x01, 0xfb, 0x80, 0x19, 0x97, 0xf4, 0x95, + 0x48, 0x16, 0xf9, 0x80, 0x16, 0x9a, 0xee, 0x01, + 0x8a, 0x17, 0x48, 0x16, 0x8a, 0x16, 0x8a, 0x11, + 0xf4, 0xe4, 0x4a, 0x11, 0xee, 0xff, 0xfb, 0x80, + 0x16, 0xa2, 0x88, 0x11, 0xf4, 0x95, 0x77, 0x10, + 0xff, 0xff, 0xf4, 0xa9, 0xf8, 0x30, 0x19, 0xcc, + 0x71, 0xe1, 0x00, 0x02, 0x00, 0x12, 0x69, 0x82, + 0x00, 0x10, 0x71, 0xe1, 0x00, 0x02, 0x00, 0x12, + 0x68, 0x82, 0xf7, 0xff, 0x71, 0xe1, 0x00, 0x02, + 0x00, 0x12, 0x68, 0x82, 0xfb, 0xff, 0x71, 0xe1, + 0x00, 0x02, 0x00, 0x12, 0x68, 0x82, 0xff, 0xf0, + 0x71, 0xe1, 0x00, 0x03, 0x00, 0x12, 0x76, 0x82, + 0xff, 0xff, 0x71, 0xe1, 0x00, 0x04, 0x00, 0x12, + 0x76, 0x82, 0xff, 0xff, 0x71, 0xe1, 0x00, 0x02, + 0x00, 0x12, 0x69, 0x82, 0x00, 0x20, 0x71, 0xe1, + 0x00, 0x02, 0x00, 0x11, 0xf2, 0x73, 0x19, 0xda, + 0x68, 0x81, 0xff, 0xef, 0x77, 0x11, 0x00, 0x7b, + 0x10, 0x81, 0xfb, 0x80, 0x19, 0x97, 0xf0, 0x00, + 0x00, 0xb4, 0x77, 0x11, 0x00, 0x7b, 0x10, 0x81, + 0xfb, 0x80, 0x19, 0x97, 0xf0, 0x00, 0x00, 0xb9, + 0xf9, 0x80, 0x16, 0x9a, 0xee, 0x01, 0x8a, 0x11, + 0xf4, 0xe4, 0x00, 0xa4, 0x00, 0x00, 0x19, 0xdf, + 0x00, 0x01, 0x2a, 0xe6, 0x00, 0x00, 0x00, 0x01, + 0x2a, 0xe7, 0x00, 0x00, 0x00, 0x03, 0x2a, 0x12, + 0x0c, 0x01, 0xc3, 0x4f, 0x00, 0x00, 0x00, 0x01, + 0x2a, 0x15, 0x00, 0x00, 0x00, 0x02, 0x2a, 0x16, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x2a, 0x5d, + 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, + 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, + 0x00, 0x74, 0x00, 0x20, 0x00, 0x54, 0x00, 0x65, + 0x00, 0x63, 0x00, 0x68, 0x00, 0x6e, 0x00, 0x6f, + 0x00, 0x54, 0x00, 0x72, 0x00, 0x65, 0x00, 0x6e, + 0x00, 0x64, 0x00, 0x20, 0x00, 0x41, 0x00, 0x47, + 0x00, 0x00, 0x00, 0x04, 0x2a, 0x76, 0x00, 0x30, + 0x00, 0x2e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x0c, + 0x2a, 0x7a, 0x00, 0x46, 0x00, 0x65, 0x00, 0x62, + 0x00, 0x20, 0x00, 0x32, 0x00, 0x37, 0x00, 0x20, + 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x09, 0x2a, 0x86, 0x00, 0x31, + 0x00, 0x34, 0x00, 0x3a, 0x00, 0x33, 0x00, 0x35, + 0x00, 0x3a, 0x00, 0x33, 0x00, 0x33, 0x00, 0x00, + 0x00, 0x0f, 0x2a, 0x8f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x2a, 0x9e, 0x00, 0x00, + 0x00, 0x01, 0x2a, 0x9f, 0x00, 0x00, 0x00, 0x01, + 0x2a, 0xa0, 0x00, 0x00, 0x00, 0x01, 0x2a, 0xa1, + 0x00, 0x00, 0x00, 0x01, 0x2a, 0xa2, 0x00, 0x00, + 0x00, 0x01, 0x29, 0x7e, 0x00, 0x00, 0x00, 0x02, + 0x29, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x29, 0x82, 0xff, 0xff, 0x00, 0x01, 0x2a, 0xa7, + 0x00, 0x00, 0x00, 0x05, 0x2a, 0xa8, 0x71, 0x41, + 0x20, 0x00, 0x20, 0x00, 0x00, 0x23, 0x04, 0x00, + 0x00, 0x0a, 0x2a, 0xad, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x2a, 0xb7, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xa0, 0x82, 0x40, + 0x00, 0x08, 0x30, 0x7f, 0x00, 0x80, 0x01, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x27, 0x6e, 0x00, 0x00, + 0x00, 0x01, 0x27, 0x6f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x1a, 0x83, 0x04, 0xe8, + 0x04, 0xcf, 0x04, 0xc5, 0x04, 0xba, 0x04, 0xb0, + 0x04, 0xac, 0x04, 0x9c, 0x04, 0x8c, 0x04, 0x81, + 0x00, 0x78, 0x00, 0x00, 0x01, 0x00, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xaa, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x02, 0x23, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x05, 0xe5, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x02, 0xb5, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x0e, 0x33, 0xf4, 0x95, 0xf4, 0x95, 0xf2, 0x73, + 0x07, 0xef, 0xf4, 0x95, 0xf4, 0x95, 0x00, 0x00, +}; + diff -Nru a/drivers/media/dvb/ttusb-dec/Kconfig b/drivers/media/dvb/ttusb-dec/Kconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/ttusb-dec/Kconfig Sat Jul 19 12:54:30 2003 @@ -0,0 +1,24 @@ +config DVB_TTUSB_DEC + tristate "Technotrend/Hauppauge USB DEC2000-T devices" + depends on DVB_CORE && USB + help + Support for external USB adapters designed by Technotrend and + produced by Hauppauge, shipped under the brand name 'DEC2000-T'. + + Even if these devices have a MPEG decoder built in, they transmit + only compressed MPEG data over the USB bus, so you need + an external software decoder to watch TV on your computer. + + Say Y if you own such a device and want to use it. + +config DVB_TTUSB_DEC_FIRMWARE_FILE + string "Full pathname of dec2000t.bin firmware file" + depends on DVB_TTUSB_DEC + default "/etc/dvb/dec2000t.bin" + help + The DEC2000-T requires a firmware in order to boot into a mode in + which it is a slave to the PC. The firmware file can obtained as + follows: + wget http://hauppauge.lightpath.net/de/dec215a.exe + unzip -j dec215a.exe Software/Oem/STB/App/Boot/STB_PC_T.bin + mv STB_PC_T.bin /etc/dvb/dec2000t.bin diff -Nru a/drivers/media/dvb/ttusb-dec/Makefile b/drivers/media/dvb/ttusb-dec/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/ttusb-dec/Makefile Sat Jul 19 12:54:30 2003 @@ -0,0 +1,11 @@ + +obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o dec2000_frontend.o + +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ + +host-progs := fdump + +$(obj)/ttusb_dec.o: $(obj)/dsp_dec2000.h + +$(obj)/dsp_dec2000.h: $(patsubst "%", %, $(CONFIG_DVB_TTUSB_DEC_FIRMWARE_FILE)) $(obj)/fdump + $(obj)/fdump $< dsp_dec2000 > $@ diff -Nru a/drivers/media/dvb/ttusb-dec/dec2000_frontend.c b/drivers/media/dvb/ttusb-dec/dec2000_frontend.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/ttusb-dec/dec2000_frontend.c Sat Jul 19 12:54:30 2003 @@ -0,0 +1,180 @@ +/* + * TTUSB DEC-2000-t Frontend + * + * Copyright (C) 2003 Alex Woods + * + * 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 "dvb_frontend.h" +#include "dvb_functions.h" + +static int debug = 0; + +#define dprintk if (debug) printk + +static struct dvb_frontend_info dec2000_frontend_info = { + name: "TechnoTrend/Hauppauge DEC-2000-t Frontend", + type: FE_OFDM, + frequency_min: 51000000, + frequency_max: 858000000, + frequency_stepsize: 62500, + caps: FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO, +}; + +static int dec2000_frontend_ioctl(struct dvb_frontend *fe, unsigned int cmd, + void *arg) +{ + dprintk("%s\n", __FUNCTION__); + + switch (cmd) { + + case FE_GET_INFO: + dprintk("%s: FE_GET_INFO\n", __FUNCTION__); + memcpy(arg, &dec2000_frontend_info, + sizeof (struct dvb_frontend_info)); + break; + + case FE_READ_STATUS: { + fe_status_t *status = (fe_status_t *)arg; + dprintk("%s: FE_READ_STATUS\n", __FUNCTION__); + *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | + FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK; + break; + } + + case FE_READ_BER: { + u32 *ber = (u32 *)arg; + dprintk("%s: FE_READ_BER\n", __FUNCTION__); + *ber = 0; + return -ENOSYS; + break; + } + + case FE_READ_SIGNAL_STRENGTH: { + dprintk("%s: FE_READ_SIGNAL_STRENGTH\n", __FUNCTION__); + *(s32 *)arg = 0xFF; + return -ENOSYS; + break; + } + + case FE_READ_SNR: + dprintk("%s: FE_READ_SNR\n", __FUNCTION__); + *(s32 *)arg = 0; + return -ENOSYS; + break; + + case FE_READ_UNCORRECTED_BLOCKS: + dprintk("%s: FE_READ_UNCORRECTED_BLOCKS\n", __FUNCTION__); + *(u32 *)arg = 0; + return -ENOSYS; + break; + + case FE_SET_FRONTEND:{ + struct dvb_frontend_parameters *p = + (struct dvb_frontend_parameters *)arg; + u8 b[] = { 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x00, 0xff }; + u32 freq; + struct i2c_msg msg = { addr: 0x71, flags: 0, len:20 }; + + dprintk("%s: FE_SET_FRONTEND\n", __FUNCTION__); + + dprintk(" frequency->%d\n", p->frequency); + dprintk(" symbol_rate->%d\n", + p->u.qam.symbol_rate); + dprintk(" inversion->%d\n", p->inversion); + + freq = htonl(p->frequency / 1000); + memcpy(&b[4], &freq, sizeof (int)); + msg.buf = b; + fe->i2c->xfer(fe->i2c, &msg, 1); + + break; + } + + case FE_GET_FRONTEND: + dprintk("%s: FE_GET_FRONTEND\n", __FUNCTION__); + break; + + case FE_SLEEP: + dprintk("%s: FE_SLEEP\n", __FUNCTION__); + return -ENOSYS; + break; + + case FE_INIT: + dprintk("%s: FE_INIT\n", __FUNCTION__); + break; + + case FE_RESET: + dprintk("%s: FE_RESET\n", __FUNCTION__); + break; + + default: + dprintk("%s: unknown IOCTL (0x%X)\n", __FUNCTION__, cmd); + return -EINVAL; + + } + + return 0; +} + +static int dec2000_frontend_attach(struct dvb_i2c_bus *i2c) +{ + dprintk("%s\n", __FUNCTION__); + + dvb_register_frontend(dec2000_frontend_ioctl, i2c, NULL, + &dec2000_frontend_info); + + return 0; +} + +static void dec2000_frontend_detach(struct dvb_i2c_bus *i2c) +{ + dprintk("%s\n", __FUNCTION__); + + dvb_unregister_frontend(dec2000_frontend_ioctl, i2c); +} + +static int __init dec2000_frontend_init(void) +{ + return dvb_register_i2c_device(THIS_MODULE, dec2000_frontend_attach, + dec2000_frontend_detach); +} + +static void __exit dec2000_frontend_exit(void) +{ + dvb_unregister_i2c_device(dec2000_frontend_attach); +} + +module_init(dec2000_frontend_init); +module_exit(dec2000_frontend_exit); + +MODULE_DESCRIPTION("TechnoTrend/Hauppauge DEC-2000-t Frontend"); +MODULE_AUTHOR("Alex Woods +#include +#include +#include +#include + + +int main (int argc, char **argv) +{ + unsigned char buf[8]; + unsigned int i, count, bytes = 0; + int fd; + + if (argc != 3) { + fprintf (stderr, "\n\tusage: %s \n\n", + argv[0]); + return -1; + } + + fd = open (argv[1], O_RDONLY); + + printf ("\n#include \n\nu8 %s [] __initdata = {", + argv[2]); + + while ((count = read (fd, buf, 8)) > 0) { + printf ("\n\t"); + for (i=0;i + * + * 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 "ttusb_dec.h" +#include "dvb_frontend.h" + +static int debug = 0; + +#define dprintk if (debug) printk + +static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command, + int param_length, const u8 params[], + int *result_length, u8 cmd_result[]) +{ + int result, actual_len, i; + u8 b[COMMAND_PACKET_SIZE + 4]; + u8 c[COMMAND_PACKET_SIZE + 4]; + + dprintk("%s\n", __FUNCTION__); + + if ((result = down_interruptible(&dec->usb_sem))) { + printk("%s: Failed to down usb semaphore.\n", __FUNCTION__); + return result; + } + + b[0] = 0xaa; + b[1] = ++dec->trans_count; + b[2] = command; + b[3] = param_length; + + if (params) + memcpy(&b[4], params, param_length); + + if (debug) { + printk("%s: command: ", __FUNCTION__); + for (i = 0; i < param_length + 4; i++) + printk("0x%02X ", b[i]); + printk("\n"); + } + + result = usb_bulk_msg(dec->udev, dec->command_pipe, b, sizeof(b), + &actual_len, HZ); + + if (result) { + printk("%s: command bulk message failed: error %d\n", + __FUNCTION__, result); + up(&dec->usb_sem); + return result; + } + + result = usb_bulk_msg(dec->udev, dec->result_pipe, c, sizeof(c), + &actual_len, HZ); + + if (result) { + printk("%s: result bulk message failed: error %d\n", + __FUNCTION__, result); + up(&dec->usb_sem); + return result; + } else { + if (debug) { + printk("%s: result: ", __FUNCTION__); + for (i = 0; i < actual_len; i++) + printk("0x%02X ", c[i]); + printk("\n"); + } + + if (result_length) + *result_length = c[3]; + if (cmd_result && c[3] > 0) + memcpy(cmd_result, &c[4], c[3]); + + up(&dec->usb_sem); + + return 0; + } +} + +static int ttusb_dec_av_pes2ts_cb(void *priv, unsigned char *data) +{ + struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)priv; + + dvbdmxfeed->cb.ts(data, 188, 0, 0, &dvbdmxfeed->feed.ts, DMX_OK); + + return 0; +} + +static void ttusb_dec_set_pids(struct ttusb_dec *dec) +{ + u8 b[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff }; + + u16 pcr = htons(dec->pid[DMX_PES_PCR]); + u16 audio = htons(dec->pid[DMX_PES_AUDIO]); + u16 video = htons(dec->pid[DMX_PES_VIDEO]); + + dprintk("%s\n", __FUNCTION__); + + memcpy(&b[0], &pcr, 2); + memcpy(&b[2], &audio, 2); + memcpy(&b[4], &video, 2); + + ttusb_dec_send_command(dec, 0x50, sizeof(b), b, NULL, NULL); + + if (!down_interruptible(&dec->pes2ts_sem)) { + dvb_filter_pes2ts_init(&dec->a_pes2ts, dec->pid[DMX_PES_AUDIO], + ttusb_dec_av_pes2ts_cb, dec->demux.feed); + dvb_filter_pes2ts_init(&dec->v_pes2ts, dec->pid[DMX_PES_VIDEO], + ttusb_dec_av_pes2ts_cb, dec->demux.feed); + + up(&dec->pes2ts_sem); + } +} + +static int ttusb_dec_i2c_master_xfer(struct dvb_i2c_bus *i2c, + const struct i2c_msg msgs[], int num) +{ + int result, i; + + dprintk("%s\n", __FUNCTION__); + + for (i = 0; i < num; i++) + if ((result = ttusb_dec_send_command(i2c->data, msgs[i].addr, + msgs[i].len, msgs[i].buf, + NULL, NULL))) + return result; + + return 0; +} + +static void ttusb_dec_process_av_pes(struct ttusb_dec * dec, u8 * av_pes, + int length) +{ + int i; + u16 csum = 0; + u8 c; + + if (length < 16) { + printk("%s: packet too short.\n", __FUNCTION__); + return; + } + + for (i = 0; i < length; i += 2) { + csum ^= le16_to_cpup((u16 *)(av_pes + i)); + c = av_pes[i]; + av_pes[i] = av_pes[i + 1]; + av_pes[i + 1] = c; + } + + if (csum) { + printk("%s: checksum failed.\n", __FUNCTION__); + return; + } + + if (length > 8 + MAX_AV_PES_LENGTH + 4) { + printk("%s: packet too long.\n", __FUNCTION__); + return; + } + + if (!(av_pes[0] == 'A' && av_pes[1] == 'V')) { + printk("%s: invalid AV_PES packet.\n", __FUNCTION__); + return; + } + + switch (av_pes[2]) { + + case 0x01: { /* VideoStream */ + int prebytes = av_pes[5] & 0x03; + int postbytes = (av_pes[5] & 0x0c) >> 2; + u16 v_pes_payload_length; + + if (dec->v_pes_postbytes > 0 && + dec->v_pes_postbytes == prebytes) { + memcpy(&dec->v_pes[dec->v_pes_length], + &av_pes[12], prebytes); + + if (!down_interruptible(&dec->pes2ts_sem)) { + dvb_filter_pes2ts(&dec->v_pes2ts, + dec->v_pes, + dec->v_pes_length + + prebytes); + + up(&dec->pes2ts_sem); + } + } + + if (av_pes[5] & 0x10) { + dec->v_pes[7] = 0x80; + dec->v_pes[8] = 0x05; + + dec->v_pes[9] = 0x21 | + ((av_pes[8] & 0xc0) >> 5); + dec->v_pes[10] = ((av_pes[8] & 0x3f) << 2) | + ((av_pes[9] & 0xc0) >> 6); + dec->v_pes[11] = 0x01 | + ((av_pes[9] & 0x3f) << 2) | + ((av_pes[10] & 0x80) >> 6); + dec->v_pes[12] = ((av_pes[10] & 0x7f) << 1) | + ((av_pes[11] & 0xc0) >> 7); + dec->v_pes[13] = 0x01 | + ((av_pes[11] & 0x7f) << 1); + + memcpy(&dec->v_pes[14], &av_pes[12 + prebytes], + length - 16 - prebytes); + dec->v_pes_length = 14 + length - 16 - prebytes; + } else { + dec->v_pes[7] = 0x00; + dec->v_pes[8] = 0x00; + + memcpy(&dec->v_pes[9], &av_pes[8], length - 12); + dec->v_pes_length = 9 + length - 12; + } + + dec->v_pes_postbytes = postbytes; + + if (dec->v_pes[9 + dec->v_pes[8]] == 0x00 && + dec->v_pes[10 + dec->v_pes[8]] == 0x00 && + dec->v_pes[11 + dec->v_pes[8]] == 0x01) + dec->v_pes[6] = 0x84; + else + dec->v_pes[6] = 0x80; + + v_pes_payload_length = htons(dec->v_pes_length - 6 + + postbytes); + memcpy(&dec->v_pes[4], &v_pes_payload_length, 2); + + if (postbytes == 0) { + if (!down_interruptible(&dec->pes2ts_sem)) { + dvb_filter_pes2ts(&dec->v_pes2ts, + dec->v_pes, + dec->v_pes_length); + + up(&dec->pes2ts_sem); + } + } + + break; + } + + case 0x02: /* MainAudioStream */ + dvb_filter_pes2ts(&dec->a_pes2ts, &av_pes[8], length - 12); + break; + + default: + printk("%s: unknown AV_PES type: %02x.\n", __FUNCTION__, + av_pes[2]); + break; + + } +} + +static void ttusb_dec_process_urb_frame(struct ttusb_dec * dec, u8 * b, + int length) +{ + while (length) { + switch (dec->av_pes_state) { + + case 0: + case 1: + case 3: + if (*b++ == 0xaa) { + dec->av_pes_state++; + if (dec->av_pes_state == 4) + dec->av_pes_length = 0; + } else { + dec->av_pes_state = 0; + } + + length--; + break; + + case 2: + if (*b++ == 0x00) { + dec->av_pes_state++; + } else { + dec->av_pes_state = 0; + } + + length--; + break; + + case 4: + dec->av_pes[dec->av_pes_length++] = *b++; + + if (dec->av_pes_length == 8) { + dec->av_pes_state++; + dec->av_pes_payload_length = le16_to_cpup( + (u16 *)(dec->av_pes + 6)); + } + + length--; + break; + + case 5: { + int remainder = dec->av_pes_payload_length + + 8 - dec->av_pes_length; + + if (length >= remainder) { + memcpy(dec->av_pes + dec->av_pes_length, + b, remainder); + dec->av_pes_length += remainder; + b += remainder; + length -= remainder; + dec->av_pes_state++; + } else { + memcpy(&dec->av_pes[dec->av_pes_length], + b, length); + dec->av_pes_length += length; + length = 0; + } + + break; + } + + case 6: + dec->av_pes[dec->av_pes_length++] = *b++; + + if (dec->av_pes_length == + 8 + dec->av_pes_payload_length + 4) { + ttusb_dec_process_av_pes(dec, dec->av_pes, + dec->av_pes_length); + dec->av_pes_state = 0; + } + + length--; + break; + + default: + printk("%s: illegal packet state encountered.\n", + __FUNCTION__); + dec->av_pes_state = 0; + + } + + } +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +static void ttusb_dec_process_urb(struct urb *urb) +#else +static void ttusb_dec_process_urb(struct urb *urb, struct pt_regs *ptregs) +#endif +{ + struct ttusb_dec *dec = urb->context; + + if (!urb->status) { + int i; + + for (i = 0; i < FRAMES_PER_ISO_BUF; i++) { + struct usb_iso_packet_descriptor *d; + u8 *b; + int length; + + d = &urb->iso_frame_desc[i]; + b = urb->transfer_buffer + d->offset; + length = d->actual_length; + + ttusb_dec_process_urb_frame(dec, b, length); + } + } else { + /* -ENOENT is expected when unlinking urbs */ + if (urb->status != -ENOENT) + dprintk("%s: urb error: %d\n", __FUNCTION__, + urb->status); + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + if (dec->iso_stream_count) + usb_submit_urb(urb, GFP_KERNEL); +#endif +} + +static void ttusb_dec_setup_urbs(struct ttusb_dec *dec) +{ + int i, j, buffer_offset = 0; + + dprintk("%s\n", __FUNCTION__); + + for (i = 0; i < ISO_BUF_COUNT; i++) { + int frame_offset = 0; + struct urb *urb = dec->iso_urb[i]; + + urb->dev = dec->udev; + urb->context = dec; + urb->complete = ttusb_dec_process_urb; + urb->pipe = dec->stream_pipe; + urb->transfer_flags = URB_ISO_ASAP; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + urb->interval = 1; +#endif + urb->number_of_packets = FRAMES_PER_ISO_BUF; + urb->transfer_buffer_length = ISO_FRAME_SIZE * + FRAMES_PER_ISO_BUF; + urb->transfer_buffer = dec->iso_buffer + buffer_offset; + buffer_offset += ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF; + + for (j = 0; j < FRAMES_PER_ISO_BUF; j++) { + urb->iso_frame_desc[j].offset = frame_offset; + urb->iso_frame_desc[j].length = ISO_FRAME_SIZE; + frame_offset += ISO_FRAME_SIZE; + } + } +} + +static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec) +{ + int i; + + dprintk("%s\n", __FUNCTION__); + + if (down_interruptible(&dec->iso_sem)) + return; + + dec->iso_stream_count--; + + if (!dec->iso_stream_count) { + u8 b0[] = { 0x00 }; + + for (i = 0; i < ISO_BUF_COUNT; i++) + usb_unlink_urb(dec->iso_urb[i]); + + ttusb_dec_send_command(dec, 0x81, sizeof(b0), b0, NULL, NULL); + } + + up(&dec->iso_sem); +} + +/* Setting the interface of the DEC tends to take down the USB communications + * for a short period, so it's important not to call this function just before + * trying to talk to it. + */ +static void ttusb_dec_set_streaming_interface(struct ttusb_dec *dec) +{ + if (!dec->interface) { + usb_set_interface(dec->udev, 0, 8); + dec->interface = 8; + } +} + +static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec) +{ + int i, result; + + dprintk("%s\n", __FUNCTION__); + + if (down_interruptible(&dec->iso_sem)) + return -EAGAIN; + + if (!dec->iso_stream_count) { + u8 b0[] = { 0x05 }; + + ttusb_dec_send_command(dec, 0x80, sizeof(b0), b0, NULL, NULL); + + ttusb_dec_setup_urbs(dec); + + for (i = 0; i < ISO_BUF_COUNT; i++) { + if ((result = usb_submit_urb(dec->iso_urb[i] + , GFP_KERNEL))) { + printk("%s: failed urb submission %d: " + "error %d\n", __FUNCTION__, i, result); + + while (i) { + usb_unlink_urb(dec->iso_urb[i - 1]); + i--; + } + + up(&dec->iso_sem); + return result; + } + } + + dec->av_pes_state = 0; + dec->v_pes_postbytes = 0; + } + + dec->iso_stream_count++; + + up(&dec->iso_sem); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + ttusb_dec_set_streaming_interface(dec); +#endif + + return 0; +} + +static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + struct ttusb_dec *dec = dvbdmx->priv; + + dprintk("%s\n", __FUNCTION__); + + if (!dvbdmx->dmx.frontend) + return -EINVAL; + + dprintk(" pid: 0x%04X\n", dvbdmxfeed->pid); + + switch (dvbdmxfeed->type) { + + case DMX_TYPE_TS: + dprintk(" type: DMX_TYPE_TS\n"); + break; + + case DMX_TYPE_SEC: + dprintk(" type: DMX_TYPE_SEC\n"); + break; + + default: + dprintk(" type: unknown (%d)\n", dvbdmxfeed->type); + return -EINVAL; + + } + + dprintk(" ts_type:"); + + if (dvbdmxfeed->ts_type & TS_DECODER) + dprintk(" TS_DECODER"); + + if (dvbdmxfeed->ts_type & TS_PACKET) + dprintk(" TS_PACKET"); + + if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY) + dprintk(" TS_PAYLOAD_ONLY"); + + dprintk("\n"); + + switch (dvbdmxfeed->pes_type) { + + case DMX_TS_PES_VIDEO: + dprintk(" pes_type: DMX_TS_PES_VIDEO\n"); + dec->pid[DMX_PES_PCR] = dvbdmxfeed->pid; + dec->pid[DMX_PES_VIDEO] = dvbdmxfeed->pid; + ttusb_dec_set_pids(dec); + break; + + case DMX_TS_PES_AUDIO: + dprintk(" pes_type: DMX_TS_PES_AUDIO\n"); + dec->pid[DMX_PES_AUDIO] = dvbdmxfeed->pid; + ttusb_dec_set_pids(dec); + break; + + case DMX_TS_PES_TELETEXT: + dec->pid[DMX_PES_TELETEXT] = dvbdmxfeed->pid; + dprintk(" pes_type: DMX_TS_PES_TELETEXT\n"); + break; + + case DMX_TS_PES_PCR: + dprintk(" pes_type: DMX_TS_PES_PCR\n"); + dec->pid[DMX_PES_PCR] = dvbdmxfeed->pid; + ttusb_dec_set_pids(dec); + break; + + case DMX_TS_PES_OTHER: + dprintk(" pes_type: DMX_TS_PES_OTHER\n"); + break; + + default: + dprintk(" pes_type: unknown (%d)\n", dvbdmxfeed->pes_type); + return -EINVAL; + + } + + ttusb_dec_start_iso_xfer(dec); + + return 0; +} + +static int ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + struct ttusb_dec *dec = dvbdmxfeed->demux->priv; + + dprintk("%s\n", __FUNCTION__); + + ttusb_dec_stop_iso_xfer(dec); + + return 0; +} + +static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec) +{ + int i; + + dprintk("%s\n", __FUNCTION__); + + for (i = 0; i < ISO_BUF_COUNT; i++) + if (dec->iso_urb[i]) + usb_free_urb(dec->iso_urb[i]); + + pci_free_consistent(NULL, + ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * + ISO_BUF_COUNT), + dec->iso_buffer, dec->iso_dma_handle); +} + +static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec) +{ + int i; + + dprintk("%s\n", __FUNCTION__); + + dec->iso_buffer = pci_alloc_consistent(NULL, + ISO_FRAME_SIZE * + (FRAMES_PER_ISO_BUF * + ISO_BUF_COUNT), + &dec->iso_dma_handle); + + memset(dec->iso_buffer, 0, + sizeof(ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT))); + + for (i = 0; i < ISO_BUF_COUNT; i++) { + struct urb *urb; + + if (!(urb = usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_KERNEL))) { + ttusb_dec_free_iso_urbs(dec); + return -ENOMEM; + } + + dec->iso_urb[i] = urb; + } + + ttusb_dec_setup_urbs(dec); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + for (i = 0; i < ISO_BUF_COUNT; i++) { + int next = (i + 1) % ISO_BUF_COUNT; + dec->iso_urb[i]->next = dec->iso_urb[next]; + } +#endif + + return 0; +} + +static void ttusb_dec_init_v_pes(struct ttusb_dec *dec) +{ + dprintk("%s\n", __FUNCTION__); + + dec->v_pes[0] = 0x00; + dec->v_pes[1] = 0x00; + dec->v_pes[2] = 0x01; + dec->v_pes[3] = 0xe0; +} + +static void ttusb_dec_init_usb(struct ttusb_dec *dec) +{ + dprintk("%s\n", __FUNCTION__); + + sema_init(&dec->usb_sem, 1); + sema_init(&dec->iso_sem, 1); + + dec->command_pipe = usb_sndbulkpipe(dec->udev, COMMAND_PIPE); + dec->result_pipe = usb_rcvbulkpipe(dec->udev, RESULT_PIPE); + dec->stream_pipe = usb_rcvisocpipe(dec->udev, STREAM_PIPE); + + ttusb_dec_alloc_iso_urbs(dec); +} + +#include "dsp_dec2000.h" + +static int ttusb_dec_boot_dsp(struct ttusb_dec *dec) +{ + int i, j, actual_len, result, size, trans_count; + u8 b0[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xc8, 0x61, + 0x00 }; + u8 b1[] = { 0x61 }; + u8 b[ARM_PACKET_SIZE]; + u32 dsp_length = htonl(sizeof(dsp_dec2000)); + + dprintk("%s\n", __FUNCTION__); + + memcpy(b0, &dsp_length, 4); + + result = ttusb_dec_send_command(dec, 0x41, sizeof(b0), b0, NULL, NULL); + + if (result) + return result; + + trans_count = 0; + j = 0; + + for (i = 0; i < sizeof(dsp_dec2000); i += COMMAND_PACKET_SIZE) { + size = sizeof(dsp_dec2000) - i; + if (size > COMMAND_PACKET_SIZE) + size = COMMAND_PACKET_SIZE; + + b[j + 0] = 0xaa; + b[j + 1] = trans_count++; + b[j + 2] = 0xf0; + b[j + 3] = size; + memcpy(&b[j + 4], &dsp_dec2000[i], size); + + j += COMMAND_PACKET_SIZE + 4; + + if (j >= ARM_PACKET_SIZE) { + result = usb_bulk_msg(dec->udev, dec->command_pipe, b, + ARM_PACKET_SIZE, &actual_len, + HZ / 10); + j = 0; + } else if (size < COMMAND_PACKET_SIZE) { + result = usb_bulk_msg(dec->udev, dec->command_pipe, b, + j - COMMAND_PACKET_SIZE + size, + &actual_len, HZ / 10); + } + } + + result = ttusb_dec_send_command(dec, 0x43, sizeof(b1), b1, NULL, NULL); + + return result; +} + +static void ttusb_dec_init_stb(struct ttusb_dec *dec) +{ + u8 c[COMMAND_PACKET_SIZE]; + int c_length; + int result; + + dprintk("%s\n", __FUNCTION__); + + result = ttusb_dec_send_command(dec, 0x08, 0, NULL, &c_length, c); + + if (!result) + if (c_length != 0x0c || (c_length == 0x0c && c[9] != 0x63)) + ttusb_dec_boot_dsp(dec); +} + +static int ttusb_dec_init_dvb(struct ttusb_dec *dec) +{ + int result; + + dprintk("%s\n", __FUNCTION__); + + if ((result = dvb_register_adapter(&dec->adapter, "dec2000")) < 0) { + printk("%s: dvb_register_adapter failed: error %d\n", + __FUNCTION__, result); + + return result; + } + + if (!(dec->i2c_bus = dvb_register_i2c_bus(ttusb_dec_i2c_master_xfer, + dec, dec->adapter, 0))) { + printk("%s: dvb_register_i2c_bus failed\n", __FUNCTION__); + + dvb_unregister_adapter(dec->adapter); + + return -ENOMEM; + } + + dec->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING; + + dec->demux.priv = (void *)dec; + dec->demux.filternum = 31; + dec->demux.feednum = 31; + dec->demux.start_feed = ttusb_dec_start_feed; + dec->demux.stop_feed = ttusb_dec_stop_feed; + dec->demux.write_to_decoder = NULL; + + if ((result = dvb_dmx_init(&dec->demux)) < 0) { + printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__, + result); + + dvb_unregister_i2c_bus(ttusb_dec_i2c_master_xfer, dec->adapter, + 0); + dvb_unregister_adapter(dec->adapter); + + return result; + } + + dec->dmxdev.filternum = 32; + dec->dmxdev.demux = &dec->demux.dmx; + dec->dmxdev.capabilities = 0; + + if ((result = dvb_dmxdev_init(&dec->dmxdev, dec->adapter)) < 0) { + printk("%s: dvb_dmxdev_init failed: error %d\n", + __FUNCTION__, result); + + dvb_dmx_release(&dec->demux); + dvb_unregister_i2c_bus(ttusb_dec_i2c_master_xfer, dec->adapter, + 0); + dvb_unregister_adapter(dec->adapter); + + return result; + } + + dec->frontend.source = DMX_FRONTEND_0; + + if ((result = dec->demux.dmx.add_frontend(&dec->demux.dmx, + &dec->frontend)) < 0) { + printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__, + result); + + dvb_dmxdev_release(&dec->dmxdev); + dvb_dmx_release(&dec->demux); + dvb_unregister_i2c_bus(ttusb_dec_i2c_master_xfer, dec->adapter, + 0); + dvb_unregister_adapter(dec->adapter); + + return result; + } + + if ((result = dec->demux.dmx.connect_frontend(&dec->demux.dmx, + &dec->frontend)) < 0) { + printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__, + result); + + dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend); + dvb_dmxdev_release(&dec->dmxdev); + dvb_dmx_release(&dec->demux); + dvb_unregister_i2c_bus(ttusb_dec_i2c_master_xfer, dec->adapter, + 0); + dvb_unregister_adapter(dec->adapter); + + return result; + } + + sema_init(&dec->pes2ts_sem, 1); + + dvb_net_init(dec->adapter, &dec->dvb_net, &dec->demux.dmx); + + return 0; +} + +static void ttusb_dec_exit_dvb(struct ttusb_dec *dec) +{ + dprintk("%s\n", __FUNCTION__); + + dvb_net_release(&dec->dvb_net); + dec->demux.dmx.close(&dec->demux.dmx); + dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend); + dvb_dmxdev_release(&dec->dmxdev); + dvb_dmx_release(&dec->demux); + dvb_unregister_i2c_bus(ttusb_dec_i2c_master_xfer, dec->adapter, 0); + dvb_unregister_adapter(dec->adapter); +} + +static void ttusb_dec_exit_usb(struct ttusb_dec *dec) +{ + int i; + + dprintk("%s\n", __FUNCTION__); + + dec->iso_stream_count = 0; + + for (i = 0; i < ISO_BUF_COUNT; i++) + usb_unlink_urb(dec->iso_urb[i]); + + ttusb_dec_free_iso_urbs(dec); +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +static void *ttusb_dec_probe(struct usb_device *udev, unsigned int ifnum, + const struct usb_device_id *id) +{ + struct ttusb_dec *dec; + + dprintk("%s\n", __FUNCTION__); + + if (ifnum != 0) + return NULL; + + if (!(dec = kmalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) { + printk("%s: couldn't allocate memory.\n", __FUNCTION__); + return NULL; + } + + memset(dec, 0, sizeof(struct ttusb_dec)); + + dec->udev = udev; + + ttusb_dec_init_usb(dec); + ttusb_dec_init_stb(dec); + ttusb_dec_init_dvb(dec); + ttusb_dec_init_v_pes(dec); + + return (void *)dec; +} +#else +static int ttusb_dec_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *udev; + struct ttusb_dec *dec; + + dprintk("%s\n", __FUNCTION__); + + udev = interface_to_usbdev(intf); + + if (!(dec = kmalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) { + printk("%s: couldn't allocate memory.\n", __FUNCTION__); + return -ENOMEM; + } + + memset(dec, 0, sizeof(struct ttusb_dec)); + + dec->udev = udev; + + ttusb_dec_init_usb(dec); + ttusb_dec_init_stb(dec); + ttusb_dec_init_dvb(dec); + ttusb_dec_init_v_pes(dec); + + usb_set_intfdata(intf, (void *)dec); + ttusb_dec_set_streaming_interface(dec); + + return 0; +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +static void ttusb_dec_disconnect(struct usb_device *udev, void *data) +{ + struct ttusb_dec *dec = data; +#else +static void ttusb_dec_disconnect(struct usb_interface *intf) +{ + struct ttusb_dec *dec = usb_get_intfdata(intf); + + usb_set_intfdata(intf, NULL); +#endif + + dprintk("%s\n", __FUNCTION__); + + ttusb_dec_exit_usb(dec); + ttusb_dec_exit_dvb(dec); + + kfree(dec); +} + +static struct usb_device_id ttusb_dec_table[] = { + {USB_DEVICE(0x0b48, 0x1006)}, /* Unconfirmed */ + {USB_DEVICE(0x0b48, 0x1007)}, /* Unconfirmed */ + {USB_DEVICE(0x0b48, 0x1008)}, /* DEC 2000 t */ + {} +}; + +static struct usb_driver ttusb_dec_driver = { + name: DRIVER_NAME, + probe: ttusb_dec_probe, + disconnect: ttusb_dec_disconnect, + id_table: ttusb_dec_table, +}; + +static int __init ttusb_dec_init(void) +{ + int result; + + if ((result = usb_register(&ttusb_dec_driver)) < 0) { + printk("%s: initialisation failed: error %d.\n", __FUNCTION__, + result); + return result; + } + + return 0; +} + +static void __exit ttusb_dec_exit(void) +{ + usb_deregister(&ttusb_dec_driver); +} + +module_init(ttusb_dec_init); +module_exit(ttusb_dec_exit); + +MODULE_AUTHOR("Alex Woods "); +MODULE_DESCRIPTION(DRIVER_NAME); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(usb, ttusb_dec_table); + +MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "Debug level"); diff -Nru a/drivers/media/dvb/ttusb-dec/ttusb_dec.h b/drivers/media/dvb/ttusb-dec/ttusb_dec.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.h Sat Jul 19 12:54:30 2003 @@ -0,0 +1,87 @@ +/* + * TTUSB DEC Driver + * + * Copyright (C) 2003 Alex Woods + * + * 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 _TTUSB_DEC_H +#define _TTUSB_DEC_H + +#include "asm/semaphore.h" +#include "dmxdev.h" +#include "dvb_demux.h" +#include "dvb_filter.h" +#include "dvb_i2c.h" +#include "dvb_net.h" + +#define DRIVER_NAME "TechnoTrend/Hauppauge DEC USB" + +#define COMMAND_PIPE 0x03 +#define RESULT_PIPE 0x84 +#define STREAM_PIPE 0x88 + +#define COMMAND_PACKET_SIZE 0x3c +#define ARM_PACKET_SIZE 0x1000 + +#define ISO_BUF_COUNT 0x04 +#define FRAMES_PER_ISO_BUF 0x04 +#define ISO_FRAME_SIZE 0x0380 + +#define MAX_AV_PES_LENGTH 6144 + +struct ttusb_dec { + /* DVB bits */ + struct dvb_adapter *adapter; + struct dmxdev dmxdev; + struct dvb_demux demux; + struct dmx_frontend frontend; + struct dvb_i2c_bus *i2c_bus; + struct dvb_net dvb_net; + + u16 pid[DMX_PES_OTHER]; + + /* USB bits */ + struct usb_device *udev; + u8 trans_count; + unsigned int command_pipe; + unsigned int result_pipe; + unsigned int stream_pipe; + int interface; + struct semaphore usb_sem; + + void *iso_buffer; + dma_addr_t iso_dma_handle; + struct urb *iso_urb[ISO_BUF_COUNT]; + int iso_stream_count; + struct semaphore iso_sem; + + u8 av_pes[MAX_AV_PES_LENGTH + 4]; + int av_pes_state; + int av_pes_length; + int av_pes_payload_length; + + struct dvb_filter_pes2ts a_pes2ts; + struct dvb_filter_pes2ts v_pes2ts; + struct semaphore pes2ts_sem; + + u8 v_pes[16 + MAX_AV_PES_LENGTH]; + int v_pes_length; + int v_pes_postbytes; +}; + +#endif diff -Nru a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig --- a/drivers/media/video/Kconfig Sat Jul 19 12:54:29 2003 +++ b/drivers/media/video/Kconfig Sat Jul 19 12:54:29 2003 @@ -257,5 +257,30 @@ whenever you want). If you want to compile it as a module, say M here and read . +config VIDEO_HEXIUM_ORION + tristate "Hexium HV-PCI6 and Orion frame grabber" + depends on VIDEO_DEV && PCI + ---help--- + This is a video4linux driver for the Hexium HV-PCI6 and + Orion frame grabber cards by Hexium. + + This driver is available as a module called hexium_orion + ( = code which can be inserted in and removed from the + running kernel whenever you want). If you want to compile + it as a module, say M here and read . + +config VIDEO_HEXIUM_GEMINI + tristate "Hexium Gemini frame grabber" + depends on VIDEO_DEV && PCI + ---help--- + This is a video4linux driver for the Hexium Gemini frame + grabber card by Hexium. Please note that the Gemini Dual + card is *not* fully supported. + + This driver is available as a module called hexium_gemini + ( = code which can be inserted in and removed from the + running kernel whenever you want). If you want to compile + it as a module, say M here and read . + endmenu diff -Nru a/drivers/media/video/Makefile b/drivers/media/video/Makefile --- a/drivers/media/video/Makefile Sat Jul 19 12:54:24 2003 +++ b/drivers/media/video/Makefile Sat Jul 19 12:54:24 2003 @@ -31,6 +31,8 @@ obj-$(CONFIG_VIDEO_MEYE) += meye.o obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ obj-$(CONFIG_VIDEO_MXB) += saa7111.o tuner.o tda9840.o tea6415c.o tea6420.o mxb.o +obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o +obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o obj-$(CONFIG_VIDEO_DPC) += saa7111.o dpc7146.o obj-$(CONFIG_TUNER_3036) += tuner-3036.o diff -Nru a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c --- a/drivers/media/video/dpc7146.c Sat Jul 19 12:54:24 2003 +++ b/drivers/media/video/dpc7146.c Sat Jul 19 12:54:24 2003 @@ -173,6 +173,8 @@ return 0; } +static struct saa7146_ext_vv vv_data; + /* this function only gets called when the probing was successful */ static int dpc_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) { @@ -183,7 +185,7 @@ /* checking for i2c-devices can be omitted here, because we already did this in "dpc_vl42_probe" */ - saa7146_vv_init(dev); + saa7146_vv_init(dev,&vv_data); if( 0 != saa7146_register_device(&dpc->video_dev, dev, "dpc", VFL_TYPE_GRABBER)) { ERR(("cannot register capture v4l2 device. skipping.\n")); return -1; @@ -246,8 +248,9 @@ } #endif -static int dpc_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) +static int dpc_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { + struct saa7146_dev *dev = fh->dev; struct dpc* dpc = (struct dpc*)dev->ext_priv; /* struct saa7146_vv *vv = dev->vv_data; @@ -307,23 +310,32 @@ } static struct saa7146_standard standard[] = { - { "PAL-BG", V4L2_STD_PAL_BG, SAA7146_PAL_VALUES }, - { "PAL-I", V4L2_STD_PAL_I, SAA7146_PAL_VALUES }, - { "NTSC", V4L2_STD_NTSC, SAA7146_NTSC_VALUES }, - { "SECAM", V4L2_STD_SECAM, SAA7146_SECAM_VALUES }, + { + .name = "PAL", .id = V4L2_STD_PAL, + .v_offset = 0x17, .v_field = 288, .v_calc = 576, + .h_offset = 0x14, .h_pixels = 680, .h_calc = 680+1, + .v_max_out = 576, .h_max_out = 768, + }, { + .name = "NTSC", .id = V4L2_STD_NTSC, + .v_offset = 0x16, .v_field = 240, .v_calc = 480, + .h_offset = 0x06, .h_pixels = 708, .h_calc = 708+1, + .v_max_out = 480, .h_max_out = 640, + }, { + .name = "SECAM", .id = V4L2_STD_SECAM, + .v_offset = 0x14, .v_field = 288, .v_calc = 576, + .h_offset = 0x14, .h_pixels = 720, .h_calc = 720+1, + .v_max_out = 576, .h_max_out = 768, + } }; -static -struct saa7146_extension extension; +static struct saa7146_extension extension; -static -struct saa7146_pci_extension_data dpc = { +static struct saa7146_pci_extension_data dpc = { .ext_priv = "Multimedia eXtension Board", .ext = &extension, }; -static -struct pci_device_id pci_tbl[] = { +static struct pci_device_id pci_tbl[] = { { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7146, @@ -337,8 +349,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); -static -struct saa7146_ext_vv vv_data = { +static struct saa7146_ext_vv vv_data = { .inputs = DPC_INPUTS, .capabilities = V4L2_CAP_VBI_CAPTURE, .stds = &standard[0], @@ -348,14 +359,12 @@ .ioctl = dpc_ioctl, }; -static -struct saa7146_extension extension = { +static struct saa7146_extension extension = { .name = "dpc7146 demonstration board", .flags = SAA7146_USE_I2C_IRQ, .pci_tbl = &pci_tbl[0], .module = THIS_MODULE, - .ext_vv_data = &vv_data, .probe = dpc_probe, .attach = dpc_attach, diff -Nru a/drivers/media/video/hexium.h b/drivers/media/video/hexium.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/video/hexium.h Sat Jul 19 12:54:30 2003 @@ -0,0 +1,51 @@ +#ifndef __HEXIUM__ +#define __HEXIUM__ + +#define HEXIUM_HV_PCI6_ORION 1 +#define HEXIUM_ORION_1SVHS_3BNC 2 +#define HEXIUM_ORION_4BNC 3 +#define HEXIUM_GEMUINI 4 +#define HEXIUM_GEMUINI_DUAL 5 + +static struct saa7146_standard hexium_standards[] = { + { + .name = "PAL", .id = V4L2_STD_PAL, + .v_offset = 0x17, .v_field = 288, .v_calc = 576, + .h_offset = 0x14, .h_pixels = 680, .h_calc = 680+1, + .v_max_out = 576, .h_max_out = 768, + }, { + .name = "NTSC", .id = V4L2_STD_NTSC, + .v_offset = 0x17, .v_field = 240, .v_calc = 480, + .h_offset = 0x06, .h_pixels = 640, .h_calc = 641+1, + .v_max_out = 480, .h_max_out = 640, + }, { + .name = "SECAM", .id = V4L2_STD_SECAM, + .v_offset = 0x14, .v_field = 288, .v_calc = 576, + .h_offset = 0x14, .h_pixels = 720, .h_calc = 720+1, + .v_max_out = 576, .h_max_out = 768, + } +}; + + +#define HEXIUM_INPUTS 9 +static struct v4l2_input hexium_inputs[HEXIUM_INPUTS] = { + { 0, "CVBS 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { 1, "CVBS 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { 2, "CVBS 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { 3, "CVBS 4", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { 4, "CVBS 5", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { 5, "CVBS 6", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { 6, "Y/C 1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { 7, "Y/C 2", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { 8, "Y/C 3", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, +}; + +#define HEXIUM_AUDIOS 0 + +struct hexium_data +{ + s8 adr; + u8 byte; +}; + +#endif diff -Nru a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/video/hexium_gemini.c Sat Jul 19 12:54:30 2003 @@ -0,0 +1,411 @@ +/* + hexium_gemini.c - v4l2 driver for Hexium Gemini frame grabber cards + + Visit http://www.mihu.de/linux/saa7146/ and follow the link + to "hexium" for further details about this card. + + Copyright (C) 2003 Michael Hunold + + 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 DEBUG_VARIABLE debug + +#include + +static int debug = 255; +MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "debug verbosity"); + +/* global variables */ +int hexium_num = 0; + +#include "hexium_gemini.h" + +/* bring hardware to a sane state. this has to be done, just in case someone + wants to capture from this device before it has been properly initialized. + the capture engine would badly fail, because no valid signal arrives on the + saa7146, thus leading to timeouts and stuff. */ +static int hexium_init_done(struct saa7146_dev *dev) +{ + struct hexium *hexium = (struct hexium *) dev->ext_priv; + union i2c_smbus_data data; + int i = 0; + + DEB_D(("hexium_init_done called.\n")); + + /* initialize the helper ics to useful values */ + for (i = 0; i < sizeof(hexium_ks0127b); i++) { + data.byte = hexium_ks0127b[i]; + if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) { + printk("failed for address 0x%02x\n", i); + } + } + + return 0; +} + +static int hexium_set_input(struct hexium *hexium, int input) +{ + union i2c_smbus_data data; + + DEB_D((".\n")); + + data.byte = hexium_input_select[input].byte; + if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, hexium_input_select[input].adr, I2C_SMBUS_BYTE_DATA, &data)) { + return -1; + } + + return 0; +} + +static int hexium_set_standard(struct hexium *hexium, struct hexium_data *vdec) +{ + union i2c_smbus_data data; + int i = 0; + + DEB_D((".\n")); + + while (vdec[i].adr != -1) { + data.byte = vdec[i].byte; + if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x6c, 0, I2C_SMBUS_WRITE, vdec[i].adr, I2C_SMBUS_BYTE_DATA, &data)) { + printk("failed for address 0x%02x\n", i); + return -1; + } + i++; + } + return 0; +} + +static struct saa7146_ext_vv vv_data; + +/* this function only gets called when the probing was successful */ +static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) +{ + struct hexium *hexium = (struct hexium *) dev->ext_priv; + + DEB_EE((".\n")); + + hexium = (struct hexium *) kmalloc(sizeof(struct hexium), GFP_KERNEL); + if (NULL == hexium) { + printk("hexium_v4l2.o: hexium_probe: not enough kernel memory.\n"); + return -ENOMEM; + } + memset(hexium, 0x0, sizeof(struct hexium)); + (struct hexium *) dev->ext_priv = hexium; + + /* FIXME: enable i2c-port pins, video-port-pins + video port pins should be enabled here ?! */ + saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26)); + + saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); + if (i2c_add_adapter(&hexium->i2c_adapter) < 0) { + DEB_S(("cannot register i2c-device. skipping.\n")); + kfree(hexium); + return -EFAULT; + } + + /* set HWControl GPIO number 2 */ + saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); + + saa7146_write(dev, DD1_INIT, 0x07000700); + saa7146_write(dev, DD1_STREAM_B, 0x00000000); + saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); + + /* the rest */ + hexium->cur_input = 0; + hexium_init_done(dev); + + hexium_set_standard(hexium, hexium_pal); + hexium->cur_std = V4L2_STD_PAL; + + hexium_set_input(hexium, 0); + hexium->cur_input = 0; + + saa7146_vv_init(dev, &vv_data); + if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium", VFL_TYPE_GRABBER)) { + ERR(("cannot register capture v4l2 device. skipping.\n")); + return -1; + } + + printk("hexium: found 'hexium frame grabber'-%d.\n", hexium_num); + hexium_num++; + + return 0; +} + +static int hexium_detach(struct saa7146_dev *dev) +{ + struct hexium *hexium = (struct hexium *) dev->ext_priv; + + DEB_EE(("dev:%p\n", dev)); + + saa7146_unregister_device(&hexium->video_dev, dev); + saa7146_vv_release(dev); + + hexium_num--; + + i2c_del_adapter(&hexium->i2c_adapter); + kfree(hexium); + return 0; +} + +static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) +{ + struct saa7146_dev *dev = fh->dev; + struct hexium *hexium = (struct hexium *) dev->ext_priv; +/* + struct saa7146_vv *vv = dev->vv_data; +*/ + switch (cmd) { + case VIDIOC_ENUMINPUT: + { + struct v4l2_input *i = arg; + DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index)); + + if (i->index < 0 || i->index >= HEXIUM_INPUTS) { + return -EINVAL; + } + + memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input)); + + DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index)); + return 0; + } + case VIDIOC_G_INPUT: + { + int *input = (int *) arg; + *input = hexium->cur_input; + + DEB_D(("VIDIOC_G_INPUT: %d\n", *input)); + return 0; + } + case VIDIOC_S_INPUT: + { + int input = *(int *) arg; + + DEB_EE(("VIDIOC_S_INPUT %d.\n", input)); + + if (input < 0 || input >= HEXIUM_INPUTS) { + return -EINVAL; + } + + hexium->cur_input = input; + hexium_set_input(hexium, input); + + return 0; + } + /* the saa7146 provides some controls (brightness, contrast, saturation) + which gets registered *after* this function. because of this we have + to return with a value != 0 even if the function succeded.. */ + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *qc = arg; + int i; + + for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) { + if (hexium_controls[i].id == qc->id) { + *qc = hexium_controls[i]; + DEB_D(("VIDIOC_QUERYCTRL %d.\n", qc->id)); + return 0; + } + } + return -EAGAIN; + } + case VIDIOC_G_CTRL: + { + struct v4l2_control *vc = arg; + int i; + + for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) { + if (hexium_controls[i].id == vc->id) { + break; + } + } + + if (i < 0) { + return -EAGAIN; + } + + switch (vc->id) { + case V4L2_CID_PRIVATE_BASE:{ + vc->value = hexium->cur_bw; + DEB_D(("VIDIOC_G_CTRL BW:%d.\n", vc->value)); + return 0; + } + } + return -EINVAL; + } + + case VIDIOC_S_CTRL: + { + struct v4l2_control *vc = arg; + int i = 0; + + for (i = HEXIUM_CONTROLS - 1; i >= 0; i--) { + if (hexium_controls[i].id == vc->id) { + break; + } + } + + if (i < 0) { + return -EAGAIN; + } + + switch (vc->id) { + case V4L2_CID_PRIVATE_BASE:{ + hexium->cur_bw = vc->value; + break; + } + } + + DEB_D(("VIDIOC_S_CTRL BW:%d.\n", hexium->cur_bw)); + + if (0 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) { + hexium_set_standard(hexium, hexium_pal); + return 0; + } + if (0 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) { + hexium_set_standard(hexium, hexium_ntsc); + return 0; + } + if (0 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) { + hexium_set_standard(hexium, hexium_secam); + return 0; + } + if (1 == hexium->cur_bw && V4L2_STD_PAL == hexium->cur_std) { + hexium_set_standard(hexium, hexium_pal_bw); + return 0; + } + if (1 == hexium->cur_bw && V4L2_STD_NTSC == hexium->cur_std) { + hexium_set_standard(hexium, hexium_ntsc_bw); + return 0; + } + if (1 == hexium->cur_bw && V4L2_STD_SECAM == hexium->cur_std) { + /* fixme: is there no bw secam mode? */ + return -EINVAL; + } + + return -EINVAL; + } + default: +/* + DEB_D(("v4l2_ioctl does not handle this ioctl.\n")); +*/ + return -ENOIOCTLCMD; + } + return 0; +} + +static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std) +{ + struct hexium *hexium = (struct hexium *) dev->ext_priv; + + if (V4L2_STD_PAL == std->id) { + hexium_set_standard(hexium, hexium_pal); + hexium->cur_std = V4L2_STD_PAL; + return 0; + } else if (V4L2_STD_NTSC == std->id) { + hexium_set_standard(hexium, hexium_ntsc); + hexium->cur_std = V4L2_STD_NTSC; + return 0; + } else if (V4L2_STD_SECAM == std->id) { + hexium_set_standard(hexium, hexium_secam); + hexium->cur_std = V4L2_STD_SECAM; + return 0; + } + + return -1; +} + +static struct saa7146_extension hexium_extension; + +static struct saa7146_pci_extension_data hexium_gemini_4bnc = { + .ext_priv = "Hexium Gemini (4 BNC)", + .ext = &hexium_extension, +}; + +static struct saa7146_pci_extension_data hexium_gemini_dual_4bnc = { + .ext_priv = "Hexium Gemini Dual (4 BNC)", + .ext = &hexium_extension, +}; + +static struct pci_device_id pci_tbl[] = { + { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7146, + .subvendor = 0x17c8, + .subdevice = 0x2401, + .driver_data = (unsigned long) &hexium_gemini_4bnc, + }, + { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7146, + .subvendor = 0x17c8, + .subdevice = 0x2402, + .driver_data = (unsigned long) &hexium_gemini_dual_4bnc, + }, + { + .vendor = 0, + } +}; + +MODULE_DEVICE_TABLE(pci, pci_tbl); + +static struct saa7146_ext_vv vv_data = { + .inputs = HEXIUM_INPUTS, + .capabilities = 0, + .stds = &hexium_standards[0], + .num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard), + .std_callback = &std_callback, + .ioctls = &ioctls[0], + .ioctl = hexium_ioctl, +}; + +static struct saa7146_extension hexium_extension = { + .name = "hexium gemini", + .flags = SAA7146_USE_I2C_IRQ, + + .pci_tbl = &pci_tbl[0], + .module = THIS_MODULE, + + .attach = hexium_attach, + .detach = hexium_detach, + + .irq_mask = 0, + .irq_func = NULL, +}; + +int __init hexium_init_module(void) +{ + if (0 != saa7146_register_extension(&hexium_extension)) { + DEB_S(("failed to register extension.\n")); + return -ENODEV; + } + + return 0; +} + +void __exit hexium_cleanup_module(void) +{ + saa7146_unregister_extension(&hexium_extension); +} + +module_init(hexium_init_module); +module_exit(hexium_cleanup_module); + +MODULE_DESCRIPTION("video4linux-2 driver for Hexium Gemini frame grabber cards"); +MODULE_AUTHOR("Michael Hunold "); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/media/video/hexium_gemini.h b/drivers/media/video/hexium_gemini.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/video/hexium_gemini.h Sat Jul 19 12:54:30 2003 @@ -0,0 +1,103 @@ +#ifndef __HEXIUM_GEMINI__ +#define __HEXIUM_GEMINI__ + +#include "hexium.h" + +static struct saa7146_extension_ioctls ioctls[] = { + { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE }, + { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE }, + { VIDIOC_QUERYCTRL, SAA7146_BEFORE }, + { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE }, + { VIDIOC_S_STD, SAA7146_AFTER }, + { VIDIOC_G_CTRL, SAA7146_BEFORE }, + { VIDIOC_S_CTRL, SAA7146_BEFORE }, + { 0, 0 } +}; + +#define HEXIUM_CONTROLS 1 +static struct v4l2_queryctrl hexium_controls[] = { + { V4L2_CID_PRIVATE_BASE, V4L2_CTRL_TYPE_BOOLEAN, "B/W", 0, 1, 1, 0, 0 }, +}; + +#define HEXIUM_GEMUINI_V_1_0 1 +#define HEXIUM_GEMUINI_DUAL_V_1_0 2 + +struct hexium +{ + int type; + struct video_device video_dev; + struct i2c_adapter i2c_adapter; + + int cur_input; /* current input */ + v4l2_std_id cur_std; /* current standard */ + int cur_bw; /* current black/white status */ +}; + +/* Samsung KS0127B decoder default registers */ +static u8 hexium_ks0127b[0x100]={ +/*00*/ 0x00,0x52,0x30,0x40,0x01,0x0C,0x2A,0x10, +/*08*/ 0x00,0x00,0x00,0x60,0x00,0x00,0x0F,0x06, +/*10*/ 0x00,0x00,0xE4,0xC0,0x00,0x00,0x00,0x00, +/*18*/ 0x14,0x9B,0xFE,0xFF,0xFC,0xFF,0x03,0x22, +/*20*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*28*/ 0x00,0x00,0x00,0x00,0x00,0x2C,0x9B,0x00, +/*30*/ 0x00,0x00,0x10,0x80,0x80,0x10,0x80,0x80, +/*38*/ 0x01,0x04,0x00,0x00,0x00,0x29,0xC0,0x00, +/*40*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*48*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*50*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*58*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*60*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*68*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*70*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*78*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*80*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*88*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*90*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*98*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*A0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*A8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*B0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*B8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*C0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*C8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*D0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*D8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*E0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*E8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*F0*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*F8*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +}; + +static struct hexium_data hexium_pal[] = { + { 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF } +}; + +static struct hexium_data hexium_pal_bw[] = { + { 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF } +}; + +static struct hexium_data hexium_ntsc[] = { + { 0x01, 0x53 }, { 0x12, 0x04 }, { 0x2D, 0x23 }, { 0x2E, 0x81 }, { -1 , 0xFF } +}; + +static struct hexium_data hexium_ntsc_bw[] = { + { 0x01, 0x53 }, { 0x12, 0x04 }, { 0x2D, 0x23 }, { 0x2E, 0x81 }, { -1 , 0xFF } +}; + +static struct hexium_data hexium_secam[] = { + { 0x01, 0x52 }, { 0x12, 0x64 }, { 0x2D, 0x2C }, { 0x2E, 0x9B }, { -1 , 0xFF } +}; + +static struct hexium_data hexium_input_select[] = { + { 0x02, 0x60 }, + { 0x02, 0x64 }, + { 0x02, 0x61 }, + { 0x02, 0x65 }, + { 0x02, 0x62 }, + { 0x02, 0x66 }, + { 0x02, 0x68 }, + { 0x02, 0x69 }, + { 0x02, 0x6A }, +}; +#endif diff -Nru a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/video/hexium_orion.c Sat Jul 19 12:54:30 2003 @@ -0,0 +1,328 @@ +/* + hexium_orion.c - v4l2 driver for the Hexium Orion frame grabber cards + + Visit http://www.mihu.de/linux/saa7146/ and follow the link + to "hexium" for further details about this card. + + Copyright (C) 2003 Michael Hunold + + 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 DEBUG_VARIABLE debug + +#include + +static int debug = 255; +MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "debug verbosity"); + +/* global variables */ +int hexium_num = 0; + +#include "hexium_orion.h" + +/* this is only called for old HV-PCI6/Orion cards + without eeprom */ +static int hexium_probe(struct saa7146_dev *dev) +{ + struct hexium *hexium = 0; + union i2c_smbus_data data; + int err = 0; + + DEB_EE((".\n")); + + /* there are no hexium orion cards with revision 0 saa7146s */ + if (0 == dev->revision) { + return -EFAULT; + } + + hexium = (struct hexium *) kmalloc(sizeof(struct hexium), GFP_KERNEL); + if (NULL == hexium) { + printk("hexium_orion.o: hexium_probe: not enough kernel memory.\n"); + return -ENOMEM; + } + memset(hexium, 0x0, sizeof(struct hexium)); + + /* FIXME: enable i2c-port pins, video-port-pins + video port pins should be enabled here ?! */ + saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26)); + + saa7146_write(dev, DD1_INIT, 0x02000200); + saa7146_write(dev, DD1_STREAM_B, 0x00000000); + saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); + + saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); + if (i2c_add_adapter(&hexium->i2c_adapter) < 0) { + DEB_S(("cannot register i2c-device. skipping.\n")); + kfree(hexium); + return -EFAULT; + } + + /* set SAA7110 control GPIO 0 */ + saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI); + /* set HWControl GPIO number 2 */ + saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); + + mdelay(10); + + /* detect newer Hexium Orion cards by subsystem ids */ + if (0x17c8 == dev->pci->subsystem_vendor && 0x0101 == dev->pci->subsystem_device) { + printk("hexium_orion.o: device is a Hexium Orion w/ 1 SVHS + 3 BNC inputs.\n"); + /* we store the pointer in our private data field */ + (struct hexium *) dev->ext_priv = hexium; + hexium->type = HEXIUM_ORION_1SVHS_3BNC; + return 0; + } + + if (0x17c8 == dev->pci->subsystem_vendor && 0x2101 == dev->pci->subsystem_device) { + printk("hexium_orion.o: device is a Hexium Orion w/ 4 BNC inputs.\n"); + /* we store the pointer in our private data field */ + (struct hexium *) dev->ext_priv = hexium; + hexium->type = HEXIUM_ORION_4BNC; + return 0; + } + + /* check if this is an old hexium Orion card by looking at + a saa7110 at address 0x4e */ + if (0 == (err = i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_READ, 0x00, I2C_SMBUS_BYTE_DATA, &data))) { + printk("hexium_orion.o: device is a Hexium HV-PCI6/Orion (old).\n"); + /* we store the pointer in our private data field */ + (struct hexium *) dev->ext_priv = hexium; + hexium->type = HEXIUM_HV_PCI6_ORION; + return 0; + } + + i2c_del_adapter(&hexium->i2c_adapter); + kfree(hexium); + return -EFAULT; +} + +/* bring hardware to a sane state. this has to be done, just in case someone + wants to capture from this device before it has been properly initialized. + the capture engine would badly fail, because no valid signal arrives on the + saa7146, thus leading to timeouts and stuff. */ +static int hexium_init_done(struct saa7146_dev *dev) +{ + struct hexium *hexium = (struct hexium *) dev->ext_priv; + union i2c_smbus_data data; + int i = 0; + + DEB_D(("hexium_init_done called.\n")); + + /* initialize the helper ics to useful values */ + for (i = 0; i < sizeof(hexium_saa7110); i++) { + data.byte = hexium_saa7110[i]; + if (0 != i2c_smbus_xfer(&hexium->i2c_adapter, 0x4e, 0, I2C_SMBUS_WRITE, i, I2C_SMBUS_BYTE_DATA, &data)) { + printk("hexium_orion: failed for address 0x%02x\n", i); + } + } + + return 0; +} + +static struct saa7146_ext_vv vv_data; + +/* this function only gets called when the probing was successful */ +static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) +{ + struct hexium *hexium = (struct hexium *) dev->ext_priv; + + DEB_EE((".\n")); + + saa7146_vv_init(dev, &vv_data); + if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium", VFL_TYPE_GRABBER)) { + ERR(("cannot register capture v4l2 device. skipping.\n")); + return -1; + } + + printk("hexium_orion.o: found 'hexium orion' frame grabber-%d.\n", hexium_num); + hexium_num++; + + /* the rest */ + hexium->cur_input = 0; + hexium_init_done(dev); + + return 0; +} + +static int hexium_detach(struct saa7146_dev *dev) +{ + struct hexium *hexium = (struct hexium *) dev->ext_priv; + + DEB_EE(("dev:%p\n", dev)); + + saa7146_unregister_device(&hexium->video_dev, dev); + saa7146_vv_release(dev); + + hexium_num--; + + i2c_del_adapter(&hexium->i2c_adapter); + kfree(hexium); + return 0; +} + +static int hexium_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) +{ + struct saa7146_dev *dev = fh->dev; + struct hexium *hexium = (struct hexium *) dev->ext_priv; +/* + struct saa7146_vv *vv = dev->vv_data; +*/ + switch (cmd) { + case VIDIOC_ENUMINPUT: + { + struct v4l2_input *i = arg; + DEB_EE(("VIDIOC_ENUMINPUT %d.\n", i->index)); + + if (i->index < 0 || i->index >= HEXIUM_INPUTS) { + return -EINVAL; + } + + memcpy(i, &hexium_inputs[i->index], sizeof(struct v4l2_input)); + + DEB_D(("v4l2_ioctl: VIDIOC_ENUMINPUT %d.\n", i->index)); + return 0; + } + case VIDIOC_G_INPUT: + { + int *input = (int *) arg; + *input = hexium->cur_input; + + DEB_D(("VIDIOC_G_INPUT: %d\n", *input)); + return 0; + } + case VIDIOC_S_INPUT: + { + int input = *(int *) arg; + + if (input < 0 || input >= HEXIUM_INPUTS) { + return -EINVAL; + } + + hexium->cur_input = input; + + /* fixme: switch input here, switch audio, too! */ +// saa7146_set_hps_source_and_sync(dev, input_port_selection[input].hps_source, input_port_selection[input].hps_sync); + printk("hexium_orion.o: VIDIOC_S_INPUT: fixme switch input.\n"); + + return 0; + } + default: +/* + DEB_D(("v4l2_ioctl does not handle this ioctl.\n")); +*/ + return -ENOIOCTLCMD; + } + return 0; +} + +static int std_callback(struct saa7146_dev *dev, struct saa7146_standard *std) +{ + return 0; +} + +static struct saa7146_extension extension; + +static struct saa7146_pci_extension_data hexium_hv_pci6 = { + .ext_priv = "Hexium HV-PCI6 / Orion", + .ext = &extension, +}; + +static struct saa7146_pci_extension_data hexium_orion_1svhs_3bnc = { + .ext_priv = "Hexium HV-PCI6 / Orion (1 SVHS/3 BNC)", + .ext = &extension, +}; + +static struct saa7146_pci_extension_data hexium_orion_4bnc = { + .ext_priv = "Hexium HV-PCI6 / Orion (4 BNC)", + .ext = &extension, +}; + +static struct pci_device_id pci_tbl[] = { + { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7146, + .subvendor = 0x0000, + .subdevice = 0x0000, + .driver_data = (unsigned long) &hexium_hv_pci6, + }, + { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7146, + .subvendor = 0x17c8, + .subdevice = 0x0101, + .driver_data = (unsigned long) &hexium_orion_1svhs_3bnc, + }, + { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7146, + .subvendor = 0x17c8, + .subdevice = 0x2101, + .driver_data = (unsigned long) &hexium_orion_4bnc, + }, + { + .vendor = 0, + } +}; + +MODULE_DEVICE_TABLE(pci, pci_tbl); + +static struct saa7146_ext_vv vv_data = { + .inputs = HEXIUM_INPUTS, + .capabilities = 0, + .stds = &hexium_standards[0], + .num_stds = sizeof(hexium_standards) / sizeof(struct saa7146_standard), + .std_callback = &std_callback, + .ioctls = &ioctls[0], + .ioctl = hexium_ioctl, +}; + +static struct saa7146_extension extension = { + .name = "hexium HV-PCI6/Orion", + .flags = 0, // SAA7146_USE_I2C_IRQ, + + .pci_tbl = &pci_tbl[0], + .module = THIS_MODULE, + + .probe = hexium_probe, + .attach = hexium_attach, + .detach = hexium_detach, + + .irq_mask = 0, + .irq_func = NULL, +}; + +int __init hexium_init_module(void) +{ + if (0 != saa7146_register_extension(&extension)) { + DEB_S(("failed to register extension.\n")); + return -ENODEV; + } + + return 0; +} + +void __exit hexium_cleanup_module(void) +{ + saa7146_unregister_extension(&extension); +} + +module_init(hexium_init_module); +module_exit(hexium_cleanup_module); + +MODULE_DESCRIPTION("video4linux-2 driver for Hexium Orion frame grabber cards"); +MODULE_AUTHOR("Michael Hunold "); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/media/video/hexium_orion.h b/drivers/media/video/hexium_orion.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/video/hexium_orion.h Sat Jul 19 12:54:30 2003 @@ -0,0 +1,138 @@ +#ifndef __HEXIUM_ORION__ +#define __HEXIUM_ORION__ + +#include "hexium.h" + +static struct saa7146_extension_ioctls ioctls[] = { + { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE }, + { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE }, + { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE }, + { VIDIOC_S_STD, SAA7146_AFTER }, + { 0, 0 } +}; + +struct hexium +{ + int type; + struct video_device video_dev; + struct i2c_adapter i2c_adapter; + int cur_input; /* current input */ +}; + +/* Philips SAA7110 decoder default registers */ +static u8 hexium_saa7110[53]={ +/*00*/ 0x4C,0x3C,0x0D,0xEF,0xBD,0xF0,0x00,0x00, +/*08*/ 0xF8,0xF8,0x60,0x60,0x40,0x86,0x18,0x90, +/*10*/ 0x00,0x2C,0x40,0x46,0x42,0x1A,0xFF,0xDA, +/*18*/ 0xF0,0x8B,0x00,0x00,0x00,0x00,0x00,0x00, +/*20*/ 0xD9,0x17,0x40,0x41,0x80,0x41,0x80,0x4F, +/*28*/ 0xFE,0x01,0x0F,0x0F,0x03,0x01,0x81,0x03, +/*30*/ 0x44,0x75,0x01,0x8C,0x03 +}; + +static struct { + struct hexium_data data[8]; +} hexium_input_select[] = { +{ + { /* input 0 */ + { 0x06, 0x00 }, + { 0x20, 0xD9 }, + { 0x21, 0x17 }, // 0x16, + { 0x22, 0x40 }, + { 0x2C, 0x03 }, + { 0x30, 0x44 }, + { 0x31, 0x75 }, // ?? + { 0x21, 0x16 }, // 0x03, + } +}, { + { /* input 1 */ + { 0x06, 0x00 }, + { 0x20, 0xD8 }, + { 0x21, 0x17 }, // 0x16, + { 0x22, 0x40 }, + { 0x2C, 0x03 }, + { 0x30, 0x44 }, + { 0x31, 0x75 }, // ?? + { 0x21, 0x16 }, // 0x03, + } +}, { + { /* input 2 */ + { 0x06, 0x00 }, + { 0x20, 0xBA }, + { 0x21, 0x07 }, // 0x05, + { 0x22, 0x91 }, + { 0x2C, 0x03 }, + { 0x30, 0x60 }, + { 0x31, 0xB5 }, // ?? + { 0x21, 0x05 }, // 0x03, + } +}, { + { /* input 3 */ + { 0x06, 0x00 }, + { 0x20, 0xB8 }, + { 0x21, 0x07 }, // 0x05, + { 0x22, 0x91 }, + { 0x2C, 0x03 }, + { 0x30, 0x60 }, + { 0x31, 0xB5 }, // ?? + { 0x21, 0x05 }, // 0x03, + } +}, { + { /* input 4 */ + { 0x06, 0x00 }, + { 0x20, 0x7C }, + { 0x21, 0x07 }, // 0x03 + { 0x22, 0xD2 }, + { 0x2C, 0x83 }, + { 0x30, 0x60 }, + { 0x31, 0xB5 }, // ?? + { 0x21, 0x03 }, + } +}, { + { /* input 5 */ + { 0x06, 0x00 }, + { 0x20, 0x78 }, + { 0x21, 0x07 }, // 0x03, + { 0x22, 0xD2 }, + { 0x2C, 0x83 }, + { 0x30, 0x60 }, + { 0x31, 0xB5 }, // ? + { 0x21, 0x03 }, + } +}, { + { /* input 6 */ + { 0x06, 0x80 }, + { 0x20, 0x59 }, + { 0x21, 0x17 }, + { 0x22, 0x42 }, + { 0x2C, 0xA3 }, + { 0x30, 0x44 }, + { 0x31, 0x75 }, + { 0x21, 0x12 }, + } +}, { + { /* input 7 */ + { 0x06, 0x80 }, + { 0x20, 0x9A }, + { 0x21, 0x17 }, + { 0x22, 0xB1 }, + { 0x2C, 0x13 }, + { 0x30, 0x60 }, + { 0x31, 0xB5 }, + { 0x21, 0x14 }, + } +}, { + { /* input 8 */ + { 0x06, 0x80 }, + { 0x20, 0x3C }, + { 0x21, 0x27 }, + { 0x22, 0xC1 }, + { 0x2C, 0x23 }, + { 0x30, 0x44 }, + { 0x31, 0x75 }, + { 0x21, 0x21 }, + } +} +}; + +#endif diff -Nru a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c --- a/drivers/media/video/mxb.c Sat Jul 19 12:54:22 2003 +++ b/drivers/media/video/mxb.c Sat Jul 19 12:54:22 2003 @@ -81,7 +81,7 @@ enum { TUNER, AUX1, AUX3, AUX3_YC }; static struct v4l2_input mxb_inputs[MXB_INPUTS] = { - { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 1, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, + { TUNER, "Tuner", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, { AUX1, "AUX1", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, { AUX3, "AUX3 Composite", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, { AUX3_YC, "AUX3 S-Video", V4L2_INPUT_TYPE_CAMERA, 4, 0, V4L2_STD_PAL_BG|V4L2_STD_NTSC_M, 0 }, @@ -101,8 +101,8 @@ /* this array holds the information of the audio source (mxb_audios), which has to be switched corresponding to the video source (mxb_channels) */ -static int video_audio_connect[MXB_AUDIOS] = - { 0, 1, 2, 3, 3 }; +static int video_audio_connect[MXB_INPUTS] = + { 0, 1, 3, 3 }; /* these are the necessary input-output-pins for bringing one audio source (see above) to the CD-output */ @@ -173,8 +173,7 @@ int cur_mute; /* current mute status */ }; -static -struct saa7146_extension extension; +static struct saa7146_extension extension; static int mxb_vbi_bypass(struct saa7146_dev* dev) { @@ -431,10 +430,11 @@ polling method ... */ extension.flags &= ~SAA7146_USE_I2C_IRQ; for(i = 1;;i++) { - msg.len = mxb_saa7740_init[i].length; - if (msg.len == -1U) { + if( -1 == mxb_saa7740_init[i].length ) { break; } + + msg.len = mxb_saa7740_init[i].length; msg.buf = &mxb_saa7740_init[i].data[0]; if( 1 != (err = i2c_transfer(&mxb->i2c_adapter, &msg, 1))) { DEB_D(("failed to initialize 'sound arena module'.\n")); @@ -472,6 +472,8 @@ } */ +static struct saa7146_ext_vv vv_data; + /* this function only gets called when the probing was successful */ static int mxb_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) { @@ -482,7 +484,7 @@ /* checking for i2c-devices can be omitted here, because we already did this in "mxb_vl42_probe" */ - saa7146_vv_init(dev); + saa7146_vv_init(dev,&vv_data); if( 0 != saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) { ERR(("cannot register capture v4l2 device. skipping.\n")); return -1; @@ -566,8 +568,9 @@ return 0; } -static int mxb_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) +static int mxb_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg) { + struct saa7146_dev *dev = fh->dev; struct mxb* mxb = (struct mxb*)dev->ext_priv; struct saa7146_vv *vv = dev->vv_data; @@ -1002,20 +1005,35 @@ } static struct saa7146_standard standard[] = { - { "PAL-BG", V4L2_STD_PAL_BG, SAA7146_PAL_VALUES }, - { "PAL-I", V4L2_STD_PAL_I, SAA7146_PAL_VALUES }, - { "NTSC", V4L2_STD_NTSC, SAA7146_NTSC_VALUES }, - { "SECAM", V4L2_STD_SECAM, SAA7146_SECAM_VALUES }, + { + .name = "PAL-BG", .id = V4L2_STD_PAL_BG, + .v_offset = 0x17, .v_field = 288, .v_calc = 576, + .h_offset = 0x14, .h_pixels = 680, .h_calc = 680+1, + .v_max_out = 576, .h_max_out = 768, + }, { + .name = "PAL-I", .id = V4L2_STD_PAL_I, + .v_offset = 0x17, .v_field = 288, .v_calc = 576, + .h_offset = 0x14, .h_pixels = 680, .h_calc = 680+1, + .v_max_out = 576, .h_max_out = 768, + }, { + .name = "NTSC", .id = V4L2_STD_NTSC, + .v_offset = 0x16, .v_field = 240, .v_calc = 480, + .h_offset = 0x06, .h_pixels = 708, .h_calc = 708+1, + .v_max_out = 480, .h_max_out = 640, + }, { + .name = "SECAM", .id = V4L2_STD_SECAM, + .v_offset = 0x14, .v_field = 288, .v_calc = 576, + .h_offset = 0x14, .h_pixels = 720, .h_calc = 720+1, + .v_max_out = 576, .h_max_out = 768, + } }; -static -struct saa7146_pci_extension_data mxb = { +static struct saa7146_pci_extension_data mxb = { .ext_priv = "Multimedia eXtension Board", .ext = &extension, }; -static -struct pci_device_id pci_tbl[] = { +static struct pci_device_id pci_tbl[] = { { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7146, @@ -1029,8 +1047,7 @@ MODULE_DEVICE_TABLE(pci, pci_tbl); -static -struct saa7146_ext_vv vv_data = { +static struct saa7146_ext_vv vv_data = { .inputs = MXB_INPUTS, .capabilities = V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE, .stds = &standard[0], @@ -1040,14 +1057,12 @@ .ioctl = mxb_ioctl, }; -static -struct saa7146_extension extension = { +static struct saa7146_extension extension = { .name = MXB_IDENTIFIER, .flags = SAA7146_USE_I2C_IRQ, .pci_tbl = &pci_tbl[0], .module = THIS_MODULE, - .ext_vv_data = &vv_data, .probe = mxb_probe, .attach = mxb_attach, diff -Nru a/drivers/media/video/pms.c b/drivers/media/video/pms.c --- a/drivers/media/video/pms.c Sat Jul 19 12:54:27 2003 +++ b/drivers/media/video/pms.c Sat Jul 19 12:54:27 2003 @@ -12,6 +12,10 @@ * Most of this code is directly derived from his userspace driver. * His driver works so send any reports to alan@redhat.com unless the * userspace driver also doesn't work for you... + * + * Changes: + * 08/07/2003 Daniele Bellucci + * - pms_capture: report back -EFAULT */ #include @@ -659,7 +663,8 @@ if(dt+len>count) dt=count-len; cnt += dev->height; - copy_to_user(buf, tmp+32, dt); + if (copy_to_user(buf, tmp+32, dt)) + return -EFAULT; buf += dt; len += dt; } diff -Nru a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c --- a/drivers/message/fusion/mptctl.c Sat Jul 19 12:54:21 2003 +++ b/drivers/message/fusion/mptctl.c Sat Jul 19 12:54:21 2003 @@ -88,7 +88,6 @@ #include /* needed for access to Scsi_Host struct */ #include -#include /* for io_request_lock (spinlock) decl */ #include "../../scsi/scsi.h" #include "../../scsi/hosts.h" diff -Nru a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c --- a/drivers/message/fusion/mptscsih.c Sat Jul 19 12:54:24 2003 +++ b/drivers/message/fusion/mptscsih.c Sat Jul 19 12:54:24 2003 @@ -72,7 +72,6 @@ #include #include #include -#include /* for io_request_lock (spinlock) decl */ #include /* for mdelay */ #include /* needed for in_interrupt() proto */ #include /* notifier code */ diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c --- a/drivers/message/i2o/i2o_block.c Sat Jul 19 12:54:26 2003 +++ b/drivers/message/i2o/i2o_block.c Sat Jul 19 12:54:26 2003 @@ -87,8 +87,6 @@ #define MAJOR_NR I2O_MAJOR -#include - #define MAX_I2OB 16 #define MAX_I2OB_DEPTH 8 diff -Nru a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c --- a/drivers/message/i2o/i2o_scsi.c Sat Jul 19 12:54:26 2003 +++ b/drivers/message/i2o/i2o_scsi.c Sat Jul 19 12:54:26 2003 @@ -54,7 +54,7 @@ #include #include #include -#include +#include #include #include "../../scsi/scsi.h" #include "../../scsi/hosts.h" diff -Nru a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c --- a/drivers/mtd/mtd_blkdevs.c Sat Jul 19 12:54:21 2003 +++ b/drivers/mtd/mtd_blkdevs.c Sat Jul 19 12:54:21 2003 @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig --- a/drivers/net/Kconfig Sat Jul 19 12:54:27 2003 +++ b/drivers/net/Kconfig Sat Jul 19 12:54:27 2003 @@ -1153,7 +1153,7 @@ config SEEQ8005 tristate "SEEQ8005 support (EXPERIMENTAL)" - depends on NET_ISA && OBSOLETE && EXPERIMENTAL + depends on NET_ISA && EXPERIMENTAL help This is a driver for the SEEQ 8005 network (Ethernet) card. If this is for you, read the Ethernet-HOWTO, available from diff -Nru a/drivers/net/eql.c b/drivers/net/eql.c --- a/drivers/net/eql.c Sat Jul 19 12:54:27 2003 +++ b/drivers/net/eql.c Sat Jul 19 12:54:27 2003 @@ -162,22 +162,12 @@ static char version[] __initdata = "Equalizer2002: Simon Janes (simon@ncm.com) and David S. Miller (davem@redhat.com)\n"; -static int __init eql_init(struct net_device *dev) +static void __init eql_setup(struct net_device *dev) { - static unsigned int version_printed; - equalizer_t *eql; + equalizer_t *eql = dev->priv; SET_MODULE_OWNER(dev); - if (version_printed++ == 0) - printk(version); - - dev->priv = kmalloc(sizeof (equalizer_t), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof (equalizer_t)); - eql = dev->priv; - init_timer(&eql->timer); eql->timer.data = (unsigned long) dev->priv; eql->timer.expires = jiffies + EQL_DEFAULT_RESCHED_IVAL; @@ -203,8 +193,6 @@ dev->type = ARPHRD_SLIP; dev->tx_queue_len = 5; /* Hands them off fast */ - - return 0; } static int eql_open(struct net_device *dev) @@ -598,23 +586,28 @@ return -EINVAL; } -static struct net_device dev_eql; +static struct net_device *dev_eql; static int __init eql_init_module(void) { - strcpy(dev_eql.name, "eql"); - dev_eql.init = eql_init; - if (register_netdev(&dev_eql) != 0) { - printk("eql: register_netdev() returned non-zero.\n"); - return -EIO; - } - return 0; + int err; + + printk(version); + + dev_eql = alloc_netdev(sizeof(equalizer_t), "eql", eql_setup); + if (!dev_eql) + return -ENOMEM; + + err = register_netdev(dev_eql); + if (err) + kfree(dev_eql); + return err; } static void __exit eql_cleanup_module(void) { - kfree(dev_eql.priv); - unregister_netdev(&dev_eql); + unregister_netdev(dev_eql); + kfree(dev_eql); } module_init(eql_init_module); diff -Nru a/drivers/net/fc/iph5526.c b/drivers/net/fc/iph5526.c --- a/drivers/net/fc/iph5526.c Sat Jul 19 12:54:23 2003 +++ b/drivers/net/fc/iph5526.c Sat Jul 19 12:54:23 2003 @@ -48,7 +48,6 @@ #include #include #include -#include #include /* had the declarations for init_fcdev among others + includes if_fcdevice.h */ diff -Nru a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c --- a/drivers/net/irda/vlsi_ir.c Sat Jul 19 12:54:21 2003 +++ b/drivers/net/irda/vlsi_ir.c Sat Jul 19 12:54:21 2003 @@ -474,10 +474,8 @@ if (pos + nbytes > size) nbytes = size - pos; - if (!access_ok(VERIFY_WRITE, buf, nbytes)) - return -EINVAL; - - copy_to_user(buf, procdata->data + pos, nbytes); + if (copy_to_user(buf, procdata->data + pos, nbytes)) + return -EFAULT; *ppos += nbytes; diff -Nru a/drivers/net/ni65.c b/drivers/net/ni65.c --- a/drivers/net/ni65.c Sat Jul 19 12:54:24 2003 +++ b/drivers/net/ni65.c Sat Jul 19 12:54:24 2003 @@ -245,6 +245,7 @@ int cmdr_addr; int cardno; int features; + spinlock_t ring_lock; }; static int ni65_probe1(struct net_device *dev,int); @@ -299,7 +300,7 @@ int irqval = request_irq(dev->irq, &ni65_interrupt,0, cards[p->cardno].cardname,dev); if (irqval) { - printk ("%s: unable to get IRQ %d (irqval=%d).\n", + printk(KERN_ERR "%s: unable to get IRQ %d (irqval=%d).\n", dev->name,dev->irq, irqval); return -EAGAIN; } @@ -409,12 +410,14 @@ p = (struct priv *) dev->priv; p->cmdr_addr = ioaddr + cards[i].cmd_offset; p->cardno = i; + spin_lock_init(&p->ring_lock); - printk("%s: %s found at %#3x, ", dev->name, cards[p->cardno].cardname , ioaddr); + printk(KERN_INFO "%s: %s found at %#3x, ", dev->name, cards[p->cardno].cardname , ioaddr); outw(inw(PORT+L_RESET),PORT+L_RESET); /* first: reset the card */ if( (j=readreg(CSR0)) != 0x4) { - printk(KERN_ERR "can't RESET card: %04x\n",j); + printk("failed.\n"); + printk(KERN_ERR "%s: Can't RESET card: %04x\n", dev->name, j); ni65_free_buffer(p); release_region(ioaddr, cards[p->cardno].total_size); return -EAGAIN; @@ -467,7 +470,8 @@ break; } if(i == 5) { - printk("Can't detect DMA channel!\n"); + printk("failed.\n"); + printk(KERN_ERR "%s: Can't detect DMA channel!\n", dev->name); ni65_free_buffer(p); release_region(ioaddr, cards[p->cardno].total_size); return -EAGAIN; @@ -480,13 +484,13 @@ if(dev->irq < 2) { - unsigned long irq_mask, delay; + unsigned long irq_mask; ni65_init_lance(p,dev->dev_addr,0,0); irq_mask = probe_irq_on(); writereg(CSR0_INIT|CSR0_INEA,CSR0); /* trigger interrupt */ - delay = jiffies + HZ/50; - while (time_before(jiffies, delay)) ; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ/50); dev->irq = probe_irq_off(irq_mask); if(!dev->irq) { @@ -503,7 +507,7 @@ if(request_dma(dev->dma, cards[p->cardno].cardname ) != 0) { - printk("%s: Can't request dma-channel %d\n",dev->name,(int) dev->dma); + printk(KERN_ERR "%s: Can't request dma-channel %d\n",dev->name,(int) dev->dma); ni65_free_buffer(p); release_region(ioaddr, cards[p->cardno].total_size); return -EAGAIN; @@ -570,7 +574,7 @@ if(type) { ret = skb = alloc_skb(2+16+size,GFP_KERNEL|GFP_DMA); if(!skb) { - printk("%s: unable to allocate %s memory.\n",dev->name,what); + printk(KERN_WARNING "%s: unable to allocate %s memory.\n",dev->name,what); return NULL; } skb->dev = dev; @@ -581,12 +585,12 @@ else { ret = ptr = kmalloc(T_BUF_SIZE,GFP_KERNEL | GFP_DMA); if(!ret) { - printk("%s: unable to allocate %s memory.\n",dev->name,what); + printk(KERN_WARNING "%s: unable to allocate %s memory.\n",dev->name,what); return NULL; } } if( (u32) virt_to_phys(ptr+size) > 0x1000000) { - printk("%s: unable to allocate %s memory in lower 16MB!\n",dev->name,what); + printk(KERN_WARNING "%s: unable to allocate %s memory in lower 16MB!\n",dev->name,what); if(type) kfree_skb(skb); else @@ -692,7 +696,7 @@ writedatareg(CSR0_STOP); if(debuglevel > 1) - printk("ni65_stop_start\n"); + printk(KERN_DEBUG "ni65_stop_start\n"); if(p->features & INIT_RING_BEFORE_START) { int i; @@ -846,6 +850,8 @@ p = (struct priv *) dev->priv; + spin_lock(&p->ring_lock); + while(--bcnt) { csr0 = inw(PORT+L_DATAREG); @@ -867,7 +873,7 @@ { struct priv *p = (struct priv *) dev->priv; if(debuglevel > 1) - printk("%s: general error: %04x.\n",dev->name,csr0); + printk(KERN_ERR "%s: general error: %04x.\n",dev->name,csr0); if(csr0 & CSR0_BABL) p->stats.tx_errors++; if(csr0 & CSR0_MISS) { @@ -879,7 +885,7 @@ } if(csr0 & CSR0_MERR) { if(debuglevel > 1) - printk("%s: Ooops .. memory error: %04x.\n",dev->name,csr0); + printk(KERN_ERR "%s: Ooops .. memory error: %04x.\n",dev->name,csr0); ni65_stop_start(dev,p); } } @@ -932,12 +938,13 @@ #endif if( (csr0 & (CSR0_RXON | CSR0_TXON)) != (CSR0_RXON | CSR0_TXON) ) { - printk("%s: RX or TX was offline -> restart\n",dev->name); + printk(KERN_DEBUG "%s: RX or TX was offline -> restart\n",dev->name); ni65_stop_start(dev,p); } else writedatareg(CSR0_INEA); + spin_unlock(&p->ring_lock); return IRQ_HANDLED; } @@ -1147,9 +1154,7 @@ memset((char *)p->tmdbounce[p->tmdbouncenum]+skb->len, 0, len-skb->len); dev_kfree_skb (skb); - save_flags(flags); - cli(); - + spin_lock_irqsave(&p->ring_lock, flags); tmdp = p->tmdhead + p->tmdnum; tmdp->u.buffer = (u32) isa_virt_to_bus(p->tmdbounce[p->tmdbouncenum]); p->tmdbouncenum = (p->tmdbouncenum + 1) & (TMDNUM - 1); @@ -1157,8 +1162,7 @@ #ifdef XMT_VIA_SKB } else { - save_flags(flags); - cli(); + spin_lock_irqsave(&p->ring_lock, flags); tmdp = p->tmdhead + p->tmdnum; tmdp->u.buffer = (u32) isa_virt_to_bus(skb->data); @@ -1178,8 +1182,8 @@ p->lock = 0; dev->trans_start = jiffies; - - restore_flags(flags); + + spin_unlock_irqrestore(&p->ring_lock, flags); } return 0; @@ -1238,10 +1242,8 @@ { struct priv *p; p = (struct priv *) dev_ni65.priv; - if(!p) { - printk("Ooops .. no private struct\n"); - return; - } + if(!p) + BUG(); disable_dma(dev_ni65.dma); free_dma(dev_ni65.dma); unregister_netdev(&dev_ni65); @@ -1250,6 +1252,7 @@ dev_ni65.priv = NULL; } #endif /* MODULE */ + MODULE_LICENSE("GPL"); /* diff -Nru a/drivers/net/ni65.h b/drivers/net/ni65.h --- a/drivers/net/ni65.h Sat Jul 19 12:54:30 2003 +++ b/drivers/net/ni65.h Sat Jul 19 12:54:30 2003 @@ -20,32 +20,32 @@ #define CSR0_BABL 0x4000 /* Babble transmitter timeout error (RC) */ #define CSR0_CERR 0x2000 /* Collision Error (RC) */ #define CSR0_MISS 0x1000 /* Missed packet (RC) */ -#define CSR0_MERR 0x0800 /* Memory Error (RC) */ +#define CSR0_MERR 0x0800 /* Memory Error (RC) */ #define CSR0_RINT 0x0400 /* Receiver Interrupt (RC) */ -#define CSR0_TINT 0x0200 /* Transmit Interrupt (RC) */ +#define CSR0_TINT 0x0200 /* Transmit Interrupt (RC) */ #define CSR0_IDON 0x0100 /* Initialization Done (RC) */ #define CSR0_INTR 0x0080 /* Interrupt Flag (R) */ #define CSR0_INEA 0x0040 /* Interrupt Enable (RW) */ #define CSR0_RXON 0x0020 /* Receiver on (R) */ -#define CSR0_TXON 0x0010 /* Transmitter on (R) */ +#define CSR0_TXON 0x0010 /* Transmitter on (R) */ #define CSR0_TDMD 0x0008 /* Transmit Demand (RS) */ -#define CSR0_STOP 0x0004 /* Stop (RS) */ +#define CSR0_STOP 0x0004 /* Stop (RS) */ #define CSR0_STRT 0x0002 /* Start (RS) */ #define CSR0_INIT 0x0001 /* Initialize (RS) */ -#define CSR0_CLRALL 0x7f00 /* mask for all clearable bits */ +#define CSR0_CLRALL 0x7f00 /* mask for all clearable bits */ /* * Initialization Block Mode operation Bit Definitions. */ #define M_PROM 0x8000 /* Promiscuous Mode */ -#define M_INTL 0x0040 /* Internal Loopback */ -#define M_DRTY 0x0020 /* Disable Retry */ +#define M_INTL 0x0040 /* Internal Loopback */ +#define M_DRTY 0x0020 /* Disable Retry */ #define M_COLL 0x0010 /* Force Collision */ #define M_DTCR 0x0008 /* Disable Transmit CRC) */ #define M_LOOP 0x0004 /* Loopback */ -#define M_DTX 0x0002 /* Disable the Transmitter */ -#define M_DRX 0x0001 /* Disable the Receiver */ +#define M_DTX 0x0002 /* Disable the Transmitter */ +#define M_DRX 0x0001 /* Disable the Receiver */ /* @@ -56,7 +56,7 @@ #define RCV_ERR 0x40 /* Error Summary */ #define RCV_FRAM 0x20 /* Framing Error */ #define RCV_OFLO 0x10 /* Overflow Error */ -#define RCV_CRC 0x08 /* CRC Error */ +#define RCV_CRC 0x08 /* CRC Error */ #define RCV_BUF_ERR 0x04 /* Buffer Error */ #define RCV_START 0x02 /* Start of Packet */ #define RCV_END 0x01 /* End of Packet */ @@ -67,7 +67,7 @@ */ #define XMIT_OWN 0x80 /* owner bit 0 = host, 1 = lance */ -#define XMIT_ERR 0x40 /* Error Summary */ +#define XMIT_ERR 0x40 /* Error Summary */ #define XMIT_RETRY 0x10 /* more the 1 retry needed to Xmit */ #define XMIT_1_RETRY 0x08 /* one retry needed to Xmit */ #define XMIT_DEF 0x04 /* Deferred */ @@ -78,53 +78,44 @@ * transmit status (2) (valid if XMIT_ERR == 1) */ -#define XMIT_TDRMASK 0x03ff /* time-domain-reflectometer-value */ -#define XMIT_RTRY 0x0400 /* Failed after 16 retransmissions */ -#define XMIT_LCAR 0x0800 /* Loss of Carrier */ -#define XMIT_LCOL 0x1000 /* Late collision */ -#define XMIT_RESERV 0x2000 /* Reserved */ -#define XMIT_UFLO 0x4000 /* Underflow (late memory) */ -#define XMIT_BUFF 0x8000 /* Buffering error (no ENP) */ - -struct init_block -{ - unsigned short mode; - unsigned char eaddr[6]; - unsigned char filter[8]; - /* bit 29-31: number of rmd's (power of 2) */ - u32 rrp; /* receive ring pointer (align 8) */ - /* bit 29-31: number of tmd's (power of 2) */ - u32 trp; /* transmit ring pointer (align 8) */ +#define XMIT_TDRMASK 0x03ff /* time-domain-reflectometer-value */ +#define XMIT_RTRY 0x0400 /* Failed after 16 retransmissions */ +#define XMIT_LCAR 0x0800 /* Loss of Carrier */ +#define XMIT_LCOL 0x1000 /* Late collision */ +#define XMIT_RESERV 0x2000 /* Reserved */ +#define XMIT_UFLO 0x4000 /* Underflow (late memory) */ +#define XMIT_BUFF 0x8000 /* Buffering error (no ENP) */ + +struct init_block { + unsigned short mode; + unsigned char eaddr[6]; + unsigned char filter[8]; + /* bit 29-31: number of rmd's (power of 2) */ + u32 rrp; /* receive ring pointer (align 8) */ + /* bit 29-31: number of tmd's (power of 2) */ + u32 trp; /* transmit ring pointer (align 8) */ }; -struct rmd /* Receive Message Descriptor */ -{ - union - { - volatile u32 buffer; - struct - { - volatile unsigned char dummy[3]; - volatile unsigned char status; - } s; - } u; - volatile short blen; - volatile unsigned short mlen; +struct rmd { /* Receive Message Descriptor */ + union { + volatile u32 buffer; + struct { + volatile unsigned char dummy[3]; + volatile unsigned char status; + } s; + } u; + volatile short blen; + volatile unsigned short mlen; }; -struct tmd -{ - union - { - volatile u32 buffer; - struct - { - volatile unsigned char dummy[3]; - volatile unsigned char status; - } s; - } u; - volatile unsigned short blen; - volatile unsigned short status2; +struct tmd { + union { + volatile u32 buffer; + struct { + volatile unsigned char dummy[3]; + volatile unsigned char status; + } s; + } u; + volatile unsigned short blen; + volatile unsigned short status2; }; - - diff -Nru a/drivers/net/pcmcia/Kconfig b/drivers/net/pcmcia/Kconfig --- a/drivers/net/pcmcia/Kconfig Sat Jul 19 12:54:26 2003 +++ b/drivers/net/pcmcia/Kconfig Sat Jul 19 12:54:26 2003 @@ -113,7 +113,7 @@ If unsure, say N. config PCMCIA_AXNET - tristate "broken NS8390-cards support" + tristate "Asix AX88190 PCMCIA support" depends on NET_PCMCIA && PCMCIA ---help--- Say Y here if you intend to attach an Asix AX88190-based PCMCIA diff -Nru a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c --- a/drivers/net/seeq8005.c Sat Jul 19 12:54:26 2003 +++ b/drivers/net/seeq8005.c Sat Jul 19 12:54:26 2003 @@ -700,7 +700,8 @@ * wait_for_buffer * * This routine waits for the SEEQ chip to assert that the FIFO is ready - * by checking for a window interrupt, and then clearing it + * by checking for a window interrupt, and then clearing it. This has to + * occur in the interrupt handler! */ inline void wait_for_buffer(struct net_device * dev) { @@ -710,7 +711,7 @@ tmp = jiffies + HZ; while ( ( ((status=inw(SEEQ_STATUS)) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && time_before(jiffies, tmp)) - mb(); + cpu_relax(); if ( (status & SEEQSTAT_WINDOW_INT) == SEEQSTAT_WINDOW_INT) outw( SEEQCMD_WINDOW_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD); diff -Nru a/drivers/net/wan/comx-hw-comx.c b/drivers/net/wan/comx-hw-comx.c --- a/drivers/net/wan/comx-hw-comx.c Sat Jul 19 12:54:22 2003 +++ b/drivers/net/wan/comx-hw-comx.c Sat Jul 19 12:54:22 2003 @@ -11,6 +11,7 @@ * * Contributors: * Arnaldo Carvalho de Melo - 0.86 + * Daniele Bellucci - 0.87 * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -42,9 +43,12 @@ * - printk cleanups * Version 0.86 (00/08/15): * - resource release on failure at COMX_init + * + * Version 0.87 (03/07/09) + * - audit copy_from_user in comxhw_write_proc */ -#define VERSION "0.86" +#define VERSION "0.87" #include #include @@ -1084,7 +1088,8 @@ if (hw->firmware->data) { kfree(hw->firmware->data); } - copy_from_user(tmp + file->f_pos, buffer, count); + if (copy_from_user(tmp + file->f_pos, buffer, count)) + return -EFAULT; hw->firmware->len = entry->size = file->f_pos + count; hw->firmware->data = tmp; file->f_pos += count; diff -Nru a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c --- a/drivers/net/wan/sdladrv.c Sat Jul 19 12:54:23 2003 +++ b/drivers/net/wan/sdladrv.c Sat Jul 19 12:54:23 2003 @@ -160,10 +160,6 @@ /****** Function Prototypes *************************************************/ -/* Module entry points. These are called by the OS and must be public. */ -int init_module (void); -void cleanup_module (void); - /* Hardware-specific functions */ static int sdla_detect (sdlahw_t* hw); static int sdla_autodpm (sdlahw_t* hw); @@ -325,11 +321,7 @@ * Context: process */ -#ifdef MODULE -int init_module (void) -#else int sdladrv_init(void) -#endif { int i=0; @@ -354,9 +346,12 @@ * Module 'remove' entry point. * o release all remaining system resources */ -void cleanup_module (void) +static void sdladrv_cleanup(void) { } + +module_init(sdladrv_init); +module_cleanup(sdladrv_cleanup); #endif /******* Kernel APIs ********************************************************/ diff -Nru a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c --- a/drivers/net/wan/sdlamain.c Sat Jul 19 12:54:26 2003 +++ b/drivers/net/wan/sdlamain.c Sat Jul 19 12:54:26 2003 @@ -177,10 +177,6 @@ extern void disable_irq(unsigned int); extern void enable_irq(unsigned int); -/* Module entry points */ -int init_module (void); -void cleanup_module (void); - /* WAN link driver entry points */ static int setup(struct wan_device* wandev, wandev_conf_t* conf); static int shutdown(struct wan_device* wandev); @@ -246,11 +242,7 @@ * Context: process */ -#ifdef MODULE -int init_module (void) -#else int wanpipe_init(void) -#endif { int cnt, err = 0; @@ -313,7 +305,7 @@ * o unregister all adapters from the WAN router * o release all remaining system resources */ -void cleanup_module (void) +static void wanpipe_cleanup(void) { int i; @@ -329,6 +321,8 @@ printk(KERN_INFO "\nwanpipe: WANPIPE Modules Unloaded.\n"); } +module_init(wanpipe_init); +module_exit(wanpipe_cleanup); #endif /******* WAN Device Driver Entry Points *************************************/ diff -Nru a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c --- a/drivers/net/wan/syncppp.c Sat Jul 19 12:54:24 2003 +++ b/drivers/net/wan/syncppp.c Sat Jul 19 12:54:24 2003 @@ -161,7 +161,7 @@ * then put the packet into tx_queue, and call sppp_flush_xmit() * after spinlock is released. */ -static void sppp_flush_xmit() +static void sppp_flush_xmit(void) { struct sk_buff *skb; while ((skb = skb_dequeue(&tx_queue)) != NULL) diff -Nru a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c --- a/drivers/net/wireless/ray_cs.c Sat Jul 19 12:54:24 2003 +++ b/drivers/net/wireless/ray_cs.c Sat Jul 19 12:54:24 2003 @@ -25,6 +25,8 @@ * - reorganize kmallocs in ray_attach, checking all for failure * and releasing the previous allocations if one fails * + * Daniele Bellucci - 07/10/2003 + * - Audit copy_to_user in ioctl(SIOCGIWESSID) * =============================================================================*/ @@ -1315,7 +1317,8 @@ /* Push it out ! */ wrq->u.data.length = strlen(essid) + 1; wrq->u.data.flags = 1; /* active */ - copy_to_user(wrq->u.data.pointer, essid, sizeof(essid)); + if (copy_to_user(wrq->u.data.pointer, essid, sizeof(essid))) + err = -EFAULT; } break; diff -Nru a/drivers/parisc/led.c b/drivers/parisc/led.c --- a/drivers/parisc/led.c Sat Jul 19 12:54:24 2003 +++ b/drivers/parisc/led.c Sat Jul 19 12:54:24 2003 @@ -14,6 +14,10 @@ * TODO: * - speed-up calculations with inlined assembler * - interface to write to second row of LCD from /proc (if technically possible) + * + * Changes: + * - Audit copy_from_user in led_proc_write. + * Daniele Bellucci */ #include @@ -160,7 +164,9 @@ memset(lbuf, 0, count); - copy_from_user(lbuf, buf, count); + if (copy_from_user(lbuf, buf, count)) + return -EFAULT; + cur = lbuf; /* skip initial spaces */ diff -Nru a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c --- a/drivers/parport/parport_pc.c Sat Jul 19 12:54:29 2003 +++ b/drivers/parport/parport_pc.c Sat Jul 19 12:54:29 2003 @@ -94,7 +94,8 @@ } superios[NR_SUPERIOS] __devinitdata = { {0,},}; static int user_specified __devinitdata = 0; -#if defined(CONFIG_PARPORT_PC_FIFO) || defined(CONFIG_PARPORT_PC_SUPERIO) +#if defined(CONFIG_PARPORT_PC_SUPERIO) || \ + (defined(CONFIG_PARPORT_1284) && defined(CONFIG_PARPORT_PC_FIFO)) static int verbose_probing; #endif static int registered_parport; @@ -3116,7 +3117,8 @@ MODULE_PARM(irq, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s"); MODULE_PARM_DESC(dma, "DMA channel"); MODULE_PARM(dma, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s"); -#if defined(CONFIG_PARPORT_PC_FIFO) || defined(CONFIG_PARPORT_PC_SUPERIO) +#if defined(CONFIG_PARPORT_PC_SUPERIO) || \ + (defined(CONFIG_PARPORT_1284) && defined(CONFIG_PARPORT_PC_FIFO)) MODULE_PARM_DESC(verbose_probing, "Log chit-chat during initialisation"); MODULE_PARM(verbose_probing, "i"); #endif diff -Nru a/drivers/pci/Makefile b/drivers/pci/Makefile --- a/drivers/pci/Makefile Sat Jul 19 12:54:28 2003 +++ b/drivers/pci/Makefile Sat Jul 19 12:54:28 2003 @@ -2,7 +2,7 @@ # Makefile for the PCI bus specific drivers. # -obj-y += access.o bus.o probe.o pci.o pool.o quirks.o \ +obj-y += access.o bus.o probe.o remove.o pci.o pool.o quirks.o \ names.o pci-driver.o search.o pci-sysfs.o obj-$(CONFIG_PM) += power.o obj-$(CONFIG_PROC_FS) += proc.o diff -Nru a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig --- a/drivers/pci/hotplug/Kconfig Sat Jul 19 12:54:24 2003 +++ b/drivers/pci/hotplug/Kconfig Sat Jul 19 12:54:24 2003 @@ -99,22 +99,17 @@ When in doubt, say N. config HOTPLUG_PCI_CPCI - tristate "CompactPCI Hotplug driver" + bool "CompactPCI Hotplug driver" depends on HOTPLUG_PCI help Say Y here if you have a CompactPCI system card with CompactPCI hotswap support per the PICMG 2.1 specification. - This code is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called cpci_hotplug. If you want to compile it - as a module, say M here and read . - When in doubt, say N. config HOTPLUG_PCI_CPCI_ZT5550 tristate "Ziatech ZT5550 CompactPCI Hotplug driver" - depends on HOTPLUG_PCI_CPCI && X86 + depends on HOTPLUG_PCI && HOTPLUG_PCI_CPCI && X86 help Say Y here if you have an Performance Technologies (formerly Intel, formerly just Ziatech) Ziatech ZT5550 CompactPCI system card. @@ -128,7 +123,7 @@ config HOTPLUG_PCI_CPCI_GENERIC tristate "Generic port I/O CompactPCI Hotplug driver" - depends on HOTPLUG_PCI_CPCI && X86 + depends on HOTPLUG_PCI && HOTPLUG_PCI_CPCI && X86 help Say Y here if you have a CompactPCI system card that exposes the #ENUM hotswap signal as a bit in a system register that can be read through diff -Nru a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c --- a/drivers/pci/hotplug/acpiphp_glue.c Sat Jul 19 12:54:24 2003 +++ b/drivers/pci/hotplug/acpiphp_glue.c Sat Jul 19 12:54:24 2003 @@ -607,7 +607,7 @@ /* check if this bridge has ejectable slots */ if (detect_ejectable_slots(handle) > 0) { - dbg("found PCI-to-PCI bridge at PCI %s\n", dev->slot_name); + dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); add_p2p_bridge(handle, seg, bus, device, function); } @@ -693,7 +693,7 @@ if (func->flags & FUNC_HAS_PS0) { dbg("%s: executing _PS0 on %s\n", __FUNCTION__, - func->pci_dev->slot_name); + pci_name(func->pci_dev)); status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL); if (ACPI_FAILURE(status)) { warn("%s: _PS0 failed\n", __FUNCTION__); diff -Nru a/drivers/pci/hotplug/acpiphp_pci.c b/drivers/pci/hotplug/acpiphp_pci.c --- a/drivers/pci/hotplug/acpiphp_pci.c Sat Jul 19 12:54:21 2003 +++ b/drivers/pci/hotplug/acpiphp_pci.c Sat Jul 19 12:54:21 2003 @@ -212,7 +212,7 @@ int count; struct pci_resource *res; - dbg("Device %s\n", dev->slot_name); + dbg("Device %s\n", pci_name(dev)); for (count = 0; address[count]; count++) { /* for 6 BARs */ pci_read_config_dword(dev, address[count], &bar); @@ -337,7 +337,7 @@ struct pci_dev *dev; dev = func->pci_dev; - dbg("Hot-pluggable device %s\n", dev->slot_name); + dbg("Hot-pluggable device %s\n", pci_name(dev)); for (count = 0; address[count]; count++) { /* for 6 BARs */ pci_read_config_dword(dev, address[count], &bar); diff -Nru a/drivers/pci/hotplug/cpci_hotplug.h b/drivers/pci/hotplug/cpci_hotplug.h --- a/drivers/pci/hotplug/cpci_hotplug.h Sat Jul 19 12:54:23 2003 +++ b/drivers/pci/hotplug/cpci_hotplug.h Sat Jul 19 12:54:23 2003 @@ -75,7 +75,6 @@ extern int cpci_hp_unregister_controller(struct cpci_hp_controller *controller); extern int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last); extern int cpci_hp_unregister_bus(struct pci_bus *bus); -extern struct slot *cpci_find_slot(struct pci_bus *bus, unsigned int devfn); extern int cpci_hp_start(void); extern int cpci_hp_stop(void); diff -Nru a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c --- a/drivers/pci/hotplug/cpci_hotplug_core.c Sat Jul 19 12:54:24 2003 +++ b/drivers/pci/hotplug/cpci_hotplug_core.c Sat Jul 19 12:54:24 2003 @@ -427,34 +427,6 @@ return 0; } -struct slot * -cpci_find_slot(struct pci_bus *bus, unsigned int devfn) -{ - struct slot *slot; - struct slot *found; - struct list_head *tmp; - - if(!bus) { - return NULL; - } - - spin_lock(&list_lock); - if(!slots) { - spin_unlock(&list_lock); - return NULL; - } - found = NULL; - list_for_each(tmp, &slot_list) { - slot = list_entry(tmp, struct slot, slot_list); - if(slot->bus == bus && slot->devfn == devfn) { - found = slot; - break; - } - } - spin_unlock(&list_lock); - return found; -} - /* This is the interrupt mode interrupt handler */ irqreturn_t cpci_hp_intr(int irq, void *data, struct pt_regs *regs) @@ -924,6 +896,5 @@ EXPORT_SYMBOL_GPL(cpci_hp_unregister_controller); EXPORT_SYMBOL_GPL(cpci_hp_register_bus); EXPORT_SYMBOL_GPL(cpci_hp_unregister_bus); -EXPORT_SYMBOL_GPL(cpci_find_slot); EXPORT_SYMBOL_GPL(cpci_hp_start); EXPORT_SYMBOL_GPL(cpci_hp_stop); diff -Nru a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c --- a/drivers/pci/hotplug/cpci_hotplug_pci.c Sat Jul 19 12:54:25 2003 +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c Sat Jul 19 12:54:25 2003 @@ -448,7 +448,7 @@ } static int configure_visit_pci_dev(struct pci_dev_wrapped *wrapped_dev, - struct pci_bus_wrapped *wrapped_bus) + struct pci_bus_wrapped *wrapped_bus) { int rc; struct pci_dev *dev = wrapped_dev->dev; @@ -461,8 +461,8 @@ * We need to fix up the hotplug representation with the Linux * representation. */ - slot = cpci_find_slot(dev->bus, dev->devfn); - if(slot) { + if(wrapped_dev->data) { + slot = (struct slot*) wrapped_dev->data; slot->dev = dev; } @@ -494,9 +494,7 @@ return -ENODEV; /* Remove the Linux representation */ - if(pci_remove_device_safe(dev) == 0) { - kfree(dev); - } else { + if(pci_remove_device_safe(dev)) { err("Could not remove device\n"); return -1; } @@ -504,8 +502,8 @@ /* * Now remove the hotplug representation. */ - slot = cpci_find_slot(dev->bus, dev->devfn); - if(slot) { + if(wrapped_dev->data) { + slot = (struct slot*) wrapped_dev->data; slot->dev = NULL; } else { dbg("No hotplug representation for %02x:%02x.%x", @@ -574,13 +572,18 @@ /* Still NULL? Well then scan for it! */ if(slot->dev == NULL) { + int n; dbg("pci_dev still null"); /* * This will generate pci_dev structures for all functions, but * we will only call this case when lookup fails. */ - slot->dev = pci_scan_slot(slot->bus, slot->devfn); + n = pci_scan_slot(slot->bus, slot->devfn); + dbg("%s: pci_scan_slot returned %d", __FUNCTION__, n); + if(n > 0) + pci_bus_add_devices(slot->bus); + slot->dev = pci_find_slot(slot->bus->number, slot->devfn); if(slot->dev == NULL) { err("Could not find PCI device for slot %02x", slot->number); return 0; @@ -603,6 +606,10 @@ continue; wrapped_dev.dev = dev; wrapped_bus.bus = slot->dev->bus; + if(i) + wrapped_dev.data = NULL; + else + wrapped_dev.data = (void*) slot; rc = pci_visit_dev(&configure_functions, &wrapped_dev, &wrapped_bus); } } @@ -635,9 +642,14 @@ if(dev) { wrapped_dev.dev = dev; wrapped_bus.bus = dev->bus; + if(i) + wrapped_dev.data = NULL; + else + wrapped_dev.data = (void*) slot; dbg("%s - unconfigure phase 2", __FUNCTION__); rc = pci_visit_dev(&unconfigure_functions_phase2, - &wrapped_dev, &wrapped_bus); + &wrapped_dev, + &wrapped_bus); if(rc) break; } diff -Nru a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c --- a/drivers/pci/hotplug.c Sat Jul 19 12:54:28 2003 +++ b/drivers/pci/hotplug.c Sat Jul 19 12:54:28 2003 @@ -10,8 +10,6 @@ #define DBG(x...) #endif -static void pci_free_resources(struct pci_dev *dev); - int pci_hotplug (struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) { @@ -57,7 +55,7 @@ envp[i++] = scratch; length += snprintf (scratch, buffer_size - length, "PCI_SLOT_NAME=%s", - pdev->slot_name); + pci_name(pdev)); if ((buffer_size - length <= 0) || (i >= num_envp)) return -ENOMEM; @@ -172,105 +170,3 @@ } EXPORT_SYMBOL(pci_visit_dev); -static void pci_destroy_dev(struct pci_dev *dev) -{ - pci_proc_detach_device(dev); - device_unregister(&dev->dev); - - /* Remove the device from the device lists, and prevent any further - * list accesses from this device */ - spin_lock(&pci_bus_lock); - list_del(&dev->bus_list); - list_del(&dev->global_list); - dev->bus_list.next = dev->bus_list.prev = NULL; - dev->global_list.next = dev->global_list.prev = NULL; - spin_unlock(&pci_bus_lock); - - pci_free_resources(dev); - pci_dev_put(dev); -} - -/** - * pci_remove_device_safe - remove an unused hotplug device - * @dev: the device to remove - * - * Delete the device structure from the device lists and - * notify userspace (/sbin/hotplug), but only if the device - * in question is not being used by a driver. - * Returns 0 on success. - */ -int pci_remove_device_safe(struct pci_dev *dev) -{ - if (pci_dev_driver(dev)) - return -EBUSY; - pci_destroy_dev(dev); - return 0; -} -EXPORT_SYMBOL(pci_remove_device_safe); - -static void -pci_free_resources(struct pci_dev *dev) -{ - int i; - - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource *res = dev->resource + i; - if (res->parent) - release_resource(res); - } -} - -/** - * pci_remove_bus_device - remove a PCI device and any children - * @dev: the device to remove - * - * Remove a PCI device from the device lists, informing the drivers - * that the device has been removed. We also remove any subordinate - * buses and children in a depth-first manner. - * - * For each device we remove, delete the device structure from the - * device lists, remove the /proc entry, and notify userspace - * (/sbin/hotplug). - */ -void pci_remove_bus_device(struct pci_dev *dev) -{ - if (dev->subordinate) { - struct pci_bus *b = dev->subordinate; - - pci_remove_behind_bridge(dev); - pci_proc_detach_bus(b); - - spin_lock(&pci_bus_lock); - list_del(&b->node); - spin_unlock(&pci_bus_lock); - - kfree(b); - dev->subordinate = NULL; - } - - pci_destroy_dev(dev); -} - -/** - * pci_remove_behind_bridge - remove all devices behind a PCI bridge - * @dev: PCI bridge device - * - * Remove all devices on the bus, except for the parent bridge. - * This also removes any child buses, and any devices they may - * contain in a depth-first manner. - */ -void pci_remove_behind_bridge(struct pci_dev *dev) -{ - struct list_head *l, *n; - - if (dev->subordinate) { - list_for_each_safe(l, n, &dev->subordinate->devices) { - struct pci_dev *dev = pci_dev_b(l); - - pci_remove_bus_device(dev); - } - } -} - -EXPORT_SYMBOL(pci_remove_bus_device); -EXPORT_SYMBOL(pci_remove_behind_bridge); diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c --- a/drivers/pci/pci.c Sat Jul 19 12:54:24 2003 +++ b/drivers/pci/pci.c Sat Jul 19 12:54:24 2003 @@ -506,7 +506,7 @@ pci_resource_flags(pdev, bar) & IORESOURCE_IO ? "I/O" : "mem", bar + 1, /* PCI BAR # */ pci_resource_len(pdev, bar), pci_resource_start(pdev, bar), - pdev->slot_name); + pci_name(pdev)); return -EBUSY; } @@ -555,7 +555,7 @@ pci_resource_flags(pdev, i) & IORESOURCE_IO ? "I/O" : "mem", i + 1, /* PCI BAR # */ pci_resource_len(pdev, i), pci_resource_start(pdev, i), - pdev->slot_name); + pci_name(pdev)); while(--i >= 0) pci_release_region(pdev, i); @@ -576,7 +576,7 @@ pci_read_config_word(dev, PCI_COMMAND, &cmd); if (! (cmd & PCI_COMMAND_MASTER)) { - DBG("PCI: Enabling bus mastering for device %s\n", dev->slot_name); + DBG("PCI: Enabling bus mastering for device %s\n", pci_name(dev)); cmd |= PCI_COMMAND_MASTER; pci_write_config_word(dev, PCI_COMMAND, cmd); } @@ -620,7 +620,7 @@ return 0; printk(KERN_WARNING "PCI: cache line size of %d is not supported " - "by device %s\n", pci_cache_line_size << 2, dev->slot_name); + "by device %s\n", pci_cache_line_size << 2, pci_name(dev)); return -EINVAL; } @@ -653,7 +653,7 @@ pci_read_config_word(dev, PCI_COMMAND, &cmd); if (! (cmd & PCI_COMMAND_INVALIDATE)) { - DBG("PCI: Enabling Mem-Wr-Inval for device %s\n", dev->slot_name); + DBG("PCI: Enabling Mem-Wr-Inval for device %s\n", pci_name(dev)); cmd |= PCI_COMMAND_INVALIDATE; pci_write_config_word(dev, PCI_COMMAND, cmd); } diff -Nru a/drivers/pci/pool.c b/drivers/pci/pool.c --- a/drivers/pci/pool.c Sat Jul 19 12:54:29 2003 +++ b/drivers/pci/pool.c Sat Jul 19 12:54:29 2003 @@ -233,7 +233,7 @@ struct pci_page, page_list); if (is_page_busy (pool->blocks_per_page, page->bitmap)) { printk (KERN_ERR "pci_pool_destroy %s/%s, %p busy\n", - pool->dev ? pool->dev->slot_name : NULL, + pool->dev ? pci_name(pool->dev) : NULL, pool->name, page->vaddr); /* leak the still-in-use consistent memory */ list_del (&page->page_list); @@ -359,7 +359,7 @@ if ((page = pool_find_page (pool, dma)) == 0) { printk (KERN_ERR "pci_pool_free %s/%s, %p/%lx (bad dma)\n", - pool->dev ? pool->dev->slot_name : NULL, + pool->dev ? pci_name(pool->dev) : NULL, pool->name, vaddr, (unsigned long) dma); return; } @@ -372,13 +372,13 @@ #ifdef CONFIG_DEBUG_SLAB if (((dma - page->dma) + (void *)page->vaddr) != vaddr) { printk (KERN_ERR "pci_pool_free %s/%s, %p (bad vaddr)/%Lx\n", - pool->dev ? pool->dev->slot_name : NULL, + pool->dev ? pci_name(pool->dev) : NULL, pool->name, vaddr, (unsigned long long) dma); return; } if (page->bitmap [map] & (1UL << block)) { printk (KERN_ERR "pci_pool_free %s/%s, dma %Lx already free\n", - pool->dev ? pool->dev->slot_name : NULL, + pool->dev ? pci_name(pool->dev) : NULL, pool->name, (unsigned long long)dma); return; } diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c --- a/drivers/pci/quirks.c Sat Jul 19 12:54:21 2003 +++ b/drivers/pci/quirks.c Sat Jul 19 12:54:21 2003 @@ -33,7 +33,7 @@ while ((d = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, d))) { pci_read_config_byte(d, 0x82, &dlc); if (!(dlc & 1<<1)) { - printk(KERN_ERR "PCI: PIIX3: Enabling Passive Release on %s\n", d->slot_name); + printk(KERN_ERR "PCI: PIIX3: Enabling Passive Release on %s\n", pci_name(d)); dlc |= 1<<1; pci_write_config_byte(d, 0x82, dlc); } @@ -437,7 +437,7 @@ if (new_irq != irq) { printk(KERN_INFO "PCI: Via IRQ fixup for %s, from %d to %d\n", - dev->slot_name, irq, new_irq); + pci_name(dev), irq, new_irq); udelay(15); pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); @@ -598,7 +598,7 @@ return; printk(KERN_INFO "PCI: Ignoring BAR%d-%d of IDE controller %s\n", - first_bar, last_bar, dev->slot_name); + first_bar, last_bar, pci_name(dev)); } /* @@ -856,7 +856,7 @@ (f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) && (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) { #ifdef DEBUG - printk(KERN_INFO "PCI: Calling quirk %p for %s\n", f->hook, dev->slot_name); + printk(KERN_INFO "PCI: Calling quirk %p for %s\n", f->hook, pci_name(dev)); #endif f->hook(dev); } diff -Nru a/drivers/pci/remove.c b/drivers/pci/remove.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/remove.c Sat Jul 19 12:54:30 2003 @@ -0,0 +1,113 @@ +#include +#include +#include "pci.h" + +#undef DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +static void pci_free_resources(struct pci_dev *dev) +{ + int i; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + struct resource *res = dev->resource + i; + if (res->parent) + release_resource(res); + } +} + +static void pci_destroy_dev(struct pci_dev *dev) +{ + pci_proc_detach_device(dev); + device_unregister(&dev->dev); + + /* Remove the device from the device lists, and prevent any further + * list accesses from this device */ + spin_lock(&pci_bus_lock); + list_del(&dev->bus_list); + list_del(&dev->global_list); + dev->bus_list.next = dev->bus_list.prev = NULL; + dev->global_list.next = dev->global_list.prev = NULL; + spin_unlock(&pci_bus_lock); + + pci_free_resources(dev); + pci_dev_put(dev); +} + +/** + * pci_remove_device_safe - remove an unused hotplug device + * @dev: the device to remove + * + * Delete the device structure from the device lists and + * notify userspace (/sbin/hotplug), but only if the device + * in question is not being used by a driver. + * Returns 0 on success. + */ +int pci_remove_device_safe(struct pci_dev *dev) +{ + if (pci_dev_driver(dev)) + return -EBUSY; + pci_destroy_dev(dev); + return 0; +} +EXPORT_SYMBOL(pci_remove_device_safe); + +/** + * pci_remove_bus_device - remove a PCI device and any children + * @dev: the device to remove + * + * Remove a PCI device from the device lists, informing the drivers + * that the device has been removed. We also remove any subordinate + * buses and children in a depth-first manner. + * + * For each device we remove, delete the device structure from the + * device lists, remove the /proc entry, and notify userspace + * (/sbin/hotplug). + */ +void pci_remove_bus_device(struct pci_dev *dev) +{ + if (dev->subordinate) { + struct pci_bus *b = dev->subordinate; + + pci_remove_behind_bridge(dev); + pci_proc_detach_bus(b); + + spin_lock(&pci_bus_lock); + list_del(&b->node); + spin_unlock(&pci_bus_lock); + + kfree(b); + dev->subordinate = NULL; + } + + pci_destroy_dev(dev); +} + +/** + * pci_remove_behind_bridge - remove all devices behind a PCI bridge + * @dev: PCI bridge device + * + * Remove all devices on the bus, except for the parent bridge. + * This also removes any child buses, and any devices they may + * contain in a depth-first manner. + */ +void pci_remove_behind_bridge(struct pci_dev *dev) +{ + struct list_head *l, *n; + + if (dev->subordinate) { + list_for_each_safe(l, n, &dev->subordinate->devices) { + struct pci_dev *dev = pci_dev_b(l); + + pci_remove_bus_device(dev); + } + } +} + +EXPORT_SYMBOL(pci_remove_bus_device); +EXPORT_SYMBOL(pci_remove_behind_bridge); diff -Nru a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c --- a/drivers/pci/setup-bus.c Sat Jul 19 12:54:30 2003 +++ b/drivers/pci/setup-bus.c Sat Jul 19 12:54:30 2003 @@ -81,7 +81,7 @@ struct pci_bus_region region; printk("PCI: Bus %d, cardbus bridge: %s\n", - bus->number, bridge->slot_name); + bus->number, pci_name(bridge)); pcibios_resource_to_bus(bridge, ®ion, bus->resource[0]); if (bus->resource[0]->flags & IORESOURCE_IO) { @@ -344,7 +344,7 @@ if (order > 11) { printk(KERN_WARNING "PCI: region %s/%d " "too large: %lx-%lx\n", - dev->slot_name, i, r->start, r->end); + pci_name(dev), i, r->start, r->end); r->flags = 0; continue; } @@ -513,7 +513,7 @@ default: printk(KERN_INFO "PCI: not setting up bridge %s " - "for bus %d\n", dev->slot_name, b->number); + "for bus %d\n", pci_name(dev), b->number); break; } } diff -Nru a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c --- a/drivers/pci/setup-res.c Sat Jul 19 12:54:27 2003 +++ b/drivers/pci/setup-res.c Sat Jul 19 12:54:27 2003 @@ -68,7 +68,7 @@ if ((new ^ check) & mask) { printk(KERN_ERR "PCI: Error while updating region " - "%s/%d (%08x != %08x)\n", dev->slot_name, resno, + "%s/%d (%08x != %08x)\n", pci_name(dev), resno, new, check); } @@ -80,7 +80,7 @@ if (check != new) { printk(KERN_ERR "PCI: Error updating region " "%s/%d (high %08x != %08x)\n", - dev->slot_name, resno, new, check); + pci_name(dev), resno, new, check); } } } @@ -101,7 +101,7 @@ printk(KERN_ERR "PCI: %s region %d of %s %s [%lx:%lx]\n", root ? "Address space collision on" : "No parent found for", - resource, dtype, dev->slot_name, res->start, res->end); + resource, dtype, pci_name(dev), res->start, res->end); } return err; @@ -139,7 +139,7 @@ if (ret) { printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n", - resno, res->start, res->end, dev->slot_name); + resno, res->start, res->end, pci_name(dev)); } else if (resno < PCI_BRIDGE_RESOURCES) { pci_update_resource(dev, res, resno); } diff -Nru a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c --- a/drivers/pcmcia/hd64465_ss.c Sat Jul 19 12:54:25 2003 +++ b/drivers/pcmcia/hd64465_ss.c Sat Jul 19 12:54:25 2003 @@ -1,5 +1,5 @@ /* - * $Id$ + * $Id: hd64465_ss.c,v 1.7 2003/07/06 14:42:50 lethal Exp $ * * Device driver for the PCMCIA controller module of the * Hitachi HD64465 handheld companion chip. @@ -24,7 +24,6 @@ * * by Greg Banks * (c) 2000 PocketPenguins Inc - * */ #include @@ -37,28 +36,26 @@ #include #include #include -#include +#include #include #include -#include +#include +#include #include #include #include +#include +#include #include #include -#include #include "cs_internal.h" #define MODNAME "hd64465_ss" /* #define HD64465_DEBUG 1 */ -#ifndef HD64465_DEBUG -#define HD64465_DEBUG 0 -#endif - #if HD64465_DEBUG #define DPRINTK(args...) printk(MODNAME ": " args) #else @@ -66,7 +63,8 @@ #endif extern int hd64465_io_debug; - +extern void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags); +extern void p3_iounmap(void *addr); /*============================================================*/ @@ -74,37 +72,22 @@ typedef struct hs_socket_t { + unsigned int number; u_int irq; u_long mem_base; + void *io_base; u_long mem_length; - void (*handler)(void *info, u_int events); - void *handler_info; - u_int pending_events; u_int ctrl_base; socket_state_t state; pccard_io_map io_maps[MAX_IO_WIN]; pccard_mem_map mem_maps[MAX_WIN]; - struct vm_struct *io_vma; /* allocated kernel vm for mapping IO space */ + struct pcmcia_socket socket; } hs_socket_t; -#define HS_MAX_SOCKETS 2 -static hs_socket_t hs_sockets[HS_MAX_SOCKETS]; -static spinlock_t hs_pending_event_lock = SPIN_LOCK_UNLOCKED; -/* Calculate socket number from ptr into hs_sockets[] */ -#define hs_sockno(sp) (sp - hs_sockets) -static socket_cap_t hs_socket_cap = -{ - SS_CAP_PCCARD /* support 16 bit cards */ - |SS_CAP_STATIC_MAP /* mappings are fixed in host memory */ - , - 0xffde/*0xffff*/, /* IRQs mapped in s/w so can do any, really */ - HD64465_PCC_WINDOW, /* 16MB fixed window size */ - 0, /* no PCI support */ - 0, /* no CardBus support */ - 0 /* no bus operations needed */ -}; +#define HS_MAX_SOCKETS 2 +static hs_socket_t hs_sockets[HS_MAX_SOCKETS]; #define hs_in(sp, r) inb((sp)->ctrl_base + (r)) #define hs_out(sp, v, r) outb(v, (sp)->ctrl_base + (r)) @@ -179,7 +162,7 @@ { unsigned short cscier; - DPRINTK("hs_socket_enable_ireq(sock=%d)\n", hs_sockno(sp)); + DPRINTK("hs_socket_enable_ireq(sock=%d)\n", sp->number); cscier = hs_in(sp, CSCIER); cscier &= ~HD64465_PCCCSCIER_PIREQE_MASK; @@ -191,7 +174,7 @@ { unsigned short cscier; - DPRINTK("hs_socket_disable_ireq(sock=%d)\n", hs_sockno(sp)); + DPRINTK("hs_socket_disable_ireq(sock=%d)\n", sp->number); cscier = hs_in(sp, CSCIER); cscier &= ~HD64465_PCCCSCIER_PIREQE_MASK; @@ -255,7 +238,7 @@ */ static void hs_map_irq(hs_socket_t *sp, unsigned int irq) { - DPRINTK("hs_map_irq(sock=%d irq=%d)\n", hs_sockno(sp), irq); + DPRINTK("hs_map_irq(sock=%d irq=%d)\n", sp->number, irq); if (irq >= HS_NUM_MAPPED_IRQS) return; @@ -272,7 +255,7 @@ */ static void hs_unmap_irq(hs_socket_t *sp, unsigned int irq) { - DPRINTK("hs_unmap_irq(sock=%d irq=%d)\n", hs_sockno(sp), irq); + DPRINTK("hs_unmap_irq(sock=%d irq=%d)\n", sp->number, irq); if (irq >= HS_NUM_MAPPED_IRQS) return; @@ -301,7 +284,7 @@ { u_int psr; u_int vcci = 0; - u_int sock = hs_sockno(sp); + u_int sock = sp->number; DPRINTK("hs_set_voltage(%d, %d, %d)\n", sock, Vcc, Vpp); @@ -359,13 +342,12 @@ /*============================================================*/ -static int hs_init(unsigned int sock) +static int hs_init(struct pcmcia_socket *s) { - hs_socket_t *sp = &hs_sockets[sock]; + hs_socket_t *sp = container_of(s, struct hs_socket_t, socket); - DPRINTK("hs_init(%d)\n", sock); + DPRINTK("hs_init(%d)\n", sp->number); - sp->pending_events = 0; sp->state.Vcc = 0; sp->state.Vpp = 0; hs_set_voltages(sp, 0, 0); @@ -375,9 +357,12 @@ /*============================================================*/ -static int hs_suspend(unsigned int sock) +static int hs_suspend(struct pcmcia_socket *s) { - DPRINTK("hs_suspend(%d)\n", sock); +#ifdef HD64465_DEBUG + hs_socket_t *sp = container_of(s, struct hs_socket_t, socket); + DPRINTK("hs_suspend(%d)\n", sp->number); +#endif /* TODO */ @@ -386,32 +371,10 @@ /*============================================================*/ -static int hs_register_callback(unsigned int sock, - void (*handler)(void *, unsigned int), void * info) -{ - hs_socket_t *sp = &hs_sockets[sock]; - - DPRINTK("hs_register_callback(%d)\n", sock); - sp->handler = handler; - sp->handler_info = info; - return 0; -} - -/*============================================================*/ -static int hs_inquire_socket(unsigned int sock, socket_cap_t *cap) +static int hs_get_status(struct pcmcia_socket *s, u_int *value) { - DPRINTK("hs_inquire_socket(%d)\n", sock); - - *cap = hs_socket_cap; - return 0; -} - -/*============================================================*/ - -static int hs_get_status(unsigned int sock, u_int *value) -{ - hs_socket_t *sp = &hs_sockets[sock]; + hs_socket_t *sp = container_of(s, struct hs_socket_t, socket); unsigned int isr; u_int status = 0; @@ -473,9 +436,9 @@ /*============================================================*/ -static int hs_get_socket(unsigned int sock, socket_state_t *state) +static int hs_get_socket(struct pcmcia_socket *s, socket_state_t *state) { - hs_socket_t *sp = &hs_sockets[sock]; + hs_socket_t *sp = container_of(s, struct hs_socket_t, socket); DPRINTK("hs_get_socket(%d)\n", sock); @@ -485,9 +448,9 @@ /*============================================================*/ -static int hs_set_socket(unsigned int sock, socket_state_t *state) +static int hs_set_socket(struct pcmcia_socket *s, socket_state_t *state) { - hs_socket_t *sp = &hs_sockets[sock]; + hs_socket_t *sp = container_of(s, struct hs_socket_t, socket); u_long flags; u_int changed; unsigned short cscier; @@ -495,12 +458,12 @@ DPRINTK("hs_set_socket(sock=%d, flags=%x, csc_mask=%x, Vcc=%d, Vpp=%d, io_irq=%d)\n", sock, state->flags, state->csc_mask, state->Vcc, state->Vpp, state->io_irq); - save_and_cli(flags); /* Don't want interrupts happening here */ + local_irq_save(flags); /* Don't want interrupts happening here */ if (state->Vpp != sp->state.Vpp || state->Vcc != sp->state.Vcc) { if (!hs_set_voltages(sp, state->Vcc, state->Vpp)) { - restore_flags(flags); + local_irq_restore(flags); return -EINVAL; } } @@ -588,7 +551,7 @@ /* hd64465_io_debug = 0; */ sp->state = *state; - restore_flags(flags); + local_irq_restore(flags); #if HD64465_DEBUG > 10 if (state->flags & SS_OUTPUT_ENA) @@ -599,10 +562,11 @@ /*============================================================*/ -static int hs_set_io_map(unsigned int sock, struct pccard_io_map *io) +static int hs_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) { - hs_socket_t *sp = &hs_sockets[sock]; + hs_socket_t *sp = container_of(s, struct hs_socket_t, socket); int map = io->map; + int sock = sp->number; struct pccard_io_map *sio; pgprot_t prot; @@ -639,10 +603,9 @@ printk(KERN_INFO MODNAME ": MAP_0WS unimplemented\n"); if (io->flags & MAP_ACTIVE) { - unsigned long pstart, psize, paddrbase, vaddrbase; + unsigned long pstart, psize, paddrbase; paddrbase = virt_to_phys((void*)(sp->mem_base + 2 * HD64465_PCC_WINDOW)); - vaddrbase = (unsigned long)sp->io_vma->addr; pstart = io->start & PAGE_MASK; psize = ((io->stop + PAGE_SIZE) & PAGE_MASK) - pstart; @@ -653,26 +616,17 @@ * page will be mapped. But the code allows for weird cards * that might want IO ports > 4K. */ - DPRINTK("remap_page_range(vaddr=0x%08lx, paddr=0x%08lx, size=0x%08lxx)\n", - vaddrbase + pstart, paddrbase + pstart, psize); -#error This does not work. Firstly remap_page_range() uses current->mm for -#error the address space, which is wrong for kernel mappings. remap_page_range -#error also does flush_{cache,tlb}_range() which ONLY works for user mappings. -#error Next, remap_page_range() now wants to take a vm_area_struct arg. - remap_page_range(vaddrbase + pstart, paddrbase + pstart, psize, prot); + sp->io_base = p3_ioremap(paddrbase + pstart, psize, pgprot_val(prot)); /* * Change the mapping used by inb() outb() etc */ - hd64465_port_map( - io->start, + hd64465_port_map(io->start, io->stop - io->start + 1, - vaddrbase + io->start,0); + (unsigned long)sp->io_base + io->start, 0); } else { - hd64465_port_unmap( - sio->start, - sio->stop - sio->start + 1); - /* TODO: remap_page_range() to mark pages not present ? */ + hd64465_port_unmap(sio->start, sio->stop - sio->start + 1); + p3_iounmap(sp->io_base); } *sio = *io; @@ -681,9 +635,9 @@ /*============================================================*/ -static int hs_set_mem_map(unsigned int sock, struct pccard_mem_map *mem) +static int hs_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem) { - hs_socket_t *sp = &hs_sockets[sock]; + hs_socket_t *sp = container_of(s, struct hs_socket_t, socket); struct pccard_mem_map *smem; int map = mem->map; unsigned long paddr, size; @@ -722,13 +676,6 @@ /*============================================================*/ -static void hs_proc_setup(unsigned int sock, struct proc_dir_entry *base) -{ - DPRINTK("hs_proc_setup(%d)\n", sock); -} - -/*============================================================*/ - /* * This function is registered with the HD64465 glue code to do a * secondary demux step on the PCMCIA interrupts. It handles @@ -756,35 +703,9 @@ /* * Interrupt handling routine. - * - * This uses the schedule_work() technique to cause reportable events - * such as card insertion and removal to be handled in keventd's - * process context. */ - -static void hs_events_bh(void *dummy) -{ - hs_socket_t *sp; - u_int events; - int i; - - for (i=0; ipending_events; - sp->pending_events = 0; - spin_unlock_irq(&hs_pending_event_lock); - - if (sp->handler) - sp->handler(sp->handler_info, events); - } -} - -static DECLARE_WORK(hs_events_task, hs_events_bh, NULL); - -static void hs_interrupt(int irq, void *dev, struct pt_regs *regs) +static irqreturn_t hs_interrupt(int irq, void *dev, struct pt_regs *regs) { hs_socket_t *sp = (hs_socket_t *)dev; u_int events = 0; @@ -801,7 +722,7 @@ if ((hs_in(sp, ISR) & HD64465_PCCISR_PCD_MASK) != 0) { printk(KERN_NOTICE MODNAME ": socket %d, card not a supported card type or not inserted correctly\n", - hs_sockno(sp)); + sp->number); /* Don't do the rest unless a card is present */ cscr &= ~(HD64465_PCCCSCR_PCDC| HD64465_PCCCSCR_PRC| @@ -839,34 +760,22 @@ hs_out(sp, cscr, CSCR); - if (events) { - /* - * Arrange for events to be reported to the registered - * event handler function (from CardServices) in a process - * context (keventd) "soon". - */ - spin_lock(&hs_pending_event_lock); - sp->pending_events |= events; - spin_unlock(&hs_pending_event_lock); - - schedule_work(&hs_events_task); - } + if (events) + pcmcia_parse_events(&sp->socket, events); + + return IRQ_HANDLED; } /*============================================================*/ static struct pccard_operations hs_operations = { - .owner = THIS_MODULE, .init = hs_init, .suspend = hs_suspend, - .register_callback = hs_register_callback, - .inquire_socket = hs_inquire_socket, .get_status = hs_get_status, .get_socket = hs_get_socket, .set_socket = hs_set_socket, .set_io_map = hs_set_io_map, .set_mem_map = hs_set_mem_map, - .proc_setup = hs_proc_setup, }; static int hs_init_socket(hs_socket_t *sp, int irq, unsigned long mem_base, @@ -886,9 +795,6 @@ for (i=0 ; imem_maps[i].map = i; - if ((sp->io_vma = get_vm_area(HS_IO_MAP_SIZE, VM_IOREMAP)) == 0) - return -ENOMEM; - hd64465_register_irq_demux(sp->irq, hs_irq_demux, sp); if ((err = request_irq(sp->irq, hs_interrupt, SA_INTERRUPT, MODNAME, sp)) < 0) @@ -925,9 +831,8 @@ hs_reset_socket(sp, 1); - printk(KERN_INFO "HD64465 PCMCIA bridge socket %d at 0x%08lx irq %d io window %ldK@0x%08lx\n", - i, sp->mem_base, sp->irq, - sp->io_vma->size>>10, (unsigned long)sp->io_vma->addr); + printk(KERN_INFO "HD64465 PCMCIA bridge socket %d at 0x%08lx irq %d\n", + i, sp->mem_base, sp->irq); return 0; } @@ -935,7 +840,10 @@ static void hs_exit_socket(hs_socket_t *sp) { unsigned short cscier, gcr; + unsigned long flags; + local_irq_save(flags); + /* turn off interrupts in hardware */ cscier = hs_in(sp, CSCIER); cscier = (cscier & IER_MASK) | IER_OFF; @@ -955,19 +863,13 @@ free_irq(sp->irq, hs_interrupt); hd64465_unregister_irq_demux(sp->irq); } - if (sp->io_vma != 0) - vfree(sp->io_vma->addr); -} -static struct pcmcia_socket_class_data hd64465_data = { - .nsock = HS_MAX_SOCKETS, - .ops = &hs_operations, -}; + local_irq_restore(flags); +} static struct device_driver hd64465_driver = { .name = "hd64465-pcmcia", .bus = &platform_bus_type, - .devclass = &pcmcia_socket_class, .suspend = pcmcia_socket_dev_suspend, .resume = pcmcia_socket_dev_resume, }; @@ -996,7 +898,8 @@ } /* hd64465_io_debug = 1; */ - register_driver(&hd64465_driver); + if (driver_register(&hd64465_driver)) + return -EINVAL; /* Wake both sockets out of STANDBY mode */ /* TODO: wait 15ms */ @@ -1014,14 +917,22 @@ v |= HD64465_PCCCSCR_PSWSEL; outb(v, HD64465_REG_PCC0CSCR); - hs_set_voltages(&hs_sockets[0], 0, 0); - hs_set_voltages(&hs_sockets[1], 0, 0); - /* * Setup hs_sockets[] structures and request system resources. * TODO: on memory allocation failure, power down the socket * before quitting. */ + for (i=0; iprivate[3]) #define rl_config(socket) ((socket)->private[4]) +static void ricoh_zoom_video(struct pcmcia_socket *sock, int onoff) +{ + u8 reg; + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + + reg = config_readb(socket, RL5C4XX_MISC_CONTROL); + if (onoff) + /* Zoom zoom, we will all go together, zoom zoom, zoom zoom */ + reg |= RL5C4XX_ZV_ENABLE; + else + reg &= ~RL5C4XX_ZV_ENABLE; + + config_writeb(socket, RL5C4XX_MISC_CONTROL, reg); +} + +static void ricoh_set_zv(struct pcmcia_socket *sock) +{ + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + if(socket->dev->vendor == PCI_VENDOR_ID_RICOH) + { + switch(socket->dev->device) + { + /* There may be more .. */ + case PCI_DEVICE_ID_RICOH_RL5C478: + sock->zoom_video = ricoh_zoom_video; + break; + } + } +} + static int ricoh_init(struct pcmcia_socket *sock) { struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); yenta_init(sock); + ricoh_set_zv(sock); config_writew(socket, RL5C4XX_MISC, rl_misc(socket)); config_writew(socket, RL5C4XX_16BIT_CTL, rl_ctl(socket)); diff -Nru a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h --- a/drivers/pcmcia/ti113x.h Sat Jul 19 12:54:24 2003 +++ b/drivers/pcmcia/ti113x.h Sat Jul 19 12:54:24 2003 @@ -148,14 +148,96 @@ return 0; } +/* + * Zoom video control for TI122x/113x chips + */ + +static void ti_zoom_video(struct pcmcia_socket *sock, int onoff) +{ + u8 reg; + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + + /* If we don't have a Zoom Video switch this is harmless, + we just tristate the unused (ZV) lines */ + reg = config_readb(socket, TI113X_CARD_CONTROL); + if (onoff) + /* Zoom zoom, we will all go together, zoom zoom, zoom zoom */ + reg |= TI113X_CCR_ZVENABLE; + else + reg &= ~TI113X_CCR_ZVENABLE; + config_writeb(socket, TI113X_CARD_CONTROL, reg); +} + +/* + * The 145x series can also use this. They have an additional + * ZV autodetect mode we don't use but don't actually need. + * FIXME: manual says its in func0 and func1 but disagrees with + * itself about this - do we need to force func0, if so we need + * to know a lot more about socket pairings in pcmcia_socket than + * we do now.. uggh. + */ + +static void ti1250_zoom_video(struct pcmcia_socket *sock, int onoff) +{ + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + int shift = 0; + u8 reg; + + ti_zoom_video(sock, onoff); + + reg = config_readb(socket, 0x84); + reg |= (1<<7); /* ZV bus enable */ + + if(PCI_FUNC(socket->dev->devfn)==1) + shift = 1; + + if(onoff) + { + reg &= ~(1<<6); /* Clear select bit */ + reg |= shift<<6; /* Favour our socket */ + reg |= 1<dev->vendor == PCI_VENDOR_ID_TI) + { + switch(socket->dev->device) + { + /* There may be more .. */ + case PCI_DEVICE_ID_TI_1220: + case PCI_DEVICE_ID_TI_1221: + case PCI_DEVICE_ID_TI_1225: + sock->zoom_video = ti_zoom_video; + break; + case PCI_DEVICE_ID_TI_1250: + case PCI_DEVICE_ID_TI_1251A: + case PCI_DEVICE_ID_TI_1251B: + case PCI_DEVICE_ID_TI_1450: + sock->zoom_video = ti1250_zoom_video; + } + } +} static int ti_init(struct pcmcia_socket *sock) { struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); yenta_init(sock); + ti_set_zv(sock); ti_intctl(socket); return 0; } + /* * Generic TI init - TI has an extension for the * INTCTL register that sets the PCI CSC interrupt. @@ -176,9 +258,6 @@ if (new != reg) exca_writeb(socket, I365_INTCTL, new); -#if 0 - /* THIS CAUSES HANGS! Disabled for now, do not know why */ - /* * If ISA interrupts don't work, then fall back to routing card * interrupts to the PCI interrupt of the socket. @@ -190,7 +269,7 @@ u8 irqmux, devctl; devctl = config_readb(socket, TI113X_DEVICE_CONTROL); - if (devctl & TI113X_DCR_IMODE_MASK != TI12XX_DCR_IMODE_ALL_SERIAL) { + if ((devctl & TI113X_DCR_IMODE_MASK) != TI12XX_DCR_IMODE_ALL_SERIAL) { printk (KERN_INFO "ti113x: Routing card interrupts to PCI\n"); devctl &= ~TI113X_DCR_IMODE_MASK; @@ -203,7 +282,6 @@ config_writeb(socket, TI113X_DEVICE_CONTROL, devctl); } } -#endif socket->socket.ops->init = ti_init; return 0; @@ -220,6 +298,7 @@ { struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); yenta_init(sock); + ti_set_zv(sock); config_writel(socket, TI113X_SYSTEM_CONTROL, ti_sysctl(socket)); config_writeb(socket, TI113X_CARD_CONTROL, ti_cardctl(socket)); @@ -248,6 +327,7 @@ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); yenta_init(sock); ti113x_init(sock); + ti_set_zv(sock); ti_irqmux(socket) = config_readl(socket, TI122X_IRQMUX); ti_irqmux(socket) = (ti_irqmux(socket) & ~0x0f) | 0x02; /* route INTA */ if (!(ti_sysctl(socket) & TI122X_SCR_INTRTIE)) diff -Nru a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c --- a/drivers/pcmcia/yenta_socket.c Sat Jul 19 12:54:25 2003 +++ b/drivers/pcmcia/yenta_socket.c Sat Jul 19 12:54:25 2003 @@ -297,6 +297,8 @@ } exca_writeb(socket, I365_CSCINT, reg); exca_readb(socket, I365_CSC); + if(sock->zoom_video) + sock->zoom_video(sock, state->flags & SS_ZVCARD); } config_writew(socket, CB_BRIDGE_CONTROL, bridge); /* Socket event mask: get card insert/remove events.. */ diff -Nru a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c --- a/drivers/pnp/isapnp/core.c Sat Jul 19 12:54:25 2003 +++ b/drivers/pnp/isapnp/core.c Sat Jul 19 12:54:25 2003 @@ -255,14 +255,22 @@ static int isapnp_next_rdp(void) { int rdp = isapnp_rdp; + static int old_rdp = 0; + + if(old_rdp) + { + release_region(old_rdp, 1); + old_rdp = 0; + } while (rdp <= 0x3ff) { /* * We cannot use NE2000 probe spaces for ISAPnP or we * will lock up machines. */ - if ((rdp < 0x280 || rdp > 0x380) && !check_region(rdp, 1)) + if ((rdp < 0x280 || rdp > 0x380) && request_region(rdp, 1, "ISAPnP")) { isapnp_rdp = rdp; + old_rdp = rdp; return 0; } rdp += RDP_STEP; diff -Nru a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c --- a/drivers/s390/block/dasd.c Sat Jul 19 12:54:25 2003 +++ b/drivers/s390/block/dasd.c Sat Jul 19 12:54:25 2003 @@ -16,7 +16,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c --- a/drivers/s390/block/dasd_genhd.c Sat Jul 19 12:54:26 2003 +++ b/drivers/s390/block/dasd_genhd.c Sat Jul 19 12:54:26 2003 @@ -9,7 +9,7 @@ * * Dealing with devices registered to multiple major numbers. * - * $Revision: 1.29 $ + * $Revision: 1.31 $ */ #include @@ -17,7 +17,6 @@ #include #include #include -#include #include @@ -200,7 +199,6 @@ dasd_destroy_partitions(struct dasd_device * device) { del_gendisk(device->gdp); - put_disk(device->gdp); } int diff -Nru a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c --- a/drivers/s390/block/dasd_ioctl.c Sat Jul 19 12:54:25 2003 +++ b/drivers/s390/block/dasd_ioctl.c Sat Jul 19 12:54:25 2003 @@ -14,7 +14,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c --- a/drivers/s390/block/xpram.c Sat Jul 19 12:54:26 2003 +++ b/drivers/s390/block/xpram.c Sat Jul 19 12:54:26 2003 @@ -31,7 +31,6 @@ #include #include #include -#include #include #include /* HDIO_GETGEO */ #include diff -Nru a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c --- a/drivers/s390/char/tape_block.c Sat Jul 19 12:54:26 2003 +++ b/drivers/s390/char/tape_block.c Sat Jul 19 12:54:26 2003 @@ -13,7 +13,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c --- a/drivers/s390/cio/chsc.c Sat Jul 19 12:54:25 2003 +++ b/drivers/s390/cio/chsc.c Sat Jul 19 12:54:25 2003 @@ -1,7 +1,7 @@ /* * drivers/s390/cio/chsc.c * S/390 common I/O routines -- channel subsystem call - * $Revision: 1.73 $ + * $Revision: 1.74 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -206,6 +206,7 @@ if (!page) return -ENOMEM; + err = 0; for (irq = 0; irq <= highest_subchannel; irq++) { /* * retrieve information for each sch @@ -222,13 +223,14 @@ "not work\n", err); cio_chsc_err_msg = 1; } - return err; + goto out; } clear_page(page); } cio_chsc_desc_avail = 1; +out: free_page((unsigned long)page); - return 0; + return err; } __initcall(chsc_get_sch_descriptions); @@ -428,7 +430,7 @@ ret = css_probe_device(irq); if (ret == -ENXIO) /* We're through */ - return; + break; continue; } diff -Nru a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c --- a/drivers/s390/cio/cio.c Sat Jul 19 12:54:30 2003 +++ b/drivers/s390/cio/cio.c Sat Jul 19 12:54:30 2003 @@ -1,7 +1,7 @@ /* * drivers/s390/cio/cio.c * S/390 common I/O routines -- low level i/o calls - * $Revision: 1.98 $ + * $Revision: 1.100 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -16,10 +16,12 @@ #include #include #include +#include #include #include #include +#include #include "airq.h" #include "cio.h" @@ -442,6 +444,11 @@ if (sch->schib.pmcw.ena) break; } + if (ret == -EBUSY) { + struct irb irb; + if (tsch(sch->irq, &irb) != 0) + break; + } } sprintf (dbf_txt, "ret:%d", ret); CIO_TRACE_EVENT (2, dbf_txt); @@ -608,6 +615,7 @@ tpi_info = (struct tpi_info *) __LC_SUBCHANNEL_ID; irb = (struct irb *) __LC_IRB; do { + kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++; /* * Non I/O-subchannel thin interrupts are processed differently */ diff -Nru a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c --- a/drivers/s390/cio/device.c Sat Jul 19 12:54:26 2003 +++ b/drivers/s390/cio/device.c Sat Jul 19 12:54:26 2003 @@ -1,7 +1,7 @@ /* * drivers/s390/cio/device.c * bus driver for ccw devices - * $Revision: 1.58 $ + * $Revision: 1.60 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -434,6 +434,13 @@ return ret; } +void +ccw_device_unregister(void *data) +{ + device_unregister((struct device *)data); +} + + static void ccw_device_release(struct device *dev) { @@ -513,17 +520,11 @@ wake_up(&ccw_device_init_wq); } -static void +static int io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch) { int rc; - if (!get_device(&sch->dev)) { - if (cdev->dev.release) - cdev->dev.release(&cdev->dev); - return; - } - sch->dev.driver_data = cdev; sch->driver = &io_subchannel_driver; cdev->ccwlock = &sch->lock; @@ -540,9 +541,6 @@ snprintf (cdev->dev.bus_id, DEVICE_ID_SIZE, "0:%04x", sch->schib.pmcw.dev); - /* Do first half of device_register. */ - device_initialize(&cdev->dev); - /* Increase counter of devices currently in recognition. */ atomic_inc(&ccw_device_init_count); @@ -551,13 +549,10 @@ rc = ccw_device_recognition(cdev); spin_unlock_irq(cdev->ccwlock); if (rc) { - sch->dev.driver_data = 0; - put_device(&sch->dev); - if (cdev->dev.release) - cdev->dev.release(&cdev->dev); if (atomic_dec_and_test(&ccw_device_init_count)) wake_up(&ccw_device_init_wq); } + return rc; } static int @@ -565,6 +560,7 @@ { struct subchannel *sch; struct ccw_device *cdev; + int rc; sch = to_subchannel(pdev); if (sch->dev.driver_data) { @@ -573,8 +569,20 @@ * Register it and exit. This happens for all early * device, e.g. the console. */ - ccw_device_register(sch->dev.driver_data); + cdev = sch->dev.driver_data; + device_initialize(&cdev->dev); + ccw_device_register(cdev); subchannel_add_files(&sch->dev); + /* + * Check if the device is already online. If it is + * the reference count needs to be corrected + * (see ccw_device_online and css_init_done for the + * ugly details). + */ + if (cdev->private->state != DEV_STATE_NOT_OPER && + cdev->private->state != DEV_STATE_OFFLINE && + cdev->private->state != DEV_STATE_BOXED) + get_device(&cdev->dev); return 0; } cdev = kmalloc (sizeof(*cdev), GFP_KERNEL); @@ -592,7 +600,23 @@ .parent = pdev, .release = ccw_device_release, }; - io_subchannel_recog(cdev, to_subchannel(pdev)); + /* Do first half of device_register. */ + device_initialize(&cdev->dev); + + if (!get_device(&sch->dev)) { + if (cdev->dev.release) + cdev->dev.release(&cdev->dev); + return 0; + } + + rc = io_subchannel_recog(cdev, to_subchannel(pdev)); + if (rc) { + sch->dev.driver_data = 0; + put_device(&sch->dev); + if (cdev->dev.release) + cdev->dev.release(&cdev->dev); + } + return 0; } @@ -604,6 +628,8 @@ static int ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch) { + int rc; + /* Initialize the ccw_device structure. */ cdev->dev = (struct device) { .parent = &sch->dev, @@ -613,7 +639,11 @@ .parent = &css_bus_device, .bus = &css_bus_type, }; - io_subchannel_recog(cdev, sch); + + rc = io_subchannel_recog(cdev, sch); + if (rc) + return rc; + /* Now wait for the async. recognition to come to an end. */ while (!dev_fsm_final_state(cdev)) wait_cons_dev(); diff -Nru a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h --- a/drivers/s390/cio/device.h Sat Jul 19 12:54:27 2003 +++ b/drivers/s390/cio/device.h Sat Jul 19 12:54:27 2003 @@ -65,6 +65,8 @@ void io_subchannel_recog_done(struct ccw_device *cdev); +void ccw_device_unregister(void *); + int ccw_device_recognition(struct ccw_device *); int ccw_device_online(struct ccw_device *); int ccw_device_offline(struct ccw_device *); diff -Nru a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c --- a/drivers/s390/cio/device_fsm.c Sat Jul 19 12:54:25 2003 +++ b/drivers/s390/cio/device_fsm.c Sat Jul 19 12:54:25 2003 @@ -188,7 +188,7 @@ wake_up(&cdev->private->wait_q); - if (state != DEV_STATE_ONLINE) + if (css_init_done && state != DEV_STATE_ONLINE) put_device (&cdev->dev); } @@ -293,7 +293,7 @@ if (cdev->private->state != DEV_STATE_OFFLINE) return -EINVAL; sch = to_subchannel(cdev->dev.parent); - if (!get_device(&cdev->dev)) + if (css_init_done && !get_device(&cdev->dev)) return -ENODEV; if (cio_enable_subchannel(sch, sch->schib.pmcw.isc) != 0) { /* Couldn't enable the subchannel for i/o. Sick device. */ @@ -384,7 +384,9 @@ ccw_device_offline_notoper(struct ccw_device *cdev, enum dev_event dev_event) { cdev->private->state = DEV_STATE_NOT_OPER; - device_unregister(&cdev->dev); + INIT_WORK(&cdev->private->kick_work, + ccw_device_unregister, (void *) &cdev->dev); + queue_work(ccw_device_work, &cdev->private->kick_work); wake_up(&cdev->private->wait_q); } @@ -403,8 +405,10 @@ // FIXME: not-oper indication to device driver ? ccw_device_call_handler(cdev); } + INIT_WORK(&cdev->private->kick_work, + ccw_device_unregister, (void *) &cdev->dev); + queue_work(ccw_device_work, &cdev->private->kick_work); wake_up(&cdev->private->wait_q); - device_unregister(&cdev->dev); } /* diff -Nru a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c --- a/drivers/s390/cio/qdio.c Sat Jul 19 12:54:25 2003 +++ b/drivers/s390/cio/qdio.c Sat Jul 19 12:54:25 2003 @@ -55,7 +55,7 @@ #include "ioasm.h" #include "chsc.h" -#define VERSION_QDIO_C "$Revision: 1.51 $" +#define VERSION_QDIO_C "$Revision: 1.55 $" /****************** MODULE PARAMETER VARIABLES ********************/ MODULE_AUTHOR("Utz Bacher "); @@ -1643,6 +1643,7 @@ default: BUG(); } + ccw_device_set_timeout(cdev, 0); wake_up(&cdev->private->wait_q); } @@ -1891,26 +1892,25 @@ result=-EIO; goto exit; } - /* 4: request block - * 2: general char - * 512: chsc char */ - if ((scsc_area->general_char[1] & 0x00800000) != 0x00800000) { + /* Check for bit 41. */ + if ((scsc_area->general_char[1] & 0x00400000) != 0x00400000) { QDIO_PRINT_WARN("Adapter interruption facility not " \ "installed.\n"); result=-ENOENT; goto exit; } - if ((scsc_area->chsc_char[2] & 0x00180000) != 0x00180000) { + /* Check for bits 107 and 108. */ + if ((scsc_area->chsc_char[3] & 0x00180000) != 0x00180000) { QDIO_PRINT_WARN("Set Chan Subsys. Char. & Fast-CHSCs " \ "not available.\n"); result=-ENOENT; goto exit; } - /* Check for hydra thin interrupts. */ + /* Check for hydra thin interrupts (bit 67). */ hydra_thinints = ((scsc_area->general_char[2] & 0x10000000) == 0x10000000); - sprintf(dbf_text,"hydra_ti%1x", hydra_thinints); + sprintf(dbf_text,"hydrati%1x", hydra_thinints); QDIO_DBF_TEXT0(0,setup,dbf_text); exit: free_page ((unsigned long) scsc_area); @@ -2413,8 +2413,10 @@ QDIO_DBF_TEXT0(0,setup,dbf_text); QDIO_DBF_TEXT0(0,trace,dbf_text); - if (qdio_establish_irq_check_for_errors(cdev, cstat, dstat)) + if (qdio_establish_irq_check_for_errors(cdev, cstat, dstat)) { + ccw_device_set_timeout(cdev, 0); return; + } irq_ptr = cdev->private->qdio_data; @@ -2439,7 +2441,7 @@ qdio_initialize_set_siga_flags_output(irq_ptr); qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ESTABLISHED); - + ccw_device_set_timeout(cdev, 0); } int @@ -2698,6 +2700,8 @@ "returned %i, next try returned %i\n", irq_ptr->irq,result,result2); result=result2; + if (result) + ccw_device_set_timeout(cdev, 0); } spin_unlock_irqrestore(get_ccwdev_lock(cdev),saveflags); @@ -3000,7 +3004,6 @@ int buffer_length, int *eof, void *data) { int c=0; - int irq; /* we are always called with buffer_length=4k, so we all deliver on the first read */ @@ -3020,7 +3023,7 @@ perf_stats.siga_ins); _OUTP_IT("Number of SIGA out's issued : %u\n", perf_stats.siga_outs); - _OUTP_IT("Number of PCIs caught : %u\n", + _OUTP_IT("Number of PCIs caught : %u\n", perf_stats.pcis); _OUTP_IT("Number of adapter interrupts caught : %u\n", perf_stats.thinints); @@ -3037,27 +3040,6 @@ perf_stats.outbound_cnt); _OUTP_IT("\n"); - /* - * FIXME: Rather use driver_for_each_dev, if we had it. - * I know this loop destroys our layering, but at least gets the - * performance stats out... - */ - for (irq=0;irq <= highest_subchannel; irq++) { - struct qdio_irq *irq_ptr; - struct ccw_device *cdev; - - if (!ioinfo[irq]) - continue; - cdev = ioinfo[irq]->dev.driver_data; - if (!cdev) - continue; - irq_ptr = cdev->private->qdio_data; - if (!irq_ptr) - continue; - _OUTP_IT("Polling time on irq %4x " \ - ": %u\n", - irq_ptr->irq,irq_ptr->input_qs[0]->timing.threshold); - } return c; } diff -Nru a/drivers/s390/net/qeth.c b/drivers/s390/net/qeth.c --- a/drivers/s390/net/qeth.c Sat Jul 19 12:54:30 2003 +++ b/drivers/s390/net/qeth.c Sat Jul 19 12:54:30 2003 @@ -1,6 +1,6 @@ /* * - * linux/drivers/s390/net/qeth.c ($Revision: 1.118 $) + * linux/drivers/s390/net/qeth.c ($Revision: 1.126 $) * * Linux on zSeries OSA Express and HiperSockets support * @@ -165,7 +165,7 @@ "reserved for low memory situations"); /****************** MODULE STUFF **********************************/ -#define VERSION_QETH_C "$Revision: 1.118 $" +#define VERSION_QETH_C "$Revision: 1.126 $" static const char *version = "qeth S/390 OSA-Express driver (" VERSION_QETH_C "/" VERSION_QETH_H "/" VERSION_QETH_MPC_H QETH_VERSION_IPV6 QETH_VERSION_VLAN ")"; @@ -1156,7 +1156,7 @@ return skb; } -static struct sk_buff * +static inline struct sk_buff * qeth_get_next_skb(struct qeth_card *card, int *element_ptr, int *pos_in_el_ptr, void **hdr_ptr, struct qdio_buffer *buffer) @@ -1464,8 +1464,21 @@ skb->ip_summed = card->options.checksum_type; if (card->options.checksum_type == HW_CHECKSUMMING) { /* do we have a checksummed packet? */ - if (*(__u8 *) (hdr_ptr + 11) & QETH_EXT_HEADER_CSUM_TRANSP_REQ) { - /* skb->ip_summed is set already */ + + /* + * we only check for TCP/UDP checksums when the pseudo + * header was also checked successfully -- for the + * rest of the packets, it's not clear, whether the + * upper layer csum is alright. And they shouldn't + * occur too often anyway in real life + */ + + if ((*(__u8*)(hdr_ptr+11) & (QETH_EXT_HEADER_CSUM_HDR_REQ | + QETH_EXT_HEADER_CSUM_TRANSP_REQ)) == + (QETH_EXT_HEADER_CSUM_HDR_REQ | + QETH_EXT_HEADER_CSUM_TRANSP_REQ)) { +#if 0 + /* csum does not need to be set inbound anyway */ /* * vlan is not an issue here, it's still in @@ -1485,11 +1498,15 @@ (&skb->data[ip_len + QETH_TCP_CSUM_OFFSET]); } +#endif /* 0 */ + skb->ip_summed=CHECKSUM_UNNECESSARY; } else { /* make the stack check it */ skb->ip_summed = SW_CHECKSUMMING; } - } + } else + skb->ip_summed=card->options.checksum_type; + __qeth_rebuild_skb_vlan(card, skb, hdr_ptr); } @@ -1596,7 +1613,7 @@ #endif } -static __u8 +static inline __u8 __qeth_get_flags_v4(int multicast) { if (multicast == RTN_MULTICAST) @@ -1606,7 +1623,7 @@ return QETH_CAST_UNICAST; } -static __u8 +static inline __u8 __qeth_get_flags_v6(int multicast) { if (multicast == RTN_MULTICAST) @@ -1625,7 +1642,7 @@ QETH_HEADER_IPV6; } -static void +static inline void qeth_fill_header(struct qeth_hdr *hdr, struct sk_buff *skb, int version, int multicast) { @@ -1681,7 +1698,7 @@ __max(QETH_DBF_DATA_LEN, QETH_DBF_DATA_LEN)); } -static int inline +static inline int qeth_fill_buffer(struct qdio_buffer *buffer, char *dataptr, int length, int element) { @@ -1735,7 +1752,7 @@ return element; } -static void +static inline void qeth_flush_packed_packets(struct qeth_card *card, int queue, int under_int) { struct qdio_buffer *buffer; @@ -1900,7 +1917,7 @@ return ERROR_LINK_FAILURE; /* should never happen */ } -static void +static inline void qeth_free_buffer(struct qeth_card *card, int queue, int bufno, int qdio_error, int siga_error) { @@ -2013,7 +2030,7 @@ card->send_retries[queue][bufno] = 0; } -static void +static inline void qeth_free_all_skbs(struct qeth_card *card) { int q, b; @@ -2049,7 +2066,7 @@ } #ifdef QETH_VLAN -void +static inline void qeth_insert_ipv6_vlan_tag(struct sk_buff *__skb) { @@ -2088,7 +2105,7 @@ #endif } -static void +static inline void qeth_send_packet_fast(struct qeth_card *card, struct sk_buff *skb, struct net_device *dev, int queue, int version, int multicast) @@ -2183,7 +2200,7 @@ /* no checks, if all elements are used, as then we would not be here (at most 127 buffers are enqueued) */ -static void +static inline void qeth_send_packet_packed(struct qeth_card *card, struct sk_buff *skb, struct net_device *dev, int queue, int version, int multicast) @@ -2391,7 +2408,7 @@ } } -static int +static inline int qeth_do_send_packet(struct qeth_card *card, struct sk_buff *skb, struct net_device *dev) { @@ -2829,23 +2846,27 @@ if (!buffer) { if (atomic_read(&card->escape_softsetup)) - result = 0; + return 0; else - result = -1; - } else { - reply = (struct ipa_cmd *) PDU_ENCAPSULATION(buffer); - if ((update_cmd) && (reply)) - memcpy(cmd, reply, sizeof (struct ipa_cmd)); - result = reply->return_code; - - /* some special sausages: */ - if ((ipa_cmd == IPA_CMD_SETASSPARMS) && (result == 0)) { - result = reply->data.setassparms.return_code; - } - if ((ipa_cmd == IPA_CMD_SETADAPTERPARMS) && (result == 0)) { - result = reply->data.setadapterparms.return_code; - } + return -1; + } + reply = (struct ipa_cmd *) PDU_ENCAPSULATION(buffer); + if ((update_cmd) && (reply)) + memcpy(cmd, reply, sizeof (struct ipa_cmd)); + result = reply->return_code; + + /* some special sausages: */ + if ((ipa_cmd == IPA_CMD_SETASSPARMS) && (result == 0)) { + result = reply->data.setassparms.return_code; + if ((reply->data.setassparms.assist_no==IPA_INBOUND_CHECKSUM) && + (reply->data.setassparms.command_code == IPA_CMD_ASS_START)) + card->csum_enable_mask = + reply->data.setassparms.data.flags_32bit; + } + if ((ipa_cmd == IPA_CMD_SETADAPTERPARMS) && (result == 0)) { + result = reply->data.setadapterparms.return_code; } + return result; } @@ -5599,7 +5620,7 @@ } result=qeth_send_setassparms_simple_with_data (card,IPA_INBOUND_CHECKSUM, - IPA_CMD_ASS_ENABLE, IPA_CHECKSUM_ENABLE_MASK); + IPA_CMD_ASS_ENABLE, card->csum_enable_mask); if (result) { PRINT_WARN("Could not enable inbound " \ "checksumming on %s: 0x%x, " \ @@ -6881,6 +6902,14 @@ return level; /* hmmm... don't know what to do with that level. */ } +/* returns last four digits of bus_id */ +static inline __u16 +__raw_devno_from_bus_id(char *id) +{ + id += (strlen(id) - 4); + return (__u16) simple_strtoul(id, &id, 16); +} + static int qeth_idx_activate_read(struct qeth_card *card) { @@ -6905,7 +6934,7 @@ memcpy(QETH_IDX_ACT_FUNC_LEVEL(card->dma_stuff->sendbuf), &card->func_level, 2); - temp = _ccw_device_get_device_number(card->ddev); + temp = __raw_devno_from_bus_id(card->ddev->dev.bus_id); memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(card->dma_stuff->sendbuf), &temp, 2); temp = (card->cula << 8) + card->unit_addr2; memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(card->dma_stuff->sendbuf), @@ -7501,10 +7530,8 @@ for (; tmp && (!result); tmp = tmp->next) { if (atomic_read(&tmp->shutdown_phase)) continue; - if (dev == tmp->dev) { - result = QETH_VERIFY_IS_REAL_DEV; - } - result = __qeth_verify_dev_vlan(dev, tmp); + result = (dev == tmp->dev)? + QETH_VERIFY_IS_REAL_DEV:__qeth_verify_dev_vlan(dev, tmp); } read_unlock(&list_lock); return result; @@ -8547,6 +8574,8 @@ card->ip_mc_new_state.ipm6_ifa = NULL; #endif /* QETH_IPV6 */ + card->csum_enable_mask = IPA_CHECKSUM_DEFAULT_ENABLE_MASK; + /* setup net_device stuff */ card->dev->priv = card; @@ -9087,21 +9116,19 @@ /* FIXME: this is really a mess... */ #ifdef QETH_IPV6 - if (atomic_read(&card->rt4fld) && atomic_read(&card->rt6fld)) - strcpy(router_str, "no"); - else if (atomic_read(&card->rt4fld) - || atomic_read(&card->rt6fld)) - strcpy(router_str, "mix"); + if (atomic_read(&card->rt4fld) || atomic_read(&card->rt6fld)) + strcpy(router_str, "FLD"); #else/* QETH_IPV6 */ if (atomic_read(&card->rt4fld)) - strcpy(router_str, "no"); + strcpy(router_str, "FLD"); #endif /* QETH_IPV6 */ else if (((card->options.routing_type4 & ROUTER_MASK) == PRIMARY_ROUTER) #ifdef QETH_IPV6 && - ((card->options.routing_type6 & ROUTER_MASK) == - PRIMARY_ROUTER) + (((card->options.routing_type6 & ROUTER_MASK) == + PRIMARY_ROUTER) || + (!qeth_is_supported(IPA_IPv6))) #endif /* QETH_IPV6 */ ) { strcpy(router_str, "pri"); @@ -9110,8 +9137,9 @@ SECONDARY_ROUTER) #ifdef QETH_IPV6 && - ((card->options.routing_type6 & ROUTER_MASK) == - SECONDARY_ROUTER) + (((card->options.routing_type6 & ROUTER_MASK) == + SECONDARY_ROUTER) || + (!qeth_is_supported(IPA_IPv6))) #endif /* QETH_IPV6 */ ) { strcpy(router_str, "sec"); @@ -9120,8 +9148,9 @@ MULTICAST_ROUTER) #ifdef QETH_IPV6 && - ((card->options.routing_type6 & ROUTER_MASK) == - MULTICAST_ROUTER) + (((card->options.routing_type6 & ROUTER_MASK) == + MULTICAST_ROUTER) || + (!qeth_is_supported(IPA_IPv6))) #endif /* QETH_IPV6 */ ) { strcpy(router_str, "mc"); @@ -9130,8 +9159,9 @@ PRIMARY_CONNECTOR) #ifdef QETH_IPV6 && - ((card->options.routing_type6 & ROUTER_MASK) == - PRIMARY_CONNECTOR) + (((card->options.routing_type6 & ROUTER_MASK) == + PRIMARY_CONNECTOR) || + (!qeth_is_supported(IPA_IPv6))) #endif /* QETH_IPV6 */ ) { strcpy(router_str, "p.c"); @@ -9140,8 +9170,9 @@ SECONDARY_CONNECTOR) #ifdef QETH_IPV6 && - ((card->options.routing_type6 & ROUTER_MASK) == - SECONDARY_CONNECTOR) + (((card->options.routing_type6 & ROUTER_MASK) == + SECONDARY_CONNECTOR) || + (!qeth_is_supported(IPA_IPv6))) #endif /* QETH_IPV6 */ ) { strcpy(router_str, "s.c"); @@ -9150,8 +9181,9 @@ NO_ROUTER) #ifdef QETH_IPV6 && - ((card->options.routing_type6 & ROUTER_MASK) == - NO_ROUTER) + (((card->options.routing_type6 & ROUTER_MASK) == + NO_ROUTER) || + (!qeth_is_supported(IPA_IPv6))) #endif /* QETH_IPV6 */ ) { strcpy(router_str, "no"); @@ -10115,7 +10147,7 @@ return -EINVAL; if (atomic_read(&card->rt4fld)) - return sprintf(buf, "%s\n", "no"); + return sprintf(buf, "%s\n", "FLD"); switch (card->options.routing_type4 & ROUTER_MASK) { case PRIMARY_ROUTER: @@ -10202,7 +10234,10 @@ return -EINVAL; if (atomic_read(&card->rt6fld)) - return sprintf(buf, "%s\n", "no"); + return sprintf(buf, "%s\n", "FLD"); + + if (!qeth_is_supported(IPA_IPv6)) + return sprintf(buf, "%s\n", "n/a"); switch (card->options.routing_type6 & ROUTER_MASK) { case PRIMARY_ROUTER: @@ -11060,6 +11095,10 @@ qeth_remove_card_from_list(card); QETH_DBF_TEXT4(0, trace, "freecard"); + + memset(card->dev, 0, sizeof (struct net_device)); + card->dev->priv = card; + strncpy(card->dev->name, card->dev_name, IFNAMSIZ); ccw_device_set_offline(card->ddev); ccw_device_set_offline(card->wdev); diff -Nru a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h --- a/drivers/s390/net/qeth.h Sat Jul 19 12:54:21 2003 +++ b/drivers/s390/net/qeth.h Sat Jul 19 12:54:21 2003 @@ -14,7 +14,7 @@ #define QETH_NAME " qeth" -#define VERSION_QETH_H "$Revision: 1.47 $" +#define VERSION_QETH_H "$Revision: 1.49 $" /******************** CONFIG STUFF ***********************/ //#define QETH_DBF_LIKE_HELL @@ -938,6 +938,8 @@ __u32 ipa6_enabled; __u32 adp_supported; + __u32 csum_enable_mask; + atomic_t startlan_attempts; atomic_t enable_routing_attempts4; atomic_t rt4fld; @@ -1021,7 +1023,7 @@ case QETH_MPC_LINK_TYPE_LANE_TR: /* fallthrough */ case QETH_MPC_LINK_TYPE_HSTR: - return ARPHRD_IEEE802; + return ARPHRD_IEEE802_TR; default: return ARPHRD_ETHER; } diff -Nru a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h --- a/drivers/s390/net/qeth_mpc.h Sat Jul 19 12:54:25 2003 +++ b/drivers/s390/net/qeth_mpc.h Sat Jul 19 12:54:25 2003 @@ -10,7 +10,7 @@ #ifndef __QETH_MPC_H__ #define __QETH_MPC_H__ -#define VERSION_QETH_MPC_H "$Revision: 1.15 $" +#define VERSION_QETH_MPC_H "$Revision: 1.16 $" #define QETH_IPA_TIMEOUT (card->ipa_timeout) #define QETH_MPC_TIMEOUT 2000 @@ -188,7 +188,7 @@ #define IPA_CMD_ASS_ARP_QUERY_INFO 0x0104 #define IPA_CMD_ASS_ARP_QUERY_STATS 0x0204 -#define IPA_CHECKSUM_ENABLE_MASK 0x001a +#define IPA_CHECKSUM_DEFAULT_ENABLE_MASK 0x001a #define IPA_CMD_ASS_FILTER_SET_TYPES 0x0003 diff -Nru a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c --- a/drivers/sbus/char/envctrl.c Sat Jul 19 12:54:23 2003 +++ b/drivers/sbus/char/envctrl.c Sat Jul 19 12:54:23 2003 @@ -14,6 +14,9 @@ * * EB - Added support for CP1500 Global Address and PS/Voltage monitoring. * Eric Brower + * + * DB - Audit every copy_to_user in envctrl_read. + * Daniele Bellucci */ #include @@ -571,7 +574,8 @@ data[0] = (unsigned char)(warning_temperature); ret = 1; - copy_to_user((unsigned char *)buf, data, ret); + if (copy_to_user((unsigned char *)buf, data, ret)) + ret = -EFAULT; break; case ENVCTRL_RD_SHUTDOWN_TEMPERATURE: @@ -580,14 +584,16 @@ data[0] = (unsigned char)(shutdown_temperature); ret = 1; - copy_to_user((unsigned char *)buf, data, ret); + if (copy_to_user((unsigned char *)buf, data, ret)) + ret = -EFAULT; break; case ENVCTRL_RD_MTHRBD_TEMPERATURE: if (!(pchild = envctrl_get_i2c_child(ENVCTRL_MTHRBDTEMP_MON))) return 0; ret = envctrl_read_noncpu_info(pchild, ENVCTRL_MTHRBDTEMP_MON, data); - copy_to_user((unsigned char *)buf, data, ret); + if (copy_to_user((unsigned char *)buf, data, ret)) + ret = -EFAULT; break; case ENVCTRL_RD_CPU_TEMPERATURE: @@ -596,7 +602,8 @@ ret = envctrl_read_cpu_info(read_cpu, pchild, ENVCTRL_CPUTEMP_MON, data); /* Reset cpu to the default cpu0. */ - copy_to_user((unsigned char *)buf, data, ret); + if (copy_to_user((unsigned char *)buf, data, ret)) + ret = -EFAULT; break; case ENVCTRL_RD_CPU_VOLTAGE: @@ -605,21 +612,24 @@ ret = envctrl_read_cpu_info(read_cpu, pchild, ENVCTRL_CPUVOLTAGE_MON, data); /* Reset cpu to the default cpu0. */ - copy_to_user((unsigned char *)buf, data, ret); + if (copy_to_user((unsigned char *)buf, data, ret)) + ret = -EFAULT; break; case ENVCTRL_RD_SCSI_TEMPERATURE: if (!(pchild = envctrl_get_i2c_child(ENVCTRL_SCSITEMP_MON))) return 0; ret = envctrl_read_noncpu_info(pchild, ENVCTRL_SCSITEMP_MON, data); - copy_to_user((unsigned char *)buf, data, ret); + if (copy_to_user((unsigned char *)buf, data, ret)) + ret = -EFAULT; break; case ENVCTRL_RD_ETHERNET_TEMPERATURE: if (!(pchild = envctrl_get_i2c_child(ENVCTRL_ETHERTEMP_MON))) return 0; ret = envctrl_read_noncpu_info(pchild, ENVCTRL_ETHERTEMP_MON, data); - copy_to_user((unsigned char *)buf, data, ret); + if (copy_to_user((unsigned char *)buf, data, ret)) + ret = -EFAULT; break; case ENVCTRL_RD_FAN_STATUS: @@ -627,7 +637,8 @@ return 0; data[0] = envctrl_i2c_read_8574(pchild->addr); ret = envctrl_i2c_fan_status(pchild,data[0], data); - copy_to_user((unsigned char *)buf, data, ret); + if (copy_to_user((unsigned char *)buf, data, ret)) + ret = -EFAULT; break; case ENVCTRL_RD_GLOBALADDRESS: @@ -635,7 +646,8 @@ return 0; data[0] = envctrl_i2c_read_8574(pchild->addr); ret = envctrl_i2c_globaladdr(pchild, data[0], data); - copy_to_user((unsigned char *)buf, data, ret); + if (copy_to_user((unsigned char *)buf, data, ret)) + ret = -EFAULT; break; case ENVCTRL_RD_VOLTAGE_STATUS: @@ -645,7 +657,8 @@ return 0; data[0] = envctrl_i2c_read_8574(pchild->addr); ret = envctrl_i2c_voltage_status(pchild, data[0], data); - copy_to_user((unsigned char *)buf, data, ret); + if (copy_to_user((unsigned char *)buf, data, ret)) + ret = -EFAULT; break; default: diff -Nru a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c --- a/drivers/sbus/char/jsflash.c Sat Jul 19 12:54:25 2003 +++ b/drivers/sbus/char/jsflash.c Sat Jul 19 12:54:25 2003 @@ -38,12 +38,8 @@ #include #include -/* - * is controlled from the outside with these definitions. - */ #define MAJOR_NR JSFD_MAJOR -#include #include #include #include diff -Nru a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c --- a/drivers/scsi/3w-xxxx.c Sat Jul 19 12:54:29 2003 +++ b/drivers/scsi/3w-xxxx.c Sat Jul 19 12:54:29 2003 @@ -187,7 +187,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c --- a/drivers/scsi/53c700.c Sat Jul 19 12:54:23 2003 +++ b/drivers/scsi/53c700.c Sat Jul 19 12:54:23 2003 @@ -131,7 +131,7 @@ #include #include #include -#include +#include #include #include @@ -172,7 +172,7 @@ STATIC int NCR_700_slave_configure(Scsi_Device *SDpnt); STATIC void NCR_700_slave_destroy(Scsi_Device *SDpnt); -static struct device_attribute **NCR_700_dev_attrs = NULL; +STATIC struct device_attribute *NCR_700_dev_attrs[]; static char *NCR_700_phase[] = { "", @@ -2027,25 +2027,12 @@ .show = NCR_700_show_active_tags, }; -STATIC int __init -NCR_700_init(void) -{ - scsi_sysfs_modify_sdev_attribute(&NCR_700_dev_attrs, - &NCR_700_queue_depth_attr); - scsi_sysfs_modify_sdev_attribute(&NCR_700_dev_attrs, - &NCR_700_active_tags_attr); - return 0; -} - -/* NULL exit routine to keep modutils happy */ -STATIC void __exit -NCR_700_exit(void) -{ -} +STATIC struct device_attribute *NCR_700_dev_attrs[] = { + &NCR_700_queue_depth_attr, + &NCR_700_active_tags_attr, + NULL, +}; EXPORT_SYMBOL(NCR_700_detect); EXPORT_SYMBOL(NCR_700_release); EXPORT_SYMBOL(NCR_700_intr); - -module_init(NCR_700_init); -module_exit(NCR_700_exit); diff -Nru a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c --- a/drivers/scsi/53c7xx.c Sat Jul 19 12:54:30 2003 +++ b/drivers/scsi/53c7xx.c Sat Jul 19 12:54:30 2003 @@ -249,7 +249,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/AM53C974.c b/drivers/scsi/AM53C974.c --- a/drivers/scsi/AM53C974.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/AM53C974.c Sat Jul 19 12:54:25 2003 @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c --- a/drivers/scsi/BusLogic.c Sat Jul 19 12:54:29 2003 +++ b/drivers/scsi/BusLogic.c Sat Jul 19 12:54:29 2003 @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c --- a/drivers/scsi/NCR53C9x.c Sat Jul 19 12:54:23 2003 +++ b/drivers/scsi/NCR53C9x.c Sat Jul 19 12:54:23 2003 @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c --- a/drivers/scsi/NCR53c406a.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/NCR53c406a.c Sat Jul 19 12:54:25 2003 @@ -51,7 +51,7 @@ #include #include -#include +#include #include #include "scsi.h" #include "hosts.h" diff -Nru a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c --- a/drivers/scsi/NCR_D700.c Sat Jul 19 12:54:23 2003 +++ b/drivers/scsi/NCR_D700.c Sat Jul 19 12:54:23 2003 @@ -218,7 +218,8 @@ goto irq_failed; } - scsi_add_host(host, p->dev); + scsi_add_host(host, p->dev); /* XXX handle failure */ + scsi_scan_host(host); p->hosts[siop] = host; hostdata->dev = p->dev; @@ -387,7 +388,6 @@ static void __exit NCR_D700_exit(void) { mca_unregister_driver(&NCR_D700_driver); - scsi_sysfs_release_attributes(&NCR_D700_driver_template); } module_init(NCR_D700_init); diff -Nru a/drivers/scsi/NCR_Q720.c b/drivers/scsi/NCR_Q720.c --- a/drivers/scsi/NCR_Q720.c Sat Jul 19 12:54:23 2003 +++ b/drivers/scsi/NCR_Q720.c Sat Jul 19 12:54:23 2003 @@ -85,6 +85,7 @@ __u8 scsr1 = readb(vaddr + NCR_Q720_SCSR_OFFSET + 1); __u8 differential = readb(vaddr + NCR_Q720_SCSR_OFFSET) & 0x20; __u8 version; + int error; scsi_id = scsr1 >> 4; /* enable burst length 16 (FIXME: should allow this) */ @@ -120,9 +121,12 @@ scsr1 &= ~0x01; writeb(scsr1, vaddr + NCR_Q720_SCSR_OFFSET + 1); - scsi_add_host(p->hosts[siop], p->dev); - - return 0; + error = scsi_add_host(p->hosts[siop], p->dev); + if (error) + ncr53c8xx_release(p->hosts[siop]); + else + scsi_scan_host(p->hosts[siop]); + return error; fail: return -ENODEV; @@ -347,7 +351,6 @@ NCR_Q720_exit(void) { mca_unregister_driver(&NCR_Q720_driver); - //scsi_sysfs_release_attributes(&NCR_Q720_driver_template); } module_init(NCR_Q720_init); diff -Nru a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c --- a/drivers/scsi/a2091.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/a2091.c Sat Jul 19 12:54:25 2003 @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c --- a/drivers/scsi/a3000.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/a3000.c Sat Jul 19 12:54:26 2003 @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c --- a/drivers/scsi/aacraid/aachba.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/aacraid/aachba.c Sat Jul 19 12:54:24 2003 @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include "scsi.h" #include "hosts.h" diff -Nru a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c --- a/drivers/scsi/aacraid/commctrl.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/aacraid/commctrl.c Sat Jul 19 12:54:24 2003 @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include "scsi.h" diff -Nru a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c --- a/drivers/scsi/aacraid/comminit.c Sat Jul 19 12:54:22 2003 +++ b/drivers/scsi/aacraid/comminit.c Sat Jul 19 12:54:22 2003 @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c --- a/drivers/scsi/aacraid/commsup.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/aacraid/commsup.c Sat Jul 19 12:54:26 2003 @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include "scsi.h" #include "hosts.h" diff -Nru a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c --- a/drivers/scsi/aacraid/dpcsup.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/aacraid/dpcsup.c Sat Jul 19 12:54:25 2003 @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include "scsi.h" #include "hosts.h" diff -Nru a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c --- a/drivers/scsi/aacraid/linit.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/aacraid/linit.c Sat Jul 19 12:54:24 2003 @@ -50,7 +50,7 @@ #include #include #include -#include +#include #include "scsi.h" #include "hosts.h" #include diff -Nru a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c --- a/drivers/scsi/aacraid/rx.c Sat Jul 19 12:54:30 2003 +++ b/drivers/scsi/aacraid/rx.c Sat Jul 19 12:54:30 2003 @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c --- a/drivers/scsi/aacraid/sa.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/aacraid/sa.c Sat Jul 19 12:54:25 2003 @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c --- a/drivers/scsi/advansys.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/advansys.c Sat Jul 19 12:54:24 2003 @@ -798,7 +798,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c --- a/drivers/scsi/aha152x.c Sat Jul 19 12:54:22 2003 +++ b/drivers/scsi/aha152x.c Sat Jul 19 12:54:22 2003 @@ -225,7 +225,7 @@ #include #include #include -#include +#include #include "scsi.h" #include "hosts.h" #include @@ -241,9 +241,7 @@ #include #include #include -#include #include -#include #include #include "scsi.h" @@ -941,7 +939,8 @@ struct Scsi_Host *shpnt = lookup_irq(irqno); if (!shpnt) { - printk(KERN_ERR "aha152x%d: catched software interrupt %d for unknown controller.\n", HOSTNO, irqno); + /* no point using HOSTNO here! */ + printk(KERN_ERR "aha152x: catched software interrupt %d for unknown controller.\n", irqno); return IRQ_NONE; } @@ -1049,6 +1048,10 @@ printk(KERN_INFO "aha152x%d: trying software interrupt, ", shost->host_no); + + /* need to have host registered before triggering any interrupt */ + aha152x_host[registered_count] = shost; + mb(); SETPORT(DMACNTRL0, SWINT|INTEN); mdelay(1000); free_irq(shost->irq, shost); @@ -1064,7 +1067,7 @@ printk(KERN_ERR "aha152x%d: IRQ %d possibly wrong. " "Please verify.\n", shost->host_no, shost->irq); - goto out_release_region; + goto out_unregister_host; } printk("ok.\n"); @@ -1077,12 +1080,12 @@ "aha152x", shost) < 0) { printk(KERN_ERR "aha152x%d: failed to reassign interrupt.\n", shost->host_no); - goto out_release_region; + goto out_unregister_host; } - - aha152x_host[registered_count] = shost; return shost; /* the pcmcia stub needs the return value; */ +out_unregister_host: + aha152x_host[registered_count] = NULL; out_release_region: release_region(shost->io_port, IO_RANGE); out_unregister: diff -Nru a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c --- a/drivers/scsi/aha1542.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/aha1542.c Sat Jul 19 12:54:25 2003 @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/drivers/scsi/aha1542.h b/drivers/scsi/aha1542.h --- a/drivers/scsi/aha1542.h Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/aha1542.h Sat Jul 19 12:54:26 2003 @@ -130,7 +130,6 @@ }; static int aha1542_detect(Scsi_Host_Template *); -static int aha1542_command(Scsi_Cmnd *); static int aha1542_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); static int aha1542_abort(Scsi_Cmnd * SCpnt); static int aha1542_bus_reset(Scsi_Cmnd * SCpnt); diff -Nru a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c --- a/drivers/scsi/aha1740.c Sat Jul 19 12:54:23 2003 +++ b/drivers/scsi/aha1740.c Sat Jul 19 12:54:23 2003 @@ -34,7 +34,7 @@ * are deemed to be part of the source code. */ -#include +#include #include #include #include @@ -375,7 +375,7 @@ #endif /* locate an available ecb */ - spin_lock_irqsave(&SCpnt->device->host->host_lock, flags); + spin_lock_irqsave(SCpnt->device->host->host_lock, flags); ecbno = host->last_ecb_used + 1; /* An optimization */ if (ecbno >= AHA1740_ECBS) ecbno = 0; @@ -394,7 +394,7 @@ doubles as reserved flag */ host->last_ecb_used = ecbno; - spin_unlock_irqrestore(&SCpnt->device->host->host_lock, flags); + spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags); #ifdef DEBUG printk("Sending command (%d %x)...", ecbno, done); @@ -491,7 +491,7 @@ unsigned int base = SCpnt->device->host->io_port; DEB(printk("aha1740[%d] critical section\n",ecbno)); - spin_lock_irqsave(&SCpnt->device->host->host_lock, flags); + spin_lock_irqsave(SCpnt->device->host->host_lock, flags); for (loopcnt = 0; ; loopcnt++) { if (inb(G2STAT(base)) & G2STAT_MBXOUT) break; if (loopcnt == LOOPCNT_WARN) { @@ -511,7 +511,7 @@ panic("aha1740.c: attn wait failed!\n"); } outb(ATTN_START | (target & 7), ATTN(base)); /* Start it up */ - spin_unlock_irqrestore(&SCpnt->device->host->host_lock, flags); + spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags); DEB(printk("aha1740[%d] request queued.\n",ecbno)); } else printk(KERN_ALERT "aha1740_queuecommand: done can't be NULL\n"); @@ -594,7 +594,7 @@ if (!request_region(slotbase, SLOTSIZE, "aha1740")) /* See if in use */ return -EBUSY; if (!aha1740_test_port(slotbase)) - goto err_release; + goto err_release_region; aha1740_getconfig(slotbase,&irq_level,&translation); if ((inb(G2STAT(slotbase)) & (G2STAT_MBXOUT|G2STAT_BUSY)) != G2STAT_MBXOUT) { @@ -609,7 +609,7 @@ shpnt = scsi_host_alloc(&aha1740_template, sizeof(struct aha1740_hostdata)); if(shpnt == NULL) - goto err_release; + goto err_release_region; shpnt->base = 0; shpnt->io_port = slotbase; @@ -625,21 +625,27 @@ if (!host->ecb_dma_addr) { printk (KERN_ERR "aha1740_probe: Couldn't map ECB, giving up\n"); scsi_unregister (shpnt); - goto err_release; + goto err_host_put; } DEB(printk("aha1740_probe: enable interrupt channel %d\n",irq_level)); if (request_irq(irq_level,aha1740_intr_handle,0,"aha1740",shpnt)) { printk(KERN_ERR "aha1740_probe: Unable to allocate IRQ %d.\n", irq_level); - goto err_release; + goto err_unmap; } eisa_set_drvdata (edev, shpnt); - scsi_add_host (shpnt, dev); + scsi_add_host (shpnt, dev); /* XXX handle failure */ + scsi_scan_host (shpnt); return 0; - err_release: + err_unmap: + dma_unmap_single (&edev->dev, host->ecb_dma_addr, + sizeof (host->ecb), DMA_BIDIRECTIONAL); + err_host_put: + scsi_host_put (shpnt); + err_release_region: release_region(slotbase, SLOTSIZE); return -ENODEV; diff -Nru a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c --- a/drivers/scsi/aic7xxx/aic79xx_osm.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c Sat Jul 19 12:54:25 2003 @@ -2173,7 +2173,8 @@ ahd_unlock(ahd, &s); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - scsi_add_host(host, &ahd->dev_softc->dev); + scsi_add_host(host, &ahd->dev_softc->dev); /* XXX handle failure */ + scsi_scan_host(host); #endif return (0); } diff -Nru a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h --- a/drivers/scsi/aic7xxx/aic79xx_osm.h Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h Sat Jul 19 12:54:25 2003 @@ -43,7 +43,6 @@ #define _AIC79XX_LINUX_H_ #include -#include #include #include #include diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c Sat Jul 19 12:54:22 2003 +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c Sat Jul 19 12:54:22 2003 @@ -139,7 +139,7 @@ #endif #include /* For fetching system memory size */ -#include /* For block_size() */ +#include /* For block_size() */ /* * Lock protecting manipulation of the ahc softc list. @@ -1811,7 +1811,8 @@ ahc_unlock(ahc, &s); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL)); + scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL)); /* XXX handle failure */ + scsi_scan_host(host); #endif return (0); } diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h Sat Jul 19 12:54:24 2003 @@ -60,7 +60,6 @@ #define _AIC7XXX_LINUX_H_ #include -#include #include #include #include diff -Nru a/drivers/scsi/aic7xxx/aiclib.c b/drivers/scsi/aic7xxx/aiclib.c --- a/drivers/scsi/aic7xxx/aiclib.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/aic7xxx/aiclib.c Sat Jul 19 12:54:25 2003 @@ -30,7 +30,6 @@ * $Id$ */ -#include #include #include #include diff -Nru a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c --- a/drivers/scsi/aic7xxx_old.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/aic7xxx_old.c Sat Jul 19 12:54:24 2003 @@ -233,11 +233,10 @@ #include #include #include -#include +#include #include #include #include -#include #include #include "scsi.h" #include "hosts.h" diff -Nru a/drivers/scsi/amiga7xx.c b/drivers/scsi/amiga7xx.c --- a/drivers/scsi/amiga7xx.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/amiga7xx.c Sat Jul 19 12:54:24 2003 @@ -9,7 +9,7 @@ */ #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c --- a/drivers/scsi/arm/acornscsi.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/arm/acornscsi.c Sat Jul 19 12:54:25 2003 @@ -138,7 +138,7 @@ #include #include #include -#include +#include #include #include #include @@ -3043,9 +3043,13 @@ acornscsi_resetcard(ashost); ret = scsi_add_host(host, &ec->dev); - if (ret == 0) - goto out; + if (ret) + goto err_7; + + scsi_scan_host(host); + goto out; + err_7: free_irq(host->irq, ashost); err_6: release_region(host->io_port, 2048); diff -Nru a/drivers/scsi/arm/arxescsi.c b/drivers/scsi/arm/arxescsi.c --- a/drivers/scsi/arm/arxescsi.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/arm/arxescsi.c Sat Jul 19 12:54:25 2003 @@ -19,7 +19,7 @@ * 22-10-2000 SH Updated for new registering scheme. */ #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c --- a/drivers/scsi/arm/cumana_1.c Sat Jul 19 12:54:22 2003 +++ b/drivers/scsi/arm/cumana_1.c Sat Jul 19 12:54:22 2003 @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include @@ -297,9 +297,13 @@ printk("\n"); ret = scsi_add_host(host, &ec->dev); - if (ret == 0) - goto out; + if (ret) + goto out_free_irq; + + scsi_scan_host(host); + goto out; + out_free_irq: free_irq(host->irq, host); out_release: release_region(host->io_port, host->n_io_port); diff -Nru a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c --- a/drivers/scsi/arm/cumana_2.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/arm/cumana_2.c Sat Jul 19 12:54:26 2003 @@ -17,7 +17,7 @@ * 02-04-2000 RMK 0.0.4 Updated for new error handling code. */ #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/arm/ecoscsi.c b/drivers/scsi/arm/ecoscsi.c --- a/drivers/scsi/arm/ecoscsi.c Sat Jul 19 12:54:29 2003 +++ b/drivers/scsi/arm/ecoscsi.c Sat Jul 19 12:54:29 2003 @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include @@ -205,7 +205,8 @@ NCR5380_print_options(host); printk("\n"); - scsi_add_host(host, NULL); + scsi_add_host(host, NULL); /* XXX handle failure */ + scsi_scan_host(host); return 0; release_reg: diff -Nru a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c --- a/drivers/scsi/arm/eesox.c Sat Jul 19 12:54:30 2003 +++ b/drivers/scsi/arm/eesox.c Sat Jul 19 12:54:30 2003 @@ -23,7 +23,7 @@ * error handling code. */ #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c --- a/drivers/scsi/arm/fas216.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/arm/fas216.c Sat Jul 19 12:54:24 2003 @@ -35,7 +35,7 @@ * condition status from targets. */ #include -#include +#include #include #include #include @@ -2861,6 +2861,8 @@ ret = scsi_add_host(host, dev); if (ret) fas216_writeb(info, REG_CMD, CMD_RESETCHIP); + else + scsi_scan_host(host); return ret; } diff -Nru a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c --- a/drivers/scsi/arm/oak.c Sat Jul 19 12:54:21 2003 +++ b/drivers/scsi/arm/oak.c Sat Jul 19 12:54:21 2003 @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include @@ -158,9 +158,13 @@ printk("\n"); ret = scsi_add_host(host, &ec->dev); - if (ret == 0) - goto out; + if (ret) + goto out_release; + + scsi_scan_host(host); + goto out; + out_release: release_region(host->io_port, host->n_io_port); unreg: scsi_host_put(host); diff -Nru a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c --- a/drivers/scsi/arm/powertec.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/arm/powertec.c Sat Jul 19 12:54:26 2003 @@ -8,7 +8,7 @@ * published by the Free Software Foundation. */ #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/arm/queue.c b/drivers/scsi/arm/queue.c --- a/drivers/scsi/arm/queue.c Sat Jul 19 12:54:23 2003 +++ b/drivers/scsi/arm/queue.c Sat Jul 19 12:54:23 2003 @@ -15,7 +15,7 @@ * 30-Aug-2000 RMK Use Linux list handling and spinlocks */ #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c --- a/drivers/scsi/atari_scsi.c Sat Jul 19 12:54:30 2003 +++ b/drivers/scsi/atari_scsi.c Sat Jul 19 12:54:30 2003 @@ -86,7 +86,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c --- a/drivers/scsi/atp870u.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/atp870u.c Sat Jul 19 12:54:24 2003 @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/drivers/scsi/blz1230.c b/drivers/scsi/blz1230.c --- a/drivers/scsi/blz1230.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/blz1230.c Sat Jul 19 12:54:26 2003 @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/blz2060.c b/drivers/scsi/blz2060.c --- a/drivers/scsi/blz2060.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/blz2060.c Sat Jul 19 12:54:25 2003 @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/bvme6000.c b/drivers/scsi/bvme6000.c --- a/drivers/scsi/bvme6000.c Sat Jul 19 12:54:23 2003 +++ b/drivers/scsi/bvme6000.c Sat Jul 19 12:54:23 2003 @@ -5,7 +5,7 @@ */ #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/constants.c b/drivers/scsi/constants.c --- a/drivers/scsi/constants.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/constants.c Sat Jul 19 12:54:26 2003 @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include "scsi.h" #include "hosts.h" diff -Nru a/drivers/scsi/cpqfcTScontrol.c b/drivers/scsi/cpqfcTScontrol.c --- a/drivers/scsi/cpqfcTScontrol.c Sat Jul 19 12:54:22 2003 +++ b/drivers/scsi/cpqfcTScontrol.c Sat Jul 19 12:54:22 2003 @@ -30,7 +30,7 @@ #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) -#include +#include #include #include #include // request_region() prototype diff -Nru a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c --- a/drivers/scsi/cpqfcTSinit.c Sat Jul 19 12:54:22 2003 +++ b/drivers/scsi/cpqfcTSinit.c Sat Jul 19 12:54:22 2003 @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/cpqfcTSworker.c b/drivers/scsi/cpqfcTSworker.c --- a/drivers/scsi/cpqfcTSworker.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/cpqfcTSworker.c Sat Jul 19 12:54:26 2003 @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/cyberstorm.c b/drivers/scsi/cyberstorm.c --- a/drivers/scsi/cyberstorm.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/cyberstorm.c Sat Jul 19 12:54:26 2003 @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/cyberstormII.c b/drivers/scsi/cyberstormII.c --- a/drivers/scsi/cyberstormII.c Sat Jul 19 12:54:27 2003 +++ b/drivers/scsi/cyberstormII.c Sat Jul 19 12:54:27 2003 @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c --- a/drivers/scsi/dc395x.c Sat Jul 19 12:54:23 2003 +++ b/drivers/scsi/dc395x.c Sat Jul 19 12:54:23 2003 @@ -50,7 +50,7 @@ #include #include #include -#include +#include #include #include "scsi.h" #include "hosts.h" @@ -6214,7 +6214,8 @@ pci_set_drvdata(pdev, scsi_host); /* get the scsi mid level to scan for new devices on the bus */ - scsi_add_host(scsi_host, &pdev->dev); + scsi_add_host(scsi_host, &pdev->dev); /* XXX handle failure */ + scsi_scan_host(scsi_host); return 0; } diff -Nru a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c --- a/drivers/scsi/dec_esp.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/dec_esp.c Sat Jul 19 12:54:26 2003 @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c --- a/drivers/scsi/dmx3191d.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/dmx3191d.c Sat Jul 19 12:54:25 2003 @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c --- a/drivers/scsi/dpt_i2o.c Sat Jul 19 12:54:27 2003 +++ b/drivers/scsi/dpt_i2o.c Sat Jul 19 12:54:27 2003 @@ -47,7 +47,7 @@ #include /* for CONFIG_PCI */ #include /* for PCI support */ #include -#include +#include #include /* for udelay */ #include #include /* for printk */ diff -Nru a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c --- a/drivers/scsi/dtc.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/dtc.c Sat Jul 19 12:54:26 2003 @@ -76,7 +76,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/eata.c b/drivers/scsi/eata.c --- a/drivers/scsi/eata.c Sat Jul 19 12:54:27 2003 +++ b/drivers/scsi/eata.c Sat Jul 19 12:54:27 2003 @@ -486,7 +486,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c --- a/drivers/scsi/eata_pio.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/eata_pio.c Sat Jul 19 12:54:26 2003 @@ -58,7 +58,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/drivers/scsi/esp.c b/drivers/scsi/esp.c --- a/drivers/scsi/esp.c Sat Jul 19 12:54:30 2003 +++ b/drivers/scsi/esp.c Sat Jul 19 12:54:30 2003 @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/fastlane.c b/drivers/scsi/fastlane.c --- a/drivers/scsi/fastlane.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/fastlane.c Sat Jul 19 12:54:24 2003 @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/fcal.c b/drivers/scsi/fcal.c --- a/drivers/scsi/fcal.c Sat Jul 19 12:54:22 2003 +++ b/drivers/scsi/fcal.c Sat Jul 19 12:54:22 2003 @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c --- a/drivers/scsi/fd_mcs.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/fd_mcs.c Sat Jul 19 12:54:24 2003 @@ -79,7 +79,7 @@ #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c --- a/drivers/scsi/fdomain.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/fdomain.c Sat Jul 19 12:54:26 2003 @@ -270,7 +270,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c --- a/drivers/scsi/g_NCR5380.c Sat Jul 19 12:54:23 2003 +++ b/drivers/scsi/g_NCR5380.c Sat Jul 19 12:54:23 2003 @@ -105,7 +105,7 @@ #include #include #include -#include +#include #include "scsi.h" #include "hosts.h" #include "g_NCR5380.h" diff -Nru a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c --- a/drivers/scsi/gdth.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/gdth.c Sat Jul 19 12:54:25 2003 @@ -357,11 +357,8 @@ #include #endif -#if LINUX_VERSION_CODE >= 0x010300 -#include -#else -#include "../block/blk.h" -#endif +#include + #include "scsi.h" #include "hosts.h" #if LINUX_VERSION_CODE < 0x020503 diff -Nru a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c --- a/drivers/scsi/gvp11.c Sat Jul 19 12:54:28 2003 +++ b/drivers/scsi/gvp11.c Sat Jul 19 12:54:28 2003 @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c --- a/drivers/scsi/hosts.c Sat Jul 19 12:54:22 2003 +++ b/drivers/scsi/hosts.c Sat Jul 19 12:54:22 2003 @@ -81,19 +81,15 @@ printk(KERN_INFO "scsi%d : %s\n", shost->host_no, sht->info ? sht->info(shost) : sht->name); - error = scsi_sysfs_add_host(shost, dev); - if (!shost->can_queue) { printk(KERN_ERR "%s: can_queue = 0 no longer supported\n", sht->name); error = -EINVAL; } - if (!error) { + error = scsi_sysfs_add_host(shost, dev); + if (!error) scsi_proc_host_add(shost); - scsi_scan_host(shost); - } - return error; } @@ -151,12 +147,6 @@ dump_stack(); } - /* if its not set in the template, use the default */ - if (!sht->shost_attrs) - sht->shost_attrs = scsi_sysfs_shost_attrs; - if (!sht->sdev_attrs) - sht->sdev_attrs = scsi_sysfs_sdev_attrs; - shost = kmalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask); if (!shost) return NULL; @@ -283,8 +273,8 @@ **/ void scsi_host_get(struct Scsi_Host *shost) { - get_device(&shost->host_gendev); - class_device_get(&shost->class_dev); + get_device(&shost->shost_gendev); + class_device_get(&shost->shost_classdev); } /** @@ -293,6 +283,6 @@ **/ void scsi_host_put(struct Scsi_Host *shost) { - class_device_put(&shost->class_dev); - put_device(&shost->host_gendev); + class_device_put(&shost->shost_classdev); + put_device(&shost->shost_gendev); } diff -Nru a/drivers/scsi/i91uscsi.c b/drivers/scsi/i91uscsi.c --- a/drivers/scsi/i91uscsi.c Sat Jul 19 12:54:23 2003 +++ b/drivers/scsi/i91uscsi.c Sat Jul 19 12:54:23 2003 @@ -81,7 +81,7 @@ #include #include -#include +#include #include #include "i91uscsi.h" diff -Nru a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c --- a/drivers/scsi/ibmmca.c Sat Jul 19 12:54:23 2003 +++ b/drivers/scsi/ibmmca.c Sat Jul 19 12:54:23 2003 @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c --- a/drivers/scsi/ide-scsi.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/ide-scsi.c Sat Jul 19 12:54:26 2003 @@ -978,8 +978,10 @@ idescsi_setup (drive, idescsi); drive->disk->fops = &idescsi_ops; err = scsi_add_host(host, &idescsi_primary); - if (!err) + if (!err) { + scsi_scan_host(host); return 0; + } /* fall through on error */ ide_unregister_subdriver(drive); } diff -Nru a/drivers/scsi/imm.c b/drivers/scsi/imm.c --- a/drivers/scsi/imm.c Sat Jul 19 12:54:30 2003 +++ b/drivers/scsi/imm.c Sat Jul 19 12:54:30 2003 @@ -24,7 +24,7 @@ void imm_reset_pulse(unsigned int base); static int device_check(int host_no); -#include +#include #include #include #include diff -Nru a/drivers/scsi/imm.h b/drivers/scsi/imm.h --- a/drivers/scsi/imm.h Sat Jul 19 12:54:21 2003 +++ b/drivers/scsi/imm.h Sat Jul 19 12:54:21 2003 @@ -75,7 +75,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c --- a/drivers/scsi/in2000.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/in2000.c Sat Jul 19 12:54:26 2003 @@ -114,7 +114,6 @@ */ #include -#include #include #include #include diff -Nru a/drivers/scsi/ini9100u.c b/drivers/scsi/ini9100u.c --- a/drivers/scsi/ini9100u.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/ini9100u.c Sat Jul 19 12:54:24 2003 @@ -119,7 +119,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/inia100.c b/drivers/scsi/inia100.c --- a/drivers/scsi/inia100.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/inia100.c Sat Jul 19 12:54:24 2003 @@ -74,7 +74,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/ips.c b/drivers/scsi/ips.c --- a/drivers/scsi/ips.c Sat Jul 19 12:54:21 2003 +++ b/drivers/scsi/ips.c Sat Jul 19 12:54:21 2003 @@ -167,7 +167,7 @@ #include #include -#include +#include #include #include diff -Nru a/drivers/scsi/ips.h b/drivers/scsi/ips.h --- a/drivers/scsi/ips.h Sat Jul 19 12:54:23 2003 +++ b/drivers/scsi/ips.h Sat Jul 19 12:54:23 2003 @@ -111,7 +111,7 @@ #else #define IPS_REGISTER_HOSTS(SHT) (!ips_detect(SHT)) #define IPS_UNREGISTER_HOSTS(SHT) - #define IPS_ADD_HOST(shost,device) scsi_add_host(shost,device) + #define IPS_ADD_HOST(shost,device) do { scsi_add_host(shost,device); scsi_scan_host(shost); } while (0) #define IPS_REMOVE_HOST(shost) scsi_remove_host(shost) #define IPS_SCSI_SET_DEVICE(sh,ha) scsi_set_device(sh, &(ha)->pcidev->dev) #define IPS_PRINTK(level, pcidev, format, arg...) \ diff -Nru a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c --- a/drivers/scsi/jazz_esp.c Sat Jul 19 12:54:22 2003 +++ b/drivers/scsi/jazz_esp.c Sat Jul 19 12:54:22 2003 @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c --- a/drivers/scsi/lasi700.c Sat Jul 19 12:54:22 2003 +++ b/drivers/scsi/lasi700.c Sat Jul 19 12:54:22 2003 @@ -128,7 +128,8 @@ } dev_set_drvdata(&dev->dev, host); - scsi_add_host(host, &dev->dev); + scsi_add_host(host, &dev->dev); /* XXX handle failure */ + scsi_scan_host(host); return 0; @@ -165,7 +166,6 @@ lasi700_exit(void) { unregister_parisc_driver(&lasi700_driver); - scsi_sysfs_release_attributes(&lasi700_template); } module_init(lasi700_init); diff -Nru a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c --- a/drivers/scsi/mac53c94.c Sat Jul 19 12:54:22 2003 +++ b/drivers/scsi/mac53c94.c Sat Jul 19 12:54:22 2003 @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c --- a/drivers/scsi/mac_esp.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/mac_esp.c Sat Jul 19 12:54:25 2003 @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c --- a/drivers/scsi/mac_scsi.c Sat Jul 19 12:54:22 2003 +++ b/drivers/scsi/mac_scsi.c Sat Jul 19 12:54:22 2003 @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/drivers/scsi/mca_53c9x.c b/drivers/scsi/mca_53c9x.c --- a/drivers/scsi/mca_53c9x.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/mca_53c9x.c Sat Jul 19 12:54:24 2003 @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c --- a/drivers/scsi/megaraid.c Sat Jul 19 12:54:21 2003 +++ b/drivers/scsi/megaraid.c Sat Jul 19 12:54:21 2003 @@ -32,7 +32,7 @@ #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c --- a/drivers/scsi/mesh.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/mesh.c Sat Jul 19 12:54:26 2003 @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c --- a/drivers/scsi/mvme147.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/mvme147.c Sat Jul 19 12:54:24 2003 @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/mvme16x.c b/drivers/scsi/mvme16x.c --- a/drivers/scsi/mvme16x.c Sat Jul 19 12:54:27 2003 +++ b/drivers/scsi/mvme16x.c Sat Jul 19 12:54:27 2003 @@ -5,7 +5,7 @@ */ #include #include -#include +#include #include #include diff -Nru a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c --- a/drivers/scsi/ncr53c8xx.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/ncr53c8xx.c Sat Jul 19 12:54:24 2003 @@ -140,7 +140,7 @@ #include #include -#include +#include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,35) #include diff -Nru a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c --- a/drivers/scsi/nsp32.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/nsp32.c Sat Jul 19 12:54:24 2003 @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include @@ -1820,7 +1820,8 @@ goto free_irq; } - scsi_add_host(host, &pdev->dev); + scsi_add_host(host, &pdev->dev); /* XXX handle failure */ + scsi_scan_host(host); pci_set_drvdata(pdev, host); return 0; diff -Nru a/drivers/scsi/oktagon_esp.c b/drivers/scsi/oktagon_esp.c --- a/drivers/scsi/oktagon_esp.c Sat Jul 19 12:54:21 2003 +++ b/drivers/scsi/oktagon_esp.c Sat Jul 19 12:54:21 2003 @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/osst.c b/drivers/scsi/osst.c --- a/drivers/scsi/osst.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/osst.c Sat Jul 19 12:54:25 2003 @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c --- a/drivers/scsi/pas16.c Sat Jul 19 12:54:21 2003 +++ b/drivers/scsi/pas16.c Sat Jul 19 12:54:21 2003 @@ -117,7 +117,8 @@ #include #include #include -#include +#include +#include #include #include #include diff -Nru a/drivers/scsi/pc980155.c b/drivers/scsi/pc980155.c --- a/drivers/scsi/pc980155.c Sat Jul 19 12:54:22 2003 +++ b/drivers/scsi/pc980155.c Sat Jul 19 12:54:22 2003 @@ -11,7 +11,7 @@ */ #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/pci2000.c b/drivers/scsi/pci2000.c --- a/drivers/scsi/pci2000.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/pci2000.c Sat Jul 19 12:54:26 2003 @@ -35,7 +35,7 @@ ****************************************************************************/ #define PCI2000_VERSION "1.20" -#include +#include #include #include #include diff -Nru a/drivers/scsi/pci2220i.c b/drivers/scsi/pci2220i.c --- a/drivers/scsi/pci2220i.c Sat Jul 19 12:54:21 2003 +++ b/drivers/scsi/pci2220i.c Sat Jul 19 12:54:21 2003 @@ -50,7 +50,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c --- a/drivers/scsi/pcmcia/aha152x_stub.c Sat Jul 19 12:54:27 2003 +++ b/drivers/scsi/pcmcia/aha152x_stub.c Sat Jul 19 12:54:27 2003 @@ -44,7 +44,7 @@ #include #include #include -#include +#include #include #include "scsi.h" @@ -278,7 +278,8 @@ goto cs_failed; } - scsi_add_host(host, NULL); + scsi_add_host(host, NULL); /* XXX handle failure */ + scsi_scan_host(host); sprintf(info->node.dev_name, "scsi%d", host->host_no); link->dev = &info->node; diff -Nru a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c --- a/drivers/scsi/pcmcia/fdomain_stub.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/pcmcia/fdomain_stub.c Sat Jul 19 12:54:25 2003 @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include "scsi.h" @@ -254,7 +254,8 @@ goto cs_failed; } - scsi_add_host(host, NULL); + scsi_add_host(host, NULL); /* XXX handle failure */ + scsi_scan_host(host); sprintf(info->node.dev_name, "scsi%d", host->host_no); link->dev = &info->node; diff -Nru a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c --- a/drivers/scsi/pcmcia/nsp_cs.c Sat Jul 19 12:54:30 2003 +++ b/drivers/scsi/pcmcia/nsp_cs.c Sat Jul 19 12:54:30 2003 @@ -44,7 +44,7 @@ #include #include #include -#include +#include #include #include @@ -1773,7 +1773,8 @@ req.Base+req.Size-1); printk("\n"); - scsi_add_host(host, NULL); + scsi_add_host(host, NULL); /* XXX handle failure */ + scsi_scan_host(host); link->state &= ~DEV_CONFIG_PENDING; return; diff -Nru a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c --- a/drivers/scsi/pcmcia/qlogic_stub.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/pcmcia/qlogic_stub.c Sat Jul 19 12:54:25 2003 @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include "scsi.h" @@ -270,7 +270,8 @@ link->dev = &info->node; info->host = host; - scsi_add_host(host, NULL); + scsi_add_host(host, NULL); /* XXX handle failure */ + scsi_scan_host(host); out: link->state &= ~DEV_CONFIG_PENDING; diff -Nru a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c --- a/drivers/scsi/pluto.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/pluto.c Sat Jul 19 12:54:24 2003 @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c --- a/drivers/scsi/ppa.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/ppa.c Sat Jul 19 12:54:25 2003 @@ -15,7 +15,7 @@ /* The following #define is to avoid a clash with hosts.c */ #define PPA_CODE 1 -#include +#include #include #include #include diff -Nru a/drivers/scsi/ppa.h b/drivers/scsi/ppa.h --- a/drivers/scsi/ppa.h Sat Jul 19 12:54:27 2003 +++ b/drivers/scsi/ppa.h Sat Jul 19 12:54:27 2003 @@ -82,7 +82,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/drivers/scsi/psi240i.c b/drivers/scsi/psi240i.c --- a/drivers/scsi/psi240i.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/psi240i.c Sat Jul 19 12:54:26 2003 @@ -26,7 +26,7 @@ #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c --- a/drivers/scsi/qla1280.c Sat Jul 19 12:54:30 2003 +++ b/drivers/scsi/qla1280.c Sat Jul 19 12:54:30 2003 @@ -252,7 +252,7 @@ #include #include #include -#include +#include #include #include #include @@ -327,7 +327,7 @@ /* 3.16 */ #ifdef QLA_64BIT_PTR #define pci_dma_lo32(a) (a & 0xffffffff) -#define pci_dma_hi32(a) (a >> 32) +#define pci_dma_hi32(a) ((a >> 16)>>16) #else #define pci_dma_lo32(a) (a & 0xffffffff) #define pci_dma_hi32(a) 0 diff -Nru a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c --- a/drivers/scsi/qlogicfas.c Sat Jul 19 12:54:30 2003 +++ b/drivers/scsi/qlogicfas.c Sat Jul 19 12:54:30 2003 @@ -127,7 +127,7 @@ #endif #include -#include /* to get disk capacity */ +#include /* to get disk capacity */ #include #include #include @@ -140,6 +140,7 @@ #include #include +#include #include "scsi.h" #include "hosts.h" diff -Nru a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c --- a/drivers/scsi/qlogicfc.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/qlogicfc.c Sat Jul 19 12:54:26 2003 @@ -50,7 +50,7 @@ * */ -#include +#include #include #include #include diff -Nru a/drivers/scsi/qlogicisp.c b/drivers/scsi/qlogicisp.c --- a/drivers/scsi/qlogicisp.c Sat Jul 19 12:54:30 2003 +++ b/drivers/scsi/qlogicisp.c Sat Jul 19 12:54:30 2003 @@ -20,7 +20,7 @@ * General Public License for more details. */ -#include +#include #include #include #include diff -Nru a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c --- a/drivers/scsi/qlogicpti.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/qlogicpti.c Sat Jul 19 12:54:26 2003 @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h --- a/drivers/scsi/scsi.h Sat Jul 19 12:54:23 2003 +++ b/drivers/scsi/scsi.h Sat Jul 19 12:54:23 2003 @@ -174,11 +174,6 @@ #define SCSI_MLQUEUE_DEVICE_BUSY 0x1056 #define SCSI_MLQUEUE_EH_RETRY 0x1057 -extern int scsi_sysfs_modify_sdev_attribute(struct device_attribute ***dev_attrs, - struct device_attribute *attr); -extern int scsi_sysfs_modify_shost_attribute(struct class_device_attribute ***class_attrs, - struct class_device_attribute *attr); - /* * Legacy dma direction interfaces. * diff -Nru a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c --- a/drivers/scsi/scsi_debug.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/scsi_debug.c Sat Jul 19 12:54:25 2003 @@ -41,7 +41,7 @@ #include #include -#include +#include #include "scsi.h" #include "hosts.h" #include @@ -687,7 +687,7 @@ pcontrol = (cmd[2] & 0xc0) >> 6; pcode = cmd[2] & 0x3f; msense_6 = (MODE_SENSE == cmd[0]); - alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[6]); + alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]); /* printk(KERN_INFO "msense: dbd=%d pcontrol=%d pcode=%d " "msense_6=%d alloc_len=%d\n", dbd, pcontrol, pcode, " "msense_6, alloc_len); */ @@ -1701,7 +1701,8 @@ printk(KERN_ERR "%s: scsi_add_host failed\n", __FUNCTION__); error = -ENODEV; scsi_host_put(hpnt); - } + } else + scsi_scan_host(hpnt); return error; diff -Nru a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c --- a/drivers/scsi/scsi_ioctl.c Sat Jul 19 12:54:29 2003 +++ b/drivers/scsi/scsi_ioctl.c Sat Jul 19 12:54:29 2003 @@ -18,7 +18,7 @@ #include #include -#include +#include #include "scsi.h" #include "hosts.h" #include diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c --- a/drivers/scsi/scsi_lib.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/scsi_lib.c Sat Jul 19 12:54:25 2003 @@ -8,7 +8,7 @@ */ #include -#include +#include #include #include #include @@ -444,22 +444,8 @@ */ static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd) { - unsigned long flags; - - spin_lock_irqsave(q->queue_lock, flags); - cmd->request->special = cmd; - if (blk_rq_tagged(cmd->request)) - blk_queue_end_tag(q, cmd->request); - - /* - * set REQ_SPECIAL - we have a command - * clear REQ_DONTPREP - we assume the sg table has been - * nuked so we need to set it up again. - */ - cmd->request->flags |= REQ_SPECIAL; cmd->request->flags &= ~REQ_DONTPREP; - __elv_add_request(q, cmd->request, 0, 0); - spin_unlock_irqrestore(q->queue_lock, flags); + blk_insert_request(q, cmd->request, 1, cmd); scsi_run_queue(q); } @@ -1213,9 +1199,7 @@ * later time. */ spin_lock_irq(q->queue_lock); - if (blk_rq_tagged(req)) - blk_queue_end_tag(q, req); - __elv_add_request(q, req, 0, 0); + blk_requeue_request(q, req); sdev->device_busy--; if(sdev->device_busy == 0) blk_plug_device(q); @@ -1426,17 +1410,17 @@ if(scsi_status_is_good(sreq->sr_result)) { data->header_length = header_length; if(use_10_for_ms) { - data->length = buffer[0]*256 + buffer[1]; + data->length = buffer[0]*256 + buffer[1] + 2; data->medium_type = buffer[2]; data->device_specific = buffer[3]; data->longlba = buffer[4] & 0x01; data->block_descriptor_length = buffer[6]*256 + buffer[7]; } else { - data->length = buffer[0]; + data->length = buffer[0] + 1; data->medium_type = buffer[1]; - data->device_specific = buffer[3]; - data->block_descriptor_length = buffer[4]; + data->device_specific = buffer[2]; + data->block_descriptor_length = buffer[3]; } } diff -Nru a/drivers/scsi/scsi_module.c b/drivers/scsi/scsi_module.c --- a/drivers/scsi/scsi_module.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/scsi_module.c Sat Jul 19 12:54:24 2003 @@ -40,6 +40,7 @@ error = scsi_add_host(shost, NULL); if (error) goto fail; + scsi_scan_host(shost); } return 0; fail: diff -Nru a/drivers/scsi/scsi_pc98.c b/drivers/scsi/scsi_pc98.c --- a/drivers/scsi/scsi_pc98.c Sat Jul 19 12:54:21 2003 +++ b/drivers/scsi/scsi_pc98.c Sat Jul 19 12:54:21 2003 @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include "scsi.h" diff -Nru a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h --- a/drivers/scsi/scsi_priv.h Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/scsi_priv.h Sat Jul 19 12:54:26 2003 @@ -102,7 +102,6 @@ #endif /* CONFIG_PROC_FS */ /* scsi_scan.c */ -extern void scsi_scan_host(struct Scsi_Host *); extern void scsi_forget_host(struct Scsi_Host *); extern void scsi_free_sdev(struct scsi_device *); extern void scsi_free_shost(struct Scsi_Host *); @@ -116,11 +115,6 @@ extern void scsi_sysfs_remove_host(struct Scsi_Host *); extern int scsi_sysfs_register(void); extern void scsi_sysfs_unregister(void); - -/* definitions for the linker default sections covering the host - * class and device attributes */ -extern struct class_device_attribute *scsi_sysfs_shost_attrs[]; -extern struct device_attribute *scsi_sysfs_sdev_attrs[]; extern struct class shost_class; extern struct bus_type scsi_bus_type; diff -Nru a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c --- a/drivers/scsi/scsi_proc.c Sat Jul 19 12:54:22 2003 +++ b/drivers/scsi/scsi_proc.c Sat Jul 19 12:54:22 2003 @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c --- a/drivers/scsi/scsi_scan.c Sat Jul 19 12:54:27 2003 +++ b/drivers/scsi/scsi_scan.c Sat Jul 19 12:54:27 2003 @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include "scsi.h" #include "hosts.h" @@ -464,8 +464,7 @@ while (i >= 0 && type[i] == ' ') type[i--] = '\0'; - snprintf(sdev->sdev_driverfs_dev.name, DEVICE_NAME_SIZE, "SCSI %s", - type); + snprintf(sdev->sdev_gendev.name, DEVICE_NAME_SIZE, "SCSI %s", type); } /** diff -Nru a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c --- a/drivers/scsi/scsi_syms.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/scsi_syms.c Sat Jul 19 12:54:25 2003 @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include @@ -34,6 +34,7 @@ EXPORT_SYMBOL(scsi_register_interface); EXPORT_SYMBOL(scsi_host_alloc); EXPORT_SYMBOL(scsi_add_host); +EXPORT_SYMBOL(scsi_scan_host); EXPORT_SYMBOL(scsi_remove_host); EXPORT_SYMBOL(scsi_host_get); EXPORT_SYMBOL(scsi_host_put); diff -Nru a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c --- a/drivers/scsi/scsi_sysfs.c Sat Jul 19 12:54:23 2003 +++ b/drivers/scsi/scsi_sysfs.c Sat Jul 19 12:54:23 2003 @@ -45,7 +45,7 @@ shost_rd_attr(sg_tablesize, "%hu\n"); shost_rd_attr(unchecked_isa_dma, "%d\n"); -struct class_device_attribute *scsi_sysfs_shost_attrs[] = { +static struct class_device_attribute *scsi_sysfs_shost_attrs[] = { &class_device_attr_unique_id, &class_device_attr_host_busy, &class_device_attr_cmd_per_lun, @@ -204,7 +204,7 @@ static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field) /* Default template for device attributes. May NOT be modified */ -struct device_attribute *scsi_sysfs_sdev_attrs[] = { +static struct device_attribute *scsi_sysfs_sdev_attrs[] = { &dev_attr_device_blocked, &dev_attr_queue_depth, &dev_attr_type, @@ -228,6 +228,42 @@ scsi_free_sdev(sdev); } +static struct device_attribute *attr_overridden( + struct device_attribute **attrs, + struct device_attribute *attr) +{ + int i; + + if (!attrs) + return NULL; + for (i = 0; attrs[i]; i++) + if (!strcmp(attrs[i]->attr.name, attr->attr.name)) + return attrs[i]; + return NULL; +} + +static int attr_add(struct device *dev, struct device_attribute *attr) +{ + struct device_attribute *base_attr; + + /* + * Spare the caller from having to copy things it's not interested in. + */ + base_attr = attr_overridden(scsi_sysfs_sdev_attrs, attr); + if (base_attr) { + /* extend permissions */ + attr->attr.mode |= base_attr->attr.mode; + + /* override null show/store with default */ + if (!attr->show) + attr->show = base_attr->show; + if (!attr->store) + attr->store = base_attr->store; + } + + return device_create_file(dev, attr); +} + /** * scsi_device_register - register a scsi device with the scsi bus * @sdev: scsi_device to register @@ -239,20 +275,20 @@ { int error = 0, i; - device_initialize(&sdev->sdev_driverfs_dev); - sprintf(sdev->sdev_driverfs_dev.bus_id,"%d:%d:%d:%d", + device_initialize(&sdev->sdev_gendev); + sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); - sdev->sdev_driverfs_dev.parent = &sdev->host->host_gendev; - sdev->sdev_driverfs_dev.bus = &scsi_bus_type; - sdev->sdev_driverfs_dev.release = scsi_device_release; + sdev->sdev_gendev.parent = &sdev->host->shost_gendev; + sdev->sdev_gendev.bus = &scsi_bus_type; + sdev->sdev_gendev.release = scsi_device_release; class_device_initialize(&sdev->sdev_classdev); - sdev->sdev_classdev.dev = &sdev->sdev_driverfs_dev; + sdev->sdev_classdev.dev = &sdev->sdev_gendev; sdev->sdev_classdev.class = &sdev_class; snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE, "%d:%d:%d:%d", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); - error = device_add(&sdev->sdev_driverfs_dev); + error = device_add(&sdev->sdev_gendev); if (error) { printk(KERN_INFO "error 1\n"); return error; @@ -260,16 +296,28 @@ error = class_device_add(&sdev->sdev_classdev); if (error) { printk(KERN_INFO "error 2\n"); - device_unregister(&sdev->sdev_driverfs_dev); + device_unregister(&sdev->sdev_gendev); return error; } - for (i = 0; !error && sdev->host->hostt->sdev_attrs[i] != NULL; i++) - error = device_create_file(&sdev->sdev_driverfs_dev, - sdev->host->hostt->sdev_attrs[i]); - - if (error) - scsi_device_unregister(sdev); + if (sdev->host->hostt->sdev_attrs) { + for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) { + error = attr_add(&sdev->sdev_gendev, + sdev->host->hostt->sdev_attrs[i]); + if (error) + scsi_device_unregister(sdev); + } + } + + for (i = 0; scsi_sysfs_sdev_attrs[i]; i++) { + if (!attr_overridden(sdev->host->hostt->sdev_attrs, + scsi_sysfs_sdev_attrs[i])) { + error = device_create_file(&sdev->sdev_gendev, + scsi_sysfs_sdev_attrs[i]); + if (error) + scsi_device_unregister(sdev); + } + } return error; } @@ -280,12 +328,8 @@ **/ void scsi_device_unregister(struct scsi_device *sdev) { - int i; - - for (i = 0; sdev->host->hostt->sdev_attrs[i] != NULL; i++) - device_remove_file(&sdev->sdev_driverfs_dev, sdev->host->hostt->sdev_attrs[i]); class_device_unregister(&sdev->sdev_classdev); - device_unregister(&sdev->sdev_driverfs_dev); + device_unregister(&sdev->sdev_gendev); } int scsi_register_driver(struct device_driver *drv) @@ -315,20 +359,57 @@ void scsi_sysfs_init_host(struct Scsi_Host *shost) { - device_initialize(&shost->host_gendev); - snprintf(shost->host_gendev.bus_id, BUS_ID_SIZE, "host%d", + device_initialize(&shost->shost_gendev); + snprintf(shost->shost_gendev.bus_id, BUS_ID_SIZE, "host%d", shost->host_no); - snprintf(shost->host_gendev.name, DEVICE_NAME_SIZE, "%s", + snprintf(shost->shost_gendev.name, DEVICE_NAME_SIZE, "%s", shost->hostt->proc_name); - shost->host_gendev.release = scsi_host_release; + shost->shost_gendev.release = scsi_host_release; - class_device_initialize(&shost->class_dev); - shost->class_dev.dev = &shost->host_gendev; - shost->class_dev.class = &shost_class; - snprintf(shost->class_dev.class_id, BUS_ID_SIZE, "host%d", + class_device_initialize(&shost->shost_classdev); + shost->shost_classdev.dev = &shost->shost_gendev; + shost->shost_classdev.class = &shost_class; + snprintf(shost->shost_classdev.class_id, BUS_ID_SIZE, "host%d", shost->host_no); } +static struct class_device_attribute *class_attr_overridden( + struct class_device_attribute **attrs, + struct class_device_attribute *attr) +{ + int i; + + if (!attrs) + return NULL; + for (i = 0; attrs[i]; i++) + if (!strcmp(attrs[i]->attr.name, attr->attr.name)) + return attrs[i]; + return NULL; +} + +static int class_attr_add(struct class_device *classdev, + struct class_device_attribute *attr) +{ + struct class_device_attribute *base_attr; + + /* + * Spare the caller from having to copy things it's not interested in. + */ + base_attr = class_attr_overridden(scsi_sysfs_shost_attrs, attr); + if (base_attr) { + /* extend permissions */ + attr->attr.mode |= base_attr->attr.mode; + + /* override null show/store with default */ + if (!attr->show) + attr->show = base_attr->show; + if (!attr->store) + attr->store = base_attr->store; + } + + return class_device_create_file(classdev, attr); +} + /** * scsi_sysfs_add_host - add scsi host to subsystem * @shost: scsi host struct to add to subsystem @@ -336,31 +417,44 @@ **/ int scsi_sysfs_add_host(struct Scsi_Host *shost, struct device *dev) { - int i, error; + int error, i; - if (!shost->host_gendev.parent) - shost->host_gendev.parent = dev ? dev : &legacy_bus; + if (!shost->shost_gendev.parent) + shost->shost_gendev.parent = dev ? dev : &legacy_bus; - error = device_add(&shost->host_gendev); + error = device_add(&shost->shost_gendev); if (error) return error; - error = class_device_add(&shost->class_dev); + error = class_device_add(&shost->shost_classdev); if (error) goto clean_device; - for (i = 0; !error && shost->hostt->shost_attrs[i] != NULL; i++) - error = class_device_create_file(&shost->class_dev, - shost->hostt->shost_attrs[i]); - if (error) - goto clean_class; + if (shost->hostt->shost_attrs) { + for (i = 0; shost->hostt->shost_attrs[i]; i++) { + error = class_attr_add(&shost->shost_classdev, + shost->hostt->shost_attrs[i]); + if (error) + goto clean_class; + } + } + + for (i = 0; scsi_sysfs_shost_attrs[i]; i++) { + if (!class_attr_overridden(shost->hostt->shost_attrs, + scsi_sysfs_shost_attrs[i])) { + error = class_device_create_file(&shost->shost_classdev, + scsi_sysfs_shost_attrs[i]); + if (error) + goto clean_class; + } + } return error; clean_class: - class_device_del(&shost->class_dev); + class_device_del(&shost->shost_classdev); clean_device: - device_del(&shost->host_gendev); + device_del(&shost->shost_gendev); return error; } @@ -371,133 +465,6 @@ **/ void scsi_sysfs_remove_host(struct Scsi_Host *shost) { - class_device_del(&shost->class_dev); - device_del(&shost->host_gendev); -} - -/** scsi_sysfs_modify_shost_attribute - modify or add a host class attribute - * - * @class_attrs:host class attribute list to be added to or modified - * @attr: individual attribute to change or added - * - * returns zero if successful or error if not - **/ -int scsi_sysfs_modify_shost_attribute( - struct class_device_attribute ***class_attrs, - struct class_device_attribute *attr) -{ - int modify = -1; - int num_attrs; - - if(*class_attrs == NULL) - *class_attrs = scsi_sysfs_shost_attrs; - - for(num_attrs=0; (*class_attrs)[num_attrs] != NULL; num_attrs++) - if(strcmp((*class_attrs)[num_attrs]->attr.name, - attr->attr.name) == 0) - modify = num_attrs; - - if(*class_attrs == scsi_sysfs_shost_attrs || modify < 0) { - /* note: need space for null at the end as well */ - struct class_device_attribute **tmp_attrs = - kmalloc(sizeof(*tmp_attrs) * - (num_attrs + (modify >= 0 ? 1 : 2)), - GFP_KERNEL); - if(tmp_attrs == NULL) - return -ENOMEM; - memcpy(tmp_attrs, *class_attrs, sizeof(*tmp_attrs) * - (num_attrs + 1)); - if(*class_attrs != scsi_sysfs_shost_attrs) - kfree(*class_attrs); - *class_attrs = tmp_attrs; - } - if(modify >= 0) { - /* spare the caller from having to copy things it's - * not interested in */ - struct class_device_attribute *old_attr = - (*class_attrs)[modify]; - /* extend permissions */ - attr->attr.mode |= old_attr->attr.mode; - - /* override null show/store with default */ - if(attr->show == NULL) - attr->show = old_attr->show; - if(attr->store == NULL) - attr->store = old_attr->store; - (*class_attrs)[modify] = attr; - } else { - (*class_attrs)[num_attrs++] = attr; - (*class_attrs)[num_attrs] = NULL; - } - - return 0; -} -EXPORT_SYMBOL(scsi_sysfs_modify_shost_attribute); - -/** scsi_sysfs_modify_sdev_attribute - modify or add a host device attribute - * - * @dev_attrs: pointer to the attribute list to be added to or modified - * @attr: individual attribute to change or added - * - * returns zero if successful or error if not - **/ -int scsi_sysfs_modify_sdev_attribute(struct device_attribute ***dev_attrs, - struct device_attribute *attr) -{ - int modify = -1; - int num_attrs; - - if(*dev_attrs == NULL) - *dev_attrs = scsi_sysfs_sdev_attrs; - - for(num_attrs=0; (*dev_attrs)[num_attrs] != NULL; num_attrs++) - if(strcmp((*dev_attrs)[num_attrs]->attr.name, - attr->attr.name) == 0) - modify = num_attrs; - - if(*dev_attrs == scsi_sysfs_sdev_attrs || modify < 0) { - /* note: need space for null at the end as well */ - struct device_attribute **tmp_attrs = - kmalloc(sizeof(*tmp_attrs) * - (num_attrs + (modify >= 0 ? 1 : 2)), - GFP_KERNEL); - if(tmp_attrs == NULL) - return -ENOMEM; - memcpy(tmp_attrs, *dev_attrs, sizeof(*tmp_attrs) * - (num_attrs + 1)); - if(*dev_attrs != scsi_sysfs_sdev_attrs) - kfree(*dev_attrs); - *dev_attrs = tmp_attrs; - } - if(modify >= 0) { - /* spare the caller from having to copy things it's - * not interested in */ - struct device_attribute *old_attr = - (*dev_attrs)[modify]; - /* extend permissions */ - attr->attr.mode |= old_attr->attr.mode; - - /* override null show/store with default */ - if(attr->show == NULL) - attr->show = old_attr->show; - if(attr->store == NULL) - attr->store = old_attr->store; - (*dev_attrs)[modify] = attr; - } else { - (*dev_attrs)[num_attrs++] = attr; - (*dev_attrs)[num_attrs] = NULL; - } - - return 0; -} -EXPORT_SYMBOL(scsi_sysfs_modify_sdev_attribute); - -void scsi_sysfs_release_attributes(struct scsi_host_template *hostt) -{ - if(hostt->sdev_attrs != scsi_sysfs_sdev_attrs) - kfree(hostt->sdev_attrs); - - if(hostt->shost_attrs != scsi_sysfs_shost_attrs) - kfree(hostt->shost_attrs); + class_device_del(&shost->shost_classdev); + device_del(&shost->shost_gendev); } -EXPORT_SYMBOL(scsi_sysfs_release_attributes); diff -Nru a/drivers/scsi/scsicam.c b/drivers/scsi/scsicam.c --- a/drivers/scsi/scsicam.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/scsicam.c Sat Jul 19 12:54:25 2003 @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include "scsi.h" diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c --- a/drivers/scsi/sd.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/sd.c Sat Jul 19 12:54:26 2003 @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include @@ -606,35 +606,8 @@ static void sd_rescan(struct device *dev) { - struct scsi_device *sdp = to_scsi_device(dev); struct scsi_disk *sdkp = dev_get_drvdata(dev); - struct gendisk *gd; - struct scsi_request *SRpnt; - unsigned char *buffer; - - if (!sdkp || sdp->online == FALSE || !sdkp->media_present) - return; - - gd = sdkp->disk; - - SCSI_LOG_HLQUEUE(3, printk("sd_rescan: disk=%s\n", gd->disk_name)); - - SRpnt = scsi_allocate_request(sdp); - if (!SRpnt) { - printk(KERN_WARNING "(sd_rescan:) Request allocation " - "failure.\n"); - return; - } - - if (sdkp->device->host->unchecked_isa_dma) - buffer = kmalloc(512, GFP_DMA); - else - buffer = kmalloc(512, GFP_KERNEL); - - sd_read_capacity(sdkp, gd->disk_name, SRpnt, buffer); - set_capacity(gd, sdkp->capacity); - scsi_release_request(SRpnt); - kfree(buffer); + sd_revalidate_disk(sdkp->disk); } static struct block_device_operations sd_fops = { @@ -1318,7 +1291,7 @@ sd_revalidate_disk(gd); - gd->driverfs_dev = &sdp->sdev_driverfs_dev; + gd->driverfs_dev = &sdp->sdev_gendev; gd->flags = GENHD_FL_DRIVERFS; if (sdp->removable) gd->flags |= GENHD_FL_REMOVABLE; diff -Nru a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c --- a/drivers/scsi/seagate.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/seagate.c Sat Jul 19 12:54:24 2003 @@ -95,7 +95,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c --- a/drivers/scsi/sg.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/sg.c Sat Jul 19 12:54:25 2003 @@ -61,7 +61,7 @@ #include #include -#include +#include #include "scsi.h" #include "hosts.h" #include diff -Nru a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c --- a/drivers/scsi/sgiwd93.c Sat Jul 19 12:54:29 2003 +++ b/drivers/scsi/sgiwd93.c Sat Jul 19 12:54:29 2003 @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c --- a/drivers/scsi/sim710.c Sat Jul 19 12:54:27 2003 +++ b/drivers/scsi/sim710.c Sat Jul 19 12:54:27 2003 @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include #include @@ -138,7 +138,8 @@ goto out_unregister; } - scsi_add_host(host, dev); + scsi_add_host(host, dev); /* XXX handle failure */ + scsi_scan_host(host); hostdata->dev = dev; return 0; diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c --- a/drivers/scsi/sr.c Sat Jul 19 12:54:23 2003 +++ b/drivers/scsi/sr.c Sat Jul 19 12:54:23 2003 @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include "scsi.h" @@ -533,7 +533,7 @@ snprintf(disk->devfs_name, sizeof(disk->devfs_name), "%s/cd", sdev->devfs_name); - disk->driverfs_dev = &sdev->sdev_driverfs_dev; + disk->driverfs_dev = &sdev->sdev_gendev; register_cdrom(&cd->cdi); set_capacity(disk, cd->capacity); disk->private_data = &cd->driver; diff -Nru a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c --- a/drivers/scsi/sr_ioctl.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/sr_ioctl.c Sat Jul 19 12:54:26 2003 @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c --- a/drivers/scsi/sr_vendor.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/sr_vendor.c Sat Jul 19 12:54:25 2003 @@ -39,7 +39,7 @@ #include #include -#include +#include #include "scsi.h" #include "hosts.h" #include diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c --- a/drivers/scsi/st.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/st.c Sat Jul 19 12:54:26 2003 @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c --- a/drivers/scsi/sun3_scsi.c Sat Jul 19 12:54:22 2003 +++ b/drivers/scsi/sun3_scsi.c Sat Jul 19 12:54:22 2003 @@ -61,7 +61,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c --- a/drivers/scsi/sun3_scsi_vme.c Sat Jul 19 12:54:30 2003 +++ b/drivers/scsi/sun3_scsi_vme.c Sat Jul 19 12:54:30 2003 @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c --- a/drivers/scsi/sun3x_esp.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/sun3x_esp.c Sat Jul 19 12:54:26 2003 @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c --- a/drivers/scsi/sym53c416.c Sat Jul 19 12:54:23 2003 +++ b/drivers/scsi/sym53c416.c Sat Jul 19 12:54:23 2003 @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include #include "scsi.h" diff -Nru a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c --- a/drivers/scsi/sym53c8xx.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/sym53c8xx.c Sat Jul 19 12:54:26 2003 @@ -123,7 +123,7 @@ #include #include -#include +#include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,35) #include @@ -1327,7 +1327,7 @@ #define SetScsiAbortResult(cmd) SetScsiResult(cmd, DID_ABORT, 0xff) #endif -static void sym53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs); +static irqreturn_t sym53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs); static void sym53c8xx_timeout(unsigned long np); #define initverbose (driver_setup.verbose) @@ -7374,7 +7374,7 @@ } if (cp->xerr_status & XE_BAD_PHASE) { PRINT_ADDR(cmd); - printk ("illegal scsi phase (4/5).\n"); + printk ("invalid scsi phase (4/5).\n"); } if (cp->xerr_status & XE_SODL_UNRUN) { PRINT_ADDR(cmd); @@ -13660,7 +13660,7 @@ ** routine for each host that uses this IRQ. */ -static void sym53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs) +static irqreturn_t sym53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs) { unsigned long flags; ncb_p np = (ncb_p) dev_id; @@ -13685,6 +13685,7 @@ ncr_flush_done_cmds(done_list); NCR_UNLOCK_SCSI_DONE(done_list->device->host, flags); } + return IRQ_HANDLED; } /* diff -Nru a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c --- a/drivers/scsi/sym53c8xx_2/sym_glue.c Sat Jul 19 12:54:30 2003 +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c Sat Jul 19 12:54:30 2003 @@ -1110,6 +1110,7 @@ int sts = -1; struct sym_eh_wait eh, *ep = &eh; char devname[20]; + unsigned long flags; sprintf(devname, "%s:%d:%d", sym_name(np), cmd->device->id, cmd->device->lun); @@ -1201,7 +1202,11 @@ ep->timer.data = (u_long)cmd; ep->timed_out = 1; /* Be pessimistic for once :) */ add_timer(&ep->timer); + local_save_flags(flags); + spin_unlock_irq(cmd->device->host->host_lock); down(&ep->sem); + local_irq_restore(flags); + spin_lock(cmd->device->host->host_lock); if (ep->timed_out) sts = -2; } diff -Nru a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h --- a/drivers/scsi/sym53c8xx_2/sym_glue.h Sat Jul 19 12:54:30 2003 +++ b/drivers/scsi/sym53c8xx_2/sym_glue.h Sat Jul 19 12:54:30 2003 @@ -84,7 +84,7 @@ #include #include -#include +#include #ifdef __sparc__ # include diff -Nru a/drivers/scsi/t128.c b/drivers/scsi/t128.c --- a/drivers/scsi/t128.c Sat Jul 19 12:54:27 2003 +++ b/drivers/scsi/t128.c Sat Jul 19 12:54:27 2003 @@ -110,7 +110,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c --- a/drivers/scsi/tmscsim.c Sat Jul 19 12:54:30 2003 +++ b/drivers/scsi/tmscsim.c Sat Jul 19 12:54:30 2003 @@ -224,7 +224,7 @@ #include #include #include -#include +#include #include #include "scsi.h" diff -Nru a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c --- a/drivers/scsi/u14-34f.c Sat Jul 19 12:54:24 2003 +++ b/drivers/scsi/u14-34f.c Sat Jul 19 12:54:24 2003 @@ -414,7 +414,7 @@ #include #include #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c --- a/drivers/scsi/ultrastor.c Sat Jul 19 12:54:25 2003 +++ b/drivers/scsi/ultrastor.c Sat Jul 19 12:54:25 2003 @@ -128,7 +128,7 @@ */ #include -#include +#include #include #include #include diff -Nru a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c --- a/drivers/scsi/wd33c93.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/wd33c93.c Sat Jul 19 12:54:26 2003 @@ -79,7 +79,7 @@ #include #include #include -#include +#include #include #include "scsi.h" diff -Nru a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c --- a/drivers/scsi/wd7000.c Sat Jul 19 12:54:30 2003 +++ b/drivers/scsi/wd7000.c Sat Jul 19 12:54:30 2003 @@ -174,7 +174,7 @@ #include #include #include -#include +#include #include #include diff -Nru a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c --- a/drivers/scsi/zalon.c Sat Jul 19 12:54:26 2003 +++ b/drivers/scsi/zalon.c Sat Jul 19 12:54:26 2003 @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include @@ -85,7 +85,7 @@ { struct gsc_irq gsc_irq; u32 zalon_vers; - int irq; + int irq, error = -ENODEV; unsigned long zalon = dev->hpa; unsigned long io_port = zalon + GSC_SCSI_ZALON_OFFSET; static int unit = 0; @@ -147,11 +147,18 @@ dev_set_drvdata(&dev->dev, host); - scsi_add_host(host, &dev->dev); + error = scsi_add_host(host, &dev->dev); + if (error) + goto fail_free_irq; + scsi_scan_host(host); return 0; + + fail_free_irq: + free_irq(irq, host); fail: - return -ENODEV; + ncr53c8xx_release(host); + return error; } static struct parisc_device_id zalon_tbl[] = { diff -Nru a/drivers/serial/Kconfig b/drivers/serial/Kconfig --- a/drivers/serial/Kconfig Sat Jul 19 12:54:28 2003 +++ b/drivers/serial/Kconfig Sat Jul 19 12:54:28 2003 @@ -404,14 +404,19 @@ on your Sparc system as the console, you can do so by answering Y to this option. -config V850E_NB85E_UART +config V850E_UART bool "NEC V850E on-chip UART support" - depends on V850E_NB85E || V850E2_ANNA || V850E_AS85EP1 + depends on V850E_MA1 || V850E_ME2 || V850E_TEG || V850E2_ANNA || V850E_AS85EP1 default y -config V850E_NB85E_UART_CONSOLE +config V850E_UARTB + bool + depends V850E_UART && V850E_ME2 + default y + +config V850E_UART_CONSOLE bool "Use NEC V850E on-chip UART for console" - depends on V850E_NB85E_UART + depends on V850E_UART config SERIAL98 tristate "PC-9800 8251-based primary serial port support" @@ -426,12 +431,12 @@ config SERIAL_CORE tristate - default m if SERIAL_AMBA!=y && SERIAL_CLPS711X!=y && SERIAL_21285!=y && !SERIAL_SA1100 && !SERIAL_ANAKIN && !SERIAL_UART00 && SERIAL_8250!=y && SERIAL_MUX!=y && !SERIAL_ROCKETPORT && !SERIAL_SUNCORE && !V850E_NB85E_UART && (SERIAL_AMBA=m || SERIAL_CLPS711X=m || SERIAL_21285=m || SERIAL_8250=m || SERIAL_MUX=m || SERIAL98=m) - default y if SERIAL_AMBA=y || SERIAL_CLPS711X=y || SERIAL_21285=y || SERIAL_SA1100 || SERIAL_ANAKIN || SERIAL_UART00 || SERIAL_8250=y || SERIAL_MUX=y || SERIAL_ROCKETPORT || SERIAL_SUNCORE || V850E_NB85E_UART || SERIAL98=y + default m if SERIAL_AMBA!=y && SERIAL_CLPS711X!=y && SERIAL_21285!=y && !SERIAL_SA1100 && !SERIAL_ANAKIN && !SERIAL_UART00 && SERIAL_8250!=y && SERIAL_MUX!=y && !SERIAL_ROCKETPORT && !SERIAL_SUNCORE && !V850E_UART && (SERIAL_AMBA=m || SERIAL_CLPS711X=m || SERIAL_21285=m || SERIAL_8250=m || SERIAL_MUX=m || SERIAL98=m) + default y if SERIAL_AMBA=y || SERIAL_CLPS711X=y || SERIAL_21285=y || SERIAL_SA1100 || SERIAL_ANAKIN || SERIAL_UART00 || SERIAL_8250=y || SERIAL_MUX=y || SERIAL_ROCKETPORT || SERIAL_SUNCORE || V850E_UART || SERIAL98=y config SERIAL_CORE_CONSOLE bool - depends on SERIAL_AMBA_CONSOLE || SERIAL_CLPS711X_CONSOLE || SERIAL_21285_CONSOLE || SERIAL_SA1100_CONSOLE || SERIAL_ANAKIN_CONSOLE || SERIAL_UART00_CONSOLE || SERIAL_8250_CONSOLE || SERIAL_MUX_CONSOLE || SERIAL_SUNZILOG_CONSOLE || SERIAL_SUNSU_CONSOLE || SERIAL_SUNSAB_CONSOLE || V850E_NB85E_UART_CONSOLE || SERIAL98_CONSOLE + depends on SERIAL_AMBA_CONSOLE || SERIAL_CLPS711X_CONSOLE || SERIAL_21285_CONSOLE || SERIAL_SA1100_CONSOLE || SERIAL_ANAKIN_CONSOLE || SERIAL_UART00_CONSOLE || SERIAL_8250_CONSOLE || SERIAL_MUX_CONSOLE || SERIAL_SUNZILOG_CONSOLE || SERIAL_SUNSU_CONSOLE || SERIAL_SUNSAB_CONSOLE || V850E_UART_CONSOLE || SERIAL98_CONSOLE default y config SERIAL_68328 diff -Nru a/drivers/serial/Makefile b/drivers/serial/Makefile --- a/drivers/serial/Makefile Sat Jul 19 12:54:25 2003 +++ b/drivers/serial/Makefile Sat Jul 19 12:54:25 2003 @@ -29,5 +29,5 @@ obj-$(CONFIG_SERIAL_68328) += 68328serial.o obj-$(CONFIG_SERIAL_68360) += 68360serial.o obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o -obj-$(CONFIG_V850E_NB85E_UART) += nb85e_uart.o +obj-$(CONFIG_V850E_UART) += v850e_uart.o obj-$(CONFIG_SERIAL98) += serial98.o diff -Nru a/drivers/serial/core.c b/drivers/serial/core.c --- a/drivers/serial/core.c Sat Jul 19 12:54:23 2003 +++ b/drivers/serial/core.c Sat Jul 19 12:54:23 2003 @@ -1667,23 +1667,25 @@ return ret + 1; } - status = port->ops->get_mctrl(port); - - ret += sprintf(buf + ret, " tx:%d rx:%d", - port->icount.tx, port->icount.rx); - if (port->icount.frame) - ret += sprintf(buf + ret, " fe:%d", - port->icount.frame); - if (port->icount.parity) - ret += sprintf(buf + ret, " pe:%d", - port->icount.parity); - if (port->icount.brk) - ret += sprintf(buf + ret, " brk:%d", - port->icount.brk); - if (port->icount.overrun) - ret += sprintf(buf + ret, " oe:%d", - port->icount.overrun); + if(capable(CAP_SYS_ADMIN)) + { + status = port->ops->get_mctrl(port); + ret += sprintf(buf + ret, " tx:%d rx:%d", + port->icount.tx, port->icount.rx); + if (port->icount.frame) + ret += sprintf(buf + ret, " fe:%d", + port->icount.frame); + if (port->icount.parity) + ret += sprintf(buf + ret, " pe:%d", + port->icount.parity); + if (port->icount.brk) + ret += sprintf(buf + ret, " brk:%d", + port->icount.brk); + if (port->icount.overrun) + ret += sprintf(buf + ret, " oe:%d", + port->icount.overrun); + #define INFOBIT(bit,str) \ if (port->mctrl & (bit)) \ strncat(stat_buf, (str), sizeof(stat_buf) - \ @@ -1693,19 +1695,22 @@ strncat(stat_buf, (str), sizeof(stat_buf) - \ strlen(stat_buf) - 2) - stat_buf[0] = '\0'; - stat_buf[1] = '\0'; - INFOBIT(TIOCM_RTS, "|RTS"); - STATBIT(TIOCM_CTS, "|CTS"); - INFOBIT(TIOCM_DTR, "|DTR"); - STATBIT(TIOCM_DSR, "|DSR"); - STATBIT(TIOCM_CAR, "|CD"); - STATBIT(TIOCM_RNG, "|RI"); - if (stat_buf[0]) - stat_buf[0] = ' '; - strcat(stat_buf, "\n"); - - ret += sprintf(buf + ret, stat_buf); + stat_buf[0] = '\0'; + stat_buf[1] = '\0'; + INFOBIT(TIOCM_RTS, "|RTS"); + STATBIT(TIOCM_CTS, "|CTS"); + INFOBIT(TIOCM_DTR, "|DTR"); + STATBIT(TIOCM_DSR, "|DSR"); + STATBIT(TIOCM_CAR, "|CD"); + STATBIT(TIOCM_RNG, "|RI"); + if (stat_buf[0]) + stat_buf[0] = ' '; + strcat(stat_buf, "\n"); + + ret += sprintf(buf + ret, stat_buf); + } +#undef STATBIT +#undef INFOBIT return ret; } diff -Nru a/drivers/serial/nb85e_uart.c b/drivers/serial/nb85e_uart.c --- a/drivers/serial/nb85e_uart.c Sat Jul 19 12:54:27 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,610 +0,0 @@ -/* - * drivers/serial/nb85e_uart.c -- Serial I/O using V850E/NB85E on-chip UART - * - * Copyright (C) 2001,02,03 NEC Corporation - * Copyright (C) 2001,02,03 Miles Bader - * - * 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. - * - * Written by Miles Bader - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/* Initial UART state. This may be overridden by machine-dependent headers. */ -#ifndef NB85E_UART_INIT_BAUD -#define NB85E_UART_INIT_BAUD 115200 -#endif -#ifndef NB85E_UART_INIT_CFLAGS -#define NB85E_UART_INIT_CFLAGS (B115200 | CS8 | CREAD) -#endif - -/* XXX This should be in a header file. */ -#define NB85E_UART_BRGC_MIN 8 - -/* A string used for prefixing printed descriptions; since the same UART - macro is actually used on other chips than the V850E/NB85E. This must - be a constant string. */ -#ifndef NB85E_UART_CHIP_NAME -#define NB85E_UART_CHIP_NAME "V850E/NB85E" -#endif - - -/* Helper functions for doing baud-rate/frequency calculations. */ - -/* Calculate the minimum value for CKSR on this processor. */ -static inline unsigned cksr_min (void) -{ - int min = 0; - unsigned freq = NB85E_UART_BASE_FREQ; - while (freq > NB85E_UART_CKSR_MAX_FREQ) { - freq >>= 1; - min++; - } - return min; -} - -/* Minimum baud rate possible. */ -#define min_baud() \ - ((NB85E_UART_BASE_FREQ >> NB85E_UART_CKSR_MAX) / (2 * 255) + 1) - -/* Maximum baud rate possible. The error is quite high at max, though. */ -#define max_baud() \ - ((NB85E_UART_BASE_FREQ >> cksr_min()) / (2 * NB85E_UART_BRGC_MIN)) - - -/* Low-level UART functions. */ - -/* These masks define which control bits affect TX/RX modes, respectively. */ -#define RX_BITS \ - (NB85E_UART_ASIM_PS_MASK | NB85E_UART_ASIM_CL_8 | NB85E_UART_ASIM_ISRM) -#define TX_BITS \ - (NB85E_UART_ASIM_PS_MASK | NB85E_UART_ASIM_CL_8 | NB85E_UART_ASIM_SL_2) - -/* The UART require various delays after writing control registers. */ -static inline void nb85e_uart_delay (unsigned cycles) -{ - /* The loop takes 2 insns, so loop CYCLES / 2 times. */ - register unsigned count = cycles >> 1; - while (--count != 0) - /* nothing */; -} - -/* Configure and turn on uart channel CHAN, using the termios `control - modes' bits in CFLAGS, and a baud-rate of BAUD. */ -void nb85e_uart_configure (unsigned chan, unsigned cflags, unsigned baud) -{ - int flags; - unsigned new_config = 0; /* What we'll write to the control reg. */ - unsigned new_clk_divlog2; /* New baud-rate generate clock divider. */ - unsigned new_brgen_count; /* New counter max for baud-rate generator.*/ - /* These are the current values corresponding to the above. */ - unsigned old_config, old_clk_divlog2, old_brgen_count; - - /* Calculate new baud-rate generator config values. */ - - /* Calculate the log2 clock divider and baud-rate counter values - (note that the UART divides the resulting clock by 2, so - multiply BAUD by 2 here to compensate). */ - calc_counter_params (NB85E_UART_BASE_FREQ, baud * 2, - cksr_min(), NB85E_UART_CKSR_MAX, 8/*bits*/, - &new_clk_divlog2, &new_brgen_count); - - /* Figure out new configuration of control register. */ - if (cflags & CSTOPB) - /* Number of stop bits, 1 or 2. */ - new_config |= NB85E_UART_ASIM_SL_2; - if ((cflags & CSIZE) == CS8) - /* Number of data bits, 7 or 8. */ - new_config |= NB85E_UART_ASIM_CL_8; - if (! (cflags & PARENB)) - /* No parity check/generation. */ - new_config |= NB85E_UART_ASIM_PS_NONE; - else if (cflags & PARODD) - /* Odd parity check/generation. */ - new_config |= NB85E_UART_ASIM_PS_ODD; - else - /* Even parity check/generation. */ - new_config |= NB85E_UART_ASIM_PS_EVEN; - if (cflags & CREAD) - /* Reading enabled. */ - new_config |= NB85E_UART_ASIM_RXE; - - new_config |= NB85E_UART_ASIM_TXE; /* Writing is always enabled. */ - new_config |= NB85E_UART_ASIM_CAE; - new_config |= NB85E_UART_ASIM_ISRM; /* Errors generate a read-irq. */ - - /* Disable interrupts while we're twiddling the hardware. */ - local_irq_save (flags); - -#ifdef NB85E_UART_PRE_CONFIGURE - NB85E_UART_PRE_CONFIGURE (chan, cflags, baud); -#endif - - old_config = NB85E_UART_ASIM (chan); - old_clk_divlog2 = NB85E_UART_CKSR (chan); - old_brgen_count = NB85E_UART_BRGC (chan); - - if (new_clk_divlog2 != old_clk_divlog2 - || new_brgen_count != old_brgen_count) - { - /* The baud rate has changed. First, disable the UART. */ - NB85E_UART_ASIM (chan) = 0; - old_config = 0; - /* Reprogram the baud-rate generator. */ - NB85E_UART_CKSR (chan) = new_clk_divlog2; - NB85E_UART_BRGC (chan) = new_brgen_count; - } - - if (! (old_config & NB85E_UART_ASIM_CAE)) { - /* If we are enabling the uart for the first time, start - by turning on the enable bit, which must be done - before turning on any other bits. */ - NB85E_UART_ASIM (chan) = NB85E_UART_ASIM_CAE; - /* Enabling the uart also resets it. */ - old_config = NB85E_UART_ASIM_CAE; - } - - if (new_config != old_config) { - /* Which of the TXE/RXE bits we'll temporarily turn off - before changing other control bits. */ - unsigned temp_disable = 0; - /* Which of the TXE/RXE bits will be enabled. */ - unsigned enable = 0; - unsigned changed_bits = new_config ^ old_config; - - /* Which of RX/TX will be enabled in the new configuration. */ - if (new_config & RX_BITS) - enable |= (new_config & NB85E_UART_ASIM_RXE); - if (new_config & TX_BITS) - enable |= (new_config & NB85E_UART_ASIM_TXE); - - /* Figure out which of RX/TX needs to be disabled; note - that this will only happen if they're not already - disabled. */ - if (changed_bits & RX_BITS) - temp_disable |= (old_config & NB85E_UART_ASIM_RXE); - if (changed_bits & TX_BITS) - temp_disable |= (old_config & NB85E_UART_ASIM_TXE); - - /* We have to turn off RX and/or TX mode before changing - any associated control bits. */ - if (temp_disable) - NB85E_UART_ASIM (chan) = old_config & ~temp_disable; - - /* Write the new control bits, while RX/TX are disabled. */ - if (changed_bits & ~enable) - NB85E_UART_ASIM (chan) = new_config & ~enable; - - /* The UART may not be reset properly unless we - wait at least 2 `basic-clocks' until turning - on the TXE/RXE bits again. A `basic clock' - is the clock used by the baud-rate generator, i.e., - the cpu clock divided by the 2^new_clk_divlog2. */ - nb85e_uart_delay (1 << (new_clk_divlog2 + 1)); - - /* Write the final version, with enable bits turned on. */ - NB85E_UART_ASIM (chan) = new_config; - } - - local_irq_restore (flags); -} - - -/* Low-level console. */ - -#ifdef CONFIG_V850E_NB85E_UART_CONSOLE - -static void nb85e_uart_cons_write (struct console *co, - const char *s, unsigned count) -{ - if (count > 0) { - unsigned chan = co->index; - unsigned irq = IRQ_INTST (chan); - int irq_was_enabled, irq_was_pending, flags; - - /* We don't want to get `transmission completed' (INTST) - interrupts, since we're busy-waiting, so we disable - them while sending (we don't disable interrupts - entirely because sending over a serial line is really - slow). We save the status of INTST and restore it - when we're done so that using printk doesn't - interfere with normal serial transmission (other than - interleaving the output, of course!). This should - work correctly even if this function is interrupted - and the interrupt printks something. */ - - /* Disable interrupts while fiddling with INTST. */ - local_irq_save (flags); - /* Get current INTST status. */ - irq_was_enabled = nb85e_intc_irq_enabled (irq); - irq_was_pending = nb85e_intc_irq_pending (irq); - /* Disable INTST if necessary. */ - if (irq_was_enabled) - nb85e_intc_disable_irq (irq); - /* Turn interrupts back on. */ - local_irq_restore (flags); - - /* Send characters. */ - while (count > 0) { - int ch = *s++; - - if (ch == '\n') { - /* We don't have the benefit of a tty - driver, so translate NL into CR LF. */ - nb85e_uart_wait_for_xmit_ok (chan); - nb85e_uart_putc (chan, '\r'); - } - - nb85e_uart_wait_for_xmit_ok (chan); - nb85e_uart_putc (chan, ch); - - count--; - } - - /* Restore saved INTST status. */ - if (irq_was_enabled) { - /* Wait for the last character we sent to be - completely transmitted (as we'll get an INTST - interrupt at that point). */ - nb85e_uart_wait_for_xmit_done (chan); - /* Clear pending interrupts received due - to our transmission, unless there was already - one pending, in which case we want the - handler to be called. */ - if (! irq_was_pending) - nb85e_intc_clear_pending_irq (irq); - /* ... and then turn back on handling. */ - nb85e_intc_enable_irq (irq); - } - } -} - -extern struct uart_driver nb85e_uart_driver; -static struct console nb85e_uart_cons = -{ - .name = "ttyS", - .write = nb85e_uart_cons_write, - .device = uart_console_device, - .flags = CON_PRINTBUFFER, - .cflag = NB85E_UART_INIT_CFLAGS, - .index = -1, - .data = &nb85e_uart_driver, -}; - -void nb85e_uart_cons_init (unsigned chan) -{ - nb85e_uart_configure (chan, NB85E_UART_INIT_CFLAGS, - NB85E_UART_INIT_BAUD); - nb85e_uart_cons.index = chan; - register_console (&nb85e_uart_cons); - printk ("Console: %s on-chip UART channel %d\n", - NB85E_UART_CHIP_NAME, chan); -} - -#define NB85E_UART_CONSOLE &nb85e_uart_cons - -#else /* !CONFIG_V850E_NB85E_UART_CONSOLE */ -#define NB85E_UART_CONSOLE 0 -#endif /* CONFIG_V850E_NB85E_UART_CONSOLE */ - -/* TX/RX interrupt handlers. */ - -static void nb85e_uart_stop_tx (struct uart_port *port, unsigned tty_stop); - -void nb85e_uart_tx (struct uart_port *port) -{ - struct circ_buf *xmit = &port->info->xmit; - int stopped = uart_tx_stopped (port); - - if (nb85e_uart_xmit_ok (port->line)) { - int tx_ch; - - if (port->x_char) { - tx_ch = port->x_char; - port->x_char = 0; - } else if (!uart_circ_empty (xmit) && !stopped) { - tx_ch = xmit->buf[xmit->tail]; - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - } else - goto no_xmit; - - nb85e_uart_putc (port->line, tx_ch); - port->icount.tx++; - - if (uart_circ_chars_pending (xmit) < WAKEUP_CHARS) - uart_write_wakeup (port); - } - - no_xmit: - if (uart_circ_empty (xmit) || stopped) - nb85e_uart_stop_tx (port, stopped); -} - -static void nb85e_uart_tx_irq (int irq, void *data, struct pt_regs *regs) -{ - struct uart_port *port = data; - nb85e_uart_tx (port); -} - -static void nb85e_uart_rx_irq (int irq, void *data, struct pt_regs *regs) -{ - struct uart_port *port = data; - unsigned ch_stat = TTY_NORMAL; - unsigned ch = NB85E_UART_RXB (port->line); - unsigned err = NB85E_UART_ASIS (port->line); - - if (err) { - if (err & NB85E_UART_ASIS_OVE) { - ch_stat = TTY_OVERRUN; - port->icount.overrun++; - } else if (err & NB85E_UART_ASIS_FE) { - ch_stat = TTY_FRAME; - port->icount.frame++; - } else if (err & NB85E_UART_ASIS_PE) { - ch_stat = TTY_PARITY; - port->icount.parity++; - } - } - - port->icount.rx++; - - tty_insert_flip_char (port->info->tty, ch, ch_stat); - tty_schedule_flip (port->info->tty); -} - -/* Control functions for the serial framework. */ - -static void nb85e_uart_nop (struct uart_port *port) { } -static int nb85e_uart_success (struct uart_port *port) { return 0; } - -static unsigned nb85e_uart_tx_empty (struct uart_port *port) -{ - return TIOCSER_TEMT; /* Can't detect. */ -} - -static void nb85e_uart_set_mctrl (struct uart_port *port, unsigned mctrl) -{ -#ifdef NB85E_UART_SET_RTS - NB85E_UART_SET_RTS (port->line, (mctrl & TIOCM_RTS)); -#endif -} - -static unsigned nb85e_uart_get_mctrl (struct uart_port *port) -{ - /* We don't support DCD or DSR, so consider them permanently active. */ - int mctrl = TIOCM_CAR | TIOCM_DSR; - - /* We may support CTS. */ -#ifdef NB85E_UART_CTS - mctrl |= NB85E_UART_CTS(port->line) ? TIOCM_CTS : 0; -#else - mctrl |= TIOCM_CTS; -#endif - - return mctrl; -} - -static void nb85e_uart_start_tx (struct uart_port *port, unsigned tty_start) -{ - nb85e_intc_disable_irq (IRQ_INTST (port->line)); - nb85e_uart_tx (port); - nb85e_intc_enable_irq (IRQ_INTST (port->line)); -} - -static void nb85e_uart_stop_tx (struct uart_port *port, unsigned tty_stop) -{ - nb85e_intc_disable_irq (IRQ_INTST (port->line)); -} - -static void nb85e_uart_start_rx (struct uart_port *port) -{ - nb85e_intc_enable_irq (IRQ_INTSR (port->line)); -} - -static void nb85e_uart_stop_rx (struct uart_port *port) -{ - nb85e_intc_disable_irq (IRQ_INTSR (port->line)); -} - -static void nb85e_uart_break_ctl (struct uart_port *port, int break_ctl) -{ - /* Umm, do this later. */ -} - -static int nb85e_uart_startup (struct uart_port *port) -{ - int err; - - /* Alloc RX irq. */ - err = request_irq (IRQ_INTSR (port->line), nb85e_uart_rx_irq, - SA_INTERRUPT, "nb85e_uart", port); - if (err) - return err; - - /* Alloc TX irq. */ - err = request_irq (IRQ_INTST (port->line), nb85e_uart_tx_irq, - SA_INTERRUPT, "nb85e_uart", port); - if (err) { - free_irq (IRQ_INTSR (port->line), port); - return err; - } - - nb85e_uart_start_rx (port); - - return 0; -} - -static void nb85e_uart_shutdown (struct uart_port *port) -{ - /* Disable port interrupts. */ - free_irq (IRQ_INTST (port->line), port); - free_irq (IRQ_INTSR (port->line), port); - - /* Turn off xmit/recv enable bits. */ - NB85E_UART_ASIM (port->line) - &= ~(NB85E_UART_ASIM_TXE | NB85E_UART_ASIM_RXE); - /* Then reset the channel. */ - NB85E_UART_ASIM (port->line) = 0; -} - -static void -nb85e_uart_set_termios (struct uart_port *port, struct termios *termios, - struct termios *old) -{ - unsigned cflags = termios->c_cflag; - - /* Restrict flags to legal values. */ - if ((cflags & CSIZE) != CS7 && (cflags & CSIZE) != CS8) - /* The new value of CSIZE is invalid, use the old value. */ - cflags = (cflags & ~CSIZE) - | (old ? (old->c_cflag & CSIZE) : CS8); - - termios->c_cflag = cflags; - - nb85e_uart_configure (port->line, cflags, - uart_get_baud_rate (port, termios, old, - min_baud(), max_baud())); -} - -static const char *nb85e_uart_type (struct uart_port *port) -{ - return port->type == PORT_NB85E_UART ? "nb85e_uart" : 0; -} - -static void nb85e_uart_config_port (struct uart_port *port, int flags) -{ - if (flags & UART_CONFIG_TYPE) - port->type = PORT_NB85E_UART; -} - -static int -nb85e_uart_verify_port (struct uart_port *port, struct serial_struct *ser) -{ - if (ser->type != PORT_UNKNOWN && ser->type != PORT_NB85E_UART) - return -EINVAL; - if (ser->irq != IRQ_INTST (port->line)) - return -EINVAL; - return 0; -} - -static struct uart_ops nb85e_uart_ops = { - .tx_empty = nb85e_uart_tx_empty, - .get_mctrl = nb85e_uart_get_mctrl, - .set_mctrl = nb85e_uart_set_mctrl, - .start_tx = nb85e_uart_start_tx, - .stop_tx = nb85e_uart_stop_tx, - .stop_rx = nb85e_uart_stop_rx, - .enable_ms = nb85e_uart_nop, - .break_ctl = nb85e_uart_break_ctl, - .startup = nb85e_uart_startup, - .shutdown = nb85e_uart_shutdown, - .set_termios = nb85e_uart_set_termios, - .type = nb85e_uart_type, - .release_port = nb85e_uart_nop, - .request_port = nb85e_uart_success, - .config_port = nb85e_uart_config_port, - .verify_port = nb85e_uart_verify_port, -}; - -/* Initialization and cleanup. */ - -static struct uart_driver nb85e_uart_driver = { - .owner = THIS_MODULE, - .driver_name = "nb85e_uart", - .devfs_name = "tts/", - .dev_name = "ttyS", - .major = TTY_MAJOR, - .minor = NB85E_UART_MINOR_BASE, - .nr = NB85E_UART_NUM_CHANNELS, - .cons = NB85E_UART_CONSOLE, -}; - - -static struct uart_port nb85e_uart_ports[NB85E_UART_NUM_CHANNELS]; - -static int __init nb85e_uart_init (void) -{ - int rval; - - printk (KERN_INFO "%s on-chip UART\n", NB85E_UART_CHIP_NAME); - - rval = uart_register_driver (&nb85e_uart_driver); - if (rval == 0) { - unsigned chan; - - for (chan = 0; chan < NB85E_UART_NUM_CHANNELS; chan++) { - struct uart_port *port = &nb85e_uart_ports[chan]; - - memset (port, 0, sizeof *port); - - port->ops = &nb85e_uart_ops; - port->line = chan; - port->iotype = SERIAL_IO_MEM; - port->flags = UPF_BOOT_AUTOCONF; - - /* We actually use multiple IRQs, but the serial - framework seems to mainly use this for - informational purposes anyway. Here we use the TX - irq. */ - port->irq = IRQ_INTST (chan); - - /* The serial framework doesn't really use these - membase/mapbase fields for anything useful, but - it requires that they be something non-zero to - consider the port `valid', and also uses them - for informational purposes. */ - port->membase = (void *)NB85E_UART_BASE_ADDR (chan); - port->mapbase = NB85E_UART_BASE_ADDR (chan); - - /* The framework insists on knowing the uart's master - clock freq, though it doesn't seem to do anything - useful for us with it. We must make it at least - higher than (the maximum baud rate * 16), otherwise - the framework will puke during its internal - calculations, and force the baud rate to be 9600. - To be accurate though, just repeat the calculation - we use when actually setting the speed. - - The `* 8' means `* 16 / 2': 16 to account for for - the serial framework's built-in bias, and 2 because - there's an additional / 2 in the hardware. */ - port->uartclk = - (NB85E_UART_BASE_FREQ >> cksr_min()) * 8; - - uart_add_one_port (&nb85e_uart_driver, port); - } - } - - return rval; -} - -static void __exit nb85e_uart_exit (void) -{ - unsigned chan; - - for (chan = 0; chan < NB85E_UART_NUM_CHANNELS; chan++) - uart_remove_one_port (&nb85e_uart_driver, - &nb85e_uart_ports[chan]); - - uart_unregister_driver (&nb85e_uart_driver); -} - -module_init (nb85e_uart_init); -module_exit (nb85e_uart_exit); - -MODULE_AUTHOR ("Miles Bader"); -MODULE_DESCRIPTION ("NEC " NB85E_UART_CHIP_NAME " on-chip UART"); -MODULE_LICENSE ("GPL"); diff -Nru a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c --- a/drivers/serial/sunsu.c Sat Jul 19 12:54:23 2003 +++ b/drivers/serial/sunsu.c Sat Jul 19 12:54:23 2003 @@ -102,6 +102,7 @@ int l1_down; #ifdef CONFIG_SERIO struct serio serio; + int serio_open; #endif }; @@ -1021,12 +1022,13 @@ static int sunsu_serio_open(struct serio *serio) { + struct uart_sunsu_port *up = serio->driver; unsigned long flags; int ret; spin_lock_irqsave(&sunsu_serio_lock, flags); - if (serio->private == NULL) { - serio->private = (void *) -1L; + if (!up->serio_open) { + up->serio_open = 1; ret = 0; } else ret = -EBUSY; @@ -1037,10 +1039,11 @@ static void sunsu_serio_close(struct serio *serio) { + struct uart_sunsu_port *up = serio->driver; unsigned long flags; spin_lock_irqsave(&sunsu_serio_lock, flags); - serio->private = NULL; + up->serio_open = 0; spin_unlock_irqrestore(&sunsu_serio_lock, flags); } diff -Nru a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c --- a/drivers/serial/sunzilog.c Sat Jul 19 12:54:30 2003 +++ b/drivers/serial/sunzilog.c Sat Jul 19 12:54:30 2003 @@ -112,6 +112,7 @@ #ifdef CONFIG_SERIO struct serio serio; + int serio_open; #endif }; @@ -1311,12 +1312,13 @@ static int sunzilog_serio_open(struct serio *serio) { + struct uart_sunzilog_port *up = serio->driver; unsigned long flags; int ret; spin_lock_irqsave(&sunzilog_serio_lock, flags); - if (serio->private == NULL) { - serio->private = (void *) -1L; + if (!up->serio_open) { + up->serio_open = 1; ret = 0; } else ret = -EBUSY; @@ -1327,10 +1329,11 @@ static void sunzilog_serio_close(struct serio *serio) { + struct uart_sunzilog_port *up = serio->driver; unsigned long flags; spin_lock_irqsave(&sunzilog_serio_lock, flags); - serio->private = NULL; + up->serio_open = 0; spin_unlock_irqrestore(&sunzilog_serio_lock, flags); } diff -Nru a/drivers/serial/v850e_uart.c b/drivers/serial/v850e_uart.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/v850e_uart.c Sat Jul 19 12:54:27 2003 @@ -0,0 +1,549 @@ +/* + * drivers/serial/v850e_uart.c -- Serial I/O using V850E on-chip UART or UARTB + * + * Copyright (C) 2001,02,03 NEC Electronics Corporation + * Copyright (C) 2001,02,03 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +/* This driver supports both the original V850E UART interface (called + merely `UART' in the docs) and the newer `UARTB' interface, which is + roughly a superset of the first one. The selection is made at + configure time -- if CONFIG_V850E_UARTB is defined, then UARTB is + presumed, otherwise the old UART -- as these are on-CPU UARTS, a system + can never have both. + + The UARTB interface also has a 16-entry FIFO mode, which is not + yet supported by this driver. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Initial UART state. This may be overridden by machine-dependent headers. */ +#ifndef V850E_UART_INIT_BAUD +#define V850E_UART_INIT_BAUD 115200 +#endif +#ifndef V850E_UART_INIT_CFLAGS +#define V850E_UART_INIT_CFLAGS (B115200 | CS8 | CREAD) +#endif + +/* A string used for prefixing printed descriptions; since the same UART + macro is actually used on other chips than the V850E. This must be a + constant string. */ +#ifndef V850E_UART_CHIP_NAME +#define V850E_UART_CHIP_NAME "V850E" +#endif + +#define V850E_UART_MINOR_BASE 64 /* First tty minor number */ + + +/* Low-level UART functions. */ + +/* Configure and turn on uart channel CHAN, using the termios `control + modes' bits in CFLAGS, and a baud-rate of BAUD. */ +void v850e_uart_configure (unsigned chan, unsigned cflags, unsigned baud) +{ + int flags; + v850e_uart_speed_t old_speed; + v850e_uart_config_t old_config; + v850e_uart_speed_t new_speed = v850e_uart_calc_speed (baud); + v850e_uart_config_t new_config = v850e_uart_calc_config (cflags); + + /* Disable interrupts while we're twiddling the hardware. */ + local_irq_save (flags); + +#ifdef V850E_UART_PRE_CONFIGURE + V850E_UART_PRE_CONFIGURE (chan, cflags, baud); +#endif + + old_config = V850E_UART_CONFIG (chan); + old_speed = v850e_uart_speed (chan); + + if (! v850e_uart_speed_eq (old_speed, new_speed)) { + /* The baud rate has changed. First, disable the UART. */ + V850E_UART_CONFIG (chan) = V850E_UART_CONFIG_FINI; + old_config = 0; /* Force the uart to be re-initialized. */ + + /* Reprogram the baud-rate generator. */ + v850e_uart_set_speed (chan, new_speed); + } + + if (! (old_config & V850E_UART_CONFIG_ENABLED)) { + /* If we are using the uart for the first time, start by + enabling it, which must be done before turning on any + other bits. */ + V850E_UART_CONFIG (chan) = V850E_UART_CONFIG_INIT; + /* See the initial state. */ + old_config = V850E_UART_CONFIG (chan); + } + + if (new_config != old_config) { + /* Which of the TXE/RXE bits we'll temporarily turn off + before changing other control bits. */ + unsigned temp_disable = 0; + /* Which of the TXE/RXE bits will be enabled. */ + unsigned enable = 0; + unsigned changed_bits = new_config ^ old_config; + + /* Which of RX/TX will be enabled in the new configuration. */ + if (new_config & V850E_UART_CONFIG_RX_BITS) + enable |= (new_config & V850E_UART_CONFIG_RX_ENABLE); + if (new_config & V850E_UART_CONFIG_TX_BITS) + enable |= (new_config & V850E_UART_CONFIG_TX_ENABLE); + + /* Figure out which of RX/TX needs to be disabled; note + that this will only happen if they're not already + disabled. */ + if (changed_bits & V850E_UART_CONFIG_RX_BITS) + temp_disable + |= (old_config & V850E_UART_CONFIG_RX_ENABLE); + if (changed_bits & V850E_UART_CONFIG_TX_BITS) + temp_disable + |= (old_config & V850E_UART_CONFIG_TX_ENABLE); + + /* We have to turn off RX and/or TX mode before changing + any associated control bits. */ + if (temp_disable) + V850E_UART_CONFIG (chan) = old_config & ~temp_disable; + + /* Write the new control bits, while RX/TX are disabled. */ + if (changed_bits & ~enable) + V850E_UART_CONFIG (chan) = new_config & ~enable; + + v850e_uart_config_delay (new_config, new_speed); + + /* Write the final version, with enable bits turned on. */ + V850E_UART_CONFIG (chan) = new_config; + } + + local_irq_restore (flags); +} + + +/* Low-level console. */ + +#ifdef CONFIG_V850E_UART_CONSOLE + +static void v850e_uart_cons_write (struct console *co, + const char *s, unsigned count) +{ + if (count > 0) { + unsigned chan = co->index; + unsigned irq = V850E_UART_TX_IRQ (chan); + int irq_was_enabled, irq_was_pending, flags; + + /* We don't want to get `transmission completed' + interrupts, since we're busy-waiting, so we disable them + while sending (we don't disable interrupts entirely + because sending over a serial line is really slow). We + save the status of the tx interrupt and restore it when + we're done so that using printk doesn't interfere with + normal serial transmission (other than interleaving the + output, of course!). This should work correctly even if + this function is interrupted and the interrupt printks + something. */ + + /* Disable interrupts while fiddling with tx interrupt. */ + local_irq_save (flags); + /* Get current tx interrupt status. */ + irq_was_enabled = v850e_intc_irq_enabled (irq); + irq_was_pending = v850e_intc_irq_pending (irq); + /* Disable tx interrupt if necessary. */ + if (irq_was_enabled) + v850e_intc_disable_irq (irq); + /* Turn interrupts back on. */ + local_irq_restore (flags); + + /* Send characters. */ + while (count > 0) { + int ch = *s++; + + if (ch == '\n') { + /* We don't have the benefit of a tty + driver, so translate NL into CR LF. */ + v850e_uart_wait_for_xmit_ok (chan); + v850e_uart_putc (chan, '\r'); + } + + v850e_uart_wait_for_xmit_ok (chan); + v850e_uart_putc (chan, ch); + + count--; + } + + /* Restore saved tx interrupt status. */ + if (irq_was_enabled) { + /* Wait for the last character we sent to be + completely transmitted (as we'll get an + interrupt interrupt at that point). */ + v850e_uart_wait_for_xmit_done (chan); + /* Clear pending interrupts received due + to our transmission, unless there was already + one pending, in which case we want the + handler to be called. */ + if (! irq_was_pending) + v850e_intc_clear_pending_irq (irq); + /* ... and then turn back on handling. */ + v850e_intc_enable_irq (irq); + } + } +} + +extern struct uart_driver v850e_uart_driver; +static struct console v850e_uart_cons = +{ + .name = "ttyS", + .write = v850e_uart_cons_write, + .device = uart_console_device, + .flags = CON_PRINTBUFFER, + .cflag = V850E_UART_INIT_CFLAGS, + .index = -1, + .data = &v850e_uart_driver, +}; + +void v850e_uart_cons_init (unsigned chan) +{ + v850e_uart_configure (chan, V850E_UART_INIT_CFLAGS, + V850E_UART_INIT_BAUD); + v850e_uart_cons.index = chan; + register_console (&v850e_uart_cons); + printk ("Console: %s on-chip UART channel %d\n", + V850E_UART_CHIP_NAME, chan); +} + +/* This is what the init code actually calls. */ +static int v850e_uart_console_init (void) +{ + v850e_uart_cons_init (V850E_UART_CONSOLE_CHANNEL); + return 0; +} +console_initcall(v850e_uart_console_init); + +#define V850E_UART_CONSOLE &v850e_uart_cons + +#else /* !CONFIG_V850E_UART_CONSOLE */ +#define V850E_UART_CONSOLE 0 +#endif /* CONFIG_V850E_UART_CONSOLE */ + +/* TX/RX interrupt handlers. */ + +static void v850e_uart_stop_tx (struct uart_port *port, unsigned tty_stop); + +void v850e_uart_tx (struct uart_port *port) +{ + struct circ_buf *xmit = &port->info->xmit; + int stopped = uart_tx_stopped (port); + + if (v850e_uart_xmit_ok (port->line)) { + int tx_ch; + + if (port->x_char) { + tx_ch = port->x_char; + port->x_char = 0; + } else if (!uart_circ_empty (xmit) && !stopped) { + tx_ch = xmit->buf[xmit->tail]; + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + } else + goto no_xmit; + + v850e_uart_putc (port->line, tx_ch); + port->icount.tx++; + + if (uart_circ_chars_pending (xmit) < WAKEUP_CHARS) + uart_write_wakeup (port); + } + + no_xmit: + if (uart_circ_empty (xmit) || stopped) + v850e_uart_stop_tx (port, stopped); +} + +static irqreturn_t v850e_uart_tx_irq(int irq, void *data, struct pt_regs *regs) +{ + struct uart_port *port = data; + v850e_uart_tx (port); + return IRQ_HANDLED; +} + +static irqreturn_t v850e_uart_rx_irq(int irq, void *data, struct pt_regs *regs) +{ + struct uart_port *port = data; + unsigned ch_stat = TTY_NORMAL; + unsigned ch = v850e_uart_getc (port->line); + unsigned err = v850e_uart_err (port->line); + + if (err) { + if (err & V850E_UART_ERR_OVERRUN) { + ch_stat = TTY_OVERRUN; + port->icount.overrun++; + } else if (err & V850E_UART_ERR_FRAME) { + ch_stat = TTY_FRAME; + port->icount.frame++; + } else if (err & V850E_UART_ERR_PARITY) { + ch_stat = TTY_PARITY; + port->icount.parity++; + } + } + + port->icount.rx++; + + tty_insert_flip_char (port->info->tty, ch, ch_stat); + tty_schedule_flip (port->info->tty); + + return IRQ_HANDLED; +} + + +/* Control functions for the serial framework. */ + +static void v850e_uart_nop (struct uart_port *port) { } +static int v850e_uart_success (struct uart_port *port) { return 0; } + +static unsigned v850e_uart_tx_empty (struct uart_port *port) +{ + return TIOCSER_TEMT; /* Can't detect. */ +} + +static void v850e_uart_set_mctrl (struct uart_port *port, unsigned mctrl) +{ +#ifdef V850E_UART_SET_RTS + V850E_UART_SET_RTS (port->line, (mctrl & TIOCM_RTS)); +#endif +} + +static unsigned v850e_uart_get_mctrl (struct uart_port *port) +{ + /* We don't support DCD or DSR, so consider them permanently active. */ + int mctrl = TIOCM_CAR | TIOCM_DSR; + + /* We may support CTS. */ +#ifdef V850E_UART_CTS + mctrl |= V850E_UART_CTS(port->line) ? TIOCM_CTS : 0; +#else + mctrl |= TIOCM_CTS; +#endif + + return mctrl; +} + +static void v850e_uart_start_tx (struct uart_port *port, unsigned tty_start) +{ + v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line)); + v850e_uart_tx (port); + v850e_intc_enable_irq (V850E_UART_TX_IRQ (port->line)); +} + +static void v850e_uart_stop_tx (struct uart_port *port, unsigned tty_stop) +{ + v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line)); +} + +static void v850e_uart_start_rx (struct uart_port *port) +{ + v850e_intc_enable_irq (V850E_UART_RX_IRQ (port->line)); +} + +static void v850e_uart_stop_rx (struct uart_port *port) +{ + v850e_intc_disable_irq (V850E_UART_RX_IRQ (port->line)); +} + +static void v850e_uart_break_ctl (struct uart_port *port, int break_ctl) +{ + /* Umm, do this later. */ +} + +static int v850e_uart_startup (struct uart_port *port) +{ + int err; + + /* Alloc RX irq. */ + err = request_irq (V850E_UART_RX_IRQ (port->line), v850e_uart_rx_irq, + SA_INTERRUPT, "v850e_uart", port); + if (err) + return err; + + /* Alloc TX irq. */ + err = request_irq (V850E_UART_TX_IRQ (port->line), v850e_uart_tx_irq, + SA_INTERRUPT, "v850e_uart", port); + if (err) { + free_irq (V850E_UART_RX_IRQ (port->line), port); + return err; + } + + v850e_uart_start_rx (port); + + return 0; +} + +static void v850e_uart_shutdown (struct uart_port *port) +{ + /* Disable port interrupts. */ + free_irq (V850E_UART_TX_IRQ (port->line), port); + free_irq (V850E_UART_RX_IRQ (port->line), port); + + /* Turn off xmit/recv enable bits. */ + V850E_UART_CONFIG (port->line) + &= ~(V850E_UART_CONFIG_TX_ENABLE + | V850E_UART_CONFIG_RX_ENABLE); + /* Then reset the channel. */ + V850E_UART_CONFIG (port->line) = 0; +} + +static void +v850e_uart_set_termios (struct uart_port *port, struct termios *termios, + struct termios *old) +{ + unsigned cflags = termios->c_cflag; + + /* Restrict flags to legal values. */ + if ((cflags & CSIZE) != CS7 && (cflags & CSIZE) != CS8) + /* The new value of CSIZE is invalid, use the old value. */ + cflags = (cflags & ~CSIZE) + | (old ? (old->c_cflag & CSIZE) : CS8); + + termios->c_cflag = cflags; + + v850e_uart_configure (port->line, cflags, + uart_get_baud_rate (port, termios, old, + v850e_uart_min_baud(), + v850e_uart_max_baud())); +} + +static const char *v850e_uart_type (struct uart_port *port) +{ + return port->type == PORT_V850E_UART ? "v850e_uart" : 0; +} + +static void v850e_uart_config_port (struct uart_port *port, int flags) +{ + if (flags & UART_CONFIG_TYPE) + port->type = PORT_V850E_UART; +} + +static int +v850e_uart_verify_port (struct uart_port *port, struct serial_struct *ser) +{ + if (ser->type != PORT_UNKNOWN && ser->type != PORT_V850E_UART) + return -EINVAL; + if (ser->irq != V850E_UART_TX_IRQ (port->line)) + return -EINVAL; + return 0; +} + +static struct uart_ops v850e_uart_ops = { + .tx_empty = v850e_uart_tx_empty, + .get_mctrl = v850e_uart_get_mctrl, + .set_mctrl = v850e_uart_set_mctrl, + .start_tx = v850e_uart_start_tx, + .stop_tx = v850e_uart_stop_tx, + .stop_rx = v850e_uart_stop_rx, + .enable_ms = v850e_uart_nop, + .break_ctl = v850e_uart_break_ctl, + .startup = v850e_uart_startup, + .shutdown = v850e_uart_shutdown, + .set_termios = v850e_uart_set_termios, + .type = v850e_uart_type, + .release_port = v850e_uart_nop, + .request_port = v850e_uart_success, + .config_port = v850e_uart_config_port, + .verify_port = v850e_uart_verify_port, +}; + +/* Initialization and cleanup. */ + +static struct uart_driver v850e_uart_driver = { + .owner = THIS_MODULE, + .driver_name = "v850e_uart", + .devfs_name = "tts/", + .dev_name = "ttyS", + .major = TTY_MAJOR, + .minor = V850E_UART_MINOR_BASE, + .nr = V850E_UART_NUM_CHANNELS, + .cons = V850E_UART_CONSOLE, +}; + + +static struct uart_port v850e_uart_ports[V850E_UART_NUM_CHANNELS]; + +static int __init v850e_uart_init (void) +{ + int rval; + + printk (KERN_INFO "%s on-chip UART\n", V850E_UART_CHIP_NAME); + + rval = uart_register_driver (&v850e_uart_driver); + if (rval == 0) { + unsigned chan; + + for (chan = 0; chan < V850E_UART_NUM_CHANNELS; chan++) { + struct uart_port *port = &v850e_uart_ports[chan]; + + memset (port, 0, sizeof *port); + + port->ops = &v850e_uart_ops; + port->line = chan; + port->iotype = SERIAL_IO_MEM; + port->flags = UPF_BOOT_AUTOCONF; + + /* We actually use multiple IRQs, but the serial + framework seems to mainly use this for + informational purposes anyway. Here we use the TX + irq. */ + port->irq = V850E_UART_TX_IRQ (chan); + + /* The serial framework doesn't really use these + membase/mapbase fields for anything useful, but + it requires that they be something non-zero to + consider the port `valid', and also uses them + for informational purposes. */ + port->membase = (void *)V850E_UART_BASE_ADDR (chan); + port->mapbase = V850E_UART_BASE_ADDR (chan); + + /* The framework insists on knowing the uart's master + clock freq, though it doesn't seem to do anything + useful for us with it. We must make it at least + higher than (the maximum baud rate * 16), otherwise + the framework will puke during its internal + calculations, and force the baud rate to be 9600. + To be accurate though, just repeat the calculation + we use when actually setting the speed. */ + port->uartclk = v850e_uart_max_clock() * 16; + + uart_add_one_port (&v850e_uart_driver, port); + } + } + + return rval; +} + +static void __exit v850e_uart_exit (void) +{ + unsigned chan; + + for (chan = 0; chan < V850E_UART_NUM_CHANNELS; chan++) + uart_remove_one_port (&v850e_uart_driver, + &v850e_uart_ports[chan]); + + uart_unregister_driver (&v850e_uart_driver); +} + +module_init (v850e_uart_init); +module_exit (v850e_uart_exit); + +MODULE_AUTHOR ("Miles Bader"); +MODULE_DESCRIPTION ("NEC " V850E_UART_CHIP_NAME " on-chip UART"); +MODULE_LICENSE ("GPL"); diff -Nru a/drivers/telephony/Kconfig b/drivers/telephony/Kconfig --- a/drivers/telephony/Kconfig Sat Jul 19 12:54:23 2003 +++ b/drivers/telephony/Kconfig Sat Jul 19 12:54:23 2003 @@ -39,7 +39,7 @@ config PHONE_IXJ_PCMCIA tristate "QuickNet Internet LineJack/PhoneJack PCMCIA support" - depends on PHONE_IXJ + depends on PHONE_IXJ && PCMCIA help Say Y here to configure in PCMCIA service support for the Quicknet cards manufactured by Quicknet Technologies, Inc. This changes the diff -Nru a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c --- a/drivers/telephony/ixj.c Sat Jul 19 12:54:22 2003 +++ b/drivers/telephony/ixj.c Sat Jul 19 12:54:22 2003 @@ -23,6 +23,7 @@ * Fixes: David Huggins-Daines, * Fabio Ferrari, * Artis Kugevics, + * Daniele Bellucci, * * More information about the hardware related to this driver can be found * at our website: http://www.quicknet.net @@ -45,6 +46,10 @@ /* * $Log: ixj.c,v $ + * + * Revision 4.8 2003/07/09 19:39:00 Daniele Bellucci + * Audit some copy_*_user and minor cleanup. + * * Revision 4.7 2001/08/13 06:19:33 craigs * Added additional changes from Alan Cox and John Anderson for * 2.2 to 2.4 cleanup and bounds checking @@ -363,12 +368,9 @@ static IXJ *ixj_alloc(void) { int cnt; - for(cnt=0; cntcid_send, (char *)arg, sizeof(PHONE_CID)); - } - else { + if (copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID))) { + retval = -EFAULT; + break; + } + } else { memset(&j->cid_send, 0, sizeof(PHONE_CID)); } ixj_write_cidcw(j); @@ -6273,14 +6277,12 @@ /* Fall through */ case PHONE_RING_START: if(arg) { - if(copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID))) - { + if (copy_from_user(&j->cid_send, (char *)arg, sizeof(PHONE_CID))) { retval = -EFAULT; break; } ixj_write_cid(j); - } - else { + } else { memset(&j->cid_send, 0, sizeof(PHONE_CID)); } ixj_ring_start(j); @@ -6696,7 +6698,8 @@ case IXJCTL_SET_FILTER_RAW: if (copy_from_user(&jfr, (char *) arg, sizeof(jfr))) retval = -EFAULT; - retval = ixj_init_filter_raw(j, &jfr); + else + retval = ixj_init_filter_raw(j, &jfr); break; case IXJCTL_GET_FILTER_HIST: if(arg<0||arg>3) @@ -6705,8 +6708,10 @@ retval = j->filter_hist[arg]; break; case IXJCTL_INIT_TONE: - copy_from_user(&ti, (char *) arg, sizeof(ti)); - retval = ixj_init_tone(j, &ti); + if (copy_from_user(&ti, (char *) arg, sizeof(ti))) + retval = -EFAULT; + else + retval = ixj_init_tone(j, &ti); break; case IXJCTL_TONE_CADENCE: retval = ixj_build_cadence(j, (IXJ_CADENCE *) arg); @@ -6715,8 +6720,10 @@ retval = ixj_build_filter_cadence(j, (IXJ_FILTER_CADENCE *) arg); break; case IXJCTL_SIGCTL: - if (copy_from_user(&j->sigdef, (char *)arg, sizeof(IXJ_SIGDEF))) + if (copy_from_user(&j->sigdef, (char *)arg, sizeof(IXJ_SIGDEF))) { retval = -EFAULT; + break; + } j->ixj_signals[j->sigdef.event] = j->sigdef.signal; if(j->sigdef.event < 33) { raise = 1; @@ -7693,7 +7700,7 @@ MODULE_AUTHOR("Ed Okerson "); MODULE_LICENSE("GPL"); -void ixj_exit(void) +static void __exit ixj_exit(void) { cleanup(); } @@ -7852,7 +7859,7 @@ return probe; } -int __init ixj_init(void) +static int __init ixj_init(void) { int cnt = 0; int probe = 0; diff -Nru a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c --- a/drivers/usb/class/bluetty.c Sat Jul 19 12:54:26 2003 +++ b/drivers/usb/class/bluetty.c Sat Jul 19 12:54:26 2003 @@ -1320,7 +1320,8 @@ bluetooth_tty_driver->owner = THIS_MODULE; bluetooth_tty_driver->driver_name = "usb-bluetooth"; - bluetooth_tty_driver->name = "usb/ttub/"; + bluetooth_tty_driver->name = "ttyUB"; + bluetooth_tty_driver->devfs_name = "usb/ttub/"; bluetooth_tty_driver->major = BLUETOOTH_TTY_MAJOR; bluetooth_tty_driver->minor_start = 0; bluetooth_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; diff -Nru a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c --- a/drivers/usb/class/cdc-acm.c Sat Jul 19 12:54:25 2003 +++ b/drivers/usb/class/cdc-acm.c Sat Jul 19 12:54:25 2003 @@ -765,7 +765,8 @@ return -ENOMEM; acm_tty_driver->owner = THIS_MODULE, acm_tty_driver->driver_name = "acm", - acm_tty_driver->name = "usb/acm/", + acm_tty_driver->name = "ttyACM", + acm_tty_driver->devfs_name = "usb/acm/", acm_tty_driver->major = ACM_TTY_MAJOR, acm_tty_driver->minor_start = 0, acm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL, diff -Nru a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c --- a/drivers/usb/class/usblp.c Sat Jul 19 12:54:23 2003 +++ b/drivers/usb/class/usblp.c Sat Jul 19 12:54:23 2003 @@ -359,7 +359,6 @@ file->private_data = usblp; usblp->writeurb->transfer_buffer_length = 0; - usblp->writeurb->status = 0; usblp->wcomplete = 1; /* we begin writeable */ usblp->rcomplete = 0; @@ -833,22 +832,15 @@ init_waitqueue_head(&usblp->wait); usblp->ifnum = intf->altsetting->desc.bInterfaceNumber; - retval = usb_register_dev(intf, &usblp_class); - if (retval) { - err("Not able to get a minor for this device."); - goto abort; - } - usblp->minor = intf->minor; - usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL); if (!usblp->writeurb) { err("out of memory"); - goto abort_minor; + goto abort; } usblp->readurb = usb_alloc_urb(0, GFP_KERNEL); if (!usblp->readurb) { err("out of memory"); - goto abort_minor; + goto abort; } /* Malloc device ID string buffer to the largest expected length, @@ -856,7 +848,7 @@ * could change in length. */ if (!(usblp->device_id_string = kmalloc(USBLP_DEVICE_ID_SIZE, GFP_KERNEL))) { err("out of memory for device_id_string"); - goto abort_minor; + goto abort; } usblp->writebuf = usblp->readbuf = NULL; @@ -868,19 +860,19 @@ if (!(usblp->writebuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE, GFP_KERNEL, &usblp->writeurb->transfer_dma))) { err("out of memory for write buf"); - goto abort_minor; + goto abort; } if (!(usblp->readbuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE, GFP_KERNEL, &usblp->readurb->transfer_dma))) { err("out of memory for read buf"); - goto abort_minor; + goto abort; } /* Allocate buffer for printer status */ usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL); if (!usblp->statusbuf) { err("out of memory for statusbuf"); - goto abort_minor; + goto abort; } /* Lookup quirks for this printer. */ @@ -894,12 +886,12 @@ dbg("incompatible printer-class device 0x%4.4X/0x%4.4X", dev->descriptor.idVendor, dev->descriptor.idProduct); - goto abort_minor; + goto abort; } /* Setup the selected alternate setting and endpoints. */ if (usblp_set_protocol(usblp, protocol) < 0) - goto abort_minor; + goto abort; /* Retrieve and store the device ID string. */ usblp_cache_device_id_string(usblp); @@ -920,10 +912,17 @@ usblp->present = 1; + retval = usb_register_dev(intf, &usblp_class); + if (retval) { + err("Not able to get a minor for this device."); + goto abort_intfdata; + } + usblp->minor = intf->minor; + return 0; -abort_minor: - usb_deregister_dev(intf, &usblp_class); +abort_intfdata: + usb_set_intfdata (intf, NULL); abort: if (usblp) { if (usblp->writebuf) diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c --- a/drivers/usb/core/hcd-pci.c Sat Jul 19 12:54:25 2003 +++ b/drivers/usb/core/hcd-pci.c Sat Jul 19 12:54:25 2003 @@ -81,7 +81,7 @@ if (!dev->irq) { err ("Found HC with no IRQ. Check BIOS/PCI %s setup!", - dev->slot_name); + pci_name(dev)); return -ENODEV; } @@ -99,7 +99,7 @@ retval = -EFAULT; clean_1: release_mem_region (resource, len); - err ("init %s fail, %d", dev->slot_name, retval); + err ("init %s fail, %d", pci_name(dev), retval); return retval; } @@ -136,7 +136,7 @@ goto clean_1; } else { release_region (resource, len); - err ("init %s fail, %d", dev->slot_name, retval); + err ("init %s fail, %d", pci_name(dev), retval); return retval; } } @@ -144,7 +144,7 @@ hcd->driver = driver; hcd->description = driver->description; hcd->pdev = dev; - hcd->self.bus_name = dev->slot_name; + hcd->self.bus_name = pci_name(dev); hcd->product_desc = dev->dev.name; hcd->self.controller = &dev->dev; hcd->controller = hcd->self.controller; @@ -279,6 +279,7 @@ /** * usb_hcd_pci_suspend - power management suspend of a PCI-based HCD * @dev: USB Host Controller being suspended + * @state: state that the controller is going into * * Store this function in the HCD's struct pci_driver as suspend(). */ diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c --- a/drivers/usb/core/hcd.c Sat Jul 19 12:54:25 2003 +++ b/drivers/usb/core/hcd.c Sat Jul 19 12:54:25 2003 @@ -1293,7 +1293,8 @@ } /* then kill any current requests */ - spin_lock_irqsave (&hcd_data_lock, flags); + local_irq_save (flags); + spin_lock (&hcd_data_lock); list_for_each_entry (urb, &dev->urb_list, urb_list) { int tmp = urb->pipe; @@ -1311,13 +1312,13 @@ if (urb->status != -EINPROGRESS) continue; usb_get_urb (urb); - spin_unlock_irqrestore (&hcd_data_lock, flags); + spin_unlock (&hcd_data_lock); - spin_lock_irqsave (&urb->lock, flags); + spin_lock (&urb->lock); tmp = urb->status; if (tmp == -EINPROGRESS) urb->status = -ESHUTDOWN; - spin_unlock_irqrestore (&urb->lock, flags); + spin_unlock (&urb->lock); /* kick hcd unless it's already returning this */ if (tmp == -EINPROGRESS) { @@ -1340,7 +1341,8 @@ /* list contents may have changed */ goto rescan; } - spin_unlock_irqrestore (&hcd_data_lock, flags); + spin_unlock (&hcd_data_lock); + local_irq_restore (flags); /* synchronize with the hardware, so old configuration state * clears out immediately (and will be freed). diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c --- a/drivers/usb/core/usb.c Sat Jul 19 12:54:25 2003 +++ b/drivers/usb/core/usb.c Sat Jul 19 12:54:25 2003 @@ -80,6 +80,23 @@ static int usb_generic_driver_data; +/* deallocate hcd/hardware state ... and nuke all pending urbs */ +static void nuke_urbs(struct usb_device *dev) +{ + void (*disable)(struct usb_device *, int); + int i; + + if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->disable) + return; + dbg("nuking urbs assigned to %s", dev->dev.bus_id); + + disable = dev->bus->op->disable; + for (i = 0; i < 15; i++) { + disable(dev, i); + disable(dev, USB_DIR_IN | i); + } +} + /* needs to be called with BKL held */ int usb_device_probe(struct device *dev) { @@ -116,6 +133,9 @@ down(&driver->serialize); + /* release all urbs for this device */ + nuke_urbs(interface_to_usbdev(intf)); + if (intf->driver && intf->driver->disconnect) intf->driver->disconnect(intf); @@ -896,6 +916,9 @@ usb_disconnect(child); } + /* deallocate hcd/hardware state ... and nuke all pending urbs */ + nuke_urbs(dev); + /* disconnect() drivers from interfaces (a key side effect) */ dev_dbg (&dev->dev, "unregistering interfaces\n"); if (dev->actconfig) { @@ -905,16 +928,6 @@ /* remove this interface */ interface = &dev->actconfig->interface[i]; device_unregister(&interface->dev); - } - } - - /* deallocate hcd/hardware state */ - if (ops->disable) { - void (*disable)(struct usb_device *, int) = ops->disable; - - for (i = 0; i < 15; i++) { - disable (dev, i); - disable (dev, USB_DIR_IN | i); } } diff -Nru a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c --- a/drivers/usb/gadget/ether.c Sat Jul 19 12:54:29 2003 +++ b/drivers/usb/gadget/ether.c Sat Jul 19 12:54:29 2003 @@ -1,5 +1,5 @@ /* - * ether.c -- CDC 1.1 Ethernet gadget driver + * ether.c -- Ethernet gadget driver, with CDC and non-CDC options * * Copyright (C) 2003 David Brownell * @@ -58,21 +58,23 @@ /*-------------------------------------------------------------------------*/ /* - * "Communications Device Class" (CDC) Ethernet class driver + * Ethernet gadget driver -- with CDC and non-CDC options * * CDC Ethernet is the standard USB solution for sending Ethernet frames * using USB. Real hardware tends to use the same framing protocol but look * different for control features. And Microsoft pushes their own approach * (RNDIS) instead of the standard. + * + * There's some hardware that can't talk CDC. We make that hardware + * implement a "minimalist" vendor-agnostic CDC core: same framing, but + * link-level setup only requires activating the configuration. */ -#define DRIVER_DESC "CDC Ethernet Gadget" -#define DRIVER_VERSION "29 April 2003" +#define DRIVER_DESC "Ethernet Gadget" +#define DRIVER_VERSION "Bastille Day 2003" static const char shortname [] = "ether"; static const char driver_desc [] = DRIVER_DESC; -static const char control_name [] = "Communications Control"; -static const char data_name [] = "CDC Ethernet Data"; #define MIN_PACKET sizeof(struct ethhdr) #define MAX_PACKET ETH_DATA_LEN /* biggest packet we'll rx/tx */ @@ -92,8 +94,7 @@ const struct usb_endpoint_descriptor *in, *out, *status; - struct semaphore mutex; - struct net_device net; + struct net_device *net; struct net_device_stats stats; atomic_t tx_qlen; @@ -112,7 +113,7 @@ static unsigned qmult = 4; -#define HS_FACTOR 15 +#define HS_FACTOR 5 #define qlen(gadget) \ (qmult*((gadget->speed == USB_SPEED_HIGH) ? HS_FACTOR : 1)) @@ -128,7 +129,7 @@ /* Thanks to NetChip Technologies for donating this product ID. * - * DO NOT REUSE THESE IDs with any other driver!! Ever!! + * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! * Instead: allocate your own, using normal USB-IF procedures. */ #define DRIVER_VENDOR_NUM 0x0525 /* NetChip */ @@ -158,6 +159,11 @@ * for some reason doesn't handle full speed bulk maxpacket of 64. */ +#define DEV_CONFIG_VALUE 3 /* some hardware cares */ + +/* #undef on hardware that can't implement CDC */ +#define DEV_CONFIG_CDC + /* * NetChip 2280, PCI based. * @@ -172,7 +178,7 @@ #define DRIVER_VERSION_NUM 0x0101 #define EP0_MAXPACKET 64 static const char EP_OUT_NAME [] = "ep-a"; -#define EP_OUT_NUM 2 +#define EP_OUT_NUM 1 static const char EP_IN_NAME [] = "ep-b"; #define EP_IN_NUM 2 static const char EP_STATUS_NAME [] = "ep-f"; @@ -194,22 +200,21 @@ #endif /* - * PXA-250 UDC: widely used in second gen Linux-capable PDAs. + * PXA-2xx UDC: widely used in second gen Linux-capable ARM PDAs + * and other products. * - * no limitations except from set_interface: docs say "no" to a third - * interface. and the interrupt-only endpoints don't toggle, so we'll - * just use a bulk-capable one instead. + * multiple interfaces (or altsettings) aren't usable. so this hardware + * can't implement CDC, which needs both capabilities. */ -#ifdef CONFIG_USB_ETH_PXA250 -#define CHIP "pxa250" +#ifdef CONFIG_USB_ETH_PXA2XX +#undef DEV_CONFIG_CDC +#define CHIP "pxa2xx" #define DRIVER_VERSION_NUM 0x0103 #define EP0_MAXPACKET 16 -static const char EP_OUT_NAME [] = "ep12out-bulk"; -#define EP_OUT_NUM 12 -static const char EP_IN_NAME [] = "ep11in-bulk"; -#define EP_IN_NUM 11 -static const char EP_STATUS_NAME [] = "ep6in-bulk"; -#define EP_STATUS_NUM 6 +static const char EP_OUT_NAME [] = "ep2out-bulk"; +#define EP_OUT_NUM 2 +static const char EP_IN_NAME [] = "ep1in-bulk"; +#define EP_IN_NUM 1 /* doesn't support bus-powered operation */ #define SELFPOWER USB_CONFIG_ATT_SELFPOWER /* supports remote wakeup, but this driver doesn't */ @@ -247,6 +252,29 @@ # error Configure some USB peripheral controller driver! #endif +/* We normally expect hardware that can talk CDC. That involves + * using multiple interfaces and altsettings, and maybe a status + * interrupt. Driver binding to be done according to USB-IF class, + * though you can use different VENDOR and PRODUCT numbers if you + * want (and they're officially assigned). + * + * For hardware that can't talk CDC, we use the same vendor ID that + * ARM Linux has used for ethernet-over-usb, both with sa1100 and + * with pxa250. We're protocol-compatible, if the host-side drivers + * use the endpoint descriptors. DRIVER_VERSION_NUM is nonzero, so + * drivers that need to hard-wire endpoint numbers have a hook. + */ +#ifdef DEV_CONFIG_CDC +#define DEV_CONFIG_CLASS USB_CLASS_COMM +#else +#define DEV_CONFIG_CLASS USB_CLASS_VENDOR_SPEC +#undef EP_STATUS_NUM +#undef DRIVER_VENDOR_NUM +#undef DRIVER_PRODUCT_NUM +#define DRIVER_VENDOR_NUM 0x049f +#define DRIVER_PRODUCT_NUM 0x505a +#endif /* CONFIG_CDC_ETHER */ + /* power usage is config specific. * hardware that supports remote wakeup defaults to disabling it. */ @@ -274,7 +302,8 @@ /*-------------------------------------------------------------------------*/ #define xprintk(d,level,fmt,args...) \ - dev_printk(level , &(d)->gadget->dev , fmt , ## args) + printk(level "%s %s: " fmt , shortname , (d)->gadget->dev.bus_id , \ + ## args) #ifdef DEBUG #undef DEBUG @@ -309,7 +338,7 @@ /* * DESCRIPTORS ... most are static, but strings and (full) configuration * descriptors are built on demand. Notice how most of the cdc descriptors - * add no value to simple (typical) configurations. + * aren't needed in the "minimalist" mode. */ #define STRING_MANUFACTURER 1 @@ -323,15 +352,14 @@ /* * This device advertises one configuration. */ -#define CONFIG_CDC_ETHER 3 - static const struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, .bcdUSB = __constant_cpu_to_le16 (0x0200), - .bDeviceClass = USB_CLASS_COMM, + + .bDeviceClass = DEV_CONFIG_CLASS, .bDeviceSubClass = 0, .bDeviceProtocol = 0, .bMaxPacketSize0 = EP0_MAXPACKET, @@ -350,13 +378,26 @@ .bDescriptorType = USB_DT_CONFIG, /* compute wTotalLength on the fly */ +#ifdef DEV_CONFIG_CDC .bNumInterfaces = 2, - .bConfigurationValue = CONFIG_CDC_ETHER, +#else + .bNumInterfaces = 1, +#endif + .bConfigurationValue = DEV_CONFIG_VALUE, .iConfiguration = STRING_PRODUCT, .bmAttributes = USB_CONFIG_ATT_ONE | SELFPOWER | WAKEUP, .bMaxPower = (MAX_USB_POWER + 1) / 2, }; +#ifdef DEV_CONFIG_CDC + +/* + * Compared to the "minimalist" non-CDC model, the CDC model adds + * three class descriptors, two interface descrioptors, and a status + * endpoint. Both have a "data" interface and two bulk endpoints. + * There are also differences in how control requests are handled. + */ + /* master comm interface optionally has a status notification endpoint */ static const struct usb_interface_descriptor @@ -446,7 +487,7 @@ * some drivers (like current Linux cdc-ether!) "need" it to exist even * if they ignore the connect/disconnect notifications that real aether * can provide. more advanced cdc configurations might want to support - * encapsulated commands. + * encapsulated commands (vendor-specific, using control-OUT). */ #define LOG2_STATUS_INTERVAL_MSEC 6 @@ -494,6 +535,29 @@ .bInterfaceProtocol = 0, .iInterface = STRING_DATA, }; +#else + +/* + * "Minimalist" non-CDC option is a simple vendor-neutral model that most + * full speed controllers can handle: one interface, two bulk endpoints. + */ + +static const struct usb_interface_descriptor +data_intf = { + .bLength = sizeof data_intf, + .bDescriptorType = USB_DT_INTERFACE, + + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = STRING_DATA, +}; + +#endif /* DEV_CONFIG_CDC */ + static const struct usb_endpoint_descriptor fs_source_desc = { @@ -563,12 +627,12 @@ .bDescriptorType = USB_DT_DEVICE_QUALIFIER, .bcdUSB = __constant_cpu_to_le16 (0x0200), - .bDeviceClass = USB_CLASS_VENDOR_SPEC, + .bDeviceClass = DEV_CONFIG_CLASS, /* assumes ep0 uses the same value for both speeds ... */ .bMaxPacketSize0 = EP0_MAXPACKET, - .bNumConfigurations = 2, + .bNumConfigurations = 1, }; /* maxpacket and other transfer characteristics vary by speed. */ @@ -581,16 +645,24 @@ #endif /* !HIGHSPEED */ +/*-------------------------------------------------------------------------*/ + +/* descriptors that are built on-demand */ + +#ifdef DEV_CONFIG_CDC /* address that the host will use ... usually assigned at random */ static char ethaddr [2 * ETH_ALEN + 1]; +#endif /* static strings, in iso 8859/1 */ static struct usb_string strings [] = { { STRING_MANUFACTURER, UTS_SYSNAME " " UTS_RELEASE "/" CHIP, }, { STRING_PRODUCT, driver_desc, }, +#ifdef DEV_CONFIG_CDC { STRING_ETHADDR, ethaddr, }, - { STRING_CONTROL, control_name, }, - { STRING_DATA, data_name, }, + { STRING_CONTROL, "CDC Communications Control", }, +#endif + { STRING_DATA, "Ethernet Data", }, { } /* end of list */ }; @@ -607,14 +679,18 @@ config_buf (enum usb_device_speed speed, u8 *buf, u8 type, unsigned index) { const unsigned config_len = USB_DT_CONFIG_SIZE - + 3 * USB_DT_INTERFACE_SIZE +#ifdef DEV_CONFIG_CDC + + 2 * USB_DT_INTERFACE_SIZE + sizeof header_desc + sizeof union_desc + sizeof ether_desc #ifdef EP_STATUS_NUM + USB_DT_ENDPOINT_SIZE #endif +#endif /* DEV_CONFIG_CDC */ + + USB_DT_INTERFACE_SIZE + 2 * USB_DT_ENDPOINT_SIZE; + #ifdef HIGHSPEED int hs; #endif @@ -636,6 +712,7 @@ hs = !hs; #endif +#ifdef DEV_CONFIG_CDC /* control interface, class descriptors, optional status endpoint */ memcpy (buf, &control_intf, USB_DT_INTERFACE_SIZE); buf += USB_DT_INTERFACE_SIZE; @@ -660,6 +737,7 @@ /* default data altsetting has no endpoints */ memcpy (buf, &data_nop_intf, USB_DT_INTERFACE_SIZE); buf += USB_DT_INTERFACE_SIZE; +#endif /* DEV_CONFIG_CDC */ /* the "real" data interface has two endpoints */ memcpy (buf, &data_intf, USB_DT_INTERFACE_SIZE); @@ -684,6 +762,8 @@ /*-------------------------------------------------------------------------*/ +static void eth_start (struct eth_dev *dev, int gfp_flags); + static int set_ether_config (struct eth_dev *dev, int gfp_flags) { @@ -694,7 +774,8 @@ gadget_for_each_ep (ep, gadget) { const struct usb_endpoint_descriptor *d; - /* NOTE: the host isn't allowed to use these two data +#ifdef DEV_CONFIG_CDC + /* With CDC, the host isn't allowed to use these two data * endpoints in the default altsetting for the interface. * so we don't activate them yet. */ @@ -714,10 +795,11 @@ dev->out_ep = ep; dev->out = d; continue; + } #ifdef EP_STATUS_NUM /* optional status/notification endpoint */ - } else if (strcmp (ep->name, EP_STATUS_NAME) == 0) { + else if (strcmp (ep->name, EP_STATUS_NAME) == 0) { d = ep_desc (gadget, &hs_status_desc, &fs_status_desc); result = usb_ep_enable (ep, d); if (result == 0) { @@ -726,16 +808,57 @@ dev->status = d; continue; } + } #endif +#else /* !CONFIG_CDC_ETHER */ + + /* non-CDC is simpler: if the device is there, + * it's live with rx and tx endpoints. + */ + /* one endpoint writes data back IN to the host */ + if (strcmp (ep->name, EP_IN_NAME) == 0) { + d = ep_desc (gadget, &hs_source_desc, &fs_source_desc); + result = usb_ep_enable (ep, d); + if (result == 0) { + ep->driver_data = dev; + dev->in_ep = ep; + dev->in = d; + continue; + } + + /* one endpoint just reads OUT packets */ + } else if (strcmp (ep->name, EP_OUT_NAME) == 0) { + d = ep_desc (gadget, &hs_sink_desc, &fs_sink_desc); + result = usb_ep_enable (ep, d); + if (result == 0) { + ep->driver_data = dev; + dev->out_ep = ep; + dev->out = d; + continue; + } + } + +#endif /* !CONFIG_CDC_ETHER */ + /* ignore any other endpoints */ - } else + else continue; /* stop on error */ ERROR (dev, "can't enable %s, result %d\n", ep->name, result); break; } + if (!result && (!dev->in_ep || !dev->out_ep)) + result = -ENODEV; + +#ifndef DEV_CONFIG_CDC + if (result == 0) { + netif_carrier_on (dev->net); + if (netif_running (dev->net)) + eth_start (dev, GFP_ATOMIC); + } +#endif /* !CONFIG_CDC_ETHER */ if (result == 0) DEBUG (dev, "qlen %d\n", qlen (gadget)); @@ -751,8 +874,8 @@ DEBUG (dev, "%s\n", __FUNCTION__); - netif_stop_queue (&dev->net); - netif_carrier_off (&dev->net); + netif_stop_queue (dev->net); + netif_carrier_off (dev->net); /* just disable endpoints, forcing completion of pending i/o. * all our completion handlers free their requests in this case. @@ -797,7 +920,7 @@ hw_optimize (gadget); switch (number) { - case CONFIG_CDC_ETHER: + case DEV_CONFIG_VALUE: result = set_ether_config (dev, gfp_flags); break; default: @@ -807,8 +930,6 @@ return result; } - if (!result && (!dev->in_ep || !dev->out_ep)) - result = -ENODEV; if (result) eth_reset_config (dev); else { @@ -896,6 +1017,7 @@ * FIXME ugly idiom, maybe we'd be better with just * a "cancel the whole queue" primitive since any * unlink-one primitive has way too many error modes. + * here, we "know" toggle is already clear... */ usb_ep_disable (dev->status_ep); usb_ep_enable (dev->status_ep, dev->status); @@ -953,8 +1075,6 @@ */ #define CDC_SET_ETHERNET_PACKET_FILTER 0x43 /* required */ -static void eth_start (struct eth_dev *dev, int gfp_flags); - /* * The setup() callback implements all the ep0 functionality that's not * handled lower down. CDC has a number of less-common features: @@ -1018,6 +1138,17 @@ value = eth_set_config (dev, ctrl->wValue, GFP_ATOMIC); spin_unlock (&dev->lock); break; +#ifdef CONFIG_USB_ETH_PXA2XX + /* PXA UDC prevents us from using SET_INTERFACE in normal ways. + * And it hides GET_CONFIGURATION and GET_INTERFACE too. + */ + case USB_REQ_SET_INTERFACE: + spin_lock (&dev->lock); + value = eth_set_config (dev, DEV_CONFIG_VALUE, GFP_ATOMIC); + spin_unlock (&dev->lock); + break; + +#else /* hardware that that stays out of our way */ case USB_REQ_GET_CONFIGURATION: if (ctrl->bRequestType != USB_DIR_IN) break; @@ -1056,15 +1187,15 @@ if (ctrl->wValue == 1) { usb_ep_enable (dev->in_ep, dev->in); usb_ep_enable (dev->out_ep, dev->out); - netif_carrier_on (&dev->net); + netif_carrier_on (dev->net); #ifdef EP_STATUS_NUM issue_start_status (dev); #endif - if (netif_running (&dev->net)) + if (netif_running (dev->net)) eth_start (dev, GFP_ATOMIC); } else { - netif_stop_queue (&dev->net); - netif_carrier_off (&dev->net); + netif_stop_queue (dev->net); + netif_carrier_off (dev->net); } value = 0; break; @@ -1079,12 +1210,14 @@ /* if carrier is on, data interface is active. */ *(u8 *)req->buf = - ((ctrl->wIndex == 1) && netif_carrier_ok (&dev->net)) + ((ctrl->wIndex == 1) && netif_carrier_ok (dev->net)) ? 1 : 0, value = min (ctrl->wLength, (u16) 1); break; +#endif +#ifdef DEV_CONFIG_CDC case CDC_SET_ETHERNET_PACKET_FILTER: /* see 6.2.30: no data, wIndex = interface, * wValue = packet filter bitmap @@ -1099,6 +1232,7 @@ */ value = 0; break; +#endif /* DEV_CONFIG_CDC */ default: VDEBUG (dev, @@ -1129,8 +1263,8 @@ unsigned long flags; spin_lock_irqsave (&dev->lock, flags); - netif_stop_queue (&dev->net); - netif_carrier_off (&dev->net); + netif_stop_queue (dev->net); + netif_carrier_off (dev->net); eth_reset_config (dev); spin_unlock_irqrestore (&dev->lock, flags); @@ -1175,10 +1309,10 @@ memset (&info, 0, sizeof info); info.cmd = ETHTOOL_GDRVINFO; - strncpy (info.driver, shortname, sizeof info.driver); - strncpy (info.version, DRIVER_VERSION, sizeof info.version); - strncpy (info.fw_version, CHIP, sizeof info.fw_version); - strncpy (info.bus_info, dev->gadget->dev.bus_id, + strlcpy (info.driver, shortname, sizeof info.driver); + strlcpy (info.version, DRIVER_VERSION, sizeof info.version); + strlcpy (info.fw_version, CHIP, sizeof info.fw_version); + strlcpy (info.bus_info, dev->gadget->dev.bus_id, sizeof info.bus_info); if (copy_to_user (useraddr, &info, sizeof (info))) return -EFAULT; @@ -1227,7 +1361,7 @@ int retval = 0; size_t size; - size = (sizeof (struct ethhdr) + dev->net.mtu + RX_EXTRA); + size = (sizeof (struct ethhdr) + dev->net->mtu + RX_EXTRA); if ((skb = alloc_skb (size, gfp_flags)) == 0) { DEBUG (dev, "no rx skb\n"); @@ -1241,16 +1375,9 @@ req->complete = rx_complete; req->context = skb; - if (netif_running (&dev->net)) { - retval = usb_ep_queue (dev->out_ep, req, gfp_flags); - if (retval == -ENOMEM) - defer_kevent (dev, WORK_RX_MEMORY); - if (retval) - DEBUG (dev, "%s %d\n", __FUNCTION__, retval); - } else { - DEBUG (dev, "%s stopped\n", __FUNCTION__); - retval = -ENOLINK; - } + retval = usb_ep_queue (dev->out_ep, req, gfp_flags); + if (retval == -ENOMEM) + defer_kevent (dev, WORK_RX_MEMORY); if (retval) { DEBUG (dev, "rx submit --> %d\n", retval); dev_kfree_skb_any (skb); @@ -1278,8 +1405,8 @@ break; } - skb->dev = &dev->net; - skb->protocol = eth_type_trans (skb, &dev->net); + skb->dev = dev->net; + skb->protocol = eth_type_trans (skb, dev->net); dev->stats.rx_packets++; dev->stats.rx_bytes += skb->len; @@ -1294,9 +1421,7 @@ case -ECONNRESET: // unlink case -ESHUTDOWN: // disconnect etc VDEBUG (dev, "rx shutdown, code %d\n", status); - usb_ep_free_request (dev->out_ep, req); - req = 0; - break; + goto clean; /* data overrun */ case -EOVERFLOW: @@ -1311,7 +1436,11 @@ if (skb) dev_kfree_skb_any (skb); - + if (!netif_running (dev->net)) { +clean: + usb_ep_free_request (dev->out_ep, req); + req = 0; + } if (req) rx_submit (dev, req, GFP_ATOMIC); } @@ -1323,7 +1452,7 @@ if (test_bit (WORK_RX_MEMORY, &dev->todo)) { struct usb_request *req = 0; - if (netif_running (&dev->net)) + if (netif_running (dev->net)) req = usb_ep_alloc_request (dev->in_ep, GFP_KERNEL); else clear_bit (WORK_RX_MEMORY, &dev->todo); @@ -1342,18 +1471,25 @@ struct sk_buff *skb = req->context; struct eth_dev *dev = ep->driver_data; - if (req->status) + switch (req->status) { + default: dev->stats.tx_errors++; - else + VDEBUG (dev, "tx err %d\n", req->status); + /* FALLTHROUGH */ + case -ECONNRESET: // unlink + case -ESHUTDOWN: // disconnect etc + break; + case 0: dev->stats.tx_bytes += skb->len; + } dev->stats.tx_packets++; usb_ep_free_request (ep, req); dev_kfree_skb_any (skb); atomic_inc (&dev->tx_qlen); - if (netif_carrier_ok (&dev->net)) - netif_wake_queue (&dev->net); + if (netif_carrier_ok (dev->net)) + netif_wake_queue (dev->net); } static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) @@ -1437,7 +1573,7 @@ /* and open the tx floodgates */ atomic_set (&dev->tx_qlen, size); - netif_wake_queue (&dev->net); + netif_wake_queue (dev->net); } static int eth_open (struct net_device *net) @@ -1445,10 +1581,8 @@ struct eth_dev *dev = (struct eth_dev *) net->priv; DEBUG (dev, "%s\n", __FUNCTION__); - down (&dev->mutex); - if (netif_carrier_ok (&dev->net)) + if (netif_carrier_ok (dev->net)) eth_start (dev, GFP_KERNEL); - up (&dev->mutex); return 0; } @@ -1457,7 +1591,6 @@ struct eth_dev *dev = (struct eth_dev *) net->priv; DEBUG (dev, "%s\n", __FUNCTION__); - down (&dev->mutex); netif_stop_queue (net); DEBUG (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n", @@ -1469,7 +1602,7 @@ if (dev->gadget->speed != USB_SPEED_UNKNOWN) { usb_ep_disable (dev->in_ep); usb_ep_disable (dev->out_ep); - if (netif_carrier_ok (&dev->net)) { + if (netif_carrier_ok (dev->net)) { DEBUG (dev, "host still using in/out endpoints\n"); usb_ep_enable (dev->in_ep, dev->in); usb_ep_enable (dev->out_ep, dev->out); @@ -1480,7 +1613,6 @@ #endif } - up (&dev->mutex); return 0; } @@ -1492,7 +1624,6 @@ struct eth_dev *dev = get_gadget_data (gadget); DEBUG (dev, "unbind\n"); - down (&dev->mutex); /* we've already been disconnected ... no i/o is active */ if (dev->req) { @@ -1500,15 +1631,13 @@ dev->req->buf, dev->req->dma, USB_BUFSIZ); usb_ep_free_request (gadget->ep0, dev->req); + dev->req = 0; } - unregister_netdev (&dev->net); - up (&dev->mutex); + unregister_netdev (dev->net); /* assuming we used keventd, it must quiesce too */ flush_scheduled_work (); - - kfree (dev); set_gadget_data (gadget, 0); } @@ -1517,22 +1646,24 @@ { struct eth_dev *dev; struct net_device *net; + int status = -ENOMEM; +#ifdef DEV_CONFIG_CDC u8 node_id [ETH_ALEN]; /* just one upstream link at a time */ if (ethaddr [0] != 0) return -ENODEV; +#endif - dev = kmalloc (sizeof *dev, SLAB_KERNEL); - if (!dev) - return -ENOMEM; - memset (dev, 0, sizeof *dev); + net = alloc_etherdev (sizeof *dev); + if (!net) + return status; + dev = net->priv; spin_lock_init (&dev->lock); - init_MUTEX_LOCKED (&dev->mutex); INIT_WORK (&dev->work, eth_work, dev); /* network device setup */ - net = &dev->net; + dev->net = net; SET_MODULE_OWNER (net); net->priv = dev; strcpy (net->name, "usb%d"); @@ -1545,6 +1676,7 @@ net->dev_addr [0] &= 0xfe; // clear multicast bit net->dev_addr [0] |= 0x02; // set local assignment bit (IEEE802) +#ifdef DEV_CONFIG_CDC /* ... another address for the host, on the other end of the * link, gets exported through CDC (see CDC spec table 41) */ @@ -1554,6 +1686,7 @@ snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X", node_id [0], node_id [1], node_id [2], node_id [3], node_id [4], node_id [5]); +#endif net->change_mtu = eth_change_mtu; net->get_stats = eth_get_stats; @@ -1567,36 +1700,38 @@ /* preallocate control response and buffer */ dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL); if (!dev->req) - goto enomem; + goto fail; dev->req->complete = eth_setup_complete; dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ, &dev->req->dma, GFP_KERNEL); if (!dev->req->buf) { usb_ep_free_request (gadget->ep0, dev->req); - goto enomem; + goto fail; } /* finish hookup to lower layer ... */ dev->gadget = gadget; set_gadget_data (gadget, dev); gadget->ep0->driver_data = dev; - + INFO (dev, "%s, " CHIP ", version: " DRIVER_VERSION "\n", driver_desc); +#ifdef DEV_CONFIG_CDC + INFO (dev, "CDC host enet %s\n", ethaddr); +#endif + /* two kinds of host-initiated state changes: * - iff DATA transfer is active, carrier is "on" * - tx queueing enabled if open *and* carrier is "on" */ - INFO (dev, "%s, host enet %s, version: " DRIVER_VERSION "\n", - driver_desc, ethaddr); - register_netdev (&dev->net); - netif_stop_queue (&dev->net); - netif_carrier_off (&dev->net); - - up (&dev->mutex); - return 0; + netif_stop_queue (dev->net); + netif_carrier_off (dev->net); -enomem: + // SET_NETDEV_DEV (dev->net, &gadget->dev); + status = register_netdev (dev->net); + if (status == 0) + return status; +fail: eth_unbind (gadget); - return -ENOMEM; + return status; } /*-------------------------------------------------------------------------*/ diff -Nru a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c --- a/drivers/usb/gadget/net2280.c Sat Jul 19 12:54:22 2003 +++ b/drivers/usb/gadget/net2280.c Sat Jul 19 12:54:22 2003 @@ -2496,7 +2496,7 @@ device_remove_file (&pdev->dev, &dev_attr_registers); pci_set_drvdata (pdev, 0); - INFO (dev, "unbind from pci %s\n", pdev->slot_name); + INFO (dev, "unbind from pci %s\n", pci_name(pdev)); kfree (dev); the_controller = 0; @@ -2518,7 +2518,7 @@ * usb_gadget_driver_{register,unregister}() must change. */ if (the_controller) { - WARN (the_controller, "ignoring %s\n", pdev->slot_name); + WARN (the_controller, "ignoring %s\n", pci_name(pdev)); return -EBUSY; } @@ -2534,7 +2534,7 @@ dev->pdev = pdev; dev->gadget.ops = &net2280_ops; - strcpy (dev->gadget.dev.bus_id, pdev->slot_name); + strcpy (dev->gadget.dev.bus_id, pci_name(pdev)); strcpy (dev->gadget.dev.name, pdev->dev.name); dev->gadget.dev.parent = &pdev->dev; dev->gadget.dev.dma_mask = pdev->dev.dma_mask; diff -Nru a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h --- a/drivers/usb/gadget/net2280.h Sat Jul 19 12:54:26 2003 +++ b/drivers/usb/gadget/net2280.h Sat Jul 19 12:54:26 2003 @@ -654,7 +654,7 @@ #define xprintk(dev,level,fmt,args...) \ printk(level "%s %s: " fmt , driver_name , \ - dev->pdev->slot_name , ## args) + pci_name(dev->pdev) , ## args) #ifdef DEBUG #undef DEBUG diff -Nru a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c --- a/drivers/usb/gadget/zero.c Sat Jul 19 12:54:24 2003 +++ b/drivers/usb/gadget/zero.c Sat Jul 19 12:54:24 2003 @@ -92,7 +92,7 @@ /*-------------------------------------------------------------------------*/ -#define DRIVER_VERSION "19 Feb 2003" +#define DRIVER_VERSION "Bastille Day 2003" static const char shortname [] = "zero"; static const char longname [] = "Gadget Zero"; @@ -160,18 +160,18 @@ #endif /* - * PXA-250 UDC: widely used in second gen Linux-capable PDAs. + * PXA-2xx UDC: widely used in second gen Linux-capable PDAs. * * This has fifteen fixed-function full speed endpoints, and it * can support all USB transfer types. * - * It only supports three configurations (numbered 1, 2, or 3) - * with two interfaces each ... there's partial hardware support - * for set_configuration and set_interface, preventing some more - * interesting config/interface/endpoint arrangements. + * These supports three or four configurations, with fixed numbers. + * The hardware interprets SET_INTERFACE, net effect is that you + * can't use altsettings or reset the interfaces independently. + * So stick to a single interface. */ -#ifdef CONFIG_USB_ZERO_PXA250 -#define CHIP "pxa250" +#ifdef CONFIG_USB_ZERO_PXA2XX +#define CHIP "pxa2xx" #define DRIVER_VERSION_NUM 0x0103 #define EP0_MAXPACKET 16 static const char EP_OUT_NAME [] = "ep12out-bulk"; @@ -291,9 +291,12 @@ static unsigned buflen = 4096; static unsigned qlen = 32; +static unsigned pattern = 0; module_param (buflen, uint, S_IRUGO|S_IWUSR); module_param (qlen, uint, S_IRUGO|S_IWUSR); +module_param (pattern, uint, S_IRUGO|S_IWUSR); + /* * Normally the "loopback" configuration is second (index 1) so @@ -497,8 +500,8 @@ /* * config descriptors are also handcrafted. these must agree with code - * that sets configurations, and with code managing interface altsettings. - * other complexity may come from: + * that sets configurations, and with code managing interfaces and their + * altsettings. other complexity may come from: * * - high speed support, including "other speed config" rules * - multiple configurations @@ -506,7 +509,7 @@ * - embedded class or vendor-specific descriptors * * this handles high speed, and has a second config that could as easily - * have been an alternate interface setting. + * have been an alternate interface setting (on most hardware). * * NOTE: to demonstrate (and test) more USB capabilities, this driver * should include an altsetting to test interrupt transfers, including @@ -608,16 +611,29 @@ struct usb_request *req ) { - int i; + unsigned i; + u8 *buf = req->buf; - for (i = 0; i < req->actual; i++) { - if (((u8 *)req->buf) [i] != 0) { - ERROR (dev, "nonzero OUT byte from host, " - "buf [%d] = %d\n", - i, ((u8 *)req->buf) [i]); - usb_ep_set_halt (ep); - return -EINVAL; + for (i = 0; i < req->actual; i++, buf++) { + switch (pattern) { + /* all-zeroes has no synchronization issues */ + case 0: + if (*buf == 0) + continue; + break; + /* mod63 stays in sync with short-terminated transfers, + * or otherwise when host and gadget agree on how large + * each usb transfer request should be. resync is done + * with set_interface or set_config. + */ + case 1: + if (*buf == (u8)(i % 63)) + continue; + break; } + ERROR (dev, "bad OUT byte, buf [%d] = %d\n", i, *buf); + usb_ep_set_halt (ep); + return -EINVAL; } return 0; } @@ -629,7 +645,18 @@ struct usb_request *req ) { - memset (req->buf, 0, req->length); + unsigned i; + u8 *buf = req->buf; + + switch (pattern) { + case 0: + memset (req->buf, 0, req->length); + break; + case 1: + for (i = 0; i < req->length; i++) + *buf++ = (u8) (i % 63); + break; + } } /* if there is only one request in the queue, there'll always be an @@ -651,10 +678,13 @@ break; /* this endpoint is normally active while we're configured */ + case -ECONNABORTED: /* hardware forced ep reset */ case -ECONNRESET: /* request dequeued */ case -ESHUTDOWN: /* disconnect from host */ VDEBUG (dev, "%s gone (%d), %d/%d\n", ep->name, status, req->actual, req->length); + if (ep == dev->out_ep) + check_read_data (dev, ep, req); free_ep_req (ep, req); return; @@ -693,6 +723,9 @@ memset (req->buf, 0, req->length); req->complete = source_sink_complete; + if (strcmp (ep->name, EP_IN_NAME) == 0) + reinit_write_data (ep->driver_data, ep, req); + status = usb_ep_queue (ep, req, gfp_flags); if (status) { struct zero_dev *dev = ep->driver_data; @@ -801,6 +834,8 @@ * rely on the hardware driver to clean up on disconnect or * endpoint disable. */ + case -ECONNABORTED: /* hardware forced ep reset */ + case -ECONNRESET: /* request dequeued */ case -ESHUTDOWN: /* disconnect from host */ free_ep_req (ep, req); return; @@ -905,7 +940,7 @@ * * note that some device controller hardware will constrain what this * code can do, perhaps by disallowing more than one configuration or - * by limiting configuration choices (like the pxa250). + * by limiting configuration choices (like the pxa2xx). */ static int zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags) @@ -1046,7 +1081,8 @@ break; /* until we add altsetting support, or other interfaces, - * only 0/0 are possible. + * only 0/0 are possible. pxa2xx only supports 0/0 (poorly) + * and already killed pending endpoint I/O. */ case USB_REQ_SET_INTERFACE: if (ctrl->bRequestType != USB_RECIP_INTERFACE) diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c --- a/drivers/usb/host/ohci-hcd.c Sat Jul 19 12:54:22 2003 +++ b/drivers/usb/host/ohci-hcd.c Sat Jul 19 12:54:22 2003 @@ -319,6 +319,7 @@ int epnum = ep & USB_ENDPOINT_NUMBER_MASK; unsigned long flags; struct ed *ed; + unsigned limit = 1000; /* ASSERT: any requests/urbs are being unlinked */ /* ASSERT: nobody can be submitting urbs for this any more */ @@ -337,6 +338,8 @@ ed->state = ED_IDLE; switch (ed->state) { case ED_UNLINK: /* wait for hw to finish? */ + /* major IRQ delivery trouble loses INTR_SF too... */ + WARN_ON (limit-- == 0); spin_unlock_irqrestore (&ohci->lock, flags); set_current_state (TASK_UNINTERRUPTIBLE); schedule_timeout (1); diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c --- a/drivers/usb/host/ohci-q.c Sat Jul 19 12:54:29 2003 +++ b/drivers/usb/host/ohci-q.c Sat Jul 19 12:54:29 2003 @@ -43,6 +43,16 @@ spin_lock (&urb->lock); if (likely (urb->status == -EINPROGRESS)) urb->status = 0; + /* report short control reads right even though the data TD always + * has TD_R set. (much simpler, but creates the 1-td limit.) + */ + if (unlikely (urb->transfer_flags & URB_SHORT_NOT_OK) + && unlikely (usb_pipecontrol (urb->pipe)) + && urb->actual_length < urb->transfer_buffer_length + && usb_pipein (urb->pipe) + && urb->status == 0) { + urb->status = -EREMOTEIO; + } spin_unlock (&urb->lock); // what lock protects these? diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c --- a/drivers/usb/host/uhci-hcd.c Sat Jul 19 12:54:27 2003 +++ b/drivers/usb/host/uhci-hcd.c Sat Jul 19 12:54:27 2003 @@ -2007,19 +2007,17 @@ unsigned int io_addr = uhci->io_addr; int i; - if (!uhci->hcd.pdev || - uhci->hcd.pdev->vendor != PCI_VENDOR_ID_INTEL || - uhci->hcd.pdev->device != PCI_DEVICE_ID_INTEL_82371AB_2) + if (!uhci->hcd.pdev || uhci->hcd.pdev->vendor != PCI_VENDOR_ID_INTEL) return 1; - /* This is a 82371AB/EB/MB USB controller which has a bug that - * causes false resume indications if any port has an - * over current condition. To prevent problems, we will not - * allow a global suspend if any ports are OC. + /* Some of Intel's USB controllers have a bug that causes false + * resume indications if any port has an over current condition. + * To prevent problems, we will not allow a global suspend if + * any ports are OC. * - * Some motherboards using the 82371AB/EB/MB (but not the USB portion) - * appear to hardwire the over current inputs active to disable - * the USB ports. + * Some motherboards using Intel's chipsets (but not using all + * the USB ports) appear to hardwire the over current inputs active + * to disable the USB ports. */ /* check for over current condition on any port */ diff -Nru a/drivers/usb/image/hpusbscsi.c b/drivers/usb/image/hpusbscsi.c --- a/drivers/usb/image/hpusbscsi.c Sat Jul 19 12:54:30 2003 +++ b/drivers/usb/image/hpusbscsi.c Sat Jul 19 12:54:30 2003 @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include "../../scsi/scsi.h" #include "../../scsi/hosts.h" @@ -109,7 +109,8 @@ goto out_unlink_controlurb; new->host->hostdata[0] = (unsigned long)new; - scsi_add_host(new->host, &intf->dev); + scsi_add_host(new->host, &intf->dev); /* XXX handle failure */ + scsi_scan_host(new->host); new->sense_command[0] = REQUEST_SENSE; new->sense_command[4] = HPUSBSCSI_SENSE_LENGTH; @@ -306,7 +307,10 @@ if(unlikely(u->status < 0)) { if (likely(hpusbscsi->state != HP_STATE_FREE)) handle_usb_error(hpusbscsi); - return; + if (u->status == -ECONNRESET || u->status == -ENOENT || u->status == -ESHUTDOWN) + return; + else + goto resub; } scsi_state = hpusbscsi->scsi_state_byte; @@ -348,6 +352,8 @@ TRACE_STATE; break; } +resub: + usb_submit_urb(u, GFP_ATOMIC); } static void simple_command_callback(struct urb *u, struct pt_regs *regs) @@ -427,7 +433,7 @@ hpusbscsi->state = HP_STATE_WAIT; } else { issue_request_sense(hpusbscsi); - } + } } } else { if (likely(hpusbscsi->scallback != NULL)) diff -Nru a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c --- a/drivers/usb/image/microtek.c Sat Jul 19 12:54:30 2003 +++ b/drivers/usb/image/microtek.c Sat Jul 19 12:54:30 2003 @@ -134,7 +134,7 @@ #include #include -#include +#include #include "../../scsi/scsi.h" #include "../../scsi/hosts.h" @@ -817,7 +817,8 @@ goto out_free_urb; new_desc->host->hostdata[0] = (unsigned long)new_desc; - scsi_add_host(new_desc->host, NULL); + scsi_add_host(new_desc->host, NULL); /* XXX handle failure */ + scsi_scan_host(new_desc->host); usb_set_intfdata(intf, new_desc); return 0; diff -Nru a/drivers/usb/image/scanner.c b/drivers/usb/image/scanner.c --- a/drivers/usb/image/scanner.c Sat Jul 19 12:54:24 2003 +++ b/drivers/usb/image/scanner.c Sat Jul 19 12:54:24 2003 @@ -364,6 +364,11 @@ * Mustek, Pacific Image Electronics, Plustek, and Visioneer scanners. * Fixed names of some other scanners. * + * 0.4.14 2003-07-15 + * - Fixed race between open and probe (Oliver Neukum). + * - Added vendor/product ids for Avision, Canon, HP, Microtek and Relisys scanners. + * - Clean up irq urb when not enough memory is available. + * * TODO * - Performance * - Select/poll methods @@ -1068,6 +1073,9 @@ /* Ok, now initialize all the relevant values */ if (!(scn->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) { err("probe_scanner(%d): Not enough memory for the output buffer.", intf->minor); + if (have_intr) + usb_unlink_urb(scn->scn_irq); + usb_free_urb(scn->scn_irq); kfree(scn); up(&scn_mutex); return -ENOMEM; @@ -1076,6 +1084,9 @@ if (!(scn->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) { err("probe_scanner(%d): Not enough memory for the input buffer.", intf->minor); + if (have_intr) + usb_unlink_urb(scn->scn_irq); + usb_free_urb(scn->scn_irq); kfree(scn->obuf); kfree(scn); up(&scn_mutex); @@ -1117,10 +1128,9 @@ info ("USB scanner device (0x%04x/0x%04x) now attached to %s", dev->descriptor.idVendor, dev->descriptor.idProduct, name); - up(&scn_mutex); - usb_set_intfdata(intf, scn); - + up(&scn_mutex); + return 0; } diff -Nru a/drivers/usb/image/scanner.h b/drivers/usb/image/scanner.h --- a/drivers/usb/image/scanner.h Sat Jul 19 12:54:24 2003 +++ b/drivers/usb/image/scanner.h Sat Jul 19 12:54:24 2003 @@ -43,7 +43,7 @@ // #define DEBUG -#define DRIVER_VERSION "0.4.13" +#define DRIVER_VERSION "0.4.14" #define DRIVER_DESC "USB Scanner Driver" #include @@ -103,6 +103,7 @@ /* Avision */ { USB_DEVICE(0x0638, 0x0268) }, /* iVina 1200U */ { USB_DEVICE(0x0638, 0x0a10) }, /* iVina FB1600 (=Umax Astra 4500) */ + { USB_DEVICE(0x0638, 0x0a20) }, /* iVina FB1800 (=Umax Astra 4700) */ /* Benq: see Acer */ /* Brother */ { USB_DEVICE(0x04f9, 0x010f) }, /* MFC 5100C */ @@ -115,10 +116,12 @@ { USB_DEVICE(0x04a9, 0x2206) }, /* CanoScan N650U/N656U */ { USB_DEVICE(0x04a9, 0x2207) }, /* CanoScan N1220U */ { USB_DEVICE(0x04a9, 0x2208) }, /* CanoScan D660U */ + { USB_DEVICE(0x04a9, 0x220a) }, /* CanoScan D2400UF */ { USB_DEVICE(0x04a9, 0x220b) }, /* CanoScan D646U */ { USB_DEVICE(0x04a9, 0x220c) }, /* CanoScan D1250U2 */ { USB_DEVICE(0x04a9, 0x220d) }, /* CanoScan N670U/N676U/LIDE 20 */ { USB_DEVICE(0x04a9, 0x220e) }, /* CanoScan N1240U/LIDE 30 */ + { USB_DEVICE(0x04a9, 0x220f) }, /* CanoScan 8000F */ { USB_DEVICE(0x04a9, 0x2213) }, /* LIDE 50 */ { USB_DEVICE(0x04a9, 0x3042) }, /* FS4000US */ /* Colorado -- See Primax/Colorado below */ @@ -158,6 +161,7 @@ { USB_DEVICE(0x03f0, 0x0901) }, /* ScanJet 2300C */ { USB_DEVICE(0x03F0, 0x1005) }, /* ScanJet 5400C */ { USB_DEVICE(0x03F0, 0x1105) }, /* ScanJet 5470C */ + { USB_DEVICE(0x03f0, 0x1205) }, /* ScanJet 5550C */ { USB_DEVICE(0x03f0, 0x1305) }, /* Scanjet 4570c */ { USB_DEVICE(0x03f0, 0x1411) }, /* PSC 750 */ { USB_DEVICE(0x03f0, 0x2005) }, /* ScanJet 3570c */ @@ -173,6 +177,7 @@ /* Memorex */ { USB_DEVICE(0x0461, 0x0346) }, /* 6136u - repackaged Primax ? */ /* Microtek */ + { USB_DEVICE(0x05da, 0x20c9) }, /* ScanMaker 6700 */ { USB_DEVICE(0x05da, 0x30ce) }, /* ScanMaker 3800 */ { USB_DEVICE(0x05da, 0x30cf) }, /* ScanMaker 4800 */ { USB_DEVICE(0x04a7, 0x0224) }, /* Scanport 3000 (actually Visioneer?)*/ @@ -250,6 +255,7 @@ { USB_DEVICE(0x06dc, 0x0014) }, /* Winscan Pro 2448U */ /* Relisis */ // { USB_DEVICE(0x0475, 0x0103) }, /* Episode - undetected endpoint */ + { USB_DEVICE(0x0475, 0x0210) }, /* Scorpio Ultra 3 */ /* Seiko/Epson Corp. */ { USB_DEVICE(0x04b8, 0x0101) }, /* Perfection 636U and 636Photo */ { USB_DEVICE(0x04b8, 0x0102) }, /* GT-2200 */ diff -Nru a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c --- a/drivers/usb/media/dabusb.c Sat Jul 19 12:54:25 2003 +++ b/drivers/usb/media/dabusb.c Sat Jul 19 12:54:25 2003 @@ -721,7 +721,7 @@ /* --------------------------------------------------------------------- */ -static int dabusb_probe (struct usb_interface *intf, +static int dabusb_probe (struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *usbdev = interface_to_usbdev(intf); @@ -738,9 +738,7 @@ if (intf->altsetting->desc.bInterfaceNumber != _DABUSB_IF && usbdev->descriptor.idProduct == 0x9999) return -ENODEV; - retval = usb_register_dev(intf, &dabusb_class); - if (retval) - return -ENOMEM; + s = &dabusb[intf->minor]; @@ -766,8 +764,15 @@ } } dbg("bound to interface: %d", ifnum); - up (&s->mutex); usb_set_intfdata (intf, s); + up (&s->mutex); + + retval = usb_register_dev(intf, &dabusb_class); + if (retval) { + usb_set_intfdata (intf, NULL); + return -ENOMEM; + } + return 0; reject: diff -Nru a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c --- a/drivers/usb/misc/usblcd.c Sat Jul 19 12:54:21 2003 +++ b/drivers/usb/misc/usblcd.c Sat Jul 19 12:54:21 2003 @@ -1,4 +1,4 @@ -/***************************************************************************** +/***************************************************************************** * USBLCD Kernel Driver * * See http://www.usblcd.de for Hardware and Documentation. * * Version 1.03 * @@ -18,7 +18,7 @@ #include #include -#define DRIVER_VERSION "USBLCD Driver Version 1.03" +#define DRIVER_VERSION "USBLCD Driver Version 1.04" #define USBLCD_MINOR 144 @@ -257,7 +257,7 @@ struct lcd_usb_data *lcd = &lcd_instance; int i; int retval; - + if (dev->descriptor.idProduct != 0x0001 ) { warn(KERN_INFO "USBLCD model not supported."); return -ENODEV; @@ -274,29 +274,31 @@ (i & 0xF000)>>12,(i & 0xF00)>>8,(i & 0xF0)>>4,(i & 0xF), dev->devnum); - retval = usb_register_dev(intf, &usb_lcd_class); - if (retval) { - err("Not able to get a minor for this device."); - return -ENOMEM; - } + lcd->present = 1; lcd->lcd_dev = dev; if (!(lcd->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) { err("probe_lcd: Not enough memory for the output buffer"); - usb_deregister_dev(intf, &usb_lcd_class); return -ENOMEM; } dbg("probe_lcd: obuf address:%p", lcd->obuf); if (!(lcd->ibuf = (char *) kmalloc(IBUF_SIZE, GFP_KERNEL))) { err("probe_lcd: Not enough memory for the input buffer"); - usb_deregister_dev(intf, &usb_lcd_class); kfree(lcd->obuf); return -ENOMEM; } dbg("probe_lcd: ibuf address:%p", lcd->ibuf); + + retval = usb_register_dev(intf, &usb_lcd_class); + if (retval) { + err("Not able to get a minor for this device."); + kfree(lcd->obuf); + kfree(lcd->ibuf); + return -ENOMEM; + } usb_set_intfdata (intf, lcd); return 0; diff -Nru a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c --- a/drivers/usb/misc/usbtest.c Sat Jul 19 12:54:29 2003 +++ b/drivers/usb/misc/usbtest.c Sat Jul 19 12:54:29 2003 @@ -47,6 +47,7 @@ const char *name; u8 ep_in; /* bulk/intr source */ u8 ep_out; /* bulk/intr sink */ + unsigned autoconf : 1; int alt; }; @@ -78,6 +79,61 @@ /*-------------------------------------------------------------------------*/ +static int +get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf) +{ + int tmp; + struct usb_host_interface *alt; + struct usb_host_endpoint *in, *out; + struct usb_device *udev; + + for (tmp = 0; tmp < intf->max_altsetting; tmp++) { + unsigned ep; + + in = out = 0; + alt = intf->altsetting + tmp; + + /* take the first altsetting with in-bulk + out-bulk; + * ignore other endpoints and altsetttings. + */ + for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) { + struct usb_host_endpoint *e; + + e = alt->endpoint + ep; + if (e->desc.bmAttributes != USB_ENDPOINT_XFER_BULK) + continue; + if (e->desc.bEndpointAddress & USB_DIR_IN) { + if (!in) + in = e; + } else { + if (!out) + out = e; + } + if (in && out) + goto found; + } + } + return -EINVAL; + +found: + udev = testdev_to_usbdev (dev); + if (alt->desc.bAlternateSetting != 0) { + tmp = usb_set_interface (udev, + alt->desc.bInterfaceNumber, + alt->desc.bAlternateSetting); + if (tmp < 0) + return tmp; + } + + dev->in_pipe = usb_rcvbulkpipe (udev, + in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + dev->out_pipe = usb_sndbulkpipe (udev, + out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + return 0; +} + +/*-------------------------------------------------------------------------*/ + /* Support for testing basic non-queued I/O streams. * * These just package urbs as requests that can be easily canceled. @@ -1275,14 +1331,26 @@ wtest = " intr-out"; } } else { - if (info->ep_in) { - dev->in_pipe = usb_rcvbulkpipe (udev, info->ep_in); - rtest = " bulk-in"; + if (info->autoconf) { + int status; + + status = get_endpoints (dev, intf); + if (status < 0) { + dbg ("couldn't get endpoints, %d\n", status); + return status; + } + } else { + if (info->ep_in) + dev->in_pipe = usb_rcvbulkpipe (udev, + info->ep_in); + if (info->ep_out) + dev->out_pipe = usb_sndbulkpipe (udev, + info->ep_out); } - if (info->ep_out) { - dev->out_pipe = usb_sndbulkpipe (udev, info->ep_out); + if (dev->in_pipe) + rtest = " bulk-in"; + if (dev->out_pipe) wtest = " bulk-out"; - } } usb_set_intfdata (intf, dev); @@ -1336,11 +1404,6 @@ }; /* ezusb family device with dedicated usb test firmware, - * or a peripheral running Linux and 'zero.c' test firmware. - * - * FIXME usbtest should read the descriptors, since compatible - * test firmware might run on hardware (pxa250 for one) that - * can't configure an ep2in-bulk. */ static struct usbtest_info fw_info = { .name = "usb test device", @@ -1349,10 +1412,20 @@ .alt = 0, }; +/* peripheral running Linux and 'zero.c' test firmware, or + * its user-mode cousin. different versions of this use + * different hardware with the same vendor/product codes. + * host side MUST rely on the endpoint descriptors. + */ +static struct usbtest_info gz_info = { + .name = "Linux gadget zero", + .autoconf = 1, + .alt = 0, +}; + static struct usbtest_info um_info = { - .name = "user mode test driver", - .ep_in = 7, - .ep_out = 3, + .name = "Linux user mode test driver", + .autoconf = 1, .alt = -1, }; @@ -1418,7 +1491,7 @@ /* "Gadget Zero" firmware runs under Linux */ { USB_DEVICE (0x0525, 0xa4a0), - .driver_info = (unsigned long) &fw_info, + .driver_info = (unsigned long) &gz_info, }, /* so does a user-mode variant */ diff -Nru a/drivers/usb/net/ax8817x.c b/drivers/usb/net/ax8817x.c --- a/drivers/usb/net/ax8817x.c Sat Jul 19 12:54:23 2003 +++ b/drivers/usb/net/ax8817x.c Sat Jul 19 12:54:23 2003 @@ -1208,6 +1208,7 @@ net->init = ax8817x_net_init; net->priv = ax_info; + SET_NETDEV_DEV(net, &intf->dev); ret = register_netdev(net); if (ret < 0) { err("%s: Failed net init (%d)\n", __FUNCTION__, ret); diff -Nru a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c --- a/drivers/usb/net/catc.c Sat Jul 19 12:54:25 2003 +++ b/drivers/usb/net/catc.c Sat Jul 19 12:54:25 2003 @@ -936,6 +936,7 @@ printk("%2.2x.\n", netdev->dev_addr[i]); usb_set_intfdata(intf, catc); + SET_NETDEV_DEV(netdev, &intf->dev); if (register_netdev(netdev) != 0) { usb_set_intfdata(intf, NULL); usb_free_urb(catc->ctrl_urb); diff -Nru a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c --- a/drivers/usb/net/kaweth.c Sat Jul 19 12:54:26 2003 +++ b/drivers/usb/net/kaweth.c Sat Jul 19 12:54:26 2003 @@ -1123,8 +1123,9 @@ if (dma_supported (&intf->dev, 0xffffffffffffffffULL)) kaweth->net->features |= NETIF_F_HIGHDMA; + SET_NETDEV_DEV(netdev, &intf->dev); if (register_netdev(netdev) != 0) { - kaweth_err("Error calling init_etherdev."); + kaweth_err("Error registering netdev."); goto err_intfdata; } diff -Nru a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c --- a/drivers/usb/net/pegasus.c Sat Jul 19 12:54:30 2003 +++ b/drivers/usb/net/pegasus.c Sat Jul 19 12:54:30 2003 @@ -1262,7 +1262,6 @@ } set_ethernet_addr(pegasus); fill_skb_pool(pegasus); - printk("%s: %s\n", net->name, usb_dev_id[dev_index].name); if (pegasus->features & PEGASUS_II) { info("setup Pegasus II specific registers"); setup_pegasus_II(pegasus); @@ -1273,9 +1272,11 @@ pegasus->phy = 1; } usb_set_intfdata(intf, pegasus); + SET_NETDEV_DEV(net, &intf->dev); res = register_netdev(net); if (res) goto out4; + printk("%s: %s\n", net->name, usb_dev_id[dev_index].name); return 0; out4: diff -Nru a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c --- a/drivers/usb/net/rtl8150.c Sat Jul 19 12:54:25 2003 +++ b/drivers/usb/net/rtl8150.c Sat Jul 19 12:54:25 2003 @@ -830,6 +830,7 @@ usb_set_intfdata(intf, dev); + SET_NETDEV_DEV(netdev, &intf->dev); if (register_netdev(netdev) != 0) { err("couldn't register the device"); goto out2; diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c --- a/drivers/usb/net/usbnet.c Sat Jul 19 12:54:25 2003 +++ b/drivers/usb/net/usbnet.c Sat Jul 19 12:54:25 2003 @@ -2602,7 +2602,7 @@ dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1); - SET_NETDEV_DEV(dev->net, &dev->udev->dev); + SET_NETDEV_DEV(dev->net, &udev->dev); status = register_netdev (dev->net); if (status) goto out3; diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c --- a/drivers/usb/serial/ftdi_sio.c Sat Jul 19 12:54:26 2003 +++ b/drivers/usb/serial/ftdi_sio.c Sat Jul 19 12:54:26 2003 @@ -257,6 +257,7 @@ { USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_DSS20_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID, 0, 0x3ff) }, @@ -321,6 +322,7 @@ { USB_DEVICE_VER(FTDI_VID, FTDI_XF_634_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_VNHCPCUSB_D_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_DSS20_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_1_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_MTXORB_VID, FTDI_MTXORB_2_PID, 0x400, 0xffff) }, @@ -396,6 +398,7 @@ { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_DSS20_PID) }, { USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) }, { USB_DEVICE(FTDI_VID, FTDI_VNHCPCUSB_D_PID) }, { USB_DEVICE(FTDI_MTXORB_VID, FTDI_MTXORB_0_PID) }, diff -Nru a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h --- a/drivers/usb/serial/ftdi_sio.h Sat Jul 19 12:54:27 2003 +++ b/drivers/usb/serial/ftdi_sio.h Sat Jul 19 12:54:27 2003 @@ -105,7 +105,13 @@ #define SEALEVEL_2803_6_PID 0X2863 /* SeaLINK+8 (2803) Port 6 */ #define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */ #define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */ + +/* + * DSS-20 Sync Station for Sony Ericsson P800 + */ +#define FTDI_DSS20_PID 0xFC82 + /* * Home Electronics (www.home-electro.com) USB gadgets */ diff -Nru a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c --- a/drivers/usb/serial/ipaq.c Sat Jul 19 12:54:27 2003 +++ b/drivers/usb/serial/ipaq.c Sat Jul 19 12:54:27 2003 @@ -125,10 +125,13 @@ { USB_DEVICE(LINKUP_VENDOR_ID, LINKUP_PRODUCT_ID) }, { USB_DEVICE(MICROSOFT_VENDOR_ID, MICROSOFT_00CE_ID) }, { USB_DEVICE(PORTATEC_VENDOR_ID, PORTATEC_PRODUCT_ID) }, + { USB_DEVICE(ROVER_VENDOR_ID, ROVER_P5_ID) }, { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_WIRELESS_ID) }, { USB_DEVICE(SOCKET_VENDOR_ID, SOCKET_PRODUCT_ID) }, { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_ID) }, + { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E310_ID) }, { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E740_ID) }, + { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E335_ID) }, { USB_DEVICE(HTC_VENDOR_ID, HTC_PRODUCT_ID) }, { USB_DEVICE(NEC_VENDOR_ID, NEC_PRODUCT_ID) }, { USB_DEVICE(ASUS_VENDOR_ID, ASUS_A600_PRODUCT_ID) }, diff -Nru a/drivers/usb/serial/ipaq.h b/drivers/usb/serial/ipaq.h --- a/drivers/usb/serial/ipaq.h Sat Jul 19 12:54:21 2003 +++ b/drivers/usb/serial/ipaq.h Sat Jul 19 12:54:21 2003 @@ -61,6 +61,9 @@ #define PORTATEC_VENDOR_ID 0x0961 #define PORTATEC_PRODUCT_ID 0x0010 +#define ROVER_VENDOR_ID 0x047b +#define ROVER_P5_ID 0x3000 + #define SAGEM_VENDOR_ID 0x5e04 #define SAGEM_WIRELESS_ID 0xce00 @@ -69,7 +72,9 @@ #define TOSHIBA_VENDOR_ID 0x0930 #define TOSHIBA_PRODUCT_ID 0x0700 +#define TOSHIBA_E310_ID 0x0705 #define TOSHIBA_E740_ID 0x0706 +#define TOSHIBA_E335_ID 0x0707 #define HTC_VENDOR_ID 0x0bb4 #define HTC_PRODUCT_ID 0x00ce diff -Nru a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c --- a/drivers/usb/serial/usb-serial.c Sat Jul 19 12:54:24 2003 +++ b/drivers/usb/serial/usb-serial.c Sat Jul 19 12:54:24 2003 @@ -530,7 +530,9 @@ /* if disconnect beat us to the punch here, there's nothing to do */ if (tty && tty->driver_data) { __serial_close(port, filp); + tty->driver_data = NULL; } + port->tty = NULL; } static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count) diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c --- a/drivers/usb/serial/visor.c Sat Jul 19 12:54:24 2003 +++ b/drivers/usb/serial/visor.c Sat Jul 19 12:54:24 2003 @@ -509,18 +509,17 @@ { struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + /* free up the transfer buffer, as usb_free_urb() does not do this */ + kfree (urb->transfer_buffer); + if (port_paranoia_check (port, __FUNCTION__)) return; dbg("%s - port %d", __FUNCTION__, port->number); - if (urb->status) { - dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); - return; - } - - /* free up the transfer buffer, as usb_free_urb() does not do this */ - kfree (urb->transfer_buffer); + if (urb->status) + dbg("%s - nonzero write bulk status received: %d", + __FUNCTION__, urb->status); schedule_work(&port->work); } diff -Nru a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h --- a/drivers/usb/storage/debug.h Sat Jul 19 12:54:30 2003 +++ b/drivers/usb/storage/debug.h Sat Jul 19 12:54:30 2003 @@ -46,7 +46,6 @@ #include #include -#include #include #include "usb.h" diff -Nru a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c --- a/drivers/usb/storage/isd200.c Sat Jul 19 12:54:25 2003 +++ b/drivers/usb/storage/isd200.c Sat Jul 19 12:54:25 2003 @@ -280,6 +280,7 @@ /* maximum number of LUNs supported */ unsigned char MaxLUNs; + struct scsi_cmnd srb; }; @@ -404,15 +405,15 @@ void* pointer, int value ) { union ata_cdb ata; - struct scsi_cmnd srb; struct scsi_device srb_dev; struct isd200_info *info = (struct isd200_info *)us->extra; + struct scsi_cmnd *srb = &info->srb; int status; memset(&ata, 0, sizeof(ata)); - memset(&srb, 0, sizeof(srb)); memset(&srb_dev, 0, sizeof(srb_dev)); - srb.device = &srb_dev; + srb->device = &srb_dev; + ++srb->serial_number; ata.generic.SignatureByte0 = info->ConfigData.ATAMajorCommand; ata.generic.SignatureByte1 = info->ConfigData.ATAMinorCommand; @@ -425,9 +426,9 @@ ata.generic.RegisterSelect = REG_CYLINDER_LOW | REG_CYLINDER_HIGH | REG_STATUS | REG_ERROR; - srb.sc_data_direction = SCSI_DATA_READ; - srb.request_buffer = pointer; - srb.request_bufflen = value; + srb->sc_data_direction = SCSI_DATA_READ; + srb->request_buffer = pointer; + srb->request_bufflen = value; break; case ACTION_ENUM: @@ -437,7 +438,7 @@ ACTION_SELECT_5; ata.generic.RegisterSelect = REG_DEVICE_HEAD; ata.write.DeviceHeadByte = value; - srb.sc_data_direction = SCSI_DATA_NONE; + srb->sc_data_direction = SCSI_DATA_NONE; break; case ACTION_RESET: @@ -446,7 +447,7 @@ ACTION_SELECT_3|ACTION_SELECT_4; ata.generic.RegisterSelect = REG_DEVICE_CONTROL; ata.write.DeviceControlByte = ATA_DC_RESET_CONTROLLER; - srb.sc_data_direction = SCSI_DATA_NONE; + srb->sc_data_direction = SCSI_DATA_NONE; break; case ACTION_REENABLE: @@ -455,7 +456,7 @@ ACTION_SELECT_3|ACTION_SELECT_4; ata.generic.RegisterSelect = REG_DEVICE_CONTROL; ata.write.DeviceControlByte = ATA_DC_REENABLE_CONTROLLER; - srb.sc_data_direction = SCSI_DATA_NONE; + srb->sc_data_direction = SCSI_DATA_NONE; break; case ACTION_SOFT_RESET: @@ -464,16 +465,16 @@ ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND; ata.write.DeviceHeadByte = info->DeviceHead; ata.write.CommandByte = WIN_SRST; - srb.sc_data_direction = SCSI_DATA_NONE; + srb->sc_data_direction = SCSI_DATA_NONE; break; case ACTION_IDENTIFY: US_DEBUGP(" isd200_action(IDENTIFY)\n"); ata.generic.RegisterSelect = REG_COMMAND; ata.write.CommandByte = WIN_IDENTIFY; - srb.sc_data_direction = SCSI_DATA_READ; - srb.request_buffer = (void *)&info->drive; - srb.request_bufflen = sizeof(struct hd_driveid); + srb->sc_data_direction = SCSI_DATA_READ; + srb->request_buffer = (void *)&info->drive; + srb->request_bufflen = sizeof(struct hd_driveid); break; default: @@ -481,9 +482,9 @@ break; } - memcpy(srb.cmnd, &ata, sizeof(ata.generic)); - srb.cmd_len = sizeof(ata.generic); - status = usb_stor_Bulk_transport(&srb, us); + memcpy(srb->cmnd, &ata, sizeof(ata.generic)); + srb->cmd_len = sizeof(ata.generic); + status = usb_stor_Bulk_transport(srb, us); if (status == USB_STOR_TRANSPORT_GOOD) status = ISD200_GOOD; else { @@ -834,7 +835,7 @@ int detect ) { int status = ISD200_GOOD; - unsigned char regs[8]; + unsigned char *regs = us->iobuf; unsigned long endTime; struct isd200_info *info = (struct isd200_info *)us->extra; int recheckAsMaster = FALSE; @@ -856,7 +857,7 @@ break; status = isd200_action( us, ACTION_READ_STATUS, - regs, sizeof(regs) ); + regs, 8 ); if ( status != ISD200_GOOD ) break; diff -Nru a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c --- a/drivers/usb/storage/jumpshot.c Sat Jul 19 12:54:21 2003 +++ b/drivers/usb/storage/jumpshot.c Sat Jul 19 12:54:21 2003 @@ -86,7 +86,6 @@ static int jumpshot_get_status(struct us_data *us) { - unsigned char reply; int rc; if (!us) @@ -94,14 +93,14 @@ // send the setup rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe, - 0, 0xA0, 0, 7, &reply, 1); + 0, 0xA0, 0, 7, us->iobuf, 1); if (rc != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - if (reply != 0x50) { + if (us->iobuf[0] != 0x50) { US_DEBUGP("jumpshot_get_status: 0x%2x\n", - (unsigned short) (reply)); + us->iobuf[0]); return USB_STOR_TRANSPORT_ERROR; } @@ -115,7 +114,7 @@ unsigned char *dest, int use_sg) { - unsigned char command[] = { 0, 0, 0, 0, 0, 0xe0, 0x20 }; + unsigned char *command = us->iobuf; unsigned char *buffer = NULL; unsigned char *ptr; unsigned char thistime; @@ -154,7 +153,8 @@ command[3] = (sector >> 8) & 0xFF; command[4] = (sector >> 16) & 0xFF; - command[5] |= (sector >> 24) & 0x0F; + command[5] = 0xE0 | ((sector >> 24) & 0x0F); + command[6] = 0x20; // send the setup + command result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, @@ -199,7 +199,7 @@ unsigned char *src, int use_sg) { - unsigned char command[7] = { 0, 0, 0, 0, 0, 0xE0, 0x30 }; + unsigned char *command = us->iobuf; unsigned char *buffer = NULL; unsigned char *ptr; unsigned char thistime; @@ -240,7 +240,8 @@ command[3] = (sector >> 8) & 0xFF; command[4] = (sector >> 16) & 0xFF; - command[5] |= (sector >> 24) & 0x0F; + command[5] = 0xE0 | ((sector >> 24) & 0x0F); + command[6] = 0x30; // send the setup + command result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, @@ -291,13 +292,19 @@ static int jumpshot_id_device(struct us_data *us, struct jumpshot_info *info) { - unsigned char command[2] = { 0xe0, 0xec }; - unsigned char reply[512]; + unsigned char *command = us->iobuf; + unsigned char *reply; int rc; if (!us || !info) return USB_STOR_TRANSPORT_ERROR; + command[0] = 0xE0; + command[1] = 0xEC; + reply = kmalloc(512, GFP_NOIO); + if (!reply) + return USB_STOR_TRANSPORT_ERROR; + // send the setup rc = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, 0, 0x20, 0, 6, command, 2); @@ -305,20 +312,27 @@ if (rc != USB_STOR_XFER_GOOD) { US_DEBUGP("jumpshot_id_device: Gah! " "send_control for read_capacity failed\n"); - return rc; + rc = USB_STOR_TRANSPORT_ERROR; + goto leave; } // read the reply rc = jumpshot_bulk_read(us, reply, sizeof(reply)); - if (rc != USB_STOR_XFER_GOOD) - return USB_STOR_TRANSPORT_ERROR; + if (rc != USB_STOR_XFER_GOOD) { + rc = USB_STOR_TRANSPORT_ERROR; + goto leave; + } info->sectors = ((u32)(reply[117]) << 24) | ((u32)(reply[116]) << 16) | ((u32)(reply[115]) << 8) | ((u32)(reply[114]) ); - return USB_STOR_TRANSPORT_GOOD; + rc = USB_STOR_TRANSPORT_GOOD; + + leave: + kfree(reply); + return rc; } static int jumpshot_handle_mode_sense(struct us_data *us, diff -Nru a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c --- a/drivers/usb/storage/protocol.c Sat Jul 19 12:54:21 2003 +++ b/drivers/usb/storage/protocol.c Sat Jul 19 12:54:21 2003 @@ -130,8 +130,9 @@ void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us) { /* Pad the ATAPI command with zeros + * * NOTE: This only works because a Scsi_Cmnd struct field contains - * a unsigned char cmnd[12], so we know we have storage available + * a unsigned char cmnd[16], so we know we have storage available */ for (; srb->cmd_len<12; srb->cmd_len++) srb->cmnd[srb->cmd_len] = 0; @@ -149,13 +150,10 @@ void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us) { - int old_cmnd = 0; - - /* Fix some commands -- this is a form of mode translation - * ATAPI devices only accept 12 byte long commands + /* Pad the ATAPI command with zeros * * NOTE: This only works because a Scsi_Cmnd struct field contains - * a unsigned char cmnd[12], so we know we have storage available + * a unsigned char cmnd[16], so we know we have storage available */ /* Pad the ATAPI command with zeros */ @@ -165,60 +163,10 @@ /* set command length to 12 bytes */ srb->cmd_len = 12; - /* determine the correct (or minimum) data length for these commands */ - switch (srb->cmnd[0]) { - - /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */ - case MODE_SENSE: - case MODE_SELECT: - /* save the command so we can tell what it was */ - old_cmnd = srb->cmnd[0]; - - srb->cmnd[11] = 0; - srb->cmnd[10] = 0; - srb->cmnd[9] = 0; - srb->cmnd[8] = srb->cmnd[4]; - srb->cmnd[7] = 0; - srb->cmnd[6] = 0; - srb->cmnd[5] = 0; - srb->cmnd[4] = 0; - srb->cmnd[3] = 0; - srb->cmnd[2] = srb->cmnd[2]; - srb->cmnd[1] = srb->cmnd[1]; - srb->cmnd[0] = srb->cmnd[0] | 0x40; - break; - - /* change READ_6/WRITE_6 to READ_10/WRITE_10, which - * are ATAPI commands */ - case WRITE_6: - case READ_6: - srb->cmnd[11] = 0; - srb->cmnd[10] = 0; - srb->cmnd[9] = 0; - srb->cmnd[8] = srb->cmnd[4]; - srb->cmnd[7] = 0; - srb->cmnd[6] = 0; - srb->cmnd[5] = srb->cmnd[3]; - srb->cmnd[4] = srb->cmnd[2]; - srb->cmnd[3] = srb->cmnd[1] & 0x1F; - srb->cmnd[2] = 0; - srb->cmnd[1] = srb->cmnd[1] & 0xE0; - srb->cmnd[0] = srb->cmnd[0] | 0x20; - break; - } /* end switch on cmnd[0] */ - - /* convert MODE_SELECT data here */ - if (old_cmnd == MODE_SELECT) - usb_stor_scsiSense6to10(srb); - /* send the command to the transport layer */ usb_stor_invoke_transport(srb, us); - if (srb->result == SAM_STAT_GOOD) { - - /* Fix the MODE_SENSE data if we translated the command */ - if (old_cmnd == MODE_SENSE) - usb_stor_scsiSense10to6(srb); + if (srb->result == SAM_STAT_GOOD) { /* fix the INQUIRY data if necessary */ fix_inquiry_data(srb); } @@ -227,19 +175,23 @@ void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us) { - int old_cmnd = 0; - /* fix some commands -- this is a form of mode translation * UFI devices only accept 12 byte long commands * * NOTE: This only works because a Scsi_Cmnd struct field contains - * a unsigned char cmnd[12], so we know we have storage available + * a unsigned char cmnd[16], so we know we have storage available */ + /* Pad the ATAPI command with zeros */ + for (; srb->cmd_len<12; srb->cmd_len++) + srb->cmnd[srb->cmd_len] = 0; + /* set command length to 12 bytes (this affects the transport layer) */ srb->cmd_len = 12; - /* determine the correct (or minimum) data length for these commands */ + /* XXX We should be constantly re-evaluating the need for these */ + + /* determine the correct data length for these commands */ switch (srb->cmnd[0]) { /* for INQUIRY, UFI devices only ever return 36 bytes */ @@ -247,33 +199,6 @@ srb->cmnd[4] = 36; break; - /* change MODE_SENSE/MODE_SELECT from 6 to 10 byte commands */ - case MODE_SENSE: - case MODE_SELECT: - /* save the command so we can tell what it was */ - old_cmnd = srb->cmnd[0]; - - srb->cmnd[11] = 0; - srb->cmnd[10] = 0; - srb->cmnd[9] = 0; - - /* if we're sending data, we send all. If getting data, - * get the minimum */ - if (srb->cmnd[0] == MODE_SELECT) - srb->cmnd[8] = srb->cmnd[4]; - else - srb->cmnd[8] = 8; - - srb->cmnd[7] = 0; - srb->cmnd[6] = 0; - srb->cmnd[5] = 0; - srb->cmnd[4] = 0; - srb->cmnd[3] = 0; - srb->cmnd[2] = srb->cmnd[2]; - srb->cmnd[1] = srb->cmnd[1]; - srb->cmnd[0] = srb->cmnd[0] | 0x40; - break; - /* again, for MODE_SENSE_10, we get the minimum (8) */ case MODE_SENSE_10: srb->cmnd[7] = 0; @@ -284,38 +209,12 @@ case REQUEST_SENSE: srb->cmnd[4] = 18; break; - - /* change READ_6/WRITE_6 to READ_10/WRITE_10, which - * are UFI commands */ - case WRITE_6: - case READ_6: - srb->cmnd[11] = 0; - srb->cmnd[10] = 0; - srb->cmnd[9] = 0; - srb->cmnd[8] = srb->cmnd[4]; - srb->cmnd[7] = 0; - srb->cmnd[6] = 0; - srb->cmnd[5] = srb->cmnd[3]; - srb->cmnd[4] = srb->cmnd[2]; - srb->cmnd[3] = srb->cmnd[1] & 0x1F; - srb->cmnd[2] = 0; - srb->cmnd[1] = srb->cmnd[1] & 0xE0; - srb->cmnd[0] = srb->cmnd[0] | 0x20; - break; } /* end switch on cmnd[0] */ - /* convert MODE_SELECT data here */ - if (old_cmnd == MODE_SELECT) - usb_stor_scsiSense6to10(srb); - /* send the command to the transport layer */ usb_stor_invoke_transport(srb, us); - if (srb->result == SAM_STAT_GOOD) { - - /* Fix the MODE_SENSE data if we translated the command */ - if (old_cmnd == MODE_SENSE) - usb_stor_scsiSense10to6(srb); + if (srb->result == SAM_STAT_GOOD) { /* Fix the data for an INQUIRY, if necessary */ fix_inquiry_data(srb); } @@ -323,68 +222,10 @@ void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us) { - int old_cmnd = 0; - - /* This code supports devices which do not support {READ|WRITE}_6 - * Apparently, neither Windows or MacOS will use these commands, - * so some devices do not support them - */ - if (us->flags & US_FL_MODE_XLATE) { - US_DEBUGP("Invoking Mode Translation\n"); - /* save the old command for later */ - old_cmnd = srb->cmnd[0]; - - switch (srb->cmnd[0]) { - /* change READ_6/WRITE_6 to READ_10/WRITE_10 */ - case WRITE_6: - case READ_6: - srb->cmd_len = 12; - srb->cmnd[11] = 0; - srb->cmnd[10] = 0; - srb->cmnd[9] = 0; - srb->cmnd[8] = srb->cmnd[4]; - srb->cmnd[7] = 0; - srb->cmnd[6] = 0; - srb->cmnd[5] = srb->cmnd[3]; - srb->cmnd[4] = srb->cmnd[2]; - srb->cmnd[3] = srb->cmnd[1] & 0x1F; - srb->cmnd[2] = 0; - srb->cmnd[1] = srb->cmnd[1] & 0xE0; - srb->cmnd[0] = srb->cmnd[0] | 0x20; - break; - - /* convert MODE_SELECT data here */ - case MODE_SENSE: - case MODE_SELECT: - srb->cmd_len = 12; - srb->cmnd[11] = 0; - srb->cmnd[10] = 0; - srb->cmnd[9] = 0; - srb->cmnd[8] = srb->cmnd[4]; - srb->cmnd[7] = 0; - srb->cmnd[6] = 0; - srb->cmnd[5] = 0; - srb->cmnd[4] = 0; - srb->cmnd[3] = 0; - srb->cmnd[2] = srb->cmnd[2]; - srb->cmnd[1] = srb->cmnd[1]; - srb->cmnd[0] = srb->cmnd[0] | 0x40; - break; - } /* switch (srb->cmnd[0]) */ - } /* if (us->flags & US_FL_MODE_XLATE) */ - - /* convert MODE_SELECT data here */ - if ((us->flags & US_FL_MODE_XLATE) && (old_cmnd == MODE_SELECT)) - usb_stor_scsiSense6to10(srb); - /* send the command to the transport layer */ usb_stor_invoke_transport(srb, us); - if (srb->result == SAM_STAT_GOOD) { - - /* Fix the MODE_SENSE data if we translated the command */ - if ((us->flags & US_FL_MODE_XLATE) && (old_cmnd == MODE_SENSE)) - usb_stor_scsiSense10to6(srb); + if (srb->result == SAM_STAT_GOOD) { /* Fix the INQUIRY data if necessary */ fix_inquiry_data(srb); diff -Nru a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h --- a/drivers/usb/storage/protocol.h Sat Jul 19 12:54:24 2003 +++ b/drivers/usb/storage/protocol.h Sat Jul 19 12:54:24 2003 @@ -41,7 +41,7 @@ #ifndef _PROTOCOL_H_ #define _PROTOCOL_H_ -#include +#include #include "scsi.h" #include "usb.h" diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c --- a/drivers/usb/storage/scsiglue.c Sat Jul 19 12:54:25 2003 +++ b/drivers/usb/storage/scsiglue.c Sat Jul 19 12:54:25 2003 @@ -263,7 +263,6 @@ #define DO_FLAG(a) if (f & US_FL_##a) pos += sprintf(pos, " " #a) DO_FLAG(SINGLE_LUN); - DO_FLAG(MODE_XLATE); DO_FLAG(SCM_MULT_TARG); DO_FLAG(FIX_INQUIRY); DO_FLAG(FIX_CAPACITY); @@ -345,500 +344,4 @@ [7] = 0x0a, /* additional length */ [12] = 0x24 /* Invalid Field in CDB */ }; - -#define USB_STOR_SCSI_SENSE_HDRSZ 4 -#define USB_STOR_SCSI_SENSE_10_HDRSZ 8 - -struct usb_stor_scsi_sense_hdr -{ - __u8* dataLength; - __u8* mediumType; - __u8* devSpecParms; - __u8* blkDescLength; -}; - -typedef struct usb_stor_scsi_sense_hdr Usb_Stor_Scsi_Sense_Hdr; - -union usb_stor_scsi_sense_hdr_u -{ - Usb_Stor_Scsi_Sense_Hdr hdr; - __u8* array[USB_STOR_SCSI_SENSE_HDRSZ]; -}; - -typedef union usb_stor_scsi_sense_hdr_u Usb_Stor_Scsi_Sense_Hdr_u; - -struct usb_stor_scsi_sense_hdr_10 -{ - __u8* dataLengthMSB; - __u8* dataLengthLSB; - __u8* mediumType; - __u8* devSpecParms; - __u8* reserved1; - __u8* reserved2; - __u8* blkDescLengthMSB; - __u8* blkDescLengthLSB; -}; - -typedef struct usb_stor_scsi_sense_hdr_10 Usb_Stor_Scsi_Sense_Hdr_10; - -union usb_stor_scsi_sense_hdr_10_u -{ - Usb_Stor_Scsi_Sense_Hdr_10 hdr; - __u8* array[USB_STOR_SCSI_SENSE_10_HDRSZ]; -}; - -typedef union usb_stor_scsi_sense_hdr_10_u Usb_Stor_Scsi_Sense_Hdr_10_u; - -void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* , Usb_Stor_Scsi_Sense_Hdr_u*, - Usb_Stor_Scsi_Sense_Hdr_10_u*, int* ); - -int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 ) -{ - __u8 *buffer=0; - int outputBufferSize = 0; - int length=0; - struct scatterlist *sg = 0; - int i=0, j=0, element=0; - Usb_Stor_Scsi_Sense_Hdr_u the6Locations; - Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations; - int sb=0,si=0,db=0,di=0; - int sgLength=0; - - US_DEBUGP("-- converting 10 byte sense data to 6 byte\n"); - the10->cmnd[0] = the10->cmnd[0] & 0xBF; - - /* Determine buffer locations */ - usb_stor_scsiSenseParseBuffer( the10, &the6Locations, &the10Locations, - &length ); - - /* Work out minimum buffer to output */ - outputBufferSize = *the10Locations.hdr.dataLengthLSB; - outputBufferSize += USB_STOR_SCSI_SENSE_HDRSZ; - - /* Check to see if we need to trucate the output */ - if ( outputBufferSize > length ) - { - printk( KERN_WARNING USB_STORAGE - "Had to truncate MODE_SENSE_10 buffer into MODE_SENSE.\n" ); - printk( KERN_WARNING USB_STORAGE - "outputBufferSize is %d and length is %d.\n", - outputBufferSize, length ); - } - outputBufferSize = length; - - /* Data length */ - if ( *the10Locations.hdr.dataLengthMSB != 0 ) /* MSB must be zero */ - { - printk( KERN_WARNING USB_STORAGE - "Command will be truncated to fit in SENSE6 buffer.\n" ); - *the6Locations.hdr.dataLength = 0xff; - } - else - { - *the6Locations.hdr.dataLength = *the10Locations.hdr.dataLengthLSB; - } - - /* Medium type and DevSpecific parms */ - *the6Locations.hdr.mediumType = *the10Locations.hdr.mediumType; - *the6Locations.hdr.devSpecParms = *the10Locations.hdr.devSpecParms; - - /* Block descriptor length */ - if ( *the10Locations.hdr.blkDescLengthMSB != 0 ) /* MSB must be zero */ - { - printk( KERN_WARNING USB_STORAGE - "Command will be truncated to fit in SENSE6 buffer.\n" ); - *the6Locations.hdr.blkDescLength = 0xff; - } - else - { - *the6Locations.hdr.blkDescLength = *the10Locations.hdr.blkDescLengthLSB; - } - - if ( the10->use_sg == 0 ) - { - buffer = the10->request_buffer; - /* Copy the rest of the data */ - memmove( &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]), - &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]), - outputBufferSize - USB_STOR_SCSI_SENSE_HDRSZ ); - /* initialise last bytes left in buffer due to smaller header */ - memset( &(buffer[outputBufferSize - -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ)]), - 0, - USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ ); - } - else - { - sg = (struct scatterlist *) the10->request_buffer; - /* scan through this scatterlist and figure out starting positions */ - for ( i=0; i < the10->use_sg; i++) - { - sgLength = sg[i].length; - for ( j=0; juse_sg; - } - element++; - } - } - - /* Now we know where to start the copy from */ - element = USB_STOR_SCSI_SENSE_HDRSZ; - while ( element < outputBufferSize - -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) ) - { - /* check limits */ - if ( sb >= the10->use_sg || - si >= sg[sb].length || - db >= the10->use_sg || - di >= sg[db].length ) - { - printk( KERN_ERR USB_STORAGE - "Buffer overrun averted, this shouldn't happen!\n" ); - break; - } - - /* copy one byte */ - { - char *src = sg_address(sg[sb]) + si; - char *dst = sg_address(sg[db]) + di; - - *dst = *src; - } - - /* get next destination */ - if ( sg[db].length-1 == di ) - { - db++; - di=0; - } - else - { - di++; - } - - /* get next source */ - if ( sg[sb].length-1 == si ) - { - sb++; - si=0; - } - else - { - si++; - } - - element++; - } - /* zero the remaining bytes */ - while ( element < outputBufferSize ) - { - /* check limits */ - if ( db >= the10->use_sg || - di >= sg[db].length ) - { - printk( KERN_ERR USB_STORAGE - "Buffer overrun averted, this shouldn't happen!\n" ); - break; - } - - *(char*)(sg_address(sg[db])) = 0; - - /* get next destination */ - if ( sg[db].length-1 == di ) - { - db++; - di=0; - } - else - { - di++; - } - element++; - } - } - - /* All done any everything was fine */ - return 0; -} - -int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 ) -{ - /* will be used to store part of buffer */ - __u8 tempBuffer[USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ], - *buffer=0; - int outputBufferSize = 0; - int length=0; - struct scatterlist *sg = 0; - int i=0, j=0, element=0; - Usb_Stor_Scsi_Sense_Hdr_u the6Locations; - Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations; - int sb=0,si=0,db=0,di=0; - int lsb=0,lsi=0,ldb=0,ldi=0; - - US_DEBUGP("-- converting 6 byte sense data to 10 byte\n"); - the6->cmnd[0] = the6->cmnd[0] | 0x40; - - /* Determine buffer locations */ - usb_stor_scsiSenseParseBuffer( the6, &the6Locations, &the10Locations, - &length ); - - /* Work out minimum buffer to output */ - outputBufferSize = *the6Locations.hdr.dataLength; - outputBufferSize += USB_STOR_SCSI_SENSE_10_HDRSZ; - - /* Check to see if we need to trucate the output */ - if ( outputBufferSize > length ) - { - printk( KERN_WARNING USB_STORAGE - "Had to truncate MODE_SENSE into MODE_SENSE_10 buffer.\n" ); - printk( KERN_WARNING USB_STORAGE - "outputBufferSize is %d and length is %d.\n", - outputBufferSize, length ); - } - outputBufferSize = length; - - /* Block descriptor length - save these before overwriting */ - tempBuffer[2] = *the10Locations.hdr.blkDescLengthMSB; - tempBuffer[3] = *the10Locations.hdr.blkDescLengthLSB; - *the10Locations.hdr.blkDescLengthLSB = *the6Locations.hdr.blkDescLength; - *the10Locations.hdr.blkDescLengthMSB = 0; - - /* reserved - save these before overwriting */ - tempBuffer[0] = *the10Locations.hdr.reserved1; - tempBuffer[1] = *the10Locations.hdr.reserved2; - *the10Locations.hdr.reserved1 = *the10Locations.hdr.reserved2 = 0; - - /* Medium type and DevSpecific parms */ - *the10Locations.hdr.devSpecParms = *the6Locations.hdr.devSpecParms; - *the10Locations.hdr.mediumType = *the6Locations.hdr.mediumType; - - /* Data length */ - *the10Locations.hdr.dataLengthLSB = *the6Locations.hdr.dataLength; - *the10Locations.hdr.dataLengthMSB = 0; - - if ( !the6->use_sg ) - { - buffer = the6->request_buffer; - /* Copy the rest of the data */ - memmove( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]), - &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]), - outputBufferSize-USB_STOR_SCSI_SENSE_10_HDRSZ ); - /* Put the first four bytes (after header) in place */ - memcpy( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]), - tempBuffer, - USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ ); - } - else - { - sg = (struct scatterlist *) the6->request_buffer; - /* scan through this scatterlist and figure out ending positions */ - for ( i=0; i < the6->use_sg; i++) - { - for ( j=0; juse_sg; - break; - } - element++; - } - } - /* scan through this scatterlist and figure out starting positions */ - element = length-1; - /* destination is the last element */ - db=the6->use_sg-1; - di=sg[db].length-1; - for ( i=the6->use_sg-1; i >= 0; i--) - { - for ( j=sg[i].length-1; j>=0; j-- ) - { - /* get to end of header and find source for copy */ - if ( element == length - 1 - - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) ) - { - sb=i; - si=j; - /* we've found both sets now, exit loops */ - j=-1; - i=-1; - } - element--; - } - } - /* Now we know where to start the copy from */ - element = length-1 - - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ); - while ( element >= USB_STOR_SCSI_SENSE_10_HDRSZ ) - { - /* check limits */ - if ( ( sb <= lsb && si < lsi ) || - ( db <= ldb && di < ldi ) ) - { - printk( KERN_ERR USB_STORAGE - "Buffer overrun averted, this shouldn't happen!\n" ); - break; - } - - /* copy one byte */ - { - char *src = sg_address(sg[sb]) + si; - char *dst = sg_address(sg[db]) + di; - - *dst = *src; - } - - /* get next destination */ - if ( di == 0 ) - { - db--; - di=sg[db].length-1; - } - else - { - di--; - } - - /* get next source */ - if ( si == 0 ) - { - sb--; - si=sg[sb].length-1; - } - else - { - si--; - } - - element--; - } - /* copy the remaining four bytes */ - while ( element >= USB_STOR_SCSI_SENSE_HDRSZ ) - { - /* check limits */ - if ( db <= ldb && di < ldi ) - { - printk( KERN_ERR USB_STORAGE - "Buffer overrun averted, this shouldn't happen!\n" ); - break; - } - - { - char *dst = sg_address(sg[db]) + di; - - *dst = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ]; - } - - - /* get next destination */ - if ( di == 0 ) - { - db--; - di=sg[db].length-1; - } - else - { - di--; - } - element--; - } - } - - /* All done and everything was fine */ - return 0; -} - -void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* srb, Usb_Stor_Scsi_Sense_Hdr_u* the6, - Usb_Stor_Scsi_Sense_Hdr_10_u* the10, - int* length_p ) - -{ - int i = 0, j=0, element=0; - struct scatterlist *sg = 0; - int length = 0; - __u8* buffer=0; - - /* are we scatter-gathering? */ - if ( srb->use_sg != 0 ) - { - /* loop over all the scatter gather structures and - * get pointer to the data members in the headers - * (also work out the length while we're here) - */ - sg = (struct scatterlist *) srb->request_buffer; - for (i = 0; i < srb->use_sg; i++) - { - length += sg[i].length; - /* We only do the inner loop for the headers */ - if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ ) - { - /* scan through this scatterlist */ - for ( j=0; jarray[element] = sg_address(sg[i]) + j; - the10->array[element] = sg_address(sg[i]) + j; - - } - else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ ) - { - /* only the longer headers still cares now */ - the10->array[element] = sg_address(sg[i]) + j; - - } - /* increase element counter */ - element++; - } - } - } - } - else - { - length = srb->request_bufflen; - buffer = srb->request_buffer; - if ( length < USB_STOR_SCSI_SENSE_10_HDRSZ ) - printk( KERN_ERR USB_STORAGE - "Buffer length smaller than header!!" ); - for( i=0; iarray[i] = &(buffer[i]); - the10->array[i] = &(buffer[i]); - } - else - { - the10->array[i] = &(buffer[i]); - } - } - } - - /* Set value of length passed in */ - *length_p = length; -} diff -Nru a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h --- a/drivers/usb/storage/scsiglue.h Sat Jul 19 12:54:25 2003 +++ b/drivers/usb/storage/scsiglue.h Sat Jul 19 12:54:25 2003 @@ -41,7 +41,7 @@ #ifndef _SCSIGLUE_H_ #define _SCSIGLUE_H_ -#include +#include #include "scsi.h" #include "hosts.h" diff -Nru a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c --- a/drivers/usb/storage/sddr09.c Sat Jul 19 12:54:27 2003 +++ b/drivers/usb/storage/sddr09.c Sat Jul 19 12:54:27 2003 @@ -261,12 +261,13 @@ */ static int sddr09_test_unit_ready(struct us_data *us) { - unsigned char command[6] = { - 0, LUNBITS, 0, 0, 0, 0 - }; + unsigned char *command = us->iobuf; int result; - result = sddr09_send_scsi_command(us, command, sizeof(command)); + memset(command, 0, 6); + command[1] = LUNBITS; + + result = sddr09_send_scsi_command(us, command, 6); US_DEBUGP("sddr09_test_unit_ready returns %d\n", result); @@ -281,12 +282,15 @@ */ static int sddr09_request_sense(struct us_data *us, unsigned char *sensebuf, int buflen) { - unsigned char command[12] = { - 0x03, LUNBITS, 0, 0, buflen, 0, 0, 0, 0, 0, 0, 0 - }; + unsigned char *command = us->iobuf; int result; - result = sddr09_send_scsi_command(us, command, sizeof(command)); + memset(command, 0, 12); + command[0] = 0x03; + command[1] = LUNBITS; + command[4] = buflen; + + result = sddr09_send_scsi_command(us, command, 12); if (result != USB_STOR_TRANSPORT_GOOD) { US_DEBUGP("request sense failed\n"); return result; @@ -331,20 +335,23 @@ int nr_of_pages, int bulklen, unsigned char *buf, int use_sg) { - unsigned char command[12] = { - 0xe8, LUNBITS | x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; + unsigned char *command = us->iobuf; int result; + command[0] = 0xE8; + command[1] = LUNBITS | x; command[2] = MSB_of(fromaddress>>16); command[3] = LSB_of(fromaddress>>16); command[4] = MSB_of(fromaddress & 0xFFFF); command[5] = LSB_of(fromaddress & 0xFFFF); - + command[6] = 0; + command[7] = 0; + command[8] = 0; + command[9] = 0; command[10] = MSB_of(nr_of_pages); command[11] = LSB_of(nr_of_pages); - result = sddr09_send_scsi_command(us, command, sizeof(command)); + result = sddr09_send_scsi_command(us, command, 12); if (result != USB_STOR_TRANSPORT_GOOD) { US_DEBUGP("Result for send_control in sddr09_read2%d %d\n", @@ -458,17 +465,18 @@ */ static int sddr09_erase(struct us_data *us, unsigned long Eaddress) { - unsigned char command[12] = { - 0xea, LUNBITS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; + unsigned char *command = us->iobuf; int result; + memset(command, 0, 12); + command[0] = 0xEA; + command[1] = LUNBITS; command[6] = MSB_of(Eaddress>>16); command[7] = LSB_of(Eaddress>>16); command[8] = MSB_of(Eaddress & 0xFFFF); command[9] = LSB_of(Eaddress & 0xFFFF); - result = sddr09_send_scsi_command(us, command, sizeof(command)); + result = sddr09_send_scsi_command(us, command, 12); if (result != USB_STOR_TRANSPORT_GOOD) US_DEBUGP("Result for send_control in sddr09_erase %d\n", @@ -493,11 +501,12 @@ unsigned long Waddress, unsigned long Eaddress, int nr_of_pages, int bulklen, unsigned char *buf, int use_sg) { - unsigned char command[12] = { - 0xe9, LUNBITS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; + unsigned char *command = us->iobuf; int result; + command[0] = 0xE9; + command[1] = LUNBITS; + command[2] = MSB_of(Waddress>>16); command[3] = LSB_of(Waddress>>16); command[4] = MSB_of(Waddress & 0xFFFF); @@ -511,7 +520,7 @@ command[10] = MSB_of(nr_of_pages); command[11] = LSB_of(nr_of_pages); - result = sddr09_send_scsi_command(us, command, sizeof(command)); + result = sddr09_send_scsi_command(us, command, 12); if (result != USB_STOR_TRANSPORT_GOOD) { US_DEBUGP("Result for send_control in sddr09_writeX %d\n", @@ -554,15 +563,15 @@ */ static int sddr09_read_sg_test_only(struct us_data *us) { - unsigned char command[15] = { - 0xe7, LUNBITS, 0 - }; + unsigned char *command = us->iobuf; int result, bulklen, nsg, ct; unsigned char *buf; unsigned long address; nsg = bulklen = 0; - + command[0] = 0xE7; + command[1] = LUNBITS; + command[2] = 0; address = 040000; ct = 1; nsg++; bulklen += (ct << 9); @@ -628,20 +637,22 @@ static int sddr09_read_status(struct us_data *us, unsigned char *status) { - unsigned char command[12] = { - 0xec, LUNBITS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - unsigned char data[64]; + unsigned char *command = us->iobuf; + unsigned char *data = us->iobuf; int result; US_DEBUGP("Reading status...\n"); - result = sddr09_send_scsi_command(us, command, sizeof(command)); + memset(command, 0, 12); + command[0] = 0xEC; + command[1] = LUNBITS; + + result = sddr09_send_scsi_command(us, command, 12); if (result != USB_STOR_TRANSPORT_GOOD) return result; result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, - data, sizeof(data), NULL); + data, 64, NULL); *status = data[0]; return (result == USB_STOR_XFER_GOOD ? USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR); @@ -953,13 +964,15 @@ */ static int sddr09_read_deviceID(struct us_data *us, unsigned char *deviceID) { - unsigned char command[12] = { - 0xed, LUNBITS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - unsigned char content[64]; + unsigned char *command = us->iobuf; + unsigned char *content = us->iobuf; int result, i; - result = sddr09_send_scsi_command(us, command, sizeof(command)); + memset(command, 0, 12); + command[0] = 0xED; + command[1] = LUNBITS; + + result = sddr09_send_scsi_command(us, command, 12); if (result != USB_STOR_TRANSPORT_GOOD) return result; @@ -1006,11 +1019,13 @@ static int sddr09_reset(struct us_data *us) { - unsigned char command[12] = { - 0xeb, LUNBITS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; + unsigned char *command = us->iobuf; + + memset(command, 0, 12); + command[0] = 0xEB; + command[1] = LUNBITS; - return sddr09_send_scsi_command(us, command, sizeof(command)); + return sddr09_send_scsi_command(us, command, 12); } #endif @@ -1313,7 +1328,7 @@ int sddr09_init(struct us_data *us) { int result; - unsigned char data[18]; + unsigned char *data = us->iobuf; result = sddr09_send_command(us, 0x01, USB_DIR_IN, data, 2); if (result != USB_STOR_TRANSPORT_GOOD) { @@ -1333,10 +1348,10 @@ US_DEBUGP("SDDR09init: %02X %02X\n", data[0], data[1]); // get 07 00 - result = sddr09_request_sense(us, data, sizeof(data)); + result = sddr09_request_sense(us, data, 18); if (result == USB_STOR_TRANSPORT_GOOD && data[2] != 0) { int j; - for (j=0; jiobuf; + unsigned char *status = us->iobuf; struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; /* send command */ + memset(command, 0, 8); + command[5] = 0xB0; + command[7] = 0x80; result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8); @@ -158,10 +159,8 @@ int use_sg) { int result = USB_STOR_TRANSPORT_GOOD; - unsigned char command[8] = { - 0, 0, 0, 0, 0, 0xb0, 0, 0x85 - }; - unsigned char status[8]; + unsigned char *command = us->iobuf; + unsigned char *status = us->iobuf; struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; unsigned int pba; @@ -205,11 +204,15 @@ address = (pba << info->blockshift) + page; + command[0] = 0; command[1] = LSB_of(address>>16); command[2] = LSB_of(address>>8); command[3] = LSB_of(address); + command[4] = 0; + command[5] = 0xB0; command[6] = LSB_of(pages << (1 - info->smallpageshift)); + command[7] = 0x85; /* send command */ result = sddr55_bulk_transport(us, @@ -274,10 +277,8 @@ int use_sg) { int result = USB_STOR_TRANSPORT_GOOD; - unsigned char command[8] = { - 0, 0, 0, 0, 0, 0xb0, 0, 0x86 - }; - unsigned char status[8]; + unsigned char *command = us->iobuf; + unsigned char *status = us->iobuf; struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra; unsigned int pba; @@ -380,6 +381,8 @@ command[6] = MSB_of(lba % 1000); command[4] |= LSB_of(pages >> info->smallpageshift); + command[5] = 0xB0; + command[7] = 0x86; /* send command */ result = sddr55_bulk_transport(us, @@ -473,11 +476,12 @@ unsigned char *deviceID) { int result; - unsigned char command[8] = { - 0, 0, 0, 0, 0, 0xb0, 0, 0x84 - }; - unsigned char content[64]; + unsigned char *command = us->iobuf; + unsigned char *content = us->iobuf; + memset(command, 0, 8); + command[5] = 0xB0; + command[7] = 0x84; result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8); US_DEBUGP("Result of send_control for device ID is %d\n", @@ -598,7 +602,7 @@ struct sddr55_card_info *info = (struct sddr55_card_info *)(us->extra); int numblocks; unsigned char *buffer; - unsigned char command[8] = { 0, 0, 0, 0, 0, 0xb0, 0, 0x8a}; + unsigned char *command = us->iobuf; int i; unsigned short lba; unsigned short max_lba; @@ -614,7 +618,10 @@ if (!buffer) return -1; + memset(command, 0, 8); + command[5] = 0xB0; command[6] = numblocks * 2 / 256; + command[7] = 0x8A; result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8); diff -Nru a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h --- a/drivers/usb/storage/transport.h Sat Jul 19 12:54:24 2003 +++ b/drivers/usb/storage/transport.h Sat Jul 19 12:54:24 2003 @@ -42,7 +42,7 @@ #define _TRANSPORT_H_ #include -#include +#include #include "usb.h" #include "scsi.h" diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h --- a/drivers/usb/storage/unusual_devs.h Sat Jul 19 12:54:26 2003 +++ b/drivers/usb/storage/unusual_devs.h Sat Jul 19 12:54:26 2003 @@ -119,7 +119,7 @@ UNUSUAL_DEV( 0x04cb, 0x0100, 0x0000, 0x2210, "Fujifilm", "FinePix 1400Zoom", - US_SC_8070, US_PR_CBI, NULL, US_FL_FIX_INQUIRY), + US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), /* Reported by Peter Wächtler * The device needs the flags only. @@ -236,7 +236,7 @@ UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450, "Sony", "DSC-S30/S70/S75/505V/F505/F707/F717/P8", - US_SC_SCSI, US_PR_CB, NULL, + US_SC_SCSI, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN | US_FL_MODE_XLATE ), /* Reported by wim@geeks.nl */ @@ -555,7 +555,7 @@ UNUSUAL_DEV( 0x08ca, 0x2011, 0x0000, 0x9999, "AIPTEK", "PocketCAM 3Mega", - US_SC_SCSI, US_PR_BULK, NULL, + US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_MODE_XLATE ), /* aeb */ diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c --- a/drivers/usb/storage/usb.c Sat Jul 19 12:54:24 2003 +++ b/drivers/usb/storage/usb.c Sat Jul 19 12:54:24 2003 @@ -958,6 +958,8 @@ goto BadDevice; } + scsi_scan_host(us->host); + printk(KERN_DEBUG "WARNING: USB Mass Storage data integrity not assured\n"); printk(KERN_DEBUG diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h --- a/drivers/usb/storage/usb.h Sat Jul 19 12:54:26 2003 +++ b/drivers/usb/storage/usb.h Sat Jul 19 12:54:26 2003 @@ -45,7 +45,7 @@ #define _USB_H_ #include -#include +#include #include #include #include @@ -69,11 +69,10 @@ /* Flag definitions: these entries are static */ #define US_FL_SINGLE_LUN 0x00000001 /* allow access to only LUN 0 */ -#define US_FL_MODE_XLATE 0x00000002 /* translate _6 to _10 commands for - Win/MacOS compatibility */ +#define US_FL_MODE_XLATE 0 /* [no longer used] */ #define US_FL_IGNORE_SER 0 /* [no longer used] */ #define US_FL_SCM_MULT_TARG 0x00000020 /* supports multiple targets */ -#define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs fixing */ +#define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs faking */ #define US_FL_FIX_CAPACITY 0x00000080 /* READ CAPACITY response too big */ /* Dynamic flag definitions: used in set_bit() etc. */ diff -Nru a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c --- a/drivers/usb/usb-skeleton.c Sat Jul 19 12:54:25 2003 +++ b/drivers/usb/usb-skeleton.c Sat Jul 19 12:54:25 2003 @@ -507,7 +507,7 @@ struct usb_endpoint_descriptor *endpoint; size_t buffer_size; int i; - int retval; + int retval = -ENOMEM; /* See if the device offered us matches what we can accept */ if ((udev->descriptor.idVendor != USB_SKEL_VENDOR_ID) || @@ -515,18 +515,11 @@ return -ENODEV; } - retval = usb_register_dev (interface, &skel_class); - if (retval) { - /* something prevented us from registering this driver */ - err ("Not able to get a minor for this device."); - goto exit; - } - /* allocate memory for our device state and initialize it */ dev = kmalloc (sizeof(struct usb_skel), GFP_KERNEL); if (dev == NULL) { err ("Out of memory"); - goto exit_minor; + goto error; } memset (dev, 0x00, sizeof (*dev)); @@ -603,24 +596,24 @@ /* allow device read, write and ioctl */ dev->present = 1; + /* we can register the device now, as it is ready */ + usb_set_intfdata (interface, dev); + retval = usb_register_dev (interface, &skel_class); + if (retval) { + /* something prevented us from registering this driver */ + err ("Not able to get a minor for this device."); + usb_set_intfdata (interface, NULL); + goto error; + } + + /* let the user know what node this device is now attached to */ info ("USB Skeleton device now attached to USBSkel-%d", dev->minor); - - goto exit; + return 0; error: skel_delete (dev); - dev = NULL; - -exit_minor: - usb_deregister_dev (interface, &skel_class); - -exit: - if (dev) { - usb_set_intfdata (interface, dev); - return 0; - } - return -ENODEV; + return retval; } diff -Nru a/drivers/video/Makefile b/drivers/video/Makefile --- a/drivers/video/Makefile Sat Jul 19 12:54:23 2003 +++ b/drivers/video/Makefile Sat Jul 19 12:54:23 2003 @@ -69,7 +69,7 @@ obj-$(CONFIG_FB_VIRTUAL) += vfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_HIT) += hitfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_E1355) += epson1355fb.o -obj-$(CONFIG_FB_PVR2) += pvr2fb.o +obj-$(CONFIG_FB_PVR2) += pvr2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_VOODOO1) += sstfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o diff -Nru a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c --- a/drivers/video/pvr2fb.c Sat Jul 19 12:54:22 2003 +++ b/drivers/video/pvr2fb.c Sat Jul 19 12:54:22 2003 @@ -4,7 +4,7 @@ * Dreamcast. * * Copyright (c) 2001 M. R. Brown - * Copyright (c) 2001 Paul Mundt + * Copyright (c) 2001, 2002, 2003 Paul Mundt * * This file is part of the LinuxDC project (linuxdc.sourceforge.net). * @@ -12,14 +12,15 @@ /* * This driver is mostly based on the excellent amifb and vfb sources. It uses - * an odd scheme for converting hardware values to/from framebuffer values, here are - * some hacked-up formulas: + * an odd scheme for converting hardware values to/from framebuffer values, + * here are some hacked-up formulas: * - * The Dreamcast has screen offsets from each side of its four borders and the start - * offsets of the display window. I used these values to calculate 'pseudo' values - * (think of them as placeholders) for the fb video mode, so that when it came time - * to convert these values back into their hardware values, I could just add mode- - * specific offsets to get the correct mode settings: + * The Dreamcast has screen offsets from each side of its four borders and + * the start offsets of the display window. I used these values to calculate + * 'pseudo' values (think of them as placeholders) for the fb video mode, so + * that when it came time to convert these values back into their hardware + * values, I could just add mode- specific offsets to get the correct mode + * settings: * * left_margin = diwstart_h - borderstart_h; * right_margin = borderstop_h - (diwstart_h + xres); @@ -29,9 +30,9 @@ * hsync_len = borderstart_h + (hsync_total - borderstop_h); * vsync_len = borderstart_v + (vsync_total - borderstop_v); * - * Then, when it's time to convert back to hardware settings, the only constants - * are the borderstart_* offsets, all other values are derived from the fb video - * mode: + * Then, when it's time to convert back to hardware settings, the only + * constants are the borderstart_* offsets, all other values are derived from + * the fb video mode: * * // PAL * borderstart_h = 116; @@ -57,7 +58,6 @@ #include #include #include -#include #ifdef CONFIG_SH_DREAMCAST #include @@ -66,14 +66,9 @@ #endif #ifdef CONFIG_MTRR - #include +#include #endif -#include