]> git.neil.brown.name Git - history.git/commitdiff
Import 2.3.23pre2 2.3.23pre2
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:27:49 +0000 (15:27 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:27:49 +0000 (15:27 -0500)
186 files changed:
Documentation/Changes
Documentation/Configure.help
Documentation/vm/locking [new file with mode: 0644]
MAINTAINERS
arch/arm/def-configs/footbridge
arch/arm/defconfig
arch/i386/Makefile
arch/i386/config.in
arch/i386/kernel/pci-visws.c
arch/i386/kernel/visws_apic.c
arch/i386/vmlinux.lds [new file with mode: 0644]
arch/i386/vmlinux.lds.S [deleted file]
arch/ppc/kernel/chrp_pci.c
arch/ppc/kernel/chrp_setup.c
arch/ppc/kernel/mbx_setup.c
arch/ppc/kernel/pmac_setup.c
arch/ppc/kernel/prep_setup.c
arch/ppc/kernel/setup.c
arch/ppc/mbx_defconfig
arch/sh/Makefile
arch/sh/config.in
arch/sh/defconfig
arch/sh/kernel/Makefile
arch/sh/kernel/entry.S
arch/sh/kernel/head.S
arch/sh/kernel/irq.c
arch/sh/kernel/irq_onchip.c
arch/sh/kernel/process.c
arch/sh/kernel/setup.c
arch/sh/kernel/signal.c
arch/sh/kernel/sys_sh.c
arch/sh/kernel/test-img.c [deleted file]
arch/sh/kernel/time.c
arch/sh/kernel/traps.c
arch/sh/lib/Makefile
arch/sh/lib/checksum.S [new file with mode: 0644]
arch/sh/lib/checksum.c [deleted file]
arch/sh/lib/csum_partial_copy.c [deleted file]
arch/sh/lib/memcpy.S
arch/sh/lib/memmove.S
arch/sh/lib/memset.S
arch/sh/lib/old-checksum.c
arch/sh/lib/wordcopy.S [deleted file]
arch/sh/mm/Makefile
arch/sh/mm/cache.c [new file with mode: 0644]
arch/sh/mm/extable.c
arch/sh/mm/fault.c
arch/sh/mm/init.c
arch/sh/mm/ioremap.c
arch/sh/vmlinux.lds.S
drivers/block/Config.in
drivers/block/Makefile
drivers/block/aec6210.c
drivers/block/alim15x3.c
drivers/block/cy82c693.c
drivers/block/hpt34x.c
drivers/block/hpt366.c
drivers/block/icside.c
drivers/block/ide-cd.c
drivers/block/ide-cd.h
drivers/block/ide-disk.c
drivers/block/ide-dma.c
drivers/block/ide-floppy.c
drivers/block/ide-geometry.c
drivers/block/ide-pci.c
drivers/block/ide-pmac.c
drivers/block/ide-probe.c
drivers/block/ide-proc.c
drivers/block/ide-tape.c
drivers/block/ide.c
drivers/block/paride/pcd.c
drivers/block/pdc202xx.c
drivers/block/pdc4030.c
drivers/block/piix.c
drivers/block/sis5513.c
drivers/block/trm290.c
drivers/block/via82c586.c [deleted file]
drivers/block/via82cxxx.c [new file with mode: 0644]
drivers/cdrom/cdrom.c
drivers/char/Makefile
drivers/char/istallion.c
drivers/char/pcxx.c
drivers/char/radio-cadet.c
drivers/char/stallion.c
drivers/i2o/Config.in
drivers/net/hamradio/baycom_par.c
drivers/net/hamradio/soundmodem/sm.c
drivers/net/slhc.c
drivers/pci/quirks.c
drivers/scsi/atp870u.c
drivers/scsi/atp870u.h
drivers/scsi/ide-scsi.c
drivers/scsi/inia100.h
drivers/scsi/ips.c
drivers/scsi/ips.h
drivers/scsi/u14-34f.h
drivers/sound/maestro.c
drivers/sound/sound_core.c
drivers/usb/cpia.c
drivers/usb/hp_scanner.c
drivers/usb/inits.h
drivers/usb/uhci.c
drivers/usb/uhci.h
drivers/usb/usb.c
drivers/usb/usb.h
drivers/video/Config.in
drivers/video/Makefile
drivers/video/aty128.h [new file with mode: 0644]
drivers/video/aty128fb.c [new file with mode: 0644]
drivers/video/atyfb.c
drivers/video/chipsfb.c
drivers/video/offb.c
fs/dcache.c
fs/exec.c
fs/inode.c
fs/minix/truncate.c
fs/nfs/dir.c
fs/nfs/inode.c
fs/nfs/nfs2xdr.c
fs/nfs/proc.c
fs/proc/array.c
include/asm-i386/page.h
include/asm-i386/page_offset.h [deleted file]
include/asm-sh/addrspace.h
include/asm-sh/atomic.h
include/asm-sh/bitops.h
include/asm-sh/bugs.h
include/asm-sh/byteorder.h
include/asm-sh/cache.h
include/asm-sh/checksum.h
include/asm-sh/delay.h
include/asm-sh/elf.h
include/asm-sh/hardirq.h
include/asm-sh/hdreg.h [new file with mode: 0644]
include/asm-sh/ide.h [new file with mode: 0644]
include/asm-sh/io.h
include/asm-sh/ioctl.h
include/asm-sh/ioctls.h
include/asm-sh/irq.h
include/asm-sh/mmu_context.h
include/asm-sh/namei.h
include/asm-sh/page.h
include/asm-sh/pgtable.h
include/asm-sh/processor.h
include/asm-sh/ptrace.h
include/asm-sh/sigcontext.h
include/asm-sh/signal.h
include/asm-sh/smp_lock.h [deleted file]
include/asm-sh/smplock.h [new file with mode: 0644]
include/asm-sh/socket.h
include/asm-sh/softirq.h
include/asm-sh/system.h
include/asm-sh/termbits.h
include/asm-sh/termios.h
include/asm-sh/types.h
include/asm-sh/uaccess.h
include/asm-sh/unistd.h
include/linux/cdrom.h
include/linux/fs.h
include/linux/hdreg.h
include/linux/ide.h
include/linux/mm.h
include/linux/nfs.h
include/linux/nfs_fs.h
include/linux/nfs_fs_i.h
include/linux/proc_fs.h
include/linux/sched.h
include/linux/sysv_fs.h
include/net/ip.h
init/main.c
ipc/shm.c
kernel/exit.c
kernel/fork.c
kernel/ksyms.c
kernel/ptrace.c
kernel/time.c
mm/mlock.c
mm/mmap.c
mm/mprotect.c
mm/mremap.c
mm/vmscan.c
net/core/dst.c
net/core/skbuff.c
net/ipv4/tcp_ipv4.c
net/sunrpc/clnt.c
net/sunrpc/sched.c

index f910c4c7e8ab2de34192a070c5ae4b9578ad01e1..7048d0f14c60b7d144b34ffa0f034f913b165005 100644 (file)
@@ -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
 ================
index 807d2875511ba3472c4b9d6277614e82e6a1ae02..9dc8623641a714156e0e48f1c7788cf133c837c9 100644 (file)
@@ -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 (file)
index 0000000..6efdcec
--- /dev/null
@@ -0,0 +1,88 @@
+Started Oct 1999 by Kanoj Sarcar <kanoj@sgi.com>
+
+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. 
index 67c855554f99af3ebf82f598cdfa861977fba88c..628715592dad70de4d1a98fdded71a7cf6f80460 100644 (file)
@@ -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
index ce85d6ffc469e1c4fe9238d452d11f8f038430a7..2641675c38da1facf9bde8346cd2b381b0003143 100644 (file)
@@ -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
index 4f1ec7e28e2b230b6a5be622812bf6dcf6cd8e76..6ede3c2f519eb90fbf3e8c79c3d4645d0adcb880 100644 (file)
@@ -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
index 9978cac9d67753d3597be20fef50e440536faaa8..37b2371a0bcf125e3664935079f5ad881dd3cbe1 100644 (file)
@@ -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
index 9d373d1ed3f72069ae6197ffe5d2258044791322..529b648beeab394e84ec4061434599feaa2ca99f 100644 (file)
@@ -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
index 63620c635facfe3119d0fe2a48fe1da7b3313ec9..8a954ce8b6165f5516eedd3ef7e737bea12eac9f 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <asm/smp.h>
 #include <asm/lithium.h>
+#include <asm/io.h>
 
 #include "pci-i386.h"
 
index de79fe61e07551e0aec9c92a7f4304d9a50c4bd4..6c767d0ebff8b1e512ed06e907b9dc4ce70ab31f 100644 (file)
@@ -37,7 +37,7 @@
 
 #include <asm/cobalt.h>
 
-#include "irq.h"
+#include <linux/irq.h>
 
 /*
  * This is the PIIX4-based 8259 that is wired up indirectly to Cobalt
diff --git a/arch/i386/vmlinux.lds b/arch/i386/vmlinux.lds
new file mode 100644 (file)
index 0000000..9624cae
--- /dev/null
@@ -0,0 +1,75 @@
+/* ld script to make i386 Linux kernel
+ * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
+ */
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+SECTIONS
+{
+  . = 0xC0000000 + 0x100000;
+  _text = .;                   /* Text and read-only data */
+  .text : {
+       *(.text)
+       *(.fixup)
+       *(.gnu.warning)
+       } = 0x9090
+  .text.lock : { *(.text.lock) }       /* out-of-line lock text */
+  .rodata : { *(.rodata) }
+  .kstrtab : { *(.kstrtab) }
+
+  . = ALIGN(16);               /* Exception table */
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  __start___ksymtab = .;       /* Kernel symbol table */
+  __ksymtab : { *(__ksymtab) }
+  __stop___ksymtab = .;
+
+  _etext = .;                  /* End of text section */
+
+  .data : {                    /* Data */
+       *(.data)
+       CONSTRUCTORS
+       }
+
+  _edata = .;                  /* End of data section */
+
+  . = ALIGN(8192);             /* init_task */
+  .data.init_task : { *(.data.init_task) }
+
+  . = ALIGN(4096);             /* Init code and data */
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(16);
+  __setup_start = .;
+  .setup.init : { *(.setup.init) }
+  __setup_end = .;
+  __initcall_start = .;
+  .initcall.init : { *(.initcall.init) }
+  __initcall_end = .;
+  . = ALIGN(4096);
+  __init_end = .;
+
+  . = ALIGN(4096);
+  .data.page_aligned : { *(.data.idt) }
+
+  . = ALIGN(32);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+  __bss_start = .;             /* BSS */
+  .bss : {
+       *(.bss)
+       }
+  _end = . ;
+
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+}
diff --git a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds.S
deleted file mode 100644 (file)
index 9a9ff07..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/* ld script to make i386 Linux kernel
- * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
- */
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-ENTRY(_start)
-SECTIONS
-{
-  . = PAGE_OFFSET_RAW + 0x100000;
-  _text = .;                   /* Text and read-only data */
-  .text : {
-       *(.text)
-       *(.fixup)
-       *(.gnu.warning)
-       } = 0x9090
-  .text.lock : { *(.text.lock) }       /* out-of-line lock text */
-  .rodata : { *(.rodata) }
-  .kstrtab : { *(.kstrtab) }
-
-  . = ALIGN(16);               /* Exception table */
-  __start___ex_table = .;
-  __ex_table : { *(__ex_table) }
-  __stop___ex_table = .;
-
-  __start___ksymtab = .;       /* Kernel symbol table */
-  __ksymtab : { *(__ksymtab) }
-  __stop___ksymtab = .;
-
-  _etext = .;                  /* End of text section */
-
-  .data : {                    /* Data */
-       *(.data)
-       CONSTRUCTORS
-       }
-
-  _edata = .;                  /* End of data section */
-
-  . = ALIGN(8192);             /* init_task */
-  .data.init_task : { *(.data.init_task) }
-
-  . = ALIGN(4096);             /* Init code and data */
-  __init_begin = .;
-  .text.init : { *(.text.init) }
-  .data.init : { *(.data.init) }
-  . = ALIGN(16);
-  __setup_start = .;
-  .setup.init : { *(.setup.init) }
-  __setup_end = .;
-  __initcall_start = .;
-  .initcall.init : { *(.initcall.init) }
-  __initcall_end = .;
-  . = ALIGN(4096);
-  __init_end = .;
-
-  . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
-
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
-  __bss_start = .;             /* BSS */
-  .bss : {
-       *(.bss)
-       }
-  _end = . ;
-
-  /* Stabs debugging sections.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  .stab.excl 0 : { *(.stab.excl) }
-  .stab.exclstr 0 : { *(.stab.exclstr) }
-  .stab.index 0 : { *(.stab.index) }
-  .stab.indexstr 0 : { *(.stab.indexstr) }
-  .comment 0 : { *(.comment) }
-}
index da752ccb63b711ea2b9027843eb67ccfbab53bef..983a9f2eb3d206bab044eb31aa5b7ebc251ec18b 100644 (file)
@@ -16,7 +16,6 @@
 #include <asm/hydra.h>
 #include <asm/prom.h>
 #include <asm/gg2.h>
-#include <asm/ide.h>
 #include <asm/machdep.h>
 
 #include "pci.h"
index 4f71def9adc16e8b2ce3c5088e3283d164ddf377..934f377b50c9fad3b8aadf20b7e00d1e54e03a7c 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/reboot.h>
 #include <linux/init.h>
 #include <linux/blk.h>
+#include <linux/ide.h>
 #include <linux/ioport.h>
 #include <linux/console.h>
 #include <linux/pci.h>
@@ -40,8 +41,6 @@
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
-#include <linux/ide.h>
-#include <asm/ide.h>
 #include <asm/prom.h>
 #include <asm/gg2.h>
 #include <asm/pci-bridge.h>
index 67cab4503d821648d0f94e7a683036ff898a0168..5ba7d878e914ecd8fa3000e790e7b6b8568758b3 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/reboot.h>
 #include <linux/init.h>
 #include <linux/blk.h>
+#include <linux/ide.h>
 #include <linux/ioport.h>
 
 #include <asm/mmu.h>
@@ -37,7 +38,6 @@
 #include <asm/residual.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
-#include <asm/ide.h>
 #include <asm/mbx.h>
 #include <asm/machdep.h>
 
index 3418a7e8b7b340cfda753c9477df3cba52371fe0..41ff21aed173060bf0e595dacc59b6b4f5ae2049 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/ioport.h>
 #include <linux/major.h>
 #include <linux/blk.h>
+#include <linux/ide.h>
 #include <linux/vt_kern.h>
 #include <linux/console.h>
 #include <linux/ide.h>
@@ -57,7 +58,6 @@
 #include <asm/ohare.h>
 #include <asm/mediabay.h>
 #include <asm/feature.h>
-#include <asm/ide.h>
 #include <asm/machdep.h>
 #include <asm/keyboard.h>
 #include <asm/dma.h>
@@ -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)
 {
index 53c859a162a523adcd7f4db6379788885d052663..a04347d4b97be4a7613604f95dcd2b00481ea4c1 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/residual.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
-#include <asm/ide.h>
 #include <asm/cache.h>
 #include <asm/dma.h>
 #include <asm/machdep.h>
index 57955efcac5249269a24598993213e42772ff8f1..7177c800677b58095cbda24efee4ca115a23769d 100644 (file)
 #include <linux/reboot.h>
 #include <linux/delay.h>
 #include <linux/blk.h>
+#include <linux/ide.h>
 
 #include <asm/init.h>
 #include <asm/residual.h>
 #include <asm/io.h>
-#include <linux/ide.h>
-#include <asm/ide.h>
 #include <asm/prom.h>
 #include <asm/processor.h>
 #include <asm/pgtable.h>
index 494717c54461aabedc64a57c58b24ce149e5b154..7080efb3ec99feba17a5741e907b685dccfb8f93 100644 (file)
@@ -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
index c1c6f1e29f3e20f63d0832871cdb36fed06335e1..31fcf5d694a553ac3e426759133d5536573075b1 100644 (file)
@@ -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
 #
 # 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
index 48874a0f0f9cb4d22ffa7dd2916b9456c42d3db7..516dc37484ef61370365b2a469961e2767e623e8 100644 (file)
@@ -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
index bd830d4a954e15fda1d0fc1a7ee8f7c69d306c12..dcf006a15e07ade4c1be68124563d4fa9c73fa6c 100644 (file)
 #
 # 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
index 0a2abf8587c399ee084f78ef424803ab9f742544..6cf0b319efe47a73e1fa8c268bbb8f0e324abc17 100644 (file)
@@ -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  :=
 
index 7fca58b30cb079cd54553e37c1d725a26b17fea6..ebec230b8a81e440cdcbce658b57e4aedee92451 100644 (file)
@@ -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 <linux/sys.h>
 #include <linux/linkage.h>
+#include <linux/config.h>
 
 ! NOTE:
 ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
  * 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)
index ed466ba38921296175f8f730688489e850be7a74..eda9e347d1c212cfa68ab7ab976ec4d262d82e3a 100644 (file)
@@ -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
  *
  * Head.S contains the SH exception handlers and startup code.
  */
-#include <linux/config.h>
-#include <linux/threads.h>
 #include <linux/linkage.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
 
-#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
index f75af500369a98db8a117d594acda29ef2492d97..e87972c737ca1fbd4f24d6b18b69a1ceeba555ce 100644 (file)
@@ -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, &regs, 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);
 }
 
 /*
index 2eae049e5beccf4ef70e9fc934ae2162c05b1fb6..fbce65fcb0805b0fedb42941ac0747bb755bd76e 100644 (file)
@@ -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
 
 #include <linux/irq.h>
 
-
-/*
- * 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)
index 744da694b6ed206887d935ecfb4ff8d6317dba22..9d90c013318156fac9853223a9108b7d649a29ee 100644 (file)
@@ -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
  */
 
 /*
 
 #include <linux/irq.h>
 
+#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, &current->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], &current->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], &regs);
+       return do_fork(SIGCHLD, regs.sp, &regs);
 }
 
 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, &regs);
 }
 
@@ -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], &regs);
+       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.sp, &regs);
 }
 
 /*
index 6714fd96d6ab73fb610bd0679873230f0b5cf43a..3053656e7315bdd8e6cbed8b538d9eacc9270c22 100644 (file)
@@ -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 <asm/processor.h>
 #include <linux/console.h>
+#include <asm/pgtable.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/io.h>
@@ -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,
index 66fa36c85613352090f4b1f80a30f76e4fff89cd..8583afff15a8704bf4a380a2bfd55d93c3e3771e 100644 (file)
@@ -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 <linux/config.h>
-
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -24,6 +23,7 @@
 #include <linux/stddef.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
+#include <asm/pgtable.h>
 
 #define DEBUG_SIG 0
 
@@ -50,7 +50,7 @@ sys_sigsuspend(old_sigset_t mask,
        recalc_sigpending(current);
        spin_unlock_irq(&current->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(&current->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;
                }
        }
index 6999cff81fa2aeab78d1dbc5b9e9fc62a4d7565e..a485f10a388ca892310b9b8037815e4e8e418836 100644 (file)
@@ -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 <linux/errno.h>
@@ -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(&current->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(&current->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 (file)
index daade9f..0000000
+++ /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,
-};
index 6f4598a7e0abb7bb6481951be703d9a3565dc30a..42bdf2febf49762a3f119fe52f0d67477ca751ff 100644 (file)
@@ -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 <linux/config.h>
+
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/timex.h>
 #include <linux/irq.h>
 
+#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 */
 
 #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("");
index 3d3cba23cf39623961b9eb53e7f2e841634c4180..8a9b3e1f9b87c9b66f19975abd19ee3051876a6a 100644 (file)
@@ -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);
 }
index a9010ddb207f82075130586b8d134cac02b2b80a..934c84744c59feb7bcc06501b81392ecdfbfcd38 100644 (file)
@@ -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 (file)
index 0000000..8eb4c05
--- /dev/null
@@ -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, <jorge@laser.satlink.net>
+ *             Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ *             Tom May, <ftom@netcom.com>
+ *              Pentium Pro/II routines:
+ *              Alexander Kjeldaas <astor@guardian.no>
+ *              Finn Arne Gangstad <finnag@guardian.no>
+ *             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 <asm/errno.h>
+#include <linux/linkage.h>
+
+/*
+ * 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 (file)
index f076bd3..0000000
+++ /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 <linux/string.h>
-
-#include <asm/byteorder.h>
-
-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 (file)
index 1fb36ab..0000000
+++ /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, <ralf@waldorf-gmbh.de>
- *             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 <net/checksum.h>
-#include <linux/types.h>
-#include <asm/byteorder.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-/*
- * 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;
-}
index 3a4aca9190f63bf990d3039ddc429de30c41d4f3..6f31216620f8946eb768408a6e0dea8b16c5984a 100644 (file)
-! 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 <linux/linkage.h>
 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
index e95dc3709778b55a7c1ddc4dd16b8daecf78dcaf..61b97b7c2a46b5da8d0254427a3d2681223d30cd 100644 (file)
+/* $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 <linux/linkage.h>
 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<r5)
+        mov.b  r1,@(r0,r4)
+       add     #1,r4
+9:
+       add     r4,r0
+       rts
+        sub    r6,r0
+
+case_none:
+       bra     8b
+        add    #-1,r4
+
+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    #-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<r5)
+        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    #5,r4
+       add     #-3,r0
+       bra     8b
+        add    #-1,r4
index c97648a4a19a57f2c0dc3b9e192388a204727a7a..312d605e4debb6610bfacb18df566d8af45bca21 100644 (file)
@@ -1,72 +1,57 @@
-! Taken from newlib-1.8.0
+/* $Id: memset.S,v 1.1 1999/09/18 16:57:09 gniibe Exp $
+ *
+ * "memset" implementation of SuperH
+ *
+ * Copyright (C) 1999  Niibe Yutaka
+ *
+ */
+
+/*
+ *            void *memset(void *s, int c, size_t n);
+ */
 
-!
-! Fast SH memset
-!
-! by Toshiyasu Morita (tm@netcom.com)
-!
-! Entry: r4: destination pointer
-!        r5: fill value
-!        r6: byte count
-!
-! Exit:  r0-r3: trashed
-!
 #include <linux/linkage.h>
 
 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
index ae3a38043a7f2ad2c66558a708e749556a210a04..df741335d367b2812ae11edd296e62b5872bcf61 100644 (file)
@@ -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 (file)
index c116623..0000000
+++ /dev/null
@@ -1,1289 +0,0 @@
-#include <linux/linkage.h>
-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:
index c89c2b9e36aeb7be53766d408494abb69970413a..981c25380d76cf1c3c4c093a49dcea36e01c6576 100644 (file)
@@ -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 (file)
index 0000000..d15c623
--- /dev/null
@@ -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 <linux/init.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/threads.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#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; j<CACHE_IC_NUM_WAYS; j++) {
+                       addr = CACHE_IC_ADDRESS_ARRAY|(j<<CACHE_IC_WAY_SHIFT)|
+                               (v&CACHE_IC_ENTRY_MASK);
+                       data = ctrl_inl(addr);
+                       if ((data & 0xfffffc00) == (p&0xfffffc00)
+                           && (data & CACHE_VALID)) {
+                               data &= ~CACHE_VALID;
+                               ctrl_outl(data,addr);
+                               break;
+                       }
+               }
+#if CACHE_IC_ADDRESS_ARRAY != CACHE_OC_ADDRESS_ARRAY
+               asm volatile("ocbi      %0"
+                            : /* no output */
+                            : "m" (__m(v)));
+#endif
+       }
+       back_to_p1(__dummy);
+       restore_flags(flags);
+}
+
+/* write back the dirty cache, but not invalidate the cache */
+void cache_wback_area(unsigned long start, unsigned long end)
+{
+       unsigned long flags, __dummy;
+       unsigned long v;
+
+       start &= ~(L1_CACHE_BYTES-1);
+       save_and_cli(flags);
+       jump_to_p2(__dummy);
+
+       for (v = start; v < end; v+=L1_CACHE_BYTES) {
+#if CACHE_IC_ADDRESS_ARRAY == CACHE_OC_ADDRESS_ARRAY
+               unsigned long addr, data, j;
+               unsigned long p = __pa(v);
+
+               for (j=0; j<CACHE_OC_NUM_WAYS; j++) {
+                       addr = CACHE_OC_ADDRESS_ARRAY|(j<<CACHE_OC_WAY_SHIFT)|
+                               (v&CACHE_OC_ENTRY_MASK);
+                       data = ctrl_inl(addr);
+                       if ((data & 0xfffffc00) == (p&0xfffffc00)
+                           && (data & CACHE_VALID)
+                           && (data & CACHE_UPDATED)) {
+                               data &= ~CACHE_UPDATED;
+                               ctrl_outl(data,addr);
+                               break;
+                       }
+               }
+#else
+               asm volatile("ocbwb     %0"
+                            : /* no output */
+                            : "m" (__m(v)));
+#endif
+       }
+       back_to_p1(__dummy);
+       restore_flags(flags);
+}
+
+/*
+ * Write back the cache.
+ *
+ * For SH-4, flush (write back) Operand Cache, as Instruction Cache
+ * doesn't have "updated" data.
+ */
+static void cache_wback_all(void)
+{
+       unsigned long flags, __dummy;
+       unsigned long addr, data, i, j;
+
+       save_and_cli(flags);
+       jump_to_p2(__dummy);
+
+       for (i=0; i<CACHE_OC_NUM_ENTRIES; i++) {
+               for (j=0; j<CACHE_OC_NUM_WAYS; j++) {
+                       addr = CACHE_OC_ADDRESS_ARRAY|(j<<CACHE_OC_WAY_SHIFT)|
+                               (i<<CACHE_OC_ENTRY_SHIFT);
+                       data = ctrl_inl(addr);
+                       if (data & CACHE_VALID) {
+                               data &= ~(CACHE_VALID|CACHE_UPDATED);
+                               ctrl_outl(data,addr);
+                       }
+               }
+       }
+
+       back_to_p1(__dummy);
+       restore_flags(flags);
+}
+
+static void
+detect_cpu_and_cache_system(void)
+{
+#if defined(__sh3__)
+       unsigned long __dummy, addr0, addr1, data0, data1, data2, data3;
+
+       jump_to_p2(__dummy);
+       /* Check if the entry shadows or not.
+        * When shadowed, it's 128-entry system.
+        * Otherwise, it's 256-entry system.
+        */
+       addr0 = CACHE_OC_ADDRESS_ARRAY + (3 << 12);
+       addr1 = CACHE_OC_ADDRESS_ARRAY + (1 << 12);
+       data0  = ctrl_inl(addr0);
+       data0  ^= 0x00000001;
+       ctrl_outl(data0,addr0);
+       data1 = ctrl_inl(addr1);
+       data2 = data1 ^ 0x00000001;
+       ctrl_outl(data2,addr1);
+       data3 = ctrl_inl(addr0);
+
+       /* Invaliate them, in case the cache has been enabled already. */
+       ctrl_outl(data0&~0x00000001,addr0);
+       ctrl_outl(data2&~0x00000001,addr1);
+       back_to_p1(__dummy);
+
+       if (data0 == data1 && data2 == data3) { /* Shadow */
+               cache_system_info.way_shift = 11;
+               cache_system_info.entry_mask = 0x7f0;
+               cache_system_info.num_entries = 128;
+               cpu_data->type = 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
index 35c4451ebcdfde67f9a92cbbedd8c7c25bf76fcf..dc77f57fe2438317a9de8ab0776bee0e8d2dd711 100644 (file)
@@ -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
index c1348d5b4a3c6072385cbdbda46dfafa747ec73e..595e413457a65c1fb2e2b2bfbe0fe73082cd9b05 100644 (file)
@@ -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 <linux/interrupt.h>
 
 #include <asm/system.h>
+#include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/hardirq.h>
@@ -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);
 }
index 3a6bfc1a2ba50bcb315f28386469cf1c9d1a14e9..56ab03cf9bc8306e58620d8bd954132ea0ed4a61 100644 (file)
@@ -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 <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
+#include <asm/io.h>
 
 /*
  * 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)
 {
index f786379cfc790cd64e10ac608851ee26583ba2d2..90fd190eff9bc520c774809fb5837a727b2dd382 100644 (file)
@@ -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.
index a812c91f8f61dad9bf4016cce06aeac6a3401f83..688c4c9c4b92aa91107a8fc464810ddb1b4bece6 100644 (file)
@@ -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 <linux/config.h>
@@ -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 : {
index c23b8d094b4c0292d885b5a0d6d697bb60acbe4e..7f70e32eed7fa94ad384b7d7c07d46a2d24bc476 100644 (file)
@@ -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
index 8519318d93f01469188b70c06b1f9e23118fee9e..1de4fa58139fd32c5296a1f07d04c4535dec1669 100644 (file)
@@ -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
-
index c52d8450db07f1f91cd516f5f3dd659070819880..75bb8657fb4dc9067c672a45a05c41405389a8de 100644 (file)
@@ -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
 #include <asm/io.h>
 #include <asm/irq.h>
 
+/*
+ * 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) {
index b7a0a5c4f46273ef7d532d234e413fdea2c75f35..5453610523a9e58723b4f017368b65182fa91056 100644 (file)
@@ -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 <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/hdreg.h>
 #include <linux/ide.h>
 
 #include <asm/io.h>
@@ -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);
+}
index e204bc0e6d76e1403974950bda4999b430796974..77fdf08210a7be174f36937bf2540951a1458e5e 100644 (file)
@@ -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);
 }
 
index 284bf40bc08e7917f0cf277e59887f786abb39ec..816b4b8059027d1426e50d363c98fb645d359d89 100644 (file)
@@ -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 <linux/config.h>
@@ -58,7 +57,7 @@ static void hpt34x_clear_chipset (ide_drive_t *drive)
        pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, &reg1);
        pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, &reg2);
        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;
 }
 
index b61f7168727ef57ccae6839754f4e67109e8b225..d45b5f71926781d9c4cfbb0ab990e255df7222f3 100644 (file)
@@ -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 <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 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 <linux/types.h>
@@ -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, &reg1);
-       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, &reg51h);
+               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, &reg40);
+       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, &reg40);
+       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);
+}
index 629ad927dedf54cafe9e87f3bb260f19a1ee1968..a9282de3fa5b09d987e8a23e0544cb495f305a78 100644 (file)
@@ -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);
 
index b3ba0356226f61d506e5fa1dfea9ccc712e3e09c..9977809abc76b8702aeb398da5dc9f215ae8ab5e 100644 (file)
@@ -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;
 }
index ae1a252edb231b66f6fd608c058e3ad1981b7f1f..e87c0b4311fe6b8c38da3df1d717130cdbe9c070 100644 (file)
@@ -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))
index d2941a1ab7a8cea13ba21161eed934ec0897f03c..8fa7745b4d567b17fececcea59f144bff635f1f3 100644 (file)
@@ -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)
index d3c65751677080b2057a664c62cde8e0d8a39327..b1d0979c3ba9c9b7ccb2b5cc0b9e25523732b846 100644 (file)
@@ -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);
index f1c8baef8bc4346988fb7226b73b68b8e8139cf0..3db1c1515644511d6d3c06e23ce15986a6f81e23 100644 (file)
@@ -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;
index 974fb24f19623866db849d1ad5367cb6b79e93e8..44aa1844df4dafaee30202df75edff40258cc3e7 100644 (file)
@@ -5,6 +5,9 @@
 
 #include <asm/io.h>
 
+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
index 311bd470bfac0574d415934be4f6be4bb362901e..73ffa67ea7b1f85c7a1e0da538ffb34e6903817c 100644 (file)
@@ -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);
 }
 
 /*
index 1ad5b3b969ac95f27a910ed74bd01d6ffc86f967..c3e800249b02914a61d6a994646cca6c9854741a 100644 (file)
@@ -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:
index 62008341eff1b4bdbd868bdaf56a85c7b88441ad..d430c5b1d97a817afe5c9f0776e502f004e8b923 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/delay.h>
 #include <linux/ide.h>
 
-
 #include <asm/byteorder.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
@@ -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? */
index 8afe1568f3e0313a1910c0c6e7e5cb12210f034f..48d77c1607f80773cf4a878444b5cf3b94d3609e 100644 (file)
 #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);
index 6e8313733b3636f5eb30e1011bc9be7415eede36..bbf222338bd62c2520ea98b46479bbfccc3c49f2 100644 (file)
@@ -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.
index d2cb4b34b4e1da3fc58748a2cbcccdf567d31db6..1a506e3536ebe7601eb04138d701116d3a87bade 100644 (file)
 #include <linux/kmod.h>
 #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);
        }
 }
index 0275173205cc4567abc199dccfe2722cccf63635..96e0e421e82c9b18d5cdc7a45f2987ebbeaa0173 100644 (file)
@@ -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<PCD_UNITS;unit++) {
+               if (!PCD.present) continue;
+               r = pcd_atapi(unit,cmd,18, buffer,"mode sense capabilities");
+               if (r) continue;
+               /* we should now have the cap page */
+               if ((buffer[11] & 1) == 0)
+                       PCD.info.mask |= CDC_CD_R;
+               if ((buffer[11] & 2) == 0)
+                       PCD.info.mask |= CDC_CD_RW;
+               if ((buffer[12] & 1) == 0)
+                       PCD.info.mask |= CDC_PLAY_AUDIO;
+               if ((buffer[14] & 1) == 0)
+                       PCD.info.mask |= CDC_LOCK;
+               if ((buffer[14] & 8) == 0)
+                       PCD.info.mask |= CDC_OPEN_TRAY;
+               if ((buffer[14] >> 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;
index aeffcc9ba93908588b1af8cec86203c31e1ddf1c..2155aa8af6ef481b88094066d658b85872d27432 100644 (file)
@@ -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.
  *      = ((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 <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
@@ -88,6 +94,8 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
+#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;
        }
 }
index 84fbb48561da9e5090641142a6a49e48d00534fd..d53c2d394a059778cfcf7b17d0d452ff164b7f43 100644 (file)
@@ -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);
index b1fd76014baa93d212649fa4855419bd72c04645..a9bcb347cf228598b7cd61dab6376708080ccabb 100644 (file)
@@ -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;
 
index 08bbb1c9168ffc454ea41cd01a9d9590d5c3ff15..8a3abd0253a53d989e8df9b6acd04e199a27be7d 100644 (file)
@@ -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 <linux/types.h>
 
 #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 <linux/stat.h>
+#include <linux/proc_fs.h>
+
+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, &reg);
+       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, &reg);
+       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, &reg);
+       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, &reg2);
+       rc = pci_read_config_word(bmide_dev, 0x4e, &reg3);
+       p += sprintf(p, "Prefetch Count: %d \t \t \t \t %d\n",
+                    reg2, reg3);
+
+       rc = pci_read_config_byte(bmide_dev, 0x4b, &reg);            
+       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, &reg);
+       rc = pci_read_config_byte(bmide_dev, 0x45, &reg1);
+       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, &reg);
+       rc = pci_read_config_byte(bmide_dev, 0x44, &reg1);
+       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, &reg);            
+       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, &reg);
+       rc = pci_read_config_byte(bmide_dev, 0x47, &reg1);
+       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, &reg);
+       rc = pci_read_config_byte(bmide_dev, 0x46, &reg1);
+       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, &reg48h);
 
        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, &reg52h);
                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, &reg48h);
+
+       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;
 }
