From bd79a781829a4fac2c3d24441cdecb7f37f9cd03 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:27:49 -0500 Subject: [PATCH] Import 2.3.23pre2 --- Documentation/Changes | 6 +- Documentation/Configure.help | 332 +- Documentation/vm/locking | 88 + MAINTAINERS | 10 + arch/arm/def-configs/footbridge | 2 +- arch/arm/defconfig | 2 +- arch/i386/Makefile | 4 - arch/i386/config.in | 6 +- arch/i386/kernel/pci-visws.c | 1 + arch/i386/kernel/visws_apic.c | 2 +- arch/i386/{vmlinux.lds.S => vmlinux.lds} | 2 +- arch/ppc/kernel/chrp_pci.c | 1 - arch/ppc/kernel/chrp_setup.c | 3 +- arch/ppc/kernel/mbx_setup.c | 2 +- arch/ppc/kernel/pmac_setup.c | 4 +- arch/ppc/kernel/prep_setup.c | 1 - arch/ppc/kernel/setup.c | 3 +- arch/ppc/mbx_defconfig | 2 +- arch/sh/Makefile | 39 +- arch/sh/config.in | 31 +- arch/sh/defconfig | 55 +- arch/sh/kernel/Makefile | 2 +- arch/sh/kernel/entry.S | 250 +- arch/sh/kernel/head.S | 94 +- arch/sh/kernel/irq.c | 64 +- arch/sh/kernel/irq_onchip.c | 67 +- arch/sh/kernel/process.c | 120 +- arch/sh/kernel/setup.c | 136 +- arch/sh/kernel/signal.c | 115 +- arch/sh/kernel/sys_sh.c | 92 +- arch/sh/kernel/test-img.c | 69 - arch/sh/kernel/time.c | 200 +- arch/sh/kernel/traps.c | 9 +- arch/sh/lib/Makefile | 6 +- arch/sh/lib/checksum.S | 318 ++ arch/sh/lib/checksum.c | 170 - arch/sh/lib/csum_partial_copy.c | 75 - arch/sh/lib/memcpy.S | 334 +- arch/sh/lib/memmove.S | 660 ++-- arch/sh/lib/memset.S | 105 +- arch/sh/lib/old-checksum.c | 2 - arch/sh/lib/wordcopy.S | 1289 -------- arch/sh/mm/Makefile | 2 +- arch/sh/mm/cache.c | 366 +++ arch/sh/mm/extable.c | 3 +- arch/sh/mm/fault.c | 59 +- arch/sh/mm/init.c | 15 +- arch/sh/mm/ioremap.c | 3 +- arch/sh/vmlinux.lds.S | 7 +- drivers/block/Config.in | 31 +- drivers/block/Makefile | 5 +- drivers/block/aec6210.c | 9 +- drivers/block/alim15x3.c | 735 +++-- drivers/block/cy82c693.c | 28 +- drivers/block/hpt34x.c | 176 +- drivers/block/hpt366.c | 263 +- drivers/block/icside.c | 3 +- drivers/block/ide-cd.c | 223 +- drivers/block/ide-cd.h | 3 +- drivers/block/ide-disk.c | 13 +- drivers/block/ide-dma.c | 10 +- drivers/block/ide-floppy.c | 9 +- drivers/block/ide-geometry.c | 3 + drivers/block/ide-pci.c | 205 +- drivers/block/ide-pmac.c | 3 +- drivers/block/ide-probe.c | 35 +- drivers/block/ide-proc.c | 73 +- drivers/block/ide-tape.c | 9 +- drivers/block/ide.c | 201 +- drivers/block/paride/pcd.c | 210 +- drivers/block/pdc202xx.c | 343 +- drivers/block/pdc4030.c | 28 +- drivers/block/piix.c | 55 +- drivers/block/sis5513.c | 299 +- drivers/block/trm290.c | 3 +- drivers/block/{via82c586.c => via82cxxx.c} | 220 +- drivers/cdrom/cdrom.c | 136 +- drivers/char/Makefile | 4 +- drivers/char/istallion.c | 1 + drivers/char/pcxx.c | 4 +- drivers/char/radio-cadet.c | 1 + drivers/char/stallion.c | 1 + drivers/i2o/Config.in | 4 +- drivers/net/hamradio/baycom_par.c | 2 +- drivers/net/hamradio/soundmodem/sm.c | 2 +- drivers/net/slhc.c | 12 +- drivers/pci/quirks.c | 1 + drivers/scsi/atp870u.c | 3458 +++++++++----------- drivers/scsi/atp870u.h | 8 +- drivers/scsi/ide-scsi.c | 19 +- drivers/scsi/inia100.h | 4 +- drivers/scsi/ips.c | 8 +- drivers/scsi/ips.h | 4 +- drivers/scsi/u14-34f.h | 2 + drivers/sound/maestro.c | 2 +- drivers/sound/sound_core.c | 3 + drivers/usb/cpia.c | 52 +- drivers/usb/hp_scanner.c | 2 +- drivers/usb/inits.h | 9 +- drivers/usb/uhci.c | 216 +- drivers/usb/uhci.h | 13 +- drivers/usb/usb.c | 47 +- drivers/usb/usb.h | 46 +- drivers/video/Config.in | 1 + drivers/video/Makefile | 4 + drivers/video/aty128.h | 594 ++++ drivers/video/aty128fb.c | 2151 ++++++++++++ drivers/video/atyfb.c | 4 +- drivers/video/chipsfb.c | 26 +- drivers/video/offb.c | 25 + fs/dcache.c | 5 + fs/exec.c | 7 + fs/inode.c | 16 +- fs/minix/truncate.c | 2 +- fs/nfs/dir.c | 137 +- fs/nfs/inode.c | 226 +- fs/nfs/nfs2xdr.c | 36 +- fs/nfs/proc.c | 8 +- fs/proc/array.c | 220 +- include/asm-i386/page.h | 19 +- include/asm-i386/page_offset.h | 8 - include/asm-sh/addrspace.h | 55 +- include/asm-sh/atomic.h | 24 +- include/asm-sh/bitops.h | 24 +- include/asm-sh/bugs.h | 18 + include/asm-sh/byteorder.h | 3 +- include/asm-sh/cache.h | 8 + include/asm-sh/checksum.h | 232 +- include/asm-sh/delay.h | 25 +- include/asm-sh/elf.h | 15 +- include/asm-sh/hardirq.h | 2 +- include/asm-sh/hdreg.h | 12 + include/asm-sh/ide.h | 112 + include/asm-sh/io.h | 79 +- include/asm-sh/ioctl.h | 2 +- include/asm-sh/ioctls.h | 6 +- include/asm-sh/irq.h | 6 +- include/asm-sh/mmu_context.h | 32 +- include/asm-sh/namei.h | 2 +- include/asm-sh/page.h | 12 +- include/asm-sh/pgtable.h | 35 +- include/asm-sh/processor.h | 90 +- include/asm-sh/ptrace.h | 8 +- include/asm-sh/sigcontext.h | 15 +- include/asm-sh/signal.h | 12 - include/asm-sh/smp_lock.h | 17 - include/asm-sh/smplock.h | 70 + include/asm-sh/socket.h | 19 +- include/asm-sh/softirq.h | 3 +- include/asm-sh/system.h | 15 +- include/asm-sh/termbits.h | 19 +- include/asm-sh/termios.h | 7 +- include/asm-sh/types.h | 8 +- include/asm-sh/uaccess.h | 42 +- include/asm-sh/unistd.h | 15 +- include/linux/cdrom.h | 76 +- include/linux/fs.h | 9 +- include/linux/hdreg.h | 2 + include/linux/ide.h | 5 +- include/linux/mm.h | 6 + include/linux/nfs.h | 15 +- include/linux/nfs_fs.h | 20 +- include/linux/nfs_fs_i.h | 8 +- include/linux/proc_fs.h | 1 + include/linux/sched.h | 5 + include/linux/sysv_fs.h | 1 - include/net/ip.h | 2 + init/main.c | 4 + ipc/shm.c | 2 + kernel/exit.c | 34 +- kernel/fork.c | 7 +- kernel/ksyms.c | 2 +- kernel/ptrace.c | 10 +- kernel/time.c | 22 +- mm/mlock.c | 25 +- mm/mmap.c | 27 +- mm/mprotect.c | 26 +- mm/mremap.c | 4 + mm/vmscan.c | 34 +- net/core/dst.c | 1 - net/core/skbuff.c | 2 + net/ipv4/tcp_ipv4.c | 2 - net/sunrpc/clnt.c | 4 + net/sunrpc/sched.c | 17 +- 184 files changed, 10390 insertions(+), 7000 deletions(-) create mode 100644 Documentation/vm/locking rename arch/i386/{vmlinux.lds.S => vmlinux.lds} (98%) delete mode 100644 arch/sh/kernel/test-img.c create mode 100644 arch/sh/lib/checksum.S delete mode 100644 arch/sh/lib/checksum.c delete mode 100644 arch/sh/lib/csum_partial_copy.c delete mode 100644 arch/sh/lib/wordcopy.S create mode 100644 arch/sh/mm/cache.c rename drivers/block/{via82c586.c => via82cxxx.c} (77%) create mode 100644 drivers/video/aty128.h create mode 100644 drivers/video/aty128fb.c delete mode 100644 include/asm-i386/page_offset.h create mode 100644 include/asm-sh/hdreg.h create mode 100644 include/asm-sh/ide.h delete mode 100644 include/asm-sh/smp_lock.h create mode 100644 include/asm-sh/smplock.h diff --git a/Documentation/Changes b/Documentation/Changes index f910c4c7e8ab..7048d0f14c60 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -43,7 +43,7 @@ Current Minimal Requirements encountered a bug! If you're unsure what version you're currently running, the suggested command should tell you. -- Kernel modutils 2.3.5 ; insmod -V +- Kernel modutils 2.3.6 ; insmod -V - Gnu C 2.7.2.3 ; gcc --version - Binutils 2.8.1.0.23 ; ld -v - Linux libc5 C Library 5.4.46 ; ls -l /lib/libc* @@ -567,8 +567,8 @@ ftp://metalab.unc.edu/pub/Linux/GCC/ld.so-1.9.9.tar.gz Modules utilities ================= -The 2.3.5 release: -ftp://ftp.ocs.com.au/pub/modutils/v2.3/modutils-2.3.5.tar.gz +The 2.3.6 release: +ftp://ftp.ocs.com.au/pub/modutils/v2.3/modutils-2.3.6.tar.gz Procps utilities ================ diff --git a/Documentation/Configure.help b/Documentation/Configure.help index 807d2875511b..9dc8623641a7 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -175,13 +175,13 @@ CONFIG_MATHEMU on the Alpha. The only time you would ever not say Y is to say M in order to debug the code. Say Y unless you know what you are doing. -Big memory support +Support for over 1Gig of memory CONFIG_BIGMEM - Linux can use up to 2 Gigabytes (= 2^31 bytes) of physical memory. + Linux can use up to 1 Gigabytes (= 2^30 bytes) of physical memory. If you are compiling a kernel which will never run on a machine with more than 1 Gigabyte, answer N here. Otherwise, say Y. - The actual amount of physical memory should be specified using a + The actual amount of physical memory may need to be specified using a kernel command line option such as "mem=256M". (Try "man bootparam" or see the documentation of your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time. The lilo procedure @@ -578,12 +578,6 @@ IDEDMA_NEW_DRIVE_LISTINGS If in doubt, say N. -Winbond SL82c105 support -CONFIG_BLK_DEV_SL82C105 - If you have a Winbond SL82c105 IDE controller, say Y here to enable - special configuration for this chip. This is common on various CHRP - motherboards, but could be used elsewhere. If in doubt, say Y. - Boot off-board chipsets first support CONFIG_BLK_DEV_OFFBOARD Normally, IDE controllers built into the motherboard (on-board @@ -621,82 +615,32 @@ CONFIG_IDEDMA_PCI_AUTO It is normally safe to answer Y to this question unless your motherboard uses a VIA VP2 chipset, in which case you should say N. -Other IDE chipset support -CONFIG_IDE_CHIPSETS - Say Y here if you want to include enhanced support for various IDE - interface chipsets used on motherboards and add-on cards. You can - then pick your particular IDE chip from among the following options. - This enhanced support may be necessary for Linux to be able to - access the 3rd/4th drives in some systems. It may also enable - setting of higher speed I/O rates to improve system performance with - these chipsets. Most of these also require special kernel boot - parameters to actually turn on the support at runtime; you can find - a list of these in the file Documentation/ide.txt. - - People with SCSI-only systems can say N here. - -Generic 4 drives/port support -CONFIG_BLK_DEV_4DRIVES - Certain older chipsets, including the Tekram 690CD, use a single set - of I/O ports at 0x1f0 to control up to four drives, instead of the - customary two drives per port. Support for this can be enabled at - runtime using the "ide0=four" kernel boot parameter if you say Y - here. - -DTC-2278 support -CONFIG_BLK_DEV_DTC2278 - This driver is enabled at runtime using the "ide0=dtc2278" kernel - 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 Documentation/ide.txt and drivers/block/dtc2278.c - files for more info. - -Holtek HT6560B support -CONFIG_BLK_DEV_HT6560B - This driver is enabled at runtime using the "ide0=ht6560b" kernel - 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 Documentation/ide.txt and drivers/block/ht6560b.c files for - more info. +AEC6210 chipset support +CONFIG_BLK_DEV_AEC6210 + This driver adds up to 4 more EIDE devices sharing a single + interrupt. This add-on card is a bootable PCI UDMA controller. In + order to get this card to initialize correctly in some cases, you + should say Y here, and preferably also to "Use DMA by default when + available". -PROMISE DC4030 support (EXPERIMENTAL) -CONFIG_BLK_DEV_PDC4030 - This driver provides support for the secondary IDE interface and - cache of Promise IDE chipsets, e.g. DC4030 and DC5030. This driver - is known to incur timeouts/retries during heavy I/O to drives - attached to the secondary interface. CDROM and TAPE devices are not - supported yet. This driver is enabled at runtime using the - "ide0=dc4030" kernel boot parameter. See the Documentation/ide.txt - and drivers/block/pdc4030.c files for more info. + Please read the comments at the top of drivers/block/aec6210.c -PS/2 ESDI hard disk support -CONFIG_BLK_DEV_PS2 - Say Y here if you have a PS/2 machine with a MCA bus and an ESDI - hard disk. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called ps2esdi.o. +ALI M15x3 chipset support (EXPERIMENTAL) +CONFIG_BLK_DEV_ALI15X3 + This driver ensures (U)DMA support for ALI 1543 and 1543C, + 1535, 1535D onboard chipsets. It also tests for Simplex mode and + enables normal dual channel support. -Tekram TRM290 chipset support (EXPERIMENTAL) -CONFIG_BLK_DEV_TRM290 - 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 drivers/block/trm290.c. + If you say Y here, you also need to say Y to "Use DMA by default + when available", above. -OPTi 82C621 enhanced support (EXPERIMENTAL) -CONFIG_BLK_DEV_OPTI621 - This is a driver for the OPTi 82C621 EIDE controller. - Please read the comments at the top of drivers/block/opti621.c. + Please read the comments at the top of drivers/block/alim15x3.c -NS87415 support (EXPERIMENTAL) -CONFIG_BLK_DEV_NS87415 - This driver adds detection and support for the NS87415 chip - (used in SPARC64, among others). + If unsure, say N. - Please read the comments at the top of drivers/block/ns87415.c. +CMD646 chipset support (EXPERIMENTAL) +CONFIG_BLK_DEV_CMD646 + Say Y here if you have an IDE controller which uses this chipset. CY82C693 chipset support (EXPERIMENTAL) CONFIG_BLK_DEV_CY82C693 @@ -706,36 +650,80 @@ CONFIG_BLK_DEV_CY82C693 If you say Y here, you need to say Y to "Use DMA by default when available" as well. -VIA82C586 chipset support (EXPERIMENTAL) -CONFIG_BLK_DEV_VIA82C586 - Saying Y here adds initial timing settings for VIA (U)DMA onboard - IDE controllers that are ATA3 compliant. May work with ATA4 systems, - but not tested to date. To use some features of this chipset, you - will have to issue a kernel command line as described in the file - drivers/block/via82c586.c. Furthermore, if you also say Y to "/proc - filesystem support" and set DISPLAY_APOLLO_TIMINGS in via82c586.c, - you will be able to read information about the IDE controller from - the virtual file /proc/ide/via. +HPT34X chipset support +CONFIG_BLK_DEV_HPT34X + This driver adds up to 4 more EIDE devices sharing a single + interrupt. The HPT343 chipset in its current form is a non-bootable + controller; the HPT345/HPT363 chipset is a bootable (needs BIOS FIX) + PCI UDMA controllers. This driver requires dynamic tuning of the + chipset during the ide-probe at boot time. It is reported to support + DVD II drives, by the manufacturer. - If you say Y here, you also need to say Y to "Use DMA by default - when available", above. +HPT34X DMA support (EXPERIMENTAL) +CONFIG_BLK_DEV_HPT34X_DMA + you need to say Y to "Use DMA by default when available" if you say + Y here. + + Please read the comments at the top of drivers/block/hpt34x.c + +HPT366 chipset support +CONFIG_BLK_DEV_HPT366 + This is an Ultra DMA chipset for ATA-66. + + This driver adds up to 4 more EIDE devices sharing a single + interrupt. The HPT366 chipset in its current form is a non-bootable. + This driver requires dynamic tuning of the chipset during the + ide-probe at boot. It is reported to support DVD II drives, by the + manufacturer. + + Please read the comments at the top of drivers/block/hpt366.c + +HPT366 (EXPERIMENTAL) +CONFIG_BLK_DEV_HPT366_SHARED + This requires CONFIG_BLK_DEV_HPT366. + It appears that there are different versions or releases of this hardware + by ABit. Since some cases the second channel of the onboard chipset works + and others fail, it is default disabled. This is required to be set if you + want to attempt the setup of the second channel. + + JUMBO WARNING, do not boot a kernel with this enabled if it is your only + one. You may not be able to get back into your machine without physically + detaching the attached devices. If unsure, say N. -CMD646 chipset support (EXPERIMENTAL) -CONFIG_BLK_DEV_CMD646 - Say Y here if you have an IDE controller which uses this chipset. +NS87415 support (EXPERIMENTAL) +CONFIG_BLK_DEV_NS87415 + This driver adds detection and support for the NS87415 chip + (used in SPARC64, among others). -ALI M15x3 chipset support (EXPERIMENTAL) -CONFIG_BLK_DEV_ALI15X3 - This driver ensures (U)DMA support for ALI 1533, 1543 and 1543C - onboard chipsets. It also tests for Simplex mode and enables - normal dual channel support. + Please read the comments at the top of drivers/block/ns87415.c. - If you say Y here, you also need to say Y to "Use DMA by default - when available", above. +OPTi 82C621 enhanced support (EXPERIMENTAL) +CONFIG_BLK_DEV_OPTI621 + This is a driver for the OPTi 82C621 EIDE controller. + Please read the comments at the top of drivers/block/opti621.c. - Please read the comments at the top of drivers/block/alim15x3.c +Intel PIIXn chipsets support +CONFIG_BLK_DEV_PIIX + This driver adds PIO mode setting and tuning for all PIIX IDE + controllers by Intel. Since the BIOS can sometimes improperly tune + PIO 0-4 mode settings, this allows dynamic tuning of the chipset + via the standard end-user tool 'hdparm'. + + Please read the comments at the top of drivers/block/piix.c + + If unsure, say N. + +PIIXn Tuning support +CONFIG_BLK_DEV_PIIX_TUNING + This driver extension adds DMA mode setting and tuning for all PIIX + IDE controllers by Intel. Since the BIOS can sometimes improperly + set up the device/adapter combination and speed limits, it has + become a necessity to back/forward speed devices as needed. + + Case 430HX/440FX PIIX3 need speed limits to reduce UDMA to DMA mode + 2 if the BIOS can not perform this task at initialization. If unsure, say N. @@ -767,7 +755,7 @@ CONFIG_BLK_DEV_PDC202XX If unsure, say N. -Special UDMA Feature (EXPERIMENTAL) +Special UDMA Feature PDC202XX_FORCE_BURST_BIT For PDC20246 and PDC20262 Ultra DMA chipsets. Designed originally for PDC20246/Ultra33 that has BIOS setup failures when using 3 or @@ -777,71 +765,97 @@ PDC202XX_FORCE_BURST_BIT If unsure, say N. -Special Mode Feature (DANGEROUS) +Special Mode Feature (EXPERIMENTAL) PDC202XX_FORCE_MASTER_MODE For PDC20246 and PDC20262 Ultra DMA chipsets. This is reserved for possible Hardware RAID 0,1 for the FastTrak Series. Say N. -AEC6210 chipset support -CONFIG_BLK_DEV_AEC6210 - This driver adds up to 4 more EIDE devices sharing a single - interrupt. This add-on card is a bootable PCI UDMA controller. In - order to get this card to initialize correctly in some cases, you - should say Y here, and preferably also to "Use DMA by default when - available". +Winbond SL82c105 support +CONFIG_BLK_DEV_SL82C105 + If you have a Winbond SL82c105 IDE controller, say Y here to enable + special configuration for this chip. This is common on various CHRP + motherboards, but could be used elsewhere. If in doubt, say Y. - Please read the comments at the top of drivers/block/aec6210.c +Tekram TRM290 chipset support (EXPERIMENTAL) +CONFIG_BLK_DEV_TRM290 + 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 drivers/block/trm290.c. -HPT366 chipset support -CONFIG_BLK_DEV_HPT366 - This is an Ultra DMA chipset for ATA-66. - - This driver adds up to 4 more EIDE devices sharing a single - interrupt. The HPT366 chipset in its current form is a non-bootable. - This driver requires dynamic tuning of the chipset during the - ide-probe at boot. It is reported to support DVD II drives, by the - manufacturer. - -Intel PIIXn chipsets support -CONFIG_BLK_DEV_PIIX - This driver adds PIO mode setting and tuning for all PIIX IDE - controllers by Intel. Since the BIOS can sometimes improperly tune - PIO 0-4 mode settings, this allows dynamic tuning of the chipset - via the standard end-user tool 'hdparm'. +VIA82CXXX chipset support (EXPERIMENTAL) +CONFIG_BLK_DEV_VIA82CXXX + This allows you to to configure your chipset for a better use while + running (U)DMA: it will allow you to enable efficiently the second + channel dma usage, as it is may not be set by BIOS. It allows you to + run a kernel command line at boot time in order to set fifo config. + If no command line is provided, it will try to set fifo configuration + at its best. It will allow you to get a proc/ide/via display + (while running a "cat") provided you enabled "proc" support. + Please read the comments at the top of drivers/block/via82cxxx.c - Please read the comments at the top of drivers/block/piix.c + If you say Y here, you also need to say Y to "Use DMA by default + when available", above. If unsure, say N. -PIIXn Tuning support (EXPERIMENTAL) -CONFIG_BLK_DEV_PIIX_TUNING - This driver extension adds DMA mode setting and tuning for all PIIX - IDE controllers by Intel. Since the BIOS can sometimes improperly - set up the device/adapter combination and speed limits, it has - become a necessity to back/forward speed devices as needed. +Other IDE chipset support +CONFIG_IDE_CHIPSETS + Say Y here if you want to include enhanced support for various IDE + interface chipsets used on motherboards and add-on cards. You can + then pick your particular IDE chip from among the following options. + This enhanced support may be necessary for Linux to be able to + access the 3rd/4th drives in some systems. It may also enable + setting of higher speed I/O rates to improve system performance with + these chipsets. Most of these also require special kernel boot + parameters to actually turn on the support at runtime; you can find + a list of these in the file Documentation/ide.txt. + + People with SCSI-only systems can say N here. - Case 430HX/440FX PIIX3 need speed limits to reduce UDMA to DMA mode - 2 if the BIOS can not perform this task at initialization. +Generic 4 drives/port support +CONFIG_BLK_DEV_4DRIVES + Certain older chipsets, including the Tekram 690CD, use a single set + of I/O ports at 0x1f0 to control up to four drives, instead of the + customary two drives per port. Support for this can be enabled at + runtime using the "ide0=four" kernel boot parameter if you say Y + here. - If unsure, say N. +ALI M14xx support +CONFIG_BLK_DEV_ALI14XX + This driver is enabled at runtime using the "ide0=ali14xx" kernel + boot parameter. It enables support for the secondary IDE interface + of the ALI M1439/1443/1445/1487/1489 chipsets, and permits faster + I/O speeds to be set as well. See the files Documentation/ide.txt + and drivers/block/ali14xx.c for more info. -HPT34X chipset support -CONFIG_BLK_DEV_HPT34X - This driver adds up to 4 more EIDE devices sharing a single - interrupt. The HPT343 chipset in its current form is a non-bootable - controller; the HPT345/HPT363 chipset is a bootable (needs BIOS FIX) - PCI UDMA controllers. This driver requires dynamic tuning of the - chipset during the ide-probe at boot time. It is reported to support - DVD II drives, by the manufacturer. +DTC-2278 support +CONFIG_BLK_DEV_DTC2278 + This driver is enabled at runtime using the "ide0=dtc2278" kernel + 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 Documentation/ide.txt and drivers/block/dtc2278.c + files for more info. -HPT34X DMA support (DANGEROUS) -CONFIG_BLK_DEV_HPT34X_DMA - you need to say Y to "Use DMA by default when available" if you say - Y here. +Holtek HT6560B support +CONFIG_BLK_DEV_HT6560B + This driver is enabled at runtime using the "ide0=ht6560b" kernel + 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 Documentation/ide.txt and drivers/block/ht6560b.c files for + more info. - Please read the comments at the top of drivers/block/hpt343.c +PROMISE DC4030 support (EXPERIMENTAL) +CONFIG_BLK_DEV_PDC4030 + This driver provides support for the secondary IDE interface and + cache of Promise IDE chipsets, e.g. DC4030 and DC5030. This driver + is known to incur timeouts/retries during heavy I/O to drives + attached to the secondary interface. CDROM and TAPE devices are not + supported yet. This driver is enabled at runtime using the + "ide0=dc4030" kernel boot parameter. See the Documentation/ide.txt + and drivers/block/pdc4030.c files for more info. QDI QD6580 support CONFIG_BLK_DEV_QD6580 @@ -858,13 +872,15 @@ CONFIG_BLK_DEV_UMC8672 See the files Documentation/ide.txt and drivers/block/umc8672.c for more info. -ALI M14xx support -CONFIG_BLK_DEV_ALI14XX - This driver is enabled at runtime using the "ide0=ali14xx" kernel - boot parameter. It enables support for the secondary IDE interface - of the ALI M1439/1443/1445/1487/1489 chipsets, and permits faster - I/O speeds to be set as well. See the files Documentation/ide.txt - and drivers/block/ali14xx.c for more info. +PS/2 ESDI hard disk support +CONFIG_BLK_DEV_PS2 + Say Y here if you have a PS/2 machine with a MCA bus and an ESDI + hard disk. + + If you want to compile the driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read Documentation/modules.txt. The module will be + called ps2esdi.o. Amiga builtin Gayle IDE interface support CONFIG_BLK_DEV_GAYLE diff --git a/Documentation/vm/locking b/Documentation/vm/locking new file mode 100644 index 000000000000..6efdcec3e065 --- /dev/null +++ b/Documentation/vm/locking @@ -0,0 +1,88 @@ +Started Oct 1999 by Kanoj Sarcar + +The intent of this file is to have an uptodate, running commentary +from different people about how locking and synchronization is done +in the Linux vm code. + +vmlist_access_lock/vmlist_modify_lock +-------------------------------------- + +Page stealers pick processes out of the process pool and scan for +the best process to steal pages from. To guarantee the existance +of the victim mm, a mm_count inc and a mmdrop are done in swap_out(). +Page stealers hold kernel_lock to protect against a bunch of races. +The vma list of the victim mm is also scanned by the stealer, +and the vmlist_lock is used to preserve list sanity against the +process adding/deleting to the list. This also gurantees existance +of the vma. Vma existance gurantee while invoking the driver +swapout() method in try_to_swap_out() also relies on the fact +that do_munmap() temporarily gets lock_kernel before decimating +the vma, thus the swapout() method must snapshot all the vma +fields it needs before going to sleep (which will release the +lock_kernel held by the page stealer). Currently, filemap_swapout +is the only method that depends on this shaky interlocking. + +Any code that modifies the vmlist, or the vm_start/vm_end/ +vm_flags:VM_LOCKED/vm_next of any vma *in the list* must prevent +kswapd from looking at the chain. This does not include driver mmap() +methods, for example, since the vma is still not in the list. + +The rules are: +1. To modify the vmlist (add/delete or change fields in an element), +you must hold mmap_sem to guard against clones doing mmap/munmap/faults, +(ie all vm system calls and faults), and from ptrace, swapin due to +swap deletion etc. +2. To modify the vmlist (add/delete or change fields in an element), +you must also hold vmlist_modify_lock, to guard against page stealers +scanning the list. +3. To scan the vmlist (find_vma()), you must either + a. grab mmap_sem, which should be done by all cases except + page stealer. +or + b. grab vmlist_access_lock, only done by page stealer. +4. While holding the vmlist_modify_lock, you must be able to guarantee +that no code path will lead to page stealing. A better guarantee is +to claim non sleepability, which ensures that you are not sleeping +for a lock, whose holder might in turn be doing page stealing. +5. You must be able to guarantee that while holding vmlist_modify_lock +or vmlist_access_lock of mm A, you will not try to get either lock +for mm B. + +The caveats are: +1. find_vma() makes use of, and updates, the mmap_cache pointer hint. +The update of mmap_cache is racy (page stealer can race with other code +that invokes find_vma with mmap_sem held), but that is okay, since it +is a hint. This can be fixed, if desired, by having find_vma grab the +vmlist lock. + + +Code that add/delete elements from the vmlist chain are +1. callers of insert_vm_struct +2. callers of merge_segments +3. callers of avl_remove + +Code that changes vm_start/vm_end/vm_flags:VM_LOCKED of vma's on +the list: +1. expand_stack +2. mprotect +3. mlock +4. mremap + +It is advisable that changes to vm_start/vm_end be protected, although +in some cases it is not really needed. Eg, vm_start is modified by +expand_stack(), it is hard to come up with a destructive scenario without +having the vmlist protection in this case. + +The vmlist lock nests with the inode i_shared_lock and the kmem cache +c_spinlock spinlocks. This is okay, since code that holds i_shared_lock +never asks for memory, and the kmem code asks for pages after dropping +c_spinlock. + +The vmlist lock can be a sleeping or spin lock. In either case, care +must be taken that it is not held on entry to the driver methods, since +those methods might sleep or ask for memory, causing deadlocks. + +The current implementation of the vmlist lock uses the page_table_lock, +which is also the spinlock that page stealers use to protect changes to +the victim process' ptes. Thus we have a reduction in the total number +of locks. diff --git a/MAINTAINERS b/MAINTAINERS index 67c855554f99..628715592dad 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -831,6 +831,16 @@ STARMODE RADIO IP (STRIP) PROTOCOL DRIVER W: http://mosquitonet.Stanford.EDU/strip.html S: Unsupported ? +SUPERH +P: Niibe Yutaka +M: gniibe@chroot.org +P: Kazumoto Kojima +M: kkojima@rr.iij4u.or.jp +L: linux-sh@m17n.org +W: http://www.m17n.org/linux-sh/ +W: http://www.rr.iij4u.or.jp/~kkojima/linux-sh4.html +S: Maintained + SVGA HANDLING P: Martin Mares M: mj@atrey.karlin.mff.cuni.cz diff --git a/arch/arm/def-configs/footbridge b/arch/arm/def-configs/footbridge index ce85d6ffc469..2641675c38da 100644 --- a/arch/arm/def-configs/footbridge +++ b/arch/arm/def-configs/footbridge @@ -89,7 +89,7 @@ CONFIG_IDEDMA_AUTO=y # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_VIA82C586 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_BLK_DEV_CMD646 is not set CONFIG_BLK_DEV_SL82C105=y # CONFIG_IDE_CHIPSETS is not set diff --git a/arch/arm/defconfig b/arch/arm/defconfig index 4f1ec7e28e2b..6ede3c2f519e 100644 --- a/arch/arm/defconfig +++ b/arch/arm/defconfig @@ -89,7 +89,7 @@ CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_VIA82C586 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_BLK_DEV_CMD646 is not set CONFIG_BLK_DEV_SL82C105=y # CONFIG_IDE_CHIPSETS is not set diff --git a/arch/i386/Makefile b/arch/i386/Makefile index 9978cac9d677..37b2371a0bcf 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -84,9 +84,6 @@ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot vmlinux: arch/i386/vmlinux.lds -arch/i386/vmlinux.lds: arch/i386/vmlinux.lds.S FORCE - $(CPP) -C -P -imacros $(HPATH)/asm-i386/page_offset.h -Ui386 arch/i386/vmlinux.lds.S >arch/i386/vmlinux.lds - FORCE: ; .PHONY: zImage bzImage compressed zlilo bzlilo zdisk bzdisk install \ @@ -119,7 +116,6 @@ archclean: @$(MAKEBOOT) clean archmrproper: - rm -f arch/i386/vmlinux.lds archdep: @$(MAKEBOOT) dep diff --git a/arch/i386/config.in b/arch/i386/config.in index 9d373d1ed3f7..529b648beeab 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -42,10 +42,6 @@ if [ "$CONFIG_MK7" = "y" ]; then define_bool CONFIG_X86_USE_3DNOW y fi -choice 'Maximum Physical Memory' \ - "1GB CONFIG_1GB \ - 2GB CONFIG_2GB" 1GB - bool 'Math emulation' CONFIG_MATH_EMULATION bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR bool 'Symmetric multi-processing support' CONFIG_SMP @@ -63,7 +59,7 @@ endmenu mainmenu_option next_comment comment 'General setup' -bool 'BIGMEM support' CONFIG_BIGMEM +bool 'Support for over 1Gig of memory' CONFIG_BIGMEM bool 'Networking support' CONFIG_NET bool 'SGI Visual Workstation support' CONFIG_VISWS if [ "$CONFIG_VISWS" = "y" ]; then diff --git a/arch/i386/kernel/pci-visws.c b/arch/i386/kernel/pci-visws.c index 63620c635fac..8a954ce8b616 100644 --- a/arch/i386/kernel/pci-visws.c +++ b/arch/i386/kernel/pci-visws.c @@ -14,6 +14,7 @@ #include #include +#include #include "pci-i386.h" diff --git a/arch/i386/kernel/visws_apic.c b/arch/i386/kernel/visws_apic.c index de79fe61e075..6c767d0ebff8 100644 --- a/arch/i386/kernel/visws_apic.c +++ b/arch/i386/kernel/visws_apic.c @@ -37,7 +37,7 @@ #include -#include "irq.h" +#include /* * This is the PIIX4-based 8259 that is wired up indirectly to Cobalt diff --git a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds similarity index 98% rename from arch/i386/vmlinux.lds.S rename to arch/i386/vmlinux.lds index 9a9ff07e7f2a..9624cae47bd1 100644 --- a/arch/i386/vmlinux.lds.S +++ b/arch/i386/vmlinux.lds @@ -6,7 +6,7 @@ OUTPUT_ARCH(i386) ENTRY(_start) SECTIONS { - . = PAGE_OFFSET_RAW + 0x100000; + . = 0xC0000000 + 0x100000; _text = .; /* Text and read-only data */ .text : { *(.text) diff --git a/arch/ppc/kernel/chrp_pci.c b/arch/ppc/kernel/chrp_pci.c index da752ccb63b7..983a9f2eb3d2 100644 --- a/arch/ppc/kernel/chrp_pci.c +++ b/arch/ppc/kernel/chrp_pci.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include "pci.h" diff --git a/arch/ppc/kernel/chrp_setup.c b/arch/ppc/kernel/chrp_setup.c index 4f71def9adc1..934f377b50c9 100644 --- a/arch/ppc/kernel/chrp_setup.c +++ b/arch/ppc/kernel/chrp_setup.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -40,8 +41,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/arch/ppc/kernel/mbx_setup.c b/arch/ppc/kernel/mbx_setup.c index 67cab4503d82..5ba7d878e914 100644 --- a/arch/ppc/kernel/mbx_setup.c +++ b/arch/ppc/kernel/mbx_setup.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -37,7 +38,6 @@ #include #include #include -#include #include #include diff --git a/arch/ppc/kernel/pmac_setup.c b/arch/ppc/kernel/pmac_setup.c index 3418a7e8b7b3..41ff21aed173 100644 --- a/arch/ppc/kernel/pmac_setup.c +++ b/arch/ppc/kernel/pmac_setup.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -57,7 +58,6 @@ #include #include #include -#include #include #include #include @@ -421,7 +421,7 @@ note_scsi_host(struct device_node *node, void *host) #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) extern int pmac_ide_count; extern struct device_node *pmac_ide_node[]; -static int ide_majors[] = { 3, 22, 33, 34, 56, 57, 88, 89 }; +static int ide_majors[] = { 3, 22, 33, 34, 56, 57, 88, 89, 90, 91 }; kdev_t __init find_ide_boot(void) { diff --git a/arch/ppc/kernel/prep_setup.c b/arch/ppc/kernel/prep_setup.c index 53c859a162a5..a04347d4b97b 100644 --- a/arch/ppc/kernel/prep_setup.c +++ b/arch/ppc/kernel/prep_setup.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 57955efcac52..7177c800677b 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -11,12 +11,11 @@ #include #include #include +#include #include #include #include -#include -#include #include #include #include diff --git a/arch/ppc/mbx_defconfig b/arch/ppc/mbx_defconfig index 494717c54461..7080efb3ec99 100644 --- a/arch/ppc/mbx_defconfig +++ b/arch/ppc/mbx_defconfig @@ -74,7 +74,7 @@ CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_VIA82C586 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_BLK_DEV_CMD646 is not set CONFIG_BLK_DEV_SL82C105=y # CONFIG_IDE_CHIPSETS is not set diff --git a/arch/sh/Makefile b/arch/sh/Makefile index c1c6f1e29f3e..31fcf5d694a5 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -1,9 +1,11 @@ -# $Id$ +# $Id: Makefile,v 1.1 1999/09/18 16:55:51 gniibe Exp gniibe $ # # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive # for more details. # +# Copyright (C) 1999 Kaz Kojima +# # This file is included by the global makefile so that you can add your own # architecture-specific flags and dependencies. Remember to do have actions # for "archclean" and "archdep" for cleaning up and making dependencies for @@ -13,25 +15,35 @@ # # Select the object file format to substitute into the linker script. # -tool-prefix = sh-gniibe- -oformat = elf +tool-prefix = sh-elf + +ifdef CONFIG_LITTLE_ENDIAN +CFLAGS += -ml +AFLAGS += -ml +# LINKFLAGS += -EL +LDFLAGS := -EL + +LD =$(CROSS_COMPILE)ld $(LDFLAGS) + +endif ifdef CONFIG_CROSSCOMPILE CROSS_COMPILE = $(tool-prefix) endif -LINKFLAGS = # -EL # -static #-N MODFLAGS += # # -CFLAGS += -m3 # -ml -LINKFLAGS += -LDFLAGS += # -EL -# -# -HOSTCC = cc +ifdef CONFIG_CPU_SH3 +CFLAGS += -m3 +AFLAGS += -m3 +endif +ifdef CONFIG_CPU_SH4 +CFLAGS += -m4 +AFLAGS += -m4 +endif # # Choosing incompatible machines durings configuration will result in @@ -52,14 +64,16 @@ HEAD := arch/sh/kernel/head.o arch/sh/kernel/init_task.o SUBDIRS := $(SUBDIRS) $(addprefix arch/sh/, kernel mm lib) CORE_FILES := arch/sh/kernel/kernel.o arch/sh/mm/mm.o $(CORE_FILES) -LIBS := $(TOPDIR)/arch/sh/lib/lib.a $(LIBS) $(TOPDIR)/arch/sh/lib/lib.a /home/niibe/lib/gcc-lib/sh-gniibe-elf/egcs-2.91.66/libgcc.a +LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) +LIBS := $(TOPDIR)/arch/sh/lib/lib.a $(LIBS) $(TOPDIR)/arch/sh/lib/lib.a \ + $(LIBGCC) MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot vmlinux: arch/sh/vmlinux.lds arch/sh/vmlinux.lds: arch/sh/vmlinux.lds.S FORCE - gcc -E -C -P -I$(HPATH) -imacros $(HPATH)/linux/config.h -Ush arch/sh/vmlinux.lds.S >arch/sh/vmlinux.lds + gcc -E -C -P -I$(HPATH) -Ush arch/sh/vmlinux.lds.S >arch/sh/vmlinux.lds FORCE: ; @@ -77,6 +91,7 @@ archclean: # $(MAKE) -C arch/$(ARCH)/tools clean archmrproper: + rm -f arch/sh/vmlinux.lds archdep: @$(MAKEBOOT) dep diff --git a/arch/sh/config.in b/arch/sh/config.in index 48874a0f0f9c..516dc37484ef 100644 --- a/arch/sh/config.in +++ b/arch/sh/config.in @@ -12,28 +12,24 @@ endmenu mainmenu_option next_comment comment 'Processor type and features' choice 'Processor family' \ - "SH3 CONFIG_CPU_SH3 \ - SH4 CONFIG_CPU_SH4" SH3 + "SH-3 CONFIG_CPU_SH3 \ + SH-4 CONFIG_CPU_SH4" SH-3 bool 'Little Endian' CONFIG_LITTLE_ENDIAN -hex 'Physical memory start address' CONFIG_MEMORY_START 0c000000 +hex 'Physical memory start address' CONFIG_MEMORY_START 08000000 +bool 'Use SH CPU internal real time clock' CONFIG_SH_CPU_RTC endmenu mainmenu_option next_comment comment 'Loadable module support' bool 'Enable loadable module support' CONFIG_MODULES if [ "$CONFIG_MODULES" = "y" ]; then - bool ' Set version information on all symbols for modules' CONFIG_MODVERSIONS - bool ' Kernel module loader' CONFIG_KMOD + bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS + bool 'Kernel module loader' CONFIG_KMOD fi endmenu -define_bool CONFIG_SERIAL n -define_bool CONFIG_SH3SCI_SERIAL y -define_bool CONFIG_SERIAL_CONSOLE y - mainmenu_option next_comment -comment 'Floppy, IDE, and other block devices' - +comment 'General setup' bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT @@ -41,6 +37,18 @@ bool 'Sysctl support' CONFIG_SYSCTL tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC +endmenu + +mainmenu_option next_comment +comment 'Character devices' +define_bool CONFIG_SERIAL n +define_bool CONFIG_SERIAL_CONSOLE y +bool 'SuperH SCI support' CONFIG_SH_SCI_SERIAL +bool 'SuperH SCIF support' CONFIG_SH_SCIF_SERIAL +endmenu + +mainmenu_option next_comment +comment 'Floppy, IDE, and other block devices' tristate 'RAM disk support' CONFIG_BLK_DEV_RAM if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then @@ -75,4 +83,5 @@ mainmenu_option next_comment comment 'Kernel hacking' bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ +bool 'GDB Stub kernel debug' CONFIG_DEBUG_KERNEL_WITH_GDB_STUB endmenu diff --git a/arch/sh/defconfig b/arch/sh/defconfig index bd830d4a954e..dcf006a15e07 100644 --- a/arch/sh/defconfig +++ b/arch/sh/defconfig @@ -10,48 +10,41 @@ # # Processor type and features # -CONFIG_CPU_SH3=y -# CONFIG_CPU_SH4 is not set -# CONFIG_LITTLE_ENDIAN is not set -CONFIG_MEMORY_START=0c000000 +# CONFIG_CPU_SH3 is not set +CONFIG_CPU_SH4=y +CONFIG_LITTLE_ENDIAN=y +CONFIG_MEMORY_START=08000000 # # Loadable module support # # CONFIG_MODULES is not set -# CONFIG_SERIAL is not set -CONFIG_SH3SCI_SERIAL=y -CONFIG_SERIAL_CONSOLE=y # -# Floppy, IDE, and other block devices +# General setup # # CONFIG_NET is not set -CONFIG_SYSVIPC=y +# CONFIG_SYSVIPC is not set # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_SYSCTL is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_INITRD=y -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set # -# Networking options +# Character devices # -# CONFIG_PACKET is not set -# CONFIG_NETLINK is not set -# CONFIG_FIREWALL is not set -# CONFIG_FILTER is not set -# CONFIG_UNIX is not set -# CONFIG_INET is not set +# CONFIG_SERIAL is not set +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SH_SCI_SERIAL is not set +CONFIG_SH_SCIF_SERIAL=y # -# +# Floppy, IDE, and other block devices # -# CONFIG_IPX is not set -# CONFIG_ATALK is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set # # Unix 98 PTY support @@ -66,8 +59,12 @@ CONFIG_BLK_DEV_INITRD=y # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set +# CONFIG_UDF_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set # CONFIG_HPFS_FS is not set @@ -77,17 +74,16 @@ CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set -# -# Network File Systems -# - # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -# CONFIG_SMD_DISKLABEL is not set -# CONFIG_SGI_DISKLABEL is not set +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_SUN_PARTITION is not set # CONFIG_NLS is not set # @@ -99,3 +95,4 @@ CONFIG_MSDOS_PARTITION=y # Kernel hacking # # CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_KERNEL_WITH_GDB_STUB=y diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 0a2abf8587c3..6cf0b319efe4 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -11,7 +11,7 @@ O_TARGET := kernel.o O_OBJS := process.o signal.o entry.o traps.o irq.o irq_onchip.o \ - ptrace.o setup.o time.o sys_sh.o test-img.o semaphore.o + ptrace.o setup.o time.o sys_sh.o semaphore.o OX_OBJS := sh_ksyms.o MX_OBJS := diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S index 7fca58b30cb0..ebec230b8a81 100644 --- a/arch/sh/kernel/entry.S +++ b/arch/sh/kernel/entry.S @@ -1,4 +1,4 @@ -/* $Id$ +/* $Id: entry.S,v 1.15 1999/10/17 01:32:52 gniibe Exp $ * * linux/arch/sh/entry.S * @@ -12,6 +12,7 @@ #include #include +#include ! NOTE: ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address @@ -28,18 +29,18 @@ * Stack layout in 'ret_from_syscall': * ptrace needs to have all regs on the stack. * if the order here is changed, it needs to be - * updated in process.c:copy_thread, signal.c:do_signal, - * ptrace.c and ptrace.h + * updated in ptrace.c and ptrace.h * - * syscall # + * syscall # + * ssr + * r15 = stack pointer * r0 * ... - * r15 + * r14 * gbr * mach * macl * pr - * ssr * spc * */ @@ -57,14 +58,23 @@ PF_TRACESYS = 0x20 ENOSYS = 38 -TRA = 0xffffffd0 -EXPEVT = 0xffffffd4 -INTEVT = 0xffffffd8 +#if defined(__sh3__) +TRA = 0xffffffd0 +EXPEVT = 0xffffffd4 +INTEVT = 0xffffffd8 +MMU_TEA = 0xfffffffc ! TLB Exception Address Register +#elif defined(__SH4__) +TRA = 0xff000020 +EXPEVT = 0xff000024 +INTEVT = 0xff000028 +MMU_TEA = 0xff00000c ! TLB Exception Address Register +#endif /* Offsets to the stack */ SYSCALL_NR = 0 -R0 = 4 -R15 = 64 +SR = 4 +SP = 8 +R0 = 12 #define k0 r0 #define k1 r1 @@ -99,20 +109,19 @@ R15 = 64 ! Although this could be written in assembly language (and it'd be faster), ! this first version depends *much* on C implementation. ! -MMU_TEA = 0xfffffffc ! TLB Exception Address Register -#define DO_FAULT(write) \ - mov #MMU_TEA,r0; \ - mov.l @r0,r6; \ - /* STI */ \ - mov.l 3f,r1; \ - stc sr,r0; \ - and r1,r0; \ - ldc r0,sr; \ - /* */ \ - mov r15,r4; \ - mov.l 2f,r0; \ - jmp @r0; \ +#define DO_FAULT(write) \ + mov.l 4f,r0; \ + mov.l @r0,r6; \ + /* STI */ \ + mov.l 3f,r1; \ + stc sr,r0; \ + and r1,r0; \ + ldc r0,sr; \ + /* */ \ + mov r15,r4; \ + mov.l 2f,r0; \ + jmp @r0; \ mov #write,r5; .balign 4 @@ -133,22 +142,65 @@ initial_page_write: .balign 4 2: .long SYMBOL_NAME(do_page_fault) 3: .long 0xefffffff ! BL=0 +4: .long MMU_TEA +#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB + .balign 4 + /* Unwind the stack and jmp to the debug entry */ +debug: + add #4,r15 ! skip syscall number + ldc.l @r15+,ssr + mov.l @r15+,r10 ! original stack + mov.l @r15+,r0 + mov.l @r15+,r1 + mov.l @r15+,r2 + mov.l @r15+,r3 + mov.l @r15+,r4 + mov.l @r15+,r5 + mov.l @r15+,r6 + mov.l @r15+,r7 + stc sr,r14 + mov.l 8f,r9 ! BL =1, RB=1 + or r9,r14 + ldc r14,sr ! here, change the register bank + mov r10,k0 + mov.l @r15+,r8 + mov.l @r15+,r9 + mov.l @r15+,r10 + mov.l @r15+,r11 + mov.l @r15+,r12 + mov.l @r15+,r13 + mov.l @r15+,r14 + ldc.l @r15+,gbr + lds.l @r15+,mach + lds.l @r15+,macl + lds.l @r15+,pr + ldc.l @r15+,spc + mov k0,r15 + ! + mov.l 9f,k0 + jmp @k0 + nop + .balign 4 +8: .long 0x300000f0 +9: .long 0xa0000100 +#endif .balign 4 -error: mov #-1,r0 +error: ! STI mov.l 2f,r1 stc sr,r0 and r1,r0 ldc r0,sr ! - mov.l r0,@r15 ! syscall nr = -1 mov.l 1f,r1 + mov #-1,r0 jmp @r1 - nop + mov.l r0,@r15 ! syscall nr = -1 .balign 4 1: .long SYMBOL_NAME(do_exception_error) +2: .long 0xefffffff ! BL=0 reschedule: mova SYMBOL_NAME(ret_from_syscall),r0 @@ -159,12 +211,13 @@ reschedule: 1: .long SYMBOL_NAME(schedule) badsys: mov #-ENOSYS,r0 - bra SYMBOL_NAME(ret_from_syscall) + rts ! go to ret_from_syscall.. mov.l r0,@(R0,r15) signal_return: ! We can reach here from an interrupt handler, ! so, we need to unblock interrupt. + /* STI */ mov.l 1f,r1 stc sr,r0 and r1,r0 @@ -185,15 +238,25 @@ signal_return: ! ENTRY(ret_from_fork) bra SYMBOL_NAME(ret_from_syscall) - add #4,r15 ! pop down bogus r0 + add #4,r15 ! pop down bogus r0 (see switch_to MACRO) ! ! The immediate value of "trapa" indicates the number of arguments ! placed on the stack. ! +! Note that TRA register contains the value = Imm x 4. +! system_call: - mov #TRA,r2 + mov.l 1f,r2 mov.l @r2,r8 + ! +#ifdef CONFIG_DEBUG_KERNEL_WITH_GDB_STUB + mov #0x20,r1 + extu.b r1,r1 + shll2 r1 + cmp/hs r1,r8 + bt debug +#endif ! STI mov.l 2f,r1 stc sr,r2 @@ -202,14 +265,15 @@ system_call: ! mov.l __n_sys,r1 cmp/ge r1,r0 - bt badsys + bt/s badsys + mov r0,r2 ! stc ksp,r1 ! mov.l __tsk_flags,r0 ! add r0,r1 ! mov.l @r1,r0 ! Is it trace? tst #PF_TRACESYS,r0 - bt 6f + bt 5f ! Trace system call mov #-ENOSYS,r1 mov.l r1,@(R0,r15) @@ -217,32 +281,36 @@ system_call: jsr @r1 nop mova 4f,r0 - bra 7f + bra 6f lds r0,pr ! -6: mova 1f,r0 +5: mova ret,r0 ! normal case lds r0,pr ! Build the stack frame if TRA > 0 -7: cmp/pl r8 + ! +6: mov r2,r3 + mov r8,r2 + cmp/pl r8 bf 9f - shll2 r8 ! x4 - mov #R15,r0 - mov.l @(r0,r15),r0 ! get original stack -8: add #-4,r8 - mov.l @(r0,r8),r1 + mov.l @(SP,r15),r0 ! get original stack +7: add #-4,r8 +8: mov.l @(r0,r8),r1 ! May cause address error exception.. mov.l r1,@-r15 cmp/pl r8 - bt 8b + bt 7b ! -9: mov.l @(SYSCALL_NR,r15),r0 +9: mov r3,r0 shll2 r0 ! x4 mov.l __sct,r1 add r1,r0 mov.l @r0,r1 jmp @r1 - nop + mov r2,r8 + + ! In case of trace .balign 4 -4: mov.l r0,@(R0,r15) ! save the return value +4: add r8,r15 ! pop off the arguments + mov.l r0,@(R0,r15) ! save the return value mov.l 3f,r1 mova SYMBOL_NAME(ret_from_syscall),r0 jmp @r1 @@ -250,11 +318,36 @@ system_call: .balign 4 3: .long SYMBOL_NAME(syscall_trace) 2: .long 0xefffffff ! BL=0 -1: mov.l r0,@(R0,r15) ! save the return value +1: .long TRA + + .section .fixup,"ax" +fixup_syscall_argerr: + rts + mov.l 1f,r0 +1: .long -22 ! -EINVAL +.previous + + .section __ex_table, "a" + .balign 4 + .long 8b,fixup_syscall_argerr +.previous + + +ENTRY(ret_from_irq) + mov.l @(SR,r15),r0 ! get original stack + shll r0 + shll r0 ! kernel space? + bt restore_all ! Yes, it's from kernel, go back soon + ! XXX: Is it better to run through bottom half? + ! In such a case, we should go "ret_from_syscall" instead + bra ret_with_reschedule + nop + +ret: add r8,r15 ! pop off the arguments + mov.l r0,@(R0,r15) ! save the return value /* fall through */ ENTRY(ret_from_syscall) -ENTRY(ret_from_irq) mov.l __bh_mask,r0 mov.l @r0,r1 mov.l __bh_active,r0 @@ -276,9 +369,10 @@ ret_with_reschedule: tst #0xff,r0 bf signal_return ! - .balign 4 restore_all: add #4,r15 ! skip syscall number + ldc.l @r15+,ssr + mov.l @r15+,r10 ! original stack mov.l @r15+,r0 mov.l @r15+,r1 mov.l @r15+,r2 @@ -291,6 +385,7 @@ restore_all: mov.l __blrb_flags,r9 ! BL =1, RB=1 or r9,r14 ldc r14,sr ! here, change the register bank + mov r10,k0 mov.l @r15+,r8 mov.l @r15+,r9 mov.l @r15+,r10 @@ -298,12 +393,10 @@ restore_all: mov.l @r15+,r12 mov.l @r15+,r13 mov.l @r15+,r14 - mov.l @r15+,k0 ldc.l @r15+,gbr lds.l @r15+,mach lds.l @r15+,macl lds.l @r15+,pr - ldc.l @r15+,ssr ldc.l @r15+,spc mov k0,r15 rte @@ -330,29 +423,32 @@ ENTRY(vbr_base) ! .balign 256,0,256 general_exception: - mov #EXPEVT,k2 + mov.l 1f,k2 mov.l 2f,k3 bra handle_exception mov.l @k2,k2 .balign 4 2: .long SYMBOL_NAME(ret_from_syscall) +1: .long EXPEVT ! ! .balign 1024,0,1024 tlb_miss: - mov #EXPEVT,k2 + mov.l 1f,k2 mov.l 3f,k3 bra handle_exception mov.l @k2,k2 ! .balign 512,0,512 interrupt: - mov #INTEVT,k2 + mov.l 2f,k2 mov.l 4f,k3 bra handle_exception mov.l @k2,k2 .balign 4 +1: .long EXPEVT +2: .long INTEVT 3: .long SYMBOL_NAME(ret_from_syscall) 4: .long SYMBOL_NAME(ret_from_irq) @@ -362,15 +458,13 @@ handle_exception: ! Using k0, k1 for scratch registers (r0_bank1, and r1_bank1), ! save all registers onto stack. ! - mov.l 2f,k1 stc ssr,k0 ! from kernel space? shll k0 ! Check MD bit (bit30) shll k0 bt/s 1f ! it's from kernel to kernel transition mov r15,k0 ! save original stack to k0 anyway mov kernel_sp,r15 ! change to kernel stack -1: stc.l spc,@-r15 ! save control registers - stc.l ssr,@-r15 +1: stc.l spc,@-r15 sts.l pr,@-r15 ! lds k3,pr ! Set the return address to pr @@ -378,9 +472,9 @@ handle_exception: sts.l macl,@-r15 sts.l mach,@-r15 stc.l gbr,@-r15 - mov.l k0,@-r15 ! save orignal stack, and general registers mov.l r14,@-r15 ! + mov.l 2f,k1 stc sr,r14 ! back to normal register bank, and and k1,r14 ! .. ldc r14,sr ! ...changed here. @@ -399,6 +493,8 @@ handle_exception: mov.l r2,@-r15 mov.l r1,@-r15 mov.l r0,@-r15 + stc.l r0_bank,@-r15 ! save orignal stack + stc.l ssr,@-r15 mov.l r0,@-r15 ! push r0 again (for syscall number) ! Then, dispatch to the handler, according to the excepiton code. stc k_ex_code,r1 @@ -413,10 +509,14 @@ handle_exception: 1: .long SYMBOL_NAME(exception_handling_table) 2: .long 0xdfffffff ! RB=0, BL=1 +none: + rts + nop + .data ENTRY(exception_handling_table) - .long 0 - .long 0 + .long none /* XXX: Avoid spurious interrupt */ + .long error .long tlb_miss_load .long tlb_miss_store .long initial_page_write @@ -424,13 +524,13 @@ ENTRY(exception_handling_table) .long tlb_protection_violation_store .long error ! address_error_load (filled by trap_init) .long error ! address_error_store (filled by trap_init) - .long 0 - .long 0 + .long error ! fpu_exception + .long error .long system_call ! Unconditional Trap .long error ! reserved_instruction (filled by trap_init) .long error ! illegal_slot_instruction (filled by trap_init) ENTRY(nmi_slot) - .long error ! Not implemented yet + .long none ! Not implemented yet ENTRY(user_break_point_trap) .long error ! Not implemented yet ENTRY(interrupt_table) @@ -450,7 +550,7 @@ ENTRY(interrupt_table) .long SYMBOL_NAME(do_IRQ) ! 1100 .long SYMBOL_NAME(do_IRQ) ! 1101 .long SYMBOL_NAME(do_IRQ) ! 1110 - .long 0 + .long error ! Internal hardware .long SYMBOL_NAME(do_IRQ) ! TMU0 tuni0 .long SYMBOL_NAME(do_IRQ) ! TMU1 tuni1 @@ -468,14 +568,24 @@ ENTRY(interrupt_table) .long SYMBOL_NAME(do_IRQ) ! rovi .long SYMBOL_NAME(do_IRQ) .long SYMBOL_NAME(do_IRQ) + .long SYMBOL_NAME(do_IRQ) ! Hitachi UDI + .long SYMBOL_NAME(do_IRQ) ! GPIO + .long SYMBOL_NAME(do_IRQ) ! DMAC dmte0 + .long SYMBOL_NAME(do_IRQ) ! dmte1 + .long SYMBOL_NAME(do_IRQ) ! dmte2 + .long SYMBOL_NAME(do_IRQ) ! dmte3 + .long SYMBOL_NAME(do_IRQ) ! dmae .long SYMBOL_NAME(do_IRQ) - .long SYMBOL_NAME(do_IRQ) - .long SYMBOL_NAME(do_IRQ) - .long SYMBOL_NAME(do_IRQ) - .long SYMBOL_NAME(do_IRQ) - .long SYMBOL_NAME(do_IRQ) - .long SYMBOL_NAME(do_IRQ) - .long SYMBOL_NAME(do_IRQ) + .long SYMBOL_NAME(do_IRQ) ! SCIF eri + .long SYMBOL_NAME(do_IRQ) ! rxi + .long SYMBOL_NAME(do_IRQ) ! bri + .long SYMBOL_NAME(do_IRQ) ! txi + .long error + .long error + .long error + .long error + .long error ! fpu + .long error ! fpu ENTRY(sys_call_table) .long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/ @@ -568,7 +678,7 @@ ENTRY(sys_call_table) .long SYMBOL_NAME(sys_swapon) .long SYMBOL_NAME(sys_reboot) .long SYMBOL_NAME(old_readdir) - .long SYMBOL_NAME(sys_ni_syscall) /* old_mmap */ /* 90 */ + .long SYMBOL_NAME(sys_mmap) /* 90 */ .long SYMBOL_NAME(sys_munmap) .long SYMBOL_NAME(sys_truncate) .long SYMBOL_NAME(sys_ftruncate) diff --git a/arch/sh/kernel/head.S b/arch/sh/kernel/head.S index ed466ba38921..eda9e347d1c2 100644 --- a/arch/sh/kernel/head.S +++ b/arch/sh/kernel/head.S @@ -1,8 +1,8 @@ -/* $Id$ +/* $Id: head.S,v 1.6 1999/10/05 12:34:16 gniibe Exp $ * * arch/sh/kernel/head.S * - * Copyright (C) 1999 Niibe Yutaka + * Copyright (C) 1999 Niibe Yutaka & Kaz Kojima * * 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 @@ -10,60 +10,74 @@ * * Head.S contains the SH exception handlers and startup code. */ -#include -#include #include -#include -#include -#ifdef CONFIG_CPU_SH3 -/* Following values are assumed to be as small as immediate. */ -#define CCR 0xffffffec /* Address of Cache Control Register */ -#define CACHE_INIT 0x00000009 /* 8k-byte cache, flush, enable */ -#elif CONFIG_CPU_SH4 -/* Should fill here. */ -#endif + .section .empty_zero_page, "aw" +ENTRY(empty_zero_page) + .long 1 /* MOUNT_ROOT_RDONLY */ + .long 0 /* RAMDISK_FLAGS */ + .long 0x0200 /* ORIG_ROOT_DEV */ + .long 1 /* LOADER_TYPE */ + .long 0x88400000 /* INITRD_START */ + .long 0x00400000 /* INITRD_SIZE */ + .long 0x89000000 /* MEMORY_END */ + .long 0 + .text + .balign 4096,0,4096 +/* + * Condition at the entry of _stext: + * + * BSC has already been initialized. + * INTC may or may not be initialized. + * VBR may or may not be initialized. + * MMU may or may not be initialized. + * Cache may or may not be initialized. + * Hardware (including on-chip modules) may or may not be initialized. + * + * The register R4&R5 holds the address of the parameter block, which has + * command-line data, etc. + * + */ ENTRY(_stext) - ! Switch to register bank 0 - stc sr,r1 ! - mov.l 1f,r0 ! RB=0, BL=1 - and r1,r0 - ldc r0,sr - ! Enable cache -#ifdef CONFIG_CPU_SH3 - mov #CCR,r1 - mov.l @r1,r0 - cmp/eq #1,r0 ! If it's enabled already, don't flush it - bt/s 8f - mov #CACHE_INIT,r0 - mov.l r0,@r1 -#elif CONFIG_CPU_SH4 - ! Should fill here. +#if defined(__SH4__) + ! Initialize FPSCR + /* GCC (as of 2.95.1) assumes FPU with double precision mode. */ + mov.l 7f,r0 + lds r0,fpscr #endif -8: + ! Initialize Status Register + mov.l 1f,r0 ! MD=1, RB=0, BL=1 + ldc r0,sr ! mov.l 2f,r0 mov r0,r15 ! Set initial r15 (stack pointer) ldc r0,r4_bank ! and stack base + ! + ! Enable cache + mov.l 6f,r0 + jsr @r0 + nop ! Clear BSS area mov.l 3f,r1 + add #4,r1 mov.l 4f,r2 mov #0,r0 -9: mov.l r0,@r1 - cmp/hs r2,r1 - bf/s 9b - add #4,r1 +9: cmp/hs r2,r1 + bf/s 9b ! while (r1 < r2) + mov.l r0,@-r2 ! Start kernel mov.l 5f,r0 jmp @r0 nop .balign 4 -1: .long 0xdfffffff ! RB=0, BL=1 -2: .long SYMBOL_NAME(stack) -3: .long SYMBOL_NAME(__bss_start) -4: .long SYMBOL_NAME(_end) -5: .long SYMBOL_NAME(start_kernel) - -.data +1: .long 0x50000000 ! MD=1, RB=0, BL=1 +2: .long SYMBOL_NAME(stack) +3: .long SYMBOL_NAME(__bss_start) +4: .long SYMBOL_NAME(_end) +5: .long SYMBOL_NAME(start_kernel) +6: .long SYMBOL_NAME(cache_init) +#if defined(__SH4__) +7: .long 0x00080000 +#endif diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index f75af500369a..e87972c737ca 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -1,10 +1,11 @@ -/* +/* $Id: irq.c,v 1.4 1999/10/11 13:12:14 gniibe Exp $ + * * linux/arch/sh/kernel/irq.c * * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar * * - * SuperH version: Copyright (C) 1999 Niibe Yutaka + * SuperH version: Copyright (C) 1999 Niibe Yutaka */ /* @@ -48,7 +49,7 @@ spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED; /* * Controller mappings for all interrupt sources: */ -irq_desc_t irq_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = { 0, &no_irq_type, }}; +irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { [0 ... NR_IRQS-1] = { 0, &no_irq_type, }}; /* * Special irq handlers. @@ -56,6 +57,37 @@ irq_desc_t irq_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = { 0, &no_irq_type, }}; void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } +/* + * Generic no controller code + */ + +static void enable_none(unsigned int irq) { } +static unsigned int startup_none(unsigned int irq) { return 0; } +static void disable_none(unsigned int irq) { } +static void ack_none(unsigned int irq) +{ +/* + * 'what should we do if we get a hw irq event on an illegal vector'. + * each architecture has to answer this themselves, it doesnt deserve + * a generic callback i think. + */ + printk("unexpected IRQ trap at vector %02x\n", irq); +} + +/* startup is the same as "enable", shutdown is same as "disable" */ +#define shutdown_none disable_none +#define end_none enable_none + +struct hw_interrupt_type no_irq_type = { + "none", + startup_none, + shutdown_none, + enable_none, + disable_none, + ack_none, + end_none +}; + /* * Generic, controller-independent functions: */ @@ -203,6 +235,8 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, struct irqaction * action; unsigned int status; + regs.syscall_nr = -1; /* It's not system call */ + /* Get IRQ number */ asm volatile("stc r2_bank,%0\n\t" "shlr2 %0\n\t" @@ -257,7 +291,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, for (;;) { handle_IRQ_event(irq, ®s, action); spin_lock(&irq_controller_lock); - + if (!(desc->status & IRQ_PENDING)) break; desc->status &= ~IRQ_PENDING; @@ -265,7 +299,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, } desc->status &= ~IRQ_INPROGRESS; if (!(desc->status & IRQ_DISABLED)){ - irq_desc[irq].handler->end(irq); + irq_desc[irq].handler->end(irq); } spin_unlock(&irq_controller_lock); @@ -334,16 +368,22 @@ void free_irq(unsigned int irq, void *dev_id) /* Found it - now remove it from the list of entries */ *pp = action->next; - if (irq_desc[irq].action) - break; - irq_desc[irq].status |= IRQ_DISABLED; - irq_desc[irq].handler->shutdown(irq); - break; + if (!irq_desc[irq].action) { + irq_desc[irq].status |= IRQ_DISABLED; + irq_desc[irq].handler->shutdown(irq); + } + spin_unlock_irqrestore(&irq_controller_lock,flags); + + /* Wait to make sure it's not being used on another CPU */ + while (irq_desc[irq].status & IRQ_INPROGRESS) + barrier(); + kfree(action); + return; } printk("Trying to free free IRQ%d\n",irq); - break; + spin_unlock_irqrestore(&irq_controller_lock,flags); + return; } - spin_unlock_irqrestore(&irq_controller_lock,flags); } /* diff --git a/arch/sh/kernel/irq_onchip.c b/arch/sh/kernel/irq_onchip.c index 2eae049e5bec..fbce65fcb080 100644 --- a/arch/sh/kernel/irq_onchip.c +++ b/arch/sh/kernel/irq_onchip.c @@ -1,4 +1,5 @@ -/* +/* $Id: irq_onchip.c,v 1.3 1999/10/11 13:12:19 gniibe Exp $ + * * linux/arch/sh/kernel/irq_onchip.c * * Copyright (C) 1999 Niibe Yutaka @@ -31,32 +32,6 @@ #include - -/* - * SH (non-)specific no controller code - */ - -static void enable_none(unsigned int irq) { } -static unsigned int startup_none(unsigned int irq) { return 0; } -static void disable_none(unsigned int irq) { } -static void ack_none(unsigned int irq) -{ -} - -/* startup is the same as "enable", shutdown is same as "disable" */ -#define shutdown_none disable_none -#define end_none enable_none - -struct hw_interrupt_type no_irq_type = { - "none", - startup_none, - shutdown_none, - enable_none, - disable_none, - ack_none, - end_none -}; - struct ipr_data { int offset; int priority; @@ -104,22 +79,25 @@ static struct hw_interrupt_type onChip_irq_type = { * IPRC 15-12 11-8 7-4 3-0 * */ +#if defined(__sh3__) #define INTC_IPR 0xfffffee2UL /* Word access */ +#define INTC_SIZE 0x2 +#elif defined(__SH4__) +#define INTC_IPR 0xffd00004UL /* Word access */ +#define INTC_SIZE 0x4 +#endif void disable_onChip_irq(unsigned int irq) { /* Set priority in IPR to 0 */ int offset = ipr_data[irq-TIMER_IRQ].offset; - unsigned long intc_ipr_address = INTC_IPR + offset/16; + unsigned long intc_ipr_address = INTC_IPR + (offset/16*INTC_SIZE); unsigned short mask = 0xffff ^ (0xf << (offset%16)); - unsigned long __dummy; - - asm volatile("mov.w @%1,%0\n\t" - "and %2,%0\n\t" - "mov.w %0,@%1" - : "=&z" (__dummy) - : "r" (intc_ipr_address), "r" (mask) - : "memory" ); + unsigned long val; + + val = ctrl_inw(intc_ipr_address); + val &= mask; + ctrl_outw(val, intc_ipr_address); } static void enable_onChip_irq(unsigned int irq) @@ -127,16 +105,13 @@ static void enable_onChip_irq(unsigned int irq) /* Set priority in IPR back to original value */ int offset = ipr_data[irq-TIMER_IRQ].offset; int priority = ipr_data[irq-TIMER_IRQ].priority; - unsigned long intc_ipr_address = INTC_IPR + offset/16; + unsigned long intc_ipr_address = INTC_IPR + (offset/16*INTC_SIZE); unsigned short value = (priority << (offset%16)); - unsigned long __dummy; - - asm volatile("mov.w @%1,%0\n\t" - "or %2,%0\n\t" - "mov.w %0,@%1" - : "=&z" (__dummy) - : "r" (intc_ipr_address), "r" (value) - : "memory" ); + unsigned long val; + + val = ctrl_inw(intc_ipr_address); + val |= value; + ctrl_outw(val, intc_ipr_address); } void make_onChip_irq(unsigned int irq) @@ -149,13 +124,11 @@ void make_onChip_irq(unsigned int irq) static void mask_and_ack_onChip(unsigned int irq) { disable_onChip_irq(irq); - sti(); } static void end_onChip_irq(unsigned int irq) { enable_onChip_irq(irq); - cli(); } void __init init_IRQ(void) diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 744da694b6ed..9d90c0133181 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -1,9 +1,10 @@ -/* +/* $Id: process.c,v 1.7 1999/09/23 00:05:41 gniibe Exp $ + * * linux/arch/sh/kernel/process.c * * Copyright (C) 1995 Linus Torvalds * - * SuperH version: Copyright (C) 1999 Niibe Yutaka + * SuperH version: Copyright (C) 1999 Niibe Yutaka & Kaz Kojima */ /* @@ -41,6 +42,10 @@ #include +#if defined(__SH4__) +struct task_struct *last_task_used_math = NULL; +#endif + static int hlt_counter=0; #define HARD_IDLE_TIMEOUT (HZ / 3) @@ -92,22 +97,21 @@ void machine_power_off(void) void show_regs(struct pt_regs * regs) { printk("\n"); - printk("PC: [<%08lx>]", regs->pc); - printk(" SP: %08lx", regs->u_regs[UREG_SP]); - printk(" SR: %08lx\n", regs->sr); - printk("R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", - regs->u_regs[0],regs->u_regs[1], - regs->u_regs[2],regs->u_regs[3]); - printk("R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n", - regs->u_regs[4],regs->u_regs[5], - regs->u_regs[6],regs->u_regs[7]); - printk("R8 : %08lx R9 : %08lx R10: %08lx R11: %08lx\n", - regs->u_regs[8],regs->u_regs[9], - regs->u_regs[10],regs->u_regs[11]); - printk("R12: %08lx R13: %08lx R14: %08lx\n", - regs->u_regs[12],regs->u_regs[13], - regs->u_regs[14]); - printk("MACH: %08lx MACL: %08lx GBR: %08lx PR: %08lx", + printk("PC : %08lx SP : %08lx SR : %08lx TEA : %08lx\n", + regs->pc, regs->sp, regs->sr, ctrl_inl(MMU_TEA)); + printk("R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", + regs->regs[0],regs->regs[1], + regs->regs[2],regs->regs[3]); + printk("R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n", + regs->regs[4],regs->regs[5], + regs->regs[6],regs->regs[7]); + printk("R8 : %08lx R9 : %08lx R10 : %08lx R11 : %08lx\n", + regs->regs[8],regs->regs[9], + regs->regs[10],regs->regs[11]); + printk("R12 : %08lx R13 : %08lx R14 : %08lx\n", + regs->regs[12],regs->regs[13], + regs->regs[14]); + printk("MACH: %08lx MACL: %08lx GBR : %08lx PR : %08lx\n", regs->mach, regs->macl, regs->gbr, regs->pr); } @@ -163,13 +167,35 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) */ void exit_thread(void) { +#if defined(__sh3__) /* nothing to do ... */ +#elif defined(__SH4__) +#if 0 /* for the time being... */ + /* Forget lazy fpu state */ + if (last_task_used_math == current) { + set_status_register (SR_FD, 0); + write_system_register (fpscr, FPSCR_PR); + last_task_used_math = NULL; + } +#endif +#endif } void flush_thread(void) { +#if defined(__sh3__) /* do nothing */ /* Possibly, set clear debug registers */ +#elif defined(__SH4__) +#if 0 /* for the time being... */ + /* Forget lazy fpu state */ + if (last_task_used_math == current) { + set_status_register (SR_FD, 0); + write_system_register (fpscr, FPSCR_PR); + last_task_used_math = NULL; + } +#endif +#endif } void release_thread(struct task_struct *dead_task) @@ -180,6 +206,15 @@ void release_thread(struct task_struct *dead_task) /* Fill in the fpu structure for a core dump.. */ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r) { +#if defined(__SH4__) +#if 0 /* for the time being... */ + /* We store the FPU info in the task->thread area. */ + if (! (regs->sr & SR_FD)) { + memcpy (r, ¤t->thread.fpu, sizeof (*r)); + return 1; + } +#endif +#endif return 0; /* Task didn't use the fpu at all. */ } @@ -191,14 +226,26 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, struct pt_regs *childregs; childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long) p)) - 1; - *childregs = *regs; + +#if defined(__SH4__) +#if 0 /* for the time being... */ + if (last_task_used_math == current) { + set_status_register (SR_FD, 0); + sh4_save_fp (p); + } + /* New tasks loose permission to use the fpu. This accelerates context + switching for most programs since they don't use the fpu. */ + p->thread.sr = (read_control_register (sr) &~ SR_MD) | SR_FD; + childregs->sr |= SR_FD; +#endif +#endif if (user_mode(regs)) { - childregs->u_regs[UREG_SP] = usp; + childregs->sp = usp; } else { - childregs->u_regs[UREG_SP] = (unsigned long)p+2*PAGE_SIZE; + childregs->sp = (unsigned long)p+2*PAGE_SIZE; } - childregs->u_regs[0] = 0; /* Set return value for child */ + childregs->regs[0] = 0; /* Set return value for child */ p->thread.sp = (unsigned long) childregs; p->thread.pc = (unsigned long) ret_from_fork; @@ -215,18 +262,22 @@ void dump_thread(struct pt_regs * regs, struct user * dump) { /* changed the size calculations - should hopefully work better. lbt */ dump->magic = CMAGIC; - dump->start_code = 0; - dump->start_stack = regs->u_regs[UREG_SP] & ~(PAGE_SIZE - 1); - dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT; - dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT; - dump->u_dsize -= dump->u_tsize; - dump->u_ssize = 0; + dump->start_code = current->mm->start_code; + dump->start_data = current->mm->start_data; + dump->start_stack = regs->sp & ~(PAGE_SIZE - 1); + dump->u_tsize = (current->mm->end_code - dump->start_code) >> PAGE_SHIFT; + dump->u_dsize = (current->mm->brk + (PAGE_SIZE-1) - dump->start_data) >> PAGE_SHIFT; + dump->u_ssize = (current->mm->start_stack - dump->start_stack + + PAGE_SIZE - 1) >> PAGE_SHIFT; /* Debug registers will come here. */ - if (dump->start_stack < TASK_SIZE) - dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT; - dump->regs = *regs; + +#if 0 /* defined(__SH4__) */ + /* FPU */ + memcpy (&dump->regs[EF_SIZE/4], ¤t->thread.fpu, + sizeof (current->thread.fpu)); +#endif } /* @@ -248,7 +299,7 @@ asmlinkage int sys_fork(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs regs) { - return do_fork(SIGCHLD, regs.u_regs[UREG_SP], ®s); + return do_fork(SIGCHLD, regs.sp, ®s); } asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, @@ -256,7 +307,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct pt_regs regs) { if (!newsp) - newsp = regs.u_regs[UREG_SP]; + newsp = regs.sp; return do_fork(clone_flags, newsp, ®s); } @@ -274,8 +325,7 @@ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs regs) { - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, - regs.u_regs[UREG_SP], ®s); + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.sp, ®s); } /* diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 6714fd96d6ab..3053656e7315 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -1,4 +1,5 @@ -/* +/* $Id: setup.c,v 1.4 1999/10/17 02:49:24 gniibe Exp $ + * * linux/arch/sh/kernel/setup.c * * Copyright (C) 1999 Niibe Yutaka @@ -29,6 +30,7 @@ #endif #include #include +#include #include #include #include @@ -38,8 +40,7 @@ * Machine setup.. */ -struct sh_cpuinfo boot_cpu_data = { 0, 0, 0, 0, }; -extern int _text, _etext, _edata, _end, _stext, __bss_start; +struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 0, 0, 0, }; #ifdef CONFIG_BLK_DEV_RAM extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ @@ -48,13 +49,31 @@ extern int rd_image_start; /* starting block # of image */ #endif extern int root_mountflags; +extern int _text, _etext, _edata, _end; + +/* + * This is set up by the setup-routine at boot-time + */ +#define PARAM ((unsigned char *)empty_zero_page) + +#define MOUNT_ROOT_RDONLY (*(unsigned long *) (PARAM+0x000)) +#define RAMDISK_FLAGS (*(unsigned long *) (PARAM+0x004)) +#define ORIG_ROOT_DEV (*(unsigned long *) (PARAM+0x008)) +#define LOADER_TYPE (*(unsigned long *) (PARAM+0x00c)) +#define INITRD_START (*(unsigned long *) (PARAM+0x010)) +#define INITRD_SIZE (*(unsigned long *) (PARAM+0x014)) +#define MEMORY_END (*(unsigned long *) (PARAM+0x018)) +/* ... */ +#define COMMAND_LINE ((char *) (PARAM+0x100)) +#define COMMAND_LINE_SIZE 256 + +#define RAMDISK_IMAGE_START_MASK 0x07FF +#define RAMDISK_PROMPT_FLAG 0x8000 +#define RAMDISK_LOAD_FLAG 0x4000 -#define COMMAND_LINE_SIZE 1024 static char command_line[COMMAND_LINE_SIZE] = { 0, }; char saved_command_line[COMMAND_LINE_SIZE]; -extern unsigned char *root_fs_image; - struct resource standard_io_resources[] = { { "dma1", 0x00, 0x1f }, { "pic1", 0x20, 0x3f }, @@ -68,7 +87,6 @@ struct resource standard_io_resources[] = { #define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource)) - /* System RAM - interrupted by the 640kB-1M hole */ #define code_resource (ram_resources[3]) #define data_resource (ram_resources[4]) @@ -87,17 +105,26 @@ static struct resource rom_resources[MAXROMS] = { { "Video ROM", 0xc0000, 0xc7fff } }; - void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p) { - *cmdline_p = command_line; - *memory_start_p = (unsigned long) &_end; - *memory_end_p = 0x8c400000; /* For my board. */ - ram_resources[1].end = *memory_end_p-1; + unsigned long memory_start, memory_end; + + ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV); + +#ifdef CONFIG_BLK_DEV_RAM + rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; + rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); + rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); +#endif + if (!MOUNT_ROOT_RDONLY) + root_mountflags &= ~MS_RDONLY; + + memory_start = (unsigned long) &_end; + memory_end = MEMORY_END; - init_mm.start_code = (unsigned long)&_stext; + 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; @@ -107,51 +134,25 @@ void __init setup_arch(char **cmdline_p, data_resource.start = virt_to_bus(&_etext); data_resource.end = virt_to_bus(&_edata)-1; - ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0); + /* Save unparsed command line copy for /proc/cmdline */ + memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); + saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; - initrd_below_start_ok = 1; - initrd_start = (long)&root_fs_image; - initrd_end = (long)&__bss_start; - mount_initrd = 1; + memcpy(command_line, COMMAND_LINE, COMMAND_LINE_SIZE); + command_line[COMMAND_LINE_SIZE-1] = '\0'; + /* Not support "mem=XXX[kKmM]" command line option. */ + *cmdline_p = command_line; -#if 0 - /* Request the standard RAM and ROM resources - they eat up PCI memory space */ - request_resource(&iomem_resource, ram_resources+0); - request_resource(&iomem_resource, ram_resources+1); - request_resource(&iomem_resource, ram_resources+2); - request_resource(ram_resources+1, &code_resource); - request_resource(ram_resources+1, &data_resource); -#endif - -#if 0 - for (i = 0; i < STANDARD_IO_RESOURCES; i++) - request_resource(&ioport_resource, standard_io_resources+i); -#endif - -#if 0 - rd_image_start = (long)root_fs_image; - rd_prompt = 0; - rd_doload = 1; -#endif + memory_end &= PAGE_MASK; + ram_resources[1].end = memory_end-1; -#if 0 - ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV); - -#ifdef CONFIG_BLK_DEV_RAM - rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; - rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); - rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); -#endif - - if (!MOUNT_ROOT_RDONLY) - root_mountflags &= ~MS_RDONLY; -#endif + *memory_start_p = memory_start; + *memory_end_p = memory_end; #ifdef CONFIG_BLK_DEV_INITRD -#if 0 if (LOADER_TYPE) { - initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET : 0; + initrd_start = INITRD_START ? INITRD_START : 0; initrd_end = initrd_start+INITRD_SIZE; if (initrd_end > memory_end) { printk("initrd extends beyond end of memory " @@ -162,6 +163,29 @@ void __init setup_arch(char **cmdline_p, } #endif +#if 0 + /* + * Request the standard RAM and ROM resources - + * they eat up PCI memory space + */ + request_resource(&iomem_resource, ram_resources+0); + request_resource(&iomem_resource, ram_resources+1); + request_resource(&iomem_resource, ram_resources+2); + request_resource(ram_resources+1, &code_resource); + request_resource(ram_resources+1, &data_resource); + probe_roms(); + + /* request I/O space for devices used on all i[345]86 PCs */ + for (i = 0; i < STANDARD_IO_RESOURCES; i++) + request_resource(&ioport_resource, standard_io_resources+i); +#endif + +#ifdef CONFIG_VT +#if defined(CONFIG_VGA_CONSOLE) + conswitchp = &vga_con; +#elif defined(CONFIG_DUMMY_CONSOLE) + conswitchp = &dummy_con; +#endif #endif } @@ -173,12 +197,12 @@ int get_cpuinfo(char *buffer) { char *p = buffer; -#ifdef CONFIG_CPU_SH3 - p += sprintf(p,"cpu family\t: SH3\n" +#if defined(__sh3__) + p += sprintf(p,"cpu family\t: SH-3\n" "cache size\t: 8K-byte\n"); -#elif CONFIG_CPU_SH4 - p += sprintf(p,"cpu family\t: SH4\n" - "cache size\t: ??K-byte\n"); +#elif defined(__SH4__) + p += sprintf(p,"cpu family\t: SH-4\n" + "cache size\t: 8K-byte/16K-byte\n"); #endif p += sprintf(p, "bogomips\t: %lu.%02lu\n\n", (loops_per_sec+2500)/500000, diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c index 66fa36c85613..8583afff15a8 100644 --- a/arch/sh/kernel/signal.c +++ b/arch/sh/kernel/signal.c @@ -1,4 +1,5 @@ -/* +/* $Id: signal.c,v 1.10 1999/09/27 23:25:44 gniibe Exp $ + * * linux/arch/sh/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -9,8 +10,6 @@ * */ -#include - #include #include #include @@ -24,6 +23,7 @@ #include #include #include +#include #define DEBUG_SIG 0 @@ -50,7 +50,7 @@ sys_sigsuspend(old_sigset_t mask, recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); - regs.u_regs[0] = -EINTR; + regs.regs[0] = -EINTR; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); @@ -80,7 +80,7 @@ sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); - regs.u_regs[0] = -EINTR; + regs.regs[0] = -EINTR; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); @@ -126,7 +126,7 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss, unsigned long r6, unsigned long r7, struct pt_regs regs) { - return do_sigaltstack(uss, uoss, regs.u_regs[UREG_SP]); + return do_sigaltstack(uss, uoss, regs.sp); } @@ -137,7 +137,7 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct sigframe { struct sigcontext sc; - /* FPU should come here: SH-3 has no FPU */ + /* FPU data should come here: SH-3 has no FPU */ unsigned long extramask[_NSIG_WORDS-1]; char retcode[4]; }; @@ -158,22 +158,22 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *r0_p) { unsigned int err = 0; -#define COPY(x) err |= __get_user(regs->x, &sc->x) - COPY(u_regs[1]); - COPY(u_regs[2]); COPY(u_regs[3]); - COPY(u_regs[4]); COPY(u_regs[5]); - COPY(u_regs[6]); COPY(u_regs[7]); - COPY(u_regs[8]); COPY(u_regs[9]); - COPY(u_regs[10]); COPY(u_regs[11]); - COPY(u_regs[12]); COPY(u_regs[13]); - COPY(u_regs[14]); COPY(u_regs[15]); - COPY(gbr); COPY(mach); - COPY(macl); COPY(pr); - COPY(sr); COPY(pc); +#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x) + COPY(regs[1]); + COPY(regs[2]); COPY(regs[3]); + COPY(regs[4]); COPY(regs[5]); + COPY(regs[6]); COPY(regs[7]); + COPY(regs[8]); COPY(regs[9]); + COPY(regs[10]); COPY(regs[11]); + COPY(regs[12]); COPY(regs[13]); + COPY(regs[14]); COPY(sp); + COPY(gbr); COPY(mach); + COPY(macl); COPY(pr); + COPY(sr); COPY(pc); #undef COPY regs->syscall_nr = -1; /* disable syscall checks */ - err |= __get_user(*r0_p, &sc->u_regs[0]); + err |= __get_user(*r0_p, &sc->sc_regs[0]); return err; } @@ -182,7 +182,7 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs regs) { - struct sigframe *frame = (struct sigframe *)regs.u_regs[UREG_SP]; + struct sigframe *frame = (struct sigframe *)regs.sp; sigset_t set; int r0; @@ -213,7 +213,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs regs) { - struct rt_sigframe *frame = (struct rt_sigframe *)regs.u_regs[UREG_SP]; + struct rt_sigframe *frame = (struct rt_sigframe *)regs.sp; sigset_t set; stack_t st; int r0; @@ -236,7 +236,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5, goto badframe; /* It is more difficult to avoid calling this function than to call it and ignore errors. */ - do_sigaltstack(&st, NULL, regs.u_regs[UREG_SP]); + do_sigaltstack(&st, NULL, regs.sp); return r0; @@ -255,18 +255,18 @@ setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, { int err = 0; -#define COPY(x) err |= __put_user(regs->x, &sc->x) - COPY(u_regs[0]); COPY(u_regs[1]); - COPY(u_regs[2]); COPY(u_regs[3]); - COPY(u_regs[4]); COPY(u_regs[5]); - COPY(u_regs[6]); COPY(u_regs[7]); - COPY(u_regs[8]); COPY(u_regs[9]); - COPY(u_regs[10]); COPY(u_regs[11]); - COPY(u_regs[12]); COPY(u_regs[13]); - COPY(u_regs[14]); COPY(u_regs[15]); - COPY(gbr); COPY(mach); - COPY(macl); COPY(pr); - COPY(sr); COPY(pc); +#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x) + COPY(regs[0]); COPY(regs[1]); + COPY(regs[2]); COPY(regs[3]); + COPY(regs[4]); COPY(regs[5]); + COPY(regs[6]); COPY(regs[7]); + COPY(regs[8]); COPY(regs[9]); + COPY(regs[10]); COPY(regs[11]); + COPY(regs[12]); COPY(regs[13]); + COPY(regs[14]); COPY(sp); + COPY(gbr); COPY(mach); + COPY(macl); COPY(pr); + COPY(sr); COPY(pc); #undef COPY /* non-iBCS2 extensions.. */ @@ -294,7 +294,7 @@ static void setup_frame(int sig, struct k_sigaction *ka, int err = 0; int signal; - frame = get_sigframe(ka, regs->u_regs[UREG_SP], sizeof(*frame)); + frame = get_sigframe(ka, regs->sp, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; @@ -318,8 +318,8 @@ static void setup_frame(int sig, struct k_sigaction *ka, regs->pr = (unsigned long) ka->sa.sa_restorer; } else { /* This is ; mov #__NR_sigreturn,r0 ; trapa #0 */ -#ifdef CONFIG_LITTLE_ENDIAN - unsigned long code = 0x00c300e0 | (__NR_sigreturn << 8); +#ifdef __LITTLE_ENDIAN__ + unsigned long code = 0xc300e000 | (__NR_sigreturn); #else unsigned long code = 0xe000c300 | (__NR_sigreturn << 16); #endif @@ -332,8 +332,8 @@ static void setup_frame(int sig, struct k_sigaction *ka, goto give_sigsegv; /* Set up registers for signal handler */ - regs->u_regs[UREG_SP] = (unsigned long) frame; - regs->u_regs[4] = signal; /* Arg for signal handler */ + regs->sp = (unsigned long) frame; + regs->regs[4] = signal; /* Arg for signal handler */ regs->pc = (unsigned long) ka->sa.sa_handler; set_fs(USER_DS); @@ -343,6 +343,7 @@ static void setup_frame(int sig, struct k_sigaction *ka, current->comm, current->pid, frame, regs->pc, regs->pr); #endif + flush_icache_range(regs->pr, regs->pr+4); return; give_sigsegv: @@ -358,7 +359,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, int err = 0; int signal; - frame = get_sigframe(ka, regs->u_regs[UREG_SP], sizeof(*frame)); + frame = get_sigframe(ka, regs->sp, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; @@ -376,9 +377,9 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); - err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->u_regs[UREG_SP]), - &frame->uc.uc_stack.ss_flags); + err |= __put_user((void *)current->sas_ss_sp, + &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); @@ -390,8 +391,8 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs->pr = (unsigned long) ka->sa.sa_restorer; } else { /* This is ; mov #__NR_sigreturn,r0 ; trapa #0 */ -#ifdef CONFIG_LITTLE_ENDIAN - unsigned long code = 0x00c300e0 | (__NR_sigreturn << 8); +#ifdef __LITTLE_ENDIAN__ + unsigned long code = 0xc300e000 | (__NR_sigreturn); #else unsigned long code = 0xe000c300 | (__NR_sigreturn << 16); #endif @@ -404,8 +405,8 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, goto give_sigsegv; /* Set up registers for signal handler */ - regs->u_regs[UREG_SP] = (unsigned long) frame; - regs->u_regs[4] = signal; /* Arg for signal handler */ + regs->sp = (unsigned long) frame; + regs->regs[4] = signal; /* Arg for signal handler */ regs->pc = (unsigned long) ka->sa.sa_handler; set_fs(USER_DS); @@ -415,6 +416,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, current->comm, current->pid, frame, regs->pc, regs->pr); #endif + flush_icache_range(regs->pr, regs->pr+4); return; give_sigsegv: @@ -434,19 +436,19 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, /* Are we from a system call? */ if (regs->syscall_nr >= 0) { /* If so, check system call restarting.. */ - switch (regs->u_regs[0]) { + switch (regs->regs[0]) { case -ERESTARTNOHAND: - regs->u_regs[0] = -EINTR; + regs->regs[0] = -EINTR; break; case -ERESTARTSYS: if (!(ka->sa.sa_flags & SA_RESTART)) { - regs->u_regs[0] = -EINTR; + regs->regs[0] = -EINTR; break; } /* fallthrough */ case -ERESTARTNOINTR: - regs->u_regs[0] = regs->syscall_nr; + regs->regs[0] = regs->syscall_nr; regs->pc -= 2; } } @@ -577,7 +579,6 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) /* NOTREACHED */ } } - /* Whee! Actually deliver the signal. */ handle_signal(signr, ka, &info, oldset, regs); return 1; @@ -586,10 +587,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) /* Did we come from a system call? */ if (regs->syscall_nr >= 0) { /* Restart the system call - no handlers present */ - if (regs->u_regs[0] == -ERESTARTNOHAND || - regs->u_regs[0] == -ERESTARTSYS || - regs->u_regs[0] == -ERESTARTNOINTR) { - regs->u_regs[0] = regs->syscall_nr; + if (regs->regs[0] == -ERESTARTNOHAND || + regs->regs[0] == -ERESTARTSYS || + regs->regs[0] == -ERESTARTNOINTR) { + regs->regs[0] = regs->syscall_nr; regs->pc -= 2; } } diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c index 6999cff81fa2..a485f10a388c 100644 --- a/arch/sh/kernel/sys_sh.c +++ b/arch/sh/kernel/sys_sh.c @@ -1,9 +1,11 @@ /* - * linux/arch/i386/kernel/sys_i386.c + * linux/arch/sh/kernel/sys_sh.c * * This file contains various random system calls that - * have a non-standard calling sequence on the Linux/i386 + * have a non-standard calling sequence on the Linux/SuperH * platform. + * + * Taken from i386 version. */ #include @@ -41,66 +43,32 @@ asmlinkage int sys_pipe(unsigned long * fildes) return error; } -/* - * Perform the select(nd, in, out, ex, tv) and mmap() system - * calls. Linux/i386 didn't use to be able to handle more than - * 4 system call parameters, so these system calls used a memory - * block for parameter passing.. - */ - -struct mmap_arg_struct { - unsigned long addr; - unsigned long len; - unsigned long prot; - unsigned long flags; - unsigned long fd; - unsigned long offset; -}; - -asmlinkage int old_mmap(struct mmap_arg_struct *arg) +asmlinkage unsigned long +sys_mmap(int fd, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flags, unsigned long off) { int error = -EFAULT; - struct file * file = NULL; - struct mmap_arg_struct a; - - if (copy_from_user(&a, arg, sizeof(a))) - return -EFAULT; + struct file *file = NULL; down(¤t->mm->mmap_sem); lock_kernel(); - if (!(a.flags & MAP_ANONYMOUS)) { + if (!(flags & MAP_ANONYMOUS)) { error = -EBADF; - file = fget(a.fd); + file = fget(fd); if (!file) goto out; } - a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset); + error = do_mmap(file, addr, len, prot, flags, off); if (file) fput(file); out: unlock_kernel(); up(¤t->mm->mmap_sem); - return error; -} - -extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); - -struct sel_arg_struct { - unsigned long n; - fd_set *inp, *outp, *exp; - struct timeval *tvp; -}; - -asmlinkage int old_select(struct sel_arg_struct *arg) -{ - struct sel_arg_struct a; - if (copy_from_user(&a, arg, sizeof(a))) - return -EFAULT; - /* sys_select() does the appropriate kernel locking */ - return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); + return error; } /* @@ -198,9 +166,6 @@ asmlinkage int sys_ipc (uint call, int first, int second, return -EINVAL; } -/* - * Old cruft - */ asmlinkage int sys_uname(struct old_utsname * name) { int err; @@ -212,35 +177,6 @@ asmlinkage int sys_uname(struct old_utsname * name) return err?-EFAULT:0; } -asmlinkage int sys_olduname(struct oldold_utsname * name) -{ - int error; - - if (!name) - return -EFAULT; - if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) - return -EFAULT; - - down(&uts_sem); - - error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); - error |= __put_user(0,name->sysname+__OLD_UTS_LEN); - error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); - error |= __put_user(0,name->nodename+__OLD_UTS_LEN); - error |= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); - error |= __put_user(0,name->release+__OLD_UTS_LEN); - error |= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); - error |= __put_user(0,name->version+__OLD_UTS_LEN); - error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); - error |= __put_user(0,name->machine+__OLD_UTS_LEN); - - up(&uts_sem); - - error = error ? -EFAULT : 0; - - return error; -} - asmlinkage int sys_pause(void) { current->state = TASK_INTERRUPTIBLE; diff --git a/arch/sh/kernel/test-img.c b/arch/sh/kernel/test-img.c deleted file mode 100644 index daade9f6d11b..000000000000 --- a/arch/sh/kernel/test-img.c +++ /dev/null @@ -1,69 +0,0 @@ -unsigned char root_fs_image[] -__attribute__((__section__(".data.disk_image"))) -= { -0x1f,0x8b,0x08,0x08,0x5d,0xd5,0xc7,0x37,0x00,0x03,0x72,0x2e,0x62,0x69,0x6e,0x00, -0xed,0xdc,0x3f,0x6c,0x1b,0x55,0x1c,0xc0,0xf1,0xdf,0xf9,0xdc,0x04,0x27,0x69,0xb1, -0x93,0x14,0x10,0x48,0x91,0xd3,0x02,0x4d,0x8a,0xb8,0xd4,0x21,0x8a,0x09,0x02,0x02, -0xb5,0x4a,0xab,0x52,0x65,0x69,0x11,0x03,0x42,0xc2,0xb1,0x8f,0xc4,0x92,0xe3,0x03, -0x9f,0x8d,0xca,0x14,0xd8,0x88,0x2a,0xa6,0x0e,0x88,0xa9,0x20,0xb1,0x87,0x8d,0xa5, -0x5b,0x86,0xcc,0x90,0x78,0x77,0xd4,0x60,0x75,0xa9,0x40,0xe2,0xdf,0xd0,0x42,0x78, -0x77,0xef,0x9c,0x38,0x24,0x72,0x49,0x20,0xc9,0x70,0xdf,0x8f,0xf2,0xf3,0xd9,0x77, -0xbf,0xf3,0xbb,0x67,0xbf,0xdf,0xf9,0x4f,0xf4,0x2c,0x02,0x20,0xac,0xe2,0x2a,0x5e, -0x53,0x61,0xaa,0x18,0x0e,0xd6,0x19,0xad,0x09,0x49,0x1d,0x5e,0x5e,0x7d,0x75,0x39, -0xfd,0x6c,0x6d,0x39,0x6d,0x48,0xbf,0x5c,0xfd,0xc9,0xf0,0xf3,0x56,0xd5,0x3a,0x99, -0xba,0xf7,0xd0,0x76,0x8a,0x53,0x5f,0xc4,0xdf,0xcd,0x24,0x56,0x6e,0x9e,0x59,0xb9, -0x30,0x3e,0x73,0x3b,0xf7,0x3f,0x76,0x01,0xc0,0x3e,0x79,0x75,0x1f,0x55,0x71,0x4c, -0x74,0xfd,0x47,0x8f,0xf6,0x70,0x00,0x1c,0xa2,0x8d,0x8d,0x49,0x6f,0xf1,0xc9,0x06, -0x00,0x00,0x08,0x8d,0xe6,0xfb,0x00,0xef,0x73,0x7c,0x33,0x0e,0xf3,0xfd,0xc7,0xbd, -0xd7,0xc5,0xff,0xd0,0x31,0x5a,0x5b,0x4e,0xf7,0x05,0xa1,0xb7,0x1c,0x93,0x48,0x4b, -0x5e,0xe7,0x61,0x1e,0x14,0x80,0x50,0xf0,0xcf,0x3f,0xe7,0x76,0x3b,0xff,0x45,0xe4, -0x89,0x96,0xbc,0x47,0x54,0xc4,0x54,0x74,0xa9,0xe8,0x56,0xd1,0xa3,0xe2,0xb8,0x8a, -0x13,0x2a,0x1e,0x15,0xfd,0xfd,0x68,0x42,0x45,0xaf,0x8a,0xbe,0xbd,0xb6,0xaf,0xce, -0x7f,0x7f,0xaa,0x76,0xef,0x07,0xd1,0x6c,0xbf,0xf5,0xfc,0xd7,0xbf,0xf7,0xae,0x6d, -0x32,0xda,0x6c,0x6b,0xb6,0x7f,0x56,0x9d,0x77,0x4f,0x05,0xb1,0x5b,0xfb,0x27,0x0f, -0xa8,0xfd,0x6f,0x06,0xf5,0xf2,0xfe,0x8e,0xfe,0xff,0x63,0xaf,0xff,0xf0,0xc5,0x54, -0xdb,0xfe,0x7f,0x7a,0xeb,0xf2,0x15,0x53,0xe4,0xe6,0xaa,0x7e,0xed,0x19,0x0b,0xda, -0xbf,0x75,0xd9,0xd8,0xd6,0xff,0xc7,0xf6,0xdf,0x7c,0xdb,0xf6,0x37,0xbe,0xd6,0x63, -0x6a,0xe7,0xe3,0xbf,0x7d,0x2f,0xcb,0x1a,0x29,0x16,0x4a,0xd5,0xeb,0xe5,0x7d,0x7c, -0x73,0xde,0xae,0x7d,0xaf,0x8f,0x3d,0x2a,0xc3,0xda,0xbc,0x1e,0x51,0x6d,0xe9,0x31, -0xde,0xaf,0x8e,0xac,0xe8,0xb8,0x95,0xe7,0xde,0x77,0xaa,0xa5,0xbc,0x1e,0xf3,0x3d, -0x62,0x4a,0xde,0xfe,0xc8,0x1f,0xfb,0x3d,0xea,0x49,0x71,0xa7,0x0b,0x25,0x6f,0xfc, -0xdf,0x36,0x3b,0x65,0xdf,0x07,0x08,0xe0,0x48,0xe8,0xd7,0xb2,0xad,0xfa,0xff,0xd5, -0xd4,0xf5,0x0f,0x20,0x24,0xf8,0xa7,0x1f,0x10,0x5e,0xd4,0x3f,0x10,0x5e,0xd4,0x3f, -0x10,0x5e,0xd4,0x3f,0x10,0x5e,0xd4,0x3f,0x10,0x5e,0xd4,0x3f,0x10,0x5e,0xd4,0x3f, -0x10,0x5e,0xd4,0x3f,0x10,0x5e,0xd4,0x3f,0x10,0x5e,0xd4,0x3f,0x10,0x5e,0xd4,0x3f, -0x10,0x4a,0x7a,0x4e,0xcf,0xce,0xf9,0x3f,0xde,0xbc,0xb6,0xbb,0x66,0xa7,0xe4,0x9c, -0x92,0xeb,0x14,0xed,0xa3,0x3d,0x48,0x00,0x07,0x42,0xcf,0xe3,0xdb,0x59,0xff,0xde, -0x7c,0xd6,0xbb,0x66,0x54,0x0a,0xa5,0x42,0xe5,0x68,0x8f,0x10,0xc0,0x41,0x99,0xbf, -0x70,0xe5,0x0d,0x23,0xd2,0x32,0x43,0x38,0x22,0x67,0xc5,0x9f,0x32,0x1c,0xff,0x4a, -0x2d,0xc7,0xd4,0xd5,0x75,0x7f,0xfd,0x98,0x24,0xd5,0xb6,0x21,0x89,0xf9,0x53,0xe1, -0x83,0x1d,0xe2,0x41,0x18,0xd3,0x3a,0xfc,0x9f,0x11,0x34,0x74,0x78,0xb7,0x07,0x83, -0xd8,0xd4,0xe1,0x27,0x67,0xd6,0x8d,0x46,0x7c,0xa4,0x51,0x8f,0xd6,0x3a,0x4a,0xbf, -0x2c,0xc9,0x7b,0xa7,0x3f,0x33,0x16,0xcc,0x5a,0xb4,0x61,0xd6,0xa3,0x4b,0xe2,0xdc, -0x91,0xee,0xd2,0xef,0x22,0x89,0xa7,0x55,0xbc,0x38,0xd2,0x98,0xff,0xb9,0x1e,0xf1, -0xb2,0xa6,0xcd,0xf3,0x89,0x85,0xce,0x75,0xa3,0xf6,0x78,0xe3,0xa4,0x97,0x27,0xb1, -0xc5,0xbf,0x24,0x76,0x6a,0x68,0xa1,0x7b,0xa5,0x6f,0x4d,0x3e,0x34,0x52,0xe9,0x1b, -0x0f,0xf2,0xa7,0x7f,0x34,0xea,0xcf,0x2c,0xc9,0xe2,0x1f,0x6b,0x6a,0xfb,0xf7,0x27, -0xd6,0x0d,0xab,0xd7,0xbe,0xb3,0x26,0x03,0x89,0x86,0x0c,0xf4,0xd6,0x33,0x03,0x7d, -0x4b,0xf2,0x43,0xd7,0xba,0x21,0xb1,0x5a,0xac,0x71,0xdc,0xbb,0x17,0x2f,0x4f,0xed, -0x7b,0xe6,0xc6,0x83,0xc5,0xdf,0xbc,0xf5,0xaa,0xcd,0x97,0xe5,0x9d,0xcf,0xe7,0x55, -0xbf,0x2a,0xf2,0xdd,0x93,0x1b,0xea,0xf6,0xb5,0x6b,0xb3,0x05,0x37,0xa9,0xfe,0xae, -0x56,0x3f,0xb0,0xcb,0x97,0x06,0xbd,0xe9,0xda,0x32,0x39,0xd9,0x25,0xae,0x33,0x67, -0x57,0x66,0x0b,0xa5,0x99,0x64,0xb5,0x54,0x75,0xab,0xd9,0xa2,0x65,0x59,0xde,0xc6, -0x4b,0x76,0xb1,0xe8,0x24,0xdf,0x76,0xca,0xc5,0xbc,0x97,0x7c,0x31,0x93,0x79,0x29, -0x39,0x74,0x71,0xea,0xad,0xe1,0xa4,0x3d,0x93,0x73,0x9f,0x1f,0xb5,0x26,0x52,0xd6, -0xf8,0x78,0x32,0x35,0x31,0x31,0x71,0xee,0x85,0xd4,0x58,0x72,0xc8,0x5f,0x9d,0xb2, -0x52,0xd6,0x68,0xb2,0x6c,0x17,0xed,0xac,0x6b,0x0f,0x8b,0x58,0xee,0xc7,0x73,0x95, -0xec,0xb4,0x5a,0x56,0xca,0x7a,0x39,0xdb,0xbc,0x56,0xb1,0xaf,0x57,0xc4,0x2a,0x3b, -0xf9,0x6c,0x25,0x2b,0x96,0xbe,0xcc,0x55,0x9c,0xb2,0xab,0x6e,0xe8,0xc5,0xb4,0xab, -0x2e,0x72,0xce,0xdc,0x9c,0x5d,0xda,0xd3,0xe9,0xfb,0xa9,0xe0,0xf9,0xeb,0xf0,0xfb, -0x2f,0xe2,0xc5,0xb7,0x2d,0xdb,0x9b,0x9f,0x14,0x07,0x83,0xbc,0x88,0x7e,0x9e,0x0c, -0x15,0xf2,0xea,0x2e,0x79,0xc3,0x41,0x9e,0xa9,0xc7,0x81,0xd1,0x3a,0x16,0x64,0x6b, -0x1c,0xc9,0xc8,0xd6,0xb8,0x69,0x9b,0x37,0xfe,0x2f,0xf3,0x5e,0x11,0xfd,0x93,0x0d, -0x0f,0x6b,0xf7,0xbc,0x6c,0x9b,0x1e,0xef,0xe7,0xa5,0x77,0xc9,0x4b,0xe8,0xfb,0xda, -0x5c,0xfd,0xa5,0xba,0x78,0x73,0x97,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x87,0xe8,0x6f,0x20,0x01,0xec,0xc5,0x00,0x00,0x01,0x00, -}; diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c index 6f4598a7e0ab..42bdf2febf49 100644 --- a/arch/sh/kernel/time.c +++ b/arch/sh/kernel/time.c @@ -1,12 +1,15 @@ -/* +/* $Id: time.c,v 1.2 1999/10/11 13:12:02 gniibe Exp $ + * * linux/arch/sh/kernel/time.c * - * Copyright (C) 1999 Niibe Yutaka + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka * * Some code taken from i386 version. * Copyright (C) 1991, 1992, 1995 Linus Torvalds */ +#include + #include #include #include @@ -28,6 +31,11 @@ #include #include +#define TMU_TOCR_INIT 0x00 +#define TMU0_TCR_INIT 0x0020 +#define TMU_TSTR_INIT 1 + +#if defined(__sh3__) #define TMU_TOCR 0xfffffe90 /* Byte access */ #define TMU_TSTR 0xfffffe92 /* Byte access */ @@ -35,13 +43,63 @@ #define TMU0_TCNT 0xfffffe98 /* Long access */ #define TMU0_TCR 0xfffffe9c /* Word access */ -#define TMU_TOCR_INIT 0x00 -#define TMU0_TCR_INIT 0x0020 -#define TMU_TSTR_INIT 1 - -#define CLOCK_MHZ (60/4) #define INTERVAL 37500 /* (1000000*CLOCK_MHZ/HZ/2) ??? */ +/* SH-3 RTC */ +#define R64CNT 0xfffffec0 +#define RSECCNT 0xfffffec2 +#define RMINCNT 0xfffffec4 +#define RHRCNT 0xfffffec6 +#define RWKCNT 0xfffffec8 +#define RDAYCNT 0xfffffeca +#define RMONCNT 0xfffffecc +#define RYRCNT 0xfffffece +#define RSECAR 0xfffffed0 +#define RMINAR 0xfffffed2 +#define RHRAR 0xfffffed4 +#define RWKAR 0xfffffed6 +#define RDAYAR 0xfffffed8 +#define RMONAR 0xfffffeda +#define RCR1 0xfffffedc +#define RCR2 0xfffffede + +#elif defined(__SH4__) +#define TMU_TOCR 0xffd80000 /* Byte access */ +#define TMU_TSTR 0xffd80004 /* Byte access */ + +#define TMU0_TCOR 0xffd80008 /* Long access */ +#define TMU0_TCNT 0xffd8000c /* Long access */ +#define TMU0_TCR 0xffd80010 /* Word access */ + +#define INTERVAL 83333 + +/* SH-4 RTC */ +#define R64CNT 0xffc80000 +#define RSECCNT 0xffc80004 +#define RMINCNT 0xffc80008 +#define RHRCNT 0xffc8000c +#define RWKCNT 0xffc80010 +#define RDAYCNT 0xffc80014 +#define RMONCNT 0xffc80018 +#define RYRCNT 0xffc8001c /* 16bit */ +#define RSECAR 0xffc80020 +#define RMINAR 0xffc80024 +#define RHRAR 0xffc80028 +#define RWKAR 0xffc8002c +#define RDAYAR 0xffc80030 +#define RMONAR 0xffc80034 +#define RCR1 0xffc80038 +#define RCR2 0xffc8003c +#endif + +#ifndef BCD_TO_BIN +#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) +#endif + +#ifndef BIN_TO_BCD +#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10) +#endif + extern rwlock_t xtime_lock; #define TICK_SIZE tick @@ -82,14 +140,48 @@ void do_settimeofday(struct timeval *tv) write_unlock_irq(&xtime_lock); } -/* - */ static int set_rtc_time(unsigned long nowtime) { -/* XXX should be implemented XXXXXXXXXX */ - int retval = -1; +#ifdef CONFIG_SH_CPU_RTC + int retval = 0; + int real_seconds, real_minutes, cmos_minutes; + + ctrl_outb(2, RCR2); /* reset pre-scaler & stop RTC */ + + cmos_minutes = ctrl_inb(RMINCNT); + BCD_TO_BIN(cmos_minutes); + + /* + * since we're only adjusting minutes and seconds, + * don't interfere with hour overflow. This avoids + * messing with unknown time zones but requires your + * RTC not to be off by more than 15 minutes + */ + real_seconds = nowtime % 60; + real_minutes = nowtime / 60; + if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) + real_minutes += 30; /* correct for half hour time zone */ + real_minutes %= 60; + + if (abs(real_minutes - cmos_minutes) < 30) { + BIN_TO_BCD(real_seconds); + BIN_TO_BCD(real_minutes); + ctrl_outb(real_seconds, RSECCNT); + ctrl_outb(real_minutes, RMINCNT); + } else { + printk(KERN_WARNING + "set_rtc_time: can't update from %d to %d\n", + cmos_minutes, real_minutes); + retval = -1; + } + + ctrl_outb(2, RCR2); /* start RTC */ return retval; +#else + /* XXX should support other clock devices? */ + return -1; +#endif } /* last time the RTC clock got updated */ @@ -131,14 +223,12 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg */ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - unsigned long __dummy; + unsigned long timer_status; /* Clear UNF bit */ - asm volatile("mov.w %1,%0\n\t" - "and %2,%0\n\t" - "mov.w %0,%1" - : "=&z" (__dummy) - : "m" (__m(TMU0_TCR)), "r" (~0x100)); + timer_status = ctrl_inw(TMU0_TCR); + timer_status &= ~0x100; + ctrl_outw(timer_status, TMU0_TCR); /* * Here we are in the timer irq handler. We just have irqs locally @@ -187,16 +277,67 @@ static inline unsigned long mktime(unsigned int year, unsigned int mon, static unsigned long get_rtc_time(void) { -/* XXX not implemented yet */ +#ifdef CONFIG_SH_CPU_RTC + unsigned int sec, min, hr, wk, day, mon, yr, yr100; + + again: + ctrl_outb(1, RCR1); /* clear CF bit */ + do { + sec = ctrl_inb(RSECCNT); + min = ctrl_inb(RMINCNT); + hr = ctrl_inb(RHRCNT); + wk = ctrl_inb(RWKCNT); + day = ctrl_inb(RDAYCNT); + mon = ctrl_inb(RMONCNT); +#if defined(__SH4__) + yr = ctrl_inw(RYRCNT); + yr100 = (yr >> 8); + yr &= 0xff; +#else + yr = ctrl_inb(RYRCNT); + yr100 = (yr == 0x99) ? 0x19 : 0x20; +#endif + } while ((ctrl_inb(RCR1) & 0x80) != 0); + + BCD_TO_BIN(yr100); + BCD_TO_BIN(yr); + BCD_TO_BIN(mon); + BCD_TO_BIN(day); + BCD_TO_BIN(hr); + BCD_TO_BIN(min); + BCD_TO_BIN(sec); + + if (yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 || + hr > 23 || min > 59 || sec > 59) { + printk(KERN_ERR + "SH RTC: invalid value, resetting to 1 Jan 2000\n"); + ctrl_outb(2, RCR2); /* reset, stop */ + ctrl_outb(0, RSECCNT); + ctrl_outb(0, RMINCNT); + ctrl_outb(0, RHRCNT); + ctrl_outb(6, RWKCNT); + ctrl_outb(1, RDAYCNT); + ctrl_outb(1, RMONCNT); +#if defined(__SH4__) + ctrl_outw(0x2000, RYRCNT); +#else + ctrl_outb(0, RYRCNT); +#endif + ctrl_outb(1, RCR2); /* start */ + goto again; + } + + return mktime(yr100 * 100 + yr, mon, day, hr, min, sec); +#else + /* XXX should support other clock devices? */ return 0; +#endif } static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL}; void __init time_init(void) { - unsigned long __dummy; - xtime.tv_sec = get_rtc_time(); xtime.tv_usec = 0; @@ -204,19 +345,12 @@ void __init time_init(void) setup_irq(TIMER_IRQ, &irq0); /* Start TMU0 */ - asm volatile("mov %1,%0\n\t" - "mov.b %0,%2 ! external clock input\n\t" - "mov %3,%0\n\t" - "mov.w %0,%4 ! enable timer0 interrupt\n\t" - "mov.l %5,%6\n\t" - "mov.l %5,%7\n\t" - "mov %8,%0\n\t" - "mov.b %0,%9" - : "=&z" (__dummy) - : "i" (TMU_TOCR_INIT), "m" (__m(TMU_TOCR)), - "i" (TMU0_TCR_INIT), "m" (__m(TMU0_TCR)), - "r" (INTERVAL), "m" (__m(TMU0_TCOR)), "m" (__m(TMU0_TCNT)), - "i" (TMU_TSTR_INIT), "m" (__m(TMU_TSTR))); + ctrl_outb(TMU_TOCR_INIT,TMU_TOCR); + ctrl_outw(TMU0_TCR_INIT,TMU0_TCR); + ctrl_outl(INTERVAL,TMU0_TCOR); + ctrl_outl(INTERVAL,TMU0_TCNT); + ctrl_outb(TMU_TSTR_INIT,TMU_TSTR); + #if 0 /* Start RTC */ asm volatile(""); diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index 3d3cba23cf39..8a9b3e1f9b87 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c @@ -1,4 +1,5 @@ -/* +/* $Id: traps.c,v 1.3 1999/09/21 14:37:19 gniibe Exp $ + * * linux/arch/sh/traps.c * * SuperH version: Copyright (C) 1999 Niibe Yutaka @@ -56,10 +57,6 @@ asmlinkage void do_##name(unsigned long r4, unsigned long r5, \ #define VMALLOC_OFFSET (8*1024*1024) #define MODULE_RANGE (8*1024*1024) -static void show_registers(struct pt_regs *regs) -{/* Not implemented yet. */ -} - spinlock_t die_lock; void die(const char * str, struct pt_regs * regs, long err) @@ -67,7 +64,7 @@ void die(const char * str, struct pt_regs * regs, long err) console_verbose(); spin_lock_irq(&die_lock); printk("%s: %04lx\n", str, err & 0xffff); - show_registers(regs); + show_regs(regs); spin_unlock_irq(&die_lock); do_exit(SIGSEGV); } diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile index a9010ddb207f..934c84744c59 100644 --- a/arch/sh/lib/Makefile +++ b/arch/sh/lib/Makefile @@ -6,9 +6,7 @@ $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o L_TARGET = lib.a -# L_OBJS = checksum.o old-checksum.o semaphore.o delay.o \ -# usercopy.o getuser.o putuser.o -L_OBJS = delay.o memcpy.o memset.o memmove.o csum_partial_copy.o \ - wordcopy.o checksum.o # usercopy.o getuser.o putuser.o +L_OBJS = delay.o memcpy.o memset.o memmove.o old-checksum.o \ + checksum.o include $(TOPDIR)/Rules.make diff --git a/arch/sh/lib/checksum.S b/arch/sh/lib/checksum.S new file mode 100644 index 000000000000..8eb4c05ef89d --- /dev/null +++ b/arch/sh/lib/checksum.S @@ -0,0 +1,318 @@ +/* $Id: checksum.S,v 1.1 1999/09/18 16:56:53 gniibe Exp $ + * + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * IP/TCP/UDP checksumming routines + * + * Authors: Jorge Cwik, + * Arnt Gulbrandsen, + * Tom May, + * Pentium Pro/II routines: + * Alexander Kjeldaas + * Finn Arne Gangstad + * Lots of code moved from tcp.c and ip.c; see those files + * for more names. + * + * Changes: Ingo Molnar, converted csum_partial_copy() to 2.1 exception + * handling. + * Andi Kleen, add zeroing on error + * converted to pure assembler + * + * SuperH version: Copyright (C) 1999 Niibe Yutaka + * + * 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 + +/* + * computes a partial checksum, e.g. for TCP/UDP fragments + */ + +/* + * unsigned int csum_partial(const unsigned char *buf, int len, + * unsigned int sum); + */ + +.text +ENTRY(csum_partial) + /* + * Experiments with Ethernet and SLIP connections show that buff + * is aligned on either a 2-byte or 4-byte boundary. We get at + * least a twofold speedup on 486 and Pentium if it is 4-byte aligned. + * Fortunately, it is easy to convert 2-byte alignment to 4-byte + * alignment for the unrolled loop. + */ + mov r5,r1 + mov r4,r0 + tst #2,r0 ! Check alignment. + bt 2f ! Jump if alignment is ok. + ! + add #-2,r5 ! Alignment uses up two bytes. + cmp/pz r5 ! + bt/s 1f ! Jump if we had at least two bytes. + clrt + bra 6f + add #2,r5 ! r5 was < 2. Deal with it. +1: + mov.w @r4+,r0 + extu.w r0,r0 + addc r0,r6 + bf 2f + add #1,r6 +2: + mov #-5,r0 + shld r0,r5 + tst r5,r5 + bt/s 4f ! if it's =0, go to 4f + clrt +3: + mov.l @r4+,r0 + addc r0,r6 + mov.l @r4+,r0 + addc r0,r6 + mov.l @r4+,r0 + addc r0,r6 + mov.l @r4+,r0 + addc r0,r6 + mov.l @r4+,r0 + addc r0,r6 + mov.l @r4+,r0 + addc r0,r6 + mov.l @r4+,r0 + addc r0,r6 + mov.l @r4+,r0 + addc r0,r6 + movt r0 + dt r5 + bf/s 3b + cmp/eq #1,r0 + mov #0,r0 + addc r0,r6 +4: + mov r1,r5 + mov #0x1c,r0 + and r0,r5 + tst r5,r5 + bt/s 6f + clrt + shlr2 r5 +5: + mov.l @r4+,r0 + addc r0,r6 + movt r0 + dt r5 + bf/s 5b + cmp/eq #1,r0 + mov #0,r0 + addc r0,r6 +6: + mov r1,r5 + mov #3,r0 + and r0,r5 + tst r5,r5 + bt 9f ! if it's =0 go to 9f + mov #2,r1 + cmp/hs r1,r5 + bf 7f + mov.w @r4+,r0 + extu.w r0,r0 + cmp/eq r1,r5 + bt/s 8f + clrt + shll16 r0 + addc r0,r6 +7: + mov.b @r4+,r0 + extu.b r0,r0 +8: + addc r0,r6 + mov #0,r0 + addc r0,r6 +9: + rts + mov r6,r0 + +/* +unsigned int csum_partial_copy_generic (const char *src, char *dst, int len, + int sum, int *src_err_ptr, int *dst_err_ptr) + */ + +/* + * Copy from ds while checksumming, otherwise like csum_partial + * + * The macros SRC and DST specify the type of access for the instruction. + * thus we can call a custom exception handler for all access types. + * + * FIXME: could someone double-check whether I haven't mixed up some SRC and + * DST definitions? It's damn hard to trigger all cases. I hope I got + * them all but there's no guarantee. + */ + +#define SRC(y...) \ + 9999: y; \ + .section __ex_table, "a"; \ + .long 9999b, 6001f ; \ + .previous + +#define DST(y...) \ + 9999: y; \ + .section __ex_table, "a"; \ + .long 9999b, 6002f ; \ + .previous + +ENTRY(csum_partial_copy_generic) + mov.l r5,@-r15 + mov.l r6,@-r15 + + mov #2,r0 + tst r0,r5 ! Check alignment. + bt 2f ! Jump if alignment is ok. + add #-2,r6 ! Alignment uses up two bytes. + cmp/pz r6 ! Jump if we had at least two bytes. + bt/s 1f + clrt + bra 4f + add #2,r6 ! ecx was < 2. Deal with it. +SRC(1: mov.w @r4+,r0 ) +DST( mov.w r0,@r5 ) + add #2,r5 + extu.w r0,r0 + addc r0,r7 + mov #0,r0 + addc r0,r7 +2: + mov r6,r2 + mov #-5,r0 + shld r0,r6 + tst r6,r6 + bf/s 2f + clrt +SRC(1: mov.l @r4+,r0 ) +SRC( mov.l @r4+,r1 ) + addc r0,r7 +DST( mov.l r0,@r5 ) + add #4,r5 + addc r1,r7 +DST( mov.l r1,@r5 ) + add #4,r5 + +SRC( mov.l @r4+,r0 ) +SRC( mov.l @r4+,r1 ) + addc r0,r7 +DST( mov.l r0,@r5 ) + add #4,r5 + addc r1,r7 +DST( mov.l r1,@r5 ) + add #4,r5 + +SRC( mov.l @r4+,r0 ) +SRC( mov.l @r4+,r1 ) + addc r0,r7 +DST( mov.l r0,@r5 ) + add #4,r5 + addc r1,r7 +DST( mov.l r1,@r5 ) + add #4,r5 + +SRC( mov.l @r4+,r0 ) +SRC( mov.l @r4+,r1 ) + addc r0,r7 +DST( mov.l r0,@r5 ) + add #4,r5 + addc r1,r7 +DST( mov.l r1,@r5 ) + add #4,r5 + movt r0 + dt r6 + bf/s 1b + cmp/eq #1,r0 + mov #0,r0 + addc r0,r7 + +2: mov r2,r6 + mov #0x1c,r0 + and r0,r6 + cmp/pl r6 + bf/s 4f + clrt + shlr2 r6 +SRC(3: mov.l @r4+,r0 ) + addc r0,r7 +DST( mov.l r0,@r5 ) + add #4,r5 + movt r0 + dt r6 + bf/s 3b + cmp/eq #1,r0 + mov #0,r0 + addc r0,r7 +4: mov r2,r6 + mov #3,r0 + and r0,r6 + cmp/pl r6 + bf 7f + mov #2,r1 + cmp/hs r1,r6 + bf 5f +SRC( mov.w @r4+,r0 ) +DST( mov.w r0,@r5 ) + extu.w r0,r0 + add #2,r5 + cmp/eq r1,r6 + bt/s 6f + clrt + shll16 r0 + addc r0,r7 +SRC(5: mov.b @r4+,r0 ) +DST( mov.b r0,@r5 ) + extu.b r0,r0 +6: addc r0,r7 + mov #0,r0 + addc r0,r7 +7: +5000: + +# Exception handler: +.section .fixup, "ax" + +6001: + mov.l @(8,r15),r0 ! src_err_ptr + mov #-EFAULT,r1 + mov.l r1,@r0 + + ! zero the complete destination - computing the rest + ! is too much work + mov.l @(4,r15),r5 ! dst + mov.l @r15,r6 ! len + mov #0,r7 +1: mov.b r7,@r5 + dt r6 + bf/s 1b + add #1,r5 + mov.l 8000f,r0 + jmp @r0 + nop + .balign 4 +8000: .long 5000b + +6002: + mov.l @(12,r15),r0 ! dst_err_ptr + mov #-EFAULT,r1 + mov.l r1,@r0 + mov.l 8001f,r0 + jmp @r0 + nop + .balign 4 +8001: .long 5000b + +.previous + add #8,r15 + rts + mov r7,r0 diff --git a/arch/sh/lib/checksum.c b/arch/sh/lib/checksum.c deleted file mode 100644 index f076bd3c69f3..000000000000 --- a/arch/sh/lib/checksum.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Taken from: - * arch/alpha/lib/checksum.c - * - * This file contains network checksum routines that are better done - * in an architecture-specific manner due to speed.. - */ - -#include - -#include - -static inline unsigned short from64to16(unsigned long long x) -{ - /* add up 32-bit words for 33 bits */ - x = (x & 0xffffffff) + (x >> 32); - /* add up 16-bit and 17-bit words for 17+c bits */ - x = (x & 0xffff) + (x >> 16); - /* add up 16-bit and 2-bit for 16+c bit */ - x = (x & 0xffff) + (x >> 16); - /* add up carry.. */ - x = (x & 0xffff) + (x >> 16); - return x; -} - -/* - * computes the checksum of the TCP/UDP pseudo-header - * returns a 16-bit checksum, already complemented. - */ -unsigned short int csum_tcpudp_magic(unsigned long saddr, - unsigned long daddr, - unsigned short len, - unsigned short proto, - unsigned int sum) -{ - return ~from64to16(saddr + daddr + sum + - ((unsigned long) ntohs(len) << 16) + - ((unsigned long) proto << 8)); -} - -unsigned int csum_tcpudp_nofold(unsigned long saddr, - unsigned long daddr, - unsigned short len, - unsigned short proto, - unsigned int sum) -{ - unsigned long long result; - - result = (saddr + daddr + sum + - ((unsigned long) ntohs(len) << 16) + - ((unsigned long) proto << 8)); - - /* Fold down to 32-bits so we don't loose in the typedef-less - network stack. */ - /* 64 to 33 */ - result = (result & 0xffffffff) + (result >> 32); - /* 33 to 32 */ - result = (result & 0xffffffff) + (result >> 32); - return result; -} - -/* - * Do a 64-bit checksum on an arbitrary memory area.. - * - * This isn't a great routine, but it's not _horrible_ either. The - * inner loop could be unrolled a bit further, and there are better - * ways to do the carry, but this is reasonable. - */ -static inline unsigned long do_csum(const unsigned char * buff, int len) -{ - int odd, count; - unsigned long long result = 0; - - if (len <= 0) - goto out; - odd = 1 & (unsigned long) buff; - if (odd) { - result = *buff << 8; - len--; - buff++; - } - count = len >> 1; /* nr of 16-bit words.. */ - if (count) { - if (2 & (unsigned long) buff) { - result += *(unsigned short *) buff; - count--; - len -= 2; - buff += 2; - } - count >>= 1; /* nr of 32-bit words.. */ - if (count) { - if (4 & (unsigned long) buff) { - result += *(unsigned int *) buff; - count--; - len -= 4; - buff += 4; - } - count >>= 1; /* nr of 64-bit words.. */ - if (count) { - unsigned long carry = 0; - do { - unsigned long w = *(unsigned long *) buff; - count--; - buff += 8; - result += carry; - result += w; - carry = (w > result); - } while (count); - result += carry; - result = (result & 0xffffffff) + (result >> 32); - } - if (len & 4) { - result += *(unsigned int *) buff; - buff += 4; - } - } - if (len & 2) { - result += *(unsigned short *) buff; - buff += 2; - } - } - if (len & 1) - result += *buff; - result = from64to16(result); - if (odd) - result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); -out: - return result; -} - -/* - * This is a version of ip_compute_csum() optimized for IP headers, - * which always checksum on 4 octet boundaries. - */ -unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl) -{ - return ~do_csum(iph,ihl*4); -} - -/* - * computes the checksum of a memory block at buff, length len, - * and adds in "sum" (32-bit) - * - * returns a 32-bit number suitable for feeding into itself - * or csum_tcpudp_magic - * - * this function must be called with even lengths, except - * for the last fragment, which may be odd - * - * it's best to have buff aligned on a 32-bit boundary - */ -unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) -{ - unsigned long long result = do_csum(buff, len); - - /* add in old sum, and carry.. */ - result += sum; - /* 32+c bits -> 32 bits */ - result = (result & 0xffffffff) + (result >> 32); - return result; -} - -/* - * this routine is used for miscellaneous IP-like checksums, mainly - * in icmp.c - */ -unsigned short ip_compute_csum(unsigned char * buff, int len) -{ - return ~from64to16(do_csum(buff,len)); -} diff --git a/arch/sh/lib/csum_partial_copy.c b/arch/sh/lib/csum_partial_copy.c deleted file mode 100644 index 1fb36ab05de3..000000000000 --- a/arch/sh/lib/csum_partial_copy.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * MIPS specific IP/TCP/UDP checksumming routines - * - * Authors: Ralf Baechle, - * Lots of code moved from tcp.c and ip.c; see those files - * for more names. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * $Id: csum_partial_copy.c,v 1.2 1998/09/16 13:29:32 ralf Exp $ - */ -#include -#include -#include -#include -#include - -/* - * copy while checksumming, otherwise like csum_partial - */ -unsigned int csum_partial_copy(const char *src, char *dst, - int len, unsigned int sum) -{ - /* - * It's 2:30 am and I don't feel like doing it real ... - * This is lots slower than the real thing (tm) - */ - sum = csum_partial(src, len, sum); - memcpy(dst, src, len); - - return sum; -} - -/* - * Copy from userspace and compute checksum. If we catch an exception - * then zero the rest of the buffer. - */ -unsigned int csum_partial_copy_from_user (const char *src, char *dst, - int len, unsigned int sum, - int *err_ptr) -{ - int missing; - - missing = copy_from_user(dst, src, len); - if (missing) { - memset(dst + len - missing, 0, missing); - *err_ptr = -EFAULT; - } - - return csum_partial(dst, len, sum); -} - -/* - * Copy to userspace and compute checksum. - */ -unsigned int csum_partial_copy_to_user (const char *src, char *dst, - int len, unsigned int sum, - int *err_ptr) -{ - sum = csum_partial(src, len, sum); - - if (copy_to_user(dst, src, len)) { - *err_ptr = -EFAULT; - return sum; - } - - return sum; -} diff --git a/arch/sh/lib/memcpy.S b/arch/sh/lib/memcpy.S index 3a4aca9190f6..6f31216620f8 100644 --- a/arch/sh/lib/memcpy.S +++ b/arch/sh/lib/memcpy.S @@ -1,131 +1,227 @@ -! Taken from newlib-1.8.0 +/* $Id: memcpy.S,v 1.3 1999/09/28 11:32:48 gniibe Exp $ + * + * "memcpy" implementation of SuperH + * + * Copyright (C) 1999 Niibe Yutaka + * + */ -! -! Fast SH memcpy -! -! by Toshiyasu Morita (tm@netcom.com) -! hacked by J"orn Rernnecke (amylaar@cygnus.co.uk) ("o for o-umlaut) -! -! Entry: r4: destination pointer -! r5: source pointer -! r6: byte count -! -! Exit: r0: destination pointer -! r1-r7: trashed -! -! Notes: Usually one wants to do small reads and write a longword, but -! unfortunately it is difficult in some cases to concatanate bytes -! into a longword on the SH, so this does a longword read and small -! writes. -! -! This implementation makes two assumptions about how it is called: -! -! 1.: If the byte count is nonzero, the address of the last byte to be -! copied is unsigned greater than the address of the first byte to -! be copied. This could be easily swapped for a signed comparison, -! but the algorithm used needs some comparison. -! -! 2.: When there are two or three bytes in the last word of an 11-or-bore -! bytes memory chunk to b copied, the rest of the word can be read -! without size effects. -! This could be easily changed by increasing the minumum size of -! a fast memcpy and the amount subtracted from r7 before L_2l_loop be 2, -! however, this would cost a few extra cyles on average. -! +/* + * void *memcpy(void *dst, const void *src, size_t n); + * No overlap between the memory of DST and of SRC are assumed. + */ #include ENTRY(memcpy) - ! Big endian version copies with decreasing addresses. - mov r4,r0 - add r6,r0 - sub r4,r5 - mov #11,r1 - cmp/hs r1,r6 - bf/s L_small + tst r6,r6 + bt/s 9f ! if n=0, do nothing + mov r4,r0 + sub r4,r5 ! From here, r5 has the distance to r0 + add r6,r0 ! From here, r0 points the end of copying point + mov #12,r1 + cmp/gt r6,r1 + bt/s 7f ! if it's too small, copy a byte at once add #-1,r5 - mov r5,r3 - add r0,r3 - shlr r3 - bt/s L_even - mov r4,r7 - mov.b @(r0,r5),r2 - add #-1,r3 - mov.b r2,@-r0 -L_even: - tst #1,r0 - add #-1,r5 - bf/s L_odddst - add #8,r7 - tst #2,r0 - bt L_al4dst - add #-1,r3 - mov.w @(r0,r5),r1 - mov.w r1,@-r0 -L_al4dst: - shlr r3 - bt L_al4both - mov.w @(r0,r5),r1 - swap.w r1,r1 - add #4,r7 - add #-4,r5 - .align 2 -L_2l_loop: - mov.l @(r0,r5),r2 - xtrct r2,r1 - mov.l r1,@-r0 - cmp/hs r7,r0 - mov.l @(r0,r5),r1 - xtrct r1,r2 - mov.l r2,@-r0 - bt L_2l_loop - bra L_cleanup - add #5,r5 + add #1,r5 + ! From here, r6 is free + ! + ! r4 --> [ ... ] DST [ ... ] SRC + ! [ ... ] [ ... ] + ! : : + ! r0 --> [ ... ] r0+r5 --> [ ... ] + ! + ! + mov r5,r1 + mov #3,r2 + and r2,r1 + shll2 r1 + mov r0,r3 ! Save the value on R0 to R3 + mova jmptable,r0 + add r1,r0 + mov.l @r0,r1 + jmp @r1 + mov r3,r0 ! and back to R0 + .balign 4 +jmptable: + .long case0 + .long case1 + .long case2 + .long case3 - nop ! avoid nop in executed code. -L_al4both: - add #-2,r5 - .align 2 -L_al4both_loop: - mov.l @(r0,r5),r1 - cmp/hs r7,r0 - bt/s L_al4both_loop + ! copy a byte at once +7: mov r4,r2 + add #1,r2 +8: + cmp/hi r2,r0 + mov.b @(r0,r5),r1 + bt/s 8b ! while (r0>r2) + mov.b r1,@-r0 +9: + rts + nop + +case0: + ! + ! GHIJ KLMN OPQR --> GHIJ KLMN OPQR + ! + ! First, align to long word boundary + mov r0,r3 + and r2,r3 + tst r3,r3 + bt/s 2f + add #-4,r5 + add #3,r5 +1: dt r3 + mov.b @(r0,r5),r1 + bf/s 1b + mov.b r1,@-r0 + ! + add #-3,r5 +2: ! Second, copy a long word at once + mov r4,r2 + add #7,r2 +3: mov.l @(r0,r5),r1 + cmp/hi r2,r0 + bt/s 3b mov.l r1,@-r0 - bra L_cleanup + ! + ! Third, copy a byte at once, if necessary + cmp/eq r4,r0 + bt/s 9b add #3,r5 + bra 8b + add #-6,r2 - nop ! avoid nop in executed code. -L_odddst: - shlr r3 - bt L_al4src - mov.w @(r0,r5),r1 - mov.b r1,@-r0 - shlr8 r1 - mov.b r1,@-r0 -L_al4src: - add #-2,r5 - .align 2 -L_odd_loop: - mov.l @(r0,r5),r2 - cmp/hs r7,r0 - mov.b r2,@-r0 - shlr8 r2 - mov.w r2,@-r0 - shlr16 r2 - mov.b r2,@-r0 - bt L_odd_loop - - add #3,r5 -L_cleanup: -L_small: +case1: + ! + ! GHIJ KLMN OPQR --> ...G HIJK LMNO PQR. + ! + ! First, align to long word boundary + mov r0,r3 + and r2,r3 + tst r3,r3 + bt/s 2f + add #-1,r5 +1: dt r3 + mov.b @(r0,r5),r1 + bf/s 1b + mov.b r1,@-r0 + ! +2: ! Second, read a long word and write a long word at once + mov.l @(r0,r5),r1 + add #-4,r5 + mov r4,r2 + add #7,r2 + ! +#ifdef __LITTLE_ENDIAN__ +3: mov r1,r3 ! RQPO + shll16 r3 + shll8 r3 ! Oxxx + mov.l @(r0,r5),r1 ! NMLK + mov r1,r6 + shlr8 r6 ! xNML + or r6,r3 ! ONML + cmp/hi r2,r0 + bt/s 3b + mov.l r3,@-r0 +#else +3: mov r1,r3 ! OPQR + shlr16 r3 + shlr8 r3 ! xxxO + mov.l @(r0,r5),r1 ! KLMN + mov r1,r6 + shll8 r6 ! LMNx + or r6,r3 ! LMNO + cmp/hi r2,r0 + bt/s 3b + mov.l r3,@-r0 +#endif + ! + ! Third, copy a byte at once, if necessary cmp/eq r4,r0 - bt L_ready - add #1,r4 - .align 2 -L_cleanup_loop: - mov.b @(r0,r5),r2 + bt/s 9b + add #4,r5 + bra 8b + add #-6,r2 + +case2: + ! + ! GHIJ KLMN OPQR --> ..GH IJKL MNOP QR.. + ! + ! First, align to word boundary + tst #1,r0 + bt/s 2f + add #-1,r5 + mov.b @(r0,r5),r1 + mov.b r1,@-r0 + ! +2: ! Second, read a word and write a word at once + add #-1,r5 + mov r4,r2 + add #3,r2 + ! +3: mov.w @(r0,r5),r1 + cmp/hi r2,r0 + bt/s 3b + mov.w r1,@-r0 + ! + ! Third, copy a byte at once, if necessary cmp/eq r4,r0 - mov.b r2,@-r0 - bf L_cleanup_loop -L_ready: + bt/s 9b + add #1,r5 + mov.b @(r0,r5),r1 rts - nop + mov.b r1,@-r0 + +case3: + ! + ! GHIJ KLMN OPQR --> .GHI JKLM NOPQ R... + ! + ! First, align to long word boundary + mov r0,r3 + and r2,r3 + tst r3,r3 + bt/s 2f + add #-1,r5 +1: dt r3 + mov.b @(r0,r5),r1 + bf/s 1b + mov.b r1,@-r0 + ! +2: ! Second, read a long word and write a long word at once + add #-2,r5 + mov.l @(r0,r5),r1 + add #-4,r5 + mov r4,r2 + add #7,r2 + ! +#ifdef __LITTLE_ENDIAN__ +3: mov r1,r3 ! RQPO + shll8 r3 ! QPOx + mov.l @(r0,r5),r1 ! NMLK + mov r1,r6 + shlr16 r6 + shlr8 r6 ! xxxN + or r6,r3 ! QPON + cmp/hi r2,r0 + bt/s 3b + mov.l r3,@-r0 +#else +3: mov r1,r3 ! OPQR + shlr8 r3 ! xOPQ + mov.l @(r0,r5),r1 ! KLMN + mov r1,r6 + shll16 r6 + shll8 r6 ! Nxxx + or r6,r3 ! NOPQ + cmp/hi r2,r0 + bt/s 3b + mov.l r3,@-r0 +#endif + ! + ! Third, copy a byte at once, if necessary + cmp/eq r4,r0 + bt/s 9b + add #6,r5 + bra 8b + add #-6,r2 diff --git a/arch/sh/lib/memmove.S b/arch/sh/lib/memmove.S index e95dc3709778..61b97b7c2a46 100644 --- a/arch/sh/lib/memmove.S +++ b/arch/sh/lib/memmove.S @@ -1,422 +1,254 @@ +/* $Id: memmove.S,v 1.2 1999/09/21 12:55:49 gniibe Exp $ + * + * "memmove" implementation of SuperH + * + * Copyright (C) 1999 Niibe Yutaka + * + */ + +/* + * void *memmove(void *dst, const void *src, size_t n); + * The memory areas may overlap. + */ + #include ENTRY(memmove) - mov.l r8,@-r15 - mov.l r9,@-r15 - mov.l r14,@-r15 - sts.l pr,@-r15 - add #-28,r15 - mov r15,r14 - mov.l r4,@r14 - mov.l r5,@(4,r14) - mov.l r6,@(8,r14) - mov.l @r14,r1 - mov.l r1,@(12,r14) - mov.l @(4,r14),r1 - mov.l r1,@(16,r14) - mov.l @(12,r14),r1 - mov.l @(16,r14),r2 - sub r2,r1 - mov.l @(8,r14),r2 - cmp/hs r2,r1 - bt .L54 - bra .L2 - nop -.L54: - mov.l @(8,r14),r1 - mov #15,r2 - cmp/gt r2,r1 - bt .LF100 - bra .L52 - nop -.LF100: - mov.l @(12,r14),r2 - neg r2,r1 - mov #3,r2 - and r1,r2 - mov.l @(8,r14),r1 - mov r1,r9 - sub r2,r9 - mov r9,r2 - mov.l r2,@(8,r14) -.L4: - mov.l @(12,r14),r2 - neg r2,r1 - mov #3,r2 - and r1,r2 - mov.l r2,@(20,r14) -.L7: - mov.l @(20,r14),r1 - cmp/pl r1 - bt .L9 - bra .L6 - nop - .align 2 -.L9: - mov r14,r2 - mov r14,r1 - add #24,r1 - mov.l @(16,r14),r2 - mov.b @r2,r3 - mov.b r3,@r1 - mov.l @(16,r14),r1 - mov r1,r2 - add #1,r2 - mov.l r2,@(16,r14) - mov.l @(20,r14),r1 - mov r1,r2 - add #-1,r2 - mov.l r2,@(20,r14) - mov.l @(12,r14),r1 - mov r14,r2 - mov r14,r3 - add #24,r3 - mov.b @r3,r2 - mov.b r2,@r1 - mov.l @(12,r14),r1 - mov r1,r2 - add #1,r2 - mov.l r2,@(12,r14) - bra .L7 - nop - .align 2 -.L8: -.L6: - bra .L5 - nop - .align 2 -.L10: - bra .L4 - nop - .align 2 -.L5: - nop -.L11: - mov.l @(16,r14),r1 + ! if dest > src, call memcpy (it copies in decreasing order) + cmp/hi r5,r4 + bf 1f + mov.l 2f,r0 + jmp @r0 + nop + .balign 4 +2: .long SYMBOL_NAME(memcpy) +1: + sub r5,r4 ! From here, r4 has the distance to r0 + tst r6,r6 + bt/s 9f ! if n=0, do nothing + mov r5,r0 + add r6,r5 + mov #12,r1 + cmp/gt r6,r1 + bt/s 8f ! if it's too small, copy a byte at once + add #-1,r4 + add #1,r4 + ! + ! [ ... ] DST [ ... ] SRC + ! [ ... ] [ ... ] + ! : : + ! r0+r4--> [ ... ] r0 --> [ ... ] + ! : : + ! [ ... ] [ ... ] + ! r5 --> + ! + mov r4,r1 mov #3,r2 - and r1,r2 - tst r2,r2 - bf .L14 - mov r15,r2 - mov.l @(12,r14),r1 - mov.l @(16,r14),r2 - mov.l @(8,r14),r7 - mov r7,r3 - shlr2 r3 - mov r1,r4 - mov r2,r5 - mov r3,r6 - mov.l .L46,r8 - jsr @r8 - nop - bra .L15 - nop - .align 2 -.L14: - mov r15,r2 - mov.l @(12,r14),r1 - mov.l @(16,r14),r2 - mov.l @(8,r14),r7 - mov r7,r3 - shlr2 r3 - mov r1,r4 - mov r2,r5 - mov r3,r6 - mov.l .L47,r8 - jsr @r8 - nop -.L15: - mov.l @(8,r14),r1 - mov #-4,r2 - and r2,r1 - mov.l @(16,r14),r2 - add r2,r1 - mov.l r1,@(16,r14) - mov.l @(8,r14),r1 - mov #-4,r2 and r2,r1 - mov.l @(12,r14),r2 - add r2,r1 - mov.l r1,@(12,r14) - mov.l @(8,r14),r1 - mov #3,r2 - and r1,r2 - mov.l r2,@(8,r14) -.L13: -.L52: - bra .L3 - nop - .align 2 -.L16: - bra .L11 - nop - .align 2 -.L12: -.L3: - nop -.L17: - mov.l @(8,r14),r1 - mov.l r1,@(20,r14) -.L20: - mov.l @(20,r14),r1 - cmp/pl r1 - bt .L22 - bra .L19 - nop - .align 2 -.L22: - mov r14,r2 - mov r14,r1 - add #24,r1 - mov.l @(16,r14),r2 - mov.b @r2,r3 - mov.b r3,@r1 - mov.l @(16,r14),r1 - mov r1,r2 - add #1,r2 - mov.l r2,@(16,r14) - mov.l @(20,r14),r1 - mov r1,r2 - add #-1,r2 - mov.l r2,@(20,r14) - mov.l @(12,r14),r1 - mov r14,r2 - mov r14,r3 - add #24,r3 - mov.b @r3,r2 - mov.b r2,@r1 - mov.l @(12,r14),r1 + shll2 r1 + mov r0,r3 ! Save the value on R0 to R3 + mova jmptable,r0 + add r1,r0 + mov.l @r0,r1 + jmp @r1 + mov r3,r0 ! and back to R0 + .balign 4 +jmptable: + .long case0 + .long case1 + .long case2 + .long case3 + + ! copy a byte at once +8: mov.b @r0+,r1 + cmp/hs r5,r0 + bf/s 8b ! while (r0 GHIJ KLMN OPQR + ! + ! First, align to long word boundary + mov r0,r3 + and r2,r3 + tst r3,r3 + bt/s 2f + add #-1,r4 + mov #4,r2 + sub r3,r2 +1: dt r2 + mov.b @r0+,r1 + bf/s 1b + mov.b r1,@(r0,r4) + ! +2: ! Second, copy a long word at once + add #-3,r4 + add #-3,r5 +3: mov.l @r0+,r1 + cmp/hs r5,r0 + bf/s 3b + mov.l r1,@(r0,r4) + add #3,r5 + ! + ! Third, copy a byte at once, if necessary + cmp/eq r5,r0 + bt/s 9b + add #4,r4 + bra 8b + add #-1,r4 + +case3: + ! + ! GHIJ KLMN OPQR --> ...G HIJK LMNO PQR. + ! + ! First, align to long word boundary + mov r0,r3 + and r2,r3 + tst r3,r3 + bt/s 2f + add #-1,r4 + mov #4,r2 + sub r3,r2 +1: dt r2 + mov.b @r0+,r1 + bf/s 1b + mov.b r1,@(r0,r4) + ! +2: ! Second, read a long word and write a long word at once + add #-2,r4 + mov.l @(r0,r4),r1 + add #-7,r5 + add #-4,r4 + ! +#ifdef __LITTLE_ENDIAN__ + shll8 r1 +3: mov r1,r3 ! JIHG + shlr8 r3 ! xJIH + mov.l @r0+,r1 ! NMLK mov r1,r2 - add #1,r2 - mov.l r2,@(12,r14) - bra .L20 - nop - .align 2 -.L21: -.L19: - bra .L18 - nop - .align 2 -.L23: - bra .L17 - nop - .align 2 -.L18: - bra .L24 - nop - .align 2 -.L2: - mov.l @(16,r14),r1 - mov.l @(8,r14),r2 - add r2,r1 - mov.l r1,@(16,r14) - mov.l @(12,r14),r1 - mov.l @(8,r14),r2 - add r2,r1 - mov.l r1,@(12,r14) - mov.l @(8,r14),r1 - mov #15,r2 - cmp/gt r2,r1 - bt .LF101 - bra .L53 - nop -.LF101: - mov.l @(12,r14),r1 - mov #3,r2 - and r1,r2 - mov.l @(8,r14),r1 - mov r1,r9 - sub r2,r9 - mov r9,r2 - mov.l r2,@(8,r14) -.L26: - mov.l @(12,r14),r1 - mov #3,r2 - and r1,r2 - mov.l r2,@(20,r14) -.L29: - mov.l @(20,r14),r1 - cmp/pl r1 - bt .L31 - bra .L28 - nop - .align 2 -.L31: - mov.l @(16,r14),r1 - mov r1,r2 - add #-1,r2 - mov.l r2,@(16,r14) - mov r14,r2 - mov r14,r1 - add #24,r1 - mov.l @(16,r14),r2 - mov.b @r2,r3 - mov.b r3,@r1 - mov.l @(12,r14),r1 - mov r1,r2 - add #-1,r2 - mov.l r2,@(12,r14) - mov.l @(20,r14),r1 - mov r1,r2 - add #-1,r2 - mov.l r2,@(20,r14) - mov.l @(12,r14),r1 - mov r14,r2 - mov r14,r3 - add #24,r3 - mov.b @r3,r2 - mov.b r2,@r1 - bra .L29 - nop - .align 2 -.L30: -.L28: - bra .L27 - nop - .align 2 -.L32: - bra .L26 - nop - .align 2 -.L27: - nop -.L33: - mov.l @(16,r14),r1 - mov #3,r2 - and r1,r2 - tst r2,r2 - bf .L36 - mov r15,r2 - mov.l @(12,r14),r1 - mov.l @(16,r14),r2 - mov.l @(8,r14),r7 - mov r7,r3 - shlr2 r3 - mov r1,r4 - mov r2,r5 - mov r3,r6 - mov.l .L48,r8 - jsr @r8 - nop - bra .L37 - nop - .align 2 -.L36: - mov r15,r2 - mov.l @(12,r14),r1 - mov.l @(16,r14),r2 - mov.l @(8,r14),r7 - mov r7,r3 - shlr2 r3 - mov r1,r4 - mov r2,r5 - mov r3,r6 - mov.l .L49,r8 - jsr @r8 - nop -.L37: - mov.l @(8,r14),r1 - mov #-4,r2 - and r2,r1 - mov.l @(16,r14),r2 - mov r2,r9 - sub r1,r9 - mov r9,r1 - mov.l r1,@(16,r14) - mov.l @(8,r14),r1 - mov #-4,r2 - and r2,r1 - mov.l @(12,r14),r2 - mov r2,r9 - sub r1,r9 - mov r9,r1 - mov.l r1,@(12,r14) - mov.l @(8,r14),r1 - mov #3,r2 - and r1,r2 - mov.l r2,@(8,r14) -.L35: -.L53: - bra .L25 - nop - .align 2 -.L38: - bra .L33 - nop - .align 2 -.L34: -.L25: - nop -.L39: - mov.l @(8,r14),r1 - mov.l r1,@(20,r14) -.L42: - mov.l @(20,r14),r1 - cmp/pl r1 - bt .L44 - bra .L41 - nop - .align 2 -.L44: - mov.l @(16,r14),r1 + shll16 r2 + shll8 r2 ! Kxxx + or r2,r3 ! KJIH + cmp/hs r5,r0 + bf/s 3b + mov.l r3,@(r0,r4) +#else + shlr8 r1 +3: mov r1,r3 ! GHIJ + shll8 r3 ! HIJx + mov.l @r0+,r1 ! KLMN mov r1,r2 - add #-1,r2 - mov.l r2,@(16,r14) - mov r14,r2 - mov r14,r1 - add #24,r1 - mov.l @(16,r14),r2 - mov.b @r2,r3 - mov.b r3,@r1 - mov.l @(12,r14),r1 + shlr16 r2 + shlr8 r2 ! xxxK + or r2,r3 ! HIJK + cmp/hs r5,r0 + bf/s 3b + mov.l r3,@(r0,r4) +#endif + add #7,r5 + ! + ! Third, copy a byte at once, if necessary + cmp/eq r5,r0 + bt/s 9b + add #7,r4 + add #-3,r0 + bra 8b + add #-1,r4 + +case2: + ! + ! GHIJ KLMN OPQR --> ..GH IJKL MNOP QR.. + ! + ! First, align to word boundary + tst #1,r0 + bt/s 2f + add #-1,r4 + mov.b @r0+,r1 + mov.b r1,@(r0,r4) + ! +2: ! Second, read a word and write a word at once + add #-1,r4 + add #-1,r5 + ! +3: mov.w @r0+,r1 + cmp/hs r5,r0 + bf/s 3b + mov.w r1,@(r0,r4) + add #1,r5 + ! + ! Third, copy a byte at once, if necessary + cmp/eq r5,r0 + bt/s 9b + add #2,r4 + mov.b @r0,r1 + mov.b r1,@(r0,r4) + bra 9b + add #1,r0 + +case1: + ! + ! GHIJ KLMN OPQR --> .GHI JKLM NOPQ R... + ! + ! First, align to long word boundary + mov r0,r3 + and r2,r3 + tst r3,r3 + bt/s 2f + add #-1,r4 + mov #4,r2 + sub r3,r2 +1: dt r2 + mov.b @r0+,r1 + bf/s 1b + mov.b r1,@(r0,r4) + ! +2: ! Second, read a long word and write a long word at once + mov.l @(r0,r4),r1 + add #-7,r5 + add #-4,r4 + ! +#ifdef __LITTLE_ENDIAN__ + shll16 r1 + shll8 r1 +3: mov r1,r3 ! JIHG + shlr16 r3 + shlr8 r3 ! xxxJ + mov.l @r0+,r1 ! NMLK mov r1,r2 - add #-1,r2 - mov.l r2,@(12,r14) - mov.l @(20,r14),r1 + shll8 r2 ! MLKx + or r2,r3 ! MLKJ + cmp/hs r5,r0 + bf/s 3b + mov.l r3,@(r0,r4) +#else + shlr16 r1 + shlr8 r1 +3: mov r1,r3 ! GHIJ + shll16 r3 + shll8 r3 ! Jxxx + mov.l @r0+,r1 ! KLMN mov r1,r2 - add #-1,r2 - mov.l r2,@(20,r14) - mov.l @(12,r14),r1 - mov r14,r2 - mov r14,r3 - add #24,r3 - mov.b @r3,r2 - mov.b r2,@r1 - bra .L42 - nop - .align 2 -.L43: -.L41: - bra .L24 - nop - .align 2 -.L45: - bra .L39 - nop - .align 2 -.L40: -.L24: - mov.l @r14,r1 - mov r1,r0 - bra .L1 - nop - .align 2 -.L1: - add #28,r14 - mov r14,r15 - lds.l @r15+,pr - mov.l @r15+,r14 - mov.l @r15+,r9 - mov.l @r15+,r8 - rts - nop -.L50: - .align 2 -.L46: - .long __wordcopy_fwd_aligned -.L47: - .long __wordcopy_fwd_dest_aligned -.L48: - .long __wordcopy_bwd_aligned -.L49: - .long __wordcopy_bwd_dest_aligned -.Lfe1: + shlr8 r2 ! xKLM + or r2,r3 ! JKLM + cmp/hs r5,r0 + bf/s 3b ! while(r0 ENTRY(memset) - mov r4,r3 ! Save return value - - mov r6,r0 ! Check explicitly for zero - cmp/eq #0,r0 - bt L_exit - - mov #12,r0 ! Check for small number of bytes + tst r6,r6 + bt/s 5f ! if n=0, do nothing + add r6,r4 + mov #12,r0 cmp/gt r6,r0 - bt L_store_byte_loop - - neg r4,r0 ! Align destination - add #4,r0 + bt/s 4f ! if it's too small, set a byte at once + mov r4,r0 and #3,r0 - tst r0,r0 - bt L_dup_bytes - .balignw 4,0x0009 -L_align_loop: - mov.b r5,@r4 - add #-1,r6 - add #1,r4 + cmp/eq #0,r0 + bt/s 2f ! It's aligned + sub r0,r6 +1: dt r0 - bf L_align_loop - -L_dup_bytes: - extu.b r5,r5 ! Duplicate bytes across longword - swap.b r5,r0 - or r0,r5 - swap.w r5,r0 - or r0,r5 - - mov r6,r2 ! Calculate number of double longwords - shlr2 r2 - shlr r2 - - .balignw 4,0x0009 -L_store_long_loop: - mov.l r5,@r4 ! Store double longs to memory - dt r2 - mov.l r5,@(4,r4) - add #8,r4 - bf L_store_long_loop - + bf/s 1b + mov.b r5,@-r4 +2: ! make VVVV + swap.b r5,r0 ! V0 + or r0,r5 ! VV + swap.w r5,r0 ! VV00 + or r0,r5 ! VVVV + ! + mov r6,r0 + shlr2 r0 + shlr r0 ! r0 = r6 >> 3 +3: + dt r0 + mov.l r5,@-r4 ! set 8-byte at once + bf/s 3b + mov.l r5,@-r4 + ! mov #7,r0 and r0,r6 tst r6,r6 - bt L_exit - .balignw 4,0x0009 -L_store_byte_loop: - mov.b r5,@r4 ! Store bytes to memory - add #1,r4 + bt 5f + ! fill bytes +4: dt r6 - bf L_store_byte_loop - -L_exit: + bf/s 4b + mov.b r5,@-r4 +5: rts - mov r3,r0 + mov r4,r0 diff --git a/arch/sh/lib/old-checksum.c b/arch/sh/lib/old-checksum.c index ae3a38043a7f..df741335d367 100644 --- a/arch/sh/lib/old-checksum.c +++ b/arch/sh/lib/old-checksum.c @@ -15,5 +15,3 @@ unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum) return sum; } - - diff --git a/arch/sh/lib/wordcopy.S b/arch/sh/lib/wordcopy.S deleted file mode 100644 index c116623d0abc..000000000000 --- a/arch/sh/lib/wordcopy.S +++ /dev/null @@ -1,1289 +0,0 @@ -#include -ENTRY(_wordcopy_fwd_aligned) - mov.l r14,@-r15 - add #-20,r15 - mov r15,r14 - mov.l r4,@r14 - mov.l r5,@(4,r14) - mov.l r6,@(8,r14) - mov.l @(8,r14),r2 - mov #7,r1 - and r2,r1 - mov #0,r2 - mov #7,r3 - sub r2,r1 - cmp/hi r3,r1 - bf .L29 - bra .L2 - nop -.L29: - mova .L22,r0 - add r1,r1 - mov.w @(r0,r1),r1 - add r0,r1 - jmp @r1 - nop - .align 2 - .align 2 -.L22: - .word .L15-.L22 - .word .L18-.L22 - .word .L3-.L22 - .word .L5-.L22 - .word .L7-.L22 - .word .L9-.L22 - .word .L11-.L22 - .word .L13-.L22 - .align 2 -.L3: - mov.l @(4,r14),r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @(4,r14),r1 - mov r1,r2 - add #-24,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-28,r2 - mov.l r2,@r14 - mov.l @(8,r14),r1 - mov r1,r2 - add #6,r2 - mov.l r2,@(8,r14) - bra .L4 - nop - .align 2 -.L5: - mov.l @(4,r14),r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @(4,r14),r1 - mov r1,r2 - add #-20,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-24,r2 - mov.l r2,@r14 - mov.l @(8,r14),r1 - mov r1,r2 - add #5,r2 - mov.l r2,@(8,r14) - bra .L6 - nop - .align 2 -.L7: - mov.l @(4,r14),r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @(4,r14),r1 - mov r1,r2 - add #-16,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-20,r2 - mov.l r2,@r14 - mov.l @(8,r14),r1 - mov r1,r2 - add #4,r2 - mov.l r2,@(8,r14) - bra .L8 - nop - .align 2 -.L9: - mov.l @(4,r14),r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @(4,r14),r1 - mov r1,r2 - add #-12,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-16,r2 - mov.l r2,@r14 - mov.l @(8,r14),r1 - mov r1,r2 - add #3,r2 - mov.l r2,@(8,r14) - bra .L10 - nop - .align 2 -.L11: - mov.l @(4,r14),r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @(4,r14),r1 - mov r1,r2 - add #-8,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-12,r2 - mov.l r2,@r14 - mov.l @(8,r14),r1 - mov r1,r2 - add #2,r2 - mov.l r2,@(8,r14) - bra .L12 - nop - .align 2 -.L13: - mov.l @(4,r14),r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @(4,r14),r1 - mov r1,r2 - add #-4,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-8,r2 - mov.l r2,@r14 - mov.l @(8,r14),r1 - mov r1,r2 - add #1,r2 - mov.l r2,@(8,r14) - bra .L14 - nop - .align 2 -.L15: - bra .L16 - nop - bra .L1 - nop - .align 2 -.L16: - mov.l @(4,r14),r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @r14,r1 - mov r1,r2 - add #-4,r2 - mov.l r2,@r14 - bra .L17 - nop - .align 2 -.L18: - mov.l @(4,r14),r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @(4,r14),r1 - mov r1,r2 - add #4,r2 - mov.l r2,@(4,r14) - mov.l @(8,r14),r1 - mov r1,r2 - add #-1,r2 - mov.l r2,@(8,r14) - bra .L19 - nop - bra .L20 - nop - .align 2 -.L19: - bra .L21 - nop - .align 2 -.L23: -.L2: - nop -.L24: -.L21: - mov.l @(4,r14),r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @r14,r1 - mov.l @(16,r14),r2 - mov.l r2,@r1 -.L17: - mov.l @(4,r14),r2 - mov r2,r1 - add #4,r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @r14,r2 - mov r2,r1 - add #4,r1 - mov.l @(12,r14),r2 - mov.l r2,@r1 -.L14: - mov.l @(4,r14),r2 - mov r2,r1 - add #8,r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @r14,r2 - mov r2,r1 - add #8,r1 - mov.l @(16,r14),r2 - mov.l r2,@r1 -.L12: - mov.l @(4,r14),r2 - mov r2,r1 - add #12,r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @r14,r2 - mov r2,r1 - add #12,r1 - mov.l @(12,r14),r2 - mov.l r2,@r1 -.L10: - mov.l @(4,r14),r2 - mov r2,r1 - add #16,r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @r14,r2 - mov r2,r1 - add #16,r1 - mov.l @(16,r14),r2 - mov.l r2,@r1 -.L8: - mov.l @(4,r14),r2 - mov r2,r1 - add #20,r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @r14,r2 - mov r2,r1 - add #20,r1 - mov.l @(12,r14),r2 - mov.l r2,@r1 -.L6: - mov.l @(4,r14),r2 - mov r2,r1 - add #24,r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @r14,r2 - mov r2,r1 - add #24,r1 - mov.l @(16,r14),r2 - mov.l r2,@r1 -.L4: - mov.l @(4,r14),r2 - mov r2,r1 - add #28,r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @r14,r2 - mov r2,r1 - add #28,r1 - mov.l @(12,r14),r2 - mov.l r2,@r1 - mov.l @(4,r14),r1 - mov r1,r2 - add #32,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #32,r2 - mov.l r2,@r14 - mov.l @(8,r14),r1 - mov r1,r2 - add #-8,r2 - mov.l r2,@(8,r14) -.L26: - mov.l @(8,r14),r1 - tst r1,r1 - bf .L27 - bra .L25 - nop - .align 2 -.L27: - bra .L21 - nop - .align 2 -.L25: - nop -.L20: - mov.l @r14,r1 - mov.l @(16,r14),r2 - mov.l r2,@r1 -.L1: - add #20,r14 - mov r14,r15 - mov.l @r15+,r14 - rts - nop -.Lfe1: - .size __wordcopy_fwd_aligned,.Lfe1-__wordcopy_fwd_aligned - .global ___lshrsi3 - .global ___ashlsi3 - .align 2 - .global __wordcopy_fwd_dest_aligned - .type __wordcopy_fwd_dest_aligned,@function -__wordcopy_fwd_dest_aligned: - mov.l r8,@-r15 - mov.l r9,@-r15 - mov.l r14,@-r15 - sts.l pr,@-r15 - add #-40,r15 - mov r15,r14 - mov.l r4,@r14 - mov.l r5,@(4,r14) - mov.l r6,@(8,r14) - mov.l @(4,r14),r1 - mov #3,r2 - and r1,r2 - mov r2,r1 - mov r1,r2 - shll2 r2 - add r2,r2 - mov.l r2,@(28,r14) - mov.l @(28,r14),r2 - neg r2,r1 - add #32,r1 - mov.l r1,@(32,r14) - mov.l @(4,r14),r1 - mov #-4,r2 - and r2,r1 - mov.l r1,@(4,r14) - mov.l @(8,r14),r2 - mov #3,r1 - and r2,r1 - mov #0,r2 - mov #3,r3 - sub r2,r1 - cmp/hi r3,r1 - bf .L53 - bra .L31 - nop -.L53: - mova .L43,r0 - add r1,r1 - mov.w @(r0,r1),r1 - add r0,r1 - jmp @r1 - nop - .align 2 - .align 2 -.L43: - .word .L36-.L43 - .word .L39-.L43 - .word .L32-.L43 - .word .L34-.L43 - .align 2 -.L32: - mov.l @(4,r14),r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @(4,r14),r2 - mov r2,r1 - add #4,r1 - mov.l @r1,r2 - mov.l r2,@(20,r14) - mov.l @(4,r14),r1 - mov r1,r2 - add #-4,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-12,r2 - mov.l r2,@r14 - mov.l @(8,r14),r1 - mov r1,r2 - add #2,r2 - mov.l r2,@(8,r14) - bra .L33 - nop - .align 2 -.L34: - mov.l @(4,r14),r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @(4,r14),r2 - mov r2,r1 - add #4,r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @r14,r1 - mov r1,r2 - add #-8,r2 - mov.l r2,@r14 - mov.l @(8,r14),r1 - mov r1,r2 - add #1,r2 - mov.l r2,@(8,r14) - bra .L35 - nop - .align 2 -.L36: - bra .L37 - nop - bra .L30 - nop - .align 2 -.L37: - mov.l @(4,r14),r1 - mov.l @r1,r2 - mov.l r2,@(24,r14) - mov.l @(4,r14),r2 - mov r2,r1 - add #4,r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @(4,r14),r1 - mov r1,r2 - add #4,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-4,r2 - mov.l r2,@r14 - bra .L38 - nop - .align 2 -.L39: - mov.l @(4,r14),r1 - mov.l @r1,r2 - mov.l r2,@(20,r14) - mov.l @(4,r14),r2 - mov r2,r1 - add #4,r1 - mov.l @r1,r2 - mov.l r2,@(24,r14) - mov.l @(4,r14),r1 - mov r1,r2 - add #8,r2 - mov.l r2,@(4,r14) - mov.l @(8,r14),r1 - mov r1,r2 - add #-1,r2 - mov.l r2,@(8,r14) - bra .L40 - nop - bra .L41 - nop - .align 2 -.L40: - bra .L42 - nop - .align 2 -.L44: -.L31: - nop -.L45: -.L42: - mov.l @(4,r14),r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @r14,r8 - mov.l .L49,r1 - mov.l @(20,r14),r4 - mov.l @(28,r14),r5 - jsr @r1 - nop - mov r0,r9 - mov.l .L50,r1 - mov.l @(24,r14),r4 - mov.l @(32,r14),r5 - jsr @r1 - nop - mov.l r0,@(36,r14) - mov.l @(36,r14),r1 - or r9,r1 - mov.l r1,@r8 -.L38: - mov.l @(4,r14),r2 - mov r2,r1 - add #4,r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @r14,r1 - mov r1,r8 - add #4,r8 - mov.l .L49,r1 - mov.l @(24,r14),r4 - mov.l @(28,r14),r5 - jsr @r1 - nop - mov r0,r9 - mov.l .L50,r1 - mov.l @(12,r14),r4 - mov.l @(32,r14),r5 - jsr @r1 - nop - mov.l r0,@(36,r14) - mov.l @(36,r14),r1 - or r9,r1 - mov.l r1,@r8 -.L35: - mov.l @(4,r14),r2 - mov r2,r1 - add #8,r1 - mov.l @r1,r2 - mov.l r2,@(20,r14) - mov.l @r14,r1 - mov r1,r8 - add #8,r8 - mov.l .L49,r1 - mov.l @(12,r14),r4 - mov.l @(28,r14),r5 - jsr @r1 - nop - mov r0,r9 - mov.l .L50,r1 - mov.l @(16,r14),r4 - mov.l @(32,r14),r5 - jsr @r1 - nop - mov.l r0,@(36,r14) - mov.l @(36,r14),r1 - or r9,r1 - mov.l r1,@r8 -.L33: - mov.l @(4,r14),r2 - mov r2,r1 - add #12,r1 - mov.l @r1,r2 - mov.l r2,@(24,r14) - mov.l @r14,r1 - mov r1,r8 - add #12,r8 - mov.l .L49,r1 - mov.l @(16,r14),r4 - mov.l @(28,r14),r5 - jsr @r1 - nop - mov r0,r9 - mov.l .L50,r1 - mov.l @(20,r14),r4 - mov.l @(32,r14),r5 - jsr @r1 - nop - mov.l r0,@(36,r14) - mov.l @(36,r14),r1 - or r9,r1 - mov.l r1,@r8 - mov.l @(4,r14),r1 - mov r1,r2 - add #16,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #16,r2 - mov.l r2,@r14 - mov.l @(8,r14),r1 - mov r1,r2 - add #-4,r2 - mov.l r2,@(8,r14) -.L47: - mov.l @(8,r14),r1 - tst r1,r1 - bf .L48 - bra .L46 - nop - .align 2 -.L48: - bra .L42 - nop - .align 2 -.L46: - nop -.L41: - mov.l @r14,r8 - mov.l .L49,r1 - mov.l @(20,r14),r4 - mov.l @(28,r14),r5 - jsr @r1 - nop - mov r0,r9 - mov.l .L50,r1 - mov.l @(24,r14),r4 - mov.l @(32,r14),r5 - jsr @r1 - nop - mov.l r0,@(36,r14) - mov.l @(36,r14),r1 - or r9,r1 - mov.l r1,@r8 -.L30: - add #40,r14 - mov r14,r15 - lds.l @r15+,pr - mov.l @r15+,r14 - mov.l @r15+,r9 - mov.l @r15+,r8 - rts - nop -.L51: - .align 2 -.L49: - .long ___lshrsi3 -.L50: - .long ___ashlsi3 -.Lfe2: - .size __wordcopy_fwd_dest_aligned,.Lfe2-__wordcopy_fwd_dest_aligned - .align 2 - .global __wordcopy_bwd_aligned - .type __wordcopy_bwd_aligned,@function -__wordcopy_bwd_aligned: - mov.l r14,@-r15 - add #-20,r15 - mov r15,r14 - mov.l r4,@r14 - mov.l r5,@(4,r14) - mov.l r6,@(8,r14) - mov.l @(8,r14),r2 - mov #7,r1 - and r2,r1 - mov #0,r2 - mov #7,r3 - sub r2,r1 - cmp/hi r3,r1 - bf .L82 - bra .L55 - nop -.L82: - mova .L75,r0 - add r1,r1 - mov.w @(r0,r1),r1 - add r0,r1 - jmp @r1 - nop - .align 2 - .align 2 -.L75: - .word .L68-.L75 - .word .L71-.L75 - .word .L56-.L75 - .word .L58-.L75 - .word .L60-.L75 - .word .L62-.L75 - .word .L64-.L75 - .word .L66-.L75 - .align 2 -.L56: - mov.l @(4,r14),r1 - mov r1,r2 - add #-8,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-4,r2 - mov.l r2,@r14 - mov.l @(4,r14),r2 - mov r2,r1 - add #4,r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @(8,r14),r1 - mov r1,r2 - add #6,r2 - mov.l r2,@(8,r14) - bra .L57 - nop - .align 2 -.L58: - mov.l @(4,r14),r1 - mov r1,r2 - add #-12,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-8,r2 - mov.l r2,@r14 - mov.l @(4,r14),r2 - mov r2,r1 - add #8,r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @(8,r14),r1 - mov r1,r2 - add #5,r2 - mov.l r2,@(8,r14) - bra .L59 - nop - .align 2 -.L60: - mov.l @(4,r14),r1 - mov r1,r2 - add #-16,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-12,r2 - mov.l r2,@r14 - mov.l @(4,r14),r2 - mov r2,r1 - add #12,r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @(8,r14),r1 - mov r1,r2 - add #4,r2 - mov.l r2,@(8,r14) - bra .L61 - nop - .align 2 -.L62: - mov.l @(4,r14),r1 - mov r1,r2 - add #-20,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-16,r2 - mov.l r2,@r14 - mov.l @(4,r14),r2 - mov r2,r1 - add #16,r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @(8,r14),r1 - mov r1,r2 - add #3,r2 - mov.l r2,@(8,r14) - bra .L63 - nop - .align 2 -.L64: - mov.l @(4,r14),r1 - mov r1,r2 - add #-24,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-20,r2 - mov.l r2,@r14 - mov.l @(4,r14),r2 - mov r2,r1 - add #20,r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @(8,r14),r1 - mov r1,r2 - add #2,r2 - mov.l r2,@(8,r14) - bra .L65 - nop - .align 2 -.L66: - mov.l @(4,r14),r1 - mov r1,r2 - add #-28,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-24,r2 - mov.l r2,@r14 - mov.l @(4,r14),r2 - mov r2,r1 - add #24,r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @(8,r14),r1 - mov r1,r2 - add #1,r2 - mov.l r2,@(8,r14) - bra .L67 - nop - .align 2 -.L68: - bra .L69 - nop - bra .L54 - nop - .align 2 -.L69: - mov.l @(4,r14),r1 - mov r1,r2 - add #-32,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-28,r2 - mov.l r2,@r14 - mov.l @(4,r14),r2 - mov r2,r1 - add #28,r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - bra .L70 - nop - .align 2 -.L71: - mov.l @(4,r14),r1 - mov r1,r2 - add #-36,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-32,r2 - mov.l r2,@r14 - mov.l @(4,r14),r2 - mov r2,r1 - add #32,r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @(8,r14),r1 - mov r1,r2 - add #-1,r2 - mov.l r2,@(8,r14) - bra .L72 - nop - bra .L73 - nop - .align 2 -.L72: - bra .L74 - nop - .align 2 -.L76: -.L55: - nop -.L77: -.L74: - mov.l @(4,r14),r2 - mov r2,r1 - add #28,r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @r14,r2 - mov r2,r1 - add #28,r1 - mov.l @(16,r14),r2 - mov.l r2,@r1 -.L70: - mov.l @(4,r14),r2 - mov r2,r1 - add #24,r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @r14,r2 - mov r2,r1 - add #24,r1 - mov.l @(12,r14),r2 - mov.l r2,@r1 -.L67: - mov.l @(4,r14),r2 - mov r2,r1 - add #20,r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @r14,r2 - mov r2,r1 - add #20,r1 - mov.l @(16,r14),r2 - mov.l r2,@r1 -.L65: - mov.l @(4,r14),r2 - mov r2,r1 - add #16,r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @r14,r2 - mov r2,r1 - add #16,r1 - mov.l @(12,r14),r2 - mov.l r2,@r1 -.L63: - mov.l @(4,r14),r2 - mov r2,r1 - add #12,r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @r14,r2 - mov r2,r1 - add #12,r1 - mov.l @(16,r14),r2 - mov.l r2,@r1 -.L61: - mov.l @(4,r14),r2 - mov r2,r1 - add #8,r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @r14,r2 - mov r2,r1 - add #8,r1 - mov.l @(12,r14),r2 - mov.l r2,@r1 -.L59: - mov.l @(4,r14),r2 - mov r2,r1 - add #4,r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @r14,r2 - mov r2,r1 - add #4,r1 - mov.l @(16,r14),r2 - mov.l r2,@r1 -.L57: - mov.l @(4,r14),r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @r14,r1 - mov.l @(12,r14),r2 - mov.l r2,@r1 - mov.l @(4,r14),r1 - mov r1,r2 - add #-32,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-32,r2 - mov.l r2,@r14 - mov.l @(8,r14),r1 - mov r1,r2 - add #-8,r2 - mov.l r2,@(8,r14) -.L79: - mov.l @(8,r14),r1 - tst r1,r1 - bf .L80 - bra .L78 - nop - .align 2 -.L80: - bra .L74 - nop - .align 2 -.L78: - nop -.L73: - mov.l @r14,r2 - mov r2,r1 - add #28,r1 - mov.l @(16,r14),r2 - mov.l r2,@r1 -.L54: - add #20,r14 - mov r14,r15 - mov.l @r15+,r14 - rts - nop -.Lfe3: - .size __wordcopy_bwd_aligned,.Lfe3-__wordcopy_bwd_aligned - .align 2 - .global __wordcopy_bwd_dest_aligned - .type __wordcopy_bwd_dest_aligned,@function -__wordcopy_bwd_dest_aligned: - mov.l r8,@-r15 - mov.l r9,@-r15 - mov.l r14,@-r15 - sts.l pr,@-r15 - add #-40,r15 - mov r15,r14 - mov.l r4,@r14 - mov.l r5,@(4,r14) - mov.l r6,@(8,r14) - mov.l @(4,r14),r1 - mov #3,r2 - and r1,r2 - mov r2,r1 - mov r1,r2 - shll2 r2 - add r2,r2 - mov.l r2,@(28,r14) - mov.l @(28,r14),r2 - neg r2,r1 - add #32,r1 - mov.l r1,@(32,r14) - mov.l @(4,r14),r1 - mov #-4,r2 - and r2,r1 - mov.l r1,@(4,r14) - mov.l @(4,r14),r1 - mov r1,r2 - add #4,r2 - mov.l r2,@(4,r14) - mov.l @(8,r14),r2 - mov #3,r1 - and r2,r1 - mov #0,r2 - mov #3,r3 - sub r2,r1 - cmp/hi r3,r1 - bf .L106 - bra .L84 - nop -.L106: - mova .L96,r0 - add r1,r1 - mov.w @(r0,r1),r1 - add r0,r1 - jmp @r1 - nop - .align 2 - .align 2 -.L96: - .word .L89-.L96 - .word .L92-.L96 - .word .L85-.L96 - .word .L87-.L96 - .align 2 -.L85: - mov.l @(4,r14),r1 - mov r1,r2 - add #-12,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-4,r2 - mov.l r2,@r14 - mov.l @(4,r14),r2 - mov r2,r1 - add #8,r1 - mov.l @r1,r2 - mov.l r2,@(20,r14) - mov.l @(4,r14),r2 - mov r2,r1 - add #4,r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @(8,r14),r1 - mov r1,r2 - add #2,r2 - mov.l r2,@(8,r14) - bra .L86 - nop - .align 2 -.L87: - mov.l @(4,r14),r1 - mov r1,r2 - add #-16,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-8,r2 - mov.l r2,@r14 - mov.l @(4,r14),r2 - mov r2,r1 - add #12,r1 - mov.l @r1,r2 - mov.l r2,@(24,r14) - mov.l @(4,r14),r2 - mov r2,r1 - add #8,r1 - mov.l @r1,r2 - mov.l r2,@(20,r14) - mov.l @(8,r14),r1 - mov r1,r2 - add #1,r2 - mov.l r2,@(8,r14) - bra .L88 - nop - .align 2 -.L89: - bra .L90 - nop - bra .L83 - nop - .align 2 -.L90: - mov.l @(4,r14),r1 - mov r1,r2 - add #-20,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-12,r2 - mov.l r2,@r14 - mov.l @(4,r14),r2 - mov r2,r1 - add #16,r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @(4,r14),r2 - mov r2,r1 - add #12,r1 - mov.l @r1,r2 - mov.l r2,@(24,r14) - bra .L91 - nop - .align 2 -.L92: - mov.l @(4,r14),r1 - mov r1,r2 - add #-24,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-16,r2 - mov.l r2,@r14 - mov.l @(4,r14),r2 - mov r2,r1 - add #20,r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @(4,r14),r2 - mov r2,r1 - add #16,r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @(8,r14),r1 - mov r1,r2 - add #-1,r2 - mov.l r2,@(8,r14) - bra .L93 - nop - bra .L94 - nop - .align 2 -.L93: - bra .L95 - nop - .align 2 -.L97: -.L84: - nop -.L98: -.L95: - mov.l @(4,r14),r2 - mov r2,r1 - add #12,r1 - mov.l @r1,r2 - mov.l r2,@(24,r14) - mov.l @r14,r1 - mov r1,r8 - add #12,r8 - mov.l .L102,r1 - mov.l @(12,r14),r4 - mov.l @(28,r14),r5 - jsr @r1 - nop - mov r0,r9 - mov.l .L103,r1 - mov.l @(16,r14),r4 - mov.l @(32,r14),r5 - jsr @r1 - nop - mov.l r0,@(36,r14) - mov.l @(36,r14),r1 - or r9,r1 - mov.l r1,@r8 -.L91: - mov.l @(4,r14),r2 - mov r2,r1 - add #8,r1 - mov.l @r1,r2 - mov.l r2,@(20,r14) - mov.l @r14,r1 - mov r1,r8 - add #8,r8 - mov.l .L102,r1 - mov.l @(24,r14),r4 - mov.l @(28,r14),r5 - jsr @r1 - nop - mov r0,r9 - mov.l .L103,r1 - mov.l @(12,r14),r4 - mov.l @(32,r14),r5 - jsr @r1 - nop - mov.l r0,@(36,r14) - mov.l @(36,r14),r1 - or r9,r1 - mov.l r1,@r8 -.L88: - mov.l @(4,r14),r2 - mov r2,r1 - add #4,r1 - mov.l @r1,r2 - mov.l r2,@(16,r14) - mov.l @r14,r1 - mov r1,r8 - add #4,r8 - mov.l .L102,r1 - mov.l @(20,r14),r4 - mov.l @(28,r14),r5 - jsr @r1 - nop - mov r0,r9 - mov.l .L103,r1 - mov.l @(24,r14),r4 - mov.l @(32,r14),r5 - jsr @r1 - nop - mov.l r0,@(36,r14) - mov.l @(36,r14),r1 - or r9,r1 - mov.l r1,@r8 -.L86: - mov.l @(4,r14),r1 - mov.l @r1,r2 - mov.l r2,@(12,r14) - mov.l @r14,r8 - mov.l .L102,r1 - mov.l @(16,r14),r4 - mov.l @(28,r14),r5 - jsr @r1 - nop - mov r0,r9 - mov.l .L103,r1 - mov.l @(20,r14),r4 - mov.l @(32,r14),r5 - jsr @r1 - nop - mov.l r0,@(36,r14) - mov.l @(36,r14),r1 - or r9,r1 - mov.l r1,@r8 - mov.l @(4,r14),r1 - mov r1,r2 - add #-16,r2 - mov.l r2,@(4,r14) - mov.l @r14,r1 - mov r1,r2 - add #-16,r2 - mov.l r2,@r14 - mov.l @(8,r14),r1 - mov r1,r2 - add #-4,r2 - mov.l r2,@(8,r14) -.L100: - mov.l @(8,r14),r1 - tst r1,r1 - bf .L101 - bra .L99 - nop - .align 2 -.L101: - bra .L95 - nop - .align 2 -.L99: - nop -.L94: - mov.l @r14,r1 - mov r1,r8 - add #12,r8 - mov.l .L102,r1 - mov.l @(12,r14),r4 - mov.l @(28,r14),r5 - jsr @r1 - nop - mov r0,r9 - mov.l .L103,r1 - mov.l @(16,r14),r4 - mov.l @(32,r14),r5 - jsr @r1 - nop - mov.l r0,@(36,r14) - mov.l @(36,r14),r1 - or r9,r1 - mov.l r1,@r8 -.L83: - add #40,r14 - mov r14,r15 - lds.l @r15+,pr - mov.l @r15+,r14 - mov.l @r15+,r9 - mov.l @r15+,r8 - rts - nop -.L104: - .align 2 -.L102: - .long ___lshrsi3 -.L103: - .long ___ashlsi3 -.Lfe4: diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile index c89c2b9e36ae..981c25380d76 100644 --- a/arch/sh/mm/Makefile +++ b/arch/sh/mm/Makefile @@ -8,6 +8,6 @@ # Note 2! The CFLAGS definition is now in the main makefile... O_TARGET := mm.o -O_OBJS := init.o fault.o ioremap.o extable.o +O_OBJS := init.o fault.o ioremap.o extable.o cache.o include $(TOPDIR)/Rules.make diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c new file mode 100644 index 000000000000..d15c62385c87 --- /dev/null +++ b/arch/sh/mm/cache.c @@ -0,0 +1,366 @@ +/* $Id: cache.c,v 1.7 1999/09/23 11:43:07 gniibe Exp $ + * + * linux/arch/sh/mm/cache.c + * + * Copyright (C) 1999 Niibe Yutaka + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__sh3__) +#define CCR 0xffffffec /* Address of Cache Control Register */ +#define CCR_CACHE_VAL 0x00000005 /* 8k-byte cache, P1-wb, enable */ +#define CCR_CACHE_INIT 0x0000000d /* 8k-byte cache, CF, P1-wb, enable */ +#define CCR_CACHE_ENABLE 1 + +#define CACHE_IC_ADDRESS_ARRAY 0xf0000000 /* SH-3 has unified cache system */ +#define CACHE_OC_ADDRESS_ARRAY 0xf0000000 +#define CACHE_VALID 1 +#define CACHE_UPDATED 2 + +/* 7709A/7729 has 16K cache (256-entry), while 7702 has only 2K(direct) + 7702 is not supported (yet) */ +struct _cache_system_info { + int way_shift; + int entry_mask; + int num_entries; +}; + +static struct _cache_system_info cache_system_info; + +#define CACHE_OC_WAY_SHIFT (cache_system_info.way_shift) +#define CACHE_IC_WAY_SHIFT (cache_system_info.way_shift) +#define CACHE_OC_ENTRY_SHIFT 4 +#define CACHE_OC_ENTRY_MASK (cache_system_info.entry_mask) +#define CACHE_IC_ENTRY_MASK (cache_system_info.entry_mask) +#define CACHE_OC_NUM_ENTRIES (cache_system_info.num_entries) +#define CACHE_OC_NUM_WAYS 4 +#define CACHE_IC_NUM_WAYS 4 +#elif defined(__SH4__) +#define CCR 0xff00001c /* Address of Cache Control Register */ +#define CCR_CACHE_VAL 0x00000105 /* 8k+16k-byte cache,P1-wb,enable */ +#define CCR_CACHE_INIT 0x0000090d /* 8k+16k-byte cache,CF,P1-wb,enable */ +#define CCR_CACHE_ENABLE 0x00000101 + +#define CACHE_IC_ADDRESS_ARRAY 0xf0000000 +#define CACHE_OC_ADDRESS_ARRAY 0xf4000000 +#define CACHE_VALID 1 +#define CACHE_UPDATED 2 + +#define CACHE_OC_WAY_SHIFT 13 +#define CACHE_IC_WAY_SHIFT 13 +#define CACHE_OC_ENTRY_SHIFT 5 +#define CACHE_OC_ENTRY_MASK 0x3fe0 +#define CACHE_IC_ENTRY_MASK 0x1fe0 +#define CACHE_OC_NUM_ENTRIES 512 +#define CACHE_OC_NUM_WAYS 1 +#define CACHE_IC_NUM_WAYS 1 +#endif + +#define jump_to_p2(__dummy) \ + asm volatile("mova 1f,%0\n\t" \ + "add %1,%0\n\t" \ + "jmp @r0 ! Jump to P2 area\n\t" \ + " nop\n\t" \ + ".balign 4\n" \ + "1:" \ + : "=&z" (__dummy) \ + : "r" (0x20000000)) + +#define back_to_p1(__dummy) \ + asm volatile("nop;nop;nop;nop;nop;nop\n\t" \ + "mova 9f,%0\n\t" \ + "sub %1,%0\n\t" \ + "jmp @r0 ! Back to P1 area\n\t" \ + " nop\n\t" \ + ".balign 4\n" \ + "9:" \ + : "=&z" (__dummy) \ + : "r" (0x20000000), "0" (__dummy)) + +/* Write back caches to memory (if needed) and invalidates the caches */ +void cache_flush_area(unsigned long start, unsigned long end) +{ + unsigned long flags, __dummy; + unsigned long addr, data, v, p; + + start &= ~(L1_CACHE_BYTES-1); + save_and_cli(flags); + jump_to_p2(__dummy); + + for (v = start; v < end; v+=L1_CACHE_BYTES) { + p = __pa(v); + addr = CACHE_IC_ADDRESS_ARRAY | + (v&CACHE_IC_ENTRY_MASK) | 0x8 /* A-bit */; + data = (v&0xfffffc00); /* U=0, V=0 */ + ctrl_outl(data,addr); +#if CACHE_IC_ADDRESS_ARRAY != CACHE_OC_ADDRESS_ARRAY + asm volatile("ocbp %0" + : /* no output */ + : "m" (__m(v))); +#endif + } + back_to_p1(__dummy); + restore_flags(flags); +} + +/* Purge (just invalidate, no write back) the caches */ +/* This is expected to work well.. but.. + + On SH7708S, the write-back cache is written back on "purge". + (it's not expected, though). + + It seems that we have no way to just purge (with no write back action) + the cache line. */ +void cache_purge_area(unsigned long start, unsigned long end) +{ + unsigned long flags, __dummy; + unsigned long addr, data, v, p, j; + + start &= ~(L1_CACHE_BYTES-1); + save_and_cli(flags); + jump_to_p2(__dummy); + + for (v = start; v < end; v+=L1_CACHE_BYTES) { + p = __pa(v); + for (j=0; jtype = CPU_SH7708; + } else { /* 7709A or 7729 */ + cache_system_info.way_shift = 12; + cache_system_info.entry_mask = 0xff0; + cache_system_info.num_entries = 256; + cpu_data->type = CPU_SH7729; + } +#elif defined(__SH4__) + cpu_data->type = CPU_SH7750; +#endif +} + +void __init cache_init(void) +{ + unsigned long __dummy, ccr; + + detect_cpu_and_cache_system(); + + ccr = ctrl_inl(CCR); + if (ccr == CCR_CACHE_VAL) + return; + if (ccr & CCR_CACHE_ENABLE) + /* Should check RA here. If RA was 1, + we only need to flush the half of the caches. */ + cache_wback_all(); + + jump_to_p2(__dummy); + ctrl_outl(CCR_CACHE_INIT, CCR); + back_to_p1(__dummy); +} + +#if defined(__SH4__) +/* Write back data caches, and invalidates instructiin caches */ +void flush_icache_range(unsigned long start, unsigned long end) +{ + unsigned long flags, __dummy; + unsigned long addr, data, v; + + start &= ~(L1_CACHE_BYTES-1); + save_and_cli(flags); + jump_to_p2(__dummy); + + for (v = start; v < end; v+=L1_CACHE_BYTES) { + /* Write back O Cache */ + asm volatile("ocbwb %0" + : /* no output */ + : "m" (__m(v))); + /* Invalidate I Cache */ + addr = CACHE_IC_ADDRESS_ARRAY | + (v&CACHE_IC_ENTRY_MASK) | 0x8 /* A-bit */; + data = (v&0xfffffc00); /* Valid=0 */ + ctrl_outl(data,addr); + } + back_to_p1(__dummy); + restore_flags(flags); +} + +void flush_cache_all(void) +{ + unsigned long flags,__dummy; + + /* Write back Operand Cache */ + cache_wback_all (); + + /* Then, invalidate Instruction Cache and Operand Cache */ + save_and_cli(flags); + jump_to_p2(__dummy); + ctrl_outl(CCR_CACHE_INIT, CCR); + back_to_p1(__dummy); + restore_flags(flags); +} + +void flush_cache_mm(struct mm_struct *mm) +{ + /* Is there any good way? */ + /* XXX: possibly call flush_cache_range for each vm area */ + flush_cache_all(); +} + +void flush_cache_range(struct mm_struct *mm, unsigned long start, + unsigned long end) +{ + unsigned long flags, __dummy; + unsigned long addr, data, v; + + start &= ~(L1_CACHE_BYTES-1); + save_and_cli(flags); + jump_to_p2(__dummy); + + for (v = start; v < end; v+=L1_CACHE_BYTES) { + addr = CACHE_IC_ADDRESS_ARRAY | + (v&CACHE_IC_ENTRY_MASK) | 0x8 /* A-bit */; + data = (v&0xfffffc00); /* Update=0, Valid=0 */ + ctrl_outl(data,addr); + addr = CACHE_OC_ADDRESS_ARRAY | + (v&CACHE_OC_ENTRY_MASK) | 0x8 /* A-bit */; + ctrl_outl(data,addr); + } + back_to_p1(__dummy); + restore_flags(flags); +} + +void flush_cache_page(struct vm_area_struct *vma, unsigned long addr) +{ + flush_cache_range(vma->vm_mm, addr, addr+PAGE_SIZE); +} + +void flush_page_to_ram(unsigned long page) +{ /* Page is in physical address */ + /* XXX: for the time being... */ + flush_cache_all(); +} +#endif diff --git a/arch/sh/mm/extable.c b/arch/sh/mm/extable.c index 35c4451ebcdf..dc77f57fe243 100644 --- a/arch/sh/mm/extable.c +++ b/arch/sh/mm/extable.c @@ -1,4 +1,5 @@ -/* +/* $Id: extable.c,v 1.1 1999/09/18 16:57:37 gniibe Exp $ + * * linux/arch/sh/mm/extable.c * Taken from: * linux/arch/i386/mm/extable.c diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c index c1348d5b4a3c..595e413457a6 100644 --- a/arch/sh/mm/fault.c +++ b/arch/sh/mm/fault.c @@ -1,4 +1,5 @@ -/* +/* $Id: fault.c,v 1.3 1999/09/21 23:09:53 gniibe Exp $ + * * linux/arch/sh/mm/fault.c * Copyright (C) 1999 Niibe Yutaka * @@ -20,6 +21,7 @@ #include #include +#include #include #include #include @@ -225,20 +227,23 @@ void update_mmu_cache(struct vm_area_struct * vma, asid = get_asid(); - save_and_cli(flags); address &= PAGE_MASK; +#if 0/*defined(__SH4__)*//* SH-4 has separate I/D caches: XXX really needed? */ + if ((vma->vm_flags & VM_EXEC) != 0) +/* && + ((pte_val(pte) & (_PAGE_PRESENT | _PAGE_DIRTY)) == + (_PAGE_PRESENT | _PAGE_DIRTY))) */ + flush_icache_range(address,address+PAGE_SIZE); +#endif + save_and_cli(flags); /* Set PTEH register */ - asm volatile ("mov.l %0,%1" - : /* no output */ - : "r" (address | asid), "m" (__m(MMU_PTEH))); + ctrl_outl((address|asid), MMU_PTEH); pteval = pte_val(pte); pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */ pteval |= _PAGE_FLAGS_HARDWARE_DEFAULT; /* add default flags */ /* Set PTEL register */ - asm volatile ("mov.l %0,%1" - : /* no output */ - : "r" (pteval), "m" (__m(MMU_PTEL))); + ctrl_outl(pteval, MMU_PTEL); /* Load the TLB */ asm volatile ("ldtlb" : /* no output */ : /* no input */ @@ -250,11 +255,27 @@ static __inline__ void __flush_tlb_page(unsigned long asid, unsigned long page) { unsigned long addr, data; +#if defined(__sh3__) addr = MMU_TLB_ADDRESS_ARRAY | (page & 0x1F000) | MMU_PAGE_ASSOC_BIT; data = page | asid; /* VALID bit is off */ - __asm__ __volatile__ ("mov.l %0,%1" - : /* no output */ - : "r" (data), "m" (__m(addr))); + ctrl_outl(data, addr); +#elif defined(__SH4__) + int i; + + addr = MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT; + data = page | asid; /* VALID bit is off */ + ctrl_outl(data, addr); + + for (i=0; i<4; i++) { + addr = MMU_ITLB_ADDRESS_ARRAY | (i<<8); + data = ctrl_inl(addr); + data &= ~0x30; + if (data == (page | asid)) { + ctrl_outl(data, addr); + break; + } + } +#endif } void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) @@ -262,9 +283,13 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) unsigned long asid; if (vma->vm_mm->context != NO_CONTEXT) { + unsigned long flags; + page &= PAGE_MASK; asid = vma->vm_mm->context & MMU_CONTEXT_ASID_MASK; + save_and_cli(flags); __flush_tlb_page (asid, page); + restore_flags(flags); } } @@ -277,7 +302,7 @@ void flush_tlb_range(struct mm_struct *mm, unsigned long start, save_and_cli(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - if (size > (MMU_NTLB_ENTRIES/4)) { /* So many TLB to flush */ + if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */ get_new_mmu_context(mm); if (mm == current->mm) set_asid(mm->context & MMU_CONTEXT_ASID_MASK); @@ -314,13 +339,11 @@ void flush_tlb_mm(struct mm_struct *mm) void flush_tlb_all(void) { - unsigned long flags, __dummy; + unsigned long flags, status; save_and_cli(flags); - asm volatile("mov.l %1,%0\n\t" - "or #4,%0\n\t" /* Set TF-bit to flush */ - "mov.l %0,%1" - : "=&z" (__dummy) - : "m" (__m(MMUCR))); + status = ctrl_inl(MMUCR); + status |= 0x04; /* Set TF-bit to flush */ + ctrl_outl(status,MMUCR); restore_flags(flags); } diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 3a6bfc1a2ba5..56ab03cf9bc8 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -1,4 +1,5 @@ -/* +/* $Id: init.c,v 1.3 1999/10/11 10:41:30 gniibe Exp $ + * * linux/arch/sh/mm/init.c * * Copyright (C) 1999 Niibe Yutaka @@ -29,6 +30,7 @@ #include #include #include +#include /* * Cache of MMU context last used. @@ -127,7 +129,7 @@ int do_check_pgt_cache(int low, int high) */ pte_t * __bad_pagetable(void) { - extern char empty_bad_page_table[PAGE_SIZE]; + extern unsigned long empty_bad_page_table[PAGE_SIZE]; unsigned long page = (unsigned long)empty_bad_page_table; clear_page(page); @@ -202,16 +204,17 @@ paging_init(unsigned long start_mem, unsigned long end_mem) pgd_val(pg_dir[0]) = 0; /* Enable MMU */ - __asm__ __volatile__ ("mov.l %0,%1" - : /* no output */ - : "r" (MMU_CONTROL_INIT), "m" (__m(MMUCR))); + ctrl_outl(MMU_CONTROL_INIT, MMUCR); + + mmu_context_cache = MMU_CONTEXT_FIRST_VERSION; + set_asid(mmu_context_cache & MMU_CONTEXT_ASID_MASK); return free_area_init(start_mem, end_mem); } unsigned long empty_bad_page[1024]; unsigned long empty_bad_page_table[1024]; -unsigned long empty_zero_page[1024]; +extern unsigned long empty_zero_page[1024]; void __init mem_init(unsigned long start_mem, unsigned long end_mem) { diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c index f786379cfc79..90fd190eff9b 100644 --- a/arch/sh/mm/ioremap.c +++ b/arch/sh/mm/ioremap.c @@ -1,4 +1,5 @@ -/* +/* $Id: ioremap.c,v 1.1 1999/09/18 16:57:48 gniibe Exp $ + * * arch/sh/mm/ioremap.c * * Re-map IO memory to kernel address space so that we can access it. diff --git a/arch/sh/vmlinux.lds.S b/arch/sh/vmlinux.lds.S index a812c91f8f61..688c4c9c4b92 100644 --- a/arch/sh/vmlinux.lds.S +++ b/arch/sh/vmlinux.lds.S @@ -1,4 +1,5 @@ -/* ld script to make SuperH Linux kernel +/* $Id: vmlinux.lds.S,v 1.3 1999/10/05 12:33:48 gniibe Exp $ + * ld script to make SuperH Linux kernel * Written by Niibe Yutaka */ #include @@ -15,6 +16,7 @@ SECTIONS __text = .; /* Text and read-only data */ _text = .; /* Text and read-only data */ .text : { + *(.empty_zero_page) *(.text) *(.fixup) *(.gnu.warning) @@ -66,9 +68,6 @@ SECTIONS . = ALIGN(32); .data.cacheline_aligned : { *(.data.cacheline_aligned) } - . = ALIGN(4096); - .data.disk_image : { *(.data.disk_image) } - . = ALIGN(4); ___bss_start = .; /* BSS */ .bss : { diff --git a/drivers/block/Config.in b/drivers/block/Config.in index c23b8d094b4c..7f70e32eed7f 100644 --- a/drivers/block/Config.in +++ b/drivers/block/Config.in @@ -62,17 +62,15 @@ else fi if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" = "y" ]; then bool ' HPT34X chipset support' CONFIG_BLK_DEV_HPT34X - if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" -a \ - "$CONFIG_BLK_DEV_HPT34X" = "y" ]; then - bool ' HPT34X DMA support (DANGEROUS)' CONFIG_BLK_DEV_HPT34X_DMA + if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" -a "$CONFIG_BLK_DEV_HPT34X" = "y" ]; then + bool ' HPT34X DMA support (EXPERIMENTAL)' CONFIG_BLK_DEV_HPT34X_DMA fi bool ' HPT366 chipset support' CONFIG_BLK_DEV_HPT366 fi if [ "$CONFIG_X86" = "y" ]; then bool ' Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX - if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" -a \ - "$CONFIG_BLK_DEV_PIIX" = "y" ]; then - bool ' PIIXn Tuning support (EXPERIMENTAL)' CONFIG_BLK_DEV_PIIX_TUNING + if [ "$CONFIG_BLK_DEV_PIIX" = "y" ]; then + bool ' PIIXn Tuning support' CONFIG_BLK_DEV_PIIX_TUNING fi fi if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then @@ -83,19 +81,20 @@ else fi if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" = "y" ]; then bool ' PROMISE PDC20246/PDC20262 support' CONFIG_BLK_DEV_PDC202XX - if [ "$CONFIG_EXPERIMENTAL" = "y" -a \ - "$CONFIG_BLK_DEV_PDC202XX" = "y" ]; then - bool ' Special UDMA Feature (EXPERIMENTAL)' CONFIG_PDC202XX_FORCE_BURST_BIT - bool ' Special Mode Feature (DANGEROUS)' CONFIG_PDC202XX_FORCE_MASTER_MODE + if [ "$CONFIG_BLK_DEV_PDC202XX" = "y" ]; then + bool ' Special UDMA Feature' CONFIG_PDC202XX_FORCE_BURST_BIT + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool ' Special Mode Feature (EXPERIMENTAL)' CONFIG_PDC202XX_FORCE_MASTER_MODE + fi + fi + if [ "$CONFIG_X86" = "y" ]; then + bool ' SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 fi - fi - if [ "$CONFIG_X86" = "y" ]; then - bool ' SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 fi if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then bool ' Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290 if [ "$CONFIG_X86" = "y" ]; then - bool ' VIA82C586 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82C586 + bool ' VIA82CXXX chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82CXXX fi fi fi @@ -139,8 +138,7 @@ else bool ' ALI M14xx support' CONFIG_BLK_DEV_ALI14XX bool ' DTC-2278 support' CONFIG_BLK_DEV_DTC2278 bool ' Holtek HT6560B support' CONFIG_BLK_DEV_HT6560B - if [ "$CONFIG_BLK_DEV_IDEDISK" = "y" -a \ - "$CONFIG_EXPERIMENTAL" = "y" ]; then + if [ "$CONFIG_BLK_DEV_IDEDISK" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then bool ' PROMISE DC4030 support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC4030 fi bool ' QDI QD6580 support' CONFIG_BLK_DEV_QD6580 @@ -225,6 +223,7 @@ if [ "$CONFIG_IDE_CHIPSETS" = "y" -o \ "$CONFIG_BLK_DEV_HPT366" = "y" -o \ "$CONFIG_BLK_DEV_IDE_PMAC" = "y" -o \ "$CONFIG_BLK_DEV_OPTI621" = "y" -o \ + "$CONFIG_BLK_DEV_PDC202XX" = "y" -o \ "$CONFIG_BLK_DEV_PIIX" = "y" -o \ "$CONFIG_BLK_DEV_SIS5513" = "y" -o \ "$CONFIG_BLK_DEV_SL82C105" = "y" ]; then diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 8519318d93f0..1de4fa58139f 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -230,8 +230,8 @@ ifeq ($(CONFIG_BLK_DEV_UMC8672),y) IDE_OBJS += umc8672.o endif -ifeq ($(CONFIG_BLK_DEV_VIA82C586),y) -IDE_OBJS += via82c586.o +ifeq ($(CONFIG_BLK_DEV_VIA82CXXX),y) +IDE_OBJS += via82cxxx.o endif ### if CONFIG_BLK_DEV_IDE is n, IDE_OBJS will be ignored @@ -379,4 +379,3 @@ ide-mod.o: ide.o $(IDE_OBJS) ide-probe-mod.o: ide-probe.o ide-geometry.o $(LD) $(LD_RFLAG) -r -o $@ ide-probe.o ide-geometry.o - diff --git a/drivers/block/aec6210.c b/drivers/block/aec6210.c index c52d8450db07..75bb8657fb4d 100644 --- a/drivers/block/aec6210.c +++ b/drivers/block/aec6210.c @@ -1,7 +1,8 @@ /* - * linux/drivers/block/aec6210.c Version 0.01 Nov 17, 1998 + * linux/drivers/block/aec6210.c Version 0.02 Sept. 3, 1999 * - * Copyright (C) 1998-99 Andre Hedrick + * Copyright (C) 1998-99 Andre Hedrick (andre@suse.com) + * May be copied or modified under the terms of the GNU General Public License * * pio 0 :: 40: 00 07 00 00 00 00 00 00 02 07 a6 04 00 02 00 02 * pio 1 :: 40: 0a 07 00 00 00 00 00 00 02 07 a6 05 00 02 00 02 @@ -50,6 +51,10 @@ #include #include +/* + * TO DO: active tuning and correction of cards without a bios. + */ + unsigned int __init pci_init_aec6210 (struct pci_dev *dev, const char *name) { if (dev->resource[PCI_ROM_RESOURCE].start) { diff --git a/drivers/block/alim15x3.c b/drivers/block/alim15x3.c index b7a0a5c4f462..5453610523a9 100644 --- a/drivers/block/alim15x3.c +++ b/drivers/block/alim15x3.c @@ -1,21 +1,28 @@ /* - * linux/drivers/block/alim15x3.c Version 0.05 Jun. 29, 1999 + * linux/drivers/block/alim15x3.c Version 0.06 Sept. 3, 1999 * * Copyright (C) 1998-99 Michel Aubry, Maintainer * Copyright (C) 1998-99 Andrzej Krzysztofowicz, Maintainer - * Copyright (C) 1998-99 Andre Hedrick, Integrater and Maintainer * - * (U)DMA capable version of ali 1533/1543(C) + * Copyright (C) 1998-99 Andre Hedrick (andre@suse.com) + * May be copied or modified under the terms of the GNU General Public License * - * Default disable (U)DMA on all devices execpt hard disks. - * This measure of overkill is needed to stablize the chipset code. + * (U)DMA capable version of ali 1533/1543(C), 1535(D) * + * version: 1.0 beta2 (Sep. 2, 1999) + * e-mail your problems to cjtsai@ali.com.tw + * + ********************************************************************** + * 9/7/99 --Parts from the above author are included and need to be + * converted into standard interface, once I finish the thought. */ #include #include #include #include +#include +#include #include #include @@ -59,188 +66,7 @@ char *channel_status[8] = { "error DRQ ", "error DRQ busy" }; -#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ - -static void ali15x3_tune_drive (ide_drive_t *drive, byte pio) -{ - ide_pio_data_t d; - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - int s_time, a_time, c_time; - byte s_clc, a_clc, r_clc; - unsigned long flags; - int bus_speed = ide_system_bus_speed(); - int port = hwif->index ? 0x5c : 0x58; - - pio = ide_get_best_pio_mode(drive, pio, 5, &d); - s_time = ide_pio_timings[pio].setup_time; - a_time = ide_pio_timings[pio].active_time; - if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8) - s_clc = 0; - if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8) - a_clc = 0; - c_time = ide_pio_timings[pio].cycle_time; - -#if 0 - if ((r_clc = ((c_time - s_time - a_time) * bus_speed + 999) / 1000) >= 16) - r_clc = 0; -#endif - if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) { - r_clc = 1; - } else { - if (r_clc >= 16) - r_clc = 0; - } - save_flags(flags); - cli(); - pci_write_config_byte(dev, port, s_clc); - pci_write_config_byte(dev, port+drive->select.b.unit+2, (a_clc << 4) | r_clc); - restore_flags(flags); - - /* - * setup active rec - * { 70, 165, 365 }, PIO Mode 0 - * { 50, 125, 208 }, PIO Mode 1 - * { 30, 100, 110 }, PIO Mode 2 - * { 30, 80, 70 }, PIO Mode 3 with IORDY - * { 25, 70, 25 }, PIO Mode 4 with IORDY ns - * { 20, 50, 30 } PIO Mode 5 with IORDY (nonstandard) - */ - -} - -unsigned int __init pci_init_ali15x3 (struct pci_dev *dev, const char *name) -{ - byte confreg0 = 0, confreg1 =0, progif = 0; - int errors = 0; - - if (pci_read_config_byte(dev, 0x50, &confreg1)) - goto veryspecialsettingserror; - if (!(confreg1 & 0x02)) - if (pci_write_config_byte(dev, 0x50, confreg1 | 0x02)) - goto veryspecialsettingserror; - - if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif)) - goto veryspecialsettingserror; - if (!(progif & 0x40)) { - /* - * The way to enable them is to set progif - * writable at 0x4Dh register, and set bit 6 - * of progif to 1: - */ - if (pci_read_config_byte(dev, 0x4d, &confreg0)) - goto veryspecialsettingserror; - if (confreg0 & 0x80) - if (pci_write_config_byte(dev, 0x4d, confreg0 & ~0x80)) - goto veryspecialsettingserror; - if (pci_write_config_byte(dev, PCI_CLASS_PROG, progif | 0x40)) - goto veryspecialsettingserror; - if (confreg0 & 0x80) - if (pci_write_config_byte(dev, 0x4d, confreg0)) - errors++; - } - - if ((pci_read_config_byte(dev, PCI_CLASS_PROG, &progif)) || (!(progif & 0x40))) - goto veryspecialsettingserror; - - printk("%s: enabled read of IDE channels state (en/dis-abled) %s.\n", - name, errors ? "with Error(s)" : "Succeeded" ); - return 0; - -veryspecialsettingserror: - printk("%s: impossible to enable read of IDE channels state (en/dis-abled)!\n", name); - return 0; -} - -int ali15x3_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - if (drive->media == ide_cdrom) { - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - struct hd_driveid *id = drive->id; - byte cd_dma_fifo = 0; - - pci_read_config_byte(dev, 0x53, &cd_dma_fifo); - - if (((id->field_valid & 4) || (id->field_valid & 2)) && - (id->capability & 1) && hwif->autodma) { - unsigned long dma_set_bit = hwif->dma_base + 2; -#if 0 - if (cd_dma_fifo & 0x02) - pci_write_config_byte(dev, 0x53, cd_dma_fifo & ~0x02); - pci_write_config_byte(dev, 0x53, cd_dma_fifo|0x01); -#else - pci_write_config_byte(dev, 0x53, cd_dma_fifo|0x01|0x02); -#endif - if (drive->select.b.unit & 0x01) { - outb(inb(dma_set_bit)|0x40, dma_set_bit); - } else { - outb(inb(dma_set_bit)|0x20, dma_set_bit); - } - } else { - if (cd_dma_fifo & 0x01) - pci_write_config_byte(dev, 0x53, cd_dma_fifo & ~0x01); - pci_write_config_byte(dev, 0x53, cd_dma_fifo|0x02); - } - } else if (drive->media != ide_disk) { - return ide_dmaproc(ide_dma_off_quietly, drive); - } - default: - break; - } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ -} - -void __init ide_init_ali15x3 (ide_hwif_t *hwif) -{ - struct pci_dev *dev; - byte ideic, inmir, iderev; - byte irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6, - 1, 11, 0, 12, 0, 14, 0, 15 }; - - pci_read_config_byte(hwif->pci_dev, PCI_REVISION_ID, &iderev); - - hwif->irq = hwif->channel ? 15 : 14; - for (dev = pci_devices; dev; dev=dev->next) /* look for ISA bridge */ - if (dev->vendor==PCI_VENDOR_ID_AL && - dev->device==PCI_DEVICE_ID_AL_M1533) - break; - if (dev) { - pci_read_config_byte(dev, 0x58, &ideic); - ideic = ideic & 0x03; - if ((hwif->channel && ideic == 0x03) || - (!hwif->channel && !ideic)) { - pci_read_config_byte(dev, 0x44, &inmir); - inmir = inmir & 0x0f; - hwif->irq = irq_routing_table[inmir]; - } else - if (hwif->channel && !(ideic & 0x01)) { - pci_read_config_byte(dev, 0x75, &inmir); - inmir = inmir & 0x0f; - hwif->irq = irq_routing_table[inmir]; - } - } -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) - bmide_dev = hwif->pci_dev; - ali_display_info = &ali_get_info; -#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ - - hwif->tuneproc = &ali15x3_tune_drive; - if ((hwif->dma_base) && (iderev >= 0xC1)) { - /* M1543C or newer for DMAing */ - hwif->dmaproc = &ali15x3_dmaproc; - } else { - hwif->autodma = 0; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - } - return; -} - -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) static int ali_get_info(char *buffer, char **addr, off_t offset, int count, int dummy) { byte reg53h, reg5xh, reg5yh, reg5xh1, reg5yh1; @@ -407,3 +233,540 @@ static int ali_get_info(char *buffer, char **addr, off_t offset, int count, int return p-buffer; /* => must be less than 4k! */ } #endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ + +static byte m5229_revision = 0; +static byte chip_is_1543c_e = 0; +static byte cable_80_pin[2] = { 0, 0 }; + +byte ali_proc = 0; +static struct pci_dev *isa_dev; + +static void ali15x3_tune_drive (ide_drive_t *drive, byte pio) +{ + ide_pio_data_t d; + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + int s_time, a_time, c_time; + byte s_clc, a_clc, r_clc; + unsigned long flags; + int bus_speed = ide_system_bus_speed(); + int port = hwif->index ? 0x5c : 0x58; + + pio = ide_get_best_pio_mode(drive, pio, 5, &d); + s_time = ide_pio_timings[pio].setup_time; + a_time = ide_pio_timings[pio].active_time; + if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8) + s_clc = 0; + if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8) + a_clc = 0; + c_time = ide_pio_timings[pio].cycle_time; + +#if 0 + if ((r_clc = ((c_time - s_time - a_time) * bus_speed + 999) / 1000) >= 16) + r_clc = 0; +#endif + + if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) { + r_clc = 1; + } else { + if (r_clc >= 16) + r_clc = 0; + } + save_flags(flags); + cli(); + pci_write_config_byte(dev, port, s_clc); + pci_write_config_byte(dev, port+drive->select.b.unit+2, (a_clc << 4) | r_clc); + restore_flags(flags); + + /* + * setup active rec + * { 70, 165, 365 }, PIO Mode 0 + * { 50, 125, 208 }, PIO Mode 1 + * { 30, 100, 110 }, PIO Mode 2 + * { 30, 80, 70 }, PIO Mode 3 with IORDY + * { 25, 70, 25 }, PIO Mode 4 with IORDY ns + * { 20, 50, 30 } PIO Mode 5 with IORDY (nonstandard) + */ + +} + +static __inline__ unsigned char dma2_bits_to_command(unsigned char bits) +{ + if (bits & 0x04) + return XFER_MW_DMA_2; + if (bits & 0x02) + return XFER_MW_DMA_1; + return XFER_MW_DMA_0; +} + +static __inline__ unsigned char udma2_bits_to_command(unsigned char bits) +{ + if (bits & 0x10) + return XFER_UDMA_4; + if (bits & 0x08) + return XFER_UDMA_3; + if (bits & 0x04) + return XFER_UDMA_2; + if (bits & 0x02) + return XFER_UDMA_1; + return XFER_UDMA_0; +} + +static __inline__ int wait_for_ready(ide_drive_t *drive) +{ + int timeout = 20000; /* (old value: 100) */ + byte stat; + + while (--timeout) { + stat = GET_STAT(); + /* + * printk("STAT(%2x) ", stat); + */ + if (!(stat & BUSY_STAT)) { + if ((stat & READY_STAT) || (stat & ERR_STAT)) { + break; + } + } + /* + * (old value: 100) + */ + udelay(150); + } + if ((stat & ERR_STAT) || timeout <= 0) + return 1; + return 0; +} + +static void ali15x3_do_setfeature(ide_drive_t *drive, byte command) +{ + unsigned long flags; + byte old_select; + + save_flags(flags); + cli(); + + /* save old selected device */ + old_select = IN_BYTE(IDE_SELECT_REG); + /* "SELECT " */ + OUT_BYTE(drive->select.all, IDE_SELECT_REG); + /* "SETXFER " */ + OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); + /* "CMND " */ + OUT_BYTE(command, IDE_NSECTOR_REG); + + if(wait_for_ready(drive)) /* "wait " */ + goto out; + + /* "SETFEATURE " */ + OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); + /* "wait " */ + (void) wait_for_ready(drive); + +out: + /* + * restore to old "selected device" + */ + OUT_BYTE(old_select, IDE_SELECT_REG); + restore_flags(flags); +} + +static void ali15x3_dma2_enable(ide_drive_t *drive, unsigned long dma_base) +{ + byte unit = (drive->select.b.unit & 0x01); + byte bits = (drive->id->dma_mword | drive->id->dma_1word) & 0x07; + byte tmpbyte; + ide_hwif_t *hwif = HWIF(drive); + unsigned long flags; + int m5229_udma_setting_index = hwif->channel? 0x57 : 0x56; + + ali15x3_do_setfeature(drive, dma2_bits_to_command(bits)); + + /* + * clear "ultra enable" bit + */ + pci_read_config_byte(hwif->pci_dev, m5229_udma_setting_index, &tmpbyte); + if (unit) { + tmpbyte &= 0x7f; + } else { + tmpbyte &= 0xf7; + } + save_flags(flags); + cli(); + pci_write_config_byte(hwif->pci_dev, m5229_udma_setting_index, tmpbyte); + restore_flags(flags); + drive->id->dma_ultra = 0x00; + + /* + * Enable DMA + */ + outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); + printk("ALI15X3: MultiWord DMA enabled\n"); +} + +static void ali15x3_udma_enable(ide_drive_t *drive, unsigned long dma_base) +{ + byte unit = (drive->select.b.unit & 0x01); + byte bits = drive->id->dma_ultra & 0x1f; + byte tmpbyte; + ide_hwif_t *hwif = HWIF(drive); + unsigned long flags; + unsigned char udma_mode = 0; + int m5229_udma_setting_index = hwif->channel? 0x57 : 0x56; + + if (bits & 0x18) { + /* + * 00011000, disk: ultra66 + */ + if (m5229_revision < 0xc2) { + /* + * controller: ultra33 + */ + bits = 0x04; + /* + * 00000100, use ultra33, mode 2 + */ + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0004; + } else { + /* + * controller: ultra66 + * + * Try to detect word93 bit13 and + * 80-pin cable (from host view) + */ + if (!((drive->id->word93 & 0x2000) && + cable_80_pin[hwif->channel])) { + bits = 0x04; + /* + * 00000100, use ultra33, mode 2 + */ + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0004; + } + } + } + + /* + * set feature regardless + */ + ali15x3_do_setfeature(drive, udma_mode = udma2_bits_to_command(bits)); + udma_mode &= 0x0f; /* get UDMA mode */ + + /* + * Enable DMA and UltraDMA + */ + outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); + /* + * m5229 ultra + */ + pci_read_config_byte(hwif->pci_dev, m5229_udma_setting_index, &tmpbyte); + /* + * clear bit0~3 or bit 4~7 + */ + tmpbyte &= (0x0f << ((1-unit) << 2)); + /* + * enable ultra dma and set timing + */ + tmpbyte |= ((0x08 | (4-udma_mode)) << (unit << 2)); + /* + * set to m5229 + */ + save_flags(flags); + cli(); + pci_write_config_byte(hwif->pci_dev, m5229_udma_setting_index, tmpbyte); + restore_flags(flags); + + if (udma_mode >= 3) { + /* + * ultra 66 + */ + pci_read_config_byte(hwif->pci_dev, 0x4b, &tmpbyte); + tmpbyte |= 1; + save_flags(flags); + cli(); + pci_write_config_byte(hwif->pci_dev, 0x4b, tmpbyte); + restore_flags(flags); + } + + printk("ALI15X3: Ultra DMA enabled\n"); +} + +static int ali15x3_dma_onoff(ide_drive_t *drive, int enable) +{ + if (enable) { + ide_hwif_t *hwif = HWIF(drive); + unsigned long dma_base = hwif->dma_base; + struct hd_driveid *id = drive->id; + + if ((id->field_valid & 0x0004) && + (id->dma_ultra & 0x001f)) { + /* + * 1543C_E, in ultra mode, WDC "harddisk" + * will cause "CRC" errors (even if no CRC problem), + * so we try to use "DMA" here + */ + if (m5229_revision <= 0x20) { + /* + * Normal MultiWord DMA modes. + */ + ali15x3_dma2_enable(drive, dma_base); + } else if ((m5229_revision < 0xC2) && + ((drive->media!=ide_disk) || + (chip_is_1543c_e && + strstr(id->model, "WDC ")))) { + /* + * Normal MultiWord DMA modes. + */ + ali15x3_dma2_enable(drive, dma_base); + } else { + /* + * m5229_revision >= 0xC2 for UltraDMA modes. + */ + ali15x3_udma_enable(drive, dma_base); + } + } else { + /* + * Normal MultiWord DMA modes. + */ + ali15x3_dma2_enable(drive, dma_base); + } + } + + drive->using_dma = enable; /* on, off */ + return 0; +} + +static int ali15x3_config_drive_for_dma(ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + + if ((m5229_revision<=0x20) && (drive->media!=ide_disk)) + return hwif->dmaproc(ide_dma_off_quietly, drive); + /* + * Even if the drive is not _currently_ in a DMA + * mode, we succeed, and we'll enable it manually + * below in alim15x3_dma_onoff + */ + if ((id != NULL) && (id->capability & 1) && hwif->autodma) { + if (id->field_valid & 0x0004) { + if (id->dma_ultra & 0x001F) + return hwif->dmaproc(ide_dma_on, drive); + } + if (id->field_valid & 0x0002) { + if ((id->dma_mword & 0x0007) || (id->dma_1word & 0x0007)) + return hwif->dmaproc(ide_dma_on, drive); + } + } + return hwif->dmaproc(ide_dma_off_quietly, drive); +} + +static int ali15x3_dmaproc (ide_dma_action_t func, ide_drive_t *drive) +{ + switch(func) { + case ide_dma_check: + return ali15x3_config_drive_for_dma(drive); + case ide_dma_on: + case ide_dma_off: + case ide_dma_off_quietly: + return ali15x3_dma_onoff(drive, (func == ide_dma_on)); + case ide_dma_write: + if ((m5229_revision < 0xC2) && (drive->media != ide_disk)) + return 1; /* try PIO instead of DMA */ + break; + default: + break; + } + + return ide_dmaproc(func, drive); /* use standard DMA stuff */ +} + +unsigned int __init pci_init_ali15x3 (struct pci_dev *dev, const char *name) +{ + struct pci_dev *isa; + unsigned long fixdma_base = dev->resource[4].start; + byte tmpbyte; + + pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision); + + for (isa = pci_devices; isa; isa=isa->next) { + /* + * look for ISA bridge + */ + if (isa->vendor == PCI_VENDOR_ID_AL && + isa->device == PCI_DEVICE_ID_AL_M1533) { + isa_dev = isa; + break; + } + } + + if (!fixdma_base || fixdma_base == PCI_BASE_ADDRESS_IO_MASK) { + /* + * + */ + } else { + /* + * enable DMA capable bit, and "not" simplex only + */ + outb(inb(fixdma_base+2) & 0x60, fixdma_base+2); + + if (inb(fixdma_base+2) & 0x80) + printk("%s: simplex device: DMA will fail!!\n", name); + } + + /* + * FIXME !!! This detection needs to be in "ata66_ali15x3()" + * below as a standard detection return. + */ + + if (m5229_revision >= 0xC2) { + unsigned long flags; + /* + * 1543C-B?, 1535, 1535D, 1553 + * Note 1: not all "motherboard" support this detection + * Note 2: if no udma 66 device, the detection may "error". + * but in this case, we will not set the device to + * ultra 66, the detection result is not important + */ + save_flags(flags); + cli(); + + /* + * enable "Cable Detection", m5229, 0x4b, bit3 + */ + pci_read_config_byte(dev, 0x4b, &tmpbyte); + pci_write_config_byte(dev, 0x4b, tmpbyte | 0x08); + + /* + * set south-bridge's enable bit, m1533, 0x79 + */ + pci_read_config_byte(isa_dev, 0x79, &tmpbyte); + if (m5229_revision == 0xC2) { + /* + * 1543C-B0 (m1533, 0x79, bit 2) + */ + pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x04); + } else if (m5229_revision == 0xC3) { + /* + * 1553/1535 (m1533, 0x79, bit 1) + */ + pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02); + } + restore_flags(flags); + /* + * Ultra66 cable detection (from Host View) + * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin + */ + pci_read_config_byte(dev, 0x4a, &tmpbyte); + /* + * 0x4a, bit0 is 0 => primary channel + * has 80-pin (from host view) + */ + if (!(tmpbyte & 0x01)) + cable_80_pin[0] = 1; + /* + * 0x4a, bit1 is 0 => secondary channel + * has 80-pin (from host view) + */ + if (!(tmpbyte & 0x02)) + cable_80_pin[1] = 1; + } else { + unsigned long flags; + /* + * revision 0x20 (1543-E, 1543-F) + * revision 0xC0, 0xC1 (1543C-C, 1543C-D, 1543C-E) + * clear CD-ROM DMA write bit, m5229, 0x4b, bit 7 + */ + pci_read_config_byte(dev, 0x4b, &tmpbyte); + save_flags(flags); + cli(); + /* + * clear bit 7 + */ + pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F); + restore_flags(flags); + + /* + * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010 + */ + pci_read_config_byte(isa_dev, 0x5e, &tmpbyte); + chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0; + } + + return 0; +} + +unsigned int __init ata66_ali15x3 (ide_hwif_t *hwif) +{ + /* + * FIXME !!!! + * {0x4a,0x01,0x01}, {0x4a,0x02,0x02} + */ + return 0; +} + +void __init ide_init_ali15x3 (ide_hwif_t *hwif) +{ + byte ideic, inmir; + byte irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6, + 1, 11, 0, 12, 0, 14, 0, 15 }; + + hwif->irq = hwif->channel ? 15 : 14; + + if (isa_dev) { + /* + * read IDE interface control + */ + pci_read_config_byte(isa_dev, 0x58, &ideic); + + /* bit0, bit1 */ + ideic = ideic & 0x03; + + /* get IRQ for IDE Controller */ + if ((hwif->channel && ideic == 0x03) || + (!hwif->channel && !ideic)) { + /* + * get SIRQ1 routing table + */ + pci_read_config_byte(isa_dev, 0x44, &inmir); + inmir = inmir & 0x0f; + hwif->irq = irq_routing_table[inmir]; + } else if (hwif->channel && !(ideic & 0x01)) { + /* + * get SIRQ2 routing table + */ + pci_read_config_byte(isa_dev, 0x75, &inmir); + inmir = inmir & 0x0f; + hwif->irq = irq_routing_table[inmir]; + } + } + + hwif->tuneproc = &ali15x3_tune_drive; + if ((hwif->dma_base) && (m5229_revision >= 0xC1)) { + /* + * M1543C or newer for DMAing + */ + hwif->dmaproc = &ali15x3_dmaproc; + hwif->autodma = 1; + } else { + hwif->autodma = 0; + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + } + +#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) + ali_proc = 1; + bmide_dev = hwif->pci_dev; + ali_display_info = &ali_get_info; +#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ + + return; +} + +void ide_dmacapable_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase) +{ + if ((dmabase) && (m5229_revision < 0x20)) { + return; + } + ide_setup_dma(hwif, dmabase, 8); +} diff --git a/drivers/block/cy82c693.c b/drivers/block/cy82c693.c index e204bc0e6d76..77fdf08210a7 100644 --- a/drivers/block/cy82c693.c +++ b/drivers/block/cy82c693.c @@ -1,8 +1,8 @@ /* - * linux/drivers/block/cy82c693.c Version 0.33 Jan. 23, 1999 + * linux/drivers/block/cy82c693.c Version 0.34 Sept 3, 1999 * - * Copyright (C) 1998, 1999 Andreas S. Krebs (akrebs@altavista.net), Maintainer - * Copyright (C) 1998 Andre Hedrick, Integrater + * Copyright (C) 1998-99 Andreas S. Krebs (akrebs@altavista.net), Maintainer + * Copyright (C) 1998-99 Andre Hedrick, Integrater * * CYPRESS CY82C693 chipset IDE controller * @@ -31,6 +31,7 @@ * * * History: + * AMH@1999-08-24: v0.34 init_cy82c693_chip moved to pci_init_cy82c693 * ASK@1999-01-23: v0.33 made a few minor code clean ups * removed DMA clock speed setting by default * added boot message @@ -53,7 +54,7 @@ #include "ide_modes.h" /* the current version */ -#define CY82_VERSION "CY82C693U driver v0.33 99-01-23 Andreas S. Krebs (akrebs@altavista.net)" +#define CY82_VERSION "CY82C693U driver v0.34 99-09-03 Andreas S. Krebs (akrebs@altavista.net)" /* * The following are used to debug the driver. @@ -377,20 +378,10 @@ static void cy82c693_tune_drive (ide_drive_t *drive, byte pio) unsigned int __init pci_init_cy82c693(struct pci_dev *dev, const char *name) { - return 0; -} - -static void init_cy82c693_chip (struct pci_dev *dev) -{ - static int initDone = 0; #ifdef CY82C693_SETDMA_CLOCK byte data; #endif /* CY82C693_SETDMA_CLOCK */ - if (initDone != 0) /* only perform setup once */ - return; - initDone = 1; - /* write info about this verion of the driver */ printk (KERN_INFO CY82_VERSION "\n"); @@ -401,7 +392,7 @@ static void init_cy82c693_chip (struct pci_dev *dev) data = IN_BYTE(CY82_DATA_PORT); #if CY82C693_DEBUG_INFO - printk (KERN_INFO "CY82U693: Peripheral Configuration Register: 0x%X\n", data); + printk (KERN_INFO "%s: Peripheral Configuration Register: 0x%X\n", name, data); #endif /* CY82C693_DEBUG_INFO */ /* @@ -422,10 +413,11 @@ static void init_cy82c693_chip (struct pci_dev *dev) OUT_BYTE(data, CY82_DATA_PORT); #if CY82C693_DEBUG_INFO - printk (KERN_INFO "CY82U693: New Peripheral Configuration Register: 0x%X\n", data); + printk (KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n", name, data); #endif /* CY82C693_DEBUG_INFO */ -#endif /* CY82C693_SETDMA_CLOCK */ +#endif /* CY82C693_SETDMA_CLOCK */ + return 0; } /* @@ -437,7 +429,5 @@ void __init ide_init_cy82c693(ide_hwif_t *hwif) if (hwif->dma_base) hwif->dmaproc = &cy82c693_dmaproc; hwif->tuneproc = &cy82c693_tune_drive; - - init_cy82c693_chip(hwif->pci_dev); } diff --git a/drivers/block/hpt34x.c b/drivers/block/hpt34x.c index 284bf40bc08e..816b4b805902 100644 --- a/drivers/block/hpt34x.c +++ b/drivers/block/hpt34x.c @@ -1,7 +1,9 @@ /* - * linux/drivers/block/hpt34x.c Version 0.25 July 11, 1999 + * linux/drivers/block/hpt34x.c Version 0.27 Sept 03, 1999 + * + * Copyright (C) 1998-99 Andre Hedrick (andre@suse.com) + * May be copied or modified under the terms of the GNU General Public License * - * Copyright (C) 1998-99 Andre Hedrick * * 00:12.0 Unknown mass storage controller: * Triones Technologies, Inc. @@ -14,9 +16,6 @@ * hdg: DMA 1 (0x0012 0x0052) (0x0030 0x0070) * hdh: DMA 1 (0x0052 0x0252) (0x0070 0x00f0) * - * drive_number - * = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); - * = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); */ #include @@ -58,7 +57,7 @@ static void hpt34x_clear_chipset (ide_drive_t *drive) pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, ®1); pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, ®2); tmp1 = ((0x00 << (3*drive_number)) | (reg1 & ~(7 << (3*drive_number)))); - tmp2 = ((0x00 << drive_number) | reg2); + tmp2 = (reg2 & ~(0x11 << drive_number)); pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1); pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2); } @@ -105,7 +104,7 @@ static int hpt34x_tune_chipset (ide_drive_t *drive, byte speed) * after the drive is reported by the OS. Initally for designed for * HPT343 UDMA chipset by HighPoint|Triones Technologies, Inc. */ -static int config_chipset_for_dma (ide_drive_t *drive) +static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) { struct hd_driveid *id = drive->id; byte speed = 0x00; @@ -117,76 +116,29 @@ static int config_chipset_for_dma (ide_drive_t *drive) return ((int) ide_dma_off_quietly); #endif /* HPT343_DISABLE_ALL_DMAING */ - if (id->dma_ultra & 0x0010) { - goto backspeed; - } else if (id->dma_ultra & 0x0008) { - goto backspeed; - } else if (id->dma_ultra & 0x0004) { -backspeed: - if (!((id->dma_ultra >> 8) & 4)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0404; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } + hpt34x_clear_chipset(drive); + + if ((id->dma_ultra & 0x0010) && ultra) { speed = XFER_UDMA_2; - } else if (id->dma_ultra & 0x0002) { - if (!((id->dma_ultra >> 8) & 2)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0202; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } + } else if ((id->dma_ultra & 0x0008) && ultra) { + speed = XFER_UDMA_2; + } else if ((id->dma_ultra & 0x0004) && ultra) { + speed = XFER_UDMA_2; + } else if ((id->dma_ultra & 0x0002) && ultra) { speed = XFER_UDMA_1; - } else if (id->dma_ultra & 0x0001) { - if (!((id->dma_ultra >> 8) & 1)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0101; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } + } else if ((id->dma_ultra & 0x0001) && ultra) { speed = XFER_UDMA_0; } else if (id->dma_mword & 0x0004) { - if (!((id->dma_mword >> 8) & 4)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0404; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_MW_DMA_2; } else if (id->dma_mword & 0x0002) { - if (!((id->dma_mword >> 8) & 2)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0202; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_MW_DMA_1; } else if (id->dma_mword & 0x0001) { - if (!((id->dma_mword >> 8) & 1)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0101; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_MW_DMA_0; } else if (id->dma_1word & 0x0004) { - if (!((id->dma_1word >> 8) & 4)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0404; - drive->id->dma_mword &= ~0x0F00; - } speed = XFER_SW_DMA_2; } else if (id->dma_1word & 0x0002) { - if (!((id->dma_1word >> 8) & 2)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0202; - drive->id->dma_mword &= ~0x0F00; - } speed = XFER_SW_DMA_1; } else if (id->dma_1word & 0x0001) { - if (!((id->dma_1word >> 8) & 1)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0101; - drive->id->dma_mword &= ~0x0F00; - } speed = XFER_SW_DMA_0; } else { return ((int) ide_dma_off_quietly); @@ -242,7 +194,6 @@ static void hpt34x_tune_drive (ide_drive_t *drive, byte pio) { byte speed; - hpt34x_clear_chipset(drive); switch(pio) { case 4: speed = XFER_PIO_4;break; case 3: speed = XFER_PIO_3;break; @@ -250,6 +201,7 @@ static void hpt34x_tune_drive (ide_drive_t *drive, byte pio) case 1: speed = XFER_PIO_1;break; default: speed = XFER_PIO_0;break; } + hpt34x_clear_chipset(drive); (void) hpt34x_tune_chipset(drive, speed); } @@ -268,7 +220,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive) if (id->field_valid & 4) { if (id->dma_ultra & 0x0007) { /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive); + dma_func = config_chipset_for_dma(drive, 1); if ((id->field_valid & 2) && (dma_func != ide_dma_on)) goto try_dma_modes; @@ -278,7 +230,7 @@ try_dma_modes: if ((id->dma_mword & 0x0007) || (id->dma_1word & 0x0007)) { /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive); + dma_func = config_chipset_for_dma(drive, 0); if (dma_func != ide_dma_on) goto no_dma_set; } @@ -287,7 +239,7 @@ try_dma_modes: goto no_dma_set; } /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive); + dma_func = config_chipset_for_dma(drive, 0); if (dma_func != ide_dma_on) goto no_dma_set; } else { @@ -300,6 +252,12 @@ no_dma_set: config_chipset_for_pio(drive); } + +#if 0 + if (dma_func == ide_dma_on) + dma_func = ide_dma_off; +#endif + return HWIF(drive)->dmaproc(dma_func, drive); } @@ -313,22 +271,44 @@ no_dma_set: int hpt34x_dmaproc (ide_dma_action_t func, ide_drive_t *drive) { + ide_hwif_t *hwif = HWIF(drive); + unsigned long dma_base = hwif->dma_base; + byte unit = (drive->select.b.unit & 0x01); + unsigned int count, reading = 0; + byte dma_stat; + switch (func) { - case ide_dma_check: - hpt34x_clear_chipset(drive); - return config_drive_xfer_rate(drive); -#if 0 case ide_dma_off: case ide_dma_off_quietly: + outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2); + break; case ide_dma_on: + outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); + break; case ide_dma_check: return config_drive_xfer_rate(drive); case ide_dma_read: + reading = 1 << 3; case ide_dma_write: - case ide_dma_begin: - case ide_dma_end: - case ide_dma_test_irq: -#endif + if (!(count = ide_build_dmatable(drive, func))) + return 1; /* try PIO instead of DMA */ + outl(virt_to_bus(hwif->dmatable), dma_base + 4); /* PRD table */ + reading |= 0x01; + outb(reading, dma_base); /* specify r/w */ + outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */ + drive->waiting_for_dma = 1; + if (drive->media != ide_disk) + return 0; + drive->timeout = WAIT_CMD; + ide_set_handler(drive, &ide_dma_intr); /* issue cmd to drive */ + OUT_BYTE((reading == 9) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); + return 0; + case ide_dma_end: /* returns 1 on error, 0 otherwise */ + drive->waiting_for_dma = 0; + outb(inb(dma_base)&~1, dma_base); /* stop DMA */ + dma_stat = inb(dma_base+2); /* get DMA status */ + outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ + return (dma_stat & 7) != 4; /* verify good DMA status */ default: break; } @@ -342,10 +322,17 @@ int hpt34x_dmaproc (ide_dma_action_t func, ide_drive_t *drive) unsigned int __init pci_init_hpt34x (struct pci_dev *dev, const char *name) { + int i = 0; + unsigned long hpt34xIoBase = dev->resource[4].start; unsigned short cmd; + unsigned long flags; + + __save_flags(flags); /* local CPU only */ + __cli(); /* local CPU only */ pci_write_config_byte(dev, HPT34X_PCI_INIT_REG, 0x00); pci_read_config_word(dev, PCI_COMMAND, &cmd); + if (cmd & PCI_COMMAND_MEMORY) { if (dev->resource[PCI_ROM_RESOURCE].start) { pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); @@ -353,27 +340,28 @@ unsigned int __init pci_init_hpt34x (struct pci_dev *dev, const char *name) } pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0); } else { - int i = 0; - unsigned long hpt34xIoBase = dev->resource[4].start; - - pci_write_config_word(dev, PCI_COMMAND, cmd & ~PCI_COMMAND_IO); - dev->resource[0].start = (hpt34xIoBase + 0x20); - dev->resource[1].start = (hpt34xIoBase + 0x34); - dev->resource[2].start = (hpt34xIoBase + 0x28); - dev->resource[3].start = (hpt34xIoBase + 0x3c); - for(i=0; i<4; i++) - dev->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; - /* - * Since 20-23 can be assigned and are R/W, we correct them. - */ - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, dev->resource[0].start); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, dev->resource[1].start); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, dev->resource[2].start); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_3, dev->resource[3].start); - - pci_write_config_word(dev, PCI_COMMAND, cmd); pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); } + + pci_write_config_word(dev, PCI_COMMAND, cmd & ~PCI_COMMAND_IO); + dev->resource[0].start = (hpt34xIoBase + 0x20); + dev->resource[1].start = (hpt34xIoBase + 0x34); + dev->resource[2].start = (hpt34xIoBase + 0x28); + dev->resource[3].start = (hpt34xIoBase + 0x3c); + for(i=0; i<4; i++) + dev->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; + /* + * Since 20-23 can be assigned and are R/W, we correct them. + */ + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, dev->resource[0].start); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, dev->resource[1].start); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, dev->resource[2].start); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_3, dev->resource[3].start); + + pci_write_config_word(dev, PCI_COMMAND, cmd); + + __restore_flags(flags); /* local CPU only */ + return dev->irq; } diff --git a/drivers/block/hpt366.c b/drivers/block/hpt366.c index b61f7168727e..d45b5f719267 100644 --- a/drivers/block/hpt366.c +++ b/drivers/block/hpt366.c @@ -1,11 +1,13 @@ /* - * linux/drivers/block/hpt366.c Version 0.12 August 16, 1999 + * linux/drivers/block/hpt366.c Version 0.13 Sept. 3, 1999 * * Copyright (C) 1999 Andre Hedrick + * May be copied or modified under the terms of the GNU General Public License * - * drive_number - * = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); - * = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); + * Thanks to HighPoint Technologies for their assistance, and hardware. + * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his + * donation of an ABit BP6 mainboard, processor, and memory acellerated + * development and support. */ #include @@ -114,17 +116,18 @@ struct chipset_bus_clock_list_entry twenty_five_base [] = { }; #define HPT366_DEBUG_DRIVE_INFO 0 -#define HPT366_ALLOW_ATA66_4 0 +#define HPT366_ALLOW_ATA66_4 1 #define HPT366_ALLOW_ATA66_3 1 -#define HPT366_ALLOW_ATA33_2 1 -#define HPT366_ALLOW_ATA33_1 1 -#define HPT366_ALLOW_ATA33_0 1 extern char *ide_xfer_verbose (byte xfer_rate); +byte hpt363_shared_irq = 0; static int check_in_drive_lists (ide_drive_t *drive, const char **list) { struct hd_driveid *id = drive->id; +#if HPT366_DEBUG_DRIVE_INFO + printk("check_in_drive_lists(%s, %p)\n", drive->name, list); +#endif /* HPT366_DEBUG_DRIVE_INFO */ while (*list) { if (!strcmp(*list++,id->model)) { @@ -139,50 +142,62 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list) static unsigned int pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table) { +#if HPT366_DEBUG_DRIVE_INFO + printk("pci_bus_clock_list(speed=0x%02x, table=%p)\n", speed, chipset_table); +#endif /* HPT366_DEBUG_DRIVE_INFO */ for ( ; chipset_table->xfer_speed ; chipset_table++) - if (chipset_table->xfer_speed == speed) + if (chipset_table->xfer_speed == speed) { +#if HPT366_DEBUG_DRIVE_INFO + printk("pci_bus_clock_list: found match: 0x%08x\n", chipset_table->chipset_settings); +#endif /* HPT366_DEBUG_DRIVE_INFO */ return chipset_table->chipset_settings; + } +#if HPT366_DEBUG_DRIVE_INFO + printk("pci_bus_clock_list: using default: 0x%08x\n", 0x01208585); +#endif /* HPT366_DEBUG_DRIVE_INFO */ return 0x01208585; } static int hpt366_tune_chipset (ide_drive_t *drive, byte speed) { int err; - byte busclock; - #if HPT366_DEBUG_DRIVE_INFO int drive_number = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); #endif /* HPT366_DEBUG_DRIVE_INFO */ - byte regtime = (drive->select.b.unit & 0x01) ? 0x43 : 0x40; + byte regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; unsigned int reg1 = 0; unsigned int reg2 = 0; +#if HPT366_DEBUG_DRIVE_INFO + printk("hpt366_tune_chipset(%s, speed=0x%02x)\n", drive->name, speed); +#endif /* HPT366_DEBUG_DRIVE_INFO */ + pci_read_config_dword(HWIF(drive)->pci_dev, regtime, ®1); - pci_read_config_byte(HWIF(drive)->pci_dev, regtime|0x01, &busclock); - switch(busclock) { - case 0xd9: + /* detect bus speed by looking at control reg timing: */ + switch((reg1 >> 8) & 7) { + case 5: reg2 = pci_bus_clock_list(speed, forty_base); break; - case 0x85: + case 9: reg2 = pci_bus_clock_list(speed, twenty_five_base); break; - case 0xa7: default: + printk("hpt366: assuming 33Mhz PCI bus\n"); + case 7: reg2 = pci_bus_clock_list(speed, thirty_three_base); break; } - - if (drive->id->dword_io & 1) - reg2 |= 0x80000000; - else - reg2 &= ~0x80000000; + /* + * Disable on-chip PIO FIFO/buffer (to avoid problems handling I/O errors later) + */ + reg2 &= ~0x80000000; pci_write_config_dword(HWIF(drive)->pci_dev, regtime, reg2); err = ide_config_drive_speed(drive, speed); #if HPT366_DEBUG_DRIVE_INFO - printk("%s: %s drive%d (0x%08x 0x%08x) 0x%04x\n", - drive->name, ide_xfer_verbose(speed), + printk("%s: speed=0x%02x(%s), drive%d, old=0x%08x, new=0x%08x, err=0x%04x\n", + drive->name, speed, ide_xfer_verbose(speed), drive_number, reg1, reg2, err); #endif /* HPT366_DEBUG_DRIVE_INFO */ return(err); @@ -203,127 +218,89 @@ static int config_chipset_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; byte speed = 0x00; + unsigned int reg40 = 0; + int rval; if ((id->dma_ultra & 0x0010) && (!check_in_drive_lists(drive, bad_ata66_4)) && (HPT366_ALLOW_ATA66_4) && (HWIF(drive)->udma_four)) { - if (!((id->dma_ultra >> 8) & 16)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x1010; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_UDMA_4; } else if ((id->dma_ultra & 0x0008) && (!check_in_drive_lists(drive, bad_ata66_3)) && (HPT366_ALLOW_ATA66_3) && (HWIF(drive)->udma_four)) { - if (!((id->dma_ultra >> 8) & 8)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0808; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_UDMA_3; - } else if ((id->dma_ultra & 0x0004) && - (HPT366_ALLOW_ATA33_2) && - (!check_in_drive_lists(drive, bad_ata33))) { - if (!((id->dma_ultra >> 8) & 4)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0404; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && - (HPT366_ALLOW_ATA33_1) && - (!check_in_drive_lists(drive, bad_ata33))) { - if (!((id->dma_ultra >> 8) & 2)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0202; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; + } else if (id->dma_ultra && (!check_in_drive_lists(drive, bad_ata33))) { + if (id->dma_ultra & 0x0004) { + speed = XFER_UDMA_2; + } else if (id->dma_ultra & 0x0002) { + speed = XFER_UDMA_1; + } else if (id->dma_ultra & 0x0001) { + speed = XFER_UDMA_0; } - speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && - (HPT366_ALLOW_ATA33_0) && - (!check_in_drive_lists(drive, bad_ata33))) { - if (!((id->dma_ultra >> 8) & 1)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0101; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } - speed = XFER_UDMA_0; } else if (id->dma_mword & 0x0004) { - drive->id->dma_ultra &= ~0xFF00; - if (!((id->dma_mword >> 8) & 4)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0404; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_MW_DMA_2; } else if (id->dma_mword & 0x0002) { - drive->id->dma_ultra &= ~0xFF00; - if (!((id->dma_mword >> 8) & 2)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0202; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_MW_DMA_1; } else if (id->dma_mword & 0x0001) { - drive->id->dma_ultra &= ~0xFF00; - if (!((id->dma_mword >> 8) & 1)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0101; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_MW_DMA_0; } else if (id->dma_1word & 0x0004) { - drive->id->dma_ultra &= ~0xFF00; - if (!((id->dma_1word >> 8) & 4)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0404; - drive->id->dma_mword &= ~0x0F00; - } speed = XFER_SW_DMA_2; } else if (id->dma_1word & 0x0002) { - drive->id->dma_ultra &= ~0xFF00; - if (!((id->dma_1word >> 8) & 2)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0202; - drive->id->dma_mword &= ~0x0F00; - } speed = XFER_SW_DMA_1; } else if (id->dma_1word & 0x0001) { - drive->id->dma_ultra &= ~0xFF00; - if (!((id->dma_1word >> 8) & 1)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0101; - drive->id->dma_mword &= ~0x0F00; - } speed = XFER_SW_DMA_0; } else { +#if HPT366_DEBUG_DRIVE_INFO + printk("%s: config_chipset_for_dma: returning 'ide_dma_off_quietly'\n", drive->name); +#endif /* HPT366_DEBUG_DRIVE_INFO */ return ((int) ide_dma_off_quietly); } + /* Disable the "fast interrupt" prediction. + * Instead, always wait for the real interrupt from the drive! + */ + { + byte reg51h = 0; + pci_read_config_byte(HWIF(drive)->pci_dev, 0x51, ®51h); + if (reg51h & 0x80) + pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, reg51h & ~0x80); + } + + /* + * Preserve existing PIO settings: + */ + pci_read_config_dword(HWIF(drive)->pci_dev, 0x40, ®40); + speed = (speed & ~0xc0000000) | (reg40 & 0xc0000000); + +#if HPT366_DEBUG_DRIVE_INFO + printk("%s: config_chipset_for_dma: speed=0x%04x\n", drive->name, speed); +#endif /* HPT366_DEBUG_DRIVE_INFO */ (void) hpt366_tune_chipset(drive, speed); - return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on : + rval = (int)( ((id->dma_ultra >> 11) & 3) ? ide_dma_on : ((id->dma_ultra >> 8) & 7) ? ide_dma_on : ((id->dma_mword >> 8) & 7) ? ide_dma_on : ((id->dma_1word >> 8) & 7) ? ide_dma_on : ide_dma_off_quietly); + +#if HPT366_DEBUG_DRIVE_INFO + printk("%s: config_chipset_for_dma: returning %d (%s)\n", drive->name, rval, rval == ide_dma_on ? "dma_on" : "dma_off"); +#endif /* HPT366_DEBUG_DRIVE_INFO */ + return rval; } static void config_chipset_for_pio (ide_drive_t *drive) { unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90}; unsigned short xfer_pio = drive->id->eide_pio_modes; - byte timing, speed, pio; + unsigned int reg40 = 0; +#if HPT366_DEBUG_DRIVE_INFO + printk("%s: config_chipset_for_pio\n", drive->name); +#endif /* HPT366_DEBUG_DRIVE_INFO */ pio = ide_get_best_pio_mode(drive, 255, 5, NULL); if (xfer_pio> 4) @@ -353,6 +330,14 @@ static void config_chipset_for_pio (ide_drive_t *drive) speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW; break; } + /* + * Preserve existing DMA settings: + */ + pci_read_config_dword(HWIF(drive)->pci_dev, 0x40, ®40); + speed = (speed & ~0x30070000) | (reg40 & 0x30070000); +#if HPT366_DEBUG_DRIVE_INFO + printk("%s: config_chipset_for_pio: speed=0x%04x\n", drive->name, speed); +#endif /* HPT366_DEBUG_DRIVE_INFO */ (void) hpt366_tune_chipset(drive, speed); } @@ -428,8 +413,9 @@ no_dma_set: int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive) { +#if 0 byte reg50h = 0, reg52h = 0; - +#endif switch (func) { case ide_dma_check: return config_drive_xfer_rate(drive); @@ -463,28 +449,81 @@ int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive) unsigned int __init pci_init_hpt366 (struct pci_dev *dev, const char *name) { - byte ata66 = 0; + byte test = 0; - pci_read_config_byte(dev, 0x5a, &ata66); if (dev->resource[PCI_ROM_RESOURCE].start) pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - printk("%s: reg5ah=0x%02x ATA-%s Cable Port%d\n", name, ata66, (ata66 & 0x02) ? "33" : "66", PCI_FUNC(dev->devfn)); + + pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &test); + if (test != 0x08) + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x08); + + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &test); + if (test != 0x78) + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); + + pci_read_config_byte(dev, PCI_MIN_GNT, &test); + if (test != 0x08) + pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); + + pci_read_config_byte(dev, PCI_MAX_LAT, &test); + if (test != 0x08) + pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); + return dev->irq; } +unsigned int __init ata66_hpt366 (ide_hwif_t *hwif) +{ + byte ata66 = 0; + + pci_read_config_byte(hwif->pci_dev, 0x5a, &ata66); +#ifdef DEBUG + printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n", + ata66, (ata66 & 0x02) ? "33" : "66", + PCI_FUNC(hwif->pci_dev->devfn)); +#endif /* DEBUG */ + return ((ata66 & 0x02) ? 0 : 1); +} + void __init ide_init_hpt366 (ide_hwif_t *hwif) { +#if 0 + if ((PCI_FUNC(hwif->pci_dev->devfn) & 1) && (hpt363_shared_irq)) { + hwif->mate = &ide_hwifs[hwif->index-1]; + hwif->mate->mate = hwif; + hwif->serialized = hwif->mate->serialized = 1; + } +#endif + hwif->tuneproc = &hpt366_tune_drive; if (hwif->dma_base) { - byte ata66 = 0; - hwif->dmaproc = &hpt366_dmaproc; - pci_read_config_byte(hwif->pci_dev, 0x5a, &ata66); - hwif->udma_four = (ata66 & 0x02) ? 0 : 1; } else { - hwif->udma_four = 0; hwif->autodma = 0; hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; } } + +void ide_dmacapable_hpt366 (ide_hwif_t *hwif, unsigned long dmabase) +{ + byte masterdma = 0, slavedma = 0; + byte dma_new = 0, dma_old = inb(dmabase+2); + unsigned long flags; + + __save_flags(flags); /* local CPU only */ + __cli(); /* local CPU only */ + + dma_new = dma_old; + pci_read_config_byte(hwif->pci_dev, 0x43, &masterdma); + pci_read_config_byte(hwif->pci_dev, 0x47, &slavedma); + + if (masterdma & 0x30) dma_new |= 0x20; + if (slavedma & 0x30) dma_new |= 0x40; + if (dma_new != dma_old) outb(dma_new, dmabase+2); + + __restore_flags(flags); /* local CPU only */ + + ide_setup_dma(hwif, dmabase, 8); +} diff --git a/drivers/block/icside.c b/drivers/block/icside.c index 629ad927dedf..a9282de3fa5b 100644 --- a/drivers/block/icside.c +++ b/drivers/block/icside.c @@ -382,7 +382,8 @@ icside_dmaproc(ide_dma_action_t func, ide_drive_t *drive) if (drive->media != ide_disk) return 0; - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD); + drive->timeout = WAIT_CMD; + ide_set_handler(drive, &ide_dma_intr); OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); diff --git a/drivers/block/ide-cd.c b/drivers/block/ide-cd.c index b3ba0356226f..9977809abc76 100644 --- a/drivers/block/ide-cd.c +++ b/drivers/block/ide-cd.c @@ -699,7 +699,7 @@ static int cdrom_start_packet_command (ide_drive_t *drive, int xferlen, (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { - ide_set_handler (drive, handler, WAIT_CMD); + ide_set_handler (drive, handler); OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ } else { OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ @@ -716,9 +716,13 @@ static int cdrom_start_packet_command (ide_drive_t *drive, int xferlen, HANDLER is the interrupt handler to call when the command completes or there's data ready. */ static int cdrom_transfer_packet_command (ide_drive_t *drive, - char *cmd_buf, int cmd_len, + unsigned char *cmd_buf, int cmd_len, ide_handler_t *handler) { + /* set timeout to an hour */ + if (cmd_buf[0] == GPCMD_BLANK || cmd_buf[0] == GPCMD_FORMAT_UNIT) + drive->timeout = 3600*HZ; + if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { /* Here we should have been called after receiving an interrupt from the device. DRQ should how be set. */ @@ -734,7 +738,7 @@ static int cdrom_transfer_packet_command (ide_drive_t *drive, } /* Arm the interrupt handler. */ - ide_set_handler (drive, handler, WAIT_CMD); + ide_set_handler (drive, handler); /* Send the command to the device. */ atapi_output_bytes (drive, cmd_buf, cmd_len); @@ -827,6 +831,12 @@ int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason) atapi_output_bytes (drive, &dum, sizeof (dum)); len -= sizeof (dum); } + } else if (ireason == 1) { + /* Some drives (ASUS) seem to tell us that status + * info is available. just get it and ignore. + */ + GET_STAT(); + return 0; } else { /* Drive wants a command packet, or invalid ireason... */ printk ("%s: cdrom_read_intr: bad interrupt reason %d\n", @@ -837,7 +847,6 @@ int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason) return -1; } - /* * Interrupt routine. Called when a read request has completed. */ @@ -966,7 +975,7 @@ static void cdrom_read_intr (ide_drive_t *drive) /* Done moving data! Wait for another interrupt. */ - ide_set_handler (drive, &cdrom_read_intr, WAIT_CMD); + ide_set_handler (drive, &cdrom_read_intr); } @@ -1026,8 +1035,6 @@ static int cdrom_read_from_buffer (ide_drive_t *drive) return 0; } - - /* * Routine to send a read packet command to the drive. * This is usually called directly from cdrom_start_read. @@ -1084,7 +1091,7 @@ static void cdrom_start_read_continuation (ide_drive_t *drive) pc.c[0] = GPCMD_READ_10; pc.c[7] = (nframes >> 8); pc.c[8] = (nframes & 0xff); - put_unaligned(htonl (frame), (unsigned int *) &pc.c[2]); + put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]); /* Send the command to the drive and return. */ (void) cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c), @@ -1127,7 +1134,7 @@ static void cdrom_start_seek_continuation (ide_drive_t *drive) memset (&pc.c, 0, sizeof (pc.c)); pc.c[0] = GPCMD_SEEK; - put_unaligned(htonl (frame), (unsigned int *) &pc.c[2]); + put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]); (void) cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c), &cdrom_seek_intr); } @@ -1179,8 +1186,6 @@ static void cdrom_start_read (ide_drive_t *drive, unsigned int block) } - - /**************************************************************************** * Execute all other packet commands. */ @@ -1197,6 +1202,9 @@ static void cdrom_pc_intr (ide_drive_t *drive) struct request *rq = HWGROUP(drive)->rq; struct packet_command *pc = (struct packet_command *)rq->buffer; + /* restore timeout after blank or format command */ + drive->timeout = WAIT_CMD; + /* Check for errors. */ if (cdrom_decode_status (drive, 0, &stat)) return; @@ -1282,7 +1290,7 @@ static void cdrom_pc_intr (ide_drive_t *drive) } /* Now we wait for another interrupt. */ - ide_set_handler (drive, &cdrom_pc_intr, WAIT_CMD); + ide_set_handler (drive, &cdrom_pc_intr); } @@ -1334,6 +1342,7 @@ int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc) if (pc->sense_data == NULL) pc->sense_data = &my_reqbuf; pc->sense_data->sense_key = 0; + /* Start of retry loop. */ do { ide_init_drive_cmd (&req); @@ -1368,7 +1377,6 @@ int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc) /* End of retry loop. */ } while (pc->stat != 0 && retries >= 0); - /* Return an error if the command failed. */ if (pc->stat != 0) return -EIO; @@ -1397,16 +1405,8 @@ int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc) static void ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long block) { - if (rq -> cmd == PACKET_COMMAND || rq -> cmd == REQUEST_SENSE_COMMAND) - cdrom_do_packet_command (drive); - else if (rq -> cmd == RESET_DRIVE_COMMAND) { - cdrom_end_request (1, drive); - ide_do_reset (drive); - return; - } else if (rq -> cmd != READ) { - printk ("ide-cd: bad cmd %d\n", rq -> cmd); - cdrom_end_request (0, drive); - } else { + switch (rq->cmd) { + case READ: { struct cdrom_info *info = drive->driver_data; if (CDROM_CONFIG_FLAGS(drive)->seeking) { @@ -1415,7 +1415,7 @@ void ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long bloc if ((stat & SEEK_STAT) != SEEK_STAT) { if (elpased < IDECD_SEEK_TIMEOUT) { - ide_stall_queue (drive, IDECD_SEEK_TIMER); + ide_stall_queue(drive, IDECD_SEEK_TIMER); return; } printk ("%s: DSC timeout\n", drive->name); @@ -1427,6 +1427,26 @@ void ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long bloc else cdrom_start_read (drive, block); info->last_block = block; + break; + } + + case PACKET_COMMAND: + case REQUEST_SENSE_COMMAND: { + cdrom_do_packet_command(drive); + break; + } + + case RESET_DRIVE_COMMAND: { + cdrom_end_request(1, drive); + ide_do_reset(drive); + break; + } + + default: { + printk("ide-cd: bad cmd %d\n", rq -> cmd); + cdrom_end_request(0, drive); + break; + } } } @@ -1600,7 +1620,7 @@ cdrom_read_capacity (ide_drive_t *drive, unsigned *capacity, stat = cdrom_queue_packet_command (drive, &pc); if (stat == 0) - *capacity = ntohl (capbuf.lba); + *capacity = be32_to_cpu(capbuf.lba); return stat; } @@ -1879,64 +1899,7 @@ int cdrom_get_toc_entry (ide_drive_t *drive, int track, -/* This gets the mechanism status per ATAPI draft spec 2.6 */ -static int -cdrom_read_mech_status (ide_drive_t *drive, char *buf, int buflen, - struct atapi_request_sense *reqbuf) -{ - struct packet_command pc; - - memset (&pc, 0, sizeof (pc)); - pc.sense_data = reqbuf; - - pc.buffer = buf; - pc.buflen = buflen; - pc.c[0] = GPCMD_MECHANISM_STATUS; - pc.c[8] = (buflen >> 8); - pc.c[9] = (buflen & 0xff); - return cdrom_queue_packet_command (drive, &pc); -} - -/* Read the drive mechanism status and slot table into our internal buffer. - If the buffer does not yet exist, allocate it. */ -static int -cdrom_read_changer_info (ide_drive_t *drive) -{ - int nslots; - struct cdrom_info *info = drive->driver_data; - - if (info->changer_info) - nslots = info->changer_info->hdr.nslots; - - else { - struct atapi_mechstat_header mechbuf; - int stat; - - stat = cdrom_read_mech_status (drive, - (char *)&mechbuf, - sizeof (mechbuf), - NULL); - if (stat) - return stat; - - nslots = mechbuf.nslots; - info->changer_info = - (struct atapi_changer_info *) - kmalloc (sizeof (struct atapi_changer_info) + - nslots * sizeof (struct atapi_slot), - GFP_KERNEL); - if (info->changer_info == NULL) - return -ENOMEM; - } - - return cdrom_read_mech_status - (drive, - (char *)&info->changer_info->hdr, - sizeof (struct atapi_mechstat_header) + - nslots * sizeof (struct atapi_slot), - NULL); -} /* the generic packet interface to cdrom.c */ static int ide_cdrom_packet(struct cdrom_device_info *cdi, @@ -1952,8 +1915,7 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi, memcpy(pc.c, cgc->cmd, CDROM_PACKET_SIZE); pc.buffer = cgc->buffer; pc.buflen = cgc->buflen; - cgc->stat = cdrom_queue_packet_command(drive, &pc); - return cgc->stat; + return cgc->stat = cdrom_queue_packet_command(drive, &pc); } static @@ -2130,7 +2092,6 @@ static int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr) { ide_drive_t *drive = (ide_drive_t*) cdi->handle; - struct cdrom_info *info = drive->driver_data; if (slot_nr == CDSL_CURRENT) { @@ -2147,24 +2108,8 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr) } return CDS_DRIVE_NOT_READY; - } - -#if ! STANDARD_ATAPI - else if (cdi->sanyo_slot > 0) - return CDS_NO_INFO; -#endif /* not STANDARD_ATAPI */ - - else { - struct atapi_changer_info *ci; - int stat = cdrom_read_changer_info (drive); - if (stat < 0) - return stat; - ci = info->changer_info; - - if (ci->slots[slot_nr].disc_present) - return CDS_DISC_OK; - else - return CDS_NO_DISC; + } else { + return -EINVAL; } } @@ -2215,47 +2160,14 @@ int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi, int slot_nr) { ide_drive_t *drive = (ide_drive_t*) cdi->handle; - struct cdrom_info *info = drive->driver_data; - struct atapi_request_sense reqbuf; - int retval; if (slot_nr == CDSL_CURRENT) { (void) cdrom_check_status (drive, NULL); - retval = CDROM_STATE_FLAGS (drive)->media_changed; CDROM_STATE_FLAGS (drive)->media_changed = 0; + return CDROM_STATE_FLAGS (drive)->media_changed; + } else { + return -EINVAL; } - -#if ! STANDARD_ATAPI - else if (cdi->sanyo_slot > 0) { - retval = 0; - } -#endif /* not STANDARD_ATAPI */ - - else { - struct atapi_changer_info *ci; - int stat = cdrom_read_changer_info (drive); - if (stat < 0) - return stat; - ci = info->changer_info; - - /* This test may be redundant with cdrom.c. */ - if (slot_nr < 0 || slot_nr >= ci->hdr.nslots) - return -EINVAL; - - retval = ci->slots[slot_nr].change; - } - - /* if the media has changed, check if a disc is in the drive - and read the toc info. */ - if (retval || !CDROM_STATE_FLAGS (drive)->toc_valid) { - /* if cdrom_read_toc fails, return 1 to indicate - that a disc change has occured. there might not - be a disc in the drive. */ - if ((retval = cdrom_read_toc (drive, &reqbuf))) - return 1; - } - - return retval; } @@ -2361,11 +2273,12 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) * be queued with ide_cdrom_packet(), which extracts the * drive from cdi->handle. Since this device hasn't been * registered with the Uniform layer yet, it can't do this. - * Same goes cdi->ops. + * Same goes for cdi->ops. */ cdi->handle = (ide_drive_t *) drive; cdi->ops = &ide_cdrom_dops; - do { /* we seem to get stat=0x01,err=0x00 the first time (??) */ + /* we seem to get stat=0x01,err=0x00 the first time (??) */ + do { if (attempts-- <= 0) return 0; stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0); @@ -2402,14 +2315,9 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) #endif /* not STANDARD_ATAPI */ if (buf.cap.mechtype == mechtype_individual_changer || buf.cap.mechtype == mechtype_cartridge_changer) { - struct atapi_mechstat_header mechbuf; - - stat = cdrom_read_mech_status (drive, (char*)&mechbuf, - sizeof (mechbuf), NULL); - if (!stat) { + if ((nslots = cdrom_number_of_slots(cdi)) > 1) { CDROM_CONFIG_FLAGS (drive)->is_changer = 1; CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 1; - nslots = mechbuf.nslots; } } @@ -2445,7 +2353,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) else printk (" drive"); - printk (", %dkB Cache", ntohs(buf.cap.buffer_size)); + printk (", %dkB Cache", be16_to_cpu(buf.cap.buffer_size)); if (drive->using_dma) { if ((drive->id->field_valid & 4) && @@ -2482,13 +2390,12 @@ int ide_cdrom_setup (ide_drive_t *drive) int minor = drive->select.b.unit << PARTN_BITS; int nslots; - kdev_t dev = MKDEV(HWIF(drive)->major, minor); - - set_device_ro (dev, 1); + set_device_ro(MKDEV(HWIF(drive)->major, minor), 1); blksize_size[HWIF(drive)->major][minor] = CD_FRAMESIZE; - drive->special.all = 0; - drive->ready_stat = 0; + drive->special.all = 0; + drive->ready_stat = 0; + drive->timeout = WAIT_CMD; CDROM_STATE_FLAGS (drive)->media_changed = 1; CDROM_STATE_FLAGS (drive)->toc_valid = 0; @@ -2594,6 +2501,8 @@ int ide_cdrom_setup (ide_drive_t *drive) info->sector_buffered = 0; info->nsectors_buffered = 0; info->changer_info = NULL; + info->last_block = 0; + info->start_seek = 0; nslots = ide_cdrom_probe_capabilities (drive); @@ -2654,14 +2563,14 @@ int ide_cdrom_cleanup(ide_drive_t *drive) if (ide_unregister_subdriver (drive)) return 1; if (info->sector_buffer != NULL) - kfree (info->sector_buffer); + kfree(info->sector_buffer); if (info->toc != NULL) - kfree (info->toc); + kfree(info->toc); if (info->changer_info != NULL) - kfree (info->changer_info); + kfree(info->changer_info); if (devinfo->handle == drive && unregister_cdrom (devinfo)) printk ("%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name); - kfree (info); + kfree(info); drive->driver_data = NULL; return 0; } diff --git a/drivers/block/ide-cd.h b/drivers/block/ide-cd.h index ae1a252edb23..e87c0b4311fe 100644 --- a/drivers/block/ide-cd.h +++ b/drivers/block/ide-cd.h @@ -96,7 +96,8 @@ struct ide_cd_state_flags { __u8 media_changed : 1; /* Driver has noticed a media change. */ __u8 toc_valid : 1; /* Saved TOC information is current. */ __u8 door_locked : 1; /* We think that the drive door is locked. */ - __u8 reserved : 5; + __u8 writing : 1; /* the drive is currently writing */ + __u8 reserved : 4; byte current_speed; /* Current speed of the drive */ }; #define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags)) diff --git a/drivers/block/ide-disk.c b/drivers/block/ide-disk.c index d2941a1ab7a8..8fa7745b4d56 100644 --- a/drivers/block/ide-disk.c +++ b/drivers/block/ide-disk.c @@ -175,7 +175,7 @@ read_next: if (i > 0) { if (msect) goto read_next; - ide_set_handler (drive, &read_intr, WAIT_CMD); + ide_set_handler (drive, &read_intr); } } @@ -206,7 +206,7 @@ static void write_intr (ide_drive_t *drive) ide_end_request(1, hwgroup); if (i > 0) { idedisk_output_data (drive, rq->buffer, SECTOR_WORDS); - ide_set_handler (drive, &write_intr, WAIT_CMD); + ide_set_handler (drive, &write_intr); } goto out; } @@ -271,7 +271,7 @@ static void multwrite_intr (ide_drive_t *drive) if (stat & DRQ_STAT) { if (rq->nr_sectors) { ide_multwrite(drive, drive->mult_count); - ide_set_handler (drive, &multwrite_intr, WAIT_CMD); + ide_set_handler (drive, &multwrite_intr); goto out; } } else { @@ -385,7 +385,7 @@ static void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long bl if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_read, drive))) return; #endif /* CONFIG_BLK_DEV_IDEDMA */ - ide_set_handler(drive, &read_intr, WAIT_CMD); + ide_set_handler(drive, &read_intr); OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, IDE_COMMAND_REG); return; } @@ -404,10 +404,10 @@ static void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long bl __cli(); /* local CPU only */ if (drive->mult_count) { HWGROUP(drive)->wrq = *rq; /* scratchpad */ - ide_set_handler (drive, &multwrite_intr, WAIT_CMD); + ide_set_handler (drive, &multwrite_intr); ide_multwrite(drive, drive->mult_count); } else { - ide_set_handler (drive, &write_intr, WAIT_CMD); + ide_set_handler (drive, &write_intr); idedisk_output_data(drive, rq->buffer, SECTOR_WORDS); } return; @@ -506,6 +506,7 @@ static void idedisk_pre_reset (ide_drive_t *drive) drive->special.all = 0; drive->special.b.set_geometry = 1; drive->special.b.recalibrate = 1; + drive->timeout = WAIT_CMD; if (OK_TO_RESET_CONTROLLER) drive->mult_count = 0; if (!drive->keep_settings) diff --git a/drivers/block/ide-dma.c b/drivers/block/ide-dma.c index d3c657516770..b1d0979c3ba9 100644 --- a/drivers/block/ide-dma.c +++ b/drivers/block/ide-dma.c @@ -420,7 +420,8 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive) drive->waiting_for_dma = 1; if (drive->media != ide_disk) return 0; - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD);/* issue cmd to drive */ + drive->timeout = WAIT_CMD; + ide_set_handler(drive, &ide_dma_intr);/* issue cmd to drive */ OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); case ide_dma_begin: /* Note that this is done *after* the cmd has @@ -537,14 +538,7 @@ unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const switch(dev->device) { case PCI_DEVICE_ID_CMD_643: -#ifdef CONFIG_BLK_DEV_ALI15X3 case PCI_DEVICE_ID_AL_M5219: - case PCI_DEVICE_ID_AL_M5229: - /* - * Ali 15x3 chipsets know as ALI IV and V report - * this as simplex, skip this test for them. - */ -#endif /* CONFIG_BLK_DEV_ALI15X3 */ outb(inb(dma_base+2) & 0x60, dma_base+2); if (inb(dma_base+2) & 0x80) { printk("%s: simplex device: DMA forced\n", name); diff --git a/drivers/block/ide-floppy.c b/drivers/block/ide-floppy.c index f1c8baef8bc4..3db1c1515644 100644 --- a/drivers/block/ide-floppy.c +++ b/drivers/block/ide-floppy.c @@ -916,7 +916,7 @@ static void idefloppy_pc_intr (ide_drive_t *drive) if (temp > pc->buffer_size) { printk (KERN_ERR "ide-floppy: The floppy wants to send us more data than expected - discarding data\n"); idefloppy_discard_data (drive,bcount.all); - ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD); + ide_set_handler (drive,&idefloppy_pc_intr); return; } #if IDEFLOPPY_DEBUG_LOG @@ -938,7 +938,7 @@ static void idefloppy_pc_intr (ide_drive_t *drive) pc->actually_transferred+=bcount.all; /* Update the current position */ pc->current_position+=bcount.all; - ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD); /* And set the interrupt handler again */ + ide_set_handler (drive,&idefloppy_pc_intr); /* And set the interrupt handler again */ } static void idefloppy_transfer_pc (ide_drive_t *drive) @@ -956,7 +956,7 @@ static void idefloppy_transfer_pc (ide_drive_t *drive) ide_do_reset (drive); return; } - ide_set_handler (drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD); /* Set the interrupt routine */ + ide_set_handler (drive, &idefloppy_pc_intr); /* Set the interrupt routine */ atapi_output_bytes (drive, floppy->pc->c, 12); /* Send the actual packet */ } @@ -1025,7 +1025,7 @@ static void idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc) #endif /* CONFIG_BLK_DEV_IDEDMA */ if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) { - ide_set_handler (drive, &idefloppy_transfer_pc, IDEFLOPPY_WAIT_CMD); + ide_set_handler (drive, &idefloppy_transfer_pc); OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ } else { OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); @@ -1519,6 +1519,7 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy) *((unsigned short *) &gcw) = drive->id->config; drive->driver_data = floppy; drive->ready_stat = 0; + drive->timeout = IDEFLOPPY_WAIT_CMD; memset (floppy, 0, sizeof (idefloppy_floppy_t)); floppy->drive = drive; floppy->pc = floppy->pc_stack; diff --git a/drivers/block/ide-geometry.c b/drivers/block/ide-geometry.c index 974fb24f1962..44aa1844df4d 100644 --- a/drivers/block/ide-geometry.c +++ b/drivers/block/ide-geometry.c @@ -5,6 +5,9 @@ #include +extern ide_drive_t * get_info_ptr(kdev_t); +extern unsigned long current_capacity (ide_drive_t *); + /* * We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc * controller that is BIOS compatible with ST-506, and thus showing up in our diff --git a/drivers/block/ide-pci.c b/drivers/block/ide-pci.c index 311bd470bfac..73ffa67ea7b1 100644 --- a/drivers/block/ide-pci.c +++ b/drivers/block/ide-pci.c @@ -57,8 +57,9 @@ #define DEVID_CY82C693 ((ide_pci_devid_t){PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693}) #define DEVID_HINT ((ide_pci_devid_t){0x3388, 0x8013}) #define DEVID_CX5530 ((ide_pci_devid_t){PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE}) +#define DEVID_AMD7409 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, 0x7409}) -#define IDE_IGNORE ((void *)-1) +#define IDE_IGNORE ((void *)-1) #ifdef CONFIG_BLK_DEV_TRM290 extern void ide_init_trm290(ide_hwif_t *); @@ -106,54 +107,66 @@ extern void ide_init_rz1000(ide_hwif_t *); #define INIT_RZ1000 IDE_IGNORE #endif -#ifdef CONFIG_BLK_DEV_VIA82C586 -extern unsigned int pci_init_via82c568(struct pci_dev *, const char *); -extern void ide_init_via82c586(ide_hwif_t *); -extern void ide_dmacapable_via82c586(ide_hwif_t *, unsigned long dmabase); -#define PCI_VIA82C586 &pci_init_via82c568 -#define INIT_VIA82C586 &ide_init_via82c586 -#define DMA_VIA82C586 &ide_dmacapable_via82c586 +#ifdef CONFIG_BLK_DEV_VIA82CXXX +extern unsigned int pci_init_via82cxxx(struct pci_dev *, const char *); +extern unsigned int ata66_via82cxxx(ide_hwif_t *); +extern void ide_init_via82cxxx(ide_hwif_t *); +extern void ide_dmacapable_via82cxxx(ide_hwif_t *, unsigned long); +#define PCI_VIA82CXXX &pci_init_via82cxxx +#define ATA66_VIA82CXXX &ata66_via82cxxx +#define INIT_VIA82CXXX &ide_init_via82cxxx +#define DMA_VIA82CXXX &ide_dmacapable_via82cxxx #else -#define PCI_VIA82C586 NULL -#define INIT_VIA82C586 NULL -#define DMA_VIA82C586 NULL +#define PCI_VIA82CXXX NULL +#define ATA66_VIA82CXXX NULL +#define INIT_VIA82CXXX NULL +#define DMA_VIA82CXXX NULL #endif #ifdef CONFIG_BLK_DEV_ALI15X3 extern unsigned int pci_init_ali15x3(struct pci_dev *, const char *); +extern unsigned int ata66_ali15x3(ide_hwif_t *); extern void ide_init_ali15x3(ide_hwif_t *); +extern void ide_dmacapable_ali15x3(ide_hwif_t *, unsigned long); #define PCI_ALI15X3 &pci_init_ali15x3 -#define INIT_ALI15X3 &ide_init_ali15x3 +#define ATA66_ALI15X3 &ata66_ali15x3 +#define INIT_ALI15X3 &ide_init_ali15x3 +#define DMA_ALI15X3 &ide_dmacapable_ali15x3 #else #define PCI_ALI15X3 NULL -#define INIT_ALI15X3 NULL +#define ATA66_ALI15X3 NULL +#define INIT_ALI15X3 NULL +#define DMA_ALI15X3 NULL #endif #ifdef CONFIG_BLK_DEV_CY82C693 extern unsigned int pci_init_cy82c693(struct pci_dev *, const char *); extern void ide_init_cy82c693(ide_hwif_t *); #define PCI_CY82C693 &pci_init_cy82c693 -#define INIT_CY82C693 &ide_init_cy82c693 +#define INIT_CY82C693 &ide_init_cy82c693 #else #define PCI_CY82C693 NULL -#define INIT_CY82C693 NULL +#define INIT_CY82C693 NULL #endif #ifdef CONFIG_BLK_DEV_PDC202XX extern unsigned int pci_init_pdc202xx(struct pci_dev *, const char *); +extern unsigned int ata66_pdc202xx(ide_hwif_t *); extern void ide_init_pdc202xx(ide_hwif_t *); #define PCI_PDC202XX &pci_init_pdc202xx -#define INIT_PDC202XX &ide_init_pdc202xx +#define ATA66_PDC202XX &ata66_pdc202xx +#define INIT_PDC202XX &ide_init_pdc202xx #else #define PCI_PDC202XX NULL -#define INIT_PDC202XX NULL +#define ATA66_PDC202XX NULL +#define INIT_PDC202XX NULL #endif #ifdef CONFIG_BLK_DEV_PIIX extern void ide_init_piix(ide_hwif_t *); -#define INIT_PIIX &ide_init_piix +#define INIT_PIIX &ide_init_piix #else -#define INIT_PIIX NULL +#define INIT_PIIX NULL #endif #ifdef CONFIG_BLK_DEV_AEC6210 @@ -167,29 +180,40 @@ extern unsigned int pci_init_aec6210(struct pci_dev *, const char *); extern unsigned int pci_init_hpt34x(struct pci_dev *, const char *); extern void ide_init_hpt34x(ide_hwif_t *); #define PCI_HPT34X &pci_init_hpt34x -#define INIT_HPT34X &ide_init_hpt34x +#define INIT_HPT34X &ide_init_hpt34x #else #define PCI_HPT34X NULL -#define INIT_HPT34X NULL +#define INIT_HPT34X NULL #endif #ifdef CONFIG_BLK_DEV_HPT366 +extern byte hpt363_shared_irq; extern unsigned int pci_init_hpt366(struct pci_dev *, const char *); +extern unsigned int ata66_hpt366(ide_hwif_t *); extern void ide_init_hpt366(ide_hwif_t *); +extern void ide_dmacapable_hpt366(ide_hwif_t *, unsigned long); #define PCI_HPT366 &pci_init_hpt366 +#define ATA66_HPT366 &ata66_hpt366 #define INIT_HPT366 &ide_init_hpt366 +#define DMA_HPT366 &ide_dmacapable_hpt366 #else +static byte hpt363_shared_irq = 0; #define PCI_HPT366 NULL -#define INIT_HPT366 IDE_IGNORE +#define ATA66_HPT366 NULL +#define INIT_HPT366 NULL +#define DMA_HPT366 NULL #endif #ifdef CONFIG_BLK_DEV_SIS5513 extern unsigned int pci_init_sis5513(struct pci_dev *, const char *); +extern unsigned int ata66_sis5513(ide_hwif_t *); extern void ide_init_sis5513(ide_hwif_t *); #define PCI_SIS5513 &pci_init_sis5513 +#define ATA66_SIS5513 &ata66_sis5513 #define INIT_SIS5513 &ide_init_sis5513 #else #define PCI_SIS5513 NULL +#define ATA66_SIS5513 NULL #define INIT_SIS5513 NULL #endif @@ -206,49 +230,48 @@ typedef struct ide_pci_device_s { ide_pci_devid_t devid; const char *name; unsigned int (*init_chipset)(struct pci_dev *dev, const char *name); + unsigned int (*ata66_check)(ide_hwif_t *hwif); void (*init_hwif)(ide_hwif_t *hwif); void (*dma_init)(ide_hwif_t *hwif, unsigned long dmabase); ide_pci_enablebit_t enablebits[2]; byte bootable; - byte sixtysix; unsigned int extra; } ide_pci_device_t; static ide_pci_device_t ide_pci_chipsets[] __initdata = { - {DEVID_PIIXa, "PIIX", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, - {DEVID_PIIXb, "PIIX", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, - {DEVID_PIIX3, "PIIX3", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, - {DEVID_PIIX4, "PIIX4", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, - {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_VP_IDE, "VP_IDE", PCI_VIA82C586, INIT_VIA82C586, DMA_VIA82C586, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0, 0 }, - {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 0, 16 }, - {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 1, 48 }, - {DEVID_RZ1000, "RZ1000", NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_RZ1001, "RZ1001", NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_SAMURAI, "SAMURAI", NULL, INIT_SAMURAI, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_CMD640, "CMD640", NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_NS87410, "NS87410", NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0, 0 }, - {DEVID_SIS5513, "SIS5513", PCI_SIS5513, INIT_SIS5513, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 1, 0 }, - {DEVID_CMD643, "CMD643", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_CMD646, "CMD646", NULL, INIT_CMD646, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0, 0 }, - {DEVID_HT6565, "HT6565", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_OPTI621, "OPTI621", NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_OPTI621X,"OPTI621X", NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_TRM290, "TRM290", NULL, INIT_TRM290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_NS87415, "NS87415", NULL, INIT_NS87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_AEC6210, "AEC6210", PCI_AEC6210, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, 0 }, - {DEVID_W82C105, "W82C105", NULL, INIT_W82C105, NULL, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0, 0 }, - {DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_HPT34X, "HPT34X", PCI_HPT34X, INIT_HPT34X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0, 16 }, - {DEVID_HPT366, "HPT366", PCI_HPT366, INIT_HPT366, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 1, 256 }, - {DEVID_ALI15X3, "ALI15X3", PCI_ALI15X3, INIT_ALI15X3, NULL, {{0x09,0x20,0x20}, {0x09,0x10,0x10}}, ON_BOARD, 0, 0 }, - {DEVID_CY82C693,"CY82C693", PCI_CY82C693, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_CX5530, "CX5530", NULL, INIT_CX5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }}; - -static byte hpt363_shared_irq = 0; + {DEVID_PIIXa, "PIIX", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIXb, "PIIX", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX3, "PIIX3", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4, "PIIX4", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_VP_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, + {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 }, + {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, + {DEVID_RZ1000, "RZ1000", NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_RZ1001, "RZ1001", NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_SAMURAI, "SAMURAI", NULL, NULL, INIT_SAMURAI, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CMD640, "CMD640", NULL, NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_NS87410, "NS87410", NULL, NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0 }, + {DEVID_SIS5513, "SIS5513", PCI_SIS5513, ATA66_SIS5513, INIT_SIS5513, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 0 }, + {DEVID_CMD643, "CMD643", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CMD646, "CMD646", NULL, NULL, INIT_CMD646, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_HT6565, "HT6565", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_OPTI621, "OPTI621", NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, + {DEVID_OPTI621X,"OPTI621X", NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, + {DEVID_TRM290, "TRM290", NULL, NULL, INIT_TRM290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_NS87415, "NS87415", NULL, NULL, INIT_NS87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_AEC6210, "AEC6210", PCI_AEC6210, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_W82C105, "W82C105", NULL, NULL, INIT_W82C105, NULL, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 }, + {DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_HPT34X, "HPT34X", PCI_HPT34X, NULL, INIT_HPT34X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 }, + {DEVID_HPT366, "HPT366", PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 256 }, + {DEVID_ALI15X3, "ALI15X3", PCI_ALI15X3, ATA66_ALI15X3, INIT_ALI15X3, DMA_ALI15X3, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CY82C693,"CY82C693", PCI_CY82C693, NULL, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CX5530, "CX5530", NULL, NULL, INIT_CX5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_AMD7409, "AMD7409", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }}; /* * This allows offboard ide-pci cards the enable a BIOS, verify interrupt @@ -260,24 +283,24 @@ static unsigned int __init ide_special_settings (struct pci_dev *dev, const char switch(dev->device) { case PCI_DEVICE_ID_TTI_HPT343: { + int i; + unsigned long hpt34xIoBase = dev->resource[4].start; unsigned short pcicmd = 0; pci_write_config_byte(dev, 0x80, 0x00); pci_read_config_word(dev, PCI_COMMAND, &pcicmd); if (!(pcicmd & PCI_COMMAND_MEMORY)) { - int i; - unsigned long hpt34xIoBase = dev->resource[4].start; - - dev->resource[0].start = (hpt34xIoBase + 0x20); - dev->resource[1].start = (hpt34xIoBase + 0x34); - dev->resource[2].start = (hpt34xIoBase + 0x28); - dev->resource[3].start = (hpt34xIoBase + 0x3c); - for(i=0; i<4; i++) - dev->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); } else { pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0); } + + dev->resource[0].start = (hpt34xIoBase + 0x20); + dev->resource[1].start = (hpt34xIoBase + 0x34); + dev->resource[2].start = (hpt34xIoBase + 0x28); + dev->resource[3].start = (hpt34xIoBase + 0x3c); + for(i=0; i<4; i++) + dev->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; } case PCI_DEVICE_ID_TTI_HPT366: case PCI_DEVICE_ID_PROMISE_20246: @@ -530,8 +553,7 @@ check_if_enabled: hwif->irq = hwif->channel ? 15 : 14; goto bypass_umc_dma; } - if ((!d->sixtysix) && (hwif->udma_four)) - hwif->udma_four = 0; + hwif->udma_four = (d->ata66_check) ? d->ata66_check(hwif) : 0; #ifdef CONFIG_BLK_DEV_IDEDMA if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513) || IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X)) @@ -582,40 +604,35 @@ bypass_umc_dma: static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d) { - struct pci_dev *dev2; + struct pci_dev *dev2 = NULL, *findev; ide_pci_device_t *d2; unsigned char pin1 = 0, pin2 = 0; - d2 = d; if (PCI_FUNC(dev->devfn) & 1) return; - - for (dev2=pci_devices; dev2; dev2=dev2->next) { - if ((dev2->vendor == dev->vendor) && - (dev2->device == dev->device) && - (PCI_FUNC(dev2->devfn) & 1)) - break; - } pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); - if (dev2) { - pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); - hpt363_shared_irq = (pin1 != pin2) ? 1 : 0; - } - - if (hpt363_shared_irq) { - printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", - d->name, pin1, pin2); + for (findev=pci_devices; findev; findev=findev->next) { + if ((findev->vendor == dev->vendor) && + (findev->device == dev->device) && + ((findev->devfn - dev->devfn) == 1) && + (PCI_FUNC(findev->devfn) & 1)) { + dev2 = findev; + pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); + hpt363_shared_irq = (pin1 != pin2) ? 1 : 0; + if (hpt363_shared_irq) { + d->bootable = ON_BOARD; + printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", d->name, pin1, pin2); + } + break; + } } - - printk("%s: IDE controller on PCI bus %02x dev %02x\n", - d->name, dev->bus->number, dev->devfn); + printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); ide_setup_pci_device(dev, d); - - if (dev2 && !hpt363_shared_irq) { - printk("%s: IDE controller on PCI bus %02x dev %02x\n", - d2->name, dev2->bus->number, dev2->devfn); - ide_setup_pci_device(dev2, d2); - } + if (!dev2) + return; + d2 = d; + printk("%s: IDE controller on PCI bus %02x dev %02x\n", d2->name, dev2->bus->number, dev2->devfn); + ide_setup_pci_device(dev2, d2); } /* diff --git a/drivers/block/ide-pmac.c b/drivers/block/ide-pmac.c index 1ad5b3b969ac..c3e800249b02 100644 --- a/drivers/block/ide-pmac.c +++ b/drivers/block/ide-pmac.c @@ -363,7 +363,8 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive) drive->waiting_for_dma = 1; if (drive->media != ide_disk) return 0; - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD); + drive->timeout = WAIT_CMD; + ide_set_handler(drive, &ide_dma_intr); OUT_BYTE(func==ide_dma_write? WIN_WRITEDMA: WIN_READDMA, IDE_COMMAND_REG); case ide_dma_begin: diff --git a/drivers/block/ide-probe.c b/drivers/block/ide-probe.c index 62008341eff1..d430c5b1d97a 100644 --- a/drivers/block/ide-probe.c +++ b/drivers/block/ide-probe.c @@ -42,7 +42,6 @@ #include #include - #include #include #include @@ -85,6 +84,9 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) ide_fixstring (id->fw_rev, sizeof(id->fw_rev), bswap); ide_fixstring (id->serial_no, sizeof(id->serial_no), bswap); + if (strstr(id->model, "E X A B Y T E N E S T")) + return; + id->model[sizeof(id->model)-1] = '\0'; /* we depend on this a lot! */ printk("%s: %s, ", drive->name, id->model); drive->present = 1; @@ -323,6 +325,35 @@ static int do_probe (ide_drive_t *drive, byte cmd) return rc; } +/* + * + */ +static void enable_nest (ide_drive_t *drive) +{ + unsigned long timeout; + + printk("%s: enabling %s -- ", HWIF(drive)->name, drive->id->model); + SELECT_DRIVE(HWIF(drive), drive); + ide_delay_50ms(); + OUT_BYTE(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG); + timeout = jiffies + WAIT_WORSTCASE; + do { + if (jiffies > timeout) { + printk("failed (timeout)\n"); + return; + } + ide_delay_50ms(); + } while (GET_STAT() & BUSY_STAT); + ide_delay_50ms(); + if (!OK_STAT(GET_STAT(), 0, BAD_STAT)) + printk("failed (status = 0x%02x)\n", GET_STAT()); + else + printk("success\n"); + if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */ + (void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */ + } +} + /* * probe_for_drive() tests for existence of a given drive using do_probe(). * @@ -336,6 +367,8 @@ static inline byte probe_for_drive (ide_drive_t *drive) if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */ (void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */ } + if (drive->id && strstr(drive->id->model, "E X A B Y T E N E S T")) + enable_nest(drive); if (!drive->present) return 0; /* drive not found */ if (drive->id == NULL) { /* identification failed? */ diff --git a/drivers/block/ide-proc.c b/drivers/block/ide-proc.c index 8afe1568f3e0..48d77c1607f8 100644 --- a/drivers/block/ide-proc.c +++ b/drivers/block/ide-proc.c @@ -73,14 +73,21 @@ #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #endif -#ifdef CONFIG_BLK_DEV_VIA82C586 -int (*via_display_info)(char *, char **, off_t, int, int) = NULL; -#endif /* CONFIG_BLK_DEV_VIA82C586 */ - #ifdef CONFIG_BLK_DEV_ALI15X3 +extern byte ali_proc; int (*ali_display_info)(char *, char **, off_t, int, int) = NULL; #endif /* CONFIG_BLK_DEV_ALI15X3 */ +#ifdef CONFIG_BLK_DEV_SIS5513 +extern byte sis_proc; +int (*sis_display_info)(char *, char **, off_t, int, int) = NULL; +#endif /* CONFIG_BLK_DEV_SIS5513 */ + +#ifdef CONFIG_BLK_DEV_VIA82CXXX +extern byte via_proc; +int (*via_display_info)(char *, char **, off_t, int, int) = NULL; +#endif /* CONFIG_BLK_DEV_VIA82CXXX */ + static int ide_getxdigit(char c) { int digit; @@ -243,7 +250,27 @@ static int proc_ide_write_config } #endif /* CONFIG_BLK_DEV_IDEPCI */ } else { /* not pci */ -#ifndef CONFIG_Q40 +#if !defined(__mc68000__) && !defined(CONFIG_APUS) + +/* + * Geert Uytterhoeven + * + * unless you can explain me what it really does. + * On m68k, we don't have outw() and outl() yet, + * and I need a good reason to implement it. + * + * BTW, IMHO the main remaining portability problem with the IDE driver + * is that it mixes IO (ioport) and MMIO (iomem) access on different platforms. + * + * I think all accesses should be done using + * + * ide_in[bwl](ide_device_instance, offset) + * ide_out[bwl](ide_device_instance, value, offset) + * + * so the architecture specific code can #define ide_{in,out}[bwl] to the + * appropriate function. + * + */ switch (digits) { case 2: outb(val, reg); break; @@ -252,7 +279,7 @@ static int proc_ide_write_config case 8: outl(val, reg); break; } -#endif /* CONFIG_Q40 */ +#endif /* !__mc68000__ && !CONFIG_APUS */ } } } @@ -750,18 +777,24 @@ void proc_ide_create(void) ent = create_proc_entry("drivers", 0, proc_ide_root); if (!ent) return; ent->read_proc = proc_ide_read_drivers; -#ifdef CONFIG_BLK_DEV_VIA82C586 - if (via_display_info) { - ent = create_proc_entry("via", 0, proc_ide_root); - ent->get_info = via_display_info; - } -#endif /* CONFIG_BLK_DEV_VIA82C586 */ #ifdef CONFIG_BLK_DEV_ALI15X3 - if (ali_display_info) { + if ((ali_display_info) && (ali_proc)) { ent = create_proc_entry("ali", 0, proc_ide_root); ent->get_info = ali_display_info; } #endif /* CONFIG_BLK_DEV_ALI15X3 */ +#ifdef CONFIG_BLK_DEV_SIS5513 + if ((sis_display_info) && (sis_proc)) { + ent = create_proc_entry("sis", 0, proc_ide_root); + ent->get_info = sis_display_info; + } +#endif /* CONFIG_BLK_DEV_SIS5513 */ +#ifdef CONFIG_BLK_DEV_VIA82CXXX + if ((via_display_info) && (via_proc)) { + ent = create_proc_entry("via", 0, proc_ide_root); + ent->get_info = via_display_info; + } +#endif /* CONFIG_BLK_DEV_VIA82CXXX */ } void proc_ide_destroy(void) @@ -770,14 +803,18 @@ void proc_ide_destroy(void) * Mmmm.. does this free up all resources, * or do we need to do a more proper cleanup here ?? */ -#ifdef CONFIG_BLK_DEV_VIA82C586 - if (via_display_info) - remove_proc_entry("ide/via",0); -#endif /* CONFIG_BLK_DEV_VIA82C586 */ #ifdef CONFIG_BLK_DEV_ALI15X3 - if (ali_display_info) + if ((ali_display_info) && (ali_proc)) remove_proc_entry("ide/ali",0); #endif /* CONFIG_BLK_DEV_ALI15X3 */ +#ifdef CONFIG_BLK_DEV_SIS5513 + if ((sis_display_info) && (sis_proc)) + remove_proc_entry("ide/sis", 0); +#endif /* CONFIG_BLK_DEV_SIS5513 */ +#ifdef CONFIG_BLK_DEV_VIA82CXXX + if ((via_display_info) && (via_proc)) + remove_proc_entry("ide/via",0); +#endif /* CONFIG_BLK_DEV_VIA82CXXX */ remove_proc_entry("ide/drivers", 0); destroy_proc_ide_interfaces(); remove_proc_entry("ide", 0); diff --git a/drivers/block/ide-tape.c b/drivers/block/ide-tape.c index 6e8313733b36..bbf222338bd6 100644 --- a/drivers/block/ide-tape.c +++ b/drivers/block/ide-tape.c @@ -1833,7 +1833,7 @@ static void idetape_pc_intr (ide_drive_t *drive) if (temp > pc->buffer_size) { printk (KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n"); idetape_discard_data (drive,bcount.all); - ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD); + ide_set_handler (drive,&idetape_pc_intr); return; } #if IDETAPE_DEBUG_LOG @@ -1855,7 +1855,7 @@ static void idetape_pc_intr (ide_drive_t *drive) pc->actually_transferred+=bcount.all; /* Update the current position */ pc->current_position+=bcount.all; - ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD); /* And set the interrupt handler again */ + ide_set_handler (drive,&idetape_pc_intr); /* And set the interrupt handler again */ } /* @@ -1928,7 +1928,7 @@ static void idetape_transfer_pc(ide_drive_t *drive) ide_do_reset (drive); return; } - ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD); /* Set the interrupt routine */ + ide_set_handler(drive, &idetape_pc_intr); /* Set the interrupt routine */ atapi_output_bytes (drive,pc->c,12); /* Send the actual packet */ } @@ -1995,7 +1995,7 @@ static void idetape_issue_packet_command (ide_drive_t *drive, idetape_pc_t *pc) } #endif /* CONFIG_BLK_DEV_IDEDMA */ if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { - ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD); + ide_set_handler(drive, &idetape_transfer_pc); OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); } else { OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); @@ -3579,6 +3579,7 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor) spin_lock_init(&tape->spinlock); drive->driver_data = tape; drive->ready_stat = 0; /* An ATAPI device ignores DRDY */ + drive->timeout = IDETAPE_WAIT_CMD; #ifdef CONFIG_BLK_DEV_IDEPCI /* * These two ide-pci host adapters appear to need this disabled. diff --git a/drivers/block/ide.c b/drivers/block/ide.c index d2cb4b34b4e1..1a506e3536eb 100644 --- a/drivers/block/ide.c +++ b/drivers/block/ide.c @@ -149,9 +149,9 @@ #include #endif /* CONFIG_KMOD */ -#ifdef CONFIG_BLK_DEV_VIA82C586 -extern byte fifoconfig; /* defined in via82c586.c used by ide_setup()*/ -#endif +#ifdef CONFIG_BLK_DEV_VIA82CXXX +extern byte fifoconfig; /* defined in via82cxxx.c used by ide_setup() */ +#endif /* CONFIG_BLK_DEV_VIA82CXXX */ static const byte ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, @@ -504,7 +504,7 @@ void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup) * timer is started to prevent us from waiting forever in case * something goes wrong (see the ide_timer_expiry() handler later on). */ -void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout) +void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler) { unsigned long flags; ide_hwgroup_t *hwgroup = HWGROUP(drive); @@ -517,7 +517,7 @@ void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int t } #endif hwgroup->handler = handler; - hwgroup->timer.expires = jiffies + timeout; + hwgroup->timer.expires = jiffies + drive->timeout; add_timer(&(hwgroup->timer)); spin_unlock_irqrestore(&hwgroup->spinlock, flags); } @@ -565,6 +565,7 @@ static void do_reset1 (ide_drive_t *, int); /* needed below */ static void atapi_reset_pollfunc (ide_drive_t *drive) { ide_hwgroup_t *hwgroup = HWGROUP(drive); + unsigned long old_timeout; byte stat; SELECT_DRIVE(HWIF(drive),drive); @@ -574,7 +575,10 @@ static void atapi_reset_pollfunc (ide_drive_t *drive) printk("%s: ATAPI reset complete\n", drive->name); } else { if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) { - ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20); + old_timeout = drive->timeout; + drive->timeout = HZ / 20; + ide_set_handler (drive, &atapi_reset_pollfunc); + drive->timeout = old_timeout; return; /* continue polling */ } hwgroup->poll_timeout = 0; /* end of polling */ @@ -595,11 +599,15 @@ static void reset_pollfunc (ide_drive_t *drive) { ide_hwgroup_t *hwgroup = HWGROUP(drive); ide_hwif_t *hwif = HWIF(drive); + unsigned long old_timeout; byte tmp; if (!OK_STAT(tmp=GET_STAT(), 0, BUSY_STAT)) { if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) { - ide_set_handler (drive, &reset_pollfunc, HZ/20); + old_timeout = drive->timeout; + drive->timeout = HZ / 20; + ide_set_handler (drive, &reset_pollfunc); + drive->timeout = old_timeout; return; /* continue polling */ } printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp); @@ -667,6 +675,7 @@ static void do_reset1 (ide_drive_t *drive, int do_not_try_atapi) unsigned long flags; ide_hwif_t *hwif = HWIF(drive); ide_hwgroup_t *hwgroup = HWGROUP(drive); + unsigned long old_timeout; __save_flags(flags); /* local CPU only */ __cli(); /* local CPU only */ @@ -678,7 +687,10 @@ static void do_reset1 (ide_drive_t *drive, int do_not_try_atapi) udelay (20); OUT_BYTE (WIN_SRST, IDE_COMMAND_REG); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20); + old_timeout = drive->timeout; + drive->timeout = HZ / 20; + ide_set_handler (drive, &atapi_reset_pollfunc); + drive->timeout = old_timeout; __restore_flags (flags); /* local CPU only */ return; } @@ -708,7 +720,19 @@ static void do_reset1 (ide_drive_t *drive, int do_not_try_atapi) OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* clear SRST, leave nIEN */ udelay(10); /* more than enough time */ hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler (drive, &reset_pollfunc, HZ/20); + old_timeout = drive->timeout; + drive->timeout = HZ / 20; + ide_set_handler (drive, &reset_pollfunc); + drive->timeout = old_timeout; + + /* + * Some weird controller like resetting themselves to a strange + * state when the disks are reset this way. At least, the Winbond + * 553 documentation says that + */ + if (hwif->resetproc != NULL) + hwif->resetproc(drive); + #endif /* OK_TO_RESET_CONTROLLER */ __restore_flags (flags); /* local CPU only */ @@ -899,7 +923,7 @@ void ide_error (ide_drive_t *drive, const char *msg, byte stat) */ void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler) { - ide_set_handler (drive, handler, WAIT_CMD); + ide_set_handler (drive, handler); if (IDE_CONTROL_REG) OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */ OUT_BYTE(nsect,IDE_NSECTOR_REG); @@ -1018,6 +1042,10 @@ static void execute_drive_cmd (ide_drive_t *drive, struct request *rq) if (args[0] == WIN_SMART) { OUT_BYTE(0x4f, IDE_LCYL_REG); OUT_BYTE(0xc2, IDE_HCYL_REG); + OUT_BYTE(args[2],IDE_FEATURE_REG); + OUT_BYTE(args[1],IDE_SECTOR_REG); + ide_cmd(drive, args[0], args[3], &drive_cmd_intr); + return; } OUT_BYTE(args[2],IDE_FEATURE_REG); ide_cmd(drive, args[0], args[1], &drive_cmd_intr); @@ -1218,13 +1246,37 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, unsigned long *hwgroup_flags bdev->current_request = hwgroup->rq = drive->queue; spin_unlock_irqrestore(&io_request_lock, io_flags); +#if 0 if (hwif->irq != masked_irq) - disable_irq(hwif->irq); + disable_irq_nosync(hwif->irq); spin_unlock_irqrestore(&hwgroup->spinlock, *hwgroup_flags); start_request(drive); spin_lock_irqsave(&hwgroup->spinlock, *hwgroup_flags); if (hwif->irq != masked_irq) enable_irq(hwif->irq); +#else + + if (masked_irq && hwif->irq != masked_irq) { + printk("%s: (disable_irq) %smasked_irq %d\n", + drive->name, + masked_irq ? "" : "un_", hwif->irq); + +#if 0 + disable_irq(hwif->irq); +#else + disable_irq_nosync(hwif->irq); +#endif + } + spin_unlock_irqrestore(&hwgroup->spinlock, *hwgroup_flags); + start_request(drive); + spin_lock_irqsave(&hwgroup->spinlock, *hwgroup_flags); + if (masked_irq && hwif->irq != masked_irq) { + printk("%s: (enable_irq) %smasked_irq %d\n", + drive->name, + masked_irq ? "" : "un_", hwif->irq); + enable_irq(hwif->irq); + } +#endif } } @@ -1373,8 +1425,8 @@ void ide_timer_expiry (unsigned long data) } hwgroup->busy = 1; /* should already be "1" */ hwgroup->handler = NULL; - del_timer(&hwgroup->timer); /* Is this needed?? */ - if (hwgroup->poll_timeout != 0) { /* polling in progress? */ + /* polling in progress or just don't timeout */ + if (hwgroup->poll_timeout != 0) { spin_unlock_irqrestore(&hwgroup->spinlock, flags); handler(drive); } else if (drive_is_ready(drive)) { @@ -1612,8 +1664,10 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio } spin_unlock_irqrestore(&io_request_lock, flags); do_hwgroup_request(hwgroup); - if (action == ide_wait && rq->rq_status != RQ_INACTIVE) + if (action == ide_wait) { down(&sem); /* wait for it to be serviced */ + rq->sem = NULL; + } return rq->errors ? -EIO : 0; /* return -EIO if errors */ } @@ -2270,8 +2324,13 @@ void ide_delay_50ms (void) int ide_config_drive_speed (ide_drive_t *drive, byte speed) { + struct hd_driveid *id = drive->id; + unsigned long flags; int err; + __save_flags(flags); /* local CPU only */ + __cli(); /* local CPU only */ + /* * Don't use ide_wait_cmd here - it will * attempt to set_geometry and recalibrate, @@ -2287,6 +2346,109 @@ int ide_config_drive_speed (ide_drive_t *drive, byte speed) err = ide_wait_stat(drive, DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT, WAIT_CMD); +#if 0 + if (IDE_CONTROL_REG) + OUT_BYTE(drive->ctl, IDE_CONTROL_REG); +#endif + + __restore_flags(flags); /* local CPU only */ + + switch(speed) { + case XFER_UDMA_4: + if (!((id->dma_ultra >> 8) & 16)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x1010; + } + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + break; + case XFER_UDMA_3: + if (!((id->dma_ultra >> 8) & 8)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0808; + } + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + break; + case XFER_UDMA_2: + if (!((id->dma_ultra >> 8) & 4)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0404; + } + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + break; + case XFER_UDMA_1: + if (!((id->dma_ultra >> 8) & 2)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0202; + } + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + break; + case XFER_UDMA_0: + if (!((id->dma_ultra >> 8) & 1)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0101; + } + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + break; + case XFER_MW_DMA_2: + drive->id->dma_ultra &= ~0xFF00; + if (!((id->dma_mword >> 8) & 4)) { + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_mword |= 0x0404; + } + drive->id->dma_1word &= ~0x0F00; + break; + case XFER_MW_DMA_1: + drive->id->dma_ultra &= ~0xFF00; + if (!((id->dma_mword >> 8) & 2)) { + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_mword |= 0x0202; + } + drive->id->dma_1word &= ~0x0F00; + break; + case XFER_MW_DMA_0: + drive->id->dma_ultra &= ~0xFF00; + if (!((id->dma_mword >> 8) & 1)) { + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_mword |= 0x0101; + } + drive->id->dma_1word &= ~0x0F00; + break; + case XFER_SW_DMA_2: + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_mword &= ~0x0F00; + if (!((id->dma_1word >> 8) & 4)) { + drive->id->dma_1word &= ~0x0F00; + drive->id->dma_1word |= 0x0404; + } + break; + case XFER_SW_DMA_1: + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_mword &= ~0x0F00; + if (!((id->dma_1word >> 8) & 2)) { + drive->id->dma_1word &= ~0x0F00; + drive->id->dma_1word |= 0x0202; + } + break; + case XFER_SW_DMA_0: + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_mword &= ~0x0F00; + if (!((id->dma_1word >> 8) & 1)) { + drive->id->dma_1word &= ~0x0F00; + drive->id->dma_1word |= 0x0101; + } + break; + default: + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + break; + } + return(err); } @@ -2803,7 +2965,7 @@ void __init ide_setup (char *s) } } -#if defined(CONFIG_BLK_DEV_VIA82C586) +#if defined(CONFIG_BLK_DEV_VIA82CXXX) /* * Look for drive option "splitfifo=..." */ @@ -2853,7 +3015,7 @@ void __init ide_setup (char *s) fifoconfig = tmp; goto done; } -#endif /* defined(CONFIG_BLK_DEV_VIA82C586) */ +#endif /* defined(CONFIG_BLK_DEV_VIA82CXXX) */ if (s[0] != 'i' || s[1] != 'd' || s[2] != 'e') goto bad_option; @@ -3393,6 +3555,7 @@ EXPORT_SYMBOL(do_ide9_request); EXPORT_SYMBOL(ide_scan_devices); EXPORT_SYMBOL(ide_register_subdriver); EXPORT_SYMBOL(ide_unregister_subdriver); +EXPORT_SYMBOL(ide_replace_subdriver); EXPORT_SYMBOL(ide_input_data); EXPORT_SYMBOL(ide_output_data); EXPORT_SYMBOL(atapi_input_bytes); @@ -3464,7 +3627,11 @@ static void __init parse_options (char *line) while ((line = next) != NULL) { if ((next = strchr(line,' ')) != NULL) *next++ = 0; - if (!strncmp(line,"ide",3) || (!strncmp(line,"hd",2) && line[2] != '=')) + if (!strncmp(line,"ide",3) || +#ifdef CONFIG_BLK_DEV_VIA82CXXX + !strncmp(line,"splitfifo",9) || +#endif /* CONFIG_BLK_DEV_VIA82CXXX */ + (!strncmp(line,"hd",2) && line[2] != '=')) ide_setup(line); } } diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index 0275173205cc..96e0e421e82c 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c @@ -214,8 +214,11 @@ static int pcd_drive_reset(struct cdrom_device_info *cdi); static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn); static int pcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg); +static int pcd_packet(struct cdrom_device_info *cdi, + struct cdrom_generic_command *cgc); static int pcd_detect(void); +static void pcd_probe_capabilities(void); static void do_pcd_read_drq(void); static void do_pcd_request(void); static void do_pcd_read(void); @@ -276,14 +279,18 @@ static struct cdrom_device_ops pcd_dops = { pcd_drive_reset, pcd_audio_ioctl, 0, /* dev_ioctl */ - CDC_CLOSE_TRAY | - CDC_OPEN_TRAY | - CDC_LOCK | - CDC_MCN | - CDC_MEDIA_CHANGED | - CDC_RESET | - CDC_PLAY_AUDIO, - 0 + CDC_CLOSE_TRAY | + CDC_OPEN_TRAY | + CDC_LOCK | + CDC_MCN | + CDC_MEDIA_CHANGED | + CDC_RESET | + CDC_PLAY_AUDIO | + CDC_GENERIC_PACKET | + CDC_CD_R | + CDC_CD_RW, + 0, + pcd_packet, }; static void pcd_init_units( void ) @@ -325,6 +332,9 @@ int pcd_init (void) /* preliminary initialisation */ if (pcd_detect()) return -1; + /* get the atapi capabilities page */ + pcd_probe_capabilities(); + if (register_blkdev(MAJOR_NR,name,&cdrom_fops)) { printk("pcd: unable to get major number %d\n",MAJOR_NR); return -1; @@ -525,6 +535,16 @@ static int pcd_atapi( int unit, char * cmd, int dlen, char * buf, char * fun ) return r; } +static int pcd_packet(struct cdrom_device_info *cdi, + struct cdrom_generic_command *cgc) +{ + char *un_cmd; + int unit = DEVICE_NR(cdi->dev); + + un_cmd = cgc->cmd; + return pcd_atapi(unit,un_cmd,cgc->buflen,cgc->buffer, "generic packet"); +} + #define DBMSG(msg) ((verbose>1)?(msg):NULL) static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr) @@ -667,6 +687,32 @@ static int pcd_probe( int unit, int ms, char * id ) return -1; } +static void pcd_probe_capabilities( void ) + +{ int unit, r; + char buffer[32]; + char cmd[12]={0x5a,1<<3,0x2a,0,0,0,0,18,0,0,0,0}; + + for (unit=0;unit> 6) == 0) + PCD.info.mask |= CDC_CLOSE_TRAY; + } +} + static int pcd_detect( void ) { char id[18]; @@ -836,63 +882,6 @@ static int pcd_audio_ioctl(struct cdrom_device_info *cdi, switch (cmd) { - case CDROMPAUSE: - - { char cmd[12]={GPCMD_PAUSE_RESUME,0,0,0,0,0,0,0,0,0,0,0}; - - return (pcd_atapi(unit,cmd,0,NULL,"pause")) * EIO; - } - - case CDROMRESUME: - - { char cmd[12]={GPCMD_PAUSE_RESUME,0,0,0,0,0,0,0,1,0,0,0}; - - return (pcd_atapi(unit,cmd,0,NULL,"resume")) * EIO; - } - - case CDROMPLAYMSF: - - { char cmd[12]={GPCMD_PLAY_AUDIO_MSF,0,0,0,0,0,0,0,0,0,0,0}; - struct cdrom_msf* msf = (struct cdrom_msf*)arg; - - cmd[3] = msf->cdmsf_min0; - cmd[4] = msf->cdmsf_sec0; - cmd[5] = msf->cdmsf_frame0; - cmd[6] = msf->cdmsf_min1; - cmd[7] = msf->cdmsf_sec1; - cmd[8] = msf->cdmsf_frame1; - - return (pcd_atapi(unit,cmd,0,NULL,"play msf")) * EIO; - } - - case CDROMPLAYBLK: - - { char cmd[12]={GPCMD_PLAY_AUDIO_10,0,0,0,0,0,0,0,0,0,0,0}; - struct cdrom_blk* blk = (struct cdrom_blk*)arg; - - cmd[2] = blk->from >> 24; - cmd[3] = blk->from >> 16; - cmd[4] = blk->from >> 8; - cmd[5] = blk->from; - cmd[7] = blk->len >> 8; - cmd[8] = blk->len; - - return (pcd_atapi(unit,cmd,0,NULL,"play block")) * EIO; - } - - case CDROMPLAYTRKIND: - - { char cmd[12]={GPCMD_PLAYAUDIO_TI,0,0,0,0,0,0,0,0,0,0,0}; - struct cdrom_ti* ti = (struct cdrom_ti*)arg; - - cmd[4] = ti->cdti_trk0; - cmd[5] = ti->cdti_ind0; - cmd[7] = ti->cdti_trk1; - cmd[8] = ti->cdti_ind1; - - return (pcd_atapi(unit,cmd,0,NULL,"play track")) * EIO; - } - case CDROMREADTOCHDR: { char cmd[12]={GPCMD_READ_TOC_PMA_ATIP,0,0,0,0,0,0,0,12,0,0,0}; @@ -936,97 +925,6 @@ static int pcd_audio_ioctl(struct cdrom_device_info *cdi, return r * EIO; } - case CDROMSTOP: - - { char cmd[12]={GPCMD_START_STOP_UNIT,1,0,0,0,0,0,0,0,0,0,0}; - - return (pcd_atapi(unit,cmd,0,NULL,"stop")) * EIO; - } - - case CDROMSTART: - - { char cmd[12]={GPCMD_START_STOP_UNIT,1,0,0,1,0,0,0,0,0,0,0}; - - return (pcd_atapi(unit,cmd,0,NULL,"start")) * EIO; - } - - case CDROMVOLCTRL: - - { char cmd[12]={GPCMD_MODE_SENSE_10,0,0,0,0,0,0,0,0,0,0,0}; - char buffer[32]; - char mask[32]; - struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg; - - cmd[2] = 0xe; - cmd[4] = 28; - - if (pcd_atapi(unit,cmd,28,buffer,"mode sense vol")) - return -EIO; - - cmd[2] = 0x4e; - - if (pcd_atapi(unit,cmd,28,buffer,"mode sense vol mask")) - return -EIO; - - buffer[0] = 0; - - buffer[21] = volctrl->channel0 & mask[21]; - buffer[23] = volctrl->channel1 & mask[23]; - buffer[25] = volctrl->channel2 & mask[25]; - buffer[27] = volctrl->channel3 & mask[27]; - - cmd[0] = 0x55; - cmd[1] = 0x10; - - return pcd_atapi(unit,cmd,28,buffer,"mode select vol") * EIO; - } - - case CDROMVOLREAD: - - { char cmd[12]={GPCMD_MODE_SENSE_10,0,0,0,0,0,0,0,0,0,0,0}; - char buffer[32]; - struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg; - int r; - - cmd[2] = 0xe; - cmd[4] = 28; - - r = pcd_atapi(unit,cmd,28,buffer,"mode sense vol read"); - - volctrl->channel0 = buffer[21]; - volctrl->channel1 = buffer[23]; - volctrl->channel2 = buffer[25]; - volctrl->channel3 = buffer[27]; - - return r * EIO; - } - - - case CDROMSUBCHNL: - - { char cmd[12]={GPCMD_READ_SUBCHANNEL,2,0x40,1,0,0,0,0,16,0,0,0}; - struct cdrom_subchnl* subchnl = (struct cdrom_subchnl*)arg; - char buffer[32]; - - if (pcd_atapi(unit,cmd,16,buffer,"read subchannel")) - return -EIO; - - subchnl->cdsc_audiostatus = buffer[1]; - subchnl->cdsc_format = CDROM_MSF; - subchnl->cdsc_ctrl = buffer[5] & 0xf; - subchnl->cdsc_trk = buffer[6]; - subchnl->cdsc_ind = buffer[7]; - - subchnl->cdsc_reladdr.msf.minute = buffer[13]; - subchnl->cdsc_reladdr.msf.second = buffer[14]; - subchnl->cdsc_reladdr.msf.frame = buffer[15]; - subchnl->cdsc_absaddr.msf.minute = buffer[9]; - subchnl->cdsc_absaddr.msf.second = buffer[10]; - subchnl->cdsc_absaddr.msf.frame = buffer[11]; - - return 0; - } - default: return -ENOSYS; diff --git a/drivers/block/pdc202xx.c b/drivers/block/pdc202xx.c index aeffcc9ba939..2155aa8af6ef 100644 --- a/drivers/block/pdc202xx.c +++ b/drivers/block/pdc202xx.c @@ -1,8 +1,8 @@ /* - * linux/drivers/block/pdc202xx.c Version 0.26 May 12, 1999 + * linux/drivers/block/pdc202xx.c Version 0.27 Sept. 3, 1999 * - * Copyright (C) 1998-99 Andre Hedrick - * (hedrick@astro.dyer.vanderbilt.edu) + * Copyright (C) 1998-99 Andre Hedrick (andre@suse.com) + * May be copied or modified under the terms of the GNU General Public License * * Promise Ultra33 cards with BIOS v1.20 through 1.28 will need this * compiled into the kernel if you have more than one card installed. @@ -72,6 +72,12 @@ * = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); */ +/* + * Portions Copyright (C) 1999 Promise Technology, Inc. + * Author: Frank Tiernan (frankt@promise.com) + * Released under terms of General Public License + */ + #include #include #include @@ -88,6 +94,8 @@ #include #include +#include "ide_modes.h" + #define PDC202XX_DEBUG_DRIVE_INFO 0 #define PDC202XX_DECODE_REGISTER_INFO 0 @@ -208,27 +216,78 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; + unsigned long high_16 = dev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK; int err; unsigned int drive_conf; byte drive_pci; - byte test1, test2, speed; - byte AP, BP, CP, DP, EP; + byte test1, test2, speed = -1; + byte AP, BP, CP, DP, TB, TC; + unsigned short EP; + byte CLKSPD = IN_BYTE(high_16 + 0x11); int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); byte udma_66 = ((id->word93 & 0x2000) && (hwif->udma_four)) ? 1 : 0; - byte udma_33 = ultra ? (inb((dev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK) + 0x001f) & 1) : 0; - - pci_read_config_byte(dev, 0x50, &EP); + byte udma_33 = ultra ? (inb(high_16 + 0x001f) & 1) : 0; + + /* + * Set the control register to use the 66Mhz system + * clock for UDMA 3/4 mode operation. If one drive on + * a channel is U66 capable but the other isn't we + * fall back to U33 mode. The BIOS INT 13 hooks turn + * the clock on then off for each read/write issued. I don't + * do that here because it would require modifying the + * kernel, seperating the fop routines from the kernel or + * somehow hooking the fops calls. It may also be possible to + * leave the 66Mhz clock on and readjust the timing + * parameters. + */ + + byte mask = hwif->channel ? 0x08 : 0x02; + unsigned short c_mask = hwif->channel ? (1<<11) : (1<<10); + byte ultra_66 = ((id->dma_ultra & 0x0010) || (id->dma_ultra & 0x0008)) ? 1 : 0; + + pci_read_config_word(dev, 0x50, &EP); + + if ((ultra_66) && (EP & c_mask)) { +#ifdef DEBUG + printk("ULTRA66: %s channel of Ultra 66 requires an 80-pin cable for Ultra66 operation.\n", hwif->channel ? "Secondary", "Primary"); + printk(" Switching to Ultra33 mode.\n"); +#endif /* DEBUG */ + /* Primary : zero out second bit */ + /* Secondary : zero out fourth bit */ + OUT_BYTE(CLKSPD & ~mask, (high_16 + 0x11)); + } else { + if (ultra_66) { + /* + * check to make sure drive on same channel + * is u66 capable + */ + if (hwif->drives[!(drive_number%2)].id) { + if ((hwif->drives[!(drive_number%2)].id->dma_ultra & 0x0010) || + (hwif->drives[!(drive_number%2)].id->dma_ultra & 0x0008)) { + OUT_BYTE(CLKSPD | mask, (high_16 + 0x11)); + } else { + OUT_BYTE(CLKSPD & ~mask, (high_16 + 0x11)); + } + } else { /* udma4 drive by itself */ + OUT_BYTE(CLKSPD | mask, (high_16 + 0x11)); + } + } + } switch(drive_number) { case 0: drive_pci = 0x60; pci_read_config_dword(dev, drive_pci, &drive_conf); + if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) + goto chipset_is_set; pci_read_config_byte(dev, (drive_pci), &test1); if (!(test1 & SYNC_ERRDY_EN)) pci_write_config_byte(dev, (drive_pci), test1|SYNC_ERRDY_EN); break; case 1: drive_pci = 0x64; pci_read_config_dword(dev, drive_pci, &drive_conf); + if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) + goto chipset_is_set; pci_read_config_byte(dev, 0x60, &test1); pci_read_config_byte(dev, (drive_pci), &test2); if ((test1 & SYNC_ERRDY_EN) && !(test2 & SYNC_ERRDY_EN)) @@ -236,12 +295,16 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) break; case 2: drive_pci = 0x68; pci_read_config_dword(dev, drive_pci, &drive_conf); + if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) + goto chipset_is_set; pci_read_config_byte(dev, (drive_pci), &test1); if (!(test1 & SYNC_ERRDY_EN)) pci_write_config_byte(dev, (drive_pci), test1|SYNC_ERRDY_EN); break; case 3: drive_pci = 0x6c; pci_read_config_dword(dev, drive_pci, &drive_conf); + if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) + goto chipset_is_set; pci_read_config_byte(dev, 0x68, &test1); pci_read_config_byte(dev, (drive_pci), &test2); if ((test1 & SYNC_ERRDY_EN) && !(test2 & SYNC_ERRDY_EN)) @@ -251,6 +314,8 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) return ide_dma_off; } +chipset_is_set: + if (drive->media != ide_disk) return ide_dma_off_quietly; @@ -285,127 +350,46 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) pci_read_config_byte(dev, (drive_pci)|0x02, &CP); if ((id->dma_ultra & 0x0010) && (udma_66) && (udma_33)) { - if (!((id->dma_ultra >> 8) & 16)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x1010; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } /* speed 8 == UDMA mode 4 == speed 6 plus cable */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x20); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x01); - speed = XFER_UDMA_4; + speed = XFER_UDMA_4; TB = 0x20; TC = 0x01; } else if ((id->dma_ultra & 0x0008) && (udma_66) && (udma_33)) { - if (!((id->dma_ultra >> 8) & 8)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0808; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } /* speed 7 == UDMA mode 3 == speed 5 plus cable */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x40); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x02); - speed = XFER_UDMA_3; + speed = XFER_UDMA_3; TB = 0x40; TC = 0x02; } else if ((id->dma_ultra & 0x0004) && (udma_33)) { - if (!((id->dma_ultra >> 8) & 4)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0404; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } /* speed 6 == UDMA mode 2 */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x20); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x01); - speed = XFER_UDMA_2; + speed = XFER_UDMA_2; TB = 0x20; TC = 0x01; } else if ((id->dma_ultra & 0x0002) && (udma_33)) { - if (!((id->dma_ultra >> 8) & 2)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0202; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } /* speed 5 == UDMA mode 1 */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x40); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x02); - speed = XFER_UDMA_1; + speed = XFER_UDMA_1; TB = 0x40; TC = 0x02; } else if ((id->dma_ultra & 0x0001) && (udma_33)) { - if (!((id->dma_ultra >> 8) & 1)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0101; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } /* speed 4 == UDMA mode 0 */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x03); - speed = XFER_UDMA_0; + speed = XFER_UDMA_0; TB = 0x60; TC = 0x03; } else if (id->dma_mword & 0x0004) { - if (!((id->dma_mword >> 8) & 4)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0404; - drive->id->dma_1word &= ~0x0F00; - } /* speed 4 == DMA mode 2 multi-word */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x03); - speed = XFER_MW_DMA_2; + speed = XFER_MW_DMA_2; TB = 0x60; TC = 0x03; } else if (id->dma_mword & 0x0002) { - if (!((id->dma_mword >> 8) & 2)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0202; - drive->id->dma_1word &= ~0x0F00; - } /* speed 3 == DMA mode 1 multi-word */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x04); - speed = XFER_MW_DMA_1; + speed = XFER_MW_DMA_1; TB = 0x60; TC = 0x04; } else if (id->dma_mword & 0x0001) { - if (!((id->dma_mword >> 8) & 1)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0101; - drive->id->dma_1word &= ~0x0F00; - } /* speed 2 == DMA mode 0 multi-word */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x05); - speed = XFER_MW_DMA_0; + speed = XFER_MW_DMA_0; TB = 0x60; TC = 0x05; } else if (id->dma_1word & 0x0004) { - if (!((id->dma_1word >> 8) & 4)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0404; - } /* speed 2 == DMA mode 2 single-word */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x05); - speed = XFER_SW_DMA_2; + speed = XFER_SW_DMA_2; TB = 0x60; TC = 0x05; } else if (id->dma_1word & 0x0002) { - if (!((id->dma_1word >> 8) & 2)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0202; - } /* speed 1 == DMA mode 1 single-word */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x80); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x06); - speed = XFER_SW_DMA_1; + speed = XFER_SW_DMA_1; TB = 0x80; TC = 0x06; } else if (id->dma_1word & 0x0001) { - if (!((id->dma_1word >> 8) & 1)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0101; - } /* speed 0 == DMA mode 0 single-word */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0xC0); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x0B); - speed = XFER_SW_DMA_0; + speed = XFER_SW_DMA_0; TB = 0xC0; TC = 0x0B; } else { /* restore original pci-config space */ pci_write_config_dword(dev, drive_pci, drive_conf); return ide_dma_off_quietly; } - err = ide_config_drive_speed(drive, speed); + pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); + pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC); #if PDC202XX_DECODE_REGISTER_INFO pci_read_config_byte(dev, (drive_pci), &AP); @@ -418,6 +402,8 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) decode_registers(REG_D, DP); #endif /* PDC202XX_DECODE_REGISTER_INFO */ + err = ide_config_drive_speed(drive, speed); + #if PDC202XX_DEBUG_DRIVE_INFO printk("%s: %s drive%d 0x%08x ", drive->name, ide_xfer_verbose(speed), @@ -441,6 +427,83 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) * 11, 5, 4, 3, 2, 1, 0 */ +static int config_chipset_for_pio (ide_drive_t *drive, byte pio) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + byte drive_pci, speed; + byte AP, BP, TA, TB; + + int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); + int err; + + switch (drive_number) { + case 0: drive_pci = 0x60; break; + case 1: drive_pci = 0x64; break; + case 2: drive_pci = 0x68; break; + case 3: drive_pci = 0x6c; break; + default: return 1; + } + + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + + + if ((AP & 0x0F) || (BP & 0x07)) { + /* clear PIO modes of lower 8421 bits of A Register */ + pci_write_config_byte(dev, (drive_pci), AP & ~0x0F); + pci_read_config_byte(dev, (drive_pci), &AP); + + /* clear PIO modes of lower 421 bits of B Register */ + pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0x07); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + } + + pio = (pio == 5) ? 4 : pio; + switch (ide_get_best_pio_mode(drive, 255, pio, NULL)) { + case 4: speed = XFER_PIO_4; TA=0x01; TB=0x04; break; + case 3: speed = XFER_PIO_3; TA=0x02; TB=0x06; break; + case 2: speed = XFER_PIO_2; TA=0x03; TB=0x08; break; + case 1: speed = XFER_PIO_1; TA=0x05; TB=0x0C; break; + case 0: + default: speed = XFER_PIO_0; TA=0x09; TB=0x13; break; + } + pci_write_config_byte(dev, (drive_pci), AP|TA); + pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); + +#if PDC202XX_DECODE_REGISTER_INFO + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + pci_read_config_byte(dev, (drive_pci)|0x02, &CP); + pci_read_config_byte(dev, (drive_pci)|0x03, &DP); + + decode_registers(REG_A, AP); + decode_registers(REG_B, BP); + decode_registers(REG_C, CP); + decode_registers(REG_D, DP); +#endif /* PDC202XX_DECODE_REGISTER_INFO */ + + err = ide_config_drive_speed(drive, speed); + +#if PDC202XX_DEBUG_DRIVE_INFO + printk("%s: %s drive%d 0x%08x ", + drive->name, ide_xfer_verbose(speed), + drive_number, drive_conf); + pci_read_config_dword(dev, drive_pci, &drive_conf); + printk("0x%08x\n", drive_conf); +#endif /* PDC202XX_DEBUG_DRIVE_INFO */ + + return err; +} + +static void pdc202xx_tune_drive (ide_drive_t *drive, byte pio) +{ + (void) config_chipset_for_pio(drive, pio); +} + static int config_drive_xfer_rate (ide_drive_t *drive) { struct hd_driveid *id = drive->id; @@ -450,9 +513,10 @@ static int config_drive_xfer_rate (ide_drive_t *drive) if (id && (id->capability & 1) && hwif->autodma) { /* Consult the list of known "bad" drives */ if (ide_dmaproc(ide_dma_bad_drive, drive)) { - return HWIF(drive)->dmaproc(ide_dma_off, drive); + dma_func = ide_dma_off; + goto fast_ata_pio; } - + dma_func = ide_dma_off_quietly; if (id->field_valid & 4) { if (id->dma_ultra & 0x001F) { /* Force if Capable UltraDMA */ @@ -463,17 +527,31 @@ static int config_drive_xfer_rate (ide_drive_t *drive) } } else if (id->field_valid & 2) { try_dma_modes: - if ((id->dma_mword & 0x0004) || - (id->dma_1word & 0x0004)) { + if ((id->dma_mword & 0x0007) || + (id->dma_1word & 0x0007)) { /* Force if Capable regular DMA modes */ dma_func = config_chipset_for_dma(drive, 0); + if (dma_func != ide_dma_on) + goto no_dma_set; + } + } else if (ide_dmaproc(ide_dma_good_drive, drive)) { + if (id->eide_dma_time > 150) { + goto no_dma_set; } - } else if ((ide_dmaproc(ide_dma_good_drive, drive)) && - (id->eide_dma_time > 150)) { /* Consult the list of known "good" drives */ dma_func = config_chipset_for_dma(drive, 0); + if (dma_func != ide_dma_on) + goto no_dma_set; + } else { + goto fast_ata_pio; } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: + dma_func = ide_dma_off_quietly; +no_dma_set: + (void) config_chipset_for_pio(drive, 5); } + return HWIF(drive)->dmaproc(dma_func, drive); } @@ -498,6 +576,26 @@ unsigned int __init pci_init_pdc202xx (struct pci_dev *dev, const char *name) byte primary_mode = inb(high_16 + 0x001a); byte secondary_mode = inb(high_16 + 0x001b); + if (dev->device == PCI_DEVICE_ID_PROMISE_20262) { + int i = 0; + /* + * software reset - this is required because the bios + * will set UDMA timing on if the hdd supports it. The + * user may want to turn udma off. A bug in the pdc20262 + * is that it cannot handle a downgrade in timing from UDMA + * to DMA. Disk accesses after issuing a set feature command + * will result in errors. A software reset leaves the timing + * registers intact, but resets the drives. + */ + + OUT_BYTE(udma_speed_flag | 0x10, high_16 + 0x001f); + ide_delay_50ms(); + ide_delay_50ms(); + OUT_BYTE(udma_speed_flag & ~0x10, high_16 + 0x001f); + for (i=0; i<40; i++) + ide_delay_50ms(); + } + if (dev->resource[PCI_ROM_RESOURCE].start) { pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); @@ -547,24 +645,23 @@ unsigned int __init pci_init_pdc202xx (struct pci_dev *dev, const char *name) return dev->irq; } +unsigned int __init ata66_pdc202xx (ide_hwif_t *hwif) +{ + unsigned short mask = (hwif->channel) ? (1<<11) : (1<<10); + unsigned short CIS; + + pci_read_config_word(hwif->pci_dev, 0x50, &CIS); + return ((CIS & mask) ? 0 : 1); +} + void __init ide_init_pdc202xx (ide_hwif_t *hwif) { + hwif->tuneproc = &pdc202xx_tune_drive; + if (hwif->dma_base) { hwif->dmaproc = &pdc202xx_dmaproc; - - switch(hwif->pci_dev->device) { - case PCI_DEVICE_ID_PROMISE_20262: -#if 0 - { - unsigned long high_16 = hwif->pci_dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK; - hwif->udma_four = 1; - } -#endif - break; - case PCI_DEVICE_ID_PROMISE_20246: - default: - hwif->udma_four = 0; - break; - } + } else { + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; } } diff --git a/drivers/block/pdc4030.c b/drivers/block/pdc4030.c index 84fbb48561da..d53c2d394a05 100644 --- a/drivers/block/pdc4030.c +++ b/drivers/block/pdc4030.c @@ -162,6 +162,7 @@ int __init setup_pdc4030 (ide_hwif_t *hwif) if (!hwif) return 0; drive = &hwif->drives[0]; + drive->timeout = HZ/100; hwif2 = &ide_hwifs[hwif->index+1]; if (hwif->chipset == ide_pdc4030) /* we've already been found ! */ return 1; @@ -169,7 +170,8 @@ int __init setup_pdc4030 (ide_hwif_t *hwif) if (IN_BYTE(IDE_NSECTOR_REG) == 0xFF || IN_BYTE(IDE_SECTOR_REG) == 0xFF) { return 0; } - OUT_BYTE(0x08,IDE_CONTROL_REG); + if (IDE_CONTROL_REG) + OUT_BYTE(0x08,IDE_CONTROL_REG); if (pdc4030_cmd(drive,PROMISE_GET_CONFIG)) { return 0; } @@ -307,6 +309,9 @@ static void promise_read_intr (ide_drive_t *drive) unsigned int sectors_left, sectors_avail, nsect; struct request *rq; + /* reset timeout */ + drive->timeout = HZ/100; + if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) { ide_error(drive, "promise_read_intr", stat); return; @@ -361,7 +366,8 @@ read_next: if (stat & DRQ_STAT) goto read_again; if (stat & BUSY_STAT) { - ide_set_handler (drive, &promise_read_intr, WAIT_CMD); + drive->timeout = WAIT_CMD; + ide_set_handler (drive, &promise_read_intr); #ifdef DEBUG_READ printk(KERN_DEBUG "%s: promise_read: waiting for" "interrupt\n", drive->name); @@ -390,7 +396,8 @@ static void promise_complete_pollfunc(ide_drive_t *drive) if (GET_STAT() & BUSY_STAT) { if (time_before(jiffies, hwgroup->poll_timeout)) { - ide_set_handler(drive, &promise_complete_pollfunc, 1); + drive->timeout = 1; + ide_set_handler(drive, &promise_complete_pollfunc); return; /* continue polling... */ } hwgroup->poll_timeout = 0; @@ -419,7 +426,8 @@ static void promise_write_pollfunc (ide_drive_t *drive) if (IN_BYTE(IDE_NSECTOR_REG) != 0) { if (time_before(jiffies, hwgroup->poll_timeout)) { - ide_set_handler (drive, &promise_write_pollfunc, 1); + drive->timeout = 1; + ide_set_handler (drive, &promise_write_pollfunc); return; /* continue polling... */ } hwgroup->poll_timeout = 0; @@ -433,7 +441,8 @@ static void promise_write_pollfunc (ide_drive_t *drive) */ ide_multwrite(drive, 4); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler(drive, &promise_complete_pollfunc, 1); + drive->timeout = 1; + ide_set_handler(drive, &promise_complete_pollfunc); #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n", drive->name, GET_STAT()); @@ -466,7 +475,8 @@ static void promise_write (ide_drive_t *drive) if (rq->nr_sectors > 4) { ide_multwrite(drive, rq->nr_sectors - 4); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler (drive, &promise_write_pollfunc, 1); + drive->timeout = 1; + ide_set_handler (drive, &promise_write_pollfunc); } else { /* * There are 4 or fewer sectors to transfer, do them all in one go @@ -474,7 +484,8 @@ static void promise_write (ide_drive_t *drive) */ ide_multwrite(drive, rq->nr_sectors); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler(drive, &promise_complete_pollfunc, 1); + drive->timeout = 1; + ide_set_handler(drive, &promise_complete_pollfunc); #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, " "status = %02x\n", drive->name, GET_STAT()); @@ -517,7 +528,8 @@ void do_pdc4030_io (ide_drive_t *drive, struct request *rq) printk(KERN_DEBUG "%s: read: waiting for " "interrupt\n", drive->name); #endif - ide_set_handler(drive, &promise_read_intr, WAIT_CMD); + drive->timeout = WAIT_CMD; + ide_set_handler(drive, &promise_read_intr); return; } udelay(1); diff --git a/drivers/block/piix.c b/drivers/block/piix.c index b1fd76014baa..a9bcb347cf22 100644 --- a/drivers/block/piix.c +++ b/drivers/block/piix.c @@ -1,8 +1,9 @@ /* - * linux/drivers/block/piix.c Version 0.25 July 11, 1999 + * linux/drivers/block/piix.c Version 0.27 Sept. 3, 1999 * * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer - * Copyright (C) 1998-1999 Andre Hedrick, Author and Maintainer + * Copyright (C) 1998-1999 Andre Hedrick (andre@suse.com) + * May be copied or modified under the terms of the GNU General Public License * * PIO mode setting function for Intel chipsets. * For use instead of BIOS settings. @@ -182,30 +183,13 @@ static int piix_config_drive_for_dma(ide_drive_t *drive) } } - if ((id->dma_ultra & 0x0010) && (ultra)) { - goto backspeed; - } else if ((id->dma_ultra & 0x0008) && (ultra)) { - goto backspeed; - } else if ((id->dma_ultra & 0x0004) && (ultra)) { -backspeed: - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - if (!((id->dma_ultra >> 8) & 4)) { - drive->id->dma_ultra &= ~0x0F00; - drive->id->dma_ultra |= 0x0404; - } + if (((id->dma_ultra & 0x0010) || (id->dma_ultra & 0x0008) || (id->dma_ultra & 0x0004)) && (ultra)) { u_speed = 2 << (drive_number * 4); if (!(reg4a & u_speed)) { pci_write_config_word(dev, 0x4a, reg4a|u_speed); } speed = XFER_UDMA_2; } else if ((id->dma_ultra & 0x0002) && (ultra)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - if (!((id->dma_ultra >> 8) & 2)) { - drive->id->dma_ultra &= ~0x0F00; - drive->id->dma_ultra |= 0x0202; - } u_speed = 1 << (drive_number * 4); if (!(reg4a & u_speed)) { pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); @@ -213,12 +197,6 @@ backspeed: } speed = XFER_UDMA_1; } else if ((id->dma_ultra & 0x0001) && (ultra)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - if (!((id->dma_ultra >> 8) & 1)) { - drive->id->dma_ultra &= ~0x0F00; - drive->id->dma_ultra |= 0x0101; - } u_speed = 0 << (drive_number * 4); if (!(reg4a & u_speed)) { pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); @@ -228,32 +206,14 @@ backspeed: } else if (id->dma_mword & 0x0004) { if (reg4a & a_speed) pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - drive->id->dma_ultra &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - if (!((id->dma_mword >> 8) & 4)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0404; - } speed = XFER_MW_DMA_2; } else if (id->dma_mword & 0x0002) { if (reg4a & a_speed) pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - drive->id->dma_ultra &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - if (!((id->dma_mword >> 8) & 2)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0202; - } speed = XFER_MW_DMA_1; } else if (id->dma_1word & 0x0004) { if (reg4a & a_speed) pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - drive->id->dma_ultra &= ~0x0F00; - drive->id->dma_mword &= ~0x0F00; - if (!((id->dma_1word >> 8) & 4)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0404; - } speed = XFER_SW_DMA_2; } else { speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); @@ -264,10 +224,7 @@ backspeed: (void) ide_config_drive_speed(drive, speed); #if PIIX_DEBUG_DRIVE_INFO - printk("%s: %s drive%d ", - drive->name, - ide_xfer_verbose(speed), - drive_number); + printk("%s: %s drive%d ", drive->name, ide_xfer_verbose(speed), drive_number); printk("\n"); #endif /* PIIX_DEBUG_DRIVE_INFO */ @@ -291,7 +248,7 @@ static int piix_dmaproc(ide_dma_action_t func, ide_drive_t *drive) } #endif /* CONFIG_BLK_DEV_PIIX_TUNING */ -void ide_init_piix (ide_hwif_t *hwif) +void __init ide_init_piix (ide_hwif_t *hwif) { hwif->tuneproc = &piix_tune_drive; diff --git a/drivers/block/sis5513.c b/drivers/block/sis5513.c index 08bbb1c9168f..8a3abd0253a5 100644 --- a/drivers/block/sis5513.c +++ b/drivers/block/sis5513.c @@ -1,11 +1,11 @@ /* - * linux/drivers/block/sis5513.c Version 0.06 July 11, 1999 + * linux/drivers/block/sis5513.c Version 0.07 Sept. 3, 1999 * - * Copyright (C) 1999 Andre Hedrick + * Copyright (C) 1999 Andre Hedrick (andre@suse.com) + * May be copied or modified under the terms of the GNU General Public License * - * drive_number - * = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); - * = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); + * Thanks to SIS Taiwan for direct support and hardware. + * Tested and designed on the SiS620/5513 chipset. */ #include @@ -27,10 +27,178 @@ #include "ide_modes.h" +#define SIS5513_DEBUG_DRIVE_INFO 0 + +#define DISPLAY_SIS_TIMINGS + static struct pci_dev *host_dev; -#define SIS5513_DEBUG_DRIVE_INFO 0 +#if 0 +static struct _pio_mode_mapping { + byte data_active; + byte recovery; + byte pio_mode; +} pio_mode_mapping[] = { + { 8, 12, 0 }, + { 6, 7, 1 }, + { 4, 4, 2 }, + { 3, 3, 3 }, + { 3, 1, 4 } +}; + +static struct _dma_mode_mapping { + byte data_active; + byte recovery; + byte dma_mode; +} dma_mode_mapping[] = { + { 8, 8, 0 }, + { 3, 2, 1 }, + { 3, 1, 2 } +}; + +static struct _udma_mode_mapping { + byte cycle_time; + char * udma_mode; +} udma_mode_mapping[] = { + { 8, "Mode 0" }, + { 6, "Mode 1" }, + { 4, "Mode 2" }, + { 3, "Mode 3" }, + { 2, "Mode 4" }, + { 0, "Undefined" } +}; + +static __inline__ char * find_udma_mode (byte cycle_time) +{ + int n; + + for (n = 0; n <= 4; n++) + if (udma_mode_mapping[n].cycle_time <= cycle_time) + return udma_mode_mapping[n].udma_mode; + return udma_mode_mapping[4].udma_mode; +} +#endif + +#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static int sis_get_info(char *, char **, off_t, int, int); +extern int (*sis_display_info)(char *, char **, off_t, int, int); /* ide-proc.c */ +struct pci_dev *bmide_dev; + +static char *cable_type[] = { + "80 pins", + "40 pins" +}; + +static char *recovery_time [] ={ + "12 PCICLK", "1 PCICLK", + "2 PCICLK", "3 PCICLK", + "4 PCICLK", "5 PCICLCK", + "6 PCICLK", "7 PCICLCK", + "8 PCICLK", "9 PCICLCK", + "10 PCICLK", "11 PCICLK", + "13 PCICLK", "14 PCICLK", + "15 PCICLK", "15 PCICLK" +}; + +static char *cycle_time [] = { + "Undefined", "2 CLCK", + "3 CLK", "4 CLK", + "5 CLK", "6 CLK", + "7 CLK", "8 CLK" +}; + +static char *active_time [] = { + "8 PCICLK", "1 PCICLCK", + "2 PCICLK", "2 PCICLK", + "4 PCICLK", "5 PCICLK", + "6 PCICLK", "12 PCICLK" +}; + +static int sis_get_info (char *buffer, char **addr, off_t offset, int count, int dummy) +{ + int rc; + char *p = buffer; + byte reg,reg1; +#if 0 + byte cyc, rec, act; +#endif + u16 reg2, reg3; + + p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); + rc = pci_read_config_byte(bmide_dev, 0x4a, ®); + p += sprintf(p, "Channel Status: %s \t \t \t \t %s \n", + (reg & 0x02) ? "On" : "Off", + (reg & 0x04) ? "On" : "Off"); + + rc = pci_read_config_byte(bmide_dev, 0x09, ®); + p += sprintf(p, "Operation Mode: %s \t \t \t %s \n", + (reg & 0x01) ? "Native" : "Compatible", + (reg & 0x04) ? "Native" : "Compatible"); + + rc = pci_read_config_byte(bmide_dev, 0x48, ®); + p += sprintf(p, "Cable Type: %s \t \t \t %s\n", + (reg & 0x10) ? cable_type[1] : cable_type[0], + (reg & 0x20) ? cable_type[1] : cable_type[0]); + + rc = pci_read_config_word(bmide_dev, 0x4c, ®2); + rc = pci_read_config_word(bmide_dev, 0x4e, ®3); + p += sprintf(p, "Prefetch Count: %d \t \t \t \t %d\n", + reg2, reg3); + + rc = pci_read_config_byte(bmide_dev, 0x4b, ®); + p += sprintf(p, "Drvie 0: Postwrite %s \t \t Postwrite %s\n", + (reg & 0x10) ? "Enabled" : "Disabled", + (reg & 0x40) ? "Enabled" : "Disabled"); + p += sprintf(p, " Prefetch %s \t \t Prefetch %s\n", + (reg & 0x01) ? "Enabled" : "Disabled", + (reg & 0x04) ? "Enabled" : "Disabled"); + + rc = pci_read_config_byte(bmide_dev, 0x41, ®); + rc = pci_read_config_byte(bmide_dev, 0x45, ®1); + p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n", + (reg & 0x80) ? "Enabled" : "Disabled", + (reg1 & 0x80) ? "Enabled" : "Disabled"); + p += sprintf(p, " UDMA Cycle Time %s \t UDMA Cycle Time %s\n", + cycle_time[(reg & 0x70) >> 4], cycle_time[(reg1 & 0x70) >> 4]); + p += sprintf(p, " Data Active Time %s \t Data Active Time %s\n", + active_time[(reg & 0x07)], active_time[(reg &0x07)] ); + + rc = pci_read_config_byte(bmide_dev, 0x40, ®); + rc = pci_read_config_byte(bmide_dev, 0x44, ®1); + p += sprintf(p, " Data Recovery Time %s \t Data Recovery Time %s\n", + recovery_time[(reg & 0x0f)], recovery_time[(reg1 & 0x0f)]); + + + rc = pci_read_config_byte(bmide_dev, 0x4b, ®); + p += sprintf(p, "Drvie 1: Postwrite %s \t \t Postwrite %s\n", + (reg & 0x20) ? "Enabled" : "Disabled", + (reg & 0x80) ? "Enabled" : "Disabled"); + p += sprintf(p, " Prefetch %s \t \t Prefetch %s\n", + (reg & 0x02) ? "Enabled" : "Disabled", + (reg & 0x08) ? "Enabled" : "Disabled"); + + rc = pci_read_config_byte(bmide_dev, 0x43, ®); + rc = pci_read_config_byte(bmide_dev, 0x47, ®1); + p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n", + (reg & 0x80) ? "Enabled" : "Disabled", + (reg1 & 0x80) ? "Enabled" : "Disabled"); + p += sprintf(p, " UDMA Cycle Time %s \t UDMA Cycle Time %s\n", + cycle_time[(reg & 0x70) >> 4], cycle_time[(reg1 & 0x70) >> 4]); + p += sprintf(p, " Data Active Time %s \t Data Active Time %s\n", + active_time[(reg & 0x07)], active_time[(reg &0x07)] ); + + rc = pci_read_config_byte(bmide_dev, 0x42, ®); + rc = pci_read_config_byte(bmide_dev, 0x46, ®1); + p += sprintf(p, " Data Recovery Time %s \t Data Recovery Time %s\n", + recovery_time[(reg & 0x0f)], recovery_time[(reg1 & 0x0f)]); + return p-buffer; +} +#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */ +byte sis_proc = 0; extern char *ide_xfer_verbose (byte xfer_rate); /* @@ -79,36 +247,18 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) } if ((id->dma_ultra & 0x0010) && (ultra) && (udma_66) && (four_two)) { - if (!((id->dma_ultra >> 8) & 16)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x1010; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } if (!(test2 & 0x90)) { pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); pci_write_config_byte(dev, drive_pci|0x01, test2|0x90); } speed = XFER_UDMA_4; } else if ((id->dma_ultra & 0x0008) && (ultra) && (udma_66) && (four_two)) { - if (!((id->dma_ultra >> 8) & 8)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0808; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } if (!(test2 & 0xA0)) { pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); pci_write_config_byte(dev, drive_pci|0x01, test2|0xA0); } speed = XFER_UDMA_3; } else if ((id->dma_ultra & 0x0004) && (ultra)) { - if (!((id->dma_ultra >> 8) & 4)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0404; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } mask = (four_two) ? 0xB0 : 0xA0; if (!(test2 & mask)) { pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); @@ -116,12 +266,6 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) } speed = XFER_UDMA_2; } else if ((id->dma_ultra & 0x0002) && (ultra)) { - if (!((id->dma_ultra >> 8) & 2)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0202; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } mask = (four_two) ? 0xD0 : 0xC0; if (!(test2 & mask)) { pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); @@ -129,58 +273,22 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) } speed = XFER_UDMA_1; } else if ((id->dma_ultra & 0x0001) && (ultra)) { - if (!((id->dma_ultra >> 8) & 1)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0101; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } if (!(test2 & unmask)) { pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); pci_write_config_byte(dev, drive_pci|0x01, test2|unmask); } speed = XFER_UDMA_0; } else if (id->dma_mword & 0x0004) { - if (!((id->dma_mword >> 8) & 4)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0404; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_MW_DMA_2; } else if (id->dma_mword & 0x0002) { - if (!((id->dma_mword >> 8) & 2)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0202; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_MW_DMA_1; } else if (id->dma_mword & 0x0001) { - if (!((id->dma_mword >> 8) & 1)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0101; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_MW_DMA_0; } else if (id->dma_1word & 0x0004) { - if (!((id->dma_1word >> 8) & 4)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0404; - drive->id->dma_mword &= ~0x0F00; - } speed = XFER_SW_DMA_2; } else if (id->dma_1word & 0x0002) { - if (!((id->dma_1word >> 8) & 2)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0202; - drive->id->dma_mword &= ~0x0F00; - } speed = XFER_SW_DMA_1; } else if (id->dma_1word & 0x0001) { - if (!((id->dma_1word >> 8) & 1)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0101; - drive->id->dma_mword &= ~0x0F00; - } speed = XFER_SW_DMA_0; } else { return ((int) ide_dma_off_quietly); @@ -189,10 +297,7 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) err = ide_config_drive_speed(drive, speed); #if SIS5513_DEBUG_DRIVE_INFO - printk("%s: %s drive%d\n", - drive->name, - ide_xfer_verbose(speed), - drive_number); + printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive_number); #endif /* SIS5513_DEBUG_DRIVE_INFO */ return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on : @@ -333,10 +438,9 @@ int sis5513_dmaproc (ide_dma_action_t func, ide_drive_t *drive) unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name) { struct pci_dev *host; - byte latency = 0, reg48h = 0; + byte latency = 0; pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency); - pci_read_config_byte(dev, 0x48, ®48h); for (host = pci_devices; host; host=host->next) { if (host->vendor == PCI_VENDOR_ID_SI && @@ -344,30 +448,18 @@ unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name) if (latency != 0x10) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10); host_dev = host; - printk("%s: Chipset Core ATA-66, SiS620\n", name); - printk("%s: Primary ATA-%s, Secondary ATA-%s Cable Detect\n", - name, - (reg48h & 0x10) ? "33" : "66", - (reg48h & 0x20) ? "33" : "66"); break; } else if (host->vendor == PCI_VENDOR_ID_SI && host->device == PCI_DEVICE_ID_SI_530) { host_dev = host; - printk("%s: Chipset Core ATA-66, SiS530\n", name); - printk("%s: Primary ATA-%s, Secondary ATA-%s Cable Detect\n", - name, - (reg48h & 0x10) ? "33" : "66", - (reg48h & 0x20) ? "33" : "66"); break; } else if (host->vendor == PCI_VENDOR_ID_SI && host->device == PCI_DEVICE_ID_SI_5600) { host_dev = host; - printk("SIS5600:%s Chipset Core ATA-33\n", name); break; } else if (host->vendor == PCI_VENDOR_ID_SI && host->device == PCI_DEVICE_ID_SI_5597) { host_dev = host; - printk("SIS5597:%s Chipset Core ATA-33\n", name); break; } } @@ -377,18 +469,38 @@ unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name) pci_read_config_byte(dev, 0x52, ®52h); if (!(reg52h & 0x04)) + /* set IDE controller to operate in Compabitility mode obly */ pci_write_config_byte(dev, 0x52, reg52h|0x04); +#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) + sis_proc = 1; + bmide_dev = dev; + sis_display_info = &sis_get_info; +#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */ } - return 0; } -void __init ide_init_sis5513 (ide_hwif_t *hwif) +unsigned int __init ata66_sis5513 (ide_hwif_t *hwif) { - byte reg48h = 0; + byte reg48h = 0, ata66 = 0; byte mask = hwif->channel ? 0x20 : 0x10; - pci_read_config_byte(hwif->pci_dev, 0x48, ®48h); + + if (host_dev) { + switch(host_dev->device) { + case PCI_DEVICE_ID_SI_530: + case PCI_DEVICE_ID_SI_620: + ata66 = (reg48h & mask) ? 0 : 1; + default: + break; + } + } + return (ata66); +} + +void __init ide_init_sis5513 (ide_hwif_t *hwif) +{ + hwif->irq = hwif->channel ? 15 : 14; if (!(hwif->dma_base)) @@ -398,20 +510,15 @@ void __init ide_init_sis5513 (ide_hwif_t *hwif) switch(host_dev->device) { case PCI_DEVICE_ID_SI_530: case PCI_DEVICE_ID_SI_620: - hwif->autodma = 1; - hwif->udma_four = (reg48h & mask) ? 0 : 1; - hwif->dmaproc = &sis5513_dmaproc; - return; case PCI_DEVICE_ID_SI_5600: case PCI_DEVICE_ID_SI_5597: hwif->autodma = 1; - hwif->udma_four = 0; hwif->dmaproc = &sis5513_dmaproc; - return; + break; default: hwif->autodma = 0; - hwif->udma_four = 0; - return; + break; } } + return; } diff --git a/drivers/block/trm290.c b/drivers/block/trm290.c index ad6a75d0f8df..5c7c8fd3c70e 100644 --- a/drivers/block/trm290.c +++ b/drivers/block/trm290.c @@ -192,7 +192,8 @@ static int trm290_dmaproc (ide_dma_action_t func, ide_drive_t *drive) outw((count * 2) - 1, hwif->dma_base+2); /* start DMA */ if (drive->media != ide_disk) return 0; - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD); + drive->timeout = WAIT_CMD; + ide_set_handler(drive, &ide_dma_intr); OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); return 0; case ide_dma_begin: diff --git a/drivers/block/via82c586.c b/drivers/block/via82cxxx.c similarity index 77% rename from drivers/block/via82c586.c rename to drivers/block/via82cxxx.c index e5697014eeaa..e6f61c03fc9b 100644 --- a/drivers/block/via82c586.c +++ b/drivers/block/via82cxxx.c @@ -1,9 +1,12 @@ /* - * linux/drivers/block/via82c586.c Version 0.04 July 11, 1999 + * linux/drivers/block/via82cxxx.c Version 0.05 Sept. 03, 1999 * - * Copyright (C) 1998 Michel Aubry, Maintainer - * Copyright (C) 1998 Andre Hedrick, Maintainer + * Copyright (C) 1998-99 Michel Aubry, Maintainer + * Copyright (C) 1999 Jeff Garzik, MVP4 Support (jgarzik@pobox.com) + * Copyright (C) 1998-99 Andre Hedrick (andre@suse.com) + * May be copied or modified under the terms of the GNU General Public License * + * The VIA MVP-4 is reported OK with UDMA. * The VIA MVP-3 is reported OK with UDMA. * The TX Pro III is also reported OK with UDMA. * @@ -57,8 +60,44 @@ #include -static struct pci_dev *host_dev; -static struct pci_dev *isa_dev; +static struct pci_dev *host_dev = NULL; +static struct pci_dev *isa_dev = NULL; + +static const struct { + const char *name; + unsigned short host_id; +} ApolloHostChipInfo[] = { + { "VT 82C585 Apollo VP1/VPX", PCI_DEVICE_ID_VIA_82C585, }, + { "VT 82C595 Apollo VP2", PCI_DEVICE_ID_VIA_82C595, }, + { "VT 82C597 Apollo VP3", PCI_DEVICE_ID_VIA_82C597_0, }, + { "VT 82C598 Apollo MVP3", PCI_DEVICE_ID_VIA_82C598_0, }, + { "VT 82C680 Apollo P6", PCI_DEVICE_ID_VIA_82C680, }, + { "VT 82C691 Apollo Pro", PCI_DEVICE_ID_VIA_82C691, }, + { "VT 82C693 Apollo Pro Plus", PCI_DEVICE_ID_VIA_82C693, }, + { "Apollo MVP4", PCI_DEVICE_ID_VIA_8501_0, }, +}; + +#define NUM_APOLLO_ISA_CHIP_DEVICES 2 +#define VIA_FLAG_CHECK_REV 0x00000001 +#define VIA_FLAG_ATA_66 0x00000002 + +static const struct { + unsigned short host_id; + unsigned short isa_id; + unsigned int flags; +} ApolloISAChipInfo[] = { + { PCI_DEVICE_ID_VIA_82C585, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV }, + { PCI_DEVICE_ID_VIA_82C595, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV }, + { PCI_DEVICE_ID_VIA_82C597_0, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV }, + { PCI_DEVICE_ID_VIA_82C598_0, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV }, + { PCI_DEVICE_ID_VIA_82C598_0, PCI_DEVICE_ID_VIA_82C596, 0 }, + { PCI_DEVICE_ID_VIA_82C680, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV }, + { PCI_DEVICE_ID_VIA_82C691, PCI_DEVICE_ID_VIA_82C596, 0 }, + { PCI_DEVICE_ID_VIA_82C693, PCI_DEVICE_ID_VIA_82C596, 0 }, + { PCI_DEVICE_ID_VIA_8501_0, PCI_DEVICE_ID_VIA_82C686, VIA_FLAG_ATA_66 }, +}; + +#define arraysize(x) (sizeof(x)/sizeof(*(x))) #define DISPLAY_VIA_TIMINGS @@ -298,6 +337,7 @@ static int via_get_info (char *buffer, char **addr, off_t offset, int count, int * Used to set Fifo configuration via kernel command line: */ +byte via_proc = 0; byte fifoconfig = 0; static byte newfifo = 0; @@ -340,8 +380,8 @@ static void set_via_timings (ide_hwif_t *hwif) /* * setting Channel read and End-of-sector FIFO flush. * (This feature ensures that FIFO flush is enabled: - * - for read DMA when interrupt asserts the given channel. - * - at the end of each sector for the given channel.) + * - for read DMA when interrupt asserts the given channel. + * - at the end of each sector for the given channel.) */ if ((rc = pci_read_config_byte(dev, 0x46, &via_config))) errors++; @@ -363,7 +403,7 @@ static void set_via_timings (ide_hwif_t *hwif) } /* - * Sets VIA 82c586 FIFO configuration: + * Sets VIA 82cxxx FIFO configuration: * This chipsets gets a splitable fifo. This can be driven either by command * line option (eg "splitfifo=2,2,3" which asks this driver to switch all the * 16 fifo levels to the second drive, and give it a threshold of 3 for (u)dma @@ -435,139 +475,71 @@ static int via_set_fifoconfig(ide_hwif_t *hwif) (newfifo & 0x01) ? "1/4" : "1/2")); #if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) + via_proc = 1; bmide_dev = hwif->pci_dev; via_display_info = &via_get_info; #endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS*/ return 0; } -unsigned int __init pci_init_via82c568 (struct pci_dev *dev, const char *name) +unsigned int __init pci_init_via82cxxx (struct pci_dev *dev, const char *name) { struct pci_dev *host; struct pci_dev *isa; + int i, j, ata33, ata66; byte revision = 0; - for (host = pci_devices; host; host=host->next) { - if (host->vendor == PCI_VENDOR_ID_VIA && - host->device == PCI_DEVICE_ID_VIA_82C585) { - host_dev = host; - printk("VT 82C585 Apollo VP1/VPX"); - for (isa = pci_devices; isa; isa=isa->next) { - if (isa->vendor == PCI_VENDOR_ID_VIA && - isa->device == PCI_DEVICE_ID_VIA_82C586_1) { - isa_dev = isa; - pci_read_config_byte(isa_dev, 0x0d, &revision); - if (revision >= 0x20) - printk(" Chipset Core ATA-33"); - break; - } - } - printk("\n"); - break; - } else if (host->vendor == PCI_VENDOR_ID_VIA && - host->device == PCI_DEVICE_ID_VIA_82C595) { - host_dev = host; - printk("VT 82C595 Apollo VP2"); - for (isa = pci_devices; isa; isa=isa->next) { - if (isa->vendor == PCI_VENDOR_ID_VIA && - isa->device == PCI_DEVICE_ID_VIA_82C586_1) { - isa_dev = isa; - pci_read_config_byte(isa_dev, 0x0d, &revision); - if (revision >= 0x20) - printk(" Chipset Core ATA-33"); - break; - } - } - printk("\n"); - break; - } else if (host->vendor == PCI_VENDOR_ID_VIA && - host->device == PCI_DEVICE_ID_VIA_82C597_0) { - host_dev = host; - printk("VT 82C597 Apollo VP3"); - for (isa = pci_devices; isa; isa=isa->next) { - if (isa->vendor == PCI_VENDOR_ID_VIA && - isa->device == PCI_DEVICE_ID_VIA_82C586_1) { - isa_dev = isa; - pci_read_config_byte(isa_dev, 0x0d, &revision); - if (revision >= 0x20) - printk(" Chipset Core ATA-33"); - break; - } - } - printk("\n"); - break; - } else if (host->vendor == PCI_VENDOR_ID_VIA && - host->device == PCI_DEVICE_ID_VIA_82C598_0) { - host_dev = host; - printk("VT 82C598 Apollo MVP3"); - for (isa = pci_devices; isa; isa=isa->next) { - if (isa->vendor == PCI_VENDOR_ID_VIA && - isa->device == PCI_DEVICE_ID_VIA_82C586_1) { - isa_dev = isa; - pci_read_config_byte(isa_dev, 0x0d, &revision); - if (revision >= 0x20) - printk(" Chipset Core ATA-33"); - break; - } else if (isa->vendor == PCI_VENDOR_ID_VIA && - isa->device == PCI_DEVICE_ID_VIA_82C596) { - isa_dev = isa; - printk(" Chipset Core ATA-33"); - break; - } - } - printk("\n"); - break; - } else if (host->vendor == PCI_VENDOR_ID_VIA && - host->device == PCI_DEVICE_ID_VIA_82C680) { - host_dev = host; - printk("VT 82C680 Apollo P6"); - for (isa = pci_devices; isa; isa=isa->next) { - if (isa->vendor == PCI_VENDOR_ID_VIA && - isa->device == PCI_DEVICE_ID_VIA_82C586_1) { - isa_dev = isa; - pci_read_config_byte(isa_dev, 0x0d, &revision); - if (revision >= 0x20) - printk(" Chipset Core ATA-33"); - break; - } + for (i = 0; i < arraysize (ApolloHostChipInfo) && !host_dev; i++) { + host = pci_find_device (PCI_VENDOR_ID_VIA, + ApolloHostChipInfo[i].host_id, + NULL); + if (!host) + continue; + + host_dev = host; + printk(ApolloHostChipInfo[i].name); + + for (j = 0; j < arraysize (ApolloISAChipInfo) && !isa_dev; j++) { + if (ApolloISAChipInfo[j].host_id != + ApolloHostChipInfo[i].host_id) + continue; + + isa = pci_find_device (PCI_VENDOR_ID_VIA, + ApolloISAChipInfo[i].isa_id, + NULL); + if (!isa) + continue; + + isa_dev = isa; + + ata33 = 1; + ata66 = 0; + + if (ApolloISAChipInfo[i].flags & VIA_FLAG_CHECK_REV) { + pci_read_config_byte(isa_dev, 0x0d, &revision); + ata33 = (revision >= 0x20) ? 1 : 0; + } else if (ApolloISAChipInfo[i].flags & VIA_FLAG_ATA_66) { + ata33 = 0; + ata66 = 1; } - printk("\n"); - break; - } else if (host->vendor == PCI_VENDOR_ID_VIA && - host->device == PCI_DEVICE_ID_VIA_82C691) { - host_dev = host; - printk("VT 82C691 Apollo Pro"); - for (isa = pci_devices; isa; isa=isa->next) { - if (isa->vendor == PCI_VENDOR_ID_VIA && - isa->device == PCI_DEVICE_ID_VIA_82C596) { - isa_dev = isa; - printk(" Chipset Core ATA-33"); - break; - } - } - printk("\n"); - break; - } else if (host->vendor == PCI_VENDOR_ID_VIA && - host->device == PCI_DEVICE_ID_VIA_82C693) { - host_dev = host; - printk("VT 82C693 Apollo Pro Plus"); - for (isa = pci_devices; isa; isa=isa->next) { - if (isa->vendor == PCI_VENDOR_ID_VIA && - isa->device == PCI_DEVICE_ID_VIA_82C596) { - isa_dev = isa; - printk(" Chipset Core ATA-33"); - break; - } - } - printk("\n"); - break; + + if (ata33 | ata66) + printk(" Chipset Core ATA-%s", ata66 ? "66" : "33"); } + printk("\n"); } + + return 0; +} + +unsigned int __init ata66_via82cxxx (ide_hwif_t *hwif) +{ + /* (Jeff Garzik) FIXME!!! for MVP4 */ return 0; } -void __init ide_init_via82c586 (ide_hwif_t *hwif) +void __init ide_init_via82cxxx (ide_hwif_t *hwif) { set_via_timings(hwif); } @@ -581,7 +553,7 @@ void __init ide_init_via82c586 (ide_hwif_t *hwif) * bypasses the setup if not capable. */ -void ide_dmacapable_via82c586 (ide_hwif_t *hwif, unsigned long dmabase) +void ide_dmacapable_via82cxxx (ide_hwif_t *hwif, unsigned long dmabase) { if (!done) { via_set_fifoconfig(hwif); diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 7a46ed183620..b41356423f1d 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -177,10 +177,15 @@ for ide-cd to handle multisession discs. -- Export cdrom_mode_sense and cdrom_mode_select. -- init_cdrom_command() for setting up a cgc command. + + 3.05 Sep 23, 1999 - Jens Axboe + -- Changed the interface for CDROM_SEND_PACKET. Before it was virtually + impossible to send the drive data in a sensible way. + -------------------------------------------------------------------------*/ -#define REVISION "Revision: 3.04" -#define VERSION "Id: cdrom.c 3.04 1999/09/14" +#define REVISION "Revision: 3.05" +#define VERSION "Id: cdrom.c 3.05 1999/09/23" /* I use an error-log mask to give fine grain control over the type of messages dumped to the system logs. The available masks include: */ @@ -213,6 +218,7 @@ #include #include #include +#include #include #include #include @@ -302,6 +308,8 @@ struct file_operations cdrom_fops = */ #define ENSURE(call, bits) if (cdo->call == NULL) *change_capability &= ~(bits) +static int cdrom_setup_writemode(struct cdrom_device_info *cdi); + int register_cdrom(struct cdrom_device_info *cdi) { static char banner_printed = 0; @@ -316,7 +324,7 @@ int register_cdrom(struct cdrom_device_info *cdi) if (cdo->open == NULL || cdo->release == NULL) return -2; if ( !banner_printed ) { - printk(KERN_INFO "Uniform CDROM driver " REVISION "\n"); + printk(KERN_INFO "Uniform CD-ROM driver " REVISION "\n"); banner_printed = 1; #ifdef CONFIG_SYSCTL cdrom_sysctl_register(); @@ -349,6 +357,9 @@ int register_cdrom(struct cdrom_device_info *cdi) cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name); cdi->next = topCdromPtr; topCdromPtr = cdi; + if (CDROM_CAN(CDC_CD_R) || CDROM_CAN(CDC_CD_RW) || CDROM_CAN(CDC_DVD_R)) + (void)cdrom_setup_writemode(cdi); + return 0; } #undef ENSURE @@ -1701,8 +1712,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, unsigned long arg) { struct cdrom_device_ops *cdo = cdi->ops; - kdev_t dev = cdi->dev; struct cdrom_generic_command cgc; + kdev_t dev = cdi->dev; char buffer[32]; int ret = 0; @@ -1919,7 +1930,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, case CDROMSTART: case CDROMSTOP: { - cdinfo(CD_DO_IOCTL, "entering audio ioctl (start/stop)\n"); + cdinfo(CD_DO_IOCTL, "entering CDROMSTART/CDROMSTOP\n"); cgc.cmd[0] = GPCMD_START_STOP_UNIT; cgc.cmd[1] = 1; cgc.cmd[4] = (cmd == CDROMSTART) ? 1 : 0; @@ -1928,7 +1939,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, case CDROMPAUSE: case CDROMRESUME: { - cdinfo(CD_DO_IOCTL, "entering audio ioctl (pause/resume)\n"); + cdinfo(CD_DO_IOCTL, "entering CDROMPAUSE/CDROMRESUME\n"); cgc.cmd[0] = GPCMD_PAUSE_RESUME; cgc.cmd[8] = (cmd == CDROMRESUME) ? 1 : 0; return cdo->generic_packet(cdi, &cgc); @@ -1938,7 +1949,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, dvd_struct s; if (!CDROM_CAN(CDC_DVD)) return -ENOSYS; - cdinfo(CD_DO_IOCTL, "entering dvd_read_struct\n"); + cdinfo(CD_DO_IOCTL, "entering DVD_READ_STRUCT\n"); IOCTL_IN(arg, dvd_struct, s); if ((ret = dvd_read_struct(cdi, &s))) return ret; @@ -1950,7 +1961,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, dvd_authinfo ai; if (!CDROM_CAN(CDC_DVD)) return -ENOSYS; - cdinfo(CD_DO_IOCTL, "entering dvd_auth\n"); + cdinfo(CD_DO_IOCTL, "entering DVD_AUTH\n"); IOCTL_IN(arg, dvd_authinfo, ai); if ((ret = dvd_do_auth (cdi, &ai))) return ret; @@ -1959,26 +1970,58 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, } case CDROM_SEND_PACKET: { + __u8 *userbuf, copy = 0; if (!CDROM_CAN(CDC_GENERIC_PACKET)) return -ENOSYS; - cdinfo(CD_DO_IOCTL, "entering send_packet\n"); + cdinfo(CD_DO_IOCTL, "entering CDROM_SEND_PACKET\n"); IOCTL_IN(arg, struct cdrom_generic_command, cgc); - cgc.buffer = kmalloc(cgc.buflen, GFP_KERNEL); + copy = !!cgc.buflen; + userbuf = cgc.buffer; + cgc.buffer = NULL; + if (userbuf != NULL && copy) { + /* usually commands just copy data one way, i.e. + * we send a buffer to the drive and the command + * specifies whether the drive will read or + * write to that buffer. usually the buffers + * are very small, so we don't loose that much + * by doing a redundant copy each time. */ + if (!access_ok(VERIFY_WRITE, userbuf, cgc.buflen)) { + printk("can't get write perms\n"); + return -EFAULT; + } + if (!access_ok(VERIFY_READ, userbuf, cgc.buflen)) { + printk("can't get read perms\n"); + return -EFAULT; + } + } + /* reasonable limits */ + if (cgc.buflen < 0 || cgc.buflen > 131072) { + printk("invalid size given\n"); + return -EINVAL; + } + if (copy) { + cgc.buffer = kmalloc(cgc.buflen, GFP_KERNEL); + if (cgc.buffer == NULL) + return -ENOMEM; + __copy_from_user(cgc.buffer, userbuf, cgc.buflen); + } ret = cdo->generic_packet(cdi, &cgc); - if (copy_to_user((void*)arg, cgc.buffer, cgc.buflen)) - ret = -EFAULT; + if (copy && !ret) + __copy_to_user(userbuf, cgc.buffer, cgc.buflen); kfree(cgc.buffer); return ret; } case CDROM_NEXT_WRITABLE: { - long next; + long next = 0; + cdinfo(CD_DO_IOCTL, "entering CDROM_NEXT_WRITABLE\n"); if ((ret = cdrom_get_next_writable(dev, &next))) return ret; IOCTL_OUT(arg, long, next); return 0; } case CDROM_LAST_WRITTEN: { - long last; + long last = 0; + cdinfo(CD_DO_IOCTL, "entering CDROM_LAST_WRITTEN\n"); if ((ret = cdrom_get_last_written(dev, &last))) return ret; IOCTL_OUT(arg, long, last); @@ -2038,10 +2081,10 @@ int cdrom_get_last_written(kdev_t dev, long *last_written) track_information ti; __u32 last_track; int ret = -1; - + if (!CDROM_CAN(CDC_GENERIC_PACKET)) goto use_toc; - + if ((ret = cdrom_get_disc_info(dev, &di))) goto use_toc; @@ -2089,7 +2132,7 @@ int cdrom_get_next_writable(kdev_t dev, long *next_writable) track_information ti; __u16 last_track; int ret = -1; - + if (!CDROM_CAN(CDC_GENERIC_PACKET)) goto use_last_written; @@ -2125,6 +2168,58 @@ use_last_written: } } +/* return 0 if succesful and the disc can be considered writeable. */ +static int cdrom_setup_writemode(struct cdrom_device_info *cdi) +{ + struct cdrom_generic_command cgc; + write_param_page wp; + disc_information di; + track_information ti; + int ret, last_track; + + memset(&di, 0, sizeof(disc_information)); + memset(&ti, 0, sizeof(track_information)); + memset(&wp, 0, sizeof(write_param_page)); + + if ((ret = cdrom_get_disc_info(cdi->dev, &di))) + return ret; + + last_track = (di.last_track_msb << 8) | di.last_track_lsb; + if ((ret = cdrom_get_track_info(cdi->dev, last_track, 1, &ti))) + return ret; + + init_cdrom_command(&cgc, &wp, 0x3c); + if ((ret = cdrom_mode_sense(cdi, &cgc, GPMODE_WRITE_PARMS_PAGE, 0))) + return ret; + + /* sanity checks */ + if ((ti.damage && !ti.nwa_v) || ti.blank) + return 1; + + cdi->packet_size = wp.packet_size = be32_to_cpu(ti.fixed_packet_size); + cdi->nwa = ti.nwa_v ? be32_to_cpu(ti.next_writable) : 0; + wp.track_mode = ti.track_mode; + /* write_type 0 == packet/incremental writing */ + wp.write_type = 0; + + /* MODE1 or MODE2 writing */ + switch (ti.data_mode) { + case 1: wp.data_block_type = 8; break; + case 2: wp.data_block_type = 13; break; + default: return 1; + } + + if ((ret = cdrom_mode_select(cdi, &cgc))) + return ret; + + printk("%s: writeable with %s packets of %lu in length", cdi->name, + wp.fp ? "fixed" : "variable", + (unsigned long)cdi->packet_size); + printk(", nwa = %lu\n", (unsigned long)cdi->nwa); + + return 0; +} + EXPORT_SYMBOL(cdrom_get_next_writable); EXPORT_SYMBOL(cdrom_get_last_written); EXPORT_SYMBOL(cdrom_count_tracks); @@ -2385,21 +2480,18 @@ static void cdrom_sysctl_register(void) initialized = 1; } -#ifdef MODULE static void cdrom_sysctl_unregister(void) { unregister_sysctl_table(cdrom_sysctl_header); } -#endif /* endif MODULE */ #endif /* endif CONFIG_SYSCTL */ #ifdef MODULE - int init_module(void) { #ifdef CONFIG_SYSCTL cdrom_sysctl_register(); -#endif /* CONFIG_SYSCTL */ +#endif return 0; } @@ -2410,5 +2502,5 @@ void cleanup_module(void) cdrom_sysctl_unregister(); #endif /* CONFIG_SYSCTL */ } - #endif /* endif MODULE */ + diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 3e91edffd5e8..c3a8239f6749 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -117,7 +117,7 @@ else endif ifeq ($(CONFIG_COMPUTONE),y) -L_OBJS += ip2.o ip2main.o +O_OBJS += ip2.o ip2main.o else ifeq ($(CONFIG_COMPUTONE),m) M_OBJS += ip2.o ip2main.o @@ -165,7 +165,7 @@ else endif ifeq ($(CONFIG_SX),y) -L_OBJS += sx.o generic_serial.o +O_OBJS += sx.o generic_serial.o else ifeq ($(CONFIG_SX),m) M_OBJS += sx.o diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 5176f28f4e9a..57f3d719942c 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/char/pcxx.c b/drivers/char/pcxx.c index 36db3299d5a3..75f27e8305da 100644 --- a/drivers/char/pcxx.c +++ b/drivers/char/pcxx.c @@ -1589,8 +1589,8 @@ load_fep: ch->blocked_open = 0; ch->callout_termios = pcxe_callout.init_termios; ch->normal_termios = pcxe_driver.init_termios; - init_waitqueue_head(ch->open_wait); - init_waitqueue_head(ch->close_wait); + init_waitqueue_head(&ch->open_wait); + init_waitqueue_head(&ch->close_wait); ch->asyncflags = 0; } diff --git a/drivers/char/radio-cadet.c b/drivers/char/radio-cadet.c index 239a611b2277..98b66f0c28b1 100644 --- a/drivers/char/radio-cadet.c +++ b/drivers/char/radio-cadet.c @@ -39,6 +39,7 @@ struct timer_list tunertimer,rdstimer,readtimer; static __u8 rdsin=0,rdsout=0,rdsstat=0; static unsigned char rdsbuf[RDS_BUFFER]; static int cadet_lock=0; +static int cadet_probe(void); /* * Signal Strength Threshold Values diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index b25be2cd06aa..aac42d44b91a 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -28,6 +28,7 @@ #include #include +#include /* for linux/stallion.h */ #include #include #include diff --git a/drivers/i2o/Config.in b/drivers/i2o/Config.in index 3a0735c25c61..4cc286578b13 100644 --- a/drivers/i2o/Config.in +++ b/drivers/i2o/Config.in @@ -5,7 +5,9 @@ tristate 'I2O support' CONFIG_I2O dep_tristate ' I2O PCI support' CONFIG_I2O_PCI $CONFIG_I2O dep_tristate ' I2O Block OSM' CONFIG_I2O_BLOCK $CONFIG_I2O -dep_tristate ' I2O LAN OSM' CONFIG_I2O_LAN $CONFIG_I2O +if [ "$CONFIG_NET" = "y" ]; then + dep_tristate ' I2O LAN OSM' CONFIG_I2O_LAN $CONFIG_I2O +fi dep_tristate ' I2O SCSI OSM' CONFIG_I2O_SCSI $CONFIG_I2O $CONFIG_SCSI dep_tristate ' I2O /proc support' CONFIG_I2O_PROC $CONFIG_I2O diff --git a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c index 9ba70b2555d8..0bd2a172594a 100644 --- a/drivers/net/hamradio/baycom_par.c +++ b/drivers/net/hamradio/baycom_par.c @@ -572,7 +572,7 @@ module_exit(cleanup_baycompar); static int __init baycom_par_setup(char *str) { - static unsigned __initdata nr_dev = 0; + static unsigned nr_dev = 0; int ints[2]; if (nr_dev >= NR_PORTS) diff --git a/drivers/net/hamradio/soundmodem/sm.c b/drivers/net/hamradio/soundmodem/sm.c index 99d9061f98a3..6fa4aca6ba94 100644 --- a/drivers/net/hamradio/soundmodem/sm.c +++ b/drivers/net/hamradio/soundmodem/sm.c @@ -726,7 +726,7 @@ module_exit(cleanup_soundmodem); static int __init sm_setup(char *str) { - static unsigned __initdata nr_dev = 0; + static unsigned nr_dev = 0; int ints[8]; if (nr_dev >= NR_PORTS) diff --git a/drivers/net/slhc.c b/drivers/net/slhc.c index 7dc3fbf39a5d..87e498884aae 100644 --- a/drivers/net/slhc.c +++ b/drivers/net/slhc.c @@ -758,12 +758,6 @@ void __init slhc_install(void) #endif /* MODULE */ #else /* CONFIG_INET */ -EXPORT_SYMBOL(slhc_init); -EXPORT_SYMBOL(slhc_free); -EXPORT_SYMBOL(slhc_remember); -EXPORT_SYMBOL(slhc_compress); -EXPORT_SYMBOL(slhc_uncompress); -EXPORT_SYMBOL(slhc_toss); int slhc_toss(struct slcompress *comp) @@ -804,5 +798,11 @@ slhc_init(int rslots, int tslots) printk(KERN_DEBUG "Called IP function on non IP-system: slhc_init"); return NULL; } +EXPORT_SYMBOL(slhc_init); +EXPORT_SYMBOL(slhc_free); +EXPORT_SYMBOL(slhc_remember); +EXPORT_SYMBOL(slhc_compress); +EXPORT_SYMBOL(slhc_uncompress); +EXPORT_SYMBOL(slhc_toss); #endif /* CONFIG_INET */ diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 3a2ae4599b7e..7c2ff12d5a1d 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -128,6 +128,7 @@ static struct pci_fixup pci_fixups[] __initdata = { */ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_isa_dma_hangs }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, quirk_isa_dma_hangs }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, quirk_isa_dma_hangs }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, quirk_triton }, diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index 83215d11520c..5d0e54153436 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c @@ -1,7 +1,7 @@ /* $Id: atp870u.c,v 1.0 1997/05/07 15:22:00 root Exp root $ * linux/kernel/atp870u.c * - * Copyright (C) 1997 Wu Ching Chen + * Copyright (C) 1997 Wu Ching Chen * 2.1.x update (C) 1998 Krzysztof G. Baranowski * * Marcelo Tosatti : SMP fixes @@ -30,745 +30,620 @@ #include -struct proc_dir_entry proc_scsi_atp870u = { - PROC_SCSI_ATP870U, 7, "atp870u", - S_IFDIR | S_IRUGO | S_IXUGO, 2 +struct proc_dir_entry proc_scsi_atp870u = +{ + PROC_SCSI_ATP870U, 7, "atp870u", + S_IFDIR | S_IRUGO | S_IXUGO, 2 }; void mydlyu(unsigned int); + /* -static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/atp870u.c,v 1.0 1997/05/07 15:22:00 root Exp root $"; -*/ - -static unsigned char admaxu=1,host_idu[2],chip_veru[2],scam_on[2],global_map[2]; -static unsigned short int active_idu[2],wide_idu[2],sync_idu,ultra_map[2]; -static int workingu[2]={0,0}; -static Scsi_Cmnd *querequ[2][qcnt],*curr_req[2][16]; -static unsigned char devspu[2][16] = {{0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}, - {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, - 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}}; -static unsigned char dirctu[2][16],last_cmd[2],in_snd[2],in_int[2]; + * static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/atp870u.c,v 1.0 1997/05/07 15:22:00 root Exp root $"; + */ + +static unsigned char admaxu = 1, host_idu[2], chip_veru[2], scam_on[2], global_map[2]; +static unsigned short int active_idu[2], wide_idu[2], sync_idu, ultra_map[2]; +static int workingu[2] = {0, 0}; + +static Scsi_Cmnd *querequ[2][qcnt], *curr_req[2][16]; + +static unsigned char devspu[2][16] = { + {0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}, + {0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20} +}; + +static unsigned char dirctu[2][16], last_cmd[2], in_snd[2], in_int[2]; static unsigned char ata_cdbu[2][16]; -static unsigned int ioportu[2]={0,0}; -static unsigned int irqnumu[2]={0,0}; +static unsigned int ioportu[2] = {0, 0}; +static unsigned int irqnumu[2] = {0, 0}; static unsigned short int pciportu[2]; -static unsigned long prdaddru[2][16],tran_lenu[2][16],last_lenu[2][16]; +static unsigned long prdaddru[2][16], tran_lenu[2][16], last_lenu[2][16]; static unsigned char prd_tableu[2][16][1024]; static unsigned char *prd_posu[2][16]; -static unsigned char quhdu[2],quendu[2]; -static unsigned char devtypeu[2][16] = {{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; -static struct Scsi_Host * atp_host[2]={NULL,NULL}; +static unsigned char quhdu[2], quendu[2]; + +static unsigned char devtypeu[2][16] = +{ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +}; + +static struct Scsi_Host *atp_host[2] = {NULL, NULL}; static void atp870u_intr_handle(int irq, void *dev_id, struct pt_regs *regs) { - unsigned long flags; - unsigned short int tmpcip,id; - unsigned char i,j,h,tarid,lun; - unsigned char *prd; - Scsi_Cmnd *workrequ; - unsigned int workportu,tmport; - unsigned long adrcntu,k; - int errstus; - - for ( h=0; h < 2; h++ ) - { - if ( ( irq & 0x0f ) == irqnumu[h] ) - { - goto irq_numok; + unsigned long flags; + unsigned short int tmpcip, id; + unsigned char i, j, h, tarid, lun; + unsigned char *prd; + Scsi_Cmnd *workrequ; + unsigned int workportu, tmport; + unsigned long adrcntu, k; + int errstus; + + for (h = 0; h < 2; h++) { + if (irq == irqnumu[h]) { + goto irq_numok; + } } - } - return; + return; irq_numok: - in_int[h]=1; - workportu=ioportu[h]; - tmport=workportu; - - if ( workingu[h] != 0 ) - { - tmport += 0x1f; - j=inb(tmport); - tmpcip=pciportu[h]; - if ((inb(tmpcip) & 0x08) != 0) - { - tmpcip += 0x2; - while((inb(tmpcip) & 0x08) != 0); - } - tmpcip=pciportu[h]; - outb(0x00,tmpcip); - tmport -=0x08; - i=inb(tmport); - if ((j & 0x40) == 0) - { - if ((last_cmd[h] & 0x40) == 0) - { - last_cmd[h]=0xff; - } - } - else - { - last_cmd[h] |= 0x40; - } - tmport -= 0x02; - tarid=inb(tmport); - tmport += 0x02; - if ((tarid & 0x40) != 0) - { - tarid=(tarid & 0x07) | 0x08; - } - else - { - tarid &= 0x07; - } - if ( i == 0x85 ) - { - if (wide_idu[h] != 0) - { - tmport=workportu+0x1b; - j=inb(tmport) & 0x0e; - j |= 0x01; - outb(j,tmport); - } - if (((quhdu[h] != quendu[h]) || (last_cmd[h] != 0xff)) && - (in_snd[h] == 0)) - { - send_s870(h); - } - in_int[h]=0; - return; - } - if ( i == 0x21 ) - { - tmport -= 0x05; - adrcntu=0; - ((unsigned char *)&adrcntu)[2]=inb(tmport++); - ((unsigned char *)&adrcntu)[1]=inb(tmport++); - ((unsigned char *)&adrcntu)[0]=inb(tmport); - k=last_lenu[h][tarid]; - k -= adrcntu; - tran_lenu[h][tarid]= k; - last_lenu[h][tarid]=adrcntu; - tmport -= 0x04; - outb(0x41,tmport); - tmport += 0x08; - outb(0x08,tmport); - in_int[h]=0; - return ; - } - - if ((i == 0x80) || (i == 0x8f)) - { - lun=0; - tmport -= 0x07; - j=inb(tmport); - if ( j == 0x44 ) - { - tmport += 0x0d; - lun=inb(tmport) & 0x07; - } - else - { - if ( j == 0x41 ) - { + in_int[h] = 1; + workportu = ioportu[h]; + tmport = workportu; + + if (workingu[h] != 0) + { + tmport += 0x1f; + j = inb(tmport); + + tmpcip = pciportu[h]; + if ((inb(tmpcip) & 0x08) != 0) + { + tmpcip += 0x2; + while ((inb(tmpcip) & 0x08) != 0); + } + tmpcip = pciportu[h]; + outb(0x00, tmpcip); + tmport -= 0x08; + + i = inb(tmport); + if ((j & 0x40) == 0) + { + if ((last_cmd[h] & 0x40) == 0) + { + last_cmd[h] = 0xff; + } + } + else last_cmd[h] |= 0x40; + + tmport -= 0x02; + tarid = inb(tmport); tmport += 0x02; - adrcntu=0; - ((unsigned char *)&adrcntu)[2]=inb(tmport++); - ((unsigned char *)&adrcntu)[1]=inb(tmport++); - ((unsigned char *)&adrcntu)[0]=inb(tmport); - k=last_lenu[h][tarid]; - k -= adrcntu; - tran_lenu[h][tarid]= k; - last_lenu[h][tarid]=adrcntu; - tmport += 0x04; - outb(0x08,tmport); - in_int[h]=0; - return ; - } - else - { - outb(0x46,tmport); - dirctu[h][tarid]=0x00; + + if ((tarid & 0x40) != 0) { + tarid = (tarid & 0x07) | 0x08; + } else { + tarid &= 0x07; + } + if (i == 0x85) + { + if (wide_idu[h] != 0) + { + tmport = workportu + 0x1b; + j = inb(tmport) & 0x0e; + j |= 0x01; + outb(j, tmport); + } + if (((quhdu[h] != quendu[h]) || (last_cmd[h] != 0xff)) && + (in_snd[h] == 0)) + { + send_s870(h); + } + in_int[h] = 0; + return; + } + if (i == 0x21) + { + tmport -= 0x05; + adrcntu = 0; + ((unsigned char *) &adrcntu)[2] = inb(tmport++); + ((unsigned char *) &adrcntu)[1] = inb(tmport++); + ((unsigned char *) &adrcntu)[0] = inb(tmport); + k = last_lenu[h][tarid]; + k -= adrcntu; + tran_lenu[h][tarid] = k; + last_lenu[h][tarid] = adrcntu; + tmport -= 0x04; + outb(0x41, tmport); + tmport += 0x08; + outb(0x08, tmport); + in_int[h] = 0; + return; + } + if ((i == 0x80) || (i == 0x8f)) + { + lun = 0; + tmport -= 0x07; + j = inb(tmport); + if (j == 0x44) { + tmport += 0x0d; + lun = inb(tmport) & 0x07; + } else { + if (j == 0x41) + { + tmport += 0x02; + adrcntu = 0; + ((unsigned char *) &adrcntu)[2] = inb(tmport++); + ((unsigned char *) &adrcntu)[1] = inb(tmport++); + ((unsigned char *) &adrcntu)[0] = inb(tmport); + k = last_lenu[h][tarid]; + k -= adrcntu; + tran_lenu[h][tarid] = k; + last_lenu[h][tarid] = adrcntu; + tmport += 0x04; + outb(0x08, tmport); + in_int[h] = 0; + return; + } + else + { + outb(0x46, tmport); + dirctu[h][tarid] = 0x00; + tmport += 0x02; + outb(0x00, tmport++); + outb(0x00, tmport++); + outb(0x00, tmport++); + tmport += 0x03; + outb(0x08, tmport); + in_int[h] = 0; + return; + } + } + tmport = workportu + 0x10; + outb(0x45, tmport); + tmport += 0x06; + tarid = inb(tmport); + if ((tarid & 0x10) != 0) + { + tarid = (tarid & 0x07) | 0x08; + } else { + tarid &= 0x07; + } + workrequ = curr_req[h][tarid]; + tmport = workportu + 0x0f; + outb(lun, tmport); + tmport += 0x02; + outb(devspu[h][tarid], tmport++); + adrcntu = tran_lenu[h][tarid]; + k = last_lenu[h][tarid]; + outb(((unsigned char *) &k)[2], tmport++); + outb(((unsigned char *) &k)[1], tmport++); + outb(((unsigned char *) &k)[0], tmport++); + j = tarid; + if (tarid > 7) { + j = (j & 0x07) | 0x40; + } + j |= dirctu[h][tarid]; + outb(j, tmport++); + outb(0x80, tmport); + tmport = workportu + 0x1b; + j = inb(tmport) & 0x0e; + id = 1; + id = id << tarid; + if ((id & wide_idu[h]) != 0) { + j |= 0x01; + } + outb(j, tmport); + if (last_lenu[h][tarid] == 0) { + tmport = workportu + 0x18; + outb(0x08, tmport); + in_int[h] = 0; + return; + } + prd = prd_posu[h][tarid]; + while (adrcntu != 0) + { + id = ((unsigned short int *) (prd))[2]; + if (id == 0) { + k = 0x10000; + } else { + k = id; + } + if (k > adrcntu) { + ((unsigned short int *) (prd))[2] = (unsigned short int) + (k - adrcntu); + ((unsigned long *) (prd))[0] += adrcntu; + adrcntu = 0; + prd_posu[h][tarid] = prd; + } else { + adrcntu -= k; + prdaddru[h][tarid] += 0x08; + prd += 0x08; + if (adrcntu == 0) { + prd_posu[h][tarid] = prd; + } + } + } + tmpcip = pciportu[h] + 0x04; + outl(prdaddru[h][tarid], tmpcip); + tmpcip -= 0x02; + outb(0x06, tmpcip); + outb(0x00, tmpcip); + tmpcip -= 0x02; + tmport = workportu + 0x18; + if (dirctu[h][tarid] != 0) { + outb(0x08, tmport); + outb(0x01, tmpcip); + in_int[h] = 0; + return; + } + outb(0x08, tmport); + outb(0x09, tmpcip); + in_int[h] = 0; + return; + } + workrequ = curr_req[h][tarid]; + if (i == 0x42) { + errstus = 0x02; + workrequ->result = errstus; + goto go_42; + } + if (i == 0x16) + { + errstus = 0; + tmport -= 0x08; + errstus = inb(tmport); + workrequ->result = errstus; +go_42: + spin_lock_irqsave(&io_request_lock, flags); + (*workrequ->scsi_done) (workrequ); + spin_unlock_irqrestore(&io_request_lock, flags); + + curr_req[h][tarid] = 0; + workingu[h]--; + if (wide_idu[h] != 0) { + tmport = workportu + 0x1b; + j = inb(tmport) & 0x0e; + j |= 0x01; + outb(j, tmport); + } + if (((last_cmd[h] != 0xff) || (quhdu[h] != quendu[h])) && + (in_snd[h] == 0)) + { + send_s870(h); + } + in_int[h] = 0; + return; + } + if (i == 0x4f) { + i = 0x89; + } + i &= 0x0f; + if (i == 0x09) { + tmpcip = tmpcip + 4; + outl(prdaddru[h][tarid], tmpcip); + tmpcip = tmpcip - 2; + outb(0x06, tmpcip); + outb(0x00, tmpcip); + tmpcip = tmpcip - 2; + tmport = workportu + 0x10; + outb(0x41, tmport); + dirctu[h][tarid] = 0x00; + tmport += 0x08; + outb(0x08, tmport); + outb(0x09, tmpcip); + in_int[h] = 0; + return; + } + if (i == 0x08) { + tmpcip = tmpcip + 4; + outl(prdaddru[h][tarid], tmpcip); + tmpcip = tmpcip - 2; + outb(0x06, tmpcip); + outb(0x00, tmpcip); + tmpcip = tmpcip - 2; + tmport = workportu + 0x10; + outb(0x41, tmport); + tmport += 0x05; + outb((unsigned char) (inb(tmport) | 0x20), tmport); + dirctu[h][tarid] = 0x20; + tmport += 0x03; + outb(0x08, tmport); + outb(0x01, tmpcip); + in_int[h] = 0; + return; + } + tmport -= 0x07; + if (i == 0x0a) { + outb(0x30, tmport); + } else { + outb(0x46, tmport); + } + dirctu[h][tarid] = 0x00; tmport += 0x02; - outb(0x00,tmport++); - outb(0x00,tmport++); - outb(0x00,tmport++); - tmport+=0x03; - outb(0x08,tmport); - in_int[h]=0; + outb(0x00, tmport++); + outb(0x00, tmport++); + outb(0x00, tmport++); + tmport += 0x03; + outb(0x08, tmport); + in_int[h] = 0; return; - } - } - tmport=workportu + 0x10; - outb(0x45,tmport); - tmport += 0x06; - tarid=inb(tmport); - if ((tarid & 0x10) != 0) - { - tarid=(tarid & 0x07) | 0x08; - } - else - { - tarid &= 0x07; - } - workrequ=curr_req[h][tarid]; - tmport=workportu + 0x0f; - outb(lun,tmport); - tmport += 0x02; - outb(devspu[h][tarid],tmport++); - adrcntu=tran_lenu[h][tarid]; - k=last_lenu[h][tarid]; - outb(((unsigned char *)&k)[2],tmport++); - outb(((unsigned char *)&k)[1],tmport++); - outb(((unsigned char *)&k)[0],tmport++); - j=tarid; - if ( tarid > 7 ) - { - j = (j & 0x07) | 0x40; - } - j |= dirctu[h][tarid]; - outb(j,tmport++); - outb(0x80,tmport); - tmport=workportu + 0x1b; - j=inb(tmport) & 0x0e; - id=1; - id=id << tarid; - if ((id & wide_idu[h]) != 0) - { - j |= 0x01; - } - outb(j,tmport); - if ( last_lenu[h][tarid] == 0 ) - { - tmport=workportu + 0x18; - outb(0x08,tmport); - in_int[h]=0; - return ; - } - prd=prd_posu[h][tarid]; - while ( adrcntu != 0 ) - { - id=((unsigned short int *)(prd))[2]; - if ( id == 0 ) - { - k=0x10000; - } - else - { - k=id; - } - if ( k > adrcntu ) - { - ((unsigned short int *)(prd))[2] =(unsigned short int) - (k - adrcntu); - ((unsigned long *)(prd))[0] += adrcntu; - adrcntu=0; - prd_posu[h][tarid]=prd; - } - else - { - adrcntu -= k; - prdaddru[h][tarid] += 0x08; - prd += 0x08; - if ( adrcntu == 0 ) - { - prd_posu[h][tarid]=prd; - } - } - } - tmpcip=pciportu[h] + 0x04; - outl(prdaddru[h][tarid],tmpcip); - tmpcip -= 0x02; - outb(0x06,tmpcip); - outb(0x00,tmpcip); - tmpcip -= 0x02; - tmport=workportu + 0x18; - if ( dirctu[h][tarid] != 0 ) - { - outb(0x08,tmport); - outb(0x01,tmpcip); - in_int[h]=0; - return; - } - outb(0x08,tmport); - outb(0x09,tmpcip); - in_int[h]=0; - return; - } - - workrequ=curr_req[h][tarid]; - if ( i == 0x42 ) - { - errstus=0x02; - workrequ->result=errstus; - goto go_42; - } - if ( i == 0x16 ) - { - errstus=0; - tmport -= 0x08; - errstus=inb(tmport); - workrequ->result=errstus; -/* if ( errstus == 0x02 ) - { - tmport +=0x10; - if ((inb(tmport) & 0x80) != 0) - { - printk(" autosense "); - } - tmport -=0x09; - outb(0,tmport); - tmport=workportu+0x3a; - outb((unsigned char)(inb(tmport) | 0x10),tmport); - tmport -= 0x39; - - outb(0x08,tmport++); - outb(0x7f,tmport++); - outb(0x03,tmport++); - outb(0x00,tmport++); - outb(0x00,tmport++); - outb(0x00,tmport++); - outb(0x0e,tmport++); - outb(0x00,tmport); - tmport+=0x07; - outb(0x00,tmport++); - tmport++; - outb(devspu[h][workrequ->target],tmport++); - outb(0x00,tmport++); - outb(0x00,tmport++); - outb(0x0e,tmport++); - tmport+=0x03; - outb(0x09,tmport); - tmport+=0x07; - i=0; - adrcntu=(unsigned long)(&workrequ->sense_buffer[0]); -get_sens: - j=inb(tmport); - if ((j & 0x01) != 0) - { - tmport-=0x06; - (unsigned char)(((caddr_t) adrcntu)[i++])=inb(tmport); - tmport+=0x06; - goto get_sens; - } - if ((j & 0x80) == 0) - { - goto get_sens; - } - if ((j & 0x40) == 0) - { - tmport-=0x08; - i=inb(tmport); - } - tmport=workportu+0x3a; - outb((unsigned char)(inb(tmport) & 0xef),tmport); - tmport=workportu+0x01; - outb(0x2c,tmport); - tmport += 0x15; - outb(0x80,tmport); - } */ -go_42: - spin_lock_irqsave(&io_request_lock, flags); - (*workrequ->scsi_done)(workrequ); - spin_unlock_irqrestore(&io_request_lock, flags); - - curr_req[h][tarid]=0; - workingu[h]--; - if (wide_idu[h] != 0) - { - tmport=workportu+0x1b; - j=inb(tmport) & 0x0e; - j |= 0x01; - outb(j,tmport); - } - if (((last_cmd[h] != 0xff) || (quhdu[h] != quendu[h])) && - (in_snd[h] == 0)) - { - send_s870(h); - } - in_int[h]=0; - return; - } - if ( i == 0x4f ) - { - i=0x89; - } - i &= 0x0f; - if ( i == 0x09 ) - { - tmpcip=tmpcip+4; - outl(prdaddru[h][tarid],tmpcip); - tmpcip=tmpcip-2; - outb(0x06,tmpcip); - outb(0x00,tmpcip); - tmpcip=tmpcip-2; - tmport=workportu+0x10; - outb(0x41,tmport); - dirctu[h][tarid]=0x00; - tmport += 0x08; - outb(0x08,tmport); - outb(0x09,tmpcip); - in_int[h]=0; - return; - } - if ( i == 0x08 ) - { - tmpcip=tmpcip+4; - outl(prdaddru[h][tarid],tmpcip); - tmpcip=tmpcip-2; - outb(0x06,tmpcip); - outb(0x00,tmpcip); - tmpcip=tmpcip-2; - tmport=workportu+0x10; - outb(0x41,tmport); - tmport += 0x05; - outb((unsigned char)(inb(tmport) | 0x20),tmport); - dirctu[h][tarid]=0x20; - tmport += 0x03; - outb(0x08,tmport); - outb(0x01,tmpcip); - in_int[h]=0; - return; - } - tmport -= 0x07; - if ( i == 0x0a ) - { - outb(0x30,tmport); - } - else - { - outb(0x46,tmport); - } - dirctu[h][tarid]=0x00; - tmport += 0x02; - outb(0x00,tmport++); - outb(0x00,tmport++); - outb(0x00,tmport++); - tmport+=0x03; - outb(0x08,tmport); - in_int[h]=0; - return; - } - else - { - tmport=workportu+0x17; - inb(tmport); - workingu[h]=0; - in_int[h]=0; - return; - } + } else { + tmport = workportu + 0x17; + inb(tmport); + workingu[h] = 0; + in_int[h] = 0; + return; + } } -int atp870u_queuecommand(Scsi_Cmnd * req_p, void (*done)(Scsi_Cmnd *)) +int atp870u_queuecommand(Scsi_Cmnd * req_p, void (*done) (Scsi_Cmnd *)) { - unsigned char i,h; - unsigned long flags; - unsigned short int m; - unsigned int tmport; - - for( h=0; h <= admaxu; h++ ) - { - if ( req_p->host == atp_host[h] ) - { - goto host_ok; - } - } - return 0; + unsigned char i, h; + unsigned long flags; + unsigned short int m; + unsigned int tmport; + + for (h = 0; h <= admaxu; h++) { + if (req_p->host == atp_host[h]) { + goto host_ok; + } + } + return 0; host_ok: - if ( req_p->channel != 0 ) - { - req_p->result = 0x00040000; - done(req_p); - return 0; - } - m=1; - m= m << req_p->target; - if ( ( m & active_idu[h] ) == 0 ) - { - req_p->result = 0x00040000; - done(req_p); - return 0; - } - if (done) - { - req_p->scsi_done = done; - } - else - { - printk("atp870u_queuecommand: done can't be NULL\n"); - req_p->result = 0; - done(req_p); - return 0; - } - quendu[h]++; - if ( quendu[h] >= qcnt ) - { - quendu[h]=0; - } - wait_que_empty: - if ( quhdu[h] == quendu[h] ) - { - goto wait_que_empty; - } - save_flags(flags); - cli(); - querequ[h][quendu[h]]=req_p; - if ( quendu[h] == 0 ) - { - i=qcnt-1; - } - else - { - i=quendu[h]-1; - } - tmport = ioportu[h]+0x1c; - restore_flags(flags); - if ((inb(tmport) == 0) && (in_int[h] == 0) && (in_snd[h] == 0)) - { - send_s870(h); - } - return 0; + if (req_p->channel != 0) { + req_p->result = 0x00040000; + done(req_p); + return 0; + } + m = 1; + m = m << req_p->target; + if ((m & active_idu[h]) == 0) { + req_p->result = 0x00040000; + done(req_p); + return 0; + } + if (done) { + req_p->scsi_done = done; + } else { + printk("atp870u_queuecommand: done can't be NULL\n"); + req_p->result = 0; + done(req_p); + return 0; + } + quendu[h]++; + if (quendu[h] >= qcnt) { + quendu[h] = 0; + } +wait_que_empty: + if (quhdu[h] == quendu[h]) { + goto wait_que_empty; + } + save_flags(flags); + cli(); + querequ[h][quendu[h]] = req_p; + if (quendu[h] == 0) { + i = qcnt - 1; + } else { + i = quendu[h] - 1; + } + tmport = ioportu[h] + 0x1c; + restore_flags(flags); + if ((inb(tmport) == 0) && (in_int[h] == 0) && (in_snd[h] == 0)) { + send_s870(h); + } + return 0; } -void mydlyu(unsigned int dlycnt ) +void mydlyu(unsigned int dlycnt) { - unsigned int i ; - for ( i = 0 ; i < dlycnt ; i++ ) - { - inb(0x80); - } + unsigned int i; + for (i = 0; i < dlycnt; i++) { + inb(0x80); + } } void send_s870(unsigned char h) { - unsigned int tmport; - Scsi_Cmnd *workrequ; - unsigned long flags; - unsigned int i; - unsigned char j,tarid; - unsigned char *prd; - unsigned short int tmpcip,w; - unsigned long l,bttl; - unsigned int workportu; - struct scatterlist * sgpnt; + unsigned int tmport; + Scsi_Cmnd *workrequ; + unsigned long flags; + unsigned int i; + unsigned char j, tarid; + unsigned char *prd; + unsigned short int tmpcip, w; + unsigned long l, bttl; + unsigned int workportu; + struct scatterlist *sgpnt; save_flags(flags); cli(); - if ( in_snd[h] != 0 ) - { - restore_flags(flags); - return; + if (in_snd[h] != 0) { + restore_flags(flags); + return; } - in_snd[h]=1; - if ((last_cmd[h] != 0xff) && ((last_cmd[h] & 0x40) != 0)) - { - last_cmd[h] &= 0x0f; - workrequ=curr_req[h][last_cmd[h]]; - goto cmd_subp; + in_snd[h] = 1; + if ((last_cmd[h] != 0xff) && ((last_cmd[h] & 0x40) != 0)) { + last_cmd[h] &= 0x0f; + workrequ = curr_req[h][last_cmd[h]]; + goto cmd_subp; } workingu[h]++; - j=quhdu[h]; + j = quhdu[h]; quhdu[h]++; - if ( quhdu[h] >= qcnt ) - { - quhdu[h]=0; + if (quhdu[h] >= qcnt) { + quhdu[h] = 0; } - workrequ=querequ[h][quhdu[h]]; - if ( curr_req[h][workrequ->target] == 0 ) - { - curr_req[h][workrequ->target]=workrequ; - last_cmd[h]=workrequ->target; - goto cmd_subp; + workrequ = querequ[h][quhdu[h]]; + if (curr_req[h][workrequ->target] == 0) { + curr_req[h][workrequ->target] = workrequ; + last_cmd[h] = workrequ->target; + goto cmd_subp; } - quhdu[h]=j; + quhdu[h] = j; workingu[h]--; - in_snd[h]=0; + in_snd[h] = 0; restore_flags(flags); - return ; + return; cmd_subp: - workportu=ioportu[h]; - tmport=workportu+0x1f; - if ((inb(tmport) & 0xb0) != 0) - { - goto abortsnd; - } - tmport=workportu+0x1c; - if ( inb(tmport) == 0 ) - { - goto oktosend; - } + workportu = ioportu[h]; + tmport = workportu + 0x1f; + if ((inb(tmport) & 0xb0) != 0) { + goto abortsnd; + } + tmport = workportu + 0x1c; + if (inb(tmport) == 0) { + goto oktosend; + } abortsnd: - last_cmd[h] |= 0x40; - in_snd[h]=0; - restore_flags(flags); - return; -oktosend: - memcpy(&ata_cdbu[h][0], &workrequ->cmnd[0], workrequ->cmd_len); - if ( ata_cdbu[h][0] == 0x25 ) - { - if ( workrequ->request_bufflen > 8 ) - { - workrequ->request_bufflen=0x08; - } - } - if ( ata_cdbu[h][0] == 0x12 ) - { - if ( workrequ->request_bufflen > 0x24 ) - { - workrequ->request_bufflen = 0x24; - ata_cdbu[h][4]=0x24; - } - } - - tmport=workportu+0x1b; - j=inb(tmport) & 0x0e; - tarid=workrequ->target; - w=1; - w = w << tarid; - if ((w & wide_idu[h]) != 0) - { - j |= 0x01; - } - outb(j,tmport); - tmport=workportu; - outb(workrequ->cmd_len,tmport++); - outb(0x2c,tmport++); - outb(0xcf,tmport++); - for ( i=0 ; i < workrequ->cmd_len ; i++ ) - { - outb(ata_cdbu[h][i],tmport++); - } - tmport=workportu+0x0f; - outb(0x00,tmport); - tmport+=0x02; - outb(devspu[h][tarid],tmport++); - if (workrequ->use_sg) - { - - l=0; - sgpnt = (struct scatterlist *) workrequ->request_buffer; - for(i=0; iuse_sg; i++) - { - if(sgpnt[i].length == 0 || workrequ->use_sg > ATP870U_SCATTER) - { - panic("Foooooooood fight!"); - } - l += sgpnt[i].length; - } - } - else - { - l=workrequ->request_bufflen; - } - outb((unsigned char)(((unsigned char *)(&l))[2]),tmport++); - outb((unsigned char)(((unsigned char *)(&l))[1]),tmport++); - outb((unsigned char)(((unsigned char *)(&l))[0]),tmport++); - j=tarid; - last_lenu[h][j]=l; - tran_lenu[h][j]=0; - if ((j & 0x08) != 0) - { - j=(j & 0x07) | 0x40; - } - if ((ata_cdbu[h][0] == 0x0a) || (ata_cdbu[h][0] == 0x2a) || - (ata_cdbu[h][0] == 0xaa) || (ata_cdbu[h][0] == 0x15)) - { - outb((unsigned char)(j | 0x20),tmport++); - } - else - { - outb(j,tmport++); - } - outb(0x80,tmport); - tmport=workportu + 0x1c; - dirctu[h][tarid]=0; - if ( l == 0 ) - { - if ( inb(tmport) == 0 ) - { - tmport=workportu+0x18; - outb(0x08,tmport); - } - else - { last_cmd[h] |= 0x40; - } - in_snd[h]=0; - restore_flags(flags); - return; - } - tmpcip=pciportu[h]; - prd=&prd_tableu[h][tarid][0]; - prd_posu[h][tarid]=prd; - if (workrequ->use_sg) - { - sgpnt = (struct scatterlist *) workrequ->request_buffer; - i=0; - for(j=0; juse_sg; j++) - { - (unsigned long)(((unsigned long *)(prd))[i >> 1])=(unsigned long)sgpnt[j].address; - (unsigned short int)(((unsigned short int *)(prd))[i+2])=sgpnt[j].length; - (unsigned short int)(((unsigned short int *)(prd))[i+3])=0; - i +=0x04; - } - (unsigned short int)(((unsigned short int *)(prd))[i-1])=0x8000; - } - else - { - bttl=(unsigned long)workrequ->request_buffer; - l=workrequ->request_bufflen; - i=0; - while ( l > 0x10000 ) - { - (unsigned short int)(((unsigned short int *)(prd))[i+3])=0x0000; - (unsigned short int)(((unsigned short int *)(prd))[i+2])=0x0000; - (unsigned long)(((unsigned long *)(prd))[i >> 1])=bttl; - l -= 0x10000; - bttl += 0x10000; - i += 0x04; - } - (unsigned short int)(((unsigned short int *)(prd))[i+3])=0x8000; - (unsigned short int)(((unsigned short int *)(prd))[i+2])=l; - (unsigned long)(((unsigned long *)(prd))[i >> 1])=bttl; - } - tmpcip=tmpcip+4; - prdaddru[h][tarid]=(unsigned long)&prd_tableu[h][tarid][0]; - outl(prdaddru[h][tarid],tmpcip); - tmpcip=tmpcip-2; - outb(0x06,tmpcip); - outb(0x00,tmpcip); - tmpcip=tmpcip-2; - if ((ata_cdbu[h][0] == 0x0a) || (ata_cdbu[h][0] == 0x2a) || - (ata_cdbu[h][0] == 0xaa) || (ata_cdbu[h][0] == 0x15)) - { - dirctu[h][tarid]=0x20; - if ( inb(tmport) == 0 ) - { - tmport=workportu+0x18; - outb(0x08,tmport); - outb(0x01,tmpcip); - } - else - { - last_cmd[h] |= 0x40; - } - in_snd[h]=0; - restore_flags(flags); - return; - } - if ( inb(tmport) == 0 ) - { - tmport=workportu+0x18; - outb(0x08,tmport); - outb(0x09,tmpcip); - } - else - { - last_cmd[h] |= 0x40; - } - in_snd[h]=0; - restore_flags(flags); - return; + in_snd[h] = 0; + restore_flags(flags); + return; +oktosend: + memcpy(&ata_cdbu[h][0], &workrequ->cmnd[0], workrequ->cmd_len); + if (ata_cdbu[h][0] == 0x25) { + if (workrequ->request_bufflen > 8) { + workrequ->request_bufflen = 0x08; + } + } + if (ata_cdbu[h][0] == 0x12) { + if (workrequ->request_bufflen > 0x24) { + workrequ->request_bufflen = 0x24; + ata_cdbu[h][4] = 0x24; + } + } + tmport = workportu + 0x1b; + j = inb(tmport) & 0x0e; + tarid = workrequ->target; + w = 1; + w = w << tarid; + if ((w & wide_idu[h]) != 0) { + j |= 0x01; + } + outb(j, tmport); + tmport = workportu; + outb(workrequ->cmd_len, tmport++); + outb(0x2c, tmport++); + outb(0xcf, tmport++); + for (i = 0; i < workrequ->cmd_len; i++) { + outb(ata_cdbu[h][i], tmport++); + } + tmport = workportu + 0x0f; + outb(0x00, tmport); + tmport += 0x02; + outb(devspu[h][tarid], tmport++); + if (workrequ->use_sg) + { + l = 0; + sgpnt = (struct scatterlist *) workrequ->request_buffer; + for (i = 0; i < workrequ->use_sg; i++) + { + if (sgpnt[i].length == 0 || workrequ->use_sg > ATP870U_SCATTER) + { + panic("Foooooooood fight!"); + } + l += sgpnt[i].length; + } + } else { + l = workrequ->request_bufflen; + } + outb((unsigned char) (((unsigned char *) (&l))[2]), tmport++); + outb((unsigned char) (((unsigned char *) (&l))[1]), tmport++); + outb((unsigned char) (((unsigned char *) (&l))[0]), tmport++); + j = tarid; + last_lenu[h][j] = l; + tran_lenu[h][j] = 0; + if ((j & 0x08) != 0) { + j = (j & 0x07) | 0x40; + } + if ((ata_cdbu[h][0] == 0x0a) || (ata_cdbu[h][0] == 0x2a) || + (ata_cdbu[h][0] == 0xaa) || (ata_cdbu[h][0] == 0x15)) { + outb((unsigned char) (j | 0x20), tmport++); + } else { + outb(j, tmport++); + } + outb(0x80, tmport); + tmport = workportu + 0x1c; + dirctu[h][tarid] = 0; + if (l == 0) { + if (inb(tmport) == 0) { + tmport = workportu + 0x18; + outb(0x08, tmport); + } else { + last_cmd[h] |= 0x40; + } + in_snd[h] = 0; + restore_flags(flags); + return; + } + tmpcip = pciportu[h]; + prd = &prd_tableu[h][tarid][0]; + prd_posu[h][tarid] = prd; + if (workrequ->use_sg) + { + sgpnt = (struct scatterlist *) workrequ->request_buffer; + i = 0; + for (j = 0; j < workrequ->use_sg; j++) { + (unsigned long) (((unsigned long *) (prd))[i >> 1]) = virt_to_bus(sgpnt[j].address); + (unsigned short int) (((unsigned short int *) (prd))[i + 2]) = sgpnt[j].length; + (unsigned short int) (((unsigned short int *) (prd))[i + 3]) = 0; + i += 0x04; + } + (unsigned short int) (((unsigned short int *) (prd))[i - 1]) = 0x8000; + } else { + bttl = virt_to_bus(workrequ->request_buffer); + l = workrequ->request_bufflen; + i = 0; + while (l > 0x10000) { + (unsigned short int) (((unsigned short int *) (prd))[i + 3]) = 0x0000; + (unsigned short int) (((unsigned short int *) (prd))[i + 2]) = 0x0000; + (unsigned long) (((unsigned long *) (prd))[i >> 1]) = bttl; + l -= 0x10000; + bttl += 0x10000; + i += 0x04; + } + (unsigned short int) (((unsigned short int *) (prd))[i + 3]) = 0x8000; + (unsigned short int) (((unsigned short int *) (prd))[i + 2]) = l; + (unsigned long) (((unsigned long *) (prd))[i >> 1]) = bttl; + } + tmpcip = tmpcip + 4; + prdaddru[h][tarid] = virt_to_bus(&prd_tableu[h][tarid][0]); + outl(prdaddru[h][tarid], tmpcip); + tmpcip = tmpcip - 2; + outb(0x06, tmpcip); + outb(0x00, tmpcip); + tmpcip = tmpcip - 2; + if ((ata_cdbu[h][0] == 0x0a) || (ata_cdbu[h][0] == 0x2a) || + (ata_cdbu[h][0] == 0xaa) || (ata_cdbu[h][0] == 0x15)) + { + dirctu[h][tarid] = 0x20; + if (inb(tmport) == 0) { + tmport = workportu + 0x18; + outb(0x08, tmport); + outb(0x01, tmpcip); + } else { + last_cmd[h] |= 0x40; + } + in_snd[h] = 0; + restore_flags(flags); + return; + } + if (inb(tmport) == 0) + { + tmport = workportu + 0x18; + outb(0x08, tmport); + outb(0x09, tmpcip); + } else { + last_cmd[h] |= 0x40; + } + in_snd[h] = 0; + restore_flags(flags); + return; } @@ -780,1101 +655,964 @@ static void internal_done(Scsi_Cmnd * SCpnt) int atp870u_command(Scsi_Cmnd * SCpnt) { - atp870u_queuecommand(SCpnt, internal_done); + atp870u_queuecommand(SCpnt, internal_done); - SCpnt->SCp.Status = 0; - while (!SCpnt->SCp.Status) - barrier(); - return SCpnt->result; + SCpnt->SCp.Status = 0; + while (!SCpnt->SCp.Status) + barrier(); + return SCpnt->result; } -unsigned char fun_scam ( unsigned char host,unsigned short int * val ) +unsigned char fun_scam(unsigned char host, unsigned short int *val) { - unsigned int tmport ; - unsigned short int i,k; - unsigned char j; + unsigned int tmport; + unsigned short int i, k; + unsigned char j; - tmport = ioportu[host]+0x1c; - outw(*val,tmport); + tmport = ioportu[host] + 0x1c; + outw(*val, tmport); FUN_D7: - for ( i=0; i < 10; i++ ) /* stable >= bus settle delay(400 ns) */ - { - k=inw(tmport); - j= (unsigned char)(k >> 8); - if ((k & 0x8000) != 0) /* DB7 all release? */ - { - goto FUN_D7; + for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ + k = inw(tmport); + j = (unsigned char) (k >> 8); + if ((k & 0x8000) != 0) { /* DB7 all release? */ + goto FUN_D7; + } } - } - *val |= 0x4000; /* assert DB6 */ - outw(*val,tmport); - *val &= 0xdfff; /* assert DB5 */ - outw(*val,tmport); + *val |= 0x4000; /* assert DB6 */ + outw(*val, tmport); + *val &= 0xdfff; /* assert DB5 */ + outw(*val, tmport); FUN_D5: - for ( i=0; i < 10; i++ ) /* stable >= bus settle delay(400 ns) */ - { - if ((inw(tmport) & 0x2000) != 0) /* DB5 all release? */ - { - goto FUN_D5; - } - } - *val |= 0x8000; /* no DB4-0, assert DB7 */ - *val &= 0xe0ff; - outw(*val,tmport); - *val &= 0xbfff; /* release DB6 */ - outw(*val,tmport); -FUN_D6: - for ( i=0; i < 10; i++ ) /* stable >= bus settle delay(400 ns) */ - { - if ((inw(tmport) & 0x4000) != 0) /* DB6 all release? */ - { - goto FUN_D6; - } - } - - return j; + for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ + if ((inw(tmport) & 0x2000) != 0) { /* DB5 all release? */ + goto FUN_D5; + } + } + *val |= 0x8000; /* no DB4-0, assert DB7 */ + *val &= 0xe0ff; + outw(*val, tmport); + *val &= 0xbfff; /* release DB6 */ + outw(*val, tmport); + FUN_D6: + for (i = 0; i < 10; i++) { /* stable >= bus settle delay(400 ns) */ + if ((inw(tmport) & 0x4000) != 0) { /* DB6 all release? */ + goto FUN_D6; + } + } + + return j; } -void tscam( unsigned char host ) +void tscam(unsigned char host) { - unsigned int tmport ; - unsigned char i,j,k; - unsigned long n; - unsigned short int m,assignid_map,val; - unsigned char mbuf[33],quintet[2]; - static unsigned char g2q_tab[8]={ 0x38,0x31,0x32,0x2b,0x34,0x2d,0x2e,0x27 }; + unsigned int tmport; + unsigned char i, j, k; + unsigned long n; + unsigned short int m, assignid_map, val; + unsigned char mbuf[33], quintet[2]; + static unsigned char g2q_tab[8] = + {0x38, 0x31, 0x32, 0x2b, 0x34, 0x2d, 0x2e, 0x27}; - for ( i=0; i < 0x10; i++ ) - { - mydlyu(0xffff); - } - - tmport = ioportu[host]+1; - outb(0x08,tmport++); - outb(0x7f,tmport); - tmport = ioportu[host]+0x11; - outb(0x20,tmport); - - if ((scam_on[host] & 0x40) == 0) - { - return; - } - - m=1; - m <<= host_idu[host]; - j=16; - if ( chip_veru[host] < 4 ) - { - m |= 0xff00; - j=8; - } - assignid_map=m; - tmport = ioportu[host]+0x02; - outb(0x02,tmport++); /* 2*2=4ms,3EH 2/32*3E=3.9ms */ - outb(0,tmport++); - outb(0,tmport++); - outb(0,tmport++); - outb(0,tmport++); - outb(0,tmport++); - outb(0,tmport++); - - for ( i = 0 ; i < j ; i ++ ) - { - m=1; - m=m< 7 ) - { - k=(i & 0x07) | 0x40; - } - else - { - k=i; - } - outb(k,tmport++); - tmport = ioportu[host]+0x1b; - if ( chip_veru[host] == 4 ) - { - outb((unsigned char)((inb(tmport) & 0x0e) | 0x01),tmport); - } - else - { - outb((unsigned char)(inb(tmport) & 0x0e),tmport); - } + for (i = 0; i < 0x10; i++) { + mydlyu(0xffff); + } + + tmport = ioportu[host] + 1; + outb(0x08, tmport++); + outb(0x7f, tmport); + tmport = ioportu[host] + 0x11; + outb(0x20, tmport); + + if ((scam_on[host] & 0x40) == 0) { + return; + } + m = 1; + m <<= host_idu[host]; + j = 16; + if (chip_veru[host] < 4) { + m |= 0xff00; + j = 8; + } + assignid_map = m; + tmport = ioportu[host] + 0x02; + outb(0x02, tmport++); /* 2*2=4ms,3EH 2/32*3E=3.9ms */ + outb(0, tmport++); + outb(0, tmport++); + outb(0, tmport++); + outb(0, tmport++); + outb(0, tmport++); + outb(0, tmport++); + + for (i = 0; i < j; i++) { + m = 1; + m = m << i; + if ((m & assignid_map) != 0) { + continue; + } + tmport = ioportu[host] + 0x0f; + outb(0, tmport++); + tmport += 0x02; + outb(0, tmport++); + outb(0, tmport++); + outb(0, tmport++); + if (i > 7) { + k = (i & 0x07) | 0x40; + } else { + k = i; + } + outb(k, tmport++); + tmport = ioportu[host] + 0x1b; + if (chip_veru[host] == 4) { + outb((unsigned char) ((inb(tmport) & 0x0e) | 0x01), tmport); + } else { + outb((unsigned char) (inb(tmport) & 0x0e), tmport); + } wait_rdyok: - tmport = ioportu[host]+0x18; - outb(0x09,tmport); - tmport += 0x07; - - while ((inb(tmport) & 0x80) == 0x00); - tmport -= 0x08; - k=inb(tmport); - if ( k != 0x16 ) - { - if ((k == 0x85) || (k == 0x42)) - { - continue; - } - tmport = ioportu[host]+0x10; - outb(0x41,tmport); - goto wait_rdyok; - } - assignid_map |= m; - - } - tmport = ioportu[host]+0x02; - outb(0x7f,tmport); - tmport = ioportu[host]+0x1b; - outb(0x02,tmport); - - outb(0,0x80); - - val=0x0080; /* bsy */ - tmport = ioportu[host]+0x1c; - outw(val,tmport); - val |=0x0040; /* sel */ - outw(val,tmport); - val |=0x0004; /* msg */ - outw(val,tmport); - inb(0x80); /* 2 deskew delay(45ns*2=90ns) */ - val &=0x007f; /* no bsy */ - outw(val,tmport); - mydlyu(0xffff); /* recommanded SCAM selection response time */ - mydlyu(0xffff); - val &=0x00fb; /* after 1ms no msg */ - outw(val,tmport); + tmport = ioportu[host] + 0x18; + outb(0x09, tmport); + tmport += 0x07; + + while ((inb(tmport) & 0x80) == 0x00); + tmport -= 0x08; + k = inb(tmport); + if (k != 0x16) { + if ((k == 0x85) || (k == 0x42)) { + continue; + } + tmport = ioportu[host] + 0x10; + outb(0x41, tmport); + goto wait_rdyok; + } + assignid_map |= m; + + } + tmport = ioportu[host] + 0x02; + outb(0x7f, tmport); + tmport = ioportu[host] + 0x1b; + outb(0x02, tmport); + + outb(0, 0x80); + + val = 0x0080; /* bsy */ + tmport = ioportu[host] + 0x1c; + outw(val, tmport); + val |= 0x0040; /* sel */ + outw(val, tmport); + val |= 0x0004; /* msg */ + outw(val, tmport); + inb(0x80); /* 2 deskew delay(45ns*2=90ns) */ + val &= 0x007f; /* no bsy */ + outw(val, tmport); + mydlyu(0xffff); /* recommanded SCAM selection response time */ + mydlyu(0xffff); + val &= 0x00fb; /* after 1ms no msg */ + outw(val, tmport); wait_nomsg: - if ((inb(tmport) & 0x04) != 0) - { - goto wait_nomsg; - } - outb(1,0x80); - mydlyu(100); - for ( n=0; n < 0x30000; n++ ) - { - if ((inb(tmport) & 0x80) != 0) /* bsy ? */ - { - goto wait_io; + if ((inb(tmport) & 0x04) != 0) { + goto wait_nomsg; + } + outb(1, 0x80); + mydlyu(100); + for (n = 0; n < 0x30000; n++) { + if ((inb(tmport) & 0x80) != 0) { /* bsy ? */ + goto wait_io; + } } - } - goto TCM_SYNC; + goto TCM_SYNC; wait_io: - for ( n=0; n < 0x30000; n++ ) - { - if ((inb(tmport) & 0x81) == 0x0081) - { - goto wait_io1; + for (n = 0; n < 0x30000; n++) { + if ((inb(tmport) & 0x81) == 0x0081) { + goto wait_io1; + } } - } - goto TCM_SYNC; + goto TCM_SYNC; wait_io1: - inb(0x80); - val |=0x8003; /* io,cd,db7 */ - outw(val,tmport); - inb(0x80); - val &=0x00bf; /* no sel */ - outw(val,tmport); - outb(2,0x80); + inb(0x80); + val |= 0x8003; /* io,cd,db7 */ + outw(val, tmport); + inb(0x80); + val &= 0x00bf; /* no sel */ + outw(val, tmport); + outb(2, 0x80); TCM_SYNC: - mydlyu(0x800); - if ((inb(tmport) & 0x80) == 0x00) /* bsy ? */ - { - outw(0,tmport--); - outb(0,tmport); - tmport=ioportu[host] + 0x15; - outb(0,tmport); - tmport += 0x03; - outb(0x09,tmport); - tmport += 0x07; - while ((inb(tmport) & 0x80) == 0); - tmport -= 0x08; - inb(tmport); - return; - } - - val &= 0x00ff; /* synchronization */ - val |= 0x3f00; - fun_scam(host,&val); - outb(3,0x80); - val &= 0x00ff; /* isolation */ - val |= 0x2000; - fun_scam(host,&val); - outb(4,0x80); - i=8; - j=0; + mydlyu(0x800); + if ((inb(tmport) & 0x80) == 0x00) { /* bsy ? */ + outw(0, tmport--); + outb(0, tmport); + tmport = ioportu[host] + 0x15; + outb(0, tmport); + tmport += 0x03; + outb(0x09, tmport); + tmport += 0x07; + while ((inb(tmport) & 0x80) == 0); + tmport -= 0x08; + inb(tmport); + return; + } + val &= 0x00ff; /* synchronization */ + val |= 0x3f00; + fun_scam(host, &val); + outb(3, 0x80); + val &= 0x00ff; /* isolation */ + val |= 0x2000; + fun_scam(host, &val); + outb(4, 0x80); + i = 8; + j = 0; TCM_ID: - if ((inw(tmport) & 0x2000) == 0) - { - goto TCM_ID; - } - outb(5,0x80); - val &= 0x00ff; /* get ID_STRING */ - val |= 0x2000; - k=fun_scam(host,&val); - if ((k & 0x03) == 0) - { - goto TCM_5; - } - mbuf[j] <<= 0x01; - mbuf[j] &= 0xfe; - if ((k & 0x02) != 0) - { - mbuf[j] |= 0x01; - } - i--; - if ( i > 0 ) - { - goto TCM_ID; - } - j++; - i=8; - goto TCM_ID; - -TCM_5: /* isolation complete.. */ + if ((inw(tmport) & 0x2000) == 0) { + goto TCM_ID; + } + outb(5, 0x80); + val &= 0x00ff; /* get ID_STRING */ + val |= 0x2000; + k = fun_scam(host, &val); + if ((k & 0x03) == 0) { + goto TCM_5; + } + mbuf[j] <<= 0x01; + mbuf[j] &= 0xfe; + if ((k & 0x02) != 0) { + mbuf[j] |= 0x01; + } + i--; + if (i > 0) { + goto TCM_ID; + } + j++; + i = 8; + goto TCM_ID; + +TCM_5: /* isolation complete.. */ /* mbuf[32]=0; - printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */ - i=15; - j=mbuf[0]; - if ((j & 0x20) != 0) /* bit5=1:ID upto 7 */ - { - i=7; - } - if ((j & 0x06) == 0) /* IDvalid? */ - { - goto G2Q5; - } - k=mbuf[1]; + printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */ + i = 15; + j = mbuf[0]; + if ((j & 0x20) != 0) { /* bit5=1:ID upto 7 */ + i = 7; + } + if ((j & 0x06) == 0) { /* IDvalid? */ + goto G2Q5; + } + k = mbuf[1]; small_id: - m=1; - m <<= k; - if ((m & assignid_map) == 0) - { - goto G2Q_QUIN; - } - if ( k > 0 ) - { - k--; - goto small_id; - } -G2Q5: /* srch from max acceptable ID# */ - k=i; /* max acceptable ID# */ + m = 1; + m <<= k; + if ((m & assignid_map) == 0) { + goto G2Q_QUIN; + } + if (k > 0) { + k--; + goto small_id; + } +G2Q5: /* srch from max acceptable ID# */ + k = i; /* max acceptable ID# */ G2Q_LP: - m=1; - m <<= k; - if ((m & assignid_map) == 0) - { - goto G2Q_QUIN; - } - if ( k > 0 ) - { - k--; - goto G2Q_LP; - } -G2Q_QUIN: /* k=binID#, */ - assignid_map |= m; - if ( k < 8 ) - { - quintet[0]=0x38; /* 1st dft ID<8 */ - } - else - { - quintet[0]=0x31; /* 1st ID>=8 */ - } - k &= 0x07; - quintet[1]=g2q_tab[k]; - - val &= 0x00ff; /* AssignID 1stQuintet,AH=001xxxxx */ - m=quintet[0] << 8; - val |= m; - fun_scam(host,&val); - val &= 0x00ff; /* AssignID 2ndQuintet,AH=001xxxxx */ - m=quintet[1] << 8; - val |= m; - fun_scam(host,&val); - - goto TCM_SYNC; + m = 1; + m <<= k; + if ((m & assignid_map) == 0) { + goto G2Q_QUIN; + } + if (k > 0) { + k--; + goto G2Q_LP; + } +G2Q_QUIN: /* k=binID#, */ + assignid_map |= m; + if (k < 8) { + quintet[0] = 0x38; /* 1st dft ID<8 */ + } else { + quintet[0] = 0x31; /* 1st ID>=8 */ + } + k &= 0x07; + quintet[1] = g2q_tab[k]; + + val &= 0x00ff; /* AssignID 1stQuintet,AH=001xxxxx */ + m = quintet[0] << 8; + val |= m; + fun_scam(host, &val); + val &= 0x00ff; /* AssignID 2ndQuintet,AH=001xxxxx */ + m = quintet[1] << 8; + val |= m; + fun_scam(host, &val); + + goto TCM_SYNC; } -void is870(unsigned long host,unsigned int wkport ) +void is870(unsigned long host, unsigned int wkport) { - unsigned int tmport ; - unsigned char i,j,k,rmb; - unsigned short int m; - static unsigned char mbuf[512]; - static unsigned char satn[9] = { 0,0,0,0,0,0,0,6,6 }; - static unsigned char inqd[9] = { 0x12,0,0,0,0x24,0,0,0x24,6 }; - static unsigned char synn[6] = { 0x80,1,3,1,0x19,0x0e }; - static unsigned char synu[6] = { 0x80,1,3,1,0x0c,0x0e }; - static unsigned char synw[6] = { 0x80,1,3,1,0x0c,0x07 }; - static unsigned char wide[6] = { 0x80,1,2,3,1,0 }; - - sync_idu=0; - tmport=wkport+0x3a; - outb((unsigned char)(inb(tmport) | 0x10),tmport); - - for ( i = 0 ; i < 16 ; i ++ ) - { - if ((chip_veru[host] != 4) && (i > 7)) - { - break; - } - m=1; - m=m< 7)) { + break; + } + m = 1; + m = m << i; + if ((m & active_idu[host]) != 0) { + continue; + } + if (i == host_idu[host]) { + printk(" ID: %2d Host Adapter\n", host_idu[host]); + continue; + } + if (chip_veru[host] == 4) { + tmport = wkport + 0x1b; + j = (inb(tmport) & 0x0e) | 0x01; + outb(j, tmport); + } + tmport = wkport + 1; + outb(0x08, tmport++); + outb(0x7f, tmport++); + outb(satn[0], tmport++); + outb(satn[1], tmport++); + outb(satn[2], tmport++); + outb(satn[3], tmport++); + outb(satn[4], tmport++); + outb(satn[5], tmport++); + tmport += 0x06; + outb(0, tmport); + tmport += 0x02; + outb(devspu[host][i], tmport++); + outb(0, tmport++); + outb(satn[6], tmport++); + outb(satn[7], tmport++); + j = i; + if ((j & 0x08) != 0) { + j = (j & 0x07) | 0x40; + } + outb(j, tmport); + tmport += 0x03; + outb(satn[8], tmport); + tmport += 0x07; + + while ((inb(tmport) & 0x80) == 0x00); + tmport -= 0x08; + if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { + continue; + } + while (inb(tmport) != 0x8e); + active_idu[host] |= m; + + tmport = wkport + 0x10; + outb(0x30, tmport); + tmport = wkport + 0x04; + outb(0x00, tmport); phase_cmd: - tmport=wkport+0x18; - outb(0x08,tmport); - tmport+=0x07; - while ((inb(tmport) & 0x80) == 0x00); - tmport-=0x08; - j=inb(tmport); - if ( j != 0x16 ) - { - tmport=wkport+0x10; - outb(0x41,tmport); - goto phase_cmd; - } + tmport = wkport + 0x18; + outb(0x08, tmport); + tmport += 0x07; + while ((inb(tmport) & 0x80) == 0x00); + tmport -= 0x08; + j = inb(tmport); + if (j != 0x16) { + tmport = wkport + 0x10; + outb(0x41, tmport); + goto phase_cmd; + } sel_ok: - tmport=wkport+3; - outb(inqd[0],tmport++); - outb(inqd[1],tmport++); - outb(inqd[2],tmport++); - outb(inqd[3],tmport++); - outb(inqd[4],tmport++); - outb(inqd[5],tmport); - tmport+=0x07; - outb(0,tmport); - tmport+=0x02; - outb(devspu[host][i],tmport++); - outb(0,tmport++); - outb(inqd[6],tmport++); - outb(inqd[7],tmport++); - tmport+=0x03; - outb(inqd[8],tmport); - tmport+=0x07; - while ((inb(tmport) & 0x80) == 0x00); - tmport-=0x08; - if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) - { - continue; - } - while ( inb(tmport) != 0x8e ); - if ( chip_veru[host] == 4 ) - { - tmport=wkport+0x1b; - j=inb(tmport) & 0x0e; - outb(j,tmport); - } - tmport=wkport+0x18; - outb(0x08,tmport); - tmport += 0x07; - j=0; + tmport = wkport + 3; + outb(inqd[0], tmport++); + outb(inqd[1], tmport++); + outb(inqd[2], tmport++); + outb(inqd[3], tmport++); + outb(inqd[4], tmport++); + outb(inqd[5], tmport); + tmport += 0x07; + outb(0, tmport); + tmport += 0x02; + outb(devspu[host][i], tmport++); + outb(0, tmport++); + outb(inqd[6], tmport++); + outb(inqd[7], tmport++); + tmport += 0x03; + outb(inqd[8], tmport); + tmport += 0x07; + while ((inb(tmport) & 0x80) == 0x00); + tmport -= 0x08; + if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { + continue; + } + while (inb(tmport) != 0x8e); + if (chip_veru[host] == 4) { + tmport = wkport + 0x1b; + j = inb(tmport) & 0x0e; + outb(j, tmport); + } + tmport = wkport + 0x18; + outb(0x08, tmport); + tmport += 0x07; + j = 0; rd_inq_data: - k=inb(tmport); - if ((k & 0x01) != 0 ) - { - tmport-=0x06; - mbuf[j++]=inb(tmport); - tmport+=0x06; - goto rd_inq_data; - } - if ((k & 0x80) == 0 ) - { - goto rd_inq_data; - } - tmport-=0x08; - j=inb(tmport); - if ( j == 0x16 ) - { - goto inq_ok; - } - tmport=wkport+0x10; - outb(0x46,tmport); - tmport+=0x02; - outb(0,tmport++); - outb(0,tmport++); - outb(0,tmport++); - tmport+=0x03; - outb(0x08,tmport); - tmport+=0x07; - while ((inb(tmport) & 0x80) == 0x00); - tmport-=0x08; - if (inb(tmport) != 0x16) - { - goto sel_ok; - } + k = inb(tmport); + if ((k & 0x01) != 0) { + tmport -= 0x06; + mbuf[j++] = inb(tmport); + tmport += 0x06; + goto rd_inq_data; + } + if ((k & 0x80) == 0) { + goto rd_inq_data; + } + tmport -= 0x08; + j = inb(tmport); + if (j == 0x16) { + goto inq_ok; + } + tmport = wkport + 0x10; + outb(0x46, tmport); + tmport += 0x02; + outb(0, tmport++); + outb(0, tmport++); + outb(0, tmport++); + tmport += 0x03; + outb(0x08, tmport); + tmport += 0x07; + while ((inb(tmport) & 0x80) == 0x00); + tmport -= 0x08; + if (inb(tmport) != 0x16) { + goto sel_ok; + } inq_ok: - mbuf[36]=0; - printk(" ID: %2d %s\n",i,&mbuf[8]); - devtypeu[host][i]=mbuf[0]; - rmb=mbuf[1]; - if ( chip_veru[host] != 4 ) - { - goto not_wide; - } - if ((mbuf[7] & 0x60) == 0) - { - goto not_wide; - } - if ((global_map[host] & 0x20) == 0) - { - goto not_wide; - } - tmport=wkport+0x1b; - j=(inb(tmport) & 0x0e) | 0x01; - outb(j,tmport); - tmport=wkport+3; - outb(satn[0],tmport++); - outb(satn[1],tmport++); - outb(satn[2],tmport++); - outb(satn[3],tmport++); - outb(satn[4],tmport++); - outb(satn[5],tmport++); - tmport+=0x06; - outb(0,tmport); - tmport+=0x02; - outb(devspu[host][i],tmport++); - outb(0,tmport++); - outb(satn[6],tmport++); - outb(satn[7],tmport++); - tmport+=0x03; - outb(satn[8],tmport); - tmport+=0x07; - - while ((inb(tmport) & 0x80) == 0x00); - tmport-=0x08; - if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) - { - continue; - } - while ( inb(tmport) != 0x8e ); + mbuf[36] = 0; + printk(" ID: %2d %s\n", i, &mbuf[8]); + devtypeu[host][i] = mbuf[0]; + rmb = mbuf[1]; + if (chip_veru[host] != 4) { + goto not_wide; + } + if ((mbuf[7] & 0x60) == 0) { + goto not_wide; + } + if ((global_map[host] & 0x20) == 0) { + goto not_wide; + } + tmport = wkport + 0x1b; + j = (inb(tmport) & 0x0e) | 0x01; + outb(j, tmport); + tmport = wkport + 3; + outb(satn[0], tmport++); + outb(satn[1], tmport++); + outb(satn[2], tmport++); + outb(satn[3], tmport++); + outb(satn[4], tmport++); + outb(satn[5], tmport++); + tmport += 0x06; + outb(0, tmport); + tmport += 0x02; + outb(devspu[host][i], tmport++); + outb(0, tmport++); + outb(satn[6], tmport++); + outb(satn[7], tmport++); + tmport += 0x03; + outb(satn[8], tmport); + tmport += 0x07; + + while ((inb(tmport) & 0x80) == 0x00); + tmport -= 0x08; + if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { + continue; + } + while (inb(tmport) != 0x8e); try_wide: - j=0; - tmport=wkport+0x14; - outb(0x05,tmport); - tmport += 0x04; - outb(0x20,tmport); - tmport+=0x07; - - while ((inb(tmport) & 0x80) == 0 ) - { - if ((inb(tmport) & 0x01) != 0 ) - { - tmport-=0x06; - outb(wide[j++],tmport); - tmport+=0x06; - } - } - tmport-=0x08; - while ((inb(tmport) & 0x80) == 0x00); - j=inb(tmport) & 0x0f; - if ( j == 0x0f ) - { - goto widep_in; - } - if ( j == 0x0a ) - { - goto widep_cmd; - } - if ( j == 0x0e ) - { - goto try_wide; - } - continue; + j = 0; + tmport = wkport + 0x14; + outb(0x05, tmport); + tmport += 0x04; + outb(0x20, tmport); + tmport += 0x07; + + while ((inb(tmport) & 0x80) == 0) { + if ((inb(tmport) & 0x01) != 0) { + tmport -= 0x06; + outb(wide[j++], tmport); + tmport += 0x06; + } + } + tmport -= 0x08; + while ((inb(tmport) & 0x80) == 0x00); + j = inb(tmport) & 0x0f; + if (j == 0x0f) { + goto widep_in; + } + if (j == 0x0a) { + goto widep_cmd; + } + if (j == 0x0e) { + goto try_wide; + } + continue; widep_out: - tmport=wkport+0x18; - outb(0x20,tmport); - tmport+=0x07; - while ((inb(tmport) & 0x80) == 0 ) - { - if ((inb(tmport) & 0x01) != 0 ) - { - tmport-=0x06; - outb(0,tmport); - tmport+=0x06; - } - } - tmport-=0x08; - j=inb(tmport) & 0x0f; - if ( j == 0x0f ) - { - goto widep_in; - } - if ( j == 0x0a ) - { - goto widep_cmd; - } - if ( j == 0x0e ) - { - goto widep_out; - } - continue; + tmport = wkport + 0x18; + outb(0x20, tmport); + tmport += 0x07; + while ((inb(tmport) & 0x80) == 0) { + if ((inb(tmport) & 0x01) != 0) { + tmport -= 0x06; + outb(0, tmport); + tmport += 0x06; + } + } + tmport -= 0x08; + j = inb(tmport) & 0x0f; + if (j == 0x0f) { + goto widep_in; + } + if (j == 0x0a) { + goto widep_cmd; + } + if (j == 0x0e) { + goto widep_out; + } + continue; widep_in: - tmport=wkport+0x14; - outb(0xff,tmport); - tmport += 0x04; - outb(0x20,tmport); - tmport+=0x07; - k=0; + tmport = wkport + 0x14; + outb(0xff, tmport); + tmport += 0x04; + outb(0x20, tmport); + tmport += 0x07; + k = 0; widep_in1: - j=inb(tmport); - if ((j & 0x01) != 0) - { - tmport-=0x06; - mbuf[k++]=inb(tmport); - tmport+=0x06; - goto widep_in1; - } - if ((j & 0x80) == 0x00) - { - goto widep_in1; - } - tmport-=0x08; - j=inb(tmport) & 0x0f; - if ( j == 0x0f ) - { - goto widep_in; - } - if ( j == 0x0a ) - { - goto widep_cmd; - } - if ( j == 0x0e ) - { - goto widep_out; - } - continue; + j = inb(tmport); + if ((j & 0x01) != 0) { + tmport -= 0x06; + mbuf[k++] = inb(tmport); + tmport += 0x06; + goto widep_in1; + } + if ((j & 0x80) == 0x00) { + goto widep_in1; + } + tmport -= 0x08; + j = inb(tmport) & 0x0f; + if (j == 0x0f) { + goto widep_in; + } + if (j == 0x0a) { + goto widep_cmd; + } + if (j == 0x0e) { + goto widep_out; + } + continue; widep_cmd: - tmport=wkport+0x10; - outb(0x30,tmport); - tmport=wkport+0x14; - outb(0x00,tmport); - tmport+=0x04; - outb(0x08,tmport); - tmport+=0x07; - while ((inb(tmport) & 0x80) == 0x00); - tmport-=0x08; - j=inb(tmport); - if ( j != 0x16 ) - { - if ( j == 0x4e ) - { - goto widep_out; - } - continue; - } - if ( mbuf[0] != 0x01 ) - { - goto not_wide; - } - if ( mbuf[1] != 0x02 ) - { - goto not_wide; - } - if ( mbuf[2] != 0x03 ) - { - goto not_wide; - } - if ( mbuf[3] != 0x01 ) - { - goto not_wide; - } - m=1; - m = m << i; - wide_idu[host] |= m; + tmport = wkport + 0x10; + outb(0x30, tmport); + tmport = wkport + 0x14; + outb(0x00, tmport); + tmport += 0x04; + outb(0x08, tmport); + tmport += 0x07; + while ((inb(tmport) & 0x80) == 0x00); + tmport -= 0x08; + j = inb(tmport); + if (j != 0x16) { + if (j == 0x4e) { + goto widep_out; + } + continue; + } + if (mbuf[0] != 0x01) { + goto not_wide; + } + if (mbuf[1] != 0x02) { + goto not_wide; + } + if (mbuf[2] != 0x03) { + goto not_wide; + } + if (mbuf[3] != 0x01) { + goto not_wide; + } + m = 1; + m = m << i; + wide_idu[host] |= m; not_wide: - if ((devtypeu[host][i] == 0x00) || (devtypeu[host][i] == 0x07)) - { - goto set_sync; - } - continue; + if ((devtypeu[host][i] == 0x00) || (devtypeu[host][i] == 0x07)) { + goto set_sync; + } + continue; set_sync: - tmport=wkport+0x1b; - j=inb(tmport) & 0x0e; - if ((m & wide_idu[host]) != 0 ) - { - j |= 0x01; - } - outb(j,tmport); - tmport=wkport+3; - outb(satn[0],tmport++); - outb(satn[1],tmport++); - outb(satn[2],tmport++); - outb(satn[3],tmport++); - outb(satn[4],tmport++); - outb(satn[5],tmport++); - tmport+=0x06; - outb(0,tmport); - tmport+=0x02; - outb(devspu[host][i],tmport++); - outb(0,tmport++); - outb(satn[6],tmport++); - outb(satn[7],tmport++); - tmport+=0x03; - outb(satn[8],tmport); - tmport+=0x07; - - while ((inb(tmport) & 0x80) == 0x00); - tmport-=0x08; - if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) - { - continue; - } - while ( inb(tmport) != 0x8e); + tmport = wkport + 0x1b; + j = inb(tmport) & 0x0e; + if ((m & wide_idu[host]) != 0) { + j |= 0x01; + } + outb(j, tmport); + tmport = wkport + 3; + outb(satn[0], tmport++); + outb(satn[1], tmport++); + outb(satn[2], tmport++); + outb(satn[3], tmport++); + outb(satn[4], tmport++); + outb(satn[5], tmport++); + tmport += 0x06; + outb(0, tmport); + tmport += 0x02; + outb(devspu[host][i], tmport++); + outb(0, tmport++); + outb(satn[6], tmport++); + outb(satn[7], tmport++); + tmport += 0x03; + outb(satn[8], tmport); + tmport += 0x07; + + while ((inb(tmport) & 0x80) == 0x00); + tmport -= 0x08; + if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) { + continue; + } + while (inb(tmport) != 0x8e); try_sync: - j=0; - tmport=wkport+0x14; - outb(0x06,tmport); - tmport += 0x04; - outb(0x20,tmport); - tmport+=0x07; - - while ((inb(tmport) & 0x80) == 0 ) - { - if ((inb(tmport) & 0x01) != 0 ) - { - tmport-=0x06; - if ( rmb != 0 ) - { - outb(synn[j++],tmport); - } - else - { - if ((m & wide_idu[host]) != 0) - { - outb(synw[j++],tmport); - } - else - { - if ((m & ultra_map[host]) != 0) - { - outb(synu[j++],tmport); + j = 0; + tmport = wkport + 0x14; + outb(0x06, tmport); + tmport += 0x04; + outb(0x20, tmport); + tmport += 0x07; + + while ((inb(tmport) & 0x80) == 0) { + if ((inb(tmport) & 0x01) != 0) { + tmport -= 0x06; + if (rmb != 0) { + outb(synn[j++], tmport); + } else { + if ((m & wide_idu[host]) != 0) { + outb(synw[j++], tmport); + } else { + if ((m & ultra_map[host]) != 0) { + outb(synu[j++], tmport); + } else { + outb(synn[j++], tmport); + } + } + } + tmport += 0x06; + } } - else - { - outb(synn[j++],tmport); - } - } - } - tmport+=0x06; - } - } - tmport-=0x08; - while ((inb(tmport) & 0x80) == 0x00); - j=inb(tmport) & 0x0f; - if ( j == 0x0f ) - { - goto phase_ins; - } - if ( j == 0x0a ) - { - goto phase_cmds; - } - if ( j == 0x0e ) - { - goto try_sync; - } - continue; + tmport -= 0x08; + while ((inb(tmport) & 0x80) == 0x00); + j = inb(tmport) & 0x0f; + if (j == 0x0f) { + goto phase_ins; + } + if (j == 0x0a) { + goto phase_cmds; + } + if (j == 0x0e) { + goto try_sync; + } + continue; phase_outs: - tmport=wkport+0x18; - outb(0x20,tmport); - tmport+=0x07; - while ((inb(tmport) & 0x80) == 0x00) - { - if ((inb(tmport) & 0x01) != 0x00) - { - tmport-=0x06; - outb(0x00,tmport); - tmport+=0x06; - } - } - tmport-=0x08; - j=inb(tmport); - if ( j == 0x85 ) - { - goto tar_dcons; - } - j &= 0x0f; - if ( j == 0x0f ) - { - goto phase_ins; - } - if ( j == 0x0a ) - { - goto phase_cmds; - } - if ( j == 0x0e ) - { - goto phase_outs; - } - continue; + tmport = wkport + 0x18; + outb(0x20, tmport); + tmport += 0x07; + while ((inb(tmport) & 0x80) == 0x00) { + if ((inb(tmport) & 0x01) != 0x00) { + tmport -= 0x06; + outb(0x00, tmport); + tmport += 0x06; + } + } + tmport -= 0x08; + j = inb(tmport); + if (j == 0x85) { + goto tar_dcons; + } + j &= 0x0f; + if (j == 0x0f) { + goto phase_ins; + } + if (j == 0x0a) { + goto phase_cmds; + } + if (j == 0x0e) { + goto phase_outs; + } + continue; phase_ins: - tmport=wkport+0x14; - outb(0xff,tmport); - tmport += 0x04; - outb(0x20,tmport); - tmport+=0x07; - k=0; + tmport = wkport + 0x14; + outb(0xff, tmport); + tmport += 0x04; + outb(0x20, tmport); + tmport += 0x07; + k = 0; phase_ins1: - j=inb(tmport); - if ((j & 0x01) != 0x00) - { - tmport-=0x06; - mbuf[k++]=inb(tmport); - tmport+=0x06; - goto phase_ins1; - } - if ((j & 0x80) == 0x00) - { - goto phase_ins1; - } - tmport-=0x08; - while ((inb(tmport) & 0x80) == 0x00); - j=inb(tmport); - if ( j == 0x85 ) - { - goto tar_dcons; - } - j &= 0x0f; - if ( j == 0x0f ) - { - goto phase_ins; - } - if ( j == 0x0a ) - { - goto phase_cmds; - } - if ( j == 0x0e ) - { - goto phase_outs; - } - continue; + j = inb(tmport); + if ((j & 0x01) != 0x00) { + tmport -= 0x06; + mbuf[k++] = inb(tmport); + tmport += 0x06; + goto phase_ins1; + } + if ((j & 0x80) == 0x00) { + goto phase_ins1; + } + tmport -= 0x08; + while ((inb(tmport) & 0x80) == 0x00); + j = inb(tmport); + if (j == 0x85) { + goto tar_dcons; + } + j &= 0x0f; + if (j == 0x0f) { + goto phase_ins; + } + if (j == 0x0a) { + goto phase_cmds; + } + if (j == 0x0e) { + goto phase_outs; + } + continue; phase_cmds: - tmport=wkport+0x10; - outb(0x30,tmport); + tmport = wkport + 0x10; + outb(0x30, tmport); tar_dcons: - tmport=wkport+0x14; - outb(0x00,tmport); - tmport+=0x04; - outb(0x08,tmport); - tmport+=0x07; - while ((inb(tmport) & 0x80) == 0x00); - tmport-=0x08; - j=inb(tmport); - if ( j != 0x16 ) - { - continue; - } - if ( mbuf[0] != 0x01 ) - { - continue; - } - if ( mbuf[1] != 0x03 ) - { - continue; - } - if ( mbuf[4] == 0x00 ) - { - continue; - } - if ( mbuf[3] > 0x64 ) - { - continue; - } - if ( mbuf[4] > 0x0c ) - { - mbuf[4]=0x0c; - } - devspu[host][i] = mbuf[4]; - if ((mbuf[3] < 0x0d) && (rmb == 0)) - { - j=0xa0; - goto set_syn_ok; - } - if ( mbuf[3] < 0x1a ) - { - j=0x20; - goto set_syn_ok; - } - if ( mbuf[3] < 0x33 ) - { - j=0x40; - goto set_syn_ok; - } - if ( mbuf[3] < 0x4c ) - { - j=0x50; - goto set_syn_ok; - } - j=0x60; -set_syn_ok: - devspu[host][i] = (devspu[host][i] & 0x0f) | j; - } - tmport=wkport+0x3a; - outb((unsigned char)(inb(tmport) & 0xef),tmport); + tmport = wkport + 0x14; + outb(0x00, tmport); + tmport += 0x04; + outb(0x08, tmport); + tmport += 0x07; + while ((inb(tmport) & 0x80) == 0x00); + tmport -= 0x08; + j = inb(tmport); + if (j != 0x16) { + continue; + } + if (mbuf[0] != 0x01) { + continue; + } + if (mbuf[1] != 0x03) { + continue; + } + if (mbuf[4] == 0x00) { + continue; + } + if (mbuf[3] > 0x64) { + continue; + } + if (mbuf[4] > 0x0c) { + mbuf[4] = 0x0c; + } + devspu[host][i] = mbuf[4]; + if ((mbuf[3] < 0x0d) && (rmb == 0)) { + j = 0xa0; + goto set_syn_ok; + } + if (mbuf[3] < 0x1a) { + j = 0x20; + goto set_syn_ok; + } + if (mbuf[3] < 0x33) { + j = 0x40; + goto set_syn_ok; + } + if (mbuf[3] < 0x4c) { + j = 0x50; + goto set_syn_ok; + } + j = 0x60; + set_syn_ok: + devspu[host][i] = (devspu[host][i] & 0x0f) | j; + } + tmport = wkport + 0x3a; + outb((unsigned char) (inb(tmport) & 0xef), tmport); } /* return non-zero on detection */ int atp870u_detect(Scsi_Host_Template * tpnt) { - unsigned char irq,h,k; - unsigned long flags; - unsigned int base_io,error,tmport; - unsigned short index = 0; - unsigned char pci_bus[3], pci_device_fn[3], chip_ver[3],host_id; - struct Scsi_Host * shpnt = NULL; - int count = 0; - static unsigned short devid[7]={0x8002,0x8010,0x8020,0x8030,0x8040,0x8050,0}; - static struct pci_dev *pdev = NULL, *acard_pdev[3]; - - printk("aec671x_detect: \n"); - if (!pci_present()) - { - printk(" NO BIOS32 SUPPORT.\n"); - return count; - } - - tpnt->proc_dir = &proc_scsi_atp870u; - - for ( h = 0 ; h < 2 ; h++ ) - { - active_idu[h]=0; - wide_idu[h]=0; - host_idu[h]=0x07; - quhdu[h]=0; - quendu[h]=0; - pci_bus[h]=0; - pci_device_fn[h]=0xff; - chip_ver[h]=0; - last_cmd[h]=0xff; - in_snd[h]=0; - in_int[h]=0; - for ( k = 0 ; k < qcnt ; k++ ) - { - querequ[h][k]=0; - } - for ( k = 0 ; k < 16 ; k++ ) - { - curr_req[h][k]=0; - } - } - h=0; - while ( devid[h] != 0 ) - { - pdev = pci_find_device(0x1191,devid[h],pdev); - if (pdev == NULL) { - h++; - index=0; - continue; - } - chip_ver[2]=0; - - /* To avoid messing with the things below... */ - acard_pdev[2] = pdev; - pci_device_fn[2] = pdev->devfn; - pci_bus[2] = pdev->bus->number; - - if ( devid[h] == 0x8002 ) - { - error = pci_read_config_byte(pdev,0x08,&chip_ver[2]); - if ( chip_ver[2] < 2 ) - { - goto nxt_devfn; - } - } - if ( devid[h] == 0x8010 ) - { - chip_ver[2]=0x04; - } - if ( pci_device_fn[2] < pci_device_fn[0] ) - { - acard_pdev[1]=acard_pdev[0]; - pci_bus[1]=pci_bus[0]; - pci_device_fn[1]=pci_device_fn[0]; - chip_ver[1]=chip_ver[0]; - acard_pdev[0]=acard_pdev[2]; - pci_bus[0]=pci_bus[2]; - pci_device_fn[0]=pci_device_fn[2]; - chip_ver[0]=chip_ver[2]; - } - else if ( pci_device_fn[2] < pci_device_fn[1] ) - { - acard_pdev[1]=acard_pdev[2]; - pci_bus[1]=pci_bus[2]; - pci_device_fn[1]=pci_device_fn[2]; - chip_ver[1]=chip_ver[2]; - } -nxt_devfn: - index++; - if ( index > 3 ) - { - index=0; - h++; - } - } - for ( h=0; h < 2; h++ ) - { - if ( pci_device_fn[h] == 0xff ) - { - return count; - } - - pdev = acard_pdev[h]; - pdev->devfn = pci_device_fn[h]; - pdev->bus->number = pci_bus[h]; - - /* Found an atp870u/w. */ - error = pci_read_config_dword(pdev,0x10,&base_io); - error += pci_read_config_byte(pdev,0x3c,&irq); - error += pci_read_config_byte(pdev,0x49,&host_id); - - base_io &= 0xfffffff8; - printk(" ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d IO:%x, IRQ:%d.\n" - ,h,base_io,irq); - ioportu[h]=base_io; - pciportu[h]=base_io + 0x20; - irqnumu[h]=irq; - host_id &= 0x07; - host_idu[h]=host_id; - chip_veru[h]=chip_ver[h]; - - tmport=base_io+0x22; - scam_on[h]=inb(tmport); - tmport += 0x0b; - global_map[h]=inb(tmport++); - ultra_map[h]=inw(tmport); - if ( ultra_map[h] == 0 ) - { - scam_on[h]=0x00; - global_map[h]=0x20; - ultra_map[h]=0xffff; - } - - shpnt = scsi_register(tpnt,4); - - save_flags(flags); - cli(); - if (request_irq(irq,atp870u_intr_handle, 0, "atp870u", NULL)) - { - printk("Unable to allocate IRQ for Acard controller.\n"); - goto unregister; - } - - tmport=base_io+0x3a; - k=(inb(tmport) & 0xf3) | 0x10; - outb(k,tmport); - outb((k & 0xdf),tmport); - mydlyu(0x8000); - outb(k,tmport); - mydlyu(0x8000); - tmport=base_io; - outb((host_id | 0x08),tmport); - tmport += 0x18; - outb(0,tmport); - tmport += 0x07; - while ((inb(tmport) & 0x80) == 0); - tmport -= 0x08; - inb(tmport); - tmport = base_io +1; - outb(8,tmport++); - outb(0x7f,tmport); - tmport = base_io + 0x11; - outb(0x20,tmport); - - tscam(h); - is870(h,base_io); - tmport=base_io+0x3a; - outb((inb(tmport) & 0xef),tmport); - - atp_host[h] = shpnt; - if ( chip_ver[h] == 4 ) - { - shpnt->max_id = 16; - } - shpnt->this_id = host_id; - shpnt->unique_id = base_io; - shpnt->io_port = base_io; - shpnt->n_io_port = 0x40; /* Number of bytes of I/O space used */ - shpnt->irq = irq; - restore_flags(flags); - request_region(base_io, 0x40,"atp870u"); /* Register the IO ports that we use */ - count++; - index++; - continue; + unsigned char irq, h, k; + unsigned long flags; + unsigned int base_io, error, tmport; + unsigned short index = 0; + unsigned char pci_bus[3], pci_device_fn[3], chip_ver[3], host_id; + struct Scsi_Host *shpnt = NULL; + int count = 0; + static unsigned short devid[7] = + {0x8002, 0x8010, 0x8020, 0x8030, 0x8040, 0x8050, 0}; + static struct pci_dev *pdev = NULL, *acard_pdev[3]; + + printk("aec671x_detect: \n"); + if (!pci_present()) { + printk(" NO BIOS32 SUPPORT.\n"); + return count; + } + tpnt->proc_dir = &proc_scsi_atp870u; + + for (h = 0; h < 2; h++) { + active_idu[h] = 0; + wide_idu[h] = 0; + host_idu[h] = 0x07; + quhdu[h] = 0; + quendu[h] = 0; + pci_bus[h] = 0; + pci_device_fn[h] = 0xff; + chip_ver[h] = 0; + last_cmd[h] = 0xff; + in_snd[h] = 0; + in_int[h] = 0; + for (k = 0; k < qcnt; k++) { + querequ[h][k] = 0; + } + for (k = 0; k < 16; k++) { + curr_req[h][k] = 0; + } + } + h = 0; + while (devid[h] != 0) { + pdev = pci_find_device(0x1191, devid[h], pdev); + if (pdev == NULL) { + h++; + index = 0; + continue; + } + chip_ver[2] = 0; + + /* To avoid messing with the things below... */ + acard_pdev[2] = pdev; + pci_device_fn[2] = pdev->devfn; + pci_bus[2] = pdev->bus->number; + + if (devid[h] == 0x8002) { + error = pci_read_config_byte(pdev, 0x08, &chip_ver[2]); + if (chip_ver[2] < 2) { + goto nxt_devfn; + } + } + if (devid[h] == 0x8010) { + chip_ver[2] = 0x04; + } + if (pci_device_fn[2] < pci_device_fn[0]) { + acard_pdev[1] = acard_pdev[0]; + pci_bus[1] = pci_bus[0]; + pci_device_fn[1] = pci_device_fn[0]; + chip_ver[1] = chip_ver[0]; + acard_pdev[0] = acard_pdev[2]; + pci_bus[0] = pci_bus[2]; + pci_device_fn[0] = pci_device_fn[2]; + chip_ver[0] = chip_ver[2]; + } else if (pci_device_fn[2] < pci_device_fn[1]) { + acard_pdev[1] = acard_pdev[2]; + pci_bus[1] = pci_bus[2]; + pci_device_fn[1] = pci_device_fn[2]; + chip_ver[1] = chip_ver[2]; + } + nxt_devfn: + index++; + if (index > 3) { + index = 0; + h++; + } + } + for (h = 0; h < 2; h++) { + if (pci_device_fn[h] == 0xff) { + return count; + } + pdev = acard_pdev[h]; + pdev->devfn = pci_device_fn[h]; + pdev->bus->number = pci_bus[h]; + + /* Found an atp870u/w. */ + error = pci_read_config_dword(pdev, 0x10, &base_io); + error += pci_read_config_byte(pdev, 0x3c, &irq); + error += pci_read_config_byte(pdev, 0x49, &host_id); + + base_io &= 0xfffffff8; + printk(" ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d IO:%x, IRQ:%d.\n" + ,h, base_io, irq); + ioportu[h] = base_io; + pciportu[h] = base_io + 0x20; + irqnumu[h] = irq; + host_id &= 0x07; + host_idu[h] = host_id; + chip_veru[h] = chip_ver[h]; + + tmport = base_io + 0x22; + scam_on[h] = inb(tmport); + tmport += 0x0b; + global_map[h] = inb(tmport++); + ultra_map[h] = inw(tmport); + if (ultra_map[h] == 0) { + scam_on[h] = 0x00; + global_map[h] = 0x20; + ultra_map[h] = 0xffff; + } + shpnt = scsi_register(tpnt, 4); + + save_flags(flags); + cli(); + if (request_irq(irq, atp870u_intr_handle, 0, "atp870u", NULL)) { + printk("Unable to allocate IRQ for Acard controller.\n"); + goto unregister; + } + tmport = base_io + 0x3a; + k = (inb(tmport) & 0xf3) | 0x10; + outb(k, tmport); + outb((k & 0xdf), tmport); + mydlyu(0x8000); + outb(k, tmport); + mydlyu(0x8000); + tmport = base_io; + outb((host_id | 0x08), tmport); + tmport += 0x18; + outb(0, tmport); + tmport += 0x07; + while ((inb(tmport) & 0x80) == 0); + tmport -= 0x08; + inb(tmport); + tmport = base_io + 1; + outb(8, tmport++); + outb(0x7f, tmport); + tmport = base_io + 0x11; + outb(0x20, tmport); + + tscam(h); + is870(h, base_io); + tmport = base_io + 0x3a; + outb((inb(tmport) & 0xef), tmport); + + atp_host[h] = shpnt; + if (chip_ver[h] == 4) { + shpnt->max_id = 16; + } + shpnt->this_id = host_id; + shpnt->unique_id = base_io; + shpnt->io_port = base_io; + shpnt->n_io_port = 0x40; /* Number of bytes of I/O space used */ + shpnt->irq = irq; + restore_flags(flags); + request_region(base_io, 0x40, "atp870u"); /* Register the IO ports that we use */ + count++; + index++; + continue; unregister: - scsi_unregister(shpnt); - restore_flags(flags); - index++; - continue; - } + scsi_unregister(shpnt); + restore_flags(flags); + index++; + continue; + } - return count; + return count; } /* The abort command does not leave the device in a clean state where @@ -1883,162 +1621,147 @@ unregister: int atp870u_abort(Scsi_Cmnd * SCpnt) { - unsigned char h,j; - unsigned int tmport; + unsigned char h, j; + unsigned int tmport; /* printk(" atp870u_abort: \n"); */ - for ( h=0; h <= admaxu; h++ ) - { - if ( SCpnt->host == atp_host[h] ) - { - goto find_adp; + for (h = 0; h <= admaxu; h++) { + if (SCpnt->host == atp_host[h]) { + goto find_adp; + } } - } - panic("Abort host not found !"); + panic("Abort host not found !"); find_adp: - printk(" workingu=%x last_cmd=%x ",workingu[h],last_cmd[h]); - printk(" quhdu=%x quendu=%x ",quhdu[h],quendu[h]); - tmport=ioportu[h]; - for ( j=0; j < 0x17; j++) - { - printk(" r%2x=%2x",j,inb(tmport++)); - } - tmport += 0x05; - printk(" r1c=%2x",inb(tmport)); - tmport += 0x03; - printk(" r1f=%2x in_snd=%2x ",inb(tmport),in_snd[h]); - tmport++; - printk(" r20=%2x",inb(tmport)); - tmport += 0x02; - printk(" r22=%2x \n",inb(tmport)); - return (SCSI_ABORT_SNOOZE); + printk(" workingu=%x last_cmd=%x ", workingu[h], last_cmd[h]); + printk(" quhdu=%x quendu=%x ", quhdu[h], quendu[h]); + tmport = ioportu[h]; + for (j = 0; j < 0x17; j++) { + printk(" r%2x=%2x", j, inb(tmport++)); + } + tmport += 0x05; + printk(" r1c=%2x", inb(tmport)); + tmport += 0x03; + printk(" r1f=%2x in_snd=%2x ", inb(tmport), in_snd[h]); + tmport++; + printk(" r20=%2x", inb(tmport)); + tmport += 0x02; + printk(" r22=%2x \n", inb(tmport)); + return (SCSI_ABORT_SNOOZE); } int atp870u_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) { - unsigned char h; - /* - * See if a bus reset was suggested. - */ -/* printk("atp870u_reset: \n"); */ - for( h=0; h <= admaxu; h++ ) - { - if ( SCpnt->host == atp_host[h] ) - { - goto find_host; - } - } - panic("Reset bus host not found !"); + unsigned char h; + /* + * See if a bus reset was suggested. + */ +/* printk("atp870u_reset: \n"); */ + for (h = 0; h <= admaxu; h++) { + if (SCpnt->host == atp_host[h]) { + goto find_host; + } + } + panic("Reset bus host not found !"); find_host: -/* SCpnt->result = 0x00080000; - SCpnt->scsi_done(SCpnt); - workingu[h]=0; - quhdu[h]=0; - quendu[h]=0; - return (SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET); */ - return (SCSI_RESET_SNOOZE); +/* SCpnt->result = 0x00080000; + SCpnt->scsi_done(SCpnt); + workingu[h]=0; + quhdu[h]=0; + quendu[h]=0; + return (SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET); */ + return (SCSI_RESET_SNOOZE); } -const char * -atp870u_info(struct Scsi_Host *notused) +const char *atp870u_info(struct Scsi_Host *notused) { - static char buffer[128]; + static char buffer[128]; - strcpy(buffer, "ACARD AEC-6710/6712 PCI Ultra/W SCSI-3 Adapter Driver V1.0 "); + strcpy(buffer, "ACARD AEC-6710/6712 PCI Ultra/W SCSI-3 Adapter Driver V1.0 "); - return buffer; + return buffer; } -int -atp870u_set_info(char *buffer, int length, struct Scsi_Host *HBAptr) +int atp870u_set_info(char *buffer, int length, struct Scsi_Host *HBAptr) { - return (-ENOSYS); /* Currently this is a no-op */ + return (-ENOSYS); /* Currently this is a no-op */ } #define BLS buffer + len + size -int -atp870u_proc_info(char *buffer, char **start, off_t offset, int length, - int hostno, int inout) +int atp870u_proc_info(char *buffer, char **start, off_t offset, int length, + int hostno, int inout) { - struct Scsi_Host *HBAptr; - static u8 buff[512]; - int i; - int size = 0; - int len = 0; - off_t begin = 0; - off_t pos = 0; - - HBAptr = NULL; - for (i = 0; i < 2; i++) - { - if ((HBAptr = atp_host[i]) != NULL) - { - if (HBAptr->host_no == hostno) - { - break; - } - HBAptr = NULL; - } - } - - if (HBAptr == NULL) - { - size += sprintf(BLS, "Can't find adapter for host number %d\n", hostno); - len += size; pos = begin + len; size = 0; - goto stop_output; - } - - if (inout == TRUE) /* Has data been written to the file? */ - { - return (atp870u_set_info(buffer, length, HBAptr)); - } - - if (offset == 0) - { - memset(buff, 0, sizeof(buff)); - } - - size += sprintf(BLS, "ACARD AEC-671X Driver Version: 1.0\n"); - len += size; pos = begin + len; size = 0; - - size += sprintf(BLS, "\n"); - size += sprintf(BLS, "Adapter Configuration:\n"); - size += sprintf(BLS, " Base IO: %#.4lx\n", HBAptr->io_port); - size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq); - len += size; pos = begin + len; size = 0; - -stop_output: - *start = buffer + (offset - begin); /* Start of wanted data */ - len -= (offset - begin); /* Start slop */ - if (len > length) - { - len = length; /* Ending slop */ - } - - return (len); + struct Scsi_Host *HBAptr; + static u8 buff[512]; + int i; + int size = 0; + int len = 0; + off_t begin = 0; + off_t pos = 0; + + HBAptr = NULL; + for (i = 0; i < 2; i++) { + if ((HBAptr = atp_host[i]) != NULL) { + if (HBAptr->host_no == hostno) { + break; + } + HBAptr = NULL; + } + } + + if (HBAptr == NULL) { + size += sprintf(BLS, "Can't find adapter for host number %d\n", hostno); + len += size; + pos = begin + len; + size = 0; + goto stop_output; + } + if (inout == TRUE) { /* Has data been written to the file? */ + return (atp870u_set_info(buffer, length, HBAptr)); + } + if (offset == 0) { + memset(buff, 0, sizeof(buff)); + } + size += sprintf(BLS, "ACARD AEC-671X Driver Version: 1.0\n"); + len += size; + pos = begin + len; + size = 0; + + size += sprintf(BLS, "\n"); + size += sprintf(BLS, "Adapter Configuration:\n"); + size += sprintf(BLS, " Base IO: %#.4lx\n", HBAptr->io_port); + size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq); + len += size; + pos = begin + len; + size = 0; + + stop_output: + *start = buffer + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); /* Start slop */ + if (len > length) { + len = length; /* Ending slop */ + } + return (len); } #include "sd.h" -int atp870u_biosparam(Scsi_Disk * disk, kdev_t dev, int * ip) +int atp870u_biosparam(Scsi_Disk * disk, kdev_t dev, int *ip) { - int heads, sectors, cylinders; + int heads, sectors, cylinders; - heads = 64; - sectors = 32; - cylinders = disk->capacity / (heads * sectors); + heads = 64; + sectors = 32; + cylinders = disk->capacity / (heads * sectors); - if ( cylinders > 1024 ) - { - heads = 255; - sectors = 63; - cylinders = disk->capacity / (heads * sectors); - } - - ip[0] = heads; - ip[1] = sectors; - ip[2] = cylinders; + if (cylinders > 1024) { + heads = 255; + sectors = 63; + cylinders = disk->capacity / (heads * sectors); + } + ip[0] = heads; + ip[1] = sectors; + ip[2] = cylinders; - return 0; + return 0; } #ifdef MODULE @@ -2046,4 +1769,3 @@ Scsi_Host_Template driver_template = ATP870U; #include "scsi_module.c" #endif - diff --git a/drivers/scsi/atp870u.h b/drivers/scsi/atp870u.h index 64cb56b9e877..83698d4c7b24 100644 --- a/drivers/scsi/atp870u.h +++ b/drivers/scsi/atp870u.h @@ -1,7 +1,7 @@ #ifndef _ATP870U_H /* $Id: atp870u.h,v 1.0 1997/05/07 15:09:00 root Exp root $ - * + * Header file for the ACARD 870U/W driver for Linux * * $Log: atp870u.h,v $ @@ -20,10 +20,10 @@ int atp870u_detect(Scsi_Host_Template *); int atp870u_command(Scsi_Cmnd *); -int atp870u_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +int atp870u_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); int atp870u_abort(Scsi_Cmnd *); int atp870u_reset(Scsi_Cmnd *, unsigned int); -int atp870u_biosparam(Disk *, kdev_t, int*); +int atp870u_biosparam(Disk *, kdev_t, int *); void send_s870(unsigned char); #define qcnt 32 @@ -31,7 +31,7 @@ void send_s870(unsigned char); #define ATP870U_CMDLUN 1 #ifndef NULL - #define NULL 0 +#define NULL 0 #endif extern struct proc_dir_entry proc_scsi_atp870u; diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index b89f39c8fd24..78328d5ee5b3 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -299,11 +299,6 @@ static void idescsi_end_request (byte uptodate, ide_hwgroup_t *hwgroup) scsi->pc = NULL; } -static inline unsigned long get_timeout(idescsi_pc_t *pc) -{ - return IDE_MAX(WAIT_CMD, pc->timeout - jiffies); -} - /* * Our interrupt handler. */ @@ -364,7 +359,8 @@ static void idescsi_pc_intr (ide_drive_t *drive) pc->actually_transferred += temp; pc->current_position += temp; idescsi_discard_data (drive,bcount - temp); - ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc)); + drive->timeout = IDE_MAX(WAIT_CMD, pc->timeout - jiffies); + ide_set_handler(drive, &idescsi_pc_intr); return; } #if IDESCSI_DEBUG_LOG @@ -388,7 +384,8 @@ static void idescsi_pc_intr (ide_drive_t *drive) pc->actually_transferred+=bcount; /* Update the current position */ pc->current_position+=bcount; - ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc)); /* And set the interrupt handler again */ + drive->timeout = IDE_MAX(WAIT_CMD, pc->timeout - jiffies); + ide_set_handler(drive, &idescsi_pc_intr); /* And set the interrupt handler again */ } static void idescsi_transfer_pc (ide_drive_t *drive) @@ -407,7 +404,8 @@ static void idescsi_transfer_pc (ide_drive_t *drive) ide_do_reset (drive); return; } - ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc)); /* Set the interrupt routine */ + drive->timeout = IDE_MAX(WAIT_CMD, pc->timeout - jiffies); + ide_set_handler(drive, &idescsi_pc_intr); /* Set the interrupt routine */ atapi_output_bytes (drive, scsi->pc->c, 12); /* Send the actual packet */ } @@ -441,7 +439,8 @@ static void idescsi_issue_pc (ide_drive_t *drive, idescsi_pc_t *pc) (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); } if (test_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags)) { - ide_set_handler (drive, &idescsi_transfer_pc, get_timeout(pc)); + drive->timeout = IDE_MAX(WAIT_CMD, pc->timeout - jiffies); + ide_set_handler (drive, &idescsi_transfer_pc); OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ } else { OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); @@ -488,7 +487,7 @@ static void idescsi_add_settings(ide_drive_t *drive) /* * drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function */ - ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_SHORT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); + ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); ide_add_setting(drive, "transform", SETTING_RW, -1, -1, TYPE_INT, 0, 3, 1, 1, &scsi->transform, NULL); diff --git a/drivers/scsi/inia100.h b/drivers/scsi/inia100.h index 51d63a589d8a..3486897ee13e 100644 --- a/drivers/scsi/inia100.h +++ b/drivers/scsi/inia100.h @@ -349,8 +349,8 @@ typedef struct orc_scb { /* Scsi_Ctrl_Blk */ #define ORC_BUSDEVRST 0x01 /* SCSI Bus Device Reset */ /* Status of ORCSCB_Status */ -#define SCB_COMPLETE 0x00 /* SCB request completed */ -#define SCB_POST 0x01 /* SCB is posted by the HOST */ +#define ORCSCB_COMPLETE 0x00 /* SCB request completed */ +#define ORCSCB_POST 0x01 /* SCB is posted by the HOST */ /* Bit Definition for ORCSCB_Flags */ #define SCF_DISINT 0x01 /* Disable HOST interrupt */ diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 450fc370e4aa..3a422e6bc611 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -1840,10 +1840,10 @@ ips_next(ips_ha_t *ha) { } if ((scb->scsi_cmd->request.cmd == READ) && (SC->request_bufflen)) - scb->dcdb.cmd_attribute |= DATA_IN; + scb->dcdb.cmd_attribute |= IPS_DATA_IN; if ((scb->scsi_cmd->request.cmd == WRITE) && (SC->request_bufflen)) - scb->dcdb.cmd_attribute |= DATA_OUT; + scb->dcdb.cmd_attribute |= IPS_DATA_OUT; if (scb->data_len >= IPS_MAX_XFER) { scb->dcdb.cmd_attribute |= TRANSFER_64K; @@ -2274,10 +2274,10 @@ ips_done(ips_ha_t *ha, ips_scb_t *scb) { } if ((scb->scsi_cmd->request.cmd == READ) && (scb->data_len)) - scb->dcdb.cmd_attribute |= DATA_IN; + scb->dcdb.cmd_attribute |= IPS_DATA_IN; if ((scb->scsi_cmd->request.cmd == WRITE) && (scb->data_len)) - scb->dcdb.cmd_attribute |= DATA_OUT; + scb->dcdb.cmd_attribute |= IPS_DATA_OUT; if (scb->data_len >= IPS_MAX_XFER) { scb->dcdb.cmd_attribute |= TRANSFER_64K; diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h index a4244234afb0..791b144d738c 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h @@ -237,8 +237,8 @@ #define NO_DISCONNECT 0x00 #define DISCONNECT_ALLOWED 0x80 #define NO_AUTO_REQUEST_SENSE 0x40 - #define DATA_IN 0x01 - #define DATA_OUT 0x02 + #define IPS_DATA_IN 0x01 + #define IPS_DATA_OUT 0x02 #define TRANSFER_64K 0x08 #define NOTIMEOUT 0x00 #define TIMEOUT10 0x10 diff --git a/drivers/scsi/u14-34f.h b/drivers/scsi/u14-34f.h index 381e718d8659..ff49b56ead8d 100644 --- a/drivers/scsi/u14-34f.h +++ b/drivers/scsi/u14-34f.h @@ -18,7 +18,9 @@ int u14_34f_biosparam(Disk *, kdev_t, int *); #define U14_34F_VERSION "5.11.00" +#ifndef LinuxVersionCode #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) +#endif #define ULTRASTOR_14_34F { \ name: "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \ diff --git a/drivers/sound/maestro.c b/drivers/sound/maestro.c index f64554deefb1..07c1dc7b358f 100644 --- a/drivers/sound/maestro.c +++ b/drivers/sound/maestro.c @@ -847,7 +847,7 @@ static void maestro_write(struct ess_state *ess, u16 reg, u16 data) __maestro_write(ess->card,reg,data); - spin_unlock_irqrestore(&card->lock,flags); + spin_unlock_irqrestore(&ess->card->lock,flags); } static u16 __maestro_read(struct ess_card *card, u16 reg) diff --git a/drivers/sound/sound_core.c b/drivers/sound/sound_core.c index 8e31dfe1274b..ede422a46806 100644 --- a/drivers/sound/sound_core.c +++ b/drivers/sound/sound_core.c @@ -58,6 +58,9 @@ extern int msnd_classic_init(void); #ifdef CONFIG_SOUND_MSNDPIN extern int msnd_pinnacle_init(void); #endif +#ifdef CONFIG_SOUND_CMPCI +extern init_cmpci(void); +#endif /* * Low level list operator. Scan the ordered list, find a hole and diff --git a/drivers/usb/cpia.c b/drivers/usb/cpia.c index 02df6145596b..976ab02da812 100644 --- a/drivers/usb/cpia.c +++ b/drivers/usb/cpia.c @@ -356,7 +356,7 @@ goto error; int i; int y, u, y1, v, r, g, b; - /* We want atleast 2 bytes for the length */ + /* We want at least 2 bytes for the length */ if (scratch_left(data) < 2) goto out; @@ -536,8 +536,9 @@ static int cpia_compress_isochronous(struct usb_cpia *cpia, struct usb_isoc_desc return totlen; } -static int cpia_isoc_irq(int status, void *__buffer, int len, void *dev_id) +static int cpia_isoc_irq(int status, void *__buffer, int len, void *isocdesc) { + void *dev_id = ((struct usb_isoc_desc *)isocdesc)->context; struct usb_cpia *cpia = (struct usb_cpia *)dev_id; struct cpia_sbuf *sbuf; int i; @@ -584,6 +585,12 @@ static int cpia_init_isoc(struct usb_cpia *cpia) cpia->cursbuf = 0; cpia->scratchlen = 0; + /* Alternate interface 3 is is the biggest frame size */ + if (usb_set_interface(cpia->dev, 1, 3) < 0) { + printk("usb_set_interface error\n"); + return -EBUSY; + } + /* We double buffer the Iso lists */ err = usb_init_isoc(dev, usb_rcvisocpipe(dev, 1), FRAMES_PER_DESC, cpia, &cpia->sbuf[0].isodesc); @@ -618,7 +625,7 @@ static int cpia_init_isoc(struct usb_cpia *cpia) for (fx = 0; fx < FRAMES_PER_DESC; fx++) id->frames[fx].frame_length = FRAME_SIZE_PER_DESC; - /* and the desc. [1] */ + /* and for desc. [1] */ id = cpia->sbuf[1].isodesc; id->start_type = 0; /* will follow the first desc. */ id->callback_frames = 10; /* on every 10th frame */ @@ -628,17 +635,16 @@ static int cpia_init_isoc(struct usb_cpia *cpia) for (fx = 0; fx < FRAMES_PER_DESC; fx++) id->frames[fx].frame_length = FRAME_SIZE_PER_DESC; - usb_run_isoc(cpia->sbuf[0].isodesc, NULL); - usb_run_isoc(cpia->sbuf[1].isodesc, cpia->sbuf[0].isodesc); + err = usb_run_isoc(cpia->sbuf[0].isodesc, NULL); + if (err) + printk(KERN_ERR "CPiA USB driver error (%d) on usb_run_isoc\n", err); + err = usb_run_isoc(cpia->sbuf[1].isodesc, cpia->sbuf[0].isodesc); + if (err) + printk(KERN_ERR "CPiA USB driver error (%d) on usb_run_isoc\n", err); #ifdef CPIA_DEBUG printk("done scheduling\n"); #endif - /* Alternate interface 3 is is the biggest frame size */ - if (usb_set_interface(cpia->dev, 1, 3) < 0) { - printk("usb_set_interface error\n"); - return -EBUSY; - } #if 0 if (usb_cpia_grab_frame(dev, 120) < 0) { @@ -915,11 +921,8 @@ static int cpia_ioctl(struct video_device *dev, unsigned int cmd, void *arg) p.brightness = 180 << 8; /* XXX */ p.contrast = 192 << 8; /* XXX */ p.whiteness = 105 << 8; /* XXX */ -#if 0 p.depth = 24; -#endif - p.depth = 16; - p.palette = VIDEO_PALETTE_YUYV; + p.palette = VIDEO_PALETTE_RGB24; if (copy_to_user(arg, &p, sizeof(p))) return -EFAULT; @@ -940,6 +943,8 @@ static int cpia_ioctl(struct video_device *dev, unsigned int cmd, void *arg) #ifdef CPIA_DEBUG printk("Attempting to set palette %d, depth %d\n", p.palette, p.depth); + printk("SPICT: brightness=%d, hue=%d, colour=%d, contrast=%d, whiteness=%d\n", + p.brightness, p.hue, p.colour, p.contrast, p.whiteness); #endif return 0; @@ -1009,7 +1014,6 @@ static int cpia_ioctl(struct video_device *dev, unsigned int cmd, void *arg) { struct video_mmap vm; - if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm))) return -EFAULT; @@ -1090,11 +1094,26 @@ printk("back from sleeping\n"); return cpia_new_frame(cpia, -1); } + case VIDIOCGFBUF: + { + struct video_buffer vb; + +#ifdef CPIA_DEBUG + printk("GFBUF\n"); +#endif + + memset(&vb, 0, sizeof(vb)); + vb.base = NULL; /* frame buffer not supported, not used */ + + if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb))) + return -EFAULT; + + return 0; + } case VIDIOCKEY: return 0; case VIDIOCCAPTURE: return -EINVAL; - case VIDIOCGFBUF: case VIDIOCSFBUF: return -EINVAL; case VIDIOCGTUNER: @@ -1333,4 +1352,3 @@ void cleanup_module(void) usb_cpia_cleanup(); } #endif - diff --git a/drivers/usb/hp_scanner.c b/drivers/usb/hp_scanner.c index e69d8f63e37f..1da9f605a38b 100644 --- a/drivers/usb/hp_scanner.c +++ b/drivers/usb/hp_scanner.c @@ -192,7 +192,7 @@ read_scanner(struct file * file, char * buffer, if (partial) { count = this_read = partial; - } else if (result == USB_ST_TIMEOUT || result == 15) { + } else if (result == USB_ST_TIMEOUT || result == 15) { /* FIXME: 15 ??? */ if(!maxretry--) { printk(KERN_DEBUG "read_scanner: maxretry timeout\n"); return -ETIME; diff --git a/drivers/usb/inits.h b/drivers/usb/inits.h index 1d9acb1a4995..b3b45f59aa55 100644 --- a/drivers/usb/inits.h +++ b/drivers/usb/inits.h @@ -1,13 +1,14 @@ -int usb_kbd_init(void); +int usb_acm_init(void); int usb_audio_init(void); int usb_hub_init(void); -int usb_acm_init(void); -int usb_printer_init(void); void usb_hub_cleanup(void); +int usb_kbd_init(void); +void usb_major_init(void); void usb_mouse_cleanup(void); -int usb_scsi_init(void); int usb_hp_scanner_init(void); void usb_hp_scanner_cleanup(void); +int usb_printer_init(void); int proc_usb_init (void); void proc_usb_cleanup (void); +int usb_scsi_init(void); int usb_serial_init (void); diff --git a/drivers/usb/uhci.c b/drivers/usb/uhci.c index 57cf20ff6d7e..c08feee15ba0 100644 --- a/drivers/usb/uhci.c +++ b/drivers/usb/uhci.c @@ -91,7 +91,7 @@ static int uhci_kill_isoc (struct usb_isoc_desc *isocdesc); /* * Map status to standard result codes * - * is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status) + * is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status)] * is True for output TDs and False for input TDs. */ static int uhci_map_status(int status, int dir_out) @@ -145,27 +145,22 @@ static int uhci_td_result(struct uhci_device *dev, struct uhci_td *td, unsigned do { status = uhci_status_bits(tmp->status); - if (status) - break; -#if 0 - if (debug) { + if (status) { + if (debug) { /* Must reset the toggle on first error */ - if (uhci_debug) { + if (uhci_debug) printk(KERN_DEBUG "Set toggle from %x rval %ld\n", (unsigned int)tmp, rval ? *rval : 0); - } usb_settoggle(dev->usb, uhci_endpoint(tmp->info), uhci_packetout(tmp->info) ^ 1, uhci_toggle(tmp->info)); break; } - } else { - if (rval && ((tmp->info & 0xFF) == USB_PID_IN)) - *rval += uhci_actual_length(tmp->status); } -#endif + /* The length field is only valid if the TD was completed */ + if (!status) if (!(tmp->status & TD_CTRL_ACTIVE) && uhci_packetin(tmp->info)) { bytesreceived += uhci_actual_length(tmp->status); if (rval) @@ -190,12 +185,13 @@ static int uhci_td_result(struct uhci_device *dev, struct uhci_td *td, unsigned if (!status) return USB_ST_NOERROR; - /* XXX FIXME APC BackUPS Pro kludge */ + /* APC BackUPS Pro kludge */ /* It tries to send all of the descriptor instead of */ /* the amount we requested */ if (tmp->status & TD_CTRL_IOC && tmp->status & TD_CTRL_ACTIVE && - tmp->status & TD_CTRL_NAK /* && its a control TD */) + tmp->status & TD_CTRL_NAK && + tmp->pipetype == PIPE_CONTROL) return USB_ST_NOERROR; #if 0 @@ -208,8 +204,7 @@ static int uhci_td_result(struct uhci_device *dev, struct uhci_td *td, unsigned /* If this wasn't the last TD and SPD is set, ACTIVE */ /* is not and NAK isn't then we received a short */ /* packet */ - if (tmp->status & TD_CTRL_SPD && - !(tmp->status & TD_CTRL_NAK)) + if (tmp->status & TD_CTRL_SPD && !(tmp->status & TD_CTRL_NAK)) return USB_ST_NOERROR; } @@ -516,7 +511,7 @@ static void uhci_remove_irq_list(struct uhci_td *td) * bit set. Maybe it could be extended to handle the QH's also, * but it doesn't seem necessary right now. * The layout looks as follows: - * frame list pointer -> iso td's (if any) -> + * frame list pointer -> iso td's (if any) -> * periodic interrupt td (if framelist 0) -> irq qh -> control qh -> bulk qh */ @@ -532,7 +527,7 @@ static void uhci_add_frame_list(struct uhci *uhci, struct uhci_td *td, unsigned td->backptr = &uhci->fl->frame[framenum]; td->link = uhci->fl->frame[framenum]; if (!(td->link & (UHCI_PTR_TERM | UHCI_PTR_QH))) { - nexttd = (struct uhci_td *)bus_to_virt(td->link & ~15); + nexttd = (struct uhci_td *)uhci_ptr_to_virt(td->link); nexttd->backptr = &td->link; } wmb(); @@ -550,7 +545,7 @@ static void uhci_remove_frame_list(struct uhci *uhci, struct uhci_td *td) spin_lock_irqsave(&framelist_lock, flags); *(td->backptr) = td->link; if (!(td->link & (UHCI_PTR_TERM | UHCI_PTR_QH))) { - nexttd = (struct uhci_td *)bus_to_virt(td->link & ~15); + nexttd = (struct uhci_td *)uhci_ptr_to_virt(td->link); nexttd->backptr = td->backptr; } spin_unlock_irqrestore(&framelist_lock, flags); @@ -568,7 +563,7 @@ static void uhci_remove_frame_list(struct uhci *uhci, struct uhci_td *td) unsigned frn = inw(uhci->io_addr + USBFRNUM); __u32 link = uhci->fl->frame[frn % UHCI_NUMFRAMES]; if (!(link & (UHCI_PTR_TERM | UHCI_PTR_QH))) { - struct uhci_td *tdl = (struct uhci_td *)bus_to_virt(link & ~15); + struct uhci_td *tdl = (struct uhci_td *)uhci_ptr_to_virt(link); for (;;) { if (tdl == td) { printk(KERN_WARNING "uhci_remove_frame_list: td possibly still in use!!\n"); @@ -576,9 +571,9 @@ static void uhci_remove_frame_list(struct uhci *uhci, struct uhci_td *td) } if (tdl->link & (UHCI_PTR_TERM | UHCI_PTR_QH)) break; - tdl = (struct uhci_td *)bus_to_virt(tdl->link & ~15); + tdl = (struct uhci_td *)uhci_ptr_to_virt(tdl->link); } - } + } } } @@ -603,6 +598,7 @@ static void uhci_remove_transfer(struct uhci_td *td, char removeirq) /* Remove it from the skeleton */ uhci_remove_qh(td->qh->skel, td->qh); uhci_qh_free(td->qh); + do { nextlink = curtd->link; @@ -612,10 +608,11 @@ static void uhci_remove_transfer(struct uhci_td *td, char removeirq) uhci_remove_td(curtd); uhci_td_free(curtd); + if (nextlink & UHCI_PTR_TERM) /* Tail? */ break; - curtd = bus_to_virt(nextlink & ~UHCI_PTR_BITS); + curtd = (struct uhci_td *)uhci_ptr_to_virt(nextlink); if (!--maxcount) { printk(KERN_ERR "runaway td's!?\n"); break; @@ -624,7 +621,7 @@ static void uhci_remove_transfer(struct uhci_td *td, char removeirq) } /* - * Request a interrupt handler.. + * Request an interrupt handler.. * * Returns 0 (success) or negative (failure). * Also returns/sets a "handle pointer" that release_irq can use to stop this @@ -665,9 +662,8 @@ static int uhci_request_irq(struct usb_device *usb_dev, unsigned int pipe, td->bandwidth_alloc = bustime; /* if period 0, set _REMOVE flag */ - if (period == 0) { + if (!period) td->flags |= UHCI_TD_REMOVE; - } qh->skel = &dev->uhci->skelqh[__interval_to_skel(period)]; @@ -690,7 +686,7 @@ static int uhci_request_irq(struct usb_device *usb_dev, unsigned int pipe, * * This function can NOT be called from an interrupt. */ -int uhci_release_irq(struct usb_device *usb, void *handle) +static int uhci_release_irq(struct usb_device *usb, void *handle) { struct uhci_td *td; struct uhci_qh *qh; @@ -699,12 +695,13 @@ int uhci_release_irq(struct usb_device *usb, void *handle) if (!td) return USB_ST_INTERNALERROR; + qh = td->qh; + /* Remove it from the internal irq_list */ uhci_remove_irq_list(td); /* Remove the interrupt TD and QH */ uhci_remove_td(td); - qh = td->qh; uhci_remove_qh(qh->skel, qh); if (td->completed != NULL) @@ -744,7 +741,7 @@ static int uhci_get_current_frame_number(struct usb_device *usb_dev) */ static int uhci_init_isoc (struct usb_device *usb_dev, unsigned int pipe, - int frame_count, /* bandwidth % = 100 * this / 1000 */ + int frame_count, /* bandwidth % = 100 * this / 1024 */ void *context, struct usb_isoc_desc **isocdesc) { @@ -896,7 +893,7 @@ static int uhci_run_isoc (struct usb_isoc_desc *isocdesc, } } /* end START_RELATIVE */ else - if (isocdesc->start_type == START_ABSOLUTE) { /* within the scope of cur_frame */ + if (isocdesc->start_type == START_ABSOLUTE) { /* within the scope of cur_frame */ ix = USB_WRAP_FRAMENR(isocdesc->start_frame - cur_frame); if (ix < START_FRAME_FUDGE || /* too small */ ix > CAN_SCHEDULE_FRAMES) { /* too large */ @@ -999,6 +996,7 @@ static int uhci_run_isoc (struct usb_isoc_desc *isocdesc, td->completed = isocdesc->callback_fn; uhci_add_irq_list(dev->uhci, td, isocdesc->callback_fn, isocdesc); /* TBD: D.K. ??? */ } + return 0; } /* end uhci_run_isoc */ @@ -1028,6 +1026,7 @@ static int uhci_kill_isoc (struct usb_isoc_desc *isocdesc) } for (ix = 0, td = isocdesc->td; ix < isocdesc->frame_count; ix++, td++) { + /* Deactivate and unlink */ uhci_remove_frame_list(uhci, td); td->status &= ~(TD_CTRL_ACTIVE | TD_CTRL_IOC); } /* end for ix */ @@ -1044,9 +1043,9 @@ static void uhci_free_isoc (struct usb_isoc_desc *isocdesc) if (isocdesc->start_frame >= 0) uhci_kill_isoc(isocdesc); - /* Remove all td's from the IRQ list. */ - for(i = 0; i < isocdesc->frame_count; i++) - uhci_remove_irq_list(((struct uhci_td *)(isocdesc->td))+i); + /* Remove all TD's from the IRQ list. */ + for (i = 0; i < isocdesc->frame_count; i++) + uhci_remove_irq_list(((struct uhci_td *)isocdesc->td) + i); /* Free the associate memory. */ if (isocdesc->td) @@ -1137,7 +1136,8 @@ static int uhci_run_control(struct uhci_device *dev, struct uhci_td *first, stru * there is no restriction on length of transfers * anymore */ -static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devrequest *cmd, void *data, int len, int timeout) +static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devrequest *cmd, + void *data, int len, int timeout) { struct uhci_device *dev = usb_to_uhci(usb_dev); struct uhci_td *first, *td, *prevtd; @@ -1176,8 +1176,10 @@ static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devre prevtd = td; td = uhci_td_alloc(dev); - if (!td) - return -ENOMEM; + if (!td) { + uhci_td_free(prevtd); + return -ENOMEM; + } prevtd->link = virt_to_bus(td) | UHCI_PTR_DEPTH; @@ -1261,9 +1263,12 @@ static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devre if (uhci_debug && ret) { __u8 *p = (__u8 *)cmd; + printk("dev %d, pipe %X requested %ld bytes, got %ld, status=%d:\n", + usb_dev->devnum, pipe, bytesrequested, bytesread, ret); printk(KERN_DEBUG "Failed cmd - %02X %02X %02X %02X %02X %02X %02X %02X\n", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); } + return ret; } @@ -1344,7 +1349,7 @@ static int uhci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *da if (!td) return -ENOMEM; - prevtd = first; //This is fake, but at least it's not NULL + prevtd = first; // This is fake, but at least it's not NULL while (len > 0) { /* Build the TD for control status */ int pktsze = len; @@ -1376,7 +1381,7 @@ static int uhci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *da usb_dotoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); } - td->link = 1; /* Terminate */ + td->link = UHCI_PTR_TERM; /* Terminate */ td->status |= TD_CTRL_IOC; /* CHANGE DIRECTION HERE! SAVE IT SOMEWHERE IN THE ENDPOINT!!! */ @@ -1619,7 +1624,6 @@ static void uhci_check_configuration(struct uhci *uhci) } while (nr < maxchild); } -#if 0 static int fixup_isoc_desc (struct uhci_td *td) { struct usb_isoc_desc *isocdesc = td->dev_id; @@ -1647,7 +1651,7 @@ static int fixup_isoc_desc (struct uhci_td *td) if ((frm->frame_status = uhci_map_status (uhci_status_bits (prtd->status), uhci_packetout (prtd->info)))) isocdesc->error_count++; - + prtd++; frm++; if (++fx >= isocdesc->frame_count) { /* wrap fx, prtd, and frm */ @@ -1671,8 +1675,106 @@ static int fixup_isoc_desc (struct uhci_td *td) return 0; } -#endif /* 0 */ +int uhci_isoc_callback(struct uhci *uhci, struct uhci_td *td, int status, unsigned long rval) +{ + struct usb_isoc_desc *isocdesc = td->dev_id; + int ret; + + /* + * Fixup the isocdesc for the driver: total_completed_frames, + * error_count, total_length, frames array. + * + * ret = callback_fn (int error_count, void *buffer, + * int len, void *isocdesc); + */ + + fixup_isoc_desc (td); + + ret = td->completed (isocdesc->error_count, bus_to_virt (td->buffer), + isocdesc->total_length, isocdesc); + + /* + * Isoc. handling of return value from td->completed (callback function) + */ + + switch (ret) { + case CB_CONTINUE: /* similar to the REMOVE condition below */ + /* TBD */ + uhci_td_free (td); + break; + + case CB_REUSE: /* similar to the re-add condition below, + * but Not ACTIVE */ + /* TBD */ + /* usb_dev = td->dev->usb; */ + + list_add(&td->irq_list, &uhci->interrupt_list); + + td->status = (td->status & (TD_CTRL_SPD | TD_CTRL_C_ERR_MASK | + TD_CTRL_LS | TD_CTRL_IOS | TD_CTRL_IOC)) | + TD_CTRL_IOC; + + /* The HC removes it, so re-add it */ + /* Insert into a QH? */ + uhci_insert_td_in_qh(td->qh, td); + break; + + case CB_RESTART: /* similar to re-add, but mark ACTIVE */ + /* TBD */ + /* usb_dev = td->dev->usb; */ + + list_add(&td->irq_list, &uhci->interrupt_list); + + td->status = (td->status & (TD_CTRL_SPD | TD_CTRL_C_ERR_MASK | + TD_CTRL_LS | TD_CTRL_IOS | TD_CTRL_IOC)) | + TD_CTRL_ACTIVE | TD_CTRL_IOC; + + /* The HC removes it, so re-add it */ + uhci_insert_td_in_qh(td->qh, td); + break; + + case CB_ABORT: /* kill/abort */ + /* TBD */ + uhci_kill_isoc (isocdesc); + break; + } /* end isoc. TD switch */ + + return 0; +} + +int uhci_callback(struct uhci *uhci, struct uhci_td *td, int status, unsigned long rval) +{ + if (td->completed(status, bus_to_virt(td->buffer), rval, td->dev_id)) { + struct usb_device *usb_dev = td->dev->usb; + + list_add(&td->irq_list, &uhci->interrupt_list); + + usb_dotoggle(usb_dev, usb_pipeendpoint(td->info), usb_pipeout(td->info) ^ 1); + td->info &= ~(1 << TD_TOKEN_TOGGLE); /* clear data toggle */ + td->info |= usb_gettoggle(usb_dev, usb_pipeendpoint(td->info), + uhci_packetout(td->info)) << TD_TOKEN_TOGGLE; /* toggle between data0 and data1 */ + td->status = (td->status & 0x2F000000) | TD_CTRL_ACTIVE | TD_CTRL_IOC; + /* The HC only removes it when it completed */ + /* successfully, so force remove and re-add it. */ + uhci_remove_td(td); + uhci_insert_td_in_qh(td->qh, td); + } else if (td->flags & UHCI_TD_REMOVE) { + struct usb_device *usb_dev = td->dev->usb; + + /* marked for removal */ + td->flags &= ~UHCI_TD_REMOVE; + usb_dotoggle(usb_dev, usb_pipeendpoint(td->info), uhci_packetout(td->info)); + uhci_remove_qh(td->qh->skel, td->qh); + uhci_qh_free(td->qh); + if (td->pipetype == PIPE_INTERRUPT) + usb_release_bandwidth(usb_dev, td->bandwidth_alloc); + uhci_td_free(td); + } + + return 0; +} + static void uhci_interrupt_notify(struct uhci *uhci) { struct list_head *tmp, *head = &uhci->interrupt_list; @@ -1697,32 +1799,11 @@ static void uhci_interrupt_notify(struct uhci *uhci) list_del(&td->irq_list); INIT_LIST_HEAD(&td->irq_list); - if (td->completed(status, bus_to_virt(td->buffer), rval, - td->dev_id)) { - struct usb_device *usb_dev = td->dev->usb; - - list_add(&td->irq_list, &uhci->interrupt_list); - - usb_dotoggle(usb_dev, usb_pipeendpoint(td->info), usb_pipeout(td->info) ^ 1); - td->info &= ~(1 << 19); /* clear data toggle */ - td->info |= usb_gettoggle(usb_dev, usb_pipeendpoint(td->info), - uhci_packetout(td->info)) << 19; /* toggle between data0 and data1 */ - td->status = (td->status & 0x2F000000) | TD_CTRL_ACTIVE | TD_CTRL_IOC; - /* The HC only removes it when it completed */ - /* successfully, so force remove and re-add it */ - uhci_remove_td(td); - uhci_insert_td_in_qh(td->qh, td); - } else if (td->flags & UHCI_TD_REMOVE) { - struct usb_device *usb_dev = td->dev->usb; - - /* marked for removal */ - td->flags &= ~UHCI_TD_REMOVE; - usb_dotoggle(usb_dev, usb_pipeendpoint(td->info), uhci_packetout(td->info)); - uhci_remove_qh(td->qh->skel, td->qh); - uhci_qh_free(td->qh); - uhci_td_free(td); - if (td->pipetype == PIPE_INTERRUPT) - usb_release_bandwidth(usb_dev, td->bandwidth_alloc); + if (td->pipetype == PIPE_ISOCHRONOUS) { + uhci_isoc_callback(uhci, td, status, rval); + } + else { + uhci_callback(uhci, td, status, rval); } /* If completed does not wants to reactivate, then */ @@ -1800,7 +1881,8 @@ static void uhci_init_ticktd(struct uhci *uhci) td->link = uhci->fl->frame[0]; td->backptr = &uhci->fl->frame[0]; td->status = TD_CTRL_IOC; - td->info = (15 << 21) | (0x7f << 8) | USB_PID_IN; /* (ignored) input packet, 16 bytes, device 127 */ + td->info = (15 << 21) | (0x7f << 8) | USB_PID_IN; + /* (ignored) input packet, 16 bytes, device 127 */ td->buffer = 0; td->qh = NULL; td->pipetype = -1; diff --git a/drivers/usb/uhci.h b/drivers/usb/uhci.h index 7d3ead8f641a..96bd338867f7 100644 --- a/drivers/usb/uhci.h +++ b/drivers/usb/uhci.h @@ -125,6 +125,7 @@ struct uhci_framelist { #define TD_TOKEN_TOGGLE 19 #define uhci_maxlen(token) ((token) >> 21) +#define uhci_expected_length(info) ((info >> 21) + 1) /* 1-based */ #define uhci_toggle(token) (((token) >> TD_TOKEN_TOGGLE) & 1) #define uhci_endpoint(token) (((token) >> 15) & 0xf) #define uhci_devaddr(token) (((token) >> 8) & 0x7f) @@ -181,12 +182,6 @@ struct uhci_td { */ struct uhci; -#if 0 -#define UHCI_MAXTD 64 - -#define UHCI_MAXQH 16 -#endif - /* The usb device part must be first! Not anymore -jerdfelt */ struct uhci_device { struct usb_device *usb; @@ -194,10 +189,6 @@ struct uhci_device { atomic_t refcnt; struct uhci *uhci; -#if 0 - struct uhci_qh qh[UHCI_MAXQH]; /* These are the "common" qh's for each device */ - struct uhci_td td[UHCI_MAXTD]; -#endif unsigned long data[16]; }; @@ -278,7 +269,7 @@ struct uhci_device { * and we should meet that frequency when requested to do so. * This will require some change(s) to the UHCI skeleton. */ -static inline int __interval_to_skel(interval) +static inline int __interval_to_skel(int interval) { if (interval < 16) { if (interval < 4) { diff --git a/drivers/usb/usb.c b/drivers/usb/usb.c index 88e0e96625fe..add3bb463323 100644 --- a/drivers/usb/usb.c +++ b/drivers/usb/usb.c @@ -789,10 +789,7 @@ int usb_set_protocol(struct usb_device *dev, int protocol) dr.index = 1; dr.length = 0; - if (dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev, 0), &dr, NULL, 0, HZ)) - return -1; - - return 0; + return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev, 0), &dr, NULL, 0, HZ); } /* keyboards want a nonzero duration according to HID spec, but @@ -807,10 +804,7 @@ int usb_set_idle(struct usb_device *dev, int duration, int report_id) dr.index = 1; dr.length = 0; - if (dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev, 0), &dr, NULL, 0, HZ)) - return -1; - - return 0; + return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev, 0), &dr, NULL, 0, HZ); } static void usb_set_maxpacket(struct usb_device *dev) @@ -873,8 +867,8 @@ int usb_clear_halt(struct usb_device *dev, int endp) if (result) return result; - if (status & 1) - return 1; /* still halted */ + if (status & 1) /* endpoint status is Halted */ + return USB_ST_STALL; /* still halted */ #endif usb_endpoint_running(dev, endp & 0x0f, usb_endpoint_out(endp)); @@ -888,6 +882,7 @@ int usb_clear_halt(struct usb_device *dev, int endp) int usb_set_interface(struct usb_device *dev, int interface, int alternate) { devrequest dr; + int err; dr.requesttype = 1; dr.request = USB_REQ_SET_INTERFACE; @@ -895,8 +890,9 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) dr.index = interface; dr.length = 0; - if (dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev, 0), &dr, NULL, 0, HZ)) - return -1; + err = dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev, 0), &dr, NULL, 0, HZ); + if (err) + return err; dev->ifnum = interface; dev->actconfig->interface[interface].act_altsetting = alternate; @@ -946,10 +942,7 @@ int usb_get_report(struct usb_device *dev, unsigned char type, unsigned char id, dr.index = index; dr.length = size; - if (dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev, 0), &dr, buf, size, HZ)) - return -1; - - return 0; + return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev, 0), &dr, buf, size, HZ); } int usb_get_configuration(struct usb_device *dev) @@ -1056,10 +1049,13 @@ char *usb_string(struct usb_device *dev, int index) * By the time we get here, the device has gotten a new device ID * and is in the default state. We need to identify the thing and * get the ball rolling.. + * + * Returns 0 for success, != 0 for error. */ int usb_new_device(struct usb_device *dev) { int addr; + int err; printk(KERN_INFO "USB new device connect, assigned device number %d\n", dev->devnum); @@ -1073,8 +1069,10 @@ int usb_new_device(struct usb_device *dev) dev->devnum = 0; /* Slow devices */ - if (usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8)) { - printk(KERN_ERR "usbcore: USB device not responding, giving up\n"); + err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8); + if (err) { + printk(KERN_ERR "usbcore: USB device not responding, giving up (error=%d)\n", + err); dev->devnum = -1; return 1; } @@ -1090,16 +1088,20 @@ int usb_new_device(struct usb_device *dev) dev->devnum = addr; - if (usb_set_address(dev)) { - printk(KERN_ERR "usbcore: USB device not accepting new address\n"); + err = usb_set_address(dev); + if (err) { + printk(KERN_ERR "usbcore: USB device not accepting new address (error=%d)\n", + err); dev->devnum = -1; return 1; } wait_ms(10); /* Let the SET_ADDRESS settle */ - if (usb_get_device_descriptor(dev)) { - printk(KERN_ERR "usbcore: unable to get device descriptor\n"); + err = usb_get_device_descriptor(dev); + if (err) { + printk(KERN_ERR "usbcore: unable to get device descriptor (error=%d)\n", + err); dev->devnum = -1; return 1; } @@ -1324,7 +1326,6 @@ void usb_major_init(void) if (register_chrdev(180,"usb",&usb_fops)) { printk("unable to get major %d for usb devices\n", MISC_MAJOR); - return -EIO; } } diff --git a/drivers/usb/usb.h b/drivers/usb/usb.h index 71510623d4ca..5581b2e0da00 100644 --- a/drivers/usb/usb.h +++ b/drivers/usb/usb.h @@ -199,31 +199,32 @@ typedef struct { } devrequest __attribute__ ((packed)); /* - * Status codes (these follow OHCI controllers condition codes) + * Status codes (these [used to] follow OHCI controllers condition codes) */ -#define USB_ST_NOERROR 0x0 -#define USB_ST_CRC 0x1 -#define USB_ST_BITSTUFF 0x2 -#define USB_ST_DTMISMATCH 0x3 /* data toggle mismatch */ -#define USB_ST_STALL 0x4 -#define USB_ST_NORESPONSE 0x5 /* device not responding/handshaking */ -#define USB_ST_PIDCHECK 0x6 /* Check bits on PID failed */ -#define USB_ST_PIDUNDEF 0x7 /* PID unexpected/undefined */ -#define USB_ST_DATAOVERRUN 0x8 -#define USB_ST_DATAUNDERRUN 0x9 -#define USB_ST_RESERVED1 0xA -#define USB_ST_RESERVED2 0xB -#define USB_ST_BUFFEROVERRUN 0xC -#define USB_ST_BUFFERUNDERRUN 0xD -#define USB_ST_RESERVED3 0xE -#define USB_ST_RESERVED4 0xF +#define USB_ST_NOERROR 0 +#define USB_ST_CRC -1 +#define USB_ST_BITSTUFF -2 +#define USB_ST_DTMISMATCH -3 /* data toggle mismatch */ +#define USB_ST_STALL -4 +#define USB_ST_NORESPONSE -5 /* device not responding/handshaking */ +#define USB_ST_PIDCHECK -6 /* Check bits on PID failed */ +#define USB_ST_PIDUNDEF -7 /* PID unexpected/undefined */ +#define USB_ST_DATAOVERRUN -8 +#define USB_ST_DATAUNDERRUN -9 +#define USB_ST_RESERVED1 -10 +#define USB_ST_RESERVED2 -11 +#define USB_ST_BUFFEROVERRUN -12 +#define USB_ST_BUFFERUNDERRUN -13 +#define USB_ST_RESERVED3 -14 +#define USB_ST_RESERVED4 -15 /* internal errors */ -#define USB_ST_REMOVED 0x100 -#define USB_ST_TIMEOUT 0x110 -#define USB_ST_INTERNALERROR -1 -#define USB_ST_NOTSUPPORTED -2 -#define USB_ST_BANDWIDTH_ERROR -3 +#define USB_ST_REMOVED -100 +#define USB_ST_TIMEOUT -101 +#define USB_ST_INTERNALERROR -200 +#define USB_ST_NOTSUPPORTED -201 +#define USB_ST_BANDWIDTH_ERROR -202 +#define USB_ST_NOCHANGE -203 /* @@ -684,7 +685,6 @@ int usb_get_protocol(struct usb_device *dev); int usb_set_protocol(struct usb_device *dev, int protocol); int usb_set_interface(struct usb_device *dev, int interface, int alternate); int usb_set_idle(struct usb_device *dev, int duration, int report_id); -int usb_set_interface(struct usb_device *dev, int interface, int alternate); int usb_set_configuration(struct usb_device *dev, int configuration); int usb_get_report(struct usb_device *dev, unsigned char type, unsigned char id, unsigned char index, void *buf, int size); char *usb_string(struct usb_device *dev, int index); diff --git a/drivers/video/Config.in b/drivers/video/Config.in index a8e223f6bf04..77d72f3f3055 100644 --- a/drivers/video/Config.in +++ b/drivers/video/Config.in @@ -96,6 +96,7 @@ if [ "$CONFIG_FB" = "y" ]; then bool ' Multihead support' CONFIG_FB_MATROX_MULTIHEAD fi tristate ' ATI Mach64 display support (EXPERIMENTAL)' CONFIG_FB_ATY + bool ' ATI Rage 128 display support (EXPERIMENTAL)' CONFIG_FB_ATY128 bool ' 3Dfx Banshee/Voodoo3 display support (EXPERIMENTAL)' CONFIG_FB_3DFX fi fi diff --git a/drivers/video/Makefile b/drivers/video/Makefile index e4f8cefe1c80..c422b0b9fcf9 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -113,6 +113,10 @@ else endif endif +ifeq ($(CONFIG_FB_ATY128),y) +L_OBJS += aty128fb.o +endif + ifeq ($(CONFIG_FB_IGA),y) L_OBJS += igafb.o endif diff --git a/drivers/video/aty128.h b/drivers/video/aty128.h new file mode 100644 index 000000000000..d48ebd82fb35 --- /dev/null +++ b/drivers/video/aty128.h @@ -0,0 +1,594 @@ +/* $Id: aty128.h,v 1.1 1999/10/12 11:00:40 geert Exp $ + * linux/drivers/video/aty128.h + * Register definitions for ATI Rage128 boards + * + * Anthony Tong , 1999 + */ + +#ifndef REG_RAGE128_H +#define REG_RAGE128_H + +#define MM_INDEX 0x0000 +#define MM_DATA 0x0004 +#define CLOCK_CNTL_INDEX 0x0008 +#define CLOCK_CNTL_DATA 0x000c +#define BIOS_0_SCRATCH 0x0010 +#define BIOS_1_SCRATCH 0x0014 +#define BIOS_2_SCRATCH 0x0018 +#define BIOS_3_SCRATCH 0x001c +#define BUS_CNTL 0x0030 +#define BUS_CNTL1 0x0034 +#define MEM_VGA_WP_SEL 0x0038 +#define MEM_VGA_RP_SEL 0x003c +#define GEN_INT_CNTL 0x0040 +#define GEN_INT_STATUS 0x0044 +#define CRTC_GEN_CNTL 0x0050 +#define CRTC_EXT_CNTL 0x0054 +#define DAC_CNTL 0x0058 +#define CRTC_STATUS 0x005c +#define GPIO_MONID 0x0068 +#define I2C_CNTL_1 0x0094 +#define PALETTE_INDEX 0x00b0 +#define PALETTE_DATA 0x00b4 +#define CONFIG_CNTL 0x00e0 +#define CONFIG_XSTRAP 0x00e4 +#define CONFIG_BONDS 0x00e8 +#define GEN_RESET_CNTL 0x00f0 +#define GEN_STATUS 0x00f4 +#define CONFIG_MEMSIZE 0x00f8 +#define CONFIG_APER_0_BASE 0x0100 +#define CONFIG_APER_1_BASE 0x0104 +#define CONFIG_APER_SIZE 0x0108 +#define CONFIG_REG_1_BASE 0x010c +#define CONFIG_REG_APER_SIZE 0x0110 +#define CONFIG_MEMSIZE_EMBEDDED 0x0114 +#define TEST_DEBUG_CNTL 0x0120 +#define TEST_DEBUG_MUX 0x0124 +#define HW_DEBUG 0x0128 +#define TEST_DEBUG_OUT 0x012c +#define HOST_PATH_CNTL 0x0130 +#define SW_SEMAPHORE 0x013c +#define MEM_CNTL 0x0140 +#define EXT_MEM_CNTL 0x0144 +#define MEM_ADDR_CONFIG 0x0148 +#define MEM_INTF_CNTL 0x014c +#define MEM_STR_CNTL 0x0150 +#define MEM_INIT_LAT_TIMER 0x0154 +#define MEM_SDRAM_MODE_REG 0x0158 +#define AGP_BASE 0x0170 +#define AGP_CNTL 0x0174 +#define AGP_APER_OFFSET 0x0178 +#define PCI_GART_PAGE 0x017c +#define PC_NGUI_MODE 0x0180 +#define PC_NGUI_CTLSTAT 0x0184 +#define VIDEOMUX_CNTL 0x0190 +#define MPP_TB_CONFIG 0x01C0 +#define MPP_GP_CONFIG 0x01C8 +#define VIPH_CONTROL 0x01D0 +#define CRTC_H_TOTAL_DISP 0x0200 +#define CRTC_H_SYNC_STRT_WID 0x0204 +#define CRTC_V_TOTAL_DISP 0x0208 +#define CRTC_V_SYNC_STRT_WID 0x020c +#define CRTC_VLINE_CRNT_VLINE 0x0210 +#define CRTC_CRNT_FRAME 0x0214 +#define CRTC_GUI_TRIG_VLINE 0x0218 +#define CRTC_DEBUG 0x021c +#define CRTC_OFFSET 0x0224 +#define CRTC_OFFSET_CNTL 0x0228 +#define CRTC_PITCH 0x022c +#define OVR_CLR 0x0230 +#define OVR_WID_LEFT_RIGHT 0x0234 +#define OVR_WID_TOP_BOTTOM 0x0238 +#define SNAPSHOT_VH_COUNTS 0x0240 +#define SNAPSHOT_F_COUNT 0x0244 +#define N_VIF_COUNT 0x0248 +#define SNAPSHOT_VIF_COUNT 0x024c +#define CUR_OFFSET 0x0260 +#define CUR_HORZ_VERT_POSN 0x0264 +#define CUR_HORZ_VERT_OFF 0x0268 +#define CUR_CLR0 0x026c +#define CUR_CLR1 0x0270 +#define DAC_CRC_SIG 0x02cc +#define DDA_CONFIG 0x02e0 +#define DDA_ON_OFF 0x02e4 +#define VGA_DDA_CONFIG 0x02e8 +#define VGA_DDA_ON_OFF 0x02ec +#define OV0_Y_X_START 0x0400 +#define OV0_Y_X_END 0x0404 +#define OV0_EXCLUSIVE_HORZ 0x0408 +#define OV0_EXCLUSIVE_VERT 0x040c +#define OV0_REG_LOAD_CNTL 0x0410 +#define OV0_SCALE_CNTL 0x0420 +#define OV0_V_INC 0x0424 +#define OV0_P1_V_ACCUM_INIT 0x0428 +#define OV0_P23_V_ACCUM_INIT 0x042c +#define OV0_P1_BLANK_LINES_AT_TOP 0x0430 +#define OV0_P23_BLANK_LINES_AT_TOP 0x0434 +#define OV0_VID_BUF0_BASE_ADRS 0x0440 +#define OV0_VID_BUF1_BASE_ADRS 0x0444 +#define OV0_VID_BUF2_BASE_ADRS 0x0448 +#define OV0_VID_BUF3_BASE_ADRS 0x044c +#define OV0_VID_BUF4_BASE_ADRS 0x0450 +#define OV0_VID_BUF5_BASE_ADRS 0x0454 +#define OV0_VID_BUF_PITCH0_VALUE 0x0460 +#define OV0_VID_BUF_PITCH1_VALUE 0x0464 +#define OV0_OCTWORDS_PER_LINE_M1 0x046c +#define OV0_AUTO_FLIP_CNTRL 0x0470 +#define OV0_DEINTERLACE_PATTERN 0x0474 +#define OV0_H_INC 0x0480 +#define OV0_STEP_BY 0x0484 +#define OV0_P1_H_ACCUM_INIT 0x0488 +#define OV0_P23_H_ACCUM_INIT 0x048c +#define OV0_P1_X_START_END 0x0494 +#define OV0_P2_X_START_END 0x0498 +#define OV0_P3_X_START_END 0x049c +#define OV0_FILTER_CNTL 0x04a0 +#define OV0_FOUR_TAP_COEF_0 0x04b0 +#define OV0_FOUR_TAP_COEF_1 0x04b4 +#define OV0_FOUR_TAP_COEF_2 0x04b8 +#define OV0_FOUR_TAP_COEF_3 0x04bc +#define OV0_FOUR_TAP_COEF_4 0x04c0 +#define OV0_COLOR_CNTL 0x04e0 +#define OV0_VIDEO_KEY_CLR 0x04e4 +#define OV0_VIDEO_KEY_MASK 0x04e8 +#define OV0_GRAPHICS_KEY_CLR 0x04ec +#define OV0_GRAPHICS_KEY_MASK 0x04f0 +#define OV0_KEY_CNTL 0x04f4 +#define OV0_TEST 0x04f8 +#define SUBPIC_CNTL 0x0540 +#define PM4_BUFFER_OFFSET 0x0700 +#define PM4_BUFFER_CNTL 0x0704 +#define PM4_BUFFER_WM_CNTL 0x0708 +#define PM4_BUFFER_DL_RPTR_ADDR 0x070c +#define PM4_BUFFER_DL_RPTR 0x0710 +#define PM4_BUFFER_DL_WPTR 0x0714 +#define PM4_VC_FPU_SETUP 0x071c +#define PM4_FPU_CNTL 0x0720 +#define PM4_VC_FORMAT 0x0724 +#define PM4_VC_CNTL 0x0728 +#define PM4_VC_I01 0x072c +#define PM4_VC_VLOFF 0x0730 +#define PM4_VC_VLSIZE 0x0734 +#define PM4_IW_INDOFF 0x0738 +#define PM4_IW_INDSIZE 0x073c +#define PM4_FPU_FPX0 0x0740 +#define CRC_CMDFIFO_ADDR 0x0740 +#define PM4_FPU_FPY0 0x0744 +#define CRC_CMDFIFO_DOUT 0x0744 +#define PM4_FPU_FPX1 0x0748 +#define PM4_FPU_FPY1 0x074c +#define PM4_FPU_FPX2 0x0750 +#define PM4_FPU_FPY2 0x0754 +#define PM4_FPU_FPY3 0x0758 +#define PM4_FPU_FPY4 0x075c +#define PM4_FPU_FPY5 0x0760 +#define PM4_FPU_FPY6 0x0764 +#define PM4_FPU_FPR 0x0768 +#define PM4_FPU_FPG 0x076c +#define PM4_FPU_FPB 0x0770 +#define PM4_FPU_FPA 0x0774 +#define PM4_FPU_INTXY0 0x0780 +#define PM4_FPU_INTXY1 0x0784 +#define PM4_FPU_INTXY2 0x0788 +#define PM4_FPU_INTARGB 0x078c +#define PM4_FPU_FPTWICEAREA 0x0790 +#define PM4_FPU_DMAJOR01 0x0794 +#define PM4_FPU_DMAJOR12 0x0798 +#define PM4_FPU_DMAJOR02 0x079c +#define PM4_FPU_STAT 0x07a0 +#define PM4_STAT 0x07b8 +#define PM4_TEST_CNTL 0x07d0 +#define PM4_MICROCODE_ADDR 0x07d4 +#define PM4_MICROCODE_RADDR 0x07d8 +#define PM4_MICROCODE_DATAH 0x07dc +#define PM4_MICROCODE_DATAL 0x07e0 +#define PM4_CMDFIFO_ADDR 0x07e4 +#define PM4_CMDFIFO_DATAH 0x07e8 +#define PM4_CMDFIFO_DATAL 0x07ec +#define PM4_BUFFER_ADDR 0x07f0 +#define PM4_BUFFER_DATAH 0x07f4 +#define PM4_BUFFER_DATAL 0x07f8 +#define PM4_MICRO_CNTL 0x07fc +#define VID_BUFFER_CONTROL 0x0900 +#define CAP_INT_CNTL 0x0908 +#define CAP_INT_STATUS 0x090c +#define CAP0_BUF0_OFFSET 0x0920 +#define CAP0_BUF1_OFFSET 0x0924 +#define CAP0_BUF0_EVEN_OFFSET 0x0928 +#define CAP0_BUF1_EVEN_OFFSET 0x092c +#define CAP0_BUF_PITCH 0x0930 +#define CAP0_V_WINDOW 0x0934 +#define CAP0_H_WINDOW 0x0938 +#define CAP0_VBI_ODD_OFFSET 0x093c +#define CAP0_VBI_EVEN_OFFSET 0x0940 +#define CAP0_VBI_V_WINDOW 0x0944 +#define CAP0_VBI_H_WINDOW 0x0948 +#define CAP0_PORT_MODE_CNTL 0x094c +#define CAP0_TRIG_CNTL 0x0950 +#define CAP0_DEBUG 0x0954 +#define CAP0_CONFIG 0x0958 +#define CAP0_ANC_ODD_OFFSET 0x095c +#define CAP0_ANC_EVEN_OFFSET 0x0960 +#define CAP0_ANC_H_WINDOW 0x0964 +#define CAP0_VIDEO_SYNC_TEST 0x0968 +#define CAP0_ONESHOT_BUF_OFFSET 0x096c +#define CAP0_BUF_STATUS 0x0970 +#define CAP0_DWNSC_XRATIO 0x0978 +#define CAP0_XSHARPNESS 0x097c +#define CAP1_BUF0_OFFSET 0x0990 +#define CAP1_BUF1_OFFSET 0x0994 +#define CAP1_BUF0_EVEN_OFFSET 0x0998 +#define CAP1_BUF1_EVEN_OFFSET 0x099c +#define CAP1_BUF_PITCH 0x09a0 +#define CAP1_V_WINDOW 0x09a4 +#define CAP1_H_WINDOW 0x09a8 +#define CAP1_VBI_ODD_OFFSET 0x09ac +#define CAP1_VBI_EVEN_OFFSET 0x09b0 +#define CAP1_VBI_V_WINDOW 0x09b4 +#define CAP1_VBI_H_WINDOW 0x09b8 +#define CAP1_PORT_MODE_CNTL 0x09bc +#define CAP1_TRIG_CNTL 0x09c0 +#define CAP1_DEBUG 0x09c4 +#define CAP1_CONFIG 0x09c8 +#define CAP1_ANC_ODD_OFFSET 0x09cc +#define CAP1_ANC_EVEN_OFFSET 0x09d0 +#define CAP1_ANC_H_WINDOW 0x09d4 +#define CAP1_VIDEO_SYNC_TEST 0x09d8 +#define CAP1_ONESHOT_BUF_OFFSET 0x09dc +#define CAP1_BUF_STATUS 0x09e0 +#define CAP1_DWNSC_XRATIO 0x09e8 +#define CAP1_XSHARPNESS 0x09ec +#define BM_FRAME_BUF_OFFSET 0x0a00 +#define BM_SYSTEM_MEM_ADDR 0x0a04 +#define BM_COMMAND 0x0a08 +#define BM_STATUS 0x0a0c +#define BM_QUEUE_STATUS 0x0a10 +#define BM_QUEUE_FREE_STATUS 0x0A14 +#define BM_CHUNK_0_VAL 0x0a18 +#define BM_CHUNK_1_VAL 0x0a1C +#define BM_VIP0_BUF 0x0A20 +#define BM_VIP0_ACTIVE 0x0A24 +#define BM_VIP1_BUF 0x0A30 +#define BM_VIP1_ACTIVE 0x0A34 +#define BM_VIP2_BUF 0x0A40 +#define BM_VIP2_ACTIVE 0x0A44 +#define BM_VIP3_BUF 0x0A50 +#define BM_VIP3_ACTIVE 0x0A54 +#define BM_VIDCAP_BUF0 0x0a60 +#define BM_VIDCAP_BUF1 0x0a64 +#define BM_VIDCAP_BUF2 0x0a68 +#define BM_VIDCAP_ACTIVE 0x0a6c +#define BM_GUI 0x0a80 +#define SURFACE_DELAY 0x0b00 + +/****************************************************************************** + * GUI Block Memory Mapped Registers * + * These registers are FIFOed. * + *****************************************************************************/ +#define PM4_FIFO_DATA_EVEN 0x1000 +#define PM4_FIFO_DATA_ODD 0x1004 + +#define DST_OFFSET 0x1404 +#define DST_PITCH 0x1408 +#define DST_WIDTH 0x140c +#define DST_HEIGHT 0x1410 +#define SRC_X 0x1414 +#define SRC_Y 0x1418 +#define DST_X 0x141c +#define DST_Y 0x1420 +#define SRC_PITCH_OFFSET 0x1428 +#define DST_PITCH_OFFSET 0x142c +#define SRC_Y_X 0x1434 +#define DST_Y_X 0x1438 +#define DST_HEIGHT_WIDTH 0x143c +#define DP_GUI_MASTER_CNTL 0x146c +#define BRUSH_SCALE 0x1470 +#define BRUSH_Y_X 0x1474 +#define DP_BRUSH_BKGD_CLR 0x1478 +#define DP_BRUSH_FRGD_CLR 0x147c +#define BRUSH_DATA0 0x1480 +#define BRUSH_DATA1 0x1484 +#define BRUSH_DATA2 0x1488 +#define BRUSH_DATA3 0x148c +#define BRUSH_DATA4 0x1490 +#define BRUSH_DATA5 0x1494 +#define BRUSH_DATA6 0x1498 +#define BRUSH_DATA7 0x149c +#define BRUSH_DATA8 0x14a0 +#define BRUSH_DATA9 0x14a4 +#define BRUSH_DATA10 0x14a8 +#define BRUSH_DATA11 0x14ac +#define BRUSH_DATA12 0x14b0 +#define BRUSH_DATA13 0x14b4 +#define BRUSH_DATA14 0x14b8 +#define BRUSH_DATA15 0x14bc +#define BRUSH_DATA16 0x14c0 +#define BRUSH_DATA17 0x14c4 +#define BRUSH_DATA18 0x14c8 +#define BRUSH_DATA19 0x14cc +#define BRUSH_DATA20 0x14d0 +#define BRUSH_DATA21 0x14d4 +#define BRUSH_DATA22 0x14d8 +#define BRUSH_DATA23 0x14dc +#define BRUSH_DATA24 0x14e0 +#define BRUSH_DATA25 0x14e4 +#define BRUSH_DATA26 0x14e8 +#define BRUSH_DATA27 0x14ec +#define BRUSH_DATA28 0x14f0 +#define BRUSH_DATA29 0x14f4 +#define BRUSH_DATA30 0x14f8 +#define BRUSH_DATA31 0x14fc +#define BRUSH_DATA32 0x1500 +#define BRUSH_DATA33 0x1504 +#define BRUSH_DATA34 0x1508 +#define BRUSH_DATA35 0x150c +#define BRUSH_DATA36 0x1510 +#define BRUSH_DATA37 0x1514 +#define BRUSH_DATA38 0x1518 +#define BRUSH_DATA39 0x151c +#define BRUSH_DATA40 0x1520 +#define BRUSH_DATA41 0x1524 +#define BRUSH_DATA42 0x1528 +#define BRUSH_DATA43 0x152c +#define BRUSH_DATA44 0x1530 +#define BRUSH_DATA45 0x1534 +#define BRUSH_DATA46 0x1538 +#define BRUSH_DATA47 0x153c +#define BRUSH_DATA48 0x1540 +#define BRUSH_DATA49 0x1544 +#define BRUSH_DATA50 0x1548 +#define BRUSH_DATA51 0x154c +#define BRUSH_DATA52 0x1550 +#define BRUSH_DATA53 0x1554 +#define BRUSH_DATA54 0x1558 +#define BRUSH_DATA55 0x155c +#define BRUSH_DATA56 0x1560 +#define BRUSH_DATA57 0x1564 +#define BRUSH_DATA58 0x1568 +#define BRUSH_DATA59 0x156c +#define BRUSH_DATA60 0x1570 +#define BRUSH_DATA61 0x1574 +#define BRUSH_DATA62 0x1578 +#define BRUSH_DATA63 0x157c +#define DST_WIDTH_X 0x1588 +#define DST_HEIGHT_WIDTH_8 0x158c +#define SRC_X_Y 0x1590 +#define DST_X_Y 0x1594 +#define DST_WIDTH_HEIGHT 0x1598 +#define DST_WIDTH_X_INCY 0x159c +#define DST_HEIGHT_Y 0x15a0 +#define DST_X_SUB 0x15a4 +#define DST_Y_SUB 0x15a8 +#define SRC_OFFSET 0x15ac +#define SRC_PITCH 0x15b0 +#define DST_HEIGHT_WIDTH_BW 0x15b4 +#define CLR_CMP_CNTL 0x15c0 +#define CLR_CMP_CLR_SRC 0x15c4 +#define CLR_CMP_CLR_DST 0x15c8 +#define CLR_CMP_MASK 0x15cc +#define DP_SRC_FRGD_CLR 0x15d8 +#define DP_SRC_BKGD_CLR 0x15dc +#define GUI_SCRATCH_REG0 0x15e0 +#define GUI_SCRATCH_REG1 0x15e4 +#define GUI_SCRATCH_REG2 0x15e8 +#define GUI_SCRATCH_REG3 0x15ec +#define GUI_SCRATCH_REG4 0x15f0 +#define GUI_SCRATCH_REG5 0x15f4 +#define LEAD_BRES_ERR 0x1600 +#define LEAD_BRES_INC 0x1604 +#define LEAD_BRES_DEC 0x1608 +#define TRAIL_BRES_ERR 0x160c +#define TRAIL_BRES_INC 0x1610 +#define TRAIL_BRES_DEC 0x1614 +#define TRAIL_X 0x1618 +#define LEAD_BRES_LNTH 0x161c +#define TRAIL_X_SUB 0x1620 +#define LEAD_BRES_LNTH_SUB 0x1624 +#define DST_BRES_ERR 0x1628 +#define DST_BRES_INC 0x162c +#define DST_BRES_DEC 0x1630 +#define DST_BRES_LNTH 0x1634 +#define DST_BRES_LNTH_SUB 0x1638 +#define SC_LEFT 0x1640 +#define SC_RIGHT 0x1644 +#define SC_TOP 0x1648 +#define SC_BOTTOM 0x164c +#define SRC_SC_RIGHT 0x1654 +#define SRC_SC_BOTTOM 0x165c +#define AUX_SC_CNTL 0x1660 +#define AUX1_SC_LEFT 0x1664 +#define AUX1_SC_RIGHT 0x1668 +#define AUX1_SC_TOP 0x166c +#define AUX1_SC_BOTTOM 0x1670 +#define AUX2_SC_LEFT 0x1674 +#define AUX2_SC_RIGHT 0x1678 +#define AUX2_SC_TOP 0x167c +#define AUX2_SC_BOTTOM 0x1680 +#define AUX3_SC_LEFT 0x1684 +#define AUX3_SC_RIGHT 0x1688 +#define AUX3_SC_TOP 0x168c +#define AUX3_SC_BOTTOM 0x1690 +#define GUI_DEBUG0 0x16a0 +#define GUI_DEBUG1 0x16a4 +#define GUI_TIMEOUT 0x16b0 +#define GUI_TIMEOUT0 0x16b4 +#define GUI_TIMEOUT1 0x16b8 +#define GUI_PROBE 0x16bc +#define DP_CNTL 0x16c0 +#define DP_DATATYPE 0x16c4 +#define DP_MIX 0x16c8 +#define DP_WRITE_MASK 0x16cc +#define DP_CNTL_XDIR_YDIR_YMAJOR 0x16d0 +#define DEFAULT_OFFSET 0x16e0 +#define DEFAULT_PITCH 0x16e4 +#define DEFAULT_SC_BOTTOM_RIGHT 0x16e8 +#define SC_TOP_LEFT 0x16ec +#define SC_BOTTOM_RIGHT 0x16f0 +#define SRC_SC_BOTTOM_RIGHT 0x16f4 +#define WAIT_UNTIL 0x1720 +#define CACHE_CNTL 0x1724 +#define GUI_STAT 0x1740 +#define PC_GUI_MODE 0x1744 +#define PC_GUI_CTLSTAT 0x1748 +#define PC_DEBUG_MODE 0x1760 +#define BRES_DST_ERR_DEC 0x1780 +#define TRAIL_BRES_T12_ERR_DEC 0x1784 +#define TRAIL_BRES_T12_INC 0x1788 +#define DP_T12_CNTL 0x178c +#define DST_BRES_T1_LNTH 0x1790 +#define DST_BRES_T2_LNTH 0x1794 +#define HOST_DATA0 0x17c0 +#define HOST_DATA1 0x17c4 +#define HOST_DATA2 0x17c8 +#define HOST_DATA3 0x17cc +#define HOST_DATA4 0x17d0 +#define HOST_DATA5 0x17d4 +#define HOST_DATA6 0x17d8 +#define HOST_DATA7 0x17dc +#define HOST_DATA_LAST 0x17e0 +#define SECONDARY_SCALE_PITCH 0x1980 +#define SECONDARY_SCALE_X_INC 0x1984 +#define SECONDARY_SCALE_Y_INC 0x1988 +#define SECONDARY_SCALE_HACC 0x198c +#define SECONDARY_SCALE_VACC 0x1990 +#define SCALE_SRC_HEIGHT_WIDTH 0x1994 +#define SCALE_OFFSET_0 0x1998 +#define SCALE_PITCH 0x199c +#define SCALE_X_INC 0x19a0 +#define SCALE_Y_INC 0x19a4 +#define SCALE_HACC 0x19a8 +#define SCALE_VACC 0x19ac +#define SCALE_DST_X_Y 0x19b0 +#define SCALE_DST_HEIGHT_WIDTH 0x19b4 +#define SCALE_3D_CNTL 0x1a00 +#define SCALE_3D_DATATYPE 0x1a20 +#define SETUP_CNTL 0x1bc4 +#define SOLID_COLOR 0x1bc8 +#define WINDOW_XY_OFFSET 0x1bcc +#define DRAW_LINE_POINT 0x1bd0 +#define SETUP_CNTL_PM4 0x1bd4 +#define DST_PITCH_OFFSET_C 0x1c80 +#define DP_GUI_MASTER_CNTL_C 0x1c84 +#define SC_TOP_LEFT_C 0x1c88 +#define SC_BOTTOM_RIGHT_C 0x1c8c + +#define CLR_CMP_MASK_3D 0x1A28 +#define MISC_3D_STATE_CNTL_REG 0x1CA0 +#define MC_SRC1_CNTL 0x19D8 +#define TEX_CNTL 0x1800 + +/* CONSTANTS */ +#define GUI_ACTIVE 0x80000000 +#define ENGINE_IDLE 0x0 + +#define PLL_WR_EN 0x00000080 + +#define CLK_PIN_CNTL 0x0001 +#define PPLL_CNTL 0x0002 +#define PPLL_REF_DIV 0x0003 +#define PPLL_DIV_0 0x0004 +#define PPLL_DIV_1 0x0005 +#define PPLL_DIV_2 0x0006 +#define PPLL_DIV_3 0x0007 +#define VCLK_ECP_CNTL 0x0008 +#define HTOTAL_CNTL 0x0009 +#define X_MPLL_REF_FB_DIV 0x000a +#define XPLL_CNTL 0x000b +#define XDLL_CNTL 0x000c +#define XCLK_CNTL 0x000d +#define MPLL_CNTL 0x000e +#define MCLK_CNTL 0x000f +#define AGP_PLL_CNTL 0x0010 +#define FCP_CNTL 0x0012 +#define PLL_TEST_CNTL 0x0013 + +#define PPLL_RESET 0x01 +#define PPLL_ATOMIC_UPDATE_EN 0x10000 +#define PPLL_VGA_ATOMIC_UPDATE_EN 0x20000 +#define PPLL_REF_DIV_MASK 0x3FF +#define PPLL_FB3_DIV_MASK 0x7FF +#define PPLL_POST3_DIV_MASK 0x70000 +#define PPLL_ATOMIC_UPDATE_R 0x8000 +#define PPLL_ATOMIC_UPDATE_W 0x8000 +#define MEM_CFG_TYPE_MASK 0x3 +#define XCLK_SRC_SEL_MASK 0x7 +#define XPLL_FB_DIV_MASK 0xFF00 +#define X_MPLL_REF_DIV_MASK 0xFF + +/* CRTC control values (CRTC_GEN_CNTL) */ +#define CRTC_CSYNC_EN 0x00000010 + +#define CRTC_PIX_WIDTH_MASK 0x00000700 +#define CRTC_PIX_WIDTH_4BPP 0x00000100 +#define CRTC_PIX_WIDTH_8BPP 0x00000200 +#define CRTC_PIX_WIDTH_15BPP 0x00000300 +#define CRTC_PIX_WIDTH_16BPP 0x00000400 +#define CRTC_PIX_WIDTH_24BPP 0x00000500 +#define CRTC_PIX_WIDTH_32BPP 0x00000600 + +/* DAC_CNTL bit constants */ +#define DAC_8BIT_EN 0x00000100 + +/* GEN_RESET_CNTL bit constants */ +#define SOFT_RESET_GUI 0x00000001 +#define SOFT_RESET_VCLK 0x00000100 +#define SOFT_RESET_PCLK 0x00000200 +#define SOFT_RESET_ECP 0x00000400 +#define SOFT_RESET_DISPENG_XCLK 0x00000800 + +/* PC_GUI_CTLSTAT bit constants */ +#define PC_BUSY_INIT 0x10000000 +#define PC_BUSY_GUI 0x20000000 +#define PC_BUSY_NGUI 0x40000000 +#define PC_BUSY 0x80000000 + +#define BUS_MASTER_DIS 0x00000040 +#define PM4_BUFFER_CNTL_NONPM4 0x00000000 + +/* DP_GUI_MASTER_CNTL bit constants */ +#define GMC_SRC_PITCH_OFFSET_DEFAULT 0x00000000 +#define GMC_DST_PITCH_OFFSET_DEFAULT 0x00000000 +#define GMC_SRC_CLIP_DEFAULT 0x00000000 +#define GMC_DST_CLIP_DEFAULT 0x00000000 +#define GMC_BRUSH_SOLIDCOLOR 0x000000d0 +#define GMC_SRC_DSTCOLOR 0x00003000 +#define GMC_BYTE_ORDER_MSB_TO_LSB 0x00000000 +#define GMC_DP_SRC_RECT 0x02000000 +#define GMC_3D_FCN_EN_CLR 0x00000000 +#define GMC_AUX_CLIP_CLEAR 0x20000000 +#define GMC_DST_CLR_CMP_FCN_CLEAR 0x10000000 +#define GMC_WRITE_MASK_SET 0x40000000 +#define GMC_DP_CONVERSION_TEMP_6500 0x00000000 + +/* DP_GUI_MASTER_CNTL ROP3 named constants */ +#define ROP3_PATCOPY 0x00f00000 +#define ROP3_SRCCOPY 0x00cc0000 // S + +#define SRC_DSTCOLOR 0x00030000 + +/* DP_CNTL bit constants */ +#define DST_X_RIGHT_TO_LEFT 0x00000000 +#define DST_X_LEFT_TO_RIGHT 0x00000001 +#define DST_Y_BOTTOM_TO_TOP 0x00000000 +#define DST_Y_TOP_TO_BOTTOM 0x00000002 +#define DST_X_MAJOR 0x00000000 +#define DST_Y_MAJOR 0x00000004 +#define DST_X_TILE 0x00000008 +#define DST_Y_TILE 0x00000010 +#define DST_LAST_PEL 0x00000020 +#define DST_TRAIL_X_RIGHT_TO_LEFT 0x00000000 +#define DST_TRAIL_X_LEFT_TO_RIGHT 0x00000040 +#define DST_TRAP_FILL_RIGHT_TO_LEFT 0x00000000 +#define DST_TRAP_FILL_LEFT_TO_RIGHT 0x00000080 +#define DST_BRES_SIGN 0x00000100 +#define DST_HOST_BIG_ENDIAN_EN 0x00000200 +#define DST_POLYLINE_NONLAST 0x00008000 +#define DST_RASTER_STALL 0x00010000 +#define DST_POLY_EDGE 0x00040000 + +/* DP_MIX bit constants */ +#define DP_SRC_RECT 0x00000200 +#define DP_SRC_HOST 0x00000300 +#define DP_SRC_HOST_BYTEALIGN 0x00000400 + +#endif /* REG_RAGE128_H */ diff --git a/drivers/video/aty128fb.c b/drivers/video/aty128fb.c new file mode 100644 index 000000000000..16b37c8705e8 --- /dev/null +++ b/drivers/video/aty128fb.c @@ -0,0 +1,2151 @@ +/* $Id: aty128fb.c,v 1.1 1999/10/12 11:00:43 geert Exp $ + * linux/drivers/video/aty128fb.c -- Frame buffer device for ATI Rage128 + * + * Copyright (C) Summer 1999, Anthony Tong + * + * Brad Douglas + * - x86 support + * - MTRR + * - Probe ROM for PLL + * + * Based off of Geert's atyfb.c and vfb.c. + * + * TODO: + * - panning + * - fix 15/16 bpp on big endian arch's + * - monitor sensing (DDC) + * - other platform support (only ppc/x86 supported) + * - PPLL_REF_DIV & XTALIN calculation + * - determine MCLK from previous hardware setting + */ + +/* + * A special note of gratitude to ATI's devrel for providing documentation, + * example code and hardware. Thanks Nitya. -atong + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_PPC) +#include +#include +#include +#include