index ad6a75d0f8dfbeda8f89bbab13fdccb1a47cadc2..5c7c8fd3c70e86bee47d087d0d0aca87cb1e6b2d 100644 (file)
@@ -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/via82c586.c
deleted file mode 100644 (file)
index e569701..0000000
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- * linux/drivers/block/via82c586.c     Version 0.04    July 11, 1999
- *
- *  Copyright (C) 1998 Michel Aubry, Maintainer
- *  Copyright (C) 1998 Andre Hedrick, Maintainer
- *
- *  The VIA MVP-3 is reported OK with UDMA.
- *  The TX Pro III is also reported OK with UDMA.
- *
- *  VIA chips also have a single FIFO, with the same 64 bytes deep
- *  buffer (16 levels of 4 bytes each).
- *
- *  However, VIA chips can have the buffer split either 8:8 levels,
- *  16:0 levels or 0:16 levels between both channels. One could think
- *  of using this feature, as even if no level of FIFO is given to a
- *  given channel, one can for instance always reach ATAPI drives through
- *  it, or, if one channel is unused, configuration defaults to
- *  an even split FIFO levels.
- *  
- *  This feature is available only through a kernel command line :
- *             "splitfifo=Chan,Thr0,Thr1" or "splitfifo=Chan".
- *             where:  Chan =1,2,3 or 4 and Thrx = 1,2,3,or 4.
- *
- *  If Chan == 1:
- *     gives all the fifo to channel 0,
- *     sets its threshold to Thr0/4,
- *     and disables any dma access to channel 1.
- *
- *  If chan == 2:
- *     gives all the fifo to channel 1,
- *     sets its threshold to Thr1/4,
- *     and disables any dma access to channel 0.
- *
- *  If chan == 3 or 4:
- *     shares evenly fifo between channels,
- *     gives channel 0 a threshold of Thr0/4,
- *     and channel 1 a threshold of Thr1/4.
- *
- *  Note that by default (if no command line is provided) and if a channel
- *  has been disabled in Bios, all the fifo is given to the active channel,
- *  and its threshold is set to 3/4.
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/blkdev.h>
-#include <linux/hdreg.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/ide.h>
-
-#include <asm/io.h>
-
-static struct pci_dev *host_dev;
-static struct pci_dev *isa_dev;
-
-#define DISPLAY_VIA_TIMINGS
-
-#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static char *FIFO_str[] = {
-       " 1 ",
-       "3/4",
-       "1/2",
-       "1/4"
-};
-
-static char *control3_str[] = {
-       "No limitation",
-       "64",
-       "128",
-       "192"
-};
-
-static int via_get_info(char *, char **, off_t, int, int);
-extern int (*via_display_info)(char *, char **, off_t, int, int); /* ide-proc.c */
-static struct pci_dev *bmide_dev;
-
-static char * print_apollo_drive_config (char *buf, struct pci_dev *dev)
-{
-       int rc;
-       unsigned int time;
-       byte tm;
-       char *p = buf;  
-       /* Drive Timing Control */
-       rc = pci_read_config_dword(dev, 0x48, &time);
-       p += sprintf(p, "Act Pls Width:  %02d          %02d           %02d          %02d\n",
-                       ((time & 0xf0000000)>>28) + 1,
-                       ((time & 0xf00000)>>20) + 1,
-                       ((time & 0xf000)>>12) + 1,
-                       ((time & 0xf0)>>4) + 1 );
-       p += sprintf(p, "Recovery Time:  %02d          %02d           %02d          %02d\n",
-                       ((time & 0x0f000000)>>24) + 1,
-                       ((time & 0x0f0000)>>16) + 1,
-                       ((time & 0x0f00)>>8) + 1,
-                       (time & 0x0f) + 1 );
-       /* Address Setup Time */
-       rc = pci_read_config_byte(dev, 0x4C, &tm);
-       p += sprintf(p, "Add. Setup T.:  %01dT          %01dT           %01dT          %01dT\n",
-                       ((tm & 0xc0)>>6) + 1,
-                       ((tm & 0x30)>>4) + 1,
-                       ((tm & 0x0c)>>2) + 1,
-                       (tm & 0x03) + 1 );
-       /* UltraDMA33 Extended Timing Control */
-       rc = pci_read_config_dword(dev, 0x50, &time);
-       p += sprintf(p, "------------------UDMA-Timing-Control------------------------\n");
-       p += sprintf(p, "Enable Meth.:    %01d           %01d            %01d           %01d\n",
-                       (time & 0x80000000)     ? 1 : 0,
-                       (time & 0x800000)       ? 1 : 0,
-                       (time & 0x8000)         ? 1 : 0,
-                       (time & 0x80)           ? 1 : 0 );
-       p += sprintf(p, "Enable:         %s         %s          %s         %s\n",
-                       (time & 0x40000000)     ? "yes" : "no ",
-                       (time & 0x400000)       ? "yes" : "no ",
-                       (time & 0x4000)         ? "yes" : "no ",
-                       (time & 0x40)           ? "yes" : "no " );
-       p += sprintf(p, "Transfer Mode: %s         %s          %s         %s\n",
-                       (time & 0x20000000)     ? "PIO" : "DMA",
-                       (time & 0x200000)       ? "PIO" : "DMA",
-                       (time & 0x2000)         ? "PIO" : "DMA",
-                       (time & 0x20)           ? "PIO" : "DMA" );
-       p += sprintf(p, "Cycle Time:     %01dT          %01dT           %01dT          %01dT\n",
-                       ((time & 0x03000000)>>24) + 2,
-                       ((time & 0x030000)>>16) + 2,
-                       ((time & 0x0300)>>8) + 2,
-                       (time & 0x03) + 2 );
-       return (char *)p;
-}
-
-static char * print_apollo_ide_config (char *buf, struct pci_dev *dev)
-{
-       byte time, tmp; 
-       unsigned short size0, size1;
-       int rc;
-       char *p = buf;  
-       rc = pci_read_config_byte(dev, 0x41, &time);
-       p += sprintf(p, "Prefetch Buffer :      %s                     %s\n",
-               (time & 128)    ? "on " : "off",
-               (time & 32)     ? "on " : "off" );
-       p += sprintf(p, "Post Write Buffer:     %s                     %s\n",
-               (time & 64)     ? "on " : "off",
-               (time & 16)     ? "on " : "off" );
-       /* FIFO configuration */
-       rc = pci_read_config_byte(dev, 0x43, &time);
-       tmp = ((time & 0x20)>>2) + ((time & 0x40)>>3);
-       p += sprintf(p, "FIFO Conf/Chan. :      %02d                      %02d\n",
-                       16 - tmp, tmp);
-       tmp = (time & 0x0F)>>2;
-       p += sprintf(p, "Threshold Prim. :      %s                     %s\n",
-                       FIFO_str[tmp],
-                       FIFO_str[time & 0x03] );
-       /* chipset Control3 */
-       rc = pci_read_config_byte(dev, 0x46, &time);
-       p += sprintf(p, "Read DMA FIFO flush:   %s                     %s\n",
-                       (time & 0x80)   ? "on " : "off",
-                       (time & 0x40)   ? "on " : "off" );
-       p += sprintf(p, "End Sect. FIFO flush:  %s                     %s\n",
-                       (time & 0x20)   ? "on " : "off",
-                       (time & 0x10)   ? "on " : "off" );
-       p += sprintf(p, "Max DRDY Pulse Width:  %s %s\n",
-                       control3_str[(time & 0x03)],
-                       (time & 0x03) ? "PCI clocks" : "" );
-       /* Primary and Secondary sector sizes */
-       rc = pci_read_config_word(dev, 0x60, &size0);
-       rc = pci_read_config_word(dev, 0x68, &size1);
-       p += sprintf(p, "Bytes Per Sector:      %03d                     %03d\n",
-                       size0 & 0xfff,
-                       size1 & 0xfff );
-
-       return (char *)p;
-}
-
-static char * print_apollo_chipset_control1 (char *buf, struct pci_dev *dev)
-{
-       byte t;
-       int rc;
-       char *p = buf;  
-       unsigned short c;
-       byte l, l_max;   
-       rc = pci_read_config_word(dev, 0x04, &c);
-       rc = pci_read_config_byte(dev, 0x44, &t);
-       rc = pci_read_config_byte(dev, 0x0d, &l);
-       rc = pci_read_config_byte(dev, 0x3f, &l_max);
-
-       p += sprintf(p, "Command register = 0x%x\n", c);
-       p += sprintf(p, "Master Read  Cycle IRDY %d Wait State\n",
-                       (t & 64) >>6 );
-       p += sprintf(p, "Master Write Cycle IRDY %d Wait State\n",
-                       (t & 32) >> 5 );
-       p += sprintf(p, "FIFO Output Data 1/2 Clock Advance: %s\n",
-                       (t & 16) ? "on " : "off" );
-       p += sprintf(p, "Bus Master IDE Status Register Read Retry: %s\n",
-                       (t & 8) ? "on " : "off" );
-       p += sprintf(p, "Latency timer = %d (max. = %d)\n",
-                       l, l_max);
-
-       return (char *)p;
-}
-static char * print_apollo_chipset_control2 (char *buf, struct pci_dev *dev)
-{
-       byte t;
-       int rc;
-       char *p = buf;  
-       rc = pci_read_config_byte(dev, 0x45, &t);
-       p += sprintf(p, "Interrupt Steering Swap: %s\n",
-                       (t & 64) ? "on ":"off" );
-
-       return (char *)p;
-}
-static char * print_apollo_chipset_control3 (char *buf, struct pci_dev *dev,
-                                               unsigned short n)
-{
-       /*
-        * at that point we can be sure that register 0x20 of the
-        * chipset contains the right address...
-        */
-       unsigned int bibma;
-       int rc;
-       byte c0, c1;    
-       char *p = buf; 
-       rc = pci_read_config_dword(dev, 0x20, &bibma);
-       bibma = (bibma & 0xfff0) ;
-       /*
-        * at that point bibma+0x2 et bibma+0xa are byte registers
-        * to investigate:
-        */
-       c0 = inb((unsigned short)bibma + 0x02);
-       c1 = inb((unsigned short)bibma + 0x0a);
-       if (n == 0) {
-        /*p = sprintf(p,"--------------------Primary IDE------------Secondary IDE-----");*/
-               p += sprintf(p, "both channels togth:   %s                     %s\n",
-                               (c0&0x80) ? "no" : "yes",
-                               (c1&0x80) ? "no" : "yes" );
-       } else {
-        /*p = sprintf(p,"--------------drive0------drive1-------drive0------drive1----");*/
-               p += sprintf(p, "DMA enabled:    %s         %s          %s         %s\n",
-                               (c0&0x20) ? "yes" : "no ",
-                               (c0&0x40) ? "yes" : "no ",
-                               (c1&0x20) ? "yes" : "no ",
-                               (c1&0x40) ? "yes" : "no " );
-       }
-       return (char *)p;
-}
-
-static int via_get_info (char *buffer, char **addr, off_t offset, int count, int dummy)
-{
-       /*
-        * print what /proc/via displays,
-        * if required from DISPLAY_APOLLO_TIMINGS
-        */
-       char *p = buffer;
-       /* Parameter of chipset : */
-
-       /* Miscellaneous control 1 */
-       p = print_apollo_chipset_control1(buffer, bmide_dev);
-
-       /* Miscellaneous control 2 */
-       p = print_apollo_chipset_control2(p, bmide_dev);
-       /* Parameters of drives: */
-
-       /* Header */
-       p += sprintf(p, "------------------Primary IDE------------Secondary IDE-----\n");
-       p = print_apollo_chipset_control3(p, bmide_dev, 0);
-       p = print_apollo_ide_config(p, bmide_dev);
-       p += sprintf(p, "--------------drive0------drive1-------drive0------drive1----\n");
-       p = print_apollo_chipset_control3(p, bmide_dev, 1);
-       p = print_apollo_drive_config(p, bmide_dev);
-       return p-buffer;        /* hoping it is less than 4K... */
-}
-
-#endif  /* defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) */
-
-/*
- *  Used to set Fifo configuration via kernel command line:
- */
-
-byte fifoconfig = 0;
-static byte newfifo = 0;
-
-/* Used to just intialize once Fifo configuration */
-static short int done = 0;
-
-/*
- *  Set VIA Chipset Timings for (U)DMA modes enabled.
- *
- *  VIA Apollo chipset has complete support for
- *  setting up the timing parameters.
- */
-static void set_via_timings (ide_hwif_t *hwif)
-{
-       struct pci_dev  *dev = hwif->pci_dev;
-       byte post  = hwif->channel ? 0x30 : 0xc0;
-       byte flush = hwif->channel ? 0x50 : 0xa0;
-       int mask = hwif->channel ? ((newfifo & 0x60) ? 0 : 1) :
-                                  (((newfifo & 0x60) == 0x60) ? 1 : 0);
-       byte via_config = 0;
-       int rc = 0, errors = 0;
-
-       printk("%s: VIA Bus-Master ", hwif->name);
-
-       /*
-        * setting IDE read prefetch buffer and IDE post write buffer.
-        * (This feature allows prefetched reads and post writes).
-        */
-       if ((rc = pci_read_config_byte(dev, 0x41, &via_config))) 
-               errors++;
-
-       if (mask) {
-               if ((rc = pci_write_config_byte(dev, 0x41, via_config & ~post)))
-                       errors++;
-       } else {
-               if ((rc = pci_write_config_byte(dev, 0x41, via_config | post)))
-                       errors++;
-       }
-
-       /*
-        * 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.)
-        */
-       if ((rc = pci_read_config_byte(dev, 0x46, &via_config)))
-               errors++;
-
-       if (mask) {
-               if ((rc = pci_write_config_byte(dev, 0x46, via_config & ~flush)))
-                       errors++;
-       } else {
-               if ((rc = pci_write_config_byte(dev, 0x46, via_config | flush)))
-                       errors++;
-       }
-
-       if (!hwif->dma_base)
-               printk("Config %s. No DMA Enabled\n",
-                       errors ? "ERROR":"Success");
-       else
-               printk("(U)DMA Timing Config %s\n",
-                       errors ? "ERROR" : "Success");
-}
-
-/*
- *  Sets VIA 82c586 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 
- *  triggering.
- */
-
-static int via_set_fifoconfig(ide_hwif_t *hwif)
-{
-       byte fifo;
-       unsigned int timings;
-       struct pci_dev  *dev = hwif->pci_dev;
-
-       /* read port configuration */
-       if (pci_read_config_dword(dev, 0x40, &timings))
-               return 1;
-   
-       /* first read actual fifo config: */
-       if (pci_read_config_byte(dev, 0x43, &fifo))
-               return 1;
-
-       /* keep 4 and 7 bit as they seem to differ between chipsets flavors... */
-       newfifo = fifo & 0x90;
-
-       if (fifoconfig) {
-               /* we received a config request from kernel command line: */
-               newfifo |= fifoconfig & 0x6f;
-       } else {
-               /* If ever just one channel is unused, allocate all fifo levels to it
-                * and give it a 3/4 threshold for (u)dma transfers.
-                * Otherwise, share it evenly between channels:
-                */
-               if ((timings & 3) == 2) {
-                       /* only primary channel is  enabled
-                        * 16 buf. to prim. chan. thresh=3/4
-                        */
-                       newfifo |= 0x06;
-               } else if ((timings & 3) == 1) {
-                       /* only secondary channel is enabled!
-                        * 16 buffers to sec. ch. thresh=3/4
-                        */
-                       newfifo |= 0x69;
-               } else {
-                       /* fifo evenly distributed: */
-                       newfifo |= 0x2a;
-               }
-       }
-
-       /* write resulting configuration to chipset: */
-       if (pci_write_config_byte(dev, 0x43, newfifo))
-               return 1;
-
-       /* and then reread it to get the actual one */
-       if (pci_read_config_byte(dev, 0x43, &newfifo))
-               return 1;
-
-       /* print a kernel report: */
-       printk("Split FIFO Configuration: %s Primary buffers, threshold = %s\n",
-               ((newfifo & 0x60) == 0x60)      ? " 0" :
-               ((newfifo & 0x60)               ? " 8" : "16"),
-               !(newfifo & 0x0c)               ? "1" :
-               (!(newfifo & 0x08)              ? "3/4" :
-               (newfifo & 0x04)                ? "1/4" : "1/2"));
-
-       printk("                          %s Second. buffers, threshold = %s\n",
-               ((newfifo & 0x60) == 0x60)      ? "16" :
-               ((newfifo & 0x60)               ? " 8" : " 0"),
-               !(newfifo & 0x03)               ? "1" :
-               (!(newfifo & 0x02)              ? "3/4" :
-               (newfifo & 0x01)                ? "1/4" : "1/2"));
-
-#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS)
-       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)
-{
-       struct pci_dev *host;
-       struct pci_dev *isa;
-
-       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;
-                               }
-                       }
-                       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;
-               }
-       }
-       return 0;
-}
-
-void __init ide_init_via82c586 (ide_hwif_t *hwif)
-{
-       set_via_timings(hwif);
-}
-
-/*
- *  ide_dmacapable_via82c568(ide_hwif_t *, unsigned long)
- *  checks if channel "channel" of if hwif is dma
- *  capable or not, according to kernel command line,
- *  and the new fifo settings.
- *  It calls "ide_setup_dma" on capable mainboards, and
- *  bypasses the setup if not capable.
- */
-
-void ide_dmacapable_via82c586 (ide_hwif_t *hwif, unsigned long dmabase)
-{
-       if (!done) {
-               via_set_fifoconfig(hwif);
-               done = 1;
-       }
-
-       /*
-        * check if any fifo is available for requested port:
-        */
-       if (((hwif->channel == 0) && ((newfifo & 0x60) == 0x60)) ||
-           ((hwif->channel == 1) && ((newfifo & 0x60) == 0x00))) {
-               printk("    %s: VP_IDE Bus-Master DMA disabled (FIFO setting)\n", hwif->name);
-       } else {
-               ide_setup_dma(hwif, dmabase, 8);
-       }
-}
diff --git a/drivers/block/via82cxxx.c b/drivers/block/via82cxxx.c
new file mode 100644 (file)
index 0000000..e6f61c0
--- /dev/null
@@ -0,0 +1,572 @@
+/*
+ * linux/drivers/block/via82cxxx.c     Version 0.05    Sept. 03, 1999
+ *
+ *  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.
+ *
+ *  VIA chips also have a single FIFO, with the same 64 bytes deep
+ *  buffer (16 levels of 4 bytes each).
+ *
+ *  However, VIA chips can have the buffer split either 8:8 levels,
+ *  16:0 levels or 0:16 levels between both channels. One could think
+ *  of using this feature, as even if no level of FIFO is given to a
+ *  given channel, one can for instance always reach ATAPI drives through
+ *  it, or, if one channel is unused, configuration defaults to
+ *  an even split FIFO levels.
+ *  
+ *  This feature is available only through a kernel command line :
+ *             "splitfifo=Chan,Thr0,Thr1" or "splitfifo=Chan".
+ *             where:  Chan =1,2,3 or 4 and Thrx = 1,2,3,or 4.
+ *
+ *  If Chan == 1:
+ *     gives all the fifo to channel 0,
+ *     sets its threshold to Thr0/4,
+ *     and disables any dma access to channel 1.
+ *
+ *  If chan == 2:
+ *     gives all the fifo to channel 1,
+ *     sets its threshold to Thr1/4,
+ *     and disables any dma access to channel 0.
+ *
+ *  If chan == 3 or 4:
+ *     shares evenly fifo between channels,
+ *     gives channel 0 a threshold of Thr0/4,
+ *     and channel 1 a threshold of Thr1/4.
+ *
+ *  Note that by default (if no command line is provided) and if a channel
+ *  has been disabled in Bios, all the fifo is given to the active channel,
+ *  and its threshold is set to 3/4.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+
+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
+
+#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS)
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static char *FIFO_str[] = {
+       " 1 ",
+       "3/4",
+       "1/2",
+       "1/4"
+};
+
+static char *control3_str[] = {
+       "No limitation",
+       "64",
+       "128",
+       "192"
+};
+
+static int via_get_info(char *, char **, off_t, int, int);
+extern int (*via_display_info)(char *, char **, off_t, int, int); /* ide-proc.c */
+static struct pci_dev *bmide_dev;
+
+static char * print_apollo_drive_config (char *buf, struct pci_dev *dev)
+{
+       int rc;
+       unsigned int time;
+       byte tm;
+       char *p = buf;  
+       /* Drive Timing Control */
+       rc = pci_read_config_dword(dev, 0x48, &time);
+       p += sprintf(p, "Act Pls Width:  %02d          %02d           %02d          %02d\n",
+                       ((time & 0xf0000000)>>28) + 1,
+                       ((time & 0xf00000)>>20) + 1,
+                       ((time & 0xf000)>>12) + 1,
+                       ((time & 0xf0)>>4) + 1 );
+       p += sprintf(p, "Recovery Time:  %02d          %02d           %02d          %02d\n",
+                       ((time & 0x0f000000)>>24) + 1,
+                       ((time & 0x0f0000)>>16) + 1,
+                       ((time & 0x0f00)>>8) + 1,
+                       (time & 0x0f) + 1 );
+       /* Address Setup Time */
+       rc = pci_read_config_byte(dev, 0x4C, &tm);
+       p += sprintf(p, "Add. Setup T.:  %01dT          %01dT           %01dT          %01dT\n",
+                       ((tm & 0xc0)>>6) + 1,
+                       ((tm & 0x30)>>4) + 1,
+                       ((tm & 0x0c)>>2) + 1,
+                       (tm & 0x03) + 1 );
+       /* UltraDMA33 Extended Timing Control */
+       rc = pci_read_config_dword(dev, 0x50, &time);
+       p += sprintf(p, "------------------UDMA-Timing-Control------------------------\n");
+       p += sprintf(p, "Enable Meth.:    %01d           %01d            %01d           %01d\n",
+                       (time & 0x80000000)     ? 1 : 0,
+                       (time & 0x800000)       ? 1 : 0,
+                       (time & 0x8000)         ? 1 : 0,
+                       (time & 0x80)           ? 1 : 0 );
+       p += sprintf(p, "Enable:         %s         %s          %s         %s\n",
+                       (time & 0x40000000)     ? "yes" : "no ",
+                       (time & 0x400000)       ? "yes" : "no ",
+                       (time & 0x4000)         ? "yes" : "no ",
+                       (time & 0x40)           ? "yes" : "no " );
+       p += sprintf(p, "Transfer Mode: %s         %s          %s         %s\n",
+                       (time & 0x20000000)     ? "PIO" : "DMA",
+                       (time & 0x200000)       ? "PIO" : "DMA",
+                       (time & 0x2000)         ? "PIO" : "DMA",
+                       (time & 0x20)           ? "PIO" : "DMA" );
+       p += sprintf(p, "Cycle Time:     %01dT          %01dT           %01dT          %01dT\n",
+                       ((time & 0x03000000)>>24) + 2,
+                       ((time & 0x030000)>>16) + 2,
+                       ((time & 0x0300)>>8) + 2,
+                       (time & 0x03) + 2 );
+       return (char *)p;
+}
+
+static char * print_apollo_ide_config (char *buf, struct pci_dev *dev)
+{
+       byte time, tmp; 
+       unsigned short size0, size1;
+       int rc;
+       char *p = buf;  
+       rc = pci_read_config_byte(dev, 0x41, &time);
+       p += sprintf(p, "Prefetch Buffer :      %s                     %s\n",
+               (time & 128)    ? "on " : "off",
+               (time & 32)     ? "on " : "off" );
+       p += sprintf(p, "Post Write Buffer:     %s                     %s\n",
+               (time & 64)     ? "on " : "off",
+               (time & 16)     ? "on " : "off" );
+       /* FIFO configuration */
+       rc = pci_read_config_byte(dev, 0x43, &time);
+       tmp = ((time & 0x20)>>2) + ((time & 0x40)>>3);
+       p += sprintf(p, "FIFO Conf/Chan. :      %02d                      %02d\n",
+                       16 - tmp, tmp);
+       tmp = (time & 0x0F)>>2;
+       p += sprintf(p, "Threshold Prim. :      %s                     %s\n",
+                       FIFO_str[tmp],
+                       FIFO_str[time & 0x03] );
+       /* chipset Control3 */
+       rc = pci_read_config_byte(dev, 0x46, &time);
+       p += sprintf(p, "Read DMA FIFO flush:   %s                     %s\n",
+                       (time & 0x80)   ? "on " : "off",
+                       (time & 0x40)   ? "on " : "off" );
+       p += sprintf(p, "End Sect. FIFO flush:  %s                     %s\n",
+                       (time & 0x20)   ? "on " : "off",
+                       (time & 0x10)   ? "on " : "off" );
+       p += sprintf(p, "Max DRDY Pulse Width:  %s %s\n",
+                       control3_str[(time & 0x03)],
+                       (time & 0x03) ? "PCI clocks" : "" );
+       /* Primary and Secondary sector sizes */
+       rc = pci_read_config_word(dev, 0x60, &size0);
+       rc = pci_read_config_word(dev, 0x68, &size1);
+       p += sprintf(p, "Bytes Per Sector:      %03d                     %03d\n",
+                       size0 & 0xfff,
+                       size1 & 0xfff );
+
+       return (char *)p;
+}
+
+static char * print_apollo_chipset_control1 (char *buf, struct pci_dev *dev)
+{
+       byte t;
+       int rc;
+       char *p = buf;  
+       unsigned short c;
+       byte l, l_max;   
+       rc = pci_read_config_word(dev, 0x04, &c);
+       rc = pci_read_config_byte(dev, 0x44, &t);
+       rc = pci_read_config_byte(dev, 0x0d, &l);
+       rc = pci_read_config_byte(dev, 0x3f, &l_max);
+
+       p += sprintf(p, "Command register = 0x%x\n", c);
+       p += sprintf(p, "Master Read  Cycle IRDY %d Wait State\n",
+                       (t & 64) >>6 );
+       p += sprintf(p, "Master Write Cycle IRDY %d Wait State\n",
+                       (t & 32) >> 5 );
+       p += sprintf(p, "FIFO Output Data 1/2 Clock Advance: %s\n",
+                       (t & 16) ? "on " : "off" );
+       p += sprintf(p, "Bus Master IDE Status Register Read Retry: %s\n",
+                       (t & 8) ? "on " : "off" );
+       p += sprintf(p, "Latency timer = %d (max. = %d)\n",
+                       l, l_max);
+
+       return (char *)p;
+}
+static char * print_apollo_chipset_control2 (char *buf, struct pci_dev *dev)
+{
+       byte t;
+       int rc;
+       char *p = buf;  
+       rc = pci_read_config_byte(dev, 0x45, &t);
+       p += sprintf(p, "Interrupt Steering Swap: %s\n",
+                       (t & 64) ? "on ":"off" );
+
+       return (char *)p;
+}
+static char * print_apollo_chipset_control3 (char *buf, struct pci_dev *dev,
+                                               unsigned short n)
+{
+       /*
+        * at that point we can be sure that register 0x20 of the
+        * chipset contains the right address...
+        */
+       unsigned int bibma;
+       int rc;
+       byte c0, c1;    
+       char *p = buf; 
+       rc = pci_read_config_dword(dev, 0x20, &bibma);
+       bibma = (bibma & 0xfff0) ;
+       /*
+        * at that point bibma+0x2 et bibma+0xa are byte registers
+        * to investigate:
+        */
+       c0 = inb((unsigned short)bibma + 0x02);
+       c1 = inb((unsigned short)bibma + 0x0a);
+       if (n == 0) {
+        /*p = sprintf(p,"--------------------Primary IDE------------Secondary IDE-----");*/
+               p += sprintf(p, "both channels togth:   %s                     %s\n",
+                               (c0&0x80) ? "no" : "yes",
+                               (c1&0x80) ? "no" : "yes" );
+       } else {
+        /*p = sprintf(p,"--------------drive0------drive1-------drive0------drive1----");*/
+               p += sprintf(p, "DMA enabled:    %s         %s          %s         %s\n",
+                               (c0&0x20) ? "yes" : "no ",
+                               (c0&0x40) ? "yes" : "no ",
+                               (c1&0x20) ? "yes" : "no ",
+                               (c1&0x40) ? "yes" : "no " );
+       }
+       return (char *)p;
+}
+
+static int via_get_info (char *buffer, char **addr, off_t offset, int count, int dummy)
+{
+       /*
+        * print what /proc/via displays,
+        * if required from DISPLAY_APOLLO_TIMINGS
+        */
+       char *p = buffer;
+       /* Parameter of chipset : */
+
+       /* Miscellaneous control 1 */
+       p = print_apollo_chipset_control1(buffer, bmide_dev);
+
+       /* Miscellaneous control 2 */
+       p = print_apollo_chipset_control2(p, bmide_dev);
+       /* Parameters of drives: */
+
+       /* Header */
+       p += sprintf(p, "------------------Primary IDE------------Secondary IDE-----\n");
+       p = print_apollo_chipset_control3(p, bmide_dev, 0);
+       p = print_apollo_ide_config(p, bmide_dev);
+       p += sprintf(p, "--------------drive0------drive1-------drive0------drive1----\n");
+       p = print_apollo_chipset_control3(p, bmide_dev, 1);
+       p = print_apollo_drive_config(p, bmide_dev);
+       return p-buffer;        /* hoping it is less than 4K... */
+}
+
+#endif  /* defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+/*
+ *  Used to set Fifo configuration via kernel command line:
+ */
+
+byte via_proc = 0;
+byte fifoconfig = 0;
+static byte newfifo = 0;
+
+/* Used to just intialize once Fifo configuration */
+static short int done = 0;
+
+/*
+ *  Set VIA Chipset Timings for (U)DMA modes enabled.
+ *
+ *  VIA Apollo chipset has complete support for
+ *  setting up the timing parameters.
+ */
+static void set_via_timings (ide_hwif_t *hwif)
+{
+       struct pci_dev  *dev = hwif->pci_dev;
+       byte post  = hwif->channel ? 0x30 : 0xc0;
+       byte flush = hwif->channel ? 0x50 : 0xa0;
+       int mask = hwif->channel ? ((newfifo & 0x60) ? 0 : 1) :
+                                  (((newfifo & 0x60) == 0x60) ? 1 : 0);
+       byte via_config = 0;
+       int rc = 0, errors = 0;
+
+       printk("%s: VIA Bus-Master ", hwif->name);
+
+       /*
+        * setting IDE read prefetch buffer and IDE post write buffer.
+        * (This feature allows prefetched reads and post writes).
+        */
+       if ((rc = pci_read_config_byte(dev, 0x41, &via_config))) 
+               errors++;
+
+       if (mask) {
+               if ((rc = pci_write_config_byte(dev, 0x41, via_config & ~post)))
+                       errors++;
+       } else {
+               if ((rc = pci_write_config_byte(dev, 0x41, via_config | post)))
+                       errors++;
+       }
+
+       /*
+        * 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.)
+        */
+       if ((rc = pci_read_config_byte(dev, 0x46, &via_config)))
+               errors++;
+
+       if (mask) {
+               if ((rc = pci_write_config_byte(dev, 0x46, via_config & ~flush)))
+                       errors++;
+       } else {
+               if ((rc = pci_write_config_byte(dev, 0x46, via_config | flush)))
+                       errors++;
+       }
+
+       if (!hwif->dma_base)
+               printk("Config %s. No DMA Enabled\n",
+                       errors ? "ERROR":"Success");
+       else
+               printk("(U)DMA Timing Config %s\n",
+                       errors ? "ERROR" : "Success");
+}
+
+/*
+ *  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 
+ *  triggering.
+ */
+
+static int via_set_fifoconfig(ide_hwif_t *hwif)
+{
+       byte fifo;
+       unsigned int timings;
+       struct pci_dev  *dev = hwif->pci_dev;
+
+       /* read port configuration */
+       if (pci_read_config_dword(dev, 0x40, &timings))
+               return 1;
+   
+       /* first read actual fifo config: */
+       if (pci_read_config_byte(dev, 0x43, &fifo))
+               return 1;
+
+       /* keep 4 and 7 bit as they seem to differ between chipsets flavors... */
+       newfifo = fifo & 0x90;
+
+       if (fifoconfig) {
+               /* we received a config request from kernel command line: */
+               newfifo |= fifoconfig & 0x6f;
+       } else {
+               /* If ever just one channel is unused, allocate all fifo levels to it
+                * and give it a 3/4 threshold for (u)dma transfers.
+                * Otherwise, share it evenly between channels:
+                */
+               if ((timings & 3) == 2) {
+                       /* only primary channel is  enabled
+                        * 16 buf. to prim. chan. thresh=3/4
+                        */
+                       newfifo |= 0x06;
+               } else if ((timings & 3) == 1) {
+                       /* only secondary channel is enabled!
+                        * 16 buffers to sec. ch. thresh=3/4
+                        */
+                       newfifo |= 0x69;
+               } else {
+                       /* fifo evenly distributed: */
+                       newfifo |= 0x2a;
+               }
+       }
+
+       /* write resulting configuration to chipset: */
+       if (pci_write_config_byte(dev, 0x43, newfifo))
+               return 1;
+
+       /* and then reread it to get the actual one */
+       if (pci_read_config_byte(dev, 0x43, &newfifo))
+               return 1;
+
+       /* print a kernel report: */
+       printk("Split FIFO Configuration: %s Primary buffers, threshold = %s\n",
+               ((newfifo & 0x60) == 0x60)      ? " 0" :
+               ((newfifo & 0x60)               ? " 8" : "16"),
+               !(newfifo & 0x0c)               ? "1" :
+               (!(newfifo & 0x08)              ? "3/4" :
+               (newfifo & 0x04)                ? "1/4" : "1/2"));
+
+       printk("                          %s Second. buffers, threshold = %s\n",
+               ((newfifo & 0x60) == 0x60)      ? "16" :
+               ((newfifo & 0x60)               ? " 8" : " 0"),
+               !(newfifo & 0x03)               ? "1" :
+               (!(newfifo & 0x02)              ? "3/4" :
+               (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_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 (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;
+                       }
+
+                       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_via82cxxx (ide_hwif_t *hwif)
+{
+       set_via_timings(hwif);
+}
+
+/*
+ *  ide_dmacapable_via82c568(ide_hwif_t *, unsigned long)
+ *  checks if channel "channel" of if hwif is dma
+ *  capable or not, according to kernel command line,
+ *  and the new fifo settings.
+ *  It calls "ide_setup_dma" on capable mainboards, and
+ *  bypasses the setup if not capable.
+ */
+
+void ide_dmacapable_via82cxxx (ide_hwif_t *hwif, unsigned long dmabase)
+{
+       if (!done) {
+               via_set_fifoconfig(hwif);
+               done = 1;
+       }
+
+       /*
+        * check if any fifo is available for requested port:
+        */
+       if (((hwif->channel == 0) && ((newfifo & 0x60) == 0x60)) ||
+           ((hwif->channel == 1) && ((newfifo & 0x60) == 0x00))) {
+               printk("    %s: VP_IDE Bus-Master DMA disabled (FIFO setting)\n", hwif->name);
+       } else {
+               ide_setup_dma(hwif, dmabase, 8);
+       }
+}
index 7a46ed183620b8fc75658dca873b6096f9a3ee70..b41356423f1df04cd3c01f3b2af1af01b60dd219 100644 (file)
   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 <axboe@image.dk>
+  -- 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: */
 #include <linux/cdrom.h>
 #include <linux/sysctl.h>
 #include <linux/proc_fs.h>
+#include <linux/init.h>
 #include <asm/fcntl.h>
 #include <asm/segment.h>
 #include <asm/uaccess.h>
@@ -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 */
+
index 3e91edffd5e84e9ebb74a94726fdc29580ee727a..c3a8239f6749932c78b99d792d943fbb0cfcff04 100644 (file)
@@ -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
index 5176f28f4e9a8fdbbb97965117be94c5ee9d0949..57f3d719942c41820f240d15400e839106d652ad 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/serial.h>
 #include <linux/cdk.h>
 #include <linux/comstats.h>
+#include <linux/version.h>
 #include <linux/istallion.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
index 36db3299d5a306a90ae7d02b7820cb389bc2b873..75f27e8305da8aee38bdf519b100a2aa3e67cfe1 100644 (file)
@@ -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;
                }
 
index 239a611b227729ea7dab0a03bd880cfb7f332260..98b66f0c28b18a9b884b237cf6385239f7ed28dc 100644 (file)
@@ -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
index b25be2cd06aa7a781680218a94ef188ba58cec4f..aac42d44b91a22afb10c42fa4bbe22ce890a4a4a 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/version.h> /* for linux/stallion.h */
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/tty_flip.h>
index 3a0735c25c61389789f630e6086c0bac26feb32b..4cc286578b13c7b972b66f2927ac42107479b288 100644 (file)
@@ -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
 
index 9ba70b2555d834f0ac5d6dd43db5d095ebdb5736..0bd2a172594a93b111eaf3c0b92750b2ff096231 100644 (file)
@@ -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)
index 99d9061f98a3e421c6722ee85c91a2f5c8874e4e..6fa4aca6ba94f4751bb1c3c8d152d7d4c7ce9469 100644 (file)
@@ -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)
index 7dc3fbf39a5d72e39dd49ba63f900b43d0884464..87e498884aae9f93cc65a9f220c19cc4363ce9c3 100644 (file)
@@ -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 */
index 3a2ae4599b7e70c7e2789e0eaa4b3dd70df8692c..7c2ff12d5a1d886019921882a6413e4c1a57f1aa 100644 (file)
@@ -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 }, 
index 83215d11520c36d462a638caf5f55c96d71370b5..5d0e5415343676b8f78b86978352f92b71df8546 100644 (file)
@@ -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 <marcelo@conectiva.com.br> : SMP fixes 
 
 #include<linux/stat.h>
 
-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; 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])=(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<<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);
-    }
+       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<<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);
+       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 << 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
-
index 64cb56b9e8776f8f1b494ce350946e18a7fd269a..83698d4c7b248bbff38bd9ad2ab33fed6b092c25 100644 (file)
@@ -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 $
 
 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;
index b89f39c8fd241bd08d182c7c5b8d0d2f9444cdc2..78328d5ee5b3f6f9cfeb91ad7a737d4e1accaf0d 100644 (file)
@@ -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);
index 51d63a589d8a3ef06c340cbe67576f71496f9d6d..3486897ee13ecd05e8ecb026b79dc4f664912b72 100644 (file)
@@ -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 */
index 450fc370e4aa5292848f219a190eac940c801640..3a422e6bc6110aad9a5a8ed120536b4f7f1df0ca 100644 (file)
@@ -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;
index a4244234afb01d560acdd7c286ca1d16333d4ed9..791b144d738cc5861e980c8872ac761de9c0dd34 100644 (file)
    #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
index 381e718d8659276b4ec35491f10f7a771cca3488..ff49b56ead8d9231d7e95efe3e6d557544a63844 100644 (file)
@@ -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 " ", \
index f64554deefb15e6daa6e7cd0074a7e0eae8d63c4..07c1dc7b358f87a286bbb707f69500578ccd0c43 100644 (file)
@@ -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)
index 8e31dfe1274ba9b33589fd4682914110dc681d74..ede422a4680626c339bf03a6adcdce3585fa31cc 100644 (file)
@@ -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
index 02df6145596b313bc32148fb2f91b35533e6cfe3..976ab02da812ee6934c78926b710e91cd45298b8 100644 (file)
@@ -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
-
index e69d8f63e37f089e70403f77e127749454a670db..1da9f605a38b17efae904ce07f218f4bbb2e453f 100644 (file)
@@ -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;
index 1d9acb1a4995e702804e1382a56b98f96c327132..b3b45f59aa557139d7d84850f0639aac779e8bd6 100644 (file)
@@ -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);
index 57cf20ff6d7e5a2c81abca6941ff53361ec5de9a..c08feee15ba02dcaf4a1b528b614277a7d329e38 100644 (file)
@@ -91,7 +91,7 @@ static int uhci_kill_isoc (struct usb_isoc_desc *isocdesc);
 /*
  * Map status to standard result codes
  *
- * <status> is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status)
+ * <status> is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status)]
  * <dir_out> 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;
index 7d3ead8f641ab30e7f0ff45051bac5b8b93811d6..96bd338867f757a7900aac46e1f401ba0f3ccb3f 100644 (file)
@@ -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) {
index 88e0e96625fef1c1991782f33e49b669f4146da5..add3bb4633239f564969f961338f5a8b1dbb4226 100644 (file)
@@ -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;
        }
 }
 
index 71510623d4ca82a6e48d6f3838c62537cdd56b88..5581b2e0da009788b558880d776a19c323eb0aff 100644 (file)
@@ -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);
index a8e223f6bf048708ec648319a786679fb6d64664..77d72f3f305506fe402bdac8d865bb1fb6b09f1f 100644 (file)
@@ -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
index e4f8cefe1c8094c1e9d7844358163663cb6d16f2..c422b0b9fcf96144fedfb59a5c014a7cc2b454f0 100644 (file)
@@ -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 (file)
index 0000000..d48ebd8
--- /dev/null
@@ -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 <atong@uiuc.edu>, 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 (file)
index 0000000..16b37c8
--- /dev/null
@@ -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 <atong@uiuc.edu>
+ *
+ *                             Brad Douglas <brad@neruo.com>
+ *                             - 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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <asm/uaccess.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/selection.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#if defined(CONFIG_PPC)
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <linux/nvram.h>
+#include <video/macmodes.h>
+#endif
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "aty128.h"
+
+#undef DEBUG
+#undef CONFIG_MTRR     /* not ready? */
+
+#ifdef DEBUG
+#define DBG(x)         printk(KERN_INFO "aty128fb: %s\n",(x));
+#else
+#define DBG(x)
+#endif
+
+static char *aty128fb_name = "ATY Rage128";
+
+static struct fb_var_screeninfo default_var = {
+    /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
+    640, 480, 640, 480, 0, 0, 8, 0,
+    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+    0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
+    0, FB_VMODE_NONINTERLACED
+};
+
+#pragma pack(1)
+typedef struct {
+    u8 clock_chip_type;
+    u8 struct_size;
+    u8 accelerator_entry;
+    u8 VGA_entry;
+    u16 VGA_table_offset;
+    u16 POST_table_offset;
+    u16 XCLK;
+    u16 MCLK;
+    u8 num_PLL_blocks;
+    u8 size_PLL_blocks;
+    u16 PCLK_ref_freq;
+    u16 PCLK_ref_divider;
+    u32 PCLK_min_freq;
+    u32 PCLK_max_freq;
+    u16 MCLK_ref_freq;
+    u16 MCLK_ref_divider;
+    u32 MCLK_min_freq;
+    u32 MCLK_max_freq;
+    u16 XCLK_ref_freq;
+    u16 XCLK_ref_divider;
+    u32 XCLK_min_freq;
+    u32 XCLK_max_freq;
+} PLL_BLOCK;
+#pragma pack()
+
+struct aty128_meminfo {
+    u8 ML;
+    u8 MB;
+    u8 Trcd;
+    u8 Trp;
+    u8 Twr;
+    u8 CL;
+    u8 Tr2w;
+    u8 LoopLatency;
+    u8 DspOn;
+    u8 Rloop;
+};
+
+const struct aty128_meminfo sdr_128   = { 4, 4, 3, 3, 1, 3, 1, 16, 30, 16 };
+const struct aty128_meminfo sdr_64    = { 4, 8, 3, 3, 1, 3, 1, 17, 46, 17 };
+const struct aty128_meminfo sdr_sgram = { 4, 4, 1, 2, 1, 2, 1, 16, 24, 16 };
+const struct aty128_meminfo ddr_sgram = { 4, 4, 3, 3, 2, 3, 1, 16, 31, 16 };
+
+static int currcon = 0;
+static char fontname[40] __initdata = { 0 };
+
+#if defined(CONFIG_PPC)
+static int default_vmode __initdata = VMODE_NVRAM;
+static int default_cmode __initdata = CMODE_NVRAM;
+#endif
+
+#if defined(CONFIG_MTRR)
+static int mtrr = 1;
+#endif
+
+struct aty128_constants {
+    u32 dotclock;
+    u32 ppll_min;
+    u32 ppll_max;
+    u32 ref_divider;
+    u32 xclk;
+    u32 fifo_width;
+    u32 fifo_depth;
+};
+
+struct aty128_crtc {
+    u32 gen_cntl;
+    u32 ext_cntl;
+    u32 h_total, h_sync_strt_wid;
+    u32 v_total, v_sync_strt_wid;
+    u32 pitch;
+    u32 offset, offset_cntl;
+    u32 vxres, vyres;
+    u32 bpp;
+};
+
+struct aty128_pll {
+    u32 post_divider;
+    u32 feedback_divider;
+    u32 vclk;
+};
+
+struct aty128_ddafifo {
+    u32 dda_config;
+    u32 dda_on_off;
+};
+
+/* register values for a specific mode */
+struct aty128fb_par {
+    struct aty128_crtc crtc;
+    struct aty128_pll pll;
+    struct aty128_ddafifo fifo_reg;
+    u32 accel_flags;
+};
+
+struct fb_info_aty128 {
+    struct fb_info fb_info;
+    struct aty128_constants constants;
+    unsigned long regbase_phys, regbase;
+    unsigned long frame_buffer_phys, frame_buffer;
+    const struct aty128_meminfo *mem;
+    u32 vram_size;
+    u32 BIOS_SEG;
+#ifdef CONFIG_MTRR
+    struct { int vram; int vram_valid; } mtrr;
+#endif
+    struct aty128fb_par default_par, current_par;
+    struct display disp;
+    struct { u8 red, green, blue, pad; } palette[256];
+    union {
+#ifdef FBCON_HAS_CFB16
+    u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+    u32 cfb24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+    u32 cfb32[16];
+#endif
+    } fbcon_cmap;
+    int blitter_may_be_busy;
+};
+
+#define round_div(n, d) ((n+(d/2))/d)
+
+    /*
+     *  Interface used by the world
+     */
+
+int aty128fb_setup(char *options);
+
+static int aty128fb_open(struct fb_info *info, int user);
+static int aty128fb_release(struct fb_info *info, int user);
+static int aty128fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+                      struct fb_info *info);
+static int aty128fb_get_var(struct fb_var_screeninfo *var, int con,
+                      struct fb_info *info);
+static int aty128fb_set_var(struct fb_var_screeninfo *var, int con,
+                      struct fb_info *info);
+static int aty128fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+                       struct fb_info *info);
+static int aty128fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+                       struct fb_info *info);
+static int aty128fb_pan_display(struct fb_var_screeninfo *var, int con,
+                          struct fb_info *info);
+static int aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+                    u_long arg, int con, struct fb_info *info);
+
+
+    /*
+     *  Interface to the low level console driver
+     */
+
+void aty128fb_init(void);
+#ifdef CONFIG_FB_OF
+void aty128fb_of_init(struct device_node *dp);
+#endif
+static int aty128fbcon_switch(int con, struct fb_info *info);
+static void aty128fbcon_blank(int blank, struct fb_info *info);
+
+
+    /*
+     *  Internal routines
+     */
+
+static void aty128_encode_fix(struct fb_fix_screeninfo *fix,
+                               struct aty128fb_par *par,
+                               const struct fb_info_aty128 *info);
+static void aty128_set_disp(struct display *disp,
+                       struct fb_info_aty128 *info, int bpp, int accel);
+static int aty128_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+                               u_int *transp, struct fb_info *info);
+static int aty128_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                               u_int transp, struct fb_info *info);
+static void do_install_cmap(int con, struct fb_info *info);
+static void aty128pci_probe(void);
+static int aty128find_ROM(struct fb_info_aty128 *info);
+static void aty128_timings(struct fb_info_aty128 *info);
+static void aty128_get_pllinfo(struct fb_info_aty128 *info);
+static void aty128_reset_engine(const struct fb_info_aty128 *info);
+static void aty128_flush_pixel_cache(const struct fb_info_aty128 *info);
+static void wait_for_fifo(u16 entries, const struct fb_info_aty128 *info);
+static void wait_for_idle(const struct fb_info_aty128 *info);
+static u32 bpp_to_depth(u32 bpp);
+
+#ifdef FBCON_HAS_CFB8
+static struct display_switch fbcon_aty128_8;
+#endif
+
+
+static struct fb_ops aty128fb_ops = {
+    aty128fb_open, aty128fb_release, aty128fb_get_fix,
+    aty128fb_get_var, aty128fb_set_var, aty128fb_get_cmap,
+    aty128fb_set_cmap, aty128fb_pan_display, aty128fb_ioctl
+};
+
+
+    /*
+     * Functions to read from/write to the mmio registers
+     * - endian conversions may possibly be avoided by flipping CONFIG_CNTL
+     *  or using the other register aperture? TODO.
+     */
+static inline u32
+_aty_ld_le32(volatile unsigned int regindex,
+                              const struct fb_info_aty128 *info)
+{
+    unsigned long temp;
+    u32 val;
+
+#if defined(__powerpc__)
+    eieio();
+    temp = info->regbase;
+    asm("lwbrx %0,%1,%2" : "=b"(val) : "b" (regindex), "b" (temp));
+#elif defined(__sparc_v9__)
+    temp = info->regbase + regindex;
+    asm("lduwa [%1] %2, %0" : "=r" (val) : "r" (temp), "i" (ASI_PL));
+#else
+    temp = info->regbase+regindex;
+    val = le32_to_cpu(*((volatile u32 *)(temp)));
+#endif
+    return val;
+}
+
+static inline void
+_aty_st_le32(volatile unsigned int regindex, u32 val,
+                               const struct fb_info_aty128 *info)
+{
+    unsigned long temp;
+
+#if defined(__powerpc__)
+    eieio();
+    temp = info->regbase;
+    asm("stwbrx %0,%1,%2" : : "b" (val), "b" (regindex), "b" (temp) :
+        "memory");
+#elif defined(__sparc_v9__)
+    temp = info->regbase + regindex;
+    asm("stwa %0, [%1] %2" : : "r" (val), "r" (temp), "i" (ASI_PL) : "memory");
+#else
+    temp = info->regbase+regindex;
+    *((volatile u32 *)(temp)) = cpu_to_le32(val);
+#endif
+}
+
+static inline u8
+_aty_ld_8(volatile unsigned int regindex,
+                          const struct fb_info_aty128 *info)
+{
+#if defined(__powerpc__)
+    eieio();
+#endif
+    return *(volatile u8 *)(info->regbase+regindex);
+}
+
+static inline void
+_aty_st_8(volatile unsigned int regindex, u8 val,
+                            const struct fb_info_aty128 *info)
+{
+#if defined(__powerpc__)
+    eieio();
+#endif
+    *(volatile u8 *)(info->regbase+regindex) = val;
+}
+
+#define aty_ld_le32(regindex)          _aty_ld_le32(regindex, info)
+#define aty_st_le32(regindex, val)     _aty_st_le32(regindex, val, info)
+#define aty_ld_8(regindex)             _aty_ld_8(regindex, info)
+#define aty_st_8(regindex, val)                _aty_st_8(regindex, val, info)
+
+    /*
+     * Functions to read from/write to the pll registers
+     */
+
+#define aty_ld_pll(pll_index)          _aty_ld_pll(pll_index, info)
+#define aty_st_pll(pll_index, val)     _aty_st_pll(pll_index, val, info)
+
+static u32
+_aty_ld_pll(unsigned int pll_index,
+                       const struct fb_info_aty128 *info)
+{       
+    aty_st_8(CLOCK_CNTL_INDEX, pll_index & 0x1F);
+    return aty_ld_le32(CLOCK_CNTL_DATA);
+}
+    
+static void
+_aty_st_pll(unsigned int pll_index, u32 val,
+                       const struct fb_info_aty128 *info)
+{   
+    aty_st_8(CLOCK_CNTL_INDEX, (pll_index & 0x1F) | PLL_WR_EN);
+    aty_st_le32(CLOCK_CNTL_DATA, val);
+}
+/* return true when the PLL has completed an atomic update */
+static int
+aty_pll_readupdate(const struct fb_info_aty128 *info)
+{
+    return !(aty_ld_pll(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R);
+}
+
+static void
+aty_pll_wait_readupdate(const struct fb_info_aty128 *info)
+{
+    unsigned long timeout = jiffies + HZ/100;  // should be more than enough
+    int reset = 1;
+
+    while (time_before(jiffies, timeout))
+       if (aty_pll_readupdate(info)) {
+           reset = 0;
+           break;
+       }
+
+#ifdef DEBUG
+    if (reset) /* reset engine?? */
+       printk(KERN_ERR "aty128fb: PLL write timeout!");
+#endif
+}
+
+/* tell PLL to update */
+static void
+aty_pll_writeupdate(const struct fb_info_aty128 *info)
+{
+    aty_pll_wait_readupdate(info);
+
+    aty_st_pll(PPLL_REF_DIV,
+       aty_ld_pll(PPLL_REF_DIV) | PPLL_ATOMIC_UPDATE_W);
+}
+
+
+/* write to the scratch register to test r/w functionality */
+static u32
+register_test(const struct fb_info_aty128 *info)
+{
+    u32 val, flag = 0;
+
+    val = aty_ld_le32(BIOS_0_SCRATCH);
+
+    aty_st_le32(BIOS_0_SCRATCH, 0x55555555);
+    if (aty_ld_le32(BIOS_0_SCRATCH) == 0x55555555) {
+       aty_st_le32(BIOS_0_SCRATCH, 0xAAAAAAAA);
+
+       if (aty_ld_le32(BIOS_0_SCRATCH) == 0xAAAAAAAA)
+           flag = 1; 
+    }
+
+    aty_st_le32(BIOS_0_SCRATCH, val);  // restore value
+    return flag;
+}
+
+
+    /*
+     * Accelerator functions
+     */
+static void
+wait_for_idle(const struct fb_info_aty128 *info)
+{
+    unsigned long timeout = jiffies + HZ/20;
+    int reset = 1;
+
+    wait_for_fifo(64, info);
+
+    while (time_before(jiffies, timeout))
+       if ((aty_ld_le32(GUI_STAT) & GUI_ACTIVE) != ENGINE_IDLE) {
+           reset = 0;
+           break;
+       }
+
+    if (reset)
+       aty128_reset_engine(info);
+}
+
+
+static void
+wait_for_fifo(u16 entries, const struct fb_info_aty128 *info)
+{
+    unsigned long timeout = jiffies + HZ/20;
+    int reset = 1;
+
+    while (time_before(jiffies, timeout))
+       if ((aty_ld_le32(GUI_STAT) & 0x00000FFF) < entries) {
+           reset = 0;
+           break;
+       }
+
+    if (reset)
+       aty128_reset_engine(info);
+}
+
+
+static void
+aty128_flush_pixel_cache(const struct fb_info_aty128 *info)
+{
+    int i = 16384;
+
+    aty_st_le32(PC_NGUI_CTLSTAT, aty_ld_le32(PC_NGUI_CTLSTAT) | 0x000000ff);
+
+    while (i && (aty_ld_le32(PC_NGUI_CTLSTAT) & PC_BUSY))
+       i--;
+}
+
+
+static void
+aty128_reset_engine(const struct fb_info_aty128 *info)
+{
+    u32 gen_reset_cntl, clock_cntl_index, mclk_cntl;
+
+    aty128_flush_pixel_cache(info);
+
+    clock_cntl_index = aty_ld_le32(CLOCK_CNTL_INDEX);
+    mclk_cntl = aty_ld_pll(MCLK_CNTL);
+
+    aty_st_pll(MCLK_CNTL, mclk_cntl | 0x00030000);
+
+    gen_reset_cntl = aty_ld_le32(GEN_RESET_CNTL);
+    aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl | SOFT_RESET_GUI);
+    aty_ld_le32(GEN_RESET_CNTL);
+    aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl & ~(SOFT_RESET_GUI));
+    aty_ld_le32(GEN_RESET_CNTL);
+
+    aty_st_pll(MCLK_CNTL, mclk_cntl);
+    aty_st_le32(CLOCK_CNTL_INDEX, clock_cntl_index);
+    aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl);
+
+    /* use old pio mode */
+    aty_st_le32(PM4_BUFFER_CNTL, PM4_BUFFER_CNTL_NONPM4);
+
+#ifdef DEBUG
+    printk("aty128fb: engine reset\n");
+#endif
+}
+
+
+static void
+aty128_init_engine(const struct aty128fb_par *par,
+               const struct fb_info_aty128 *info)
+{
+    u32 temp;
+    aty_st_le32(SCALE_3D_CNTL, 0x00000000);
+
+    aty128_reset_engine(info);
+
+    temp = par->crtc.pitch;    /* fix this up */
+    if (par->crtc.bpp == 24) {
+        temp = temp * 3;
+    }
+
+    /* setup engine offset registers */
+    wait_for_fifo(4, info);
+    aty_st_le32(DEFAULT_OFFSET, 0x00000000);
+
+    /* setup engine pitch registers */
+    aty_st_le32(DEFAULT_PITCH, temp);
+
+    /* set the default scissor register to max dimensions */
+    wait_for_fifo(1, info);
+    aty_st_le32(DEFAULT_SC_BOTTOM_RIGHT, (0x1FFF << 16) | 0x1FFF);
+
+    /* set the drawing controls registers */
+    wait_for_fifo(1, info);
+    aty_st_le32(DP_GUI_MASTER_CNTL,
+                       GMC_SRC_PITCH_OFFSET_DEFAULT            |
+                       GMC_DST_PITCH_OFFSET_DEFAULT            |
+                       GMC_SRC_CLIP_DEFAULT                    |
+                       GMC_DST_CLIP_DEFAULT                    |
+                       GMC_BRUSH_SOLIDCOLOR                    |
+                       (bpp_to_depth(par->crtc.bpp) << 8)      |
+                       GMC_SRC_DSTCOLOR                        |
+                       GMC_BYTE_ORDER_MSB_TO_LSB               |
+                       GMC_DP_CONVERSION_TEMP_6500             |
+                       ROP3_PATCOPY                            |
+                       GMC_DP_SRC_RECT                         |
+                       GMC_3D_FCN_EN_CLR                       |
+                       GMC_DST_CLR_CMP_FCN_CLEAR               |
+                       GMC_AUX_CLIP_CLEAR                      |
+                       GMC_WRITE_MASK_SET);
+    wait_for_fifo(8, info);
+
+    /* clear the line drawing registers */
+    aty_st_le32(DST_BRES_ERR, 0);
+    aty_st_le32(DST_BRES_INC, 0);
+    aty_st_le32(DST_BRES_DEC, 0);
+
+    /* set brush color registers */
+    aty_st_le32(DP_BRUSH_FRGD_CLR, 0xFFFFFFFF);
+    aty_st_le32(DP_BRUSH_BKGD_CLR, 0x00000000);
+
+    /* set source color registers */
+    aty_st_le32(DP_SRC_FRGD_CLR, 0xFFFFFFFF);
+    aty_st_le32(DP_SRC_BKGD_CLR, 0x00000000);
+
+    /* default write mask */
+    aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF);
+
+    /* Wait for all the writes to be completed before returning */
+    wait_for_idle(info);
+}
+
+
+    /*
+     * CRTC programming
+     */
+
+/* convert bpp values to their register representation */
+static u32
+bpp_to_depth(u32 bpp)
+{
+    if (bpp <= 8)
+       return 2;
+    else if (bpp <= 15)
+       return 3;
+    else if (bpp <= 16)
+#if 0  /* force 15bpp */
+       return 4;
+#else
+       return 3;
+#endif
+    else if (bpp <= 24)
+       return 5;
+    else if (bpp <= 32)
+       return 6;
+
+    return -EINVAL;
+}
+
+
+static void
+aty128_set_crtc(const struct aty128_crtc *crtc,
+               const struct fb_info_aty128 *info)
+{
+    aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl);
+    // aty_st_le32(CRTC_EXT_CNTL, crtc->ext_cntl);
+    aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_total);
+    aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid);
+    aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_total);
+    aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid);
+    aty_st_le32(CRTC_PITCH, crtc->pitch);
+    aty_st_le32(CRTC_OFFSET, crtc->offset);
+    aty_st_le32(CRTC_OFFSET_CNTL, crtc->offset_cntl);
+}
+
+
+static int
+aty128_var_to_crtc(const struct fb_var_screeninfo *var,
+                       struct aty128_crtc *crtc,
+                       const struct fb_info_aty128 *info)
+{
+    u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
+    u32 left, right, upper, lower, hslen, vslen, sync, vmode;
+    u32 h_total, h_disp, h_sync_strt, h_sync_wid, h_sync_pol;
+    u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
+    u32 depth;
+    u8 hsync_strt_pix[5] = { 0, 0x12, 9, 6, 5 };
+
+    /* input */
+    xres = var->xres;
+    yres = var->yres;
+    vxres = var->xres_virtual;
+    vyres = var->yres_virtual;
+    xoffset = var->xoffset;
+    yoffset = var->yoffset;
+    bpp = var->bits_per_pixel;
+    left = var->left_margin;
+    right = var->right_margin;
+    upper = var->upper_margin;
+    lower = var->lower_margin;
+    hslen = var->hsync_len;
+    vslen = var->vsync_len;
+    sync = var->sync;
+    vmode = var->vmode;
+
+    /* check for mode eligibility */
+
+    /* accept only non interlaced modes */
+    if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+       return -EINVAL;
+
+    /* convert (and round up) and validate */
+    xres = (xres + 7) & ~7;
+    xoffset = (xoffset + 7) & ~7;
+
+    if (vxres < xres + xoffset)
+       vxres = xres + xoffset;
+
+    if (vyres < yres + yoffset)
+       vyres = yres + yoffset;
+
+    if (bpp <= 8)
+       bpp = 8;
+    else if (bpp <= 16)
+       bpp = 16;
+    else if (bpp <= 32)
+       bpp = 32;
+
+    if (vxres * vyres * (bpp/8) > info->vram_size)
+       return -EINVAL;
+
+    h_disp = xres / 8 - 1;
+    h_total = (xres + right + hslen + left) / 8 - 1;
+
+    v_disp = yres - 1;
+    v_total = yres + upper + vslen + lower - 1;
+
+    h_sync_wid = hslen / 8;
+    if (h_sync_wid == 0)
+       h_sync_wid = 1;
+    else if (h_sync_wid > 0x3f)
+       h_sync_wid = 0x3f;
+
+    h_sync_strt = (xres + right - 8) + hsync_strt_pix[bpp/8];
+
+    v_disp = yres - 1;
+    v_sync_wid = vslen;
+    if (v_sync_wid == 0)
+       v_sync_wid = 1;
+    else if (v_sync_wid > 0x1f)
+       v_sync_wid = 0x1f;
+    
+    v_sync_strt = yres + lower - 1;
+
+    h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : (1 << 23);
+    v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : (1 << 23);
+
+    depth = bpp_to_depth(bpp);
+    c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;
+
+    crtc->gen_cntl = 0x03000000 | c_sync | depth << 8;
+
+    crtc->h_total = (h_disp << 16) | (h_total & 0x0000FFFF);
+    crtc->v_total = (v_disp << 16) | (v_total & 0x0000FFFF);
+
+    crtc->h_sync_strt_wid = (h_sync_wid << 16) | (h_sync_strt) | h_sync_pol;
+    crtc->v_sync_strt_wid = (v_sync_wid << 16) | (v_sync_strt) | v_sync_pol;
+
+    crtc->pitch = xres / 8;
+
+    crtc->offset = 0;
+    crtc->offset_cntl = 0;
+
+    crtc->vxres = vxres;
+    crtc->vyres = vyres;
+    crtc->bpp = bpp;
+
+    return 0;
+}
+
+
+static int
+aty128_crtc_to_var(const struct aty128_crtc *crtc,
+                       struct fb_var_screeninfo *var)
+{
+#ifdef notyet  /* xoffset and yoffset are not correctly calculated */
+    u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync;
+    u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
+    u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
+    u32 pix_width;
+
+    h_total = crtc->h_total & 0x1ff;
+    h_disp = (crtc->h_total>>16) & 0xff;
+    h_sync_strt = (crtc->h_sync_strt_wid & 0xff) |
+        ((crtc->h_sync_strt_wid>>4) & 0x100);
+    h_sync_dly = (crtc->h_sync_strt_wid>>8) & 0x7;
+    h_sync_wid = (crtc->h_sync_strt_wid>>16) & 0x1f;
+    h_sync_pol = (crtc->h_sync_strt_wid>>21) & 0x1;
+    v_total = crtc->v_total & 0x7ff;
+    v_disp = (crtc->v_total>>16) & 0x7ff;
+    v_sync_strt = crtc->v_sync_strt_wid & 0x7ff;
+    v_sync_wid = (crtc->v_sync_strt_wid>>16) & 0x1f;
+    v_sync_pol = (crtc->v_sync_strt_wid>>21) & 0x1;
+    c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
+    pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
+
+    xres = (h_disp+1)*8;
+    yres = v_disp+1;
+    left = (h_total-h_sync_strt-h_sync_wid)*8-h_sync_dly;
+    right = (h_sync_strt-h_disp)*8+h_sync_dly;
+    hslen = h_sync_wid*8;
+    upper = v_total-v_sync_strt-v_sync_wid;
+    lower = v_sync_strt-v_disp;
+    vslen = v_sync_wid;
+    sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
+        (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
+        (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
+
+    switch (pix_width) {
+#if 0
+    case CRTC_PIX_WIDTH_4BPP:
+        bpp = 4;
+        var->red.offset = 0;
+        var->red.length = 8;
+        var->green.offset = 0;
+        var->green.length = 8;
+        var->blue.offset = 0;
+        var->blue.length = 8;
+        var->transp.offset = 0;
+        var->transp.length = 0;
+        break;
+#endif
+    case CRTC_PIX_WIDTH_8BPP:
+        bpp = 8;
+        var->red.offset = 0;
+        var->red.length = 8;
+        var->green.offset = 0;
+        var->green.length = 8;
+        var->blue.offset = 0;
+        var->blue.length = 8;
+        var->transp.offset = 0;
+        var->transp.length = 0;
+        break;
+    case CRTC_PIX_WIDTH_15BPP:
+        bpp = 16;
+        var->red.offset = 10;
+        var->red.length = 5;
+        var->green.offset = 5;
+        var->green.length = 5;
+        var->blue.offset = 0;
+        var->blue.length = 5;
+        var->transp.offset = 0;
+        var->transp.length = 0;
+        break;
+    case CRTC_PIX_WIDTH_16BPP:
+        bpp = 16;
+        var->red.offset = 11;
+        var->red.length = 5;
+        var->green.offset = 5;
+        var->green.length = 6;
+        var->blue.offset = 0;
+        var->blue.length = 5;
+        var->transp.offset = 0;
+        var->transp.length = 0;
+        break;
+    case CRTC_PIX_WIDTH_24BPP:
+        bpp = 24;
+        var->red.offset = 16;
+        var->red.length = 8;
+        var->green.offset = 8;
+        var->green.length = 8;
+        var->blue.offset = 0;
+        var->blue.length = 8;
+        var->transp.offset = 0;
+        var->transp.length = 0;
+        break;
+    case CRTC_PIX_WIDTH_32BPP:
+        bpp = 32;
+        var->red.offset = 16;
+        var->red.length = 8;
+        var->green.offset = 8;
+        var->green.length = 8;
+        var->blue.offset = 0;
+        var->blue.length = 8;
+        var->transp.offset = 24;
+        var->transp.length = 8;
+        break;
+    default:
+        printk(KERN_ERR "Invalid pixel width\n");
+    }
+
+//Godda do math for xoffset and yoffset: does not exist in crtc
+    var->xres = xres;
+    var->yres = yres;
+    var->xres_virtual = crtc->vxres;
+    var->yres_virtual = crtc->vyres;
+    var->bits_per_pixel = bpp;
+    var->xoffset = crtc->xoffset;
+    var->yoffset = crtc->yoffset;
+    var->left_margin = left;
+    var->right_margin = right;
+    var->upper_margin = upper;
+    var->lower_margin = lower;
+    var->hsync_len = hslen;
+    var->vsync_len = vslen;
+    var->sync = sync;
+    var->vmode = FB_VMODE_NONINTERLACED;
+
+#endif /* notyet */
+    return 0;
+}
+
+static int
+aty128_bpp_to_var(int bpp, struct fb_var_screeninfo *var)
+{
+    /* fill in pixel info */
+    switch (bpp) {
+    case 8:
+       var->red.offset = 0;
+       var->red.length = 8;
+       var->green.offset = 0;
+       var->green.length = 8;
+       var->blue.offset = 0;
+       var->blue.length = 8;
+       var->transp.offset = 0;
+       var->transp.length = 0;
+       break;
+    case 15:
+       var->bits_per_pixel = 16;
+       var->red.offset = 10;
+       var->red.length = 5;
+       var->green.offset = 5;
+       var->green.length = 5;
+       var->blue.offset = 0;
+       var->blue.length = 5;
+       var->transp.offset = 15;
+       var->transp.length = 1;
+       break;
+    case 16:
+       var->bits_per_pixel = 16;
+       var->red.offset = 11;
+       var->red.length = 5;
+       var->green.offset = 5;
+       var->green.length = 6;
+       var->blue.offset = 0;
+       var->blue.length = 5;
+       var->transp.offset = 0;
+       var->transp.length = 0;
+       break;
+    case 32:
+       var->red.offset = 16;
+       var->red.length = 8;
+       var->green.offset = 8;
+       var->green.length = 8;
+       var->blue.offset = 0;
+       var->blue.length = 8;
+       var->transp.offset = 24;
+       var->transp.length = 8;
+       break;
+    }
+
+    return 0;
+}
+
+
+static void
+aty128_set_pll(struct aty128_pll *pll, const struct fb_info_aty128 *info)
+{
+    int div3;
+    unsigned char post_conv[] =        /* register values for post dividers */
+       { 2, 0, 1, 4, 2, 2, 6, 2, 3, 2, 2, 2, 7 };
+
+    /* select PPLL_DIV_3 */
+    aty_st_le32(CLOCK_CNTL_INDEX, aty_ld_le32(CLOCK_CNTL_INDEX) | (3 << 8));
+
+    /* reset ppll */
+    aty_st_pll(PPLL_CNTL,
+               aty_ld_pll(PPLL_CNTL) | PPLL_RESET | PPLL_ATOMIC_UPDATE_EN);
+
+    div3 = aty_ld_pll(PPLL_DIV_3);
+
+    div3 &= ~PPLL_FB3_DIV_MASK;
+    div3 |= pll->feedback_divider;
+
+    div3 &= ~PPLL_POST3_DIV_MASK;
+    div3 |= post_conv[pll->post_divider] << 16;
+
+    /* write feedback and post dividers */
+    aty_st_pll(PPLL_DIV_3, div3);
+    aty_pll_writeupdate(info);
+    aty_pll_wait_readupdate(info);
+
+    aty_st_pll(HTOTAL_CNTL, 0);        /* no horiz crtc adjustment */
+
+    aty_pll_writeupdate(info);
+
+    /* clear the reset, just in case */
+    aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~PPLL_RESET);
+}
+
+
+static int
+aty128_var_to_pll(u32 vclk_per, struct aty128_pll *pll,
+                       const struct fb_info_aty128 *info)
+{
+    const struct aty128_constants c = info->constants;
+    unsigned char post_dividers [] = {1,2,4,8,3,6,12};
+    u32 output_freq, vclk;
+    int i;
+    u32 n, d;
+
+    vclk = 100000000 / vclk_per;       /* convert units to 10 kHz */
+
+    /* adjust pixel clock if necessary */
+    if (vclk > c.ppll_max)
+       vclk = c.ppll_max;
+    if (vclk * 12 < c.ppll_min)
+       vclk = c.ppll_min;
+
+    /* now, find an acceptable divider */
+    for (i = 0; i < sizeof(post_dividers); i++) {
+       output_freq = post_dividers[i] * vclk;
+       if (output_freq >= c.ppll_min && output_freq <= c.ppll_max)
+           break;
+    }
+    pll->post_divider = post_dividers[i];
+
+    /* calculate feedback divider */
+    n = c.ref_divider * output_freq;
+    d = c.dotclock;
+    pll->feedback_divider = round_div(n, d);
+
+    pll->vclk = vclk;
+#ifdef DEBUG
+    printk("post %x  feedback %x vlck %x output %x\n",
+          pll->post_divider, pll->feedback_divider, vclk, output_freq);
+#endif
+
+    return 0;
+}
+
+
+static int
+aty128_pll_to_var(const struct aty128_pll *pll, struct fb_var_screeninfo *var)
+{
+    /* TODO */
+    return 0;
+}
+
+
+static void
+aty128_set_fifo(const struct aty128_ddafifo *dsp,
+                       const struct fb_info_aty128 *info)
+{
+    aty_st_le32(DDA_CONFIG, dsp->dda_config);
+    aty_st_le32(DDA_ON_OFF, dsp->dda_on_off);
+}
+
+
+static int
+aty128_ddafifo(struct aty128_ddafifo *dsp,
+               const struct aty128_pll *pll,
+               u32 bpp,
+               const struct fb_info_aty128 *info)
+{
+    const struct aty128_meminfo *m = info->mem;
+    u32 xclk = info->constants.xclk;
+    u32 fifo_width = info->constants.fifo_width;
+    u32 fifo_depth = info->constants.fifo_depth;
+    s32 x, b, p, ron, roff;
+    u32 n, d;
+
+    if (bpp == 15)
+       bpp = 16;
+
+    n = xclk * fifo_width;
+    d = pll->vclk*bpp;
+    x = round_div(n, d);
+
+    ron = 4 * m->MB +
+       3 * ((m->Trcd - 2 > 0) ? m->Trcd - 2 : 0) +
+       2 * m->Trp +
+       m->Twr +
+       m->CL +
+       m->Tr2w +
+       x;
+
+#ifdef DEBUG
+    printk("x %x\n", x);
+#endif
+    b = 0;
+    while (x) {
+       x >>= 1;
+       b++;
+    }
+    p = b + 1;
+
+    ron <<= (11 - p);
+
+    n <<= (11 - p);
+    x = round_div(n, d);
+    roff = x * (fifo_depth - 4);
+    if ((ron + m->Rloop) >= roff) {
+       printk("Mode out of range\n");
+       return -EINVAL;
+    }
+
+#ifdef DEBUG
+    printk("p: %x rloop: %x x: %x ron: %x roff: %x\n", p, m->Rloop, x,
+       ron, roff);
+#endif
+    dsp->dda_config = p << 16 | m->Rloop << 20 | x;
+    dsp->dda_on_off = ron << 16 | roff;
+
+    return 0;
+}
+
+
+/*
+ * This actually sets the video mode.
+ */
+static void
+aty128_set_par(struct aty128fb_par *par,
+                       struct fb_info_aty128 *info)
+{ 
+    u32 config;
+    
+    info->current_par = *par;
+
+    /* clear all registers that may interfere with mode setting */
+    aty_st_le32(OVR_CLR, 0);
+    aty_st_le32(OVR_WID_LEFT_RIGHT, 0);
+    aty_st_le32(OVR_WID_TOP_BOTTOM, 0);
+    aty_st_le32(OV0_SCALE_CNTL, 0);
+    aty_st_le32(MPP_TB_CONFIG, 0);
+    aty_st_le32(MPP_GP_CONFIG, 0);
+    aty_st_le32(SUBPIC_CNTL, 0);
+    aty_st_le32(VIPH_CONTROL, 0);
+    aty_st_le32(I2C_CNTL_1, 0);
+    aty_st_le32(GEN_INT_CNTL, 0);      /* turn off interrupts */
+    aty_st_le32(CAP0_TRIG_CNTL, 0);
+    aty_st_le32(CAP1_TRIG_CNTL, 0);
+
+    aty_st_8(CRTC_EXT_CNTL + 1, 4);    /* turn video off */
+
+    aty128_set_crtc(&par->crtc, info);
+    aty128_set_pll(&par->pll, info);
+    aty128_set_fifo(&par->fifo_reg, info);
+
+    config = aty_ld_le32(CONFIG_CNTL) & ~3;
+
+#if defined(__BIG_ENDIAN)
+    if (par->crtc.bpp >= 24)
+       config |= 2;    /* make aperture do 32 byte swapping */
+    else if (par->crtc.bpp > 8)
+       config |= 1;    /* make aperture do 16 byte swapping */
+#endif
+
+    aty_st_le32(CONFIG_CNTL, config);
+
+    aty_st_8(CRTC_EXT_CNTL + 1, 0);    /* turn the video back on */
+}
+
+
+    /*
+     *  Open/Release the frame buffer device
+     */
+
+static int aty128fb_open(struct fb_info *info, int user)
+{
+    MOD_INC_USE_COUNT;
+    return(0);                              
+}
+        
+
+static int aty128fb_release(struct fb_info *info, int user)
+{
+    MOD_DEC_USE_COUNT;
+    return(0);                                                    
+}
+
+
+static int
+aty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par,
+                       const struct fb_info_aty128 *info)
+{
+    int err;
+
+    if ((err = aty128_var_to_crtc(var, &(par->crtc), info)))
+       return err;
+
+    if ((err = aty128_var_to_pll(var->pixclock, &(par->pll), info)))
+       return err;
+
+    if ((err = aty128_ddafifo(&par->fifo_reg, &par->pll, par->crtc.bpp, info)))
+       return err;
+
+    if (var->accel_flags & FB_ACCELF_TEXT)
+       par->accel_flags = FB_ACCELF_TEXT;
+    else
+       par->accel_flags = 0;
+
+    return 0;
+}
+
+
+static int
+aty128_encode_var(struct fb_var_screeninfo *var,
+                       const struct aty128fb_par *par,
+                       const struct fb_info_aty128 *info)
+{
+    int err;
+
+    //memset(var, 0, sizeof(struct fb_var_screeninfo));
+
+    /* XXX aty128_*_to_var() aren't fully implemented! */
+    if ((err = aty128_crtc_to_var(&par->crtc, var)))
+       return err;
+
+    if ((err = aty128_pll_to_var(&par->pll, var)))
+       return err;
+
+    if ((err = aty128_bpp_to_var(var->bits_per_pixel, var)))
+       return err;
+
+    var->height = -1;
+    var->width = -1;
+    var->accel_flags = par->accel_flags;
+
+    return 0;
+}           
+
+
+    /*
+     *  Get the User Defined Part of the Display
+     */
+
+static int
+aty128fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb)
+{
+    const struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
+
+    if (con == -1)
+       aty128_encode_var(var, &info->default_par, info); 
+    else
+       *var = fb_display[con].var;
+    return 0;
+}
+
+
+    /*
+     *  Set the User Defined Part of the Display
+     */
+
+static int
+aty128fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb)
+{
+    struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
+    struct aty128fb_par par;
+    struct display *display;
+    int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
+    int accel, err;
+
+    display = (con >= 0) ? &fb_display[con] : fb->disp;
+
+    if ((err = aty128_decode_var(var, &par, info)))
+       return err;
+
+    aty128_encode_var(var, &par, info);
+
+    if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
+       return 0;
+
+    oldxres = display->var.xres;
+    oldyres = display->var.yres;
+    oldvxres = display->var.xres_virtual;
+    oldvyres = display->var.yres_virtual;
+    oldbpp = display->var.bits_per_pixel;
+    oldaccel = display->var.accel_flags;
+    display->var = *var;
+    if (oldxres != var->xres || oldyres != var->yres ||
+       oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
+       oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) {
+
+       struct fb_fix_screeninfo fix;
+       aty128_encode_fix(&fix, &par, info);
+       display->screen_base = (char *) info->frame_buffer;
+       display->visual = fix.visual;
+       display->type = fix.type;
+       display->type_aux = fix.type_aux;
+       display->ypanstep = fix.ypanstep;
+       display->ywrapstep = fix.ywrapstep;
+       display->line_length = fix.line_length;
+       display->can_soft_blank = 1;
+       display->inverse = 0;
+
+       accel = var->accel_flags & FB_ACCELF_TEXT;
+       aty128_set_disp(display, info, var->bits_per_pixel, accel);
+
+#if 0  /* acceleration is not ready */
+       if (accel)
+           display->scrollmode = 0;
+       else
+#endif
+           display->scrollmode = SCROLL_YREDRAW;
+
+       if (info->fb_info.changevar)
+           (*info->fb_info.changevar)(con);
+    }
+
+    if (!info->fb_info.display_fg || info->fb_info.display_fg->vc_num == con)
+       aty128_set_par(&par, info);
+
+    if (oldbpp != var->bits_per_pixel) {
+       if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
+           return err;
+       do_install_cmap(con, &info->fb_info);
+    } 
+
+    return 0;
+}
+
+
+static void
+aty128_set_disp(struct display *disp,
+                       struct fb_info_aty128 *info, int bpp, int accel)
+{
+    switch (bpp) {
+#ifdef FBCON_HAS_CFB8
+    case 8:
+       disp->dispsw = accel ? &fbcon_aty128_8 : &fbcon_cfb8;
+       break;
+#endif
+#ifdef FBCON_HAS_CFB16
+    case 16:
+       disp->dispsw = &fbcon_cfb16;
+       disp->dispsw_data = info->fbcon_cmap.cfb16;
+       break;
+#endif
+#ifdef FBCON_HAS_CFB24
+    case 24:
+       disp->dispsw = &fbcon_cfb24;
+       disp->dispsw_data = info->fbcon_cmap.cfb24;
+       break;
+#endif
+#ifdef FBCON_HAS_CFB32
+    case 32:
+       disp->dispsw = &fbcon_cfb32;
+       disp->dispsw_data = info->fbcon_cmap.cfb32;
+       break;
+#endif
+    default:
+       disp->dispsw = &fbcon_dummy;
+    }
+}
+
+
+static void
+aty128_encode_fix(struct fb_fix_screeninfo *fix,
+                       struct aty128fb_par *par,
+                       const struct fb_info_aty128 *info)
+{
+    memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+    
+    strcpy(fix->id, aty128fb_name);
+    fix->smem_start = (long) info->frame_buffer_phys;
+    fix->smem_len = info->vram_size;
+
+    fix->mmio_start = (long) info->regbase_phys;
+    fix->mmio_len = 0x1fff;
+
+    fix->type = FB_TYPE_PACKED_PIXELS;
+    fix->line_length = par->crtc.vxres*par->crtc.bpp/8;
+    fix->visual = par->crtc.bpp <= 8 ? FB_VISUAL_PSEUDOCOLOR
+                                       : FB_VISUAL_DIRECTCOLOR;
+
+    fix->xpanstep = 8;
+    fix->ypanstep = 1;
+
+    fix->accel = FB_ACCEL_ATI_RAGE128;
+    return;
+}
+
+
+    /*
+     *  Get the Fixed Part of the Display
+     */
+static int
+aty128fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *fb)
+{
+    const struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
+    struct aty128fb_par par;
+
+    if (con == -1)
+       par = info->default_par;
+    else
+       aty128_decode_var(&fb_display[con].var, &par, info); 
+
+    aty128_encode_fix(fix, &par, info);
+    return 0;            
+}
+
+
+    /*
+     *  Pan or Wrap the Display
+     *
+     *  Not supported (yet!)
+     */
+static int
+aty128fb_pan_display(struct fb_var_screeninfo *var, int con,
+                          struct fb_info *info)
+{
+    if (var->xoffset != 0 || var->yoffset != 0)
+       return -EINVAL;
+
+    return 0;
+}
+
+
+    /*
+     *  Get the Colormap
+     */
+
+static int
+aty128fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+                       struct fb_info *info)
+{
+    if (!info->display_fg ||
+       con == info->display_fg->vc_num) /* current console ? */        
+       return fb_get_cmap(cmap, kspc, aty128_getcolreg, info);
+    else if (fb_display[con].cmap.len) /* non default colormap? */
+       fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+    else {  
+       int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 32;
+       fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
+    }
+    return 0;
+}
+
+    /*
+     *  Set the Colormap
+     */
+
+static int
+aty128fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+                       struct fb_info *info)
+{
+    int err;
+    struct display *disp;  
+
+    if (con >= 0)
+       disp = &fb_display[con];
+    else
+       disp = info->disp;
+    if (!disp->cmap.len) {      /* no colormap allocated? */
+       int size = (disp->var.bits_per_pixel <= 16) ? 256 : 32;
+       if ((err = fb_alloc_cmap(&disp->cmap, size, 0)))
+           return err;
+    }
+    if (!info->display_fg || con == info->display_fg->vc_num)
+/* current console? */
+       return fb_set_cmap(cmap, kspc, aty128_setcolreg, info);
+    else
+       fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
+    return 0;                
+}
+
+
+    /*
+     *  Virtual Frame Buffer Specific ioctls
+     */
+
+static int
+aty128fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+                    u_long arg, int con, struct fb_info *info)
+{
+    return -EINVAL;
+}
+
+
+int __init
+aty128fb_setup(char *options)
+{
+    char *this_opt;
+
+    if (!options || !*options)
+       return 0;
+
+    for (this_opt = strtok(options, ","); this_opt;
+        this_opt = strtok(NULL, ",")) {
+       if (!strncmp(this_opt, "font:", 5)) {
+           char *p;
+           int i;
+           
+           p = this_opt +5;
+           for (i = 0; i < sizeof(fontname) - 1; i++)
+               if (!*p || *p == ' ' || *p == ',')
+                   break;
+           memcpy(fontname, this_opt + 5, i);
+           fontname[i] = 0;
+       }
+#if defined(CONFIG_PPC)
+       if (!strncmp(this_opt, "vmode:", 6)) {
+            unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
+            if (vmode > 0 && vmode <= VMODE_MAX)
+                default_vmode = vmode;
+        } else if (!strncmp(this_opt, "cmode:", 6)) {
+            unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
+            switch (cmode) {
+           case 0:
+           case 8:
+               default_cmode = CMODE_8;
+               break;
+           case 15:
+           case 16:
+               default_cmode = CMODE_16;
+               break;
+           case 24:
+           case 32:
+               default_cmode = CMODE_32;
+               break;
+            }
+        }
+#endif
+#ifdef CONFIG_MTRR
+       if(mtrr) {
+               ACCESS_FBINFO(mtrr.vram) =
+                       mtrr_add(video_base_phys, ACCESS_FBINFO(video.len),
+                               MTRR_TYPE_WRCOMB, 1);
+               ACCESS_FBINFO(mtrr.valid_vram) = 1;
+               printk(KERN_INFO "aty128fb: MTRR set to ON\n");
+       }
+#endif
+    }
+    return 0;
+}
+
+
+    /*
+     *  Initialisation
+     */
+
+static int
+aty128_init(struct fb_info_aty128 *info, const char *name)
+{
+    struct fb_var_screeninfo var;
+    u32 dac;
+    int j, k;
+    u8 chip_rev;
+
+    if (!register_test(info)) {
+       printk("Can't write to video registers\n");
+       return 0;
+    }
+
+    if (!info->vram_size)      /* may have already been probed */
+       info->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
+
+    chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F;
+
+    /* TODO be more verbose */
+    printk("aty128fb: Rage128 [rev 0x%x] ", chip_rev);
+
+    if (info->vram_size % (1024 * 1024) == 0)
+       printk("%dM ", info->vram_size / (1024*1024));
+    else
+       printk("%dk ", info->vram_size / 1024);
+
+    var = default_var;
+
+#ifdef CONFIG_PMAC
+
+    if (default_vmode == VMODE_NVRAM) {
+#ifdef CONFIG_NVRAM
+       default_vmode = nvram_read_byte(NV_VMODE);
+       if (default_vmode <= 0 || default_vmode > VMODE_MAX)
+#endif /* CONFIG_NVRAM */
+           default_vmode = VMODE_CHOOSE;
+    }
+
+    if (default_cmode == CMODE_NVRAM) {
+#ifdef CONFIG_NVRAM
+       default_cmode = nvram_read_byte(NV_CMODE);
+       if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
+#endif /* CONFIG_NVRAM */
+           default_vmode = VMODE_CHOOSE;
+    }
+
+    if (default_vmode != VMODE_CHOOSE &&
+       mac_vmode_to_var(default_vmode, default_cmode, &var))
+       var = default_var;
+
+#endif /* CONFIG_PMAC */
+
+    if (aty128_decode_var(&var, &info->default_par, info)) {
+       printk("Cannot set default mode.\n");
+       return 0;
+    }
+
+    /* fill in info */
+    strcpy(info->fb_info.modename, aty128fb_name);
+    info->fb_info.node = -1;
+    info->fb_info.fbops = &aty128fb_ops;
+    info->fb_info.disp = &info->disp;
+    strcpy(info->fb_info.fontname, fontname);
+    info->fb_info.changevar = NULL;
+    info->fb_info.switch_con = &aty128fbcon_switch;
+    info->fb_info.blank = &aty128fbcon_blank;
+    info->fb_info.flags = FBINFO_FLAG_DEFAULT;
+
+    for (j = 0; j < 16; j++) {
+        k = color_table[j];
+        info->palette[j].red = default_red[k];
+        info->palette[j].green = default_grn[k];
+        info->palette[j].blue = default_blu[k];
+    }
+
+    dac = aty_ld_le32(DAC_CNTL) & 15;  /* preserve lower three bits */
+    dac |= DAC_8BIT_EN;                        /* set 8 bit dac */
+    dac |= (0xFF << 24);               /* set DAC mask */
+    aty_st_le32(DAC_CNTL, dac);
+
+    /* turn off bus mastering, just in case */
+    aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL) | BUS_MASTER_DIS);
+
+    aty128fb_set_var(&var, -1, &info->fb_info);
+    aty128_init_engine(&info->default_par, info);
+
+    printk("\n");
+    if (register_framebuffer(&info->fb_info) < 0)
+       return 0;
+
+    printk("fb%d: %s frame buffer device on %s\n",
+          GET_FB_IDX(info->fb_info.node), aty128fb_name, name);
+
+    return 1;  /* success! */
+}
+
+
+void __init
+aty128fb_init(void)
+{
+#if defined(CONFIG_FB_OF)
+/* let offb handle init */
+#elif defined (CONFIG_PCI)
+    aty128pci_probe();
+#endif
+}
+
+
+void
+aty128pci_probe(void)
+{
+    struct pci_dev *pdev;
+    struct fb_info_aty128 *info;
+    unsigned long fb_addr, reg_addr;
+    u16 tmp;
+
+    for (pdev = pci_devices; pdev; pdev = pdev->next) {
+       if (((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) &&
+           (pdev->vendor == PCI_VENDOR_ID_ATI)) {
+           struct resource *rp;
+
+           /* FIXME add other known R128 device ID's */
+           switch (pdev->device) {
+           case 0x5245:
+           case 0x5246:
+           case 0x524B:
+           case 0x524C:
+               break;
+           default:
+               continue;
+           }
+
+           rp = &pdev->resource[0];
+           fb_addr = rp->start;
+           if (!fb_addr)
+               continue;
+           fb_addr &= PCI_BASE_ADDRESS_MEM_MASK;
+
+           rp = &pdev->resource[2];
+           reg_addr = rp->start;
+           if (!reg_addr)
+               continue;
+           reg_addr &= PCI_BASE_ADDRESS_MEM_MASK;
+
+           info = kmalloc(sizeof(struct fb_info_aty128), GFP_ATOMIC);
+           if (!info) {
+               printk("aty128fb: can't alloc fb_info_aty128\n");
+               return;
+           }
+           memset(info, 0, sizeof(struct fb_info_aty128));
+
+           info->regbase_phys = reg_addr;
+           info->regbase = (unsigned long) ioremap(reg_addr, 0x1FFF);
+
+           if (!info->regbase) {
+               kfree(info);
+               return;
+           }
+
+           info->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
+
+           info->frame_buffer = fb_addr;
+           info->frame_buffer = (unsigned long)
+                                   ioremap(fb_addr, info->vram_size);
+
+           if (!info->frame_buffer) {
+               kfree(info);
+               return;
+           }
+
+           pci_read_config_word(pdev, PCI_COMMAND, &tmp);
+           if (!(tmp & PCI_COMMAND_MEMORY)) {
+               tmp |= PCI_COMMAND_MEMORY;
+               pci_write_config_word(pdev, PCI_COMMAND, tmp);
+           }
+
+#if defined(CONFIG_PPC)
+           aty128_timings(info);
+#else
+            if (!aty128find_ROM(info)) {
+                printk("Rage128 BIOS not located.  Guessing...\n");
+                aty128_timings(info);
+            }
+            else
+                aty128_get_pllinfo(info);
+#endif
+
+           if (!aty128_init(info, "PCI")) {
+               kfree(info);
+               return;
+           }
+       }
+    }
+}
+
+
+static int
+aty128find_ROM(struct fb_info_aty128 *info)
+{
+    u32 segstart;
+    char *rom_base;
+    char *rom_base1;
+    char *rom;
+    int stage;
+    int i;
+    char aty_rom_sig[] = "761295520";
+    char R128_sig[] = "R128";
+    int flag = 0;
+DBG("E  aty128find_ROM");
+
+    for (segstart = 0x000c0000; segstart < 0x000f0000; segstart += 0x00001000) {
+        stage = 1;
+
+        rom_base = (char *) ioremap(segstart, 0x1000);
+        rom_base1 = (char *) (rom_base+1);
+
+        if ((*rom_base == 0x55) && (((*rom_base1) & 0xff) == 0xaa)) {
+            stage = 2;
+        }
+
+        if (stage != 2) {
+            iounmap(rom_base);
+            continue;
+        }
+        rom = rom_base;
+
+        for (i = 0; (i < 128 - strlen(aty_rom_sig)) && (stage != 3); i++) {
+            if (aty_rom_sig[0] == *rom) {
+                if (strncmp(aty_rom_sig, rom, strlen(aty_rom_sig)) == 0) {
+                    stage = 3;
+                }
+            }
+            rom++;
+        }
+        if (stage != 3) {
+            iounmap(rom_base);
+            continue;
+        }
+        rom = rom_base;
+
+        for (i = 0; (i < 512) && (stage != 4); i++) {
+            if (R128_sig[0] == *rom) {
+                if (strncmp(R128_sig, rom, strlen(R128_sig)) == 0) {
+                    stage = 4;
+                }
+            }
+            rom++;
+        }
+        if (stage != 4) {
+            iounmap(rom_base);
+            continue;
+        }
+
+        printk("Rage128 BIOS located at segment %4.4X\n", (u32)rom_base);
+        info->BIOS_SEG = (u32)rom_base;
+        flag = 1;
+
+        break;
+    }
+DBG("L  aty128find_ROM");
+    return (flag);
+}
+
+
+static void
+aty128_get_pllinfo(struct fb_info_aty128 *info)
+{   
+    u32 bios_header;
+    u32 *header_ptr;
+    u16 bios_header_offset, pll_info_offset;
+    PLL_BLOCK pll;
+DBG("E  aty128_get_pllinfo");
+
+    bios_header = info->BIOS_SEG + 0x48L;
+    header_ptr = (u32 *)bios_header;
+
+    bios_header_offset = (u16)*header_ptr;
+    bios_header = info->BIOS_SEG + (u32)bios_header_offset;
+    bios_header += 0x30;
+
+    header_ptr = (u32 *)bios_header;
+    pll_info_offset = (u16)*header_ptr;
+    header_ptr = (u32 *)(info->BIOS_SEG + (u32)pll_info_offset);
+
+    memcpy(&pll, header_ptr, 50);
+
+    info->constants.ppll_max = pll.PCLK_max_freq;
+    info->constants.ppll_min = pll.PCLK_min_freq;
+    info->constants.xclk = (u32)pll.XCLK;
+    info->constants.ref_divider = (u32)pll.PCLK_ref_divider;
+    info->constants.dotclock = (u32)pll.PCLK_ref_freq;
+
+    info->constants.fifo_width = 128;
+    info->constants.fifo_depth = 32;
+
+    switch(aty_ld_le32(MEM_CNTL) & 0x03) {
+    case 0:
+        info->mem = &sdr_128; 
+        break;
+    case 1:
+        info->mem = &sdr_sgram;
+        break;  
+    case 2: 
+        info->mem = &ddr_sgram;
+        break;  
+    default:        
+        info->mem = &sdr_sgram;
+    }       
+
+DBG("L  aty128get_pllinfo");
+    return;
+}           
+
+
+#ifdef CONFIG_FB_OF
+void
+aty128fb_of_init(struct device_node *dp)
+{
+    unsigned long addr, reg_addr, fb_addr;
+    struct fb_info_aty128 *info;
+    u8 bus, devfn;
+    u16 cmd;
+
+    switch (dp->n_addrs) {
+    case 3:
+       fb_addr = dp->addrs[0].address;
+       reg_addr = dp->addrs[2].address;
+       break;
+    default:
+       printk("aty128fb: TODO unexpected addresses\n");
+       return;
+    }
+
+    addr = (unsigned long) ioremap(reg_addr, 0x1FFF);
+    if (!addr) {
+       printk("aty128fb: can't map memory registers\n");
+       return;
+    }
+
+    info = kmalloc(sizeof(struct fb_info_aty128), GFP_ATOMIC);
+    if (!info) {
+       printk("aty128fb: can't alloc fb_info_aty128\n");
+       return;
+    }
+    memset(info, 0, sizeof(struct fb_info_aty128));
+
+    info->regbase_phys = reg_addr;
+    info->regbase = addr;
+
+    /* enabled memory-space accesses using config-space command register */
+    if (pci_device_loc(dp, &bus, &devfn) == 0) {
+       pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd);
+       if (!(cmd & PCI_COMMAND_MEMORY)) {
+           cmd |= PCI_COMMAND_MEMORY;
+           pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
+       }
+    }
+
+    info->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
+    info->frame_buffer_phys = fb_addr;
+    info->frame_buffer = (unsigned long) ioremap(fb_addr, info->vram_size);
+
+    /*
+     * TODO find OF values/hints.
+     *
+     * If we are booted from BootX, the MacOS ATI driver will likely have
+     * left useful tidbits in the DeviceRegistry.
+     */
+
+    if (!info->frame_buffer) {
+       printk("aty128fb: can't map frame buffer\n");
+       return;
+    }
+
+    aty128_timings(info);
+
+    if (!aty128_init(info, dp->full_name)) {
+       kfree(info);
+       return;
+    }
+}
+#endif
+
+
+/* fill in known card constants if pll_block is not available */
+static void
+aty128_timings(struct fb_info_aty128 *info)
+{
+    /* TODO make an attempt at probing */
+
+    info->constants.dotclock = 2950;
+
+    /* from documentation */
+    info->constants.ppll_min = 12500;
+    info->constants.ppll_max = 25000;  /* 23000 on some cards? */
+
+#if 1
+    /* XXX TODO. Calculate properly. Fix OF's pll ideas. */
+    info->constants.ref_divider = 0x3b;
+    aty_st_pll(PPLL_REF_DIV, info->constants.ref_divider);
+    aty_pll_writeupdate(info);
+
+    aty_st_pll(X_MPLL_REF_FB_DIV, 0x004c4c1e);
+    aty_pll_writeupdate(info);
+#else
+    info->constants.ref_divider = aty_ld_pll(PPLL_REF_DIV) & PPLL_REF_DIV_MASK;
+#endif
+
+    /* TODO. Calculate */
+    info->constants.xclk = 0x1d4d;     /* same as mclk */
+
+    info->constants.fifo_width = 128;
+    info->constants.fifo_depth = 32;
+
+    switch (aty_ld_le32(MEM_CNTL) & 0x3) {
+    case 0:
+       info->mem = &sdr_128;
+       break;
+    case 1:
+       info->mem = &sdr_sgram;
+       break;
+    case 2:
+       info->mem = &ddr_sgram;
+       break;
+    default:
+       info->mem = &sdr_sgram;
+    }
+}
+
+
+static int
+aty128fbcon_switch(int con, struct fb_info *fb)
+{
+    currcon = con;
+
+    /* Do we have to save the colormap? */
+    if (fb_display[currcon].cmap.len)
+       fb_get_cmap(&fb_display[currcon].cmap, 1, aty128_getcolreg, fb);
+
+#if 1
+    aty128fb_set_var(&fb_display[con].var, con, fb);
+#else
+{
+    struct fb_info_aty128 *info = (struct fb_info_aty128 *) fb;
+    struct aty128fb_par par;
+
+    aty128_decode_var(&fb_display[con].var, &par, info);
+    aty128_set_par(&par, info);
+    aty128_set_disp(&fb_display[con], info,
+       fb_display[con].var.bits_per_pixel);
+
+    do_install_cmap(con, fb);
+}
+#endif
+
+    return 1;
+}
+
+
+    /*
+     *  Blank the display.
+     */
+
+static void
+aty128fbcon_blank(int blank, struct fb_info *fb)
+{
+    struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
+    u8 state = 0;
+
+    if (blank & VESA_VSYNC_SUSPEND)
+       state |= 2;
+    if (blank & VESA_HSYNC_SUSPEND)
+       state |= 1;
+    if (blank & VESA_POWERDOWN)
+       state |= 4;
+
+    aty_st_8(CRTC_EXT_CNTL+1, state);
+}
+
+
+    /*
+     *  Read a single color register and split it into
+     *  colors/transparent. Return != 0 for invalid regno.
+     */
+static int
+aty128_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+                         u_int *transp, struct fb_info *fb)
+{
+    struct fb_info_aty128 *info = (struct fb_info_aty128 *) fb;
+
+    if (regno > 255)
+       return 1;
+
+    *red = (info->palette[regno].red<<8) | info->palette[regno].red;
+    *green = (info->palette[regno].green<<8) | info->palette[regno].green;
+    *blue = (info->palette[regno].blue<<8) | info->palette[regno].blue;
+    *transp = 0;
+    return 0;
+}
+
+
+    /*
+     *  Set a single color register. The values supplied are already
+     *  rounded down to the hardware's capabilities (according to the
+     *  entries in the var structure). Return != 0 for invalid regno.
+     */
+static int
+aty128_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                         u_int transp, struct fb_info *fb)
+{
+    struct fb_info_aty128 *info = (struct fb_info_aty128 *) fb;
+    u32 col;
+
+    if (regno > 255)
+       return 1;
+
+    red >>= 8;
+    green >>= 8;
+    blue >>= 8;
+    info->palette[regno].red = red;
+    info->palette[regno].green = green;
+    info->palette[regno].blue = blue;
+
+    aty_st_8(PALETTE_INDEX, regno);
+    col = red << 16 | green << 8 | blue;
+    aty_st_le32(PALETTE_DATA, col);
+
+    if (regno < 16)
+       switch (info->current_par.crtc.bpp) {
+#ifdef FBCON_HAS_CFB16
+       case 16:
+           info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) |
+               regno;
+           break;
+#endif
+#ifdef FBCON_HAS_CFB24
+       case 24:
+           info->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) |
+               regno;
+           break;
+#endif
+#ifdef FBCON_HAS_CFB32
+       case 32:
+           {
+               u32 i;
+               i = (regno << 8) | regno;
+               info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
+           }
+           break;
+#endif
+       }
+    return 0;
+}
+
+
+static void
+do_install_cmap(int con, struct fb_info *info)
+{
+    if (con != currcon)
+       return;
+    if (fb_display[con].cmap.len)
+       fb_set_cmap(&fb_display[con].cmap, 1, aty128_setcolreg, info);
+    else {
+       int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 16;
+       fb_set_cmap(fb_default_cmap(size), 1, aty128_setcolreg, info);
+    }
+}
+
+
+    /*
+     *  Accelerated functions
+     */
+
+static void
+aty128_rectdraw(s16 x, s16 y, u16 width, u16 height,
+               struct fb_info_aty128 *info)
+{
+    /* perform rectangle fill */
+    wait_for_fifo(2, info);
+    aty_st_le32(DST_Y_X, (y << 16) | x);
+    aty_st_le32(DST_HEIGHT_WIDTH, (height << 16) | width);
+}
+
+
+static void
+aty128_rectcopy(int srcx, int srcy, int dstx, int dsty,
+               u_int width, u_int height,
+               struct fb_info_aty128 *info)
+{
+    u32 direction = DST_LAST_PEL;
+    u32 pitch_value;
+
+    if (!width || !height)
+        return;
+
+    pitch_value = info->current_par.crtc.vxres;
+    if (info->current_par.crtc.bpp == 24) {
+        /* In 24 bpp, the engine is in 8 bpp - this requires that all */
+        /* horizontal coordinates and widths must be adjusted */
+        pitch_value *= 3;
+        srcx *= 3;
+        dstx *= 3;
+        width *= 3;
+    }
+    
+    if (srcy < dsty) {
+        dsty += height - 1;
+        srcy += height - 1;
+    } else
+        direction |= DST_Y_TOP_TO_BOTTOM;
+
+    if (srcx < dstx) {
+        dstx += width - 1;
+        srcx += width - 1;
+    } else
+        direction |= DST_X_LEFT_TO_RIGHT;
+
+    wait_for_fifo(4, info);
+    aty_st_le32(SRC_Y_X, (srcy << 16) | srcx);
+    aty_st_le32(DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT);
+    aty_st_le32(DP_CNTL, direction);
+    aty_st_le32(DP_DATATYPE, aty_ld_le32(DP_DATATYPE) | SRC_DSTCOLOR);
+    aty128_rectdraw(dstx, dsty, width, height, info);
+}
+
+static void
+fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy, int dx,
+                       int height, int width)
+{
+    sx *= fontwidth(p);
+    sy *= fontheight(p);
+    dx *= fontwidth(p);
+    dy *= fontheight(p);
+    width *= fontwidth(p);
+    height *= fontheight(p);
+
+    aty128_rectcopy(sx, sy, dx, dy, width, height,
+                       (struct fb_info_aty128 *)p->fb_info);
+}
+
+#ifdef FBCON_HAS_CFB8
+static struct display_switch fbcon_aty128_8 = {
+    fbcon_cfb8_setup, fbcon_aty128_bmove, fbcon_cfb8_clear, fbcon_cfb8_putc,
+    fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_cfb8_clear_margins,
+    FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
+
+#if defined(MODULE) && defined(DEBUG)
+int
+init_module(void)
+{
+    aty128pci_probe();
+    return 0;
+}
+
+void
+cleanup_module(void)
+{
+/* XXX unregister! */
+}
+#endif /* MODULE */
index edba704a3f7b1f33cc33624b9d5274afc674b0f5..db21bfc6b674e00a7417edc16400736144ac5d02 100644 (file)
@@ -2192,7 +2192,7 @@ static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp,
     }
     dsp_precision -= 5;
     /* fifo_off<<6 */
-    fifo_off = ((xclks_per_row*(fifo_size-1))>>5)+(1<<6);
+    fifo_off = ((xclks_per_row*(fifo_size-1))>>5)+(3<<6);
 
     if (info->total_vram > 1*1024*1024) {
        if (info->ram_type >= SDRAM) {
@@ -2219,7 +2219,7 @@ static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp,
     if (xclks_per_row >= (page_size<<11))
        fifo_on = ((2*page_size+1)<<6)+(xclks_per_row>>5);
     else
-       fifo_on = (3*page_size)<<6;
+       fifo_on = (3*page_size+2)<<6;
 
     dsp_xclks_per_row = xclks_per_row>>dsp_precision;
     dsp_on = fifo_on>>dsp_precision;
index dd20b767e203478b8ccbab404e9d63028801d08b..8078a667688e425f587cdc3a2526f2b633c263f3 100644 (file)
@@ -282,6 +282,14 @@ static void chipsfb_blank(int blank, struct fb_info *info)
        // useful at blank = 1 too (saves battery, extends backlight life)
        if (blank) {
                pmu_enable_backlight(0);
+               /* get the palette from the chip */
+               for (i = 0; i < 256; ++i) {
+                       out_8(p->io_base + 0x3c7, i);
+                       udelay(1);
+                       p->palette[i].red = in_8(p->io_base + 0x3c9);
+                       p->palette[i].green = in_8(p->io_base + 0x3c9);
+                       p->palette[i].blue = in_8(p->io_base + 0x3c9);
+               }
                for (i = 0; i < 256; ++i) {
                        out_8(p->io_base + 0x3c8, i);
                        udelay(1);
@@ -291,7 +299,13 @@ static void chipsfb_blank(int blank, struct fb_info *info)
                }
        } else {
                pmu_enable_backlight(1);
-               do_install_cmap(currcon, info);
+               for (i = 0; i < 256; ++i) {
+                       out_8(p->io_base + 0x3c8, i);
+                       udelay(1);
+                       out_8(p->io_base + 0x3c9, p->palette[i].red);
+                       out_8(p->io_base + 0x3c9, p->palette[i].green);
+                       out_8(p->io_base + 0x3c9, p->palette[i].blue);
+               }
        }
 }
 
@@ -711,20 +725,10 @@ chips_sleep_notify(struct pmu_sleep_notifier *self, int when)
 
        for (p = all_chips; p != NULL; p = p->next) {
                int nb = p->var.yres * p->fix.line_length;
-               int i;
 
                switch (when) {
                case PBOOK_SLEEP_NOW:
                        chipsfb_blank(1, (struct fb_info *)p);
-                       /* get the palette from the chip, Xpmac seems
-                          to set it directly in the chip */
-                       for (i = 0; i < 256; ++i) {
-                               out_8(p->io_base + 0x3c8, i);
-                               udelay(1);
-                               p->palette[i].red = in_8(p->io_base + 0x3c9);
-                               p->palette[i].green = in_8(p->io_base + 0x3c9);
-                               p->palette[i].blue = in_8(p->io_base + 0x3c9);
-                       }
                        p->save_framebuffer = vmalloc(nb);
                        if (p->save_framebuffer)
                                memcpy(p->save_framebuffer,
index 068282244ef6d201861de39802ba5f5b483aa414..d5e0c2b0455d641a1cb7d0036be0bb92ce3f6001 100644 (file)
@@ -293,6 +293,9 @@ static int offb_ioctl(struct inode *inode, struct file *file, u_int cmd,
 #ifdef CONFIG_FB_ATY
 extern void atyfb_of_init(struct device_node *dp);
 #endif /* CONFIG_FB_ATY */
+#ifdef CONFIG_FB_ATY128
+extern void aty128fb_of_init(struct device_node *dp);
+#endif /* CONFIG_FB_ATY */
 #ifdef CONFIG_FB_S3TRIO
 extern void s3triofb_init_of(struct device_node *dp);
 #endif /* CONFIG_FB_S3TRIO */
@@ -349,6 +352,21 @@ int __init offb_init(void)
                    dp->addrs[0].size = 0x01000000;
                }
            }
+
+           /*
+            * The LTPro on the Lombard powerbook has no addresses
+            * on the display nodes, they are on their parent.
+            */
+           if (dp->n_addrs == 0 && device_is_compatible(dp, "ATY,264LTPro")) {
+               int na;
+               unsigned int *ap = (unsigned int *)
+                   get_property(dp, "AAPL,address", &na);
+               if (ap != 0)
+                   for (na /= sizeof(unsigned int); na > 0; --na, ++ap)
+                       if (*ap <= addr && addr < *ap + 0x1000000)
+                           goto foundit;
+           }
+
            /*
             * See if the display address is in one of the address
             * ranges for this display.
@@ -359,6 +377,7 @@ int __init offb_init(void)
                    break;
            }
            if (i < dp->n_addrs) {
+           foundit:
                printk(KERN_INFO "MacOS display is %s\n", dp->full_name);
                macos_display = dp;
                break;
@@ -397,6 +416,12 @@ int __init offb_init(void)
 
 static int __init offb_init_driver(struct device_node *dp)
 {
+#ifdef CONFIG_FB_ATY128
+    if (!strncmp(dp->name, "ATY,Rage128", 11)) {
+       aty128fb_of_init(dp);
+       return 1;
+    }
+#endif
 #ifdef CONFIG_FB_ATY
     if (!strncmp(dp->name, "ATY", 3)) {
        atyfb_of_init(dp);
index ef45eba7d159c5057bad57e415ab01d86e85a297..5f9c066a45e00b5e98f1816346b737109cfb71f4 100644 (file)
@@ -168,6 +168,11 @@ out:
  */
 int d_invalidate(struct dentry * dentry)
 {
+       /*
+        * If it's already been dropped, return OK.
+        */
+       if (list_empty(&dentry->d_hash))
+               return 0;
        /*
         * Check whether to do a partial shrink_dcache
         * to get rid of unused child entries.
index b3f31fd0ae85acdf27ea0f5003c1251959c5fccd..f56d8b3523e97cc75b87dc592c150c0ae007527a 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -276,7 +276,9 @@ int setup_arg_pages(struct linux_binprm *bprm)
                mpnt->vm_offset = 0;
                mpnt->vm_file = NULL;
                mpnt->vm_private_data = (void *) 0;
+               vmlist_modify_lock(current->mm);
                insert_vm_struct(current->mm, mpnt);
+               vmlist_modify_unlock(current->mm);
                current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
        } 
 
@@ -467,6 +469,11 @@ int flush_old_exec(struct linux_binprm * bprm)
            permission(bprm->dentry->d_inode,MAY_READ))
                current->dumpable = 0;
 
+       /* An exec changes our domain. We are no longer part of the thread
+          group */
+          
+       current->self_exec_id++;
+                       
        flush_signal_handlers(current);
        flush_old_files(current->files);
 
index 55eddfde8765c752ef346a69c055ad9a620971a4..337770ed04f633f22f394f52d25bb18559a5b562 100644 (file)
@@ -429,7 +429,7 @@ static inline void __iget(struct inode * inode)
  * by hand after calling find_inode now! This simplify iunique and won't
  * add any additional branch in the common code.
  */
-static struct inode * find_inode(struct super_block * sb, unsigned long ino, struct list_head *head)
+static struct inode * find_inode(struct super_block * sb, unsigned long ino, struct list_head *head, find_inode_t find_actor, void *opaque)
 {
        struct list_head *tmp;
        struct inode * inode;
@@ -445,6 +445,8 @@ static struct inode * find_inode(struct super_block * sb, unsigned long ino, str
                        continue;
                if (inode->i_ino != ino)
                        continue;
+               if (find_actor && !find_actor(inode, ino, opaque))
+                       continue;
                break;
        }
        return inode;
@@ -504,7 +506,7 @@ struct inode * get_empty_inode(void)
  * We no longer cache the sb_flags in i_flags - see fs.h
  *     -- rmk@arm.uk.linux.org
  */
-static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, struct list_head *head)
+static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, struct list_head *head, find_inode_t find_actor, void *opaque)
 {
        struct inode * inode;
 
@@ -514,7 +516,7 @@ static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, s
 
                spin_lock(&inode_lock);
                /* We released the lock, so.. */
-               old = find_inode(sb, ino, head);
+               old = find_inode(sb, ino, head, find_actor, opaque);
                if (!old)
                {
                        list_add(&inode->i_list, &inode_in_use);
@@ -570,7 +572,7 @@ ino_t iunique(struct super_block *sb, ino_t max_reserved)
 retry:
        if (counter > max_reserved) {
                head = inode_hashtable + hash(sb,counter);
-               inode = find_inode(sb, res = counter++, head);
+               inode = find_inode(sb, res = counter++, head, NULL, NULL);
                if (!inode) {
                        spin_unlock(&inode_lock);
                        return res;
@@ -595,13 +597,13 @@ struct inode *igrab(struct inode *inode)
        return inode;
 }
 
-struct inode *iget(struct super_block *sb, unsigned long ino)
+struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque)
 {
        struct list_head * head = inode_hashtable + hash(sb,ino);
        struct inode * inode;
 
        spin_lock(&inode_lock);
-       inode = find_inode(sb, ino, head);
+       inode = find_inode(sb, ino, head, find_actor, opaque);
        if (inode) {
                __iget(inode);
                spin_unlock(&inode_lock);
@@ -614,7 +616,7 @@ struct inode *iget(struct super_block *sb, unsigned long ino)
         * get_new_inode() will do the right thing, re-trying the search
         * in case it had to block at any point.
         */
-       return get_new_inode(sb, ino, head);
+       return get_new_inode(sb, ino, head, find_actor, opaque);
 }
 
 void insert_inode_hash(struct inode *inode)
index f26aa086cba2dca10ffa8a89501de8056566ea9d..70b01dc207f1acc266394ae4dd128924f683ac67 100644 (file)
@@ -33,7 +33,7 @@
  */
 
 #define DATA_BUFFER_USED(bh) \
-       (atomic_read(&bh->b_count) || buffer_locked(bh))
+       (atomic_read(&bh->b_count) > 1 || buffer_locked(bh))
 
 /*
  * The functions for minix V1 fs truncation.
index 6b52b2d544c65fb73a66cd866e70fe9e08e22252..6515e0d523c95ee660c97acca0c23e0a209d487f 100644 (file)
@@ -533,13 +533,15 @@ static inline int nfs_dentry_force_reval(struct dentry *dentry, int flags)
  * If mtime is close to present time, we revalidate
  * more often.
  */
+#define NFS_REVALIDATE_NEGATIVE (1 * HZ)
 static inline int nfs_neg_need_reval(struct dentry *dentry)
 {
-       unsigned long timeout = 30 * HZ;
-       long diff = CURRENT_TIME - dentry->d_parent->d_inode->i_mtime;
+       struct inode *dir = dentry->d_parent->d_inode;
+       unsigned long timeout = NFS_ATTRTIMEO(dir);
+       long diff = CURRENT_TIME - dir->i_mtime;
 
-       if (diff < 5*60)
-               timeout = 1 * HZ;
+       if (diff < 5*60 && timeout > NFS_REVALIDATE_NEGATIVE)
+               timeout = NFS_REVALIDATE_NEGATIVE;
 
        return time_after(jiffies, dentry->d_time + timeout);
 }
@@ -581,12 +583,14 @@ static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
                goto out_bad;
        }
 
-       if (IS_ROOT(dentry))
-               goto out_valid;
-
        if (!nfs_dentry_force_reval(dentry, flags))
                goto out_valid;
 
+       if (IS_ROOT(dentry)) {
+               __nfs_revalidate_inode(NFS_DSERVER(dentry), dentry);
+               goto out_valid_renew;
+       }
+
        /*
         * Do a new lookup and check the dentry attributes.
         */
@@ -596,32 +600,29 @@ static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
                goto out_bad;
 
        /* Inode number matches? */
-       if (fattr.fileid != inode->i_ino)
+       if (NFS_FSID(inode) != fattr.fsid ||
+           NFS_FILEID(inode) != fattr.fileid)
                goto out_bad;
 
        /* Filehandle matches? */
-       if (memcmp(dentry->d_fsdata, &fhandle, sizeof(struct nfs_fh))) {
-               if (!list_empty(&dentry->d_subdirs))
-                       shrink_dcache_parent(dentry);
-               if (dentry->d_count < 2)
-                       goto out_bad;
-       }
+       if (memcmp(dentry->d_fsdata, &fhandle, sizeof(struct nfs_fh)))
+               goto out_bad;
 
        /* Ok, remeber that we successfully checked it.. */
-       nfs_renew_times(dentry);
        nfs_refresh_inode(inode, &fattr);
 
+ out_valid_renew:
+       nfs_renew_times(dentry);
 out_valid:
        return 1;
 out_bad:
+       d_drop(dentry);
+       if (!list_empty(&dentry->d_subdirs))
+               shrink_dcache_parent(dentry);
        /* Purge readdir caches. */
        if (dentry->d_parent->d_inode) {
-               invalidate_inode_pages(dentry->d_parent->d_inode);
-               nfs_flush_dircache(dentry->d_parent->d_inode);
-       }
-       if (inode && S_ISDIR(inode->i_mode)) {
-               invalidate_inode_pages(inode);
-               nfs_flush_dircache(inode);
+               nfs_zap_caches(dentry->d_parent->d_inode);
+               NFS_CACHEINV(dentry->d_parent->d_inode);
        }
        return 0;
 }
@@ -649,21 +650,6 @@ static void nfs_dentry_delete(struct dentry *dentry)
                                dentry->d_name.name, error);
        }
 
-#ifdef NFS_PARANOIA
-       /*
-        * Sanity check: if the dentry has been unhashed and the
-        * inode still has users, we could have problems ...
-        */
-       if (list_empty(&dentry->d_hash) && dentry->d_inode) {
-               struct inode *inode = dentry->d_inode;
-               int max_count = (S_ISDIR(inode->i_mode) ? 1 : inode->i_nlink);
-               if (inode->i_count > max_count) {
-printk("nfs_dentry_delete: %s/%s: ino=%ld, count=%d, nlink=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name,
-inode->i_ino, inode->i_count, inode->i_nlink);
-               }
-       }
-#endif
 }
 
 static kmem_cache_t *nfs_fh_cachep;
@@ -750,14 +736,6 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry)
                error = -EACCES;
                inode = nfs_fhget(dentry, &fhandle, &fattr);
                if (inode) {
-#ifdef NFS_PARANOIA
-if (inode->i_count > (S_ISDIR(inode->i_mode) ? 1 : inode->i_nlink)) {
-printk("nfs_lookup: %s/%s ino=%ld in use, count=%d, nlink=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name,
-inode->i_ino, inode->i_count, inode->i_nlink);
-show_dentry(&inode->i_dentry);
-}
-#endif
            no_entry:
                        d_add(dentry, inode);
                        nfs_renew_times(dentry);
@@ -779,14 +757,6 @@ static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
 
        inode = nfs_fhget(dentry, fhandle, fattr);
        if (inode) {
-#ifdef NFS_PARANOIA
-if (inode->i_count > (S_ISDIR(inode->i_mode) ? 1 : inode->i_nlink)) {
-printk("nfs_instantiate: %s/%s ino=%ld in use, count=%d, nlink=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name,
-inode->i_ino, inode->i_count, inode->i_nlink);
-show_dentry(&inode->i_dentry);
-}
-#endif
                d_instantiate(dentry, inode);
                nfs_renew_times(dentry);
                error = 0;
@@ -803,16 +773,15 @@ show_dentry(&inode->i_dentry);
 static int nfs_create(struct inode *dir, struct dentry *dentry, int mode)
 {
        int error;
-       struct nfs_sattr sattr;
+       struct iattr attr;
        struct nfs_fattr fattr;
        struct nfs_fh fhandle;
 
        dfprintk(VFS, "NFS: create(%x/%ld, %s\n",
                dir->i_dev, dir->i_ino, dentry->d_name.name);
 
-       sattr.mode = mode;
-       sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
-       sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
+       attr.ia_mode = mode;
+       attr.ia_valid = ATTR_MODE;
 
        /*
         * Invalidate the dir cache before the operation to avoid a race.
@@ -820,7 +789,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode)
        invalidate_inode_pages(dir);
        nfs_flush_dircache(dir);
        error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
-                       dentry->d_name.name, &sattr, &fhandle, &fattr);
+                       dentry->d_name.name, &attr, &fhandle, &fattr);
        if (!error)
                error = nfs_instantiate(dentry, &fhandle, &fattr);
        if (error)
@@ -834,23 +803,25 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode)
 static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
 {
        int error;
-       struct nfs_sattr sattr;
+       struct iattr attr;
        struct nfs_fattr fattr;
        struct nfs_fh fhandle;
 
        dfprintk(VFS, "NFS: mknod(%x/%ld, %s\n",
                dir->i_dev, dir->i_ino, dentry->d_name.name);
 
-       sattr.mode = mode;
-       sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
-       if (S_ISCHR(mode) || S_ISBLK(mode))
-               sattr.size = rdev; /* get out your barf bag */
-       sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
+       attr.ia_mode = mode;
+       attr.ia_valid = ATTR_MODE;
+       /* FIXME: move this to a special nfs_proc_mknod() */
+       if (S_ISCHR(mode) || S_ISBLK(mode)) {
+               attr.ia_size = rdev; /* get out your barf bag */
+               attr.ia_valid |= ATTR_SIZE;
+       }
 
        invalidate_inode_pages(dir);
        nfs_flush_dircache(dir);
        error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
-                               dentry->d_name.name, &sattr, &fhandle, &fattr);
+                               dentry->d_name.name, &attr, &fhandle, &fattr);
        if (!error)
                error = nfs_instantiate(dentry, &fhandle, &fattr);
        if (error)
@@ -864,16 +835,15 @@ static int nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rde
 static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
        int error;
-       struct nfs_sattr sattr;
+       struct iattr attr;
        struct nfs_fattr fattr;
        struct nfs_fh fhandle;
 
        dfprintk(VFS, "NFS: mkdir(%x/%ld, %s\n",
                dir->i_dev, dir->i_ino, dentry->d_name.name);
 
-       sattr.mode = mode | S_IFDIR;
-       sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
-       sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
+       attr.ia_valid = ATTR_MODE;
+       attr.ia_mode = mode | S_IFDIR;
 
        /*
         * Always drop the dentry, we can't always depend on
@@ -885,7 +855,7 @@ static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        invalidate_inode_pages(dir);
        nfs_flush_dircache(dir);
        error = nfs_proc_mkdir(NFS_DSERVER(dentry), NFS_FH(dentry->d_parent),
-                               dentry->d_name.name, &sattr, &fhandle, &fattr);
+                               dentry->d_name.name, &attr, &fhandle, &fattr);
        if (!error)
                dir->i_nlink++;
        return error;
@@ -898,13 +868,6 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
        dfprintk(VFS, "NFS: rmdir(%x/%ld, %s\n",
                dir->i_dev, dir->i_ino, dentry->d_name.name);
 
-#ifdef NFS_PARANOIA
-if (dentry->d_inode->i_count > 1)
-printk("nfs_rmdir: %s/%s inode busy?? i_count=%d, i_nlink=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name,
-dentry->d_inode->i_count, dentry->d_inode->i_nlink);
-#endif
-
        invalidate_inode_pages(dir);
        nfs_flush_dircache(dir);
        error = nfs_proc_rmdir(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
@@ -1082,12 +1045,6 @@ dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count);
 #endif
                goto out;
        }
-#ifdef NFS_PARANOIA
-if (inode && inode->i_count > inode->i_nlink)
-printk("nfs_safe_remove: %s/%s inode busy?? i_count=%d, i_nlink=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name,
-inode->i_count, inode->i_nlink);
-#endif
        /*
         * Unhash the dentry while we remove the file ...
         */
@@ -1141,7 +1098,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry)
 static int
 nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 {
-       struct nfs_sattr sattr;
+       struct iattr attr;
        int error;
 
        dfprintk(VFS, "NFS: symlink(%x/%ld, %s, %s)\n",
@@ -1160,9 +1117,8 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
         * Fill in the sattr for the call.
         * Note: SunOS 4.1.2 crashes if the mode isn't initialized!
         */
-       sattr.mode = S_IFLNK | S_IRWXUGO;
-       sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
-       sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
+       attr.ia_valid = ATTR_MODE;
+       attr.ia_mode = S_IFLNK | S_IRWXUGO;
 
        /*
         * Drop the dentry in advance to force a new lookup.
@@ -1173,7 +1129,7 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
        invalidate_inode_pages(dir);
        nfs_flush_dircache(dir);
        error = nfs_proc_symlink(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
-                               dentry->d_name.name, symname, &sattr);
+                               dentry->d_name.name, symname, &attr);
        if (!error) {
                nfs_renew_times(dentry->d_parent);
        } else if (error == -EEXIST) {
@@ -1332,13 +1288,6 @@ do_rename:
         * To prevent any new references to the target during the rename,
         * we unhash the dentry and free the inode in advance.
         */
-#ifdef NFS_PARANOIA
-if (new_inode && 
-    new_inode->i_count > (S_ISDIR(new_inode->i_mode) ? 1 : new_inode->i_nlink))
-printk("nfs_rename: %s/%s inode busy?? i_count=%d, i_nlink=%d\n",
-new_dentry->d_parent->d_name.name, new_dentry->d_name.name,
-new_inode->i_count, new_inode->i_nlink);
-#endif
        if (!list_empty(&new_dentry->d_hash)) {
                d_drop(new_dentry);
                rehash = update;
index 5421cebf99a8079cf0bceda607c9f615b41e61f4..ab1e514857e27d93d451ad795212251459cc7ea3 100644 (file)
@@ -37,7 +37,7 @@
 #define NFS_PARANOIA 1
 
 static struct inode * __nfs_fhget(struct super_block *, struct nfs_fattr *);
-static void nfs_zap_caches(struct inode *);
+void nfs_zap_caches(struct inode *);
 static void nfs_invalidate_inode(struct inode *);
 
 static void nfs_read_inode(struct inode *);
@@ -78,6 +78,8 @@ nfs_read_inode(struct inode * inode)
        inode->i_mode = 0;
        inode->i_rdev = 0;
        inode->i_op = NULL;
+       NFS_FILEID(inode) = 0;
+       NFS_FSID(inode) = 0;
        NFS_CACHEINV(inode);
        NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
 }
@@ -415,13 +417,15 @@ restart:
                dprintk("nfs_free_dentries: found %s/%s, d_count=%d, hashed=%d\n",
                        dentry->d_parent->d_name.name, dentry->d_name.name,
                        dentry->d_count, !list_empty(&dentry->d_hash));
+               if (!list_empty(&dentry->d_subdirs))
+                       shrink_dcache_parent(dentry);
                if (!dentry->d_count) {
                        dget(dentry);
                        d_drop(dentry);
                        dput(dentry);
                        goto restart;
                }
-               if (!list_empty(&dentry->d_hash))
+               if (list_empty(&dentry->d_hash))
                        unhashed++;
        }
        return unhashed;
@@ -430,7 +434,7 @@ restart:
 /*
  * Invalidate the local caches
  */
-static void
+void
 nfs_zap_caches(struct inode *inode)
 {
        NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
@@ -466,6 +470,8 @@ nfs_fill_inode(struct inode *inode, struct nfs_fattr *fattr)
         * do this once. (We don't allow inodes to change types.)
         */
        if (inode->i_mode == 0) {
+               NFS_FILEID(inode) = fattr->fileid;
+               NFS_FSID(inode) = fattr->fsid;
                inode->i_mode = fattr->mode;
                if (S_ISREG(inode->i_mode))
                        inode->i_op = &nfs_file_inode_operations;
@@ -486,6 +492,54 @@ nfs_fill_inode(struct inode *inode, struct nfs_fattr *fattr)
        nfs_refresh_inode(inode, fattr);
 }
 
+/*
+ * In NFSv3 we can have 64bit inode numbers. In order to support
+ * this, and re-exported directories (also seen in NFSv2)
+ * we are forced to allow 2 different inodes to have the same
+ * i_ino.
+ */
+static int
+nfs_find_actor(struct inode *inode, unsigned long ino, void *opaque)
+{
+       struct nfs_fattr *fattr = (struct nfs_fattr *)opaque;
+       if (NFS_FSID(inode) != fattr->fsid)
+               return 0;
+       if (NFS_FILEID(inode) != fattr->fileid)
+               return 0;
+       return 1;
+}
+
+static int
+nfs_inode_is_stale(struct inode *inode, struct nfs_fattr *fattr)
+{
+       int unhashed;
+       int is_stale = 0;
+
+       if (inode->i_mode &&
+           (fattr->mode & S_IFMT) != (inode->i_mode & S_IFMT))
+               is_stale = 1;
+
+       if (is_bad_inode(inode))
+               is_stale = 1;
+
+       /*
+        * If the inode seems stale, free up cached dentries.
+        */
+       unhashed = nfs_free_dentries(inode);
+
+       /* Assume we're holding an i_count
+        *
+        * NB: sockets sometimes have volatile file handles
+        *     don't invalidate their inodes even if all dentries are
+        *     unhashed.
+        */
+       if (unhashed && inode->i_count == unhashed + 1
+           && !S_ISSOCK(inode->i_mode) && !S_ISFIFO(inode->i_mode))
+               is_stale = 1;
+
+       return is_stale;
+}
+
 /*
  * This is our own version of iget that looks up inodes by file handle
  * instead of inode number.  We use this technique instead of using
@@ -545,54 +599,40 @@ nfs_fhget(struct dentry *dentry, struct nfs_fh *fhandle,
 static struct inode *
 __nfs_fhget(struct super_block *sb, struct nfs_fattr *fattr)
 {
-       struct inode *inode;
-       int max_count, stale_inode, unhashed = 0;
+       struct inode *inode = NULL;
+       unsigned long ino;
 
-retry:
-       inode = iget(sb, fattr->fileid);
-       if (!inode)
+       if (!fattr->nlink) {
+               printk("NFS: Buggy server - nlink == 0!\n");
                goto out_no_inode;
-       /* N.B. This should be impossible ... */
-       if (inode->i_ino != fattr->fileid)
-               goto out_bad_id;
+       }
 
-       /*
-        * Check for busy inodes, and attempt to get rid of any
-        * unused local references. If successful, we release the
-        * inode and try again.
-        *
-        * Note that the busy test uses the values in the fattr,
-        * as the inode may have become a different object.
-        * (We can probably handle modes changes here, too.)
-        */
-       stale_inode = inode->i_mode &&
-                     ((fattr->mode ^ inode->i_mode) & S_IFMT);
-       stale_inode |= inode->i_count && inode->i_count == unhashed;
-       max_count = S_ISDIR(fattr->mode) ? 1 : fattr->nlink;
-       if (stale_inode || inode->i_count > max_count + unhashed) {
-               dprintk("__nfs_fhget: inode %ld busy, i_count=%d, i_nlink=%d\n",
-                       inode->i_ino, inode->i_count, inode->i_nlink);
-               unhashed = nfs_free_dentries(inode);
-               if (stale_inode || inode->i_count > max_count + unhashed) {
-                       printk("__nfs_fhget: inode %ld still busy, i_count=%d\n",
-                               inode->i_ino, inode->i_count);
-                       if (!list_empty(&inode->i_dentry)) {
-                               struct dentry *dentry;
-                               dentry = list_entry(inode->i_dentry.next,
-                                                struct dentry, d_alias);
-                               printk("__nfs_fhget: killing %s/%s filehandle\n",
-                                       dentry->d_parent->d_name.name,
-                                       dentry->d_name.name);
-                               memset(dentry->d_fsdata, 0,
-                                       sizeof(struct nfs_fh));
-                       }
-                       remove_inode_hash(inode);
-                       nfs_invalidate_inode(inode);
-                       unhashed = 0;
-               }
+       ino = fattr->fileid;
+
+       while((inode = iget4(sb, ino, nfs_find_actor, fattr)) != NULL) {
+
+               /*
+                * Check for busy inodes, and attempt to get rid of any
+                * unused local references. If successful, we release the
+                * inode and try again.
+                *
+                * Note that the busy test uses the values in the fattr,
+                * as the inode may have become a different object.
+                * (We can probably handle modes changes here, too.)
+                */
+               if (!nfs_inode_is_stale(inode,fattr))
+                       break;
+
+               dprintk("__nfs_fhget: inode %ld still busy, i_count=%d\n",
+                      inode->i_ino, inode->i_count);
+               nfs_zap_caches(inode);
+               remove_inode_hash(inode);
                iput(inode);
-               goto retry;
        }
+
+       if (!inode)
+               goto out_no_inode;
+
        nfs_fill_inode(inode, fattr);
        dprintk("NFS: __nfs_fhget(%x/%ld ct=%d)\n",
                inode->i_dev, inode->i_ino, inode->i_count);
@@ -603,18 +643,14 @@ out:
 out_no_inode:
        printk("__nfs_fhget: iget failed\n");
        goto out;
-out_bad_id:
-       printk("__nfs_fhget: unexpected inode from iget\n");
-       goto out;
 }
 
 int
 nfs_notify_change(struct dentry *dentry, struct iattr *attr)
 {
        struct inode *inode = dentry->d_inode;
-       int error;
-       struct nfs_sattr sattr;
        struct nfs_fattr fattr;
+       int error;
 
        /*
         * Make sure the inode is up-to-date.
@@ -627,60 +663,63 @@ printk("nfs_notify_change: revalidate failed, error=%d\n", error);
                goto out;
        }
 
-       sattr.mode = (u32) -1;
-       if (attr->ia_valid & ATTR_MODE) 
-               sattr.mode = attr->ia_mode;
-
-       sattr.uid = (u32) -1;
-       if (attr->ia_valid & ATTR_UID)
-               sattr.uid = attr->ia_uid;
-
-       sattr.gid = (u32) -1;
-       if (attr->ia_valid & ATTR_GID)
-               sattr.gid = attr->ia_gid;
-
-       sattr.size = (u32) -1;
-       if ((attr->ia_valid & ATTR_SIZE) && S_ISREG(inode->i_mode))
-               sattr.size = attr->ia_size;
-
-       sattr.mtime.seconds = sattr.mtime.useconds = (u32) -1;
-       if (attr->ia_valid & ATTR_MTIME) {
-               sattr.mtime.seconds = attr->ia_mtime;
-               sattr.mtime.useconds = 0;
-       }
-
-       sattr.atime.seconds = sattr.atime.useconds = (u32) -1;
-       if (attr->ia_valid & ATTR_ATIME) {
-               sattr.atime.seconds = attr->ia_atime;
-               sattr.atime.useconds = 0;
-       }
+       if (!S_ISREG(inode->i_mode))
+               attr->ia_valid &= ~ATTR_SIZE;
 
        error = nfs_wb_all(inode);
        if (error)
                goto out;
 
        error = nfs_proc_setattr(NFS_DSERVER(dentry), NFS_FH(dentry),
-                               &sattr, &fattr);
+                               &fattr, attr);
        if (error)
                goto out;
        /*
         * If we changed the size or mtime, update the inode
         * now to avoid invalidating the page cache.
         */
-       if (sattr.size != (u32) -1) {
-               if (sattr.size != fattr.size)
-                       printk("nfs_notify_change: sattr=%d, fattr=%d??\n",
-                               sattr.size, fattr.size);
-               inode->i_size  = sattr.size;
+       if (attr->ia_valid & ATTR_SIZE) {
+               if (attr->ia_size != fattr.size)
+                       printk("nfs_notify_change: attr=%ld, fattr=%d??\n",
+                               attr->ia_size, fattr.size);
+               inode->i_size  = attr->ia_size;
                inode->i_mtime = fattr.mtime.seconds;
        }
-       if (sattr.mtime.seconds != (u32) -1)
+       if (attr->ia_valid & ATTR_MTIME)
                inode->i_mtime = fattr.mtime.seconds;
        error = nfs_refresh_inode(inode, &fattr);
 out:
        return error;
 }
 
+/*
+ * Wait for the inode to get unlocked.
+ * (Used for NFS_INO_LOCKED and NFS_INO_REVALIDATING).
+ */
+int
+nfs_wait_on_inode(struct inode *inode, int flag)
+{
+       struct task_struct      *tsk = current;
+       DECLARE_WAITQUEUE(wait, tsk);
+       int                     intr, error = 0;
+
+       intr = NFS_SERVER(inode)->flags & NFS_MOUNT_INTR;
+       add_wait_queue(&inode->i_wait, &wait);
+       for (;;) {
+               set_task_state(tsk, (intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE));
+               error = 0;
+               if (!(NFS_FLAGS(inode) & flag))
+                       break;
+               error = -ERESTARTSYS;
+               if (intr && signalled())
+                       break;
+               schedule();
+       }
+       set_task_state(tsk, TASK_RUNNING);
+       remove_wait_queue(&inode->i_wait, &wait);
+       return error;
+}
+
 /*
  * Externally visible revalidation function
  */
@@ -711,7 +750,7 @@ int nfs_release(struct inode *inode, struct file *filp)
  * the cached attributes have to be refreshed.
  */
 int
-_nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
+__nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
 {
        struct inode    *inode = dentry->d_inode;
        int              status = 0;
@@ -720,6 +759,19 @@ _nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
        dfprintk(PAGECACHE, "NFS: revalidating %s/%s, ino=%ld\n",
                dentry->d_parent->d_name.name, dentry->d_name.name,
                inode->i_ino);
+
+       if (!inode || is_bad_inode(inode))
+               return -ESTALE;
+
+       while (NFS_REVALIDATING(inode)) {
+               status = nfs_wait_on_inode(inode, NFS_INO_REVALIDATING);
+               if (status < 0)
+                       return status;
+               if (time_before(jiffies,NFS_READTIME(inode)+NFS_ATTRTIMEO(inode)))
+                       return 0;
+       }
+       NFS_FLAGS(inode) |= NFS_INO_REVALIDATING;
+
        status = nfs_proc_getattr(server, NFS_FH(dentry), &fattr);
        if (status) {
                int error;
@@ -759,6 +811,8 @@ _nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
        dfprintk(PAGECACHE, "NFS: %s/%s revalidation complete\n",
                dentry->d_parent->d_name.name, dentry->d_name.name);
 out:
+       NFS_FLAGS(inode) &= ~NFS_INO_REVALIDATING;
+       wake_up(&inode->i_wait);
        return status;
 }
 
index 1bc7d3d37c8a17ec86f67c6d28aa5777f987cc71..a7e53e6db8706a4e26dbfd2bdaa922c0b9e41ca5 100644 (file)
@@ -118,19 +118,35 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
        return p;
 }
 
+
+#define SATTR(p, attr, flag, field) \
+        *p++ = (attr->ia_valid & flag) ? htonl(attr->field) : ~(u32) 0
 static inline u32 *
-xdr_encode_sattr(u32 *p, struct nfs_sattr *sattr)
+xdr_encode_sattr(u32 *p, struct iattr *attr)
 {
-       *p++ = htonl(sattr->mode);
-       *p++ = htonl(sattr->uid);
-       *p++ = htonl(sattr->gid);
-       *p++ = htonl(sattr->size);
-       *p++ = htonl(sattr->atime.seconds);
-       *p++ = htonl(sattr->atime.useconds);
-       *p++ = htonl(sattr->mtime.seconds);
-       *p++ = htonl(sattr->mtime.useconds);
-       return p;
+       SATTR(p, attr, ATTR_MODE, ia_mode);
+       SATTR(p, attr, ATTR_UID, ia_uid);
+       SATTR(p, attr, ATTR_GID, ia_gid);
+       SATTR(p, attr, ATTR_SIZE, ia_size);
+
+       if (attr->ia_valid & (ATTR_ATIME|ATTR_ATIME_SET)) {
+               *p++ = htonl(attr->ia_atime);
+               *p++ = 0;
+       } else {
+               *p++ = ~(u32) 0;
+               *p++ = ~(u32) 0;
+       }
+
+       if (attr->ia_valid & (ATTR_MTIME|ATTR_MTIME_SET)) {
+               *p++ = htonl(attr->ia_mtime);
+               *p++ = 0;
+       } else {
+               *p++ = ~(u32) 0;        
+               *p++ = ~(u32) 0;
+       }
+       return p;
 }
+#undef SATTR
 
 /*
  * NFS encode functions
index 3b48b326ae0b17b8ead32593e213fe318b83810f..bb55ce6d691753f944995def95746136e5a57876 100644 (file)
@@ -65,7 +65,7 @@ nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 
 int
 nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle,
-                       struct nfs_sattr *sattr, struct nfs_fattr *fattr)
+                       struct nfs_fattr *fattr, struct iattr *sattr)
 {
        struct nfs_sattrargs    arg = { fhandle, sattr };
        int     status;
@@ -123,7 +123,7 @@ nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle, int swap,
 
 int
 nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir,
-                       const char *name, struct nfs_sattr *sattr,
+                       const char *name, struct iattr *sattr,
                        struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
        struct nfs_createargs   arg = { dir, name, sattr };
@@ -178,7 +178,7 @@ nfs_proc_link(struct nfs_server *server, struct nfs_fh *fhandle,
 int
 nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir,
                        const char *name, const char *path,
-                       struct nfs_sattr *sattr)
+                       struct iattr *sattr)
 {
        struct nfs_symlinkargs  arg = { dir, name, path, sattr };
        int                     status;
@@ -191,7 +191,7 @@ nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir,
 
 int
 nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir,
-                       const char *name, struct nfs_sattr *sattr,
+                       const char *name, struct iattr *sattr,
                        struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
        struct nfs_createargs   arg = { dir, name, sattr };
index 6a7b61b860589b303da59ea320f62d0b908bc240..f4cd01a7c4e92e5f488097df12e7ddd5f445f154 100644 (file)
@@ -38,6 +38,7 @@
  *
  * aeb@cwi.nl        :  /proc/partitions
  *
+ *
  * Alan Cox         :  security fixes.
  *                     <Alan.Cox@linux.org>
  *
  *
  * Gerhard Wichert   :  added BIGMEM support
  * Siemens AG           <Gerhard.Wichert@pdb.siemens.de>
- *
- * Chuck Lever       :  safe handling of task_struct
- *                      <cel@monkey.org>
- *
- * Andrea Arcangeli  : SMP race/security fixes.
  */
 
 #include <linux/types.h>
@@ -71,7 +67,6 @@
 #include <linux/slab.h>
 #include <linux/smp.h>
 #include <linux/signal.h>
-#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -474,7 +469,7 @@ static int get_array(struct mm_struct *mm, unsigned long start, unsigned long en
                                return result;
                        }
                } while (addr & ~PAGE_MASK);
-               kunmap(addr-1, KM_READ);
+               kunmap(addr, KM_READ);
        }
        return result;
 }
@@ -483,9 +478,7 @@ static struct mm_struct *get_mm(int pid)
 {
        struct task_struct *p;
        struct mm_struct *mm = NULL;
-
-       /* need kernel lock to avoid the tsk->mm to go away under us */
-       lock_kernel();
+       
        read_lock(&tasklist_lock);
        p = find_task_by_pid(pid);
        if (p)
@@ -493,10 +486,10 @@ static struct mm_struct *get_mm(int pid)
        if (mm)
                atomic_inc(&mm->mm_users);
        read_unlock(&tasklist_lock);
-       unlock_kernel();
        return mm;
 }
 
+
 static int get_env(int pid, char * buffer)
 {
        struct mm_struct *mm = get_mm(pid);
@@ -849,9 +842,6 @@ static inline char * task_mem(struct mm_struct *mm, char *buffer)
        return buffer;
 }
 
-/*
- * These next two assume that the task's sigmask_lock is held by the caller.
- */
 static void collect_sigign_sigcatch(struct task_struct *p, sigset_t *ign,
                                    sigset_t *catch)
 {
@@ -904,115 +894,77 @@ extern inline char *task_cap(struct task_struct *p, char *buffer)
                            cap_t(p->cap_effective));
 }
 
-/*
- * This is somewhat safer than it was before.  However...
- *
- * Embedded pointers in the task structure may reference data that
- * can be changed or that is no longer valid after the tasklist
- * lock is released, or that isn't even protected by the tasklist
- * lock.  Eg. tsk->tty, tsk->sig, and tsk->p_pptr can change after
- * we make our own copy of the task structure.  This doesn't matter
- * unless we are trying to use the pointed-to data as an address.
- * So there are still a few safety issues to be addressed here.
- */
+
 static int get_status(int pid, char * buffer)
 {
        char * orig = buffer;
        struct task_struct *tsk;
        struct mm_struct *mm = NULL;
 
-       /*
-        * We lock the whole kernel here because p->files and p->mm are still
-        * protected by the global kernel lock.
-        */
-       lock_kernel();
-
        read_lock(&tasklist_lock);
        tsk = find_task_by_pid(pid);
-       if (tsk) {
+       if (tsk)
                mm = tsk->mm;
-               if (mm)
-                       atomic_inc(&mm->mm_users);
-
-               buffer = task_name(tsk, buffer);
-               buffer = task_state(tsk, buffer);
-
-               spin_lock_irq(&tsk->sigmask_lock);
-               buffer = task_sig(tsk, buffer);
-               spin_unlock_irq(&tsk->sigmask_lock);
-
-               buffer = task_cap(tsk, buffer);
-       }
-       read_unlock(&tasklist_lock);
-
-       unlock_kernel();
-
-       /*
-        * We can't hold the tasklist_lock and jiggle the mmap_sem --
-        * that can result in a deadlock.
-        */
-       if (mm) {
+       if (mm)
+               atomic_inc(&mm->mm_users);
+       read_unlock(&tasklist_lock);    /* FIXME!! This should be done after the last use */
+       if (!tsk)
+               return 0;
+       buffer = task_name(tsk, buffer);
+       buffer = task_state(tsk, buffer);
+       if (mm)
                buffer = task_mem(mm, buffer);
+       buffer = task_sig(tsk, buffer);
+       buffer = task_cap(tsk, buffer);
+       if (mm)
                mmput(mm);
-       }
-
-       /*
-        * (buffer - orig) will be zero on an error exit.
-        */
        return buffer - orig;
 }
 
 static int get_stat(int pid, char * buffer)
 {
        struct task_struct *tsk;
-       struct mm_struct *mm;
+       struct mm_struct *mm = NULL;
        unsigned long vsize, eip, esp, wchan;
        long priority, nice;
-       pid_t ppid = 0;
+       int tty_pgrp;
        sigset_t sigign, sigcatch;
        char state;
-       int res = 0;
-       unsigned int tty_device;
-       int tty_pgrp;
+       int res;
 
        read_lock(&tasklist_lock);
        tsk = find_task_by_pid(pid);
-       if (!tsk)
-               goto out_unlock;
-       /* avoid the task list to go away under us (security) */
-       get_page(MAP_NR(tsk) + mem_map);
-       ppid = tsk->p_pptr->pid;
-       read_unlock(&tasklist_lock);
-
-       /* we need the big kernel lock to avoid tsk->mm and tsk->tty
-          to change under us */
-       lock_kernel();
-       mm = tsk->mm;
+       if (tsk)
+               mm = tsk->mm;
        if (mm)
                atomic_inc(&mm->mm_users);
-       tty_device = tsk->tty ? kdev_t_to_nr(tsk->tty->device) : 0;
-       tty_pgrp = tsk->tty ? tsk->tty->pgrp : -1;
-       unlock_kernel();
-
-       spin_lock_irq(&tsk->sigmask_lock);
-       collect_sigign_sigcatch(tsk, &sigign, &sigcatch);
-       spin_unlock_irq(&tsk->sigmask_lock);
-
-       eip = KSTK_EIP(tsk);
-       esp = KSTK_ESP(tsk);
-       wchan = get_wchan(tsk);
-
+       read_unlock(&tasklist_lock);    /* FIXME!! This should be done after the last use */
+       if (!tsk)
+               return 0;
        state = *get_task_state(tsk);
        vsize = eip = esp = 0;
-       if (mm)
-       {
+       if (mm) {
                struct vm_area_struct *vma;
                down(&mm->mmap_sem);
-               for (vma = mm->mmap; vma; vma = vma->vm_next)
+               vma = mm->mmap;
+               while (vma) {
                        vsize += vma->vm_end - vma->vm_start;
+                       vma = vma->vm_next;
+               }
+               eip = KSTK_EIP(tsk);
+               esp = KSTK_ESP(tsk);
                up(&mm->mmap_sem);
        }
 
+       wchan = get_wchan(tsk);
+
+       collect_sigign_sigcatch(tsk, &sigign, &sigcatch);
+
+       if (tsk->tty)
+               tty_pgrp = tsk->tty->pgrp;
+       else
+               tty_pgrp = -1;
+
        /* scale priority and nice values from timeslices to -20..20 */
        /* to make it look like a "normal" Unix priority/nice value  */
        priority = tsk->counter;
@@ -1026,10 +978,10 @@ static int get_stat(int pid, char * buffer)
                pid,
                tsk->comm,
                state,
-               ppid,
+               tsk->p_pptr->pid,
                tsk->pgrp,
                tsk->session,
-               tty_device,
+               tsk->tty ? kdev_t_to_nr(tsk->tty->device) : 0,
                tty_pgrp,
                tsk->flags,
                tsk->min_flt,
@@ -1066,16 +1018,9 @@ static int get_stat(int pid, char * buffer)
                tsk->cnswap,
                tsk->exit_signal,
                tsk->processor);
-
        if (mm)
                mmput(mm);
-       free_task_struct(tsk);
        return res;
-
-out_unlock:
-       read_unlock(&tasklist_lock);
-       unlock_kernel();
-       return 0;
 }
                
 static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size,
@@ -1223,11 +1168,11 @@ static ssize_t read_maps (int pid, struct file * file, char * buf,
                          size_t count, loff_t *ppos)
 {
        struct task_struct *p;
-       struct mm_struct *mm = NULL;
        struct vm_area_struct * map, * next;
        char * destptr = buf, * buffer;
        loff_t lineno;
        ssize_t column, i;
+       int volatile_task;
        long retval;
 
        /*
@@ -1239,30 +1184,24 @@ static ssize_t read_maps (int pid, struct file * file, char * buf,
                goto out;
 
        retval = -EINVAL;
-       lock_kernel();
        read_lock(&tasklist_lock);
        p = find_task_by_pid(pid);
-       if (p) {
-               mm = p->mm;
-               if (mm)
-                       atomic_inc(&mm->mm_users);
-       }
-       read_unlock(&tasklist_lock);
-       unlock_kernel();
+       read_unlock(&tasklist_lock);    /* FIXME!! This should be done after the last use */
        if (!p)
                goto freepage_out;
 
-       /* nothing to map */
-       if (!mm || count == 0)
+       if (!p->mm || count == 0)
                goto getlen_out;
 
+       /* Check whether the mmaps could change if we sleep */
+       volatile_task = (p != current || atomic_read(&p->mm->mm_users) > 1);
+
        /* decode f_pos */
        lineno = *ppos >> MAPS_LINE_SHIFT;
        column = *ppos & (MAPS_LINE_LENGTH-1);
 
-       down(&mm->mmap_sem);
-       /* quickly go to line "lineno" */
-       for (map = mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++)
+       /* quickly go to line lineno */
+       for (map = p->mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++)
                continue;
 
        for ( ; map ; map = next ) {
@@ -1333,13 +1272,17 @@ static ssize_t read_maps (int pid, struct file * file, char * buf,
                /* done? */
                if (count == 0)
                        break;
+
+               /* By writing to user space, we might have slept.
+                * Stop the loop, to avoid a race condition.
+                */
+               if (volatile_task)
+                       break;
        }
-       up(&mm->mmap_sem);
 
        /* encode f_pos */
        *ppos = (lineno << MAPS_LINE_SHIFT) + column;
 
-       mmput(mm);
 getlen_out:
        retval = destptr - buf;
 
@@ -1352,31 +1295,28 @@ out:
 #ifdef __SMP__
 static int get_pidcpu(int pid, char * buffer)
 {
-       struct task_struct * tsk;
-       int i, len = 0;
+       struct task_struct * tsk = current ;
+       int i, len;
 
-       /*
-        * Hold the tasklist_lock to guarantee that the task_struct
-        * address will remain valid while we examine its contents.
-        */
        read_lock(&tasklist_lock);
-       tsk = find_task_by_pid(pid);
-       if (tsk)
-               get_page(MAP_NR(tsk) + mem_map);
-       read_unlock(&tasklist_lock);
-       if (tsk) {
-               len = sprintf(buffer,
-                       "cpu  %lu %lu\n",
-                       tsk->times.tms_utime,
-                       tsk->times.tms_stime);
+       if (pid != tsk->pid)
+               tsk = find_task_by_pid(pid);
+       read_unlock(&tasklist_lock);    /* FIXME!! This should be done after the last use */
+
+       if (tsk == NULL)
+               return 0;
+
+       len = sprintf(buffer,
+               "cpu  %lu %lu\n",
+               tsk->times.tms_utime,
+               tsk->times.tms_stime);
                
-               for (i = 0 ; i < smp_num_cpus; i++)
-                       len += sprintf(buffer + len, "cpu%d %lu %lu\n",
-                               i,
-                               tsk->per_cpu_utime[cpu_logical_map(i)],
-                               tsk->per_cpu_stime[cpu_logical_map(i)]);
-               free_task_struct(tsk);
-       }
+       for (i = 0 ; i < smp_num_cpus; i++)
+               len += sprintf(buffer + len, "cpu%d %lu %lu\n",
+                       i,
+                       tsk->per_cpu_utime[cpu_logical_map(i)],
+                       tsk->per_cpu_stime[cpu_logical_map(i)]);
+
        return len;
 }
 #endif
@@ -1513,6 +1453,12 @@ static int process_unauthorized(int type, int pid)
        int ok = 0;
                
        read_lock(&tasklist_lock);
+       
+       /*
+        *      Grab the lock, find the task, save the uid and
+        *      check it has an mm still (ie its not dead)
+        */
+       
        p = find_task_by_pid(pid);
        if (p) {
                euid=p->euid;
@@ -1520,7 +1466,9 @@ static int process_unauthorized(int type, int pid)
                if(!cap_issubset(p->cap_permitted, current->cap_permitted))
                        ok=0;                   
        }
+               
        read_unlock(&tasklist_lock);
+
        if (!p)
                return 1;
 
index c3719d5d9cd19e1f0cae15253be83bda021fbf33..1eb4ac09368881d3c556e37786beed34a722d6fc 100644 (file)
@@ -83,24 +83,13 @@ typedef unsigned long pgprot_t;
  *
  * A __PAGE_OFFSET of 0xC0000000 means that the kernel has
  * a virtual address space of one gigabyte, which limits the
- * amount of physical memory you can use to about 950MB. If
- * you want to use more physical memory, change this define.
+ * amount of physical memory you can use to about 950MB. 
  *
- * For example, if you have 2GB worth of physical memory, you
- * could change this define to 0x80000000, which gives the
- * kernel 2GB of virtual memory (enough to most of your physical memory
- * as the kernel needs a bit extra for various io-memory mappings)
- *
- * IF YOU CHANGE THIS, PLEASE ALSO CHANGE
- *
- *     arch/i386/vmlinux.lds
- *
- * which has the same constant encoded..
+ * If you want more physical memory than this then see the CONFIG_BIGMEM
+ * option in the kernel configuration.
  */
 
-#include <asm/page_offset.h>
-
-#define __PAGE_OFFSET          (PAGE_OFFSET_RAW)
+#define __PAGE_OFFSET          (0xC0000000)
 
 #ifndef __ASSEMBLY__
 
diff --git a/include/asm-i386/page_offset.h b/include/asm-i386/page_offset.h
deleted file mode 100644 (file)
index bb3a64d..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <linux/config.h>
-#ifdef CONFIG_1GB
-#define PAGE_OFFSET_RAW 0xC0000000
-#elif defined(CONFIG_2GB)
-#define PAGE_OFFSET_RAW 0x80000000
-#elif defined(CONFIG_3GB)
-#define PAGE_OFFSET_RAW 0x40000000
-#endif
index 15270883750be3e04c6bdbc2b9e659a98fd87718..561b3d60cd6009c1c586e346cd843fb0829a3c11 100644 (file)
@@ -3,39 +3,48 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996 by Ralf Baechle
- * Copyright (C) 1999 by Niibe Yutaka
+ * Copyright (C) 1999 by Kaz Kojima
  *
  * Defitions for the address spaces of the SH CPUs.
  */
 #ifndef __ASM_SH_ADDRSPACE_H
 #define __ASM_SH_ADDRSPACE_H
 
-/*
- * Memory segments (32bit kernel mode addresses)
- */
-#define KUSEG                   0x00000000
-#define KSEG0                   0x80000000
-#define KSEG1                   0xa0000000
-#define KSEG2                   0xc0000000
-#define KSEG3                   0xe0000000
+/* Memory segments (32bit Priviledged mode addresses)  */
+#define P0SEG          0x00000000
+#define P1SEG          0x80000000
+#define P2SEG          0xa0000000
+#define P3SEG          0xc0000000
+#define P4SEG          0xe0000000
 
-/*
- * Returns the kernel segment base of a given address
- */
-#define KSEGX(a)                (((unsigned long)(a)) & 0xe0000000)
+#if defined(__sh3__)
+/* Should fill here */
+#elif defined(__SH4__)
+/* Detailed P4SEG  */
+#define P4SEG_STORE_QUE        (P4SEG)
+#define P4SEG_IC_ADDR  0xf0000000
+#define P4SEG_IC_DATA  0xf1000000
+#define P4SEG_ITLB_ADDR        0xf2000000
+#define P4SEG_ITLB_DATA        0xf3000000
+#define P4SEG_OC_ADDR  0xf4000000
+#define P4SEG_OC_DATA  0xf5000000
+#define P4SEG_TLB_ADDR 0xf6000000
+#define P4SEG_TLB_DATA 0xf7000000
+#define P4SEG_REG_BASE 0xff000000
+#endif
 
-/*
- * Returns the physical address of a KSEG0/KSEG1 address
- */
-#define PHYSADDR(a)            (((unsigned long)(a)) & 0x1fffffff)
+/* Returns the privileged segment base of a given address  */
+#define PXSEG(a)       (((unsigned long)(a)) & 0xe0000000)
+
+/* Returns the physical address of a PnSEG (n=1,2) address   */
+#define PHYSADDR(a)    (((unsigned long)(a)) & 0x1fffffff)
 
 /*
- * Map an address to a certain kernel segment
+ * Map an address to a certain privileged segment
  */
-#define KSEG0ADDR(a)           ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG0))
-#define KSEG1ADDR(a)           ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG1))
-#define KSEG2ADDR(a)           ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG2))
-#define KSEG3ADDR(a)           ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG3))
+#define P1SEGADDR(a)   ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P1SEG))
+#define P2SEGADDR(a)   ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P2SEG))
+#define P3SEGADDR(a)   ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P3SEG))
+#define P4SEGADDR(a)   ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P4SEG))
 
 #endif /* __ASM_SH_ADDRSPACE_H */
index d2af3d7696e9ea3b0513c7cc6c2cbba14f30333c..7f580a9aad1a9ff84ab44770cdcc9f896f2b3f6e 100644 (file)
@@ -25,7 +25,7 @@ typedef struct { int counter; } atomic_t;
  * on us. We need to use _exactly_ the address the user gave us,
  * not some alias that contains the same information.
  */
-#define __atomic_fool_gcc(x) (*(struct { int a[100]; } *)x)
+#define __atomic_fool_gcc(x) (*(volatile struct { int a[100]; } *)x)
 
 /*
  * To get proper branch prediction for the main line, we must branch
@@ -37,8 +37,7 @@ extern __inline__ void atomic_add(int i, atomic_t * v)
 {
        unsigned long flags;
 
-       save_flags(flags);
-       cli();
+       save_and_cli(flags);
        *(long *)v += i;
        restore_flags(flags);
 }
@@ -47,8 +46,7 @@ extern __inline__ void atomic_sub(int i, atomic_t *v)
 {
        unsigned long flags;
 
-       save_flags(flags);
-       cli();
+       save_and_cli(flags);
        *(long *)v -= i;
        restore_flags(flags);
 }
@@ -57,8 +55,7 @@ extern __inline__ int atomic_add_return(int i, atomic_t * v)
 {
        unsigned long temp, flags;
 
-       save_flags(flags);
-       cli();
+       save_and_cli(flags);
        temp = *(long *)v;
        temp += i;
        *(long *)v = temp;
@@ -71,8 +68,7 @@ extern __inline__ int atomic_sub_return(int i, atomic_t * v)
 {
        unsigned long temp, flags;
 
-       save_flags(flags);
-       cli();
+       save_and_cli(flags);
        temp = *(long *)v;
        temp -= i;
        *(long *)v = temp;
@@ -90,22 +86,20 @@ extern __inline__ int atomic_sub_return(int i, atomic_t * v)
 #define atomic_inc(v) atomic_add(1,(v))
 #define atomic_dec(v) atomic_sub(1,(v))
 
-extern __inline__ void atomic_clear_mask(int mask, atomic_t *v)
+extern __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v)
 {
        unsigned long flags;
 
-       save_flags(flags);
-       cli();
+       save_and_cli(flags);
        *(long *)v &= ~mask;
        restore_flags(flags);
 }
 
-extern __inline__ void atomic_set_mask(int mask, atomic_t *v)
+extern __inline__ void atomic_set_mask(unsigned int mask, atomic_t *v)
 {
        unsigned long flags;
 
-       save_flags(flags);
-       cli();
+       save_and_cli(flags);
        *(long *)v |= mask;
        restore_flags(flags);
 }
index 9808789c75bcec76bf5eb3de46a71b3f02043734..de026bcd2bd8f3282de8e982d143a5d97e63051c 100644 (file)
@@ -14,8 +14,7 @@ extern __inline__ void set_bit(int nr, void * addr)
 
        a += nr >> 5;
        mask = 1 << (nr & 0x1f);
-       save_flags(flags);
-       cli();
+       save_and_cli(flags);
        *a |= mask;
        restore_flags(flags);
 }
@@ -28,8 +27,7 @@ extern __inline__ void clear_bit(int nr, void * addr)
 
        a += nr >> 5;
        mask = 1 << (nr & 0x1f);
-       save_flags(flags);
-       cli();
+       save_and_cli(flags);
        *a &= ~mask;
        restore_flags(flags);
 }
@@ -42,8 +40,7 @@ extern __inline__ void change_bit(int nr, void * addr)
 
        a += nr >> 5;
        mask = 1 << (nr & 0x1f);
-       save_flags(flags);
-       cli();
+       save_and_cli(flags);
        *a ^= mask;
        restore_flags(flags);
 }
@@ -56,8 +53,7 @@ extern __inline__ int test_and_set_bit(int nr, void * addr)
 
        a += nr >> 5;
        mask = 1 << (nr & 0x1f);
-       save_flags(flags);
-       cli();
+       save_and_cli(flags);
        retval = (mask & *a) != 0;
        *a |= mask;
        restore_flags(flags);
@@ -73,8 +69,7 @@ extern __inline__ int test_and_clear_bit(int nr, void * addr)
 
        a += nr >> 5;
        mask = 1 << (nr & 0x1f);
-       save_flags(flags);
-       cli();
+       save_and_cli(flags);
        retval = (mask & *a) != 0;
        *a &= ~mask;
        restore_flags(flags);
@@ -90,8 +85,7 @@ extern __inline__ int test_and_change_bit(int nr, void * addr)
 
        a += nr >> 5;
        mask = 1 << (nr & 0x1f);
-       save_flags(flags);
-       cli();
+       save_and_cli(flags);
        retval = (mask & *a) != 0;
        *a ^= mask;
        restore_flags(flags);
@@ -112,7 +106,7 @@ extern __inline__ unsigned long ffz(unsigned long word)
        __asm__("1:\n"
                "shlr   %1\n\t"
                "bt/s   1b\n\t"
-               "add    #1, %0"
+               " add   #1, %0"
                : "=r" (result)
                : "r" (word), "0" (~0L));
        return result;
@@ -165,7 +159,7 @@ extern __inline__ int ext2_set_bit(int nr,void * addr)
 
        ADDR += nr >> 3;
        mask = 1 << (nr & 0x07);
-       save_flags(flags); cli();
+       save_and_cli(flags);
        retval = (mask & *ADDR) != 0;
        *ADDR |= mask;
        restore_flags(flags);
@@ -180,7 +174,7 @@ extern __inline__ int ext2_clear_bit(int nr, void * addr)
 
        ADDR += nr >> 3;
        mask = 1 << (nr & 0x07);
-       save_flags(flags); cli();
+       save_and_cli(flags);
        retval = (mask & *ADDR) != 0;
        *ADDR &= ~mask;
        restore_flags(flags);
index 4c20b768d4d390ef94c39b3bc394efd73bca1db0..99728234a1b44a04f5adfc5e90111e5395b15cda 100644 (file)
 
 static void __init check_bugs(void)
 {
+       extern unsigned long loops_per_sec;
+
+       cpu_data->loops_per_sec = loops_per_sec;
+       
+       switch (cpu_data->type) {
+       case CPU_SH7708:
+               printk("CPU: SH7708/SH7709\n");
+               break;
+       case CPU_SH7729:
+               printk("CPU: SH7709A/SH7729\n");
+               break;
+       case CPU_SH7750:
+               printk("CPU: SH7750\n");
+               break;
+       default:
+               printk("CPU: ??????\n");
+               break;
+       }
 }
 #endif /* __ASM_SH_BUGS_H */
index 5a6863485e631342d0faee1997723b09131b23ca..dcc9f824187b4e02596ca7c8f3b17f16e08845db 100644 (file)
@@ -5,7 +5,6 @@
  * Copyright (C) 1999  Niibe Yutaka
  */
 
-#include <linux/config.h>
 #include <asm/types.h>
 
 static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
@@ -34,7 +33,7 @@ static __inline__ __const__ __u16 ___arch__swab16(__u16 x)
 #  define __SWAB_64_THRU_32__
 #endif
 
-#ifdef CONFIG_LITTLE_ENDIAN
+#ifdef __LITTLE_ENDIAN__
 #include <linux/byteorder/little_endian.h>
 #else
 #include <linux/byteorder/big_endian.h>
index d22ab4e24ea23ff87a8cb16caaafd870aeb09190..f9113e77bc560210746e1f65af6d7b10b61ce508 100644 (file)
@@ -6,7 +6,11 @@
 #define __ASM_SH_CACHE_H
 
 /* bytes per L1 cache line */
+#if defined(__sh3__)
 #define        L1_CACHE_BYTES  16
+#elif defined(__SH4__)
+#define        L1_CACHE_BYTES  32
+#endif
 
 #define        L1_CACHE_ALIGN(x)       (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
 
@@ -20,4 +24,8 @@
                 __section__(".data.cacheline_aligned")))
 #endif
 
+extern void cache_flush_area(unsigned long start, unsigned long end);
+extern void cache_purge_area(unsigned long start, unsigned long end);
+extern void cache_wback_area(unsigned long start, unsigned long end);
+
 #endif /* __ASM_SH_CACHE_H */
index b2bbd8afb953d8e7b486102336d9152bd3a8ad83..6d5f89c045bbc595fc329c2c5c670feaa3b3e572 100644 (file)
@@ -1,22 +1,13 @@
 #ifndef __ASM_SH_CHECKSUM_H
 #define __ASM_SH_CHECKSUM_H
 
-
-/*
- *     This is a version of ip_compute_csum() optimized for IP headers,
- *     which always checksum on 4 octet boundaries.
- */
-extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl);
-
 /*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
+ * 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 by Kaz Kojima & Niibe Yutaka
  */
-extern unsigned short int csum_tcpudp_magic(unsigned long saddr,
-                                          unsigned long daddr,
-                                          unsigned short len,
-                                          unsigned short proto,
-                                          unsigned int sum);
 
 /*
  * computes the checksum of a memory block at buff, length len,
@@ -30,55 +21,220 @@ extern unsigned short int csum_tcpudp_magic(unsigned long saddr,
  *
  * it's best to have buff aligned on a 32-bit boundary
  */
-extern unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+asmlinkage unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
 
 /*
  * the same as csum_partial, but copies from src while it
- * checksums
+ * checksums, and handles user-space pointer exceptions correctly, when needed.
  *
  * here even more important to align src and dst on a 32-bit (or even
  * better 64-bit) boundary
  */
-unsigned int csum_partial_copy(const char *src, char *dst, int len, unsigned int sum);
+
+asmlinkage unsigned int csum_partial_copy_generic( const char *src, char *dst, int len, int sum,
+                                                  int *src_err_ptr, int *dst_err_ptr);
+
+/*
+ *     Note: when you get a NULL pointer exception here this means someone
+ *     passed in an incorrect kernel address to one of these functions. 
+ *     
+ *     If you use these functions directly please don't forget the 
+ *     verify_area().
+ */
+extern __inline__
+unsigned int csum_partial_copy_nocheck ( const char *src, char *dst,
+                                       int len, int sum)
+{
+       return csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
+}
+
+extern __inline__
+unsigned int csum_partial_copy_from_user ( const char *src, char *dst,
+                                               int len, int sum, int *err_ptr)
+{
+       return csum_partial_copy_generic ( src, dst, len, sum, err_ptr, NULL);
+}
+
+#if 0
+
+/* Not used at the moment. It is difficult to imagine for what purpose
+   it can be used :-) Please, do not forget to verify_area before it --ANK
+ */
+
+/*
+ * This combination is currently not used, but possible:
+ */
+
+extern __inline__
+unsigned int csum_partial_copy_to_user ( const char *src, char *dst,
+                                       int len, int sum, int *err_ptr)
+{
+       return csum_partial_copy_generic ( src, dst, len, sum, NULL, err_ptr);
+}
+#endif
 
 /*
- * the same as csum_partial, but copies from user space (but on the alpha
- * we have just one address space, so this is identical to the above)
+ * These are the old (and unsafe) way of doing checksums, a warning message will be
+ * printed if they are used and an exeption occurs.
  *
- * this is obsolete and will go away.
+ * these functions should go away after some time.
  */
+
 #define csum_partial_copy_fromuser csum_partial_copy
+unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum);
 
 /*
- * this is a new version of the above that records errors it finds in *errp,
- * but continues and zeros the rest of the buffer.
+ *     Fold a partial checksum
  */
-unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len, unsigned int sum, int *errp);
+
+static __inline__ unsigned int csum_fold(unsigned int sum)
+{
+       unsigned int __dummy;
+       __asm__("clrt\n\t"
+               "mov    %0,%1\n\t"
+               "shll16 %0\n\t"
+               "addc   %0,%1\n\t"
+               "movt   %0\n\t"
+               "shlr16 %1\n\t"
+               "add    %1,%0"
+               : "=r" (sum), "=&r" (__dummy)
+               : "0" (sum));
+       return ~sum;
+}
 
 /*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
+ *     This is a version of ip_compute_csum() optimized for IP headers,
+ *     which always checksum on 4 octet boundaries.
+ *
+ *      i386 version by Jorge Cwik <jorge@laser.satlink.net>, adapted
+ *      for linux by * Arnt Gulbrandsen.
  */
+static __inline__ unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
+{
+       unsigned int sum, __dummy;
+
+       __asm__ __volatile__(
+               "mov.l  @%1+,%0\n\t"
+               "add    #-4,%2\n\t"
+               "clrt\n\t"
+               "mov.l  @%1+,%3\n\t"
+               "addc   %3,%0\n\t"
+               "mov.l  @%1+,%3\n\t"
+               "addc   %3,%0\n\t"
+               "mov.l  @%1+,%3\n\t"
+               "addc   %3,%0\n"
+               "1:\t"
+               "mov.l  @%1+,%3\n\t"
+               "addc   %3,%0\n\t"
+               "movt   %3\n\t"
+               "dt     %2\n\t"
+               "bf/s   1b\n\t"
+               " cmp/eq #1,%3\n\t"
+               "mov    #0,%3\n\t"
+               "addc   %3,%0\n\t"
+       /* Since the input registers which are loaded with iph and ihl
+          are modified, we must also specify them as outputs, or gcc
+          will assume they contain their original values. */
+       : "=r" (sum), "=r" (iph), "=r" (ihl), "=&z" (__dummy)
+       : "1" (iph), "2" (ihl));
+
+       return  csum_fold(sum);
+}
 
-extern unsigned short ip_compute_csum(unsigned char * buff, int len);
+static __inline__ unsigned long csum_tcpudp_nofold(unsigned long saddr,
+                                                  unsigned long daddr,
+                                                  unsigned short len,
+                                                  unsigned short proto,
+                                                  unsigned int sum) 
+{
+#ifdef __LITTLE_ENDIAN__
+       unsigned long len_proto = (ntohs(len)<<16)+proto*256;
+#else
+       unsigned long len_proto = (proto<<16)+len;
+#endif
+       __asm__("clrt\n\t"
+               "addc   %0,%1\n\t"
+               "addc   %2,%1\n\t"
+               "addc   %3,%1\n\t"
+               "movt   %0\n\t"
+               "add    %1,%0"
+               : "=r" (sum), "=r" (len_proto)
+               : "r" (daddr), "r" (saddr), "1" (len_proto), "0" (sum));
+       return sum;
+}
 
 /*
- *     Fold a partial checksum without adding pseudo headers
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
  */
+static __inline__ unsigned short int csum_tcpudp_magic(unsigned long saddr,
+                                                      unsigned long daddr,
+                                                      unsigned short len,
+                                                      unsigned short proto,
+                                                      unsigned int sum) 
+{
+       return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
 
-static inline unsigned short csum_fold(unsigned int sum)
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+
+static __inline__ unsigned short ip_compute_csum(unsigned char * buff, int len)
 {
-       sum = (sum & 0xffff) + (sum >> 16);
-       sum = (sum & 0xffff) + (sum >> 16);
-       return ~sum;
+    return csum_fold (csum_partial(buff, len, 0));
 }
 
 #define _HAVE_ARCH_IPV6_CSUM
-/*
-extern unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
-                                          struct in6_addr *daddr,
-                                          __u16 len,
-                                          unsigned short proto,
-                                          unsigned int sum);
-*/
+static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
+                                                    struct in6_addr *daddr,
+                                                    __u16 len,
+                                                    unsigned short proto,
+                                                    unsigned int sum) 
+{
+       unsigned int __dummy;
+       __asm__("clrt\n\t"
+               "mov.l  @(0,%2),%1\n\t"
+               "addc   %1,%0\n\t"
+               "mov.l  @(4,%2),%1\n\t"
+               "addc   %1,%0\n\t"
+               "mov.l  @(8,%2),%1\n\t"
+               "addc   %1,%0\n\t"
+               "mov.l  @(12,%2),%1\n\t"
+               "addc   %1,%0\n\t"
+               "mov.l  @(0,%3),%1\n\t"
+               "addc   %1,%0\n\t"
+               "mov.l  @(4,%3),%1\n\t"
+               "addc   %1,%0\n\t"
+               "mov.l  @(8,%3),%1\n\t"
+               "addc   %1,%0\n\t"
+               "mov.l  @(12,%3),%1\n\t"
+               "addc   %1,%0\n\t"
+               "addc   %4,%0\n\t"
+               "addc   %5,%0\n\t"
+               "movt   %1\n\t"
+               "add    %1,%0\n"
+               : "=r" (sum), "=&r" (__dummy)
+               : "r" (saddr), "r" (daddr), 
+                 "r" (htonl((__u32) (len))), "r" (htonl(proto)), "0" (sum));
+
+       return csum_fold(sum);
+}
+
+/* 
+ *     Copy and checksum to user
+ */
+#define HAVE_CSUM_COPY_USER
+static __inline__ unsigned int csum_and_copy_to_user (const char *src, char *dst,
+                                   int len, int sum, int *err_ptr)
+{
+       if (access_ok(VERIFY_WRITE, dst, len))
+               return csum_partial_copy_generic(src, dst, len, sum, NULL, err_ptr);
+
+       if (len)
+               *err_ptr = -EFAULT;
+
+       return -1; /* invalid checksum */
+}
 #endif /* __ASM_SH_CHECKSUM_H */
index 9eb03f65d15b7a25d0e0b3798170e79dbccf2da9..222561a3ee87ca26ac02dc825b13972dbea2f584 100644 (file)
@@ -2,26 +2,26 @@
 #define __ASM_SH_DELAY_H
 
 /*
- * Copyright (C) 1999  Niibe Yutaka
+ * Copyright (C) 1999  Kaz Kojima
  */
 
 extern __inline__ void __delay(unsigned long loops)
 {
-       unsigned long __dummy;
        __asm__ __volatile__(
-               "1:\t"
-               "dt     %0\n\t"
-               "bf     1b"
-               :"=r" (__dummy)
-               :"0" (loops));
+               "tst    %0,%0\n\t"
+               "1:\t"
+               "bf/s   1b\n\t"
+               " dt    %0"
+               : "=r" (loops)
+               : "0" (loops));
 }
 
 extern __inline__ void __udelay(unsigned long usecs, unsigned long lps)
 {
        usecs *= 0x000010c6;            /* 2**32 / 1000000 */
-       __asm__("mul.l  %0,%2\n\t"
-               "sts    macl,%0"
-               : "=&r" (usecs)
+       __asm__("dmulu.l        %0,%2\n\t"
+               "sts    mach,%0"
+               : "=r" (usecs)
                : "0" (usecs), "r" (lps)
                : "macl", "mach");
         __delay(usecs);
@@ -36,9 +36,4 @@ extern __inline__ void __udelay(unsigned long usecs, unsigned long lps)
 
 #define udelay(usecs) __udelay((usecs),__udelay_val)
 
-extern __inline__ unsigned long muldiv(unsigned long a, unsigned long b, unsigned long c)
-{
-       return (a*b)/c;
-}
-
 #endif /* __ASM_SH_DELAY_H */
index de5512ce30e6f7196105149056004ffe1c5d743c..a0e98de5fe6693c663a337be3841066ad280cfc5 100644 (file)
@@ -5,7 +5,6 @@
  * ELF register definitions..
  */
 
-#include <linux/config.h>
 #include <asm/ptrace.h>
 #include <asm/user.h>
 #include <asm/byteorder.h>
@@ -15,12 +14,10 @@ typedef unsigned long elf_greg_t;
 #define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 
-#ifdef CONFIG_CPU_SH4
+/* Though SH-3 has no floating point regs.. */
+#define ELF_NFPREG 34
 typedef double elf_fpreg_t;
 typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
-#else /* SH 3 has no floating point regs */
-typedef struct { void *null; } elf_fpregset_t;
-#endif
 
 /*
  * This is used to ensure we don't load something for the wrong architecture.
@@ -31,7 +28,7 @@ typedef struct { void *null; } elf_fpregset_t;
  * These are used to set parameters in the core dumps.
  */
 #define ELF_CLASS      ELFCLASS32
-#ifdef __LITTLE_ENDIAN
+#ifdef __LITTLE_ENDIAN__
 #define ELF_DATA       ELFDATA2LSB
 #else
 #define ELF_DATA       ELFDATA2MSB
@@ -68,6 +65,12 @@ typedef struct { void *null; } elf_fpregset_t;
 
 #define ELF_PLATFORM  (NULL)
 
+#define ELF_PLAT_INIT(_r) \
+  do { _r->regs[0]=0; _r->regs[1]=0; _r->regs[2]=0; _r->regs[3]=0; \
+       _r->regs[4]=0; _r->regs[5]=0; _r->regs[6]=0; _r->regs[7]=0; \
+       _r->regs[8]=0; _r->regs[9]=0; _r->regs[10]=0; _r->regs[11]=0; \
+       _r->regs[12]=0; _r->regs[13]=0; _r->regs[14]=0; } while (0)
+
 #ifdef __KERNEL__
 #define SET_PERSONALITY(ex, ibcs2) \
        current->personality = PER_LINUX_32BIT
index 1957bb7b088c9971a0f5e5fedc72901b9b330e6f..bc5866f7ea8e7d35568e3004e7e5a3f3ff388430 100644 (file)
@@ -14,7 +14,7 @@ extern unsigned int local_irq_count[NR_CPUS];
 #define hardirq_enter(cpu)     (local_irq_count[cpu]++)
 #define hardirq_exit(cpu)      (local_irq_count[cpu]--)
 
-#define synchronize_irq()      do { } while (0)
+#define synchronize_irq()      barrier()
 
 #else
 
diff --git a/include/asm-sh/hdreg.h b/include/asm-sh/hdreg.h
new file mode 100644 (file)
index 0000000..4a2272c
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ *  linux/include/asm-sh/hdreg.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+#ifndef __ASM_SH_HDREG_H
+#define __ASM_SH_HDREG_H
+
+typedef unsigned short ide_ioreg_t;
+
+#endif /* __ASM_SH_HDREG_H */
diff --git a/include/asm-sh/ide.h b/include/asm-sh/ide.h
new file mode 100644 (file)
index 0000000..b9b3efc
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ *  linux/include/asm-sh/ide.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+/*
+ *  This file contains the i386 architecture specific IDE code.
+ *  In future, SuperH code.
+ */
+
+#ifndef __ASM_SH_IDE_H
+#define __ASM_SH_IDE_H
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+
+#ifndef MAX_HWIFS
+#define MAX_HWIFS      10
+#endif
+
+#define ide__sti()     __sti()
+
+static __inline__ int ide_default_irq(ide_ioreg_t base)
+{
+       switch (base) {
+               case 0x1f0: return 14;
+               case 0x170: return 15;
+               case 0x1e8: return 11;
+               case 0x168: return 10;
+               case 0x1e0: return 8;
+               case 0x160: return 12;
+               default:
+                       return 0;
+       }
+}
+
+static __inline__ ide_ioreg_t ide_default_io_base(int index)
+{
+       switch (index) {
+               case 0: return 0x1f0;
+               case 1: return 0x170;
+               case 2: return 0x1e8;
+               case 3: return 0x168;
+               case 4: return 0x1e0;
+               case 5: return 0x160;
+               default:
+                       return 0;
+       }
+}
+
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
+{
+       ide_ioreg_t reg = data_port;
+       int i;
+
+       for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+               hw->io_ports[i] = reg;
+               reg += 1;
+       }
+       if (ctrl_port) {
+               hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+       } else {
+               hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+       }
+       if (irq != NULL)
+               *irq = 0;
+}
+
+static __inline__ void ide_init_default_hwifs(void)
+{
+#ifndef CONFIG_BLK_DEV_IDEPCI
+       hw_regs_t hw;
+       int index;
+
+       for(index = 0; index < MAX_HWIFS; index++) {
+               ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
+               hw.irq = ide_default_irq(ide_default_io_base(index));
+               ide_register_hw(&hw, NULL);
+       }
+#endif /* CONFIG_BLK_DEV_IDEPCI */
+}
+
+typedef union {
+       unsigned all                    : 8;    /* all of the bits together */
+       struct {
+               unsigned head           : 4;    /* always zeros here */
+               unsigned unit           : 1;    /* drive select number, 0 or 1 */
+               unsigned bit5           : 1;    /* always 1 */
+               unsigned lba            : 1;    /* using LBA instead of CHS */
+               unsigned bit7           : 1;    /* always 1 */
+       } b;
+       } select_t;
+
+#define ide_request_irq(irq,hand,flg,dev,id)   request_irq((irq),(hand),(flg),(dev),(id))
+#define ide_free_irq(irq,dev_id)               free_irq((irq), (dev_id))
+#define ide_check_region(from,extent)          check_region((from), (extent))
+#define ide_request_region(from,extent,name)   request_region((from), (extent), (name))
+#define ide_release_region(from,extent)                release_region((from), (extent))
+
+/*
+ * The following are not needed for the non-m68k ports
+ */
+#define ide_ack_intr(hwif)             (1)
+#define ide_fix_driveid(id)            do {} while (0)
+#define ide_release_lock(lock)         do {} while (0)
+#define ide_get_lock(lock, hdlr, data) do {} while (0)
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_SH_IDE_H */
index e13c80dbee427465c13537f0e2be52cf6b02f736..57f0367b0c91aaaf3060ab4aebe45edb2924f7c4 100644 (file)
@@ -1,6 +1,18 @@
 #ifndef __ASM_SH_IO_H
 #define __ASM_SH_IO_H
-/* XXXXXXXXXXXXXXXXX */
+
+/*
+ * Convention:
+ *    read{b,w,l}/write{b,w,l} are for PCI,
+ *    while in{b,w,l}/out{b,w,l} are for ISA
+ * These may (will) be platform specific function.
+ *
+ * In addition, we have 
+ *   ctrl_in{b,w,l}/ctrl_out{b,w,l} for SuperH specific I/O.
+ *   which are processor specific.
+ */
+
+#include <asm/cache.h>
 
 #define virt_to_bus virt_to_phys
 #define bus_to_virt phys_to_virt
@@ -20,7 +32,7 @@ extern __inline__ unsigned long readl(unsigned long addr)
        return *(volatile unsigned long*)addr;
 }
 
-extern __inline__ void writeb(unsigned short b, unsigned long addr)
+extern __inline__ void writeb(unsigned char b, unsigned long addr)
 {
        *(volatile unsigned char*)addr = b;
 }
@@ -75,6 +87,36 @@ extern __inline__ void outl(unsigned int b, unsigned long addr)
        return writel(b,addr);
 }
 
+extern __inline__ unsigned long ctrl_inb(unsigned long addr)
+{
+       return *(volatile unsigned char*)addr;
+}
+
+extern __inline__ unsigned long ctrl_inw(unsigned long addr)
+{
+       return *(volatile unsigned short*)addr;
+}
+
+extern __inline__ unsigned long ctrl_inl(unsigned long addr)
+{
+       return *(volatile unsigned long*)addr;
+}
+
+extern __inline__ void ctrl_outb(unsigned char b, unsigned long addr)
+{
+       *(volatile unsigned char*)addr = b;
+}
+
+extern __inline__ void ctrl_outw(unsigned short b, unsigned long addr)
+{
+       *(volatile unsigned short*)addr = b;
+}
+
+extern __inline__ void ctrl_outl(unsigned int b, unsigned long addr)
+{
+        *(volatile unsigned long*)addr = b;
+}
+
 #define inb_p inb
 #define outb_p outb
 
@@ -93,7 +135,7 @@ extern __inline__ unsigned long virt_to_phys(volatile void * address)
 
 extern __inline__ void * phys_to_virt(unsigned long address)
 {
-       return (void *)KSEG0ADDR(address);
+       return (void *)P1SEGADDR(address);
 }
 
 extern void * ioremap(unsigned long phys_addr, unsigned long size);
@@ -115,7 +157,7 @@ extern void iounmap(void *addr);
  */
 extern __inline__ void * ioremap(unsigned long offset, unsigned long size)
 {
-       return (void *) KSEG1ADDR(offset);
+       return (void *) P2SEGADDR(offset);
 }
 
 /*
@@ -125,7 +167,7 @@ extern __inline__ void * ioremap(unsigned long offset, unsigned long size)
  */
 extern __inline__ void * ioremap_nocache (unsigned long offset, unsigned long size)
 {
-       return (void *) KSEG1ADDR(offset);
+       return (void *) P2SEGADDR(offset);
 }
 
 extern __inline__ void iounmap(void *addr)
@@ -148,11 +190,30 @@ out:
        return retval;
 }
 
-/* Nothing to do */
+/*
+ * The caches on some architectures aren't dma-coherent and have need to
+ * handle this in software.  There are three types of operations that
+ * can be applied to dma buffers.
+ *
+ *  - dma_cache_wback_inv(start, size) makes caches and RAM coherent by
+ *    writing the content of the caches back to memory, if necessary.
+ *    The function also invalidates the affected part of the caches as
+ *    necessary before DMA transfers from outside to memory.
+ *  - dma_cache_inv(start, size) invalidates the affected parts of the
+ *    caches.  Dirty lines of the caches may be written back or simply
+ *    be discarded.  This operation is necessary before dma operations
+ *    to the memory.
+ *  - dma_cache_wback(start, size) writes back any dirty lines but does
+ *    not invalidate the cache.  This can be used before DMA reads from
+ *    memory,
+ */
 
-#define dma_cache_inv(_start,_size)            do { } while (0)
-#define dma_cache_wback(_start,_size)          do { } while (0)
-#define dma_cache_wback_inv(_start,_size)      do { } while (0)
+#define dma_cache_wback_inv(_start,_size) \
+    cache_flush_area((unsigned long)(_start),((unsigned long)(_start)+(_size)))
+#define dma_cache_inv(_start,_size) \
+    cache_purge_area((unsigned long)(_start),((unsigned long)(_start)+(_size)))
+#define dma_cache_wback(_start,_size) \
+    cache_wback_area((unsigned long)(_start),((unsigned long)(_start)+(_size)))
 
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_IO_H */
index 11b8153ac0dfe0cee72bd7965d00402b26e6b5b6..5f87787e8e6126b6eca2020d05eb179b1589d60c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ioctl.h,v 1.5 1993/07/19 21:53:50 root Exp root $
+/* $Id: ioctl.h,v 1.1 1999/09/18 17:29:53 gniibe Exp $
  *
  * linux/ioctl.h for Linux by H.H. Bergman.
  */
index 56b5bff70b63598d10ff5ec82b0f96c7d0068e37..3905e572cabdbfaeea6a2f510609256affcc3533 100644 (file)
@@ -39,9 +39,9 @@
 
 #define TIOCSTI                _IOW('T', 18, char) /* 0x5412 */
 #define TIOCMGET       _IOR('T', 21, unsigned int) /* 0x5415 */
-#define TIOCMBIS       _IOW('T', 22, unsigne int) /* 0x5416 */
-#define TIOCMBIC       _IOW('T', 23, unsigne int) /* 0x5417 */
-#define TIOCMSET       _IOW('T', 24, unsigne int) /* 0x5418 */
+#define TIOCMBIS       _IOW('T', 22, unsigned int) /* 0x5416 */
+#define TIOCMBIC       _IOW('T', 23, unsigned int) /* 0x5417 */
+#define TIOCMSET       _IOW('T', 24, unsigned int) /* 0x5418 */
 # define TIOCM_LE      0x001
 # define TIOCM_DTR     0x002
 # define TIOCM_RTS     0x004
index 1a5cf7727f806c53173b41347e1e03fecd246ba5..a1c06075bae4e81bc70577bf46e4c3148aa2b87b 100644 (file)
 #define TIMER_PRIORITY          1
 
 /*
- * 40 = 24+16
+ * 48 = 32+16
  *
- * 24 for on chip support modules.
+ * 32 for on chip support modules.
  * 16 for external interrupts.
  *
  */
-#define NR_IRQS        40
+#define NR_IRQS        48
 
 extern void disable_irq(unsigned int);
 extern void disable_irq_nosync(unsigned int);
index 7bdb2bd5fa1de1a437db7466c3a8d8a4155e387d..d08cf7863afaa20326a8adbb61cee2ca04fa53cb 100644 (file)
@@ -24,6 +24,8 @@ extern unsigned long mmu_context_cache;
 extern __inline__ void
 get_new_mmu_context(struct mm_struct *mm)
 {
+       extern void flush_tlb_all(void);
+
        unsigned long mc = ++mmu_context_cache;
 
        if (!(mc & MMU_CONTEXT_ASID_MASK)) {
@@ -38,7 +40,7 @@ get_new_mmu_context(struct mm_struct *mm)
        mm->context = mc;
 }
 
-/*P
+/*
  * Get MMU context if needed.
  */
 extern __inline__ void
@@ -53,7 +55,7 @@ get_mmu_context(struct mm_struct *mm)
        }
 }
 
-/*P
+/*
  * Initialize the context related info for a new mm_struct
  * instance.
  */
@@ -63,7 +65,7 @@ extern __inline__ void init_new_context(struct task_struct *tsk,
        mm->context = NO_CONTEXT;
 }
 
-/*P
+/*
  * Destroy context related info for an mm_struct that is about
  * to be put to rest.
  */
@@ -74,18 +76,35 @@ extern __inline__ void destroy_context(struct mm_struct *mm)
 
 /* Other MMU related constants. */
 
+#if defined(__sh3__)
 #define MMU_PTEH       0xFFFFFFF0      /* Page table entry register HIGH */
 #define MMU_PTEL       0xFFFFFFF4      /* Page table entry register LOW */
+#define MMU_TTB                0xFFFFFFF8      /* Translation table base register */
+#define MMU_TEA                0xFFFFFFFC      /* TLB Exception Address */
+
 #define MMUCR          0xFFFFFFE0      /* MMU Control Register */
 
 #define MMU_TLB_ADDRESS_ARRAY 0xF2000000
 #define MMU_PAGE_ASSOC_BIT 0x80
 
 #define MMU_NTLB_ENTRIES       128     /* for 7708 */
-
 #define MMU_CONTROL_INIT 0x007 /* SV=0, TF=1, IX=1, AT=1 */
 
-#include <asm/uaccess.h> /* to get the definition of  __m */
+#elif defined(__SH4__)
+#define MMU_PTEH       0xFF000000      /* Page table entry register HIGH */
+#define MMU_PTEL       0xFF000004      /* Page table entry register LOW */
+#define MMU_TTB                0xFF000008      /* Translation table base register */
+#define MMU_TEA                0xFF00000C      /* TLB Exception Address */
+
+#define MMUCR          0xFF000010      /* MMU Control Register */
+
+#define MMU_ITLB_ADDRESS_ARRAY 0xF2000000
+#define MMU_UTLB_ADDRESS_ARRAY 0xF6000000
+#define MMU_PAGE_ASSOC_BIT 0x80
+
+#define MMU_NTLB_ENTRIES       64      /* for 7750 */
+#define MMU_CONTROL_INIT 0x205 /* SQMD=1, SV=0, TI=1, AT=1 */
+#endif
 
 extern __inline__ void set_asid (unsigned long asid)
 {
@@ -105,7 +124,7 @@ extern __inline__ unsigned long get_asid (void)
        return asid;
 }
 
-/*P
+/*
  * After we have set current->mm to a new value, this activates
  * the context for the new mm so we see the new mappings.
  */
@@ -117,7 +136,6 @@ extern __inline__ void activate_context(struct mm_struct *mm)
 
 /* MMU_TTB can be used for optimizing the fault handling.
    (Currently not used) */
-#define MMU_TTB   0xFFFFFFF8   /* Translation table base register */
 extern __inline__ void switch_mm(struct mm_struct *prev,
                                 struct mm_struct *next,
                                 struct task_struct *tsk, unsigned int cpu)
index 47043e64e57e0bfddcd83b1730610dac25440c5b..582fc77e367139640b2b704317234e30a71e4043 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: namei.h,v 1.1 1996/12/13 14:48:21 jj Exp $
+/* $Id: namei.h,v 1.1 1999/09/18 17:30:11 gniibe Exp $
  * linux/include/asm-sh/namei.h
  *
  * Included from linux/fs/namei.c
index ce6a737f76bcd024a460710fb6271c50ad9217d6..9c8b732b280556fb939713c654b8e9d0433f16a0 100644 (file)
@@ -5,12 +5,12 @@
  * Copyright (C) 1999  Niibe Yutaka
  */
 
-/* XXX 
-   [ P0 (virtual) ]               0x00000000     <------ User space
-   [ P1 (fixed)  write-through]   0x80000000     <------ Kernel space
-   [ P2 (fixed)  non-cachable]    0xA0000000     <------ Physical access
-   [ P3 (virtual) write-back]     0xC0000000     <------ not used
-   [ P4 control   ]               0xE0000000
+/*
+   [ P0/U0 (virtual) ]         0x00000000     <------ User space
+   [ P1 (fixed)   cached ]     0x80000000     <------ Kernel space
+   [ P2 (fixed)  non-cachable] 0xA0000000     <------ Physical access
+   [ P3 (virtual) cached]      0xC0000000     <------ not used
+   [ P4 control   ]            0xE0000000
  */
 
 #include <linux/config.h>
index 1520ea6905e308d0c2b8dec38bdc413807604641..cf5eab380d2b932d8620854e3912a3eb63b20d32 100644 (file)
@@ -3,19 +3,18 @@
 
 /* Copyright (C) 1999 Niibe Yutaka */
 
-#include <linux/config.h>
-
 /*
  * This file contains the functions and defines necessary to modify and use
  * the SuperH page table tree.
  */
 #ifndef __ASSEMBLY__
 #include <asm/processor.h>
+#include <asm/addrspace.h>
 #include <linux/threads.h>
 
 extern pgd_t swapper_pg_dir[1024];
 
-#ifdef CONFIG_CPU_SH3
+#if defined(__sh3__)
 /* Cache flushing:
  *
  *  - flush_cache_all() flushes entire cache
@@ -33,17 +32,17 @@ extern pgd_t swapper_pg_dir[1024];
 #define flush_cache_page(vma, vmaddr)          do { } while (0)
 #define flush_page_to_ram(page)                        do { } while (0)
 #define flush_icache_range(start, end)         do { } while (0)
-#elif CONFIG_CPU_SH4
+#elif defined(__SH4__)
 /*
  *  Caches are broken on SH-4, so we need them.
- *  You do bad job!
  */
-flush_cache_all()
-flush_cache_mm(mm)
-flush_cache_range(mm, start, end)
-flush_cache_page(vma, vmaddr)
-flush_page_to_ram(page)
-flush_icache_range(start, end)
+extern void flush_cache_all(void);
+extern void flush_cache_mm(struct mm_struct *mm);
+extern void flush_cache_range(struct mm_struct *mm, unsigned long start,
+                             unsigned long end);
+extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr);
+extern void flush_page_to_ram(unsigned long page);
+extern void flush_icache_range(unsigned long start, unsigned long end);
 #endif
 
 /* TLB flushing:
@@ -86,9 +85,9 @@ extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
 #define USER_PTRS_PER_PGD      (TASK_SIZE/PGDIR_SIZE)
 
 #ifndef __ASSEMBLY__
-#define VMALLOC_START  0xc0000000
+#define VMALLOC_START  P3SEG
 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
-#define VMALLOC_END    0xe0000000
+#define VMALLOC_END    P4SEG
 
 #define _PAGE_READ     0x001  /* software: read access alowed */
 #define _PAGE_ACCESSED 0x002  /* software: page referenced */
@@ -100,11 +99,17 @@ extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
 /*                     0x080  */
 #define _PAGE_PRESENT  0x100  /* V-bit   : page is valid */
 
+#if defined(__sh3__)
 /* Mask which drop software flags */
-#define _PAGE_FLAGS_HARDWARE_MASK      0xfffff164
+#define _PAGE_FLAGS_HARDWARE_MASK      0x1ffff164
 /* Flags defalult: SZ=1 (4k-byte), C=1 (cachable), SH=0 (not shared) */
 #define _PAGE_FLAGS_HARDWARE_DEFAULT   0x00000018
-
+#elif defined(__SH4__)
+/* Mask which drops software flags */
+#define _PAGE_FLAGS_HARDWARE_MASK      0x1ffff164
+/* Flags defalult: SZ=01 (4k-byte), C=1 (cachable), SH=0 (not shared), WT=0 */
+#define _PAGE_FLAGS_HARDWARE_DEFAULT   0x00000018
+#endif
 
 #define _PAGE_TABLE    (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
 #define _KERNPG_TABLE  (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
index 3087af5d0700d9a4f26cfc9818fd85d211e0d30e..4efcf3fe215c1d7e8478a0f05d83cf70210307b2 100644 (file)
 /*
  *  CPU type and hardware bug flags. Kept separately for each CPU.
  */
+enum cpu_type {
+       CPU_SH7708,             /* Represents 7708, 7708S, 7708R, 7709 */
+       CPU_SH7729,             /* Represents 7709A, 7729 */
+       CPU_SH7750,
+       CPU_SH_NONE
+};
 
 struct sh_cpuinfo {
+       enum cpu_type type;
        unsigned long loops_per_sec;
+
+       char    hard_math;
+
+       /* Not yet used */
        unsigned long *pgd_quick;
        unsigned long *pte_quick;
        unsigned long pgtable_cache_sz;
@@ -30,7 +41,7 @@ struct sh_cpuinfo {
 
 extern struct sh_cpuinfo boot_cpu_data;
 
-#define cpu_data &boot_cpu_data
+#define cpu_data (&boot_cpu_data)
 #define current_cpu_data boot_cpu_data
 
 /*
@@ -43,6 +54,33 @@ extern struct sh_cpuinfo boot_cpu_data;
  */
 #define TASK_UNMAPPED_BASE     (TASK_SIZE / 3)
 
+#define NUM_FPU_REGS   16
+
+struct sh_fpu_hard_struct {
+       unsigned long fp_regs[NUM_FPU_REGS];
+       unsigned long xf_regs[NUM_FPU_REGS];
+       unsigned long fpscr;
+       unsigned long fpul;
+
+       long status; /* software status information */
+};
+
+/* Dummy fpu emulator  */
+struct sh_fpu_soft_struct {
+       unsigned long fp_regs[NUM_FPU_REGS];
+       unsigned long xf_regs[NUM_FPU_REGS];
+       unsigned long fpscr;
+       unsigned long fpul;
+
+       unsigned char   lookahead;
+       unsigned long   entry_pc;
+};
+
+union sh_fpu_union {
+       struct sh_fpu_hard_struct hard;
+       struct sh_fpu_soft_struct soft;
+};
+
 struct thread_struct {
        unsigned long sp;
        unsigned long pc;
@@ -50,6 +88,9 @@ struct thread_struct {
        unsigned long trap_no, error_code;
        unsigned long address;
        /* Hardware debugging registers may come here */
+
+       /* floating point info */
+       union sh_fpu_union fpu;
 };
 
 #define INIT_MMAP \
@@ -59,6 +100,8 @@ struct thread_struct {
        sizeof(init_stack) + (long) &init_stack, /* sp */       \
        0,                                       /* pc */       \
        0, 0, \
+       0, \
+       {{{0,}},} \
 }
 
 /*
@@ -69,7 +112,7 @@ struct thread_struct {
        regs->pr = 0;                            \
        regs->sr = 0;           /* User mode. */ \
        regs->pc = new_pc;                       \
-       regs->u_regs[UREG_SP] = new_sp
+       regs->sp = new_sp
 
 /* Forward declaration, a strange C thing */
 struct task_struct;
@@ -96,6 +139,49 @@ extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 #define release_segments(mm)   do { } while(0)
 #define forget_segments()      do { } while (0)
 
+/*
+ * FPU lazy state save handling..
+ */
+#define SR_FD  0x00008000
+
+extern __inline__ void release_fpu(void)
+{
+       unsigned long __dummy;
+
+       /* Set FD flag in SR */
+       __asm__ __volatile__ ("stc      sr,%0\n\t"
+                             "or       %1,%0\n\t"
+                             "ldc      %0,sr"
+                             : "=&r" (__dummy)
+                             : "r" (SR_FD));
+}
+
+extern __inline__ void grab_fpu(void)
+{
+       unsigned long __dummy;
+
+       /* Clear out FD flag in SR */
+       __asm__ __volatile__ ("stc      sr,%0\n\t"
+                             "and      %1,%0\n\t"
+                             "ldc      %0,sr"
+                             : "=&r" (__dummy)
+                             : "r" (~SR_FD));
+}
+
+extern void save_fpu(struct task_struct *__tsk);
+
+#define unlazy_fpu(tsk) do { \
+       if (tsk->flags & PF_USEDFPU) \
+               save_fpu(tsk); \
+} while (0)
+
+#define clear_fpu(tsk) do { \
+       if (tsk->flags & PF_USEDFPU) { \
+               tsk->flags &= ~PF_USEDFPU; \
+               release_fpu(); \
+       } \
+} while (0)
+
 /*
  * Return saved PC of a blocked thread.
  */
index 3f2da6d2d9541e00df07e5a162bd8f25fe85df43..ad3ab89052672aca859da9d48953daaa4e50db4d 100644 (file)
@@ -2,7 +2,7 @@
 #define __ASM_SH_PTRACE_H
 
 /*
- * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 1999  Niibe Yutaka
  *
  */
 
  */
 struct pt_regs {
        long syscall_nr;
-       unsigned long u_regs[16];
+       unsigned long sr;
+       unsigned long sp;
+       unsigned long regs[15];
        unsigned long gbr;
        unsigned long mach;
        unsigned long macl;
        unsigned long pr;
-       unsigned long sr;
        unsigned long pc;
 };
 
@@ -27,5 +28,4 @@ struct pt_regs {
 extern void show_regs(struct pt_regs *);
 #endif
 
-#define UREG_SP 15
 #endif /* __ASM_SH_PTRACE_H */
index de712bcca024d940c390b76d98f9a412ca4d76fc..c1a77873b5f14770370ae5643cc9181ee7246381 100644 (file)
@@ -5,13 +5,14 @@ struct sigcontext {
        unsigned long   oldmask;
 
        /* CPU registers */
-       unsigned long   u_regs[16];
-       unsigned long gbr;
-       unsigned long mach;
-       unsigned long macl;
-       unsigned long pr;
-       unsigned long sr;
-       unsigned long pc;
+       unsigned long sc_regs[15];
+       unsigned long sc_gbr;
+       unsigned long sc_mach;
+       unsigned long sc_macl;
+       unsigned long sc_pr;
+       unsigned long sc_sp;
+       unsigned long sc_sr;
+       unsigned long sc_pc;
 };
 
 #endif /* __ASM_SH_SIGCONTEXT_H */
index d76c0daf2c1c66345455e2e42b66bc129b140de6..ab466321082b1f6dca1c3016014e2bc58df0c480 100644 (file)
@@ -6,10 +6,6 @@
 /* Avoid too many header ordering problems.  */
 struct siginfo;
 
-#ifdef __KERNEL__
-/* Most things should be clean enough to redefine this at will, if care
-   is taken to make libc match.  */
-
 #define _NSIG          64
 #define _NSIG_BPW      32
 #define _NSIG_WORDS    (_NSIG / _NSIG_BPW)
@@ -20,14 +16,6 @@ typedef struct {
        unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-#define NSIG           32
-typedef unsigned long sigset_t;
-
-#endif /* __KERNEL__ */
-
 #define SIGHUP          1
 #define SIGINT          2
 #define SIGQUIT                 3
diff --git a/include/asm-sh/smp_lock.h b/include/asm-sh/smp_lock.h
deleted file mode 100644 (file)
index dfe8722..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __ASM_SH_SMPLOCK_H
-#define __ASM_SH_SMPLOCK_H
-
-#ifndef __SMP__
-
-#define lock_kernel()                          do { } while(0)
-#define unlock_kernel()                                do { } while(0)
-#define release_kernel_lock(task, cpu, depth)  ((depth) = 1)
-#define reacquire_kernel_lock(task, cpu, depth)        do { } while(0)
-
-#else
-
-#error "We do not support SMP on SH yet"
-
-#endif /* __SMP__ */
-
-#endif /* __ASM_SH_SMPLOCK_H */
diff --git a/include/asm-sh/smplock.h b/include/asm-sh/smplock.h
new file mode 100644 (file)
index 0000000..2949577
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef __ASM_SH_SMPLOCK_H
+#define __ASM_SH_SMPLOCK_H
+
+/*
+ * 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.
+ */
+
+#ifndef __SMP__
+
+#define lock_kernel()                          do { } while(0)
+#define unlock_kernel()                                do { } while(0)
+#define release_kernel_lock(task, cpu, depth)  ((depth) = 1)
+#define reacquire_kernel_lock(task, cpu, depth)        do { } while(0)
+
+#else
+
+#error "We do not support SMP on SH yet"
+/*
+ * Default SMP lock implementation
+ */
+
+#include <linux/interrupt.h>
+#include <asm/spinlock.h>
+
+extern spinlock_t kernel_flag;
+
+/*
+ * Getting the big kernel lock.
+ *
+ * This cannot happen asynchronously,
+ * so we only need to worry about other
+ * CPU's.
+ */
+extern __inline__ void lock_kernel(void)
+{
+       if (!++current->lock_depth)
+               spin_lock(&kernel_flag);
+}
+
+extern __inline__ void unlock_kernel(void)
+{
+       if (--current->lock_depth < 0)
+               spin_unlock(&kernel_flag);
+}
+
+/*
+ * Release global kernel lock and global interrupt lock
+ */
+#define release_kernel_lock(task, cpu) \
+do { \
+       if (task->lock_depth >= 0) \
+               spin_unlock(&kernel_flag); \
+       release_irqlock(cpu); \
+       __sti(); \
+} while (0)
+
+/*
+ * Re-acquire the kernel lock
+ */
+#define reacquire_kernel_lock(task) \
+do { \
+       if (task->lock_depth >= 0) \
+               spin_lock(&kernel_flag); \
+} while (0)
+
+#endif /* __SMP__ */
+
+#endif /* __ASM_SH_SMPLOCK_H */
index c6d2ae97d072c72b14db7bc851ae5f0ddd3d4a4d..67f9b89e5f4773db1afbe016aeede2f924040872 100644 (file)
 #define SO_SECURITY_ENCRYPTION_TRANSPORT       23
 #define SO_SECURITY_ENCRYPTION_NETWORK         24
 
-/* Nasty libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM    1               /* stream (connection) socket   */
-#define SOCK_DGRAM     2               /* datagram (conn.less) socket  */
-#define SOCK_RAW       3               /* raw socket                   */
-#define SOCK_RDM       4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET 5               /* sequential packet socket     */
-#define SOCK_PACKET    10              /* linux specific way of        */
-                                       /* getting packets at the dev   */
-                                       /* level.  For writing rarp and */
-                                       /* other similar things on the  */
-                                       /* user level.                  */
-#endif                                 
+#define SO_BINDTODEVICE        25
+
+/* Socket filtering */
+#define SO_ATTACH_FILTER        26
+#define SO_DETACH_FILTER        27
 
 #endif /* __ASM_SH_SOCKET_H */
index 66b0963a815bb9aa34165ff803af875e3752a899..a1ff593fd310410e520b230ec7d2e5c0ba9eae52 100644 (file)
@@ -13,8 +13,7 @@ extern unsigned int local_bh_count[NR_CPUS];
 #define local_bh_enable()      cpu_bh_enable(smp_processor_id())
 
 #define get_active_bhs()       (bh_mask & bh_active)
-/* XXX */
-#define clear_active_bhs(x)    atomic_clear_mask((x),&bh_active)
+#define clear_active_bhs(x)    atomic_clear_mask((x),(atomic_t *)&bh_active)
 
 extern inline void init_bh(int nr, void (*routine)(void))
 {
index f2e452ca216c73c462696b34e8b1b0e8bb69336d..40c54212f7306252076d877b61f03aa8b746d3c3 100644 (file)
@@ -26,6 +26,7 @@ typedef struct {
  register unsigned long *__ts6 __asm__ ("r6") = &next->thread.sp; \
  register unsigned long __ts7 __asm__ ("r7") = next->thread.pc; \
  __asm__ __volatile__ (".balign 4\n\t" \
+                      "stc.l   gbr,@-r15\n\t" \
                       "sts.l   pr,@-r15\n\t" \
                       "mov.l   r8,@-r15\n\t" \
                       "mov.l   r9,@-r15\n\t" \
@@ -41,11 +42,11 @@ typedef struct {
                       "mov.l   %0,@r2          ! save PC\n\t" \
                       "mov.l   2f,%0\n\t" \
                       "jmp     @%0             ! call __switch_to\n\t" \
-                      " lds    r7,pr           !  with return to new PC\n" \
-                      "2:\n" \
-                      ".long   " "_" "__switch_to\n\t" \
+                      " lds    r7,pr           !  with return to new PC\n\t" \
                       ".balign 4\n"    \
-                      "1:\n" \
+                      "2:\n\t" \
+                      ".long   " "_" "__switch_to\n" \
+                      "1:\n\t" \
                       "mov.l   @r15+,%0        ! pop R0 from new stack\n\t" \
                       "mov.l   @r15+,r14\n\t" \
                       "mov.l   @r15+,r13\n\t" \
@@ -55,6 +56,7 @@ typedef struct {
                       "mov.l   @r15+,r9\n\t" \
                       "mov.l   @r15+,r8\n\t" \
                       "lds.l   @r15+,pr\n\t" \
+                      "ldc.l   @r15+,gbr\n\t" \
                       :"=&z" (__last) \
                       :"0" (prev), \
                        "r" (__ts1), "r" (__ts2), \
@@ -84,6 +86,9 @@ extern void __xchg_called_with_bad_pointer(void);
 #define mb()   __asm__ __volatile__ ("": : :"memory")
 #define rmb()  mb()
 #define wmb()  __asm__ __volatile__ ("": : :"memory")
+#define set_rmb(var, value) do { xchg(&var, value); } while (0)
+#define set_mb(var, value) set_rmb(var, value)
+#define set_wmb(var, value) do { var = value; wmb(); } while (0)
 
 /* Interrupt Control */
 extern __inline__ void __sti(void)
@@ -164,7 +169,7 @@ extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
        return retval;
 }
 
-static __inline__ unsigned long __xchg(unsigned long x, void * ptr, int size)
+static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
 {
        switch (size) {
        case 4:
index da16fd45cf0db7ba7c8a326ac492ee3b48941636..20e70f1395286c92047aec5c3e5f7becd126a55c 100644 (file)
@@ -117,10 +117,21 @@ struct termios {
 #define HUPCL  0002000
 #define CLOCAL 0004000
 #define CBAUDEX 0010000
-#define  B57600  0010001
-#define  B115200 0010002
-#define  B230400 0010003
-#define  B460800 0010004
+#define    B57600 0010001
+#define   B115200 0010002
+#define   B230400 0010003
+#define   B460800 0010004
+#define   B500000 0010005
+#define   B576000 0010006
+#define   B921600 0010007
+#define  B1000000 0010010
+#define  B1152000 0010011
+#define  B1500000 0010012
+#define  B2000000 0010013
+#define  B2500000 0010014
+#define  B3000000 0010015
+#define  B3500000 0010016
+#define  B4000000 0010017
 #define CIBAUD   002003600000  /* input baud rate (not used) */
 #define CMSPAR   010000000000          /* mark or space (stick) parity */
 #define CRTSCTS          020000000000          /* flow control */
index e3fada6443c1d90e496a90921ae027acaed502a3..f579c57a6417ed0a16bdd371944152f426c2b3a9 100644 (file)
@@ -47,7 +47,12 @@ struct termio {
 #define N_AX25         5
 #define N_X25          6       /* X.25 async */
 #define N_6PACK                7
-#define N_MASC         8       /* Reserved fo Mobitex module <kaz@cafe.net> */
+#define N_MASC         8       /* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964                9       /* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL 10      /* Reserved for Profibus <Dave@mvhi.com> */
+#define N_IRDA         11      /* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_SMSBLOCK     12      /* SMS block mode - for talking to GSM data cards about SMS messages */
+#define N_HDLC         13      /* synchronous HDLC */
 
 #ifdef __KERNEL__
 
index d23eeb74f6cb403b86890b0531e7434634a5aba6..2782ac29590e3e04158be3709c0d31a22ca65226 100644 (file)
@@ -27,16 +27,16 @@ typedef unsigned long long __u64;
  */
 #ifdef __KERNEL__
 
-typedef signed char s8;
+typedef __signed__ char s8;
 typedef unsigned char u8;
 
-typedef signed short s16;
+typedef __signed__ short s16;
 typedef unsigned short u16;
 
-typedef signed int s32;
+typedef __signed__ int s32;
 typedef unsigned int u32;
 
-typedef signed long long s64;
+typedef __signed__ long long s64;
 typedef unsigned long long u64;
 
 #define BITS_PER_LONG 32
index 37da013315730bb730914e3f8d5e9310ee8134a9..4d888da0aff77822df4dfe493f6be4631ac2dc49 100644 (file)
@@ -1,7 +1,8 @@
-/*
+/* $Id: uaccess.h,v 1.3 1999/10/12 14:46:20 gniibe Exp $
+ *
  * User space memory access functions
  *
- * Copyright (C) 1999 Niibe Yutaka
+ * Copyright (C) 1999  Niibe Yutaka
  *
  *  Based on:
  *     MIPS implementation version 1.15 by
@@ -48,7 +49,7 @@
        unsigned long flag,sum; \
        __asm__("clrt; addc %3,%1; movt %0; cmp/hi %4,%1; rotcl %0" \
                :"=&r" (flag), "=r" (sum) \
-               :"1" (addr), "r" (size), "r" (current->addr_limit.seg)); \
+               :"1" (addr), "r" ((int)(size)), "r" (current->addr_limit.seg)); \
        flag; })
 
 #define access_ok(type,addr,size) (__range_ok(addr,size) == 0)
@@ -229,11 +230,11 @@ __copy_user(void *__to, const void *__from, __kernel_size_t __n)
                "mov.l  5f,%1\n\t"
                "jmp    @%1\n\t"
                " mov   %7,%0\n\t"
-               ".align 4\n"
+               ".balign 4\n"
                "5:     .long 2b\n"
                ".previous\n"
                ".section __ex_table,\"a\"\n"
-               "       .align 4\n"
+               "       .balign 4\n"
                "       .long 9b,3b\n"
                "       .long 1b,2b\n"
                ".previous"
@@ -313,11 +314,11 @@ __clear_user(void *addr, __kernel_size_t size)
                "mov.l  4f,%0\n\t"
                "jmp    @%0\n\t"
                " mov   %7,%0\n"
-               ".align 4\n"
+               ".balign 4\n"
                "4:     .long 2b\n"
                ".previous\n"
                ".section __ex_table,\"a\"\n"
-               "       .align 4\n"
+               "       .balign 4\n"
                "       .long 1b,3b\n"
                ".previous"
                : "=&r" (res), "=&r" (__a), "=&r" (__s)
@@ -356,11 +357,11 @@ __strncpy_from_user(unsigned long __dest, unsigned long __src, int __count)
                "mov.l  4f,%1\n\t"
                "jmp    @%1\n\t"
                " mov   %8,%0\n\t"
-               ".align 4\n"
+               ".balign 4\n"
                "4:     .long 2b\n"
                ".previous\n"
                ".section __ex_table,\"a\"\n"
-               "       .align 4\n"
+               "       .balign 4\n"
                "       .long 9b,3b\n"
                "       .long 1b,2b\n"
                ".previous"
@@ -380,46 +381,51 @@ if(__access_ok(__sfu_src, __sfu_count)) { \
 __sfu_res = __strncpy_from_user((unsigned long) (dest), __sfu_src, __sfu_count); \
 } __sfu_res; })
 
+#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
+
 /*
  * Return the size of a string (including the ending 0!)
  */
-extern __inline__ long __strlen_user(const char *__s)
+extern __inline__ long __strnlen_user(const char *__s, long __n)
 {
        unsigned long res;
        unsigned long __dummy;
 
        __asm__ __volatile__(
                "mov    #-1,%1\n"
-               "9:\n"
+               "9:\n\t"
+               "cmp/eq %4,%0\n\t"
+               "bt     5f\n\t"
                "cmp/eq #0,%1\n\t"
                "bf/s   9b\n\t"
                "1:\t"
                " mov.b @%0+,%1\n\t"
+               "5:\t"
                "sub    %3,%0\n"
                "2:\n"
                ".section .fixup,\"ax\"\n"
                "3:\n\t"
                "mov.l  4f,%1\n\t"
                "jmp    @%1\n\t"
-               " mov   %4,%0\n"
-               ".align 4\n"
+               " mov   %5,%0\n"
+               ".balign 4\n"
                "4:     .long 2b\n"
                ".previous\n"
                ".section __ex_table,\"a\"\n"
-               "       .align 4\n"
+               "       .balign 4\n"
                "       .long 1b,3b\n"
                ".previous"
                : "=&r" (res), "=&z" (__dummy)
-               : "0" (__s), "r" (__s), "i" (-EFAULT));
+               : "0" (__s), "r" (__s), "r" (__s+__n), "i" (-EFAULT));
        return res;
 }
 
-extern __inline__ long strlen_user(const char *s)
+extern __inline__ long strnlen_user(const char *s, long n)
 {
-       if(!access_ok(VERIFY_READ, s, 0))
+       if(!access_ok(VERIFY_READ, s, n))
                return 0;
        else
-               return __strlen_user(s);
+               return __strnlen_user(s, n);
 }
 
 struct exception_table_entry
index aeb6d8715bd39da00f18f9ad0f8553732c50dd0a..c416fda37c2efd9c2daa7eb904d1ce1678d14309 100644 (file)
@@ -222,7 +222,8 @@ type name(void) \
 register long __sc0 __asm__ ("r0") = __NR_##name; \
 __asm__ __volatile__ ("trapa   #0" \
        : "=z" (__sc0) \
-       : "0" (__sc0)); \
+       : "0" (__sc0) \
+       : "memory" ); \
 __syscall_return(type,__sc0); \
 }
 
@@ -233,7 +234,8 @@ register long __sc0 __asm__ ("r0") = __NR_##name; \
 register long __sc4 __asm__ ("r4") = (long) arg1; \
 __asm__ __volatile__ ("trapa   #0" \
        : "=z" (__sc0) \
-       : "0" (__sc0), "r" (__sc4)); \
+       : "0" (__sc0), "r" (__sc4) \
+       : "memory"); \
 __syscall_return(type,__sc0); \
 }
 
@@ -245,7 +247,8 @@ register long __sc4 __asm__ ("r4") = (long) arg1; \
 register long __sc5 __asm__ ("r5") = (long) arg2; \
 __asm__ __volatile__ ("trapa   #0" \
        : "=z" (__sc0) \
-       : "0" (__sc0), "r" (__sc4), "r" (__sc5)); \
+       : "0" (__sc0), "r" (__sc4), "r" (__sc5) \
+       : "memory"); \
 __syscall_return(type,__sc0); \
 }
 
@@ -258,7 +261,8 @@ register long __sc5 __asm__ ("r5") = (long) arg2; \
 register long __sc6 __asm__ ("r6") = (long) arg3; \
 __asm__ __volatile__ ("trapa   #0" \
        : "=z" (__sc0) \
-       : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6)); \
+       : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6) \
+       : "memory"); \
 __syscall_return(type,__sc0); \
 }
 
@@ -273,7 +277,8 @@ register long __sc6 __asm__ ("r7") = (long) arg4; \
 __asm__ __volatile__ ("trapa   #0" \
        : "=z" (__sc0) \
        : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6),  \
-         "r" (__sc7)); \
+         "r" (__sc7) \
+       : "memory" ); \
 __syscall_return(type,__sc0); \
 }
 
index bf37966920460249792915685dd5e0a96a3fec19..4e4a4904449b2c2a72a86d9baf0e79fc7c38fab0 100644 (file)
@@ -673,6 +673,8 @@ struct cdrom_device_info {
 /* per-device flags */
         __u8 sanyo_slot                : 2;    /* Sanyo 3 CD changer support */
         __u8 reserved          : 6;    /* not used yet */
+       __u32 packet_size;              /* write out this number of packets */
+       __u32 nwa;                      /* next writeable address */
 };
 
 struct cdrom_device_ops {
@@ -760,8 +762,6 @@ typedef struct {
         __u8 uru                       : 1;
         __u8 dbc_v                     : 1;
        __u8 did_v                      : 1;
-#else
-#error "Please fix <asm/byteorder.h>"
 #endif
        __u8 disc_type;
        __u8 n_sessions_msb;
@@ -806,8 +806,6 @@ typedef struct {
        __u8 nwa_v                      : 1;
        __u8 lra_v                      : 1;
        __u8 reserved3                  : 6;
-#else
-#error "Please fix <asm/byteorder.h>"
 #endif
        __u32 track_start;
        __u32 next_writable;
@@ -835,15 +833,12 @@ struct cdrom_mechstat_header {
        __u8 reserved1     : 4;
        __u8 door_open     : 1;
        __u8 mech_state    : 3;
-#else
-#error "Please fix <asm/byteorder.h>"
 #endif
        __u8     curlba[3];
        __u8     nslots;
        __u8 short slot_tablelen;
 };
 
-
 struct cdrom_slot {
 #if defined(__BIG_ENDIAN_BITFIELD)
        __u8 disc_present : 1;
@@ -853,8 +848,6 @@ struct cdrom_slot {
        __u8 change       : 1;
        __u8 reserved1    : 6;
        __u8 disc_present : 1;
-#else
-#error "Please fix <asm/byteorder.h>"
 #endif
        __u8 reserved2[3];
 };
@@ -872,6 +865,71 @@ typedef enum {
        mechtype_cartridge_changer  = 5
 } mechtype_t;
 
+struct mode_page_header {
+       __u16 mode_data_length;
+       __u8 medium_type;
+       __u8 reserved1;
+       __u8 reserved2;
+       __u8 reserved3;
+       __u16 desc_length;
+};
+
+typedef struct {
+       struct mode_page_header header;
+#if defined(__BIG_ENDIAN_BITFIELD)
+       __u8 ps                 : 1;
+       __u8 reserved1          : 1;
+       __u8 page_code          : 6;
+        __u8 page_length;
+       __u8 reserved2          : 1;
+       __u8 bufe               : 1;
+       __u8 ls_v               : 1;
+       __u8 test_write         : 1;
+        __u8 write_type                : 4;
+       __u8 multi_session      : 2; /* or border, DVD */
+       __u8 fp                 : 1;
+       __u8 copy               : 1;
+       __u8 track_mode         : 4;
+       __u8 reserved3          : 4;
+       __u8 data_block_type    : 4;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+       __u8 page_code          : 6;
+       __u8 reserved1          : 1;
+       __u8 ps                 : 1;
+        __u8 page_length;
+        __u8 write_type                : 4;
+       __u8 test_write         : 1;
+       __u8 ls_v               : 1;
+       __u8 bufe               : 1;
+       __u8 reserved2          : 1;
+       __u8 track_mode         : 4;
+       __u8 copy               : 1;
+       __u8 fp                 : 1;
+       __u8 multi_session      : 2; /* or border, DVD */
+       __u8 data_block_type    : 4;
+       __u8 reserved3          : 4;
+#endif
+       __u8 link_size;
+       __u8 reserved4;
+#if defined(__BIG_ENDIAN_BITFIELD)
+       __u8 reserved5          : 2;
+       __u8 app_code           : 6;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+       __u8 app_code           : 6;
+       __u8 reserved5          : 2;
+#endif
+       __u8 session_format;
+       __u8 reserved6;
+       __u32 packet_size;
+       __u16 audio_pause;
+       __u8 mcn[16];
+       __u8 isrc[16];
+       __u8 subhdr0;
+       __u8 subhdr1;
+       __u8 subhdr2;
+       __u8 subhdr3;
+} write_param_page __attribute__((packed));
+
 #endif  /* End of kernel only stuff */ 
 
 #endif  /* _LINUX_CDROM_H */
index 47e954a8e86358668a467b37143cb87812eac7fc..c3dfc01a5c4244ef702d1da30d6f4c97b047c873 100644 (file)
@@ -886,7 +886,14 @@ extern struct dentry * __namei(const char *, unsigned int);
 extern void iput(struct inode *);
 extern struct inode * igrab(struct inode *);
 extern ino_t iunique(struct super_block *, ino_t);
-extern struct inode * iget(struct super_block *, unsigned long);
+
+typedef int (*find_inode_t)(struct inode *, unsigned long, void *);
+extern struct inode * iget4(struct super_block *, unsigned long, find_inode_t, void *);
+static inline struct inode *iget(struct super_block *sb, unsigned long ino)
+{
+       return iget4(sb, ino, NULL, NULL);
+}
+
 extern void clear_inode(struct inode *);
 extern struct inode * get_empty_inode(void);
 
index 2fee75fec10e989afce6af7c27026de6d5b6428f..df52d3ca9724b48ff2d4cb627a3fa4cfd43afdfa 100644 (file)
@@ -81,6 +81,8 @@
 #define WIN_SRST               0x08    /* ATAPI soft reset command */
 #define WIN_PACKETCMD          0xa0    /* Send a packet command. */
 
+#define EXABYTE_ENABLE_NEST    0xf0
+
 /* WIN_SMART sub-commands */
 
 #define SMART_READ_VALUES      0xd0
index 3ebe6c211bdded933392cd0f4f29421d7af3377d..4af0cd2533c236f5e7451f5dcc3cec33de0713de 100644 (file)
@@ -236,6 +236,7 @@ typedef struct ide_drive_s {
        unsigned long sleep;            /* sleep until this time */
        unsigned long service_start;    /* time we started last request */
        unsigned long service_time;     /* service time of last request */
+       unsigned long timeout;          /* max time to wait for irq */
        special_t       special;        /* special action flags */
        byte     keep_settings;         /* restore settings after drive reset */
        byte     using_dma;             /* disk is using dma for read/write */
@@ -338,6 +339,7 @@ typedef void (ide_tuneproc_t)(ide_drive_t *, byte);
  * This is used to provide support for strange interfaces
  */
 typedef void (ide_selectproc_t) (ide_drive_t *);
+typedef void (ide_resetproc_t) (ide_drive_t *);
 
 /*
  * hwif_chipset_t is used to keep track of the specific hardware
@@ -367,6 +369,7 @@ typedef struct hwif_s {
        struct gendisk  *gd;            /* gendisk structure */
        ide_tuneproc_t  *tuneproc;      /* routine to tune PIO mode for drives */
        ide_selectproc_t *selectproc;   /* tweaks hardware to select drive */
+       ide_resetproc_t *resetproc;     /* routine to reset controller after a disk reset */
        ide_dmaproc_t   *dmaproc;       /* dma read/write/abort routine */
        unsigned long   *dmatable;      /* dma physical region descriptor table */
        struct hwif_s   *mate;          /* other hwif from same PCI chip */
@@ -581,7 +584,7 @@ void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecoun
  * This is used on exit from the driver, to designate the next irq handler
  * and also to start the safety timer.
  */
-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);
 
 /*
  * Error reporting, in human readable form (luxurious, but a memory hog).
index 738191adcdd0703cc65d91950b0b878f1b0e1813..c6df59665c959ac1d8899ed47a95e87845e6ee07 100644 (file)
@@ -427,6 +427,12 @@ extern struct vm_area_struct *find_extend_vma(struct task_struct *tsk, unsigned
 #define pgcache_under_min()    (atomic_read(&page_cache_size) * 100 < \
                                page_cache.min_percent * num_physpages)
 
+#define vmlist_access_lock(mm)         spin_lock(&mm->page_table_lock)
+#define vmlist_access_unlock(mm)       spin_unlock(&mm->page_table_lock)
+#define vmlist_modify_lock(mm)         vmlist_access_lock(mm)
+#define vmlist_modify_unlock(mm)       vmlist_access_unlock(mm)
+
+
 #endif /* __KERNEL__ */
 
 #endif
index 4f7d3230e1c6d84c38845a6a0aa1b5b5fd551f14..c188fc8083e972e33c045803817872cf6ef3eb48 100644 (file)
@@ -122,15 +122,6 @@ struct nfs_fattr {
        struct nfs_time         ctime;
 };
 
-struct nfs_sattr {
-       __u32                   mode;
-       __u32                   uid;
-       __u32                   gid;
-       __u32                   size;
-       struct nfs_time         atime;
-       struct nfs_time         mtime;
-};
-
 struct nfs_fsinfo {
        __u32                   tsize;
        __u32                   bsize;
@@ -150,7 +141,7 @@ struct nfs_writeargs {
 
 struct nfs_sattrargs {
        struct nfs_fh *         fh;
-       struct nfs_sattr *      sattr;
+       struct iattr *          sattr;
 };
 
 struct nfs_diropargs {
@@ -173,7 +164,7 @@ struct nfs_readargs {
 struct nfs_createargs {
        struct nfs_fh *         fh;
        const char *            name;
-       struct nfs_sattr *      sattr;
+       struct iattr *          sattr;
 };
 
 struct nfs_renameargs {
@@ -193,7 +184,7 @@ struct nfs_symlinkargs {
        struct nfs_fh *         fromfh;
        const char *            fromname;
        const char *            topath;
-       struct nfs_sattr *      sattr;
+       struct iattr *          sattr;
 };
 
 struct nfs_readdirargs {
index d91a0b6410f427e052a60a228bc54b96ab6f5cb8..df6b7c8df36fe21f4477dcf2b78eff1786ff0fc1 100644 (file)
@@ -77,11 +77,14 @@ do { \
                               : NFS_SERVER(inode)->acregmax)
 
 #define NFS_FLAGS(inode)               ((inode)->u.nfs_i.flags)
-#define NFS_REVALIDATING(inode)                (NFS_FLAGS(inode) & NFS_INO_REVALIDATE)
+#define NFS_REVALIDATING(inode)                (NFS_FLAGS(inode) & NFS_INO_REVALIDATING)
 #define NFS_WRITEBACK(inode)           ((inode)->u.nfs_i.writeback)
 #define NFS_COOKIES(inode)             ((inode)->u.nfs_i.cookies)
 #define NFS_DIREOF(inode)              ((inode)->u.nfs_i.direof)
 
+#define NFS_FILEID(inode)              ((inode)->u.nfs_i.fileid)
+#define NFS_FSID(inode)                        ((inode)->u.nfs_i.fsid)
+
 /*
  * These are the default flags for swap requests
  */
@@ -137,7 +140,7 @@ struct nfs_wreq {
 extern int nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
                        struct nfs_fattr *fattr);
 extern int nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle,
-                       struct nfs_sattr *sattr, struct nfs_fattr *fattr);
+                       struct nfs_fattr *fattr, struct iattr *sattr);
 extern int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir,
                        const char *name, struct nfs_fh *fhandle,
                        struct nfs_fattr *fattr);
@@ -148,7 +151,7 @@ extern int nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle,
                        int swap, unsigned long offset, unsigned int count,
                        const void *buffer, struct nfs_fattr *fattr);
 extern int nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir,
-                       const char *name, struct nfs_sattr *sattr,
+                       const char *name, struct iattr *sattr,
                        struct nfs_fh *fhandle, struct nfs_fattr *fattr);
 extern int nfs_proc_remove(struct nfs_server *server, struct nfs_fh *dir,
                        const char *name);
@@ -159,9 +162,9 @@ extern int nfs_proc_link(struct nfs_server *server, struct nfs_fh *fhandle,
                        struct nfs_fh *dir, const char *name);
 extern int nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir,
                        const char *name, const char *path,
-                       struct nfs_sattr *sattr);
+                       struct iattr *sattr);
 extern int nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir,
-                       const char *name, struct nfs_sattr *sattr,
+                       const char *name, struct iattr *sattr,
                        struct nfs_fh *fhandle, struct nfs_fattr *fattr);
 extern int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir,
                        const char *name);
@@ -174,13 +177,14 @@ extern int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
  */
 extern struct super_block *nfs_read_super(struct super_block *, void *, int);
 extern int init_nfs_fs(void);
+extern void nfs_zap_caches(struct inode *);
 extern struct inode *nfs_fhget(struct dentry *, struct nfs_fh *,
                                struct nfs_fattr *);
 extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
 extern int nfs_revalidate(struct dentry *);
 extern int nfs_open(struct inode *, struct file *);
 extern int nfs_release(struct inode *, struct file *);
-extern int _nfs_revalidate_inode(struct nfs_server *, struct dentry *);
+extern int __nfs_revalidate_inode(struct nfs_server *, struct dentry *);
 
 /*
  * linux/fs/nfs/file.c
@@ -244,9 +248,9 @@ static inline int
 nfs_revalidate_inode(struct nfs_server *server, struct dentry *dentry)
 {
        struct inode *inode = dentry->d_inode;
-       if (jiffies - NFS_READTIME(inode) < NFS_ATTRTIMEO(inode))
+       if (time_before(jiffies, NFS_READTIME(inode)+NFS_ATTRTIMEO(inode)))
                return 0;
-       return _nfs_revalidate_inode(server, dentry);
+       return __nfs_revalidate_inode(server, dentry);
 }
 
 /* NFS root */
index 13bf610b6389563a4cc1744b0c61dca5f63bcefb..22681be9db4782f652512c7e90d8d692a73f275c 100644 (file)
@@ -8,6 +8,12 @@
  * nfs fs inode data in memory
  */
 struct nfs_inode_info {
+       /*
+        * The 64bit 'inode number'
+        */
+       __u32 fsid;
+       __u32 fileid;
+
        /*
         * Various flags
         */
@@ -49,7 +55,7 @@ struct nfs_inode_info {
 /*
  * Legal inode flag values
  */
-#define NFS_INO_REVALIDATE     0x0001          /* revalidating attrs */
+#define NFS_INO_REVALIDATING   0x0001          /* revalidating attrs */
 #define NFS_IS_SNAPSHOT                0x0010          /* a snapshot file */
 
 /*
index d863aaefefec9bcecdcc18bd913b39cc9777ac1b..35f730151820191d8ad4a4d1d75571306cedb678 100644 (file)
@@ -550,6 +550,7 @@ extern inline int proc_driver_register(const char *module_name)
         return 0;
 }
 
+extern struct proc_dir_entry proc_root;
 
 #endif /* CONFIG_PROC_FS */
 
index a27fb199ab8a8fe9f80fc286242d43099db0aa65..dd5dcf2c8b4cf934b2f0e85dad34ce5ab34ee919 100644 (file)
@@ -357,6 +357,10 @@ struct task_struct {
        struct signal_queue *sigqueue, **sigqueue_tail;
        unsigned long sas_ss_sp;
        size_t sas_ss_size;
+       
+/* Thread group tracking */
+       u32 parent_exec_id;
+       u32 self_exec_id;
 };
 
 /*
@@ -422,6 +426,7 @@ struct task_struct {
 /* files */    &init_files, \
 /* mm */       NULL, &init_mm, \
 /* signals */  SPIN_LOCK_UNLOCKED, &init_signals, {{0}}, {{0}}, NULL, &init_task.sigqueue, 0, 0, \
+/* exec cts */ 0,0,0, \
 }
 
 #ifndef INIT_TASK_SIZE
index cf9cab74915adb09cbabfd75c26ddf2cb7996031..5168218e00e3d1b7671b9872ae588125ac45a163 100644 (file)
@@ -384,7 +384,6 @@ extern int sysv_new_block(struct super_block * sb);
 extern void sysv_free_block(struct super_block * sb, unsigned int block);
 extern unsigned long sysv_count_free_blocks(struct super_block *sb);
 
-extern struct buffer_head * sysv_getblk(struct inode *, unsigned int, int);
 extern int sysv_get_block(struct inode *, long, struct buffer_head *, int);
 extern struct buffer_head * sysv_file_bread(struct inode *, int, int);
 
index 4d4dbf7ce2a590e7d3dbacc4efcde3b95ec3bf85..0fb977fbdde808b141a94e62d952c07006c99aab 100644 (file)
@@ -137,6 +137,7 @@ extern struct linux_mib     net_statistics;
 
 extern int sysctl_local_port_range[2];
 
+#ifdef CONFIG_INET
 extern __inline__ int ip_send(struct sk_buff *skb)
 {
        if (skb->len > skb->dst->pmtu)
@@ -181,6 +182,7 @@ extern __inline__ void ip_eth_mc_map(u32 addr, char *buf)
        buf[3]=addr&0x7F;
 }
 
+#endif
 
 extern int     ip_call_ra_chain(struct sk_buff *skb);
 
index fd1bfa17bd70853e9890d5c138abcb5393eecb86..f0d17e56c5348bbeff4baa04cf366d77809c2f89 100644 (file)
@@ -56,6 +56,10 @@ extern void nubus_init(void);
 #include <linux/isapnp.h>
 #endif
 
+#ifdef CONFIG_IRDA
+#include <net/irda/irda_device.h>
+#endif
+
 /*
  * Versions of gcc older than that listed below may actually compile
  * and link okay, but the end product can have subtle run time bugs.
index ca9275af18f6e8a7539a000a5fdca12dceaed215..71a2b4eb779c854e2e64eda9eaecc558ea21a25a 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -462,8 +462,10 @@ static int shm_map (struct vm_area_struct *shmd)
           > (unsigned long) current->rlim[RLIMIT_AS].rlim_cur)
                return -ENOMEM;
        current->mm->total_vm += tmp >> PAGE_SHIFT;
+       vmlist_modify_lock(current->mm);
        insert_vm_struct(current->mm, shmd);
        merge_segments(current->mm, shmd->vm_start, shmd->vm_end);
+       vmlist_modify_unlock(current->mm);
 
        return 0;
 }
index 6b5ed0487d04d67628b983dcbe81bd185b51c412..85d042adaae682ec35dd943d441a9886bf33ce61 100644 (file)
@@ -135,7 +135,9 @@ static inline void forget_original_parent(struct task_struct * father)
        read_lock(&tasklist_lock);
        for_each_task(p) {
                if (p->p_opptr == father) {
+                       /* We dont want people slaying init */
                        p->exit_signal = SIGCHLD;
+                       p->self_exec_id++;
                        p->p_opptr = child_reaper; /* init */
                        if (p->pdeath_signal) send_sig(p->pdeath_signal, p, 0);
                }
@@ -288,7 +290,7 @@ void exit_mm(struct task_struct *tsk)
  */
 static void exit_notify(void)
 {
-       struct task_struct * p;
+       struct task_struct * p, *t;
 
        forget_original_parent(current);
        /*
@@ -300,15 +302,39 @@ static void exit_notify(void)
         * and we were the only connection outside, so our pgrp
         * is about to become orphaned.
         */
-       if ((current->p_pptr->pgrp != current->pgrp) &&
-           (current->p_pptr->session == current->session) &&
+        
+       t = current->p_pptr;
+       
+       if ((t->pgrp != current->pgrp) &&
+           (t->session == current->session) &&
            will_become_orphaned_pgrp(current->pgrp, current) &&
            has_stopped_jobs(current->pgrp)) {
                kill_pg(current->pgrp,SIGHUP,1);
                kill_pg(current->pgrp,SIGCONT,1);
        }
 
-       /* Let father know we died */
+       /* Let father know we died 
+        *
+        * Thread signals are configurable, but you aren't going to use
+        * that to send signals to arbitary processes. 
+        * That stops right now.
+        *
+        * If the parent exec id doesn't match the exec id we saved
+        * when we started then we know the parent has changed security
+        * domain.
+        *
+        * If our self_exec id doesn't match our parent_exec_id then
+        * we have changed execution domain as these two values started
+        * the same after a fork.
+        *      
+        */
+       
+       if(current->exit_signal != SIGCHLD &&
+           ( current->parent_exec_id != t->self_exec_id  ||
+             current->self_exec_id != current->parent_exec_id) 
+           && !capable(CAP_KILL))
+               current->exit_signal = SIGCHLD;
+
        notify_parent(current, current->exit_signal);
 
        /*
index e341615f2c022350cfaf5574ba7cd79d53688427..37794d726ee3c8a06fbd99aa27c5db0b94e1528e 100644 (file)
@@ -19,8 +19,8 @@
 #include <linux/vmalloc.h>
 
 #include <asm/pgtable.h>
-#include <asm/mmu_context.h>
 #include <asm/uaccess.h>
+#include <asm/mmu_context.h>
 
 /* The idle threads do not count.. */
 int nr_threads=0;
@@ -693,6 +693,11 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs)
        if (retval)
                goto bad_fork_cleanup_sighand;
        p->semundo = NULL;
+       
+       /* Our parent execution domain becomes current domain
+          These must match for thread signalling to apply */
+          
+       p->parent_exec_id = p->self_exec_id;
 
        /* ok, now we should be set up.. */
        p->swappable = 1;
index 5c4d369ec744c806a1140c72ac8b1b0e52006219..2a0dcb85d34471b924dd2ff2f926c1b8148df282 100644 (file)
@@ -125,7 +125,7 @@ EXPORT_SYMBOL(getname);
 EXPORT_SYMBOL(_fput);
 EXPORT_SYMBOL(igrab);
 EXPORT_SYMBOL(iunique);
-EXPORT_SYMBOL(iget);
+EXPORT_SYMBOL(iget4);
 EXPORT_SYMBOL(iput);
 EXPORT_SYMBOL(__namei);
 EXPORT_SYMBOL(lookup_dentry);
index 35fa9768d4546313a9b6bdfa9116f7413cc5ef19..4327f9d1e1a5f35538b81d75809fb4a557d067b7 100644 (file)
@@ -80,12 +80,14 @@ bad_pmd:
 int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
 {
        int copied;
-       struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
-       if (!vma)
-               return 0;
+       struct vm_area_struct * vma;
 
        down(&tsk->mm->mmap_sem);
+       vma = find_extend_vma(tsk, addr);
+       if (!vma) {
+               up(&tsk->mm->mmap_sem);
+               return 0;
+       }
        copied = 0;
        for (;;) {
                unsigned long offset = addr & ~PAGE_MASK;
index 1517d6d9d10c55c1a334a1fb8cc2d29d42497b40..3585e1cc883d9c7a1c22d408f0b3a92f5b30f53c 100644 (file)
@@ -54,6 +54,10 @@ void get_fast_time(struct timeval * t)
        do_get_fast_time(t);
 }
 
+/* The xtime_lock is not only serializing the xtime read/writes but it's also
+   serializing all accesses to the global NTP variables now. */
+extern rwlock_t xtime_lock;
+
 #if !defined(__alpha__) && !defined(__ia64__)
 
 /*
@@ -93,14 +97,14 @@ asmlinkage long sys_stime(int * tptr)
                return -EPERM;
        if (get_user(value, tptr))
                return -EFAULT;
-       cli();
+       write_lock_irq(&xtime_lock);
        xtime.tv_sec = value;
        xtime.tv_usec = 0;
        time_adjust = 0;        /* stop active adjtime() */
        time_status |= STA_UNSYNC;
        time_maxerror = NTP_PHASE_LIMIT;
        time_esterror = NTP_PHASE_LIMIT;
-       sti();
+       write_unlock_irq(&xtime_lock);
        return 0;
 }
 
@@ -139,9 +143,9 @@ asmlinkage long sys_gettimeofday(struct timeval *tv, struct timezone *tz)
  */
 inline static void warp_clock(void)
 {
-       cli();
+       write_lock_irq(&xtime_lock);
        xtime.tv_sec += sys_tz.tz_minuteswest * 60;
-       sti();
+       write_unlock_irq(&xtime_lock);
 }
 
 /*
@@ -222,7 +226,7 @@ void (*hardpps_ptr)(struct timeval *) = (void (*)(struct timeval *))0;
 int do_adjtimex(struct timex *txc)
 {
         long ltemp, mtemp, save_adjust;
-       int result = time_state;        /* mostly `TIME_OK' */
+       int result;
 
        /* In order to modify anything, you gotta be super-user! */
        if (txc->modes && !capable(CAP_SYS_TIME))
@@ -240,7 +244,8 @@ int do_adjtimex(struct timex *txc)
                if (txc->tick < 900000/HZ || txc->tick > 1100000/HZ)
                        return -EINVAL;
 
-       cli(); /* SMP: global cli() is enough protection. */
+       write_lock_irq(&xtime_lock);
+       result = time_state;    /* mostly `TIME_OK' */
 
        /* Save for later - semantics of adjtime is to return old value */
        save_adjust = time_adjust;
@@ -385,7 +390,6 @@ leave:      if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0
        txc->constant      = time_constant;
        txc->precision     = time_precision;
        txc->tolerance     = time_tolerance;
-       do_gettimeofday(&txc->time);
        txc->tick          = tick;
        txc->ppsfreq       = pps_freq;
        txc->jitter        = pps_jitter >> PPS_AVG;
@@ -395,8 +399,8 @@ leave:      if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0
        txc->calcnt        = pps_calcnt;
        txc->errcnt        = pps_errcnt;
        txc->stbcnt        = pps_stbcnt;
-
-       sti();
+       write_unlock_irq(&xtime_lock);
+       do_gettimeofday(&txc->time);
        return(result);
 }
 
index be5e07cbf46bca7550a472a99ef0f66286402884..9709d1a040364e70e87756a7626e64f202fe18c5 100644 (file)
@@ -13,7 +13,9 @@
 
 static inline int mlock_fixup_all(struct vm_area_struct * vma, int newflags)
 {
+       vmlist_modify_lock(vma->vm_mm);
        vma->vm_flags = newflags;
+       vmlist_modify_unlock(vma->vm_mm);
        return 0;
 }
 
@@ -26,15 +28,17 @@ static inline int mlock_fixup_start(struct vm_area_struct * vma,
        if (!n)
                return -EAGAIN;
        *n = *vma;
-       vma->vm_start = end;
        n->vm_end = end;
-       vma->vm_offset += vma->vm_start - n->vm_start;
        n->vm_flags = newflags;
        if (n->vm_file)
                get_file(n->vm_file);
        if (n->vm_ops && n->vm_ops->open)
                n->vm_ops->open(n);
+       vmlist_modify_lock(vma->vm_mm);
+       vma->vm_offset += end - vma->vm_start;
+       vma->vm_start = end;
        insert_vm_struct(current->mm, n);
+       vmlist_modify_unlock(vma->vm_mm);
        return 0;
 }
 
@@ -47,7 +51,6 @@ static inline int mlock_fixup_end(struct vm_area_struct * vma,
        if (!n)
                return -EAGAIN;
        *n = *vma;
-       vma->vm_end = start;
        n->vm_start = start;
        n->vm_offset += n->vm_start - vma->vm_start;
        n->vm_flags = newflags;
@@ -55,7 +58,10 @@ static inline int mlock_fixup_end(struct vm_area_struct * vma,
                get_file(n->vm_file);
        if (n->vm_ops && n->vm_ops->open)
                n->vm_ops->open(n);
+       vmlist_modify_lock(vma->vm_mm);
+       vma->vm_end = start;
        insert_vm_struct(current->mm, n);
+       vmlist_modify_unlock(vma->vm_mm);
        return 0;
 }
 
@@ -75,10 +81,7 @@ static inline int mlock_fixup_middle(struct vm_area_struct * vma,
        *left = *vma;
        *right = *vma;
        left->vm_end = start;
-       vma->vm_start = start;
-       vma->vm_end = end;
        right->vm_start = end;
-       vma->vm_offset += vma->vm_start - left->vm_start;
        right->vm_offset += right->vm_start - left->vm_start;
        vma->vm_flags = newflags;
        if (vma->vm_file)
@@ -88,8 +91,14 @@ static inline int mlock_fixup_middle(struct vm_area_struct * vma,
                vma->vm_ops->open(left);
                vma->vm_ops->open(right);
        }
+       vmlist_modify_lock(vma->vm_mm);
+       vma->vm_offset += start - vma->vm_start;
+       vma->vm_start = start;
+       vma->vm_end = end;
+       vma->vm_flags = newflags;
        insert_vm_struct(current->mm, left);
        insert_vm_struct(current->mm, right);
+       vmlist_modify_unlock(vma->vm_mm);
        return 0;
 }
 
@@ -168,7 +177,9 @@ static int do_mlock(unsigned long start, size_t len, int on)
                        break;
                }
        }
+       vmlist_modify_lock(current->mm);
        merge_segments(current->mm, start, end);
+       vmlist_modify_unlock(current->mm);
        return error;
 }
 
@@ -240,7 +251,9 @@ static int do_mlockall(int flags)
                if (error)
                        break;
        }
+       vmlist_modify_lock(current->mm);
        merge_segments(current->mm, 0, TASK_SIZE);
+       vmlist_modify_unlock(current->mm);
        return error;
 }
 
index ed50bb415e8375d11fa0f7e17c4bb728ede469a7..14413b3082e03c542edd2cf2f817c18a4e29fe4d 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -323,8 +323,10 @@ unsigned long do_mmap(struct file * file, unsigned long addr, unsigned long len,
         */
        flags = vma->vm_flags;
        addr = vma->vm_start; /* can addr have changed?? */
+       vmlist_modify_lock(mm);
        insert_vm_struct(mm, vma);
        merge_segments(mm, vma->vm_start, vma->vm_end);
+       vmlist_modify_unlock(mm);
        
        mm->total_vm += len >> PAGE_SHIFT;
        if (flags & VM_LOCKED) {
@@ -527,11 +529,13 @@ static struct vm_area_struct * unmap_fixup(struct vm_area_struct *area,
        }
 
        /* Work out to one of the ends. */
-       if (end == area->vm_end)
+       if (end == area->vm_end) {
                area->vm_end = addr;
-       else if (addr == area->vm_start) {
+               vmlist_modify_lock(current->mm);
+       } else if (addr == area->vm_start) {
                area->vm_offset += (end - area->vm_start);
                area->vm_start = end;
+               vmlist_modify_lock(current->mm);
        } else {
        /* Unmapping a hole: area->vm_start < addr <= end < area->vm_end */
                /* Add end mapping -- leave beginning for below */
@@ -552,10 +556,12 @@ static struct vm_area_struct * unmap_fixup(struct vm_area_struct *area,
                if (mpnt->vm_ops && mpnt->vm_ops->open)
                        mpnt->vm_ops->open(mpnt);
                area->vm_end = addr;    /* Truncate area */
+               vmlist_modify_lock(current->mm);
                insert_vm_struct(current->mm, mpnt);
        }
 
        insert_vm_struct(current->mm, area);
+       vmlist_modify_unlock(current->mm);
        return extra;
 }
 
@@ -655,6 +661,7 @@ int do_munmap(unsigned long addr, size_t len)
 
        npp = (prev ? &prev->vm_next : &mm->mmap);
        free = NULL;
+       vmlist_modify_lock(mm);
        for ( ; mpnt && mpnt->vm_start < addr+len; mpnt = *npp) {
                *npp = mpnt->vm_next;
                mpnt->vm_next = free;
@@ -662,6 +669,8 @@ int do_munmap(unsigned long addr, size_t len)
                if (mm->mmap_avl)
                        avl_remove(mpnt, &mm->mmap_avl);
        }
+       mm->mmap_cache = NULL;  /* Kill the cache. */
+       vmlist_modify_unlock(mm);
 
        /* Ok - we have the memory areas we should free on the 'free' list,
         * so release them, and unmap the page range..
@@ -678,6 +687,11 @@ int do_munmap(unsigned long addr, size_t len)
                end = end > mpnt->vm_end ? mpnt->vm_end : end;
                size = end - st;
 
+               /*
+                * The lock_kernel interlocks with kswapd try_to_swap_out
+                * invoking a driver swapout() method, and being able to
+                * guarantee vma existance.
+                */
                lock_kernel();
                if (mpnt->vm_ops && mpnt->vm_ops->unmap)
                        mpnt->vm_ops->unmap(mpnt, st, size);
@@ -702,7 +716,6 @@ int do_munmap(unsigned long addr, size_t len)
 
        free_pgtables(mm, prev, addr, addr+len);
 
-       mm->mmap_cache = NULL;  /* Kill the cache. */
        return 0;
 }
 
@@ -786,8 +799,10 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
        flags = vma->vm_flags;
        addr = vma->vm_start;
 
+       vmlist_modify_lock(mm);
        insert_vm_struct(mm, vma);
        merge_segments(mm, vma->vm_start, vma->vm_end);
+       vmlist_modify_unlock(mm);
        
        mm->total_vm += len >> PAGE_SHIFT;
        if (flags & VM_LOCKED) {
@@ -814,7 +829,9 @@ void exit_mmap(struct mm_struct * mm)
 
        release_segments(mm);
        mpnt = mm->mmap;
+       vmlist_modify_lock(mm);
        mm->mmap = mm->mmap_avl = mm->mmap_cache = NULL;
+       vmlist_modify_unlock(mm);
        mm->rss = 0;
        mm->total_vm = 0;
        mm->locked_vm = 0;
@@ -910,6 +927,7 @@ void merge_segments (struct mm_struct * mm, unsigned long start_addr, unsigned l
                prev = mpnt;
                mpnt = mpnt->vm_next;
        }
+       mm->mmap_cache = NULL;          /* Kill the cache. */
 
        /* prev and mpnt cycle through the list, as long as
         * start_addr < mpnt->vm_end && prev->vm_start < end_addr
@@ -946,7 +964,9 @@ void merge_segments (struct mm_struct * mm, unsigned long start_addr, unsigned l
                if (mpnt->vm_ops && mpnt->vm_ops->close) {
                        mpnt->vm_offset += mpnt->vm_end - mpnt->vm_start;
                        mpnt->vm_start = mpnt->vm_end;
+                       vmlist_modify_unlock(mm);
                        mpnt->vm_ops->close(mpnt);
+                       vmlist_modify_lock(mm);
                }
                mm->map_count--;
                remove_shared_vm_struct(mpnt);
@@ -955,7 +975,6 @@ void merge_segments (struct mm_struct * mm, unsigned long start_addr, unsigned l
                kmem_cache_free(vm_area_cachep, mpnt);
                mpnt = prev;
        }
-       mm->mmap_cache = NULL;          /* Kill the cache. */
 }
 
 void __init vma_init(void)
index 61ef3116df45fb6b190f6fbfdf232a7e8b75990a..de2fd6917fa1ee436092aab9e6e9fc533d965712 100644 (file)
@@ -82,8 +82,10 @@ static void change_protection(unsigned long start, unsigned long end, pgprot_t n
 static inline int mprotect_fixup_all(struct vm_area_struct * vma,
        int newflags, pgprot_t prot)
 {
+       vmlist_modify_lock(vma->vm_mm);
        vma->vm_flags = newflags;
        vma->vm_page_prot = prot;
+       vmlist_modify_unlock(vma->vm_mm);
        return 0;
 }
 
@@ -97,16 +99,18 @@ static inline int mprotect_fixup_start(struct vm_area_struct * vma,
        if (!n)
                return -ENOMEM;
        *n = *vma;
-       vma->vm_start = end;
        n->vm_end = end;
-       vma->vm_offset += vma->vm_start - n->vm_start;
        n->vm_flags = newflags;
        n->vm_page_prot = prot;
        if (n->vm_file)
                get_file(n->vm_file);
        if (n->vm_ops && n->vm_ops->open)
                n->vm_ops->open(n);
+       vmlist_modify_lock(vma->vm_mm);
+       vma->vm_offset += end - vma->vm_start;
+       vma->vm_start = end;
        insert_vm_struct(current->mm, n);
+       vmlist_modify_unlock(vma->vm_mm);
        return 0;
 }
 
@@ -120,7 +124,6 @@ static inline int mprotect_fixup_end(struct vm_area_struct * vma,
        if (!n)
                return -ENOMEM;
        *n = *vma;
-       vma->vm_end = start;
        n->vm_start = start;
        n->vm_offset += n->vm_start - vma->vm_start;
        n->vm_flags = newflags;
@@ -129,7 +132,10 @@ static inline int mprotect_fixup_end(struct vm_area_struct * vma,
                get_file(n->vm_file);
        if (n->vm_ops && n->vm_ops->open)
                n->vm_ops->open(n);
+       vmlist_modify_lock(vma->vm_mm);
+       vma->vm_end = start;
        insert_vm_struct(current->mm, n);
+       vmlist_modify_unlock(vma->vm_mm);
        return 0;
 }
 
@@ -150,21 +156,23 @@ static inline int mprotect_fixup_middle(struct vm_area_struct * vma,
        *left = *vma;
        *right = *vma;
        left->vm_end = start;
-       vma->vm_start = start;
-       vma->vm_end = end;
        right->vm_start = end;
-       vma->vm_offset += vma->vm_start - left->vm_start;
        right->vm_offset += right->vm_start - left->vm_start;
-       vma->vm_flags = newflags;
-       vma->vm_page_prot = prot;
        if (vma->vm_file)
                atomic_add(2,&vma->vm_file->f_count);
        if (vma->vm_ops && vma->vm_ops->open) {
                vma->vm_ops->open(left);
                vma->vm_ops->open(right);
        }
+       vmlist_modify_lock(vma->vm_mm);
+       vma->vm_offset += start - vma->vm_start;
+       vma->vm_start = start;
+       vma->vm_end = end;
+       vma->vm_flags = newflags;
+       vma->vm_page_prot = prot;
        insert_vm_struct(current->mm, left);
        insert_vm_struct(current->mm, right);
+       vmlist_modify_unlock(vma->vm_mm);
        return 0;
 }
 
@@ -246,7 +254,9 @@ asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot
                        break;
                }
        }
+       vmlist_modify_lock(current->mm);
        merge_segments(current->mm, start, end);
+       vmlist_modify_unlock(current->mm);
 out:
        up(&current->mm->mmap_sem);
        return error;
index 95f4b4f9044267dc20adfe959ce4459fb15cd123..101e513108d9c0600c9cb5f899174ab7e7e44043 100644 (file)
@@ -141,8 +141,10 @@ static inline unsigned long move_vma(struct vm_area_struct * vma,
                                get_file(new_vma->vm_file);
                        if (new_vma->vm_ops && new_vma->vm_ops->open)
                                new_vma->vm_ops->open(new_vma);
+                       vmlist_modify_lock(current->mm);
                        insert_vm_struct(current->mm, new_vma);
                        merge_segments(current->mm, new_vma->vm_start, new_vma->vm_end);
+                       vmlist_modify_unlock(vma->vm_mm);
                        do_munmap(addr, old_len);
                        current->mm->total_vm += new_len >> PAGE_SHIFT;
                        if (new_vma->vm_flags & VM_LOCKED) {
@@ -220,7 +222,9 @@ asmlinkage unsigned long sys_mremap(unsigned long addr,
                /* can we just expand the current mapping? */
                if (max_addr - addr >= new_len) {
                        int pages = (new_len - old_len) >> PAGE_SHIFT;
+                       vmlist_modify_lock(vma->vm_mm);
                        vma->vm_end = addr + new_len;
+                       vmlist_modify_unlock(vma->vm_mm);
                        current->mm->total_vm += pages;
                        if (vma->vm_flags & VM_LOCKED) {
                                current->mm->locked_vm += pages;
index 1ce37062b2d6798ac3000a04e06dc7a60cd997ac..31b00047a2a39bf713172aaba6b6fe0b11dad1bf 100644 (file)
@@ -47,9 +47,6 @@ static int try_to_swap_out(struct vm_area_struct* vma, unsigned long address, pt
                goto out_failed;
 
        page = mem_map + MAP_NR(page_addr);
-       spin_lock(&vma->vm_mm->page_table_lock);
-       if (pte_val(pte) != pte_val(*page_table))
-               goto out_failed_unlock;
 
        /* Don't look at this pte if it's been accessed recently. */
        if (pte_young(pte)) {
@@ -59,14 +56,14 @@ static int try_to_swap_out(struct vm_area_struct* vma, unsigned long address, pt
                 */
                set_pte(page_table, pte_mkold(pte));
                set_bit(PG_referenced, &page->flags);
-               goto out_failed_unlock;
+               goto out_failed;
        }
 
        if (PageReserved(page)
            || PageLocked(page)
            || ((gfp_mask & __GFP_DMA) && !PageDMA(page))
            || (!(gfp_mask & __GFP_BIGMEM) && PageBIGMEM(page)))
-               goto out_failed_unlock;
+               goto out_failed;
 
        /*
         * Is the page already in the swap cache? If so, then
@@ -84,7 +81,7 @@ drop_pte:
                vma->vm_mm->rss--;
                flush_tlb_page(vma, address);
                __free_page(page);
-               goto out_failed_unlock;
+               goto out_failed;
        }
 
        /*
@@ -111,7 +108,7 @@ drop_pte:
         * locks etc.
         */
        if (!(gfp_mask & __GFP_IO))
-               goto out_failed_unlock;
+               goto out_failed;
 
        /*
         * Ok, it's really dirty. That means that
@@ -136,9 +133,9 @@ drop_pte:
        if (vma->vm_ops && vma->vm_ops->swapout) {
                int error;
                pte_clear(page_table);
-               spin_unlock(&vma->vm_mm->page_table_lock);
-               flush_tlb_page(vma, address);
                vma->vm_mm->rss--;
+               flush_tlb_page(vma, address);
+               vmlist_access_unlock(vma->vm_mm);
                error = vma->vm_ops->swapout(vma, page);
                if (!error)
                        goto out_free_success;
@@ -154,14 +151,14 @@ drop_pte:
         */
        entry = acquire_swap_entry(page);
        if (!entry)
-               goto out_failed_unlock; /* No swap space left */
+               goto out_failed; /* No swap space left */
                
        if (!(page = prepare_bigmem_swapout(page)))
-               goto out_swap_free_unlock;
+               goto out_swap_free;
 
        vma->vm_mm->rss--;
        set_pte(page_table, __pte(entry));
-       spin_unlock(&vma->vm_mm->page_table_lock);
+       vmlist_access_unlock(vma->vm_mm);
 
        flush_tlb_page(vma, address);
        swap_duplicate(entry);  /* One for the process, one for the swap cache */
@@ -175,13 +172,9 @@ drop_pte:
 out_free_success:
        __free_page(page);
        return 1;
-out_failed_unlock:
-       spin_unlock(&vma->vm_mm->page_table_lock);
-out_failed:
-       return 0;
-out_swap_free_unlock:
+out_swap_free:
        swap_free(entry);
-       spin_unlock(&vma->vm_mm->page_table_lock);
+out_failed:
        return 0;
 
 }
@@ -293,8 +286,10 @@ static int swap_out_mm(struct mm_struct * mm, int gfp_mask)
        address = mm->swap_address;
 
        /*
-        * Find the proper vm-area
+        * Find the proper vm-area after freezing the vma chain 
+        * and ptes.
         */
+       vmlist_access_lock(mm);
        vma = find_vma(mm, address);
        if (vma) {
                if (address < vma->vm_start)
@@ -310,6 +305,7 @@ static int swap_out_mm(struct mm_struct * mm, int gfp_mask)
                        address = vma->vm_start;
                }
        }
+       vmlist_access_unlock(mm);
 
        /* We didn't find anything for the process */
        mm->swap_cnt = 0;
index 990d866824559f02b4729d967882a0b0f699a1a7..50b160a4c45c2aa403a288c1550025f5bae6f83b 100644 (file)
@@ -5,7 +5,6 @@
  *
  */
 
-#include <asm/segment.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <linux/types.h>
index 58aeb6cc924a7edcba80bfcc6ada78fe92f6da47..7c8a332e212e840d8730cc93242852e0634889ef 100644 (file)
@@ -237,8 +237,10 @@ void __kfree_skb(struct sk_buff *skb)
        dst_release(skb->dst);
        if(skb->destructor)
                skb->destructor(skb);
+#ifdef CONFIG_NET              
        if(skb->rx_dev)
                dev_put(skb->rx_dev);
+#endif         
        skb_headerinit(skb, NULL, 0);  /* clean state */
        kfree_skbmem(skb);
 }
index 986868b4fc8fb0bba4d0c742db707946c3cf0bb5..87ec2d773759064ef3c94b99a6d69518d4d204e0 100644 (file)
@@ -59,8 +59,6 @@
 #include <net/ipv6.h>
 #include <net/inet_common.h>
 
-#include <asm/segment.h>
-
 #include <linux/inet.h>
 #include <linux/stddef.h>
 
index 6ffcc187bcf58cbfa7692402285e721449155173..e6df7ac762af81c2dbb5fa20cea17c78ef294978 100644 (file)
@@ -459,6 +459,7 @@ call_encode(struct rpc_task *task)
        req->rq_rvec[0].iov_len  = bufsiz;
        req->rq_rlen             = bufsiz;
        req->rq_rnr              = 1;
+       req->rq_damaged          = 0;
 
        if (task->tk_proc > clnt->cl_maxproc) {
                printk(KERN_WARNING "%s (vers %d): bad procedure number %d\n",
@@ -467,6 +468,9 @@ call_encode(struct rpc_task *task)
                return;
        }
 
+       /* Zero buffer so we have automatic zero-padding of opaque & string */
+       memset(task->tk_buffer, 0, bufsiz);
+
        /* Encode header and provided arguments */
        encode = rpcproc_encode(clnt, task->tk_proc);
        if (!(p = call_header(task))) {
index 181a7e46ca896a1b67fada4a1d2a29d3adbc15d1..76c28d7ccb025d74902e67c6b4ed39614c3269b3 100644 (file)
@@ -74,6 +74,18 @@ static int                   rpc_inhibit = 0;
 static u32                     swap_buffer[PAGE_SIZE >> 2];
 static int                     swap_buffer_used = 0;
 
+/*
+ * Make allocation of the swap_buffer SMP-safe
+ */
+static __inline__ int rpc_lock_swapbuf(void)
+{
+       return !test_and_set_bit(1, &swap_buffer_used);
+}
+static __inline__ void rpc_unlock_swapbuf(void)
+{
+       clear_bit(1, &swap_buffer_used);
+}
+
 /*
  * Spinlock for wait queues. Access to the latter also has to be
  * interrupt-safe in order to allow timers to wake up sleeping tasks.
@@ -614,7 +626,8 @@ rpc_allocate(unsigned int flags, unsigned int size)
                        dprintk("RPC:      allocated buffer %p\n", buffer);
                        return buffer;
                }
-               if ((flags & RPC_TASK_SWAPPER) && !swap_buffer_used++) {
+               if ((flags & RPC_TASK_SWAPPER) && size <= sizeof(swap_buffer)
+                   && rpc_lock_swapbuf()) {
                        dprintk("RPC:      used last-ditch swap buffer\n");
                        return swap_buffer;
                }
@@ -634,7 +647,7 @@ rpc_free(void *buffer)
                kfree(buffer);
                return;
        }
-       swap_buffer_used = 0;
+       rpc_unlock_swapbuf();
 }
 
 /*