v2.4.3.3 -> v2.4.3.4
authorLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 02:12:47 +0000 (18:12 -0800)
committerLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 02:12:47 +0000 (18:12 -0800)
  - David Miller: sparc rw semaphores moved over
  - Alan Cox: yet more resyncs
  - NIIBE Yutaka: Super-H driver update
  - David Howells: more rw-sem cleanups, updates
  - USB updates
  - Al Viro: filesystem init cleanup

341 files changed:
Documentation/Configure.help
Makefile
arch/alpha/config.in
arch/alpha/kernel/alpha_ksyms.c
arch/alpha/kernel/semaphore.c
arch/alpha/mm/init.c
arch/arm/config.in
arch/arm/kernel/semaphore.c
arch/cris/config.in
arch/cris/kernel/semaphore.c
arch/i386/config.in
arch/i386/lib/usercopy.c
arch/ia64/config.in
arch/ia64/kernel/semaphore.c
arch/m68k/amiga/config.c
arch/m68k/config.in
arch/m68k/kernel/semaphore.c
arch/m68k/kernel/setup.c
arch/mips/Makefile
arch/mips/arc/Makefile
arch/mips/arc/arc_con.c [new file with mode: 0644]
arch/mips/arc/cmdline.c
arch/mips/arc/console.c
arch/mips/arc/identify.c
arch/mips/arc/init.c
arch/mips/arc/memory.c
arch/mips/arc/misc.c
arch/mips/arc/printf.c [deleted file]
arch/mips/baget/Makefile
arch/mips/baget/prom/Makefile
arch/mips/config.in
arch/mips/ddb5074/Makefile
arch/mips/ddb5074/int-handler.S
arch/mips/ddb5074/irq.c
arch/mips/ddb5074/nile4.c
arch/mips/ddb5074/pci-dma.c [deleted file]
arch/mips/ddb5074/pci.c
arch/mips/ddb5074/prom.c
arch/mips/ddb5074/setup.c
arch/mips/ddb5074/time.c
arch/mips/ddb5476/Makefile [new file with mode: 0644]
arch/mips/ddb5476/dbg_io.c [new file with mode: 0644]
arch/mips/ddb5476/int-handler.S [new file with mode: 0644]
arch/mips/ddb5476/irq.c [new file with mode: 0644]
arch/mips/ddb5476/nile4.c [new file with mode: 0644]
arch/mips/ddb5476/pci.c [new file with mode: 0644]
arch/mips/ddb5476/prom.c [new file with mode: 0644]
arch/mips/ddb5476/setup.c [new file with mode: 0644]
arch/mips/ddb5476/time.c [new file with mode: 0644]
arch/mips/dec/Makefile
arch/mips/dec/boot/Makefile
arch/mips/defconfig
arch/mips/defconfig-cobalt
arch/mips/defconfig-ddb5476 [new file with mode: 0644]
arch/mips/defconfig-decstation
arch/mips/defconfig-ip22
arch/mips/defconfig-it8172 [new file with mode: 0644]
arch/mips/defconfig-orion
arch/mips/defconfig-rm200
arch/mips/ite-boards/generic/Makefile [new file with mode: 0644]
arch/mips/ite-boards/generic/dbg_io.c [new file with mode: 0644]
arch/mips/ite-boards/generic/int-handler.S [new file with mode: 0644]
arch/mips/ite-boards/generic/irq.c [new file with mode: 0644]
arch/mips/ite-boards/generic/it8172_cir.c [new file with mode: 0644]
arch/mips/ite-boards/generic/it8172_pci.c [new file with mode: 0644]
arch/mips/ite-boards/generic/it8172_rtc.c [new file with mode: 0644]
arch/mips/ite-boards/generic/it8172_setup.c [new file with mode: 0644]
arch/mips/ite-boards/generic/lpc.c [new file with mode: 0644]
arch/mips/ite-boards/generic/pmon_prom.c [new file with mode: 0644]
arch/mips/ite-boards/generic/puts.c [new file with mode: 0644]
arch/mips/ite-boards/generic/reset.c [new file with mode: 0644]
arch/mips/ite-boards/generic/time.c [new file with mode: 0644]
arch/mips/ite-boards/qed-4n-s01b/Makefile [new file with mode: 0644]
arch/mips/ite-boards/qed-4n-s01b/README [new file with mode: 0644]
arch/mips/ite-boards/qed-4n-s01b/init.c [new file with mode: 0644]
arch/mips/ite-boards/qed-4n-s01b/pci_fixup.c [new file with mode: 0644]
arch/mips/jazz/Makefile
arch/mips/kernel/branch.c
arch/mips/kernel/process.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/r2300_fpu.S
arch/mips/kernel/r2300_switch.S
arch/mips/kernel/r4k_fpu.S
arch/mips/kernel/r4k_misc.S
arch/mips/kernel/r4k_switch.S
arch/mips/kernel/r6000_fpu.S
arch/mips/kernel/semaphore.c
arch/mips/kernel/setup.c
arch/mips/kernel/signal.c
arch/mips/kernel/traps.c
arch/mips/lib/Makefile
arch/mips/lib/kbd-std.c
arch/mips/math-emu/Makefile [new file with mode: 0644]
arch/mips/math-emu/cp1emu.c [new file with mode: 0644]
arch/mips/math-emu/dp_add.c [new file with mode: 0644]
arch/mips/math-emu/dp_cmp.c [new file with mode: 0644]
arch/mips/math-emu/dp_div.c [new file with mode: 0644]
arch/mips/math-emu/dp_fint.c [new file with mode: 0644]
arch/mips/math-emu/dp_flong.c [new file with mode: 0644]
arch/mips/math-emu/dp_frexp.c [new file with mode: 0644]
arch/mips/math-emu/dp_fsp.c [new file with mode: 0644]
arch/mips/math-emu/dp_logb.c [new file with mode: 0644]
arch/mips/math-emu/dp_modf.c [new file with mode: 0644]
arch/mips/math-emu/dp_mul.c [new file with mode: 0644]
arch/mips/math-emu/dp_scalb.c [new file with mode: 0644]
arch/mips/math-emu/dp_simple.c [new file with mode: 0644]
arch/mips/math-emu/dp_sqrt.c [new file with mode: 0644]
arch/mips/math-emu/dp_sub.c [new file with mode: 0644]
arch/mips/math-emu/dp_tint.c [new file with mode: 0644]
arch/mips/math-emu/dp_tlong.c [new file with mode: 0644]
arch/mips/math-emu/ieee754.c [new file with mode: 0644]
arch/mips/math-emu/ieee754.h [new file with mode: 0644]
arch/mips/math-emu/ieee754d.c [new file with mode: 0644]
arch/mips/math-emu/ieee754dp.c [new file with mode: 0644]
arch/mips/math-emu/ieee754dp.h [new file with mode: 0644]
arch/mips/math-emu/ieee754int.h [new file with mode: 0644]
arch/mips/math-emu/ieee754m.c [new file with mode: 0644]
arch/mips/math-emu/ieee754sp.c [new file with mode: 0644]
arch/mips/math-emu/ieee754sp.h [new file with mode: 0644]
arch/mips/math-emu/ieee754xcpt.c [new file with mode: 0644]
arch/mips/math-emu/kernel_linkage.c [new file with mode: 0644]
arch/mips/math-emu/sp_add.c [new file with mode: 0644]
arch/mips/math-emu/sp_cmp.c [new file with mode: 0644]
arch/mips/math-emu/sp_div.c [new file with mode: 0644]
arch/mips/math-emu/sp_fdp.c [new file with mode: 0644]
arch/mips/math-emu/sp_fint.c [new file with mode: 0644]
arch/mips/math-emu/sp_flong.c [new file with mode: 0644]
arch/mips/math-emu/sp_frexp.c [new file with mode: 0644]
arch/mips/math-emu/sp_logb.c [new file with mode: 0644]
arch/mips/math-emu/sp_modf.c [new file with mode: 0644]
arch/mips/math-emu/sp_mul.c [new file with mode: 0644]
arch/mips/math-emu/sp_scalb.c [new file with mode: 0644]
arch/mips/math-emu/sp_simple.c [new file with mode: 0644]
arch/mips/math-emu/sp_sqrt.c [new file with mode: 0644]
arch/mips/math-emu/sp_sub.c [new file with mode: 0644]
arch/mips/math-emu/sp_tint.c [new file with mode: 0644]
arch/mips/math-emu/sp_tlong.c [new file with mode: 0644]
arch/mips/mips-boards/atlas/Makefile [new file with mode: 0644]
arch/mips/mips-boards/atlas/atlas_int.c [new file with mode: 0644]
arch/mips/mips-boards/atlas/atlas_rtc.c [new file with mode: 0644]
arch/mips/mips-boards/atlas/atlas_setup.c [new file with mode: 0644]
arch/mips/mips-boards/generic/Makefile [new file with mode: 0644]
arch/mips/mips-boards/generic/cmdline.c [new file with mode: 0644]
arch/mips/mips-boards/generic/display.c [new file with mode: 0644]
arch/mips/mips-boards/generic/gdb_hook.c [new file with mode: 0644]
arch/mips/mips-boards/generic/init.c [new file with mode: 0644]
arch/mips/mips-boards/generic/memory.c [new file with mode: 0644]
arch/mips/mips-boards/generic/mipsIRQ.S [new file with mode: 0644]
arch/mips/mips-boards/generic/pci.c [new file with mode: 0644]
arch/mips/mips-boards/generic/printf.c [new file with mode: 0644]
arch/mips/mips-boards/generic/reset.c [new file with mode: 0644]
arch/mips/mips-boards/generic/time.c [new file with mode: 0644]
arch/mips/mips-boards/malta/Makefile [new file with mode: 0644]
arch/mips/mips-boards/malta/malta_int.c [new file with mode: 0644]
arch/mips/mips-boards/malta/malta_rtc.c [new file with mode: 0644]
arch/mips/mips-boards/malta/malta_setup.c [new file with mode: 0644]
arch/mips/mm/Makefile
arch/mips/orion/Makefile [deleted file]
arch/mips/orion/int-handler.S [deleted file]
arch/mips/orion/irq.c [deleted file]
arch/mips/orion/ld.script.orion [deleted file]
arch/mips/orion/misc.c [deleted file]
arch/mips/orion/no_initrd.c [deleted file]
arch/mips/orion/piggyback.c [deleted file]
arch/mips/orion/promcon.c [deleted file]
arch/mips/orion/setup.c [deleted file]
arch/mips/sgi/kernel/Makefile
arch/mips/sni/Makefile
arch/mips64/config.in
arch/mips64/defconfig
arch/mips64/defconfig-ip22
arch/mips64/defconfig-ip27
arch/mips64/kernel/semaphore.c
arch/mips64/mm/Makefile
arch/mips64/tools/Makefile
arch/parisc/config.in
arch/parisc/kernel/semaphore.c
arch/ppc/config.in
arch/ppc/kernel/semaphore.c
arch/s390/config.in
arch/s390/kernel/semaphore.c
arch/s390x/config.in
arch/s390x/kernel/semaphore.c
arch/sh/config.in
arch/sh/kernel/semaphore.c
arch/sparc/config.in
arch/sparc/kernel/irq.c
arch/sparc/kernel/semaphore.c
arch/sparc/kernel/setup.c
arch/sparc/kernel/sys_sparc.c
arch/sparc/mm/init.c
arch/sparc/mm/srmmu.c
arch/sparc/mm/sun4c.c
arch/sparc64/config.in
arch/sparc64/defconfig
arch/sparc64/kernel/semaphore.c
arch/sparc64/kernel/sparc64_ksyms.c
arch/sparc64/kernel/starfire.c
arch/sparc64/kernel/sys_sparc.c
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/lib/bitops.S
arch/sparc64/solaris/timod.c
drivers/block/cciss.c
drivers/block/cciss.h
drivers/block/cciss_cmd.h
drivers/char/Makefile
drivers/char/drm/ffb_drv.c
drivers/char/ec3104_keyb.c [new file with mode: 0644]
drivers/char/epca.c
drivers/char/mem.c
drivers/char/misc.c
drivers/char/n_r3964.c
drivers/char/qpmouse.c
drivers/char/qtronix.c [new file with mode: 0644]
drivers/char/qtronixmap.map [new file with mode: 0644]
drivers/char/rio/rio_linux.c
drivers/char/rio/rioctrl.c
drivers/char/serial.c
drivers/input/keybdev.c
drivers/media/radio/Config.in
drivers/media/radio/Makefile
drivers/media/radio/radio-miropcm20.c
drivers/media/radio/rds-miropcm20.c [new file with mode: 0644]
drivers/net/acenic.c
drivers/net/appletalk/ipddp.c
drivers/net/de4x5.c
drivers/net/de600.c
drivers/net/de620.c
drivers/net/depca.c
drivers/net/gt96100eth.c [new file with mode: 0644]
drivers/net/gt96100eth.h [new file with mode: 0644]
drivers/net/hamradio/6pack.c
drivers/net/pcmcia/aironet4500_cs.c
drivers/net/saa9730.c [new file with mode: 0644]
drivers/net/saa9730.h [new file with mode: 0644]
drivers/net/tokenring/smctr.c
drivers/pci/Makefile
drivers/scsi/53c7xx.c
drivers/scsi/53c7xx.scr
drivers/scsi/megaraid.c
drivers/scsi/megaraid.h
drivers/scsi/qlogicfc.c
drivers/sgi/Makefile
drivers/sgi/char/Makefile
drivers/sound/Config.in
drivers/sound/Makefile
drivers/sound/aci.c
drivers/sound/aci.h [new file with mode: 0644]
drivers/sound/aedsp16.c
drivers/sound/emu10k1/cardmi.h
drivers/sound/emu10k1/timer.h
drivers/sound/miroaci.h [deleted file]
drivers/sound/vidc.c
drivers/sound/waveartist.c
drivers/tc/Makefile
drivers/usb/hub.c
drivers/usb/hub.h
drivers/video/Config.in
drivers/video/Makefile
drivers/video/dcfb.c [new file with mode: 0644]
drivers/video/epson1355fb.c [new file with mode: 0644]
drivers/video/fbmem.c
fs/devfs/base.c
fs/devpts/inode.c
fs/filesystems.c
fs/nfs/inode.c
fs/partitions/Makefile
fs/partitions/ibm.c
fs/proc/proc_misc.c
fs/reiserfs/fix_node.c
fs/reiserfs/prints.c
fs/reiserfs/stree.c
fs/reiserfs/super.c
fs/romfs/inode.c
fs/smbfs/ioctl.c
fs/smbfs/proc.c
fs/stat.c
fs/super.c
fs/udf/partition.c
include/asm-alpha/io.h
include/asm-alpha/ioctls.h
include/asm-alpha/pgalloc.h
include/asm-alpha/pgtable.h
include/asm-alpha/semaphore.h
include/asm-arm/semaphore.h
include/asm-cris/semaphore.h
include/asm-i386/rwsem-spin.h
include/asm-i386/rwsem.h
include/asm-ia64/ia32.h
include/asm-ia64/semaphore.h
include/asm-m68k/semaphore.h
include/asm-mips/bootinfo.h
include/asm-mips/it8172/it8172.h [new file with mode: 0644]
include/asm-mips/it8172/it8172_cir.h [new file with mode: 0644]
include/asm-mips/it8172/it8172_dbg.h [new file with mode: 0644]
include/asm-mips/it8172/it8172_int.h [new file with mode: 0644]
include/asm-mips/it8172/it8172_lpc.h [new file with mode: 0644]
include/asm-mips/it8172/it8172_pci.h [new file with mode: 0644]
include/asm-mips/it8712.h [new file with mode: 0644]
include/asm-mips/keyboard.h
include/asm-mips/mipsregs.h
include/asm-mips/pci.h
include/asm-mips/processor.h
include/asm-mips/semaphore.h
include/asm-mips/sgi/sgimc.h
include/asm-mips/shmiq.h
include/asm-mips64/errno.h
include/asm-mips64/keyboard.h
include/asm-mips64/mipsregs.h
include/asm-mips64/mmzone.h
include/asm-mips64/pci/bridge.h
include/asm-mips64/semaphore.h
include/asm-mips64/shmiq.h
include/asm-parisc/semaphore.h
include/asm-ppc/semaphore.h
include/asm-s390/semaphore.h
include/asm-s390x/semaphore.h
include/asm-sh/semaphore.h
include/asm-sparc/semaphore.h
include/asm-sparc64/bitops.h
include/asm-sparc64/pgtable.h
include/asm-sparc64/rwsem.h [new file with mode: 0644]
include/asm-sparc64/semaphore.h
include/linux/devfs_fs_kernel.h
include/linux/fs.h
include/linux/if_arp.h
include/linux/nfs_fs.h
include/linux/rwsem-spinlock.h
include/linux/rwsem.h
include/linux/sunrpc/sched.h
include/linux/tty_ldisc.h
include/linux/wanrouter.h
init/main.c
kernel/ksyms.c
lib/Makefile
lib/rwsem.c
lib/vsprintf.c
mm/bootmem.c
mm/filemap.c
mm/mmap.c
net/sunrpc/sysctl.c

index 7394550..426a2b3 100644 (file)
@@ -11002,16 +11002,16 @@ CONFIG_USB_USS720
 USB device file system
 CONFIG_USB_DEVICEFS
   If you say Y here (and to "/proc file system support" below), you
-  will get a file /proc/usb/devices which lists the devices currently
-  connected to your USB busses, a file /proc/usb/drivers which lists
-  the USB kernel client drivers currently loaded, and for every
-  connected device a file named "/proc/usb/xxx/yyy", where xxx is the
-  bus number and yyy the device number; the latter files can be used
-  by user space programs to talk directly to the device. These files
-  are "virtual", meaning they are generated on the fly and not stored
-  on the hard drive.
+  will get a file /proc/bus/usb/devices which lists the devices
+  currently connected to your USB busses, a file /proc/bus/usb/drivers
+  which lists the USB kernel client drivers currently loaded, and for
+  every connected device a file named "/proc/bus/usb/xxx/yyy", where
+  xxx is the bus number and yyy the device number; the latter files
+  can be used by user space programs to talk directly to the device.
+  These files are "virtual", meaning they are generated on the fly
+  and not stored on the hard drive.
   
-  For the format of the /proc/usb/ files, please read
+  For the format of the /proc/bus/usb/ files, please read
   Documentation/usb/proc_usb_info.txt. 
 
   Please note that this code is completely unrelated to devfs, the
index 4108a50..a1515d7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 4
-EXTRAVERSION =-pre3
+EXTRAVERSION =-pre4
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
index fe0471a..74ed60a 100644 (file)
@@ -5,6 +5,8 @@
 
 define_bool CONFIG_ALPHA y
 define_bool CONFIG_UID16 n
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 mainmenu_name "Kernel configuration of Linux for Alpha machines"
 
index 997cc77..2e8f777 100644 (file)
@@ -190,7 +190,6 @@ EXPORT_SYMBOL(kernel_flag);
 EXPORT_SYMBOL(synchronize_irq);
 EXPORT_SYMBOL(flush_tlb_all);
 EXPORT_SYMBOL(flush_tlb_mm);
-EXPORT_SYMBOL(flush_tlb_page);
 EXPORT_SYMBOL(flush_tlb_range);
 EXPORT_SYMBOL(smp_imb);
 EXPORT_SYMBOL(cpu_data);
index 7c1c9a8..b47d5b1 100644 (file)
@@ -263,185 +263,3 @@ up(struct semaphore *sem)
 #endif
        __up(sem);
 }
-
-
-/*
- * RW Semaphores
- */
-
-void
-__down_read_failed(struct rw_semaphore *sem, int count)
-{
-       DECLARE_WAITQUEUE(wait, current);
-
- retry_down:
-       if (count < 0) {
-               /* Waiting on multiple readers and/or writers.  */
-               
-               /* Undo the acquisition we started in down_read.  */
-               atomic_inc(&sem->count);
-
-               current->state = TASK_UNINTERRUPTIBLE;
-               wmb();
-               add_wait_queue(&sem->wait, &wait);
-               mb();
-               while (atomic_read(&sem->count) < 0) {
-                       schedule();
-                       set_task_state(current, TASK_UNINTERRUPTIBLE);
-               }
-
-               remove_wait_queue(&sem->wait, &wait);
-               current->state = TASK_RUNNING;
-
-               mb();
-               count = atomic_dec_return(&sem->count);
-               if (count <= 0)
-                       goto retry_down;
-       } else {
-               /* Waiting on exactly one writer.  */
-
-               current->state = TASK_UNINTERRUPTIBLE;
-               wmb();
-               add_wait_queue(&sem->wait, &wait);
-               mb();
-
-               while (!test_and_clear_bit(0, &sem->granted)) {
-                       schedule();
-                       set_task_state(current, TASK_UNINTERRUPTIBLE);
-               }
-
-               remove_wait_queue(&sem->wait, &wait);
-               current->state = TASK_RUNNING;
-       }
-}
-
-void
-__down_write_failed(struct rw_semaphore *sem, int count)
-{
-       DECLARE_WAITQUEUE(wait, current);
-
- retry_down:
-       if (count + RW_LOCK_BIAS < 0) {
-               /* Waiting on multiple readers and/or writers.  */
-
-               /* Undo the acquisition we started in down_write.  */
-               atomic_add(RW_LOCK_BIAS, &sem->count);
-
-               current->state = TASK_UNINTERRUPTIBLE;
-               wmb();
-               add_wait_queue_exclusive(&sem->wait, &wait);
-               mb();
-       
-               while (atomic_read(&sem->count) + RW_LOCK_BIAS < 0) {
-                       schedule();
-                       set_task_state(current, TASK_UNINTERRUPTIBLE);
-               }
-
-               remove_wait_queue(&sem->wait, &wait);
-               current->state = TASK_RUNNING;
-
-               count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
-               if (count != 0)
-                       goto retry_down;
-       } else {
-               /* Waiting on exactly one writer.  */
-
-               current->state = TASK_UNINTERRUPTIBLE;
-               wmb();
-               add_wait_queue_exclusive(&sem->wait, &wait);
-               mb();
-
-               while (!test_and_clear_bit(1, &sem->granted)) {
-                       schedule();
-                       set_task_state(current, TASK_UNINTERRUPTIBLE);
-               }
-
-               remove_wait_queue(&sem->write_bias_wait, &wait);
-               current->state = TASK_RUNNING;
-
-               /* If the lock is currently unbiased, awaken the sleepers.
-                  FIXME: This wakes up the readers early in a bit of a
-                  stampede -> bad!  */
-               count = atomic_read(&sem->count);
-               if (__builtin_expect(count >= 0, 0))
-                       wake_up(&sem->wait);
-       }
-}
-
-void
-__rwsem_wake(struct rw_semaphore *sem, int readers)
-{
-       if (readers) {
-               if (test_and_set_bit(0, &sem->granted))
-                       BUG();
-               wake_up(&sem->wait);
-       } else {
-               if (test_and_set_bit(1, &sem->granted))
-                       BUG();
-               wake_up(&sem->write_bias_wait);
-       }
-}
-
-void
-down_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-       __down_read(sem);
-#if WAITQUEUE_DEBUG
-       if (sem->granted & 2)
-               BUG();
-       if (atomic_read(&sem->writers))
-               BUG();
-       atomic_inc(&sem->readers);
-#endif
-}
-
-void
-down_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-       __down_write(sem);
-#if WAITQUEUE_DEBUG
-       if (sem->granted & 3)
-               BUG();
-       if (atomic_read(&sem->writers))
-               BUG();
-       if (atomic_read(&sem->readers))
-               BUG();
-       atomic_inc(&sem->writers);
-#endif
-}
-
-void
-up_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-       if (sem->granted & 2)
-               BUG();
-       if (atomic_read(&sem->writers))
-               BUG();
-       atomic_dec(&sem->readers);
-#endif
-       __up_read(sem);
-}
-
-void
-up_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-       if (sem->granted & 3)
-               BUG();
-       if (atomic_read(&sem->readers))
-               BUG();
-       if (atomic_read(&sem->writers) != 1)
-               BUG();
-       atomic_dec(&sem->writers);
-#endif
-       __up_write(sem);
-}
index 3b0ae70..eb8ab75 100644 (file)
@@ -43,20 +43,6 @@ struct thread_struct original_pcb;
 struct pgtable_cache_struct quicklists;
 #endif
 
-void
-__bad_pmd(pgd_t *pgd)
-{
-       printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd));
-       pgd_set(pgd, BAD_PAGETABLE);
-}
-
-void
-__bad_pte(pmd_t *pmd)
-{
-       printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
-       pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
-}
-
 pgd_t *
 get_pgd_slow(void)
 {
@@ -80,66 +66,26 @@ get_pgd_slow(void)
        return ret;
 }
 
-pmd_t *
-get_pmd_slow(pgd_t *pgd, unsigned long offset)
-{
-       pmd_t *pmd;
-
-       pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
-       if (pgd_none(*pgd)) {
-               if (pmd) {
-                       clear_page((void *)pmd);
-                       pgd_set(pgd, pmd);
-                       return pmd + offset;
-               }
-               pgd_set(pgd, BAD_PAGETABLE);
-               return NULL;
-       }
-       free_page((unsigned long)pmd);
-       if (pgd_bad(*pgd)) {
-               __bad_pmd(pgd);
-               return NULL;
-       }
-       return (pmd_t *) pgd_page(*pgd) + offset;
-}
-
-pte_t *
-get_pte_slow(pmd_t *pmd, unsigned long offset)
-{
-       pte_t *pte;
-
-       pte = (pte_t *) __get_free_page(GFP_KERNEL);
-       if (pmd_none(*pmd)) {
-               if (pte) {
-                       clear_page((void *)pte);
-                       pmd_set(pmd, pte);
-                       return pte + offset;
-               }
-               pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
-               return NULL;
-       }
-       free_page((unsigned long)pte);
-       if (pmd_bad(*pmd)) {
-               __bad_pte(pmd);
-               return NULL;
-       }
-       return (pte_t *) pmd_page(*pmd) + offset;
-}
-
 int do_check_pgt_cache(int low, int high)
 {
        int freed = 0;
-        if(pgtable_cache_size > high) {
-                do {
-                        if(pgd_quicklist)
-                                free_pgd_slow(get_pgd_fast()), freed++;
-                        if(pmd_quicklist)
-                                free_pmd_slow(get_pmd_fast()), freed++;
-                        if(pte_quicklist)
-                                free_pte_slow(get_pte_fast()), freed++;
-                } while(pgtable_cache_size > low);
-        }
-        return freed;
+       if(pgtable_cache_size > high) {
+               do {
+                       if(pgd_quicklist) {
+                               free_pgd_slow(get_pgd_fast());
+                               freed++;
+                       }
+                       if(pmd_quicklist) {
+                               pmd_free_slow(pmd_alloc_one_fast(NULL, 0));
+                               freed++;
+                       }
+                       if(pte_quicklist) {
+                               pte_free_slow(pte_alloc_one_fast(NULL, 0));
+                               freed++;
+                       }
+               } while(pgtable_cache_size > low);
+       }
+       return freed;
 }
 
 /*
index 2c7fab3..728b14e 100644 (file)
@@ -9,6 +9,8 @@ define_bool CONFIG_EISA n
 define_bool CONFIG_SBUS n
 define_bool CONFIG_MCA n
 define_bool CONFIG_UID16 y
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 
 mainmenu_option next_comment
@@ -44,7 +46,7 @@ choice 'ARM system type'      \
 mainmenu_option next_comment
 comment 'Archimedes/A5000 Implementations'
 # These architectures will be combined.  However, until this
-# is complete...  Note that the ARC will take precidence over
+# is complete...  Note that the ARC will take precedence over
 # A5K
 comment 'Archimedes/A5000 Implementations (select only ONE)'
 dep_bool '  Archimedes' CONFIG_ARCH_ARC $CONFIG_ARCH_ARCA5K
index aac8be6..49b0bb5 100644 (file)
@@ -165,321 +165,3 @@ int __down_trylock(struct semaphore * sem)
        spin_unlock_irqrestore(&semaphore_lock, flags);
        return 1;
 }
-
-struct rw_semaphore *down_read_failed_biased(struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       add_wait_queue(&sem->wait, &wait);      /* put ourselves at the head of the list */
-
-       for (;;) {
-               if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
-                       break;
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (!sem->read_bias_granted)
-                       schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-
-       return sem;
-}
-
-struct rw_semaphore *down_write_failed_biased(struct rw_semaphore *sem)
-{
-        struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */
-
-       for (;;) {
-               if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
-                       break;
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (!sem->write_bias_granted)
-                       schedule();
-       }
-
-       remove_wait_queue(&sem->write_bias_wait, &wait);
-       tsk->state = TASK_RUNNING;
-
-       /* if the lock is currently unbiased, awaken the sleepers
-        * FIXME: this wakes up the readers early in a bit of a
-        * stampede -> bad!
-        */
-       if (atomic_read(&sem->count) >= 0)
-               wake_up(&sem->wait);
-
-       return sem;
-}
-
-/* Wait for the lock to become unbiased.  Readers
- * are non-exclusive. =)
- */
-struct rw_semaphore *down_read_failed(struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       /* this takes care of granting the lock */
-       __up_op_read(sem, __rwsem_wake);
-
-       add_wait_queue(&sem->wait, &wait);
-
-       while (atomic_read(&sem->count) < 0) {
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (atomic_read(&sem->count) >= 0)
-                       break;
-               schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-
-       return sem;
-}
-
-/* Wait for the lock to become unbiased. Since we're
- * a writer, we'll make ourselves exclusive.
- */
-struct rw_semaphore *down_write_failed(struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       /* this takes care of granting the lock */
-       __up_op_write(sem, __rwsem_wake);
-
-       add_wait_queue_exclusive(&sem->wait, &wait);
-
-       while (atomic_read(&sem->count) < 0) {
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (atomic_read(&sem->count) >= 0)
-                       break;  /* we must attempt to acquire or bias the lock */
-               schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-
-       return sem;
-}
-
-/* Called when someone has done an up that transitioned from
- * negative to non-negative, meaning that the lock has been
- * granted to whomever owned the bias.
- */
-struct rw_semaphore *rwsem_wake_readers(struct rw_semaphore *sem)
-{
-       if (xchg(&sem->read_bias_granted, 1))
-               BUG();
-       wake_up(&sem->wait);
-       return sem;
-}
-
-struct rw_semaphore *rwsem_wake_writer(struct rw_semaphore *sem)
-{
-       if (xchg(&sem->write_bias_granted, 1))
-               BUG();
-       wake_up(&sem->write_bias_wait);
-       return sem;
-}
-
-/*
- * The semaphore operations have a special calling sequence that
- * allow us to do a simpler in-line version of them. These routines
- * need to convert that sequence back into the C sequence when
- * there is contention on the semaphore.
- *
- * ip contains the semaphore pointer on entry. Save the C-clobbered
- * registers (r0 to r3 and lr), but not ip, as we use it as a return
- * value in some cases..
- */
-#ifdef CONFIG_CPU_26
-asm("  .section        .text.lock, \"ax\"
-       .align  5
-       .globl  __down_failed
-__down_failed:
-       stmfd   sp!, {r0 - r3, lr}
-       mov     r0, ip
-       bl      __down
-       ldmfd   sp!, {r0 - r3, pc}^
-
-       .align  5
-       .globl  __down_interruptible_failed
-__down_interruptible_failed:
-       stmfd   sp!, {r0 - r3, lr}
-       mov     r0, ip
-       bl      __down_interruptible
-       mov     ip, r0
-       ldmfd   sp!, {r0 - r3, pc}^
-
-       .align  5
-       .globl  __down_trylock_failed
-__down_trylock_failed:
-       stmfd   sp!, {r0 - r3, lr}
-       mov     r0, ip
-       bl      __down_trylock
-       mov     ip, r0
-       ldmfd   sp!, {r0 - r3, pc}^
-
-       .align  5
-       .globl  __up_wakeup
-__up_wakeup:
-       stmfd   sp!, {r0 - r3, lr}
-       mov     r0, ip
-       bl      __up
-       ldmfd   sp!, {r0 - r3, pc}^
-
-       .align  5
-       .globl  __down_read_failed
-__down_read_failed:
-       stmfd   sp!, {r0 - r3, lr}
-       mov     r0, ip
-       bcc     1f
-1:     bl      down_read_failed_biased
-       ldmfd   sp!, {r0 - r3, pc}^
-2:     bl      down_read_failed
-       mov     r1, pc
-       orr     r2, r1, #
-       teqp r2, #0
-
-       ldr     r3, [r0]
-       subs    r3, r3, #1
-       str     r3, [r0]
-       ldmplfd sp!, {r0 - r3, pc}^
-  orrcs r1, r1, #0x20000000   @ Set carry
-  teqp r1, #0
-       bcc     2b
-       b       1b
-
-       .align  5
-       .globl  __down_write_failed
-__down_write_failed:
-       stmfd   sp!, {r0 - r3, lr}
-       mov     r0, ip
-       bcc     1f
-1:     bl      down_write_failed_biased
-       ldmfd   sp!, {r0 - r3, pc}^
-2:     bl      down_write_failed
-       mov r1, pc
-       orr     r2, r1, #128
-       teqp r2, #0
-
-       ldr     r3, [r0]
-       subs    r3, r3, #"RW_LOCK_BIAS_STR"
-       str     r3, [r0]
-       ldmeqfd sp!, {r0 - r3, pc}^
-  orrcs r1, r1, #0x20000000   @ Set carry
-       teqp r1, #0
-       bcc     2b
-       b       1b
-
-       .align  5
-       .globl  __rwsem_wake
-__rwsem_wake:
-       stmfd   sp!, {r0 - r3, lr}
-       mov     r0, ip
-       beq     1f
-       bl      rwsem_wake_readers
-       ldmfd   sp!, {r0 - r3, pc}^
-1:     bl      rwsem_wake_writer
-       ldmfd   sp!, {r0 - r3, pc}^
-
-       .previous
-       ");
-
-#else
-/* 32 bit version */
-asm("  .section        .text.lock, \"ax\"
-       .align  5
-       .globl  __down_failed
-__down_failed:
-       stmfd   sp!, {r0 - r3, lr}
-       mov     r0, ip
-       bl      __down
-       ldmfd   sp!, {r0 - r3, pc}
-
-       .align  5
-       .globl  __down_interruptible_failed
-__down_interruptible_failed:
-       stmfd   sp!, {r0 - r3, lr}
-       mov     r0, ip
-       bl      __down_interruptible
-       mov     ip, r0
-       ldmfd   sp!, {r0 - r3, pc}
-
-       .align  5
-       .globl  __down_trylock_failed
-__down_trylock_failed:
-       stmfd   sp!, {r0 - r3, lr}
-       mov     r0, ip
-       bl      __down_trylock
-       mov     ip, r0
-       ldmfd   sp!, {r0 - r3, pc}
-
-       .align  5
-       .globl  __up_wakeup
-__up_wakeup:
-       stmfd   sp!, {r0 - r3, lr}
-       mov     r0, ip
-       bl      __up
-       ldmfd   sp!, {r0 - r3, pc}
-
-       .align  5
-       .globl  __down_read_failed
-__down_read_failed:
-       stmfd   sp!, {r0 - r3, lr}
-       mov     r0, ip
-       bcc     1f
-1:     bl      down_read_failed_biased
-       ldmfd   sp!, {r0 - r3, pc}
-2:     bl      down_read_failed
-       mrs     r1, cpsr
-       orr     r2, r1, #128
-       msr     cpsr_c, r2
-       ldr     r3, [r0]
-       subs    r3, r3, #1
-       str     r3, [r0]
-       msr     cpsr_c, r1
-       ldmplfd sp!, {r0 - r3, pc}
-       bcc     2b
-       b       1b
-
-       .align  5
-       .globl  __down_write_failed
-__down_write_failed:
-       stmfd   sp!, {r0 - r3, lr}
-       mov     r0, ip
-       bcc     1f
-1:     bl      down_write_failed_biased
-       ldmfd   sp!, {r0 - r3, pc}
-2:     bl      down_write_failed
-       mrs     r1, cpsr
-       orr     r2, r1, #128
-       msr     cpsr_c, r2
-       ldr     r3, [r0]
-       subs    r3, r3, #"RW_LOCK_BIAS_STR"
-       str     r3, [r0]
-       msr     cpsr_c, r1
-       ldmeqfd sp!, {r0 - r3, pc}
-       bcc     2b
-       b       1b
-
-       .align  5
-       .globl  __rwsem_wake
-__rwsem_wake:
-       stmfd   sp!, {r0 - r3, lr}
-       mov     r0, ip
-       beq     1f
-       bl      rwsem_wake_readers
-       ldmfd   sp!, {r0 - r3, pc}
-1:     bl      rwsem_wake_writer
-       ldmfd   sp!, {r0 - r3, pc}
-
-       .previous
-       ");
-
-#endif
index 9d73c03..02a49c7 100644 (file)
@@ -5,6 +5,8 @@
 mainmenu_name "Linux/CRIS Kernel Configuration"
 
 define_bool CONFIG_UID16 y
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 mainmenu_option next_comment
 comment 'Code maturity level options'
index 5a9478f..d62b355 100644 (file)
@@ -127,112 +127,3 @@ int __down_trylock(struct semaphore * sem)
 {
        return waking_non_zero_trylock(sem);
 }
-
-/*
- * RW Semaphores
- */
-void
-__down_read(struct rw_semaphore *sem, int count)
-{
-       DOWN_VAR;
-
- retry_down:
-       if (count < 0) {
-               /* Wait for the lock to become unbiased.  Readers
-                  are non-exclusive.  */
-               
-               /* This takes care of granting the lock.  */
-               up_read(sem);
-
-               add_wait_queue(&sem->wait, &wait);
-               while (atomic_read(&sem->count) < 0) {
-                       set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-                       if (atomic_read(&sem->count) >= 0)
-                               break;
-                       schedule();
-               }
-
-               remove_wait_queue(&sem->wait, &wait);
-               tsk->state = TASK_RUNNING;
-
-               mb();
-               count = atomic_dec_return(&sem->count);
-               if (count <= 0)
-                       goto retry_down;
-       } else {
-               add_wait_queue(&sem->wait, &wait);
-
-               while (1) {
-                       if (test_and_clear_bit(0, &sem->granted))
-                               break;
-                       set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-                       if ((sem->granted & 1) == 0)
-                               schedule();
-               }
-
-               remove_wait_queue(&sem->wait, &wait);
-               tsk->state = TASK_RUNNING;
-       }
-}
-
-void
-__down_write(struct rw_semaphore *sem, int count)
-{
-       DOWN_VAR;
-
- retry_down:
-       if (count + RW_LOCK_BIAS < 0) {
-               up_write(sem);
-
-               add_wait_queue_exclusive(&sem->wait, &wait);
-       
-               while (atomic_read(&sem->count) < 0) {
-                       set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-                       if (atomic_read(&sem->count) >= RW_LOCK_BIAS)
-                               break;
-                       schedule();
-               }
-
-               remove_wait_queue(&sem->wait, &wait);
-               tsk->state = TASK_RUNNING;
-
-               mb();
-               count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
-               if (count != 0)
-                       goto retry_down;
-       } else {
-               /* Put ourselves at the end of the list.  */
-               add_wait_queue_exclusive(&sem->write_bias_wait, &wait);
-
-               while (1) {
-                       if (test_and_clear_bit(1, &sem->granted))
-                               break;
-                       set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-                       if ((sem->granted & 2) == 0)
-                               schedule();
-               }
-
-               remove_wait_queue(&sem->write_bias_wait, &wait);
-               tsk->state = TASK_RUNNING;
-
-               /* If the lock is currently unbiased, awaken the sleepers.
-                  FIXME: This wakes up the readers early in a bit of a
-                  stampede -> bad!  */
-               if (atomic_read(&sem->count) >= 0)
-                       wake_up(&sem->wait);
-       }
-}
-
-void
-__rwsem_wake(struct rw_semaphore *sem, unsigned long readers)
-{
-       if (readers) {
-               if (test_and_set_bit(0, &sem->granted))
-                       BUG();
-               wake_up(&sem->wait);
-       } else {
-               if (test_and_set_bit(1, &sem->granted))
-                       BUG();
-               wake_up(&sem->write_bias_wait);
-       }
-}
index 72b13df..5fa86af 100644 (file)
@@ -9,6 +9,8 @@ define_bool CONFIG_ISA y
 define_bool CONFIG_SBUS n
 
 define_bool CONFIG_UID16 y
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
 
 mainmenu_option next_comment
 comment 'Code maturity level options'
index d591e44..f53734f 100644 (file)
@@ -34,6 +34,8 @@ __generic_copy_from_user(void *to, const void *from, unsigned long n)
                else
                        mmx_copy_user_zeroing(to, from, n);
        }
+       else
+               memset(to, 0, n);
        return n;
 }
 
@@ -52,6 +54,8 @@ __generic_copy_from_user(void *to, const void *from, unsigned long n)
 {
        if (access_ok(VERIFY_READ, from, n))
                __copy_user_zeroing(to,from,n);
+       else
+               memset(to, 0, n);
        return n;
 }
 
index 24c0e99..eede124 100644 (file)
@@ -23,6 +23,8 @@ define_bool CONFIG_ISA n
 define_bool CONFIG_EISA n
 define_bool CONFIG_MCA n
 define_bool CONFIG_SBUS n
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 choice 'IA-64 processor type' \
        "Itanium                        CONFIG_ITANIUM \
index f260999..da6de32 100644 (file)
@@ -155,180 +155,3 @@ __down_trylock (struct semaphore *sem)
        spin_unlock_irqrestore(&semaphore_lock, flags);
        return 1;
 }
-
-/*
- * Helper routines for rw semaphores.  These could be optimized some
- * more, but since they're off the critical path, I prefer clarity for
- * now...
- */
-
-/*
- * This gets called if we failed to acquire the lock, but we're biased
- * to acquire the lock by virtue of causing the count to change from 0
- * to -1.  Being biased, we sleep and attempt to grab the lock until
- * we succeed.  When this function returns, we own the lock.
- */
-static inline void
-down_read_failed_biased (struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       add_wait_queue(&sem->wait, &wait);      /* put ourselves at the head of the list */
-
-       for (;;) {
-               if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
-                       break;
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (!sem->read_bias_granted)
-                       schedule();
-       }
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-}
-
-/*
- * This gets called if we failed to acquire the lock and we are not
- * biased to acquire the lock.  We undo the decrement that was
- * done earlier, go to sleep, and then attempt to re-acquire the
- * lock afterwards.
- */
-static inline void
-down_read_failed (struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       /*
-        * Undo the decrement we did in down_read() and check if we
-        * need to wake up someone.
-        */
-       __up_read(sem);
-
-       add_wait_queue(&sem->wait, &wait);
-       while (sem->count < 0) {
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (sem->count >= 0)
-                       break;
-               schedule();
-       }
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-}
-
-/*
- * Wait for the lock to become unbiased.  Readers are non-exclusive.
- */
-void
-__down_read_failed (struct rw_semaphore *sem, long count)
-{
-       while (1) {
-               if (count == -1) {
-                       down_read_failed_biased(sem);
-                       return;
-               }
-               /* unbiased */
-               down_read_failed(sem);
-
-               count = ia64_fetch_and_add(-1, &sem->count);
-               if (count >= 0)
-                       return;
-       }
-}
-
-static inline void
-down_write_failed_biased (struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       /* put ourselves at the end of the list */
-       add_wait_queue_exclusive(&sem->write_bias_wait, &wait);
-
-       for (;;) {
-               if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
-                       break;
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (!sem->write_bias_granted)
-                       schedule();
-       }
-
-       remove_wait_queue(&sem->write_bias_wait, &wait);
-       tsk->state = TASK_RUNNING;
-
-       /*
-        * If the lock is currently unbiased, awaken the sleepers
-        * FIXME: this wakes up the readers early in a bit of a
-        * stampede -> bad!
-        */
-       if (sem->count >= 0)
-               wake_up(&sem->wait);
-}
-
-
-static inline void
-down_write_failed (struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       __up_write(sem);        /* this takes care of granting the lock */
-
-       add_wait_queue_exclusive(&sem->wait, &wait);
-
-       while (sem->count < 0) {
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (sem->count >= 0)
-                       break;  /* we must attempt to acquire or bias the lock */
-               schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-}
-
-
-/*
- * Wait for the lock to become unbiased.  Since we're a writer, we'll
- * make ourselves exclusive.
- */
-void
-__down_write_failed (struct rw_semaphore *sem, long count)
-{
-       long old_count;
-
-       while (1) {
-               if (count == -RW_LOCK_BIAS) {
-                       down_write_failed_biased(sem);
-                       return;
-               }
-               down_write_failed(sem);
-
-               do {
-                       old_count = sem->count;
-                       count = old_count - RW_LOCK_BIAS;
-               } while (cmpxchg_acq(&sem->count, old_count, count) != old_count);
-
-               if (count == 0)
-                       return;
-       }
-}
-
-void
-__rwsem_wake (struct rw_semaphore *sem, long count)
-{
-       wait_queue_head_t *wq;
-
-       if (count == 0) {
-               /* wake a writer */
-               if (xchg(&sem->write_bias_granted, 1))
-                       BUG();
-               wq = &sem->write_bias_wait;
-       } else {
-               /* wake reader(s) */
-               if (xchg(&sem->read_bias_granted, 1))
-                       BUG();
-               wq = &sem->wait;
-       }
-       wake_up(wq);    /* wake up everyone on the wait queue */
-}
index 6136c40..767e85a 100644 (file)
@@ -769,20 +769,6 @@ static int amiga_wait_key (struct console *co)
     return 0;
 }
 
-void dbprintf(const char *fmt , ...)
-{
-       static char buf[1024];
-       va_list args;
-       extern void console_print (const char *str);
-       extern int vsprintf(char * buf, const char * fmt, va_list args);
-
-       va_start(args, fmt);
-       vsprintf(buf, fmt, args);
-       va_end(args);
-
-       console_print (buf);
-}
-
 static NORET_TYPE void amiga_reset( void )
     ATTRIB_NORET;
 
index 6a0bc42..c288ebe 100644 (file)
@@ -4,6 +4,8 @@
 #
 
 define_bool CONFIG_UID16 y
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 mainmenu_name "Linux/68k Kernel Configuration"
 
index d824c4e..690efce 100644 (file)
@@ -130,111 +130,3 @@ int __down_trylock(struct semaphore * sem)
 {
        return waking_non_zero_trylock(sem);
 }
-
-
-/* Wait for the lock to become unbiased.  Readers
- * are non-exclusive. =)
- */
-void down_read_failed(struct rw_semaphore *sem)
-{
-       DECLARE_WAITQUEUE(wait, current);
-
-       __up_read(sem); /* this takes care of granting the lock */
-
-       add_wait_queue(&sem->wait, &wait);
-
-       while (atomic_read(&sem->count) < 0) {
-               set_task_state(current, TASK_UNINTERRUPTIBLE);
-               if (atomic_read(&sem->count) >= 0)
-                       break;
-               schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       current->state = TASK_RUNNING;
-}
-
-void down_read_failed_biased(struct rw_semaphore *sem)
-{
-       DECLARE_WAITQUEUE(wait, current);
-
-       add_wait_queue(&sem->wait, &wait);      /* put ourselves at the head of the list */
-
-       for (;;) {
-               if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
-                       break;
-               set_task_state(current, TASK_UNINTERRUPTIBLE);
-                if (!sem->read_bias_granted)
-                       schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       current->state = TASK_RUNNING;
-}
-
-
-/* Wait for the lock to become unbiased. Since we're
- * a writer, we'll make ourselves exclusive.
- */
-void down_write_failed(struct rw_semaphore *sem)
-{
-       DECLARE_WAITQUEUE(wait, current);
-
-       __up_write(sem);        /* this takes care of granting the lock */
-
-       add_wait_queue_exclusive(&sem->wait, &wait);
-
-       while (atomic_read(&sem->count) < 0) {
-               set_task_state(current, TASK_UNINTERRUPTIBLE);
-               if (atomic_read(&sem->count) >= 0)
-                       break;  /* we must attempt to acquire or bias the lock */
-               schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       current->state = TASK_RUNNING;
-}
-
-void down_write_failed_biased(struct rw_semaphore *sem)
-{
-       DECLARE_WAITQUEUE(wait, current);
-
-       add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */
-
-       for (;;) {
-               if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
-                       break;
-               set_task_state(current, TASK_UNINTERRUPTIBLE);
-               if (!sem->write_bias_granted)
-                       schedule();
-       }
-
-       remove_wait_queue(&sem->write_bias_wait, &wait);
-       current->state = TASK_RUNNING;
-
-       /* if the lock is currently unbiased, awaken the sleepers
-        * FIXME: this wakes up the readers early in a bit of a
-        * stampede -> bad!
-        */
-       if (atomic_read(&sem->count) >= 0)
-               wake_up(&sem->wait);
-}
-
-
-/* Called when someone has done an up that transitioned from
- * negative to non-negative, meaning that the lock has been
- * granted to whomever owned the bias.
- */
-void rwsem_wake_readers(struct rw_semaphore *sem)
-{
-       if (xchg(&sem->read_bias_granted, 1))
-               BUG();
-       wake_up(&sem->wait);
-}
-
-void rwsem_wake_writer(struct rw_semaphore *sem)
-{
-       if (xchg(&sem->write_bias_granted, 1))
-               BUG();
-       wake_up(&sem->write_bias_wait);
-}
index 4e54e49..035f096 100644 (file)
 #include <linux/blk.h>
 #endif
 
-#ifndef CONFIG_AMIGA
-#define dbprintf       printk
-#endif
-
 unsigned long m68k_machtype;
 unsigned long m68k_cputype;
 unsigned long m68k_fputype;
index 23cd0c3..f0cfda4 100644 (file)
 #
 ifdef CONFIG_CPU_LITTLE_ENDIAN
 tool-prefix    = mipsel-linux-
+output-format  = elf32-littlemips
 else
 tool-prefix    = mips-linux-
+output-format  = elf32-bigmips
 endif
 
 ifdef CONFIG_CROSSCOMPILE
@@ -26,16 +28,16 @@ CROSS_COMPILE  = $(tool-prefix)
 endif
 
 #
-# The ELF GCC uses -G0 -mabicalls -fpic as default.  We don't need PIC
-# code in the kernel since it only slows down the whole thing.  For the
-# old GCC these options are just the defaults.  At some point we might
-# make use of global pointer optimizations.
+# GCC uses -G0 -mabicalls -fpic as default.  We don't want PIC in the kernel
+# code since it only slows down the whole thing.  At some point we might make
+# use of global pointer optimizations but their use of $28 conflicts with
+# the current pointer optimization.
 #
 # The DECStation requires an ECOFF kernel for remote booting, other MIPS
 # machines may also.  Since BFD is incredibly buggy with respect to
 # crossformat linking we rely on the elf2ecoff tool for format conversion.
 #
-CFLAGS         += -G 0 -mno-abicalls -fno-pic
+GCCFLAGS       := -G 0 -mno-abicalls -fno-pic
 LINKFLAGS      += -static -G 0
 MODFLAGS       += -mlong-calls
 
@@ -47,37 +49,63 @@ endif
 # CPU-dependent compiler/assembler options for optimization.
 #
 ifdef CONFIG_CPU_R3000
-CFLAGS         := $(CFLAGS) -mcpu=r3000 -mips1
+GCCFLAGS       += -mcpu=r3000 -mips1
+endif
+ifdef CONFIG_CPU_R3912
+GCCFLAGS       += -mcpu=r3000 -mips1
 endif
 ifdef CONFIG_CPU_R6000
-CFLAGS         := $(CFLAGS) -mcpu=r6000 -mips2 -Wa,--trap
+GCCFLAGS       += -mcpu=r6000 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_R4300
-CFLAGS         := $(CFLAGS) -mcpu=r4300 -mips2 -Wa,--trap
+GCCFLAGS       += -mcpu=r4300 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_R4X00
-CFLAGS         := $(CFLAGS) -mcpu=r4600 -mips2 -Wa,--trap
+GCCFLAGS       += -mcpu=r4600 -mips2 -Wa,--trap
+endif
+ifdef CONFIG_CPU_MIPS32
+GCCFLAGS       += -mcpu=r4600 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_R5000
-CFLAGS         := $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap
+GCCFLAGS       += -mcpu=r8000 -mips2 -Wa,--trap
+endif
+ifdef CONFIG_CPU_R5432
+GCCFLAGS        += -mcpu=r8000 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_NEVADA
-CFLAGS         := $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap -mmad
+GCCFLAGS       += -mcpu=r8000 -mips2 -Wa,--trap -mmad
+endif
+ifdef CONFIG_CPU_RM7000
+GCCFLAGS       += -mcpu=r8000 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_R8000
-CFLAGS         := $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap
+GCCFLAGS       += -mcpu=r8000 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_R10000
-CFLAGS         := $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap
+GCCFLAGS       += -mcpu=r8000 -mips2 -Wa,--trap
 endif
 
+ifdef CONFIG_MIPS_FPU_EMULATOR
+CORE_FILES     +=arch/mips/math-emu/fpu_emulator.o
+SUBDIRS                +=arch/mips/math-emu
+endif
+
+#
+# The pipe options is bad for my low-mem machine
+# Uncomment this if you want this.
+#
+GCCFLAGS       += -pipe
+
+CFLAGS         := -I $(TOPDIR)/include/asm/gcc $(CFLAGS) $(GCCFLAGS)
+AFLAGS         += $(GCCFLAGS)
+
 #
 # Board-dependent options and extra files
 #
 ifdef CONFIG_ALGOR_P4032
 CORE_FILES    += arch/mips/algor/algor.o
 SUBDIRS       += arch/mips/algor
-#LOADADDR      += 0x80000000
+LOADADDR      += 0x80000000
 endif
 
 #
@@ -90,6 +118,18 @@ LIBS          += arch/mips/dec/prom/rexlib.a
 LOADADDR      += 0x80040000
 endif
 
+ifdef CONFIG_MIPS_ATLAS
+LIBS          += arch/mips/mips-boards/atlas/atlas.o arch/mips/mips-boards/generic/mipsboards.o
+SUBDIRS       += arch/mips/mips-boards/generic arch/mips/mips-boards/atlas
+LOADADDR      += 0x80100000
+endif
+
+ifdef CONFIG_MIPS_MALTA
+LIBS          += arch/mips/mips-boards/malta/malta.o arch/mips/mips-boards/generic/mipsboards.o
+SUBDIRS       += arch/mips/mips-boards/malta arch/mips/mips-boards/generic
+LOADADDR      += 0x80100000
+endif
+
 #
 # Acer PICA 61, Mips Magnum 4000 and Olivetti M700.
 #
@@ -100,12 +140,6 @@ LIBS          += arch/mips/arc/arclib.a
 LOADADDR      += 0x80080000
 endif
 
-ifdef CONFIG_COBALT_MICRO_SERVER
-ARCHIVES      += arch/mips/cobalt/cobalt.o
-SUBDIRS       += arch/mips/cobalt
-LOADADDR      += 0x80000000
-endif
-
 ifdef CONFIG_SNI_RM200_PCI
 CORE_FILES    += arch/mips/sni/sni.o
 SUBDIRS       += arch/mips/sni arch/mips/arc
@@ -114,7 +148,8 @@ LOADADDR      += 0x80080000
 endif
 
 ifdef CONFIG_SGI_IP22
-LIBS          += arch/mips/sgi/kernel/sgikern.a arch/mips/arc/arclib.a
+CORE_FILES    += arch/mips/sgi/kernel/ip22-kern.o
+LIBS          += arch/mips/arc/arclib.a
 SUBDIRS       += arch/mips/sgi/kernel arch/mips/arc
 #
 # Set LOADADDR to >= 0x88069000 if you want to leave space for symmon,
@@ -152,28 +187,74 @@ LINKSCRIPT    = arch/mips/orion/ld.script.orion
 endif
 
 #
-# Choosing incompatible machines durings configuration will result in
-# error messages during linking.  Select a default linkscript if
-# none has been choosen above.
 #
-ifndef LINKSCRIPT
-ifndef CONFIG_CPU_LITTLE_ENDIAN
-LINKSCRIPT    = arch/mips/ld.script.big
-else
-LINKSCRIPT    = arch/mips/ld.script.little
+# NEC DDB Vrc-5476
+#
+ifdef CONFIG_DDB5476
+SUBDIRS       += arch/mips/ddb5476
+LIBS          += arch/mips/ddb5476/ddb5476.a
+LOADADDR      += 0x80080000
 endif
+
+#
+# Galileo EV64120 Board
+#
+ifdef CONFIG_MIPS_EV64120
+LIBS          += arch/mips/galileo-boards/ev64120/ev64120.o
+SUBDIRS       += arch/mips/galileo-boards/ev64120
+LOADADDR      += 0x80100000
 endif
-LINKFLAGS     += -T $(word 1,$(LINKSCRIPT))
 
-ifdef LOADADDR
-LINKFLAGS     += -Ttext $(word 1,$(LOADADDR))
+#
+# Galileo EV96100 Board
+#
+ifdef CONFIG_MIPS_EV96100
+LIBS          += arch/mips/galileo-boards/ev96100/ev96100.o arch/mips/galileo-boards/generic/galboards.o
+SUBDIRS       += arch/mips/galileo-boards/generic arch/mips/galileo-boards/ev96100
+LOADADDR      += 0x80100000
 endif
 
 #
-# The pipe options is bad for my low-mem machine
-# Uncomment this if you want this.
+# Momentum Ocelot board
+#
+ifdef CONFIG_MOMENCO_OCELOT
+LIBS          += arch/mips/gt64120/common/gt64120.o arch/mips/gt64120/momenco_ocelot/momenco_ocelot.o
+SUBDIRS       += arch/mips/gt64120/common arch/mips/gt64120/momenco_ocelot
+LOADADDR      += 0x80100000
+endif
+
 #
-CFLAGS         += -pipe
+# Philips Nino
+#
+ifdef CONFIG_NINO
+CORE_FILES    += arch/mips/philips/nino/nino.o \
+                arch/mips/philips/drivers/drivers.o
+SUBDIRS       += arch/mips/philips/nino arch/mips/philips/drivers
+LOADADDR      += 0x80000000
+endif
+
+#
+# ITE 8172 eval board with QED 5231 CPU
+#
+ifdef CONFIG_MIPS_ITE8172
+LIBS           += arch/mips/ite-boards/qed-4n-s01b/ite.o                    \
+                  arch/mips/ite-boards/generic/it8172.o
+SUBDIRS                += arch/mips/ite-boards/generic                              \
+                  arch/mips/ite-boards/qed-4n-s01b
+LOADADDR       += 0x80100000
+endif
+
+#
+# Choosing incompatible machines durings configuration will result in
+# error messages during linking.  Select a default linkscript if
+# none has been choosen above.
+#
+vmlinux: arch/$(ARCH)/ld.script
+
+arch/$(ARCH)/ld.script: arch/$(ARCH)/ld.script.in arch/$(ARCH)/Makefile
+       sed -e 's/@@OUTPUT_FORMAT@@/$(output-format)/' \
+           -e 's/@@LOADADDR@@/$(LOADADDR)/' <$< >$@
+LINKFLAGS      += -T arch/$(ARCH)/ld.script
 
 HEAD := arch/mips/kernel/head.o arch/mips/kernel/init_task.o
 
@@ -197,8 +278,18 @@ orionboot:
        $(ORIONBOOT) orionboot
 endif
 
+ifdef CONFIG_MIPS_EV64120
+GALILEOBOOT = $(MAKE) -C arch/$(ARCH)/galileo-boards/ev64120
+
+gboot: vmlinux
+       $(MAKE) -C arch/$(ARCH)/galileo-boards/ev64120/compressed 
+endif
+
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 
+vmlinux.ecoff: vmlinux
+       @$(MAKEBOOT) $@
+
 zImage: vmlinux
        @$(MAKEBOOT) zImage
 
@@ -209,7 +300,7 @@ zdisk: vmlinux
 
 archclean:
        @$(MAKEBOOT) clean
-       $(MAKE) -C arch/$(ARCH)/kernel clean
+       rm -f arch/$(ARCH)/ld.script
        $(MAKE) -C arch/$(ARCH)/tools clean
        $(MAKE) -C arch/mips/baget clean
 
index 7bfefcf..acba7ef 100644 (file)
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.1 1998/10/18 13:32:08 tsbogend Exp $
 #
 # Makefile for the SGI arcs prom monitor library routines
 # under Linux.
@@ -10,7 +9,10 @@
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
 L_TARGET = arclib.a
-L_OBJS  = console.o init.o printf.o memory.o tree.o env.o cmdline.o misc.o \
-         time.o file.o identify.o
+
+obj-y          += console.o init.o memory.o tree.o env.o cmdline.o misc.o \
+                  time.o file.o identify.o
+
+obj-$(CONFIG_ARC_CONSOLE)   += arc_con.o
 
 include $(TOPDIR)/Rules.make
diff --git a/arch/mips/arc/arc_con.c b/arch/mips/arc/arc_con.c
new file mode 100644 (file)
index 0000000..6fe94a6
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Wrap-around code for a console using the
+ * ARC io-routines.
+ *
+ * Copyright (c) 1998 Harald Koerfgen 
+ */
+
+#include <linux/tty.h>
+#include <linux/major.h>
+#include <linux/ptrace.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/fs.h>
+
+extern char prom_getchar (void);
+extern void prom_printf (char *, ...);
+
+static void prom_console_write(struct console *co, const char *s,
+                              unsigned count)
+{
+       unsigned i;
+
+       /*
+        *    Now, do each character
+        */
+       for (i = 0; i < count; i++) {
+               if (*s == 10)
+                       prom_printf("%c", 13);
+               prom_printf("%c", *s++);
+       }
+}
+
+static int prom_console_wait_key(struct console *co)
+{
+       return prom_getchar();
+}
+
+static int __init prom_console_setup(struct console *co, char *options)
+{
+       return 0;
+}
+
+static kdev_t prom_console_device(struct console *c)
+{
+       return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+static struct console arc_cons = {
+       "ttyS",
+       prom_console_write,
+       NULL,
+       prom_console_device,
+       prom_console_wait_key,
+       NULL,
+       prom_console_setup,
+       CON_PRINTBUFFER,
+       -1,
+       0,
+       NULL
+};
+
+/*
+ *    Register console.
+ */
+
+void __init arc_console_init(void)
+{
+       register_console(&arc_cons);
+}
index d60ff2b..e6f3483 100644 (file)
@@ -2,8 +2,6 @@
  * cmdline.c: Kernel command line creation using ARCS argc/argv.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: cmdline.c,v 1.1 1998/10/18 13:32:08 tsbogend Exp $
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -12,9 +10,9 @@
 #include <asm/sgialib.h>
 #include <asm/bootinfo.h>
 
-/* #define DEBUG_CMDLINE */
+#undef DEBUG_CMDLINE
 
-char arcs_cmdline[CL_SIZE];
+char arcs_cmdline[COMMAND_LINE_SIZE];
 
 char * __init prom_getcmdline(void)
 {
index 4de5130..8138dbd 100644 (file)
@@ -1,50 +1,99 @@
 /*
- * console.c: SGI arcs console code.
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
  *
  * Copyright (C) 1996 David S. Miller (dm@sgi.com)
  * Compability with board caches, Ulf Carlsson
- *
- * $Id: console.c,v 1.3 1999/10/09 00:00:57 ralf Exp $
  */
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <asm/sgialib.h>
 #include <asm/bcache.h>
+#include <linux/console.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+
+#ifdef CONFIG_ARC_CONSOLE
+#define __init
+#endif
 
-/* The romvec is not compatible with board caches.  Thus we disable it during
- * romvec action.  Since r4xx0.c is always compiled and linked with your kernel,
- * this shouldn't cause any harm regardless what MIPS processor you have.
+/*
+ * IP22 boardcache is not compatible with board caches.  Thus we disable it
+ * during romvec action.  Since r4xx0.c is always compiled and linked with your
+ * kernel, this shouldn't cause any harm regardless what MIPS processor you
+ * have.
  *
- * The romvec write and read functions seem to interfere with the serial lines
+ * The ARC write and read functions seem to interfere with the serial lines
  * in some way. You should be careful with them.
  */
-extern struct bcache_ops *bcops;
 
-#ifdef CONFIG_SGI_PROM_CONSOLE
-void prom_putchar(char c)
-#else
 void __init prom_putchar(char c)
-#endif
 {
        long cnt;
        char it = c;
 
-       bcops->bc_disable();
+       bc_disable();
        romvec->write(1, &it, 1, &cnt);
-       bcops->bc_enable();
+       bc_enable();
 }
 
-#ifdef CONFIG_SGI_PROM_CONSOLE
-char prom_getchar(void)
-#else
 char __init prom_getchar(void)
-#endif
 {
        long cnt;
        char c;
 
-       bcops->bc_disable();
+       bc_disable();
        romvec->read(0, &c, 1, &cnt);
-       bcops->bc_enable();
+       bc_enable();
+
        return c;
 }
+
+static char ppbuf[1024];
+
+void __init prom_printf(char *fmt, ...)
+{
+       va_list args;
+       char ch, *bptr;
+       int i;
+
+       va_start(args, fmt);
+       i = vsprintf(ppbuf, fmt, args);
+
+       bptr = ppbuf;
+
+       while ((ch = *(bptr++)) != 0) {
+               if (ch == '\n')
+                       prom_putchar('\r');
+
+               prom_putchar(ch);
+       }
+       va_end(args);
+}
+
+static void
+arc_console_write(struct console *con, const char *s, unsigned n)
+{
+       prom_printf("%s", s);
+}
+
+static kdev_t 
+arc_console_dev(struct console *c)
+{
+       return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+static struct console arc_prom_console = {
+    name:      "prom",
+    write:     arc_console_write,
+    device:    arc_console_dev,
+    flags:     CON_PRINTBUFFER,
+    index:     -1,
+};
+
+__init void arc_setup_console(void)
+{
+       register_console(&arc_prom_console);
+}
index 8cc0a22..a2ee29f 100644 (file)
@@ -6,8 +6,6 @@
  * This code is based on arch/mips/sgi/kernel/system.c, which is
  * 
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: identify.c,v 1.2 1999/02/25 21:04:13 tsbogend Exp $
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <asm/bootinfo.h>
 
 struct smatch {
-    char *name;
-    int group;
-    int type;
-    int flags;
+       char *name;
+       int group;
+       int type;
+       int flags;
 };
 
 static struct smatch mach_table[] = {
-    { "SGI-IP22", MACH_GROUP_SGI, MACH_SGI_INDY, PROM_FLAG_ARCS },
-    { "Microsoft-Jazz", MACH_GROUP_JAZZ, MACH_MIPS_MAGNUM_4000, 0 },
-    { "PICA-61", MACH_GROUP_JAZZ, MACH_ACER_PICA_61, 0 },
-    { "RM200PCI", MACH_GROUP_SNI_RM, MACH_SNI_RM200_PCI, 0 }
+       {"SGI-IP22", MACH_GROUP_SGI, MACH_SGI_INDY, PROM_FLAG_ARCS},
+       {"Microsoft-Jazz", MACH_GROUP_JAZZ, MACH_MIPS_MAGNUM_4000, 0},
+       {"PICA-61", MACH_GROUP_JAZZ, MACH_ACER_PICA_61, 0},
+       {"RM200PCI", MACH_GROUP_SNI_RM, MACH_SNI_RM200_PCI, 0}
 };
 
 int prom_flags;
 
-static struct smatch * __init string_to_mach(char *s)
+static struct smatch *__init string_to_mach(char *s)
 {
-    int i;
-    
-    for (i = 0; i < sizeof (mach_table); i++) {
-       if(!strcmp(s, mach_table[i].name))
-           return &mach_table[i];
-    }
-    prom_printf("\nYeee, could not determine architecture type <%s>\n", s);
-    prom_printf("press a key to reboot\n");
-    prom_getchar();
-    romvec->imode();
-    return NULL;
+       int i;
+
+       for (i = 0; i < sizeof(mach_table); i++) {
+               if (!strcmp(s, mach_table[i].name))
+                       return &mach_table[i];
+       }
+       prom_printf("\nYeee, could not determine architecture type <%s>\n",
+                   s);
+       prom_printf("press a key to reboot\n");
+       prom_getchar();
+       romvec->imode();
+       return NULL;
 }
 
 void __init prom_identify_arch(void)
 {
-    pcomponent *p;
-    struct smatch *mach;
-    
-    /* The root component tells us what machine architecture we
-     * have here.
-     */
-    p = prom_getchild(PROM_NULL_COMPONENT);
-    printk("ARCH: %s\n", p->iname);
-    mach = string_to_mach(p->iname);
+       pcomponent *p;
+       struct smatch *mach;
 
-    mips_machgroup = mach->group;
-    mips_machtype = mach->type;
-    prom_flags = mach->flags;
-}
+       /*
+        * The root component tells us what machine architecture we
+        * have here.
+        */
+       p = prom_getchild(PROM_NULL_COMPONENT);
+       printk("ARCH: %s\n", p->iname);
+       mach = string_to_mach(p->iname);
 
+       mips_machgroup = mach->group;
+       mips_machtype = mach->type;
+       prom_flags = mach->flags;
+}
index 05200cb..9df7557 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.5 2000/03/07 15:45:27 ralf Exp $
+/*
  * 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.
@@ -23,7 +23,9 @@ unsigned short prom_vers, prom_rev;
 
 extern void prom_testtree(void);
 
-int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+extern void arc_setup_console(void);
+
+void __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
 {
        struct linux_promblock *pb;
 
@@ -33,7 +35,20 @@ int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
        prom_argv = argv;
        prom_envp = envp;
 
-       if(pb->magic != 0x53435241) {
+#if 0
+       /* arc_printf should not use prom_printf as soon as we free
+        * the prom buffers - This horribly breaks on Indys with framebuffer
+        * as it simply stops after initialising swap - On the Indigo2 serial
+        * console you will get A LOT illegal instructions - Only enable
+        * this for early init crashes - This also brings up artefacts of
+        * printing everything twice on serial console and on GFX Console
+        * this has the effect of having the prom printing everything
+        * in the small rectangle and the kernel printing around.
+        */
+
+       arc_setup_console();
+#endif
+       if (pb->magic != 0x53435241) {
                prom_printf("Aieee, bad prom vector magic %08lx\n", pb->magic);
                while(1)
                        ;
@@ -55,5 +70,4 @@ int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
                romvec->imode();
        }
 #endif
-       return 0;
 }
index 7988cfc..3f41f74 100644 (file)
@@ -3,8 +3,6 @@
  *           given to us from the ARCS firmware.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: memory.c,v 1.10 2000/01/27 23:21:57 ralf Exp $
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -47,31 +45,25 @@ static char *arc_mtypes[8] = {
        "LoadedProgram",
        "FirmwareTemporary",
        "FirmwarePermanent",
-       "FreeContigiuous"
+       "FreeContiguous"
 };
 #define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] : arc_mtypes[a.arc]
 #endif
 
-static struct prom_pmemblock pblocks[PROM_MAX_PMEMBLOCKS];
-
-#define MEMTYPE_DONTUSE   0
-#define MEMTYPE_PROM      1
-#define MEMTYPE_FREE      2
-
 static inline int memtype_classify_arcs (union linux_memtypes type)
 {
        switch (type.arcs) {
        case arcs_fcontig:
        case arcs_free:
-               return MEMTYPE_FREE;
+               return BOOT_MEM_RAM;
        case arcs_atmp:
-               return MEMTYPE_PROM;
+               return BOOT_MEM_ROM_DATA;
        case arcs_eblock:
        case arcs_rvpage:
        case arcs_bmem:
        case arcs_prog:
        case arcs_aperm:
-               return MEMTYPE_DONTUSE;
+               return BOOT_MEM_RESERVED;
        default:
                BUG();
        }
@@ -83,15 +75,15 @@ static inline int memtype_classify_arc (union linux_memtypes type)
        switch (type.arc) {
        case arc_free:
        case arc_fcontig:
-               return MEMTYPE_FREE;
+               return BOOT_MEM_RAM;
        case arc_atmp:
-               return MEMTYPE_PROM;
+               return BOOT_MEM_ROM_DATA;
        case arc_eblock:
        case arc_rvpage:
        case arc_bmem:
        case arc_prog:
        case arc_aperm:
-               return MEMTYPE_DONTUSE;
+               return BOOT_MEM_RESERVED;
        default:
                BUG();
        }
@@ -106,50 +98,13 @@ static int __init prom_memtype_classify (union linux_memtypes type)
        return memtype_classify_arc(type);
 }
 
-static inline unsigned long find_max_low_pfn(void)
-{
-       struct prom_pmemblock *p, *highest;
-       unsigned long pfn;
-
-       p = pblocks;
-       highest = 0;
-       while (p->size != 0) {
-               if (!highest || p->base > highest->base)
-                       highest = p;
-               p++;
-       }
-
-       pfn = (highest->base + highest->size) >> PAGE_SHIFT;
-#ifdef DEBUG
-       prom_printf("find_max_low_pfn: 0x%lx pfns.\n", pfn);
-#endif
-       return pfn;
-}
-
-static inline struct prom_pmemblock *find_largest_memblock(void)
-{
-       struct prom_pmemblock *p, *largest;
-
-       p = pblocks;
-       largest = 0;
-       while (p->size != 0) {
-               if (!largest || p->size > largest->size)
-                       largest = p;
-               p++;
-       }
-
-       return largest;
-}
-
 void __init prom_meminit(void)
 {
-       struct prom_pmemblock *largest;
-       unsigned long bootmap_size;
        struct linux_mdesc *p;
-       int totram;
-       int i = 0;
 
 #ifdef DEBUG
+       int i = 0;
+
        prom_printf("ARCS MEMORY DESCRIPTOR dump:\n");
        p = ArcGetMemoryDescriptor(PROM_NULL_MDESC);
        while(p) {
@@ -160,77 +115,36 @@ void __init prom_meminit(void)
        }
 #endif
 
-       totram = 0;
-       i = 0;
        p = PROM_NULL_MDESC;
        while ((p = ArcGetMemoryDescriptor(p))) {
-               pblocks[i].type = prom_memtype_classify(p->type);
-               pblocks[i].base = p->base << PAGE_SHIFT;
-               pblocks[i].size = p->pages << PAGE_SHIFT;
+               unsigned long base, size;
+               long type;
 
-               switch (pblocks[i].type) {
-               case MEMTYPE_FREE:
-                       totram += pblocks[i].size;
-#ifdef DEBUG
-                       prom_printf("free_chunk[%d]: base=%08lx size=%x\n",
-                                   i, pblocks[i].base,
-                                   pblocks[i].size);
-#endif
-                       i++;
-                       break;
-               case MEMTYPE_PROM:
-#ifdef DEBUG
-                       prom_printf("prom_chunk[%d]: base=%08lx size=%x\n",
-                                   i, pblocks[i].base,
-                                   pblocks[i].size);
-#endif
-                       i++;
-                       break;
-               default:
-                       break;
-               }
-       }
-       pblocks[i].size = 0;
-
-       max_low_pfn = find_max_low_pfn();
-
-       largest = find_largest_memblock();
-       bootmap_size = init_bootmem(largest->base >> PAGE_SHIFT, max_low_pfn);
-
-       for (i = 0; pblocks[i].size; i++)
-               if (pblocks[i].type == MEMTYPE_FREE)
-                       free_bootmem(pblocks[i].base, pblocks[i].size);
+               base = p->base << PAGE_SHIFT;
+               size = p->pages << PAGE_SHIFT;
+               type = prom_memtype_classify(p->type);
 
-       /* This test is simpleminded.  It will fail if the bootmem bitmap
-          falls into multiple adjacent ARC memory areas.  */
-       if (bootmap_size > largest->size) {
-               prom_printf("CRITIAL: overwriting PROM data.\n");
-               BUG();
+               add_memory_region(base, size, type);
        }
-
-       /* Reserve the memory bootmap itself */
-       reserve_bootmem(largest->base, bootmap_size);
-
-       printk("PROMLIB: Total free ram %dK / %dMB.\n",
-              totram >> 10, totram >> 20);
 }
 
 void __init
 prom_free_prom_memory (void)
 {
-       struct prom_pmemblock *p;
        unsigned long freed = 0;
        unsigned long addr;
+       int i;
 
-       for (p = pblocks; p->size != 0; p++) {
-               if (p->type != MEMTYPE_PROM)
+       for (i = 0; i < boot_mem_map.nr_map; i++) {
+               if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
                        continue;
 
-               addr = PAGE_OFFSET + p->base;
-               while (addr < p->base + p->size) {
-                       ClearPageReserved(virt_to_page(addr));
-                       set_page_count(virt_to_page(addr), 1);
-                       free_page(addr);
+               addr = boot_mem_map.map[i].addr;
+               while (addr < boot_mem_map.map[i].addr
+                             + boot_mem_map.map[i].size) {
+                       ClearPageReserved(virt_to_page(__va(addr)));
+                       set_page_count(virt_to_page(__va(addr)), 1);
+                       free_page((unsigned long)__va(addr));
                        addr += PAGE_SIZE;
                        freed += PAGE_SIZE;
                }
index 4c056be..5a7edb7 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id: misc.c,v 1.1 1998/10/18 13:32:09 tsbogend Exp $
- *
+/*
  * misc.c: Miscellaneous ARCS PROM routines.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
 #include <asm/bootinfo.h>
 #include <asm/system.h>
 
-extern unsigned long mips_cputype;
 extern void *sgiwd93_host;
 extern void reset_wd33c93(void *instance);
 
 void prom_halt(void)
 {
-       bcops->bc_disable();
+       bc_disable();
        cli();
 #if CONFIG_SCSI_SGIWD93
        reset_wd33c93(sgiwd93_host);
@@ -29,7 +27,7 @@ void prom_halt(void)
 
 void prom_powerdown(void)
 {
-       bcops->bc_disable();
+       bc_disable();
        cli();
 #if CONFIG_SCSI_SGIWD93
        reset_wd33c93(sgiwd93_host);
@@ -40,7 +38,7 @@ void prom_powerdown(void)
 /* XXX is this a soft reset basically? XXX */
 void prom_restart(void)
 {
-       bcops->bc_disable();
+       bc_disable();
        cli();
 #if CONFIG_SCSI_SGIWD93
        reset_wd33c93(sgiwd93_host);
@@ -50,7 +48,7 @@ void prom_restart(void)
 
 void prom_reboot(void)
 {
-       bcops->bc_disable();
+       bc_disable();
        cli();
 #if CONFIG_SCSI_SGIWD93
        reset_wd33c93(sgiwd93_host);
@@ -60,7 +58,7 @@ void prom_reboot(void)
 
 void prom_imode(void)
 {
-       bcops->bc_disable();
+       bc_disable();
        cli();
 #if CONFIG_SCSI_SGIWD93
        reset_wd33c93(sgiwd93_host);
diff --git a/arch/mips/arc/printf.c b/arch/mips/arc/printf.c
deleted file mode 100644 (file)
index 78b1b59..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * printf.c: Putting things on the screen using SGI arcs
- *           PROM facilities.
- *
- * Copyright (C) 1996 David S. Miller (dm@sgi.com)
- *
- * $Id: printf.c,v 1.3 1999/10/09 00:00:57 ralf Exp $
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <asm/sgialib.h>
-
-static char ppbuf[1024];
-
-#ifdef CONFIG_SGI_PROM_CONSOLE
-void prom_printf(char *fmt, ...)
-#else
-void __init prom_printf(char *fmt, ...)
-#endif
-{
-       va_list args;
-       char ch, *bptr;
-       int i;
-
-       va_start(args, fmt);
-       i = vsprintf(ppbuf, fmt, args);
-
-       bptr = ppbuf;
-
-       while((ch = *(bptr++)) != 0) {
-               if(ch == '\n')
-                       prom_putchar('\r');
-
-               prom_putchar(ch);
-       }
-       va_end(args);
-       return;
-}
index f27a9e6..a62e480 100644 (file)
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.3 1999/08/13 17:07:26 harald Exp $
 #
 # Makefile for the Baget specific kernel interface routines
 # under Linux.
 all: baget.a 
 
 O_TARGET := baget.a
-O_OBJS   := baget.o print.o setup.o time.o irq.o bagetIRQ.o reset.o wbflush.o
-
-ifeq ($(CONFIG_SERIAL),y)
-       OX_OBJS += vacserial.o
-else
-       ifeq ($(CONFIG_SERIAL),m)
-               MX_OBJS += vacserial.o
-       endif
-endif
-ifeq ($(CONFIG_VAC_RTC),y)
-       OX_OBJS += vacrtc.o
-else
-       ifeq ($(CONFIG_VAC_RTC),m)
-               MX_OBJS += vacrtc.o
-       endif
-endif
+
+export-objs            := vacserial.o vacrtc.o
+obj-y                  := baget.o print.o setup.o time.o irq.o bagetIRQ.o \
+                          reset.o wbflush.o
+obj-$(CONFIG_SERIAL)   += vacserial.o
+obj-$(CONFIG_VAC_RTC)  += vacrtc.o
 
 bagetIRQ.o : bagetIRQ.S
        $(CC) $(CFLAGS) -c -o $@ $<
index a98779f..ee24ab3 100644 (file)
@@ -1,4 +1,4 @@
-# $Id$
+#
 # Makefile for the Baget/MIPS prom emulator library routines.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -7,9 +7,8 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
-O_TARGET := bagetlib.a
-O_OBJS   := init.o
+L_TARGET := bagetlib.a
 
-all:   $(O_TARGET)
+obj-y  := init.o
 
 include $(TOPDIR)/Rules.make
index 6eabec3..a1bc680 100644 (file)
@@ -28,6 +28,9 @@ bool 'Support for Olivetti M700-10' CONFIG_OLIVETTI_M700
 bool 'Support for SGI IP22' CONFIG_SGI_IP22
 bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI
 
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
+
 #
 # Select some configuration options automatically for certain systems.
 #
@@ -329,7 +332,10 @@ if [ "$CONFIG_DECSTATION" = "y" ]; then
 #   if [ "$CONFIG_ACCESSBUS" = "y" ]; then
 #      bool 'MAXINE Access.Bus mouse (VSXXX-BB/GB) support' CONFIG_DTOP_MOUSE
 #   fi
-   bool 'Enhanced Real Time Clock Support' CONFIG_RTC
+   bool 'Enhanced Real Time Clock Support' CONFIG_MIPS_RTC
+
+   define_tristate CONFIG_RTC $CONFIG_MIPS_RTC
+
    endmenu
 fi
 
index 559e0bc..15687d2 100644 (file)
@@ -8,8 +8,6 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 #
-# $Id$
-#
 
 .S.s:
        $(CPP) $(CFLAGS) $< -o $*.s
@@ -17,6 +15,7 @@
        $(CC) $(CFLAGS) -c $< -o $*.o
 
 O_TARGET = ddb5074.a
-O_OBJS  = setup.o irq.o time.o prom.o pci.o pci-dma.o int-handler.o nile4.o
+
+obj-y  := setup.o irq.o time.o prom.o pci.o int-handler.o nile4.o
 
 include $(TOPDIR)/Rules.make
index eab4d2d..a786441 100644 (file)
@@ -7,54 +7,50 @@
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id: int-handler.S,v 1.1 2000/01/26 00:07:44 ralf Exp $
  */
-
 #include <asm/asm.h>
 #include <asm/mipsregs.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
 
-       /* A lot of complication here is taken away because:
-        *
-        * 1) We handle one interrupt and return, sitting in a loop
-        *    and moving across all the pending IRQ bits in the cause
-        *    register is _NOT_ the answer, the common case is one
-        *    pending IRQ so optimize in that direction.
-        *
-        * 2) We need not check against bits in the status register
-        *    IRQ mask, that would make this routine slow as hell.
-        *
-        * 3) Linux only thinks in terms of all IRQs on or all IRQs
-        *    off, nothing in between like BSD spl() brain-damage.
-        *
-        * Furthermore, the IRQs on the INDY look basically (barring
-        * software IRQs which we don't use at all) like:
-        *
-        *      MIPS IRQ        Source
-        *      --------        ------
-        *             0        Software (ignored)
-        *             1        Software (ignored)
-        *             2        Local IRQ level zero
-        *             3        Local IRQ level one
-        *             4        8254 Timer zero
-        *             5        8254 Timer one
-        *             6        Bus Error
-        *             7        R4k timer (what we use)
-        *
-        * We handle the IRQ according to _our_ priority which is:
-        *
-        * Highest ----     R4k Timer
-        *                  Local IRQ zero
-        *                  Local IRQ one
-        *                  Bus Error
-        *                  8254 Timer zero
-        * Lowest  ----     8254 Timer one
-        *
-        * then we just return, if multiple IRQs are pending then
-        * we will just take another exception, big deal.
-        */
+/* A lot of complication here is taken away because:
+ *
+ * 1) We handle one interrupt and return, sitting in a loop and moving across
+ *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
+ *    common case is one pending IRQ so optimize in that direction.
+ *
+ * 2) We need not check against bits in the status register IRQ mask, that
+ *    would make this routine slow as hell.
+ *
+ * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
+ *    between like BSD spl() brain-damage.
+ *
+ * Furthermore, the IRQs on the INDY look basically (barring software IRQs
+ * which we don't use at all) like:
+ *
+ *     MIPS IRQ        Source
+ *      --------        ------
+ *             0       Software (ignored)
+ *             1        Software (ignored)
+ *             2        Local IRQ level zero
+ *             3        Local IRQ level one
+ *             4        8254 Timer zero
+ *             5        8254 Timer one
+ *             6        Bus Error
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ *                  Local IRQ zero
+ *                  Local IRQ one
+ *                  Bus Error
+ *                  8254 Timer zero
+ * Lowest  ----     8254 Timer one
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
 
        .text
        .set    noreorder
index 31813fe..c2b9ad9 100644 (file)
@@ -3,10 +3,7 @@
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id: irq.c,v 1.1 2000/01/26 00:07:44 ralf Exp $
  */
-
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/signal.h>
@@ -14,6 +11,7 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/ptrace.h>
@@ -27,7 +25,7 @@ extern void i8259_enable_irq(unsigned int irq_nr);
 
 extern asmlinkage void ddbIRQ(void);
 extern asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs);
-extern asmlinkage void do_IRQ(int irq, struct pt_regs * regs);
+extern asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
 
 
 void no_action(int cpl, void *dev_id, struct pt_regs *regs)
@@ -55,177 +53,174 @@ void no_action(int cpl, void *dev_id, struct pt_regs *regs)
 
 static void m1543_irq_setup(void)
 {
-    /*
-     *  The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13.  Not all
-     *  the possible IO sources in the M1543 are in use by us.  We will
-     *  use the following mapping:
-     *
-     *     IRQ1  - keyboard (default set by M1543)
-     *     IRQ3  - reserved for UART B (default set by M1543) (note that
-     *             the schematics for the DDB Vrc-5074 board seem to 
-     *             indicate that IRQ3 is connected to the DS1386 
-     *             watchdog timer interrupt output so we might have 
-     *             a conflict)
-     *     IRQ4  - reserved for UART A (default set by M1543)
-     *     IRQ5  - parallel (default set by M1543)
-     *     IRQ8  - DS1386 time of day (RTC) interrupt
-     *     IRQ12 - mouse
-     */
-    /*
-     *  Assing mouse interrupt to IRQ12 
-     */
-
-    /* Enter configuration mode */
-    outb(0x51, M1543_PNP_CONFIG);
-    outb(0x23, M1543_PNP_CONFIG);
-
-    /* Select logical device 7 (Keyboard) */
-    outb(0x07, M1543_PNP_INDEX);
-    outb(0x07, M1543_PNP_DATA);
-
-    /* Select IRQ12 */
-    outb(0x72, M1543_PNP_INDEX);
-    outb(0x0c, M1543_PNP_DATA);
-
-    /* Leave configration mode */
-    outb(0xbb, M1543_PNP_CONFIG);
-
-
-    /* Initialize the 8259 PIC in the M1543 */
-    i8259_init();
-
-    /* Enable the interrupt cascade */
-    nile4_enable_irq(NILE4_INT_INTE);
-
-    request_region(M1543_PNP_CONFIG, 2, "M1543 config");
-    request_region(M1543_INT1_MASTER_ELCR, 2, "pic ELCR");
+       /*
+        *  The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13.  Not all
+        *  the possible IO sources in the M1543 are in use by us.  We will
+        *  use the following mapping:
+        *
+        *      IRQ1  - keyboard (default set by M1543)
+        *      IRQ3  - reserved for UART B (default set by M1543) (note that
+        *              the schematics for the DDB Vrc-5074 board seem to 
+        *              indicate that IRQ3 is connected to the DS1386 
+        *              watchdog timer interrupt output so we might have 
+        *              a conflict)
+        *      IRQ4  - reserved for UART A (default set by M1543)
+        *      IRQ5  - parallel (default set by M1543)
+        *      IRQ8  - DS1386 time of day (RTC) interrupt
+        *      IRQ12 - mouse
+        */
+
+       /*
+        *  Assing mouse interrupt to IRQ12 
+        */
+
+       /* Enter configuration mode */
+       outb(0x51, M1543_PNP_CONFIG);
+       outb(0x23, M1543_PNP_CONFIG);
+
+       /* Select logical device 7 (Keyboard) */
+       outb(0x07, M1543_PNP_INDEX);
+       outb(0x07, M1543_PNP_DATA);
+
+       /* Select IRQ12 */
+       outb(0x72, M1543_PNP_INDEX);
+       outb(0x0c, M1543_PNP_DATA);
+
+       /* Leave configration mode */
+       outb(0xbb, M1543_PNP_CONFIG);
+
+
+       /* Initialize the 8259 PIC in the M1543 */
+       i8259_init();
+
+       /* Enable the interrupt cascade */
+       nile4_enable_irq(NILE4_INT_INTE);
+
+       request_region(M1543_PNP_CONFIG, 2, "M1543 config");
+       request_region(M1543_INT1_MASTER_ELCR, 2, "pic ELCR");
 }
 
 static void nile4_irq_setup(void)
 {
-    int i;
+       int i;
 
-    /* Map all interrupts to CPU int #0 */
-    nile4_map_irq_all(0);
+       /* Map all interrupts to CPU int #0 */
+       nile4_map_irq_all(0);
 
-    /* PCI INTA#-E# must be level triggered */
-    nile4_set_pci_irq_level_or_edge(0, 1);
-    nile4_set_pci_irq_level_or_edge(1, 1);
-    nile4_set_pci_irq_level_or_edge(2, 1);
-    nile4_set_pci_irq_level_or_edge(3, 1);
-    nile4_set_pci_irq_level_or_edge(4, 1);
+       /* PCI INTA#-E# must be level triggered */
+       nile4_set_pci_irq_level_or_edge(0, 1);
+       nile4_set_pci_irq_level_or_edge(1, 1);
+       nile4_set_pci_irq_level_or_edge(2, 1);
+       nile4_set_pci_irq_level_or_edge(3, 1);
+       nile4_set_pci_irq_level_or_edge(4, 1);
 
-    /* PCI INTA#-D# must be active low, INTE# must be active high */
-    nile4_set_pci_irq_polarity(0, 0);
-    nile4_set_pci_irq_polarity(1, 0);
-    nile4_set_pci_irq_polarity(2, 0);
-    nile4_set_pci_irq_polarity(3, 0);
-    nile4_set_pci_irq_polarity(4, 1);
+       /* PCI INTA#-D# must be active low, INTE# must be active high */
+       nile4_set_pci_irq_polarity(0, 0);
+       nile4_set_pci_irq_polarity(1, 0);
+       nile4_set_pci_irq_polarity(2, 0);
+       nile4_set_pci_irq_polarity(3, 0);
+       nile4_set_pci_irq_polarity(4, 1);
 
-    for (i = 0; i < 16; i++)
-       nile4_clear_irq(i);
+       for (i = 0; i < 16; i++)
+               nile4_clear_irq(i);
 
-    /* Enable CPU int #0 */
-    nile4_enable_irq_output(0);
+       /* Enable CPU int #0 */
+       nile4_enable_irq_output(0);
 
-    request_mem_region(NILE4_BASE, NILE4_SIZE, "Nile 4");
+       request_mem_region(NILE4_BASE, NILE4_SIZE, "Nile 4");
 }
 
 
 /*
  * IRQ2 is cascade interrupt to second interrupt controller
  */
-
-static struct irqaction irq2  = { no_action, 0, 0, "cascade", NULL, NULL };
+static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL };
 
 
 void disable_irq(unsigned int irq_nr)
 {
-    if (is_i8259_irq(irq_nr))
-       i8259_disable_irq(irq_nr);
-    else
-       nile4_disable_irq(irq_to_nile4(irq_nr));
+       if (is_i8259_irq(irq_nr))
+               i8259_disable_irq(irq_nr);
+       else
+               nile4_disable_irq(irq_to_nile4(irq_nr));
 }
 
 void enable_irq(unsigned int irq_nr)
 {
-    if (is_i8259_irq(irq_nr))
-       i8259_enable_irq(irq_nr);
-    else
-       nile4_enable_irq(irq_to_nile4(irq_nr));
+       if (is_i8259_irq(irq_nr))
+               i8259_enable_irq(irq_nr);
+       else
+               nile4_enable_irq(irq_to_nile4(irq_nr));
 }
 
 int table[16] = { 0, };
 
 void ddb_local0_irqdispatch(struct pt_regs *regs)
 {
-    u32 mask;
-    int nile4_irq;
+       u32 mask;
+       int nile4_irq;
 #if 1
-    volatile static int nesting = 0;
-    if (nesting++ == 0)
-       ddb5074_led_d3(1);
-    ddb5074_led_hex(nesting < 16 ? nesting : 15);
+       volatile static int nesting = 0;
+       if (nesting++ == 0)
+               ddb5074_led_d3(1);
+       ddb5074_led_hex(nesting < 16 ? nesting : 15);
 #endif
 
-    mask = nile4_get_irq_stat(0);
-    nile4_clear_irq_mask(mask);
-
-    /* Handle the timer interrupt first */
-    if (mask & (1<<NILE4_INT_GPT)) {
-       nile4_disable_irq(NILE4_INT_GPT);
-       do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs);
-       nile4_enable_irq(NILE4_INT_GPT);
-       mask &= ~(1<<NILE4_INT_GPT);
-    }
-    for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1)
-       if (mask & 1) {
-           nile4_disable_irq(nile4_irq);
-           if (nile4_irq == NILE4_INT_INTE) {
-               int i8259_irq = nile4_i8259_iack();
-               i8259_do_irq(i8259_irq, regs);
-           } else
-               do_IRQ(nile4_to_irq(nile4_irq), regs);
-           nile4_enable_irq(nile4_irq);
-       }
+       mask = nile4_get_irq_stat(0);
+       nile4_clear_irq_mask(mask);
 
+       /* Handle the timer interrupt first */
+       if (mask & (1 << NILE4_INT_GPT)) {
+               nile4_disable_irq(NILE4_INT_GPT);
+               do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs);
+               nile4_enable_irq(NILE4_INT_GPT);
+               mask &= ~(1 << NILE4_INT_GPT);
+       }
+       for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1)
+               if (mask & 1) {
+                       nile4_disable_irq(nile4_irq);
+                       if (nile4_irq == NILE4_INT_INTE) {
+                               int i8259_irq = nile4_i8259_iack();
+                               i8259_do_irq(i8259_irq, regs);
+                       } else
+                               do_IRQ(nile4_to_irq(nile4_irq), regs);
+                       nile4_enable_irq(nile4_irq);
+               }
 #if 1
-    if (--nesting == 0)
-       ddb5074_led_d3(0);
-    ddb5074_led_hex(nesting < 16 ? nesting : 15);
+       if (--nesting == 0)
+               ddb5074_led_d3(0);
+       ddb5074_led_hex(nesting < 16 ? nesting : 15);
 #endif
 }
 
 void ddb_local1_irqdispatch(void)
 {
-    printk("ddb_local1_irqdispatch called\n");
+       printk("ddb_local1_irqdispatch called\n");
 }
 
 void ddb_buserror_irq(void)
 {
-    printk("ddb_buserror_irq called\n");
+       printk("ddb_buserror_irq called\n");
 }
 
 void ddb_8254timer_irq(void)
 {
-    printk("ddb_8254timer_irq called\n");
+       printk("ddb_8254timer_irq called\n");
 }
 
 void __init ddb_irq_setup(void)
 {
 #ifdef CONFIG_REMOTE_DEBUG
-    if (remote_debug)
-       set_debug_traps();
-    breakpoint(); /* you may move this line to whereever you want :-) */
+       if (remote_debug)
+               set_debug_traps();
+       breakpoint();           /* you may move this line to whereever you want :-) */
 #endif
-    request_region(0x20, 0x20, "pic1");
-    request_region(0xa0, 0x20, "pic2");
-    i8259_setup_irq(2, &irq2);
+       request_region(0x20, 0x20, "pic1");
+       request_region(0xa0, 0x20, "pic2");
+       i8259_setup_irq(2, &irq2);
 
-    nile4_irq_setup();
-    m1543_irq_setup();
+       nile4_irq_setup();
+       m1543_irq_setup();
 
-    set_except_vector(0, ddbIRQ);
+       set_except_vector(0, ddbIRQ);
 }
-
index 35793b6..3344feb 100644 (file)
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id$
  */
-
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <asm/nile4.h>
 
+#include <asm/nile4.h>
 
-    /*
-     *  Physical Device Address Registers
-     *
-     *  Note: 32 bit addressing only!
-     */
 
-void nile4_set_pdar(u32 pdar, u32 phys, u32 size, int width, int on_memory_bus,
-                   int visible)
+/*
+ *  Physical Device Address Registers
+ *
+ *  Note: 32 bit addressing only!
+ */
+void nile4_set_pdar(u32 pdar, u32 phys, u32 size, int width,
+                   int on_memory_bus, int visible)
 {
-    u32 maskbits;
-    u32 widthbits;
-
-    if (pdar > NILE4_BOOTCS || (pdar & 7)) {
-       printk("nile4_set_pdar: invalid pdar %d\n", pdar);
-       return;
-    }
-    if (pdar == NILE4_INTCS && size != 0x00200000) {
-       printk("nile4_set_pdar: INTCS size must be 2 MB\n");
-       return;
-    }
-    switch (size) {
-#if 0  /* We don't support 4 GB yet */
+       u32 maskbits;
+       u32 widthbits;
+
+       if (pdar > NILE4_BOOTCS || (pdar & 7)) {
+               printk("nile4_set_pdar: invalid pdar %d\n", pdar);
+               return;
+       }
+       if (pdar == NILE4_INTCS && size != 0x00200000) {
+               printk("nile4_set_pdar: INTCS size must be 2 MB\n");
+               return;
+       }
+       switch (size) {
+#if 0                          /* We don't support 4 GB yet */
        case 0x100000000:       /* 4 GB */
-           maskbits = 4;
-           break;
+               maskbits = 4;
+               break;
 #endif
        case 0x80000000:        /* 2 GB */
-           maskbits = 5;
-           break;
+               maskbits = 5;
+               break;
        case 0x40000000:        /* 1 GB */
-           maskbits = 6;
-           break;
+               maskbits = 6;
+               break;
        case 0x20000000:        /* 512 MB */
-           maskbits = 7;
-           break;
+               maskbits = 7;
+               break;
        case 0x10000000:        /* 256 MB */
-           maskbits = 8;
-           break;
+               maskbits = 8;
+               break;
        case 0x08000000:        /* 128 MB */
-           maskbits = 9;
-           break;
+               maskbits = 9;
+               break;
        case 0x04000000:        /* 64 MB */
-           maskbits = 10;
-           break;
+               maskbits = 10;
+               break;
        case 0x02000000:        /* 32 MB */
-           maskbits = 11;
-           break;
+               maskbits = 11;
+               break;
        case 0x01000000:        /* 16 MB */
-           maskbits = 12;
-           break;
+               maskbits = 12;
+               break;
        case 0x00800000:        /* 8 MB */
-           maskbits = 13;
-           break;
+               maskbits = 13;
+               break;
        case 0x00400000:        /* 4 MB */
-           maskbits = 14;
-           break;
+               maskbits = 14;
+               break;
        case 0x00200000:        /* 2 MB */
-           maskbits = 15;
-           break;
-       case 0:                 /* OFF */
-           maskbits = 0;
-           break;
+               maskbits = 15;
+               break;
+       case 0:         /* OFF */
+               maskbits = 0;
+               break;
        default:
-           printk("nile4_set_pdar: unsupported size %p\n", (void *)size);
-           return;
-    }
-    switch (width) {
+               printk("nile4_set_pdar: unsupported size %p\n", (void *) size);
+               return;
+       }
+       switch (width) {
        case 8:
-           widthbits = 0;
-           break;
+               widthbits = 0;
+               break;
        case 16:
-           widthbits = 1;
-           break;
+               widthbits = 1;
+               break;
        case 32:
-           widthbits = 2;
-           break;
+               widthbits = 2;
+               break;
        case 64:
-           widthbits = 3;
-           break;
+               widthbits = 3;
+               break;
        default:
-           printk("nile4_set_pdar: unsupported width %d\n", width);
-           return;
-    }
-    nile4_out32(pdar, maskbits | (on_memory_bus ? 0x10 : 0) |
-                     (visible ? 0x20 : 0) | (widthbits << 6) |
-                     (phys & 0xffe00000));
-    nile4_out32(pdar+4, 0);
-    /*
-     *  When programming a PDAR, the register should be read immediately after
-     *  writing it. This ensures that address decoders are properly configured.
-     */
-    (void)nile4_in32(pdar);
-    (void)nile4_in32(pdar+4);
+               printk("nile4_set_pdar: unsupported width %d\n", width);
+               return;
+       }
+       nile4_out32(pdar, maskbits | (on_memory_bus ? 0x10 : 0) |
+                   (visible ? 0x20 : 0) | (widthbits << 6) |
+                   (phys & 0xffe00000));
+       nile4_out32(pdar + 4, 0);
+       /*
+        * When programming a PDAR, the register should be read immediately
+        * after writing it. This ensures that address decoders are properly
+        * configured.
+        */
+       nile4_in32(pdar);
+       nile4_in32(pdar + 4);
 }
 
 
-    /*
-     *  PCI Master Registers
-     *
-     *  Note: 32 bit addressing only!
-     */
-
+/*
+ *  PCI Master Registers
+ *
+ *  Note: 32 bit addressing only!
+ */
 void nile4_set_pmr(u32 pmr, u32 type, u32 addr)
 {
-    if (pmr != NILE4_PCIINIT0 && pmr != NILE4_PCIINIT1) {
-       printk("nile4_set_pmr: invalid pmr %d\n", pmr);
-       return;
-    }
-    switch (type) {
+       if (pmr != NILE4_PCIINIT0 && pmr != NILE4_PCIINIT1) {
+               printk("nile4_set_pmr: invalid pmr %d\n", pmr);
+               return;
+       }
+       switch (type) {
        case NILE4_PCICMD_IACK: /* PCI Interrupt Acknowledge */
        case NILE4_PCICMD_IO:   /* PCI I/O Space */
        case NILE4_PCICMD_MEM:  /* PCI Memory Space */
        case NILE4_PCICMD_CFG:  /* PCI Configuration Space */
-           break;
+               break;
        default:
-           printk("nile4_set_pmr: invalid type %d\n", type);
-           return;
-    }
-    nile4_out32(pmr, (type << 1) | 0x10 | (addr & 0xffe00000));
-    nile4_out32(pmr+4, 0);
+               printk("nile4_set_pmr: invalid type %d\n", type);
+               return;
+       }
+       nile4_out32(pmr, (type << 1) | 0x10 | (addr & 0xffe00000));
+       nile4_out32(pmr + 4, 0);
 }
 
 
-    /*
-     *  Interrupt Programming
-     */
-
+/*
+ *  Interrupt Programming
+ */
 void nile4_map_irq(int nile4_irq, int cpu_irq)
 {
-    u32 offset, t;
-
-    offset = NILE4_INTCTRL;
-    if (nile4_irq >= 8) {
-       offset += 4;
-       nile4_irq -= 8;
-    }
-    t = nile4_in32(offset);
-    t &= ~(7 << (nile4_irq*4));
-    t |= cpu_irq << (nile4_irq*4);
-    nile4_out32(offset, t);
+       u32 offset, t;
+
+       offset = NILE4_INTCTRL;
+       if (nile4_irq >= 8) {
+               offset += 4;
+               nile4_irq -= 8;
+       }
+       t = nile4_in32(offset);
+       t &= ~(7 << (nile4_irq * 4));
+       t |= cpu_irq << (nile4_irq * 4);
+       nile4_out32(offset, t);
 }
 
 void nile4_map_irq_all(int cpu_irq)
 {
-    u32 all, t;
-    
-    all = cpu_irq;
-    all |= all << 4;
-    all |= all << 8;
-    all |= all << 16;
-    t = nile4_in32(NILE4_INTCTRL);
-    t &= 0x88888888;
-    t |= all;
-    nile4_out32(NILE4_INTCTRL, t);
-    t = nile4_in32(NILE4_INTCTRL+4);
-    t &= 0x88888888;
-    t |= all;
-    nile4_out32(NILE4_INTCTRL+4, t);
+       u32 all, t;
+
+       all = cpu_irq;
+       all |= all << 4;
+       all |= all << 8;
+       all |= all << 16;
+       t = nile4_in32(NILE4_INTCTRL);
+       t &= 0x88888888;
+       t |= all;
+       nile4_out32(NILE4_INTCTRL, t);
+       t = nile4_in32(NILE4_INTCTRL + 4);
+       t &= 0x88888888;
+       t |= all;
+       nile4_out32(NILE4_INTCTRL + 4, t);
 }
 
 void nile4_enable_irq(int nile4_irq)
 {
-    u32 offset, t;
-
-    offset = NILE4_INTCTRL;
-    if (nile4_irq >= 8) {
-       offset += 4;
-       nile4_irq -= 8;
-    }
-    t = nile4_in32(offset);
-    t |= 8 << (nile4_irq*4);
-    nile4_out32(offset, t);
+       u32 offset, t;
+
+       offset = NILE4_INTCTRL;
+       if (nile4_irq >= 8) {
+               offset += 4;
+               nile4_irq -= 8;
+       }
+       t = nile4_in32(offset);
+       t |= 8 << (nile4_irq * 4);
+       nile4_out32(offset, t);
 }
 
 void nile4_disable_irq(int nile4_irq)
 {
-    u32 offset, t;
-
-    offset = NILE4_INTCTRL;
-    if (nile4_irq >= 8) {
-       offset += 4;
-       nile4_irq -= 8;
-    }
-    t = nile4_in32(offset);
-    t &= ~(8 << (nile4_irq*4));
-    nile4_out32(offset, t);
+       u32 offset, t;
+
+       offset = NILE4_INTCTRL;
+       if (nile4_irq >= 8) {
+               offset += 4;
+               nile4_irq -= 8;
+       }
+       t = nile4_in32(offset);
+       t &= ~(8 << (nile4_irq * 4));
+       nile4_out32(offset, t);
 }
 
 void nile4_disable_irq_all(void)
 {
-    nile4_out32(NILE4_INTCTRL, 0);
-    nile4_out32(NILE4_INTCTRL+4, 0);
+       nile4_out32(NILE4_INTCTRL, 0);
+       nile4_out32(NILE4_INTCTRL + 4, 0);
 }
 
 u16 nile4_get_irq_stat(int cpu_irq)
 {
-    return nile4_in16(NILE4_INTSTAT0+cpu_irq*2);
+       return nile4_in16(NILE4_INTSTAT0 + cpu_irq * 2);
 }
 
 void nile4_enable_irq_output(int cpu_irq)
 {
-    u32 t;
+       u32 t;
 
-    t = nile4_in32(NILE4_INTSTAT1+4);
-    t |= 1 << (16+cpu_irq);
-    nile4_out32(NILE4_INTSTAT1, t);
+       t = nile4_in32(NILE4_INTSTAT1 + 4);
+       t |= 1 << (16 + cpu_irq);
+       nile4_out32(NILE4_INTSTAT1, t);
 }
 
 void nile4_disable_irq_output(int cpu_irq)
 {
-    u32 t;
+       u32 t;
 
-    t = nile4_in32(NILE4_INTSTAT1+4);
-    t &= ~(1 << (16+cpu_irq));
-    nile4_out32(NILE4_INTSTAT1, t);
+       t = nile4_in32(NILE4_INTSTAT1 + 4);
+       t &= ~(1 << (16 + cpu_irq));
+       nile4_out32(NILE4_INTSTAT1, t);
 }
 
 void nile4_set_pci_irq_polarity(int pci_irq, int high)
 {
-    u32 t;
-
-    t = nile4_in32(NILE4_INTPPES);
-    if (high)
-       t &= ~(1 << (pci_irq*2));
-    else
-       t |= 1 << (pci_irq*2);
-    nile4_out32(NILE4_INTPPES, t);
+       u32 t;
+
+       t = nile4_in32(NILE4_INTPPES);
+       if (high)
+               t &= ~(1 << (pci_irq * 2));
+       else
+               t |= 1 << (pci_irq * 2);
+       nile4_out32(NILE4_INTPPES, t);
 }
 
 void nile4_set_pci_irq_level_or_edge(int pci_irq, int level)
 {
-    u32 t;
-
-    t = nile4_in32(NILE4_INTPPES);
-    if (level)
-       t |= 2 << (pci_irq*2);
-    else
-       t &= ~(2 << (pci_irq*2));
-    nile4_out32(NILE4_INTPPES, t);
+       u32 t;
+
+       t = nile4_in32(NILE4_INTPPES);
+       if (level)
+               t |= 2 << (pci_irq * 2);
+       else
+               t &= ~(2 << (pci_irq * 2));
+       nile4_out32(NILE4_INTPPES, t);
 }
 
 void nile4_clear_irq(int nile4_irq)
 {
-    nile4_out32(NILE4_INTCLR, 1 << nile4_irq);
+       nile4_out32(NILE4_INTCLR, 1 << nile4_irq);
 }
 
 void nile4_clear_irq_mask(u32 mask)
 {
-    nile4_out32(NILE4_INTCLR, mask);
+       nile4_out32(NILE4_INTCLR, mask);
 }
 
 u8 nile4_i8259_iack(void)
 {
-    u8 irq;
-
-    /* Set window 0 for interrupt acknowledge */
-    nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IACK, 0);
-    irq = *(volatile u8 *)NILE4_PCI_IACK_BASE;
-    /* Set window 0 for PCI I/O space */
-    nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IO, 0);
-    return irq;
+       u8 irq;
+
+       /* Set window 0 for interrupt acknowledge */
+       nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IACK, 0);
+       irq = *(volatile u8 *) NILE4_PCI_IACK_BASE;
+       /* Set window 0 for PCI I/O space */
+       nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IO, 0);
+       return irq;
 }
 
 #if 0
 void nile4_dump_irq_status(void)
 {
-    printk("CPUSTAT = %p:%p\n", (void *)nile4_in32(NILE4_CPUSTAT+4),
-                               (void *)nile4_in32(NILE4_CPUSTAT));
-    printk("INTCTRL = %p:%p\n", (void *)nile4_in32(NILE4_INTCTRL+4),
-                               (void *)nile4_in32(NILE4_INTCTRL));
-    printk("INTSTAT0 = %p:%p\n", (void *)nile4_in32(NILE4_INTSTAT0+4),
-                               (void *)nile4_in32(NILE4_INTSTAT0));
-    printk("INTSTAT1 = %p:%p\n", (void *)nile4_in32(NILE4_INTSTAT1+4),
-                               (void *)nile4_in32(NILE4_INTSTAT1));
-    printk("INTCLR = %p:%p\n", (void *)nile4_in32(NILE4_INTCLR+4),
-                               (void *)nile4_in32(NILE4_INTCLR));
-    printk("INTPPES = %p:%p\n", (void *)nile4_in32(NILE4_INTPPES+4),
-                               (void *)nile4_in32(NILE4_INTPPES));
+       printk("CPUSTAT = %p:%p\n", (void *) nile4_in32(NILE4_CPUSTAT + 4),
+              (void *) nile4_in32(NILE4_CPUSTAT));
+       printk("INTCTRL = %p:%p\n", (void *) nile4_in32(NILE4_INTCTRL + 4),
+              (void *) nile4_in32(NILE4_INTCTRL));
+       printk("INTSTAT0 = %p:%p\n",
+              (void *) nile4_in32(NILE4_INTSTAT0 + 4),
+              (void *) nile4_in32(NILE4_INTSTAT0));
+       printk("INTSTAT1 = %p:%p\n",
+              (void *) nile4_in32(NILE4_INTSTAT1 + 4),
+              (void *) nile4_in32(NILE4_INTSTAT1));
+       printk("INTCLR = %p:%p\n", (void *) nile4_in32(NILE4_INTCLR + 4),
+              (void *) nile4_in32(NILE4_INTCLR));
+       printk("INTPPES = %p:%p\n", (void *) nile4_in32(NILE4_INTPPES + 4),
+              (void *) nile4_in32(NILE4_INTPPES));
 }
 #endif
diff --git a/arch/mips/ddb5074/pci-dma.c b/arch/mips/ddb5074/pci-dma.c
deleted file mode 100644 (file)
index 1309e5e..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2000   Ani Joshi <ajoshi@unixbox.com>
- *
- *
- * Dynamic DMA mapping support.
- *
- * swiped from i386, and cloned for MIPS by Geert.
- *
- */
-
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-
-void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-                          dma_addr_t *dma_handle)
-{
-       void *ret;
-       int gfp = GFP_ATOMIC;
-
-       if (hwdev == NULL || hwdev->dma_mask != 0xffffffff)
-               gfp |= GFP_DMA;
-       ret = (void *)__get_free_pages(gfp, get_order(size));
-
-       if (ret != NULL) {
-               memset(ret, 0, size);
-               *dma_handle = virt_to_bus(ret);
-       }
-       return ret;
-}
-
-void pci_free_consistent(struct pci_dev *hwdev, size_t size,
-                        void *vaddr, dma_addr_t dma_handle)
-{
-       free_pages((unsigned long)vaddr, get_order(size));
-}
index d92d79e..c663c7d 100644 (file)
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Albert Dorofeev <albert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id: pci.c,v 1.4 2000/02/18 00:02:17 ralf Exp $
  */
-
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/ioport.h>
-#include <asm-mips/nile4.h>
+
+#include <asm/nile4.h>
 
 
 static u32 nile4_pre_pci_access0(int slot_num)
 {
-    u32 pci_addr = 0;
-    u32 virt_addr = NILE4_PCI_CFG_BASE;
-
-    /* Set window 1 address 8000000 - 64 bit - 2 MB (PCI config space) */
-    nile4_set_pdar(NILE4_PCIW1, PHYSADDR(virt_addr), 0x00200000, 64, 0, 0);
-    if (slot_num > 2)
-       pci_addr = 0x00040000 << slot_num;
-    else
-       virt_addr += 0x00040000 << slot_num;
-    nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_CFG, pci_addr);
-    return virt_addr;
+       u32 pci_addr = 0;
+       u32 virt_addr = NILE4_PCI_CFG_BASE;
+
+       /* Set window 1 address 8000000 - 64 bit - 2 MB (PCI config space) */
+       nile4_set_pdar(NILE4_PCIW1, PHYSADDR(virt_addr), 0x00200000, 64, 0,
+                      0);
+       if (slot_num > 2)
+               pci_addr = 0x00040000 << slot_num;
+       else
+               virt_addr += 0x00040000 << slot_num;
+       nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_CFG, pci_addr);
+       return virt_addr;
 }
 
 static void nile4_post_pci_access0(void)
 {
-    /* Set window 1 back to address 8000000 - 64 bit - 128 MB (PCI IO space) */
-    nile4_set_pdar(NILE4_PCIW1, PHYSADDR(NILE4_PCI_MEM_BASE), 0x08000000, 64,
-                  1, 1);
-    nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0);
+       /*
+        * Set window 1 back to address 8000000 - 64 bit - 128 MB
+        * (PCI IO space)
+        */
+       nile4_set_pdar(NILE4_PCIW1, PHYSADDR(NILE4_PCI_MEM_BASE),
+                      0x08000000, 64, 1, 1);
+       nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0);
 }
 
 
-static int nile4_pci_read_config_dword( struct pci_dev *dev,
-                               int where, u32 *val)
+static int nile4_pci_read_config_dword(struct pci_dev *dev,
+                                      int where, u32 * val)
 {
-    int slot_num, func_num;
-    u32 base;
-
-    /*
-     *  For starters let's do configuration cycle 0 only (one bus only)
-     */
-    if (dev->bus->number)
-       return PCIBIOS_FUNC_NOT_SUPPORTED;
-
-    slot_num = PCI_SLOT(dev->devfn);
-    func_num = PCI_FUNC(dev->devfn);
-    if (slot_num == 5) {
+       int slot_num, func_num;
+       u32 base;
+
        /*
-        *  This is Nile 4 and it will crash if we access it like other
-        *   devices
+        *  For starters let's do configuration cycle 0 only (one bus only)
         */
-       *val = nile4_in32(NILE4_PCI_BASE + where);
+       if (dev->bus->number)
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+       slot_num = PCI_SLOT(dev->devfn);
+       func_num = PCI_FUNC(dev->devfn);
+       if (slot_num == 5) {
+               /*
+                * This is Nile 4 and it will crash if we access it like other
+                * devices
+                */
+               *val = nile4_in32(NILE4_PCI_BASE + where);
+               return PCIBIOS_SUCCESSFUL;
+       }
+       base = nile4_pre_pci_access0(slot_num);
+       *val =
+           *((volatile u32 *) (base + (func_num << 8) + (where & 0xfc)));
+       nile4_post_pci_access0();
        return PCIBIOS_SUCCESSFUL;
-    }
-    base = nile4_pre_pci_access0(slot_num);
-    *val = *((volatile u32 *)(base + (func_num << 8) + (where & 0xfc)));
-    nile4_post_pci_access0();
-    return PCIBIOS_SUCCESSFUL;
 }
 
 static int nile4_pci_write_config_dword(struct pci_dev *dev, int where,
                                        u32 val)
 {
-    int slot_num, func_num;
-    u32 base;
-
-    /*
-     *  For starters let's do configuration cycle 0 only (one bus only)
-     */
-    if (dev->bus->number)
-       return PCIBIOS_FUNC_NOT_SUPPORTED;
-
-    slot_num = PCI_SLOT(dev->devfn);
-    func_num = PCI_FUNC(dev->devfn);
-    if (slot_num == 5) {
+       int slot_num, func_num;
+       u32 base;
+
        /*
-        *  This is Nile 4 and it will crash if we access it like other
-        *   devices
+        * For starters let's do configuration cycle 0 only (one bus only)
         */
-       nile4_out32(NILE4_PCI_BASE + where, val);
+       if (dev->bus->number)
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+       slot_num = PCI_SLOT(dev->devfn);
+       func_num = PCI_FUNC(dev->devfn);
+       if (slot_num == 5) {
+               /*
+                * This is Nile 4 and it will crash if we access it like other
+                * devices
+                */
+               nile4_out32(NILE4_PCI_BASE + where, val);
+               return PCIBIOS_SUCCESSFUL;
+       }
+       base = nile4_pre_pci_access0(slot_num);
+       *((volatile u32 *) (base + (func_num << 8) + (where & 0xfc))) =
+           val;
+       nile4_post_pci_access0();
        return PCIBIOS_SUCCESSFUL;
-    }
-    base = nile4_pre_pci_access0(slot_num);
-    *((volatile u32 *)(base + (func_num << 8) + (where & 0xfc))) = val;
-    nile4_post_pci_access0();
-    return PCIBIOS_SUCCESSFUL;
 }
 
-static int nile4_pci_read_config_word(struct pci_dev *dev, int where, u16 *val)
+static int nile4_pci_read_config_word(struct pci_dev *dev, int where,
+                                     u16 * val)
 {
-    int status;
-    u32 result;
-
-    status = nile4_pci_read_config_dword(dev, where, &result);
-    if (status != PCIBIOS_SUCCESSFUL)
-       return status;
-    if (where & 2)
-       result >>= 16;
-    *val = result & 0xffff;
-    return PCIBIOS_SUCCESSFUL;
+       int status;
+       u32 result;
+
+       status = nile4_pci_read_config_dword(dev, where, &result);
+       if (status != PCIBIOS_SUCCESSFUL)
+               return status;
+       if (where & 2)
+               result >>= 16;
+       *val = result & 0xffff;
+       return PCIBIOS_SUCCESSFUL;
 }
 
-static int nile4_pci_read_config_byte(struct pci_dev *dev, int where, u8 *val)
+static int nile4_pci_read_config_byte(struct pci_dev *dev, int where,
+                                     u8 * val)
 {
-    int status;
-    u32 result;
-
-    status = nile4_pci_read_config_dword(dev, where, &result);
-    if (status != PCIBIOS_SUCCESSFUL)
-       return status;
-    if (where & 1)
-       result >>= 8;
-    if (where & 2)
-       result >>= 16;
-    *val = result & 0xff;
-    return PCIBIOS_SUCCESSFUL;
+       int status;
+       u32 result;
+
+       status = nile4_pci_read_config_dword(dev, where, &result);
+       if (status != PCIBIOS_SUCCESSFUL)
+               return status;
+       if (where & 1)
+               result >>= 8;
+       if (where & 2)
+               result >>= 16;
+       *val = result & 0xff;
+       return PCIBIOS_SUCCESSFUL;
 }
 
-static int nile4_pci_write_config_word(struct pci_dev *dev, int where, u16 val)
+static int nile4_pci_write_config_word(struct pci_dev *dev, int where,
+                                      u16 val)
 {
-    int status, shift = 0;
-    u32 result;
-
-    status = nile4_pci_read_config_dword(dev, where, &result);
-    if (status != PCIBIOS_SUCCESSFUL)
-       return status;
-    if (where & 2)
-       shift += 16;
-    result &= ~(0xffff << shift);
-    result |= val << shift;
-    return nile4_pci_write_config_dword(dev, where, result);
+       int status, shift = 0;
+       u32 result;
+
+       status = nile4_pci_read_config_dword(dev, where, &result);
+       if (status != PCIBIOS_SUCCESSFUL)
+               return status;
+       if (where & 2)
+               shift += 16;
+       result &= ~(0xffff << shift);
+       result |= val << shift;
+       return nile4_pci_write_config_dword(dev, where, result);
 }
 
-static int nile4_pci_write_config_byte( struct pci_dev *dev, int where, u8 val)
+static int nile4_pci_write_config_byte(struct pci_dev *dev, int where,
+                                      u8 val)
 {
-    int status, shift = 0;
-    u32 result;
-
-    status = nile4_pci_read_config_dword(dev, where, &result);
-    if (status != PCIBIOS_SUCCESSFUL)
-       return status;
-    if (where & 2)
-       shift += 16;
-    if (where & 1)
-       shift += 8;
-    result &= ~(0xff << shift);
-    result |= val << shift;
-    return nile4_pci_write_config_dword(dev, where, result);
+       int status, shift = 0;
+       u32 result;
+
+       status = nile4_pci_read_config_dword(dev, where, &result);
+       if (status != PCIBIOS_SUCCESSFUL)
+               return status;
+       if (where & 2)
+               shift += 16;
+       if (where & 1)
+               shift += 8;
+       result &= ~(0xff << shift);
+       result |= val << shift;
+       return nile4_pci_write_config_dword(dev, where, result);
 }
 
 struct pci_ops nile4_pci_ops = {
-    nile4_pci_read_config_byte,
-    nile4_pci_read_config_word,
-    nile4_pci_read_config_dword,
-    nile4_pci_write_config_byte,
-    nile4_pci_write_config_word,
-    nile4_pci_write_config_dword
+       nile4_pci_read_config_byte,
+       nile4_pci_read_config_word,
+       nile4_pci_read_config_dword,
+       nile4_pci_write_config_byte,
+       nile4_pci_write_config_word,
+       nile4_pci_write_config_dword
 };
 
 struct {
-    struct resource ram;
-    struct resource flash;
-    struct resource isa_io;
-    struct resource pci_io;
-    struct resource isa_mem;
-    struct resource pci_mem;
-    struct resource nile4;
-    struct resource boot;
+       struct resource ram;
+       struct resource flash;
+       struct resource isa_io;
+       struct resource pci_io;
+       struct resource isa_mem;
+       struct resource pci_mem;
+       struct resource nile4;
+       struct resource boot;
 } ddb5074_resources = {
-    { "RAM", 0x00000000, 0x03ffffff,
-      IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 },
-    { "Flash ROM", 0x04000000, 0x043fffff },
-    { "Nile4 ISA I/O", 0x06000000, 0x060fffff },
-    { "Nile4 PCI I/O", 0x06100000, 0x07ffffff },
-    { "Nile4 ISA mem", 0x08000000, 0x08ffffff, IORESOURCE_MEM },
-    { "Nile4 PCI mem", 0x09000000, 0x0fffffff, IORESOURCE_MEM },
-    { "Nile4 ctrl", 0x1fa00000, 0x1fbfffff,
-      IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 },
-    { "Boot ROM", 0x1fc00000, 0x1fffffff }
+       { "RAM", 0x00000000, 0x03ffffff,
+         IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64},
+       { "Flash ROM", 0x04000000, 0x043fffff},
+       { "Nile4 ISA I/O", 0x06000000, 0x060fffff},
+       { "Nile4 PCI I/O", 0x06100000, 0x07ffffff},
+       { "Nile4 ISA mem", 0x08000000, 0x08ffffff, IORESOURCE_MEM},
+       { "Nile4 PCI mem", 0x09000000, 0x0fffffff, IORESOURCE_MEM},
+       { "Nile4 ctrl", 0x1fa00000, 0x1fbfffff,
+         IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64},
+       { "Boot ROM", 0x1fc00000, 0x1fffffff}
 };
 
 static void __init ddb5074_pci_fixup(void)
 {
-    struct pci_dev *dev;
-
-    pci_for_each_dev(dev) {
-       if (dev->vendor == PCI_VENDOR_ID_NEC &&
-           dev->device == PCI_DEVICE_ID_NEC_NILE4) {
-           /*
-            *  The first 64-bit PCI base register should point to the Nile4
-            *  control registers. Unfortunately this isn't the case, so we fix
-            *  it ourselves. This allows the serial driver to find the UART.
-            */
-           dev->resource[0] = ddb5074_resources.nile4;
-           request_resource(&iomem_resource, &dev->resource[0]);
-           /*
-            *  The second 64-bit PCI base register points to the first memory
-            *  bank. Unfortunately the address is wrong, so we fix it (again).
-            */
-           dev->resource[2] = ddb5074_resources.ram;
-           request_resource(&iomem_resource, &dev->resource[2]);
-       } else if (dev->vendor == PCI_VENDOR_ID_AL &&
-                  dev->device == PCI_DEVICE_ID_AL_M7101) {
-           /*
-            *  It's nice to have the LEDs on the GPIO pins available for
-            *  debugging
-            */
-           extern struct pci_dev *pci_pmu;
-           u8 t8;
-
-           pci_pmu = dev;              /* for LEDs D2 and D3 */
-           /* Program the lines for LEDs D2 and D3 to output */
-           nile4_pci_read_config_byte(dev, 0x7d, &t8);
-           t8 |= 0xc0;
-           nile4_pci_write_config_byte(dev, 0x7d, t8);
-           /* Turn LEDs D2 and D3 off */
-           nile4_pci_read_config_byte(dev, 0x7e, &t8);
-           t8 |= 0xc0;
-           nile4_pci_write_config_byte(dev, 0x7e, t8);
+       struct pci_dev *dev;
+
+       pci_for_each_dev(dev) {
+               if (dev->vendor == PCI_VENDOR_ID_NEC &&
+                   dev->device == PCI_DEVICE_ID_NEC_NILE4) {
+                       /*
+                        * The first 64-bit PCI base register should point to
+                        * the Nile4 control registers. Unfortunately this
+                        * isn't the case, so we fix it ourselves. This allows
+                        * the serial driver to find the UART.
+                        */
+                       dev->resource[0] = ddb5074_resources.nile4;
+                       request_resource(&iomem_resource,
+                                        &dev->resource[0]);
+                       /*
+                        * The second 64-bit PCI base register points to the
+                        * first memory bank. Unfortunately the address is
+                        * wrong, so we fix it (again).
+                        */
+                       dev->resource[2] = ddb5074_resources.ram;
+                       request_resource(&iomem_resource,
+                                        &dev->resource[2]);
+               } else if (dev->vendor == PCI_VENDOR_ID_AL
+                          && dev->device == PCI_DEVICE_ID_AL_M7101) {
+                       /*
+                        * It's nice to have the LEDs on the GPIO pins
+                        * available for debugging
+                        */
+                       extern struct pci_dev *pci_pmu;
+                       u8 t8;
+
+                       pci_pmu = dev;  /* for LEDs D2 and D3 */
+                       /* Program the lines for LEDs D2 and D3 to output */
+                       nile4_pci_read_config_byte(dev, 0x7d, &t8);
+                       t8 |= 0xc0;
+                       nile4_pci_write_config_byte(dev, 0x7d, t8);
+                       /* Turn LEDs D2 and D3 off */
+                       nile4_pci_read_config_byte(dev, 0x7e, &t8);
+                       t8 |= 0xc0;
+                       nile4_pci_write_config_byte(dev, 0x7e, t8);
+               }
        }
-    }
 }
 
 static void __init pcibios_fixup_irqs(void)
 {
-    struct pci_dev *dev;
-    int slot_num;
-
-    pci_for_each_dev(dev) {
-       slot_num = PCI_SLOT(dev->devfn);
-       switch (slot_num) {
-           case 0:
-               dev->irq = nile4_to_irq(NILE4_INT_INTE);
-               break;
-           case 1:
-               dev->irq = nile4_to_irq(NILE4_INT_INTA);
-               break;
-           case 2:     /* slot 1 */
-               dev->irq = nile4_to_irq(NILE4_INT_INTA);
-               break;
-           case 3:     /* slot 2 */
-               dev->irq = nile4_to_irq(NILE4_INT_INTB);
-               break;
-           case 4:     /* slot 3 */
-               dev->irq = nile4_to_irq(NILE4_INT_INTC);
-               break;
-           case 5:
-               /*
-                * Fixup so the serial driver can use the UART
-                */
-               dev->irq = nile4_to_irq(NILE4_INT_UART);
-               break;
-           case 13:
-               dev->irq = nile4_to_irq(NILE4_INT_INTE);
-               break;
-           default:
-               break;
+       struct pci_dev *dev;
+       int slot_num;
+
+       pci_for_each_dev(dev) {
+               slot_num = PCI_SLOT(dev->devfn);
+               switch (slot_num) {
+               case 0:
+                       dev->irq = nile4_to_irq(NILE4_INT_INTE);
+                       break;
+               case 1:
+                       dev->irq = nile4_to_irq(NILE4_INT_INTA);
+                       break;
+               case 2: /* slot 1 */
+                       dev->irq = nile4_to_irq(NILE4_INT_INTA);
+                       break;
+               case 3: /* slot 2 */
+                       dev->irq = nile4_to_irq(NILE4_INT_INTB);
+                       break;
+               case 4: /* slot 3 */
+                       dev->irq = nile4_to_irq(NILE4_INT_INTC);
+                       break;
+               case 5:
+                       /*
+                        * Fixup so the serial driver can use the UART
+                        */
+                       dev->irq = nile4_to_irq(NILE4_INT_UART);
+                       break;
+               case 13:
+                       dev->irq = nile4_to_irq(NILE4_INT_INTE);
+                       break;
+               default:
+                       break;
+               }
        }
-    }
 }
 
 void __init pcibios_init(void)
 {
-    printk("PCI: Probing PCI hardware\n");
-    ioport_resource.end = 0x1ffffff;           /*  32 MB */
-    iomem_resource.end = 0x1fffffff;           /* 512 MB */
-    /* `ram' and `nile4' are requested through the Nile4 pci_dev */
-    request_resource(&iomem_resource, &ddb5074_resources.flash);
-    request_resource(&iomem_resource, &ddb5074_resources.isa_io);
-    request_resource(&iomem_resource, &ddb5074_resources.pci_io);
-    request_resource(&iomem_resource, &ddb5074_resources.isa_mem);
-    request_resource(&iomem_resource, &ddb5074_resources.pci_mem);
-    request_resource(&iomem_resource, &ddb5074_resources.boot);
-
-    pci_scan_bus(0, &nile4_pci_ops, NULL);
-    ddb5074_pci_fixup();
-    pci_assign_unassigned_resources();
-    pcibios_fixup_irqs();
+       printk("PCI: Probing PCI hardware\n");
+       ioport_resource.end = 0x1ffffff;        /*  32 MB */
+       iomem_resource.end = 0x1fffffff;        /* 512 MB */
+       /* `ram' and `nile4' are requested through the Nile4 pci_dev */
+       request_resource(&iomem_resource, &ddb5074_resources.flash);
+       request_resource(&iomem_resource, &ddb5074_resources.isa_io);
+       request_resource(&iomem_resource, &ddb5074_resources.pci_io);
+       request_resource(&iomem_resource, &ddb5074_resources.isa_mem);
+       request_resource(&iomem_resource, &ddb5074_resources.pci_mem);
+       request_resource(&iomem_resource, &ddb5074_resources.boot);
+
+       pci_scan_bus(0, &nile4_pci_ops, NULL);
+       ddb5074_pci_fixup();
+       pci_assign_unassigned_resources();
+       pcibios_fixup_irqs();
 }
 
 void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
-    bus->resource[1] = &ddb5074_resources.pci_mem;
+       bus->resource[1] = &ddb5074_resources.pci_mem;
 }
 
-char *pcibios_setup (char *str)
+char *pcibios_setup(char *str)
 {
-    return str;
+       return str;
 }
 
 void __init pcibios_update_irq(struct pci_dev *dev, int irq)
 {
-    pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
 }
 
 void __init pcibios_fixup_pbus_ranges(struct pci_bus *bus,
                                      struct pbus_set_ranges_data *ranges)
 {
-    ranges->io_start -= bus->resource[0]->start;
-    ranges->io_end -= bus->resource[0]->start;
-    ranges->mem_start -= bus->resource[1]->start;
-    ranges->mem_end -= bus->resource[1]->start;
+       ranges->io_start -= bus->resource[0]->start;
+       ranges->io_end -= bus->resource[0]->start;
+       ranges->mem_start -= bus->resource[1]->start;
+       ranges->mem_end -= bus->resource[1]->start;
 }
 
 int pcibios_enable_resources(struct pci_dev *dev)
@@ -323,15 +335,15 @@ int pcibios_enable_resources(struct pci_dev *dev)
         *  Don't touch the Nile 4
         */
        if (dev->vendor == PCI_VENDOR_ID_NEC &&
-           dev->device == PCI_DEVICE_ID_NEC_NILE4)
-           return 0;
+           dev->device == PCI_DEVICE_ID_NEC_NILE4) return 0;
 
        pci_read_config_word(dev, PCI_COMMAND, &cmd);
        old_cmd = cmd;
-       for(idx=0; idx<6; idx++) {
+       for (idx = 0; idx < 6; idx++) {
                r = &dev->resource[idx];
                if (!r->start && r->end) {
-                       printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
+                       printk(KERN_ERR "PCI: Device %s not available because "
+                              "of resource collisions\n", dev->slot_name);
                        return -EINVAL;
                }
                if (r->flags & IORESOURCE_IO)
@@ -340,7 +352,8 @@ int pcibios_enable_resources(struct pci_dev *dev)
                        cmd |= PCI_COMMAND_MEMORY;
        }
        if (cmd != old_cmd) {
-               printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
+               printk("PCI: Enabling device %s (%04x -> %04x)\n",
+                      dev->slot_name, old_cmd, cmd);
                pci_write_config_word(dev, PCI_COMMAND, cmd);
        }
        return 0;
@@ -348,7 +361,7 @@ int pcibios_enable_resources(struct pci_dev *dev)
 
 int pcibios_enable_device(struct pci_dev *dev)
 {
-    return pcibios_enable_resources(dev);
+       return pcibios_enable_resources(dev);
 }
 
 void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
@@ -359,18 +372,23 @@ void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
 
        new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
        if (resource < 6) {
-               reg = PCI_BASE_ADDRESS_0 + 4*resource;
+               reg = PCI_BASE_ADDRESS_0 + 4 * resource;
        } else if (resource == PCI_ROM_RESOURCE) {
                res->flags |= PCI_ROM_ADDRESS_ENABLE;
                reg = dev->rom_base_reg;
        } else {
-               /* Somebody might have asked allocation of a non-standard resource */
+               /*
+                * Somebody might have asked allocation of a non-standard
+                * resource
+                */
                return;
        }
-       
+
        pci_write_config_dword(dev, reg, new);
        pci_read_config_dword(dev, reg, &check);
-       if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
+       if ((new ^ check) &
+           ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
+            PCI_BASE_ADDRESS_MEM_MASK)) {
                printk(KERN_ERR "PCI: Error while updating region "
                       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
                       new, check);
@@ -400,5 +418,4 @@ void pcibios_align_resource(void *data, struct resource *res,
 }
 
 
-struct pci_fixup pcibios_fixups[] = {};
-
+struct pci_fixup pcibios_fixups[] = { };
index b85a334..c161420 100644 (file)
@@ -3,58 +3,32 @@
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id: prom.c,v 1.1 2000/01/26 00:07:44 ralf Exp $
  */
-
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/bootmem.h>
+
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
 
 
-char arcs_cmdline[CL_SIZE];
-
-extern char _end;
-
-#define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_ALIGN(x)   (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
-
+char arcs_cmdline[COMMAND_LINE_SIZE];
 
 void __init prom_init(const char *s)
 {
-    int i = 0;
-    unsigned long mem_size, free_start, free_end, start_pfn, bootmap_size;
+       int i = 0;
 
-//  _serinit();
+       if (s != (void *) -1)
+               while (*s && i < sizeof(arcs_cmdline) - 1)
+                       arcs_cmdline[i++] = *s++;
+       arcs_cmdline[i] = '\0';
 
-    if (s != (void *)-1)
-       while (*s && i < sizeof(arcs_cmdline)-1)
-           arcs_cmdline[i++] = *s++;
-    arcs_cmdline[i] = '\0';
+       mips_machgroup = MACH_GROUP_NEC_DDB;
+       mips_machtype = MACH_NEC_DDB5074;
 
-    mips_machgroup = MACH_GROUP_NEC_DDB;
-    mips_machtype = MACH_NEC_DDB5074;
-    /* 64 MB non-upgradable */
-    mem_size = 64 << 20;
-
-    free_start = PHYSADDR(PFN_ALIGN(&_end));
-    free_end = mem_size;
-    start_pfn = PFN_UP((unsigned long)&_end);
-
-    /* Register all the contiguous memory with the bootmem allocator
-       and free it.  Be careful about the bootmem freemap.  */
-    bootmap_size = init_bootmem(start_pfn, mem_size >> PAGE_SHIFT);
-
-    /* Free the entire available memory after the _end symbol.  */
-    free_start += bootmap_size;
-    free_bootmem(free_start, free_end-free_start);
-}
-
-void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
-{
+       /* 64 MB non-upgradable */
+       add_memory_region(0, 64 << 20, BOOT_MEM_RAM);
 }
 
 void __init prom_free_prom_memory(void)
index 1512345..8091163 100644 (file)
@@ -3,10 +3,7 @@
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id: setup.c,v 1.1 2000/01/26 00:07:44 ralf Exp $
  */
-
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kbd_ll.h>
@@ -42,85 +39,83 @@ extern void console_setup(char *);
 extern struct ide_ops std_ide_ops;
 extern struct rtc_ops ddb_rtc_ops;
 
-static void (*back_to_prom)(void) = (void (*)(void))0xbfc00000;
+static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
 
 static void ddb_machine_restart(char *command)
 {
-    u32 t;
-
-    /* PCI cold reset */
-    t = nile4_in32(NILE4_PCICTRL+4);
-    t |= 0x40000000;
-    nile4_out32(NILE4_PCICTRL+4, t);
-    /* CPU cold reset */
-    t = nile4_in32(NILE4_CPUSTAT);
-    t |= 1;
-    nile4_out32(NILE4_CPUSTAT, t);
-    /* Call the PROM */
-    back_to_prom();
+       u32 t;
+
+       /* PCI cold reset */
+       t = nile4_in32(NILE4_PCICTRL + 4);
+       t |= 0x40000000;
+       nile4_out32(NILE4_PCICTRL + 4, t);
+       /* CPU cold reset */
+       t = nile4_in32(NILE4_CPUSTAT);
+       t |= 1;
+       nile4_out32(NILE4_CPUSTAT, t);
+       /* Call the PROM */
+       back_to_prom();
 }
 
 static void ddb_machine_halt(void)
 {
-    printk("DDB Vrc-5074 halted.\n");
-    do {} while (1);
+       printk("DDB Vrc-5074 halted.\n");
+       do {
+       } while (1);
 }
 
 static void ddb_machine_power_off(void)
 {
-    printk("DDB Vrc-5074 halted. Please turn off the power.\n");
-    do {} while (1);
+       printk("DDB Vrc-5074 halted. Please turn off the power.\n");
+       do {
+       } while (1);
 }
 
 extern void ddb_irq_setup(void);
 
-void (*board_time_init)(struct irqaction *irq);
+void (*board_time_init) (struct irqaction * irq);
 
 
 static void __init ddb_time_init(struct irqaction *irq)
 {
-    /* set the clock to 1 Hz */
-    nile4_out32(NILE4_T2CTRL, 1000000);
-    /* enable the General-Purpose Timer */
-    nile4_out32(NILE4_T2CTRL+4, 0x00000001);
-    /* reset timer */
-    nile4_out32(NILE4_T2CNTR, 0);
-    /* enable interrupt */
-    nile4_enable_irq(NILE4_INT_GPT);
-    i8259_setup_irq(nile4_to_irq(NILE4_INT_GPT), irq);
-    set_cp0_status(ST0_IM, IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
+       /* set the clock to 1 Hz */
+       nile4_out32(NILE4_T2CTRL, 1000000);
+       /* enable the General-Purpose Timer */
+       nile4_out32(NILE4_T2CTRL + 4, 0x00000001);
+       /* reset timer */
+       nile4_out32(NILE4_T2CNTR, 0);
+       /* enable interrupt */
+       nile4_enable_irq(NILE4_INT_GPT);
+       i8259_setup_irq(nile4_to_irq(NILE4_INT_GPT), irq);
+       change_cp0_status(ST0_IM,
+                         IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
 }
 
 void __init ddb_setup(void)
 {
-    extern int panic_timeout;
-
-    irq_setup = ddb_irq_setup;
-    mips_io_port_base = NILE4_PCI_IO_BASE;
-    isa_slot_offset = NILE4_PCI_MEM_BASE;
-    request_region(0x00, 0x20, "dma1");
-    request_region(0x40, 0x20, "timer");
-    request_region(0x70, 0x10, "rtc");
-    request_region(0x80, 0x10, "dma page reg");
-    request_region(0xc0, 0x20, "dma2");
-    board_time_init = ddb_time_init;
-
-    _machine_restart = ddb_machine_restart;
-    _machine_halt = ddb_machine_halt;
-    _machine_power_off = ddb_machine_power_off;
+       extern int panic_timeout;
+
+       irq_setup = ddb_irq_setup;
+       mips_io_port_base = NILE4_PCI_IO_BASE;
+       isa_slot_offset = NILE4_PCI_MEM_BASE;
+       request_region(0x00, 0x20, "dma1");
+       request_region(0x40, 0x20, "timer");
+       request_region(0x70, 0x10, "rtc");
+       request_region(0x80, 0x10, "dma page reg");
+       request_region(0xc0, 0x20, "dma2");
+       board_time_init = ddb_time_init;
+
+       _machine_restart = ddb_machine_restart;
+       _machine_halt = ddb_machine_halt;
+       _machine_power_off = ddb_machine_power_off;
 
 #ifdef CONFIG_BLK_DEV_IDE
-    ide_ops = &std_ide_ops;
+       ide_ops = &std_ide_ops;
 #endif
-    rtc_ops = &ddb_rtc_ops;
+       rtc_ops = &ddb_rtc_ops;
 
-    /* Reboot on panic */
-    panic_timeout = 180;
-}
-
-int __init page_is_ram(unsigned long pagenr)
-{
-    return 1;
+       /* Reboot on panic */
+       panic_timeout = 180;
 }
 
 
@@ -133,12 +128,12 @@ int __init page_is_ram(unsigned long pagenr)
 #define NS16550_BASE           (NILE4_PCI_IO_BASE+0x03f8)
 static inline u8 ns16550_in(u32 reg)
 {
-    return *(volatile u8 *)(NS16550_BASE+reg);
+       return *(volatile u8 *) (NS16550_BASE + reg);
 }
 
 static inline void ns16550_out(u32 reg, u8 val)
 {
-    *(volatile u8 *)(NS16550_BASE+reg) = val;
+       *(volatile u8 *) (NS16550_BASE + reg) = val;
 }
 #endif
 
@@ -168,87 +163,84 @@ static inline void ns16550_out(u32 reg, u8 val)
 void _serinit(void)
 {
 #if USE_NILE4_SERIAL
-    ns16550_out(NS16550_LCR, 0x80);
-    ns16550_out(NS16550_DLM, 0x00);
-    ns16550_out(NS16550_DLL, 0x36);    /* 9600 baud */
-    ns16550_out(NS16550_LCR, 0x00);
-    ns16550_out(NS16550_LCR, 0x03);
-    ns16550_out(NS16550_FCR, 0x47);
+       ns16550_out(NS16550_LCR, 0x80);
+       ns16550_out(NS16550_DLM, 0x00);
+       ns16550_out(NS16550_DLL, 0x36); /* 9600 baud */
+       ns16550_out(NS16550_LCR, 0x00);
+       ns16550_out(NS16550_LCR, 0x03);
+       ns16550_out(NS16550_FCR, 0x47);
 #else
-    /* done by PMON */
+       /* done by PMON */
 #endif
 }
 
 void _putc(char c)
 {
-    while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
-    ns16550_out(NS16550_THR, c);
-    if (c == '\n') {
        while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
-       ns16550_out(NS16550_THR, '\r');
-    }
+       ns16550_out(NS16550_THR, c);
+       if (c == '\n') {
+               while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
+               ns16550_out(NS16550_THR, '\r');
+       }
 }
 
 void _puts(const char *s)
 {
-    char c;
-    while ((c = *s++))
-       _putc(c);
+       char c;
+       while ((c = *s++))
+               _putc(c);
 }
 
 char _getc(void)
 {
-    while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR));
-    return ns16550_in(NS16550_RBR);
+       while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR));
+       return ns16550_in(NS16550_RBR);
 }
 
 int _testc(void)
 {
-    return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0;
+       return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0;
 }
 
 
-    /*
-     *  Hexadecimal 7-segment LED
-     */
-
+/*
+ *  Hexadecimal 7-segment LED
+ */
 void ddb5074_led_hex(int hex)
 {
-    outb(hex, 0x80);
+       outb(hex, 0x80);
 }
 
 
-    /*
-     *  LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543
-     */
-
+/*
+ *  LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543
+ */
 struct pci_dev *pci_pmu = NULL;
 
 void ddb5074_led_d2(int on)
 {
-    u8 t;
-
-    if (pci_pmu) {
-       pci_read_config_byte(pci_pmu, 0x7e, &t);
-       if (on)
-           t &= 0x7f;
-       else
-           t |= 0x80;
-       pci_write_config_byte(pci_pmu, 0x7e, t);
-    }
+       u8 t;
+
+       if (pci_pmu) {
+               pci_read_config_byte(pci_pmu, 0x7e, &t);
+               if (on)
+                       t &= 0x7f;
+               else
+                       t |= 0x80;
+               pci_write_config_byte(pci_pmu, 0x7e, t);
+       }
 }
 
 void ddb5074_led_d3(int on)
 {
-    u8 t;
-
-    if (pci_pmu) {
-       pci_read_config_byte(pci_pmu, 0x7e, &t);
-       if (on)
-           t &= 0xbf;
-       else
-           t |= 0x40;
-       pci_write_config_byte(pci_pmu, 0x7e, t);
-    }
-}
+       u8 t;
 
+       if (pci_pmu) {
+               pci_read_config_byte(pci_pmu, 0x7e, &t);
+               if (on)
+                       t &= 0xbf;
+               else
+                       t |= 0x40;
+               pci_write_config_byte(pci_pmu, 0x7e, t);
+       }
+}
index 14503c6..4b3f1dc 100644 (file)
@@ -3,33 +3,30 @@
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id*
  */
-
 #include <linux/init.h>
 #include <asm/mc146818rtc.h>
 
 static unsigned char ddb_rtc_read_data(unsigned long addr)
 {
-    outb_p(addr, RTC_PORT(0));
-    return inb_p(RTC_PORT(1));
+       outb_p(addr, RTC_PORT(0));
+
+       return inb_p(RTC_PORT(1));
 }
 
 static void ddb_rtc_write_data(unsigned char data, unsigned long addr)
 {
-    outb_p(addr, RTC_PORT(0));
-    outb_p(data, RTC_PORT(1));
+       outb_p(addr, RTC_PORT(0));
+       outb_p(data, RTC_PORT(1));
 }
 
 static int ddb_rtc_bcd_mode(void)
 {
-    return 1;
+       return 1;
 }
 
 struct rtc_ops ddb_rtc_ops = {
-    ddb_rtc_read_data,
-    ddb_rtc_write_data,
-    ddb_rtc_bcd_mode
+       ddb_rtc_read_data,
+       ddb_rtc_write_data,
+       ddb_rtc_bcd_mode
 };
-
diff --git a/arch/mips/ddb5476/Makefile b/arch/mips/ddb5476/Makefile
new file mode 100644 (file)
index 0000000..f214396
--- /dev/null
@@ -0,0 +1,23 @@
+#
+# Makefile for the NEC DDB Vrc-5074 specific kernel interface routines
+# under Linux.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+#
+
+.S.s:
+       $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+       $(CC) $(CFLAGS) -c $< -o $*.o
+
+O_TARGET = ddb5476.a
+
+obj-y                          += setup.o irq.o time.o prom.o pci.o \
+                                  int-handler.o nile4.o
+obj-$(CONFIG_REMOTE_DEBUG)     += dbg_io.o
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/mips/ddb5476/dbg_io.c b/arch/mips/ddb5476/dbg_io.c
new file mode 100644 (file)
index 0000000..aad938a
--- /dev/null
@@ -0,0 +1,125 @@
+
+#include <linux/config.h>
+
+#if (defined(CONFIG_DDB5476) && defined(CONFIG_REMOTE_DEBUG))
+
+/* --- CONFIG --- */
+
+/* we need uint32 uint8 */
+/* #include "types.h" */
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+
+/* --- END OF CONFIG --- */
+
+#define         UART16550_BAUD_2400             2400
+#define         UART16550_BAUD_4800             4800
+#define         UART16550_BAUD_9600             9600
+#define         UART16550_BAUD_19200            19200
+#define         UART16550_BAUD_38400            38400
+#define         UART16550_BAUD_57600            57600
+#define         UART16550_BAUD_115200           115200
+
+#define         UART16550_PARITY_NONE           0
+#define         UART16550_PARITY_ODD            0x08
+#define         UART16550_PARITY_EVEN           0x18
+#define         UART16550_PARITY_MARK           0x28
+#define         UART16550_PARITY_SPACE          0x38
+
+#define         UART16550_DATA_5BIT             0x0
+#define         UART16550_DATA_6BIT             0x1
+#define         UART16550_DATA_7BIT             0x2
+#define         UART16550_DATA_8BIT             0x3
+
+#define         UART16550_STOP_1BIT             0x0
+#define         UART16550_STOP_2BIT             0x4
+
+/* ----------------------------------------------------- */
+
+/* === CONFIG === */
+
+/* [jsun] we use the second serial port for kdb */
+#define         BASE                    0xa60002f8
+#define         MAX_BAUD                115200
+
+/* === END OF CONFIG === */
+
+/* register offset */
+#define         OFS_RCV_BUFFER          0
+#define         OFS_TRANS_HOLD          0
+#define         OFS_SEND_BUFFER         0
+#define         OFS_INTR_ENABLE         1
+#define         OFS_INTR_ID             2
+#define         OFS_DATA_FORMAT         3
+#define         OFS_LINE_CONTROL        3
+#define         OFS_MODEM_CONTROL       4
+#define         OFS_RS232_OUTPUT        4
+#define         OFS_LINE_STATUS         5
+#define         OFS_MODEM_STATUS        6
+#define         OFS_RS232_INPUT         6
+#define         OFS_SCRATCH_PAD         7
+
+#define         OFS_DIVISOR_LSB         0
+#define         OFS_DIVISOR_MSB         1
+
+
+/* memory-mapped read/write of the port */
+#define         UART16550_READ(y)    (*((volatile uint8*)(BASE + y)))
+#define         UART16550_WRITE(y, z)  ((*((volatile uint8*)(BASE + y))) = z)
+
+void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+{
+       /* disable interrupts */
+       UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+       /* set up buad rate */
+       {
+               uint32 divisor;
+
+               /* set DIAB bit */
+               UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+
+               /* set divisor */
+               divisor = MAX_BAUD / baud;
+               UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+               UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
+
+               /* clear DIAB bit */
+               UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+       }
+
+       /* set data format */
+       UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+static int remoteDebugInitialized = 0;
+
+uint8 getDebugChar(void)
+{
+       if (!remoteDebugInitialized) {
+               remoteDebugInitialized = 1;
+               debugInit(UART16550_BAUD_38400,
+                         UART16550_DATA_8BIT,
+                         UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+       }
+
+       while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
+       return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+
+int putDebugChar(uint8 byte)
+{
+       if (!remoteDebugInitialized) {
+               remoteDebugInitialized = 1;
+               debugInit(UART16550_BAUD_9600,
+                         UART16550_DATA_8BIT,
+                         UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+       }
+
+       while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
+       UART16550_WRITE(OFS_SEND_BUFFER, byte);
+       return 1;
+}
+
+#endif
diff --git a/arch/mips/ddb5476/int-handler.S b/arch/mips/ddb5476/int-handler.S
new file mode 100644 (file)
index 0000000..9a13110
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ *  arch/mips/ddb5074/int-handler.S -- NEC DDB Vrc-5074 interrupt handler
+ *
+ *  Based on arch/mips/sgi/kernel/indyIRQ.S
+ *
+ *  Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/*
+ * A lot of complication here is taken away because:
+ *
+ * 1) We handle one interrupt and return, sitting in a loop and moving across
+ *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
+ *    common case is one pending IRQ so optimize in that direction.
+ *
+ * 2) We need not check against bits in the status register IRQ mask, that
+ *    would make this routine slow as hell.
+ *
+ * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
+ *    between like BSD spl() brain-damage.
+ *
+ * Furthermore, the IRQs on the INDY look basically (barring software IRQs
+ * which we don't use at all) like:
+ *
+ *     MIPS IRQ        Source
+ *      --------        ------
+ *             0       Software (ignored)
+ *             1        Software (ignored)
+ *             2        Local IRQ level zero
+ *             3        Local IRQ level one
+ *             4        8254 Timer zero
+ *             5        8254 Timer one
+ *             6        Bus Error
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ *                  Local IRQ zero
+ *                  Local IRQ one
+ *                  Bus Error
+ *                  8254 Timer zero
+ * Lowest  ----     8254 Timer one
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+       .text
+       .set    noreorder
+       .set    noat
+       .align  5
+       NESTED(ddbIRQ, PT_SIZE, sp)
+       SAVE_ALL
+       CLI
+       .set    at
+       mfc0    s1, CP0_CAUSE           # get irq mask
+
+#if 1
+       mfc0    t2,CP0_STATUS           # get enabled interrupts
+       and     s0, s1, t2              # isolate allowed ones
+#endif
+       /* First we check for r4k counter/timer IRQ. */
+       andi    a0, s0, CAUSEF_IP2      # delay slot, check local level zero
+       beq     a0, zero, 1f
+        andi   a0, s0, CAUSEF_IP3      # delay slot, check local level one
+
+       /* Wheee, local level zero interrupt. */
+       jal     ddb_local0_irqdispatch
+        move   a0, sp                  # delay slot
+
+       j       ret_from_irq
+        nop                            # delay slot
+
+1:
+       beq     a0, zero, 1f
+        andi   a0, s0, CAUSEF_IP6      # delay slot, check bus error
+
+       /* Wheee, local level one interrupt. */
+       move    a0, sp
+       jal     ddb_local1_irqdispatch
+        nop
+
+       j       ret_from_irq
+        nop
+
+1:
+       beq     a0, zero, 1f
+        nop
+
+       /* Wheee, an asynchronous bus error... */
+       move    a0, sp
+       jal     ddb_buserror_irq
+        nop
+
+       j       ret_from_irq
+        nop
+
+1:
+       /* Here by mistake?  This is possible, what can happen
+        * is that by the time we take the exception the IRQ
+        * pin goes low, so just leave if this is the case.
+        */
+       andi    a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)
+       beq     a0, zero, 1f
+
+       /* Must be one of the 8254 timers... */
+       move    a0, sp
+       jal     ddb_8254timer_irq
+        nop
+1:
+       /* phamtom interrupt */
+       move    a0, s1
+       jal     ddb_phantom_irq
+       nop
+       j       ret_from_irq
+       nop
+       END(ddbIRQ)
diff --git a/arch/mips/ddb5476/irq.c b/arch/mips/ddb5476/irq.c
new file mode 100644 (file)
index 0000000..ea88889
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ *  arch/mips/ddb5476/irq.c -- NEC DDB Vrc-5476 interrupt routines
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/ptrace.h>
+#include <asm/nile4.h>
+
+extern void __init i8259_init(void);
+extern void i8259_disable_irq(unsigned int irq_nr);
+extern void i8259_enable_irq(unsigned int irq_nr);
+
+extern asmlinkage void ddbIRQ(void);
+extern asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs);
+extern asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
+
+
+void no_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+}
+
+
+#define M1543_PNP_CONFIG       0x03f0  /* PnP Config Port */
+#define M1543_PNP_INDEX                0x03f0  /* PnP Index Port */
+#define M1543_PNP_DATA         0x03f1  /* PnP Data Port */
+
+#define M1543_PNP_ALT_CONFIG   0x0370  /* Alternative PnP Config Port */
+#define M1543_PNP_ALT_INDEX    0x0370  /* Alternative PnP Index Port */
+#define M1543_PNP_ALT_DATA     0x0371  /* Alternative PnP Data Port */
+
+#define M1543_INT1_MASTER_CTRL 0x0020  /* INT_1 (master) Control Register */
+#define M1543_INT1_MASTER_MASK 0x0021  /* INT_1 (master) Mask Register */
+
+#define M1543_INT1_SLAVE_CTRL  0x00a0  /* INT_1 (slave) Control Register */
+#define M1543_INT1_SLAVE_MASK  0x00a1  /* INT_1 (slave) Mask Register */
+
+#define M1543_INT1_MASTER_ELCR 0x04d0  /* INT_1 (master) Edge/Level Control */
+#define M1543_INT1_SLAVE_ELCR  0x04d1  /* INT_1 (slave) Edge/Level Control */
+
+static struct {
+       struct resource m1543_config;
+       struct resource pic_elcr;
+} m1543_ioport = {
+       { "M1543 config", M1543_PNP_CONFIG, M1543_PNP_CONFIG + 1,
+         IORESOURCE_BUSY},
+       { "pic ELCR", M1543_INT1_MASTER_ELCR, M1543_INT1_MASTER_ELCR + 1,
+         IORESOURCE_BUSY}
+};
+
+static void m1543_irq_setup(void)
+{
+       /*
+        *  The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13.  Not all
+        *  the possible IO sources in the M1543 are in use by us.  We will
+        *  use the following mapping:
+        *
+        *      IRQ1  - keyboard (default set by M1543)
+        *      IRQ3  - reserved for UART B (default set by M1543) (note that
+        *              the schematics for the DDB Vrc-5476 board seem to 
+        *              indicate that IRQ3 is connected to the DS1386 
+        *              watchdog timer interrupt output so we might have 
+        *              a conflict)
+        *      IRQ4  - reserved for UART A (default set by M1543)
+        *      IRQ5  - parallel (default set by M1543)
+        *      IRQ8  - DS1386 time of day (RTC) interrupt
+        *      IRQ9  - USB (hardwired in ddb_setup)
+        *      IRQ10 - PMU (hardwired in ddb_setup)
+        *      IRQ12 - mouse
+        *      IRQ14,15 - IDE controller (need to be confirmed, jsun)
+        */
+
+       /*
+        *  Assing mouse interrupt to IRQ12 
+        */
+
+       /* Enter configuration mode */
+       outb(0x51, M1543_PNP_CONFIG);
+       outb(0x23, M1543_PNP_CONFIG);
+
+       /* Select logical device 7 (Keyboard) */
+       outb(0x07, M1543_PNP_INDEX);
+       outb(0x07, M1543_PNP_DATA);
+
+       /* Select IRQ12 */
+       outb(0x72, M1543_PNP_INDEX);
+       outb(0x0c, M1543_PNP_DATA);
+
+       /* Leave configration mode */
+       outb(0xbb, M1543_PNP_CONFIG);
+
+
+       /* Initialize the 8259 PIC in the M1543 */
+       i8259_init();
+
+       /* Enable the interrupt cascade from M1543 */
+       nile4_enable_irq(NILE4_INT_INTC);
+
+       /* request io ports */
+       if (request_resource(&ioport_resource, &m1543_ioport.m1543_config)
+           || request_resource(&ioport_resource, &m1543_ioport.pic_elcr)) {
+               printk("m1543_irq_setup : requesting io ports failed.\n");
+               for (;;);
+       }
+}
+
+static void nile4_irq_setup(void)
+{
+       int i;
+
+       /* Map all interrupts to CPU int #0 */
+       nile4_map_irq_all(0);
+
+       /* PCI INTA#-E# must be level triggered */
+       nile4_set_pci_irq_level_or_edge(0, 1);
+       nile4_set_pci_irq_level_or_edge(1, 1);
+       nile4_set_pci_irq_level_or_edge(2, 1);
+       nile4_set_pci_irq_level_or_edge(3, 1);
+
+       /* PCI INTA#, B#, D# must be active low, INTC# must be active high */
+       nile4_set_pci_irq_polarity(0, 0);
+       nile4_set_pci_irq_polarity(1, 0);
+       nile4_set_pci_irq_polarity(2, 1);
+       nile4_set_pci_irq_polarity(3, 0);
+
+       for (i = 0; i < 16; i++)
+               nile4_clear_irq(i);
+
+       /* Enable CPU int #0 */
+       nile4_enable_irq_output(0);
+
+       /* memory resource acquire in ddb_setup */
+}
+
+
+/*
+ * IRQ2 is cascade interrupt to second interrupt controller
+ */
+static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL };
+
+
+void disable_irq(unsigned int irq_nr)
+{
+       if (is_i8259_irq(irq_nr))
+               i8259_disable_irq(irq_nr);
+       else
+               nile4_disable_irq(irq_to_nile4(irq_nr));
+}
+
+void enable_irq(unsigned int irq_nr)
+{
+       if (is_i8259_irq(irq_nr))
+               i8259_enable_irq(irq_nr);
+       else
+               nile4_enable_irq(irq_to_nile4(irq_nr));
+}
+
+int table[16] = { 0, };
+
+void ddb_local0_irqdispatch(struct pt_regs *regs)
+{
+       u32 mask;
+       int nile4_irq;
+#if 0
+       volatile static int nesting = 0;
+       if (nesting++ == 0)
+               ddb5476_led_d3(1);
+       ddb5476_led_hex(nesting < 16 ? nesting : 15);
+#endif
+
+       mask = nile4_get_irq_stat(0);
+       nile4_clear_irq_mask(mask);
+
+       /* Handle the timer interrupt first */
+       if (mask & (1 << NILE4_INT_GPT)) {
+               nile4_disable_irq(NILE4_INT_GPT);
+               do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs);
+               nile4_enable_irq(NILE4_INT_GPT);
+               mask &= ~(1 << NILE4_INT_GPT);
+       }
+       for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1)
+               if (mask & 1) {
+                       nile4_disable_irq(nile4_irq);
+                       if (nile4_irq == NILE4_INT_INTC) {
+                               int i8259_irq = nile4_i8259_iack();
+                               i8259_do_irq(i8259_irq, regs);
+                       } else {
+                               do_IRQ(nile4_to_irq(nile4_irq), regs);
+                       }
+                       nile4_enable_irq(nile4_irq);
+               }
+#if 0
+       if (--nesting == 0)
+               ddb5476_led_d3(0);
+       ddb5476_led_hex(nesting < 16 ? nesting : 15);
+#endif
+}
+
+void ddb_local1_irqdispatch(void)
+{
+       printk("ddb_local1_irqdispatch called\n");
+}
+
+void ddb_buserror_irq(void)
+{
+       printk("ddb_buserror_irq called\n");
+}
+
+void ddb_8254timer_irq(void)
+{
+       printk("ddb_8254timer_irq called\n");
+}
+
+void ddb_phantom_irq(unsigned long cause)
+{
+       printk("phantom interrupts detected : \n");
+       printk("\tcause \t\t0x%08x\n", cause);
+       printk("\tcause reg\t0x%08x\n",
+              read_32bit_cp0_register(CP0_CAUSE));
+       printk("\tstatus reg\t0x%08x\n",
+              read_32bit_cp0_register(CP0_STATUS));
+}
+
+void __init ddb_irq_setup(void)
+{
+#ifdef CONFIG_REMOTE_DEBUG
+       printk("Wait for gdb client connection ...\n");
+       set_debug_traps();
+       breakpoint();           /* you may move this line to whereever you want :-) */
+#endif
+       i8259_setup_irq(2, &irq2);
+
+       nile4_irq_setup();
+       m1543_irq_setup();
+
+       /* we pin #0 - #4 (no internal timer) */
+       change_cp0_status(ST0_IM,
+                         IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
+
+       set_except_vector(0, ddbIRQ);
+}
diff --git a/arch/mips/ddb5476/nile4.c b/arch/mips/ddb5476/nile4.c
new file mode 100644 (file)
index 0000000..df6d180
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ *  arch/mips/ddb5074/nile4.c -- NEC Vrc-5074 Nile 4 support routines
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <asm/nile4.h>
+
+
+/*
+ *  Physical Device Address Registers
+ *
+ *  Note: 32 bit addressing only!
+ */
+void nile4_set_pdar(u32 pdar, u32 phys, u32 size, int width,
+                   int on_memory_bus, int visible)
+{
+       u32 maskbits;
+       u32 widthbits;
+
+       if (pdar > NILE4_BOOTCS || (pdar & 7)) {
+               printk("nile4_set_pdar: invalid pdar %d\n", pdar);
+               return;
+       }
+       if (pdar == NILE4_INTCS && size != 0x00200000) {
+               printk("nile4_set_pdar: INTCS size must be 2 MB\n");
+               return;
+       }
+       switch (size) {
+#if 0                          /* We don't support 4 GB yet */
+       case 0x100000000:       /* 4 GB */
+               maskbits = 4;
+               break;
+#endif
+       case 0x80000000:        /* 2 GB */
+               maskbits = 5;
+               break;
+       case 0x40000000:        /* 1 GB */
+               maskbits = 6;
+               break;
+       case 0x20000000:        /* 512 MB */
+               maskbits = 7;
+               break;
+       case 0x10000000:        /* 256 MB */
+               maskbits = 8;
+               break;
+       case 0x08000000:        /* 128 MB */
+               maskbits = 9;
+               break;
+       case 0x04000000:        /* 64 MB */
+               maskbits = 10;
+               break;
+       case 0x02000000:        /* 32 MB */
+               maskbits = 11;
+               break;
+       case 0x01000000:        /* 16 MB */
+               maskbits = 12;
+               break;
+       case 0x00800000:        /* 8 MB */
+               maskbits = 13;
+               break;
+       case 0x00400000:        /* 4 MB */
+               maskbits = 14;
+               break;
+       case 0x00200000:        /* 2 MB */
+               maskbits = 15;
+               break;
+       case 0:         /* OFF */
+               maskbits = 0;
+               break;
+       default:
+               printk("nile4_set_pdar: unsupported size %p\n",
+                      (void *) size);
+               return;
+       }
+       switch (width) {
+       case 8:
+               widthbits = 0;
+               break;
+       case 16:
+               widthbits = 1;
+               break;
+       case 32:
+               widthbits = 2;
+               break;
+       case 64:
+               widthbits = 3;
+               break;
+       default:
+               printk("nile4_set_pdar: unsupported width %d\n", width);
+               return;
+       }
+       nile4_out32(pdar, maskbits | (on_memory_bus ? 0x10 : 0) |
+                   (visible ? 0x20 : 0) | (widthbits << 6) |
+                   (phys & 0xffe00000));
+       nile4_out32(pdar + 4, 0);
+       /*
+        * When programming a PDAR, the register should be read immediately
+        * after writing it. This ensures that address decoders are properly
+        * configured.
+        */
+       nile4_in32(pdar);
+       nile4_in32(pdar + 4);
+}
+
+
+/*
+ *  PCI Master Registers
+ *
+ *  Note: 32 bit addressing only!
+ */
+void nile4_set_pmr(u32 pmr, u32 type, u32 addr)
+{
+       if (pmr != NILE4_PCIINIT0 && pmr != NILE4_PCIINIT1) {
+               printk("nile4_set_pmr: invalid pmr %d\n", pmr);
+               return;
+       }
+       switch (type) {
+       case NILE4_PCICMD_IACK: /* PCI Interrupt Acknowledge */
+       case NILE4_PCICMD_IO:   /* PCI I/O Space */
+       case NILE4_PCICMD_MEM:  /* PCI Memory Space */
+       case NILE4_PCICMD_CFG:  /* PCI Configuration Space */
+               break;
+       default:
+               printk("nile4_set_pmr: invalid type %d\n", type);
+               return;
+       }
+       nile4_out32(pmr, (type << 1) | 0x10 | (addr & 0xffe00000));
+       nile4_out32(pmr + 4, 0);
+}
+
+
+/*
+ *  Interrupt Programming
+ */
+void nile4_map_irq(int nile4_irq, int cpu_irq)
+{
+       u32 offset, t;
+
+       offset = NILE4_INTCTRL;
+       if (nile4_irq >= 8) {
+               offset += 4;
+               nile4_irq -= 8;
+       }
+       t = nile4_in32(offset);
+       t &= ~(7 << (nile4_irq * 4));
+       t |= cpu_irq << (nile4_irq * 4);
+       nile4_out32(offset, t);
+}
+
+void nile4_map_irq_all(int cpu_irq)
+{
+       u32 all, t;
+
+       all = cpu_irq;
+       all |= all << 4;
+       all |= all << 8;
+       all |= all << 16;
+       t = nile4_in32(NILE4_INTCTRL);
+       t &= 0x88888888;
+       t |= all;
+       nile4_out32(NILE4_INTCTRL, t);
+       t = nile4_in32(NILE4_INTCTRL + 4);
+       t &= 0x88888888;
+       t |= all;
+       nile4_out32(NILE4_INTCTRL + 4, t);
+}
+
+void nile4_enable_irq(int nile4_irq)
+{
+       u32 offset, t;
+
+       offset = NILE4_INTCTRL;
+       if (nile4_irq >= 8) {
+               offset += 4;
+               nile4_irq -= 8;
+       }
+       t = nile4_in32(offset);
+       t |= 8 << (nile4_irq * 4);
+       nile4_out32(offset, t);
+}
+
+void nile4_disable_irq(int nile4_irq)
+{
+       u32 offset, t;
+
+       offset = NILE4_INTCTRL;
+       if (nile4_irq >= 8) {
+               offset += 4;
+               nile4_irq -= 8;
+       }
+       t = nile4_in32(offset);
+       t &= ~(8 << (nile4_irq * 4));
+       nile4_out32(offset, t);
+}
+
+void nile4_disable_irq_all(void)
+{
+       nile4_out32(NILE4_INTCTRL, 0);
+       nile4_out32(NILE4_INTCTRL + 4, 0);
+}
+
+u16 nile4_get_irq_stat(int cpu_irq)
+{
+       return nile4_in16(NILE4_INTSTAT0 + cpu_irq * 2);
+}
+
+void nile4_enable_irq_output(int cpu_irq)
+{
+       u32 t;
+
+       t = nile4_in32(NILE4_INTSTAT1 + 4);
+       t |= 1 << (16 + cpu_irq);
+       nile4_out32(NILE4_INTSTAT1, t);
+}
+
+void nile4_disable_irq_output(int cpu_irq)
+{
+       u32 t;
+
+       t = nile4_in32(NILE4_INTSTAT1 + 4);
+       t &= ~(1 << (16 + cpu_irq));
+       nile4_out32(NILE4_INTSTAT1, t);
+}
+
+void nile4_set_pci_irq_polarity(int pci_irq, int high)
+{
+       u32 t;
+
+       t = nile4_in32(NILE4_INTPPES);
+       if (high)
+               t &= ~(1 << (pci_irq * 2));
+       else
+               t |= 1 << (pci_irq * 2);
+       nile4_out32(NILE4_INTPPES, t);
+}
+
+void nile4_set_pci_irq_level_or_edge(int pci_irq, int level)
+{
+       u32 t;
+
+       t = nile4_in32(NILE4_INTPPES);
+       if (level)
+               t |= 2 << (pci_irq * 2);
+       else
+               t &= ~(2 << (pci_irq * 2));
+       nile4_out32(NILE4_INTPPES, t);
+}
+
+void nile4_clear_irq(int nile4_irq)
+{
+       nile4_out32(NILE4_INTCLR, 1 << nile4_irq);
+}
+
+void nile4_clear_irq_mask(u32 mask)
+{
+       nile4_out32(NILE4_INTCLR, mask);
+}
+
+u8 nile4_i8259_iack(void)
+{
+       u8 irq;
+
+       /* Set window 0 for interrupt acknowledge */
+       nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IACK, 0);
+       irq = *(volatile u8 *) NILE4_PCI_IACK_BASE;
+       /* Set window 0 for PCI I/O space */
+       nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IO, 0);
+       return irq;
+}
+
+#if 0
+void nile4_dump_irq_status(void)
+{
+       printk("CPUSTAT = %p:%p\n", (void *) nile4_in32(NILE4_CPUSTAT + 4),
+              (void *) nile4_in32(NILE4_CPUSTAT));
+       printk("INTCTRL = %p:%p\n", (void *) nile4_in32(NILE4_INTCTRL + 4),
+              (void *) nile4_in32(NILE4_INTCTRL));
+       printk("INTSTAT0 = %p:%p\n",
+              (void *) nile4_in32(NILE4_INTSTAT0 + 4),
+              (void *) nile4_in32(NILE4_INTSTAT0));
+       printk("INTSTAT1 = %p:%p\n",
+              (void *) nile4_in32(NILE4_INTSTAT1 + 4),
+              (void *) nile4_in32(NILE4_INTSTAT1));
+       printk("INTCLR = %p:%p\n", (void *) nile4_in32(NILE4_INTCLR + 4),
+              (void *) nile4_in32(NILE4_INTCLR));
+       printk("INTPPES = %p:%p\n", (void *) nile4_in32(NILE4_INTPPES + 4),
+              (void *) nile4_in32(NILE4_INTPPES));
+}
+#endif
diff --git a/arch/mips/ddb5476/pci.c b/arch/mips/ddb5476/pci.c
new file mode 100644 (file)
index 0000000..c31113c
--- /dev/null
@@ -0,0 +1,495 @@
+/*
+ *  arch/mips/ddb5476/pci.c -- NEC DDB Vrc-5074 PCI access routines
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Albert Dorofeev <albert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+
+#include <asm-mips/nile4.h>
+
+
+static u32 nile4_pre_pci_access0(int slot_num)
+{
+       u32 pci_addr = 0;
+       u32 virt_addr = NILE4_PCI_CFG_BASE;
+
+       /* work around the bug for Vrc5476 */
+       if (slot_num == 13)
+               return NILE4_BASE + NILE4_PCI_BASE;
+
+       /* Set window 1 address 08000000 - 32 bit - 128 MB (PCI config space) */
+       nile4_set_pdar(NILE4_PCIW1, PHYSADDR(virt_addr), 0x08000000, 32, 0,
+                      0);
+
+       // [jsun] we start scanning from addr:10, 
+       // with 128M we can go up to addr:26 (slot 16)
+       if (slot_num <= 16) {
+               virt_addr += 0x00000400 << slot_num;
+       } else {
+               /* for high slot, we have to set higher PCI base addr */
+               pci_addr = 0x00000400 << slot_num;
+       }
+       nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_CFG, pci_addr);
+       return virt_addr;
+}
+
+static void nile4_post_pci_access0(void)
+{
+       /*
+        * Set window 1 back to address 08000000 - 32 bit - 128 MB
+        * (PCI IO space)
+        */
+       nile4_set_pdar(NILE4_PCIW1, PHYSADDR(NILE4_PCI_MEM_BASE),
+                      0x08000000, 32, 1, 1);
+       // nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0);
+       nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0x08000000);
+}
+
+
+static int nile4_pci_read_config_dword(struct pci_dev *dev,
+                                      int where, u32 * val)
+{
+       int slot_num, func_num;
+       u32 base;
+       u32 addr;
+
+       /*
+        *  Do we need to generate type 1 configure transaction?
+        */
+       if (dev->bus->number) {
+               /* FIXME - not working yet */
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+               /*
+                * the largest type 1 configuration addr is 16M, < 256M
+                * config space
+                */
+               slot_num = 0;
+               addr =
+                   (dev->bus->number << 16) | (dev->devfn <
+                                               8) | where | 1;
+       } else {
+               slot_num = PCI_SLOT(dev->devfn);
+               func_num = PCI_FUNC(dev->devfn);
+               addr = (func_num << 8) + where;
+       }
+
+       base = nile4_pre_pci_access0(slot_num);
+       *val = *(volatile u32 *) (base + addr);
+       nile4_post_pci_access0();
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pci_write_config_dword(struct pci_dev *dev, int where,
+                                       u32 val)
+{
+       int slot_num, func_num;
+       u32 base;
+       u32 addr;
+
+       /*
+        *  Do we need to generate type 1 configure transaction?
+        */
+       if (dev->bus->number) {
+               /* FIXME - not working yet */
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+               /* the largest type 1 configuration addr is 16M, < 256M config space */
+               slot_num = 0;
+               addr =
+                   (dev->bus->number << 16) | (dev->devfn <
+                                               8) | where | 1;
+       } else {
+               slot_num = PCI_SLOT(dev->devfn);
+               func_num = PCI_FUNC(dev->devfn);
+               addr = (func_num << 8) + where;
+       }
+
+       base = nile4_pre_pci_access0(slot_num);
+       *(volatile u32 *) (base + addr) = val;
+       nile4_post_pci_access0();
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pci_read_config_word(struct pci_dev *dev, int where,
+                                     u16 * val)
+{
+       int status;
+       u32 result;
+
+       status = nile4_pci_read_config_dword(dev, where & ~3, &result);
+       if (status != PCIBIOS_SUCCESSFUL)
+               return status;
+       if (where & 2)
+               result >>= 16;
+       *val = result & 0xffff;
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pci_read_config_byte(struct pci_dev *dev, int where,
+                                     u8 * val)
+{
+       int status;
+       u32 result;
+
+       status = nile4_pci_read_config_dword(dev, where & ~3, &result);
+       if (status != PCIBIOS_SUCCESSFUL)
+               return status;
+       if (where & 1)
+               result >>= 8;
+       if (where & 2)
+               result >>= 16;
+       *val = result & 0xff;
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pci_write_config_word(struct pci_dev *dev, int where,
+                                      u16 val)
+{
+       int status, shift = 0;
+       u32 result;
+
+       status = nile4_pci_read_config_dword(dev, where & ~3, &result);
+       if (status != PCIBIOS_SUCCESSFUL)
+               return status;
+       if (where & 2)
+               shift += 16;
+       result &= ~(0xffff << shift);
+       result |= val << shift;
+       return nile4_pci_write_config_dword(dev, where & ~3, result);
+}
+
+static int nile4_pci_write_config_byte(struct pci_dev *dev, int where,
+                                      u8 val)
+{
+       int status, shift = 0;
+       u32 result;
+
+       status = nile4_pci_read_config_dword(dev, where & ~3, &result);
+       if (status != PCIBIOS_SUCCESSFUL)
+               return status;
+       if (where & 2)
+               shift += 16;
+       if (where & 1)
+               shift += 8;
+       result &= ~(0xff << shift);
+       result |= val << shift;
+       return nile4_pci_write_config_dword(dev, where & ~3, result);
+}
+
+struct pci_ops nile4_pci_ops = {
+       nile4_pci_read_config_byte,
+       nile4_pci_read_config_word,
+       nile4_pci_read_config_dword,
+       nile4_pci_write_config_byte,
+       nile4_pci_write_config_word,
+       nile4_pci_write_config_dword
+};
+
+struct {
+       struct resource ram;
+       struct resource flash;
+       struct resource isa_io;
+       struct resource pci_io;
+       struct resource isa_mem;
+       struct resource pci_mem;
+       struct resource nile4;
+       struct resource boot;
+} ddb5476_resources = {
+       // { "RAM", 0x00000000, 0x03ffffff, IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 },
+       {
+       "RAM", 0x00000000, 0x03ffffff, IORESOURCE_MEM}, {
+       "Flash ROM", 0x04000000, 0x043fffff}, {
+       "Nile4 ISA I/O", 0x06000000, 0x060fffff}, {
+       "Nile4 PCI I/O", 0x06100000, 0x07ffffff}, {
+       "Nile4 ISA mem", 0x08000000, 0x08ffffff, IORESOURCE_MEM}, {
+       "Nile4 PCI mem", 0x09000000, 0x0fffffff, IORESOURCE_MEM},
+           // { "Nile4 ctrl", 0x1fa00000, 0x1fbfffff, IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 },
+       {
+       "Nile4 ctrl", 0x1fa00000, 0x1fbfffff, IORESOURCE_MEM}, {
+       "Boot ROM", 0x1fc00000, 0x1fffffff}
+};
+
+struct resource M5229_resources[5] = {
+       {"M5229 BAR0", 0x1f0, 0x1f3, IORESOURCE_IO},
+       {"M5229 BAR1", 0x3f4, 0x3f7, IORESOURCE_IO},
+       {"M5229 BAR2", 0x170, 0x173, IORESOURCE_IO},
+       {"M5229 BAR3", 0x374, 0x377, IORESOURCE_IO},
+       {"M5229 BAR4", 0xf000, 0xf00f, IORESOURCE_IO}
+};
+
+static void __init ddb5476_pci_fixup(void)
+{
+       struct pci_dev *dev;
+
+       pci_for_each_dev(dev) {
+               if (dev->vendor == PCI_VENDOR_ID_NEC &&
+                   dev->device == PCI_DEVICE_ID_NEC_VRC5476) {
+                       /*
+                        * The first 64-bit PCI base register should point to
+                        * the Nile4 control registers. Unfortunately this
+                        * isn't the case, so we fix it ourselves. This allows
+                        * the serial driver to find the UART.
+                        */
+                       dev->resource[0] = ddb5476_resources.nile4;
+                       request_resource(&iomem_resource,
+                                        &dev->resource[0]);
+                       /*
+                        * The second 64-bit PCI base register points to the
+                        * first memory bank. Unfortunately the address is
+                        * wrong, so we fix it (again).
+                        */
+
+                       /* [jsun] We cannot request the resource anymore,
+                        * because kernel/setup.c has already reserved "System 
+                        * RAM" resource at the same spot.  
+                        * The fundamental problem here is that PCI host 
+                        * controller should not put system RAM mapping in BAR
+                        * and make subject to PCI resource assignement.
+                        * Current fix is a total hack.  We set parent to 1 so
+                         * so that PCI resource assignement code is fooled to 
+                         * think the resource is assigned, and will not attempt
+                         * to mess with it.
+                        */
+                       dev->resource[2] = ddb5476_resources.ram;
+                       if (request_resource(&iomem_resource,
+                                            &dev->resource[2]) ) {
+                               dev->resource[2].parent = 0x1;
+                        }
+
+               } else if (dev->vendor == PCI_VENDOR_ID_AL
+                          && dev->device == PCI_DEVICE_ID_AL_M7101) {
+                       /*
+                        * It's nice to have the LEDs on the GPIO pins
+                        * available for debugging
+                        */
+                       extern struct pci_dev *pci_pmu;
+                       u8 t8;
+
+                       pci_pmu = dev;  /* for LEDs D2 and D3 */
+                       /* Program the lines for LEDs D2 and D3 to output */
+                       nile4_pci_read_config_byte(dev, 0x7d, &t8);
+                       t8 |= 0xc0;
+                       nile4_pci_write_config_byte(dev, 0x7d, t8);
+                       /* Turn LEDs D2 and D3 off */
+                       nile4_pci_read_config_byte(dev, 0x7e, &t8);
+                       t8 |= 0xc0;
+                       nile4_pci_write_config_byte(dev, 0x7e, t8);
+               } else if (dev->vendor == PCI_VENDOR_ID_AL &&
+                          dev->device == 0x5229) {
+                       int i;
+                       for (i = 0; i < 5; i++) {
+                               dev->resource[i] = M5229_resources[i];
+                               request_resource(&ioport_resource,
+                                                &dev->resource[i]);
+                       }
+               }
+       }
+}
+
+static void __init pcibios_fixup_irqs(void)
+{
+       struct pci_dev *dev;
+       int slot_num;
+
+       pci_for_each_dev(dev) {
+               slot_num = PCI_SLOT(dev->devfn);
+               switch (slot_num) {
+               case 3: /* re-programmed to USB */
+                       dev->irq = 9;   /* hard-coded; see irq.c */
+                       break;
+               case 4: /* re-programmed to PMU */
+                       dev->irq = 10;  /* hard-coded; see irq.c */
+                       break;
+               case 6: /* on-board pci-pci bridge */
+                       dev->irq = 0xff;
+                       break;
+               case 7: /* on-board ether */
+                       dev->irq = nile4_to_irq(NILE4_INT_INTB);
+                       break;
+               case 8: /* ISA-PCI bridge  */
+                       dev->irq = nile4_to_irq(NILE4_INT_INTC);
+                       break;
+               case 9: /* ext slot #3 */
+                       dev->irq = nile4_to_irq(NILE4_INT_INTD);
+                       break;
+               case 10:        /* ext slot #4 */
+                       dev->irq = nile4_to_irq(NILE4_INT_INTA);
+                       break;
+               case 13:        /* Vrc5476 */
+                       dev->irq = 0xff;
+                       break;
+               case 14:        /* HD controller, M5229 */
+                       dev->irq = 14;
+                       break;
+               default:
+                       printk
+                           ("JSUN : in pcibios_fixup_irqs - unkown slot %d\n",
+                            slot_num);
+                       panic
+                           ("JSUN : in pcibios_fixup_irqs - unkown slot.\n");
+               }
+       }
+}
+
+void __init pcibios_init(void)
+{
+       printk("PCI: Emulate bios initialization \n");
+       /* [jsun] we need to set BAR0 so that SDRAM 0 appears at 0x0 in PCI */
+       *(long *) (NILE4_BASE + NILE4_BAR0) = 0x8;
+
+       printk("PCI: Probing PCI hardware\n");
+       ioport_resource.end = 0x1ffffff;        /*  32 MB */
+       iomem_resource.end = 0x1fffffff;        /* 512 MB */
+
+       /* `ram' and `nile4' are requested through the Nile4 pci_dev */
+       request_resource(&iomem_resource, &ddb5476_resources.flash);
+       request_resource(&iomem_resource, &ddb5476_resources.isa_io);
+       request_resource(&iomem_resource, &ddb5476_resources.pci_io);
+       request_resource(&iomem_resource, &ddb5476_resources.isa_mem);
+       request_resource(&iomem_resource, &ddb5476_resources.pci_mem);
+       request_resource(&iomem_resource, &ddb5476_resources.boot);
+
+       pci_scan_bus(0, &nile4_pci_ops, NULL);
+       ddb5476_pci_fixup();
+       pci_assign_unassigned_resources();
+       pcibios_fixup_irqs();
+}
+
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+       /* [jsun] we don't know how to fix sub-buses yet */
+       if (bus->number == 0) {
+               bus->resource[1] = &ddb5476_resources.pci_mem;
+       }
+}
+
+char *pcibios_setup(char *str)
+{
+       return str;
+}
+
+void __init pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+void __init pcibios_fixup_pbus_ranges(struct pci_bus *bus,
+                                     struct pbus_set_ranges_data *ranges)
+{
+       /*
+        * our caller figure out range by going through the dev structures.  
+        * I guess this is the place to fix things up if the bus is using a 
+        * different view of the addressing space.
+        */
+
+#if 0  /*  original DDB5074 code */
+          if (bus->number == 0) {
+          ranges->io_start -= bus->resource[0]->start;
+          ranges->io_end -= bus->resource[0]->start;
+          ranges->mem_start -= bus->resource[1]->start;
+          ranges->mem_end -= bus->resource[1]->start;
+          }
+#endif
+}
+
+int pcibios_enable_resources(struct pci_dev *dev)
+{
+       u16 cmd, old_cmd;
+       int idx;
+       struct resource *r;
+
+       /*
+        *  Don't touch the Nile 4
+        */
+       if (dev->vendor == PCI_VENDOR_ID_NEC &&
+           dev->device == PCI_DEVICE_ID_NEC_VRC5476) return 0;
+
+       pci_read_config_word(dev, PCI_COMMAND, &cmd);
+       old_cmd = cmd;
+       for (idx = 0; idx < 6; idx++) {
+               r = &dev->resource[idx];
+               if (!r->start && r->end) {
+                       printk(KERN_ERR "PCI: Device %s not available because "
+                              "of resource collisions\n", dev->slot_name);
+                       return -EINVAL;
+               }
+               if (r->flags & IORESOURCE_IO)
+                       cmd |= PCI_COMMAND_IO;
+               if (r->flags & IORESOURCE_MEM)
+                       cmd |= PCI_COMMAND_MEMORY;
+       }
+       if (cmd != old_cmd) {
+               printk("PCI: Enabling device %s (%04x -> %04x)\n",
+                      dev->slot_name, old_cmd, cmd);
+               pci_write_config_word(dev, PCI_COMMAND, cmd);
+       }
+       return 0;
+}
+
+int pcibios_enable_device(struct pci_dev *dev)
+{
+       return pcibios_enable_resources(dev);
+}
+
+void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+                            struct resource *res, int resource)
+{
+       u32 new, check;
+       int reg;
+
+       new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
+       if (resource < 6) {
+               reg = PCI_BASE_ADDRESS_0 + 4 * resource;
+       } else if (resource == PCI_ROM_RESOURCE) {
+               res->flags |= PCI_ROM_ADDRESS_ENABLE;
+               reg = dev->rom_base_reg;
+       } else {
+               /*
+                * Somebody might have asked allocation of a non-standard
+                * resource
+                */
+               return;
+       }
+
+       pci_write_config_dword(dev, reg, new);
+       pci_read_config_dword(dev, reg, &check);
+       if ((new ^ check) &
+           ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
+            PCI_BASE_ADDRESS_MEM_MASK)) {
+               printk(KERN_ERR "PCI: Error while updating region "
+                      "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+                      new, check);
+       }
+}
+
+void pcibios_align_resource(void *data, struct resource *res,
+                           unsigned long size)
+{
+       struct pci_dev *dev = data;
+
+       if (res->flags & IORESOURCE_IO) {
+               unsigned long start = res->start;
+
+               /* We need to avoid collisions with `mirrored' VGA ports
+                  and other strange ISA hardware, so we always want the
+                  addresses kilobyte aligned.  */
+               if (size > 0x100) {
+                       printk(KERN_ERR "PCI: I/O Region %s/%d too large"
+                              " (%ld bytes)\n", dev->slot_name,
+                              dev->resource - res, size);
+               }
+
+               start = (start + 1024 - 1) & ~(1024 - 1);
+               res->start = start;
+       }
+}
+
+struct pci_fixup pcibios_fixups[] = { {0} };
diff --git a/arch/mips/ddb5476/prom.c b/arch/mips/ddb5476/prom.c
new file mode 100644 (file)
index 0000000..4164bd3
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *  arch/mips/ddb5476/prom.c -- NEC DDB Vrc-5476 PROM routines
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ *
+ *     Jun Sun - modified for DDB5476.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+
+char arcs_cmdline[COMMAND_LINE_SIZE];
+
+/* [jsun@junsun.net] PMON passes arguments in C main() style */
+void __init prom_init(int argc, const char **arg)
+{
+       int i;
+
+       /* arg[0] is "g", the rest is boot parameters */
+       arcs_cmdline[0] = '\0';
+       for (i = 1; i < argc; i++) {
+               if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
+                   >= sizeof(arcs_cmdline))
+                       break;
+               strcat(arcs_cmdline, arg[i]);
+               strcat(arcs_cmdline, " ");
+       }
+
+       mips_machgroup = MACH_GROUP_NEC_DDB;
+       mips_machtype = MACH_NEC_DDB5476;
+       /* 64 MB non-upgradable */
+       add_memory_region(0, 64 << 20, BOOT_MEM_RAM);
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
diff --git a/arch/mips/ddb5476/setup.c b/arch/mips/ddb5476/setup.c
new file mode 100644 (file)
index 0000000..ce644a9
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ *  arch/mips/ddb5476/setup.c -- NEC DDB Vrc-5476 setup routines
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kbd_ll.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/console.h>
+#include <linux/sched.h>
+#include <linux/mc146818rtc.h>
+#include <linux/pc_keyb.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#include <asm/addrspace.h>
+#include <asm/bcache.h>
+#include <asm/keyboard.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/gdb-stub.h>
+#include <asm/nile4.h>
+
+
+#ifdef CONFIG_REMOTE_DEBUG
+extern void rs_kgdb_hook(int);
+extern void breakpoint(void);
+#endif
+
+#if defined(CONFIG_SERIAL_CONSOLE)
+extern void console_setup(char *);
+#endif
+
+extern struct ide_ops std_ide_ops;
+extern struct rtc_ops ddb_rtc_ops;
+extern struct kbd_ops std_kbd_ops;
+
+static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
+
+static void ddb_machine_restart(char *command)
+{
+       u32 t;
+
+       /* PCI cold reset */
+       t = nile4_in32(NILE4_PCICTRL + 4);
+       t |= 0x40000000;
+       nile4_out32(NILE4_PCICTRL + 4, t);
+       /* CPU cold reset */
+       t = nile4_in32(NILE4_CPUSTAT);
+       t |= 1;
+       nile4_out32(NILE4_CPUSTAT, t);
+       /* Call the PROM */
+       back_to_prom();
+}
+
+static void ddb_machine_halt(void)
+{
+       printk("DDB Vrc-5476 halted.\n");
+       while (1);
+}
+
+static void ddb_machine_power_off(void)
+{
+       printk("DDB Vrc-5476 halted. Please turn off the power.\n");
+       while (1);
+}
+
+extern void ddb_irq_setup(void);
+
+void (*board_time_init) (struct irqaction * irq);
+
+
+static void __init ddb_time_init(struct irqaction *irq)
+{
+       /* set the clock to 1 Hz */
+       nile4_out32(NILE4_T2CTRL, 1000000);
+       /* enable the General-Purpose Timer */
+       nile4_out32(NILE4_T2CTRL + 4, 0x00000001);
+       /* reset timer */
+       nile4_out32(NILE4_T2CNTR, 0);
+       /* enable interrupt */
+       nile4_enable_irq(NILE4_INT_GPT);
+       i8259_setup_irq(nile4_to_irq(NILE4_INT_GPT), irq);
+}
+
+static struct {
+       struct resource dma1;
+       struct resource pic1;
+       struct resource timer;
+       struct resource rtc;
+       struct resource dma_page_reg;
+       struct resource pic2;
+       struct resource dma2;
+} ddb5476_ioport = {
+       {
+       "dma1", 0x00, 0x1f, IORESOURCE_BUSY}, {
+       "pic1", 0x20, 0x3f, IORESOURCE_BUSY}, {
+       "timer", 0x40, 0x5f, IORESOURCE_BUSY}, {
+       "rtc", 0x70, 0x7f, IORESOURCE_BUSY}, {
+       "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY}, {
+       "pic2", 0xa0, 0xbf, IORESOURCE_BUSY}, {
+       "dma2", 0xc0, 0xdf, IORESOURCE_BUSY}
+};
+
+static struct {
+       struct resource nile4;
+} ddb5476_iomem = {
+       { "Nile 4", NILE4_BASE, NILE4_BASE + NILE4_SIZE - 1, IORESOURCE_BUSY}
+};
+
+void __init ddb_setup(void)
+{
+       extern int panic_timeout;
+
+       irq_setup = ddb_irq_setup;
+       mips_io_port_base = NILE4_PCI_IO_BASE;
+       isa_slot_offset = NILE4_PCI_MEM_BASE;
+       board_time_init = ddb_time_init;
+
+       _machine_restart = ddb_machine_restart;
+       _machine_halt = ddb_machine_halt;
+       _machine_power_off = ddb_machine_power_off;
+
+       /* request io port/mem resources  */
+       if (request_resource(&ioport_resource, &ddb5476_ioport.dma1) ||
+           request_resource(&ioport_resource, &ddb5476_ioport.pic1) ||
+           request_resource(&ioport_resource, &ddb5476_ioport.timer) ||
+           request_resource(&ioport_resource, &ddb5476_ioport.rtc) ||
+           request_resource(&ioport_resource,
+                            &ddb5476_ioport.dma_page_reg)
+           || request_resource(&ioport_resource, &ddb5476_ioport.pic2)
+           || request_resource(&ioport_resource, &ddb5476_ioport.dma2)
+           || request_resource(&iomem_resource, &ddb5476_iomem.nile4)) {
+               printk
+                   ("ddb_setup - requesting oo port resources failed.\n");
+               for (;;);
+       }
+#ifdef CONFIG_BLK_DEV_IDE
+       ide_ops = &std_ide_ops;
+#endif
+       rtc_ops = &ddb_rtc_ops;
+
+#ifdef CONFIG_PC_KEYB
+       kbd_ops = &std_kbd_ops;
+#endif
+
+       /* Reboot on panic */
+       panic_timeout = 180;
+
+       /* [jsun] we need to set BAR0 so that SDRAM 0 appears at 0x0 in PCI */
+       /* *(long*)0xbfa00218 = 0x8; */
+
+#ifdef CONFIG_FB
+       conswitchp = &dummy_con;
+#endif
+
+
+       /* board initialization stuff - non-fundamental, but need to be set
+        * before kernel runs */
+
+       /* setup I/O space */
+       nile4_set_pdar(NILE4_PCIW0,
+                      PHYSADDR(NILE4_PCI_IO_BASE), 0x02000000, 32, 0, 0);
+       nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IO, 0);
+
+       /* map config space to 0xa8000000, 128MB */
+       nile4_set_pdar(NILE4_PCIW1,
+                      PHYSADDR(NILE4_PCI_CFG_BASE), 0x08000000, 32, 0, 0);
+       nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_CFG, 0x0);
+
+       /* ----- M1543 PCI setup ------ */
+
+       /* we know M1543 PCI-ISA controller is at addr:18 */
+       /* xxxx1010 makes USB at addr:13 and PMU at addr:14 */
+       *(volatile unsigned char *) 0xa8040072 &= 0xf0;
+       *(volatile unsigned char *) 0xa8040072 |= 0xa;
+
+       /* setup USB interrupt to IRQ 9, (bit 0:3 - 0001)
+        * no IOCHRDY signal, (bit 7 - 1)
+        * M1543C & M7101 VID and Subsys Device ID are read-only (bit 6 - 1)
+        * Bypass USB Master INTAJ level to edge conversion (bit 4 - 0)
+        */
+       *(unsigned char *) 0xa8040074 = 0xc1;
+
+       /* setup PMU(SCI to IRQ 10 (bit 0:3 - 0011)
+        * SCI routing to IRQ 13 disabled (bit 7 - 1)
+        * SCI interrupt level to edge conversion bypassed (bit 4 - 0)
+        */
+       *(unsigned char *) 0xa8040076 = 0x83;
+
+       /* setup IDE controller
+        * enable IDE controller (bit 6 - 1)
+        * IDE IDSEL to be addr:24 (bit 4:5 - 11)
+        * no IDE ATA Secondary Bus Signal Pad Control (bit 3 - 0)
+        * no IDE ATA Primary Bus Signal Pad Control (bit 2 - 0)
+        * primary IRQ is 14, secondary is 15 (bit 1:0 - 01
+        */
+       // *(unsigned char*)0xa8040058 = 0x71;
+       // *(unsigned char*)0xa8040058 = 0x79;
+       // *(unsigned char*)0xa8040058 = 0x74;              // use SIRQ, primary tri-state
+       *(unsigned char *) 0xa8040058 = 0x75;   // primary tri-state
+
+#if 0
+       /* this is not necessary if M5229 does not use SIRQ */
+       *(unsigned char *) 0xa8040044 = 0x0d;   // primary to IRQ 14
+       *(unsigned char *) 0xa8040075 = 0x0d;   // secondary to IRQ 14
+#endif
+
+       /* enable IDE in the M5229 config register 0x50 (bit 0 - 1) */
+       /* M5229 IDSEL is addr:24; see above setting */
+       *(unsigned char *) 0xa9000050 |= 0x1;
+
+       /* enable bus master (bit 2)  and IO decoding  (bit 0) */
+       *(unsigned char *) 0xa9000004 |= 0x5;
+
+       /* enable native, copied from arch/ppc/k2boot/head.S */
+       /* TODO - need volatile, need to be portable */
+       *(unsigned char *) 0xa9000009 = 0xff;
+
+       /* ----- end of M1543 PCI setup ------ */
+
+       /* ----- reset on-board ether chip  ------ */
+       *((volatile u32 *) 0xa8020004) |= 1;    /* decode I/O */
+       *((volatile u32 *) 0xa8020010) = 0;     /* set BAR address */
+
+       /* send reset command */
+       *((volatile u32 *) 0xa6000000) = 1;     /* do a soft reset */
+
+       /* disable ether chip */
+       *((volatile u32 *) 0xa8020004) = 0;     /* disable any decoding */
+
+       /* put it into sleep */
+       *((volatile u32 *) 0xa8020040) = 0x80000000;
+
+       /* ----- end of reset on-board ether chip  ------ */
+
+       /* ----- set pci window 1 to pci memory space -------- */
+       nile4_set_pdar(NILE4_PCIW1,
+                      PHYSADDR(NILE4_PCI_MEM_BASE), 0x08000000, 32, 0, 0);
+       // nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0);
+       nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0x08000000);
+
+}
+
+#define USE_NILE4_SERIAL       0
+
+#if USE_NILE4_SERIAL
+#define ns16550_in(reg)                nile4_in8((reg)*8)
+#define ns16550_out(reg, val)  nile4_out8((reg)*8, (val))
+#else
+#define NS16550_BASE           (NILE4_PCI_IO_BASE+0x03f8)
+static inline u8 ns16550_in(u32 reg)
+{
+       return *(volatile u8 *) (NS16550_BASE + reg);
+}
+
+static inline void ns16550_out(u32 reg, u8 val)
+{
+       *(volatile u8 *) (NS16550_BASE + reg) = val;
+}
+#endif
+
+#define NS16550_RBR            0
+#define NS16550_THR            0
+#define NS16550_DLL            0
+#define NS16550_IER            1
+#define NS16550_DLM            1
+#define NS16550_FCR            2
+#define NS16550_IIR            2
+#define NS16550_LCR            3
+#define NS16550_MCR            4
+#define NS16550_LSR            5
+#define NS16550_MSR            6
+#define NS16550_SCR            7
+
+#define NS16550_LSR_DR         0x01    /* Data ready */
+#define NS16550_LSR_OE         0x02    /* Overrun */
+#define NS16550_LSR_PE         0x04    /* Parity error */
+#define NS16550_LSR_FE         0x08    /* Framing error */
+#define NS16550_LSR_BI         0x10    /* Break */
+#define NS16550_LSR_THRE       0x20    /* Xmit holding register empty */
+#define NS16550_LSR_TEMT       0x40    /* Xmitter empty */
+#define NS16550_LSR_ERR                0x80    /* Error */
+
+
+void _serinit(void)
+{
+#if USE_NILE4_SERIAL
+       ns16550_out(NS16550_LCR, 0x80);
+       ns16550_out(NS16550_DLM, 0x00);
+       ns16550_out(NS16550_DLL, 0x36); /* 9600 baud */
+       ns16550_out(NS16550_LCR, 0x00);
+       ns16550_out(NS16550_LCR, 0x03);
+       ns16550_out(NS16550_FCR, 0x47);
+#else
+       /* done by PMON */
+#endif
+}
+
+void _putc(char c)
+{
+       while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
+       ns16550_out(NS16550_THR, c);
+       if (c == '\n') {
+               while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
+               ns16550_out(NS16550_THR, '\r');
+       }
+}
+
+void _puts(const char *s)
+{
+       char c;
+
+       while ((c = *s++))
+               _putc(c);
+}
+
+char _getc(void)
+{
+       while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR));
+
+       return ns16550_in(NS16550_RBR);
+}
+
+int _testc(void)
+{
+       return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0;
+}
+
+
+/*
+ *  Hexadecimal 7-segment LED
+ */
+void ddb5476_led_hex(int hex)
+{
+       outb(hex, 0x80);
+}
+
+
+/*
+ *  LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543
+ */
+struct pci_dev *pci_pmu = NULL;
+
+void ddb5476_led_d2(int on)
+{
+       u8 t;
+
+       if (pci_pmu) {
+               pci_read_config_byte(pci_pmu, 0x7e, &t);
+               if (on)
+                       t &= 0x7f;
+               else
+                       t |= 0x80;
+               pci_write_config_byte(pci_pmu, 0x7e, t);
+       }
+}
+
+void ddb5476_led_d3(int on)
+{
+       u8 t;
+
+       if (pci_pmu) {
+               pci_read_config_byte(pci_pmu, 0x7e, &t);
+               if (on)
+                       t &= 0xbf;
+               else
+                       t |= 0x40;
+               pci_write_config_byte(pci_pmu, 0x7e, t);
+       }
+}
diff --git a/arch/mips/ddb5476/time.c b/arch/mips/ddb5476/time.c
new file mode 100644 (file)
index 0000000..452aaec
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *  arch/mips/ddb5074/time.c -- Timer routines
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <linux/init.h>
+
+#include <asm/mc146818rtc.h>
+
+static unsigned char ddb_rtc_read_data(unsigned long addr)
+{
+       outb_p(addr, RTC_PORT(0));
+       return inb_p(RTC_PORT(1));
+}
+
+static void ddb_rtc_write_data(unsigned char data, unsigned long addr)
+{
+       outb_p(addr, RTC_PORT(0));
+       outb_p(data, RTC_PORT(1));
+}
+
+static int ddb_rtc_bcd_mode(void)
+{
+       return 1;
+}
+
+struct rtc_ops ddb_rtc_ops = {
+       ddb_rtc_read_data,
+       ddb_rtc_write_data,
+       ddb_rtc_bcd_mode
+};
index d3f6594..1d4f099 100644 (file)
@@ -7,30 +7,20 @@
 #
 
 .S.s:
-       $(CPP) $(CFLAGS) $< -o $*.s
+       $(CPP) $(AFLAGS) $< -o $@
 .S.o:
-       $(CC) $(CFLAGS) -c $< -o $*.o
+       $(CC) $(AFLAGS) -c $< -o $@
 
-all: dec.o
 O_TARGET := dec.o
-O_OBJS  := int-handler.o setup.o irq.o time.o reset.o rtc-dec.o
 
-ifdef CONFIG_PROM_CONSOLE
-O_OBJS   += promcon.o
-endif
+all: dec.o
 
-ifdef CONFIG_SERIAL
-O_OBJS   += serial.o
-endif
+export-objs := wbflush.o
+obj-y   := int-handler.o setup.o irq.o time.o reset.o rtc-dec.o wbflush.o
 
-ifeq ($(CONFIG_MODULES),y)
- OX_OBJS  = wbflush.o
-else
- O_OBJS   += wbflush.o
-endif
+obj-$(CONFIG_PROM_CONSOLE)     += promcon.o
+obj-$(CONFIG_SERIAL)           += serial.o
 
 int-handler.o: int-handler.S
 
-clean:
-
 include $(TOPDIR)/Rules.make
index 1257b56..3f69a6c 100644 (file)
@@ -18,7 +18,8 @@ netboot: all
 all: dec_boot.o
 
 O_TARGET := dec_boot.o
-O_OBJS  := decstation.o
+
+obj-y   := decstation.o
 
 clean:
        rm -f nbImage
index dc89879..31b9457 100644 (file)
@@ -16,16 +16,17 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_COBALT_MICRO_SERVER is not set
 # CONFIG_DECSTATION is not set
 # CONFIG_DDB5074 is not set
-# CONFIG_ORION is not set
 # CONFIG_MIPS_MAGNUM_4000 is not set
 # CONFIG_OLIVETTI_M700 is not set
 CONFIG_SGI_IP22=y
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_MCA is not set
 # CONFIG_SBUS is not set
 CONFIG_ARC32=y
 CONFIG_PC_KEYB=y
 CONFIG_SGI=y
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_PCI is not set
 
 #
@@ -84,17 +85,23 @@ CONFIG_SYSCTL=y
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -111,10 +118,8 @@ CONFIG_INET=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -131,6 +136,7 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -152,6 +158,7 @@ CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
 CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_SR_EXTRA_DEVS=2
@@ -192,14 +199,14 @@ CONFIG_SCSI_SGIWD93=y
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -229,6 +236,8 @@ CONFIG_FONT_8x16=y
 # CONFIG_QUOTA is not set
 CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -283,8 +292,6 @@ CONFIG_LOCKD=y
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -299,11 +306,13 @@ CONFIG_PARTITION_ADVANCED=y
 # CONFIG_MAC_PARTITION is not set
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 CONFIG_SGI_PARTITION=y
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -336,6 +345,11 @@ CONFIG_SGI_DS1286=y
 # CONFIG_USB is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
 # Kernel hacking
 #
 CONFIG_CROSSCOMPILE=y
index bfef9e3..e91a9d2 100644 (file)
@@ -17,18 +17,18 @@ CONFIG_COBALT_MICRO_SERVER=y
 CONFIG_COBALT_28=y
 # CONFIG_DECSTATION is not set
 # CONFIG_DDB5074 is not set
-# CONFIG_ORION is not set
 # CONFIG_MIPS_MAGNUM_4000 is not set
 # CONFIG_OLIVETTI_M700 is not set
 # CONFIG_SGI_IP22 is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_MCA is not set
 # CONFIG_SBUS is not set
-# CONFIG_ISA is not set
 CONFIG_COBALT_27=y
 CONFIG_COBALT_LCD=y
 CONFIG_COBALT_SERIAL=y
 CONFIG_PCI=y
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 
 #
 # Loadable module support
@@ -85,22 +85,26 @@ CONFIG_SYSCTL=y
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 CONFIG_BLK_DEV_LOOP=m
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_BOOT is not set
-# CONFIG_AUTODETECT_RAID is not set
 CONFIG_BLK_DEV_RAM=m
 CONFIG_BLK_DEV_RAM_SIZE=4096
 # CONFIG_BLK_DEV_INITRD is not set
 
 #
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
 # Networking options
 #
 # CONFIG_PACKET is not set
@@ -112,13 +116,11 @@ CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
 # CONFIG_IP_PNP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 CONFIG_IP_MROUTE=y
 # CONFIG_IP_PIMSM_V1 is not set
 # CONFIG_IP_PIMSM_V2 is not set
-CONFIG_IP_ALIAS=y
 # CONFIG_INET_ECN is not set
 CONFIG_SYN_COOKIES=y
 # CONFIG_IPV6 is not set
@@ -130,13 +132,13 @@ CONFIG_SYN_COOKIES=y
 #
 CONFIG_IPX=m
 # CONFIG_IPX_INTERN is not set
-# CONFIG_SPX is not set
 CONFIG_ATALK=m
 # CONFIG_DECNET is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -171,6 +173,7 @@ CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=m
+# CONFIG_CHR_DEV_OSST is not set
 CONFIG_BLK_DEV_SR=m
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_SR_EXTRA_DEVS=2
@@ -194,15 +197,14 @@ CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 CONFIG_SCSI_AIC7XXX=y
-# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set
 CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
-# CONFIG_AIC7XXX_PROC_STATS is not set
 CONFIG_AIC7XXX_RESET_DELAY=5
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
 # CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
 # CONFIG_SCSI_EATA is not set
@@ -214,8 +216,6 @@ CONFIG_AIC7XXX_RESET_DELAY=5
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 CONFIG_SCSI_NCR53C8XX=y
 # CONFIG_SCSI_SYM53C8XX is not set
@@ -233,6 +233,8 @@ CONFIG_SCSI_NCR53C8XX_IOMAPPED=y
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
@@ -265,6 +267,7 @@ CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_NET_SB1000 is not set
 
 #
@@ -277,6 +280,7 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_AT1700 is not set
 # CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
 # CONFIG_NET_ISA is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_NET_POCKET is not set
@@ -284,8 +288,9 @@ CONFIG_NET_ETHERNET=y
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_YELLOWFIN is not set
 # CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -326,6 +331,7 @@ CONFIG_ISDN=m
 CONFIG_ISDN_PPP=y
 CONFIG_ISDN_PPP_VJ=y
 CONFIG_ISDN_MPP=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
 CONFIG_ISDN_AUDIO=y
 # CONFIG_ISDN_TTY_FAX is not set
 
@@ -353,6 +359,7 @@ CONFIG_DE_AOC=y
 # CONFIG_HISAX_NO_LLC is not set
 # CONFIG_HISAX_NO_KEYPAD is not set
 CONFIG_HISAX_1TR6=y
+# CONFIG_HISAX_NI1 is not set
 
 #
 #   HiSax supported cards
@@ -374,6 +381,7 @@ CONFIG_HISAX_ELSA=y
 # CONFIG_HISAX_SPORTSTER is not set
 # CONFIG_HISAX_MIC is not set
 # CONFIG_HISAX_NETJET is not set
+# CONFIG_HISAX_NETJET_U is not set
 # CONFIG_HISAX_NICCY is not set
 # CONFIG_HISAX_ISURF is not set
 # CONFIG_HISAX_HSTSAPHIR is not set
@@ -383,6 +391,7 @@ CONFIG_HISAX_ELSA=y
 # CONFIG_HISAX_HFC_PCI is not set
 # CONFIG_HISAX_W6692 is not set
 # CONFIG_HISAX_HFC_SX is not set
+# CONFIG_HISAX_SEDLBAUER_CS is not set
 
 #
 # Active ISDN cards
@@ -393,8 +402,8 @@ CONFIG_HISAX_ELSA=y
 # CONFIG_ISDN_DRV_ACT2000 is not set
 # CONFIG_ISDN_DRV_EICON is not set
 # CONFIG_ISDN_CAPI is not set
-# CONFIG_ISDN_CAPI_MIDDLEWARE is not set
 # CONFIG_HYSDN is not set
+# CONFIG_HYSDN_CAPI is not set
 
 #
 # Old CD-ROM drivers (not SCSI, not IDE)
@@ -425,6 +434,10 @@ CONFIG_HISAX_ELSA=y
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -434,11 +447,6 @@ CONFIG_HISAX_ELSA=y
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 CONFIG_RTC=y
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -447,8 +455,13 @@ CONFIG_RTC=y
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -456,6 +469,8 @@ CONFIG_RTC=y
 CONFIG_QUOTA=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -503,6 +518,7 @@ CONFIG_NFS_FS=y
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_NCPFS_PACKET_SIGNING is not set
 # CONFIG_NCPFS_IOCTL_LOCKING is not set
@@ -510,8 +526,6 @@ CONFIG_SMB_FS=m
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -520,6 +534,7 @@ CONFIG_SMB_FS=m
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
+CONFIG_SMB_NLS=y
 CONFIG_NLS=y
 
 #
@@ -571,6 +586,11 @@ CONFIG_NLS_UTF8=m
 # CONFIG_USB is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
 # Kernel hacking
 #
 # CONFIG_CROSSCOMPILE is not set
diff --git a/arch/mips/defconfig-ddb5476 b/arch/mips/defconfig-ddb5476
new file mode 100644 (file)
index 0000000..f5aea46
--- /dev/null
@@ -0,0 +1,541 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_SMP is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Machine selection
+#
+# CONFIG_ACER_PICA_61 is not set
+# CONFIG_ALGOR_P4032 is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_DECSTATION is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_NINO is not set
+# CONFIG_MIPS_MAGNUM_4000 is not set
+# CONFIG_MOMENCO_OCELOT is not set
+CONFIG_DDB5476=y
+# CONFIG_OLIVETTI_M700 is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MCA is not set
+# CONFIG_SBUS is not set
+CONFIG_I8259=y
+CONFIG_ISA=y
+CONFIG_PCI=y
+CONFIG_PC_KEYB=y
+CONFIG_ROTTEN_IRQ=y
+CONFIG_EISA=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_R3912 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_R5000 is not set
+CONFIG_CPU_R5432=y
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_WB is not set
+
+#
+# General setup
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_FPU_EMULATOR=y
+CONFIG_KCORE_ELF=y
+CONFIG_ELF_KERNEL=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_NET=y
+# CONFIG_PCI_NAMES is not set
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+
+#
+#  
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+# CONFIG_PHONE_IXJ is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_IDEDMA_PCI is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_PCI_WIP is not set
+# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_WDC_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD7409 is not set
+# CONFIG_AMD7409_OVERRIDE is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_HPT34X_AUTODMA is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_PDC202XX is not set
+# CONFIG_PDC202XX_BURST is not set
+# CONFIG_BLK_DEV_OSB4 is not set
+# CONFIG_BLK_DEV_SIS5513 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+CONFIG_TULIP=y
+# CONFIG_DE4X5 is not set
+# CONFIG_DGRS is not set
+# CONFIG_DM9102 is not set
+CONFIG_EEPRO100=y
+# CONFIG_EEPRO100_PM is not set
+# CONFIG_LNE390 is not set
+# CONFIG_NATSEMI is not set
+CONFIG_NE2K_PCI=y
+# CONFIG_NE3210 is not set
+# CONFIG_ES3210 is not set
+# CONFIG_8139TOO is not set
+# CONFIG_RTL8129 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_LAN_SAA9730 is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+CONFIG_MOUSE=y
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_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_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Console drivers
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_CLGEN is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_ATY128 is not set
+CONFIG_FB_3DFX=y
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB32=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+# CONFIG_FBCON_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+# CONFIG_REMOTE_DEBUG is not set
+# CONFIG_LL_DEBUG is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_MIPS_UNCACHED is not set
index d7bba78..bff4fff 100644 (file)
@@ -16,13 +16,14 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_COBALT_MICRO_SERVER is not set
 CONFIG_DECSTATION=y
 # CONFIG_DDB5074 is not set
-# CONFIG_ORION is not set
 # CONFIG_MIPS_MAGNUM_4000 is not set
 # CONFIG_OLIVETTI_M700 is not set
 # CONFIG_SGI_IP22 is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_MCA is not set
 # CONFIG_SBUS is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_PCI is not set
 
 #
@@ -80,17 +81,23 @@ CONFIG_TC=y
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -107,10 +114,8 @@ CONFIG_INET=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -127,6 +132,7 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -148,6 +154,7 @@ CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 # CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 
@@ -170,6 +177,7 @@ CONFIG_SCSI_DECNCR=y
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -186,14 +194,14 @@ CONFIG_SCSI_DECNCR=y
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -224,6 +232,8 @@ CONFIG_SERIAL_CONSOLE=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -278,8 +288,6 @@ CONFIG_EXT2_FS=y
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -294,11 +302,13 @@ CONFIG_OSF_PARTITION=y
 # CONFIG_MAC_PARTITION is not set
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_SGI_PARTITION is not set
 CONFIG_ULTRIX_PARTITION=y
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -307,6 +317,11 @@ CONFIG_ULTRIX_PARTITION=y
 # CONFIG_USB is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
 # Kernel hacking
 #
 CONFIG_CROSSCOMPILE=y
index 6143660..31b9457 100644 (file)
@@ -16,16 +16,17 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_COBALT_MICRO_SERVER is not set
 # CONFIG_DECSTATION is not set
 # CONFIG_DDB5074 is not set
-# CONFIG_ORION is not set
 # CONFIG_MIPS_MAGNUM_4000 is not set
 # CONFIG_OLIVETTI_M700 is not set
 CONFIG_SGI_IP22=y
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_MCA is not set
 # CONFIG_SBUS is not set
 CONFIG_ARC32=y
 CONFIG_PC_KEYB=y
 CONFIG_SGI=y
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_PCI is not set
 
 #
@@ -84,17 +85,23 @@ CONFIG_SYSCTL=y
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -111,10 +118,8 @@ CONFIG_INET=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -131,6 +136,7 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -152,6 +158,7 @@ CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
 CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_SR_EXTRA_DEVS=2
@@ -175,6 +182,7 @@ CONFIG_SCSI_SGIWD93=y
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -191,14 +199,14 @@ CONFIG_SCSI_SGIWD93=y
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -228,6 +236,8 @@ CONFIG_FONT_8x16=y
 # CONFIG_QUOTA is not set
 CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -282,8 +292,6 @@ CONFIG_LOCKD=y
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -298,11 +306,13 @@ CONFIG_PARTITION_ADVANCED=y
 # CONFIG_MAC_PARTITION is not set
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 CONFIG_SGI_PARTITION=y
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -335,6 +345,11 @@ CONFIG_SGI_DS1286=y
 # CONFIG_USB is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
 # Kernel hacking
 #
 CONFIG_CROSSCOMPILE=y
diff --git a/arch/mips/defconfig-it8172 b/arch/mips/defconfig-it8172
new file mode 100644 (file)
index 0000000..e8b3f37
--- /dev/null
@@ -0,0 +1,569 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_SMP is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Machine selection
+#
+# CONFIG_ACER_PICA_61 is not set
+# CONFIG_ALGOR_P4032 is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_DECSTATION is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_NINO is not set
+# CONFIG_MIPS_MAGNUM_4000 is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_OLIVETTI_M700 is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SNI_RM200_PCI is not set
+CONFIG_MIPS_ITE8172=y
+# CONFIG_IT8172_REVC is not set
+CONFIG_QTRONIX_KEYBOARD=y
+CONFIG_IT8172_CIR=y
+# CONFIG_IT8172_SCR0 is not set
+# CONFIG_IT8172_SCR1 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MCA is not set
+# CONFIG_SBUS is not set
+CONFIG_PCI=y
+CONFIG_IT8712=y
+CONFIG_PC_KEYB=y
+# CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_I8259 is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_R3912 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_RM7000 is not set
+CONFIG_CPU_NEVADA=y
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_WB is not set
+
+#
+# General setup
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_FPU_EMULATOR=y
+CONFIG_KCORE_ELF=y
+CONFIG_ELF_KERNEL=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_NET=y
+CONFIG_PCI_NAMES=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_SYSCTL=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+
+#
+# RAM/ROM Device Drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_MTDRAM is not set
+
+#
+# Linearly Mapped Flash Device Drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_JEDEC is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=8000000
+CONFIG_MTD_PHYSMAP_LEN=2000000
+CONFIG_MTD_PHYSMAP_BUSWIDTH=4
+
+#
+# Drivers for chip mappings
+#
+# CONFIG_MTD_MIXMEM is not set
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_OCTAGON is not set
+# CONFIG_MTD_PNC2000 is not set
+# CONFIG_MTD_RPXLITE is not set
+# CONFIG_MTD_VMAX is not set
+
+#
+# User modules and translation layers for MTD devices
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+# CONFIG_UNIX is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+
+#
+#  
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+# CONFIG_PHONE_IXJ is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_PCI_WIP is not set
+# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_WDC_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD7409 is not set
+# CONFIG_AMD7409_OVERRIDE is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_HPT34X_AUTODMA is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+CONFIG_BLK_DEV_IT8172=y
+CONFIG_IT8172_TUNING=y
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_PDC202XX is not set
+# CONFIG_PDC202XX_BURST is not set
+# CONFIG_BLK_DEV_OSB4 is not set
+# CONFIG_BLK_DEV_SIS5513 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_IDE_CHIPSETS=y
+
+#
+# Note: most of these also require special kernel boot parameters
+#
+# CONFIG_BLK_DEV_4DRIVES is not set
+# CONFIG_BLK_DEV_ALI14XX is not set
+# CONFIG_BLK_DEV_DTC2278 is not set
+# CONFIG_BLK_DEV_HT6560B is not set
+# CONFIG_BLK_DEV_PDC4030 is not set
+# CONFIG_BLK_DEV_QD6580 is not set
+# CONFIG_BLK_DEV_UMC8672 is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_DMA_NONPCI is not set
+CONFIG_BLK_DEV_IDE_MODES=y
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+CONFIG_TULIP=y
+# CONFIG_DE4X5 is not set
+# CONFIG_DGRS is not set
+# CONFIG_DM9102 is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_EEPRO100_PM is not set
+# CONFIG_LNE390 is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_NE3210 is not set
+# CONFIG_ES3210 is not set
+CONFIG_8139TOO=y
+# CONFIG_RTL8129 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_LAN_SAA9730 is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_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_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+# CONFIG_MIPS_FPE_MODULE is not set
+# CONFIG_REMOTE_DEBUG is not set
+# CONFIG_LL_DEBUG is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_MIPS_UNCACHED is not set
index e45b978..ae5b1c1 100644 (file)
@@ -16,13 +16,14 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_COBALT_MICRO_SERVER is not set
 # CONFIG_DECSTATION is not set
 # CONFIG_DDB5074 is not set
-CONFIG_ORION=y
 # CONFIG_MIPS_MAGNUM_4000 is not set
 # CONFIG_OLIVETTI_M700 is not set
 # CONFIG_SGI_IP22 is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_MCA is not set
 # CONFIG_SBUS is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_PCI is not set
 
 #
@@ -79,18 +80,24 @@ CONFIG_NET=y
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -113,6 +120,7 @@ CONFIG_BLK_DEV_INITRD=y
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET_AUNUDP is not set
 # CONFIG_ECONET_NATIVE is not set
 # CONFIG_WAN_ROUTER is not set
@@ -180,6 +188,10 @@ CONFIG_BLK_DEV_INITRD=y
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -189,11 +201,6 @@ CONFIG_BLK_DEV_INITRD=y
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -202,8 +209,13 @@ CONFIG_BLK_DEV_INITRD=y
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -211,6 +223,8 @@ CONFIG_BLK_DEV_INITRD=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -265,6 +279,7 @@ CONFIG_EXT2_FS=y
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -278,6 +293,11 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_USB is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
 # Kernel hacking
 #
 CONFIG_CROSSCOMPILE=y
index f67154e..cf9e202 100644 (file)
@@ -16,16 +16,17 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_COBALT_MICRO_SERVER is not set
 # CONFIG_DECSTATION is not set
 # CONFIG_DDB5074 is not set
-# CONFIG_ORION is not set
 # CONFIG_MIPS_MAGNUM_4000 is not set
 # CONFIG_OLIVETTI_M700 is not set
 # CONFIG_SGI_IP22 is not set
 CONFIG_SNI_RM200_PCI=y
+# CONFIG_MCA is not set
 # CONFIG_SBUS is not set
 CONFIG_ARC32=y
 CONFIG_PCI=y
 CONFIG_ISA=y
 CONFIG_PC_KEYB=y
+CONFIG_EISA=y
 
 #
 # Loadable module support
@@ -88,17 +89,23 @@ CONFIG_BLK_DEV_FD=y
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -113,10 +120,8 @@ CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
 # CONFIG_IP_PNP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -133,6 +138,7 @@ CONFIG_INET=y
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -211,6 +217,10 @@ CONFIG_VT_CONSOLE=y
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -220,11 +230,6 @@ CONFIG_VT_CONSOLE=y
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 CONFIG_RTC=y
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -233,8 +238,13 @@ CONFIG_RTC=y
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -242,6 +252,8 @@ CONFIG_RTC=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -296,8 +308,6 @@ CONFIG_EXT2_FS=y
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -312,11 +322,13 @@ CONFIG_PARTITION_ADVANCED=y
 # CONFIG_MAC_PARTITION is not set
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 CONFIG_SGI_PARTITION=y
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -341,6 +353,11 @@ CONFIG_VGA_CONSOLE=y
 # CONFIG_USB is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
 # Kernel hacking
 #
 CONFIG_CROSSCOMPILE=y
diff --git a/arch/mips/ite-boards/generic/Makefile b/arch/mips/ite-boards/generic/Makefile
new file mode 100644 (file)
index 0000000..71d61ea
--- /dev/null
@@ -0,0 +1,36 @@
+#
+#  Copyright 2000 MontaVista Software Inc.
+#  Author: MontaVista Software, Inc.
+#      ppopov@mvista.com or support@mvista.com
+#
+# Makefile for the ITE 8172 (qed-4n-s01b) board, generic files.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.s:
+       $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+       $(CC) $(CFLAGS) -c $< -o $*.o
+
+all: it8172.o
+
+O_TARGET := it8172.o
+
+obj-y := it8172_rtc.o it8172_setup.o irq.o int-handler.o pmon_prom.o time.o lpc.o puts.o reset.o
+
+ifdef CONFIG_PCI
+obj-y += it8172_pci.o
+endif
+
+ifdef CONFIG_IT8172_CIR
+obj-y += it8172_cir.o 
+endif
+
+ifdef CONFIG_REMOTE_DEBUG
+ obj-y += dbg_io.o             
+endif
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/mips/ite-boards/generic/dbg_io.c b/arch/mips/ite-boards/generic/dbg_io.c
new file mode 100644 (file)
index 0000000..76b0c1f
--- /dev/null
@@ -0,0 +1,127 @@
+
+#include <linux/config.h>
+
+#ifdef CONFIG_REMOTE_DEBUG
+
+/* --- CONFIG --- */
+
+/* we need uint32 uint8 */
+/* #include "types.h" */
+typedef         unsigned char uint8;
+typedef         unsigned int  uint32;
+
+/* --- END OF CONFIG --- */
+
+#define         UART16550_BAUD_2400             2400
+#define         UART16550_BAUD_4800             4800
+#define         UART16550_BAUD_9600             9600
+#define         UART16550_BAUD_19200            19200
+#define         UART16550_BAUD_38400            38400
+#define         UART16550_BAUD_57600            57600
+#define         UART16550_BAUD_115200           115200
+
+#define         UART16550_PARITY_NONE           0
+#define         UART16550_PARITY_ODD            0x08
+#define         UART16550_PARITY_EVEN           0x18
+#define         UART16550_PARITY_MARK           0x28
+#define         UART16550_PARITY_SPACE          0x38
+
+#define         UART16550_DATA_5BIT             0x0
+#define         UART16550_DATA_6BIT             0x1
+#define         UART16550_DATA_7BIT             0x2
+#define         UART16550_DATA_8BIT             0x3
+
+#define         UART16550_STOP_1BIT             0x0
+#define         UART16550_STOP_2BIT             0x4
+
+/* ----------------------------------------------------- */
+
+/* === CONFIG === */
+
+/* [stevel] we use the IT8712 serial port for kgdb */
+#define        DEBUG_BASE  0xB40003F8 /* 8712 serial port 1 base address */
+#define MAX_BAUD    115200
+
+/* === END OF CONFIG === */
+
+/* register offset */
+#define         OFS_RCV_BUFFER          0
+#define         OFS_TRANS_HOLD          0
+#define         OFS_SEND_BUFFER         0
+#define         OFS_INTR_ENABLE         1
+#define         OFS_INTR_ID             2
+#define         OFS_DATA_FORMAT         3
+#define         OFS_LINE_CONTROL        3
+#define         OFS_MODEM_CONTROL       4
+#define         OFS_RS232_OUTPUT        4
+#define         OFS_LINE_STATUS         5
+#define         OFS_MODEM_STATUS        6
+#define         OFS_RS232_INPUT         6
+#define         OFS_SCRATCH_PAD         7
+
+#define         OFS_DIVISOR_LSB         0
+#define         OFS_DIVISOR_MSB         1
+
+
+/* memory-mapped read/write of the port */
+#define UART16550_READ(y)    (*((volatile uint8*)(DEBUG_BASE + y)))
+#define UART16550_WRITE(y,z) ((*((volatile uint8*)(DEBUG_BASE + y))) = z)
+
+void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+{
+    /* disable interrupts */
+    UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+    /* set up buad rate */
+    { 
+        uint32 divisor;
+       
+        /* set DIAB bit */
+        UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+        
+        /* set divisor */
+        divisor = MAX_BAUD / baud;
+        UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+        UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00)>>8);
+
+        /* clear DIAB bit */
+        UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+    }
+
+    /* set data format */
+    UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+static int remoteDebugInitialized = 0;
+
+uint8 getDebugChar(void)
+{
+    if (!remoteDebugInitialized) {
+       remoteDebugInitialized = 1;
+       debugInit(UART16550_BAUD_115200,
+                 UART16550_DATA_8BIT,
+                 UART16550_PARITY_NONE,
+                 UART16550_STOP_1BIT);
+    }
+
+    while((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
+    return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+
+int putDebugChar(uint8 byte)
+{
+    if (!remoteDebugInitialized) {
+       remoteDebugInitialized = 1;
+       debugInit(UART16550_BAUD_115200,
+                 UART16550_DATA_8BIT,
+                 UART16550_PARITY_NONE,
+                 UART16550_STOP_1BIT);
+    }
+
+    while ((UART16550_READ(OFS_LINE_STATUS) &0x20) == 0);
+    UART16550_WRITE(OFS_SEND_BUFFER, byte);
+    return 1;
+}
+
+#endif
diff --git a/arch/mips/ite-boards/generic/int-handler.S b/arch/mips/ite-boards/generic/int-handler.S
new file mode 100644 (file)
index 0000000..2997b7f
--- /dev/null
@@ -0,0 +1,61 @@
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+       .text
+       .set    macro
+       .set    noat
+       .align  5
+
+NESTED(it8172_IRQ, PT_SIZE, sp)
+       SAVE_ALL
+       CLI                             # Important: mark KERNEL mode !
+
+        /* We're working with 'reorder' set at this point. */
+       /*
+        * Get pending interrupts
+        */
+
+       mfc0    t0,CP0_CAUSE            # get pending interrupts
+       mfc0    t1,CP0_STATUS           # get enabled interrupts
+       and     t0,t1                   # isolate allowed ones
+
+       andi    t0,0xff00               # isolate pending bits
+        beqz    t0, 3f                  # spurious interrupt
+
+        andi    a0, t0, CAUSEF_IP7
+        beq     a0, zero, 1f
+        move    a0, sp
+        jal     mips_timer_interrupt
+       j       ret_from_irq
+        nop
+        
+1:
+        andi    a0, t0, CAUSEF_IP2      # the only int we expect at this time
+        beq     a0, zero, 3f           
+       move    a0,sp  
+       jal     it8172_hw0_irqdispatch
+
+       mfc0    t0,CP0_STATUS           # disable interrupts
+       ori     t0,1
+       xori    t0,1
+       mtc0    t0,CP0_STATUS
+        nop
+        nop
+        nop
+       
+       la      a1, ret_from_irq
+       jr      a1
+        nop
+       
+3:     
+       move a0, sp
+       jal     mips_spurious_interrupt
+        nop
+       la      a1, ret_from_irq
+       jr      a1
+        nop
+
+END(it8172_IRQ)
+
diff --git a/arch/mips/ite-boards/generic/irq.c b/arch/mips/ite-boards/generic/irq.c
new file mode 100644 (file)
index 0000000..ab2d6a4
--- /dev/null
@@ -0,0 +1,540 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *     ITE 8172G interrupt/setup routines.
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             ppopov@mvista.com or support@mvista.com
+ *
+ * Part of this file was derived from Carsten Langgaard's 
+ * arch/mips/mips-boards/atlas/atlas_int.c.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/malloc.h>
+#include <linux/random.h>
+#include <linux/serial_reg.h>
+
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_int.h>
+#include <asm/it8172/it8172_dbg.h>
+
+#undef DEBUG_IRQ
+#ifdef DEBUG_IRQ
+/* note: prints function name for you */
+#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#ifdef CONFIG_REMOTE_DEBUG
+extern void breakpoint(void);
+#endif
+
+/* revisit */
+#define EXT_IRQ0_TO_IP 2 /* IP 2 */
+#define EXT_IRQ5_TO_IP 7 /* IP 7 */
+
+extern void set_debug_traps(void);
+extern void mips_timer_interrupt(int irq, struct pt_regs *regs);
+extern asmlinkage void it8172_IRQ(void);
+irq_cpustat_t irq_stat [NR_CPUS];
+unsigned int local_bh_count[NR_CPUS];
+unsigned int local_irq_count[NR_CPUS];
+unsigned long spurious_count = 0;
+irq_desc_t irq_desc[NR_IRQS];
+irq_desc_t *irq_desc_base=&irq_desc[0];
+
+struct it8172_intc_regs volatile *it8172_hw0_icregs
+       = (struct it8172_intc_regs volatile *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_INTC_BASE));
+
+/* Function for careful CP0 interrupt mask access */
+static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
+{
+        unsigned long status = read_32bit_cp0_register(CP0_STATUS);
+        status &= ~((clr_mask & 0xFF) << 8);
+        status |=   (set_mask & 0xFF) << 8;
+        write_32bit_cp0_register(CP0_STATUS, status);
+}
+
+static inline void mask_irq(unsigned int irq_nr)
+{
+        modify_cp0_intmask(irq_nr, 0);
+}
+
+static inline void unmask_irq(unsigned int irq_nr)
+{
+        modify_cp0_intmask(0, irq_nr);
+}
+
+void disable_irq(unsigned int irq_nr)
+{
+        unsigned long flags;
+
+        save_and_cli(flags);
+        mask_irq(irq_nr);
+        restore_flags(flags);
+}
+
+void enable_irq(unsigned int irq_nr)
+{
+       unsigned long flags;
+
+        save_and_cli(flags);
+        unmask_irq(irq_nr);
+        restore_flags(flags);
+}
+
+
+void disable_it8172_irq(unsigned int irq_nr)
+{
+       unsigned short mask;
+
+       DPRINTK("disable_it8172_irq %d\n", irq_nr);
+
+       if ( (irq_nr >= IT8172_LPC_IRQ_BASE) && (irq_nr <= IT8172_SERIRQ_15)) {
+               /* LPC interrupt */
+               DPRINTK("disable, before lpc_mask  %x\n", it8172_hw0_icregs->lpc_mask);
+               it8172_hw0_icregs->lpc_mask |= (1 << (irq_nr - IT8172_LPC_IRQ_BASE));
+               DPRINTK("disable, after lpc_mask  %x\n", it8172_hw0_icregs->lpc_mask);
+       }
+       else if ( (irq_nr >= IT8172_LB_IRQ_BASE) && (irq_nr <= IT8172_IOCHK_IRQ)) {
+               /* Local Bus interrupt */
+               DPRINTK("before lb_mask  %x\n", it8172_hw0_icregs->lb_mask);
+               it8172_hw0_icregs->lb_mask |= (1 << (irq_nr - IT8172_LB_IRQ_BASE));
+               DPRINTK("after lb_mask  %x\n", it8172_hw0_icregs->lb_mask);
+       }
+       else if ( (irq_nr >= IT8172_PCI_DEV_IRQ_BASE) && (irq_nr <= IT8172_DMA_IRQ)) {
+               /* PCI and other interrupts */
+               DPRINTK("before pci_mask  %x\n", it8172_hw0_icregs->pci_mask);
+               it8172_hw0_icregs->pci_mask |= (1 << (irq_nr - IT8172_PCI_DEV_IRQ_BASE));
+               DPRINTK("after pci_mask  %x\n", it8172_hw0_icregs->pci_mask);
+       }
+       else if ( (irq_nr >= IT8172_NMI_IRQ_BASE) && (irq_nr <= IT8172_POWER_NMI_IRQ)) {
+               /* NMI interrupts */
+               DPRINTK("before nmi_mask  %x\n", it8172_hw0_icregs->nmi_mask);
+               it8172_hw0_icregs->nmi_mask |= (1 << (irq_nr - IT8172_NMI_IRQ_BASE));
+               DPRINTK("after nmi_mask  %x\n", it8172_hw0_icregs->nmi_mask);
+       }
+       else {
+               panic("disable_it8172_irq: bad irq %d\n", irq_nr);
+       }
+}
+
+
+void enable_it8172_irq(unsigned int irq_nr)
+{
+       DPRINTK("enable_it8172_irq %d\n", irq_nr);
+       if ( (irq_nr >= IT8172_LPC_IRQ_BASE) && (irq_nr <= IT8172_SERIRQ_15)) {
+               /* LPC interrupt */
+               DPRINTK("enable, before lpc_mask  %x\n", it8172_hw0_icregs->lpc_mask);
+               it8172_hw0_icregs->lpc_mask &= ~(1 << (irq_nr - IT8172_LPC_IRQ_BASE));
+               DPRINTK("enable, after lpc_mask  %x\n", it8172_hw0_icregs->lpc_mask);
+       }
+       else if ( (irq_nr >= IT8172_LB_IRQ_BASE) && (irq_nr <= IT8172_IOCHK_IRQ)) {
+               /* Local Bus interrupt */
+               DPRINTK("before lb_mask  %x\n", it8172_hw0_icregs->lb_mask);
+               it8172_hw0_icregs->lb_mask &= ~(1 << (irq_nr - IT8172_LB_IRQ_BASE));
+               DPRINTK("after lb_mask  %x\n", it8172_hw0_icregs->lb_mask);
+       }
+       else if ( (irq_nr >= IT8172_PCI_DEV_IRQ_BASE) && (irq_nr <= IT8172_DMA_IRQ)) {
+               /* PCI and other interrupts */
+               DPRINTK("before pci_mask  %x\n", it8172_hw0_icregs->pci_mask);
+               it8172_hw0_icregs->pci_mask &= ~(1 << (irq_nr - IT8172_PCI_DEV_IRQ_BASE));
+               DPRINTK("after pci_mask  %x\n", it8172_hw0_icregs->pci_mask);
+       }
+       else if ( (irq_nr >= IT8172_NMI_IRQ_BASE) && (irq_nr <= IT8172_POWER_NMI_IRQ)) {
+               /* NMI interrupts */
+               DPRINTK("before nmi_mask  %x\n", it8172_hw0_icregs->nmi_mask);
+               it8172_hw0_icregs->nmi_mask &= ~(1 << (irq_nr - IT8172_NMI_IRQ_BASE));
+               DPRINTK("after nmi_mask  %x\n", it8172_hw0_icregs->nmi_mask);
+       }
+       else {
+               panic("enable_it8172_irq: bad irq %d\n", irq_nr);
+       }
+}
+
+static unsigned int startup_ite_irq(unsigned int irq)
+{
+       enable_it8172_irq(irq);
+       return 0; 
+}
+
+#define shutdown_ite_irq       disable_it8172_irq
+#define mask_and_ack_ite_irq    disable_it8172_irq
+
+static void end_ite_irq(unsigned int irq)
+{
+       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+               enable_it8172_irq(irq);
+}
+
+static struct hw_interrupt_type it8172_irq_type = {
+       "ITE8172",
+       startup_ite_irq,
+       shutdown_ite_irq,
+       enable_it8172_irq,
+       disable_it8172_irq,
+       mask_and_ack_ite_irq,
+       end_ite_irq,
+       NULL
+};
+
+
+int get_irq_list(char *buf)
+{
+        int i, len = 0, j;
+        struct irqaction * action;
+
+        len += sprintf(buf+len, "           ");
+        for (j=0; j<smp_num_cpus; j++)
+                len += sprintf(buf+len, "CPU%d       ",j);
+        *(char *)(buf+len++) = '\n';
+
+        for (i = 0 ; i < NR_IRQS ; i++) {
+                action = irq_desc[i].action;
+                if ( !action || !action->handler )
+                        continue;
+                len += sprintf(buf+len, "%3d: ", i);           
+                len += sprintf(buf+len, "%10u ", kstat_irqs(i));
+                if ( irq_desc[i].handler )             
+                        len += sprintf(buf+len, " %s ", irq_desc[i].handler->typename );
+                else
+                        len += sprintf(buf+len, "  None      ");
+                len += sprintf(buf+len, "    %s",action->name);
+                for (action=action->next; action; action = action->next) {
+                        len += sprintf(buf+len, ", %s", action->name);
+                }
+                len += sprintf(buf+len, "\n");
+        }
+        len += sprintf(buf+len, "BAD: %10lu\n", spurious_count);
+        return len;
+}
+
+asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
+{
+       struct irqaction *action;
+       int cpu;
+
+       cpu = smp_processor_id();
+       irq_enter(cpu, irq);
+
+       kstat.irqs[cpu][irq]++;
+#if 0
+       if (irq_desc[irq].handler && irq_desc[irq].handler->ack) {
+       //      printk("invoking ack handler\n");
+               irq_desc[irq].handler->ack(irq);
+       }
+#endif
+
+       action = irq_desc[irq].action;
+
+       if (action && action->handler)
+       {
+               //mask_irq(1<<irq);
+               //printk("action->handler %x\n", action->handler);
+               disable_it8172_irq(irq);
+               //if (!(action->flags & SA_INTERRUPT)) __sti(); /* reenable ints */
+               do { 
+                       action->handler(irq, action->dev_id, regs);
+                       action = action->next;
+               } while ( action );
+               //__cli(); /* disable ints */
+               if (irq_desc[irq].handler)
+               {
+               }
+               //unmask_irq(1<<irq);
+               enable_it8172_irq(irq);
+       }
+       else
+       {
+               spurious_count++;
+               printk("Unhandled interrupt %d, cause %x, disabled\n", 
+                               (unsigned)irq, (unsigned)regs->cp0_cause);
+               disable_it8172_irq(irq);
+               //disable_irq(1<<irq);
+       }
+       irq_exit(cpu, irq);
+}
+
+int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+       unsigned long irqflags, const char * devname, void *dev_id)
+{
+        struct irqaction *old, **p, *action;
+        unsigned long flags;
+
+        /*
+         * IP0 and IP1 are software interrupts. IP7 is typically the timer interrupt.
+        *
+        * The ITE QED-4N-S01B board has one single interrupt line going from
+        * the system controller to the CPU. It's connected to the CPU external
+        * irq pin 1, which is IP2.  The interrupt numbers are listed in it8172_int.h;
+        * the ISA interrupts are numbered from 0 to 15, and the rest go from
+        * there.  
+         */
+
+       //printk("request_irq: %d handler %x\n", irq, handler);
+        if (irq >= NR_IRQS) 
+                return -EINVAL;
+
+        if (!handler)
+        {
+                /* Free */
+                for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next)
+                {
+                        /* Found it - now free it */
+                        save_flags(flags);
+                        cli();
+                        *p = action->next;
+                       disable_it8172_irq(irq);
+                        //disable_irq(1<<irq);
+                        restore_flags(flags);
+                        kfree(action);
+                        return 0;
+                }
+                return -ENOENT;
+        }
+        
+        action = (struct irqaction *)
+                kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+        if (!action)
+                return -ENOMEM;
+        memset(action, 0, sizeof(struct irqaction));
+        
+        save_flags(flags);
+        cli();
+        
+        action->handler = handler;
+        action->flags = irqflags;                                      
+        action->mask = 0;
+        action->name = devname;
+        action->dev_id = dev_id;
+        action->next = NULL;
+
+        p = &irq_desc[irq].action;
+        
+        if ((old = *p) != NULL) {
+                /* Can't share interrupts unless both agree to */
+                if (!(old->flags & action->flags & SA_SHIRQ))
+                        return -EBUSY;
+                /* add new interrupt at end of irq queue */
+                do {
+                        p = &old->next;
+                        old = *p;
+                } while (old);
+        }
+        *p = action;
+       enable_it8172_irq(irq);
+        restore_flags(flags);  
+#if 0
+       printk("request_irq: status %x cause %x\n", 
+                       read_32bit_cp0_register(CP0_STATUS), read_32bit_cp0_register(CP0_CAUSE));
+#endif
+        return 0;
+}
+               
+void free_irq(unsigned int irq, void *dev_id)
+{
+        request_irq(irq, NULL, 0, NULL, dev_id);
+}
+
+void enable_cpu_timer(void)
+{
+       enable_irq(1<<EXT_IRQ5_TO_IP); /* timer interrupt */
+}
+
+unsigned long probe_irq_on (void)
+{
+        return 0;
+}
+
+int probe_irq_off (unsigned long irqs)
+{
+        return 0;
+}
+
+
+void __init init_IRQ(void)
+{
+       int i;
+
+        memset(irq_desc, 0, sizeof(irq_desc));
+        set_except_vector(0, it8172_IRQ);
+
+       /* mask all interrupts */
+       it8172_hw0_icregs->lb_mask  = 0xffff;
+       it8172_hw0_icregs->lpc_mask = 0xffff;
+       it8172_hw0_icregs->pci_mask = 0xffff;
+       it8172_hw0_icregs->nmi_mask = 0xffff;
+
+       /* make all interrupts level triggered */
+       it8172_hw0_icregs->lb_trigger  = 0;
+       it8172_hw0_icregs->lpc_trigger = 0;
+       it8172_hw0_icregs->pci_trigger = 0;
+       it8172_hw0_icregs->nmi_trigger = 0;
+
+       /* active level setting */
+       /* uart, keyboard, and mouse are active high */
+       it8172_hw0_icregs->lpc_level = (0x10 | 0x2 | 0x1000);
+       it8172_hw0_icregs->lb_level |= 0x20;
+
+       /* keyboard and mouse are edge triggered */
+       it8172_hw0_icregs->lpc_trigger |= (0x2 | 0x1000); 
+
+
+#if 0
+       // Enable this piece of code to make internal USB interrupt
+       // edge triggered.
+       it8172_hw0_icregs->pci_trigger |= 
+               (1 << (IT8172_USB_IRQ - IT8172_PCI_DEV_IRQ_BASE));
+       it8172_hw0_icregs->pci_level &= 
+               ~(1 << (IT8172_USB_IRQ - IT8172_PCI_DEV_IRQ_BASE));
+#endif
+
+       for (i = 0; i <= IT8172_INT_END; i++) {
+               irq_desc[i].status      = IRQ_DISABLED;
+               irq_desc[i].action      = 0;
+               irq_desc[i].depth       = 1;
+               irq_desc[i].handler     = &it8172_irq_type;
+       }
+
+       /*
+        * Enable external int line 2
+        * All ITE interrupts are masked for now.
+        */
+       enable_irq(1<<EXT_IRQ0_TO_IP);
+       //change_cp0_status(ST0_IM, IE_IRQ2);
+
+#ifdef CONFIG_REMOTE_DEBUG
+       /* If local serial I/O used for debug port, enter kgdb at once */
+       puts("Waiting for kgdb to connect...");
+       set_debug_traps();
+       breakpoint(); 
+#endif
+}
+
+void mips_spurious_interrupt(struct pt_regs *regs)
+{
+#if 1
+       return;
+#else
+       unsigned long status, cause;
+
+       printk("got spurious interrupt\n");
+       status = read_32bit_cp0_register(CP0_STATUS);
+       cause = read_32bit_cp0_register(CP0_CAUSE);
+       printk("status %x cause %x\n", status, cause);
+       printk("epc %x badvaddr %x \n", regs->cp0_epc, regs->cp0_badvaddr);
+//     while(1);
+#endif
+}
+
+void it8172_hw0_irqdispatch(struct pt_regs *regs)
+{
+       int irq;
+       unsigned short intstatus, status;
+
+       intstatus = it8172_hw0_icregs->intstatus;
+       if (intstatus & 0x8) {
+               panic("Got NMI interrupt\n");
+       }
+       else if (intstatus & 0x4) {
+               /* PCI interrupt */
+               irq = 0;
+               status = it8172_hw0_icregs->pci_req;
+               while (!(status & 0x1)) {
+                       irq++;
+                       status >>= 1;
+               }
+               irq += IT8172_PCI_DEV_IRQ_BASE;
+               //printk("pci int %d\n", irq);
+       }
+       else if (intstatus & 0x1) {
+               /* Local Bus interrupt */
+               irq = 0;
+               status = it8172_hw0_icregs->lb_req;
+               while (!(status & 0x1)) {
+                       irq++;
+                       status >>= 1;
+               }
+               irq += IT8172_LB_IRQ_BASE;
+               //printk("lb int %d\n", irq);
+       }
+       else if (intstatus & 0x2) {
+               /* LPC interrupt */
+               /* Since some lpc interrupts are edge triggered,
+                * we could lose an interrupt this way because
+                * we acknowledge all ints at onces. Revisit.
+                */
+               status = it8172_hw0_icregs->lpc_req;
+               it8172_hw0_icregs->lpc_req = 0; /* acknowledge ints */
+               irq = 0;
+               while (!(status & 0x1)) {
+                       irq++;
+                       status >>= 1;
+               }
+               irq += IT8172_LPC_IRQ_BASE;
+               //printk("LPC int %d\n", irq);
+       }
+       else {
+               return;
+       }
+       do_IRQ(irq, regs);
+}
+
+void show_pending_irqs(void)
+{
+       fputs("intstatus:  ");
+       put32(it8172_hw0_icregs->intstatus);
+       puts("");
+
+       fputs("pci_req:  ");
+       put32(it8172_hw0_icregs->pci_req);
+       puts("");
+
+       fputs("lb_req:  ");
+       put32(it8172_hw0_icregs->lb_req);
+       puts("");
+
+       fputs("lpc_req:  ");
+       put32(it8172_hw0_icregs->lpc_req);
+       puts("");
+}
diff --git a/arch/mips/ite-boards/generic/it8172_cir.c b/arch/mips/ite-boards/generic/it8172_cir.c
new file mode 100644 (file)
index 0000000..a801e40
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *     IT8172 Consumer IR port generic routines.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_IT8172_CIR
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_cir.h>
+
+
+volatile struct it8172_cir_regs *cir_regs[NUM_CIR_PORTS] = {
+       (volatile struct it8172_cir_regs *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_CIR0_BASE)),
+       (volatile struct it8172_cir_regs *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_CIR1_BASE))};
+
+
+/*
+ * Initialize Consumer IR Port.
+ */
+int cir_port_init(struct cir_port *cir)
+{
+       int port = cir->port;
+       unsigned char data;
+
+       /* set baud rate */
+       cir_regs[port]->bdlr = cir->baud_rate & 0xff;
+       cir_regs[port]->bdhr = (cir->baud_rate >> 8) & 0xff;
+
+       /* set receiver control register */
+       cir_regs[port]->rcr = (CIR_SET_RDWOS(cir->rdwos) | CIR_SET_RXDCR(cir->rxdcr));
+
+       /* set carrier frequency register */
+       cir_regs[port]->cfr = (CIR_SET_CF(cir->cfq) | CIR_SET_HS(cir->hcfs));
+
+       /* set fifo threshold */
+       data = cir_regs[port]->mstcr & 0xf3;
+       data |= CIR_SET_FIFO_TL(cir->fifo_tl);
+       cir_regs[port]->mstcr = data;
+
+       clear_fifo(cir);
+       enable_receiver(cir);
+       disable_rx_demodulation(cir);
+
+       set_rx_active(cir);
+       int_enable(cir);
+       rx_int_enable(cir);
+
+       return 0;
+}
+
+
+void clear_fifo(struct cir_port *cir)
+{
+       cir_regs[cir->port]->mstcr |= CIR_FIFO_CLEAR;
+}
+
+void enable_receiver(struct cir_port *cir)
+{
+       cir_regs[cir->port]->rcr |= CIR_RXEN;
+}
+
+void disable_receiver(struct cir_port *cir)
+{
+       cir_regs[cir->port]->rcr &= ~CIR_RXEN;
+}
+
+void enable_rx_demodulation(struct cir_port *cir)
+{
+       cir_regs[cir->port]->rcr |= CIR_RXEND;
+}
+
+void disable_rx_demodulation(struct cir_port *cir)
+{
+       cir_regs[cir->port]->rcr &= ~CIR_RXEND;
+}
+
+void set_rx_active(struct cir_port *cir)
+{
+       cir_regs[cir->port]->rcr |= CIR_RXACT;
+}
+
+void int_enable(struct cir_port *cir)
+{
+       cir_regs[cir->port]->ier |= CIR_IEC;
+}
+
+void rx_int_enable(struct cir_port *cir)
+{
+       cir_regs[cir->port]->ier |= CIR_RDAIE;
+}
+
+void dump_regs(struct cir_port *cir)
+{
+       printk("mstcr %x ier %x iir %x cfr %x rcr %x tcr %x tfsr %x rfsr %x\n",
+       cir_regs[cir->port]->mstcr,
+       cir_regs[cir->port]->ier,
+       cir_regs[cir->port]->iir,
+       cir_regs[cir->port]->cfr,
+       cir_regs[cir->port]->rcr,
+       cir_regs[cir->port]->tcr,
+       cir_regs[cir->port]->tfsr,
+       cir_regs[cir->port]->rfsr);
+
+       while (cir_regs[cir->port]->iir & CIR_RDAI) {
+               printk("data %x\n", cir_regs[cir->port]->dr);
+       }
+}
+
+void dump_reg_addr(struct cir_port *cir)
+{
+       printk("dr %x mstcr %x ier %x iir %x cfr %x rcr %x tcr %x bdlr %x bdhr %x tfsr %x rfsr %x\n",
+       (unsigned)&cir_regs[cir->port]->dr,
+       (unsigned)&cir_regs[cir->port]->mstcr,
+       (unsigned)&cir_regs[cir->port]->ier,
+       (unsigned)&cir_regs[cir->port]->iir,
+       (unsigned)&cir_regs[cir->port]->cfr,
+       (unsigned)&cir_regs[cir->port]->rcr,
+       (unsigned)&cir_regs[cir->port]->tcr,
+       (unsigned)&cir_regs[cir->port]->bdlr,
+       (unsigned)&cir_regs[cir->port]->bdhr,
+       (unsigned)&cir_regs[cir->port]->tfsr,
+       (unsigned)&cir_regs[cir->port]->rfsr);
+}
+
+int cir_get_rx_count(struct cir_port *cir)
+{
+       return cir_regs[cir->port]->rfsr & CIR_RXFBC_MASK;
+}
+
+char cir_read_data(struct cir_port *cir)
+{
+       return cir_regs[cir->port]->dr;
+}
+
+char get_int_status(struct cir_port *cir)
+{
+       return cir_regs[cir->port]->iir;
+}
+#endif
diff --git a/arch/mips/ite-boards/generic/it8172_pci.c b/arch/mips/ite-boards/generic/it8172_pci.c
new file mode 100644 (file)
index 0000000..97eb6f1
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *     IT8172 system controller specific pci support.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+
+#ifdef CONFIG_PCI
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_pci.h>
+
+#define PCI_ACCESS_READ  0
+#define PCI_ACCESS_WRITE 1
+
+#undef DEBUG
+#undef DEBUG_CONFIG_CYCLES
+
+static int
+it8172_pcibios_config_access(unsigned char access_type, struct pci_dev *dev,
+                           unsigned char where, u32 *data)
+{
+       /* 
+        * config cycles are on 4 byte boundary only
+        */
+       unsigned char bus = dev->bus->number;
+       unsigned char dev_fn = dev->devfn;
+
+#ifdef DEBUG_CONFIG_CYCLES
+       printk("it config: type %d dev %x bus %d dev_fn %x data %x\n",
+                       access_type, dev, bus, dev_fn, *data);
+
+#endif
+
+       /* Setup address */
+       IT_WRITE(IT_CONFADDR, (bus << IT_BUSNUM_SHF) | 
+                       (dev_fn << IT_FUNCNUM_SHF) | (where & ~0x3));
+
+
+       if (access_type == PCI_ACCESS_WRITE) {
+               IT_WRITE(IT_CONFDATA, *data);
+       } 
+       else {
+               IT_READ(IT_CONFDATA, *data);
+       }
+
+       /*
+        * Revisit: check for master or target abort.
+        */
+       return 0;
+
+
+}
+
+
+/*
+ * We can't address 8 and 16 bit words directly.  Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int
+it8172_pcibios_read_config_byte (struct pci_dev *dev, int where, u8 *val)
+{
+       u32 data = 0;
+
+       if (it8172_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+               return -1;
+
+       *val = (data >> ((where & 3) << 3)) & 0xff;
+#ifdef DEBUG
+        printk("cfg read byte: bus %d dev_fn %x where %x: val %x\n", 
+                dev->bus->number, dev->devfn, where, *val);
+#endif
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int
+it8172_pcibios_read_config_word (struct pci_dev *dev, int where, u16 *val)
+{
+       u32 data = 0;
+
+       if (where & 1)
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+
+       if (it8172_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+              return -1;
+
+       *val = (data >> ((where & 3) << 3)) & 0xffff;
+#ifdef DEBUG
+        printk("cfg read word: bus %d dev_fn %x where %x: val %x\n", 
+                dev->bus->number, dev->devfn, where, *val);
+#endif
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+it8172_pcibios_read_config_dword (struct pci_dev *dev, int where, u32 *val)
+{
+       u32 data = 0;
+
+       if (where & 3)
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+       
+       if (it8172_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+               return -1;
+
+       *val = data;
+#ifdef DEBUG
+        printk("cfg read dword: bus %d dev_fn %x where %x: val %x\n", 
+                dev->bus->number, dev->devfn, where, *val);
+#endif
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int
+it8172_pcibios_write_config_byte (struct pci_dev *dev, int where, u8 val)
+{
+       u32 data = 0;
+       
+       if (it8172_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+               return -1;
+
+       data = (data & ~(0xff << ((where & 3) << 3))) |
+              (val << ((where & 3) << 3));
+
+       if (it8172_pcibios_config_access(PCI_ACCESS_WRITE, dev, where, &data))
+               return -1;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+it8172_pcibios_write_config_word (struct pci_dev *dev, int where, u16 val)
+{
+        u32 data = 0;
+
+       if (where & 1)
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+       
+        if (it8172_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+              return -1;
+
+       data = (data & ~(0xffff << ((where & 3) << 3))) | 
+              (val << ((where & 3) << 3));
+
+       if (it8172_pcibios_config_access(PCI_ACCESS_WRITE, dev, where, &data))
+              return -1;
+
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+it8172_pcibios_write_config_dword(struct pci_dev *dev, int where, u32 val)
+{
+       if (where & 3)
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+
+       if (it8172_pcibios_config_access(PCI_ACCESS_WRITE, dev, where, &val))
+              return -1;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops it8172_pci_ops = {
+       it8172_pcibios_read_config_byte,
+        it8172_pcibios_read_config_word,
+       it8172_pcibios_read_config_dword,
+       it8172_pcibios_write_config_byte,
+       it8172_pcibios_write_config_word,
+       it8172_pcibios_write_config_dword
+};
+
+void __init pcibios_init(void)
+{
+
+       printk("PCI: Probing PCI hardware on host bus 0.\n");
+       pci_scan_bus(0, &it8172_pci_ops, NULL);
+}
+
+int __init
+pcibios_enable_device(struct pci_dev *dev)
+{
+       u16 cmd, old_cmd;
+       int idx;
+       struct resource *r;
+
+       pci_read_config_word(dev, PCI_COMMAND, &cmd);
+       old_cmd = cmd;
+       for(idx=0; idx<6; idx++) {
+               r = &dev->resource[idx];
+               if (!r->start && r->end) {
+                       printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
+                       return -EINVAL;
+               }
+               if (r->flags & IORESOURCE_IO)
+                       cmd |= PCI_COMMAND_IO;
+               if (r->flags & IORESOURCE_MEM)
+                       cmd |= PCI_COMMAND_MEMORY;
+       }
+       if (dev->resource[PCI_ROM_RESOURCE].start)
+               cmd |= PCI_COMMAND_MEMORY;
+       if (cmd != old_cmd) {
+               printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
+               pci_write_config_word(dev, PCI_COMMAND, cmd);
+       }
+       return 0;
+}
+
+
+void __init
+pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+{
+    printk("pcibios_align_resource\n");
+}
+
+char * __init
+pcibios_setup(char *str)
+{
+       /* Nothing to do for now.  */
+
+       return str;
+}
+
+void __init
+pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+                        struct resource *res, int resource)
+{
+       unsigned long where, size;
+       u32 reg;
+
+       where = PCI_BASE_ADDRESS_0 + (resource * 4);
+       size = res->end - res->start;
+       pci_read_config_dword(dev, where, &reg);
+       reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
+       pci_write_config_dword(dev, where, reg);
+}
+
+void __init pcibios_fixup_bus(struct pci_bus *b)
+{
+       printk("pcibios_fixup_bus\n");
+}
+#endif /* CONFIG_PCI */
diff --git a/arch/mips/ite-boards/generic/it8172_rtc.c b/arch/mips/ite-boards/generic/it8172_rtc.c
new file mode 100644 (file)
index 0000000..4ae1e75
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             ppopov@mvista.com or support@mvista.com
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * RTC routines for ITE8172 MC146818-compatible rtc chip.
+ *
+ */
+#include <asm/spinlock.h>
+#include <linux/mc146818rtc.h>
+#include <asm/it8172/it8172.h>
+
+#define IT8172_RTC_ADR_REG  (IT8172_PCI_IO_BASE + IT_RTC_BASE)
+#define IT8172_RTC_DAT_REG  (IT8172_RTC_ADR_REG + 1)
+
+static volatile char *rtc_adr_reg = KSEG1ADDR((volatile char *)IT8172_RTC_ADR_REG);
+static volatile char *rtc_dat_reg = KSEG1ADDR((volatile char *)IT8172_RTC_DAT_REG);
+
+unsigned char it8172_rtc_read_data(unsigned long addr)
+{
+       unsigned char retval;
+
+       *rtc_adr_reg = addr;
+       retval =  *rtc_dat_reg;
+       return retval;
+}
+
+void it8172_rtc_write_data(unsigned char data, unsigned long addr)
+{
+       *rtc_adr_reg = addr;
+       *rtc_dat_reg = data;
+}
+
+static int it8172_rtc_bcd_mode(void)
+{
+       return 0;
+}
+
+struct rtc_ops it8172_rtc_ops = {
+       &it8172_rtc_read_data,
+       &it8172_rtc_write_data,
+       &it8172_rtc_bcd_mode
+};
diff --git a/arch/mips/ite-boards/generic/it8172_setup.c b/arch/mips/ite-boards/generic/it8172_setup.c
new file mode 100644 (file)
index 0000000..8fd937b
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *     IT8172/QED5231 board setup.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/console.h>
+#include <linux/mc146818rtc.h>
+#include <linux/serial_reg.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/it8172/it8172.h>
+#include <asm/it8712.h>
+#ifdef CONFIG_PC_KEYB
+#include <asm/keyboard.h>
+#endif
+
+#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE)
+extern void console_setup(char *, int *);
+char serial_console[20];
+#endif
+
+extern struct rtc_ops it8172_rtc_ops;
+extern struct resource ioport_resource;
+extern unsigned long mips_io_port_base;
+#ifdef CONFIG_BLK_DEV_IDE
+extern struct ide_ops std_ide_ops;
+extern struct ide_ops *ide_ops;
+#endif
+#ifdef CONFIG_PC_KEYB
+extern struct kbd_ops std_kbd_ops;
+int init_8712_keyboard(void);
+#endif
+
+extern int SearchIT8712(void);
+extern void InitLPCInterface(void);
+extern char * __init prom_getcmdline(void);
+extern void it8172_restart(void);
+extern void it8172_halt(void);
+extern void it8172_power_off(void);
+
+#ifdef CONFIG_IT8172_REVC
+struct {
+    struct resource ram;
+    struct resource pci_mem;
+    struct resource pci_io;
+    struct resource flash;
+    struct resource boot;
+} it8172_resources = {
+    { "RAM",           0,          0,          IORESOURCE_MEM }, /* to be initted */
+    { "PCI Mem",       0x10000000, 0x13FFFFFF, IORESOURCE_MEM },
+    { "PCI I/O",       0x14000000, 0x17FFFFFF                 },
+    { "Flash",         0x08000000, 0x0CFFFFFF                 },
+    { "Boot ROM",      0x1FC00000, 0x1FFFFFFF                 }
+};
+#else
+struct {
+    struct resource ram;
+    struct resource pci_mem0;
+    struct resource pci_mem1;
+    struct resource pci_io;
+    struct resource pci_mem2;
+    struct resource pci_mem3;
+    struct resource flash;
+    struct resource boot;
+} it8172_resources = {
+    { "RAM",           0,          0,          IORESOURCE_MEM }, /* to be initted */
+    { "PCI Mem0",      0x0C000000, 0x0FFFFFFF, IORESOURCE_MEM },
+    { "PCI Mem1",      0x10000000, 0x13FFFFFF, IORESOURCE_MEM },
+    { "PCI I/O",       0x14000000, 0x17FFFFFF                 },
+    { "PCI Mem2",      0x1A000000, 0x1BFFFFFF, IORESOURCE_MEM },
+    { "PCI Mem3",      0x1C000000, 0x1FBFFFFF, IORESOURCE_MEM },
+    { "Flash",         0x08000000, 0x0CFFFFFF                 },
+    { "Boot ROM",      0x1FC00000, 0x1FFFFFFF                 }
+};
+#endif
+
+
+void __init it8172_init_ram_resource(unsigned long memsize)
+{
+       it8172_resources.ram.end = memsize;
+}
+
+void __init it8172_setup(void)
+{
+#ifdef CONFIG_BLK_DEV_IT8172
+       unsigned short dsr;
+#endif
+       char *argptr;
+
+       argptr = prom_getcmdline();
+#ifdef CONFIG_SERIAL_CONSOLE
+       if ((argptr = strstr(argptr, "console=ttyS0")) == NULL) {
+               strcpy(serial_console, "ttyS0,115200");
+               console_setup(serial_console, NULL);
+       }
+#endif   
+
+       rtc_ops = &it8172_rtc_ops;
+
+       _machine_restart = it8172_restart;
+       _machine_halt = it8172_halt;
+       _machine_power_off = it8172_power_off;
+
+       /*
+       * IO/MEM resources. 
+       *
+       * revisit this area.
+       */
+       mips_io_port_base = KSEG1;
+       ioport_resource.start = it8172_resources.pci_io.start;
+       ioport_resource.end = it8172_resources.pci_io.end;
+#ifdef CONFIG_IT8172_REVC
+       iomem_resource.start = it8172_resources.pci_mem.start;
+       iomem_resource.end = it8172_resources.pci_mem.end;
+#else
+       iomem_resource.start = it8172_resources.pci_mem0.start;
+       iomem_resource.end = it8172_resources.pci_mem3.end;
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+       ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+#endif
+
+#ifdef CONFIG_BLK_DEV_IT8172
+       /*
+        * Pull IDE device out of standby mode.
+        */
+       IT_IO_READ16(IT_PM_DSR, dsr);
+       dsr &= ~IT_PM_DSR_IDESB;
+       IT_IO_WRITE16(IT_PM_DSR, dsr);
+
+       ide_ops = &std_ide_ops;
+#endif
+
+#ifdef CONFIG_FB
+    conswitchp = &dummy_con;
+#endif
+
+       InitLPCInterface();
+
+#ifdef CONFIG_MIPS_ITE8172
+       if (SearchIT8712()) {
+               printk("Found IT8712 Super IO\n");
+               // enable IT8712 serial port
+               LPCSetConfig(LDN_SERIAL1, 0x30, 0x01); /* enable */
+               LPCSetConfig(LDN_SERIAL1, 0x23, 0x01); /* clock selection */
+#ifdef CONFIG_PC_KEYB
+               if (init_8712_keyboard()) {
+                       printk("Unable to initialize keyboard\n");
+                       LPCSetConfig(LDN_KEYBOARD, 0x30, 0x0); /* disable keyboard */
+               }
+               else {
+                       LPCSetConfig(LDN_KEYBOARD, 0x30, 0x1); /* enable keyboard */
+                       LPCSetConfig(LDN_KEYBOARD, 0xf0, 0x2);
+                       LPCSetConfig(LDN_KEYBOARD, 0x71, 0x3);
+
+                       LPCSetConfig(LDN_MOUSE, 0x30, 0x1); /* enable mouse */
+
+                       LPCSetConfig(0x4, 0x30, 0x1);
+                       LPCSetConfig(0x4, 0xf4, LPCGetConfig(0x4, 0xf4) | 0x80);
+
+                       if ((LPCGetConfig(LDN_KEYBOARD, 0x30) == 0) || 
+                                       (LPCGetConfig(LDN_MOUSE, 0x30) == 0)) 
+                               printk("Error: keyboard or mouse not enabled\n");
+
+                       kbd_ops = &std_kbd_ops;
+               }
+#endif
+       }
+       else {
+               printk("IT8712 Super IO not found\n");
+       }
+#endif
+
+#ifdef CONFIG_IT8172_CIR
+       {
+               unsigned long data;
+               //printk("Enabling CIR0\n");
+               IT_IO_READ16(IT_PM_DSR, data);
+               data &= ~IT_PM_DSR_CIR0SB;
+               IT_IO_WRITE16(IT_PM_DSR, data);
+               //printk("DSR register: %x\n", (unsigned)IT_IO_READ16(IT_PM_DSR, data));
+       }
+#endif
+#ifdef CONFIG_IT8172_SCR0
+       {
+               unsigned i; 
+               /* Enable Smart Card Reader 0 */
+               /* First power it up */
+               IT_IO_READ16(IT_PM_DSR, i);
+               i &= ~IT_PM_DSR_SCR0SB;
+               IT_IO_WRITE16(IT_PM_DSR, i);
+               /* Then initialize its registers */
+               outb(( IT_SCR_SFR_GATE_UART_OFF     << IT_SCR_SFR_GATE_UART_BIT
+                     |IT_SCR_SFR_FET_CHARGE_213_US << IT_SCR_SFR_FET_CHARGE_BIT
+                     |IT_SCR_SFR_CARD_FREQ_3_5_MHZ << IT_SCR_SFR_CARD_FREQ_BIT
+                     |IT_SCR_SFR_FET_ACTIVE_INVERT << IT_SCR_SFR_FET_ACTIVE_BIT
+                     |IT_SCR_SFR_ENABLE_ON         << IT_SCR_SFR_ENABLE_BIT),
+                    IT8172_PCI_IO_BASE + IT_SCR0_BASE + IT_SCR_SFR);
+               outb(IT_SCR_SCDR_RESET_MODE_ASYNC << IT_SCR_SCDR_RESET_MODE_BIT,
+                    IT8172_PCI_IO_BASE + IT_SCR0_BASE + IT_SCR_SCDR);
+       }
+#endif /* CONFIG_IT8172_SCR0 */
+#ifdef CONFIG_IT8172_SCR1
+       {
+               unsigned i; 
+               /* Enable Smart Card Reader 1 */
+               /* First power it up */
+               IT_IO_READ16(IT_PM_DSR, i);
+               i &= ~IT_PM_DSR_SCR1SB;
+               IT_IO_WRITE16(IT_PM_DSR, i);
+               /* Then initialize its registers */
+               outb(( IT_SCR_SFR_GATE_UART_OFF     << IT_SCR_SFR_GATE_UART_BIT
+                     |IT_SCR_SFR_FET_CHARGE_213_US << IT_SCR_SFR_FET_CHARGE_BIT
+                     |IT_SCR_SFR_CARD_FREQ_3_5_MHZ << IT_SCR_SFR_CARD_FREQ_BIT
+                     |IT_SCR_SFR_FET_ACTIVE_INVERT << IT_SCR_SFR_FET_ACTIVE_BIT
+                     |IT_SCR_SFR_ENABLE_ON         << IT_SCR_SFR_ENABLE_BIT),
+                    IT8172_PCI_IO_BASE + IT_SCR1_BASE + IT_SCR_SFR);
+               outb(IT_SCR_SCDR_RESET_MODE_ASYNC << IT_SCR_SCDR_RESET_MODE_BIT,
+                    IT8172_PCI_IO_BASE + IT_SCR1_BASE + IT_SCR_SCDR);
+       }
+#endif /* CONFIG_IT8172_SCR1 */
+}
+
+
+#ifdef CONFIG_PC_KEYB
+/*
+ * According to the ITE Special BIOS Note for waking up the 
+ * keyboard controller...
+ */
+int init_8712_keyboard()
+{
+       unsigned int cmd_port = 0x14000064;
+       unsigned int data_port = 0x14000060;
+       unsigned char data;
+       int i;
+
+       printk("8712 keyboard init");
+
+       outb(0xaa, cmd_port); /* send self-test cmd */
+       i = 0;
+       while (!(inb(cmd_port) & 0x1)) { /* wait output buffer full */
+               i++;
+               if (i > 0xffffff)
+                       return 1;
+       }
+
+       data = inb(data_port);
+       outb(0xcb, cmd_port); /* set ps2 mode */
+       while (inb(cmd_port) & 0x2) { /* wait while input buffer full */
+               i++;
+               if (i > 0xffffff)
+                       return 1;
+       }
+       outb(0x01, data_port);
+       while (inb(cmd_port) & 0x2) { /* wait while input buffer full */
+               i++;
+               if (i > 0xffffff)
+                       return 1;
+       }
+
+       outb(0x60, cmd_port); /* write 8042 command byte */
+       while (inb(cmd_port) & 0x2) { /* wait while input buffer full */
+               i++;
+               if (i > 0xffffff)
+                       return 1;
+       }
+       outb(0x45, data_port); /* at interface, keyboard enabled, system flag */
+       while (inb(cmd_port) & 0x2) { /* wait while input buffer full */
+               i++;
+               if (i > 0xffffff)
+                       return 1;
+       }
+
+       outb(0xae, cmd_port); /* enable interface */
+       return 0;
+}
+#endif
diff --git a/arch/mips/ite-boards/generic/lpc.c b/arch/mips/ite-boards/generic/lpc.c
new file mode 100644 (file)
index 0000000..0887c63
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *     ITE Semi IT8712 Super I/O functions.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <asm/io.h>
+#include <asm/types.h>
+#include <asm/it8712.h>
+#include <asm/it8172/it8172.h>
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+void LPCEnterMBPnP()
+{
+       int i;
+       unsigned char key[4] = {0x87, 0x01, 0x55, 0x55};
+
+       for (i = 0; i<4; i++)
+               outb(key[i], LPC_KEY_ADDR);
+
+}
+
+void LPCExitMBPnP()
+{
+       outb(0x02, LPC_KEY_ADDR);
+       outb(0x02, LPC_DATA_ADDR);
+}
+
+void LPCSetConfig(char LdnNumber, char Index, char data)
+{
+       LPCEnterMBPnP();                                // Enter IT8712 MB PnP mode
+       outb(0x07, LPC_KEY_ADDR);
+       outb(LdnNumber, LPC_DATA_ADDR);
+       outb(Index, LPC_KEY_ADDR);      
+       outb(data, LPC_DATA_ADDR);
+       LPCExitMBPnP();
+}
+
+char LPCGetConfig(char LdnNumber, char Index)
+{
+       char rtn;
+
+       LPCEnterMBPnP();                                // Enter IT8712 MB PnP mode
+       outb(0x07, LPC_KEY_ADDR);
+       outb(LdnNumber, LPC_DATA_ADDR);
+       outb(Index, LPC_KEY_ADDR);      
+       rtn = inb(LPC_DATA_ADDR);
+       LPCExitMBPnP();
+       return rtn;
+}
+
+int SearchIT8712()
+{
+       unsigned char Id1, Id2;
+       unsigned short Id;
+
+       LPCEnterMBPnP();
+       outb(0x20, LPC_KEY_ADDR); /* chip id byte 1 */
+       Id1 = inb(LPC_DATA_ADDR);
+       outb(0x21, LPC_KEY_ADDR); /* chip id byte 2 */
+       Id2 = inb(LPC_DATA_ADDR);
+       Id = (Id1 << 8) | Id2;
+       LPCExitMBPnP();
+       if (Id == 0x8712) 
+               return TRUE;
+       else
+               return FALSE;
+}
+
+void InitLPCInterface()
+{
+       unsigned char bus, dev_fn;
+       unsigned long data;
+
+       bus = 0;
+       dev_fn = 1<<3 | 4; 
+
+
+       /* pci cmd, SERR# Enable */
+       IT_WRITE(IT_CONFADDR,  
+                (bus         << IT_BUSNUM_SHF)   |
+                (dev_fn      << IT_FUNCNUM_SHF) |
+                ((0x4 / 4) << IT_REGNUM_SHF));
+       IT_READ(IT_CONFDATA, data);
+       data |= 0x0100;
+       IT_WRITE(IT_CONFADDR,  
+                (bus         << IT_BUSNUM_SHF)   |
+                (dev_fn      << IT_FUNCNUM_SHF) |
+                ((0x4 / 4) << IT_REGNUM_SHF));
+       IT_WRITE(IT_CONFDATA, data);
+
+       /* setup serial irq control register */
+       IT_WRITE(IT_CONFADDR,  
+                (bus         << IT_BUSNUM_SHF)   |
+                (dev_fn      << IT_FUNCNUM_SHF) |
+                ((0x48 / 4) << IT_REGNUM_SHF));
+       IT_READ(IT_CONFDATA, data);
+       data  = (data & 0xffff00ff) | 0xc400;
+       IT_WRITE(IT_CONFADDR,  
+                (bus         << IT_BUSNUM_SHF)   |
+                (dev_fn      << IT_FUNCNUM_SHF) |
+                ((0x48 / 4) << IT_REGNUM_SHF));
+       IT_WRITE(IT_CONFDATA, data);
+
+
+       /* Enable I/O Space Subtractive Decode */
+       /* default 0x4C is 0x3f220000 */
+       IT_WRITE(IT_CONFADDR,  
+                (bus         << IT_BUSNUM_SHF)   |
+                (dev_fn      << IT_FUNCNUM_SHF) |
+                ((0x4C / 4) << IT_REGNUM_SHF));
+       IT_WRITE(IT_CONFDATA, 0x3f2200f3);
+}
diff --git a/arch/mips/ite-boards/generic/pmon_prom.c b/arch/mips/ite-boards/generic/pmon_prom.c
new file mode 100644 (file)
index 0000000..74fd619
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *    PROM library initialisation code, assuming a version of
+ *    pmon is the boot code.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             ppopov@mvista.com or support@mvista.com
+ *
+ * This file was derived from Carsten Langgaard's 
+ * arch/mips/mips-boards/xx files.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+/* #define DEBUG_CMDLINE */
+
+char arcs_cmdline[COMMAND_LINE_SIZE];
+int prom_argc;
+char **prom_argv, **prom_envp;
+
+typedef struct
+{
+    char *name;
+/*    char *val; */
+}t_env_var;
+
+
+char * __init prom_getcmdline(void)
+{
+       return &(arcs_cmdline[0]);
+}
+
+void  __init prom_init_cmdline(void)
+{
+       char *cp;
+       int actr;
+
+       actr = 1; /* Always ignore argv[0] */
+
+       cp = &(arcs_cmdline[0]);
+       while(actr < prom_argc) {
+               strcpy(cp, prom_argv[actr]);
+               cp += strlen(prom_argv[actr]);
+               *cp++ = ' ';
+               actr++;
+       }
+       if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
+               --cp;
+       *cp = '\0';
+
+}
+
+
+char *prom_getenv(char *envname)
+{
+       /*
+        * Return a pointer to the given environment variable.
+        * Environment variables are stored in the form of "memsize=64".
+        */
+
+       t_env_var *env = (t_env_var *)prom_envp;
+       int i;
+
+       i = strlen(envname);
+
+       while(env->name) {
+               if(strncmp(envname, env->name, i) == 0) {
+                       return(env->name + strlen(envname) + 1);
+               }
+               env++;
+       }
+       return(NULL);
+}
+
+static inline unsigned char str2hexnum(unsigned char c)
+{
+       if(c >= '0' && c <= '9')
+       return c - '0';
+       if(c >= 'a' && c <= 'f')
+       return c - 'a' + 10;
+       return 0; /* foo */
+}
+
+int __init page_is_ram(unsigned long pagenr)
+{
+    return 1;
+}
+
+void prom_free_prom_memory (void)
+{
+}
+
+unsigned long __init prom_get_memsize(void)
+{
+       char *memsize_str;
+       unsigned int memsize;
+
+       memsize_str = prom_getenv("memsize");
+       if (!memsize_str) {
+               printk("memsize unknown: setting to 32MB\n");
+               memsize = 32; 
+       } else {
+#ifdef DEBUG
+               printk("prom_memsize: %s\n", memsize_str);
+#endif
+               memsize = simple_strtol(memsize_str, NULL, 0);
+       }
+       return memsize;
+}
diff --git a/arch/mips/ite-boards/generic/puts.c b/arch/mips/ite-boards/generic/puts.c
new file mode 100644 (file)
index 0000000..4ff7ebf
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *     Low level uart routines to directly access a 16550 uart.
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+
+#define SERIAL_BASE   0xB4011800 /* it8172 */
+#define SER_CMD       5
+#define SER_DATA      0x00
+#define TX_BUSY       0x20
+
+#define TIMEOUT       0xffff
+#undef SLOW_DOWN
+
+static const char digits[16] = "0123456789abcdef";
+static volatile unsigned char * const com1 = (unsigned char *)SERIAL_BASE;
+
+
+#ifdef SLOW_DOWN
+static inline void slow_down()
+{
+    int k;
+    for (k=0; k<10000; k++);
+}
+#else
+#define slow_down()
+#endif
+
+void
+putch(const unsigned char c)
+{
+    unsigned char ch;
+    int i = 0;
+
+    do {
+        ch = com1[SER_CMD];
+        slow_down();
+        i++;
+        if (i>TIMEOUT) {
+            break;
+        }
+    } while (0 == (ch & TX_BUSY));
+    com1[SER_DATA] = c;
+}
+
+void
+puts(unsigned char *cp)
+{
+    unsigned char ch;
+    int i = 0;
+
+    while (*cp) {
+        do {
+             ch = com1[SER_CMD];
+            slow_down();
+            i++;
+            if (i>TIMEOUT) {
+                break;
+            }
+        } while (0 == (ch & TX_BUSY));
+        com1[SER_DATA] = *cp++;
+    }
+    putch('\r');
+    putch('\n');
+}
+
+void
+fputs(unsigned char *cp)
+{
+    unsigned char ch;
+    int i = 0;
+
+    while (*cp) {
+
+        do {
+             ch = com1[SER_CMD];
+             slow_down();
+            i++;
+            if (i>TIMEOUT) {
+                break;
+            }
+        } while (0 == (ch & TX_BUSY));
+        com1[SER_DATA] = *cp++;
+    }
+}
+
+
+void
+put64(uint64_t ul)
+{
+    int cnt;
+    unsigned ch;
+
+    cnt = 16;            /* 16 nibbles in a 64 bit long */
+    putch('0');
+    putch('x');
+    do {
+        cnt--;
+        ch = (unsigned char)(ul >> cnt * 4) & 0x0F;
+                putch(digits[ch]);
+    } while (cnt > 0);
+}
+
+void
+put32(unsigned u)
+{
+    int cnt;
+    unsigned ch;
+
+    cnt = 8;            /* 8 nibbles in a 32 bit long */
+    putch('0');
+    putch('x');
+    do {
+        cnt--;
+        ch = (unsigned char)(u >> cnt * 4) & 0x0F;
+                putch(digits[ch]);
+    } while (cnt > 0);
+}
diff --git a/arch/mips/ite-boards/generic/reset.c b/arch/mips/ite-boards/generic/reset.c
new file mode 100644 (file)
index 0000000..1e013c9
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *     ITE 8172 reset routines.
+ *
+ * Copyright (C) 1997, 2001 Ralf Baechle
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+
+void it8172_restart(char *command)
+{
+       set_cp0_status(ST0_BEV | ST0_ERL);
+       change_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+       flush_cache_all();
+       write_32bit_cp0_register(CP0_WIRED, 0);
+       __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+}
+
+void it8172_halt(void)
+{
+       printk(KERN_NOTICE "\n** You can safely turn off the power\n");
+       while (1)
+               __asm__(".set\tmips3\n\t"
+                       "wait\n\t"
+                       ".set\tmips0");
+}
+
+void it8172_power_off(void)
+{
+       it8172_halt();
+}
diff --git a/arch/mips/ite-boards/generic/time.c b/arch/mips/ite-boards/generic/time.c
new file mode 100644 (file)
index 0000000..e6e83aa
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Setting up the clock on the MIPS boards.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+
+#include <asm/mipsregs.h>
+#include <asm/ptrace.h>
+#include <asm/it8172/it8172_int.h>
+
+#include <linux/mc146818rtc.h>
+#include <linux/timex.h>
+
+extern void enable_cpu_timer(void);
+extern volatile unsigned long wall_jiffies;
+extern rwlock_t xtime_lock;
+
+unsigned long missed_heart_beats = 0;
+static long last_rtc_update = 0;
+static unsigned long r4k_offset; /* Amount to increment compare reg each time */
+static unsigned long r4k_cur;    /* What counter should be at next timer irq */
+static unsigned int timer_tick_count=0;
+
+static inline void ack_r4ktimer(unsigned long newval)
+{
+       write_32bit_cp0_register(CP0_COMPARE, newval);
+}
+
+
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be
+ * called 500 ms after the second nowtime has started, because when
+ * nowtime is written into the registers of the CMOS clock, it will
+ * jump to the next second precisely 500 ms later. Check the Motorola
+ * MC146818A or Dallas DS12887 data sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ *      sets the minutes. Usually you won't notice until after reboot!
+ */
+static int set_rtc_mmss(unsigned long nowtime)
+{
+       int retval = 0;
+       int real_seconds, real_minutes, cmos_minutes;
+       unsigned char save_control, save_freq_select;
+
+       save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
+       CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+       save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
+       CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+       cmos_minutes = CMOS_READ(RTC_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) {
+               CMOS_WRITE(real_seconds,RTC_SECONDS);
+               CMOS_WRITE(real_minutes,RTC_MINUTES);
+       } else {
+               printk(KERN_WARNING
+                      "set_rtc_mmss: can't update from %d to %d\n",
+                      cmos_minutes, real_minutes);
+               retval = -1;
+       }
+
+       /* The following flags have to be released exactly in this order,
+        * otherwise the DS12887 (popular MC146818A clone with integrated
+        * battery and quartz) will not reset the oscillator and will not
+        * update precisely 500 ms later. You won't find this mentioned in
+        * the Dallas Semiconductor data sheets, but who believes data
+        * sheets anyway ...                           -- Markus Kuhn
+        */
+       CMOS_WRITE(save_control, RTC_CONTROL);
+       CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+
+       return retval;
+}
+
+
+/*
+ * There are a lot of conceptually broken versions of the MIPS timer interrupt
+ * handler floating around.  This one is rather different, but the algorithm
+ * is provably more robust.
+ */
+void mips_timer_interrupt(struct pt_regs *regs)
+{
+       if (r4k_offset == 0)
+               goto null;
+
+       do {
+               kstat.irqs[0][MIPS_CPU_TIMER_IRQ]++;
+               do_timer(regs);
+
+               /* Historical comment/code:
+                * RTC time of day s updated approx. every 11 
+                * minutes.  Because of how the numbers work out 
+                * we need to make absolutely sure we do this update
+                * within 500ms before the * next second starts, 
+                * thus the following code.
+                */
+               read_lock(&xtime_lock);
+               if ((time_status & STA_UNSYNC) == 0 
+                   && xtime.tv_sec > last_rtc_update + 660 
+                   && xtime.tv_usec >= 500000 - (tick >> 1) 
+                   && xtime.tv_usec <= 500000 + (tick >> 1))
+                       if (set_rtc_mmss(xtime.tv_sec) == 0)
+                               last_rtc_update = xtime.tv_sec;
+                       else {
+                               /* do it again in 60 s */
+                               last_rtc_update = xtime.tv_sec - 600; 
+                       }
+               read_unlock(&xtime_lock);
+
+               r4k_cur += r4k_offset;
+               ack_r4ktimer(r4k_cur);
+
+       } while (((unsigned long)read_32bit_cp0_register(CP0_COUNT)
+                - r4k_cur) < 0x7fffffff);
+
+       return;
+
+null:
+       ack_r4ktimer(0);
+}
+
+/* 
+ * Figure out the r4k offset, the amount to increment the compare
+ * register for each time tick. 
+ * Use the RTC to calculate offset.
+ */
+static unsigned long __init cal_r4koff(void)
+{
+       unsigned long count;
+       unsigned int flags;
+
+       __save_and_cli(flags);
+
+       /* Start counter exactly on falling edge of update flag */
+       while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+       while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+       /* Start r4k counter. */
+       write_32bit_cp0_register(CP0_COUNT, 0);
+
+       /* Read counter exactly on falling edge of update flag */
+       while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+       while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+       count = read_32bit_cp0_register(CP0_COUNT);
+
+       /* restore interrupts */
+       __restore_flags(flags);
+               
+       return (count / HZ);
+}
+
+static unsigned long __init get_mips_time(void)
+{
+       unsigned int year, mon, day, hour, min, sec;
+       unsigned char save_control;
+
+       save_control = CMOS_READ(RTC_CONTROL);
+
+       /* Freeze it. */
+       CMOS_WRITE(save_control | RTC_SET, RTC_CONTROL);
+
+       /* Read regs. */
+       sec = CMOS_READ(RTC_SECONDS);
+       min = CMOS_READ(RTC_MINUTES);
+       hour = CMOS_READ(RTC_HOURS);
+
+       if (!(save_control & RTC_24H))
+       {
+               if ((hour & 0xf) == 0xc)
+                       hour &= 0x80;
+               if (hour & 0x80)
+                       hour = (hour & 0xf) + 12;     
+       }
+       day = CMOS_READ(RTC_DAY_OF_MONTH);
+       mon = CMOS_READ(RTC_MONTH);
+       year = CMOS_READ(RTC_YEAR);
+
+       /* Unfreeze clock. */
+       CMOS_WRITE(save_control, RTC_CONTROL);
+
+       if ((year += 1900) < 1970)
+               year += 100;
+
+       return mktime(year, mon, day, hour, min, sec);
+}
+
+void __init time_init(void)
+{
+        unsigned int est_freq, flags;
+
+        /* Set Data mode - binary. */ 
+        CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
+
+       printk("calculating r4koff... ");
+       r4k_offset = cal_r4koff();
+       printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);
+
+       est_freq = 2*r4k_offset*HZ;     
+       est_freq += 5000;    /* round */
+       est_freq -= est_freq%10000;
+       printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, 
+              (est_freq%1000000)*100/1000000);
+       r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset);
+
+       write_32bit_cp0_register(CP0_COMPARE, r4k_cur);
+
+       enable_cpu_timer();
+
+       /* Read time from the RTC chipset. */
+       write_lock_irqsave (&xtime_lock, flags);
+       xtime.tv_sec = get_mips_time();
+       xtime.tv_usec = 0;
+       write_unlock_irqrestore(&xtime_lock, flags);
+}
+
+/* This is for machines which generate the exact clock. */
+#define USECS_PER_JIFFY (1000000/HZ)
+
+/* Cycle counter value at the previous timer interrupt.. */
+
+static unsigned int timerhi = 0, timerlo = 0;
+
+/*
+ * FIXME: Does playing with the RP bit in c0_status interfere with this code?
+ */
+static unsigned long do_fast_gettimeoffset(void)
+{
+       u32 count;
+       unsigned long res, tmp;
+
+       /* Last jiffy when do_fast_gettimeoffset() was called. */
+       static unsigned long last_jiffies=0;
+       unsigned long quotient;
+
+       /*
+        * Cached "1/(clocks per usec)*2^32" value.
+        * It has to be recalculated once each jiffy.
+        */
+       static unsigned long cached_quotient=0;
+
+       tmp = jiffies;
+
+       quotient = cached_quotient;
+
+       if (tmp && last_jiffies != tmp) {
+               last_jiffies = tmp;
+               __asm__(".set\tnoreorder\n\t"
+                       ".set\tnoat\n\t"
+                       ".set\tmips3\n\t"
+                       "lwu\t%0,%2\n\t"
+                       "dsll32\t$1,%1,0\n\t"
+                       "or\t$1,$1,%0\n\t"
+                       "ddivu\t$0,$1,%3\n\t"
+                       "mflo\t$1\n\t"
+                       "dsll32\t%0,%4,0\n\t"
+                       "nop\n\t"
+                       "ddivu\t$0,%0,$1\n\t"
+                       "mflo\t%0\n\t"
+                       ".set\tmips0\n\t"
+                       ".set\tat\n\t"
+                       ".set\treorder"
+                       :"=&r" (quotient)
+                       :"r" (timerhi),
+                        "m" (timerlo),
+                        "r" (tmp),
+                        "r" (USECS_PER_JIFFY)
+                       :"$1");
+               cached_quotient = quotient;
+       }
+
+       /* Get last timer tick in absolute kernel time */
+       count = read_32bit_cp0_register(CP0_COUNT);
+
+       /* .. relative to previous jiffy (32 bits is enough) */
+       count -= timerlo;
+
+       __asm__("multu\t%1,%2\n\t"
+               "mfhi\t%0"
+               :"=r" (res)
+               :"r" (count),
+                "r" (quotient));
+
+       /*
+        * Due to possible jiffies inconsistencies, we need to check 
+        * the result so that we'll get a timer that is monotonic.
+        */
+       if (res >= USECS_PER_JIFFY)
+               res = USECS_PER_JIFFY-1;
+
+       return res;
+}
+
+void do_gettimeofday(struct timeval *tv)
+{
+       unsigned int flags;
+
+       read_lock_irqsave (&xtime_lock, flags);
+       *tv = xtime;
+       tv->tv_usec += do_fast_gettimeoffset();
+
+       /*
+        * xtime is atomically updated in timer_bh. jiffies - wall_jiffies
+        * is nonzero if the timer bottom half hasnt executed yet.
+        */
+       if (jiffies - wall_jiffies)
+               tv->tv_usec += USECS_PER_JIFFY;
+
+       read_unlock_irqrestore (&xtime_lock, flags);
+
+       if (tv->tv_usec >= 1000000) {
+               tv->tv_usec -= 1000000;
+               tv->tv_sec++;
+       }
+}
+
+void do_settimeofday(struct timeval *tv)
+{
+       write_lock_irq (&xtime_lock);
+
+       /* This is revolting. We need to set the xtime.tv_usec correctly.
+        * However, the value in this location is is value at the last tick.
+        * Discover what correction gettimeofday would have done, and then
+        * undo it!
+        */
+       tv->tv_usec -= do_fast_gettimeoffset();
+
+       if (tv->tv_usec < 0) {
+               tv->tv_usec += 1000000;
+               tv->tv_sec--;
+       }
+
+       xtime = *tv;
+       time_adjust = 0;                /* stop active adjtime() */
+       time_status |= STA_UNSYNC;
+       time_maxerror = NTP_PHASE_LIMIT;
+       time_esterror = NTP_PHASE_LIMIT;
+
+       write_unlock_irq (&xtime_lock);
+}
diff --git a/arch/mips/ite-boards/qed-4n-s01b/Makefile b/arch/mips/ite-boards/qed-4n-s01b/Makefile
new file mode 100644 (file)
index 0000000..3929a0c
--- /dev/null
@@ -0,0 +1,37 @@
+#
+#  Copyright 2000 MontaVista Software Inc.
+#  Author: MontaVista Software, Inc.
+#      ppopov@mvista.com or support@mvista.com
+#
+# Makefile for the ITE 8172 (qed-4n-s01b) board, board
+# specific files.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.s:
+       $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+       $(CC) $(CFLAGS) -c $< -o $*.o
+
+all: ite.o
+
+O_TARGET := ite.o
+
+obj-y := init.o 
+
+ifdef CONFIG_PCI
+obj-y += pci_fixup.o
+endif
+
+ifdef CONFIG_BLK_DEV_INITRD
+obj-y += le_ramdisk.o
+endif
+
+
+dep:
+       $(CPP) -M *.c > .depend
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/mips/ite-boards/qed-4n-s01b/README b/arch/mips/ite-boards/qed-4n-s01b/README
new file mode 100644 (file)
index 0000000..fb4b519
--- /dev/null
@@ -0,0 +1,2 @@
+This is an ITE (www.iteusa.com) eval board for the ITE 8172G
+system controller, with a QED 5231 CPU.
diff --git a/arch/mips/ite-boards/qed-4n-s01b/init.c b/arch/mips/ite-boards/qed-4n-s01b/init.c
new file mode 100644 (file)
index 0000000..8670e1f
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *     IT8172/QED5231 board setup.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_dbg.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+
+extern char _end;
+extern void  __init prom_init_cmdline(void);
+extern unsigned long __init prom_get_memsize(void);
+extern void __init it8172_init_ram_resource(unsigned long memsize);
+
+#define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_ALIGN(x)   (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
+
+
+int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+{
+       unsigned long mem_size, free_start, free_end, bootmap_size;
+       unsigned long pcicr;
+
+       prom_argc = argc;
+       prom_argv = argv;
+       prom_envp = envp;
+
+       puts("ITE board running...");
+
+       mips_machgroup = MACH_GROUP_ITE;
+       mips_machtype = MACH_QED_4N_S01B;  /* ITE board name/number */
+
+       prom_init_cmdline();
+       mem_size = prom_get_memsize();
+
+       printk("Memory size: %dMB\n", (unsigned)mem_size);
+
+       mem_size <<= 20; /* MB */
+
+       /*
+        * make the entire physical memory visible to pci bus masters
+        */
+       IT_READ(IT_MC_PCICR, pcicr);
+       pcicr &= ~0x1f; 
+       pcicr |= (mem_size - 1) >> 22;
+       IT_WRITE(IT_MC_PCICR, pcicr);
+
+       it8172_init_ram_resource(mem_size);
+       add_memory_region(0, 20 << 20, BOOT_MEM_RAM);
+
+       return 0;
+}
diff --git a/arch/mips/ite-boards/qed-4n-s01b/pci_fixup.c b/arch/mips/ite-boards/qed-4n-s01b/pci_fixup.c
new file mode 100644 (file)
index 0000000..befceff
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *     Board specific pci fixups.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+
+#ifdef CONFIG_PCI
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_pci.h>
+#include <asm/it8172/it8172_int.h>
+
+void __init board_int_line_fixup(struct pci_dev *dev)     
+{
+       unsigned int slot, func;
+       unsigned char pin;
+        const int internal_func_irqs[7] = {
+            IT8172_AC97_IRQ,
+            IT8172_DMA_IRQ,
+            IT8172_CDMA_IRQ,
+            IT8172_USB_IRQ,
+            IT8172_BRIDGE_MASTER_IRQ,
+            IT8172_IDE_IRQ,
+            IT8172_MC68K_IRQ
+        };
+
+#ifdef DEBUG
+       printk("board_int_line_fixup bus %d\n", dev->bus->number);
+#endif
+       if (dev->bus->number != 0)
+               return;
+
+       pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+
+#ifdef DEBUG
+       pci_read_config_dword(dev, PCI_SUBSYSTEM_VENDOR_ID, &vendor);
+#endif
+
+       slot = PCI_SLOT(dev->devfn);
+        func = PCI_FUNC(dev->devfn);
+
+       switch (slot) {
+                case 0x01:
+                    /*
+                     * Internal device 1 is actually 7 different internal
+                     * devices on the IT8172G (a multi-function device).
+                     */
+                    if (func < 7)
+                        dev->irq = internal_func_irqs[func];
+                    break;
+               case 0x10:
+                       switch (pin) {
+                               case 1: /* pin A */
+                                       dev->irq = IT8172_PCI_INTA_IRQ;
+                                       break;
+                               case 2: /* pin B */
+                                       dev->irq = IT8172_PCI_INTB_IRQ;
+                                       break;
+                               case 3: /* pin C */
+                                       dev->irq = IT8172_PCI_INTC_IRQ;
+                                       break;
+                               case 4: /* pin D */
+                                       dev->irq = IT8172_PCI_INTD_IRQ;
+                                       break;
+                               default:
+                                       dev->irq = 0xff; 
+                                       break;
+
+                       }
+                       break;
+               case 0x11:
+                       switch (pin) {
+                               case 1: /* pin A */
+                                       dev->irq = IT8172_PCI_INTA_IRQ;
+                                       break;
+                               case 2: /* pin B */
+                                       dev->irq = IT8172_PCI_INTB_IRQ;
+                                       break;
+                               case 3: /* pin C */
+                                       dev->irq = IT8172_PCI_INTC_IRQ;
+                                       break;
+                               case 4: /* pin D */
+                                       dev->irq = IT8172_PCI_INTD_IRQ;
+                                       break;
+                               default:
+                                       dev->irq = 0xff; 
+                                       break;
+
+                       }
+                       break;
+               case 0x12:
+                       switch (pin) {
+                               case 1: /* pin A */
+                                       dev->irq = IT8172_PCI_INTB_IRQ;
+                                       break;
+                               case 2: /* pin B */
+                                       dev->irq = IT8172_PCI_INTC_IRQ;
+                                       break;
+                               case 3: /* pin C */
+                                       dev->irq = IT8172_PCI_INTD_IRQ;
+                                       break;
+                               case 4: /* pin D */
+                                       dev->irq = IT8172_PCI_INTA_IRQ;
+                                       break;
+                               default:
+                                       dev->irq = 0xff; 
+                                       break;
+
+                       }
+                       break;
+               case 0x13:
+                       switch (pin) {
+                               case 1: /* pin A */
+                                       dev->irq = IT8172_PCI_INTC_IRQ;
+                                       break;
+                               case 2: /* pin B */
+                                       dev->irq = IT8172_PCI_INTD_IRQ;
+                                       break;
+                               case 3: /* pin C */
+                                       dev->irq = IT8172_PCI_INTA_IRQ;
+                                       break;
+                               case 4: /* pin D */
+                                       dev->irq = IT8172_PCI_INTB_IRQ;
+                                       break;
+                               default:
+                                       dev->irq = 0xff; 
+                                       break;
+
+                       }
+                       break;
+               case 0x14:
+                       switch (pin) {
+                               case 1: /* pin A */
+                                       dev->irq = IT8172_PCI_INTD_IRQ;
+                                       break;
+                               case 2: /* pin B */
+                                       dev->irq = IT8172_PCI_INTA_IRQ;
+                                       break;
+                               case 3: /* pin C */
+                                       dev->irq = IT8172_PCI_INTB_IRQ;
+                                       break;
+                               case 4: /* pin D */
+                                       dev->irq = IT8172_PCI_INTC_IRQ;
+                                       break;
+                               default:
+                                       dev->irq = 0xff; 
+                                       break;
+
+                       }
+                       break;
+               default:
+                       return;
+       }
+
+#ifdef DEBUG
+       printk("irq fixup: slot %d, vendor %x, int line %d, int number %d\n",
+                       slot, vendor, pin, dev->irq);
+#endif
+       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+
+}
+
+struct pci_fixup pcibios_fixups[] = {
+       { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, board_int_line_fixup },
+       { 0 }
+};
+#endif
index 3b3e83e..0a12a22 100644 (file)
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.5 1999/01/03 17:50:47 ralf Exp $
 #
 # Makefile for the Jazz family specific parts of the kernel
 #
@@ -8,17 +7,17 @@
 #
 
 .S.s:
-       $(CPP) $(CFLAGS) $< -o $*.s
+       $(CPP) $(CFLAGS) $< -o $@
 .S.o:
-       $(CC) $(CFLAGS) -c $< -o $*.o
+       $(CC) $(CFLAGS) -c $< -o $@
 
 all: jazz.o
+
 O_TARGET := jazz.o
-O_OBJS  := int-handler.o jazzdma.o reset.o rtc-jazz.o setup.o floppy-jazz.o \
-           kbd-jazz.o
 
-int-handler.o: int-handler.S
+obj-y   := int-handler.o irq.o jazzdma.o reset.o rtc-jazz.o setup.o \
+           floppy-jazz.o kbd-jazz.o
 
-clean:
+int-handler.o: int-handler.S
 
 include $(TOPDIR)/Rules.make
index 4ca2021..e9f32b4 100644 (file)
@@ -5,15 +5,19 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996, 1997 by Ralf Baechle
+ * Copyright (C) 1996, 97, 2000 by Ralf Baechle
  */
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <asm/branch.h>
+#include <asm/cpu.h>
 #include <asm/inst.h>
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
+#include <asm/bootinfo.h>
+#include <asm/processor.h>
 
 /*
  * Compute the return address and do emulate branch simulation, if required.
@@ -65,7 +69,7 @@ int __compute_return_epc(struct pt_regs *regs)
                switch (insn.i_format.rt) {
                case bltz_op:
                case bltzl_op:
-                       if (regs->regs[insn.i_format.rs] < 0)
+                       if ((long)regs->regs[insn.i_format.rs] < 0)
                                epc = epc + 4 + (insn.i_format.simmediate << 2);
                        else
                                epc += 8;
@@ -74,7 +78,7 @@ int __compute_return_epc(struct pt_regs *regs)
 
                case bgez_op:
                case bgezl_op:
-                       if (regs->regs[insn.i_format.rs] >= 0)
+                       if ((long)regs->regs[insn.i_format.rs] >= 0)
                                epc = epc + 4 + (insn.i_format.simmediate << 2);
                        else
                                epc += 8;
@@ -84,7 +88,7 @@ int __compute_return_epc(struct pt_regs *regs)
                case bltzal_op:
                case bltzall_op:
                        regs->regs[31] = epc + 8;
-                       if (regs->regs[insn.i_format.rs] < 0)
+                       if ((long)regs->regs[insn.i_format.rs] < 0)
                                epc = epc + 4 + (insn.i_format.simmediate << 2);
                        else
                                epc += 8;
@@ -94,7 +98,7 @@ int __compute_return_epc(struct pt_regs *regs)
                case bgezal_op:
                case bgezall_op:
                        regs->regs[31] = epc + 8;
-                       if (regs->regs[insn.i_format.rs] >= 0)
+                       if ((long)regs->regs[insn.i_format.rs] >= 0)
                                epc = epc + 4 + (insn.i_format.simmediate << 2);
                        else
                                epc += 8;
@@ -142,7 +146,7 @@ int __compute_return_epc(struct pt_regs *regs)
        case blez_op: /* not really i_format */
        case blezl_op:
                /* rt field assumed to be zero */
-               if (regs->regs[insn.i_format.rs] <= 0)
+               if ((long)regs->regs[insn.i_format.rs] <= 0)
                        epc = epc + 4 + (insn.i_format.simmediate << 2);
                else
                        epc += 8;
@@ -152,7 +156,7 @@ int __compute_return_epc(struct pt_regs *regs)
        case bgtz_op:
        case bgtzl_op:
                /* rt field assumed to be zero */
-               if (regs->regs[insn.i_format.rs] > 0)
+               if ((long)regs->regs[insn.i_format.rs] > 0)
                        epc = epc + 4 + (insn.i_format.simmediate << 2);
                else
                        epc += 8;
@@ -163,6 +167,11 @@ int __compute_return_epc(struct pt_regs *regs)
         * And now the FPA/cp1 branch instructions.
         */
        case cop1_op:
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+               if(!(mips_cpu.options & MIPS_CPU_FPU))
+                       fcr31 = current->thread.fpu.soft.sr;
+               else
+#endif
                asm ("cfc1\t%0,$31":"=r" (fcr31));
                bit = (insn.i_format.rt >> 2);
                bit += (bit != 0);
index 117403e..a4a239e 100644 (file)
@@ -1,12 +1,12 @@
-/* $Id: process.c,v 1.18 2000/01/29 01:41:59 ralf Exp $
- *
+/*
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994 - 1999 by Ralf Baechle and others.
+ * Copyright (C) 1994 - 2000 by Ralf Baechle and others.
  * Copyright (C) 1999 Silicon Graphics, Inc.
  */
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -21,6 +21,7 @@
 #include <linux/a.out.h>
 
 #include <asm/bootinfo.h>
+#include <asm/cpu.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/mipsregs.h>
@@ -55,7 +56,7 @@ void exit_thread(void)
 {
        /* Forget lazy fpu state */
        if (last_task_used_math == current) {
-               set_cp0_status(ST0_CU1, ST0_CU1);
+               set_cp0_status(ST0_CU1);
                __asm__ __volatile__("cfc1\t$0,$31");
                last_task_used_math = NULL;
        }
@@ -65,7 +66,7 @@ void flush_thread(void)
 {
        /* Forget lazy fpu state */
        if (last_task_used_math == current) {
-               set_cp0_status(ST0_CU1, ST0_CU1);
+               set_cp0_status(ST0_CU1);
                __asm__ __volatile__("cfc1\t$0,$31");
                last_task_used_math = NULL;
        }
@@ -81,9 +82,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
 
        childksp = (unsigned long)p + KERNEL_STACK_SIZE - 32;
 
-       if (last_task_used_math == current) {
-               set_cp0_status(ST0_CU1, ST0_CU1);
-               save_fp(p);
+       if (last_task_used_math == current)
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+               if (mips_cpu.options & MIPS_CPU_FPU)
+#endif
+       {
+                       set_cp0_status(ST0_CU1);
+                       save_fp(p);
        }
        /* set up new TSS. */
        childregs = (struct pt_regs *) childksp - 1;
index 4a55e23..f042b69 100644 (file)
@@ -1,14 +1,16 @@
-/* $Id: ptrace.c,v 1.17 1999/09/28 22:25:47 ralf Exp $
- *
+/*
  * 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) 1992 Ross Biro
  * Copyright (C) Linus Torvalds
- * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle
+ * Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle
  * Copyright (C) 1996 David S. Miller
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999 MIPS Technologies, Inc.
  */
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -24,6 +26,8 @@
 #include <asm/page.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
 
 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
@@ -131,13 +135,22 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        break;
                case FPR_BASE ... FPR_BASE + 31:
                        if (child->used_math) {
+                               unsigned long long *fregs
+                                       = (unsigned long long *)
+                                           &child->thread.fpu.hard.fp_regs[0];
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+                           if(!(mips_cpu.options & MIPS_CPU_FPU)) {
+                                   fregs = (unsigned long long *)
+                                       &child->thread.fpu.soft.regs[0];
+                           } else 
+#endif
                                if (last_task_used_math == child) {
                                        enable_cp1();
                                        save_fp(child);
                                        disable_cp1();
                                        last_task_used_math = NULL;
                                }
-                               tmp = child->thread.fpu.hard.fp_regs[addr - 32];
+                               tmp = (unsigned long) fregs[(addr - 32)];
                        } else {
                                tmp = -1;       /* FP not yet used  */
                        }
@@ -158,6 +171,11 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        tmp = regs->lo;
                        break;
                case FPC_CSR:
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+                       if(!(mips_cpu.options & MIPS_CPU_FPU))
+                               tmp = child->thread.fpu.soft.sr;
+                       else
+#endif
                        tmp = child->thread.fpu.hard.control;
                        break;
                case FPC_EIR: { /* implementation / version register */
@@ -198,9 +216,17 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        regs->regs[addr] = data;
                        break;
                case FPR_BASE ... FPR_BASE + 31: {
-                       unsigned int *fregs;
+                       unsigned long long *fregs;
+                       fregs = (unsigned long long *)&child->thread.fpu.hard.fp_regs[0];
                        if (child->used_math) {
-                               if (last_task_used_math == child) {
+                               if (last_task_used_math == child)
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+                                   if(!(mips_cpu.options & MIPS_CPU_FPU)) {
+                                       fregs = (unsigned long long *)
+                                           &child->thread.fpu.soft.regs[0];
+                                   } else
+#endif
+                               {
                                        enable_cp1();
                                        save_fp(child);
                                        disable_cp1();
@@ -213,7 +239,6 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                                       sizeof(child->thread.fpu.hard));
                                child->thread.fpu.hard.control = 0;
                        }
-                       fregs = child->thread.fpu.hard.fp_regs;
                        fregs[addr - FPR_BASE] = data;
                        break;
                }
@@ -227,6 +252,11 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        regs->lo = data;
                        break;
                case FPC_CSR:
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+                       if(!(mips_cpu.options & MIPS_CPU_FPU)) 
+                               child->thread.fpu.soft.sr = data;
+                       else
+#endif
                        child->thread.fpu.hard.control = data;
                        break;
                default:
index efb00dc..5489ea9 100644 (file)
@@ -1,7 +1,4 @@
-/* $Id: r2300_fpu.S,v 1.6 1999/08/09 19:43:14 harald Exp $
- *
- * r2300_fpu.S: Save/restore floating point context for signal handlers.
- *
+/*
  * 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.
@@ -30,7 +27,7 @@
        .set    noreorder
        .set    mips1
        /* Save floating point context */
-LEAF(save_fp_context)
+LEAF(_save_fp_context)
        li      v0, 0                                   # assume success
        cfc1    t1,fcr31
        EX(swc1 $f0,(SC_FPREGS+0)(a0))
@@ -65,13 +62,13 @@ LEAF(save_fp_context)
        EX(swc1 $f29,(SC_FPREGS+232)(a0))
        EX(swc1 $f30,(SC_FPREGS+240)(a0))
        EX(swc1 $f31,(SC_FPREGS+248)(a0))
-       EX(sw   t1,SC_FPC_CSR(a0))
+       EX(sw   t1,(SC_FPC_CSR)(a0))
        cfc1    t0,$0                           # implementation/version
        jr      ra
        .set    nomacro
-        EX(sw  t0,SC_FPC_EIR(a0))
+        EX(sw  t0,(SC_FPC_EIR)(a0))
        .set    macro
-       END(save_fp_context)
+       END(_save_fp_context)
 
 /*
  * Restore FPU state:
@@ -82,9 +79,9 @@ LEAF(save_fp_context)
  * frame on the current content of c0_status, not on the content of the
  * stack frame which might have been changed by the user.
  */
-LEAF(restore_fp_context)
+LEAF(_restore_fp_context)
        li      v0, 0                                   # assume success
-       EX(lw t0,SC_FPC_CSR(a0))
+       EX(lw t0,(SC_FPC_CSR)(a0))
        EX(lwc1 $f0,(SC_FPREGS+0)(a0))
        EX(lwc1 $f1,(SC_FPREGS+8)(a0))
        EX(lwc1 $f2,(SC_FPREGS+16)(a0))
@@ -119,7 +116,7 @@ LEAF(restore_fp_context)
        EX(lwc1 $f31,(SC_FPREGS+248)(a0))
        jr      ra
         ctc1   t0,fcr31
-       END(restore_fp_context)
+       END(_restore_fp_context)
 
        .type   fault@function
        .ent    fault
index c94037a..4a546eb 100644 (file)
@@ -9,7 +9,7 @@
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
  * Further modifications to make this work:
- * Copyright (c) 1998 Harald Koerfgen
+ * Copyright (c) 1998-2000 Harald Koerfgen
  */
 #include <asm/asm.h>
 #include <asm/bootinfo.h>
        .align  5
 
 /*
- * task_struct *r4xx0_resume(task_struct *prev,
- *                           task_struct *next)
+ * task_struct *resume(task_struct *prev,
+ *                     task_struct *next)
  */
 LEAF(resume)
-       .set    reorder
        mfc0    t1, CP0_STATUS
-       .set    noreorder
        sw      t1, THREAD_STATUS(a0)
        CPU_SAVE_NONSCRATCH(a0)
        sw      ra, THREAD_REG31(a0)
@@ -57,8 +55,10 @@ LEAF(resume)
        and     a2, a3
        or      a2, t1
        mtc0    a2, CP0_STATUS
+       .set    noreorder
        jr      ra
         move   v0, a0
+       .set    reorder
        END(resume)
 
 /*
@@ -74,19 +74,16 @@ LEAF(lazy_fpu_switch)
        or      t0, t3
        mtc0    t0, CP0_STATUS
 
+       .set    noreorder
        beqz    a0, 2f                          # Save floating point state
         nor    t3, zero, t3
        .set    reorder
        lw      t1, ST_OFF(a0)                  # last thread looses fpu
-       .set    noreorder
        and     t1, t3
        sw      t1, ST_OFF(a0)
-       swc1    $f0, (THREAD_FPU + 0x00)(a0)
        FPU_SAVE_SINGLE(a0, t1)                 # clobbers t1
 
 2:
-       lwc1    $f0, (THREAD_FPU + 0x00)($28)
-       .set    reorder
        FPU_RESTORE_SINGLE($28, t0)             # clobbers t0
        jr      ra
        END(lazy_fpu_switch)
@@ -94,14 +91,20 @@ LEAF(lazy_fpu_switch)
 /*
  * Save a thread's fp context.
  */
-       .set    noreorder
 LEAF(save_fp)
        FPU_SAVE_SINGLE(a0, t1)                 # clobbers t1
        jr      ra
-        swc1   $f0, (THREAD_FPU + 0x00)(a0)
        END(save_fp)
 
 /*
+ * Restore a thread's fp context.
+ */
+LEAF(restore_fp)
+       FPU_RESTORE_SINGLE(a0, t1)              # clobbers t1
+       jr      ra
+       END(restore_fp)
+
+/*
  * Load the FPU with signalling NANS.  This bit pattern we're using has
  * the property that no matter wether considered as single or as double
  * precission represents signaling NANS.
@@ -153,6 +156,8 @@ LEAF(init_fpu)
        mtc1    t0, $f28
        mtc1    t0, $f29
        mtc1    t0, $f30
+       .set    noreorder
        jr      ra
         mtc1   t0, $f31
+       .set    reorder
        END(init_fpu)
index c5649bd..6ad810d 100644 (file)
@@ -1,15 +1,15 @@
-/* $Id: r4k_fpu.S,v 1.8 1999/09/28 22:25:47 ralf Exp $
- *
- * r4k_fpu.S: Save/restore floating point context for signal handlers.
- *
+/*
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996, 1998 by Ralf Baechle
+ * Copyright (C) 1996, 1998, 2000 by Ralf Baechle
  *
  * Multi-arch abstraction and asm macros for easier reading:
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ *  Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc.
  */
 #include <asm/asm.h>
 #include <asm/errno.h>
@@ -19,7 +19,7 @@
 #include <asm/regdef.h>
 
 #define EX(a,b)                                                        \
-9:     a,##b;                                                  \
+9:     a,b;                                                    \
        .section __ex_table,"a";                                \
        PTR     9b, fault;                                      \
        .previous
@@ -27,7 +27,7 @@
        .set    noreorder
        .set    mips3
        /* Save floating point context */
-LEAF(save_fp_context)
+LEAF(_save_fp_context)
        li      v0, 0                                   # assume success
        cfc1    t1,fcr31
 
@@ -55,7 +55,7 @@ LEAF(save_fp_context)
        .set    nomacro
         EX(sw  t0,SC_FPC_EIR(a0))
        .set    macro
-       END(save_fp_context)
+       END(_save_fp_context)
 
 /*
  * Restore FPU state:
@@ -66,7 +66,7 @@ LEAF(save_fp_context)
  * frame on the current content of c0_status, not on the content of the
  * stack frame which might have been changed by the user.
  */
-LEAF(restore_fp_context)
+LEAF(_restore_fp_context)
        li      v0, 0                                   # assume success
        EX(lw   t0,SC_FPC_CSR(a0))
 
@@ -92,7 +92,7 @@ LEAF(restore_fp_context)
        EX(ldc1 $f30,(SC_FPREGS+240)(a0))
        jr      ra
         ctc1   t0,fcr31
-       END(restore_fp_context)
+       END(_restore_fp_context)
 
        .type   fault@function
        .ent    fault
index 35493e1..bfa3cb8 100644 (file)
@@ -7,6 +7,13 @@
  * Multi-cpu abstraction and reworking:
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  */
+/**************************************************************************
+ *  14 Nov, 2000.
+ *  Made support for MIPS32 CPUs.
+ *
+ *  Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *************************************************************************/
 #include <asm/asm.h>
 #include <asm/current.h>
 #include <asm/offset.h>
        sw      pte, (ptr);
 
        .set    noreorder
-       .set    mips3
 
 /*
  * From the IDT errata for the QED RM5230 (Nevada), processor revision 1.0:
@@ -147,7 +153,9 @@ invalid_tlbl:
         tlbwi
 1:
        nop
+       .set    mips3   
        eret
+       .set    mips0
 #endif
 
 nopage_tlbl:
@@ -169,7 +177,9 @@ nopage_tlbl:
         tlbwi
 1:
        nop
+       .set    mips3   
        eret
+       .set    mips0
 #endif
 
 nopage_tlbs:
@@ -201,7 +211,9 @@ nopage_tlbs:
         tlbwi
 1:
        nop
+       .set    mips3
        eret
+       .set    mips0
 #endif
 
 nowrite_mod:
index 0ac3c53..e1d10f9 100644 (file)
@@ -9,6 +9,14 @@
  * Copyright (C) 1994, 1995, 1996, by Andreas Busse
  * Copyright (C) 1999 Silicon Graphics, Inc.
  */
+/**************************************************************************
+ *  13 Nov, 2000.
+ *  Made support for MIPS32 CPUs and restoring of fp registers.
+ *
+ *  Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *************************************************************************/
+       
 #include <asm/asm.h>
 #include <asm/bootinfo.h>
 #include <asm/cachectl.h>
@@ -24,8 +32,6 @@
 
 #include <asm/asmmacro.h>
 
-       .set    mips3
-
 /*
  * task_struct *r4xx0_resume(task_struct *prev, task_struct *next)
  */
@@ -95,6 +101,14 @@ LEAF(save_fp)
        END(save_fp)
 
 /*
+ * Restore a thread's fp context.
+ */
+LEAF(restore_fp)
+       FPU_RESTORE_DOUBLE(a0, t1)              # clobbers t1
+       jr      ra
+       END(restore_fp)
+
+/*
  * Load the FPU with signalling NANS.  This bit pattern we're using has
  * the property that no matter whether considered as single or as double
  * precision represents signaling NANS.
@@ -105,6 +119,7 @@ LEAF(save_fp)
 #define FPU_DEFAULT  0x00000000
 
 LEAF(init_fpu)
+       .set    mips3
        mfc0    t0, CP0_STATUS
        li      t1, 0x20000000
        or      t0, t1
@@ -135,3 +150,4 @@ LEAF(init_fpu)
         dmtc1  t0, $f30
        .set    reorder
        END(init_fpu)
+
index 851b4dc..d8d3b13 100644 (file)
@@ -9,8 +9,6 @@
  *
  * Multi-arch abstraction and asm macros for easier reading:
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: r6000_fpu.S,v 1.5 1999/05/01 22:40:37 ralf Exp $
  */
 #include <asm/asm.h>
 #include <asm/fpregdef.h>
@@ -21,7 +19,7 @@
        .set    noreorder
        .set    mips2
        /* Save floating point context */
-       LEAF(save_fp_context)
+       LEAF(_save_fp_context)
        mfc0    t0,CP0_STATUS
        sll     t0,t0,2
        bgez    t0,1f
@@ -49,7 +47,7 @@
         sw     t0,SC_FPC_CSR(a0)
 1:     jr      ra
         nop
-       END(save_fp_context)
+       END(_save_fp_context)
 
 /* Restore FPU state:
  *  - fp gp registers
@@ -59,7 +57,7 @@
  * frame on the current content of c0_status, not on the content of the
  * stack frame which might have been changed by the user.
  */
-       LEAF(restore_fp_context)
+       LEAF(_restore_fp_context)
        mfc0    t0,CP0_STATUS
        sll     t0,t0,2
 
@@ -86,4 +84,4 @@
         ctc1   t0,fcr31
 1:     jr      ra
         nop
-       END(restore_fp_context)
+       END(_restore_fp_context)
index 5a9478f..d62b355 100644 (file)
@@ -127,112 +127,3 @@ int __down_trylock(struct semaphore * sem)
 {
        return waking_non_zero_trylock(sem);
 }
-
-/*
- * RW Semaphores
- */
-void
-__down_read(struct rw_semaphore *sem, int count)
-{
-       DOWN_VAR;
-
- retry_down:
-       if (count < 0) {
-               /* Wait for the lock to become unbiased.  Readers
-                  are non-exclusive.  */
-               
-               /* This takes care of granting the lock.  */
-               up_read(sem);
-
-               add_wait_queue(&sem->wait, &wait);
-               while (atomic_read(&sem->count) < 0) {
-                       set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-                       if (atomic_read(&sem->count) >= 0)
-                               break;
-                       schedule();
-               }
-
-               remove_wait_queue(&sem->wait, &wait);
-               tsk->state = TASK_RUNNING;
-
-               mb();
-               count = atomic_dec_return(&sem->count);
-               if (count <= 0)
-                       goto retry_down;
-       } else {
-               add_wait_queue(&sem->wait, &wait);
-
-               while (1) {
-                       if (test_and_clear_bit(0, &sem->granted))
-                               break;
-                       set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-                       if ((sem->granted & 1) == 0)
-                               schedule();
-               }
-
-               remove_wait_queue(&sem->wait, &wait);
-               tsk->state = TASK_RUNNING;
-       }
-}
-
-void
-__down_write(struct rw_semaphore *sem, int count)
-{
-       DOWN_VAR;
-
- retry_down:
-       if (count + RW_LOCK_BIAS < 0) {
-               up_write(sem);
-
-               add_wait_queue_exclusive(&sem->wait, &wait);
-       
-               while (atomic_read(&sem->count) < 0) {
-                       set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-                       if (atomic_read(&sem->count) >= RW_LOCK_BIAS)
-                               break;
-                       schedule();
-               }
-
-               remove_wait_queue(&sem->wait, &wait);
-               tsk->state = TASK_RUNNING;
-
-               mb();
-               count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
-               if (count != 0)
-                       goto retry_down;
-       } else {
-               /* Put ourselves at the end of the list.  */
-               add_wait_queue_exclusive(&sem->write_bias_wait, &wait);
-
-               while (1) {
-                       if (test_and_clear_bit(1, &sem->granted))
-                               break;
-                       set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-                       if ((sem->granted & 2) == 0)
-                               schedule();
-               }
-
-               remove_wait_queue(&sem->write_bias_wait, &wait);
-               tsk->state = TASK_RUNNING;
-
-               /* If the lock is currently unbiased, awaken the sleepers.
-                  FIXME: This wakes up the readers early in a bit of a
-                  stampede -> bad!  */
-               if (atomic_read(&sem->count) >= 0)
-                       wake_up(&sem->wait);
-       }
-}
-
-void
-__rwsem_wake(struct rw_semaphore *sem, unsigned long readers)
-{
-       if (readers) {
-               if (test_and_set_bit(0, &sem->granted))
-                       BUG();
-               wake_up(&sem->wait);
-       } else {
-               if (test_and_set_bit(1, &sem->granted))
-                       BUG();
-               wake_up(&sem->write_bias_wait);
-       }
-}
index 6023e2e..2a6bdbc 100644 (file)
@@ -4,8 +4,9 @@
  * for more details.
  *
  * Copyright (C) 1995  Linus Torvalds
- * Copyright (C) 1995, 1996, 1997, 1998  Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000  Ralf Baechle
  * Copyright (C) 1996  Stoned Elipot
+ * Copyright (C) 2000  Maciej W. Rozycki
  */
 #include <linux/config.h>
 #include <linux/errno.h>
 #include <asm/asm.h>
 #include <asm/bootinfo.h>
 #include <asm/cachectl.h>
+#include <asm/cpu.h>
 #include <asm/io.h>
 #include <asm/stackframe.h>
 #include <asm/system.h>
-#include <asm/cpu.h>
 #ifdef CONFIG_SGI_IP22
 #include <asm/sgialib.h>
 #endif
@@ -152,64 +153,171 @@ static inline int cpu_has_confreg(void)
 #endif
 }
 
+/* declaration of the global struct */
+struct mips_cpu mips_cpu = {PRID_IMP_UNKNOWN, CPU_UNKNOWN, 0, 0, 0,
+                           {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}};
+
+/* Shortcut for assembler access to mips_cpu.options */
+int *cpuoptions = &mips_cpu.options;
+
+#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4KTLB \
+               | MIPS_CPU_COUNTER | MIPS_CPU_CACHE_CDEX)
+
 static inline void cpu_probe(void)
 {
-       unsigned int prid = read_32bit_cp0_register(CP0_PRID);
-       switch(prid & 0xff00) {
+       unsigned long config1;
+
+       mips_cpu.processor_id = read_32bit_cp0_register(CP0_PRID);
+       switch (mips_cpu.processor_id & 0xff00) {
        case PRID_IMP_R2000:
-               mips_cputype = CPU_R2000;
+               mips_cpu.cputype = CPU_R2000;
+               mips_cpu.isa_level = MIPS_CPU_ISA_I;
+               mips_cpu.options = MIPS_CPU_TLB;
+               mips_cpu.tlbsize = 64;
                break;
        case PRID_IMP_R3000:
-               if((prid & 0xff) == PRID_REV_R3000A)
-                       if(cpu_has_confreg())
-                               mips_cputype = CPU_R3081E;
+               if ((mips_cpu.processor_id & 0xff) == PRID_REV_R3000A)
+                       if (cpu_has_confreg())
+                               mips_cpu.cputype = CPU_R3081E;
                        else
-                               mips_cputype = CPU_R3000A;
+                               mips_cpu.cputype = CPU_R3000A;
                else
-                        mips_cputype = CPU_R3000;
+                        mips_cpu.cputype = CPU_R3000;
+               mips_cpu.isa_level = MIPS_CPU_ISA_I;
+               mips_cpu.options = MIPS_CPU_TLB;
+               mips_cpu.tlbsize = 64;
                break;
        case PRID_IMP_R4000:
-               if((prid & 0xff) == PRID_REV_R4400)
-                       mips_cputype = CPU_R4400SC;
+               if ((mips_cpu.processor_id & 0xff) == PRID_REV_R4400)
+                       mips_cpu.cputype = CPU_R4400SC;
                else
-                       mips_cputype = CPU_R4000SC;
+                       mips_cpu.cputype = CPU_R4000SC;
+               mips_cpu.isa_level = MIPS_CPU_ISA_III;
+               mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+                                  MIPS_CPU_WATCH | MIPS_CPU_VCE;
+               mips_cpu.tlbsize = 48;
                break;
        case PRID_IMP_R4600:
-               mips_cputype = CPU_R4600;
+               mips_cpu.cputype = CPU_R4600;
+               mips_cpu.isa_level = MIPS_CPU_ISA_III;
+               mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU;
+               mips_cpu.tlbsize = 48;
                break;
+/*
+ * This processor doesn't have an MMU, so it's not "real easy" to
+ * run Linux on it. It is left purely for documentation.
+ *
        case PRID_IMP_R4650:
-               mips_cputype = CPU_R4650;
+               mips_cpu.cputype = CPU_R4650;
+               mips_cpu.isa_level = MIPS_CPU_ISA_III;
+               mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU;
+               mips_cpu.tlbsize = 48;
+               break;
+ */
+       case PRID_IMP_R3912:
+               mips_cpu.cputype = CPU_R3912;
+               mips_cpu.isa_level = MIPS_CPU_ISA_I;
+               mips_cpu.options = MIPS_CPU_TLB;
+               mips_cpu.tlbsize = 32;
                break;
        case PRID_IMP_R4700:
-               mips_cputype = CPU_R4700;
+               mips_cpu.cputype = CPU_R4700;
+               mips_cpu.isa_level = MIPS_CPU_ISA_III;
+               mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
+               mips_cpu.tlbsize = 48;
                break;
        case PRID_IMP_R5000:
-               mips_cputype = CPU_R5000;
+               mips_cpu.cputype = CPU_R5000;
+               mips_cpu.isa_level = MIPS_CPU_ISA_IV; 
+               mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
+               mips_cpu.tlbsize = 48;
+               break;
+       case PRID_IMP_R5432:
+               mips_cpu.cputype = CPU_R5432;
+               mips_cpu.isa_level = MIPS_CPU_ISA_IV; 
+               mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
+               mips_cpu.tlbsize = 48;
                break;
        case PRID_IMP_NEVADA:
-               mips_cputype = CPU_NEVADA;
+               mips_cpu.cputype = CPU_NEVADA;
+               mips_cpu.isa_level = MIPS_CPU_ISA_IV; 
+               mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | 
+                                  MIPS_CPU_DIVEC;
+               mips_cpu.tlbsize = 48;
+               mips_cpu.icache.ways = 2;
+               mips_cpu.dcache.ways = 2;
                break;
        case PRID_IMP_R6000:
-               mips_cputype = CPU_R6000;
+               mips_cpu.cputype = CPU_R6000;
+               mips_cpu.isa_level = MIPS_CPU_ISA_II;
+               mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU;
+               mips_cpu.tlbsize = 32;
                break;
        case PRID_IMP_R6000A:
-               mips_cputype = CPU_R6000A;
+               mips_cpu.cputype = CPU_R6000A;
+               mips_cpu.isa_level = MIPS_CPU_ISA_II;
+               mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU;
+               mips_cpu.tlbsize = 32;
+               break;
+       case PRID_IMP_RM7000:
+               mips_cpu.cputype = CPU_RM7000;
+               mips_cpu.isa_level = MIPS_CPU_ISA_IV;
+               mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
                break;
        case PRID_IMP_R8000:
-               mips_cputype = CPU_R8000;
+               mips_cpu.cputype = CPU_R8000;
+               mips_cpu.isa_level = MIPS_CPU_ISA_IV;
+               mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+                                  MIPS_CPU_FPU | MIPS_CPU_32FPR;
+               mips_cpu.tlbsize = 384;      /* has wierd TLB: 3-way x 128 */
                break;
        case PRID_IMP_R10000:
-               mips_cputype = CPU_R10000;
+               mips_cpu.cputype = CPU_R10000;
+               mips_cpu.isa_level = MIPS_CPU_ISA_IV;
+               mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
+                                  MIPS_CPU_FPU | MIPS_CPU_32FPR | 
+                                  MIPS_CPU_COUNTER | MIPS_CPU_WATCH;
+               mips_cpu.tlbsize = 64;
                break;
-       case PRID_IMP_RM7000:
-               mips_cputype = CPU_R5000;
+#ifdef CONFIG_CPU_MIPS32
+       case PRID_IMP_4KC:
+               mips_cpu.cputype = CPU_4KC;
+               mips_cpu.isa_level = MIPS_CPU_ISA_M32;
+               mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
+                                  MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | 
+                                  MIPS_CPU_DIVEC | MIPS_CPU_WATCH;
+               config1 = read_mips32_cp0_config1();
+               if (config1 & (1 << 3))
+                       mips_cpu.options |= MIPS_CPU_WATCH;
+               if (config1 & (1 << 2))
+                       mips_cpu.options |= MIPS_CPU_MIPS16;
+               if (config1 & 1)
+                       mips_cpu.options |= MIPS_CPU_FPU;
+               mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT;
                break;
+       case PRID_IMP_5KC:
+               mips_cpu.cputype = CPU_5KC;
+               mips_cpu.isa_level = MIPS_CPU_ISA_M64;
+               mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
+                                  MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | 
+                                  MIPS_CPU_DIVEC | MIPS_CPU_WATCH;
+               config1 = read_mips32_cp0_config1();
+               if (config1 & (1 << 3))
+                       mips_cpu.options |= MIPS_CPU_WATCH;
+               if (config1 & (1 << 2))
+                       mips_cpu.options |= MIPS_CPU_MIPS16;
+               if (config1 & 1)
+                       mips_cpu.options |= MIPS_CPU_FPU;
+               mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT;
+               break;
+#endif
        default:
-               mips_cputype = CPU_UNKNOWN;
+               mips_cpu.cputype = CPU_UNKNOWN;
        }
 }
 
-asmlinkage void __init init_arch(int argc, char **argv, char **envp, int *prom_vec)
+asmlinkage void __init
+init_arch(int argc, char **argv, char **envp, int *prom_vec)
 {
        unsigned int s;
 
@@ -232,18 +340,13 @@ asmlinkage void __init init_arch(int argc, char **argv, char **envp, int *prom_v
         */
        loadmmu();
 
-       /* Disable coprocessors */
+       /* Disable coprocessors and set FPU for 16 FPRs */
        s = read_32bit_cp0_register(CP0_STATUS);
-       s &= ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX);
+       s &= ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX|ST0_FR);
        s |= ST0_CU0;
        write_32bit_cp0_register(CP0_STATUS, s);
 
-       /*
-        * Main should never return here, but
-        * just in case, we know what happens.
-        */
-       for(;;)
-               start_kernel();
+       start_kernel();
 }
 
 static void __init default_irq_setup(void)
index b2d2a6a..b91e8a0 100644 (file)
@@ -31,8 +31,9 @@
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
-extern asmlinkage int save_fp_context(struct sigcontext *sc);
-extern asmlinkage int restore_fp_context(struct sigcontext *sc);
+
+extern asmlinkage int (*save_fp_context)(struct sigcontext *sc);
+extern asmlinkage int (*restore_fp_context)(struct sigcontext *sc);
 
 extern asmlinkage void syscall_trace(void);
 
@@ -74,12 +75,12 @@ int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
-asmlinkage inline int
-sys_sigsuspend(struct pt_regs regs)
+save_static_function(sys_sigsuspend);
+static_unused int
+_sys_sigsuspend(struct pt_regs regs)
 {
        sigset_t *uset, saveset, newset;
 
-       save_static(&regs);
        uset = (sigset_t *) regs.regs[4];
        if (copy_from_user(&newset, uset, sizeof(sigset_t)))
                return -EFAULT;
@@ -101,14 +102,14 @@ sys_sigsuspend(struct pt_regs regs)
        }
 }
 
-asmlinkage int
-sys_rt_sigsuspend(struct pt_regs regs)
+
+save_static_function(sys_rt_sigsuspend);
+static_unused int
+_sys_rt_sigsuspend(struct pt_regs regs)
 {
        sigset_t *unewset, saveset, newset;
         size_t sigsetsize;
 
-       save_static(&regs);
-
        /* XXX Don't preclude handling different sized sigset_t's.  */
        sigsetsize = regs.regs[5];
        if (sigsetsize != sizeof(sigset_t))
@@ -353,7 +354,7 @@ setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
        err |= __put_user(owned_fp, &sc->sc_ownedfp);
 
        if (current->used_math) {       /* fp is active.  */
-               set_cp0_status(ST0_CU1, ST0_CU1);
+               set_cp0_status(ST0_CU1);
                err |= save_fp_context(sc);
                last_task_used_math = NULL;
                regs->cp0_status &= ~ST0_CU1;
index 82cd94f..3bbbb23 100644 (file)
@@ -7,6 +7,9 @@
  * Modified for R3000 by Paul M. Antoine, 1995, 1996
  * Complete output from die() by Ulf Carlsson, 1998
  * Copyright (C) 1999 Silicon Graphics, Inc.
+ *
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
  */
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 
+#include <asm/bootinfo.h>
 #include <asm/branch.h>
+#include <asm/cpu.h>
 #include <asm/cachectl.h>
+#include <asm/inst.h>
 #include <asm/jazz.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
-#include <asm/bootinfo.h>
+#include <asm/siginfo.h>
 #include <asm/watch.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -51,13 +57,15 @@ extern asmlinkage void handle_ov(void);
 extern asmlinkage void handle_tr(void);
 extern asmlinkage void handle_fpe(void);
 extern asmlinkage void handle_watch(void);
+extern asmlinkage void handle_mcheck(void);
 extern asmlinkage void handle_reserved(void);
 
+extern int fpu_emulator_cop1Handler(int, struct pt_regs *);
+
 static char *cpu_names[] = CPU_NAMES;
 
 char watch_available = 0;
 char dedicated_iv_available = 0;
-char vce_available = 0;
 
 void (*ibe_board_handler)(struct pt_regs *regs);
 void (*dbe_board_handler)(struct pt_regs *regs);
@@ -308,9 +316,11 @@ int unregister_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31))
  */
 void do_fpe(struct pt_regs *regs, unsigned long fcr31)
 {
-       unsigned long pc;
-       unsigned int insn;
-       extern void simfp(unsigned int);
+
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+       if(!(mips_cpu.options & MIPS_CPU_FPU))
+               panic("Floating Point Exception with No FPU");
+#endif
 
 #ifdef CONFIG_MIPS_FPE_MODULE
        if (fpe_handler != NULL) {
@@ -318,12 +328,52 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31)
                return;
        }
 #endif
-       if (fcr31 & 0x20000) {
+
+       if (fcr31 & FPU_CSR_UNI_X) {
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+               extern void save_fp(struct task_struct *);
+               extern void restore_fp(struct task_struct *);
+               int sig;
+               /*
+                * Unimplemented operation exception.  If we've got the
+                * Full software emulator on-board, let's use it...
+                *
+                * Force FPU to dump state into task/thread context.
+                * We're moving a lot of data here for what is probably
+                * a single instruction, but the alternative is to 
+                * pre-decode the FP register operands before invoking
+                * the emulator, which seems a bit extreme for what
+                * should be an infrequent event.
+                */
+               save_fp(current);
+       
+               /* Run the emulator */
+               sig = fpu_emulator_cop1Handler(0, regs);
+
+               /* 
+                * We can't allow the emulated instruction to leave the
+                * Unimplemented Operation bit set in the FCR31 fp-register.
+                */
+               current->thread.fpu.soft.sr &= ~FPU_CSR_UNI_X;
+
+               /* Restore the hardware register state */
+               restore_fp(current);
+
+               /* If something went wrong, signal */
+               if (sig)
+                       force_sig(sig, current);
+#else
+               /* Else use mini-emulator */
+
+               extern void simfp(int);
+               unsigned long pc;
+               unsigned int insn;
+
                /* Retry instruction with flush to zero ...  */
                if (!(fcr31 & (1<<24))) {
                        printk("Setting flush to zero for %s.\n",
                               current->comm);
-                       fcr31 &= ~0x20000;
+                       fcr31 &= ~FPU_CSR_UNI_X;
                        fcr31 |= (1<<24);
                        __asm__ __volatile__(
                                "ctc1\t%0,$31"
@@ -332,20 +382,26 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31)
                        return;
                }
                pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0);
-               if (get_user(insn, (unsigned int *)pc)) {
+               if(pc & 0x80000000) insn = *(unsigned int *)pc;
+               else if (get_user(insn, (unsigned int *)pc)) {
                        /* XXX Can this happen?  */
                        force_sig(SIGSEGV, current);
                }
 
                printk(KERN_DEBUG "Unimplemented exception for insn %08x at 0x%08lx in %s.\n",
                       insn, regs->cp0_epc, current->comm);
-               simfp(insn);
+               simfp(MIPSInst(insn));
+               compute_return_epc(regs);
+#endif /* CONFIG_MIPS_FPU_EMULATOR */
+
+               return;
        }
 
        if (compute_return_epc(regs))
                return;
-       //force_sig(SIGFPE, current);
-       printk(KERN_DEBUG "Should send SIGFPE to %s\n", current->comm);
+
+       force_sig(SIGFPE, current);
+       printk(KERN_DEBUG "Sent send SIGFPE to %s\n", current->comm);
 }
 
 static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
@@ -382,12 +438,28 @@ void do_bp(struct pt_regs *regs)
         * (A short test says that IRIX 5.3 sends SIGTRAP for all break
         * insns, even for break codes that indicate arithmetic failures.
         * Weird ...)
+        * But should we continue the brokenness???  --macro
         */
-       force_sig(SIGTRAP, current);
+       switch (bcode) {
+       case 6:
+       case 7:
+               if (bcode == 7)
+                       info.si_code = FPE_INTDIV;
+               else
+                       info.si_code = FPE_INTOVF;
+               info.si_signo = SIGFPE;
+               info.si_errno = 0;
+               info.si_addr = (void *)compute_return_epc(regs);
+               force_sig_info(SIGFPE, &info, current);
+               break;
+       default:
+               force_sig(SIGTRAP, current);
+       }
 }
 
 void do_tr(struct pt_regs *regs)
 {
+       siginfo_t info;
        unsigned int opcode, bcode;
 
        if (get_insn_opcode(regs, &opcode))
@@ -398,8 +470,23 @@ void do_tr(struct pt_regs *regs)
         * (A short test says that IRIX 5.3 sends SIGTRAP for all break
         * insns, even for break codes that indicate arithmetic failures.
         * Weird ...)
+        * But should we continue the brokenness???  --macro
         */
-       force_sig(SIGTRAP, current);
+       switch (bcode) {
+       case 6:
+       case 7:
+               if (bcode == 7)
+                       info.si_code = FPE_INTDIV;
+               else
+                       info.si_code = FPE_INTOVF;
+               info.si_signo = SIGFPE;
+               info.si_errno = 0;
+               info.si_addr = (void *)compute_return_epc(regs);
+               force_sig_info(SIGFPE, &info, current);
+               break;
+       default:
+               force_sig(SIGTRAP, current);
+       }
 }
 
 #if !defined(CONFIG_CPU_HAS_LLSC)
@@ -520,11 +607,33 @@ void do_cpu(struct pt_regs *regs)
        unsigned int cpid;
        extern void lazy_fpu_switch(void*);
        extern void init_fpu(void);
-
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+       void fpu_emulator_init_fpu(void);
+       int sig;
+#endif
        cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
        if (cpid != 1)
                goto bad_cid;
 
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+       if(!(mips_cpu.options & MIPS_CPU_FPU)) {
+           if (last_task_used_math != current) {
+               if(!current->used_math) {
+                   fpu_emulator_init_fpu();
+                   current->used_math = 1;
+               }
+           }
+           sig = fpu_emulator_cop1Handler(0, regs);
+           last_task_used_math = current;
+           if(sig) {
+               force_sig(sig, current);
+           }
+           return;
+       }
+#else
+       if(!(mips_cpu.options & MIPS_CPU_FPU)) goto bad_cid;
+#endif
+
        regs->cp0_status |= ST0_CU1;
        if (last_task_used_math == current)
                return;
index 52331d2..b516963 100644 (file)
@@ -9,26 +9,23 @@
 
 L_TARGET = lib.a
 
-L_OBJS = csum_partial.o csum_partial_copy.o \
-          rtc-std.o rtc-no.o memcpy.o memset.o  watch.o\
-          strlen_user.o strncpy_user.o strnlen_user.o
+obj-y                          += csum_partial.o csum_partial_copy.o \
+                                  rtc-std.o rtc-no.o memcpy.o memset.o \
+                                  watch.o strlen_user.o strncpy_user.o \
+                                  strnlen_user.o
 
 ifdef CONFIG_CPU_R3000
-  L_OBJS += r3k_dump_tlb.o 
+  obj-y        += r3k_dump_tlb.o 
 else
-  L_OBJS += dump_tlb.o 
+  ifdef CONFIG_CPU_R3912
+    obj-y      += r3k_dump_tlb.o 
+  else
+    obj-y      += dump_tlb.o 
+  endif
 endif
 
-ifdef CONFIG_BLK_DEV_FD
-  L_OBJS += floppy-no.o floppy-std.o
-endif
-
-ifdef CONFIG_IDE
-  L_OBJS += ide-std.o ide-no.o
-endif
-
-ifdef CONFIG_PC_KEYB
-  L_OBJS += kbd-std.o kbd-no.o
-endif
+obj-$(CONFIG_BLK_DEV_FD)       += floppy-no.o floppy-std.o
+obj-$(CONFIG_IDE)              += ide-std.o ide-no.o
+obj-$(CONFIG_PC_KEYB)          += kbd-std.o kbd-no.o
 
 include $(TOPDIR)/Rules.make
index 8e7e69e..3a50c89 100644 (file)
@@ -8,6 +8,7 @@
  *
  * Copyright (C) 1998, 1999 by Ralf Baechle
  */
+#include <linux/config.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/pc_keyb.h>
 
 static void std_kbd_request_region(void)
 {
+#ifdef CONFIG_MIPS_ITE8172
+       printk("std_kbd_request_region\n");
+       request_region(0x14000060, 16, "keyboard");
+#else
        request_region(0x60, 16, "keyboard");
+#endif
 }
 
 static int std_kbd_request_irq(void (*handler)(int, void *, struct pt_regs *))
 {
+       printk("std_kbd_request_irq\n");
        return request_irq(KEYBOARD_IRQ, handler, 0, "keyboard", NULL);
 }
 
diff --git a/arch/mips/math-emu/Makefile b/arch/mips/math-emu/Makefile
new file mode 100644 (file)
index 0000000..9a6b054
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# Makefile for the Linux/MIPS kernel FPU emulation.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.o:
+       $(CC) $(CFLAGS) -c $< -o $*.o
+
+EXTRA_ASFLAGS = -mips2 -mcpu=r4000
+
+O_TARGET:= fpu_emulator.o
+
+obj-y  := cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \
+          ieee754xcpt.o dp_frexp.o dp_modf.o dp_div.o dp_mul.o dp_sub.o \
+          dp_add.o dp_fsp.o dp_cmp.o dp_logb.o dp_scalb.o dp_simple.o \
+          dp_tint.o dp_fint.o dp_tlong.o dp_flong.o sp_frexp.o sp_modf.o \
+          sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \
+          sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \
+          dp_sqrt.o sp_sqrt.o kernel_linkage.o
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
new file mode 100644 (file)
index 0000000..b0147eb
--- /dev/null
@@ -0,0 +1,1811 @@
+/*
+ * cp1emu.c: a MIPS coprocessor 1 (fpu) instruction emulator
+ * 
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * A complete emulator for MIPS coprocessor 1 instructions.  This is
+ * required for #float(switch) or #float(trap), where it catches all
+ * COP1 instructions via the "CoProcessor Unusable" exception.  
+ *
+ * More surprisingly it is also required for #float(ieee), to help out
+ * the hardware fpu at the boundaries of the IEEE-754 representation
+ * (denormalised values, infinities, underflow, etc).  It is made
+ * quite nasty because emulation of some non-COP1 instructions is
+ * required, e.g. in branch delay slots.
+ * 
+ * Notes: 
+ *  1) the IEEE754 library (-le) performs the actual arithmetic;
+ *  2) if you know that you won't have an fpu, then you'll get much 
+ *     better performance by compiling with -msoft-float!  */
+
+/**************************************************************************
+ *  Nov 7, 2000
+ *  Massive changes to integrate with Linux kernel.
+ *
+ *  Replace use of kernel data area with use of user stack 
+ *  for execution of instructions in branch delay slots.
+ *
+ *  Replace use of static kernel variables with thread_struct elements.
+ *
+ *  Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000  MIPS Technologies, Inc.  All rights reserved.
+ *************************************************************************/
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
+#include <asm/asm.h>
+#include <asm/branch.h>
+#include <asm/byteorder.h>
+#include <asm/inst.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+
+#include <asm/fpu_emulator.h>
+
+#include "ieee754.h"
+
+/* Strap kernel emulator for full MIPS IV emulation */
+
+#ifdef __mips
+#undef __mips
+#endif
+#define __mips 4
+
+typedef void *vaddr_t;
+
+/* Function which emulates the instruction in a branch delay slot. */
+
+static int mips_dsemul(struct pt_regs *, mips_instruction, vaddr_t);
+
+/* Function which emulates a floating point instruction. */
+
+static int fpu_emu(struct pt_regs *, struct mips_fpu_soft_struct *,
+        mips_instruction);
+
+#if __mips >= 4 && __mips != 32
+static int fpux_emu(struct pt_regs *,
+                   struct mips_fpu_soft_struct *, mips_instruction);
+#endif
+
+/* Further private data for which no space exists in mips_fpu_soft_struct */
+
+struct mips_fpu_emulator_private fpuemuprivate;
+
+/* Control registers */
+
+#define FPCREG_RID     0       /* $0  = revision id */
+#define FPCREG_CSR     31      /* $31 = csr */
+
+/* Convert Mips rounding mode (0..3) to IEEE library modes. */
+static const unsigned char ieee_rm[4] = {
+       IEEE754_RN, IEEE754_RZ, IEEE754_RU, IEEE754_RD
+};
+
+#if __mips >= 4
+/* convert condition code register number to csr bit */
+static const unsigned int fpucondbit[8] = {
+       FPU_CSR_COND0,
+       FPU_CSR_COND1,
+       FPU_CSR_COND2,
+       FPU_CSR_COND3,
+       FPU_CSR_COND4,
+       FPU_CSR_COND5,
+       FPU_CSR_COND6,
+       FPU_CSR_COND7
+};
+#endif
+
+
+
+/* 
+ * Redundant with logic already in kernel/branch.c,
+ * embedded in compute_return_epc.  At some point,
+ * a single subroutine should be used across both
+ * modules.
+ */
+static int isBranchInstr(mips_instruction * i)
+{
+       switch (MIPSInst_OPCODE(*i)) {
+       case spec_op:
+               switch (MIPSInst_FUNC(*i)) {
+               case jalr_op:
+               case jr_op:
+                       return 1;
+               }
+               break;
+
+       case bcond_op:
+               switch (MIPSInst_RT(*i)) {
+               case bltz_op:
+               case bgez_op:
+               case bltzl_op:
+               case bgezl_op:
+               case bltzal_op:
+               case bgezal_op:
+               case bltzall_op:
+               case bgezall_op:
+                       return 1;
+               }
+               break;
+
+       case j_op:
+       case jal_op:
+       case jalx_op:
+       case beq_op:
+       case bne_op:
+       case blez_op:
+       case bgtz_op:
+       case beql_op:
+       case bnel_op:
+       case blezl_op:
+       case bgtzl_op:
+               return 1;
+
+       case cop0_op:
+       case cop1_op:
+       case cop2_op:
+       case cop1x_op:
+               if (MIPSInst_RS(*i) == bc_op)
+                       return 1;
+               break;
+       }
+
+       return 0;
+}
+
+#define REG_TO_VA (vaddr_t)
+#define VA_TO_REG (unsigned long)
+
+static unsigned long
+mips_get_word(struct pt_regs *xcp, void *va, int *perr)
+{
+       unsigned long temp;
+
+       if (!user_mode(xcp)) {
+               *perr = 0;
+               return (*(unsigned long *) va);
+       } else {
+               /* Use kernel get_user() macro */
+               *perr = (int) get_user(temp, (unsigned long *) va);
+               return temp;
+       }
+}
+
+static unsigned long long
+mips_get_dword(struct pt_regs *xcp, void *va, int *perr)
+{
+       unsigned long long temp;
+
+       if (!user_mode(xcp)) {
+               *perr = 0;
+               return (*(unsigned long long *) va);
+       } else {
+               /* Use kernel get_user() macro */
+               *perr = (int) get_user(temp, (unsigned long long *) va);
+               return temp;
+       }
+}
+
+static int mips_put_word(struct pt_regs *xcp, void *va, unsigned long val)
+{
+       if (!user_mode(xcp)) {
+               *(unsigned long *) va = val;
+               return 0;
+       } else {
+               /* Use kernel get_user() macro */
+               return (int) put_user(val, (unsigned long *) va);
+       }
+}
+
+static int mips_put_dword(struct pt_regs *xcp, void *va, long long val)
+{
+       if (!user_mode(xcp)) {
+               *(unsigned long long *) va = val;
+               return 0;
+       } else {
+               /* Use kernel get_user() macro */
+               return (int) put_user(val, (unsigned long long *) va);
+       }
+}
+
+
+/*
+ * In the Linux kernel, we support selection of FPR format on the
+ * basis of the Status.FR bit.  This does imply that, if a full 32
+ * FPRs are desired, there needs to be a flip-flop that can be written
+ * to one at that bit position.  In any case, normal MIPS ABI uses
+ * only the even FPRs (Status.FR = 0).
+ */
+
+#define CP0_STATUS_FR_SUPPORT
+
+/*
+ * Emulate the single floating point instruction pointed at by EPC.
+ * Two instructions if the instruction is in a branch delay slot.
+ */
+
+static int
+cop1Emulate(int xcptno, struct pt_regs *xcp,
+           struct mips_fpu_soft_struct *ctx)
+{
+       mips_instruction ir;
+       vaddr_t emulpc;
+       vaddr_t contpc;
+       unsigned int cond;
+       int err = 0;
+
+
+       ir = mips_get_word(xcp, REG_TO_VA xcp->cp0_epc, &err);
+       if (err) {
+               fpuemuprivate.stats.errors++;
+               return SIGBUS;
+       }
+
+       /* XXX NEC Vr54xx bug workaround */
+       if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir))
+               xcp->cp0_cause &= ~CAUSEF_BD;
+
+       if (xcp->cp0_cause & CAUSEF_BD) {
+               /*
+                * The instruction to be emulated is in a branch delay slot
+                * which means that we have to  emulate the branch instruction
+                * BEFORE we do the cop1 instruction. 
+                *
+                * This branch could be a COP1 branch, but in that case we
+                * would have had a trap for that instruction, and would not
+                * come through this route.
+                *
+                * Linux MIPS branch emulator operates on context, updating the
+                * cp0_epc.
+                */
+               emulpc = REG_TO_VA(xcp->cp0_epc + 4);   /* Snapshot emulation target */
+
+               if (__compute_return_epc(xcp)) {
+#ifdef CP1DBG
+                       printk("failed to emulate branch at %p\n",
+                                   REG_TO_VA(xcp->cp0_epc));
+#endif
+                       return SIGILL;;
+               }
+               ir = mips_get_word(xcp, emulpc, &err);
+               if (err) {
+                       fpuemuprivate.stats.errors++;
+                       return SIGBUS;
+               }
+               contpc = REG_TO_VA xcp->cp0_epc;
+       } else {
+               emulpc = REG_TO_VA xcp->cp0_epc;
+               contpc = REG_TO_VA xcp->cp0_epc + 4;
+       }
+
+      emul:
+       fpuemuprivate.stats.emulated++;
+       switch (MIPSInst_OPCODE(ir)) {
+#ifdef CP0_STATUS_FR_SUPPORT
+               /* R4000+ 64-bit fpu registers */
+#ifndef SINGLE_ONLY_FPU
+       case ldc1_op:
+               {
+                       void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+                           + MIPSInst_SIMM(ir);
+                       int ft = MIPSInst_RT(ir);
+                       if (!(xcp->cp0_status & ST0_FR))
+                               ft &= ~1;
+                       ctx->regs[ft] = mips_get_dword(xcp, va, &err);
+                       fpuemuprivate.stats.loads++;
+                       if (err) {
+                               fpuemuprivate.stats.errors++;
+                               return SIGBUS;
+                       }
+               }
+               break;
+
+       case sdc1_op:
+               {
+                       void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+                           + MIPSInst_SIMM(ir);
+                       int ft = MIPSInst_RT(ir);
+                       if (!(xcp->cp0_status & ST0_FR))
+                               ft &= ~1;
+                       fpuemuprivate.stats.stores++;
+                       if (mips_put_dword(xcp, va, ctx->regs[ft])) {
+                               fpuemuprivate.stats.errors++;
+                               return SIGBUS;
+                       }
+               }
+               break;
+#endif
+
+       case lwc1_op:
+               {
+                       void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+                           + MIPSInst_SIMM(ir);
+                       fpureg_t val;
+                       int ft = MIPSInst_RT(ir);
+                       fpuemuprivate.stats.loads++;
+                       val = mips_get_word(xcp, va, &err);
+                       if (err) {
+                               fpuemuprivate.stats.errors++;
+                               return SIGBUS;
+                       }
+                       if (xcp->cp0_status & ST0_FR) {
+                               /* load whole register */
+                               ctx->regs[ft] = val;
+                       } else if (ft & 1) {
+                               /* load to m.s. 32 bits */
+#ifdef SINGLE_ONLY_FPU
+                               /* illegal register in single-float mode */
+                               return SIGILL;
+#else
+                               ctx->regs[(ft & ~1)] &= 0xffffffff;
+                               ctx->regs[(ft & ~1)] |= val << 32;
+#endif
+                       } else {
+                               /* load to l.s. 32 bits */
+                               ctx->regs[ft] &= ~0xffffffffLL;
+                               ctx->regs[ft] |= val;
+                       }
+               }
+               break;
+
+       case swc1_op:
+               {
+                       void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+                           + MIPSInst_SIMM(ir);
+                       unsigned int val;
+                       int ft = MIPSInst_RT(ir);
+                       fpuemuprivate.stats.stores++;
+                       if (xcp->cp0_status & ST0_FR) {
+                               /* store whole register */
+                               val = ctx->regs[ft];
+                       } else if (ft & 1) {
+#ifdef SINGLE_ONLY_FPU
+                               /* illegal register in single-float mode */
+                               return SIGILL;
+#else
+                               /* store from m.s. 32 bits */
+                               val = ctx->regs[(ft & ~1)] >> 32;
+#endif
+                       } else {
+                               /* store from l.s. 32 bits */
+                               val = ctx->regs[ft];
+                       }
+                       if (mips_put_word(xcp, va, val)) {
+                               fpuemuprivate.stats.errors++;
+                               return SIGBUS;
+                       }
+               }
+               break;
+#else                          /* old 32-bit fpu registers */
+       case lwc1_op:
+               {
+                       void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+                           + MIPSInst_SIMM(ir);
+                       ctx->regs[MIPSInst_RT(ir)] =
+                           mips_get_word(xcp, va, &err);
+                       fpuemuprivate.stats.loads++;
+                       if (err) {
+                               fpuemuprivate.stats.errors++;
+                               return SIGBUS;
+                       }
+               }
+               break;
+
+       case swc1_op:
+               {
+                       void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+                           + MIPSInst_SIMM(ir);
+                       fpuemuprivate.stats.stores++;
+                       if (mips_put_word
+                           (xcp, va, ctx->regs[MIPSInst_RT(ir)])) {
+                               fpuemuprivate.stats.errors++;
+                               return SIGBUS;
+                       }
+               }
+               break;
+       case ldc1_op:
+               {
+                       void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+                           + MIPSInst_SIMM(ir);
+                       unsigned int rt = MIPSInst_RT(ir) & ~1;
+                       int errs = 0;
+                       fpuemuprivate.stats.loads++;
+#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
+                       ctx->regs[rt + 1] =
+                           mips_get_word(xcp, va + 0, &err);
+                       errs += err;
+                       ctx->regs[rt + 0] =
+                           mips_get_word(xcp, va + 4, &err);
+                       errs += err;
+#else
+                       ctx->regs[rt + 0] =
+                           mips_get_word(xcp, va + 0, &err);
+                       errs += err;
+                       ctx->regs[rt + 1] =
+                           mips_get_word(xcp, va + 4, &err);
+                       errs += err;
+#endif
+                       if (err)
+                               return SIGBUS;
+               }
+               break;
+
+       case sdc1_op:
+               {
+                       void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+                           + MIPSInst_SIMM(ir);
+                       unsigned int rt = MIPSInst_RT(ir) & ~1;
+                       fpuemuprivate.stats.stores++;
+#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
+                       if (mips_put_word(xcp, va + 0, ctx->regs[rt + 1]))
+                               return SIGBUS;
+                       if (mips_put_word(xcp, va + 4, ctx->regs[rt + 0]))
+                               return SIGBUS;
+#else
+                       if (mips_put_word(xcp, va + 0, ctx->regs[rt + 0]))
+                               return SIGBUS;
+                       if (mips_put_word(xcp, va + 4, ctx->regs[rt + 1]))
+                               return SIGBUS;
+#endif
+               }
+               break;
+#endif
+
+       case cop1_op:
+               switch (MIPSInst_RS(ir)) {
+
+#ifdef CP0_STATUS_FR_SUPPORT
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+               case dmfc_op:
+                       /* copregister fs -> gpr[rt] */
+                       if (MIPSInst_RT(ir) != 0) {
+                               int fs = MIPSInst_RD(ir);
+                               if (!(xcp->cp0_status & ST0_FR))
+                                       fs &= ~1;
+                               xcp->regs[MIPSInst_RT(ir)] = ctx->regs[fs];
+                       }
+                       break;
+
+               case dmtc_op:
+                       /* copregister fs <- rt */
+                       {
+                               fpureg_t value;
+                               int fs = MIPSInst_RD(ir);
+                               if (!(xcp->cp0_status & ST0_FR))
+                                       fs &= ~1;
+                               value =
+                                   (MIPSInst_RT(ir) ==
+                                    0) ? 0 : xcp->regs[MIPSInst_RT(ir)];
+                               ctx->regs[fs] = value;
+                       }
+                       break;
+#endif
+
+               case mfc_op:
+                       /* copregister rd -> gpr[rt] */
+                       if (MIPSInst_RT(ir) != 0) {
+                               /* default value from l.s. 32 bits */
+                               int value = ctx->regs[MIPSInst_RD(ir)];
+                               if (MIPSInst_RD(ir) & 1) {
+#ifdef SINGLE_ONLY_FPU
+                                       /* illegal register in single-float mode */
+                                       return SIGILL;
+#else
+                                       if (!(xcp->cp0_status & ST0_FR)) {
+                                               /* move from m.s. 32 bits */
+                                               value =
+                                                   ctx->
+                                                   regs[MIPSInst_RD(ir) &
+                                                        ~1] >> 32;
+                                       }
+#endif
+                               }
+                               xcp->regs[MIPSInst_RT(ir)] = value;
+                       }
+                       break;
+
+               case mtc_op:
+                       /* copregister rd <- rt */
+                       {
+                               fpureg_t value;
+                               if (MIPSInst_RT(ir) == 0)
+                                       value = 0;
+                               else
+                                       value =
+                                           (unsigned int) xcp->
+                                           regs[MIPSInst_RT(ir)];
+                               if (MIPSInst_RD(ir) & 1) {
+#ifdef SINGLE_ONLY_FPU
+                                       /* illegal register in single-float mode */
+                                       return SIGILL;
+#else
+                                       if (!(xcp->cp0_status & ST0_FR)) {
+                                               /* move to m.s. 32 bits */
+                                               ctx->
+                                                   regs[
+                                                        (MIPSInst_RD(ir) &
+                                                         ~1)] &=
+                                                   0xffffffff;
+                                               ctx->
+                                                   regs[
+                                                        (MIPSInst_RD(ir) &
+                                                         ~1)] |=
+                                                   value << 32;
+                                               break;
+                                       }
+#endif
+                               }
+                               /* move to l.s. 32 bits */
+                               ctx->regs[MIPSInst_RD(ir)] &=
+                                   ~0xffffffffLL;
+                               ctx->regs[MIPSInst_RD(ir)] |= value;
+                       }
+                       break;
+#else
+
+               case mfc_op:
+                       /* copregister rd -> gpr[rt] */
+                       if (MIPSInst_RT(ir) != 0) {
+                               unsigned value =
+                                   ctx->regs[MIPSInst_RD(ir)];
+                               xcp->regs[MIPSInst_RT(ir)] = value;
+                       }
+                       break;
+
+               case mtc_op:
+                       /* copregister rd <- rt */
+                       {
+                               unsigned value;
+                               value =
+                                   (MIPSInst_RT(ir) ==
+                                    0) ? 0 : xcp->regs[MIPSInst_RT(ir)];
+                               ctx->regs[MIPSInst_RD(ir)] = value;
+                       }
+                       break;
+#endif
+
+               case cfc_op:
+                       /* cop control register rd -> gpr[rt] */
+                       {
+                               unsigned value;
+
+                               if (MIPSInst_RD(ir) == FPCREG_CSR) {
+                                       value = ctx->sr;
+#ifdef CSRTRACE
+                                       printk
+                                           ("%p gpr[%d]<-csr=%08x\n",
+                                            REG_TO_VA(xcp->cp0_epc),
+                                            MIPSInst_RT(ir), value);
+#endif
+                               } else if (MIPSInst_RD(ir) == FPCREG_RID)
+                                       value = 0;
+                               else
+                                       value = 0;
+                               if (MIPSInst_RT(ir))
+                                       xcp->regs[MIPSInst_RT(ir)] = value;
+                       }
+                       break;
+
+               case ctc_op:
+                       /* copregister rd <- rt */
+                       {
+                               unsigned value;
+
+                               if (MIPSInst_RT(ir) == 0)
+                                       value = 0;
+                               else
+                                       value = xcp->regs[MIPSInst_RT(ir)];
+
+                               /* we only have one writable control reg
+                                */
+                               if (MIPSInst_RD(ir) == FPCREG_CSR) {
+#ifdef CSRTRACE
+                                       printk
+                                           ("%p gpr[%d]->csr=%08x\n",
+                                            REG_TO_VA(xcp->cp0_epc),
+                                            MIPSInst_RT(ir), value);
+#endif
+                                       ctx->sr = value;
+                                       /* copy new rounding mode to ieee library state! */
+                                       ieee754_csr.rm =
+                                           ieee_rm[value & 0x3];
+                               }
+                       }
+                       break;
+
+               case bc_op:
+                       if (xcp->cp0_cause & CAUSEF_BD) {
+                               return SIGILL;
+                       }
+                       {
+                               int likely = 0;
+
+#if __mips >= 4
+                               cond =
+                                   ctx->
+                                   sr & fpucondbit[MIPSInst_RT(ir) >> 2];
+#else
+                               cond = ctx->sr & FPU_CSR_COND;
+#endif
+                               switch (MIPSInst_RT(ir) & 3) {
+                               case bcfl_op:
+                                       likely = 1;
+                               case bcf_op:
+                                       cond = !cond;
+                                       break;
+                               case bctl_op:
+                                       likely = 1;
+                               case bct_op:
+                                       break;
+                               default:
+                                       /* thats an illegal instruction */
+                                       return SIGILL;
+                               }
+
+                               xcp->cp0_cause |= CAUSEF_BD;
+                               if (cond) {
+                                       /* branch taken: emulate dslot instruction */
+                                       xcp->cp0_epc += 4;
+                                       contpc =
+                                           REG_TO_VA xcp->cp0_epc +
+                                           (MIPSInst_SIMM(ir) << 2);
+
+                                       ir =
+                                           mips_get_word(xcp,
+                                                         REG_TO_VA(xcp->
+                                                                   cp0_epc),
+                                                         &err);
+                                       if (err) {
+                                               fpuemuprivate.stats.
+                                                   errors++;
+                                               return SIGBUS;
+                                       }
+
+                                       switch (MIPSInst_OPCODE(ir)) {
+                                       case lwc1_op:
+                                       case swc1_op:
+#if (__mips >= 2 || __mips64) && !defined(SINGLE_ONLY_FPU)
+                                       case ldc1_op:
+                                       case sdc1_op:
+#endif
+                                       case cop1_op:
+#if __mips >= 4 && __mips != 32
+                                       case cop1x_op:
+#endif
+                                               /* its one of ours */
+                                               goto emul;
+#if __mips >= 4
+                                       case spec_op:
+                                               if (MIPSInst_FUNC(ir) ==
+                                                   movc_op) goto emul;
+                                               break;
+#endif
+                                       }
+
+                                       /* single step the non-cp1 instruction in the dslot */
+                                       return mips_dsemul(xcp, ir,
+                                                          contpc);
+                               } else {
+                                       /* branch not taken */
+                                       if (likely)
+                                               /* branch likely nullifies dslot if not taken */
+                                               xcp->cp0_epc += 4;
+                                       /* else continue & execute dslot as normal insn */
+                               }
+                       }
+                       break;
+
+               default:
+                       if (!(MIPSInst_RS(ir) & 0x10)) {
+                               return SIGILL;
+                       }
+                       /* a real fpu computation instruction */
+                       {
+                               int sig;
+                               if ((sig = fpu_emu(xcp, ctx, ir)))
+                                       return sig;
+                       }
+               }
+               break;
+
+#if __mips >= 4 && __mips != 32
+       case cop1x_op:
+               {
+                       int sig;
+                       if ((sig = fpux_emu(xcp, ctx, ir)))
+                               return sig;
+               }
+               break;
+#endif
+
+#if __mips >= 4
+       case spec_op:
+               if (MIPSInst_FUNC(ir) != movc_op)
+                       return SIGILL;
+               cond = fpucondbit[MIPSInst_RT(ir) >> 2];
+               if (((ctx->sr & cond) != 0) !=
+                   ((MIPSInst_RT(ir) & 1) != 0)) return 0;
+               xcp->regs[MIPSInst_RD(ir)] = xcp->regs[MIPSInst_RS(ir)];
+               break;
+#endif
+
+       default:
+               return SIGILL;
+       }
+
+       /* we did it !! */
+       xcp->cp0_epc = VA_TO_REG(contpc);
+       xcp->cp0_cause &= ~CAUSEF_BD;
+       return 0;
+}
+
+/*
+ * Emulate the arbritrary instruction ir at xcp->cp0_epc.  Required when
+ * we have to emulate the instruction in a COP1 branch delay slot.  Do
+ * not change cp0_epc due to the instruction
+ *
+ * According to the spec:
+ * 1) it shouldnt be a branch :-)
+ * 2) it can be a COP instruction :-(
+ * 3) if we are tring to run a protected memory space we must take
+ *    special care on memory access instructions :-(
+ */
+
+/*
+ * "Trampoline" return routine to catch exception following
+ *  execution of delay-slot instruction execution.
+ */
+
+int do_dsemulret(struct pt_regs *xcp)
+{
+#ifdef DSEMUL_TRACE
+       printk("desemulret\n");
+#endif
+       /* Set EPC to return to post-branch instruction */
+       xcp->cp0_epc = current->thread.dsemul_epc;
+       /*
+        * Clear the state that got us here.
+        */
+       current->thread.dsemul_aerpc = (unsigned long) 0;
+
+       return 0;
+}
+
+
+#define AdELOAD 0x8c000001     /* lw $0,1($0) */
+
+static int
+mips_dsemul(struct pt_regs *xcp, mips_instruction ir, vaddr_t cpc)
+{
+       mips_instruction *dsemul_insns;
+       mips_instruction forcetrap;
+       extern asmlinkage void handle_dsemulret(void);
+
+       if (ir == 0) {          /* a nop is easy */
+               xcp->cp0_epc = VA_TO_REG(cpc);
+               return 0;
+       }
+#ifdef DSEMUL_TRACE
+       printk("desemul %p %p\n", REG_TO_VA(xcp->cp0_epc), cpc);
+#endif
+
+       /* 
+        * The strategy is to push the instruction onto the user stack 
+        * and put a trap after it which we can catch and jump to 
+        * the required address any alternative apart from full 
+        * instruction emulation!!.
+        */
+       dsemul_insns = (mips_instruction *) (xcp->regs[29] & ~3);
+       dsemul_insns -= 3;      /* Two instructions, plus one for luck ;-) */
+       /* Verify that the stack pointer is not competely insane */
+       if (verify_area
+           (VERIFY_WRITE, dsemul_insns, sizeof(mips_instruction) * 2))
+               return SIGBUS;
+
+       if (mips_put_word(xcp, &dsemul_insns[0], ir)) {
+               fpuemuprivate.stats.errors++;
+               return (SIGBUS);
+       }
+
+       /* 
+        * Algorithmics used a system call instruction, and
+        * borrowed that vector.  MIPS/Linux version is a bit
+        * more heavyweight in the interests of portability and
+        * multiprocessor support.  We flag the thread for special
+        * handling in the unaligned access handler and force an
+        * address error excpetion.
+        */
+
+       /* If one is *really* paranoid, one tests for a bad stack pointer */
+       if ((xcp->regs[29] & 0x3) == 0x3)
+               forcetrap = AdELOAD - 1;
+       else
+               forcetrap = AdELOAD;
+
+       if (mips_put_word(xcp, &dsemul_insns[1], forcetrap)) {
+               fpuemuprivate.stats.errors++;
+               return (SIGBUS);
+       }
+
+       /* Set thread state to catch and handle the exception */
+       current->thread.dsemul_epc = (unsigned long) cpc;
+       current->thread.dsemul_aerpc = (unsigned long) &dsemul_insns[1];
+       xcp->cp0_epc = VA_TO_REG & dsemul_insns[0];
+
+       /* What we'd really like to do is just flush the line(s) of the */
+       /* icache containing the dsemulret instructions, but there's no */
+       /* mechanism to do this yet...  */
+       flush_cache_all();
+       return SIGILL;          /* force out of emulation loop */
+}
+
+/* 
+ * Conversion table from MIPS compare ops 48-63
+ * cond = ieee754dp_cmp(x,y,IEEE754_UN);
+ */
+static const unsigned char cmptab[8] = {
+       0,                                      /* cmp_0 (sig) cmp_sf */
+       IEEE754_CUN,                            /* cmp_un (sig) cmp_ngle */
+       IEEE754_CEQ,                            /* cmp_eq (sig) cmp_seq */
+       IEEE754_CEQ | IEEE754_CUN,              /* cmp_ueq (sig) cmp_ngl  */
+       IEEE754_CLT,                            /* cmp_olt (sig) cmp_lt */
+       IEEE754_CLT | IEEE754_CUN,              /* cmp_ult (sig) cmp_nge */
+       IEEE754_CLT | IEEE754_CEQ,              /* cmp_ole (sig) cmp_le */
+       IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */
+};
+
+#define SIFROMREG(si,x)        ((si) = ctx->regs[x])
+#define SITOREG(si,x)  (ctx->regs[x] = (int)(si))
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+#define DIFROMREG(di,x)        ((di) = ctx->regs[x])
+#define DITOREG(di,x)  (ctx->regs[x] = (di))
+#endif
+
+#define SPFROMREG(sp,x)        ((sp).bits = ctx->regs[x])
+#define SPTOREG(sp,x)  (ctx->regs[x] = (sp).bits)
+
+#ifdef CP0_STATUS_FR_SUPPORT
+#define DPFROMREG(dp,x)        ((dp).bits = \
+                       ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)])
+#define DPTOREG(dp,x)  (ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)]\
+                       = (dp).bits)
+#else
+/* Beware: MIPS COP1 doubles are always little_word endian in registers */
+#define DPFROMREG(dp,x)        \
+  ((dp).bits = ((unsigned long long)ctx->regs[(x)+1] << 32) | ctx->regs[x])
+#define DPTOREG(dp,x) \
+  (ctx->regs[x] = (dp).bits, ctx->regs[(x)+1] = (dp).bits >> 32)
+#endif
+
+#if __mips >= 4 && __mips != 32
+
+/*
+ * Additional MIPS4 instructions
+ */
+
+static ieee754dp fpemu_dp_recip(ieee754dp d)
+{
+       return ieee754dp_div(ieee754dp_one(0), d);
+}
+
+static ieee754dp fpemu_dp_rsqrt(ieee754dp d)
+{
+       return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d));
+}
+
+static ieee754sp fpemu_sp_recip(ieee754sp s)
+{
+       return ieee754sp_div(ieee754sp_one(0), s);
+}
+
+static ieee754sp fpemu_sp_rsqrt(ieee754sp s)
+{
+       return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s));
+}
+
+
+static ieee754dp fpemu_dp_madd(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+       return ieee754dp_add(ieee754dp_mul(s, t), r);
+}
+
+static ieee754dp fpemu_dp_msub(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+       return ieee754dp_sub(ieee754dp_mul(s, t), r);
+}
+
+static ieee754dp fpemu_dp_nmadd(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+       return ieee754dp_neg(ieee754dp_add(ieee754dp_mul(s, t), r));
+}
+
+static ieee754dp fpemu_dp_nmsub(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+       return ieee754dp_neg(ieee754dp_sub(ieee754dp_mul(s, t), r));
+}
+
+
+static ieee754sp fpemu_sp_madd(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+       return ieee754sp_add(ieee754sp_mul(s, t), r);
+}
+
+static ieee754sp fpemu_sp_msub(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+       return ieee754sp_sub(ieee754sp_mul(s, t), r);
+}
+
+static ieee754sp fpemu_sp_nmadd(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+       return ieee754sp_neg(ieee754sp_add(ieee754sp_mul(s, t), r));
+}
+
+static ieee754sp fpemu_sp_nmsub(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+       return ieee754sp_neg(ieee754sp_sub(ieee754sp_mul(s, t), r));
+}
+
+static int
+fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
+        mips_instruction ir)
+{
+       unsigned rcsr = 0;      /* resulting csr */
+
+       fpuemuprivate.stats.cp1xops++;
+
+       switch (MIPSInst_FMA_FFMT(ir)) {
+       case s_fmt:             /* 0 */
+               {
+                       ieee754sp(*handler) (ieee754sp, ieee754sp,
+                                            ieee754sp);
+                       ieee754sp fd, fr, fs, ft;
+
+                       switch (MIPSInst_FUNC(ir)) {
+                       case lwxc1_op:
+                               {
+                                       void *va =
+                                           REG_TO_VA(xcp->
+                                                     regs[MIPSInst_FR(ir)]
+                                                     +
+                                                     xcp->
+                                                     regs[MIPSInst_FT
+                                                          (ir)]);
+                                       fpureg_t val;
+                                       int err = 0;
+                                       val = mips_get_word(xcp, va, &err);
+                                       if (err) {
+                                               fpuemuprivate.stats.
+                                                   errors++;
+                                               return SIGBUS;
+                                       }
+                                       if (xcp->cp0_status & ST0_FR) {
+                                               /* load whole register */
+                                               ctx->
+                                                   regs[MIPSInst_FD(ir)] =
+                                                   val;
+                                       } else if (MIPSInst_FD(ir) & 1) {
+                                               /* load to m.s. 32 bits */
+#if defined(SINGLE_ONLY_FPU)
+                                               /* illegal register in single-float mode */
+                                               return SIGILL;
+#else
+                                               ctx->
+                                                   regs[
+                                                        (MIPSInst_FD(ir) &
+                                                         ~1)] &=
+                                                   0xffffffff;
+                                               ctx->
+                                                   regs[
+                                                        (MIPSInst_FD(ir) &
+                                                         ~1)] |=
+                                                   val << 32;
+#endif
+                                       } else {
+                                               /* load to l.s. 32 bits */
+                                               ctx->
+                                                   regs[MIPSInst_FD(ir)]
+                                                   &= ~0xffffffffLL;
+                                               ctx->
+                                                   regs[MIPSInst_FD(ir)]
+                                                   |= val;
+                                       }
+                               }
+                               break;
+
+                       case swxc1_op:
+                               {
+                                       void *va =
+                                           REG_TO_VA(xcp->
+                                                     regs[MIPSInst_FR(ir)]
+                                                     +
+                                                     xcp->
+                                                     regs[MIPSInst_FT
+                                                          (ir)]);
+                                       unsigned int val;
+                                       if (xcp->cp0_status & ST0_FR) {
+                                               /* store whole register */
+                                               val =
+                                                   ctx->
+                                                   regs[MIPSInst_FS(ir)];
+                                       } else if (MIPSInst_FS(ir) & 1) {
+#if defined(SINGLE_ONLY_FPU)
+                                               /* illegal register in single-float mode */
+                                               return SIGILL;
+#else
+                                               /* store from m.s. 32 bits */
+                                               val =
+                                                   ctx->
+                                                   regs[
+                                                        (MIPSInst_FS(ir) &
+                                                         ~1)] >> 32;
+#endif
+                                       } else {
+                                               /* store from l.s. 32 bits */
+                                               val =
+                                                   ctx->
+                                                   regs[MIPSInst_FS(ir)];
+                                       }
+                                       if (mips_put_word(xcp, va, val)) {
+                                               fpuemuprivate.stats.
+                                                   errors++;
+                                               return SIGBUS;
+                                       }
+                               }
+                               break;
+
+                       case madd_s_op:
+                               handler = fpemu_sp_madd;
+                               goto scoptop;
+                       case msub_s_op:
+                               handler = fpemu_sp_msub;
+                               goto scoptop;
+                       case nmadd_s_op:
+                               handler = fpemu_sp_nmadd;
+                               goto scoptop;
+                       case nmsub_s_op:
+                               handler = fpemu_sp_nmsub;
+                               goto scoptop;
+
+                             scoptop:
+                               SPFROMREG(fr, MIPSInst_FR(ir));
+                               SPFROMREG(fs, MIPSInst_FS(ir));
+                               SPFROMREG(ft, MIPSInst_FT(ir));
+                               fd = (*handler) (fr, fs, ft);
+                               SPTOREG(fd, MIPSInst_FD(ir));
+
+                             copcsr:
+                               if (ieee754_cxtest(IEEE754_INEXACT))
+                                       rcsr |=
+                                           FPU_CSR_INE_X | FPU_CSR_INE_S;
+                               if (ieee754_cxtest(IEEE754_UNDERFLOW))
+                                       rcsr |=
+                                           FPU_CSR_UDF_X | FPU_CSR_UDF_S;
+                               if (ieee754_cxtest(IEEE754_OVERFLOW))
+                                       rcsr |=
+                                           FPU_CSR_OVF_X | FPU_CSR_OVF_S;
+                               if (ieee754_cxtest
+                                   (IEEE754_INVALID_OPERATION)) rcsr |=
+                                           FPU_CSR_INV_X | FPU_CSR_INV_S;
+
+                               ctx->sr =
+                                   (ctx->sr & ~FPU_CSR_ALL_X) | rcsr;
+                               if ((ctx->sr >> 5) & ctx->
+                                   sr & FPU_CSR_ALL_E) {
+               /*printk ("SIGFPE: fpu csr = %08x\n",ctx->sr); */
+                                       return SIGFPE;
+                               }
+
+                               break;
+
+                       default:
+                               return SIGILL;
+                       }
+               }
+               break;
+
+#if !defined(SINGLE_ONLY_FPU)
+       case d_fmt:             /* 1 */
+               {
+                       ieee754dp(*handler) (ieee754dp, ieee754dp,
+                                            ieee754dp);
+                       ieee754dp fd, fr, fs, ft;
+
+                       switch (MIPSInst_FUNC(ir)) {
+                       case ldxc1_op:
+                               {
+                                       void *va =
+                                           REG_TO_VA(xcp->
+                                                     regs[MIPSInst_FR(ir)]
+                                                     +
+                                                     xcp->
+                                                     regs[MIPSInst_FT
+                                                          (ir)]);
+                                       int err = 0;
+                                       ctx->regs[MIPSInst_FD(ir)] =
+                                           mips_get_dword(xcp, va, &err);
+                                       if (err) {
+                                               fpuemuprivate.stats.
+                                                   errors++;
+                                               return SIGBUS;
+                                       }
+                               }
+                               break;
+
+                       case sdxc1_op:
+                               {
+                                       void *va =
+                                           REG_TO_VA(xcp->
+                                                     regs[MIPSInst_FR(ir)]
+                                                     +
+                                                     xcp->
+                                                     regs[MIPSInst_FT
+                                                          (ir)]);
+                                       if (mips_put_dword
+                                           (xcp, va,
+                                            ctx->regs[MIPSInst_FS(ir)])) {
+                                               fpuemuprivate.stats.
+                                                   errors++;
+                                               return SIGBUS;
+                                       }
+                               }
+                               break;
+
+                       case madd_d_op:
+                               handler = fpemu_dp_madd;
+                               goto dcoptop;
+                       case msub_d_op:
+                               handler = fpemu_dp_msub;
+                               goto dcoptop;
+                       case nmadd_d_op:
+                               handler = fpemu_dp_nmadd;
+                               goto dcoptop;
+                       case nmsub_d_op:
+                               handler = fpemu_dp_nmsub;
+                               goto dcoptop;
+
+                             dcoptop:
+                               DPFROMREG(fr, MIPSInst_FR(ir));
+                               DPFROMREG(fs, MIPSInst_FS(ir));
+                               DPFROMREG(ft, MIPSInst_FT(ir));
+                               fd = (*handler) (fr, fs, ft);
+                               DPTOREG(fd, MIPSInst_FD(ir));
+                               goto copcsr;
+
+                       default:
+                               return SIGILL;
+                       }
+               }
+               break;
+#endif
+
+       case 0x7:               /* 7 */
+               {
+                       if (MIPSInst_FUNC(ir) != pfetch_op) {
+                               return SIGILL;
+                       }
+                       /* ignore prefx operation */
+               }
+               break;
+
+       default:
+               return SIGILL;
+       }
+
+       return 0;
+}
+#endif
+
+
+
+/*
+ * Emulate a single COP1 arithmetic instruction.
+ */
+static int
+fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
+       mips_instruction ir)
+{
+       int rfmt;               /* resulting format */
+       unsigned rcsr = 0;      /* resulting csr */
+       unsigned cond;
+       union {
+               ieee754dp d;
+               ieee754sp s;
+               int w;
+#if __mips64
+               long long l;
+#endif
+       } rv;                   /* resulting value */
+
+       fpuemuprivate.stats.cp1ops++;
+       switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
+
+       case s_fmt:{            /* 0 */
+               ieee754sp(*handler) ();
+
+               switch (MIPSInst_FUNC(ir)) {
+                       /* binary ops */
+               case fadd_op:
+                       handler = ieee754sp_add;
+                       goto scopbop;
+               case fsub_op:
+                       handler = ieee754sp_sub;
+                       goto scopbop;
+               case fmul_op:
+                       handler = ieee754sp_mul;
+                       goto scopbop;
+               case fdiv_op:
+                       handler = ieee754sp_div;
+                       goto scopbop;
+
+                       /* unary  ops */
+#if __mips >= 2 || __mips64
+               case fsqrt_op:
+                       handler = ieee754sp_sqrt;
+                       goto scopuop;
+#endif
+#if __mips >= 4 && __mips != 32
+               case frsqrt_op:
+                       handler = fpemu_sp_rsqrt;
+                       goto scopuop;
+               case frecip_op:
+                       handler = fpemu_sp_recip;
+                       goto scopuop;
+#endif
+#if __mips >= 4
+               case fmovc_op:
+                       cond = fpucondbit[MIPSInst_FT(ir) >> 2];
+                       if (((ctx->sr & cond) != 0) !=
+                           ((MIPSInst_FT(ir) & 1) != 0))
+                               return 0;
+                       SPFROMREG(rv.s, MIPSInst_FS(ir));
+                       break;
+               case fmovz_op:
+                       if (xcp->regs[MIPSInst_FT(ir)] != 0)
+                               return 0;
+                       SPFROMREG(rv.s, MIPSInst_FS(ir));
+                       break;
+               case fmovn_op:
+                       if (xcp->regs[MIPSInst_FT(ir)] == 0)
+                               return 0;
+                       SPFROMREG(rv.s, MIPSInst_FS(ir));
+                       break;
+#endif
+               case fabs_op:
+                       handler = ieee754sp_abs;
+                       goto scopuop;
+               case fneg_op:
+                       handler = ieee754sp_neg;
+                       goto scopuop;
+               case fmov_op:
+                       /* an easy one */
+                       SPFROMREG(rv.s, MIPSInst_FS(ir));
+                       break;
+                       /* binary op on handler */
+scopbop:
+                       {
+                               ieee754sp fs, ft;
+
+                               SPFROMREG(fs, MIPSInst_FS(ir));
+                               SPFROMREG(ft, MIPSInst_FT(ir));
+
+                               rv.s = (*handler) (fs, ft);
+                               goto copcsr;
+                       }
+scopuop:
+                       {
+                               ieee754sp fs;
+
+                               SPFROMREG(fs, MIPSInst_FS(ir));
+                               rv.s = (*handler) (fs);
+                               goto copcsr;
+                       }
+copcsr:
+                       if (ieee754_cxtest(IEEE754_INEXACT))
+                               rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
+                       if (ieee754_cxtest(IEEE754_UNDERFLOW))
+                               rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
+                       if (ieee754_cxtest(IEEE754_OVERFLOW))
+                               rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
+                       if (ieee754_cxtest(IEEE754_ZERO_DIVIDE))
+                               rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S;
+                       if (ieee754_cxtest
+                               (IEEE754_INVALID_OPERATION)) rcsr |=
+                                           FPU_CSR_INV_X | FPU_CSR_INV_S;
+                               break;
+
+                               /* unary conv ops */
+               case fcvts_op:
+                       return SIGILL;  /* not defined */
+               case fcvtd_op:
+#if defined(SINGLE_ONLY_FPU)
+                       return SIGILL;  /* not defined */
+#else
+                       {
+                               ieee754sp fs;
+
+                               SPFROMREG(fs, MIPSInst_FS(ir));
+                               rv.d = ieee754dp_fsp(fs);
+                               rfmt = d_fmt;
+                               goto copcsr;
+                       }
+#endif
+               case fcvtw_op:
+                       {
+                               ieee754sp fs;
+
+                               SPFROMREG(fs, MIPSInst_FS(ir));
+                               rv.w = ieee754sp_tint(fs);
+                               rfmt = w_fmt;
+                               goto copcsr;
+                       }
+
+#if __mips >= 2 || __mips64
+               case fround_op:
+               case ftrunc_op:
+               case fceil_op:
+               case ffloor_op:
+                       {
+                               unsigned int oldrm = ieee754_csr.rm;
+                               ieee754sp fs;
+
+                               SPFROMREG(fs, MIPSInst_FS(ir));
+                               ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+                               rv.w = ieee754sp_tint(fs);
+                               ieee754_csr.rm = oldrm;
+                               rfmt = w_fmt;
+                               goto copcsr;
+                       }
+#endif                 /* __mips >= 2 */
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+               case fcvtl_op:
+                       {
+                               ieee754sp fs;
+
+                               SPFROMREG(fs, MIPSInst_FS(ir));
+                               rv.l = ieee754sp_tlong(fs);
+                               rfmt = l_fmt;
+                               goto copcsr;
+                       }
+
+               case froundl_op:
+               case ftruncl_op:
+               case fceill_op:
+               case ffloorl_op:
+                       {
+                               unsigned int oldrm = ieee754_csr.rm;
+                               ieee754sp fs;
+
+                               SPFROMREG(fs, MIPSInst_FS(ir));
+                               ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+                               rv.l = ieee754sp_tlong(fs);
+                               ieee754_csr.rm = oldrm;
+                               rfmt = l_fmt;
+                               goto copcsr;
+                       }
+#endif /* __mips64 && !fpu(single) */
+
+               default:
+                       if (MIPSInst_FUNC(ir) >= fcmp_op) {
+                               unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
+                               ieee754sp fs, ft;
+
+                               SPFROMREG(fs, MIPSInst_FS(ir));
+                               SPFROMREG(ft, MIPSInst_FT(ir));
+                               rv.w = ieee754sp_cmp(fs, ft, cmptab[cmpop & 0x7]);
+                               rfmt = -1;
+                               if ((cmpop & 0x8) && ieee754_cxtest(IEEE754_INVALID_OPERATION))
+                                       rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+                               } else {
+                                       return SIGILL;
+                               }
+                               break;
+                       }
+                       break;
+               }
+
+#if !defined(SINGLE_ONLY_FPU)
+       case d_fmt: {
+               ieee754dp(*handler) ();
+
+               switch (MIPSInst_FUNC(ir)) {
+                       /* binary ops */
+               case fadd_op:
+                       handler = ieee754dp_add;
+                       goto dcopbop;
+               case fsub_op:
+                       handler = ieee754dp_sub;
+                       goto dcopbop;
+               case fmul_op:
+                       handler = ieee754dp_mul;
+                       goto dcopbop;
+               case fdiv_op:
+                       handler = ieee754dp_div;
+                       goto dcopbop;
+
+                       /* unary  ops */
+#if __mips >= 2 || __mips64
+               case fsqrt_op:
+                       handler = ieee754dp_sqrt;
+                       goto dcopuop;
+#endif
+#if __mips >= 4 && __mips != 32
+               case frsqrt_op:
+                       handler = fpemu_dp_rsqrt;
+                       goto dcopuop;
+               case frecip_op:
+                       handler = fpemu_dp_recip;
+                       goto dcopuop;
+#endif
+#if __mips >= 4
+               case fmovc_op:
+                       cond = fpucondbit[MIPSInst_FT(ir) >> 2];
+                       if (((ctx->sr & cond) != 0) != ((MIPSInst_FT(ir) & 1) != 0))
+                               return 0;
+                       DPFROMREG(rv.d, MIPSInst_FS(ir));
+                       break;
+               case fmovz_op:
+                       if (xcp->regs[MIPSInst_FT(ir)] != 0)
+                               return 0;
+                       DPFROMREG(rv.d, MIPSInst_FS(ir));
+                       break;
+               case fmovn_op:
+                       if (xcp->regs[MIPSInst_FT(ir)] == 0)
+                               return 0;
+                       DPFROMREG(rv.d, MIPSInst_FS(ir));
+                       break;
+#endif
+               case fabs_op:
+                       handler = ieee754dp_abs;
+                       goto dcopuop;
+               case fneg_op:
+                       handler = ieee754dp_neg;
+                       goto dcopuop;
+               case fmov_op:
+                       /* an easy one */
+                       DPFROMREG(rv.d, MIPSInst_FS(ir));
+                       break;
+
+                       /* binary op on handler */
+dcopbop:
+                       {
+                               ieee754dp fs, ft;
+
+                               DPFROMREG(fs, MIPSInst_FS(ir));
+                               DPFROMREG(ft, MIPSInst_FT(ir));
+
+                               rv.d = (*handler) (fs, ft);
+                               goto copcsr;
+                       }
+dcopuop:
+                       {
+                               ieee754dp fs;
+
+                               DPFROMREG(fs, MIPSInst_FS(ir));
+                               rv.d = (*handler) (fs);
+                               goto copcsr;
+                       }
+
+               /* unary conv ops */
+               case fcvts_op:
+                       {
+                               ieee754dp fs;
+
+                               DPFROMREG(fs, MIPSInst_FS(ir));
+                               rv.s = ieee754sp_fdp(fs);
+                               rfmt = s_fmt;
+                               goto copcsr;
+                       }
+               case fcvtd_op:
+                       return SIGILL;  /* not defined */
+               case fcvtw_op:
+                       {
+                               ieee754dp fs;
+
+                               DPFROMREG(fs, MIPSInst_FS(ir));
+                               rv.w = ieee754dp_tint(fs);      /* wrong */
+                               rfmt = w_fmt;
+                               goto copcsr;
+                       }
+
+#if __mips >= 2 || __mips64
+               case fround_op:
+               case ftrunc_op:
+               case fceil_op:
+               case ffloor_op:
+                       {
+                               unsigned int oldrm = ieee754_csr.rm;
+                               ieee754dp fs;
+
+                               DPFROMREG(fs, MIPSInst_FS(ir));
+                               ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+                               rv.w = ieee754dp_tint(fs);
+                               ieee754_csr.rm = oldrm;
+                               rfmt = w_fmt;
+                               goto copcsr;
+                       }
+#endif
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+               case fcvtl_op:
+                       {
+                               ieee754dp fs;
+
+                               DPFROMREG(fs, MIPSInst_FS(ir));
+                               rv.l = ieee754dp_tlong(fs);
+                               rfmt = l_fmt;
+                               goto copcsr;
+                       }
+
+               case froundl_op:
+               case ftruncl_op:
+               case fceill_op:
+               case ffloorl_op:
+                       {
+                               unsigned int oldrm = ieee754_csr.rm;
+                               ieee754dp fs;
+
+                               DPFROMREG(fs, MIPSInst_FS(ir));
+                               ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+                               rv.l = ieee754dp_tlong(fs);
+                               ieee754_csr.rm = oldrm;
+                               rfmt = l_fmt;
+                               goto copcsr;
+                       }
+#endif /* __mips >= 3 && !fpu(single) */
+
+               default:
+                       if (MIPSInst_FUNC(ir) >= fcmp_op) {
+                               unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
+                               ieee754dp fs, ft;
+
+                               DPFROMREG(fs, MIPSInst_FS(ir));
+                               DPFROMREG(ft, MIPSInst_FT(ir));
+                               rv.w = ieee754dp_cmp(fs, ft, cmptab[cmpop & 0x7]);
+                               rfmt = -1;
+                               if ((cmpop & 0x8) && ieee754_cxtest (IEEE754_INVALID_OPERATION))
+                                       rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+                       } else {
+                               return SIGILL;
+                       }
+                       break;
+               }
+               break;
+       }
+#endif                         /* !defined(SINGLE_ONLY_FPU) */
+
+       case w_fmt: {
+               switch (MIPSInst_FUNC(ir)) {
+               case fcvts_op:
+                       /* convert word to single precision real */
+                       rv.s = ieee754sp_fint(ctx-> regs[MIPSInst_FS(ir)]);
+                       rfmt = s_fmt;
+                       goto copcsr;
+#if !defined(SINGLE_ONLY_FPU)
+               case fcvtd_op:
+                       /* convert word to double precision real */
+                       rv.d = ieee754dp_fint(ctx-> regs[MIPSInst_FS(ir)]);
+                       rfmt = d_fmt;
+                       goto copcsr;
+#endif
+               default:
+                       return SIGILL;
+               }
+               break;
+       }
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+       case l_fmt: {
+               switch (MIPSInst_FUNC(ir)) {
+               case fcvts_op:
+                       /* convert long to single precision real */
+                       rv.s = ieee754sp_flong(ctx-> regs[MIPSInst_FS(ir)]);
+                       rfmt = s_fmt;
+                       goto copcsr;
+               case fcvtd_op:
+                       /* convert long to double precision real */
+                       rv.d = ieee754dp_flong(ctx-> regs[MIPSInst_FS(ir)]);
+                       rfmt = d_fmt;
+                       goto copcsr;
+               default:
+                       return SIGILL;
+               }
+               break;
+       }
+#endif
+
+       default:
+               return SIGILL;
+       }
+
+       /*
+        * Update the fpu CSR register for this operation.
+        * If an exception is required, generate a tidy SIGFPE exception,
+        * without updating the result register.
+        * Note: cause exception bits do not accumulate, they are rewritten
+        * for each op; only the flag/sticky bits accumulate.
+        */
+       ctx->sr = (ctx->sr & ~FPU_CSR_ALL_X) | rcsr;
+       if ((ctx->sr >> 5) & ctx->sr & FPU_CSR_ALL_E) {
+               /*printk ("SIGFPE: fpu csr = %08x\n",ctx->sr); */
+               return SIGFPE;
+       }
+
+       /* 
+        * Now we can safely write the result back to the register file.
+        */
+       switch (rfmt) {
+       case -1: {
+#if __mips >= 4
+               cond = fpucondbit[MIPSInst_FD(ir) >> 2];
+#else
+               cond = FPU_CSR_COND;
+#endif
+               if (rv.w)
+                       ctx->sr |= cond;
+               else
+                       ctx->sr &= ~cond;
+               break;
+       }
+#if !defined(SINGLE_ONLY_FPU)
+       case d_fmt:
+               DPTOREG(rv.d, MIPSInst_FD(ir));
+               break;
+#endif
+       case s_fmt:
+               SPTOREG(rv.s, MIPSInst_FD(ir));
+               break;
+       case w_fmt:
+               SITOREG(rv.w, MIPSInst_FD(ir));
+               break;
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+       case l_fmt:
+               DITOREG(rv.l, MIPSInst_FD(ir));
+               break;
+#endif
+       default:
+               return SIGILL;
+       }
+
+       return 0;
+}
+
+
+/*
+ * Emulate the floating point instruction at EPC, and continue
+ * to run until we hit a non-fp instruction, or a backward
+ * branch.  This cuts down dramatically on the per instruction 
+ * exception overhead.
+ */
+int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp)
+{
+       struct mips_fpu_soft_struct *ctx = &current->thread.fpu.soft;
+       unsigned long oldepc, prevepc;
+       unsigned int insn;
+       int sig = 0;
+       int err = 0;
+
+       oldepc = xcp->cp0_epc;
+       do {
+               prevepc = xcp->cp0_epc;
+               insn = mips_get_word(xcp, REG_TO_VA(xcp->cp0_epc), &err);
+               if (err) {
+                       fpuemuprivate.stats.errors++;
+                       return SIGBUS;
+               }
+               if (insn != 0)
+                       sig = cop1Emulate(xcptno, xcp, ctx);
+               else
+                       xcp->cp0_epc += 4;      /* skip nops */
+       } while (xcp->cp0_epc > prevepc && sig == 0);
+
+       /* SIGILL indicates a non-fpu instruction */
+       if (sig == SIGILL && xcp->cp0_epc != oldepc)
+               /* but if epc has advanced, then ignore it */
+               sig = 0;
+
+       return sig;
+}
+
+
+#ifdef NOTDEF
+/*
+ * Patch up the hardware fpu state when an f.p. exception occurs.  
+ */
+static int cop1Patcher(int xcptno, struct pt_regs *xcp)
+{
+       struct mips_fpu_soft_struct *ctx = &current->thread.fpu.soft;
+       unsigned sr;
+       int sig;
+
+       /* reenable Cp1, else fpe_save() will get nested exception */
+       sr = mips_bissr(ST0_CU1);
+
+       /* get fpu registers and status, then clear pending exceptions */
+       fpe_save(ctx);
+       fpe_setsr(ctx->sr &= ~FPU_CSR_ALL_X);
+
+       /* get current rounding mode for IEEE library, and emulate insn */
+       ieee754_csr.rm = ieee_rm[ctx->sr & 0x3];
+       sig = cop1Emulate(xcptno, xcp, ctx);
+
+       /* don't return with f.p. exceptions pending */
+       ctx->sr &= ~FPU_CSR_ALL_X;
+       fpe_restore(ctx);
+
+       mips_setsr(sr);
+       return sig;
+}
+
+void _cop1_init(int emulate)
+{
+       extern int _nofpu;
+
+       if (emulate) {
+               /* 
+                * Install cop1 emulator to handle "coprocessor unusable" exception
+                */
+               xcption(XCPTCPU, cop1Handler);
+               fpuemuactive = 1;       /* tell dbg.c that we are in charge */
+               _nofpu = 0;     /* tell setjmp() it "has" an fpu */
+       } else {
+               /* 
+                * Install cop1 emulator for floating point exceptions only,
+                * i.e. denormalised results, underflow, overflow etc, which
+                * must be emulated in s/w.
+                */
+#ifdef 1
+               /* r4000 or above use dedicate exception */
+               xcption(XCPTFPE, cop1Patcher);
+#else
+               /* r3000 et al use interrupt */
+               extern int _sbd_getfpuintr(void);
+               int intno = _sbd_getfpuintr();
+               intrupt(intno, cop1Patcher, 0);
+               mips_bissr(SR_IM0 << intno);
+#endif
+
+#if (#cpu(r4640) || #cpu(r4650)) && !defined(SINGLE_ONLY_FPU)
+               /* For R4640/R4650 compiled *without* the -msingle-float flag,
+                  then we share responsibility: the h/w handles the single
+                  precision operations, and the trap emulator handles the
+                  double precision. We set fpuemuactive so that dbg.c first
+                  fetches the s/w state before saving the h/w state. */
+               fpuemuactive = 1;
+               {
+                       int i;
+                       /* initialise the unused d.p high order words to be NaN */
+                       for (i = 0; i < 32; i++)
+                               current->thread.fpu.soft.regs[i] =
+                                   0x7ff80bad00000000LL;
+               }
+#endif                         /* (r4640 || r4650) && !fpu(single) */
+       }
+}
+#endif
+
diff --git a/arch/mips/math-emu/dp_add.c b/arch/mips/math-emu/dp_add.c
new file mode 100644 (file)
index 0000000..5a3158b
--- /dev/null
@@ -0,0 +1,186 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)
+{
+       COMPXDP;
+       COMPYDP;
+
+       EXPLODEXDP;
+       EXPLODEYDP;
+
+       CLEARCX;
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+               return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "add", x,
+                                        y);
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754dp_nanxcpt(y, "add", x, y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754dp_nanxcpt(x, "add", x, y);
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+               return ieee754dp_bestnan(x, y);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return x;
+
+
+               /* Inifity handeling 
+                */
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+               if (xs == ys)
+                       return x;
+               SETCX(IEEE754_INVALID_OPERATION);
+               return ieee754dp_xcpt(ieee754dp_indef(), "add", x, y);
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+               return x;
+
+               /* Zero handeling 
+                */
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+               if (xs == ys)
+                       return x;
+               else
+                       return ieee754dp_zero(ieee754_csr.rm ==
+                                             IEEE754_RD);
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               return x;
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               DPDNORMX;
+
+               /* FALL THROUGH */
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               DPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               DPDNORMX;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+               break;
+       }
+       assert(xm & DP_HIDDEN_BIT);
+       assert(ym & DP_HIDDEN_BIT);
+
+       /* provide guard,round and stick bit space */
+       xm <<= 3;
+       ym <<= 3;
+
+       if (xe > ye) {
+               /* have to shift y fraction right to align
+                */
+               int s = xe - ye;
+               ym = XDPSRS(ym, s);
+               ye += s;
+       } else if (ye > xe) {
+               /* have to shift x fraction right to align
+                */
+               int s = ye - xe;
+               xm = XDPSRS(xm, s);
+               xe += s;
+       }
+       assert(xe == ye);
+       assert(xe <= DP_EMAX);
+
+       if (xs == ys) {
+               /* generate 28 bit result of adding two 27 bit numbers
+                * leaving result in xm,xs,xe
+                */
+               xm = xm + ym;
+               xe = xe;
+               xs = xs;
+
+               if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */
+                       xm = XDPSRS1(xm);
+                       xe++;
+               }
+       } else {
+               if (xm >= ym) {
+                       xm = xm - ym;
+                       xe = xe;
+                       xs = xs;
+               } else {
+                       xm = ym - xm;
+                       xe = xe;
+                       xs = ys;
+               }
+               if (xm == 0)
+                       return ieee754dp_zero(ieee754_csr.rm ==
+                                             IEEE754_RD);
+
+               /* normalize to rounding precision */
+               while ((xm >> (DP_MBITS + 3)) == 0) {
+                       xm <<= 1;
+                       xe--;
+               }
+
+       }
+       DPNORMRET2(xs, xe, xm, "add", x, y);
+}
diff --git a/arch/mips/math-emu/dp_cmp.c b/arch/mips/math-emu/dp_cmp.c
new file mode 100644 (file)
index 0000000..34ec4a8
--- /dev/null
@@ -0,0 +1,58 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cmp)
+{
+       CLEARCX;
+
+       if (ieee754dp_isnan(x) || ieee754dp_isnan(y)) {
+               if (cmp & IEEE754_CUN)
+                       return 1;
+               if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
+                       if (SETCX(IEEE754_INVALID_OPERATION))
+                               return ieee754si_xcpt(0, "fcmpf", x);
+               }
+               return 0;
+       } else {
+               long long int vx = x.bits;
+               long long int vy = y.bits;
+
+               if (vx < 0)
+                       vx = -vx ^ DP_SIGN_BIT;
+               if (vy < 0)
+                       vy = -vy ^ DP_SIGN_BIT;
+
+               if (vx < vy)
+                       return (cmp & IEEE754_CLT) != 0;
+               else if (vx == vy)
+                       return (cmp & IEEE754_CEQ) != 0;
+               else
+                       return (cmp & IEEE754_CGT) != 0;
+       }
+}
diff --git a/arch/mips/math-emu/dp_div.c b/arch/mips/math-emu/dp_div.c
new file mode 100644 (file)
index 0000000..fea2a0c
--- /dev/null
@@ -0,0 +1,160 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y)
+{
+       COMPXDP;
+       COMPYDP;
+
+       CLEARCX;
+
+       EXPLODEXDP;
+       EXPLODEYDP;
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+               return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "div", x,
+                                        y);
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754dp_nanxcpt(y, "div", x, y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754dp_nanxcpt(x, "div", x, y);
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+               return ieee754dp_bestnan(x, y);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return x;
+
+
+               /* Infinity handeling 
+                */
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+               SETCX(IEEE754_INVALID_OPERATION);
+               return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y);
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+               return ieee754dp_zero(xs ^ ys);
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+               return ieee754dp_inf(xs ^ ys);
+
+               /* Zero handeling 
+                */
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+               SETCX(IEEE754_INVALID_OPERATION);
+               return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y);
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               SETCX(IEEE754_ZERO_DIVIDE);
+               return ieee754dp_xcpt(ieee754dp_inf(xs ^ ys), "div", x, y);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+               return ieee754dp_zero(xs == ys ? 0 : 1);
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               DPDNORMX;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               DPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               DPDNORMX;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+               break;
+       }
+       assert(xm & DP_HIDDEN_BIT);
+       assert(ym & DP_HIDDEN_BIT);
+
+       /* provide rounding space */
+       xm <<= 3;
+       ym <<= 3;
+
+       {
+               /* now the dirty work */
+
+               unsigned long long rm = 0;
+               int re = xe - ye;
+               unsigned long long bm;
+
+               for (bm = DP_MBIT(DP_MBITS + 2); bm; bm >>= 1) {
+                       if (xm >= ym) {
+                               xm -= ym;
+                               rm |= bm;
+                               if (xm == 0)
+                                       break;
+                       }
+                       xm <<= 1;
+               }
+               rm <<= 1;
+               if (xm)
+                       rm |= 1;        /* have remainder, set sticky */
+
+               assert(rm);
+
+               /* normalise rm to rounding precision ?
+                */
+               while ((rm >> (DP_MBITS + 3)) == 0) {
+                       rm <<= 1;
+                       re--;
+               }
+
+               DPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y);
+       }
+}
diff --git a/arch/mips/math-emu/dp_fint.c b/arch/mips/math-emu/dp_fint.c
new file mode 100644 (file)
index 0000000..6f7e861
--- /dev/null
@@ -0,0 +1,78 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_fint(int x)
+{
+       COMPXDP;
+
+       CLEARCX;
+
+       if (x == 0)
+               return ieee754dp_zero(0);
+       if (x == 1 || x == -1)
+               return ieee754dp_one(x < 0);
+       if (x == 10 || x == -10)
+               return ieee754dp_ten(x < 0);
+
+       xs = (x < 0);
+       if (xs) {
+               if (x == (1 << 31))
+                       xm = ((unsigned) 1 << 31);      /* max neg can't be safely negated */
+               else
+                       xm = -x;
+       } else {
+               xm = x;
+       }
+
+#if 1
+       /* normalize - result can never be inexact or overflow */
+       xe = DP_MBITS;
+       while ((xm >> DP_MBITS) == 0) {
+               xm <<= 1;
+               xe--;
+       }
+       return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+#else
+       /* normalize */
+       xe = DP_MBITS + 3;
+       while ((xm >> (DP_MBITS + 3)) == 0) {
+               xm <<= 1;
+               xe--;
+       }
+       DPNORMRET1(xs, xe, xm, "fint", x);
+#endif
+}
+
+ieee754dp ieee754dp_funs(unsigned int u)
+{
+       if ((int) u < 0)
+               return ieee754dp_add(ieee754dp_1e31(),
+                                    ieee754dp_fint(u & ~(1 << 31)));
+       return ieee754dp_fint(u);
+}
diff --git a/arch/mips/math-emu/dp_flong.c b/arch/mips/math-emu/dp_flong.c
new file mode 100644 (file)
index 0000000..7abf5ee
--- /dev/null
@@ -0,0 +1,76 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_flong(long long x)
+{
+       COMPXDP;
+
+       CLEARCX;
+
+       if (x == 0)
+               return ieee754dp_zero(0);
+       if (x == 1 || x == -1)
+               return ieee754dp_one(x < 0);
+       if (x == 10 || x == -10)
+               return ieee754dp_ten(x < 0);
+
+       xs = (x < 0);
+       if (xs) {
+               if (x == (1ULL << 63))
+                       xm = (1ULL << 63);      /* max neg can't be safely negated */
+               else
+                       xm = -x;
+       } else {
+               xm = x;
+       }
+
+       /* normalize */
+       xe = DP_MBITS + 3;
+       if (xm >> (DP_MBITS + 1 + 3)) {
+               /* shunt out overflow bits */
+               while (xm >> (DP_MBITS + 1 + 3)) {
+                       XDPSRSX1();
+               }
+       } else {
+               /* normalize in grs extended double precision */
+               while ((xm >> (DP_MBITS + 3)) == 0) {
+                       xm <<= 1;
+                       xe--;
+               }
+       }
+       DPNORMRET1(xs, xe, xm, "dp_flong", x);
+}
+
+ieee754dp ieee754dp_fulong(unsigned long long u)
+{
+       if ((long long) u < 0)
+               return ieee754dp_add(ieee754dp_1e63(),
+                                    ieee754dp_flong(u & ~(1ULL << 63)));
+       return ieee754dp_flong(u);
+}
diff --git a/arch/mips/math-emu/dp_frexp.c b/arch/mips/math-emu/dp_frexp.c
new file mode 100644 (file)
index 0000000..db2ef85
--- /dev/null
@@ -0,0 +1,53 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+/* close to ieeep754dp_logb 
+*/
+ieee754dp ieee754dp_frexp(ieee754dp x, int *eptr)
+{
+       COMPXDP;
+       CLEARCX;
+       EXPLODEXDP;
+
+       switch (xc) {
+       case IEEE754_CLASS_SNAN:
+       case IEEE754_CLASS_QNAN:
+       case IEEE754_CLASS_INF:
+       case IEEE754_CLASS_ZERO:
+               *eptr = 0;
+               return x;
+       case IEEE754_CLASS_DNORM:
+               DPDNORMX;
+               break;
+       case IEEE754_CLASS_NORM:
+               break;
+       }
+       *eptr = xe + 1;
+       return builddp(xs, -1 + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+}
diff --git a/arch/mips/math-emu/dp_fsp.c b/arch/mips/math-emu/dp_fsp.c
new file mode 100644 (file)
index 0000000..7749e11
--- /dev/null
@@ -0,0 +1,70 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_fsp(ieee754sp x)
+{
+       COMPXSP;
+
+       CLEARCX;
+
+       EXPLODEXSP;
+
+       switch (xc) {
+       case IEEE754_CLASS_QNAN:
+       case IEEE754_CLASS_SNAN:
+               return ieee754dp_nanxcpt(builddp(xs,
+                                                DP_EMAX + 1 + DP_EBIAS,
+                                                ((unsigned long long) xm
+                                                 << (DP_MBITS -
+                                                     SP_MBITS))), "fsp",
+                                        x);
+       case IEEE754_CLASS_INF:
+               return ieee754dp_inf(xs);
+       case IEEE754_CLASS_ZERO:
+               return ieee754dp_zero(xs);
+       case IEEE754_CLASS_DNORM:
+               /* normalize */
+               while ((xm >> SP_MBITS) == 0) {
+                       xm <<= 1;
+                       xe--;
+               }
+               break;
+       case IEEE754_CLASS_NORM:
+               break;
+       }
+
+       /* CANT possibly overflow,underflow, or need rounding
+        */
+
+       /* drop the hidden bit */
+       xm &= ~SP_HIDDEN_BIT;
+
+       return builddp(xs, xe + DP_EBIAS,
+                      (unsigned long long) xm << (DP_MBITS - SP_MBITS));
+}
diff --git a/arch/mips/math-emu/dp_logb.c b/arch/mips/math-emu/dp_logb.c
new file mode 100644 (file)
index 0000000..22aeb21
--- /dev/null
@@ -0,0 +1,54 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_logb(ieee754dp x)
+{
+       COMPXDP;
+
+       CLEARCX;
+
+       EXPLODEXDP;
+
+       switch (xc) {
+       case IEEE754_CLASS_SNAN:
+               return ieee754dp_nanxcpt(x, "logb", x);
+       case IEEE754_CLASS_QNAN:
+               return x;
+       case IEEE754_CLASS_INF:
+               return ieee754dp_inf(0);
+       case IEEE754_CLASS_ZERO:
+               return ieee754dp_inf(1);
+       case IEEE754_CLASS_DNORM:
+               DPDNORMX;
+               break;
+       case IEEE754_CLASS_NORM:
+               break;
+       }
+       return ieee754dp_fint(xe);
+}
diff --git a/arch/mips/math-emu/dp_modf.c b/arch/mips/math-emu/dp_modf.c
new file mode 100644 (file)
index 0000000..6bf0f2f
--- /dev/null
@@ -0,0 +1,80 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+/* modf function is always exact for a finite number
+*/
+ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip)
+{
+       COMPXDP;
+
+       CLEARCX;
+
+       EXPLODEXDP;
+
+       switch (xc) {
+       case IEEE754_CLASS_SNAN:
+       case IEEE754_CLASS_QNAN:
+       case IEEE754_CLASS_INF:
+       case IEEE754_CLASS_ZERO:
+               *ip = x;
+               return x;
+       case IEEE754_CLASS_DNORM:
+               /* far to small */
+               *ip = ieee754dp_zero(xs);
+               return x;
+       case IEEE754_CLASS_NORM:
+               break;
+       }
+       if (xe < 0) {
+               *ip = ieee754dp_zero(xs);
+               return x;
+       }
+       if (xe >= DP_MBITS) {
+               *ip = x;
+               return ieee754dp_zero(xs);
+       }
+       /* generate ipart mantissa by clearing bottom bits 
+        */
+       *ip = builddp(xs, xe + DP_EBIAS,
+                     ((xm >> (DP_MBITS - xe)) << (DP_MBITS - xe)) &
+                     ~DP_HIDDEN_BIT);
+
+       /* generate fpart mantissa by clearing top bits
+        * and normalizing (must be able to normalize)
+        */
+       xm = (xm << (64 - (DP_MBITS - xe))) >> (64 - (DP_MBITS - xe));
+       if (xm == 0)
+               return ieee754dp_zero(xs);
+
+       while ((xm >> DP_MBITS) == 0) {
+               xm <<= 1;
+               xe--;
+       }
+       return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+}
diff --git a/arch/mips/math-emu/dp_mul.c b/arch/mips/math-emu/dp_mul.c
new file mode 100644 (file)
index 0000000..9ec5d40
--- /dev/null
@@ -0,0 +1,180 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y)
+{
+       COMPXDP;
+       COMPYDP;
+
+       CLEARCX;
+
+       EXPLODEXDP;
+       EXPLODEYDP;
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+               return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "mul", x,
+                                        y);
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754dp_nanxcpt(y, "mul", x, y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754dp_nanxcpt(x, "mul", x, y);
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+               return ieee754dp_bestnan(x, y);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return x;
+
+
+               /* Infinity handeling */
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+               SETCX(IEEE754_INVALID_OPERATION);
+               return ieee754dp_xcpt(ieee754dp_indef(), "mul", x, y);
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+               return ieee754dp_inf(xs ^ ys);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               return ieee754dp_zero(xs ^ ys);
+
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               DPDNORMX;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               DPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               DPDNORMX;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+               break;
+       }
+       /* rm = xm * ym, re = xe+ye basicly */
+       assert(xm & DP_HIDDEN_BIT);
+       assert(ym & DP_HIDDEN_BIT);
+       {
+               int re = xe + ye;
+               int rs = xs ^ ys;
+               unsigned long long rm;
+
+               /* shunt to top of word */
+               xm <<= 64 - (DP_MBITS + 1);
+               ym <<= 64 - (DP_MBITS + 1);
+
+               /* multiply 32bits xm,ym to give high 32bits rm with stickness
+                */
+
+               /* 32 * 32 => 64 */
+#define DPXMULT(x,y)   ((unsigned long long)(x) * (unsigned long long)y)
+
+               {
+                       unsigned lxm = xm;
+                       unsigned hxm = xm >> 32;
+                       unsigned lym = ym;
+                       unsigned hym = ym >> 32;
+                       unsigned long long lrm;
+                       unsigned long long hrm;
+
+                       lrm = DPXMULT(lxm, lym);
+                       hrm = DPXMULT(hxm, hym);
+
+                       {
+                               unsigned long long t = DPXMULT(lxm, hym);
+                               {
+                                       unsigned long long at =
+                                           lrm + (t << 32);
+                                       hrm += at < lrm;
+                                       lrm = at;
+                               }
+                               hrm = hrm + (t >> 32);
+                       }
+
+                       {
+                               unsigned long long t = DPXMULT(hxm, lym);
+                               {
+                                       unsigned long long at =
+                                           lrm + (t << 32);
+                                       hrm += at < lrm;
+                                       lrm = at;
+                               }
+                               hrm = hrm + (t >> 32);
+                       }
+                       rm = hrm | (lrm != 0);
+               }
+
+               /*
+                * sticky shift down to normal rounding precision
+                */
+               if ((signed long long) rm < 0) {
+                       rm =
+                           (rm >> (64 - (DP_MBITS + 1 + 3))) |
+                           ((rm << (DP_MBITS + 1 + 3)) != 0);
+                       re++;
+               } else {
+                       rm =
+                           (rm >> (64 - (DP_MBITS + 1 + 3 + 1))) |
+                           ((rm << (DP_MBITS + 1 + 3 + 1)) != 0);
+               }
+               assert(rm & (DP_HIDDEN_BIT << 3));
+               DPNORMRET2(rs, re, rm, "mul", x, y);
+       }
+}
diff --git a/arch/mips/math-emu/dp_scalb.c b/arch/mips/math-emu/dp_scalb.c
new file mode 100644 (file)
index 0000000..bb01461
--- /dev/null
@@ -0,0 +1,58 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_scalb(ieee754dp x, int n)
+{
+       COMPXDP;
+
+       CLEARCX;
+
+       EXPLODEXDP;
+
+       switch (xc) {
+       case IEEE754_CLASS_SNAN:
+               return ieee754dp_nanxcpt(x, "scalb", x, n);
+       case IEEE754_CLASS_QNAN:
+       case IEEE754_CLASS_INF:
+       case IEEE754_CLASS_ZERO:
+               return x;
+       case IEEE754_CLASS_DNORM:
+               DPDNORMX;
+               break;
+       case IEEE754_CLASS_NORM:
+               break;
+       }
+       DPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n);
+}
+
+
+ieee754dp ieee754dp_ldexp(ieee754dp x, int n)
+{
+       return ieee754dp_scalb(x, n);
+}
diff --git a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c
new file mode 100644 (file)
index 0000000..f57eee2
--- /dev/null
@@ -0,0 +1,66 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+int ieee754dp_finite(ieee754dp x)
+{
+       return DPBEXP(x) != DP_EMAX + 1 + DP_EBIAS;
+}
+
+ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y)
+{
+       CLEARCX;
+       DPSIGN(x) = DPSIGN(y);
+       return x;
+}
+
+
+ieee754dp ieee754dp_neg(ieee754dp x)
+{
+       CLEARCX;
+
+       if (ieee754dp_isnan(x)) /* but not infinity */
+               return ieee754dp_nanxcpt(x, "neg", x);
+
+       /* quick fix up */
+       DPSIGN(x) ^= 1;
+       return x;
+}
+
+
+ieee754dp ieee754dp_abs(ieee754dp x)
+{
+       CLEARCX;
+
+       if (ieee754dp_isnan(x)) /* but not infinity */
+               return ieee754dp_nanxcpt(x, "abs", x);
+
+       /* quick fix up */
+       DPSIGN(x) = 0;
+       return x;
+}
diff --git a/arch/mips/math-emu/dp_sqrt.c b/arch/mips/math-emu/dp_sqrt.c
new file mode 100644 (file)
index 0000000..1f9fa9c
--- /dev/null
@@ -0,0 +1,167 @@
+/* IEEE754 floating point arithmetic
+ * double precision square root
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+static const struct ieee754dp_konst knan = {
+#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
+       0, 0, DP_EBIAS + DP_EMAX + 1, 0
+#else
+       0, DP_EBIAS + DP_EMAX + 1, 0, 0
+#endif
+};
+
+#define nan    ((ieee754dp)knan)
+
+static const unsigned table[] = {
+       0, 1204, 3062, 5746, 9193, 13348, 18162, 23592,
+       29598, 36145, 43202, 50740, 58733, 67158, 75992,
+       85215, 83599, 71378, 60428, 50647, 41945, 34246,
+       27478, 21581, 16499, 12183, 8588, 5674, 3403,
+       1742, 661, 130
+};
+
+ieee754dp ieee754dp_sqrt(ieee754dp x)
+{
+       struct ieee754_csr oldcsr;
+       ieee754dp y, z, t;
+       unsigned scalx, yh;
+       COMPXDP;
+
+       EXPLODEXDP;
+
+       /* x == INF or NAN? */
+       switch (xc) {
+       case IEEE754_CLASS_QNAN:
+       case IEEE754_CLASS_SNAN:
+               /* sqrt(Nan) = Nan */
+               return ieee754dp_nanxcpt(x, "sqrt");
+       case IEEE754_CLASS_ZERO:
+               /* sqrt(0) = 0 */
+               return x;
+       case IEEE754_CLASS_INF:
+               if (xs)
+                       /* sqrt(-Inf) = Nan */
+                       return ieee754dp_nanxcpt(nan, "sqrt");
+               /* sqrt(+Inf) = Inf */
+               return x;
+       case IEEE754_CLASS_DNORM:
+               DPDNORMX;
+               /* fall through */
+       case IEEE754_CLASS_NORM:
+               if (xs)
+                       /* sqrt(-x) = Nan */
+                       return ieee754dp_nanxcpt(nan, "sqrt");
+               break;
+       }
+
+       /* save old csr; switch off INX enable & flag; set RN rounding */
+       oldcsr = ieee754_csr;
+       ieee754_csr.mx &= ~IEEE754_INEXACT;
+       ieee754_csr.sx &= ~IEEE754_INEXACT;
+       ieee754_csr.rm = IEEE754_RN;
+
+       /* adjust exponent to prevent overflow */
+       scalx = 0;
+       if (xe > 512) {         /* x > 2**-512? */
+               xe -= 512;      /* x = x / 2**512 */
+               scalx += 256;
+       } else if (xe < -512) { /* x < 2**-512? */
+               xe += 512;      /* x = x * 2**512 */
+               scalx -= 256;
+       }
+
+       y = x = builddp(0, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+
+       /* magic initial approximation to almost 8 sig. bits */
+       yh = y.bits >> 32;
+       yh = (yh >> 1) + 0x1ff80000;
+       yh = yh - table[(yh >> 15) & 31];
+       y.bits = ((unsigned long long) yh << 32) | (y.bits & 0xffffffff);
+
+       /* Heron's rule once with correction to improve to ~18 sig. bits */
+       /* t=x/y; y=y+t; py[n0]=py[n0]-0x00100006; py[n1]=0; */
+       t = ieee754dp_div(x, y);
+       y = ieee754dp_add(y, t);
+       y.bits -= 0x0010000600000000LL;
+       y.bits &= 0xffffffff00000000LL;
+
+       /* triple to almost 56 sig. bits: y ~= sqrt(x) to within 1 ulp */
+       /* t=y*y; z=t;  pt[n0]+=0x00100000; t+=z; z=(x-z)*y; */
+       z = t = ieee754dp_mul(y, y);
+       t.parts.bexp += 0x001;
+       t = ieee754dp_add(t, z);
+       z = ieee754dp_mul(ieee754dp_sub(x, z), y);
+
+       /* t=z/(t+x) ;  pt[n0]+=0x00100000; y+=t; */
+       t = ieee754dp_div(z, ieee754dp_add(t, x));
+       t.parts.bexp += 0x001;
+       y = ieee754dp_add(y, t);
+
+       /* twiddle last bit to force y correctly rounded */
+
+       /* set RZ, clear INEX flag */
+       ieee754_csr.rm = IEEE754_RZ;
+       ieee754_csr.sx &= ~IEEE754_INEXACT;
+
+       /* t=x/y; ...chopped quotient, possibly inexact */
+       t = ieee754dp_div(x, y);
+
+       if (ieee754_csr.sx & IEEE754_INEXACT || t.bits != y.bits) {
+
+               if (!(ieee754_csr.sx & IEEE754_INEXACT))
+                       /* t = t-ulp */
+                       t.bits -= 1;
+
+               /* add inexact to result status */
+               oldcsr.cx |= IEEE754_INEXACT;
+               oldcsr.sx |= IEEE754_INEXACT;
+
+               switch (oldcsr.rm) {
+               case IEEE754_RP:
+                       y.bits += 1;
+                       /* drop through */
+               case IEEE754_RN:
+                       t.bits += 1;
+                       break;
+               }
+
+               /* y=y+t; ...chopped sum */
+               y = ieee754dp_add(y, t);
+
+               /* adjust scalx for correctly rounded sqrt(x) */
+               scalx -= 1;
+       }
+
+       /* py[n0]=py[n0]+scalx; ...scale back y */
+       y.parts.bexp += scalx;
+
+       /* restore rounding mode, possibly set inexact */
+       ieee754_csr = oldcsr;
+
+       return y;
+}
diff --git a/arch/mips/math-emu/dp_sub.c b/arch/mips/math-emu/dp_sub.c
new file mode 100644 (file)
index 0000000..198e560
--- /dev/null
@@ -0,0 +1,193 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)
+{
+       COMPXDP;
+       COMPYDP;
+
+       CLEARCX;
+
+       EXPLODEXDP;
+       EXPLODEYDP;
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+               return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "sub", x,
+                                        y);
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754dp_nanxcpt(y, "sub", x, y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754dp_nanxcpt(x, "sub", x, y);
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+               return ieee754dp_bestnan(x, y);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return x;
+
+
+               /* Inifity handeling 
+                */
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+               if (xs != ys)
+                       return x;
+               SETCX(IEEE754_INVALID_OPERATION);
+               return ieee754dp_xcpt(ieee754dp_indef(), "sub", x, y);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+               return ieee754dp_inf(ys ^ 1);
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+               return x;
+
+               /* Zero handeling 
+                */
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+               if (xs != ys)
+                       return x;
+               else
+                       return ieee754dp_zero(ieee754_csr.rm ==
+                                             IEEE754_RD);
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               return x;
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+               /* quick fix up */
+               DPSIGN(y) ^= 1;
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               DPDNORMX;
+               /* FAAL THOROUGH */
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               /* normalize ym,ye */
+               DPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               /* normalize xm,xe */
+               DPDNORMX;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+               break;
+       }
+       /* flip sign of y and handle as add */
+       ys ^= 1;
+
+       assert(xm & DP_HIDDEN_BIT);
+       assert(ym & DP_HIDDEN_BIT);
+
+
+       /* provide guard,round and stick bit dpace */
+       xm <<= 3;
+       ym <<= 3;
+
+       if (xe > ye) {
+               /* have to shift y fraction right to align
+                */
+               int s = xe - ye;
+               ym = XDPSRS(ym, s);
+               ye += s;
+       } else if (ye > xe) {
+               /* have to shift x fraction right to align
+                */
+               int s = ye - xe;
+               xm = XDPSRS(xm, s);
+               xe += s;
+       }
+       assert(xe == ye);
+       assert(xe <= DP_EMAX);
+
+       if (xs == ys) {
+               /* generate 28 bit result of adding two 27 bit numbers
+                */
+               xm = xm + ym;
+               xe = xe;
+               xs = xs;
+
+               if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */
+                       xm = XDPSRS1(xm);       /* shift preserving sticky */
+                       xe++;
+               }
+       } else {
+               if (xm >= ym) {
+                       xm = xm - ym;
+                       xe = xe;
+                       xs = xs;
+               } else {
+                       xm = ym - xm;
+                       xe = xe;
+                       xs = ys;
+               }
+               if (xm == 0)
+                       if (ieee754_csr.rm == IEEE754_RD)
+                               return ieee754dp_zero(1);       /* round negative inf. => sign = -1 */
+                       else
+                               return ieee754dp_zero(0);       /* other round modes   => sign = 1 */
+
+               /* normalize to rounding precision 
+                */
+               while ((xm >> (DP_MBITS + 3)) == 0) {
+                       xm <<= 1;
+                       xe--;
+               }
+       }
+       DPNORMRET2(xs, xe, xm, "sub", x, y);
+}
diff --git a/arch/mips/math-emu/dp_tint.c b/arch/mips/math-emu/dp_tint.c
new file mode 100644 (file)
index 0000000..c8a151b
--- /dev/null
@@ -0,0 +1,88 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <linux/kernel.h>
+#include "ieee754dp.h"
+
+int ieee754dp_tint(ieee754dp x)
+{
+       COMPXDP;
+
+       CLEARCX;
+
+       EXPLODEXDP;
+
+       switch (xc) {
+       case IEEE754_CLASS_SNAN:
+       case IEEE754_CLASS_QNAN:
+               SETCX(IEEE754_INVALID_OPERATION);
+               return ieee754si_xcpt(ieee754si_indef(), "fixdp", x);
+       case IEEE754_CLASS_INF:
+               SETCX(IEEE754_OVERFLOW);
+               return ieee754si_xcpt(ieee754si_indef(), "fixdp", x);
+       case IEEE754_CLASS_ZERO:
+               return 0;
+       case IEEE754_CLASS_DNORM:       /* much to small */
+               SETCX(IEEE754_UNDERFLOW);
+               return ieee754si_xcpt(0, "fixdp", x);
+       case IEEE754_CLASS_NORM:
+               break;
+       }
+       if (xe >= 31) {
+               SETCX(IEEE754_OVERFLOW);
+               return ieee754si_xcpt(ieee754si_indef(), "fix", x);
+       }
+       if (xe < 0) {
+               SETCX(IEEE754_UNDERFLOW);
+               return ieee754si_xcpt(0, "fix", x);
+       }
+       /* oh gawd */
+       if (xe > DP_MBITS) {
+               xm <<= xe - DP_MBITS;
+       } else if (xe < DP_MBITS) {
+               /* XXX no rounding 
+                */
+               xm >>= DP_MBITS - xe;
+       }
+       if (xs)
+               return -xm;
+       else
+               return xm;
+}
+
+
+unsigned int ieee754dp_tuns(ieee754dp x)
+{
+       ieee754dp hb = ieee754dp_1e31();
+
+       /* what if x < 0 ?? */
+       if (ieee754dp_lt(x, hb))
+               return (unsigned) ieee754dp_tint(x);
+
+       return (unsigned) ieee754dp_tint(ieee754dp_sub(x, hb)) |
+           ((unsigned) 1 << 31);
+}
diff --git a/arch/mips/math-emu/dp_tlong.c b/arch/mips/math-emu/dp_tlong.c
new file mode 100644 (file)
index 0000000..cc8cf0f
--- /dev/null
@@ -0,0 +1,141 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+long long ieee754dp_tlong(ieee754dp x)
+{
+       COMPXDP;
+
+       CLEARCX;
+
+       EXPLODEXDP;
+
+       switch (xc) {
+       case IEEE754_CLASS_SNAN:
+       case IEEE754_CLASS_QNAN:
+               SETCX(IEEE754_INVALID_OPERATION);
+               return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+       case IEEE754_CLASS_INF:
+               SETCX(IEEE754_OVERFLOW);
+               return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+       case IEEE754_CLASS_ZERO:
+               return 0;
+       case IEEE754_CLASS_DNORM:       /* much too small */
+               SETCX(IEEE754_UNDERFLOW);
+               return ieee754di_xcpt(0, "dp_tlong", x);
+       case IEEE754_CLASS_NORM:
+               break;
+       }
+       if (xe >= 63) {
+               SETCX(IEEE754_OVERFLOW);
+               return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+       }
+       if (xe < 0) {
+               if (ieee754_csr.rm == IEEE754_RU) {
+                       if (xs) {       /* Negative  */
+                               return 0x0000000000000000LL;
+                       } else {        /* Positive */
+                               return 0x0000000000000001LL;
+                       }
+               } else if (ieee754_csr.rm == IEEE754_RD) {
+                       if (xs) {       /* Negative , return -1 */
+                               return 0xffffffffffffffffLL;
+                       } else {        /* Positive */
+                               return 0x0000000000000000LL;
+                       }
+               } else {
+                       SETCX(IEEE754_UNDERFLOW);
+                       return ieee754di_xcpt(0, "dp_tlong", x);
+               }
+       }
+       /* oh gawd */
+       if (xe > DP_MBITS) {
+               xm <<= xe - DP_MBITS;
+       } else if (xe < DP_MBITS) {
+               unsigned long long residue;
+               unsigned long long mask = 0;
+               int i;
+               int round;
+               int sticky;
+               int odd;
+
+               /* compute mask */
+               for (i = 0; i < DP_MBITS - xe; i++) {
+                       mask = mask << 1;
+                       mask = mask | 0x1;
+               }
+               residue = (xm & mask) << (64 - (DP_MBITS - xe));
+               round =
+                   ((0x8000000000000000LL & residue) !=
+                    0x0000000000000000LL);
+               sticky =
+                   ((0x7fffffffffffffffLL & residue) !=
+                    0x0000000000000000LL);
+
+               xm >>= DP_MBITS - xe;
+
+               odd = ((xm & 0x1) != 0x0000000000000000LL);
+
+               /* Do the rounding */
+               if (!round && sticky) {
+                       if ((ieee754_csr.rm == IEEE754_RU && !xs)
+                           || (ieee754_csr.rm == IEEE754_RD && xs)) {
+                               xm++;
+                       }
+               } else if (round && !sticky) {
+                       if ((ieee754_csr.rm == IEEE754_RU && !xs)
+                           || (ieee754_csr.rm == IEEE754_RD && xs)
+                           || (ieee754_csr.rm == IEEE754_RN && odd)) {
+                               xm++;
+                       }
+               } else if (round && sticky) {
+                       if ((ieee754_csr.rm == IEEE754_RU && !xs)
+                           || (ieee754_csr.rm == IEEE754_RD && xs)
+                           || (ieee754_csr.rm == IEEE754_RN)) {
+                               xm++;
+                       }
+               }
+       }
+       if (xs)
+               return -xm;
+       else
+               return xm;
+}
+
+
+unsigned long long ieee754dp_tulong(ieee754dp x)
+{
+       ieee754dp hb = ieee754dp_1e63();
+
+       /* what if x < 0 ?? */
+       if (ieee754dp_lt(x, hb))
+               return (unsigned long long) ieee754dp_tlong(x);
+
+       return (unsigned long long) ieee754dp_tlong(ieee754dp_sub(x, hb)) |
+           (1ULL << 63);
+}
diff --git a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c
new file mode 100644 (file)
index 0000000..5e86e40
--- /dev/null
@@ -0,0 +1,138 @@
+/* ieee754 floating point arithmetic
+ * single and double precision
+ *
+ * BUGS
+ * not much dp done
+ * doesnt generate IEEE754_INEXACT
+ *
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754int.h"
+
+#define DP_EBIAS       1023
+#define DP_EMIN                (-1022)
+#define DP_EMAX                1023
+
+#define SP_EBIAS       127
+#define SP_EMIN                (-126)
+#define SP_EMAX                127
+
+/* indexed by class */
+const char *const ieee754_cname[] = {
+       "Normal",
+       "Zero",
+       "Denormal",
+       "Infinity",
+       "QNaN",
+       "SNaN",
+};
+
+/* the control status register 
+*/
+struct ieee754_csr ieee754_csr;
+
+/* special constants
+*/
+
+
+#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
+#define SPSTR(s,b,m) {m,b,s}
+#define DPSTR(s,b,mh,ml) {ml,mh,b,s}
+#endif
+
+#ifdef __MIPSEB__
+#define SPSTR(s,b,m) {s,b,m}
+#define DPSTR(s,b,mh,ml) {s,b,mh,ml}
+#endif
+
+const struct ieee754dp_konst __ieee754dp_spcvals[] = {
+       DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* + zero   */
+       DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* - zero   */
+       DPSTR(0, DP_EBIAS, 0, 0),       /* + 1.0   */
+       DPSTR(1, DP_EBIAS, 0, 0),       /* - 1.0   */
+       DPSTR(0, 3 + DP_EBIAS, 0x40000, 0),     /* + 10.0   */
+       DPSTR(1, 3 + DP_EBIAS, 0x40000, 0),     /* - 10.0   */
+       DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* + infinity */
+       DPSTR(1, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* - infinity */
+       DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0x40000, 0),   /* + indef quiet Nan */
+       DPSTR(0, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF),      /* + max */
+       DPSTR(1, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF),      /* - max */
+       DPSTR(0, DP_EMIN + DP_EBIAS, 0, 0),     /* + min normal */
+       DPSTR(1, DP_EMIN + DP_EBIAS, 0, 0),     /* - min normal */
+       DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* + min denormal */
+       DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* - min denormal */
+       DPSTR(0, 31 + DP_EBIAS, 0, 0),  /* + 1.0e31 */
+       DPSTR(0, 63 + DP_EBIAS, 0, 0),  /* + 1.0e63 */
+};
+
+const struct ieee754sp_konst __ieee754sp_spcvals[] = {
+       SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 0),    /* + zero   */
+       SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 0),    /* - zero   */
+       SPSTR(0, SP_EBIAS, 0),  /* + 1.0   */
+       SPSTR(1, SP_EBIAS, 0),  /* - 1.0   */
+       SPSTR(0, 3 + SP_EBIAS, 0x200000),       /* + 10.0   */
+       SPSTR(1, 3 + SP_EBIAS, 0x200000),       /* - 10.0   */
+       SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0),    /* + infinity */
+       SPSTR(1, SP_EMAX + 1 + SP_EBIAS, 0),    /* - infinity */
+       SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0x200000),     /* + indef quiet Nan  */
+       SPSTR(0, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* + max normal */
+       SPSTR(1, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* - max normal */
+       SPSTR(0, SP_EMIN + SP_EBIAS, 0),        /* + min normal */
+       SPSTR(1, SP_EMIN + SP_EBIAS, 0),        /* - min normal */
+       SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 1),    /* + min denormal */
+       SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 1),    /* - min denormal */
+       SPSTR(0, 31 + SP_EBIAS, 0),     /* + 1.0e31 */
+       SPSTR(0, 63 + SP_EBIAS, 0),     /* + 1.0e63 */
+};
+
+
+int ieee754si_xcpt(int r, const char *op, ...)
+{
+       struct ieee754xctx ax;
+
+       if (!TSTX())
+               return r;
+       ax.op = op;
+       ax.rt = IEEE754_RT_SI;
+       ax.rv.si = r;
+       va_start(ax.ap, op);
+       ieee754_xcpt(&ax);
+       return ax.rv.si;
+}
+
+long long ieee754di_xcpt(long long r, const char *op, ...)
+{
+       struct ieee754xctx ax;
+
+       if (!TSTX())
+               return r;
+       ax.op = op;
+       ax.rt = IEEE754_RT_DI;
+       ax.rv.di = r;
+       va_start(ax.ap, op);
+       ieee754_xcpt(&ax);
+       return ax.rv.di;
+}
diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h
new file mode 100644 (file)
index 0000000..ad2c91a
--- /dev/null
@@ -0,0 +1,490 @@
+/* single and double precision fp ops
+ * missing extended precision.
+*/
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+/**************************************************************************
+ *  Nov 7, 2000
+ *  Modification to allow integration with Linux kernel 
+ *
+ *  Kevin D. Kissell, kevink@mips.com and Carsten Langgard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *************************************************************************/
+
+#ifdef __KERNEL__
+/* Going from Algorithmics to Linux native environment, add this */
+#include <linux/types.h>
+
+/* 
+ * Not very pretty, but the Linux kernel's normal va_list definition 
+ * does not allow it to be used as a structure element, as it is here.
+ */
+#ifndef _STDARG_H
+#include <stdarg.h>
+#endif
+
+#else
+
+/* Note that __KERNEL__ is taken to mean Linux kernel */
+
+#if #system(OpenBSD)
+#include <machine/types.h>
+#endif
+#include <machine/endian.h>
+
+#endif                         /* __KERNEL__ */
+
+#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
+struct ieee754dp_konst {
+       unsigned mantlo:32;
+       unsigned manthi:20;
+       unsigned bexp:11;
+       unsigned sign:1;
+};
+struct ieee754sp_konst {
+       unsigned mant:23;
+       unsigned bexp:8;
+       unsigned sign:1;
+};
+
+typedef union _ieee754dp {
+       struct ieee754dp_konst oparts;
+       struct {
+               unsigned long long mant:52;
+               unsigned int bexp:11;
+               unsigned int sign:1;
+       } parts;
+       unsigned long long bits;
+       double d;
+} ieee754dp;
+
+typedef union _ieee754sp {
+       struct ieee754sp_konst parts;
+       float f;
+       unsigned long bits;
+} ieee754sp;
+#endif
+
+#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
+struct ieee754dp_konst {
+       unsigned sign:1;
+       unsigned bexp:11;
+       unsigned manthi:20;
+       unsigned mantlo:32;
+};
+typedef union _ieee754dp {
+       struct ieee754dp_konst oparts;
+       struct {
+               unsigned int sign:1;
+               unsigned int bexp:11;
+               unsigned long long mant:52;
+       } parts;
+       double d;
+       unsigned long long bits;
+} ieee754dp;
+
+struct ieee754sp_konst {
+       unsigned sign:1;
+       unsigned bexp:8;
+       unsigned mant:23;
+};
+
+typedef union _ieee754sp {
+       struct ieee754sp_konst parts;
+       float f;
+       unsigned long bits;
+} ieee754sp;
+#endif
+
+/*
+ * single precision (often aka float)
+*/
+int ieee754sp_finite(ieee754sp x);
+int ieee754sp_class(ieee754sp x);
+
+ieee754sp ieee754sp_abs(ieee754sp x);
+ieee754sp ieee754sp_neg(ieee754sp x);
+ieee754sp ieee754sp_scalb(ieee754sp x, int);
+ieee754sp ieee754sp_logb(ieee754sp x);
+
+/* x with sign of y */
+ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y);
+
+ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y);
+ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y);
+ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y);
+ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y);
+
+ieee754sp ieee754sp_fint(int x);
+ieee754sp ieee754sp_funs(unsigned x);
+ieee754sp ieee754sp_flong(long long x);
+ieee754sp ieee754sp_fulong(unsigned long long x);
+ieee754sp ieee754sp_fdp(ieee754dp x);
+
+int ieee754sp_tint(ieee754sp x);
+unsigned int ieee754sp_tuns(ieee754sp x);
+long long ieee754sp_tlong(ieee754sp x);
+unsigned long long ieee754sp_tulong(ieee754sp x);
+
+int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cop);
+/*
+ * basic sp math
+ */
+ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip);
+ieee754sp ieee754sp_frexp(ieee754sp x, int *exp);
+ieee754sp ieee754sp_ldexp(ieee754sp x, int exp);
+
+ieee754sp ieee754sp_ceil(ieee754sp x);
+ieee754sp ieee754sp_floor(ieee754sp x);
+ieee754sp ieee754sp_trunc(ieee754sp x);
+
+ieee754sp ieee754sp_sqrt(ieee754sp x);
+
+/*
+ * double precision (often aka double)
+*/
+int ieee754dp_finite(ieee754dp x);
+int ieee754dp_class(ieee754dp x);
+
+/* x with sign of y */
+ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y);
+
+ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y);
+ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y);
+ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y);
+ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y);
+
+ieee754dp ieee754dp_abs(ieee754dp x);
+ieee754dp ieee754dp_neg(ieee754dp x);
+ieee754dp ieee754dp_scalb(ieee754dp x, int);
+
+/* return exponent as integer in floating point format 
+ */
+ieee754dp ieee754dp_logb(ieee754dp x);
+
+ieee754dp ieee754dp_fint(int x);
+ieee754dp ieee754dp_funs(unsigned x);
+ieee754dp ieee754dp_flong(long long x);
+ieee754dp ieee754dp_fulong(unsigned long long x);
+ieee754dp ieee754dp_fsp(ieee754sp x);
+
+ieee754dp ieee754dp_ceil(ieee754dp x);
+ieee754dp ieee754dp_floor(ieee754dp x);
+ieee754dp ieee754dp_trunc(ieee754dp x);
+
+int ieee754dp_tint(ieee754dp x);
+unsigned int ieee754dp_tuns(ieee754dp x);
+long long ieee754dp_tlong(ieee754dp x);
+unsigned long long ieee754dp_tulong(ieee754dp x);
+
+int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cop);
+/*
+ * basic sp math
+ */
+ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip);
+ieee754dp ieee754dp_frexp(ieee754dp x, int *exp);
+ieee754dp ieee754dp_ldexp(ieee754dp x, int exp);
+
+ieee754dp ieee754dp_ceil(ieee754dp x);
+ieee754dp ieee754dp_floor(ieee754dp x);
+ieee754dp ieee754dp_trunc(ieee754dp x);
+
+ieee754dp ieee754dp_sqrt(ieee754dp x);
+
+
+
+/* 5 types of floating point number 
+*/
+#define IEEE754_CLASS_NORM     0x00
+#define IEEE754_CLASS_ZERO     0x01
+#define IEEE754_CLASS_DNORM    0x02
+#define IEEE754_CLASS_INF      0x03
+#define IEEE754_CLASS_SNAN     0x04
+#define IEEE754_CLASS_QNAN     0x05
+extern const char *const ieee754_cname[];
+
+/* exception numbers */
+#define IEEE754_INEXACT                        0x01
+#define IEEE754_UNDERFLOW              0x02
+#define IEEE754_OVERFLOW               0x04
+#define IEEE754_ZERO_DIVIDE            0x08
+#define IEEE754_INVALID_OPERATION      0x10
+
+/* cmp operators
+*/
+#define IEEE754_CLT    0x01
+#define IEEE754_CEQ    0x02
+#define IEEE754_CGT    0x04
+#define IEEE754_CUN    0x08
+
+/* rounding mode 
+*/
+#define IEEE754_RN     0       /* round to nearest */
+#define IEEE754_RZ     1       /* round toward zero  */
+#define IEEE754_RD     2       /* round toward -Infinity */
+#define IEEE754_RU     3       /* round toward +Infinity */
+
+/* other naming */
+#define IEEE754_RM     IEEE754_RD
+#define IEEE754_RP     IEEE754_RU
+
+/* "normal" comparisons
+*/
+static __inline int ieee754sp_eq(ieee754sp x, ieee754sp y)
+{
+       return ieee754sp_cmp(x, y, IEEE754_CEQ);
+}
+
+static __inline int ieee754sp_ne(ieee754sp x, ieee754sp y)
+{
+       return ieee754sp_cmp(x, y,
+                            IEEE754_CLT | IEEE754_CGT | IEEE754_CUN);
+}
+
+static __inline int ieee754sp_lt(ieee754sp x, ieee754sp y)
+{
+       return ieee754sp_cmp(x, y, IEEE754_CLT);
+}
+
+static __inline int ieee754sp_le(ieee754sp x, ieee754sp y)
+{
+       return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ);
+}
+
+static __inline int ieee754sp_gt(ieee754sp x, ieee754sp y)
+{
+       return ieee754sp_cmp(x, y, IEEE754_CGT);
+}
+
+
+static __inline int ieee754sp_ge(ieee754sp x, ieee754sp y)
+{
+       return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ);
+}
+
+static __inline int ieee754dp_eq(ieee754dp x, ieee754dp y)
+{
+       return ieee754dp_cmp(x, y, IEEE754_CEQ);
+}
+
+static __inline int ieee754dp_ne(ieee754dp x, ieee754dp y)
+{
+       return ieee754dp_cmp(x, y,
+                            IEEE754_CLT | IEEE754_CGT | IEEE754_CUN);
+}
+
+static __inline int ieee754dp_lt(ieee754dp x, ieee754dp y)
+{
+       return ieee754dp_cmp(x, y, IEEE754_CLT);
+}
+
+static __inline int ieee754dp_le(ieee754dp x, ieee754dp y)
+{
+       return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ);
+}
+
+static __inline int ieee754dp_gt(ieee754dp x, ieee754dp y)
+{
+       return ieee754dp_cmp(x, y, IEEE754_CGT);
+}
+
+static __inline int ieee754dp_ge(ieee754dp x, ieee754dp y)
+{
+       return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ);
+}
+
+
+/* like strtod
+*/
+ieee754dp ieee754dp_fstr(const char *s, char **endp);
+char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af);
+
+
+/* the control status register 
+*/
+struct ieee754_csr {
+       unsigned pad:13;
+       unsigned noq:1;         /* set 1 for no quiet NaN's */
+       unsigned nod:1;         /* set 1 for no denormalised numbers */
+       unsigned cx:5;          /* exceptions this operation */
+       unsigned mx:5;          /* exception enable  mask */
+       unsigned sx:5;          /* exceptions total */
+       unsigned rm:2;          /* current rounding mode */
+};
+extern struct ieee754_csr ieee754_csr;
+
+static __inline unsigned ieee754_getrm(void)
+{
+       return (ieee754_csr.rm);
+}
+static __inline unsigned ieee754_setrm(unsigned rm)
+{
+       return (ieee754_csr.rm = rm);
+}
+
+/*
+ * get current exceptions
+ */
+static __inline unsigned ieee754_getcx(void)
+{
+       return (ieee754_csr.cx);
+}
+
+/* test for current exception condition 
+ */
+static __inline int ieee754_cxtest(unsigned n)
+{
+       return (ieee754_csr.cx & n);
+}
+
+/*
+ * get sticky exceptions
+ */
+static __inline unsigned ieee754_getsx(void)
+{
+       return (ieee754_csr.sx);
+}
+
+/* clear sticky conditions
+*/
+static __inline unsigned ieee754_clrsx(void)
+{
+       return (ieee754_csr.sx = 0);
+}
+
+/* test for sticky exception condition 
+ */
+static __inline int ieee754_sxtest(unsigned n)
+{
+       return (ieee754_csr.sx & n);
+}
+
+/* debugging */
+ieee754sp ieee754sp_dump(char *s, ieee754sp x);
+ieee754dp ieee754dp_dump(char *s, ieee754dp x);
+
+#define IEEE754_SPCVAL_PZERO   0
+#define IEEE754_SPCVAL_NZERO   1
+#define IEEE754_SPCVAL_PONE    2
+#define IEEE754_SPCVAL_NONE    3
+#define IEEE754_SPCVAL_PTEN    4
+#define IEEE754_SPCVAL_NTEN    5
+#define IEEE754_SPCVAL_PINFINITY       6
+#define IEEE754_SPCVAL_NINFINITY       7
+#define IEEE754_SPCVAL_INDEF   8
+#define IEEE754_SPCVAL_PMAX    9       /* +max norm */
+#define IEEE754_SPCVAL_NMAX    10      /* -max norm */
+#define IEEE754_SPCVAL_PMIN    11      /* +min norm */
+#define IEEE754_SPCVAL_NMIN    12      /* +min norm */
+#define IEEE754_SPCVAL_PMIND   13      /* +min denorm */
+#define IEEE754_SPCVAL_NMIND   14      /* +min denorm */
+#define IEEE754_SPCVAL_P1E31   15      /* + 1.0e31 */
+#define IEEE754_SPCVAL_P1E63   16      /* + 1.0e63 */
+
+extern const struct ieee754dp_konst __ieee754dp_spcvals[];
+extern const struct ieee754sp_konst __ieee754sp_spcvals[];
+#define ieee754dp_spcvals ((const ieee754dp *)__ieee754dp_spcvals)
+#define ieee754sp_spcvals ((const ieee754sp *)__ieee754sp_spcvals)
+
+/* return infinity with given sign
+*/
+#define ieee754dp_inf(sn)      \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
+#define ieee754dp_zero(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
+#define ieee754dp_one(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
+#define ieee754dp_ten(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
+#define ieee754dp_indef() \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_INDEF])
+#define ieee754dp_max(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
+#define ieee754dp_min(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
+#define ieee754dp_mind(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
+#define ieee754dp_1e31() \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_P1E31])
+#define ieee754dp_1e63() \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_P1E63])
+
+#define ieee754sp_inf(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
+#define ieee754sp_zero(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
+#define ieee754sp_one(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
+#define ieee754sp_ten(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
+#define ieee754sp_indef() \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_INDEF])
+#define ieee754sp_max(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
+#define ieee754sp_min(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
+#define ieee754sp_mind(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
+#define ieee754sp_1e31() \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_P1E31])
+#define ieee754sp_1e63() \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_P1E63])
+
+/* indefinite integer value 
+*/
+#define ieee754si_indef()      INT_MIN
+#ifdef LONG_LONG_MIN
+#define ieee754di_indef()      LONG_LONG_MIN
+#else
+#define ieee754di_indef()      (-9223372036854775807LL-1)
+#endif
+
+/* IEEE exception context, passed to handler */
+struct ieee754xctx {
+       const char *op;         /* operation name */
+       int rt;                 /* result type */
+       union {
+               ieee754sp sp;   /* single precision */
+               ieee754dp dp;   /* double precision */
+#ifdef IEEE854_XP
+               ieee754xp xp;   /* extended precision */
+#endif
+               int si;         /* standard signed integer (32bits) */
+               long long di;   /* extended signed integer (64bits) */
+       } rv;                   /* default result format implied by op */
+       va_list ap;
+};
+
+/* result types for xctx.rt */
+#define IEEE754_RT_SP  0
+#define IEEE754_RT_DP  1
+#define IEEE754_RT_XP  2
+#define IEEE754_RT_SI  3
+#define IEEE754_RT_DI  4
+
+extern void ieee754_xcpt(struct ieee754xctx *xcp);
+
+/* compat */
+#define ieee754dp_fix(x)       ieee754dp_tint(x)
+#define ieee754sp_fix(x)       ieee754sp_tint(x)
diff --git a/arch/mips/math-emu/ieee754d.c b/arch/mips/math-emu/ieee754d.c
new file mode 100644 (file)
index 0000000..b25c8c0
--- /dev/null
@@ -0,0 +1,142 @@
+/* some debug functions
+*/
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+/**************************************************************************
+ *  Nov 7, 2000
+ *  Modified to build and operate in Linux kernel environment. 
+ *
+ *  Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *************************************************************************/
+
+#include "ieee754.h"
+
+#define DP_EBIAS       1023
+#define DP_EMIN                (-1022)
+#define DP_EMAX                1023
+#define DP_FBITS       52
+
+#define SP_EBIAS       127
+#define SP_EMIN                (-126)
+#define SP_EMAX                127
+#define SP_FBITS       23
+
+#define DP_MBIT(x)     ((unsigned long long)1 << (x))
+#define DP_HIDDEN_BIT  DP_MBIT(DP_FBITS)
+#define DP_SIGN_BIT    DP_MBIT(63)
+
+
+#define SP_MBIT(x)     ((unsigned long)1 << (x))
+#define SP_HIDDEN_BIT  SP_MBIT(SP_FBITS)
+#define SP_SIGN_BIT    SP_MBIT(31)
+
+
+#define SPSIGN(sp)     (sp.parts.sign)
+#define SPBEXP(sp)     (sp.parts.bexp)
+#define SPMANT(sp)     (sp.parts.mant)
+
+#define DPSIGN(dp)     (dp.parts.sign)
+#define DPBEXP(dp)     (dp.parts.bexp)
+#define DPMANT(dp)     (dp.parts.mant)
+
+ieee754dp ieee754dp_dump(char *m, ieee754dp x)
+{
+       int i;
+
+       printk("%s", m);
+       printk("<%08x,%08x>\n", (unsigned) (x.bits >> 32),
+              (unsigned) x.bits);
+       printk("\t=");
+       switch (ieee754dp_class(x)) {
+       case IEEE754_CLASS_QNAN:
+       case IEEE754_CLASS_SNAN:
+               printk("Nan %c", DPSIGN(x) ? '-' : '+');
+               for (i = DP_FBITS - 1; i >= 0; i--)
+                       printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
+               break;
+       case IEEE754_CLASS_INF:
+               printk("%cInfinity", DPSIGN(x) ? '-' : '+');
+               break;
+       case IEEE754_CLASS_ZERO:
+               printk("%cZero", DPSIGN(x) ? '-' : '+');
+               break;
+       case IEEE754_CLASS_DNORM:
+               printk("%c0.", DPSIGN(x) ? '-' : '+');
+               for (i = DP_FBITS - 1; i >= 0; i--)
+                       printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
+               printk("e%d", DPBEXP(x) - DP_EBIAS);
+               break;
+       case IEEE754_CLASS_NORM:
+               printk("%c1.", DPSIGN(x) ? '-' : '+');
+               for (i = DP_FBITS - 1; i >= 0; i--)
+                       printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
+               printk("e%d", DPBEXP(x) - DP_EBIAS);
+               break;
+       default:
+               printk("Illegal/Unknown IEEE754 value class");
+       }
+       printk("\n");
+       return x;
+}
+
+ieee754sp ieee754sp_dump(char *m, ieee754sp x)
+{
+       int i;
+
+       printk("%s=", m);
+       printk("<%08x>\n", (unsigned) x.bits);
+       printk("\t=");
+       switch (ieee754sp_class(x)) {
+       case IEEE754_CLASS_QNAN:
+       case IEEE754_CLASS_SNAN:
+               printk("Nan %c", SPSIGN(x) ? '-' : '+');
+               for (i = SP_FBITS - 1; i >= 0; i--)
+                       printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
+               break;
+       case IEEE754_CLASS_INF:
+               printk("%cInfinity", SPSIGN(x) ? '-' : '+');
+               break;
+       case IEEE754_CLASS_ZERO:
+               printk("%cZero", SPSIGN(x) ? '-' : '+');
+               break;
+       case IEEE754_CLASS_DNORM:
+               printk("%c0.", SPSIGN(x) ? '-' : '+');
+               for (i = SP_FBITS - 1; i >= 0; i--)
+                       printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
+               printk("e%d", SPBEXP(x) - SP_EBIAS);
+               break;
+       case IEEE754_CLASS_NORM:
+               printk("%c1.", SPSIGN(x) ? '-' : '+');
+               for (i = SP_FBITS - 1; i >= 0; i--)
+                       printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
+               printk("e%d", SPBEXP(x) - SP_EBIAS);
+               break;
+       default:
+               printk("Illegal/Unknown IEEE754 value class");
+       }
+       printk("\n");
+       return x;
+}
+
diff --git a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c
new file mode 100644 (file)
index 0000000..0943d56
--- /dev/null
@@ -0,0 +1,197 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+int ieee754dp_class(ieee754dp x)
+{
+       COMPXDP;
+       EXPLODEXDP;
+       return xc;
+}
+
+int ieee754dp_isnan(ieee754dp x)
+{
+       return ieee754dp_class(x) >= IEEE754_CLASS_SNAN;
+}
+
+int ieee754dp_issnan(ieee754dp x)
+{
+       assert(ieee754dp_isnan(x));
+       if (ieee754_csr.noq)
+               return 1;
+       return !(DPMANT(x) & DP_MBIT(DP_MBITS - 1));
+}
+
+
+ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...)
+{
+       struct ieee754xctx ax;
+       if (!TSTX())
+               return r;
+
+       ax.op = op;
+       ax.rt = IEEE754_RT_DP;
+       ax.rv.dp = r;
+       va_start(ax.ap, op);
+       ieee754_xcpt(&ax);
+       return ax.rv.dp;
+}
+
+ieee754dp ieee754dp_nanxcpt(ieee754dp r, const char *op, ...)
+{
+       struct ieee754xctx ax;
+
+       assert(ieee754dp_isnan(r));
+
+       if (!ieee754dp_issnan(r))       /* QNAN does not cause invalid op !! */
+               return r;
+
+       if (!SETCX(IEEE754_INVALID_OPERATION)) {
+               /* not enabled convert to a quiet NaN */
+               if (ieee754_csr.noq)
+                       return r;
+               DPMANT(r) |= DP_MBIT(DP_MBITS - 1);
+               return r;
+       }
+
+       ax.op = op;
+       ax.rt = 0;
+       ax.rv.dp = r;
+       va_start(ax.ap, op);
+       ieee754_xcpt(&ax);
+       return ax.rv.dp;
+}
+
+ieee754dp ieee754dp_bestnan(ieee754dp x, ieee754dp y)
+{
+       assert(ieee754dp_isnan(x));
+       assert(ieee754dp_isnan(y));
+
+       if (DPMANT(x) > DPMANT(y))
+               return x;
+       else
+               return y;
+}
+
+
+/* generate a normal/denormal number with over,under handeling
+ * sn is sign
+ * xe is an unbiased exponent
+ * xm is 3bit extended precision value.
+ */
+ieee754dp ieee754dp_format(int sn, int xe, unsigned long long xm)
+{
+       assert(xm);             /* we dont gen exact zeros (probably should) */
+
+       assert((xm >> (DP_MBITS + 1 + 3)) == 0);        /* no execess */
+       assert(xm & (DP_HIDDEN_BIT << 3));
+
+       if (xe < DP_EMIN) {
+               /* strip lower bits */
+               int es = DP_EMIN - xe;
+
+               if (ieee754_csr.nod) {
+                       SETCX(IEEE754_UNDERFLOW);
+                       return ieee754dp_zero(sn);
+               }
+
+               /* sticky right shift es bits 
+                */
+               xm = XDPSRS(xm, es);
+               xe += es;
+
+               assert((xm & (DP_HIDDEN_BIT << 3)) == 0);
+               assert(xe == DP_EMIN);
+       }
+       if (xm & (DP_MBIT(3) - 1)) {
+               SETCX(IEEE754_INEXACT);
+               /* inexact must round of 3 bits 
+                */
+               switch (ieee754_csr.rm) {
+               case IEEE754_RZ:
+                       break;
+               case IEEE754_RN:
+                       xm += 0x3 + ((xm >> 3) & 1);
+                       /* xm += (xm&0x8)?0x4:0x3 */
+                       break;
+               case IEEE754_RU:        /* toward +Infinity */
+                       if (!sn)        /* ?? */
+                               xm += 0x8;
+                       break;
+               case IEEE754_RD:        /* toward -Infinity */
+                       if (sn) /* ?? */
+                               xm += 0x8;
+                       break;
+               }
+               /* adjust exponent for rounding add overflowing 
+                */
+               if (xm >> (DP_MBITS + 3 + 1)) { /* add causes mantissa overflow */
+                       xm >>= 1;
+                       xe++;
+               }
+       }
+       /* strip grs bits */
+       xm >>= 3;
+
+       assert((xm >> (DP_MBITS + 1)) == 0);    /* no execess */
+       assert(xe >= DP_EMIN);
+
+       if (xe > DP_EMAX) {
+               SETCX(IEEE754_OVERFLOW);
+               /* -O can be table indexed by (rm,sn) */
+               switch (ieee754_csr.rm) {
+               case IEEE754_RN:
+                       return ieee754dp_inf(sn);
+               case IEEE754_RZ:
+                       return ieee754dp_max(sn);
+               case IEEE754_RU:        /* toward +Infinity */
+                       if (sn == 0)
+                               return ieee754dp_inf(0);
+                       else
+                               return ieee754dp_max(1);
+               case IEEE754_RD:        /* toward -Infinity */
+                       if (sn == 0)
+                               return ieee754dp_max(0);
+                       else
+                               return ieee754dp_inf(1);
+               }
+       }
+       /* gen norm/denorm/zero */
+
+       if ((xm & DP_HIDDEN_BIT) == 0) {
+               /* we underflow (tiny/zero) */
+               assert(xe == DP_EMIN);
+               SETCX(IEEE754_UNDERFLOW);
+               return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm);
+       } else {
+               assert((xm >> (DP_MBITS + 1)) == 0);    /* no execess */
+               assert(xm & DP_HIDDEN_BIT);
+
+               return builddp(sn, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+       }
+}
diff --git a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h
new file mode 100644 (file)
index 0000000..8ab3e01
--- /dev/null
@@ -0,0 +1,83 @@
+/* 
+ * IEEE754 floating point
+ * double precision internal header file
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754int.h"
+
+#define assert(expr) ((void)0)
+
+/* 3bit extended double precision sticky right shift */
+#define XDPSRS(v,rs)   \
+  ((rs > (DP_MBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0))
+
+#define XDPSRSX1() \
+  (xe++, (xm = (xm >> 1) | (xm & 1)))
+
+#define XDPSRS1(v)     \
+  (((v) >> 1) | ((v) & 1))
+
+/* convert denormal to normalized with extended exponent */
+#define DPDNORMx(m,e) \
+  while( (m >> DP_MBITS) == 0) { m <<= 1; e--; }
+#define DPDNORMX       DPDNORMx(xm,xe)
+#define DPDNORMY       DPDNORMx(ym,ye)
+
+static __inline ieee754dp builddp(int s, int bx, unsigned long long m)
+{
+       ieee754dp r;
+
+       assert((s) == 0 || (s) == 1);
+       assert((bx) >= DP_EMIN - 1 + DP_EBIAS
+              && (bx) <= DP_EMAX + 1 + DP_EBIAS);
+       assert(((m) >> DP_MBITS) == 0);
+
+       r.parts.sign = s;
+       r.parts.bexp = bx;
+       r.parts.mant = m;
+       return r;
+}
+
+extern int ieee754dp_isnan(ieee754dp);
+extern int ieee754dp_issnan(ieee754dp);
+extern int ieee754si_xcpt(int, const char *, ...);
+extern long long ieee754di_xcpt(long long, const char *, ...);
+extern ieee754dp ieee754dp_xcpt(ieee754dp, const char *, ...);
+extern ieee754dp ieee754dp_nanxcpt(ieee754dp, const char *, ...);
+extern ieee754dp ieee754dp_bestnan(ieee754dp, ieee754dp);
+extern ieee754dp ieee754dp_format(int, int, unsigned long long);
+
+
+#define DPNORMRET2(s,e,m,name,a0,a1) \
+{ \
+    ieee754dp V = ieee754dp_format(s,e,m); \
+    if(TSTX()) \
+      return ieee754dp_xcpt(V,name,a0,a1); \
+    else \
+      return V; \
+}
+
+#define DPNORMRET1(s,e,m,name,a0)  DPNORMRET2(s,e,m,name,a0,a0)
diff --git a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h
new file mode 100644 (file)
index 0000000..6de1013
--- /dev/null
@@ -0,0 +1,135 @@
+/* 
+ * IEEE754 floating point
+ * common internal header file
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754.h"
+
+#define DP_EBIAS       1023
+#define DP_EMIN                (-1022)
+#define DP_EMAX                1023
+#define DP_MBITS       52
+
+#define SP_EBIAS       127
+#define SP_EMIN                (-126)
+#define SP_EMAX                127
+#define SP_MBITS       23
+
+#define DP_MBIT(x)     ((unsigned long long)1 << (x))
+#define DP_HIDDEN_BIT  DP_MBIT(DP_MBITS)
+#define DP_SIGN_BIT    DP_MBIT(63)
+
+#define SP_MBIT(x)     ((unsigned long)1 << (x))
+#define SP_HIDDEN_BIT  SP_MBIT(SP_MBITS)
+#define SP_SIGN_BIT    SP_MBIT(31)
+
+
+#define SPSIGN(sp)     (sp.parts.sign)
+#define SPBEXP(sp)     (sp.parts.bexp)
+#define SPMANT(sp)     (sp.parts.mant)
+
+#define DPSIGN(dp)     (dp.parts.sign)
+#define DPBEXP(dp)     (dp.parts.bexp)
+#define DPMANT(dp)     (dp.parts.mant)
+
+#define CLPAIR(x,y)    ((x)*6+(y))
+
+#define CLEARCX        \
+  (ieee754_csr.cx = 0)
+
+#define SETCX(x) \
+  (ieee754_csr.cx |= (x),ieee754_csr.sx |= (x),ieee754_csr.mx & (x))
+
+#define TSTX() \
+       (ieee754_csr.cx & ieee754_csr.mx)
+
+
+#define COMPXSP \
+  unsigned xm; int xe; int xs; int xc
+
+#define COMPYSP \
+  unsigned ym; int ye; int ys; int yc
+
+#define EXPLODESP(v,vc,vs,ve,vm) \
+{\
+    vs = SPSIGN(v);\
+    ve = SPBEXP(v);\
+    vm = SPMANT(v);\
+    if(ve == SP_EMAX+1+SP_EBIAS){\
+       if(vm == 0)\
+         vc = IEEE754_CLASS_INF;\
+       else if(vm & SP_MBIT(SP_MBITS-1)) \
+         vc = IEEE754_CLASS_QNAN;\
+       else \
+         vc = IEEE754_CLASS_SNAN;\
+    } else if(ve == SP_EMIN-1+SP_EBIAS) {\
+       if(vm) {\
+           ve = SP_EMIN;\
+           vc = IEEE754_CLASS_DNORM;\
+       } else\
+         vc = IEEE754_CLASS_ZERO;\
+    } else {\
+       ve -= SP_EBIAS;\
+       vm |= SP_HIDDEN_BIT;\
+       vc = IEEE754_CLASS_NORM;\
+    }\
+}
+#define EXPLODEXSP EXPLODESP(x,xc,xs,xe,xm)
+#define EXPLODEYSP EXPLODESP(y,yc,ys,ye,ym)
+
+
+#define COMPXDP \
+unsigned long long xm; int xe; int xs; int xc
+
+#define COMPYDP \
+unsigned long long ym; int ye; int ys; int yc
+
+#define EXPLODEDP(v,vc,vs,ve,vm) \
+{\
+    vm = DPMANT(v);\
+    vs = DPSIGN(v);\
+    ve = DPBEXP(v);\
+    if(ve == DP_EMAX+1+DP_EBIAS){\
+       if(vm == 0)\
+         vc = IEEE754_CLASS_INF;\
+       else if(vm & DP_MBIT(DP_MBITS-1)) \
+         vc = IEEE754_CLASS_QNAN;\
+       else \
+         vc = IEEE754_CLASS_SNAN;\
+    } else if(ve == DP_EMIN-1+DP_EBIAS) {\
+       if(vm) {\
+           ve = DP_EMIN;\
+           vc = IEEE754_CLASS_DNORM;\
+       } else\
+         vc = IEEE754_CLASS_ZERO;\
+    } else {\
+       ve -= DP_EBIAS;\
+       vm |= DP_HIDDEN_BIT;\
+       vc = IEEE754_CLASS_NORM;\
+    }\
+}
+#define EXPLODEXDP EXPLODEDP(x,xc,xs,xe,xm)
+#define EXPLODEYDP EXPLODEDP(y,yc,ys,ye,ym)
diff --git a/arch/mips/math-emu/ieee754m.c b/arch/mips/math-emu/ieee754m.c
new file mode 100644 (file)
index 0000000..29b4e33
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * floor, trunc, ceil
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754.h"
+
+ieee754dp ieee754dp_floor(ieee754dp x)
+{
+       ieee754dp i;
+
+       if (ieee754dp_lt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
+               return ieee754dp_sub(i, ieee754dp_one(0));
+       else
+               return i;
+}
+
+ieee754dp ieee754dp_ceil(ieee754dp x)
+{
+       ieee754dp i;
+
+       if (ieee754dp_gt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
+               return ieee754dp_add(i, ieee754dp_one(0));
+       else
+               return i;
+}
+
+ieee754dp ieee754dp_trunc(ieee754dp x)
+{
+       ieee754dp i;
+
+       (void) ieee754dp_modf(x, &i);
+       return i;
+}
diff --git a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c
new file mode 100644 (file)
index 0000000..511ec8d
--- /dev/null
@@ -0,0 +1,197 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+int ieee754sp_class(ieee754sp x)
+{
+       COMPXSP;
+       EXPLODEXSP;
+       return xc;
+}
+
+int ieee754sp_isnan(ieee754sp x)
+{
+       return ieee754sp_class(x) >= IEEE754_CLASS_SNAN;
+}
+
+int ieee754sp_issnan(ieee754sp x)
+{
+       assert(ieee754sp_isnan(x));
+       if (ieee754_csr.noq)
+               return 1;
+       return !(SPMANT(x) & SP_MBIT(SP_MBITS - 1));
+}
+
+
+ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...)
+{
+       struct ieee754xctx ax;
+
+       if (!TSTX())
+               return r;
+
+       ax.op = op;
+       ax.rt = IEEE754_RT_SP;
+       ax.rv.sp = r;
+       va_start(ax.ap, op);
+       ieee754_xcpt(&ax);
+       return ax.rv.sp;
+}
+
+ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...)
+{
+       struct ieee754xctx ax;
+
+       assert(ieee754sp_isnan(r));
+
+       if (!ieee754sp_issnan(r))       /* QNAN does not cause invalid op !! */
+               return r;
+
+       if (!SETCX(IEEE754_INVALID_OPERATION)) {
+               /* not enabled convert to a quiet NaN */
+               if (ieee754_csr.noq)
+                       return r;
+               SPMANT(r) |= SP_MBIT(SP_MBITS - 1);
+               return r;
+       }
+
+       ax.op = op;
+       ax.rt = 0;
+       ax.rv.sp = r;
+       va_start(ax.ap, op);
+       ieee754_xcpt(&ax);
+       return ax.rv.sp;
+}
+
+ieee754sp ieee754sp_bestnan(ieee754sp x, ieee754sp y)
+{
+       assert(ieee754sp_isnan(x));
+       assert(ieee754sp_isnan(y));
+
+       if (SPMANT(x) > SPMANT(y))
+               return x;
+       else
+               return y;
+}
+
+
+/* generate a normal/denormal number with over,under handeling
+ * sn is sign
+ * xe is an unbiased exponent
+ * xm is 3bit extended precision value.
+ */
+ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
+{
+       assert(xm);             /* we dont gen exact zeros (probably should) */
+
+       assert((xm >> (SP_MBITS + 1 + 3)) == 0);        /* no execess */
+       assert(xm & (SP_HIDDEN_BIT << 3));
+
+       if (xe < SP_EMIN) {
+               /* strip lower bits */
+               int es = SP_EMIN - xe;
+
+               if (ieee754_csr.nod) {
+                       SETCX(IEEE754_UNDERFLOW);
+                       return ieee754sp_zero(sn);
+               }
+
+               /* sticky right shift es bits 
+                */
+               SPXSRSXn(es);
+
+               assert((xm & (SP_HIDDEN_BIT << 3)) == 0);
+               assert(xe == SP_EMIN);
+       }
+       if (xm & (SP_MBIT(3) - 1)) {
+               SETCX(IEEE754_INEXACT);
+               /* inexact must round of 3 bits 
+                */
+               switch (ieee754_csr.rm) {
+               case IEEE754_RZ:
+                       break;
+               case IEEE754_RN:
+                       xm += 0x3 + ((xm >> 3) & 1);
+                       /* xm += (xm&0x8)?0x4:0x3 */
+                       break;
+               case IEEE754_RU:        /* toward +Infinity */
+                       if (!sn)        /* ?? */
+                               xm += 0x8;
+                       break;
+               case IEEE754_RD:        /* toward -Infinity */
+                       if (sn) /* ?? */
+                               xm += 0x8;
+                       break;
+               }
+               /* adjust exponent for rounding add overflowing 
+                */
+               if (xm >> (SP_MBITS + 1 + 3)) { /* add causes mantissa overflow */
+                       xm >>= 1;
+                       xe++;
+               }
+       }
+       /* strip grs bits */
+       xm >>= 3;
+
+       assert((xm >> (SP_MBITS + 1)) == 0);    /* no execess */
+       assert(xe >= SP_EMIN);
+
+       if (xe > SP_EMAX) {
+               SETCX(IEEE754_OVERFLOW);
+               /* -O can be table indexed by (rm,sn) */
+               switch (ieee754_csr.rm) {
+               case IEEE754_RN:
+                       return ieee754sp_inf(sn);
+               case IEEE754_RZ:
+                       return ieee754sp_max(sn);
+               case IEEE754_RU:        /* toward +Infinity */
+                       if (sn == 0)
+                               return ieee754sp_inf(0);
+                       else
+                               return ieee754sp_max(1);
+               case IEEE754_RD:        /* toward -Infinity */
+                       if (sn == 0)
+                               return ieee754sp_max(0);
+                       else
+                               return ieee754sp_inf(1);
+               }
+       }
+       /* gen norm/denorm/zero */
+
+       if ((xm & SP_HIDDEN_BIT) == 0) {
+               /* we underflow (tiny/zero) */
+               assert(xe == SP_EMIN);
+               SETCX(IEEE754_UNDERFLOW);
+               return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm);
+       } else {
+               assert((xm >> (SP_MBITS + 1)) == 0);    /* no execess */
+               assert(xm & SP_HIDDEN_BIT);
+
+               return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
+       }
+}
diff --git a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h
new file mode 100644 (file)
index 0000000..b41b2a8
--- /dev/null
@@ -0,0 +1,89 @@
+/* 
+ * IEEE754 floating point
+ * double precision internal header file
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754int.h"
+
+#define assert(expr) ((void)0)
+
+/* 3bit extended single precision sticky right shift */
+#define SPXSRSXn(rs) \
+  (xe += rs, \
+   xm = (rs > (SP_MBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0))
+
+#define SPXSRSX1() \
+  (xe++, (xm = (xm >> 1) | (xm & 1)))
+
+#define SPXSRSYn(rs) \
+   (ye+=rs, \
+    ym = (rs > (SP_MBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0))
+
+#define SPXSRSY1() \
+   (ye++, (ym = (ym >> 1) | (ym & 1)))
+
+/* convert denormal to normalized with extended exponent */
+#define SPDNORMx(m,e) \
+  while( (m >> SP_MBITS) == 0) { m <<= 1; e--; }
+#define SPDNORMX       SPDNORMx(xm,xe)
+#define SPDNORMY       SPDNORMx(ym,ye)
+
+static __inline ieee754sp buildsp(int s, int bx, unsigned m)
+{
+       ieee754sp r;
+
+       assert((s) == 0 || (s) == 1);
+       assert((bx) >= SP_EMIN - 1 + SP_EBIAS
+              && (bx) <= SP_EMAX + 1 + SP_EBIAS);
+       assert(((m) >> SP_MBITS) == 0);
+
+       r.parts.sign = s;
+       r.parts.bexp = bx;
+       r.parts.mant = m;
+
+       return r;
+}
+
+extern int ieee754sp_isnan(ieee754sp);
+extern int ieee754sp_issnan(ieee754sp);
+extern int ieee754si_xcpt(int, const char *, ...);
+extern long long ieee754di_xcpt(long long, const char *, ...);
+extern ieee754sp ieee754sp_xcpt(ieee754sp, const char *, ...);
+extern ieee754sp ieee754sp_nanxcpt(ieee754sp, const char *, ...);
+extern ieee754sp ieee754sp_bestnan(ieee754sp, ieee754sp);
+extern ieee754sp ieee754sp_format(int, int, unsigned);
+
+
+#define SPNORMRET2(s,e,m,name,a0,a1) \
+{ \
+    ieee754sp V = ieee754sp_format(s,e,m); \
+    if(TSTX()) \
+      return ieee754sp_xcpt(V,name,a0,a1); \
+    else \
+      return V; \
+}
+
+#define SPNORMRET1(s,e,m,name,a0)  SPNORMRET2(s,e,m,name,a0,a0)
diff --git a/arch/mips/math-emu/ieee754xcpt.c b/arch/mips/math-emu/ieee754xcpt.c
new file mode 100644 (file)
index 0000000..7a4d948
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+/**************************************************************************
+ *  Nov 7, 2000
+ *  Added preprocessor hacks to map to Linux kernel diagnostics. 
+ *
+ *  Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *************************************************************************/
+
+#include "ieee754.h"
+
+/*
+ * Very naff exception handler (you can plug in your own and
+ * override this).
+ */
+
+static const char *const rtnames[] = {
+       "sp", "dp", "xp", "si", "di"
+};
+
+void ieee754_xcpt(struct ieee754xctx *xcp)
+{
+       printk("floating point exception in \"%s\", type=%s\n",
+               xcp->op, rtnames[xcp->rt]);
+}
+
diff --git a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c
new file mode 100644 (file)
index 0000000..c73c42c
--- /dev/null
@@ -0,0 +1,95 @@
+/**************************************************************************
+ *
+ *  arch/mips/math_emu/kernel_linkage.c
+ *
+ *  Kevin D. Kissell, kevink@mips and Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ *************************************************************************/
+/*
+ * Routines corresponding to Linux kernel FP context
+ * manipulation primitives for the Algorithmics MIPS
+ * FPU Emulator
+ */
+
+#include <linux/sched.h>
+#include <asm/processor.h>
+#include <asm/signal.h>
+#include <asm/uaccess.h>
+
+#include <asm/fpu_emulator.h>
+
+extern struct mips_fpu_emulator_private fpuemuprivate;
+
+#define SIGNALLING_NAN 0x7ff800007ff80000LL
+
+void fpu_emulator_init_fpu(void)
+{
+       static int first = 1;
+       int i;
+       if (first) {
+               first = 0;
+               printk("Algorithmics/MIPS FPU Emulator v1.4\n");
+       }
+
+       current->thread.fpu.soft.sr = 0;
+       for (i = 0; i < 32; i++) {
+               current->thread.fpu.soft.regs[i] = SIGNALLING_NAN;
+       }
+}
+
+
+/*
+ * Emulator context save/restore to/from a signal context
+ * presumed to be on the user stack, and therefore accessed
+ * with appropriate macros from uaccess.h
+ */
+
+int fpu_emulator_save_context(struct sigcontext *sc)
+{
+       int i;
+       int err = 0;
+
+       for (i = 0; i < 32; i++) {
+               err |=
+                   __put_user(current->thread.fpu.soft.regs[i],
+                              &sc->sc_fpregs[i]);
+       }
+       err |= __put_user(current->thread.fpu.soft.sr, &sc->sc_fpc_csr);
+       err |= __put_user(fpuemuprivate.eir, &sc->sc_fpc_eir);
+
+       return err;
+}
+
+int fpu_emulator_restore_context(struct sigcontext *sc)
+{
+       int i;
+       int err = 0;
+
+       for (i = 0; i < 32; i++) {
+               err |=
+                   __get_user(current->thread.fpu.soft.regs[i],
+                              &sc->sc_fpregs[i]);
+       }
+       err |= __get_user(current->thread.fpu.soft.sr, &sc->sc_fpc_csr);
+       err |= __get_user(fpuemuprivate.eir, &sc->sc_fpc_eir);
+
+       return err;
+}
+
diff --git a/arch/mips/math-emu/sp_add.c b/arch/mips/math-emu/sp_add.c
new file mode 100644 (file)
index 0000000..61a050b
--- /dev/null
@@ -0,0 +1,180 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)
+{
+       COMPXSP;
+       COMPYSP;
+
+       EXPLODEXSP;
+       EXPLODEYSP;
+
+       CLEARCX;
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+               return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "add", x,
+                                        y);
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754sp_nanxcpt(y, "add", x, y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754sp_nanxcpt(x, "add", x, y);
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+               return ieee754sp_bestnan(x, y);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return x;
+
+
+               /* Inifity handeling 
+                */
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+               if (xs == ys)
+                       return x;
+               SETCX(IEEE754_INVALID_OPERATION);
+               return ieee754sp_xcpt(ieee754sp_indef(), "add", x, y);
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+               return x;
+
+               /* Zero handeling 
+                */
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+               if (xs == ys)
+                       return x;
+               else
+                       return ieee754sp_zero(ieee754_csr.rm ==
+                                             IEEE754_RD);
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               return x;
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               SPDNORMX;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               SPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               SPDNORMX;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+               break;
+       }
+       assert(xm & SP_HIDDEN_BIT);
+       assert(ym & SP_HIDDEN_BIT);
+
+       /* provide guard,round and stick bit space */
+       xm <<= 3;
+       ym <<= 3;
+
+       if (xe > ye) {
+               /* have to shift y fraction right to align
+                */
+               int s = xe - ye;
+               SPXSRSYn(s);
+       } else if (ye > xe) {
+               /* have to shift x fraction right to align
+                */
+               int s = ye - xe;
+               SPXSRSXn(s);
+       }
+       assert(xe == ye);
+       assert(xe <= SP_EMAX);
+
+       if (xs == ys) {
+               /* generate 28 bit result of adding two 27 bit numbers
+                * leaving result in xm,xs,xe
+                */
+               xm = xm + ym;
+               xe = xe;
+               xs = xs;
+
+               if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */
+                       SPXSRSX1();
+               }
+       } else {
+               if (xm >= ym) {
+                       xm = xm - ym;
+                       xe = xe;
+                       xs = xs;
+               } else {
+                       xm = ym - xm;
+                       xe = xe;
+                       xs = ys;
+               }
+               if (xm == 0)
+                       return ieee754sp_zero(ieee754_csr.rm ==
+                                             IEEE754_RD);
+
+               /* normalize in extended single precision */
+               while ((xm >> (SP_MBITS + 3)) == 0) {
+                       xm <<= 1;
+                       xe--;
+               }
+
+       }
+       SPNORMRET2(xs, xe, xm, "add", x, y);
+}
diff --git a/arch/mips/math-emu/sp_cmp.c b/arch/mips/math-emu/sp_cmp.c
new file mode 100644 (file)
index 0000000..d8abc9c
--- /dev/null
@@ -0,0 +1,58 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cmp)
+{
+       CLEARCX;
+
+       if (ieee754sp_isnan(x) || ieee754sp_isnan(y)) {
+               if (cmp & IEEE754_CUN)
+                       return 1;
+               if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
+                       if (SETCX(IEEE754_INVALID_OPERATION))
+                               return ieee754si_xcpt(0, "fcmpf", x);
+               }
+               return 0;
+       } else {
+               int vx = x.bits;
+               int vy = y.bits;
+
+               if (vx < 0)
+                       vx = -vx ^ SP_SIGN_BIT;
+               if (vy < 0)
+                       vy = -vy ^ SP_SIGN_BIT;
+
+               if (vx < vy)
+                       return (cmp & IEEE754_CLT) != 0;
+               else if (vx == vy)
+                       return (cmp & IEEE754_CEQ) != 0;
+               else
+                       return (cmp & IEEE754_CGT) != 0;
+       }
+}
diff --git a/arch/mips/math-emu/sp_div.c b/arch/mips/math-emu/sp_div.c
new file mode 100644 (file)
index 0000000..14a87a5
--- /dev/null
@@ -0,0 +1,160 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y)
+{
+       COMPXSP;
+       COMPYSP;
+
+       CLEARCX;
+
+       EXPLODEXSP;
+       EXPLODEYSP;
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+               return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "div", x,
+                                        y);
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754sp_nanxcpt(y, "div", x, y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754sp_nanxcpt(x, "div", x, y);
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+               return ieee754sp_bestnan(x, y);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return x;
+
+
+               /* Infinity handeling 
+                */
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+               SETCX(IEEE754_INVALID_OPERATION);
+               return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y);
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+               return ieee754sp_zero(xs ^ ys);
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+               return ieee754sp_inf(xs ^ ys);
+
+               /* Zero handeling 
+                */
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+               SETCX(IEEE754_INVALID_OPERATION);
+               return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y);
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               SETCX(IEEE754_ZERO_DIVIDE);
+               return ieee754sp_xcpt(ieee754sp_inf(xs ^ ys), "div", x, y);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+               return ieee754sp_zero(xs == ys ? 0 : 1);
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               SPDNORMX;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               SPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               SPDNORMX;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+               break;
+       }
+       assert(xm & SP_HIDDEN_BIT);
+       assert(ym & SP_HIDDEN_BIT);
+
+       /* provide rounding space */
+       xm <<= 3;
+       ym <<= 3;
+
+       {
+               /* now the dirty work */
+
+               unsigned rm = 0;
+               int re = xe - ye;
+               unsigned bm;
+
+               for (bm = SP_MBIT(SP_MBITS + 2); bm; bm >>= 1) {
+                       if (xm >= ym) {
+                               xm -= ym;
+                               rm |= bm;
+                               if (xm == 0)
+                                       break;
+                       }
+                       xm <<= 1;
+               }
+               rm <<= 1;
+               if (xm)
+                       rm |= 1;        /* have remainder, set sticky */
+
+               assert(rm);
+
+               /* normalise rm to rounding precision ?
+                */
+               while ((rm >> (SP_MBITS + 3)) == 0) {
+                       rm <<= 1;
+                       re--;
+               }
+
+               SPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y);
+       }
+}
diff --git a/arch/mips/math-emu/sp_fdp.c b/arch/mips/math-emu/sp_fdp.c
new file mode 100644 (file)
index 0000000..a7ce2f0
--- /dev/null
@@ -0,0 +1,69 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_fdp(ieee754dp x)
+{
+       COMPXDP;
+
+       CLEARCX;
+
+       EXPLODEXDP;
+
+       switch (xc) {
+       case IEEE754_CLASS_QNAN:
+       case IEEE754_CLASS_SNAN:
+               return ieee754sp_nanxcpt(buildsp(xs,
+                                                SP_EMAX + 1 + SP_EBIAS,
+                                                (unsigned long)
+                                                (xm >>
+                                                 (DP_MBITS - SP_MBITS))),
+                                        "fdp", x);
+       case IEEE754_CLASS_INF:
+               return ieee754sp_inf(xs);
+       case IEEE754_CLASS_ZERO:
+               return ieee754sp_zero(xs);
+       case IEEE754_CLASS_DNORM:
+               /* cant possibly be sp representable */
+               SETCX(IEEE754_UNDERFLOW);
+               return ieee754sp_xcpt(ieee754sp_zero(xs), "fdp", x);
+       case IEEE754_CLASS_NORM:
+               break;
+       }
+
+       {
+               unsigned long rm;
+
+               /* convert from DP_MBITS to SP_MBITS+3 with sticky right shift 
+                */
+               rm = (xm >> (DP_MBITS - (SP_MBITS + 3))) |
+                   ((xm << (64 - (DP_MBITS - (SP_MBITS + 3)))) != 0);
+
+               SPNORMRET1(xs, xe, rm, "fdp", x);
+       }
+}
diff --git a/arch/mips/math-emu/sp_fint.c b/arch/mips/math-emu/sp_fint.c
new file mode 100644 (file)
index 0000000..747fd86
--- /dev/null
@@ -0,0 +1,78 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_fint(int x)
+{
+       COMPXSP;
+
+       CLEARCX;
+
+       if (x == 0)
+               return ieee754sp_zero(0);
+       if (x == 1 || x == -1)
+               return ieee754sp_one(x < 0);
+       if (x == 10 || x == -10)
+               return ieee754sp_ten(x < 0);
+
+       xs = (x < 0);
+       if (xs) {
+               if (x == (1 << 31))
+                       xm = ((unsigned) 1 << 31);      /* max neg can't be safely negated */
+               else
+                       xm = -x;
+       } else {
+               xm = x;
+       }
+       xe = SP_MBITS + 3;
+
+       if (xm >> (SP_MBITS + 1 + 3)) {
+               /* shunt out overflow bits 
+                */
+               while (xm >> (SP_MBITS + 1 + 3)) {
+                       SPXSRSX1();
+               }
+       } else {
+               /* normalize in grs extended single precision 
+                */
+               while ((xm >> (SP_MBITS + 3)) == 0) {
+                       xm <<= 1;
+                       xe--;
+               }
+       }
+       SPNORMRET1(xs, xe, xm, "fint", x);
+}
+
+
+ieee754sp ieee754sp_funs(unsigned int u)
+{
+       if ((int) u < 0)
+               return ieee754sp_add(ieee754sp_1e31(),
+                                    ieee754sp_fint(u & ~(1 << 31)));
+       return ieee754sp_fint(u);
+}
diff --git a/arch/mips/math-emu/sp_flong.c b/arch/mips/math-emu/sp_flong.c
new file mode 100644 (file)
index 0000000..6440572
--- /dev/null
@@ -0,0 +1,77 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_flong(long long x)
+{
+       COMPXDP;                /* <--- need 64-bit mantissa temp */
+
+       CLEARCX;
+
+       if (x == 0)
+               return ieee754sp_zero(0);
+       if (x == 1 || x == -1)
+               return ieee754sp_one(x < 0);
+       if (x == 10 || x == -10)
+               return ieee754sp_ten(x < 0);
+
+       xs = (x < 0);
+       if (xs) {
+               if (x == (1ULL << 63))
+                       xm = (1ULL << 63);      /* max neg can't be safely negated */
+               else
+                       xm = -x;
+       } else {
+               xm = x;
+       }
+       xe = SP_MBITS + 3;
+
+       if (xm >> (SP_MBITS + 1 + 3)) {
+               /* shunt out overflow bits 
+                */
+               while (xm >> (SP_MBITS + 1 + 3)) {
+                       SPXSRSX1();
+               }
+       } else {
+               /* normalize in grs extended single precision */
+               while ((xm >> (SP_MBITS + 3)) == 0) {
+                       xm <<= 1;
+                       xe--;
+               }
+       }
+       SPNORMRET1(xs, xe, xm, "sp_flong", x);
+}
+
+
+ieee754sp ieee754sp_fulong(unsigned long long u)
+{
+       if ((long long) u < 0)
+               return ieee754sp_add(ieee754sp_1e63(),
+                                    ieee754sp_flong(u & ~(1ULL << 63)));
+       return ieee754sp_flong(u);
+}
diff --git a/arch/mips/math-emu/sp_frexp.c b/arch/mips/math-emu/sp_frexp.c
new file mode 100644 (file)
index 0000000..968fe30
--- /dev/null
@@ -0,0 +1,53 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+/* close to ieeep754sp_logb 
+*/
+ieee754sp ieee754sp_frexp(ieee754sp x, int *eptr)
+{
+       COMPXSP;
+       CLEARCX;
+       EXPLODEXSP;
+
+       switch (xc) {
+       case IEEE754_CLASS_SNAN:
+       case IEEE754_CLASS_QNAN:
+       case IEEE754_CLASS_INF:
+       case IEEE754_CLASS_ZERO:
+               *eptr = 0;
+               return x;
+       case IEEE754_CLASS_DNORM:
+               SPDNORMX;
+               break;
+       case IEEE754_CLASS_NORM:
+               break;
+       }
+       *eptr = xe + 1;
+       return buildsp(xs, -1 + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
+}
diff --git a/arch/mips/math-emu/sp_logb.c b/arch/mips/math-emu/sp_logb.c
new file mode 100644 (file)
index 0000000..453f966
--- /dev/null
@@ -0,0 +1,54 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_logb(ieee754sp x)
+{
+       COMPXSP;
+
+       CLEARCX;
+
+       EXPLODEXSP;
+
+       switch (xc) {
+       case IEEE754_CLASS_SNAN:
+               return ieee754sp_nanxcpt(x, "logb", x);
+       case IEEE754_CLASS_QNAN:
+               return x;
+       case IEEE754_CLASS_INF:
+               return ieee754sp_inf(0);
+       case IEEE754_CLASS_ZERO:
+               return ieee754sp_inf(1);
+       case IEEE754_CLASS_DNORM:
+               SPDNORMX;
+               break;
+       case IEEE754_CLASS_NORM:
+               break;
+       }
+       return ieee754sp_fint(xe);
+}
diff --git a/arch/mips/math-emu/sp_modf.c b/arch/mips/math-emu/sp_modf.c
new file mode 100644 (file)
index 0000000..69d6921
--- /dev/null
@@ -0,0 +1,80 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+/* modf function is always exact for a finite number
+*/
+ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip)
+{
+       COMPXSP;
+
+       CLEARCX;
+
+       EXPLODEXSP;
+
+       switch (xc) {
+       case IEEE754_CLASS_SNAN:
+       case IEEE754_CLASS_QNAN:
+       case IEEE754_CLASS_INF:
+       case IEEE754_CLASS_ZERO:
+               *ip = x;
+               return x;
+       case IEEE754_CLASS_DNORM:
+               /* far to small */
+               *ip = ieee754sp_zero(xs);
+               return x;
+       case IEEE754_CLASS_NORM:
+               break;
+       }
+       if (xe < 0) {
+               *ip = ieee754sp_zero(xs);
+               return x;
+       }
+       if (xe >= SP_MBITS) {
+               *ip = x;
+               return ieee754sp_zero(xs);
+       }
+       /* generate ipart mantissa by clearing bottom bits 
+        */
+       *ip = buildsp(xs, xe + SP_EBIAS,
+                     ((xm >> (SP_MBITS - xe)) << (SP_MBITS - xe)) &
+                     ~SP_HIDDEN_BIT);
+
+       /* generate fpart mantissa by clearing top bits
+        * and normalizing (must be able to normalize)
+        */
+       xm = (xm << (32 - (SP_MBITS - xe))) >> (32 - (SP_MBITS - xe));
+       if (xm == 0)
+               return ieee754sp_zero(xs);
+
+       while ((xm >> SP_MBITS) == 0) {
+               xm <<= 1;
+               xe--;
+       }
+       return buildsp(xs, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
+}
diff --git a/arch/mips/math-emu/sp_mul.c b/arch/mips/math-emu/sp_mul.c
new file mode 100644 (file)
index 0000000..cecf18f
--- /dev/null
@@ -0,0 +1,174 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y)
+{
+       COMPXSP;
+       COMPYSP;
+
+       CLEARCX;
+
+       EXPLODEXSP;
+       EXPLODEYSP;
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+               return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "mul", x,
+                                        y);
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754sp_nanxcpt(y, "mul", x, y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754sp_nanxcpt(x, "mul", x, y);
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+               return ieee754sp_bestnan(x, y);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return x;
+
+
+               /* Infinity handeling */
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+               SETCX(IEEE754_INVALID_OPERATION);
+               return ieee754sp_xcpt(ieee754sp_indef(), "mul", x, y);
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+               return ieee754sp_inf(xs ^ ys);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               return ieee754sp_zero(xs ^ ys);
+
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               SPDNORMX;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               SPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               SPDNORMX;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+               break;
+       }
+       /* rm = xm * ym, re = xe+ye basicly */
+       assert(xm & SP_HIDDEN_BIT);
+       assert(ym & SP_HIDDEN_BIT);
+
+       {
+               int re = xe + ye;
+               int rs = xs ^ ys;
+               unsigned rm;
+
+               /* shunt to top of word */
+               xm <<= 32 - (SP_MBITS + 1);
+               ym <<= 32 - (SP_MBITS + 1);
+
+               /* multiply 32bits xm,ym to give high 32bits rm with stickness
+                */
+               {
+                       unsigned short lxm = xm & 0xffff;
+                       unsigned short hxm = xm >> 16;
+                       unsigned short lym = ym & 0xffff;
+                       unsigned short hym = ym >> 16;
+                       unsigned lrm;
+                       unsigned hrm;
+
+                       lrm = lxm * lym;        /* 16 * 16 => 32 */
+                       hrm = hxm * hym;        /* 16 * 16 => 32 */
+
+                       {
+                               unsigned t = lxm * hym; /* 16 * 16 => 32 */
+                               {
+                                       unsigned at = lrm + (t << 16);
+                                       hrm += at < lrm;
+                                       lrm = at;
+                               }
+                               hrm = hrm + (t >> 16);
+                       }
+
+                       {
+                               unsigned t = hxm * lym; /* 16 * 16 => 32 */
+                               {
+                                       unsigned at = lrm + (t << 16);
+                                       hrm += at < lrm;
+                                       lrm = at;
+                               }
+                               hrm = hrm + (t >> 16);
+                       }
+                       rm = hrm | (lrm != 0);
+               }
+
+               /*
+                * sticky shift down to normal rounding precision
+                */
+               if ((int) rm < 0) {
+                       rm = (rm >> (32 - (SP_MBITS + 1 + 3))) |
+                           ((rm << (SP_MBITS + 1 + 3)) != 0);
+                       re++;
+               } else {
+                       rm = (rm >> (32 - (SP_MBITS + 1 + 3 + 1))) |
+                           ((rm << (SP_MBITS + 1 + 3 + 1)) != 0);
+               }
+               assert(rm & (SP_HIDDEN_BIT << 3));
+
+               SPNORMRET2(rs, re, rm, "mul", x, y);
+       }
+}
diff --git a/arch/mips/math-emu/sp_scalb.c b/arch/mips/math-emu/sp_scalb.c
new file mode 100644 (file)
index 0000000..65fdb51
--- /dev/null
@@ -0,0 +1,58 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_scalb(ieee754sp x, int n)
+{
+       COMPXSP;
+
+       CLEARCX;
+
+       EXPLODEXSP;
+
+       switch (xc) {
+       case IEEE754_CLASS_SNAN:
+               return ieee754sp_nanxcpt(x, "scalb", x, n);
+       case IEEE754_CLASS_QNAN:
+       case IEEE754_CLASS_INF:
+       case IEEE754_CLASS_ZERO:
+               return x;
+       case IEEE754_CLASS_DNORM:
+               SPDNORMX;
+               break;
+       case IEEE754_CLASS_NORM:
+               break;
+       }
+       SPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n);
+}
+
+
+ieee754sp ieee754sp_ldexp(ieee754sp x, int n)
+{
+       return ieee754sp_scalb(x, n);
+}
diff --git a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c
new file mode 100644 (file)
index 0000000..467e106
--- /dev/null
@@ -0,0 +1,66 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+int ieee754sp_finite(ieee754sp x)
+{
+       return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS;
+}
+
+ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y)
+{
+       CLEARCX;
+       SPSIGN(x) = SPSIGN(y);
+       return x;
+}
+
+
+ieee754sp ieee754sp_neg(ieee754sp x)
+{
+       CLEARCX;
+
+       if (ieee754sp_isnan(x)) /* but not infinity */
+               return ieee754sp_nanxcpt(x, "neg", x);
+
+       /* quick fix up */
+       SPSIGN(x) ^= 1;
+       return x;
+}
+
+
+ieee754sp ieee754sp_abs(ieee754sp x)
+{
+       CLEARCX;
+
+       if (ieee754sp_isnan(x)) /* but not infinity */
+               return ieee754sp_nanxcpt(x, "abs", x);
+
+       /* quick fix up */
+       SPSIGN(x) = 0;
+       return x;
+}
diff --git a/arch/mips/math-emu/sp_sqrt.c b/arch/mips/math-emu/sp_sqrt.c
new file mode 100644 (file)
index 0000000..d3eab4f
--- /dev/null
@@ -0,0 +1,115 @@
+/* IEEE754 floating point arithmetic
+ * single precision square root
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+static const struct ieee754sp_konst knan = {
+       0, SP_EBIAS + SP_EMAX + 1, 0
+};
+
+#define nan    ((ieee754sp)knan)
+
+ieee754sp ieee754sp_sqrt(ieee754sp x)
+{
+       int sign = (int) 0x80000000;
+       int ix, s, q, m, t, i;
+       unsigned int r;
+       COMPXDP;
+
+       /* take care of Inf and NaN */
+
+       EXPLODEXDP;
+
+       /* x == INF or NAN? */
+       switch (xc) {
+       case IEEE754_CLASS_QNAN:
+       case IEEE754_CLASS_SNAN:
+               /* sqrt(Nan) = Nan */
+               return ieee754sp_nanxcpt(x, "sqrt");
+       case IEEE754_CLASS_ZERO:
+               /* sqrt(0) = 0 */
+               return x;
+       case IEEE754_CLASS_INF:
+               if (xs)
+                       /* sqrt(-Inf) = Nan */
+                       return ieee754sp_nanxcpt(nan, "sqrt");
+               /* sqrt(+Inf) = Inf */
+               return x;
+       case IEEE754_CLASS_DNORM:
+       case IEEE754_CLASS_NORM:
+               if (xs)
+                       /* sqrt(-x) = Nan */
+                       return ieee754sp_nanxcpt(nan, "sqrt");
+               break;
+       }
+
+       ix = x.bits;
+
+       /* normalize x */
+       m = (ix >> 23);
+       if (m == 0) {           /* subnormal x */
+               for (i = 0; (ix & 0x00800000) == 0; i++)
+                       ix <<= 1;
+               m -= i - 1;
+       }
+       m -= 127;               /* unbias exponent */
+       ix = (ix & 0x007fffff) | 0x00800000;
+       if (m & 1)              /* odd m, double x to make it even */
+               ix += ix;
+       m >>= 1;                /* m = [m/2] */
+
+       /* generate sqrt(x) bit by bit */
+       ix += ix;
+       q = s = 0;              /* q = sqrt(x) */
+       r = 0x01000000;         /* r = moving bit from right to left */
+
+       while (r != 0) {
+               t = s + r;
+               if (t <= ix) {
+                       s = t + r;
+                       ix -= t;
+                       q += r;
+               }
+               ix += ix;
+               r >>= 1;
+       }
+
+       if (ix != 0) {
+               switch (ieee754_csr.rm) {
+               case IEEE754_RP:
+                       q += 2;
+                       break;
+               case IEEE754_RN:
+                       q += (q & 1);
+                       break;
+               }
+       }
+       ix = (q >> 1) + 0x3f000000;
+       ix += (m << 23);
+       x.bits = ix;
+       return x;
+}
diff --git a/arch/mips/math-emu/sp_sub.c b/arch/mips/math-emu/sp_sub.c
new file mode 100644 (file)
index 0000000..c28fc89
--- /dev/null
@@ -0,0 +1,187 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)
+{
+       COMPXSP;
+       COMPYSP;
+
+       CLEARCX;
+
+       EXPLODEXSP;
+       EXPLODEYSP;
+
+       switch (CLPAIR(xc, yc)) {
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+               return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "sub", x,
+                                        y);
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+               return ieee754sp_nanxcpt(y, "sub", x, y);
+
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+               return ieee754sp_nanxcpt(x, "sub", x, y);
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+               return ieee754sp_bestnan(x, y);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+       case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+               return x;
+
+
+               /* Inifity handeling 
+                */
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+               if (xs != ys)
+                       return x;
+               SETCX(IEEE754_INVALID_OPERATION);
+               return ieee754sp_xcpt(ieee754sp_indef(), "sub", x, y);
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+               return ieee754sp_inf(ys ^ 1);
+
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+               return x;
+
+               /* Zero handeling 
+                */
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+               if (xs != ys)
+                       return x;
+               else
+                       return ieee754sp_zero(ieee754_csr.rm ==
+                                             IEEE754_RD);
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+               return x;
+
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+       case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+               /* quick fix up */
+               DPSIGN(y) ^= 1;
+               return y;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+               SPDNORMX;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+               SPDNORMY;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+               SPDNORMX;
+               break;
+
+       case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+               break;
+       }
+       /* flip sign of y and handle as add */
+       ys ^= 1;
+
+       assert(xm & SP_HIDDEN_BIT);
+       assert(ym & SP_HIDDEN_BIT);
+
+
+       /* provide guard,round and stick bit space */
+       xm <<= 3;
+       ym <<= 3;
+
+       if (xe > ye) {
+               /* have to shift y fraction right to align
+                */
+               int s = xe - ye;
+               SPXSRSYn(s);
+       } else if (ye > xe) {
+               /* have to shift x fraction right to align
+                */
+               int s = ye - xe;
+               SPXSRSXn(s);
+       }
+       assert(xe == ye);
+       assert(xe <= SP_EMAX);
+
+       if (xs == ys) {
+               /* generate 28 bit result of adding two 27 bit numbers
+                */
+               xm = xm + ym;
+               xe = xe;
+               xs = xs;
+
+               if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */
+                       SPXSRSX1();     /* shift preserving sticky */
+               }
+       } else {
+               if (xm >= ym) {
+                       xm = xm - ym;
+                       xe = xe;
+                       xs = xs;
+               } else {
+                       xm = ym - xm;
+                       xe = xe;
+                       xs = ys;
+               }
+               if (xm == 0)
+                       if (ieee754_csr.rm == IEEE754_RD)
+                               return ieee754sp_zero(1);       /* round negative inf. => sign = -1 */
+                       else
+                               return ieee754sp_zero(0);       /* other round modes   => sign = 1 */
+
+               /* normalize to rounding precision 
+                */
+               while ((xm >> (SP_MBITS + 3)) == 0) {
+                       xm <<= 1;
+                       xe--;
+               }
+       }
+       SPNORMRET2(xs, xe, xm, "sub", x, y);
+}
diff --git a/arch/mips/math-emu/sp_tint.c b/arch/mips/math-emu/sp_tint.c
new file mode 100644 (file)
index 0000000..8f3ed14
--- /dev/null
@@ -0,0 +1,88 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <linux/kernel.h>
+#include "ieee754sp.h"
+
+int ieee754sp_tint(ieee754sp x)
+{
+       COMPXSP;
+
+       CLEARCX;
+
+       EXPLODEXSP;
+
+       switch (xc) {
+       case IEEE754_CLASS_SNAN:
+       case IEEE754_CLASS_QNAN:
+               SETCX(IEEE754_INVALID_OPERATION);
+               return ieee754si_xcpt(ieee754si_indef(), "fixsp", x);
+       case IEEE754_CLASS_INF:
+               SETCX(IEEE754_OVERFLOW);
+               return ieee754si_xcpt(ieee754si_indef(), "fixsp", x);
+       case IEEE754_CLASS_ZERO:
+               return 0;
+       case IEEE754_CLASS_DNORM:       /* much to small */
+               SETCX(IEEE754_UNDERFLOW);
+               return ieee754si_xcpt(0, "fixsp", x);
+       case IEEE754_CLASS_NORM:
+               break;
+       }
+       if (xe >= 31) {
+               SETCX(IEEE754_OVERFLOW);
+               return ieee754si_xcpt(ieee754si_indef(), "fix", x);
+       }
+       if (xe < 0) {
+               SETCX(IEEE754_UNDERFLOW);
+               return ieee754si_xcpt(0, "fix", x);
+       }
+       /* oh gawd */
+       if (xe > SP_MBITS) {
+               xm <<= xe - SP_MBITS;
+       } else if (xe < SP_MBITS) {
+               /* XXX no rounding 
+                */
+               xm >>= SP_MBITS - xe;
+       }
+       if (xs)
+               return -xm;
+       else
+               return xm;
+}
+
+
+unsigned int ieee754sp_tuns(ieee754sp x)
+{
+       ieee754sp hb = ieee754sp_1e31();
+
+       /* what if x < 0 ?? */
+       if (ieee754sp_lt(x, hb))
+               return (unsigned) ieee754sp_tint(x);
+
+       return (unsigned) ieee754sp_tint(ieee754sp_sub(x, hb)) |
+           ((unsigned) 1 << 31);
+}
diff --git a/arch/mips/math-emu/sp_tlong.c b/arch/mips/math-emu/sp_tlong.c
new file mode 100644 (file)
index 0000000..a7b0712
--- /dev/null
@@ -0,0 +1,87 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+long long ieee754sp_tlong(ieee754sp x)
+{
+       COMPXDP;                /* <-- need 64-bit mantissa tmp */
+
+       CLEARCX;
+
+       EXPLODEXSP;
+
+       switch (xc) {
+       case IEEE754_CLASS_SNAN:
+       case IEEE754_CLASS_QNAN:
+               SETCX(IEEE754_INVALID_OPERATION);
+               return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+       case IEEE754_CLASS_INF:
+               SETCX(IEEE754_OVERFLOW);
+               return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+       case IEEE754_CLASS_ZERO:
+               return 0;
+       case IEEE754_CLASS_DNORM:       /* much to small */
+               SETCX(IEEE754_UNDERFLOW);
+               return ieee754di_xcpt(0, "sp_tlong", x);
+       case IEEE754_CLASS_NORM:
+               break;
+       }
+       if (xe >= 63) {
+               SETCX(IEEE754_OVERFLOW);
+               return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+       }
+       if (xe < 0) {
+               SETCX(IEEE754_UNDERFLOW);
+               return ieee754di_xcpt(0, "sp_tlong", x);
+       }
+       /* oh gawd */
+       if (xe > SP_MBITS) {
+               xm <<= xe - SP_MBITS;
+       } else if (xe < SP_MBITS) {
+               /* XXX no rounding 
+                */
+               xm >>= SP_MBITS - xe;
+       }
+       if (xs)
+               return -xm;
+       else
+               return xm;
+}
+
+
+unsigned long long ieee754sp_tulong(ieee754sp x)
+{
+       ieee754sp hb = ieee754sp_1e63();
+
+       /* what if x < 0 ?? */
+       if (ieee754sp_lt(x, hb))
+               return (unsigned long long) ieee754sp_tlong(x);
+
+       return (unsigned long long) ieee754sp_tlong(ieee754sp_sub(x, hb)) |
+           (1ULL << 63);
+}
diff --git a/arch/mips/mips-boards/atlas/Makefile b/arch/mips/mips-boards/atlas/Makefile
new file mode 100644 (file)
index 0000000..b5939f8
--- /dev/null
@@ -0,0 +1,42 @@
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+#
+# ########################################################################
+#
+# This program is free software; you can distribute it and/or modify it
+# under the terms of the GNU General Public License (Version 2) as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# #######################################################################
+#
+# Makefile for the MIPS Atlas specific kernel interface routines
+# under Linux.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+.S.s:
+       $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+       $(CC) $(CFLAGS) -c $< -o $*.o
+
+all: atlas.o
+
+O_TARGET := atlas.o
+
+obj-y  := atlas_int.o atlas_rtc.o atlas_setup.o
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c
new file mode 100644 (file)
index 0000000..8ff004b
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Routines for generic manipulation of the interrupts found on the MIPS 
+ * Atlas board.
+ *
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/irq.h>
+#include <asm/mips-boards/atlas.h>
+#include <asm/mips-boards/atlasint.h>
+#include <asm/gdb-stub.h>
+
+
+struct atlas_ictrl_regs *atlas_hw0_icregs
+       = (struct atlas_ictrl_regs *)ATLAS_ICTRL_REGS_BASE;
+
+extern asmlinkage void mipsIRQ(void);
+extern void do_IRQ(int irq, struct pt_regs *regs);
+
+unsigned long spurious_count = 0;
+irq_desc_t irq_desc[NR_IRQS];
+
+#if 0
+#define DEBUG_INT(x...) printk(x)
+#else
+#define DEBUG_INT(x...)
+#endif
+
+void disable_atlas_irq(unsigned int irq_nr)
+{
+       atlas_hw0_icregs->intrsten = (1 << irq_nr);
+}
+
+void enable_atlas_irq(unsigned int irq_nr)
+{
+       atlas_hw0_icregs->intseten = (1 << irq_nr);
+}
+
+static unsigned int startup_atlas_irq(unsigned int irq)
+{
+       enable_atlas_irq(irq);
+       return 0; /* never anything pending */
+}
+
+#define shutdown_atlas_irq     disable_atlas_irq
+
+#define mask_and_ack_atlas_irq disable_atlas_irq
+
+static void end_atlas_irq(unsigned int irq)
+{
+       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+               enable_atlas_irq(irq);
+}
+
+static struct hw_interrupt_type atlas_irq_type = {
+       "Atlas",
+       startup_atlas_irq,
+       shutdown_atlas_irq,
+       enable_atlas_irq,
+       disable_atlas_irq,
+       mask_and_ack_atlas_irq,
+       end_atlas_irq,
+       NULL
+};
+
+int get_irq_list(char *buf)
+{
+       int i, len = 0;
+       int num = 0;
+       struct irqaction *action;
+
+       for (i = 0; i < ATLASINT_END; i++, num++) {
+               action = irq_desc[i].action;
+               if (!action) 
+                       continue;
+               len += sprintf(buf+len, "%2d: %8d %c %s",
+                       num, kstat.irqs[0][num],
+                       (action->flags & SA_INTERRUPT) ? '+' : ' ',
+                       action->name);
+               for (action=action->next; action; action = action->next) {
+                       len += sprintf(buf+len, ",%s %s",
+                               (action->flags & SA_INTERRUPT) ? " +" : "",
+                               action->name);
+               }
+               len += sprintf(buf+len, " [hw0]\n");
+       }
+       return len;
+}
+
+int request_irq(unsigned int irq, 
+               void (*handler)(int, void *, struct pt_regs *),
+               unsigned long irqflags, 
+               const char * devname,
+               void *dev_id)
+{  
+        struct irqaction *action;
+
+       DEBUG_INT("request_irq: irq=%d, devname = %s\n", irq, devname);
+
+       if (irq >= ATLASINT_END)
+               return -EINVAL;
+       if (!handler)
+               return -EINVAL;
+
+       action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+       if(!action)
+               return -ENOMEM;
+
+       action->handler = handler;
+       action->flags = irqflags;
+       action->mask = 0;
+       action->name = devname;
+       action->dev_id = dev_id;
+       action->next = 0;
+       irq_desc[irq].action = action;
+       enable_atlas_irq(irq);
+
+       return 0;
+}
+
+void free_irq(unsigned int irq, void *dev_id)
+{
+       struct irqaction *action;
+
+       if (irq >= ATLASINT_END) {
+               printk("Trying to free IRQ%d\n",irq);
+               return;
+       }
+
+       action = irq_desc[irq].action;
+       irq_desc[irq].action = NULL;
+       disable_atlas_irq(irq);
+       kfree(action);
+}
+
+static inline int ls1bit32(unsigned int x)
+{
+       int b = 31, s;
+
+       s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
+       s =  8; if (x <<  8 == 0) s = 0; b -= s; x <<= s;
+       s =  4; if (x <<  4 == 0) s = 0; b -= s; x <<= s;
+       s =  2; if (x <<  2 == 0) s = 0; b -= s; x <<= s;
+       s =  1; if (x <<  1 == 0) s = 0; b -= s;
+
+       return b;
+}
+
+void atlas_hw0_irqdispatch(struct pt_regs *regs)
+{
+       struct irqaction *action;
+       unsigned long int_status;
+       int irq, cpu = smp_processor_id();
+
+       int_status = atlas_hw0_icregs->intstatus; 
+
+       /* if int_status == 0, then the interrupt has already been cleared */
+       if (int_status == 0)
+               return;
+
+       irq = ls1bit32(int_status);
+       action = irq_desc[irq].action;
+
+       DEBUG_INT("atlas_hw0_irqdispatch: irq=%d\n", irq);
+
+       /* if action == NULL, then we don't have a handler for the irq */
+       if ( action == NULL ) {
+               printk("No handler for hw0 irq: %i\n", irq);
+               spurious_count++;
+               return;
+       }
+
+       irq_enter(cpu, irq);
+       kstat.irqs[0][irq]++;
+       action->handler(irq, action->dev_id, regs);
+       irq_exit(cpu, irq);
+
+       return;         
+}
+
+unsigned long probe_irq_on (void)
+{
+       return 0;
+}
+
+
+int probe_irq_off (unsigned long irqs)
+{
+       return 0;
+}
+
+#ifdef CONFIG_REMOTE_DEBUG
+extern void breakpoint(void);
+extern int remote_debug;
+#endif
+
+void __init init_IRQ(void)
+{
+       int i;
+
+       /* 
+        * Mask out all interrupt by writing "1" to all bit position in 
+        * the interrupt reset reg. 
+        */
+       atlas_hw0_icregs->intrsten = 0xffffffff;    
+
+       /* Now safe to set the exception vector. */
+       set_except_vector(0, mipsIRQ);
+
+       for (i = 0; i <= ATLASINT_END; i++) {
+               irq_desc[i].status      = IRQ_DISABLED;
+               irq_desc[i].action      = 0;
+               irq_desc[i].depth       = 1;
+               irq_desc[i].handler     = &atlas_irq_type;
+       }
+
+#ifdef CONFIG_REMOTE_DEBUG
+       if (remote_debug) {
+               set_debug_traps();
+               breakpoint();
+       }
+#endif
+}
diff --git a/arch/mips/mips-boards/atlas/atlas_rtc.c b/arch/mips/mips-boards/atlas/atlas_rtc.c
new file mode 100644 (file)
index 0000000..45b2f44
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * RTC routines for Atlas style attached Dallas chip.
+ *
+ */
+#include <linux/spinlock.h>
+#include <linux/mc146818rtc.h>
+#include <asm/mips-boards/atlas.h>
+
+
+static unsigned char atlas_rtc_read_data(unsigned long addr)
+{
+       volatile unsigned int *rtc_adr_reg = (void *)ATLAS_RTC_ADR_REG;
+       volatile unsigned int *rtc_dat_reg = (void *)ATLAS_RTC_DAT_REG;
+
+       *rtc_adr_reg = addr;
+
+       return *rtc_dat_reg;
+}
+
+static void atlas_rtc_write_data(unsigned char data, unsigned long addr)
+{
+       volatile unsigned int *rtc_adr_reg = (void *)ATLAS_RTC_ADR_REG;
+       volatile unsigned int *rtc_dat_reg = (void *)ATLAS_RTC_DAT_REG;
+
+       *rtc_adr_reg = addr;
+       *rtc_dat_reg = data;
+}
+
+static int atlas_rtc_bcd_mode(void)
+{
+       return 0;
+}
+
+struct rtc_ops atlas_rtc_ops = {
+       &atlas_rtc_read_data,
+       &atlas_rtc_write_data,
+       &atlas_rtc_bcd_mode
+};
diff --git a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c
new file mode 100644 (file)
index 0000000..42546a9
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Atlas specific setup.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/mc146818rtc.h>
+#include <linux/ioport.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/gt64120.h>
+#include <asm/mips-boards/atlasint.h>
+
+#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE)
+extern void console_setup(char *, int *);
+char serial_console[20];
+#endif
+
+#ifdef CONFIG_REMOTE_DEBUG
+extern void rs_kgdb_hook(int);
+extern void saa9730_kgdb_hook(void);
+extern void breakpoint(void);
+int remote_debug = 0;
+#endif
+
+extern struct rtc_ops atlas_rtc_ops;
+
+extern void mips_reboot_setup(void);
+
+void __init atlas_setup(void)
+{
+#ifdef CONFIG_REMOTE_DEBUG
+       int rs_putDebugChar(char);
+       char rs_getDebugChar(void);
+       int saa9730_putDebugChar(char);
+       char saa9730_getDebugChar(void);
+       extern int (*putDebugChar)(char);
+       extern char (*getDebugChar)(void);
+#endif
+       char *argptr;
+
+       ioport_resource.end = 0x7fffffff;
+
+#ifdef CONFIG_SERIAL_CONSOLE
+       argptr = prom_getcmdline();
+       if ((argptr = strstr(argptr, "console=ttyS0")) == NULL) {
+               int i = 0;
+               char *s = prom_getenv("modetty0");
+               while(s[i] >= '0' && s[i] <= '9')
+                       i++;
+               strcpy(serial_console, "ttyS0,");
+               strncpy(serial_console + 6, s, i);
+               prom_printf("Config serial console: %s\n", serial_console);
+               console_setup(serial_console, NULL);
+       }
+#endif   
+
+#ifdef CONFIG_REMOTE_DEBUG
+       argptr = prom_getcmdline();
+       if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
+               int line;
+               argptr += strlen("kgdb=ttyS");
+               if (*argptr != '0' && *argptr != '1')
+                       printk("KGDB: Uknown serial line /dev/ttyS%c, "
+                              "falling back to /dev/ttyS1\n", *argptr);
+               line = *argptr == '0' ? 0 : 1;
+               printk("KGDB: Using serial line /dev/ttyS%d for session\n",
+                      line ? 1 : 0);
+
+               if(line == 0) {
+                       rs_kgdb_hook(line);
+                       putDebugChar = rs_putDebugChar;
+                       getDebugChar = rs_getDebugChar;
+               } else {
+                       saa9730_kgdb_hook();
+                       putDebugChar = saa9730_putDebugChar;
+                       getDebugChar = saa9730_getDebugChar;
+               }
+
+               prom_printf("KGDB: Using serial line /dev/ttyS%d for session, "
+                           "please connect your debugger\n", line ? 1 : 0);
+
+               remote_debug = 1;
+               /* Breakpoints and stuff are in atlas_irq_setup() */
+       }
+#endif
+       argptr = prom_getcmdline();
+
+       if ((argptr = strstr(argptr, "nofpu")) != NULL)
+               mips_cpu.options &= ~MIPS_CPU_FPU;
+
+       rtc_ops = &atlas_rtc_ops;
+
+       mips_reboot_setup();
+}
diff --git a/arch/mips/mips-boards/generic/Makefile b/arch/mips/mips-boards/generic/Makefile
new file mode 100644 (file)
index 0000000..ebc07dc
--- /dev/null
@@ -0,0 +1,41 @@
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+#
+# ########################################################################
+#
+# This program is free software; you can distribute it and/or modify it
+# under the terms of the GNU General Public License (Version 2) as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# #######################################################################
+#
+# Makefile for the MIPS boards generic routines under Linux.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+.S.s:
+       $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+       $(CC) $(CFLAGS) -c $< -o $*.o
+
+O_TARGET := mipsboards.o
+
+obj-y                          := mipsIRQ.o pci.o reset.o display.o init.o \
+                                  memory.o printf.o cmdline.o time.o
+obj-$(CONFIG_REMOTE_DEBUG)     += gdb_hook.o
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/mips/mips-boards/generic/cmdline.c b/arch/mips/mips-boards/generic/cmdline.c
new file mode 100644 (file)
index 0000000..375891c
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Kernel command line creation using the prom monitor (YAMON) argc/argv.
+ */
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+extern int prom_argc;
+extern char **prom_argv;
+
+char arcs_cmdline[COMMAND_LINE_SIZE];
+
+char * __init prom_getcmdline(void)
+{
+       return &(arcs_cmdline[0]);
+}
+
+
+void  __init prom_init_cmdline(void)
+{
+       char *cp;
+       int actr;
+
+       actr = 1; /* Always ignore argv[0] */
+
+       cp = &(arcs_cmdline[0]);
+       while(actr < prom_argc) {
+               strcpy(cp, prom_argv[actr]);
+               cp += strlen(prom_argv[actr]);
+               *cp++ = ' ';
+               actr++;
+       }
+       if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
+               --cp;
+       *cp = '\0';
+}
diff --git a/arch/mips/mips-boards/generic/display.c b/arch/mips/mips-boards/generic/display.c
new file mode 100644 (file)
index 0000000..218c4e6
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ * 
+ * Display routines for display messages in MIPS boards ascii display.
+ *
+ */
+
+#include <asm/mips-boards/generic.h>
+
+
+void mips_display_message(const char *str)
+{
+        volatile unsigned int *display = (void *)ASCII_DISPLAY_POS_BASE;
+       int i;
+
+       for (i = 0; i <= 14; i=i+2) {
+                if (*str)
+                        display[i] = *str++;
+                else
+                        display[i] = ' ';
+       }
+}
+
+void mips_display_word(unsigned int num)
+{
+        volatile unsigned int *display = (void *)ASCII_DISPLAY_WORD_BASE;
+       
+       *display = num;
+}
diff --git a/arch/mips/mips-boards/generic/gdb_hook.c b/arch/mips/mips-boards/generic/gdb_hook.c
new file mode 100644 (file)
index 0000000..f986648
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * This is the interface to the remote debugger stub.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+
+#include <asm/serial.h>
+#include <asm/io.h>
+
+static struct serial_state rs_table[RS_TABLE_SIZE] = {
+       SERIAL_PORT_DFNS        /* Defined in serial.h */
+};
+
+static struct async_struct kdb_port_info = {0};
+
+int (*putDebugChar)(char);
+char (*getDebugChar)(void);
+
+static __inline__ unsigned int serial_in(struct async_struct *info, int offset)
+{
+       return inb(info->port + offset);
+}
+
+static __inline__ void serial_out(struct async_struct *info, int offset,
+                               int value)
+{
+       outb(value, info->port+offset);
+}
+
+void rs_kgdb_hook(int tty_no) {
+       int t;
+       struct serial_state *ser = &rs_table[tty_no];
+
+       kdb_port_info.state = ser;
+       kdb_port_info.magic = SERIAL_MAGIC;
+       kdb_port_info.port = ser->port;
+       kdb_port_info.flags = ser->flags;
+
+       /*
+        * Clear all interrupts
+        */
+       serial_in(&kdb_port_info, UART_LSR);
+       serial_in(&kdb_port_info, UART_RX);
+       serial_in(&kdb_port_info, UART_IIR);
+       serial_in(&kdb_port_info, UART_MSR);
+
+       /*
+        * Now, initialize the UART 
+        */
+       serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8);   /* reset DLAB */
+       if (kdb_port_info.flags & ASYNC_FOURPORT) {
+               kdb_port_info.MCR = UART_MCR_DTR | UART_MCR_RTS;
+               t = UART_MCR_DTR | UART_MCR_OUT1;
+       } else {
+               kdb_port_info.MCR 
+                       = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
+               t = UART_MCR_DTR | UART_MCR_RTS;
+       }
+
+       kdb_port_info.MCR = t;          /* no interrupts, please */
+       serial_out(&kdb_port_info, UART_MCR, kdb_port_info.MCR);
+       
+       /*
+        * and set the speed of the serial port
+        * (currently hardwired to 9600 8N1
+        */
+
+       /* baud rate is fixed to 9600 (is this sufficient?)*/
+       t = kdb_port_info.state->baud_base / 9600;      
+       /* set DLAB */
+       serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8 | UART_LCR_DLAB);
+       serial_out(&kdb_port_info, UART_DLL, t & 0xff);/* LS of divisor */
+       serial_out(&kdb_port_info, UART_DLM, t >> 8);  /* MS of divisor */
+       /* reset DLAB */
+       serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8);
+}
+
+int rs_putDebugChar(char c)
+{
+
+       if (!kdb_port_info.state) {     /* need to init device first */
+               return 0;
+       }
+
+       while ((serial_in(&kdb_port_info, UART_LSR) & UART_LSR_THRE) == 0)
+               ;
+
+       serial_out(&kdb_port_info, UART_TX, c);
+
+       return 1;
+}
+
+char rs_getDebugChar(void)
+{
+       if (!kdb_port_info.state) {     /* need to init device first */
+               return 0;
+       }
+
+       while (!(serial_in(&kdb_port_info, UART_LSR) & 1))
+               ;
+
+       return(serial_in(&kdb_port_info, UART_RX));
+}
+
+
+#ifdef CONFIG_MIPS_ATLAS
+
+#include <asm/mips-boards/atlas.h>
+#include <asm/mips-boards/saa9730_uart.h>
+
+#define INB(a)     inb((unsigned long)a)
+#define OUTB(x,a)  outb(x,(unsigned long)a)
+
+/*
+ * This is the interface to the remote debugger stub
+ * if the Philips part is used for the debug port,
+ * called from the platform setup code.
+ *
+ * PCI init will not have been done yet, we make a
+ * universal assumption about the way the bootloader (YAMON)
+ * have located and set up the chip.
+ */
+static t_uart_saa9730_regmap *kgdb_uart = (void *)(ATLAS_SAA9730_REG + SAA9730_UART_REGS_ADDR);
+
+static int saa9730_kgdb_active = 0;
+
+void saa9730_kgdb_hook(void) 
+{
+        volatile unsigned char t;
+
+        /*
+         * Clear all interrupts
+         */
+       t = INB(&kgdb_uart->Lsr);
+       t += INB(&kgdb_uart->Msr);
+       t += INB(&kgdb_uart->Thr_Rbr);
+       t += INB(&kgdb_uart->Iir_Fcr);
+
+        /*
+         * Now, initialize the UART
+         */
+       /* 8 data bits, one stop bit, no parity */
+       OUTB(SAA9730_LCR_DATA8, &kgdb_uart->Lcr);
+
+        /* baud rate is fixed to 9600 (is this sufficient?)*/
+       OUTB(0, &kgdb_uart->BaudDivMsb); /* HACK - Assumes standard crystal */
+       OUTB(23, &kgdb_uart->BaudDivLsb); /* HACK - known for MIPS Atlas */
+
+       /* Set RTS/DTR active */
+       OUTB(SAA9730_MCR_DTR | SAA9730_MCR_RTS, &kgdb_uart->Mcr);
+       saa9730_kgdb_active = 1;
+}
+
+int saa9730_putDebugChar(char c)
+{
+
+        if (!saa9730_kgdb_active) {     /* need to init device first */
+                return 0;
+        }
+
+        while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_THRE))
+                ;
+       OUTB(c, &kgdb_uart->Thr_Rbr);
+
+        return 1;
+}
+
+char saa9730_getDebugChar(void)
+{
+       char c;
+
+        if (!saa9730_kgdb_active) {     /* need to init device first */
+                return 0;
+        }
+        while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_DR))
+                ;
+
+       c = INB(&kgdb_uart->Thr_Rbr);
+        return(c);
+}
+
+#endif
diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c
new file mode 100644 (file)
index 0000000..70b6767
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * PROM library initialisation code.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#include <asm/io.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/gt64120.h>
+#include <asm/mips-boards/malta.h>
+
+/* Environment variable */
+typedef struct
+{
+       char *name;
+       char *val;
+} t_env_var;
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+
+int init_debug = 0;
+
+char *prom_getenv(char *envname)
+{
+        /*
+        * Return a pointer to the given environment variable.
+        */
+
+       t_env_var *env = (t_env_var *)prom_envp;
+       int i;
+
+       i = strlen(envname);
+
+       while(env->name) {
+               if(strncmp(envname, env->name, i) == 0) {
+                       return(env->val);
+               }
+               env++;
+       }
+       return(NULL);
+}
+
+static inline unsigned char str2hexnum(unsigned char c)
+{
+       if(c >= '0' && c <= '9')
+               return c - '0';
+       if(c >= 'a' && c <= 'f')
+               return c - 'a' + 10;
+       return 0; /* foo */
+}
+
+static inline void str2eaddr(unsigned char *ea, unsigned char *str)
+{
+       int i;
+
+       for(i = 0; i < 6; i++) {
+               unsigned char num;
+
+               if((*str == '.') || (*str == ':'))
+                       str++;
+               num = str2hexnum(*str++) << 4;
+               num |= (str2hexnum(*str++));
+               ea[i] = num;
+       }
+}
+int get_ethernet_addr(char *ethernet_addr)
+{
+        char *ethaddr_str;
+
+        ethaddr_str = prom_getenv("ethaddr");
+       if (!ethaddr_str) {
+               printk("ethaddr not set in boot prom\n");
+               return -1;
+       }
+       str2eaddr(ethernet_addr, ethaddr_str);
+
+       if (init_debug > 1) {
+               int i;
+               printk("get_ethernet_addr: ");
+               for (i=0; i<5; i++)
+                       printk("%02x:", (unsigned char)*(ethernet_addr+i));
+               printk("%02x\n", *(ethernet_addr+i));
+       }
+
+       return 0;
+}
+
+int __init prom_init(int argc, char **argv, char **envp)
+{
+       prom_argc = argc;
+       prom_argv = argv;
+       prom_envp = envp;
+
+       mips_display_message("LINUX");
+
+       /*
+        * Setup the North bridge to do Master byte-lane swapping when 
+        * running in bigendian.
+        */
+#if defined(__MIPSEL__)
+       GT_WRITE(GT_PCI0_CMD_OFS, GT_PCI0_CMD_MBYTESWAP_BIT |
+                GT_PCI0_CMD_SBYTESWAP_BIT);
+#else
+       GT_WRITE(GT_PCI0_CMD_OFS, 0);
+#endif
+
+#if defined(CONFIG_MIPS_MALTA)
+       mips_io_port_base = MALTA_PORT_BASE;
+#else
+       mips_io_port_base = KSEG1;
+#endif
+       setup_prom_printf(0);
+       prom_printf("\nLINUX started...\n");
+       prom_init_cmdline();
+       prom_meminit();
+
+       return 0;
+}
diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c
new file mode 100644 (file)
index 0000000..915f0a3
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * PROM library functions for acquiring/using memory descriptors given to 
+ * us from the YAMON.
+ * 
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+
+#include <asm/mips-boards/prom.h>
+
+/*#define DEBUG*/
+
+enum yamon_memtypes {
+       yamon_dontuse,
+       yamon_prom,
+       yamon_free,
+};
+struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
+
+#ifdef DEBUG
+static char *mtypes[3] = {
+       "Dont use memory",
+       "YAMON PROM memory",
+       "Free memmory",
+};
+#endif
+
+
+struct prom_pmemblock * __init prom_getmdesc(void)
+{
+       char *memsize_str;
+       unsigned int memsize;
+
+       memsize_str = prom_getenv("memsize");
+       if (!memsize_str) {
+               prom_printf("memsize not set in boot prom, set to default (32Mb)\n");
+               memsize = 0x02000000;
+       } else {
+#ifdef DEBUG
+               prom_printf("prom_memsize = %s\n", memsize_str);
+#endif
+               memsize = simple_strtol(memsize_str, NULL, 0);
+       }
+
+       memset(mdesc, 0, sizeof(mdesc));
+
+       mdesc[0].type = yamon_dontuse;
+       mdesc[0].base = 0x00000000;
+       mdesc[0].size = 0x00001000;
+
+       mdesc[1].type = yamon_prom;
+       mdesc[1].base = 0x00001000;
+       mdesc[1].size = 0x000ef000;
+
+#if (CONFIG_MIPS_MALTA)
+       /* 
+        * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the
+        * south bridge and PCI access always forwarded to the ISA Bus and 
+        * BIOSCS# is always generated.
+        * This mean that this area can't be used as DMA memory for PCI 
+        * devices.
+        */
+       mdesc[2].type = yamon_dontuse;
+       mdesc[2].base = 0x000f0000;
+       mdesc[2].size = 0x00010000;
+#else
+       mdesc[2].type = yamon_prom;
+       mdesc[2].base = 0x000f0000;
+       mdesc[2].size = 0x00010000;
+#endif
+
+       mdesc[3].type = yamon_free;
+       mdesc[3].base = 0x00100000;
+       mdesc[3].size = memsize - mdesc[3].base;
+
+       return &mdesc[0];
+}
+
+static int __init prom_memtype_classify (unsigned int type)
+{
+       switch (type) {
+       case yamon_free:
+               return BOOT_MEM_RAM;
+       case yamon_prom:
+               return BOOT_MEM_ROM_DATA;
+       default:
+               return BOOT_MEM_RESERVED;
+       }
+}
+
+void __init prom_meminit(void)
+{
+       struct prom_pmemblock *p;
+
+#ifdef DEBUG
+       int i = 0;
+
+       prom_printf("YAMON MEMORY DESCRIPTOR dump:\n");
+       p = prom_getmdesc();
+       while (p->size) {
+               prom_printf("[%d,%p]: base<%08lx> size<%08lx> type<%s>\n",
+                           i, p, p->base, p->size, mtypes[p->type]);
+               p++;
+               i++;
+       }
+#endif
+       p = prom_getmdesc();
+       while (p->size) {
+               unsigned long base, size;
+               long type;
+
+               type = prom_memtype_classify (p->type);
+               base = p->base;
+               size = p->size;
+
+               add_memory_region(base, size, type);
+
+               p++;
+       }
+}
+
+void prom_free_prom_memory (void)
+{
+       int i;
+       struct prom_pmemblock *p;
+       unsigned long freed = 0;
+       unsigned long addr;
+
+       for (i = 0; i < boot_mem_map.nr_map; i++) {
+               if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
+                       continue;
+
+               addr = boot_mem_map.map[i].addr;
+               while (addr < boot_mem_map.map[i].addr
+                             + boot_mem_map.map[i].size) {
+                       ClearPageReserved(virt_to_page(phys_to_virt(addr)));
+                       set_page_count(virt_to_page(phys_to_virt(addr)), 1);
+                       free_page(phys_to_virt(addr));
+                       addr += PAGE_SIZE;
+                       freed += PAGE_SIZE;
+               }
+       }
+       printk("Freeing prom memory: %ldkb freed\n", freed >> 10);
+}
diff --git a/arch/mips/mips-boards/generic/mipsIRQ.S b/arch/mips/mips-boards/generic/mipsIRQ.S
new file mode 100644 (file)
index 0000000..c2b9d89
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Interrupt exception dispatch code.
+ *
+ */
+#include <linux/config.h>
+
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/* A lot of complication here is taken away because:
+ *
+ * 1) We handle one interrupt and return, sitting in a loop and moving across
+ *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
+ *    common case is one pending IRQ so optimize in that direction.
+ *
+ * 2) We need not check against bits in the status register IRQ mask, that
+ *    would make this routine slow as hell.
+ *
+ * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
+ *    between like BSD spl() brain-damage.
+ *
+ * Furthermore, the IRQs on the MIPS board look basically (barring software
+ * IRQs which we don't use at all and all external interrupt sources are
+ * combined together on hardware interrupt 0 (MIPS IRQ 2)) like:
+ *
+ *     MIPS IRQ        Source
+ *      --------        ------
+ *             0       Software (ignored)
+ *             1        Software (ignored)
+ *             2        Combined hardware interrupt (hw0)
+ *             3        Hardware (ignored)
+ *             4        Hardware (ignored)
+ *             5        Hardware (ignored)
+ *             6        Hardware (ignored)
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ * Lowest  ----     Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+       .text
+       .set    noreorder
+       .set    noat
+       .align  5
+       NESTED(mipsIRQ, PT_SIZE, sp)
+       SAVE_ALL
+       CLI
+       .set    at
+
+       mfc0    s0, CP0_CAUSE           # get irq mask
+
+       /* First we check for r4k counter/timer IRQ. */
+       andi    a0, s0, CAUSEF_IP7
+       beq     a0, zero, 1f
+        andi   a0, s0, CAUSEF_IP2      # delay slot, check hw0 interrupt
+
+       /* Wheee, a timer interrupt. */
+       move    a0, sp
+       jal     mips_timer_interrupt
+        nop
+
+       j       ret_from_irq
+        nop
+
+1:
+       beq     a0, zero, 1f
+        nop
+
+       /* Wheee, combined hardware level zero interrupt. */
+#if defined(CONFIG_MIPS_ATLAS)
+       jal     atlas_hw0_irqdispatch
+#elif defined(CONFIG_MIPS_MALTA)
+       jal     malta_hw0_irqdispatch
+#else
+#error "MIPS board not supported\n"    
+#endif
+        move   a0, sp                  # delay slot
+
+       j       ret_from_irq
+        nop                            # delay slot
+
+1:
+       /*
+        * Here by mistake?  This is possible, what can happen is that by the
+        * time we take the exception the IRQ pin goes low, so just leave if
+        * this is the case.
+        */
+       move    a1,s0
+       PRINT("Got interrupt: c0_cause = %08x\n")
+       mfc0    a1, CP0_EPC
+       PRINT("c0_epc = %08x\n")
+
+       j       ret_from_irq
+        nop
+       END(mipsIRQ)
diff --git a/arch/mips/mips-boards/generic/pci.c b/arch/mips/mips-boards/generic/pci.c
new file mode 100644 (file)
index 0000000..90b6700
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * MIPS boards specific PCI support.
+ *
+ */
+#include <linux/config.h>
+
+#ifdef CONFIG_PCI
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/mips-boards/generic.h>
+#include <asm/gt64120.h>
+#ifdef CONFIG_MIPS_MALTA
+#include <asm/mips-boards/malta.h>
+#endif
+
+#define PCI_ACCESS_READ  0
+#define PCI_ACCESS_WRITE 1
+
+static int
+mips_pcibios_config_access(unsigned char access_type, struct pci_dev *dev,
+                           unsigned char where, u32 *data)
+{
+       unsigned char bus = dev->bus->number;
+       unsigned char dev_fn = dev->devfn;
+        u32 intr;
+
+       if ((bus == 0) && (dev_fn >= PCI_DEVFN(31,0)))
+               return -1; /* Because of a bug in the galileo (for slot 31). */
+
+       /* Clear cause register bits */
+       GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | 
+                                    GT_INTRCAUSE_TARABORT0_BIT));
+
+       /* Setup address */
+       GT_WRITE(GT_PCI0_CFGADDR_OFS, 
+                (bus         << GT_PCI0_CFGADDR_BUSNUM_SHF)   |
+                (dev_fn      << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
+                ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF)   |
+                GT_PCI0_CFGADDR_CONFIGEN_BIT);
+
+       if (access_type == PCI_ACCESS_WRITE) {
+               if (bus == 0 && dev_fn == 0) {
+                       /* 
+                        * Galileo is acting differently than other devices. 
+                        */
+                       GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
+               } else {
+                       GT_PCI_WRITE(GT_PCI0_CFGDATA_OFS, *data);
+               }
+       } else {
+               if (bus == 0 && dev_fn == 0) {
+                       /* 
+                        * Galileo is acting differently than other devices. 
+                        */
+                       GT_READ(GT_PCI0_CFGDATA_OFS, *data);
+               } else {
+                       GT_PCI_READ(GT_PCI0_CFGDATA_OFS, *data);
+               }
+       }
+
+       /* Check for master or target abort */
+       GT_READ(GT_INTRCAUSE_OFS, intr);
+
+       if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT))
+       {
+               /* Error occured */
+
+               /* Clear bits */
+               GT_WRITE( GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | 
+                                             GT_INTRCAUSE_TARABORT0_BIT) );
+
+               return -1;
+       }
+
+       return 0;
+}
+
+
+/*
+ * We can't address 8 and 16 bit words directly.  Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int
+mips_pcibios_read_config_byte (struct pci_dev *dev, int where, u8 *val)
+{
+       u32 data = 0;
+
+       if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+               return -1;
+
+       *val = (data >> ((where & 3) << 3)) & 0xff;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int
+mips_pcibios_read_config_word (struct pci_dev *dev, int where, u16 *val)
+{
+       u32 data = 0;
+
+       if (where & 1)
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+
+       if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+              return -1;
+
+       *val = (data >> ((where & 3) << 3)) & 0xffff;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+mips_pcibios_read_config_dword (struct pci_dev *dev, int where, u32 *val)
+{
+       u32 data = 0;
+
+       if (where & 3)
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+       
+       if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+               return -1;
+
+       *val = data;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int
+mips_pcibios_write_config_byte (struct pci_dev *dev, int where, u8 val)
+{
+       u32 data = 0;
+       
+       if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+               return -1;
+
+       data = (data & ~(0xff << ((where & 3) << 3))) |
+              (val << ((where & 3) << 3));
+
+       if (mips_pcibios_config_access(PCI_ACCESS_WRITE, dev, where, &data))
+               return -1;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+mips_pcibios_write_config_word (struct pci_dev *dev, int where, u16 val)
+{
+        u32 data = 0;
+
+       if (where & 1)
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+       
+        if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+              return -1;
+
+       data = (data & ~(0xffff << ((where & 3) << 3))) | 
+              (val << ((where & 3) << 3));
+
+       if (mips_pcibios_config_access(PCI_ACCESS_WRITE, dev, where, &data))
+              return -1;
+
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+mips_pcibios_write_config_dword(struct pci_dev *dev, int where, u32 val)
+{
+       if (where & 3)
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+
+       if (mips_pcibios_config_access(PCI_ACCESS_WRITE, dev, where, &val))
+              return -1;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops mips_pci_ops = {
+       mips_pcibios_read_config_byte,
+        mips_pcibios_read_config_word,
+       mips_pcibios_read_config_dword,
+       mips_pcibios_write_config_byte,
+       mips_pcibios_write_config_word,
+       mips_pcibios_write_config_dword
+};
+
+void __init pcibios_init(void)
+{
+#ifdef CONFIG_MIPS_MALTA
+       struct pci_dev *pdev;
+       unsigned char reg_val;
+#endif
+
+       printk("PCI: Probing PCI hardware on host bus 0.\n");
+       pci_scan_bus(0, &mips_pci_ops, NULL);
+
+       /* 
+        * Due to a bug in the Galileo system controller, we need to setup 
+        * the PCI BAR for the Galileo internal registers.
+        * This should be done in the bios/bootprom and will be fixed in
+        * a later revision of YAMON (the MIPS boards boot prom).
+        */
+       GT_WRITE(GT_PCI0_CFGADDR_OFS,
+                (0 << GT_PCI0_CFGADDR_BUSNUM_SHF)   |  /* Local bus */
+                (0 << GT_PCI0_CFGADDR_DEVNUM_SHF)   |  /* GT64120 device */
+                (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |  /* Function 0 */
+                ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) |  /* BAR 4 */
+                GT_PCI0_CFGADDR_CONFIGEN_BIT );
+
+       /* Perform the write */
+       GT_WRITE( GT_PCI0_CFGDATA_OFS, PHYSADDR(MIPS_GT_BASE)); 
+
+#ifdef CONFIG_MIPS_MALTA
+       pci_for_each_dev(pdev) {
+               if ((pdev->vendor == PCI_VENDOR_ID_INTEL)
+                   && (pdev->device == PCI_DEVICE_ID_INTEL_82371AB)
+                   && (PCI_SLOT(pdev->devfn) == 0x0a)) {
+                       /*
+                        * IDE Decode enable.
+                        */
+                       pci_read_config_byte(pdev, 0x41, &reg_val);
+                       pci_write_config_byte(pdev, 0x41, reg_val | 0x80);
+                       pci_read_config_byte(pdev, 0x43, &reg_val);
+                       pci_write_config_byte(pdev, 0x43, reg_val | 0x80);
+               }
+
+               if ((pdev->vendor == PCI_VENDOR_ID_INTEL)
+                   && (pdev->device == PCI_DEVICE_ID_INTEL_82371AB_0)
+                   && (PCI_SLOT(pdev->devfn) == 0x0a)) {
+                       /*
+                        * Set top of main memory accessible by ISA or DMA
+                        * devices to 16 Mb.
+                        */
+                       pci_read_config_byte(pdev, 0x69, &reg_val);
+                       pci_write_config_byte(pdev, 0x69, reg_val | 0xf0);
+               }
+       }
+
+       /* 
+        * Activate Floppy Controller in the SMSC FDC37M817 Super I/O 
+        * Controller.
+        * This should be done in the bios/bootprom and will be fixed in
+         * a later revision of YAMON (the MIPS boards boot prom).
+        */
+       /* Entering config state. */
+       SMSC_WRITE(SMSC_CONFIG_ENTER, SMSC_CONFIG_REG); 
+       
+       /* Activate floppy controller. */
+       SMSC_WRITE(SMSC_CONFIG_DEVNUM, SMSC_CONFIG_REG);
+       SMSC_WRITE(SMSC_CONFIG_DEVNUM_FLOPPY, SMSC_DATA_REG);
+       SMSC_WRITE(SMSC_CONFIG_ACTIVATE, SMSC_CONFIG_REG);
+       SMSC_WRITE(SMSC_CONFIG_ACTIVATE_ENABLE, SMSC_DATA_REG);
+
+       /* Exit config state. */
+       SMSC_WRITE(SMSC_CONFIG_EXIT, SMSC_CONFIG_REG);
+#endif
+}
+
+int __init
+pcibios_enable_device(struct pci_dev *dev)
+{
+       /* Not needed, since we enable all devices at startup.  */
+       return 0;
+}
+
+void __init
+pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+{
+}
+
+char * __init
+pcibios_setup(char *str)
+{
+       /* Nothing to do for now.  */
+
+       return str;
+}
+
+struct pci_fixup pcibios_fixups[] = {
+       { 0 }
+};
+
+void __init
+pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+                        struct resource *res, int resource)
+{
+       unsigned long where, size;
+       u32 reg;
+
+       where = PCI_BASE_ADDRESS_0 + (resource * 4);
+       size = res->end - res->start;
+       pci_read_config_dword(dev, where, &reg);
+       reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
+       pci_write_config_dword(dev, where, reg);
+}
+
+/*
+ *  Called after each bus is probed, but before its children
+ *  are examined.
+ */
+void __init pcibios_fixup_bus(struct pci_bus *b)
+{
+       pci_read_bridge_bases(b);
+}
+
+#endif /* CONFIG_PCI */
diff --git a/arch/mips/mips-boards/generic/printf.c b/arch/mips/mips-boards/generic/printf.c
new file mode 100644 (file)
index 0000000..4f3f6e8
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Putting things on the screen/serial line using YAMONs facilities.
+ *
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/serial.h>
+
+
+#ifdef CONFIG_MIPS_ATLAS 
+/* 
+ * Atlas registers are memory mapped on 64-bit aligned boundaries and 
+ * only word access are allowed.
+ * When reading the UART 8 bit registers only the LSB are valid.
+ */
+unsigned int atlas_serial_in(struct async_struct *info, int offset)
+{
+       return (*(volatile unsigned int *)(info->port + mips_io_port_base + offset*8) & 0xff);
+}
+
+void atlas_serial_out(struct async_struct *info, int offset, int value)
+{
+       *(volatile unsigned int *)(info->port + mips_io_port_base + offset*8) = value;
+}
+
+#define serial_in  atlas_serial_in
+#define serial_out atlas_serial_out
+
+#else
+
+static unsigned int serial_in(struct async_struct *info, int offset)
+{
+       return inb(info->port + offset);
+}
+
+static void serial_out(struct async_struct *info, int offset,
+                               int value)
+{
+       outb(value, info->port + offset);
+}
+#endif
+
+static struct serial_state rs_table[] = {
+       SERIAL_PORT_DFNS        /* Defined in serial.h */
+};
+
+/*
+ * Hooks to fake "prom" console I/O before devices 
+ * are fully initialized. 
+ */
+static struct async_struct prom_port_info = {0};
+
+void __init setup_prom_printf(int tty_no) {
+       struct serial_state *ser = &rs_table[tty_no];
+
+       prom_port_info.state = ser;
+       prom_port_info.magic = SERIAL_MAGIC;
+       prom_port_info.port = ser->port;
+       prom_port_info.flags = ser->flags;
+
+       /* No setup of UART - assume YAMON left in sane state */
+}
+
+int putPromChar(char c)
+{
+        if (!prom_port_info.state) {   /* need to init device first */
+               return 0;
+       }
+
+       while ((serial_in(&prom_port_info, UART_LSR) & UART_LSR_THRE) == 0)
+               ;
+
+       serial_out(&prom_port_info, UART_TX, c);
+
+       return 1;
+}
+
+char getPromChar(void)
+{
+       if (!prom_port_info.state) {    /* need to init device first */
+               return 0;
+       }
+
+       while (!(serial_in(&prom_port_info, UART_LSR) & 1))
+               ;
+
+       return(serial_in(&prom_port_info, UART_RX));
+}
+
+static char buf[1024];
+
+void __init prom_printf(char *fmt, ...)
+{
+       va_list args;
+       int l;
+       char *p, *buf_end;
+       long flags;
+
+       int putPromChar(char);
+
+       /* Low level, brute force, not SMP safe... */
+       save_and_cli(flags);
+       va_start(args, fmt);
+       l = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf) */
+       va_end(args);
+
+       buf_end = buf + l;
+
+       for (p = buf; p < buf_end; p++) {
+               /* Crude cr/nl handling is better than none */
+               if(*p == '\n')putPromChar('\r');
+               putPromChar(*p);
+       }
+       restore_flags(flags);
+}
diff --git a/arch/mips/mips-boards/generic/reset.c b/arch/mips/mips-boards/generic/reset.c
new file mode 100644 (file)
index 0000000..83cd0c3
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Reset the MIPS boards.
+ *
+ */
+#include <linux/config.h>
+
+#include <asm/reboot.h>
+#include <asm/mips-boards/generic.h>
+#if defined(CONFIG_MIPS_ATLAS)
+#include <asm/mips-boards/atlas.h>
+#endif
+
+static void mips_machine_restart(char *command);
+static void mips_machine_halt(void);
+#if defined(CONFIG_MIPS_ATLAS)
+static void atlas_machine_power_off(void);
+#endif
+
+static void mips_machine_restart(char *command)
+{
+        volatile unsigned int *softres_reg = (void *)SOFTRES_REG;
+
+       *softres_reg = GORESET;
+}
+
+static void mips_machine_halt(void)
+{
+        volatile unsigned int *softres_reg = (void *)SOFTRES_REG;
+
+       *softres_reg = GORESET;
+}
+
+#if defined(CONFIG_MIPS_ATLAS)
+static void atlas_machine_power_off(void)
+{
+        volatile unsigned int *psustby_reg = (void *)ATLAS_PSUSTBY_REG;
+
+       *psustby_reg = ATLAS_GOSTBY;
+}
+#endif
+
+void mips_reboot_setup(void)
+{
+       _machine_restart = mips_machine_restart;
+       _machine_halt = mips_machine_halt;
+#if defined(CONFIG_MIPS_ATLAS)
+       _machine_power_off = atlas_machine_power_off;
+#endif
+#if defined(CONFIG_MIPS_MALTA)
+       _machine_power_off = mips_machine_halt;
+#endif
+}
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
new file mode 100644 (file)
index 0000000..8819f46
--- /dev/null
@@ -0,0 +1,410 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Setting up the clock on the MIPS boards.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+
+#include <asm/mipsregs.h>
+#include <asm/ptrace.h>
+#include <asm/div64.h>
+
+#include <linux/mc146818rtc.h>
+#include <linux/timex.h>
+
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+
+extern volatile unsigned long wall_jiffies;
+static long last_rtc_update = 0;
+unsigned long missed_heart_beats = 0;
+
+static unsigned long r4k_offset; /* Amount to increment compare reg each time */
+static unsigned long r4k_cur;    /* What counter should be at next timer irq */
+extern rwlock_t xtime_lock;
+
+#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
+
+#if defined(CONFIG_MIPS_ATLAS)
+static char display_string[] = "        LINUX ON ATLAS       ";
+#endif
+#if defined(CONFIG_MIPS_MALTA)
+static char display_string[] = "        LINUX ON MALTA       ";
+#endif
+static unsigned int display_count = 0;
+#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8) 
+
+static unsigned int timer_tick_count=0;
+
+
+static inline void ack_r4ktimer(unsigned long newval)
+{
+       write_32bit_cp0_register(CP0_COMPARE, newval);
+}
+
+
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be
+ * called 500 ms after the second nowtime has started, because when
+ * nowtime is written into the registers of the CMOS clock, it will
+ * jump to the next second precisely 500 ms later. Check the Motorola
+ * MC146818A or Dallas DS12887 data sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ *      sets the minutes. Usually you won't notice until after reboot!
+ */
+static int set_rtc_mmss(unsigned long nowtime)
+{
+       int retval = 0;
+       int real_seconds, real_minutes, cmos_minutes;
+       unsigned char save_control, save_freq_select;
+
+       save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
+       CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+       save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
+       CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+       cmos_minutes = CMOS_READ(RTC_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) {
+               CMOS_WRITE(real_seconds,RTC_SECONDS);
+               CMOS_WRITE(real_minutes,RTC_MINUTES);
+       } else {
+               printk(KERN_WARNING
+                      "set_rtc_mmss: can't update from %d to %d\n",
+                      cmos_minutes, real_minutes);
+               retval = -1;
+       }
+
+       /* The following flags have to be released exactly in this order,
+        * otherwise the DS12887 (popular MC146818A clone with integrated
+        * battery and quartz) will not reset the oscillator and will not
+        * update precisely 500 ms later. You won't find this mentioned in
+        * the Dallas Semiconductor data sheets, but who believes data
+        * sheets anyway ...                           -- Markus Kuhn
+        */
+       CMOS_WRITE(save_control, RTC_CONTROL);
+       CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+
+       return retval;
+}
+
+/*
+ * There are a lot of conceptually broken versions of the MIPS timer interrupt
+ * handler floating around.  This one is rather different, but the algorithm
+ * is provably more robust.
+ */
+void mips_timer_interrupt(struct pt_regs *regs)
+{
+       int irq = 7;
+
+       if (r4k_offset == 0)
+               goto null;
+
+       do {
+               kstat.irqs[0][irq]++;
+               do_timer(regs);
+
+               /* Historical comment/code:
+                * RTC time of day s updated approx. every 11 
+                * minutes.  Because of how the numbers work out 
+                * we need to make absolutely sure we do this update
+                * within 500ms before the * next second starts, 
+                * thus the following code.
+                */
+               read_lock(&xtime_lock);
+               if ((time_status & STA_UNSYNC) == 0 
+                   && xtime.tv_sec > last_rtc_update + 660 
+                   && xtime.tv_usec >= 500000 - (tick >> 1) 
+                   && xtime.tv_usec <= 500000 + (tick >> 1))
+                       if (set_rtc_mmss(xtime.tv_sec) == 0)
+                               last_rtc_update = xtime.tv_sec;
+                       else
+                               /* do it again in 60 s */
+                               last_rtc_update = xtime.tv_sec - 600; 
+               read_unlock(&xtime_lock);
+
+               if ((timer_tick_count++ % HZ) == 0) {
+                   mips_display_message(&display_string[display_count++]);
+                   if (display_count == MAX_DISPLAY_COUNT)
+                       display_count = 0;
+               }
+
+               r4k_cur += r4k_offset;
+               ack_r4ktimer(r4k_cur);
+
+       } while (((unsigned long)read_32bit_cp0_register(CP0_COUNT)
+                - r4k_cur) < 0x7fffffff);
+
+       return;
+
+null:
+       ack_r4ktimer(0);
+}
+
+/* 
+ * Figure out the r4k offset, the amount to increment the compare
+ * register for each time tick. 
+ * Use the RTC to calculate offset.
+ */
+static unsigned long __init cal_r4koff(void)
+{
+       unsigned long count;
+       unsigned int flags;
+
+       __save_and_cli(flags);
+
+       /* Start counter exactly on falling edge of update flag */
+       while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+       while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+       /* Start r4k counter. */
+       write_32bit_cp0_register(CP0_COUNT, 0);
+
+       /* Read counter exactly on falling edge of update flag */
+       while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+       while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+       count = read_32bit_cp0_register(CP0_COUNT);
+
+       /* restore interrupts */
+       __restore_flags(flags);
+
+       return (count / HZ);
+}
+
+static unsigned long __init get_mips_time(void)
+{
+       unsigned int year, mon, day, hour, min, sec;
+       unsigned char save_control;
+
+       save_control = CMOS_READ(RTC_CONTROL);
+
+       /* Freeze it. */
+       CMOS_WRITE(save_control | RTC_SET, RTC_CONTROL);
+
+       /* Read regs. */
+       sec = CMOS_READ(RTC_SECONDS);
+       min = CMOS_READ(RTC_MINUTES);
+       hour = CMOS_READ(RTC_HOURS);
+
+       if (!(save_control & RTC_24H))
+       {
+               if ((hour & 0xf) == 0xc)
+                       hour &= 0x80;
+               if (hour & 0x80)
+                       hour = (hour & 0xf) + 12;     
+       }
+       day = CMOS_READ(RTC_DAY_OF_MONTH);
+       mon = CMOS_READ(RTC_MONTH);
+       year = CMOS_READ(RTC_YEAR);
+
+       /* Unfreeze clock. */
+       CMOS_WRITE(save_control, RTC_CONTROL);
+
+       if ((year += 1900) < 1970)
+               year += 100;
+
+       return mktime(year, mon, day, hour, min, sec);
+}
+
+void __init time_init(void)
+{
+        unsigned int est_freq, flags;
+
+        /* Set Data mode - binary. */ 
+        CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
+
+       printk("calculating r4koff... ");
+       r4k_offset = cal_r4koff();
+       printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);
+
+       est_freq = 2*r4k_offset*HZ;     
+       est_freq += 5000;    /* round */
+       est_freq -= est_freq%10000;
+       printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, 
+              (est_freq%1000000)*100/1000000);
+       r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset);
+
+       write_32bit_cp0_register(CP0_COMPARE, r4k_cur);
+       change_cp0_status(ST0_IM, ALLINTS);
+
+       /* Read time from the RTC chipset. */
+       write_lock_irqsave (&xtime_lock, flags);
+       xtime.tv_sec = get_mips_time();
+       xtime.tv_usec = 0;
+       write_unlock_irqrestore(&xtime_lock, flags);
+}
+
+/* This is for machines which generate the exact clock. */
+#define USECS_PER_JIFFY (1000000/HZ)
+#define USECS_PER_JIFFY_FRAC (0x100000000*1000000/HZ&0xffffffff)
+
+/* Cycle counter value at the previous timer interrupt.. */
+
+static unsigned int timerhi = 0, timerlo = 0;
+
+/*
+ * FIXME: Does playing with the RP bit in c0_status interfere with this code?
+ */
+static unsigned long do_fast_gettimeoffset(void)
+{
+       u32 count;
+       unsigned long res, tmp;
+
+       /* Last jiffy when do_fast_gettimeoffset() was called. */
+       static unsigned long last_jiffies=0;
+       unsigned long quotient;
+
+       /*
+        * Cached "1/(clocks per usec)*2^32" value.
+        * It has to be recalculated once each jiffy.
+        */
+       static unsigned long cached_quotient=0;
+
+       tmp = jiffies;
+
+       quotient = cached_quotient;
+
+       if (tmp && last_jiffies != tmp) {
+               last_jiffies = tmp;
+#ifdef CONFIG_CPU_MIPS32
+               if (last_jiffies != 0) {
+                       unsigned long r0;
+                       do_div64_32(r0, timerhi, timerlo, tmp);
+                       do_div64_32(quotient, USECS_PER_JIFFY,
+                                   USECS_PER_JIFFY_FRAC, r0);
+                       cached_quotient = quotient;
+               }
+#else
+               __asm__(".set\tnoreorder\n\t"
+                       ".set\tnoat\n\t"
+                       ".set\tmips3\n\t"
+                       "lwu\t%0,%2\n\t"
+                       "dsll32\t$1,%1,0\n\t"
+                       "or\t$1,$1,%0\n\t"
+                       "ddivu\t$0,$1,%3\n\t"
+                       "mflo\t$1\n\t"
+                       "dsll32\t%0,%4,0\n\t"
+                       "nop\n\t"
+                       "ddivu\t$0,%0,$1\n\t"
+                       "mflo\t%0\n\t"
+                       ".set\tmips0\n\t"
+                       ".set\tat\n\t"
+                       ".set\treorder"
+                       :"=&r" (quotient)
+                       :"r" (timerhi),
+                        "m" (timerlo),
+                        "r" (tmp),
+                        "r" (USECS_PER_JIFFY)
+                       :"$1");
+               cached_quotient = quotient;
+#endif
+       }
+
+       /* Get last timer tick in absolute kernel time */
+       count = read_32bit_cp0_register(CP0_COUNT);
+
+       /* .. relative to previous jiffy (32 bits is enough) */
+       count -= timerlo;
+
+       __asm__("multu\t%1,%2\n\t"
+               "mfhi\t%0"
+               :"=r" (res)
+               :"r" (count),
+                "r" (quotient));
+
+       /*
+        * Due to possible jiffies inconsistencies, we need to check 
+        * the result so that we'll get a timer that is monotonic.
+        */
+       if (res >= USECS_PER_JIFFY)
+               res = USECS_PER_JIFFY-1;
+
+       return res;
+}
+
+void do_gettimeofday(struct timeval *tv)
+{
+       unsigned int flags;
+
+       read_lock_irqsave (&xtime_lock, flags);
+       *tv = xtime;
+       tv->tv_usec += do_fast_gettimeoffset();
+
+       /*
+        * xtime is atomically updated in timer_bh. jiffies - wall_jiffies
+        * is nonzero if the timer bottom half hasnt executed yet.
+        */
+       if (jiffies - wall_jiffies)
+               tv->tv_usec += USECS_PER_JIFFY;
+
+       read_unlock_irqrestore (&xtime_lock, flags);
+
+       if (tv->tv_usec >= 1000000) {
+               tv->tv_usec -= 1000000;
+               tv->tv_sec++;
+       }
+}
+
+void do_settimeofday(struct timeval *tv)
+{
+       write_lock_irq (&xtime_lock);
+
+       /* This is revolting. We need to set the xtime.tv_usec correctly.
+        * However, the value in this location is is value at the last tick.
+        * Discover what correction gettimeofday would have done, and then
+        * undo it!
+        */
+       tv->tv_usec -= do_fast_gettimeoffset();
+
+       if (tv->tv_usec < 0) {
+               tv->tv_usec += 1000000;
+               tv->tv_sec--;
+       }
+
+       xtime = *tv;
+       time_adjust = 0;                /* stop active adjtime() */
+       time_status |= STA_UNSYNC;
+       time_maxerror = NTP_PHASE_LIMIT;
+       time_esterror = NTP_PHASE_LIMIT;
+
+       write_unlock_irq (&xtime_lock);
+}
diff --git a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile
new file mode 100644 (file)
index 0000000..e71c8e8
--- /dev/null
@@ -0,0 +1,40 @@
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+#
+# ########################################################################
+#
+# This program is free software; you can distribute it and/or modify it
+# under the terms of the GNU General Public License (Version 2) as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# #######################################################################
+#
+# Makefile for the MIPS Malta specific kernel interface routines
+# under Linux.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+.S.s:
+       $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+       $(CC) $(CFLAGS) -c $< -o $*.o
+
+O_TARGET := malta.o
+
+obj-y := malta_int.o malta_rtc.o malta_setup.o
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c
new file mode 100644 (file)
index 0000000..2e3126e
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Routines for generic manipulation of the interrupts found on the MIPS 
+ * Malta board.
+ * The interrupt controller is located in the South Bridge a PIIX4 device 
+ * with two internal 82C95 interrupt controllers.
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/random.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/mips-boards/malta.h>
+#include <asm/mips-boards/maltaint.h>
+#include <asm/mips-boards/piix4.h>
+#include <asm/gt64120.h>
+#include <asm/mips-boards/generic.h>
+
+extern asmlinkage void mipsIRQ(void);
+
+unsigned int local_bh_count[NR_CPUS];
+unsigned int local_irq_count[NR_CPUS];
+unsigned long spurious_count = 0;
+
+static struct irqaction *hw0_irq_action[MALTAINT_END] = {
+       NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL
+};
+
+static struct irqaction r4ktimer_action = {
+       NULL, 0, 0, "R4000 timer/counter", NULL, NULL,
+};
+
+static struct irqaction *irq_action[8] = {
+       NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, &r4ktimer_action
+};
+
+#if 0
+#define DEBUG_INT(x...) printk(x)
+#else
+#define DEBUG_INT(x...)
+#endif
+
+/*
+ * This contains the interrupt mask for both 82C59 interrupt controllers.
+ */
+static unsigned int cached_int_mask = 0xffff;
+
+
+void disable_irq(unsigned int irq_nr)
+{
+        unsigned long flags;
+
+       if(irq_nr >= MALTAINT_END) {
+               printk("whee, invalid irq_nr %d\n", irq_nr);
+               panic("IRQ, you lose...");
+       }
+
+       save_and_cli(flags);
+       cached_int_mask |= (1 << irq_nr);
+       if (irq_nr & 8) {
+               outb((cached_int_mask >> 8) & 0xff, PIIX4_ICTLR2_OCW1);
+       } else {
+               outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1);
+       }
+       restore_flags(flags);
+}
+
+
+void enable_irq(unsigned int irq_nr)
+{
+        unsigned long flags;
+
+       if(irq_nr >= MALTAINT_END) {
+               printk("whee, invalid irq_nr %d\n", irq_nr);
+               panic("IRQ, you lose...");
+       }
+
+       save_and_cli(flags);
+       cached_int_mask &= ~(1 << irq_nr);
+       if (irq_nr & 8) {
+               outb((cached_int_mask >> 8) & 0xff, PIIX4_ICTLR2_OCW1);
+
+               /* Enable irq 2 (cascade interrupt). */
+               cached_int_mask &= ~(1 << 2); 
+               outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1);
+       } else {
+               outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1);
+       }       
+       restore_flags(flags);
+}
+
+
+int get_irq_list(char *buf)
+{
+       int i, len = 0;
+       int num = 0;
+       struct irqaction *action;
+
+       for (i = 0; i < 8; i++, num++) {
+               action = irq_action[i];
+               if (!action) 
+                       continue;
+               len += sprintf(buf+len, "%2d: %8d %c %s",
+                       num, kstat.irqs[0][num],
+                       (action->flags & SA_INTERRUPT) ? '+' : ' ',
+                       action->name);
+               for (action=action->next; action; action = action->next) {
+                       len += sprintf(buf+len, ",%s %s",
+                               (action->flags & SA_INTERRUPT) ? " +" : "",
+                               action->name);
+               }
+               len += sprintf(buf+len, " [on-chip]\n");
+       }
+       for (i = 0; i < MALTAINT_END; i++, num++) {
+               action = hw0_irq_action[i];
+               if (!action) 
+                       continue;
+               len += sprintf(buf+len, "%2d: %8d %c %s",
+                       num, kstat.irqs[0][num],
+                       (action->flags & SA_INTERRUPT) ? '+' : ' ',
+                       action->name);
+               for (action=action->next; action; action = action->next) {
+                       len += sprintf(buf+len, ",%s %s",
+                               (action->flags & SA_INTERRUPT) ? " +" : "",
+                               action->name);
+               }
+               len += sprintf(buf+len, " [hw0]\n");
+       }
+       return len;
+}
+
+
+static int setup_irq(unsigned int irq, struct irqaction * new)
+{
+       int shared = 0;
+       struct irqaction *old, **p;
+
+       p = &hw0_irq_action[irq];
+       if ((old = *p) != NULL) {
+               /* Can't share interrupts unless both agree to */
+               if (!(old->flags & new->flags & SA_SHIRQ))
+                       return -EBUSY;
+
+               /* Can't share interrupts unless both are same type */
+               if ((old->flags ^ new->flags) & SA_INTERRUPT)
+                       return -EBUSY;
+
+               /* add new interrupt at end of irq queue */
+               do {
+                       p = &old->next;
+                       old = *p;
+               } while (old);
+               shared = 1;
+       }
+
+       if (new->flags & SA_SAMPLE_RANDOM)
+               rand_initialize_irq(irq);
+
+       *p = new;
+       if (!shared)
+               enable_irq(irq);
+
+       return 0;
+}
+
+int request_irq(unsigned int irq, 
+               void (*handler)(int, void *, struct pt_regs *),
+               unsigned long irqflags, 
+               const char * devname,
+               void *dev_id)
+{  
+        struct irqaction *action;
+       int retval;
+
+       DEBUG_INT("request_irq: irq=%d, devname = %s\n", irq, devname);
+
+        if (irq >= MALTAINT_END)
+               return -EINVAL;
+       if (!handler)
+               return -EINVAL;
+
+       action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+       if(!action)
+               return -ENOMEM;
+
+       action->handler = handler;
+       action->flags = irqflags;
+       action->mask = 0;
+       action->name = devname;
+       action->dev_id = dev_id;
+       action->next = 0;
+
+       retval = setup_irq(irq, action);
+       if (retval)
+               kfree(action);
+
+       return retval;  
+}
+
+
+void free_irq(unsigned int irq, void *dev_id)
+{
+       struct irqaction *action, **p;
+
+       if (irq >= MALTAINT_END) {
+               printk("Trying to free IRQ%d\n",irq);
+               return;
+       }
+       
+       for (p = &hw0_irq_action[irq]; (action = *p) != NULL; 
+            p = &action->next) 
+       {
+               if (action->dev_id != dev_id)
+                       continue;
+
+               /* Found it - now free it */
+               *p = action->next;
+               kfree(action);
+               if (!hw0_irq_action[irq])
+                       disable_irq(irq);
+               return;
+       }
+       printk("Trying to free IRQ%d\n",irq);
+}
+
+void __init init_IRQ(void)
+{
+       irq_setup();
+}
+
+static inline int get_int(int *irq)
+{
+       /*  
+        * Determine highest priority pending interrupt by performing
+         * a PCI Interrupt Acknowledge cycle.
+        */
+       GT_READ(GT_PCI0_IACK_OFS, *irq);
+       *irq &= 0xFF;
+
+       /*  
+        * IRQ7 is used to detect spurious interrupts.
+        * The interrupt acknowledge cycle returns IRQ7, if no 
+        * interrupts is requested.
+        * We can differentiate between this situation and a
+        * "Normal" IRQ7 by reading the ISR.
+        */
+       if (*irq == 7) 
+       {
+               outb(PIIX4_OCW3_SEL | PIIX4_OCW3_ISR, PIIX4_ICTLR1_OCW3);
+               if (!(inb(PIIX4_ICTLR1_OCW3) & (1 << 7)))
+                       return -1;    /* Spurious interrupt. */
+       }
+
+       return 0;
+}
+
+static inline void ack_int(int irq)
+{
+       if (irq & 8) {
+               /* Specific EOI to cascade */
+               outb(PIIX4_OCW2_SEL | PIIX4_OCW2_NSEOI | PIIX4_OCW2_ILS_2, 
+                    PIIX4_ICTLR1_OCW2);
+
+               /* Non specific EOI to cascade */
+               outb(PIIX4_OCW2_SEL | PIIX4_OCW2_NSEOI, PIIX4_ICTLR2_OCW2);
+       } else {
+               /* Non specific EOI to cascade */
+               outb(PIIX4_OCW2_SEL | PIIX4_OCW2_NSEOI, PIIX4_ICTLR1_OCW2);
+       }
+}
+
+void malta_hw0_irqdispatch(struct pt_regs *regs)
+{
+        struct irqaction *action;
+       int irq=0, cpu = smp_processor_id();
+
+       DEBUG_INT("malta_hw0_irqdispatch\n");
+       
+       if (get_int(&irq))
+               return;  /* interrupt has already been cleared */
+
+       disable_irq(irq);
+       ack_int(irq);
+
+       DEBUG_INT("malta_hw0_irqdispatch: irq=%d\n", irq);
+       action = hw0_irq_action[irq];
+
+       /* 
+        * if action == NULL, then we don't have a handler 
+        * for the irq 
+        */
+       if ( action == NULL )
+               return;
+
+       irq_enter(cpu, irq);
+       kstat.irqs[0][irq + 8]++;
+       do {
+               action->handler(irq, action->dev_id, regs);
+               action = action->next;
+       } while (action);
+
+       enable_irq(irq);
+       irq_exit(cpu, irq);
+}
+
+
+unsigned long probe_irq_on (void)
+{
+       unsigned int i, irqs = 0;
+       unsigned long delay;
+
+       /* first, enable any unassigned irqs */
+       for (i = MALTAINT_END-1; i > 0; i--) {
+               if (!hw0_irq_action[i]) {
+                       enable_irq(i);
+                       irqs |= (1 << i);
+               }
+       }
+
+       /* wait for spurious interrupts to mask themselves out again */
+       for (delay = jiffies + HZ/10; time_before(jiffies, delay); )
+               /* about 100ms delay */;
+
+       /* now filter out any obviously spurious interrupts */
+       return irqs & ~cached_int_mask;
+}
+
+
+int probe_irq_off (unsigned long irqs)
+{
+       unsigned int i;
+
+       irqs &= cached_int_mask;
+       if (!irqs)
+               return 0;
+       i = ffz(~irqs);
+       if (irqs != (irqs & (1 << i)))
+               i = -i;
+
+       return i;
+}
+
+
+void __init maltaint_init(void)
+{
+        /* 
+        * Mask out all interrupt by writing "1" to all bit position in 
+        * the IMR register. 
+        */
+       outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1);
+       outb((cached_int_mask >> 8) & 0xff, PIIX4_ICTLR2_OCW1);
+
+       /* Now safe to set the exception vector. */
+       set_except_vector(0, mipsIRQ);
+}
diff --git a/arch/mips/mips-boards/malta/malta_rtc.c b/arch/mips/mips-boards/malta/malta_rtc.c
new file mode 100644 (file)
index 0000000..2fde1fd
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * RTC routines for Malta style attached PIIX4 device, which contains a
+ * Motorola MC146818A-compatible Real Time Clock.
+ *
+ */
+#include <linux/spinlock.h>
+#include <linux/mc146818rtc.h>
+#include <asm/mips-boards/malta.h>
+
+static unsigned char malta_rtc_read_data(unsigned long addr)
+{
+       outb(addr, MALTA_RTC_ADR_REG);
+       return inb(MALTA_RTC_DAT_REG);
+}
+
+static void malta_rtc_write_data(unsigned char data, unsigned long addr)
+{
+       outb(addr, MALTA_RTC_ADR_REG);
+       outb(data, MALTA_RTC_DAT_REG);
+}
+
+static int malta_rtc_bcd_mode(void)
+{
+       return 0;
+}
+
+struct rtc_ops malta_rtc_ops = {
+       &malta_rtc_read_data,
+       &malta_rtc_write_data,
+       &malta_rtc_bcd_mode
+};
diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c
new file mode 100644 (file)
index 0000000..6b362b0
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Malta specific setup, including init of the feature struct.
+ *
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/mc146818rtc.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#ifdef CONFIG_BLK_DEV_IDE
+#include <linux/ide.h>
+#endif
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/malta.h>
+#include <asm/mips-boards/maltaint.h>
+#ifdef CONFIG_BLK_DEV_FD
+#include <asm/floppy.h>
+#endif
+#include <asm/dma.h>
+
+#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE)
+extern void console_setup(char *, int *);
+char serial_console[20];
+#endif
+
+#ifdef CONFIG_REMOTE_DEBUG
+extern void set_debug_traps(void);
+extern void rs_kgdb_hook(int);
+extern void breakpoint(void);
+static int remote_debug = 0;
+#endif
+
+#ifdef CONFIG_BLK_DEV_IDE
+extern struct ide_ops std_ide_ops;
+#endif
+#ifdef CONFIG_BLK_DEV_FD
+extern struct fd_ops std_fd_ops;
+#endif
+extern struct rtc_ops malta_rtc_ops;
+
+extern void mips_reboot_setup(void);
+
+struct resource standard_io_resources[] = {
+       { "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
+       { "pic1", 0x20, 0x3f, IORESOURCE_BUSY },
+       { "timer", 0x40, 0x5f, IORESOURCE_BUSY },
+       { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
+       { "pic2", 0xa0, 0xbf, IORESOURCE_BUSY },
+       { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
+};
+
+#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
+
+static void __init malta_irq_setup(void)
+{
+       maltaint_init();
+
+#ifdef CONFIG_REMOTE_DEBUG
+       if (remote_debug) {
+               set_debug_traps();
+               breakpoint(); 
+       }
+#endif
+}
+
+
+void __init malta_setup(void)
+{
+#ifdef CONFIG_REMOTE_DEBUG
+       int rs_putDebugChar(char);
+       char rs_getDebugChar(void);
+       extern int (*putDebugChar)(char);
+       extern char (*getDebugChar)(void);
+#endif
+       char *argptr;
+       int i;
+
+       irq_setup = malta_irq_setup;
+
+       /* Request I/O space for devices used on the Malta board. */
+       for (i = 0; i < STANDARD_IO_RESOURCES; i++)
+               request_resource(&ioport_resource, standard_io_resources+i);
+
+       /* 
+        * Enable DMA channel 4 (cascade channel) in the PIIX4 south bridge.
+        */
+       enable_dma(4);
+
+#ifdef CONFIG_SERIAL_CONSOLE
+       argptr = prom_getcmdline();
+       if ((argptr = strstr(argptr, "console=")) == NULL) {
+               argptr = prom_getcmdline();
+               strcat(argptr, " console=ttyS0,38400");
+       }
+#endif
+
+#ifdef CONFIG_REMOTE_DEBUG
+       argptr = prom_getcmdline();
+       if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
+               int line;
+               argptr += strlen("kgdb=ttyS");
+               if (*argptr != '0' && *argptr != '1')
+                       printk("KGDB: Uknown serial line /dev/ttyS%c, "
+                              "falling back to /dev/ttyS1\n", *argptr);
+               line = *argptr == '0' ? 0 : 1;
+               printk("KGDB: Using serial line /dev/ttyS%d for session\n",
+                      line ? 1 : 0);
+
+               rs_kgdb_hook(line);
+               putDebugChar = rs_putDebugChar;
+               getDebugChar = rs_getDebugChar;
+
+               prom_printf("KGDB: Using serial line /dev/ttyS%d for session, "
+                           "please connect your debugger\n", line ? 1 : 0);
+
+               remote_debug = 1;
+               /* Breakpoints and stuff are in malta_irq_setup() */
+       }
+#endif
+
+       argptr = prom_getcmdline();
+       if ((argptr = strstr(argptr, "nofpu")) != NULL)
+               mips_cpu.options &= ~MIPS_CPU_FPU;
+               
+       rtc_ops = &malta_rtc_ops;
+#ifdef CONFIG_BLK_DEV_IDE
+        ide_ops = &std_ide_ops;
+#endif
+#ifdef CONFIG_BLK_DEV_FD
+        fd_ops = &std_fd_ops;
+#endif
+       mips_reboot_setup();
+}
index d8929b9..16ed11a 100644 (file)
@@ -8,34 +8,20 @@
 # Note 2! The CFLAGS definition is now in the main makefile...
 
 O_TARGET := mm.o
-O_OBJS  := extable.o init.o fault.o loadmmu.o
 
-ifdef CONFIG_CPU_R3000
-O_OBJS   += r2300.o
-endif
-
-ifdef CONFIG_CPU_R4300
-O_OBJS   += r4xx0.o
-endif
-
-ifdef CONFIG_CPU_R4X00
-O_OBJS   += r4xx0.o
-endif
-
-ifdef CONFIG_CPU_R5000
-O_OBJS   += r4xx0.o
-endif
-
-ifdef CONFIG_CPU_NEVADA
-O_OBJS   += r4xx0.o
-endif
-
-ifdef CONFIG_SGI_IP22
-O_OBJS   += umap.o
-endif
-
-ifdef CONFIG_BAGET_MIPS
-O_OBJS   += umap.o
-endif
+export-objs                    += umap.o
+obj-y                          += extable.o init.o fault.o loadmmu.o
+
+obj-$(CONFIG_CPU_R3000)                += r2300.o
+obj-$(CONFIG_CPU_R3912)                += r2300.o
+obj-$(CONFIG_CPU_R4300)                += r4xx0.o
+obj-$(CONFIG_CPU_R4X00)                += r4xx0.o
+obj-$(CONFIG_CPU_R5000)                += r4xx0.o
+obj-$(CONFIG_CPU_NEVADA)       += r4xx0.o
+obj-$(CONFIG_CPU_R5432)                += r5432.o
+obj-$(CONFIG_CPU_RM7000)       += rm7k.o
+obj-$(CONFIG_CPU_MIPS32)       += mips32.o
+obj-$(CONFIG_SGI_IP22)         += umap.o
+obj-$(CONFIG_BAGET_MIPS)       += umap.o
 
 include $(TOPDIR)/Rules.make
diff --git a/arch/mips/orion/Makefile b/arch/mips/orion/Makefile
deleted file mode 100644 (file)
index a42da1b..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License.  See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-#
-# Produce a bootimage for the IPSX
-#  Copyright (C) 2000 Cort Dougan <cort@fsmlabs.com>
-#
-
-.S.s:
-       $(CPP) $(CFLAGS) $< -o $*.s
-.S.o:
-       $(CC) $(CFLAGS) -c $< -o $*.o
-
-OBJS = promcon.o char.o serial.8530.o orion.hw.init.o setup.o irq.o int-handler.o
-
-all: orionkern.a
-
-orionkern.a: $(OBJS) initrd.o #no_initrd.o
-       $(AR) rcs orionkern.a $(OBJS) initrd.o #no_initrd.o
-       sync
-
-initrd.c: piggyback ramdisk.image.gz
-       ./piggyback initrd < ramdisk.image.gz > initrd.c
-
-piggyback: piggyback.c
-       $(HOSTCC) $(HOSTCFLAGS) -o piggyback piggyback.c
-
-orionboot: orion.ctl
-
-patchapp: patchapp.c
-       $(HOSTCC) -o $@ $^
-
-orion.ctl: patchapp ../../../vmlinux
-       $(OBJCOPY) -Obinary ../../../vmlinux orion.nosym
-       ./patchapp orion.nosym orion
-       cp -f orion.bin orion.ctl
-
-# Don't build dependencies, this may die if $(CC) isn't gcc
-dep:
-
-clean:
-       rm -f patchapp orion.bin orion.nosym orion.ctl initrd.c
-
-dummy:
-
-include $(TOPDIR)/Rules.make
diff --git a/arch/mips/orion/int-handler.S b/arch/mips/orion/int-handler.S
deleted file mode 100644 (file)
index e5023b9..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-       .text
-       .set    mips1
-       .set    reorder
-       .set    macro
-       .set    noat
-       .align  5
-
-NESTED(orionIRQ, PT_SIZE, sp)
-       SAVE_ALL
-       CLI                             # Important: mark KERNEL mode !
-       /*
-        * Get pending interrupts
-        */
-       mfc0    t0,CP0_CAUSE            # get pending interrupts
-       mfc0    t1,CP0_STATUS           # get enabled interrupts
-       and     t0,t1                   # isolate allowed ones
-       andi    t0,0xff00               # isolate pending bits
-       sll     t0,16                   # shift the pending bits down
-       beqz    t0,3f                   # no pending intrs, then spurious
-       nop                             # delay slot
-       
-       /*
-        * Find irq with highest priority
-        * FIXME: This is slow - use binary search
-        */
-       la      a0,7
-1:     bltz    t0,2f                   # found pending irq
-       subu    a0,1
-       sll     t0,1
-       b       1b
-       nop                             # delay slot
-
-call_do_IRQ:
-2:     move    a1,sp
-       jal     do_IRQ
-       nop                             # delay slot
-
-       mfc0    t0,CP0_STATUS           # disable interrupts
-       ori     t0,1
-       xori    t0,1
-       mtc0    t0,CP0_STATUS
-       
-       la      a1, ret_from_irq
-       jr      a1
-       
-3:     j       spurious_interrupt
-END(orionIRQ)
-
diff --git a/arch/mips/orion/irq.c b/arch/mips/orion/irq.c
deleted file mode 100644 (file)
index d92ab73..0000000
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Code to handle irqs on Orion boards
- *  -- Cort <cort@fsmlabs.com>
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-
-#include <asm/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-#include <asm/orion.h>
-
-void (*board_time_init)(struct irqaction *irq);
-extern asmlinkage void orionIRQ(void);
-unsigned long spurious_count = 0;
-irq_desc_t irq_desc[NR_IRQS];
-
-static void galileo_ack(unsigned int irq_nr)
-{
-       *((unsigned long *) (((unsigned)( 0x14000000  )|0xA0000000)   + 0xC18) ) = (((( 0 )&0xff)<<24)+ ((( 0 )&0xff00)<<8)+    ((( 0 )&0xff0000)>>8)+  ((( 0 )&0xff000000)>>24))  ;
-}
-
-struct hw_interrupt_type galileo_pic = {
-        " Galileo  ",
-        NULL,
-        NULL,
-        NULL, /* unmask_irq */
-        NULL, /* mask_irq */
-        galileo_ack, /* mask_and_ack */
-        0
-};
-
-/* Function for careful CP0 interrupt mask access */
-static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
-{
-       unsigned long status = read_32bit_cp0_register(CP0_STATUS);
-       status &= ~((clr_mask & 0xFF) << 8);
-       status |=   (set_mask & 0xFF) << 8;
-       write_32bit_cp0_register(CP0_STATUS, status);
-}
-
-static inline void mask_irq(unsigned int irq_nr)
-{
-        modify_cp0_intmask(irq_nr, 0);
-}
-
-static inline void unmask_irq(unsigned int irq_nr)
-{
-       modify_cp0_intmask(0, irq_nr);
-}
-
-void disable_irq(unsigned int irq_nr)
-{
-       unsigned long flags;
-
-       save_and_cli(flags);
-       mask_irq(irq_nr);
-       restore_flags(flags);
-}
-
-void enable_irq(unsigned int irq_nr)
-{
-       unsigned long flags;
-
-       save_and_cli(flags);
-       unmask_irq(irq_nr);
-       restore_flags(flags);
-}
-
-/*static struct irqaction *irq_action[NR_IRQS] = {
-       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
-};
-*/
-void __init orion_time_init(struct irqaction *irq)
-{
-       __u32 timer_count;
-       
-       irq_desc[2].handler = &galileo_pic;
-       irq_desc[2].action = irq;
-       
-       /* This code was provided by the CoSine guys and despite its
-        * appearance init's the timer.
-        * -- Cort
-        */
-       *((__u32 *) (((unsigned)( 0x14000000  )|0xA0000000)   + 0x864) ) = (((( 0 )&0xff)<<24)+ ((( 0 )&0xff00)<<8)+    ((( 0 )&0xff0000)>>8)+  ((( 0 )&0xff000000)>>24)) ;
-       
-       *((__u32 *) (((unsigned)( 0x14000000  )|0xA0000000)   + 0x850) ) = (((( 0 )&0xff)<<24)+ ((( 0 )&0xff00)<<8)+    ((( 0 )&0xff0000)>>8)+  ((( 0 )&0xff000000)>>24)) ;
-
-        timer_count = 300000000/100;
-       
-       *((__u32 *) (((unsigned)( 0x14000000  )|0xA0000000)   + 0x850) ) = ((((  timer_count  )&0xff)<<24)+     (((  timer_count  )&0xff00)<<8)+        (((  timer_count  )&0xff0000)>>8)+      (((  timer_count  )&0xff000000)>>24))  ;
-
-       *((__u32 *) (((unsigned)( 0x14000000  )|0xA0000000)   + 0xC1C) ) = ((((  0x100   )&0xff)<<24)+  (((  0x100   )&0xff00)<<8)+     (((  0x100   )&0xff0000)>>8)+   (((  0x100   )&0xff000000)>>24))  ;
-     
-       *((__u32 *) (((unsigned)( 0x14000000  )|0xA0000000)   + 0x864) ) = ((((  0x03  )&0xff)<<24)+    (((  0x03  )&0xff00)<<8)+       (((  0x03  )&0xff0000)>>8)+     (((  0x03  )&0xff000000)>>24))  ;
-     
-       *((__u32 *) (((unsigned)( 0x14000000  )|0xA0000000)   + 0xC18) ) = (((( 0 )&0xff)<<24)+ ((( 0 )&0xff00)<<8)+    ((( 0 )&0xff0000)>>8)+  ((( 0 )&0xff000000)>>24))  ;
-}
-
-int get_irq_list(char *buf)
-{
-       int i, len = 0, j;
-       struct irqaction * action;
-
-       len += sprintf(buf+len, "           ");
-       for (j=0; j<smp_num_cpus; j++)
-               len += sprintf(buf+len, "CPU%d       ",j);
-       *(char *)(buf+len++) = '\n';
-
-       for (i = 0 ; i < NR_IRQS ; i++) {
-               action = irq_desc[i].action;
-               if ( !action || !action->handler )
-                       continue;
-               len += sprintf(buf+len, "%3d: ", i);            
-               len += sprintf(buf+len, "%10u ", kstat_irqs(i));
-               if ( irq_desc[i].handler )              
-                       len += sprintf(buf+len, " %s ", irq_desc[i].handler->typename );
-               else
-                       len += sprintf(buf+len, "  None      ");
-               len += sprintf(buf+len, "    %s",action->name);
-               for (action=action->next; action; action = action->next) {
-                       len += sprintf(buf+len, ", %s", action->name);
-               }
-               len += sprintf(buf+len, "\n");
-       }
-       len += sprintf(buf+len, "BAD: %10lu\n", spurious_count);
-       return len;
-}
-
-asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
-{
-       struct irqaction *action;
-       int do_random, cpu;
-       int status;
-
-       cpu = smp_processor_id();
-       irq_enter(cpu);
-       kstat.irqs[cpu][irq]++;
-       status = 0;
-
-       if (irq_desc[irq].handler->ack)
-               irq_desc[irq].handler->ack(irq);
-       
-       action = irq_desc[irq].action;
-       if (action && action->handler)
-       {
-               if (!(action->flags & SA_INTERRUPT))
-                       __sti();
-               do { 
-                       status |= action->flags;
-                       action->handler(irq, action->dev_id, regs);
-                       action = action->next;
-               } while ( action );
-               __cli();
-               if (irq_desc[irq].handler)
-               {
-                       if (irq_desc[irq].handler->end)
-                               irq_desc[irq].handler->end(irq);
-                       else if (irq_desc[irq].handler->enable)
-                               irq_desc[irq].handler->enable(irq);
-               }
-       }
-
-       irq_exit(cpu);
-
-       if (softirq_active(cpu)&softirq_mask(cpu))
-               do_softirq();
-
-       /* unmasking and bottom half handling is done magically for us. */
-}
-
-int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
-       unsigned long irqflags, const char * devname, void *dev_id)
-{
-       struct irqaction *old, **p, *action;
-       unsigned long flags;
-
-       if (irq >= NR_IRQS)
-               return -EINVAL;
-       if (!handler)
-       {
-               /* Free */
-               for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next)
-               {
-                       /* Found it - now free it */
-                       save_flags(flags);
-                       cli();
-                       *p = action->next;
-                       restore_flags(flags);
-                       kfree(action);
-                       return 0;
-               }
-               return -ENOENT;
-       }
-       
-       action = (struct irqaction *)
-               kmalloc(sizeof(struct irqaction), GFP_KERNEL);
-       if (!action)
-               return -ENOMEM;
-       
-       save_flags(flags);
-       cli();
-       
-       action->handler = handler;
-       action->flags = irqflags;                                       
-       action->mask = 0;
-       action->name = devname;
-       action->dev_id = dev_id;
-       action->next = NULL;
-       enable_irq(irq);
-       
-       p = &irq_desc[irq].action;
-       
-       if ((old = *p) != NULL) {
-               /* Can't share interrupts unless both agree to */
-               if (!(old->flags & action->flags & SA_SHIRQ))
-                       return -EBUSY;
-               /* add new interrupt at end of irq queue */
-               do {
-                       p = &old->next;
-                       old = *p;
-               } while (old);
-       }
-       *p = action;
-
-       restore_flags(flags);   
-       return 0;
-}
-               
-void free_irq(unsigned int irq, void *dev_id)
-{
-       request_irq(irq, NULL, 0, NULL, dev_id);
-}
-
-
-unsigned long probe_irq_on (void)
-{
-       return 0;
-}
-
-int probe_irq_off (unsigned long irqs)
-{
-       return 0;
-}
-
-int (*irq_cannonicalize)(int irq);
-
-int orion_irq_cannonicalize(int i)
-{
-       return i;
-}
-
-void __init init_IRQ(void)
-{
-       
-       irq_cannonicalize = orion_irq_cannonicalize;
-       set_except_vector(0, orionIRQ);
-}
-
-EXPORT_SYMBOL(irq_cannonicalize);
-
diff --git a/arch/mips/orion/ld.script.orion b/arch/mips/orion/ld.script.orion
deleted file mode 100644 (file)
index 1c9faa3..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-OUTPUT_FORMAT("elf32-bigmips")
-OUTPUT_ARCH(mips)
-ENTRY(kernel_entry)
-SECTIONS
-{
-  /* Read-only sections, merged into text segment: */
-  . = 0x80100000;
-  /* app_header is needed for the Orion bootloader -- Cort */
-  .app_header  :       { *(.app_header) }
-  .init          : { *(.init)          } =0
-  .text      :
-  {
-    _ftext = . ;
-    *(.text)
-    *(.rodata)
-    *(.rodata1)
-    /* .gnu.warning sections are handled specially by elf32.em.  */
-    *(.gnu.warning)
-  } =0
-  _etext = .;
-  PROVIDE (etext = .);
-
-  . = ALIGN(8192);
-  .data.init_task : { *(.data.init_task) }
-
-  /* Startup code */
-  . = ALIGN(4096);
-  __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);     /* Align double page for init_task_union */
-  __init_end = .;
-
-  . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
-
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
-  .fini      : { *(.fini)    } =0
-  .reginfo : { *(.reginfo) }
-  /* Adjust the address for the data segment.  We want to adjust up to
-     the same address within the page on the next page up.  It would
-     be more correct to do this:
-       . = .;
-     The current expression does not correctly handle the case of a
-     text segment ending precisely at the end of a page; it causes the
-     data segment to skip a page.  The above expression does not have
-     this problem, but it will currently (2/95) cause BFD to allocate
-     a single segment, combining both text and data, for this case.
-     This will prevent the text segment from being shared among
-     multiple executions of the program; I think that is more
-     important than losing a page of the virtual address space (note
-     that no actual memory is lost; the page which is skipped can not
-     be referenced).  */
-  . = .;
-  .data    :
-  {
-    _fdata = . ;
-    *(.data)
-    CONSTRUCTORS
-  }
-  .data1   : { *(.data1) }
-  _gp = . + 0x8000;
-  .lit8 : { *(.lit8) }
-  .lit4 : { *(.lit4) }
-  .ctors         : { *(.ctors)   }
-  .dtors         : { *(.dtors)   }
-  .got           : { *(.got.plt) *(.got) }
-  .dynamic       : { *(.dynamic) }
-  /* We want the small data sections together, so single-instruction offsets
-     can access them all, and initialized data all before uninitialized, so
-     we can shorten the on-disk segment size.  */
-  .sdata     : { *(.sdata) }
-  _edata  =  .;
-  PROVIDE (edata = .);
-
-  __bss_start = .;
-  _fbss = .;
-  .sbss      : { *(.sbss) *(.scommon) }
-  .bss       :
-  {
-   *(.dynbss)
-   *(.bss)
-   *(COMMON)
-  _end = . ;
-  PROVIDE (end = .);
-  }
-  /* These are needed for ELF backends which have not yet been
-     converted to the new style linker.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  /* DWARF debug sections.
-     Symbols in the .debug DWARF section are relative to the beginning of the
-     section so we begin .debug at 0.  It's not clear yet what needs to happen
-     for the others.   */
-  .debug          0 : { *(.debug) }
-  .debug_srcinfo  0 : { *(.debug_srcinfo) }
-  .debug_aranges  0 : { *(.debug_aranges) }
-  .debug_pubnames 0 : { *(.debug_pubnames) }
-  .debug_sfnames  0 : { *(.debug_sfnames) }
-  .line           0 : { *(.line) }
-  /* These must appear regardless of  .  */
-  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
-  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
-}
diff --git a/arch/mips/orion/misc.c b/arch/mips/orion/misc.c
deleted file mode 100644 (file)
index e5cce6f..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Catch-all for Orion-specify code that doesn't fit easily elsewhere.
- *   -- Cort
- */
-
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/hdreg.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/string.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/utsname.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
-#ifdef CONFIG_BLK_DEV_RAM
-#include <linux/blk.h>
-#endif
-#include <linux/ide.h>
-#ifdef CONFIG_RTC
-#include <linux/timex.h>
-#endif
-
-#include <asm/asm.h>
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/io.h>
-#include <asm/stackframe.h>
-#include <asm/system.h>
-#include <asm/cpu.h>
-#include <linux/bootmem.h>
-#include <asm/addrspace.h>
-#include <asm/mc146818rtc.h>
-
-char arcs_cmdline[CL_SIZE] = {0, };
-extern int _end;
-
-static unsigned char orion_rtc_read_data(unsigned long addr)
-{
-       return 0;
-}
-
-static void orion_rtc_write_data(unsigned char data, unsigned long addr)
-{
-}
-
-static int orion_rtc_bcd_mode(void)
-{
-       return 0;
-}
-
-struct rtc_ops orion_rtc_ops = {
-       &orion_rtc_read_data,
-       &orion_rtc_write_data,
-       &orion_rtc_bcd_mode
-};
-
-extern void InitCIB(void);
-extern void InitQpic(void);
-extern void InitCupid(void);
-
-void __init orion_setup(void)
-{
-       InitCIB();
-       InitQpic();
-       InitCupid();
-}
-
-#define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_ALIGN(x)   (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
-
-
-
-int orion_sysinit(void)
-{
-       unsigned long mem_size, free_start, free_end, start_pfn, bootmap_size;
-       
-       mips_machgroup = MACH_GROUP_ORION;
-       /* 64 MB non-upgradable */
-       mem_size = 32 << 20;
-       
-       free_start = PHYSADDR(PFN_ALIGN(&_end));
-       free_end = mem_size;
-       start_pfn = PFN_UP((unsigned long)&_end);
-       
-       /* Register all the contiguous memory with the bootmem allocator
-          and free it.  Be careful about the bootmem freemap.  */
-       bootmap_size = init_bootmem(start_pfn, mem_size >> PAGE_SHIFT);
-       
-       /* Free the entire available memory after the _end symbol.  */
-       free_start += bootmap_size;
-       free_bootmem(free_start, free_end-free_start);
-}
diff --git a/arch/mips/orion/no_initrd.c b/arch/mips/orion/no_initrd.c
deleted file mode 100644 (file)
index fcf446a..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-unsigned long *orion_initrd_start = 0;
-unsigned long orion_initrd_size = 0;
diff --git a/arch/mips/orion/piggyback.c b/arch/mips/orion/piggyback.c
deleted file mode 100644 (file)
index 1b03f68..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-
-extern long ce_exec_config[];
-
-int main(int argc, char *argv[])
-{
-       int i, cnt, pos, len;
-       unsigned int cksum, val;
-       unsigned char *lp;
-       unsigned char buf[8192];
-       if (argc != 2)
-       {
-               fprintf(stderr, "usage: %s name <in-file >out-file\n",
-                       argv[0]);
-               exit(1);
-       }
-       fprintf(stdout, "/*\n");
-       fprintf(stdout, "* Miscellaneous data structures:\n");
-       fprintf(stdout, "* WARNING - this file is automatically generated!\n");
-       fprintf(stdout, "*/\n");
-       fprintf(stdout, "\n");
-       fprintf(stdout, "unsigned long orion_%s_start[] = {\n", argv[1]);
-       pos = 0;
-       cksum = 0;
-       while ((len = read(0, buf, sizeof(buf))) > 0)
-       {
-               cnt = 0;
-               lp = (unsigned char *)buf;
-               len = (len + 3) & ~3;  /* Round up to longwords */
-               for (i = 0;  i < len;  i += 4)
-               {
-                       if (cnt == 0)
-                       {
-                               fprintf(stdout, "\t");
-                       }
-                       fprintf(stdout, "0x%02X%02X%02X%02X", lp[0], lp[1], lp[2], lp[3]);
-                       val = *(unsigned long *)lp;
-                       cksum ^= val;
-                       lp += 4;
-                       if (++cnt == 4)
-                       {
-                               cnt = 0;
-                               fprintf(stdout, ", /* %x */\n", pos+i-12);
-                               fflush(stdout);
-                       } else
-                       {
-                               fprintf(stdout, ",");
-                       }
-               }
-               pos += len;
-       }
-       fprintf(stdout, "0 };\n");
-       fprintf(stdout, "unsigned long orion_%s_size = 0x%x;\n", argv[1], pos);
-       fflush(stdout);
-       fclose(stdout);
-       fprintf(stderr, "cksum = %x\n", cksum);
-       exit(0);
-}
diff --git a/arch/mips/orion/promcon.c b/arch/mips/orion/promcon.c
deleted file mode 100644 (file)
index 8609b88..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Wrap-around code for a console using the
- * SGI PROM io-routines.
- *
- * Copyright (c) 1999 Ulf Carlsson
- *
- * Derived from DECstation promcon.c
- * Copyright (c) 1998 Harald Koerfgen 
- */
-
-#include <linux/tty.h>
-#include <linux/major.h>
-#include <linux/ptrace.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/fs.h>
-/*
-#include <asm/sgialib.h>
-*/
-extern void prom_printf(char *fmt, ...);
-unsigned long splx(unsigned long mask){return 0;}
-#if 0
-unsigned long ramsize=0x100000;
-unsigned long RamSize(){return ramsize;}
-extern void prom_printf(char *fmt, ...);
-unsigned long splx(unsigned long mask){return 0;}
-long PssSetIntHandler(unsigned long intnum, void *handler){}
-long PssEnableInt(unsigned long intnum){}
-long PssDisableInt(unsigned long intnum){}
-unsigned long t_ident(char name[4], unsigned long node, unsigned long *tid){}
-#endif
-
-extern void  SerialPollConout(unsigned char c);
-static void prom_console_write(struct console *co, const char *s,
-                              unsigned count)
-{
-    unsigned i;
-
-    /*
-     *    Now, do each character
-     */
-    for (i = 0; i < count; i++) {
-       if (*s == 10)
-         SerialPollConout(13);
-       SerialPollConout(*s++);
-    }
-}
-extern int prom_getchar(void);
-static int prom_console_wait_key(struct console *co)
-{
-    return prom_getchar();
-}
-
-extern void SerialPollInit(void);
-extern void  SerialSetup(unsigned long  baud, unsigned long  console, unsigned long  host, unsigned long  intr_desc);
-static int __init prom_console_setup(struct console *co, char *options)
-{
-  SerialSetup(19200,1,1,3);
-  SerialPollInit();
-  SerialPollOn();
-  return 0;
-}
-
-static kdev_t prom_console_device(struct console *c)
-{
-    return MKDEV(TTY_MAJOR, 64 + c->index);
-}
-
-static struct console sercons =
-{
-    name:      "ttyS",
-    write:     prom_console_write,
-    device:    prom_console_device,
-    wait_key:  prom_console_wait_key,
-    setup:     prom_console_setup,
-    flags:     CON_PRINTBUFFER,
-    index:     -1,
-};
-
-/*
- *    Register console.
- */
-
-void serial_console_init(void)
-{
-       register_console(&sercons);
-}
-
-extern void prom_putchar(int mychar);
-
-static char ppbuf[1000];
-
-
-void prom_printf(char *fmt, ...)
-{
-       va_list args;
-       char ch, *bptr;
-       int i;
-
-       va_start(args, fmt);
-       i = vsprintf(ppbuf, fmt, args);
-
-       bptr = ppbuf;
-
-       while((ch = *(bptr++)) != 0) {
-               if(ch == '\n')
-                       prom_putchar('\r');
-
-               prom_putchar(ch);
-       }
-       va_end(args);
-       return;
-}
-
-
-
-void prom_putchar(int mychar){}
-int prom_getchar(void){return 0;}
-struct app_header_s {
-  unsigned long    MAGIC_JMP;
-  unsigned long    MAGIC_NOP;
-  unsigned long    header_tag;    
-  unsigned long    header_flags;
-  unsigned long    header_length;
-  unsigned long    header_cksum;
-     
-  void             *load_addr;
-  void             *end_addr;
-  void             *start_addr;
-  char             *app_name_p;
-  char             *version_p;
-  char             *date_p;
-  char             *time_p;
-  unsigned long    type;
-  unsigned long    crc;
-  unsigned long    reserved;
-};
-typedef struct app_header_s app_header_t;
-char linked_app_name[]="linux";
-char *linked_app_name_p=&linked_app_name[0];
-
-char linked_app_ver[]="2.4 -test1";
-char *linked_app_ver_p=&linked_app_ver[0];
-
-char linked_app_date[]="today";
-char *linked_app_date_p=&linked_app_date[0];
-
-char linked_app_time[]="now";
-char *linked_app_time_p=&linked_app_time[0];
-extern void *__bss_start;
-extern void *kernel_entry;
-
-app_header_t app_header __attribute__ ((section (".app_header"))) = {
-  (0x10000000 | (((sizeof(app_header_t)>>2)-1) & 0xffff)) ,
-  0 ,
-  (((( 0x4321  ) & 0xFFFF) << 16) | ((  0x0100  ) & 0xFFFF))  ,
-  0x80000000 ,
-  sizeof(app_header_t),
-  0,
-  &app_header,
-  &__bss_start,
-  &kernel_entry,
-  linked_app_name,
-  linked_app_ver,
-  linked_app_date,
-  linked_app_time,
-  0
-};
diff --git a/arch/mips/orion/setup.c b/arch/mips/orion/setup.c
deleted file mode 100644 (file)
index 0ff17c7..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Catch-all for Orion-specific code that doesn't fit easily elsewhere.
- *   -- Cort
- */
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/hdreg.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/string.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/utsname.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
-#include <linux/interrupt.h>
-#ifdef CONFIG_BLK_DEV_RAM
-#include <linux/blk.h>
-#endif
-#include <linux/ide.h>
-#ifdef CONFIG_RTC
-#include <linux/timex.h>
-#endif
-
-#include <asm/asm.h>
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/io.h>
-#include <asm/stackframe.h>
-#include <asm/system.h>
-#include <asm/cpu.h>
-#include <linux/bootmem.h>
-#include <asm/addrspace.h>
-#include <asm/mc146818rtc.h>
-#include <asm/orion.h>
-
-char arcs_cmdline[CL_SIZE] = { "console=ttyS0,19200" };
-extern int _end;
-
-static unsigned char orion_rtc_read_data(unsigned long addr)
-{
-       return 0;
-}
-
-static void orion_rtc_write_data(unsigned char data, unsigned long addr)
-{
-}
-
-static int orion_rtc_bcd_mode(void)
-{
-       return 0;
-}
-
-struct rtc_ops orion_rtc_ops = {
-       &orion_rtc_read_data,
-       &orion_rtc_write_data,
-       &orion_rtc_bcd_mode
-};
-
-extern void InitCIB(void);
-extern void InitQpic(void);
-extern void InitCupid(void);
-
-void __init orion_setup(void)
-{
-       extern void (*board_time_init)(struct irqaction *irq);
-       void orion_time_init(struct irqaction *);
-       
-       rtc_ops = &orion_rtc_ops;
-       board_time_init = orion_time_init;
-       mips_io_port_base = GT64120_BASE;
-
-       InitCIB();
-       InitQpic();
-       InitCupid();
-}
-
-#define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_ALIGN(x)   (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
-
-unsigned long mem_size;
-int __init prom_init(int a, char **b, char **c, int *d)
-{
-       unsigned long free_start, free_end, start_pfn, bootmap_size;
-       extern unsigned long orion_initrd_start[], orion_initrd_size;
-
-       mips_machgroup = MACH_GROUP_ORION;
-       /* 64 MB non-upgradable */
-       mem_size = 64 << 20;
-       
-       free_start = PHYSADDR(PFN_ALIGN(&_end));
-       free_end = mem_size;
-       start_pfn = PFN_UP((unsigned long)&_end);
-       
-       /* Register all the contiguous memory with the bootmem allocator
-          and free it.  Be careful about the bootmem freemap.  */
-       bootmap_size = init_bootmem(start_pfn, mem_size >> PAGE_SHIFT);
-       
-       /* Free the entire available memory after the _end symbol.  */
-       free_start += bootmap_size;
-       free_bootmem(free_start, free_end-free_start);
-
-       initrd_start = (ulong)orion_initrd_start;
-       initrd_end = (ulong)orion_initrd_start + (ulong)orion_initrd_size;
-       initrd_below_start_ok = 1;
-
-       return 0;
-}
-
-void prom_free_prom_memory (void)
-{
-}
-
-int page_is_ram(unsigned long pagenr)
-{
-       if ( pagenr < (mem_size >> PAGE_SHIFT) )
-               return 1;
-       return 0;
-}
index 6eb3f17..dd16c6c 100644 (file)
 .S.o:
        $(CC) $(CFLAGS) -c $< -o $*.o
 
-OBJS  = indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o \
-        system.o indyIRQ.o reset.o setup.o time.o
-ifdef CONFIG_SGI_PROM_CONSOLE
-OBJS += promcon.o
-endif
+O_TARGET := ip22-kern.o
 
-all: sgikern.a
+all: ip22-kern.o indyIRQ.o
 
-sgikern.a: $(OBJS)
-       $(AR) rcs sgikern.a $(OBJS)
-       sync
+obj-y  += indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o system.o \
+          indyIRQ.o reset.o setup.o time.o
 
 indyIRQ.o: indyIRQ.S
 
-dep:
-       $(CPP) $(CPPFLAGS) -M *.c > .depend
-
 include $(TOPDIR)/Rules.make
index b5091e1..7dfc732 100644 (file)
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.3 1999/01/04 16:03:57 ralf Exp $
 #
 # Makefile for the SNI specific part of the kernel
 #
 .S.o:
        $(CC) $(CFLAGS) -c $< -o $*.o
 
-all: sni.o
+all:   sni.o int-handler.o
+
 O_TARGET := sni.o
-O_OBJS  := dma.o int-handler.o io.o pci.o pcimt_scache.o reset.o setup.o
 
-int-handler.o: int-handler.S
+obj-y   := int-handler.o io.o irq.o pci.o pcimt_scache.o reset.o setup.o
 
-clean:
+int-handler.o: int-handler.S
 
 include $(TOPDIR)/Rules.make
index a424f55..c5800b6 100644 (file)
@@ -25,6 +25,9 @@ if [ "$CONFIG_SGI_IP27" = "y" ]; then
 fi
 endmenu
 
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
+
 #
 # Select some configuration options automatically based on user selections
 #
index 18168a2..eea8523 100644 (file)
@@ -120,6 +120,11 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_BRIDGE is not set
 
 #
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
 # Telephony Support
 #
 # CONFIG_PHONE is not set
@@ -422,6 +427,7 @@ CONFIG_PARTITION_ADVANCED=y
 # CONFIG_MAC_PARTITION is not set
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 CONFIG_SGI_PARTITION=y
index 39518cb..3854900 100644 (file)
@@ -110,6 +110,11 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_BRIDGE is not set
 
 #
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
 # Telephony Support
 #
 # CONFIG_PHONE is not set
index 8f8b780..eea8523 100644 (file)
@@ -120,6 +120,11 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_BRIDGE is not set
 
 #
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
 # Telephony Support
 #
 # CONFIG_PHONE is not set
@@ -165,6 +170,7 @@ CONFIG_SCSI_LOGGING=y
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -421,6 +427,7 @@ CONFIG_PARTITION_ADVANCED=y
 # CONFIG_MAC_PARTITION is not set
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 CONFIG_SGI_PARTITION=y
index 5a9478f..d62b355 100644 (file)
@@ -127,112 +127,3 @@ int __down_trylock(struct semaphore * sem)
 {
        return waking_non_zero_trylock(sem);
 }
-
-/*
- * RW Semaphores
- */
-void
-__down_read(struct rw_semaphore *sem, int count)
-{
-       DOWN_VAR;
-
- retry_down:
-       if (count < 0) {
-               /* Wait for the lock to become unbiased.  Readers
-                  are non-exclusive.  */
-               
-               /* This takes care of granting the lock.  */
-               up_read(sem);
-
-               add_wait_queue(&sem->wait, &wait);
-               while (atomic_read(&sem->count) < 0) {
-                       set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-                       if (atomic_read(&sem->count) >= 0)
-                               break;
-                       schedule();
-               }
-
-               remove_wait_queue(&sem->wait, &wait);
-               tsk->state = TASK_RUNNING;
-
-               mb();
-               count = atomic_dec_return(&sem->count);
-               if (count <= 0)
-                       goto retry_down;
-       } else {
-               add_wait_queue(&sem->wait, &wait);
-
-               while (1) {
-                       if (test_and_clear_bit(0, &sem->granted))
-                               break;
-                       set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-                       if ((sem->granted & 1) == 0)
-                               schedule();
-               }
-
-               remove_wait_queue(&sem->wait, &wait);
-               tsk->state = TASK_RUNNING;
-       }
-}
-
-void
-__down_write(struct rw_semaphore *sem, int count)
-{
-       DOWN_VAR;
-
- retry_down:
-       if (count + RW_LOCK_BIAS < 0) {
-               up_write(sem);
-
-               add_wait_queue_exclusive(&sem->wait, &wait);
-       
-               while (atomic_read(&sem->count) < 0) {
-                       set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-                       if (atomic_read(&sem->count) >= RW_LOCK_BIAS)
-                               break;
-                       schedule();
-               }
-
-               remove_wait_queue(&sem->wait, &wait);
-               tsk->state = TASK_RUNNING;
-
-               mb();
-               count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
-               if (count != 0)
-                       goto retry_down;
-       } else {
-               /* Put ourselves at the end of the list.  */
-               add_wait_queue_exclusive(&sem->write_bias_wait, &wait);
-
-               while (1) {
-                       if (test_and_clear_bit(1, &sem->granted))
-                               break;
-                       set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-                       if ((sem->granted & 2) == 0)
-                               schedule();
-               }
-
-               remove_wait_queue(&sem->write_bias_wait, &wait);
-               tsk->state = TASK_RUNNING;
-
-               /* If the lock is currently unbiased, awaken the sleepers.
-                  FIXME: This wakes up the readers early in a bit of a
-                  stampede -> bad!  */
-               if (atomic_read(&sem->count) >= 0)
-                       wake_up(&sem->wait);
-       }
-}
-
-void
-__rwsem_wake(struct rw_semaphore *sem, unsigned long readers)
-{
-       if (readers) {
-               if (test_and_set_bit(0, &sem->granted))
-                       BUG();
-               wake_up(&sem->wait);
-       } else {
-               if (test_and_set_bit(1, &sem->granted))
-                       BUG();
-               wake_up(&sem->write_bias_wait);
-       }
-}
index 3b5cea2..48dc554 100644 (file)
@@ -4,7 +4,8 @@
 
 O_TARGET := mm.o
 
-obj-y   := extable.o init.o fault.o loadmmu.o
+export-objs                    += umap.o
+obj-y                          := extable.o init.o fault.o loadmmu.o
 
 obj-$(CONFIG_CPU_R4300)                += r4xx0.o
 obj-$(CONFIG_CPU_R4X00)                += r4xx0.o
index 3218bfe..33d0c17 100644 (file)
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.1 1999/08/18 21:46:53 ralf Exp $
 #
 # Makefile for MIPS kernel build tools.
 #
index eed8018..f68410f 100644 (file)
@@ -7,6 +7,8 @@ mainmenu_name "Linux Kernel Configuration"
 
 define_bool CONFIG_PARISC y
 define_bool CONFIG_UID16 n
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 mainmenu_option next_comment
 comment 'Code maturity level options'
index 81156de..edec8e6 100644 (file)
@@ -129,111 +129,3 @@ int __down_trylock(struct semaphore * sem)
 {
        return waking_non_zero_trylock(sem);
 }
-
-
-/* Wait for the lock to become unbiased.  Readers
- * are non-exclusive. =)
- */
-void down_read_failed(struct rw_semaphore *sem)
-{
-       DECLARE_WAITQUEUE(wait, current);
-
-       __up_read(sem); /* this takes care of granting the lock */
-
-       add_wait_queue(&sem->wait, &wait);
-
-       while (atomic_read(&sem->count) < 0) {
-               set_task_state(current, TASK_UNINTERRUPTIBLE);
-               if (atomic_read(&sem->count) >= 0)
-                       break;
-               schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       current->state = TASK_RUNNING;
-}
-
-void down_read_failed_biased(struct rw_semaphore *sem)
-{
-       DECLARE_WAITQUEUE(wait, current);
-
-       add_wait_queue(&sem->wait, &wait);      /* put ourselves at the head of the list */
-
-       for (;;) {
-               if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
-                       break;
-               set_task_state(current, TASK_UNINTERRUPTIBLE);
-                if (!sem->read_bias_granted)
-                       schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       current->state = TASK_RUNNING;
-}
-
-
-/* Wait for the lock to become unbiased. Since we're
- * a writer, we'll make ourselves exclusive.
- */
-void down_write_failed(struct rw_semaphore *sem)
-{
-       DECLARE_WAITQUEUE(wait, current);
-
-       __up_write(sem);        /* this takes care of granting the lock */
-
-       add_wait_queue_exclusive(&sem->wait, &wait);
-
-       while (atomic_read(&sem->count) < 0) {
-               set_task_state(current, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE);
-               if (atomic_read(&sem->count) >= 0)
-                       break;  /* we must attempt to aquire or bias the lock */
-               schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       current->state = TASK_RUNNING;
-}
-
-void down_write_failed_biased(struct rw_semaphore *sem)
-{
-       DECLARE_WAITQUEUE(wait, current);
-
-       add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */
-
-       for (;;) {
-               if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
-                       break;
-               set_task_state(current, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE);
-               if (!sem->write_bias_granted)
-                       schedule();
-       }
-
-       remove_wait_queue(&sem->write_bias_wait, &wait);
-       current->state = TASK_RUNNING;
-
-       /* if the lock is currently unbiased, awaken the sleepers
-        * FIXME: this wakes up the readers early in a bit of a
-        * stampede -> bad!
-        */
-       if (atomic_read(&sem->count) >= 0)
-               wake_up(&sem->wait);
-}
-
-
-/* Called when someone has done an up that transitioned from
- * negative to non-negative, meaning that the lock has been
- * granted to whomever owned the bias.
- */
-void rwsem_wake_readers(struct rw_semaphore *sem)
-{
-       if (xchg(&sem->read_bias_granted, 1))
-               BUG();
-       wake_up(&sem->wait);
-}
-
-void rwsem_wake_writer(struct rw_semaphore *sem)
-{
-       if (xchg(&sem->write_bias_granted, 1))
-               BUG();
-       wake_up(&sem->write_bias_wait);
-}
index 2d07ee8..b2338d2 100644 (file)
@@ -3,6 +3,8 @@
 # see Documentation/kbuild/config-language.txt.
 #
 define_bool CONFIG_UID16 n
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 mainmenu_name "Linux/PowerPC Kernel Configuration"
 
index 0ed7eaa..d630c80 100644 (file)
@@ -137,44 +137,3 @@ int __down_trylock(struct semaphore * sem)
 {
        return waking_non_zero_trylock(sem);
 }
-
-
-/*
- * rw semaphores    Ani Joshi <ajoshi@unixbox.com>
- * based on alpha port by Andrea Arcangeli <andrea@suse.de>
- */
-
-void down_read_failed(struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       add_wait_queue_exclusive(&sem->wait, &wait);
-
-       do {
-               __set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               spin_unlock_irq(&sem->lock);
-               schedule();
-               spin_lock_irq(&sem->lock);
-       } while(sem->wr);
-
-       remove_wait_queue(&sem->wait, &wait);
-}
-
-void down_write_failed(struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       add_wait_queue_exclusive(&sem->wait, &wait);
-
-       do {
-               __set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               spin_unlock_irq(&sem->lock);
-               schedule();
-               spin_lock_irq(&sem->lock);
-       } while(sem->rd || sem->wr);
-
-       remove_wait_queue(&sem->wait, &wait);
-}
-
index 4bc88ef..47a5c0f 100644 (file)
@@ -7,6 +7,8 @@ define_bool CONFIG_ISA n
 define_bool CONFIG_EISA n
 define_bool CONFIG_MCA n
 define_bool CONFIG_UID16 y
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 mainmenu_name "Linux Kernel Configuration"
 define_bool CONFIG_ARCH_S390 y
index 8af6d82..c5f37a6 100644 (file)
@@ -158,145 +158,3 @@ int __down_trylock(struct semaphore * sem)
        spin_unlock_irqrestore(&semaphore_lock, flags);
        return 1;
 }
-
-void down_read_failed_biased(struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       add_wait_queue(&sem->wait, &wait);      /* put ourselves at the head of the list */
-
-       for (;;) {
-               if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
-                       break;
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (!sem->read_bias_granted)
-                       schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-}
-
-void down_write_failed_biased(struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */
-
-       for (;;) {
-               if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
-                       break;
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (!sem->write_bias_granted)
-                       schedule();
-       }
-
-       remove_wait_queue(&sem->write_bias_wait, &wait);
-       tsk->state = TASK_RUNNING;
-
-       /* if the lock is currently unbiased, awaken the sleepers
-        * FIXME: this wakes up the readers early in a bit of a
-        * stampede -> bad!
-        */
-       if (atomic_read(&sem->count) >= 0)
-               wake_up(&sem->wait);
-}
-
-/* Wait for the lock to become unbiased.  Readers
- * are non-exclusive. =)
- */
-void down_read_failed(struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       up_read(sem);   /* this takes care of granting the lock */
-
-       add_wait_queue(&sem->wait, &wait);
-
-       while (atomic_read(&sem->count) < 0) {
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (atomic_read(&sem->count) >= 0)
-                       break;
-               schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-}
-
-/* Wait for the lock to become unbiased. Since we're
- * a writer, we'll make ourselves exclusive.
- */
-void down_write_failed(struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       up_write(sem);  /* this takes care of granting the lock */
-
-       add_wait_queue_exclusive(&sem->wait, &wait);
-
-       while (atomic_read(&sem->count) < 0) {
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (atomic_read(&sem->count) >= 0)
-                       break;  /* we must attempt to acquire or bias the lock */
-               schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-}
-
-/* Called when someone has done an up that transitioned from
- * negative to non-negative, meaning that the lock has been
- * granted to whomever owned the bias.
- */
-void rwsem_wake_readers(struct rw_semaphore *sem)
-{
-       if (xchg(&sem->read_bias_granted, 1))
-               BUG();
-       wake_up(&sem->wait);
-}
-
-void rwsem_wake_writers(struct rw_semaphore *sem)
-{
-       if (xchg(&sem->write_bias_granted, 1))
-               BUG();
-       wake_up(&sem->write_bias_wait);
-}
-
-void __down_read_failed(int count, struct rw_semaphore *sem) 
-{
-       do {
-               if (count == -1) {
-                       down_read_failed_biased(sem);
-                       break;
-               }
-               down_read_failed(sem);
-               count = atomic_dec_return(&sem->count);
-       } while (count != 0);
-}
-
-void __down_write_failed(int count, struct rw_semaphore *sem)
-{
-       do {
-               if (count < 0 && count > -RW_LOCK_BIAS) {
-                       down_write_failed_biased(sem);
-                       break;
-               }
-               down_write_failed(sem);
-               count = atomic_add_return(-RW_LOCK_BIAS, &sem->count);
-       } while (count != 0);
-}
-
-void __rwsem_wake(int count, struct rw_semaphore *sem)
-{
-       if (count == 0)
-               rwsem_wake_readers(sem);
-       else
-               rwsem_wake_writers(sem);
-}
-
index da6231a..8329a23 100644 (file)
@@ -6,6 +6,8 @@
 define_bool CONFIG_ISA n
 define_bool CONFIG_EISA n
 define_bool CONFIG_MCA n
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 mainmenu_name "Linux Kernel Configuration"
 define_bool CONFIG_ARCH_S390 y
index 8af6d82..c5f37a6 100644 (file)
@@ -158,145 +158,3 @@ int __down_trylock(struct semaphore * sem)
        spin_unlock_irqrestore(&semaphore_lock, flags);
        return 1;
 }
-
-void down_read_failed_biased(struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       add_wait_queue(&sem->wait, &wait);      /* put ourselves at the head of the list */
-
-       for (;;) {
-               if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
-                       break;
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (!sem->read_bias_granted)
-                       schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-}
-
-void down_write_failed_biased(struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */
-
-       for (;;) {
-               if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
-                       break;
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (!sem->write_bias_granted)
-                       schedule();
-       }
-
-       remove_wait_queue(&sem->write_bias_wait, &wait);
-       tsk->state = TASK_RUNNING;
-
-       /* if the lock is currently unbiased, awaken the sleepers
-        * FIXME: this wakes up the readers early in a bit of a
-        * stampede -> bad!
-        */
-       if (atomic_read(&sem->count) >= 0)
-               wake_up(&sem->wait);
-}
-
-/* Wait for the lock to become unbiased.  Readers
- * are non-exclusive. =)
- */
-void down_read_failed(struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       up_read(sem);   /* this takes care of granting the lock */
-
-       add_wait_queue(&sem->wait, &wait);
-
-       while (atomic_read(&sem->count) < 0) {
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (atomic_read(&sem->count) >= 0)
-                       break;
-               schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-}
-
-/* Wait for the lock to become unbiased. Since we're
- * a writer, we'll make ourselves exclusive.
- */
-void down_write_failed(struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       up_write(sem);  /* this takes care of granting the lock */
-
-       add_wait_queue_exclusive(&sem->wait, &wait);
-
-       while (atomic_read(&sem->count) < 0) {
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (atomic_read(&sem->count) >= 0)
-                       break;  /* we must attempt to acquire or bias the lock */
-               schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-}
-
-/* Called when someone has done an up that transitioned from
- * negative to non-negative, meaning that the lock has been
- * granted to whomever owned the bias.
- */
-void rwsem_wake_readers(struct rw_semaphore *sem)
-{
-       if (xchg(&sem->read_bias_granted, 1))
-               BUG();
-       wake_up(&sem->wait);
-}
-
-void rwsem_wake_writers(struct rw_semaphore *sem)
-{
-       if (xchg(&sem->write_bias_granted, 1))
-               BUG();
-       wake_up(&sem->write_bias_wait);
-}
-
-void __down_read_failed(int count, struct rw_semaphore *sem) 
-{
-       do {
-               if (count == -1) {
-                       down_read_failed_biased(sem);
-                       break;
-               }
-               down_read_failed(sem);
-               count = atomic_dec_return(&sem->count);
-       } while (count != 0);
-}
-
-void __down_write_failed(int count, struct rw_semaphore *sem)
-{
-       do {
-               if (count < 0 && count > -RW_LOCK_BIAS) {
-                       down_write_failed_biased(sem);
-                       break;
-               }
-               down_write_failed(sem);
-               count = atomic_add_return(-RW_LOCK_BIAS, &sem->count);
-       } while (count != 0);
-}
-
-void __rwsem_wake(int count, struct rw_semaphore *sem)
-{
-       if (count == 0)
-               rwsem_wake_readers(sem);
-       else
-               rwsem_wake_writers(sem);
-}
-
index 4496cda..6bd49fc 100644 (file)
@@ -7,6 +7,8 @@ mainmenu_name "Linux/SuperH Kernel Configuration"
 define_bool CONFIG_SUPERH y
 
 define_bool CONFIG_UID16 y
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 mainmenu_option next_comment
 comment 'Code maturity level options'
index 7cdda22..ad89ae3 100644 (file)
@@ -135,162 +135,3 @@ int __down_trylock(struct semaphore * sem)
 {
        return waking_non_zero_trylock(sem);
 }
-
-/* Called when someone has done an up that transitioned from
- * negative to non-negative, meaning that the lock has been
- * granted to whomever owned the bias.
- */
-struct rw_semaphore *rwsem_wake_readers(struct rw_semaphore *sem)
-{
-       if (xchg(&sem->read_bias_granted, 1))
-               BUG();
-       wake_up(&sem->wait);
-       return sem;
-}
-
-struct rw_semaphore *rwsem_wake_writer(struct rw_semaphore *sem)
-{
-       if (xchg(&sem->write_bias_granted, 1))
-               BUG();
-       wake_up(&sem->write_bias_wait);
-       return sem;
-}
-
-struct rw_semaphore * __rwsem_wake(struct rw_semaphore *sem)
-{
-       if (atomic_read(&sem->count) == 0)
-               return rwsem_wake_writer(sem);
-       else
-               return rwsem_wake_readers(sem);
-}
-
-struct rw_semaphore *down_read_failed_biased(struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       add_wait_queue(&sem->wait, &wait);      /* put ourselves at the head of the list */
-
-       for (;;) {
-               if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
-                       break;
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (!sem->read_bias_granted)
-                       schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-
-       return sem;
-}
-
-struct rw_semaphore *down_write_failed_biased(struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */
-
-       for (;;) {
-               if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
-                       break;
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (!sem->write_bias_granted)
-                       schedule();
-       }
-
-       remove_wait_queue(&sem->write_bias_wait, &wait);
-       tsk->state = TASK_RUNNING;
-
-       /* if the lock is currently unbiased, awaken the sleepers
-        * FIXME: this wakes up the readers early in a bit of a
-        * stampede -> bad!
-        */
-       if (atomic_read(&sem->count) >= 0)
-               wake_up(&sem->wait);
-
-       return sem;
-}
-
-/* Wait for the lock to become unbiased.  Readers
- * are non-exclusive. =)
- */
-struct rw_semaphore *down_read_failed(struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       __up_read(sem); /* this takes care of granting the lock */
-
-       add_wait_queue(&sem->wait, &wait);
-
-       while (atomic_read(&sem->count) < 0) {
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (atomic_read(&sem->count) >= 0)
-                       break;
-               schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-
-       return sem;
-}
-
-/* Wait for the lock to become unbiased. Since we're
- * a writer, we'll make ourselves exclusive.
- */
-struct rw_semaphore *down_write_failed(struct rw_semaphore *sem)
-{
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
-
-       __up_write(sem);        /* this takes care of granting the lock */
-
-       add_wait_queue_exclusive(&sem->wait, &wait);
-
-       while (atomic_read(&sem->count) < 0) {
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (atomic_read(&sem->count) >= 0)
-                       break;  /* we must attempt to acquire or bias the lock */
-               schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-
-       return sem;
-}
-
-struct rw_semaphore *__down_read(struct rw_semaphore *sem, int carry)
-{
-       if (carry) {
-               int saved, new;
-
-               do {
-                       down_read_failed(sem);
-                       saved = atomic_read(&sem->count);
-                       if ((new = atomic_dec_return(&sem->count)) >= 0)
-                               return sem;
-               } while (!(new < 0 && saved >=0));
-       }
-
-       return down_read_failed_biased(sem);
-}
-
-struct rw_semaphore *__down_write(struct rw_semaphore *sem, int carry)
-{
-       if (carry) {
-               int saved, new;
-
-               do {
-                       down_write_failed(sem);
-                       saved = atomic_read(&sem->count);
-                       if ((new = atomic_sub_return(RW_LOCK_BIAS, &sem->count) ) == 0)
-                               return sem;
-               } while (!(new < 0 && saved >=0));
-       }
-
-       return down_write_failed_biased(sem);
-}
index 434345d..1699330 100644 (file)
@@ -48,6 +48,8 @@ define_bool CONFIG_SUN_KEYBOARD y
 define_bool CONFIG_SUN_CONSOLE y
 define_bool CONFIG_SUN_AUXIO y
 define_bool CONFIG_SUN_IO y
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 bool 'Support for SUN4 machines (disables SUN4[CDM] support)' CONFIG_SUN4
 if [ "$CONFIG_SUN4" != "y" ]; then
index 56bea7a..b9a649c 100644 (file)
@@ -8,7 +8,7 @@
  *  Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
  *  Copyright (C) 1995 Pete A. Zaitcev (zaitcev@metabyte.com)
  *  Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
- *  Copyright (C) 1998-2000 Anton Blanchard (anton@linuxcare.com)
+ *  Copyright (C) 1998-2000 Anton Blanchard (anton@samba.org)
  */
 
 #include <linux/config.h>
index 259a0a7..59a30f6 100644 (file)
@@ -151,119 +151,3 @@ int __down_trylock(struct semaphore * sem)
        spin_unlock_irqrestore(&semaphore_lock, flags);
        return 1;
 }
-
-/* rw mutexes
- * Implemented by Jakub Jelinek (jakub@redhat.com) based on
- * i386 implementation by Ben LaHaise (bcrl@redhat.com).
- */
-
-extern inline int ldstub(unsigned char *p)
-{
-       int ret;
-       asm volatile("ldstub %1, %0" : "=r" (ret) : "m" (*p) : "memory");
-       return ret;
-}
-
-#define DOWN_VAR                               \
-       struct task_struct *tsk = current;      \
-       DECLARE_WAITQUEUE(wait, tsk);
-
-void down_read_failed_biased(struct rw_semaphore *sem)
-{
-       DOWN_VAR
-
-       add_wait_queue(&sem->wait, &wait);      /* put ourselves at the head of the list */
-
-       for (;;) {
-               if (!ldstub(&sem->read_not_granted))
-                       break;
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (sem->read_not_granted)
-                       schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-}
-
-void down_write_failed_biased(struct rw_semaphore *sem)
-{
-       DOWN_VAR
-
-       add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */
-
-       for (;;) {
-               if (!ldstub(&sem->write_not_granted))
-                       break;
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (sem->write_not_granted)
-                       schedule();
-       }
-
-       remove_wait_queue(&sem->write_bias_wait, &wait);
-       tsk->state = TASK_RUNNING;
-
-       /* if the lock is currently unbiased, awaken the sleepers
-        * FIXME: this wakes up the readers early in a bit of a
-        * stampede -> bad!
-        */
-       if (sem->count >= 0)
-               wake_up(&sem->wait);
-}
-
-/* Wait for the lock to become unbiased.  Readers
- * are non-exclusive. =)
- */
-void down_read_failed(struct rw_semaphore *sem)
-{
-       DOWN_VAR
-
-       __up_read(sem); /* this takes care of granting the lock */
-
-       add_wait_queue(&sem->wait, &wait);
-
-       while (sem->count < 0) {
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (sem->count >= 0)
-                       break;
-               schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-}
-
-/* Wait for the lock to become unbiased. Since we're
- * a writer, we'll make ourselves exclusive.
- */
-void down_write_failed(struct rw_semaphore *sem)
-{
-       DOWN_VAR
-
-       __up_write(sem);        /* this takes care of granting the lock */
-
-       add_wait_queue_exclusive(&sem->wait, &wait);
-
-       while (sem->count < 0) {
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (sem->count >= 0)
-                       break;  /* we must attempt to acquire or bias the lock */
-               schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-}
-
-void __rwsem_wake(struct rw_semaphore *sem, unsigned long readers)
-{
-       if (readers) {
-               /* Due to lame ldstub we don't do here
-                  a BUG() consistency check */
-               sem->read_not_granted = 0;
-               wake_up(&sem->wait);
-       } else {
-               sem->write_not_granted = 0;
-               wake_up(&sem->write_bias_wait);
-       }
-}
index 6cc5949..41b9169 100644 (file)
@@ -2,7 +2,7 @@
  *  linux/arch/sparc/kernel/setup.c
  *
  *  Copyright (C) 1995  David S. Miller (davem@caip.rutgers.edu)
- *  Copyright (C) 2000  Anton Blanchard (anton@linuxcare.com)
+ *  Copyright (C) 2000  Anton Blanchard (anton@samba.org)
  */
 
 #include <linux/errno.h>
index 523ff11..97a68fa 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.69 2001/03/27 02:36:37 davem Exp $
+/* $Id: sys_sparc.c,v 1.70 2001/04/14 01:12:02 davem Exp $
  * linux/arch/sparc/kernel/sys_sparc.c
  *
  * This file contains various random system calls that
@@ -299,7 +299,6 @@ asmlinkage unsigned long sparc_mremap(unsigned long addr,
        } else if ((ARCH_SUN4C_SUN4 && addr < 0xe0000000 &&
                    addr + new_len > 0x20000000) ||
                   addr + new_len > TASK_SIZE - PAGE_SIZE) {
-               unsigned long (*get_addr)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
                unsigned long map_flags = 0;
                struct file *file = NULL;
 
index 89807b3..23eb484 100644 (file)
@@ -1,10 +1,10 @@
-/*  $Id: init.c,v 1.97 2001/02/26 02:57:34 anton Exp $
+/*  $Id: init.c,v 1.96 2000/11/30 08:51:50 anton Exp $
  *  linux/arch/sparc/mm/init.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  *  Copyright (C) 1995 Eddie C. Dost (ecd@skynet.be)
  *  Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- *  Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com.au)
+ *  Copyright (C) 2000 Anton Blanchard (anton@samba.org)
  */
 
 #include <linux/config.h>
index e2b6116..077d39c 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright (C) 1995 Pete Zaitcev
  * Copyright (C) 1996 Eddie C. Dost    (ecd@skynet.be)
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- * Copyright (C) 1999,2000 Anton Blanchard (anton@linuxcare.com)
+ * Copyright (C) 1999,2000 Anton Blanchard (anton@samba.org)
  */
 
 #include <linux/config.h>
index 91a1d57..5eeb742 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
  * Copyright (C) 1996 Andrew Tridgell (Andrew.Tridgell@anu.edu.au)
- * Copyright (C) 1997-2000 Anton Blanchard (anton@linuxcare.com)
+ * Copyright (C) 1997-2000 Anton Blanchard (anton@samba.org)
  * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  */
 
index b39af01..b99b220 100644 (file)
@@ -33,6 +33,8 @@ define_bool CONFIG_SPARC64 y
 
 # Global things across all Sun machines.
 define_bool CONFIG_HAVE_DEC_LOCK y
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 define_bool CONFIG_ISA n
 define_bool CONFIG_EISA n
 define_bool CONFIG_MCA n
index d9784a7..67f44f9 100644 (file)
@@ -446,6 +446,7 @@ CONFIG_VFAT_FS=m
 CONFIG_EFS_FS=m
 # CONFIG_JFFS_FS is not set
 CONFIG_CRAMFS=m
+# CONFIG_TMPFS is not set
 CONFIG_RAMFS=m
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
index 1928d5a..3483392 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: semaphore.c,v 1.5 2000/11/10 04:02:03 davem Exp $
+/* $Id: semaphore.c,v 1.6 2001/04/14 01:12:02 davem Exp $
  *  Generic semaphore code. Buyer beware. Do your own
  * specific changes in <asm/semaphore-helper.h>
  */
@@ -126,172 +126,3 @@ int __down_trylock(struct semaphore * sem)
 {
        return waking_non_zero_trylock(sem);
 }
-
-/* rw mutexes
- * Implemented by Jakub Jelinek (jakub@redhat.com) based on
- * i386 implementation by Ben LaHaise (bcrl@redhat.com).
- */
-
-asm("
-       .text
-       .align  32
-       .globl  __down_read_failed
-__down_read_failed:
-       save            %sp, -160, %sp
-       membar          #StoreStore
-       brz,pt          %g5, 3f
-        mov            %g7, %l0
-1:     call            down_read_failed
-        mov            %l0, %o0
-2:     lduw            [%l0], %l1
-       sub             %l1, 1, %l2
-       cas             [%l0], %l1, %l2
-
-       cmp             %l1, %l2
-       bne,pn          %icc, 2b
-        membar         #StoreStore
-       subcc           %l1, 1, %g0
-       bpos,pt         %icc, 4f
-        nop
-       bcc,pn          %icc, 1b
-        nop
-
-3:     call            down_read_failed_biased
-        mov            %l0, %o0
-4:     ret
-        restore
-       .previous
-");
-
-asm("
-       .text
-       .align  32
-       .globl  __down_write_failed
-__down_write_failed:
-       save            %sp, -160, %sp
-       membar          #StoreStore
-       tst             %g5
-       bge,pt          %icc, 3f
-        mov            %g7, %l0
-1:     call            down_write_failed
-        mov            %l0, %o0
-2:     lduw            [%l0], %l1
-       sethi           %hi (" RW_LOCK_BIAS_STR "), %l3
-       sub             %l1, %l3, %l2
-       cas             [%l0], %l1, %l2
-
-       cmp             %l1, %l2
-       bne,pn          %icc, 2b
-        membar         #StoreStore
-       subcc           %l1, %l3, %g0
-       be,pt           %icc, 4f
-        nop
-       bcc,pn          %icc, 1b
-        nop
-
-3:     call            down_write_failed_biased
-        mov            %l0, %o0
-4:     ret
-        restore
-       .previous
-");
-
-void down_read_failed_biased(struct rw_semaphore *sem)
-{
-       DOWN_VAR
-
-       add_wait_queue(&sem->wait, &wait);      /* put ourselves at the head of the list */
-
-       for (;;) {
-               if (test_and_clear_le_bit(0, &sem->granted))
-                       break;
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (!test_le_bit(0, &sem->granted))
-                       schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-}
-
-void down_write_failed_biased(struct rw_semaphore *sem)
-{
-       DOWN_VAR
-
-       add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */
-
-       for (;;) {
-               if (test_and_clear_le_bit(1, &sem->granted))
-                       break;
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (!test_le_bit(1, &sem->granted))
-                       schedule();
-       }
-
-       remove_wait_queue(&sem->write_bias_wait, &wait);
-       tsk->state = TASK_RUNNING;
-
-       /* if the lock is currently unbiased, awaken the sleepers
-        * FIXME: this wakes up the readers early in a bit of a
-        * stampede -> bad!
-        */
-       if (sem->count >= 0)
-               wake_up(&sem->wait);
-}
-
-/* Wait for the lock to become unbiased.  Readers
- * are non-exclusive. =)
- */
-void down_read_failed(struct rw_semaphore *sem)
-{
-       DOWN_VAR
-
-       __up_read(sem); /* this takes care of granting the lock */
-
-       add_wait_queue(&sem->wait, &wait);
-
-       while (sem->count < 0) {
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (sem->count >= 0)
-                       break;
-               schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-}
-
-/* Wait for the lock to become unbiased. Since we're
- * a writer, we'll make ourselves exclusive.
- */
-void down_write_failed(struct rw_semaphore *sem)
-{
-       DOWN_VAR
-
-       __up_write(sem);        /* this takes care of granting the lock */
-
-       add_wait_queue_exclusive(&sem->wait, &wait);
-
-       while (sem->count < 0) {
-               set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-               if (sem->count >= 0)
-                       break;  /* we must attempt to acquire or bias the lock */
-               schedule();
-       }
-
-       remove_wait_queue(&sem->wait, &wait);
-       tsk->state = TASK_RUNNING;
-}
-
-void __rwsem_wake(struct rw_semaphore *sem, unsigned long readers)
-{
-       if (readers) {
-               if (test_and_set_le_bit(0, &sem->granted))
-                       BUG();
-               wake_up(&sem->wait);
-       } else {
-               if (test_and_set_le_bit(1, &sem->granted))
-                       BUG();
-               wake_up(&sem->write_bias_wait);
-       }
-}
index f3af9b3..bfe896f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.104 2001/04/05 11:08:11 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.105 2001/04/14 01:12:02 davem Exp $
  * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -159,21 +159,16 @@ EXPORT_SYMBOL(__down_interruptible);
 EXPORT_SYMBOL(__down_trylock);
 EXPORT_SYMBOL(__up);
 
-/* rw semaphores */
-EXPORT_SYMBOL_NOVERS(__down_read_failed);
-EXPORT_SYMBOL_NOVERS(__down_write_failed);
-EXPORT_SYMBOL_NOVERS(__rwsem_wake);
-
 /* Atomic counter implementation. */
 EXPORT_SYMBOL(__atomic_add);
 EXPORT_SYMBOL(__atomic_sub);
 
 /* Atomic bit operations. */
-EXPORT_SYMBOL(__test_and_set_bit);
-EXPORT_SYMBOL(__test_and_clear_bit);
-EXPORT_SYMBOL(__test_and_change_bit);
-EXPORT_SYMBOL(__test_and_set_le_bit);
-EXPORT_SYMBOL(__test_and_clear_le_bit);
+EXPORT_SYMBOL(___test_and_set_bit);
+EXPORT_SYMBOL(___test_and_clear_bit);
+EXPORT_SYMBOL(___test_and_change_bit);
+EXPORT_SYMBOL(___test_and_set_le_bit);
+EXPORT_SYMBOL(___test_and_clear_le_bit);
 
 EXPORT_SYMBOL(ivector_table);
 EXPORT_SYMBOL(enable_irq);
index 4d89be4..fd184e5 100644 (file)
@@ -2,7 +2,7 @@
  * starfire.c: Starfire/E10000 support.
  *
  * Copyright (C) 1998 David S. Miller (davem@redhat.com)
- * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com)
+ * Copyright (C) 2000 Anton Blanchard (anton@samba.org)
  */
 
 #include <linux/kernel.h>
index e57761b..dafb4d1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.51 2001/03/27 02:36:37 davem Exp $
+/* $Id: sys_sparc.c,v 1.52 2001/04/14 01:12:02 davem Exp $
  * linux/arch/sparc64/kernel/sys_sparc.c
  *
  * This file contains various random system calls that
@@ -338,7 +338,6 @@ asmlinkage unsigned long sys64_mremap(unsigned long addr,
                    new_addr + new_len > -PAGE_OFFSET)
                        goto out_sem;
        } else if (addr < PAGE_OFFSET && addr + new_len > -PAGE_OFFSET) {
-               unsigned long (*get_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
                unsigned long map_flags = 0;
                struct file *file = NULL;
 
index 88781e5..c0b34a2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.175 2001/03/27 02:36:37 davem Exp $
+/* $Id: sys_sparc32.c,v 1.176 2001/04/14 01:12:02 davem Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -4138,7 +4138,6 @@ asmlinkage unsigned long sys32_mremap(unsigned long addr,
                if (new_addr > 0xf0000000UL - new_len)
                        goto out_sem;
        } else if (addr > 0xf0000000UL - new_len) {
-               unsigned long (*get_addr)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
                unsigned long map_flags = 0;
                struct file *file = NULL;
 
@@ -4154,7 +4153,7 @@ asmlinkage unsigned long sys32_mremap(unsigned long addr,
                }
 
                /* MREMAP_FIXED checked above. */
-               new_addr = get_unmapped_addr(file, addr, new_len,
+               new_addr = get_unmapped_area(file, addr, new_len,
                                    vma ? vma->vm_pgoff : 0,
                                    map_flags);
                ret = new_addr;
index f964e45..fafe016 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: bitops.S,v 1.1 2000/03/27 10:38:41 davem Exp $
+/* $Id: bitops.S,v 1.2 2001/04/14 01:12:02 davem Exp $
  * bitops.S: Sparc64 atomic bit operations.
  *
  * Copyright (C) 2000 David S. Miller (davem@redhat.com)
@@ -11,8 +11,8 @@
        .globl  __bitops_begin
 __bitops_begin:
 
-       .globl  __test_and_set_bit
-__test_and_set_bit:    /* %o0=nr, %o1=addr */
+       .globl  ___test_and_set_bit
+___test_and_set_bit:   /* %o0=nr, %o1=addr */
        srlx    %o0, 6, %g1
        mov     1, %g5
        sllx    %g1, 3, %g3
@@ -30,8 +30,8 @@ __test_and_set_bit:   /* %o0=nr, %o1=addr */
 2:     retl
         nop
 
-       .globl  __test_and_clear_bit
-__test_and_clear_bit:  /* %o0=nr, %o1=addr */
+       .globl  ___test_and_clear_bit
+___test_and_clear_bit: /* %o0=nr, %o1=addr */
        srlx    %o0, 6, %g1
        mov     1, %g5
        sllx    %g1, 3, %g3
@@ -49,8 +49,8 @@ __test_and_clear_bit: /* %o0=nr, %o1=addr */
 2:     retl
         nop
 
-       .globl  __test_and_change_bit
-__test_and_change_bit: /* %o0=nr, %o1=addr */
+       .globl  ___test_and_change_bit
+___test_and_change_bit:        /* %o0=nr, %o1=addr */
        srlx    %o0, 6, %g1
        mov     1, %g5
        sllx    %g1, 3, %g3
@@ -68,8 +68,8 @@ __test_and_change_bit:        /* %o0=nr, %o1=addr */
         nop
        nop
 
-       .globl  __test_and_set_le_bit
-__test_and_set_le_bit: /* %o0=nr, %o1=addr */
+       .globl  ___test_and_set_le_bit
+___test_and_set_le_bit:        /* %o0=nr, %o1=addr */
        srlx    %o0, 5, %g1
        mov     1, %g5
        sllx    %g1, 2, %g3
@@ -87,8 +87,8 @@ __test_and_set_le_bit:        /* %o0=nr, %o1=addr */
 2:     retl
         nop
 
-       .globl  __test_and_clear_le_bit
-__test_and_clear_le_bit:       /* %o0=nr, %o1=addr */
+       .globl  ___test_and_clear_le_bit
+___test_and_clear_le_bit:      /* %o0=nr, %o1=addr */
        srlx    %o0, 5, %g1
        mov     1, %g5
        sllx    %g1, 2, %g3
index 3ef9c94..c632d46 100644 (file)
@@ -611,7 +611,7 @@ int timod_putmsg(unsigned int fd, char *ctl_buf, int ctl_len,
                return 0;
        }
        default:
-               printk("timod_putmsg: unsuported command %u.\n", ret);
+               printk("timod_putmsg: unsupported command %u.\n", ret);
                break;
        }
        return -EINVAL;
index c020922..bd9622b 100644 (file)
@@ -583,13 +583,15 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
                if (iocommand.Request.Type.Direction == XFER_WRITE)
                {
                        /* Copy the data into the buffer we created */ 
-                       if (copy_from_user(buff, iocommand.buf, iocommand.buf_size))
+                       if (copy_from_user(buff, iocommand.buf,
+                                               iocommand.buf_size)) {
+                               kfree(buff);
                                return -EFAULT;
+                       }
                }
                if ((c = cmd_alloc(NULL)) == NULL)
                {
-                       if(buff!=NULL)
-                               kfree(buff);
+                       kfree(buff);
                        return -ENOMEM;
                }
                        // Fill in the command type 
@@ -636,8 +638,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
                if ( copy_to_user((void *) arg, &iocommand, sizeof( IOCTL_Command_struct) ) )
                {
                        cmd_free(NULL, c);
-                       if (buff != NULL) 
-                               kfree(buff);
+                       kfree(buff);
                        return( -EFAULT);       
                }       
 
@@ -648,11 +649,11 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
                        {
                                     cmd_free(NULL, c);
                                     kfree(buff);
+                                    return -EFAULT;    
                        }
                 }
                cmd_free(NULL, c);
-                if (buff != NULL)
-                       kfree(buff);
+                kfree(buff);
                 return(0);
        } 
 
@@ -761,7 +762,7 @@ static int revalidate_allvol(kdev_t dev)
         hba[ctlr]->gendisk.nr_real = 0;
 
         /*
-         * Tell the array controller not to give us any interupts while
+         * Tell the array controller not to give us any interrupts while
          * we check the new geometry.  Then turn interrupts back on when
          * we're done.
          */
@@ -1087,7 +1088,7 @@ static inline void complete_command( CommandList_struct *cmd, int timeout)
        if (timeout)
                status = 0; 
        if(cmd->err_info->CommandStatus != 0) 
-       { /* an error has occured */ 
+       { /* an error has occurred */ 
                switch(cmd->err_info->CommandStatus)
                {
                        case CMD_TARGET_STATUS:
@@ -1846,12 +1847,9 @@ int __init cciss_init(void)
                        || (hba[i]->errinfo_pool == NULL))
                 {
                         nr_ctlr = i;
-                       if(hba[i]->cmd_pool_bits)
-                                kfree(hba[i]->cmd_pool_bits);
-                        if(hba[i]->cmd_pool)
-                                kfree(hba[i]->cmd_pool);
-                       if(hba[i]->errinfo_pool)
-                               kfree(hba[i]->errinfo_pool);
+                       kfree(hba[i]->cmd_pool_bits);
+                       kfree(hba[i]->cmd_pool);
+                       kfree(hba[i]->errinfo_pool);
                         free_irq(hba[i]->intr, hba[i]);
                         unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
                         num_cntlrs_reg--;
index 5a0808a..bf22518 100644 (file)
@@ -122,7 +122,7 @@ static void SA5_submit_command( ctlr_info_t *h, CommandList_struct *c)
 }
 
 /*  
- *  This card is the oposite of the other cards.  
+ *  This card is the opposite of the other cards.  
  *   0 turns interrupts on... 
  *   0x08 turns them off... 
  */
@@ -138,7 +138,7 @@ static void SA5_intr_mask(ctlr_info_t *h, unsigned long val)
        }
 }
 /*
- *  This card is the oposite of the other cards.
+ *  This card is the opposite of the other cards.
  *   0 turns interrupts on...
  *   0x04 turns them off...
  */
index 456a3a0..7436aa5 100644 (file)
@@ -222,7 +222,7 @@ typedef struct _CommandList_struct {
   ErrDescriptor_struct     ErrDesc;
   SGDescriptor_struct      SG[MAXSGENTRIES];
        /* information associated with the command */ 
-  __u32                           busaddr; /* physical addres of this record */
+  __u32                           busaddr; /* physical address of this record */
   ErrorInfo_struct *      err_info; /* pointer to the allocated mem */ 
   int                     cmd_type; 
   struct _CommandList_struct *prev;
index 4ad1896..dd15957 100644 (file)
@@ -68,6 +68,23 @@ ifeq ($(ARCH),sh)
   KEYBD    = scan_keyb.o hp600_keyb.o
   CONSOLE  = console.o
   endif
+  ifeq ($(CONFIG_SH_DMIDA),y)
+  # DMIDA does not connect the HD64465 PS/2 keyboard port
+  # but we allow for USB keyboards to be plugged in.
+  KEYMAP   = defkeymap.o
+  KEYBD    = # hd64465_keyb.o pc_keyb.o
+  CONSOLE  = console.o
+  endif
+  ifeq ($(CONFIG_SH_EC3104),y)
+  KEYMAP   = defkeymap.o
+  KEYBD    = ec3104_keyb.o
+  CONSOLE  = console.o
+  endif
+  ifeq ($(CONFIG_SH_DREAMCAST),y)
+  KEYMAP   = defkeymap.o
+  KEYBD    =
+  CONSOLE  = console.o
+  endif
 endif
 
 ifeq ($(CONFIG_DECSTATION),y)
index 36bbd3f..f700f85 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ffb_drv.c,v 1.11 2001/03/27 02:36:37 davem Exp $
+/* $Id: ffb_drv.c,v 1.12 2001/04/14 01:12:03 davem Exp $
  * ffb_drv.c: Creator/Creator3D direct rendering driver.
  *
  * Copyright (C) 2000 David S. Miller (davem@redhat.com)
diff --git a/drivers/char/ec3104_keyb.c b/drivers/char/ec3104_keyb.c
new file mode 100644 (file)
index 0000000..3c0c5bf
--- /dev/null
@@ -0,0 +1,461 @@
+/*
+ * linux/drivers/char/ec3104_keyb.c
+ * 
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ * based on linux/drivers/char/pc_keyb.c, which had the following comments:
+ *
+ * Separation of the PC low-level part by Geert Uytterhoeven, May 1997
+ * See keyboard.c for the whole history.
+ *
+ * Major cleanup by Martin Mares, May 1997
+ *
+ * Combined the keyboard and PS/2 mouse handling into one file,
+ * because they share the same hardware.
+ * Johan Myreen <jem@iki.fi> 1998-10-08.
+ *
+ * Code fixes to handle mouse ACKs properly.
+ * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29.
+ */
+/* EC3104 note:
+ * This code was written without any documentation about the EC3104 chip.  While
+ * I hope I got most of the basic functionality right, the register names I use
+ * are most likely completely different from those in the chip documentation.
+ *
+ * If you have any further information about the EC3104, please tell me
+ * (prumpf@tux.org).
+ */
+
+#include <linux/config.h>
+
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/init.h>
+#include <linux/kbd_ll.h>
+#include <linux/delay.h>
+#include <linux/random.h>
+#include <linux/poll.h>
+#include <linux/miscdevice.h>
+#include <linux/malloc.h>
+#include <linux/kbd_kern.h>
+#include <linux/smp_lock.h>
+
+#include <asm/keyboard.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/ec3104.h>
+
+#include <asm/io.h>
+
+/* Some configuration switches are present in the include file... */
+
+#include <linux/pc_keyb.h>
+
+#define MSR_CTS 0x10
+#define MCR_RTS 0x02
+#define LSR_DR 0x01
+#define LSR_BOTH_EMPTY 0x60
+
+static struct e5_struct {
+       u8 packet[8];
+       int pos;
+       int length;
+
+       u8 cached_mcr;
+       u8 last_msr;
+} ec3104_keyb;
+       
+/* Simple translation table for the SysRq keys */
+
+
+#ifdef CONFIG_MAGIC_SYSRQ
+unsigned char ec3104_kbd_sysrq_xlate[128] =
+       "\000\0331234567890-=\177\t"                    /* 0x00 - 0x0f */
+       "qwertyuiop[]\r\000as"                          /* 0x10 - 0x1f */
+       "dfghjkl;'`\000\\zxcv"                          /* 0x20 - 0x2f */
+       "bnm,./\000*\000 \000\201\202\203\204\205"      /* 0x30 - 0x3f */
+       "\206\207\210\211\212\000\000789-456+1"         /* 0x40 - 0x4f */
+       "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
+       "\r\000/";                                      /* 0x60 - 0x6f */
+#endif
+
+static void kbd_write_command_w(int data);
+static void kbd_write_output_w(int data);
+#ifdef CONFIG_PSMOUSE
+static void aux_write_ack(int val);
+static void __aux_write_ack(int val);
+#endif
+
+static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
+static unsigned char handle_kbd_event(void);
+
+/* used only by send_data - set by keyboard_interrupt */
+static volatile unsigned char reply_expected;
+static volatile unsigned char acknowledge;
+static volatile unsigned char resend;
+
+
+int ec3104_kbd_setkeycode(unsigned int scancode, unsigned int keycode)
+{
+       return 0;
+}
+
+int ec3104_kbd_getkeycode(unsigned int scancode)
+{
+       return 0;
+}
+
+
+/* yes, it probably would be faster to use an array.  I don't care. */
+
+static inline unsigned char ec3104_scan2key(unsigned char scancode)
+{
+       switch (scancode) {
+       case  1: /* '`' */
+               return 41;
+               
+       case  2 ... 27:
+               return scancode;
+               
+       case 28: /* '\\' */
+               return 43;
+
+       case 29 ... 39:
+               return scancode + 1;
+
+       case 40: /* '\r' */
+               return 28;
+
+       case 41 ... 50:
+               return scancode + 3;
+
+       case 51: /* ' ' */
+               return 57;
+               
+       case 52: /* escape */
+               return 1;
+
+       case 54: /* insert/delete (labelled delete) */
+               /* this should arguably be 110, but I'd like to have ctrl-alt-del
+                * working with a standard keymap */
+               return 111;
+
+       case 55: /* left */
+               return 105;
+       case 56: /* home */
+               return 102;
+       case 57: /* end */
+               return 107;
+       case 58: /* up */
+               return 103;
+       case 59: /* down */
+               return 108;
+       case 60: /* pgup */
+               return 104;
+       case 61: /* pgdown */
+               return 109;
+       case 62: /* right */
+               return 106;
+
+       case 79 ... 88: /* f1 - f10 */
+               return scancode - 20;
+
+       case 89 ... 90: /* f11 - f12 */
+               return scancode - 2;
+
+       case 91: /* left shift */
+               return 42;
+
+       case 92: /* right shift */
+               return 54;
+
+       case 93: /* left alt */
+               return 56;
+       case 94: /* right alt */
+               return 100;
+       case 95: /* left ctrl */
+               return 29;
+       case 96: /* right ctrl */
+               return 97;
+
+       case 97: /* caps lock */
+               return 58;
+       case 102: /* left windows */
+               return 125;
+       case 103: /* right windows */
+               return 126;
+
+       case 106: /* Fn */
+               /* this is wrong. */
+               return 84;
+
+       default:
+               return 0;
+       }
+}
+               
+int ec3104_kbd_translate(unsigned char scancode, unsigned char *keycode,
+                   char raw_mode)
+{
+       scancode &= 0x7f;
+
+       *keycode = ec3104_scan2key(scancode);
+
+       return 1;
+}
+
+char ec3104_kbd_unexpected_up(unsigned char keycode)
+{
+       return 0200;
+}
+
+static inline void handle_keyboard_event(unsigned char scancode)
+{
+#ifdef CONFIG_VT
+       handle_scancode(scancode, !(scancode & 0x80));
+#endif                         
+       tasklet_schedule(&keyboard_tasklet);
+}      
+
+void ec3104_kbd_leds(unsigned char leds)
+{
+}
+
+static u8 e5_checksum(u8 *packet, int count)
+{
+       int i;
+       u8 sum = 0;
+
+       for (i=0; i<count; i++)
+               sum ^= packet[i];
+               
+       if (sum & 0x80)
+               sum ^= 0xc0;
+
+       return sum;
+}
+
+static void e5_wait_for_cts(struct e5_struct *k)
+{
+       u8 msr;
+               
+       do {
+               msr = ctrl_inb(EC3104_SER4_MSR);
+       } while (!(msr & MSR_CTS));
+}
+
+
+static void e5_send_byte(u8 byte, struct e5_struct *k)
+{
+       u8 status;
+               
+       do {
+               status = ctrl_inb(EC3104_SER4_LSR);
+       } while ((status & LSR_BOTH_EMPTY) != LSR_BOTH_EMPTY);
+       
+       printk("<%02x>", byte);
+
+       ctrl_outb(byte, EC3104_SER4_DATA);
+
+       do {
+               status = ctrl_inb(EC3104_SER4_LSR);
+       } while ((status & LSR_BOTH_EMPTY) != LSR_BOTH_EMPTY);
+       
+}
+
+static int e5_send_packet(u8 *packet, int count, struct e5_struct *k)
+{
+       int i;
+
+       disable_irq(EC3104_IRQ_SER4);
+       
+       if (k->cached_mcr & MCR_RTS) {
+               printk("e5_send_packet: too slow\n");
+               enable_irq(EC3104_IRQ_SER4);
+               return -EAGAIN;
+       }
+
+       k->cached_mcr |= MCR_RTS;
+       ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
+
+       e5_wait_for_cts(k);
+
+       printk("p: ");
+
+       for(i=0; i<count; i++)
+               e5_send_byte(packet[i], k);
+
+       e5_send_byte(e5_checksum(packet, count), k);
+
+       printk("\n");
+
+       udelay(1500);
+
+       k->cached_mcr &= ~MCR_RTS;
+       ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
+
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       
+       
+
+       enable_irq(EC3104_IRQ_SER4);
+
+       
+
+       return 0;
+}
+
+/*
+ * E5 packets we know about:
+ * E5->host 0x80 0x05 <checksum> - resend packet
+ * host->E5 0x83 0x43 <contrast> - set LCD contrast
+ * host->E5 0x85 0x41 0x02 <brightness> 0x02 - set LCD backlight
+ * E5->host 0x87 <ps2 packet> 0x00 <checksum> - external PS2 
+ * E5->host 0x88 <scancode> <checksum> - key press
+ */
+
+static void e5_receive(struct e5_struct *k)
+{
+       k->packet[k->pos++] = ctrl_inb(EC3104_SER4_DATA);
+
+       if (k->pos == 1) {
+               switch(k->packet[0]) {
+               case 0x80:
+                       k->length = 3;
+                       break;
+                       
+               case 0x87: /* PS2 ext */
+                       k->length = 6;
+                       break;
+
+               case 0x88: /* keyboard */
+                       k->length = 3;
+                       break;
+
+               default:
+                       k->length = 1;
+                       printk(KERN_WARNING "unknown E5 packet %02x\n",
+                              k->packet[0]);
+               }
+       }
+
+       if (k->pos == k->length) {
+               int i;
+
+               if (e5_checksum(k->packet, k->length) != 0)
+                       printk(KERN_WARNING "E5: wrong checksum\n");
+
+#if 0
+               printk("E5 packet [");
+               for(i=0; i<k->length; i++) {
+                       printk("%02x ", k->packet[i]);
+               }
+
+               printk("(%02x)]\n", e5_checksum(k->packet, k->length-1));
+#endif
+
+               switch(k->packet[0]) {
+               case 0x80:
+               case 0x88:
+                       handle_keyboard_event(k->packet[1]);
+                       break;
+               }
+
+               k->pos = k->length = 0;
+       }
+}
+
+static void ec3104_keyb_interrupt(int irq, void *data, struct pt_regs *regs)
+{
+       struct e5_struct *k = &ec3104_keyb;
+       u8 msr, lsr;
+
+       kbd_pt_regs = regs;
+
+       msr = ctrl_inb(EC3104_SER4_MSR);
+       
+       if ((msr & MSR_CTS) && !(k->last_msr & MSR_CTS)) {
+               if (k->cached_mcr & MCR_RTS)
+                       printk("confused: RTS already high\n");
+               /* CTS went high.  Send RTS. */
+               k->cached_mcr |= MCR_RTS;
+               
+               ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
+       } else if ((!(msr & MSR_CTS)) && (k->last_msr & MSR_CTS)) {
+               /* CTS went low. */
+               if (!(k->cached_mcr & MCR_RTS))
+                       printk("confused: RTS already low\n");
+
+               k->cached_mcr &= ~MCR_RTS;
+
+               ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
+       }
+
+       k->last_msr = msr;
+
+       lsr = ctrl_inb(EC3104_SER4_LSR);
+
+       if (lsr & LSR_DR)
+               e5_receive(k);
+}
+
+static void ec3104_keyb_clear_state(void)
+{
+       struct e5_struct *k = &ec3104_keyb;
+       u8 msr, lsr;
+       
+       /* we want CTS to be low */
+       k->last_msr = 0;
+
+       for (;;) {
+               schedule_timeout(HZ/10);
+
+               msr = ctrl_inb(EC3104_SER4_MSR);
+       
+               lsr = ctrl_inb(EC3104_SER4_LSR);
+               
+               if (lsr & LSR_DR) {
+                       e5_receive(k);
+                       continue;
+               }
+
+               if ((msr & MSR_CTS) && !(k->last_msr & MSR_CTS)) {
+                       if (k->cached_mcr & MCR_RTS)
+                               printk("confused: RTS already high\n");
+                       /* CTS went high.  Send RTS. */
+                       k->cached_mcr |= MCR_RTS;
+               
+                       ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
+               } else if ((!(msr & MSR_CTS)) && (k->last_msr & MSR_CTS)) {
+                       /* CTS went low. */
+                       if (!(k->cached_mcr & MCR_RTS))
+                               printk("confused: RTS already low\n");
+                       
+                       k->cached_mcr &= ~MCR_RTS;
+                       
+                       ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
+               } else
+                       break;
+
+               k->last_msr = msr;
+
+               continue;
+       }
+}
+
+void __init ec3104_kbd_init_hw(void)
+{
+       ec3104_keyb.last_msr = ctrl_inb(EC3104_SER4_MSR);
+       ec3104_keyb.cached_mcr = ctrl_inb(EC3104_SER4_MCR);
+
+       ec3104_keyb_clear_state();
+
+       /* Ok, finally allocate the IRQ, and off we go.. */
+       request_irq(EC3104_IRQ_SER4, ec3104_keyb_interrupt, 0, "keyboard", NULL);
+}
index 2757e55..df26fb9 100644 (file)
@@ -769,7 +769,7 @@ static int pc_write(struct tty_struct * tty, int from_user,
                globalwinon(ch);
 
                /* -----------------------------------------------------------------    
-                       Anding against size will wrap the pointer back to its begining 
+                       Anding against size will wrap the pointer back to its beginning 
                        position if it is necessary.  This will only work if size is
                        a power of 2 which should always be the case.  Size is determined 
                        by the cards on board FEP/OS.
@@ -789,7 +789,7 @@ static int pc_write(struct tty_struct * tty, int from_user,
                        tail = bc->tout;
 
                /* ------------------------------------------------------------------   
-                       Anding against size will wrap the pointer back to its begining 
+                       Anding against size will wrap the pointer back to its beginning 
                        position if it is necessary.  This will only work if size is
                        a power of 2 which should always be the case.  Size is determined 
                        by the cards on board FEP/OS.
@@ -818,7 +818,7 @@ static int pc_write(struct tty_struct * tty, int from_user,
                                tail                               head
 
                        The above diagram shows that buffer locations 2,3,4,5 and 6 have
-                       data to be transmited, while head points at the next empty
+                       data to be transmitted, while head points at the next empty
                        location.  To calculate how much space is available first we have
                        to determine if the head pointer (tin) has wrapped.  To do this
                        compare the head pointer to the tail pointer,  If head is equal
@@ -827,9 +827,9 @@ static int pc_write(struct tty_struct * tty, int from_user,
                        that value from the buffers size.  A one is subtracted from the
                        new value to indicate how much space is available between the 
                        head pointer and end of buffer; as well as the space between the
-                       begining of the buffer and the tail.  If the head is not greater
+                       beginning of the buffer and the tail.  If the head is not greater
                        or equal to the tail this indicates that the head has wrapped
-                       around to the begining of the buffer.  To calculate the space 
+                       around to the beginning of the buffer.  To calculate the space 
                        available in this case simply subtract head from tail.  This new 
                        value minus one represents the space available betwwen the head 
                        and tail pointers.  In this example head (7) is greater than tail (2)
@@ -849,7 +849,7 @@ static int pc_write(struct tty_struct * tty, int from_user,
                                head                               tail
 
                        The above diagram shows that buffer locations 7,8,9,0 and 1 have
-                       data to be transmited, while head points at the next empty
+                       data to be transmitted, while head points at the next empty
                        location.  To find the space available we compare head to tail.  If
                        head is not equal to, or greater than tail this indicates that head
                        has wrapped around. In this case head (2) is not equal to, or
@@ -1339,7 +1339,7 @@ static int block_til_ready(struct tty_struct *tty,
                }
 
                /* ---------------------------------------------------------------
-                       Allow someone else to be scheduled.  We will occasionaly go
+                       Allow someone else to be scheduled.  We will occasionally go
                        through this loop until one of the above conditions change.
                        The below schedule call will allow other processes to enter and
                        prevent this loop from hogging the cpu.
@@ -1685,7 +1685,7 @@ int __init pc_init(void)
                       the boards array is correct.  This could be wrong if
                       the card in question is PCI (And therefore has no ports 
                       entry in the boards structure.)  The rest of the 
-                      information will be valid for PCI because the begining
+                      information will be valid for PCI because the beginning
                       of pc_init scans for PCI and determines i/o and base
                       memory addresses.  I am not sure if it is possible to 
                       read the number of ports supported by the card prior to
@@ -1937,7 +1937,7 @@ static void post_fep_init(unsigned int crd)
  
        /*  -------------------------------------------------------------
                This call is made by the user via. the ioctl call DIGI_INIT.
-               It is resposible for setting up all the card specific stuff.
+               It is responsible for setting up all the card specific stuff.
        ---------------------------------------------------------------- */
        bd = &boards[crd];
 
index 3c231ab..f03bab1 100644 (file)
@@ -41,6 +41,9 @@ extern void prom_con_init(void);
 #ifdef CONFIG_MDA_CONSOLE
 extern void mda_console_init(void);
 #endif
+#if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR)
+extern void tapechar_init(void);
+#endif
 #if defined(CONFIG_ADB)
 extern void adbdev_init(void);
 #endif
@@ -643,6 +646,9 @@ int __init chr_dev_init(void)
 #if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR)
        tapechar_init();
 #endif
+#if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR)
+       tapechar_init();
+#endif
 #if defined(CONFIG_ADB)
        adbdev_init();
 #endif
index 504cd67..ba7b3a1 100644 (file)
@@ -73,10 +73,8 @@ extern void streamable_init(void);
 extern int rtc_DP8570A_init(void);
 extern int rtc_MK48T08_init(void);
 extern int ds1286_init(void);
-extern int dsp56k_init(void);
 extern int radio_init(void);
 extern int pmu_device_init(void);
-extern int qpmouse_init(void);
 extern int tosh_init(void);
 
 static int misc_read_proc(char *buf, char **start, off_t offset,
@@ -173,10 +171,20 @@ static struct file_operations misc_fops = {
 int misc_register(struct miscdevice * misc)
 {
        static devfs_handle_t devfs_handle;
-
+       struct miscdevice *c;
+       
        if (misc->next || misc->prev)
                return -EBUSY;
        down(&misc_sem);
+       c = misc_list.next;
+
+       while ((c != &misc_list) && (c->minor != misc->minor))
+               c = c->next;
+       if (c != &misc_list) {
+               up(&misc_sem);
+               return -EBUSY;
+       }
+
        if (misc->minor == MISC_DYNAMIC_MINOR) {
                int i = DYNAMIC_MINORS;
                while (--i >= 0)
@@ -245,9 +253,6 @@ EXPORT_SYMBOL(misc_deregister);
 int __init misc_init(void)
 {
        create_proc_read_entry("misc", 0, 0, misc_read_proc, NULL);
-#if defined CONFIG_82C710_MOUSE
-       qpmouse_init();
-#endif
 #ifdef CONFIG_MVME16x
        rtc_MK48T08_init();
 #endif
@@ -257,9 +262,6 @@ int __init misc_init(void)
 #ifdef CONFIG_SGI_DS1286
        ds1286_init();
 #endif
-#ifdef CONFIG_ATARI_DSP56K
-       dsp56k_init();
-#endif
 #ifdef CONFIG_MISC_RADIO
        radio_init();
 #endif
index 3d49a2c..459dec3 100644 (file)
@@ -983,13 +983,14 @@ static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg,
    {
 queue_the_message:
 
-      save_flags(flags);
-      cli();
-
       pMsg = kmalloc(sizeof(struct r3964_message), GFP_KERNEL);
       TRACE_M("add_msg - kmalloc %x",(int)pMsg);
-      if(pMsg==NULL)
+      if(pMsg==NULL) {
          return;
+      }
+
+      save_flags(flags);
+      cli();
 
       pMsg->msg_id = msg_id;
       pMsg->arg    = arg;
index d3e6068..770ebd6 100644 (file)
@@ -24,9 +24,8 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/fcntl.h>
 #include <linux/errno.h>
@@ -146,11 +145,11 @@ static int release_qp(struct inode * inode, struct file * file)
        fasync_qp(-1, file, 0);
        if (!--qp_count) {
                if (!poll_qp_status())
-                       printk("Warning: Mouse device busy in release_qp()\n");
+                       printk(KERN_WARNING "Warning: Mouse device busy in release_qp()\n");
                status = inb_p(qp_status);
                outb_p(status & ~(QP_ENABLE|QP_INTS_ON), qp_status);
                if (!poll_qp_status())
-                       printk("Warning: Mouse device busy in release_qp()\n");
+                       printk(KERN_WARNING "Warning: Mouse device busy in release_qp()\n");
                free_irq(QP_IRQ, NULL);
        }
        unlock_kernel();
@@ -188,7 +187,7 @@ static int open_qp(struct inode * inode, struct file * file)
        outb_p(status, qp_status);              /* Enable interrupts */
 
        while (!poll_qp_status()) {
-               printk("Error: Mouse device busy in open_qp()\n");
+               printk(KERN_ERR "Error: Mouse device busy in open_qp()\n");
                qp_count--;
                status &= ~(QP_ENABLE|QP_INTS_ON);
                outb_p(status, qp_status);
@@ -303,7 +302,9 @@ struct file_operations qp_fops = {
  * Initialize driver.
  */
 static struct miscdevice qp_mouse = {
-       PSMOUSE_MINOR, "QPmouse", &qp_fops
+       minor:          PSMOUSE_MINOR,
+       name:           "QPmouse",
+       fops:           &qp_fops,
 };
 
 /*
@@ -337,37 +338,36 @@ static int __init probe_qp(void)
        return 1;
 }
 
-int __init qpmouse_init(void)
+static const char msg_banner[] __initdata = KERN_INFO "82C710 type pointing device detected -- driver installed.\n";
+static const char msg_nomem[]  __initdata = KERN_ERR "qpmouse: no queue memory.\n";
+
+static int __init qpmouse_init_driver(void)
 {
        if (!probe_qp())
                return -EIO;
 
-       printk(KERN_INFO "82C710 type pointing device detected -- driver installed.\n");
+       printk(msg_banner);
+
 /*     printk("82C710 address = %x (should be 0x310)\n", qp_data); */
        queue = (struct qp_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
-       if(queue==NULL)
-       {
-               printk(KERN_ERR "qpmouse: no queue memory.\n");
+       if (queue == NULL) {
+               printk(msg_nomem);
                return -ENOMEM;
-       }       
+       }
        qp_present = 1;
        misc_register(&qp_mouse);
        memset(queue, 0, sizeof(*queue));
        queue->head = queue->tail = 0;
        init_waitqueue_head(&queue->proc_list);
-
        return 0;
 }
 
-#ifdef MODULE
-int init_module(void)
-{
-       return qpmouse_init();
-}
-
-void cleanup_module(void)
+static void __exit qpmouse_exit_driver(void)
 {
        misc_deregister(&qp_mouse);
        kfree(queue);
 }
-#endif
+
+module_init(qpmouse_init_driver);
+module_exit(qpmouse_exit_driver);
+
diff --git a/drivers/char/qtronix.c b/drivers/char/qtronix.c
new file mode 100644 (file)
index 0000000..c74aabf
--- /dev/null
@@ -0,0 +1,597 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *     Qtronix 990P infrared keyboard driver.
+ *
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             ppopov@mvista.com or support@mvista.com
+ *
+ *
+ *  The bottom portion of this driver was take from 
+ *  pc_keyb.c  Please see that file for copyrights.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+
+/* 
+ * NOTE:  
+ *
+ *     This driver has only been tested with the Consumer IR
+ *     port of the ITE 8172 system controller.
+ *
+ *     You do not need this driver if you are using the ps/2 or
+ *     USB adapter that the keyboard ships with.  You only need 
+ *     this driver if your board has a IR port and the keyboard
+ *     data is being sent directly to the IR.  In that case,
+ *     you also need some low-level IR support. See it8172_cir.c.
+ *     
+ */
+
+#ifdef CONFIG_QTRONIX_KEYBOARD
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_int.h>
+#include <asm/it8172/it8172_cir.h>
+
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/init.h>
+#include <linux/kbd_ll.h>
+#include <linux/delay.h>
+#include <linux/random.h>
+#include <linux/poll.h>
+#include <linux/miscdevice.h>
+#include <linux/malloc.h>
+#include <linux/kbd_kern.h>
+#include <linux/smp_lock.h>
+#include <asm/io.h>
+#include <linux/pc_keyb.h>
+
+#include <asm/keyboard.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#define leading1 0
+#define leading2 0xF
+
+#define KBD_CIR_PORT 0
+#define AUX_RECONNECT 170 /* scancode when ps2 device is plugged (back) in */
+
+static int data_index;
+struct cir_port *cir;
+static unsigned char kbdbytes[5];
+static unsigned char cir_data[32]; /* we only need 16 chars */
+
+static void kbd_int_handler(int irq, void *dev_id, struct pt_regs *regs);
+static int handle_data(unsigned char *p_data);
+static inline void handle_mouse_event(unsigned char scancode);
+static inline void handle_keyboard_event(unsigned char scancode, int down);
+static int __init psaux_init(void);
+
+static struct aux_queue *queue;        /* Mouse data buffer. */
+static int aux_count = 0;
+
+/*
+ * Keys accessed through the 'Fn' key
+ * The Fn key does not produce a key-up sequence. So, the first
+ * time the user presses it, it will be key-down event. The key
+ * stays down until the user presses it again.
+ */
+#define NUM_FN_KEYS 56
+static unsigned char fn_keys[NUM_FN_KEYS] = {
+       0,0,0,0,0,0,0,0,        /* 0 7   */
+       8,9,10,93,0,0,0,0,      /* 8 15  */
+       0,0,0,0,0,0,0,5,        /* 16 23 */
+       6,7,91,0,0,0,0,0,       /* 24 31 */
+       0,0,0,0,0,2,3,4,        /* 32 39 */
+       92,0,0,0,0,0,0,0,       /* 40 47 */
+       0,0,0,0,11,0,94,95        /* 48 55 */
+
+};
+
+void init_qtronix_990P_kbd(void)
+{
+       int retval;
+
+       cir = (struct cir_port *)kmalloc(sizeof(struct cir_port), GFP_KERNEL);
+       if (!cir) {
+               printk("Unable to initialize Qtronix keyboard\n");
+               return;
+       }
+
+       /* 
+        * revisit
+        * this should be programmable, somehow by the, by the user.
+        */
+       cir->port = KBD_CIR_PORT;
+       cir->baud_rate = 0x1d;
+       cir->rdwos = 0;
+       cir->rxdcr = 0x3;
+       cir->hcfs = 0;
+       cir->fifo_tl = 0;
+       cir->cfq = 0x1d;
+       cir_port_init(cir);
+
+       retval = request_irq(IT8172_CIR0_IRQ, kbd_int_handler, 
+                       (unsigned long )(SA_INTERRUPT|SA_SHIRQ), 
+                       (const char *)"Qtronix IR Keyboard", (void *)cir);
+
+       if (retval) {
+               printk("unable to allocate cir %d irq %d\n", 
+                               cir->port, IT8172_CIR0_IRQ);
+       }
+#ifdef CONFIG_PSMOUSE
+       psaux_init();
+#endif
+}
+
+static inline unsigned char BitReverse(unsigned short key)
+{
+       unsigned char rkey = 0;
+       rkey |= (key & 0x1) << 7;
+       rkey |= (key & 0x2) << 5;
+       rkey |= (key & 0x4) << 3;
+       rkey |= (key & 0x8) << 1;
+       rkey |= (key & 0x10) >> 1;
+       rkey |= (key & 0x20) >> 3;
+       rkey |= (key & 0x40) >> 5;
+       rkey |= (key & 0x80) >> 7;
+       return rkey;
+
+}
+
+
+static inline u_int8_t UpperByte(u_int8_t data)
+{
+       return (data >> 4);
+}
+
+
+static inline u_int8_t LowerByte(u_int8_t data)
+{
+       return (data & 0xF);
+}
+
+
+int CheckSumOk(u_int8_t byte1, u_int8_t byte2, 
+               u_int8_t byte3, u_int8_t byte4, u_int8_t byte5)
+{
+       u_int8_t CheckSum;
+
+       CheckSum = (byte1 & 0x0F) + byte2 + byte3 + byte4 + byte5;
+       if ( LowerByte(UpperByte(CheckSum) + LowerByte(CheckSum)) != UpperByte(byte1) )
+               return 0;
+       else
+               return 1;
+}
+
+
+static void kbd_int_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct cir_port *cir;
+       int j;
+       unsigned char int_status;
+
+       cir = (struct cir_port *)dev_id;
+       int_status = get_int_status(cir);;
+       if (int_status & 0x4) {
+               clear_fifo(cir);
+               return;
+       }
+
+       while (cir_get_rx_count(cir)) {
+
+               cir_data[data_index] = cir_read_data(cir);
+
+               if (data_index == 0) {/* expecting first byte */
+                       if (cir_data[data_index] != leading1) {
+                               //printk("!leading byte %x\n", cir_data[data_index]);
+                               set_rx_active(cir);
+                               clear_fifo(cir);
+                               continue;
+                       }
+               }
+               if (data_index == 1) {
+                       if ((cir_data[data_index] & 0xf) != leading2) {
+                               set_rx_active(cir);
+                               data_index = 0; /* start over */
+                               clear_fifo(cir);
+                               continue;
+                       }
+               }
+
+               if ( (cir_data[data_index] == 0xff)) { /* last byte */
+                       //printk("data_index %d\n", data_index);
+                       set_rx_active(cir);
+#if 0
+                       for (j=0; j<=data_index; j++) {
+                               printk("rx_data %d:  %x\n", j, cir_data[j]);
+                       }
+#endif
+                       data_index = 0;
+                       handle_data(cir_data);
+                       return;
+               }
+               else if (data_index>16) {
+                       set_rx_active(cir);
+#if 0
+                       printk("warning: data_index %d\n", data_index);
+                       for (j=0; j<=data_index; j++) {
+                               printk("rx_data %d:  %x\n", j, cir_data[j]);
+                       }
+#endif
+                       data_index = 0;
+                       clear_fifo(cir);
+                       return;
+               }
+               data_index++;
+       }
+}
+
+
+#define NUM_KBD_BYTES 5
+static int handle_data(unsigned char *p_data)
+{
+       u_int32_t bit_bucket;
+       u_int32_t i, j;
+       u_int32_t got_bits, next_byte;
+       int down = 0;
+
+       /* Reorganize the bit stream */
+       for (i=0; i<16; i++)
+               p_data[i] = BitReverse(~p_data[i]);
+
+       /* 
+        * We've already previously checked that p_data[0]
+        * is equal to leading1 and that (p_data[1] & 0xf)
+        * is equal to leading2. These twelve bits are the
+        * leader code.  We can now throw them away (the 12
+        * bits) and continue parsing the stream.
+        */
+       bit_bucket = p_data[1] << 12;
+       got_bits = 4;
+       next_byte = 2;
+
+       /* 
+        * Process four bits at a time
+        */
+       for (i=0; i<NUM_KBD_BYTES; i++) {
+
+               kbdbytes[i]=0;
+
+               for (j=0; j<8; j++) /* 8 bits per byte */
+               {
+                       if (got_bits < 4) {
+                               bit_bucket |= (p_data[next_byte++] << (8 - got_bits));
+                               got_bits += 8;
+                       }
+
+                       if ((bit_bucket & 0xF000) == 0x8000) { 
+                               /* Convert 1000b to 1 */
+                               kbdbytes[i] = 0x80 | (kbdbytes[i] >> 1);
+                               got_bits -= 4;
+                               bit_bucket = bit_bucket << 4;
+                       }
+                       else if ((bit_bucket & 0xC000) == 0x8000) {
+                               /* Convert 10b to 0 */
+                               kbdbytes[i] =  kbdbytes[i] >> 1;
+                               got_bits -= 2;
+                               bit_bucket = bit_bucket << 2;
+                       }
+                       else {
+                               /* bad serial stream */
+                               return 1;
+                       }
+
+                       if (next_byte > 16) {
+                               //printk("error: too many bytes\n");
+                               return 1;
+                       }
+               }
+       }
+
+
+       if (!CheckSumOk(kbdbytes[0], kbdbytes[1], 
+                               kbdbytes[2], kbdbytes[3], kbdbytes[4])) {
+               //printk("checksum failed\n");
+               return 1;
+       }
+
+       if (kbdbytes[1] & 0x08) {
+               //printk("m: %x %x %x\n", kbdbytes[1], kbdbytes[2], kbdbytes[3]);
+               handle_mouse_event(kbdbytes[1]);
+               handle_mouse_event(kbdbytes[2]);
+               handle_mouse_event(kbdbytes[3]);
+       }
+       else {
+               if (kbdbytes[2] == 0) down = 1;
+#if 0
+               if (down)
+                       printk("down %d\n", kbdbytes[3]);
+               else
+                       printk("up %d\n", kbdbytes[3]);
+#endif
+               handle_keyboard_event(kbdbytes[3], down);
+       }
+       return 0;
+}
+
+
+spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
+static unsigned char handle_kbd_event(void);
+
+
+int pckbd_setkeycode(unsigned int scancode, unsigned int keycode)
+{
+       printk("pckbd_setkeycode scancode %x keycode %x\n", scancode, keycode);
+       return 0;
+}
+
+int pckbd_getkeycode(unsigned int scancode)
+{
+       return scancode;
+}
+
+
+int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+                   char raw_mode)
+{
+       static int prev_scancode = 0;
+
+       if (scancode == 0x00 || scancode == 0xff) {
+               prev_scancode = 0;
+               return 0;
+       }
+
+       /* todo */
+       if (!prev_scancode && scancode == 160) { /* Fn key down */
+               //printk("Fn key down\n");
+               prev_scancode = 160;
+               return 0;
+       }
+       else if (prev_scancode && scancode == 160) { /* Fn key up */
+               //printk("Fn key up\n");
+               prev_scancode = 0;
+               return 0;
+       }
+
+       /* todo */
+       if (prev_scancode == 160) {
+               if (scancode <= NUM_FN_KEYS) {
+                       *keycode = fn_keys[scancode];
+                       //printk("fn keycode %d\n", *keycode);
+               }
+               else
+                       return 0;
+       } 
+       else if (scancode <= 127) {
+               *keycode = scancode;
+       }
+       else
+               return 0;
+
+
+       return 1;
+}
+
+char pckbd_unexpected_up(unsigned char keycode)
+{
+       //printk("pckbd_unexpected_up\n");
+       return 0;
+}
+
+static unsigned char kbd_exists = 1;
+
+static inline void handle_keyboard_event(unsigned char scancode, int down)
+{
+       kbd_exists = 1;
+       handle_scancode(scancode, down);
+       tasklet_schedule(&keyboard_tasklet);
+}      
+
+
+void pckbd_leds(unsigned char leds)
+{
+}
+
+/* dummy */
+void pckbd_init_hw(void)
+{
+}
+
+
+
+static inline void handle_mouse_event(unsigned char scancode)
+{
+       if(scancode == AUX_RECONNECT){
+               queue->head = queue->tail = 0;  /* Flush input queue */
+       //      __aux_write_ack(AUX_ENABLE_DEV);  /* ping the mouse :) */
+               return;
+       }
+
+       add_mouse_randomness(scancode);
+       if (aux_count) {
+               int head = queue->head;
+
+               queue->buf[head] = scancode;
+               head = (head + 1) & (AUX_BUF_SIZE-1);
+               if (head != queue->tail) {
+                       queue->head = head;
+                       kill_fasync(&queue->fasync, SIGIO, POLL_IN);
+                       wake_up_interruptible(&queue->proc_list);
+               }
+       }
+}
+
+static unsigned char get_from_queue(void)
+{
+       unsigned char result;
+       unsigned long flags;
+
+       spin_lock_irqsave(&kbd_controller_lock, flags);
+       result = queue->buf[queue->tail];
+       queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
+       spin_unlock_irqrestore(&kbd_controller_lock, flags);
+       return result;
+}
+
+
+static inline int queue_empty(void)
+{
+       return queue->head == queue->tail;
+}
+
+static int fasync_aux(int fd, struct file *filp, int on)
+{
+       int retval;
+
+       //printk("fasync_aux\n");
+       retval = fasync_helper(fd, filp, on, &queue->fasync);
+       if (retval < 0)
+               return retval;
+       return 0;
+}
+
+
+/*
+ * Random magic cookie for the aux device
+ */
+#define AUX_DEV ((void *)queue)
+
+static int release_aux(struct inode * inode, struct file * file)
+{
+       lock_kernel();
+       fasync_aux(-1, file, 0);
+       aux_count--;
+       unlock_kernel();
+       return 0;
+}
+
+static int open_aux(struct inode * inode, struct file * file)
+{
+       if (aux_count++) {
+               return 0;
+       }
+       queue->head = queue->tail = 0;          /* Flush input queue */
+       return 0;
+}
+
+/*
+ * Put bytes from input queue to buffer.
+ */
+
+static ssize_t read_aux(struct file * file, char * buffer,
+                       size_t count, loff_t *ppos)
+{
+       DECLARE_WAITQUEUE(wait, current);
+       ssize_t i = count;
+       unsigned char c;
+
+       if (queue_empty()) {
+               if (file->f_flags & O_NONBLOCK)
+                       return -EAGAIN;
+               add_wait_queue(&queue->proc_list, &wait);
+repeat:
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (queue_empty() && !signal_pending(current)) {
+                       schedule();
+                       goto repeat;
+               }
+               current->state = TASK_RUNNING;
+               remove_wait_queue(&queue->proc_list, &wait);
+       }
+       while (i > 0 && !queue_empty()) {
+               c = get_from_queue();
+               put_user(c, buffer++);
+               i--;
+       }
+       if (count-i) {
+               file->f_dentry->d_inode->i_atime = CURRENT_TIME;
+               return count-i;
+       }
+       if (signal_pending(current))
+               return -ERESTARTSYS;
+       return 0;
+}
+
+/*
+ * Write to the aux device.
+ */
+
+static ssize_t write_aux(struct file * file, const char * buffer,
+                        size_t count, loff_t *ppos)
+{
+       /*
+        * The ITE boards this was tested on did not have the
+        * transmit wires connected.
+        */
+       return count;
+}
+
+static unsigned int aux_poll(struct file *file, poll_table * wait)
+{
+       poll_wait(file, &queue->proc_list, wait);
+       if (!queue_empty())
+               return POLLIN | POLLRDNORM;
+       return 0;
+}
+
+struct file_operations psaux_fops = {
+       read:           read_aux,
+       write:          write_aux,
+       poll:           aux_poll,
+       open:           open_aux,
+       release:        release_aux,
+       fasync:         fasync_aux,
+};
+
+/*
+ * Initialize driver.
+ */
+static struct miscdevice psaux_mouse = {
+       PSMOUSE_MINOR, "psaux", &psaux_fops
+};
+
+static int __init psaux_init(void)
+{
+       misc_register(&psaux_mouse);
+       queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
+       memset(queue, 0, sizeof(*queue));
+       queue->head = queue->tail = 0;
+       init_waitqueue_head(&queue->proc_list);
+
+       return 0;
+}
+#endif
diff --git a/drivers/char/qtronixmap.map b/drivers/char/qtronixmap.map
new file mode 100644 (file)
index 0000000..8d1ff5c
--- /dev/null
@@ -0,0 +1,287 @@
+# Default kernel keymap. This uses 7 modifier combinations.
+keymaps 0-2,4-5,8,12
+# Change the above line into
+#      keymaps 0-2,4-6,8,12
+# in case you want the entries
+#      altgr   control keycode  83 = Boot            
+#      altgr   control keycode 111 = Boot            
+# below.
+#
+# In fact AltGr is used very little, and one more keymap can
+# be saved by mapping AltGr to Alt (and adapting a few entries):
+# keycode 100 = Alt
+#
+keycode   1 = grave        asciitilde
+       alt     keycode   1 = Meta_Escape     
+keycode   2 = one              exclam          
+       alt     keycode   2 = Meta_one        
+keycode   3 = two              at               at              
+       control keycode   3 = nul             
+       shift   control keycode   3 = nul             
+       alt     keycode   3 = Meta_two        
+keycode   4 = three            numbersign      
+       control keycode   4 = Escape          
+       alt     keycode   4 = Meta_three      
+keycode   5 = four             dollar           dollar          
+       control keycode   5 = Control_backslash
+       alt     keycode   5 = Meta_four       
+keycode   6 = five             percent         
+       control keycode   6 = Control_bracketright
+       alt     keycode   6 = Meta_five       
+keycode   7 = six              asciicircum     
+       control keycode   7 = Control_asciicircum
+       alt     keycode   7 = Meta_six        
+keycode   8 = seven            ampersand        braceleft       
+       control keycode   8 = Control_underscore
+       alt     keycode   8 = Meta_seven      
+keycode   9 = eight            asterisk         bracketleft     
+       control keycode   9 = Delete          
+       alt     keycode   9 = Meta_eight      
+keycode  10 = nine             parenleft        bracketright    
+       alt     keycode  10 = Meta_nine       
+keycode  11 = zero             parenright       braceright      
+       alt     keycode  11 = Meta_zero       
+keycode  12 = minus            underscore       backslash       
+       control keycode  12 = Control_underscore
+       shift   control keycode  12 = Control_underscore
+       alt     keycode  12 = Meta_minus      
+keycode  13 = equal            plus            
+       alt     keycode  13 = Meta_equal      
+keycode  15 = Delete           Delete          
+       control keycode  15 = BackSpace
+       alt     keycode  15 = Meta_Delete     
+keycode  16 = Tab              Tab             
+       alt     keycode  16 = Meta_Tab        
+keycode  17 = q               
+keycode  18 = w               
+keycode  19 = e
+keycode  20 = r               
+keycode  21 = t               
+keycode  22 = y               
+keycode  23 = u         
+keycode  24 = i               
+keycode  25 = o               
+keycode  26 = p               
+keycode  27 = bracketleft      braceleft       
+       control keycode  27 = Escape          
+       alt     keycode  27 = Meta_bracketleft
+keycode  28 = bracketright     braceright
+       control keycode  28 = Control_bracketright
+       alt     keycode  28 = Meta_bracketright
+keycode  29 = backslash        bar             
+       control keycode  29 = Control_backslash
+       alt     keycode  29 = Meta_backslash  
+keycode  30 = Caps_Lock
+keycode  31 = a               
+keycode  32 = s
+keycode  33 = d
+keycode  34 = f               
+keycode  35 = g               
+keycode  36 = h               
+keycode  37 = j               
+keycode  38 = k               
+keycode  39 = l               
+keycode  40 = semicolon        colon           
+       alt     keycode  39 = Meta_semicolon  
+keycode  41 = apostrophe       quotedbl        
+       control keycode  40 = Control_g       
+       alt     keycode  40 = Meta_apostrophe 
+keycode  42 = grave            asciitilde      
+       control keycode  41 = nul             
+       alt     keycode  41 = Meta_grave      
+keycode  43 = Return          
+       alt     keycode  43 = Meta_Control_m  
+keycode  44 = Shift               
+keycode  46 = z
+keycode  47 = x               
+keycode  48 = c
+keycode  49 = v               
+keycode  50 = b               
+keycode  51 = n
+keycode  52 = m
+keycode  53 = comma            less            
+       alt     keycode  51 = Meta_comma      
+keycode  54 = period           greater         
+       control keycode  52 = Compose         
+       alt     keycode  52 = Meta_period     
+keycode  55 = slash            question        
+       control keycode  53 = Delete          
+       alt     keycode  53 = Meta_slash      
+keycode  57 = Shift
+keycode  58 = Control
+keycode  60 = Alt
+keycode  61 = space            space           
+       control keycode  61 = nul             
+       alt     keycode  61 = Meta_space      
+keycode  62 = Alt
+
+keycode 75 = Insert          
+keycode 76 = Delete          
+
+keycode 83 = Up              
+keycode 84 = Down              
+
+keycode 85 = Prior           
+       shift   keycode 85 = Scroll_Backward 
+keycode 86 = Next            
+       shift   keycode 86 = Scroll_Forward  
+keycode 89 = Right           
+       alt     keycode 89 = Incr_Console
+keycode 79 = Left            
+       alt     keycode 79 = Decr_Console
+
+keycode  90 = Num_Lock
+       shift   keycode  90 = Bare_Num_Lock
+
+keycode 91 = minus
+keycode 92 = plus
+keycode 93 = KP_Multiply
+keycode 94 = period
+keycode 95 = KP_Divide
+
+keycode 107 = Select          
+keycode 108 = Down            
+
+keycode 110 = Escape           Escape          
+       alt     keycode   1 = Meta_Escape     
+
+keycode  112 = F1              F11              Console_13      
+       control keycode  112 = F1              
+       alt     keycode  112 = Console_1       
+       control alt     keycode  112 = Console_1       
+keycode  113 = F2              F12              Console_14      
+       control keycode  113 = F2              
+       alt     keycode  113 = Console_2       
+       control alt     keycode  113 = Console_2       
+keycode  114 = F3              F13              Console_15      
+       control keycode  114 = F3              
+       alt     keycode  114 = Console_3       
+       control alt     keycode  114 = Console_3       
+keycode  115 = F4              F14              Console_16      
+       control keycode  115 = F4              
+       alt     keycode  115 = Console_4       
+       control alt     keycode  115 = Console_4       
+keycode  116 = F5              F15              Console_17      
+       control keycode  116 = F5              
+       alt     keycode  116 = Console_5       
+       control alt     keycode  116 = Console_5       
+keycode  117 = F6              F16              Console_18      
+       control keycode  117 = F6              
+       alt     keycode  117 = Console_6       
+       control alt     keycode  117 = Console_6       
+keycode  118 = F7              F17              Console_19      
+       control keycode  118 = F7              
+       alt     keycode  118 = Console_7       
+       control alt     keycode  118 = Console_7       
+keycode  119 = F8              F18              Console_20      
+       control keycode  119 = F8              
+       alt     keycode  119 = Console_8       
+       control alt     keycode  119 = Console_8       
+keycode  120 = F9              F19              Console_21      
+       control keycode  120 = F9              
+       alt     keycode  120 = Console_9       
+       control alt     keycode  120 = Console_9       
+keycode  121 = F10             F20              Console_22      
+       control keycode  121 = F10             
+       alt     keycode  121 = Console_10      
+       control alt     keycode  121 = Console_10      
+       
+keycode 126 = Pause           
+
+
+string F1 = "\033[[A"
+string F2 = "\033[[B"
+string F3 = "\033[[C"
+string F4 = "\033[[D"
+string F5 = "\033[[E"
+string F6 = "\033[17~"
+string F7 = "\033[18~"
+string F8 = "\033[19~"
+string F9 = "\033[20~"
+string F10 = "\033[21~"
+string F11 = "\033[23~"
+string F12 = "\033[24~"
+string F13 = "\033[25~"
+string F14 = "\033[26~"
+string F15 = "\033[28~"
+string F16 = "\033[29~"
+string F17 = "\033[31~"
+string F18 = "\033[32~"
+string F19 = "\033[33~"
+string F20 = "\033[34~"
+string Find = "\033[1~"
+string Insert = "\033[2~"
+string Remove = "\033[3~"
+string Select = "\033[4~"
+string Prior = "\033[5~"
+string Next = "\033[6~"
+string Macro = "\033[M"
+string Pause = "\033[P"
+compose '`' 'A' to 'À'
+compose '`' 'a' to 'à'
+compose '\'' 'A' to 'Á'
+compose '\'' 'a' to 'á'
+compose '^' 'A' to 'Â'
+compose '^' 'a' to 'â'
+compose '~' 'A' to 'Ã'
+compose '~' 'a' to 'ã'
+compose '"' 'A' to 'Ä'
+compose '"' 'a' to 'ä'
+compose 'O' 'A' to 'Å'
+compose 'o' 'a' to 'å'
+compose '0' 'A' to 'Å'
+compose '0' 'a' to 'å'
+compose 'A' 'A' to 'Å'
+compose 'a' 'a' to 'å'
+compose 'A' 'E' to 'Æ'
+compose 'a' 'e' to 'æ'
+compose ',' 'C' to 'Ç'
+compose ',' 'c' to 'ç'
+compose '`' 'E' to 'È'
+compose '`' 'e' to 'è'
+compose '\'' 'E' to 'É'
+compose '\'' 'e' to 'é'
+compose '^' 'E' to 'Ê'
+compose '^' 'e' to 'ê'
+compose '"' 'E' to 'Ë'
+compose '"' 'e' to 'ë'
+compose '`' 'I' to 'Ì'
+compose '`' 'i' to 'ì'
+compose '\'' 'I' to 'Í'
+compose '\'' 'i' to 'í'
+compose '^' 'I' to 'Î'
+compose '^' 'i' to 'î'
+compose '"' 'I' to 'Ï'
+compose '"' 'i' to 'ï'
+compose '-' 'D' to 'Ð'
+compose '-' 'd' to 'ð'
+compose '~' 'N' to 'Ñ'
+compose '~' 'n' to 'ñ'
+compose '`' 'O' to 'Ò'
+compose '`' 'o' to 'ò'
+compose '\'' 'O' to 'Ó'
+compose '\'' 'o' to 'ó'
+compose '^' 'O' to 'Ô'
+compose '^' 'o' to 'ô'
+compose '~' 'O' to 'Õ'
+compose '~' 'o' to 'õ'
+compose '"' 'O' to 'Ö'
+compose '"' 'o' to 'ö'
+compose '/' 'O' to 'Ø'
+compose '/' 'o' to 'ø'
+compose '`' 'U' to 'Ù'
+compose '`' 'u' to 'ù'
+compose '\'' 'U' to 'Ú'
+compose '\'' 'u' to 'ú'
+compose '^' 'U' to 'Û'
+compose '^' 'u' to 'û'
+compose '"' 'U' to 'Ü'
+compose '"' 'u' to 'ü'
+compose '\'' 'Y' to 'Ý'
+compose '\'' 'y' to 'ý'
+compose 'T' 'H' to 'Þ'
+compose 't' 'h' to 'þ'
+compose 's' 's' to 'ß'
+compose '"' 'y' to 'ÿ'
+compose 's' 'z' to 'ß'
+compose 'i' 'j' to 'ÿ'
index 5b1ae92..00c2d3c 100644 (file)
@@ -1031,8 +1031,10 @@ static int rio_init_datastructures (void)
  free2:kfree (p->RIOHosts);
  free1:kfree (p);
  free0:
-  rio_dprintk (RIO_DEBUG_INIT, "Not enough memory! %p %p %p %p %p\n", 
-               p, p->RIOHosts, p->RIOPortp, rio_termios, rio_termios);
+  if (p) {
+       rio_dprintk (RIO_DEBUG_INIT, "Not enough memory! %p %p %p %p %p\n", 
+                      p, p->RIOHosts, p->RIOPortp, rio_termios, rio_termios);
+  }
   return -ENOMEM;
 }
 
index 4a08835..0c9fc09 100644 (file)
@@ -764,7 +764,7 @@ RIO_DEBUG_CTRL,                             if (su)
                                                        PortP->Config &= ~RIO_WAITDRAIN;
                                                }
                                         /*
-                                        ** Store setings if locking or unlocking port or if the
+                                        ** Store settings if locking or unlocking port or if the
                                         ** port is not locked, when setting the store option.
                                         */
                                         if (PortP->Mapped &&
index fc8be29..125c8b2 100644 (file)
@@ -5726,6 +5726,10 @@ static int __init serial_console_setup(struct console *co, char *options)
                case 9600:
                default:
                        cflag |= B9600;
+                       /*
+                        * Set this to a sane value to prevent a divide error
+                        */
+                       baud  = 9600;
                        break;
        }
        switch(bits) {
index c2d5b3a..502cc97 100644 (file)
@@ -37,7 +37,8 @@
 #include <linux/module.h>
 #include <linux/kbd_kern.h>
 
-#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(__alpha__) || defined(__mips__) || defined(CONFIG_SPARC64)
+#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(__alpha__) || \
+    defined(__mips__) || defined(CONFIG_SPARC64) || defined(CONFIG_SUPERH)
 
 static int x86_sysrq_alt = 0;
 #ifdef CONFIG_SPARC64
index 072c7e5..a6d3a13 100644 (file)
@@ -23,7 +23,7 @@ if [ "$CONFIG_RADIO_GEMTEK" = "y" ]; then
 fi
 dep_tristate '  Guillemot MAXI Radio FM 2000 radio' CONFIG_RADIO_MAXIRADIO $CONFIG_VIDEO_DEV
 dep_tristate '  Maestro on board radio' CONFIG_RADIO_MAESTRO $CONFIG_VIDEO_DEV
-dep_tristate '  Miro PCM20 Radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV
+dep_tristate '  miroSOUND PCM20 radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV $CONFIG_SOUND_ACI_MIXER
 dep_tristate '  SF16FMI Radio' CONFIG_RADIO_SF16FMI $CONFIG_VIDEO_DEV
 if [ "$CONFIG_RADIO_SF16FMI" = "y" ]; then
    hex '    SF16FMI I/O port (0x284 or 0x384)' CONFIG_RADIO_SF16FMI_PORT 284
index a6dbc3f..63fb571 100644 (file)
@@ -23,7 +23,9 @@ O_TARGET := radio.o
 
 export-objs     :=     
 
-list-multi     :=      
+list-multi     := miropcm20.o
+
+miropcm20-objs := radio-miropcm20.o rds-miropcm20.o
 
 obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o
 obj-$(CONFIG_RADIO_RTRACK2) += radio-rtrack2.o
@@ -34,9 +36,12 @@ obj-$(CONFIG_RADIO_TERRATEC) += radio-terratec.o
 obj-$(CONFIG_RADIO_MAXIRADIO) += radio-maxiradio.o
 obj-$(CONFIG_RADIO_RTRACK) += radio-aimslab.o
 obj-$(CONFIG_RADIO_ZOLTRIX) += radio-zoltrix.o
-obj-$(CONFIG_RADIO_MIROPCM20) += radio-miropcm20.o
+obj-$(CONFIG_RADIO_MIROPCM20) += miropcm20.o
 obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o
 obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
 obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o
 
 include $(TOPDIR)/Rules.make
+
+miropcm20.o: $(miropcm20-objs)
+       $(LD) -r -o $@ $(miropcm20-objs)
index 171995e..1e86f2f 100644 (file)
@@ -2,62 +2,53 @@
  * (c) 1998 Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
  * Thanks to Norberto Pellici for the ACI device interface specification
  * The API part is based on the radiotrack driver by M. Kirkwood
- * This driver relies on the aci mixer (drivers/sound/lowlevel/aci.c)
+ * This driver relies on the aci mixer (drivers/sound/aci.c)
  * Look there for further info...
  */
 
-#include <linux/module.h>              /* Modules                      */
-#include <linux/init.h>                        /* Initdata                     */
-#include <asm/uaccess.h>               /* copy to/from user            */
-#include <linux/videodev.h>            /* kernel radio structs         */
-#include "../../sound/miroaci.h"       /* ACI Control by acimixer      */
+/* Revision history:
+ *
+ *   1998        Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
+ *   2000-09-05  Robert Siemer <Robert.Siemer@gmx.de>
+ *        removed unfinished volume control (maybe adding it later again)
+ *        use OSS-mixer; added stereo control
+ */
+
+/* What ever you think about the ACI, version 0x07 is not very well!
+ * I cant get frequency, 'tuner status', 'tuner flags' or mute/mono
+ * conditions...                Robert 
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/videodev.h>
+#include <linux/devfs_fs_kernel.h>
+#include <asm/uaccess.h>
+
+char * aci_radio_name;
+
+#include "../../sound/aci.h"
 
 static int users = 0;
 
 struct pcm20_device
 {
-       int port;
-       int curvol;
-       unsigned long curfreq;
+       unsigned long freq;
        int muted;
+       int stereo;
 };
 
 
-/* local things */
-
-
-static void pcm20_mute(struct pcm20_device *dev)
+static int pcm20_mute(struct pcm20_device *dev, unsigned char mute)
 {
-
-       dev->muted = 1;
-       aci_write_cmd(0xa3,0x01);                       
-
+       dev->muted = mute;
+       return aci_write_cmd(0xa3, mute);
 }
 
-static int pcm20_setvol(struct pcm20_device *dev, int vol)
+static int pcm20_stereo(struct pcm20_device *dev, unsigned char stereo)
 {
-
-       if(vol == dev->curvol) {        /* requested volume = current */
-               if (dev->muted) {       /* user is unmuting the card  */
-                       dev->muted = 0;
-                       aci_write_cmd(0xa3,0x00);       /* enable card */
-               }       
-       
-               return 0;
-       }
-
-       if(vol == 0) {                  /* volume = 0 means mute the card */
-               aci_write_cmd(0x3d, 0x20);
-               aci_write_cmd(0x35, 0x20);
-               return 0;
-       }
-
-       dev->muted = 0;
-       aci_write_cmd(0x3d, 32-vol);    /* Right Channel */
-       aci_write_cmd(0x35, 32-vol);    /* Left Channel */
-       dev->curvol = vol;
-
-       return 0;
+       dev->stereo = stereo;
+       return aci_write_cmd(0xa4, !stereo);
 }
 
 static int pcm20_setfreq(struct pcm20_device *dev, unsigned long freq)
@@ -65,28 +56,79 @@ static int pcm20_setfreq(struct pcm20_device *dev, unsigned long freq)
        unsigned char freql;
        unsigned char freqh;
 
-       freq = (freq * 10) / 16;
-       freql = freq & 0xff;
-       freqh = freq >> 8;      
+       dev->freq=freq;
 
+       freq /= 160;
+       if (!(aci_version==0x07 || aci_version>=0xb0))
+               freq /= 10;  /* I don't know exactly which version
+                             * needs this hack */
+       freql = freq & 0xff;
+       freqh = freq >> 8;
 
-       aci_write_cmd_d(0xa7, freql, freqh);    /*  Tune to frequency   */
+       aci_rds_cmd(RDS_RESET, 0, 0);
+       pcm20_stereo(dev, 1);
 
-       return 0;
+       return aci_rw_cmd(0xa7, freql, freqh);  /*  Tune to frequency   */
 }
 
-int pcm20_getsigstr(struct pcm20_device *dev)
+static int pcm20_getflags(struct pcm20_device *dev, __u32 *flags, __u16 *signal)
 {
+       /* okay, check for signal, stereo and rds here... */
+       int i;
        unsigned char buf;
-       aci_indexed_cmd(0xf0, 0x32, &buf);
-       if ((buf & 0x80) == 0x80)       
+
+       if ((i=aci_rw_cmd(0xa9, -1, -1))<0)
+               return i;
+#if DEBUG
+       printk("check_sig: 0x%x\n", i);
+#endif
+       if (i & 0x80) {
+               /* no signal from tuner */
+               *flags=0;
+               *signal=0;
+               return 0;
+       } else
+               *signal=0xffff;
+
+       if ((i=aci_rw_cmd(0xa8, -1, -1))<0)
+               return i;
+       if (i & 0x40) {
+               *flags=0;
+       } else {
+               /* stereo */
+               *flags=VIDEO_TUNER_STEREO_ON;
+               /* I cant see stereo, when forced to mono */
+               dev->stereo=1;
+       }
+
+       if ((i=aci_rds_cmd(RDS_STATUS, &buf, 1))<0)
+               return i;
+       if (buf & 1)
+               /* RDS available */
+               *flags|=VIDEO_TUNER_RDS_ON;
+       else
                return 0;
-       return 1;               /* signal present               */
+
+       if ((i=aci_rds_cmd(RDS_RXVALUE, &buf, 1))<0)
+               return i;
+#if DEBUG
+       printk("rds-signal: %d\n", buf);
+#endif
+       if (buf > 15) {
+               printk("rds-miropcm20: RX strengths unexpected high...\n");
+               buf=15;
+       }
+       /* refine signal */
+       if ((*signal=SCALE(15, 0xffff, buf))==0)
+               *signal = 1;
+
+       return 0;
 }
 
 static int pcm20_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
 {
        struct pcm20_device *pcm20=dev->priv;
+       int i;
        
        switch(cmd)
        {
@@ -113,11 +155,11 @@ static int pcm20_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                                return -EFAULT;
                        if(v.tuner)     /* Only 1 tuner */ 
                                return -EINVAL;
-                       v.rangelow=(int)(87.5*16);
-                       v.rangehigh=(int)(108.0*16);
-                       v.flags=0;
+                       v.rangelow=87*16000;
+                       v.rangehigh=108*16000;
+                       pcm20_getflags(pcm20, &v.flags, &v.signal);
+                       v.flags|=VIDEO_TUNER_LOW;
                        v.mode=VIDEO_MODE_AUTO;
-                       v.signal=0xFFFF*pcm20_getsigstr(pcm20);
                        strcpy(v.name, "FM");
                        if(copy_to_user(arg,&v, sizeof(v)))
                                return -EFAULT;
@@ -134,20 +176,28 @@ static int pcm20_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                        return 0;
                }
                case VIDIOCGFREQ:
-                       if(copy_to_user(arg, &pcm20->curfreq, sizeof(pcm20->curfreq)))
+                       if(copy_to_user(arg, &pcm20->freq, sizeof(pcm20->freq)))
                                return -EFAULT;
                        return 0;
                case VIDIOCSFREQ:
-                       if(copy_from_user(&pcm20->curfreq, arg,sizeof(pcm20->curfreq)))
+                       if(copy_from_user(&pcm20->freq, arg, sizeof(pcm20->freq)))
                                return -EFAULT;
-                       pcm20_setfreq(pcm20, pcm20->curfreq);
-                       return 0;
+                       i=pcm20_setfreq(pcm20, pcm20->freq);
+#if DEBUG
+                       printk("First view (setfreq): 0x%x\n", i);
+#endif
+                       return i;
                case VIDIOCGAUDIO:
                {       
                        struct video_audio v;
                        memset(&v,0, sizeof(v));
-                       v.flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
-                       v.volume=pcm20->curvol * 2048;
+                       v.flags=VIDEO_AUDIO_MUTABLE;
+                       if (pcm20->muted)
+                               v.flags|=VIDEO_AUDIO_MUTE;
+                       v.mode=VIDEO_SOUND_STEREO;
+                       if (pcm20->stereo)
+                               v.mode|=VIDEO_SOUND_MONO;
+                       /* v.step=2048; */
                        strcpy(v.name, "Radio");
                        if(copy_to_user(arg,&v, sizeof(v)))
                                return -EFAULT;
@@ -157,14 +207,15 @@ static int pcm20_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                {
                        struct video_audio v;
                        if(copy_from_user(&v, arg, sizeof(v))) 
-                               return -EFAULT; 
+                               return -EFAULT;
                        if(v.audio) 
                                return -EINVAL;
 
-                       if(v.flags&VIDEO_AUDIO_MUTE) 
-                               pcm20_mute(pcm20);
-                       else
-                               pcm20_setvol(pcm20,v.volume/2048);      
+                       pcm20_mute(pcm20, !!(v.flags&VIDEO_AUDIO_MUTE));
+                       if(v.flags&VIDEO_SOUND_MONO)
+                               pcm20_stereo(pcm20, 0);
+                       if(v.flags&VIDEO_SOUND_STEREO)
+                               pcm20_stereo(pcm20, 1);
 
                        return 0;
                }
@@ -186,7 +237,12 @@ static void pcm20_close(struct video_device *dev)
        users--;
 }
 
-static struct pcm20_device pcm20_unit;
+static struct pcm20_device pcm20_unit=
+{
+       freq:   87*16000,
+       muted:  1,
+       stereo: 0
+};
 
 static struct video_device pcm20_radio=
 {
@@ -197,24 +253,23 @@ static struct video_device pcm20_radio=
        open:           pcm20_open,
        close:          pcm20_close,
        ioctl:          pcm20_ioctl,
+       priv:           &pcm20_unit
 };
 
 static int __init pcm20_init(void)
 {
-
-       pcm20_radio.priv=&pcm20_unit;
-       
        if(video_register_device(&pcm20_radio, VFL_TYPE_RADIO)==-1)
                return -EINVAL;
                
+       if(attach_aci_rds()<0) {
+               video_unregister_device(&pcm20_radio);
+               return -EINVAL;
+       }
+#if DEBUG
+       printk("v4l-name: %s\n", devfs_get_name(pcm20_radio.devfs_handle, 0));
+#endif
        printk(KERN_INFO "Miro PCM20 radio card driver.\n");
 
-       /* mute card - prevents noisy bootups */
-
-       /* this ensures that the volume is all the way down  */
-
-       pcm20_unit.curvol = 0;
-
        return 0;
 }
 
@@ -225,9 +280,9 @@ EXPORT_NO_SYMBOLS;
 
 static void __exit pcm20_cleanup(void)
 {
+       unload_aci_rds();
        video_unregister_device(&pcm20_radio);
 }
 
 module_init(pcm20_init);
 module_exit(pcm20_cleanup);
-
diff --git a/drivers/media/radio/rds-miropcm20.c b/drivers/media/radio/rds-miropcm20.c
new file mode 100644 (file)
index 0000000..821de6f
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ *  Many thanks to Fred Seidel <seidel@metabox.de>, the
+ *  designer of the RDS decoder hardware. With his help
+ *  I was able to code this driver.
+ *  Thanks also to Norberto Pellicci, Dominic Mounteney
+ *  <DMounteney@pinnaclesys.com> and www.teleauskunft.de
+ *  for good hints on finding Fred. It was somewhat hard
+ *  to locate him here in Germany... [:
+ *
+ * Revision history:
+ *
+ *   2000-08-09  Robert Siemer <Robert.Siemer@gmx.de>
+ *        RDS support for MiroSound PCM20 radio
+ */
+
+#define _NO_VERSION_
+
+/* #include <linux/kernel.h> */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <asm/semaphore.h>
+#include <asm/io.h>
+#include "../../sound/aci.h"
+
+#define WATCHMASK       0352 /* 11101010 */
+
+#define DEBUG 0
+
+static struct semaphore aci_rds_sem;
+
+
+#define RDS_BUSYMASK        0x10   /* Bit 4 */
+#define RDS_CLOCKMASK       0x08   /* Bit 3 */
+#define RDS_DATAMASK        0x04   /* Bit 2 */
+
+
+static void print_matrix(char array[], unsigned int length)
+{
+        int i, j;
+
+        for (i=0; i<length; i++) {
+                printk("aci-rds: ");
+                for (j=7; j>=0; j--) {
+                        printk("%d", (array[i] >> j) & 0x1);
+                }
+                if (i%8 == 0)
+                        printk(" byte-border\n");
+                else
+                        printk("\n");
+        }
+}
+
+static int byte2trans(unsigned char byte, unsigned char sendbuffer[], int size)
+{
+       int i;
+
+       if (size != 8)
+               return -1;
+       for (i = 7; i >= 0; i--)
+               sendbuffer[7-i] = (byte & (1 << i)) ? RDS_DATAMASK : 0;
+       sendbuffer[0] |= RDS_CLOCKMASK;
+
+       return 0;
+}
+
+static int trans2byte(unsigned char buffer[], int size)
+{
+       int i;
+       unsigned char byte=0;
+
+       if (size != 8)
+               return -1;
+       for (i = 7; i >= 0; i--)
+               byte |= ((buffer[7-i] & RDS_DATAMASK) ? 1 : 0) << i;
+
+       return byte;
+}
+
+static int trans2data(unsigned char readbuffer[], int readsize, unsigned char data[], int datasize)
+{
+       int i,j;
+
+       if (readsize != datasize*8)
+               return -1;
+       for (i = 0; i < datasize; i++)
+               if ((j=trans2byte(&readbuffer[i*8], 8)) < 0)
+                       return -1;
+               else
+                       data[i]=j;
+       return 0;
+}
+
+static int rds_waitread(void)
+{
+       unsigned char byte;
+       int i=2000;
+
+       do {
+               byte=inb(RDS_REGISTER);
+               if ((byte & WATCHMASK) != WATCHMASK)
+                       printk("aci-rds: Hidden information discoverd!\n");
+               i--;
+       }
+       while ((byte & RDS_BUSYMASK) && i);
+
+       if (i) {
+#if DEBUG
+               printk("rds_waitread()");
+               print_matrix(&byte, 1);
+#endif
+               return (byte);
+       } else {
+               printk("aci-rds: rds_waitread() timeout...\n");
+               return -1;
+       }
+}
+
+/* dont use any ..._nowait() function if you are not sure what you do... */
+
+static inline void rds_rawwrite_nowait(unsigned char byte)
+{
+#if DEBUG
+       printk("rds_rawwrite()");
+       print_matrix(&byte, 1);
+#endif
+       outb(byte, RDS_REGISTER);
+}
+
+static int rds_rawwrite(unsigned char byte)
+{
+       if (rds_waitread() >= 0) {
+               rds_rawwrite_nowait(byte);
+               return 0;
+       } else
+               return -1;
+}
+
+static int rds_write(unsigned char cmd)
+{
+       unsigned char sendbuffer[8];
+       int i;
+       
+       if (byte2trans(cmd, sendbuffer, 8) != 0){
+               return -1;
+       } else {
+               for (i=0; i<8; i++) {
+                       rds_rawwrite(sendbuffer[i]);
+               }
+       }
+       return 0;
+}
+
+static int rds_readcycle_nowait(void)
+{
+       rds_rawwrite_nowait(0);
+       return rds_waitread();
+}
+
+static int rds_readcycle(void)
+{
+       if (rds_rawwrite(0) < 0)
+               return -1;
+       return rds_waitread();
+}
+
+static int rds_read(unsigned char databuffer[], int datasize)
+{
+
+#define READSIZE (8*datasize)
+
+       int i,j;
+       unsigned char* readbuffer;
+
+       if (!datasize)  /* nothing to read */
+               return 0;
+
+       /* to be able to use rds_readcycle_nowait()
+          I have to readwait() here */
+       if (rds_waitread() < 0)
+               return -1;
+       
+       if ((readbuffer=kmalloc(READSIZE, GFP_KERNEL)) == 0) {
+               printk("aci-rds: Out of memory...\n");
+               return -ENOMEM;
+       } else {
+               if (signal_pending(current)) {
+                       kfree(readbuffer);
+                       return -EINTR;
+               }
+       }
+       
+       for (i=0; i< READSIZE; i++)
+               if((j=rds_readcycle_nowait()) < 0) {
+                       kfree(readbuffer);
+                       return -1;
+               } else
+                       readbuffer[i]=j;
+       if (trans2data(readbuffer, READSIZE, databuffer, datasize) < 0) {
+               kfree(readbuffer);
+               return -1;
+       }
+       kfree(readbuffer);
+       return 0;
+}
+
+static int rds_ack(void)
+{
+       int i=rds_readcycle();
+
+       if (i < 0)
+               return -1;
+       if (i & RDS_DATAMASK) {
+               return 0;  /* ACK  */
+       } else {
+               return 1;  /* NACK */
+       }
+}
+
+int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize)
+{
+       int ret;
+
+       if (down_interruptible(&aci_rds_sem))
+               return -EINTR;
+
+       if (rds_write(cmd))
+               ret = -2;
+
+       /* RDS_RESET doesn't need further processing */
+       if (cmd!=RDS_RESET && (rds_ack() || rds_read(databuffer, datasize)))
+               ret = -1;
+       else
+               ret = 0;
+
+       up(&aci_rds_sem);
+       
+       return ret;
+}
+
+int __init attach_aci_rds(void)
+{
+       init_MUTEX(&aci_rds_sem);
+       return 0;
+}
+
+void __exit unload_aci_rds(void)
+{
+}
index a2a7676..0490e40 100644 (file)
@@ -3318,6 +3318,6 @@ static int __init read_eeprom_byte(struct net_device *dev,
 
 /*
  * Local variables:
- * compile-command: "gcc -D__SMP__ -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h   -c -o acenic.o acenic.c"
+ * compile-command: "gcc -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h   -c -o acenic.o acenic.c"
  * End:
  */
index b7bca28..d3384b9 100644 (file)
  *      Director, National Security Agency.
  *
  *      This software may be used and distributed according to the terms
- *      of the GNU Public License, incorporated herein by reference.
+ *      of the GNU General Public License, incorporated herein by reference.
  */
 
-static const char *version = 
-       "ipddp.c:v0.01 8/28/97 Bradford W. Johnson <johns393@maroon.tc.umn.edu>\n";
-
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -39,7 +36,9 @@ static const char *version =
 
 #include "ipddp.h"             /* Our stuff */
 
-static struct ipddp_route *ipddp_route_list = NULL;
+static const char version[] = KERN_INFO "ipddp.c:v0.01 8/28/97 Bradford W. Johnson <johns393@maroon.tc.umn.edu>\n";
+
+static struct ipddp_route *ipddp_route_list;
 
 #ifdef CONFIG_IPDDP_ENCAP
 static int ipddp_mode = IPDDP_ENCAP;
@@ -47,12 +46,6 @@ static int ipddp_mode = IPDDP_ENCAP;
 static int ipddp_mode = IPDDP_DECAP;
 #endif
 
-/* Use 0 for production, 1 for verification, 2 for debug, 3 for verbose debug */
-#ifndef IPDDP_DEBUG
-#define IPDDP_DEBUG 1
-#endif
-static unsigned int ipddp_debug = IPDDP_DEBUG;
-
 /* Index to functions, as function prototypes. */
 static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev);
 static struct net_device_stats *ipddp_get_stats(struct net_device *dev);
@@ -64,12 +57,12 @@ static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 
 static int __init ipddp_init(struct net_device *dev)
 {
-       static unsigned version_printed = 0;
+       static unsigned version_printed;
 
        SET_MODULE_OWNER(dev);
 
-       if (ipddp_debug && version_printed++ == 0)
-                printk("%s", version);
+       if (version_printed++ == 0)
+                printk(version);
 
        /* Let the user now what mode we are in */
        if(ipddp_mode == IPDDP_ENCAP)
@@ -193,25 +186,23 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
 static int ipddp_create(struct ipddp_route *new_rt)
 {
         struct ipddp_route *rt =(struct ipddp_route*) kmalloc(sizeof(*rt), GFP_KERNEL);
-       struct ipddp_route *test;
 
-        if(rt == NULL)
+        if (rt == NULL)
                 return -ENOMEM;
 
         rt->ip = new_rt->ip;
         rt->at = new_rt->at;
         rt->next = NULL;
-        rt->dev = atrtr_get_dev(&rt->at);
-        if(rt->dev == NULL)
-        {
-               kfree(rt);
-                return (-ENETUNREACH);
+        if ((rt->dev = atrtr_get_dev(&rt->at)) == NULL) {
+               kfree(rt);
+                return -ENETUNREACH;
         }
 
-       test = ipddp_find_route(rt);
-       if(test != NULL)
-               return (-EEXIST);
-       
+       if (ipddp_find_route(rt)) {
+               kfree(rt);
+               return -EEXIST;
+       }
+
         rt->next = ipddp_route_list;
         ipddp_route_list = rt;
 
@@ -307,11 +298,16 @@ static int __init ipddp_init_module(void)
 
 static void __exit ipddp_cleanup_module(void)
 {
+        struct ipddp_route *p;
+
        unregister_netdev(&dev_ipddp);
         kfree(dev_ipddp.priv);
 
-       memset(&dev_ipddp, 0, sizeof(dev_ipddp));
-       dev_ipddp.init = ipddp_init;
+        while (ipddp_route_list) {
+                p = ipddp_route_list->next;
+                kfree(ipddp_route_list);
+                ipddp_route_list = p;
+        }
 }
 
 module_init(ipddp_init_module);
index 6da231f..4673614 100644 (file)
                            <mporter@eng.mcd.mot.com>
                           Remove double checking for DEBUG_RX in de4x5_dbg_rx()
                           from report by <geert@linux-m68k.org>
+      0.546  22-Feb-01    Fixes Alpha XP1000 oops.  The srom_search function
+                           was causing a page fault when initializing the
+                           variable 'pb', on a non de4x5 PCI device, in this
+                           case a PCI bridge (DEC chip 21152). The value of
+                           'pb' is now only initialized if a de4x5 chip is
+                           present. 
+                           <france@handhelds.org>  
     =========================================================================
 */
 
-static const char *version = "de4x5.c:V0.545 1999/11/28 davies@maniac.ultranet.com\n";
+static const char *version = "de4x5.c:V0.546 2001/02/22 davies@maniac.ultranet.com\n";
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -2304,12 +2310,12 @@ srom_search(struct pci_dev *dev)
        /* Skip the pci_bus list entry */
        if (list_entry(walk, struct pci_bus, devices) == dev->bus) continue;
 
-       pb = this_dev->bus->number;
        vendor = this_dev->vendor;
        device = this_dev->device << 8;
        if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) continue;
 
        /* Get the chip configuration revision register */
+       pb = this_dev->bus->number;
        pcibios_read_config_dword(pb, this_dev->devfn, PCI_REVISION_ID, &cfrv);
 
        /* Set the device number information */
index 4761d3b..d05bf03 100644 (file)
@@ -597,7 +597,6 @@ de600_rx_intr(struct net_device *dev)
        }
 
        skb = dev_alloc_skb(size+2);
-       restore_flags(flags);
        if (skb == NULL) {
                printk("%s: Couldn't allocate a sk_buff of size %d.\n",
                        dev->name, size);
index 22d5e0c..47262c4 100644 (file)
@@ -690,7 +690,6 @@ static int de620_rx_intr(struct net_device *dev)
                else { /* Yep! Go get it! */
                        skb_reserve(skb,2);     /* Align */
                        skb->dev = dev;
-                       skb->used = 0;
                        /* skb->data points to the start of sk_buff data area */
                        buffer = skb_put(skb,size);
                        /* copy the packet into the buffer */
index 8f77d2a..f3c85f4 100644 (file)
@@ -1818,9 +1818,7 @@ EISA_signature(char *name, s32 eisa_id)
   ManCode[5]='\0';
 
   for (i=0;(*signatures[i] != '\0') && (*name == '\0');i++) {
-    const char * volatile lhs = ManCode;
-    const char * volatile rhs = signatures[i];         /* egcs-1.1.2 bug */
-    if (strstr(lhs, rhs) != NULL) {
+    if (strstr(ManCode, signatures[i]) != NULL) {
       strcpy(name,ManCode);
       status = 1;
     }
diff --git a/drivers/net/gt96100eth.c b/drivers/net/gt96100eth.c
new file mode 100644 (file)
index 0000000..948a318
--- /dev/null
@@ -0,0 +1,1253 @@
+/*
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             stevel@mvista.com or support@mvista.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Ethernet driver for the MIPS GT96100 Advanced Communication Controller.
+ * 
+ */
+
+#ifndef __mips__
+#error This driver only works with MIPS architectures!
+#endif
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+#include "gt96100eth.h"
+
+#ifdef GT96100_DEBUG
+static int gt96100_debug = GT96100_DEBUG;
+#else
+static int gt96100_debug = 3;
+#endif
+
+// prototypes
+static void *dmaalloc(size_t size, dma_addr_t * dma_handle);
+static void dmafree(size_t size, void *vaddr);
+static int gt96100_add_hash_entry(struct net_device *dev,
+                                 unsigned char *addr);
+static void read_mib_counters(struct gt96100_private *gp);
+static int read_MII(struct net_device *dev, u32 reg);
+static int write_MII(struct net_device *dev, u32 reg, u16 data);
+static void dump_MII(struct net_device *dev);
+static void update_stats(struct gt96100_private *gp);
+static void abort(struct net_device *dev, u32 abort_bits);
+static void hard_stop(struct net_device *dev);
+static void enable_ether_irq(struct net_device *dev);
+static void disable_ether_irq(struct net_device *dev);
+static int __init gt96100_probe1(struct net_device *dev, long ioaddr,
+                                int irq, int port_num);
+static int gt96100_init(struct net_device *dev);
+static int gt96100_open(struct net_device *dev);
+static int gt96100_close(struct net_device *dev);
+static int gt96100_tx(struct sk_buff *skb, struct net_device *dev);
+static int gt96100_rx(struct net_device *dev, u32 status);
+static void gt96100_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void gt96100_tx_timeout(struct net_device *dev);
+static void gt96100_set_rx_mode(struct net_device *dev);
+static struct net_device_stats *gt96100_get_stats(struct net_device *dev);
+
+static char version[] __devinitdata =
+    "gt96100eth.c:0.1 stevel@mvista.com\n";
+
+// FIX! Need real Ethernet addresses
+static unsigned char gt96100_station_addr[2][6] __devinitdata =
+    { {0x01, 0x02, 0x03, 0x04, 0x05, 0x06},
+{0x01, 0x02, 0x03, 0x04, 0x05, 0x07}
+};
+
+#define nibswap(x) ((((x) >> 4) & 0x0f) | (((x) << 4) & 0xf0))
+
+#define RUN_AT(x) (jiffies + (x))
+
+// For reading/writing 32-bit words from/to DMA memory
+#define cpu_to_dma32 cpu_to_be32
+#define dma32_to_cpu be32_to_cpu
+
+/*
+ * Base address and interupt of the GT96100 ethernet controllers
+ */
+static struct {
+       unsigned int port;
+       int irq;
+} gt96100_iflist[NUM_INTERFACES] = {
+       {
+       GT96100_ETH0_BASE, GT96100_ETHER0_IRQ}, {
+       GT96100_ETH1_BASE, GT96100_ETHER1_IRQ}
+};
+
+/*
+  DMA memory allocation, derived from pci_alloc_consistent.
+*/
+static void *dmaalloc(size_t size, dma_addr_t * dma_handle)
+{
+       void *ret;
+
+       ret =
+           (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA,
+                                     get_order(size));
+
+       if (ret != NULL) {
+               dma_cache_inv((unsigned long) ret, size);
+               if (dma_handle != NULL)
+                       *dma_handle = virt_to_phys(ret);
+
+               /* bump virtual address up to non-cached area */
+               ret = KSEG1ADDR(ret);
+       }
+
+       return ret;
+}
+
+static void dmafree(size_t size, void *vaddr)
+{
+       vaddr = KSEG0ADDR(vaddr);
+       free_pages((unsigned long) vaddr, get_order(size));
+}
+
+
+static int read_MII(struct net_device *dev, u32 reg)
+{
+       struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+       int timedout = 20;
+       u32 smir = smirOpCode | (gp->phy_addr << smirPhyAdBit) |
+           (reg << smirRegAdBit);
+
+       // wait for last operation to complete
+       while (GT96100_READ(GT96100_ETH_SMI_REG) & smirBusy) {
+               // snooze for 1 msec and check again
+#if 0
+               current->state = TASK_INTERRUPTIBLE;
+               schedule_timeout(10 * HZ / 10000);
+#else
+               mdelay(1);
+#endif
+
+               if (--timedout == 0) {
+                       printk(KERN_ERR "%s: read_MII busy timeout!!\n",
+                              dev->name);
+                       return -1;
+               }
+       }
+
+       GT96100_WRITE(GT96100_ETH_SMI_REG, smir);
+
+       timedout = 20;
+       // wait for read to complete
+       while (!(smir = GT96100_READ(GT96100_ETH_SMI_REG) & smirReadValid)) {
+               // snooze for 1 msec and check again
+#if 0
+               current->state = TASK_INTERRUPTIBLE;
+               schedule_timeout(10 * HZ / 10000);
+#else
+               mdelay(1);
+#endif
+
+               if (--timedout == 0) {
+                       printk(KERN_ERR "%s: read_MII timeout!!\n",
+                              dev->name);
+                       return -1;
+               }
+       }
+
+       return (int) (smir & smirDataMask);
+}
+
+static int write_MII(struct net_device *dev, u32 reg, u16 data)
+{
+       struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+       int timedout = 20;
+       u32 smir =
+           (gp->phy_addr << smirPhyAdBit) | (reg << smirRegAdBit) | data;
+
+       // wait for last operation to complete
+       while (GT96100_READ(GT96100_ETH_SMI_REG) & smirBusy) {
+               // snooze for 1 msec and check again
+#if 0
+               current->state = TASK_INTERRUPTIBLE;
+               schedule_timeout(10 * HZ / 10000);
+#else
+               mdelay(1);
+#endif
+
+               if (--timedout == 0) {
+                       printk(KERN_ERR "%s: write_MII busy timeout!!\n",
+                              dev->name);
+                       return -1;
+               }
+       }
+
+       GT96100_WRITE(GT96100_ETH_SMI_REG, smir);
+       return 0;
+}
+
+
+static void dump_MII(struct net_device *dev)
+{
+       int i, val;
+
+       for (i = 0; i < 7; i++) {
+               if ((val = read_MII(dev, i)) >= 0)
+                       printk("%s: MII Reg %d=%x\n", dev->name, i, val);
+       }
+       for (i = 16; i < 21; i++) {
+               if ((val = read_MII(dev, i)) >= 0)
+                       printk("%s: MII Reg %d=%x\n", dev->name, i, val);
+       }
+}
+
+
+static int
+gt96100_add_hash_entry(struct net_device *dev, unsigned char *addr)
+{
+       struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+       u16 hashResult, stmp;
+       unsigned char ctmp, hash_ea[6];
+       u32 tblEntry, *tblEntryAddr;
+       int i;
+
+       for (i = 0; i < 6; i++) {
+               // nibble swap
+               ctmp = nibswap(addr[i]);
+               // invert every nibble
+               hash_ea[i] = ((ctmp & 1) << 3) | ((ctmp & 8) >> 3) |
+                   ((ctmp & 2) << 1) | ((ctmp & 4) >> 1);
+               hash_ea[i] |= ((ctmp & 0x10) << 3) | ((ctmp & 0x80) >> 3) |
+                   ((ctmp & 0x20) << 1) | ((ctmp & 0x40) >> 1);
+       }
+
+       if (gp->hash_mode == 0) {
+               hashResult = ((u16) hash_ea[0] & 0xfc) << 7;
+               stmp =
+                   ((u16) hash_ea[0] & 0x03) | (((u16) hash_ea[1] & 0x7f)
+                                                << 2);
+               stmp ^=
+                   (((u16) hash_ea[1] >> 7) & 0x01) | ((u16) hash_ea[2] <<
+                                                       1);
+               stmp ^= (u16) hash_ea[3] | (((u16) hash_ea[4] & 1) << 8);
+               hashResult |= stmp;
+       } else {
+               return -1;      // don't support hash mode 1
+       }
+
+       tblEntryAddr =
+           (u32 *) (&gp->hash_table[((u32) hashResult & 0x7ff) << 3]);
+
+       for (i = 0; i < HASH_HOP_NUMBER; i++) {
+               if ((*tblEntryAddr & hteValid)
+                   && !(*tblEntryAddr & hteSkip)) {
+                       // This entry is already occupied, go to next entry
+                       tblEntryAddr += 2;
+               } else {
+                       memset(tblEntryAddr, 0, 8);
+                       tblEntry = hteValid | hteRD;
+                       tblEntry |= (u32) addr[5] << 3;
+                       tblEntry |= (u32) addr[4] << 11;
+                       tblEntry |= (u32) addr[3] << 19;
+                       tblEntry |= ((u32) addr[2] & 0x1f) << 27;
+                       *(tblEntryAddr + 1) = cpu_to_dma32(tblEntry);
+                       tblEntry = ((u32) addr[2] >> 5) & 0x07;
+                       tblEntry |= (u32) addr[1] << 3;
+                       tblEntry |= (u32) addr[0] << 11;
+                       *tblEntryAddr = cpu_to_dma32(tblEntry);
+                       break;
+               }
+       }
+
+       if (i >= HASH_HOP_NUMBER) {
+               printk(KERN_ERR "%s: gt96100_add_hash_entry expired!\n",
+                      dev->name);
+               return -1;      // Couldn't find an unused entry
+       }
+
+       return 0;
+}
+
+
+static void read_mib_counters(struct gt96100_private *gp)
+{
+       u32 *mib_regs = (u32 *) & gp->mib;
+       int i;
+
+       for (i = 0; i < sizeof(mib_counters_t) / sizeof(u32); i++)
+               mib_regs[i] =
+                   GT96100ETH_READ(gp,
+                                   GT96100_ETH_MIB_COUNT_BASE +
+                                   i * sizeof(u32));
+}
+
+
+static void update_stats(struct gt96100_private *gp)
+{
+       mib_counters_t *mib = &gp->mib;
+       struct net_device_stats *stats = &gp->stats;
+
+       read_mib_counters(gp);
+
+       stats->rx_packets = mib->totalFramesReceived;
+       stats->tx_packets = mib->framesSent;
+       stats->rx_bytes = mib->totalByteReceived;
+       stats->tx_bytes = mib->byteSent;
+       stats->rx_errors = mib->totalFramesReceived - mib->framesReceived;
+       //the tx error counters are incremented by the ISR
+       //rx_dropped incremented by gt96100_rx
+       //tx_dropped incremented by gt96100_tx
+       stats->multicast = mib->multicastFramesReceived;
+       // Tx collisions incremented by ISR, so add in MIB Rx collisions
+       stats->collisions += mib->collision + mib->lateCollision;
+       stats->rx_length_errors = mib->oversizeFrames + mib->fragments;
+       // The RxError condition means the Rx DMA encountered a
+       // CPU owned descriptor, which, if things are working as
+       // they should, means the Rx ring has overflowed.
+       stats->rx_over_errors = mib->macRxError;
+       stats->rx_crc_errors = mib->cRCError;
+}
+
+static void abort(struct net_device *dev, u32 abort_bits)
+{
+       struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+       int timedout = 100;     // wait up to 100 msec for hard stop to complete
+
+       if (gt96100_debug > 2)
+               printk(KERN_INFO "%s: abort\n", dev->name);
+
+       // Return if neither Rx or Tx abort bits are set
+       if (!(abort_bits & (sdcmrAR | sdcmrAT)))
+               return;
+
+       // make sure only the Rx/Tx abort bits are set
+       abort_bits &= (sdcmrAR | sdcmrAT);
+
+       spin_lock(&gp->lock);
+
+       // abort any Rx/Tx DMA immediately
+       GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_COMM, abort_bits);
+
+       if (gt96100_debug > 2)
+               printk(KERN_INFO "%s: abort: SDMA comm = %x\n",
+                      dev->name, GT96100ETH_READ(gp,
+                                                 GT96100_ETH_SDMA_COMM));
+
+       // wait for abort to complete
+       while (GT96100ETH_READ(gp, GT96100_ETH_SDMA_COMM) & abort_bits) {
+               // snooze for 20 msec and check again
+#if 0
+               current->state = TASK_INTERRUPTIBLE;
+               schedule_timeout(10 * HZ / 10000);
+#else
+               mdelay(1);
+#endif
+
+               if (--timedout == 0) {
+                       printk(KERN_ERR "%s: abort timeout!!\n",
+                              dev->name);
+                       break;
+               }
+       }
+
+       if (gt96100_debug > 2)
+               printk(KERN_INFO "%s: abort: timedout=%d\n", dev->name,
+                      timedout);
+
+       spin_unlock(&gp->lock);
+}
+
+
+static void hard_stop(struct net_device *dev)
+{
+       struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+
+       if (gt96100_debug > 2)
+               printk(KERN_INFO "%s: hard stop\n", dev->name);
+
+       disable_ether_irq(dev);
+
+       abort(dev, sdcmrAR | sdcmrAT);
+
+       // disable port
+       GT96100ETH_WRITE(gp, GT96100_ETH_PORT_CONFIG, 0);
+}
+
+
+static void enable_ether_irq(struct net_device *dev)
+{
+       struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+       u32 intMask;
+
+       // unmask interrupts
+       GT96100ETH_WRITE(gp, GT96100_ETH_INT_MASK,
+                        icrRxBuffer | icrTxBufferLow | icrTxEndLow |
+                        icrRxError | icrTxErrorLow | icrRxOVR |
+                        icrTxUdr | icrRxBufferQ0 | icrRxErrorQ0 |
+                        icrMIIPhySTC);
+
+       // now route ethernet interrupts to GT Int0 (eth0 and eth1 will be
+       // sharing it).
+       // FIX! The kernel's irq code should do this
+       intMask = GT96100_READ(GT96100_INT0_HIGH_MASK);
+       intMask |= 1 << gp->port_num;
+       GT96100_WRITE(GT96100_INT0_HIGH_MASK, intMask);
+}
+
+static void disable_ether_irq(struct net_device *dev)
+{
+       struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+       u32 intMask;
+
+       // FIX! The kernel's irq code should do this
+       intMask = GT96100_READ(GT96100_INT0_HIGH_MASK);
+       intMask &= ~(1 << gp->port_num);
+       GT96100_WRITE(GT96100_INT0_HIGH_MASK, intMask);
+
+       GT96100ETH_WRITE(gp, GT96100_ETH_INT_MASK, 0);
+}
+
+
+/*
+ * Probe for a GT96100 ethernet controller.
+ */
+int __init gt96100_probe(struct net_device *dev)
+{
+       unsigned int base_addr = dev ? dev->base_addr : 0;
+       int i;
+
+#ifndef CONFIG_MIPS_GT96100ETH
+       return -ENODEV;
+#endif
+
+       if (gt96100_debug > 2)
+               printk(KERN_INFO "%s: gt96100_probe\n", dev->name);
+
+       if (base_addr >= KSEG0) /* Check a single specified location. */
+               return gt96100_probe1(dev, base_addr, dev->irq, 0);
+       else if (base_addr != 0)        /* Don't probe at all. */
+               return -ENXIO;
+
+//     for (i = 0; i<NUM_INTERFACES; i++) {
+       for (i = NUM_INTERFACES - 1; i >= 0; i--) {
+               int base_addr = gt96100_iflist[i].port;
+#if 0
+               if (check_region(base_addr, GT96100_ETH_IO_SIZE)) {
+                       printk(KERN_ERR
+                              "%s: gt96100_probe: ioaddr 0x%lx taken?\n",
+                              dev->name, base_addr);
+                       continue;
+               }
+#endif
+               if (gt96100_probe1
+                   (dev, base_addr, gt96100_iflist[i].irq, i) == 0)
+                       return 0;
+       }
+       return -ENODEV;
+}
+
+
+
+static int __init
+gt96100_probe1(struct net_device *dev, long ioaddr, int irq, int port_num)
+{
+       static unsigned version_printed = 0;
+       struct gt96100_private *gp = NULL;
+       int i, retval;
+       u32 cpuConfig;
+
+       // FIX! probe for GT96100 by reading a suitable register
+
+       if (gt96100_debug > 2)
+               printk(KERN_INFO "gt96100_probe1: ioaddr 0x%lx, irq %d\n",
+                      ioaddr, irq);
+
+       request_region(ioaddr, GT96100_ETH_IO_SIZE, "GT96100ETH");
+
+       cpuConfig = GT96100_READ(GT96100_CPU_INTERF_CONFIG);
+       if (cpuConfig & (1 << 12)) {
+               printk(KERN_ERR
+                      "gt96100_probe1: must be in Big Endian mode!\n");
+               retval = -ENODEV;
+               goto free_region;
+       }
+
+       if (gt96100_debug > 2)
+               printk(KERN_INFO
+                      "gt96100_probe1: chip in Big Endian mode - cool\n");
+
+       /* Allocate a new 'dev' if needed. */
+       if (dev == NULL)
+               dev = init_etherdev(0, sizeof(struct gt96100_private));
+
+       if (gt96100_debug && version_printed++ == 0)
+               printk(version);
+
+       if (irq < 0) {
+               printk(KERN_ERR
+                      "gt96100_probe1: irq unknown - probing not supported\n");
+               retval = -ENODEV;
+               goto free_region;
+       }
+
+       printk(KERN_INFO "%s: GT-96100 ethernet found at 0x%lx, irq %d\n",
+              dev->name, ioaddr, irq);
+
+       /* private struct aligned and zeroed by init_etherdev */
+       /* Fill in the 'dev' fields. */
+       dev->base_addr = ioaddr;
+       dev->irq = irq;
+       memcpy(dev->dev_addr, gt96100_station_addr[port_num],
+              sizeof(dev->dev_addr));
+
+       printk(KERN_INFO "%s: HW Address ", dev->name);
+       for (i = 0; i < sizeof(dev->dev_addr); i++) {
+               printk("%2.2x", dev->dev_addr[i]);
+               printk(i < 5 ? ":" : "\n");
+       }
+
+       /* Initialize our private structure. */
+       if (dev->priv == NULL) {
+
+               gp =
+                   (struct gt96100_private *) kmalloc(sizeof(*gp),
+                                                      GFP_KERNEL);
+               if (gp == NULL) {
+                       retval = -ENOMEM;
+                       goto free_region;
+               }
+
+               dev->priv = gp;
+       }
+
+       gp = dev->priv;
+
+       memset(gp, 0, sizeof(*gp));     // clear it
+
+       gp->port_num = port_num;
+       gp->io_size = GT96100_ETH_IO_SIZE;
+       gp->port_offset = port_num * GT96100_ETH_IO_SIZE;
+       gp->phy_addr = port_num + 1;
+
+       if (gt96100_debug > 2)
+               printk(KERN_INFO "%s: gt96100_probe1, port %d\n",
+                      dev->name, gp->port_num);
+
+       // Allocate Rx and Tx descriptor rings
+       if (gp->rx_ring == NULL) {
+               // All descriptors in ring must be 16-byte aligned
+               gp->rx_ring = dmaalloc(sizeof(gt96100_rd_t) * RX_RING_SIZE
+                                      +
+                                      sizeof(gt96100_td_t) * TX_RING_SIZE,
+                                      &gp->rx_ring_dma);
+               if (gp->rx_ring == NULL) {
+                       retval = -ENOMEM;
+                       goto free_region;
+               }
+
+               gp->tx_ring =
+                   (gt96100_td_t *) (gp->rx_ring + RX_RING_SIZE);
+               gp->tx_ring_dma =
+                   gp->rx_ring_dma + sizeof(gt96100_rd_t) * RX_RING_SIZE;
+       }
+
+       if (gt96100_debug > 2)
+               printk(KERN_INFO
+                      "%s: gt96100_probe1, rx_ring=%p, tx_ring=%p\n",
+                      dev->name, gp->rx_ring, gp->tx_ring);
+
+       // Allocate Rx Hash Table
+       if (gp->hash_table == NULL) {
+               gp->hash_table = (char *) dmaalloc(RX_HASH_TABLE_SIZE,
+                                                  &gp->hash_table_dma);
+               if (gp->hash_table == NULL) {
+                       dmafree(sizeof(gt96100_rd_t) * RX_RING_SIZE
+                               + sizeof(gt96100_td_t) * TX_RING_SIZE,
+                               gp->rx_ring);
+                       retval = -ENOMEM;
+                       goto free_region;
+               }
+       }
+
+       if (gt96100_debug > 2)
+               printk(KERN_INFO "%s: gt96100_probe1, hash=%p\n",
+                      dev->name, gp->hash_table);
+
+       spin_lock_init(&gp->lock);
+
+       dev->open = gt96100_open;
+       dev->hard_start_xmit = gt96100_tx;
+       dev->stop = gt96100_close;
+       dev->get_stats = gt96100_get_stats;
+       //dev->do_ioctl = gt96100_ioctl;
+       dev->set_multicast_list = gt96100_set_rx_mode;
+       dev->tx_timeout = gt96100_tx_timeout;
+       dev->watchdog_timeo = GT96100ETH_TX_TIMEOUT;
+
+       /* Fill in the fields of the device structure with ethernet values. */
+       ether_setup(dev);
+       return 0;
+
+      free_region:
+       release_region(ioaddr, gp->io_size);
+       unregister_netdev(dev);
+       if (dev->priv != NULL)
+               kfree(dev->priv);
+       kfree(dev);
+       printk(KERN_ERR "%s: gt96100_probe1 failed.  Returns %d\n",
+              dev->name, retval);
+       return retval;
+}
+
+
+static int gt96100_init(struct net_device *dev)
+{
+       struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+       unsigned long flags;
+       u32 phyAD, ciu;
+       int i;
+
+       if (gt96100_debug > 2)
+               printk("%s: gt96100_init: dev=%p\n", dev->name, dev);
+
+       // Stop and disable Port
+       hard_stop(dev);
+
+       spin_lock_irqsave(&gp->lock, flags);
+
+       // First things first, set-up hash table
+       memset(gp->hash_table, 0, RX_HASH_TABLE_SIZE);  // clear it
+       gp->hash_mode = 0;
+       // Add a single entry to hash table - our ethernet address
+       gt96100_add_hash_entry(dev, dev->dev_addr);
+       // Set-up DMA ptr to hash table
+       GT96100ETH_WRITE(gp, GT96100_ETH_HASH_TBL_PTR, gp->hash_table_dma);
+       if (gt96100_debug > 2)
+               printk("%s: gt96100_init: Hash Tbl Ptr=%x\n", dev->name,
+                      GT96100ETH_READ(gp, GT96100_ETH_HASH_TBL_PTR));
+
+       // Setup Tx descriptor ring
+       for (i = 0; i < TX_RING_SIZE; i++) {
+               gp->tx_ring[i].cmdstat = 0;     // CPU owns
+               gp->tx_ring[i].byte_cnt = 0;
+               gp->tx_ring[i].buff_ptr = 0;
+               gp->tx_ring[i].next =
+                   cpu_to_dma32(gp->tx_ring_dma +
+                                sizeof(gt96100_td_t) * (i + 1));
+       }
+       /* Wrap the ring. */
+       gp->tx_ring[i - 1].next = cpu_to_dma32(gp->tx_ring_dma);
+
+       // setup only the lowest priority TxCDP reg
+       GT96100ETH_WRITE(gp, GT96100_ETH_CURR_TX_DESC_PTR0,
+                        gp->tx_ring_dma);
+       GT96100ETH_WRITE(gp, GT96100_ETH_CURR_TX_DESC_PTR1, 0);
+       if (gt96100_debug > 2)
+               printk("%s: gt96100_init: Curr Tx Desc Ptr0=%x\n",
+                      dev->name, GT96100ETH_READ(gp,
+                                                 GT96100_ETH_CURR_TX_DESC_PTR0));
+
+       // Setup Rx descriptor ring 
+       for (i = 0; i < RX_RING_SIZE; i++) {
+               dma_addr_t rx_buff_dma;
+               gp->rx_ring[i].next =
+                   cpu_to_dma32(gp->rx_ring_dma +
+                                sizeof(gt96100_rd_t) * (i + 1));
+               if (gp->rx_buff[i] == NULL)
+                       gp->rx_buff[i] =
+                           dmaalloc(PKT_BUF_SZ, &rx_buff_dma);
+               else
+                       rx_buff_dma = virt_to_phys(gp->rx_buff[i]);
+               if (gp->rx_buff[i] == NULL)
+                       break;
+               gp->rx_ring[i].buff_ptr = cpu_to_dma32(rx_buff_dma);
+               gp->rx_ring[i].buff_cnt_sz =
+                   cpu_to_dma32(PKT_BUF_SZ << rdBuffSzBit);
+               // Give ownership to device, enable interrupt
+               gp->rx_ring[i].cmdstat =
+                   cpu_to_dma32((u32) (rxOwn | rxEI));
+       }
+
+       if (i != RX_RING_SIZE) {
+               int j;
+               for (j = 0; j < RX_RING_SIZE; j++) {
+                       if (gp->rx_buff[j]) {
+                               dmafree(PKT_BUF_SZ, gp->rx_buff[j]);
+                               gp->rx_buff[j] = NULL;
+                       }
+               }
+               printk(KERN_ERR "%s: Rx ring allocation failed.\n",
+                      dev->name);
+               spin_unlock_irqrestore(&gp->lock, flags);
+               return -ENOMEM;
+       }
+
+       /* Wrap the ring. */
+       gp->rx_ring[i - 1].next = cpu_to_dma32(gp->rx_ring_dma);
+
+       // Set our MII PHY device address
+       phyAD = GT96100_READ(GT96100_ETH_PHY_ADDR_REG);
+       phyAD &= ~(0x1f << (gp->port_num * 5));
+       phyAD |= gp->phy_addr << (gp->port_num * 5);
+       GT96100_WRITE(GT96100_ETH_PHY_ADDR_REG, phyAD);
+
+       if (gt96100_debug > 2)
+               printk("%s: gt96100_init: PhyAD=%x\n", dev->name,
+                      GT96100_READ(GT96100_ETH_PHY_ADDR_REG));
+
+       // Clear all the RxFDP and RXCDP regs...
+       for (i = 0; i < 4; i++) {
+               GT96100ETH_WRITE(gp, GT96100_ETH_1ST_RX_DESC_PTR0 + i * 4,
+                                0);
+               GT96100ETH_WRITE(gp, GT96100_ETH_CURR_RX_DESC_PTR0 + i * 4,
+                                0);
+       }
+       // and setup only the lowest priority RxFDP and RxCDP regs
+       GT96100ETH_WRITE(gp, GT96100_ETH_1ST_RX_DESC_PTR0,
+                        gp->rx_ring_dma);
+       GT96100ETH_WRITE(gp, GT96100_ETH_CURR_RX_DESC_PTR0,
+                        gp->rx_ring_dma);
+       if (gt96100_debug > 2)
+               printk("%s: gt96100_init: 1st/Curr Rx Desc Ptr0=%x/%x\n",
+                      dev->name, GT96100ETH_READ(gp,
+                                                 GT96100_ETH_1ST_RX_DESC_PTR0),
+                      GT96100ETH_READ(gp, GT96100_ETH_CURR_RX_DESC_PTR0));
+
+       // init Rx/Tx indeces and pkt counters
+       gp->rx_next_out = gp->tx_next_in = gp->tx_next_out = 0;
+       gp->tx_count = 0;
+
+       // setup DMA
+
+       // FIX! this should be done by Kernel setup code
+       ciu = GT96100_READ(GT96100_CIU_ARBITER_CONFIG);
+       ciu |= (0x0c << (gp->port_num * 2));    // set Ether DMA req priority to high
+       // FIX! setting the following bit causes the EV96100 board to hang!!!
+       //ciu |= (1 << (24+gp->port_num));   // pull Ethernet port out of Reset???
+       // FIX! endian mode???
+       ciu &= ~(1 << 31);      // set desc endianess to Big
+       GT96100_WRITE(GT96100_CIU_ARBITER_CONFIG, ciu);
+       if (gt96100_debug > 2)
+               printk("%s: gt96100_init: CIU Config=%x/%x\n", dev->name,
+                      ciu, GT96100_READ(GT96100_CIU_ARBITER_CONFIG));
+
+       // We want the Rx/Tx DMA to write/read data to/from memory in
+       // Big Endian mode. Also set DMA Burst Size to 8 64Bit words.
+       // FIX! endian mode???
+       GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_CONFIG,
+                        //sdcrBLMR | sdcrBLMT |
+                        (0xf << sdcrRCBit) | sdcrRIFB | (3 << sdcrBSZBit));
+       if (gt96100_debug > 2)
+               printk("%s: gt96100_init: SDMA Config=%x\n", dev->name,
+                      GT96100ETH_READ(gp, GT96100_ETH_SDMA_CONFIG));
+
+       // start Rx DMA
+       GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_COMM, sdcmrERD);
+       if (gt96100_debug > 2)
+               printk("%s: gt96100_init: SDMA Comm=%x\n", dev->name,
+                      GT96100ETH_READ(gp, GT96100_ETH_SDMA_COMM));
+
+       // enable interrupts
+       enable_ether_irq(dev);
+
+       /*
+        * Disable all Type-of-Service queueing. All Rx packets will be
+        * treated normally and will be sent to the lowest priority
+        * queue.
+        *
+        * Disable flow-control for now. FIX! support flow control?
+        */
+       // clear all the MIB ctr regs
+       // Enable reg clear on read. FIX! desc of this bit is inconsistent
+       // in the GT-96100A datasheet.
+       GT96100ETH_WRITE(gp, GT96100_ETH_PORT_CONFIG_EXT,
+                        pcxrFCTL | pcxrFCTLen | pcxrFLP);
+       read_mib_counters(gp);
+       GT96100ETH_WRITE(gp, GT96100_ETH_PORT_CONFIG_EXT,
+                        pcxrFCTL | pcxrFCTLen | pcxrFLP | pcxrMIBclrMode);
+
+       if (gt96100_debug > 2)
+               printk("%s: gt96100_init: Port Config Ext=%x\n", dev->name,
+                      GT96100ETH_READ(gp, GT96100_ETH_PORT_CONFIG_EXT));
+
+       // enable this port (set hash size to 1/2K)
+       GT96100ETH_WRITE(gp, GT96100_ETH_PORT_CONFIG, pcrEN | pcrHS);
+       if (gt96100_debug > 2)
+               printk("%s: gt96100_init: Port Config=%x\n", dev->name,
+                      GT96100ETH_READ(gp, GT96100_ETH_PORT_CONFIG));
+
+       // we should now be receiving frames
+       if (gt96100_debug > 2)
+               dump_MII(dev);
+
+       spin_unlock_irqrestore(&gp->lock, flags);
+       return 0;
+}
+
+
+static int gt96100_open(struct net_device *dev)
+{
+       int retval;
+
+       MOD_INC_USE_COUNT;
+
+       if (gt96100_debug > 2)
+               printk("%s: gt96100_open: dev=%p\n", dev->name, dev);
+
+       if ((retval = request_irq(dev->irq, &gt96100_interrupt,
+                                 SA_SHIRQ, dev->name, dev))) {
+               printk(KERN_ERR "%s: unable to get IRQ %d\n", dev->name,
+                      dev->irq);
+               MOD_DEC_USE_COUNT;
+               return retval;
+       }
+       // Initialize and startup the GT-96100 ethernet port
+       if ((retval = gt96100_init(dev))) {
+               printk(KERN_ERR "%s: error in gt96100_init\n", dev->name);
+               free_irq(dev->irq, dev);
+               MOD_DEC_USE_COUNT;
+               return retval;
+       }
+
+       netif_start_queue(dev);
+
+       if (gt96100_debug > 2)
+               printk("%s: gt96100_open: Initialization done.\n",
+                      dev->name);
+
+       return 0;
+}
+
+static int gt96100_close(struct net_device *dev)
+{
+       struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+       int i;
+
+       if (gt96100_debug > 2)
+               printk("%s: gt96100_close: dev=%p\n", dev->name, dev);
+
+       // stop the device
+       if (netif_device_present(dev)) {
+               netif_stop_queue(dev);
+               hard_stop(dev);
+       }
+       // free the Rx DMA buffers
+       for (i = 0; i < RX_RING_SIZE; i++) {
+               if (gp->rx_buff[i]) {
+                       dmafree(PKT_BUF_SZ, gp->rx_buff[i]);
+                       gp->rx_buff[i] = NULL;
+               }
+       }
+
+       free_irq(dev->irq, dev);
+
+       MOD_DEC_USE_COUNT;
+       return 0;
+}
+
+
+static int gt96100_tx(struct sk_buff *skb, struct net_device *dev)
+{
+       struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+       unsigned long flags;
+       int nextIn;
+
+       if (gt96100_debug > 2)
+               printk("%s: gt96100_tx: skb->len=%d, skb->data=%p\n",
+                      dev->name, skb->len, skb->data);
+
+       spin_lock_irqsave(&gp->lock, flags);
+
+       if (gp->tx_count >= TX_RING_SIZE) {
+               printk(KERN_WARNING
+                      "%s: Tx Ring full, refusing to send buffer.\n",
+                      dev->name);
+               gp->stats.tx_dropped++;
+               spin_unlock_irqrestore(&gp->lock, flags);
+               return 1;
+       }
+       // Prepare the Descriptor at tx_next_in
+       nextIn = gp->tx_next_in;
+
+       if (dma32_to_cpu(gp->tx_ring[nextIn].cmdstat) & txOwn) {
+               printk(KERN_ERR "%s: gt96100_tx: TxOwn bit wrong!!\n",
+                      dev->name);
+       }
+
+       gp->tx_skbuff[nextIn] = skb;
+       gp->tx_ring[nextIn].byte_cnt =
+           cpu_to_dma32(skb->len << tdByteCntBit);
+       gp->tx_ring[nextIn].buff_ptr =
+           cpu_to_dma32(virt_to_phys(skb->data));
+       // Give ownership to device, set first and last desc, enable interrupt
+       // Setting of ownership bit must be *last*!
+       gp->tx_ring[nextIn].cmdstat =
+           cpu_to_dma32((u32) (txOwn | txEI | txFirst | txLast));
+
+       // increment tx_next_in with wrap
+       gp->tx_next_in = (nextIn + 1) % TX_RING_SIZE;
+       // If count is zero, DMA should be stopped, so restart
+       if (gp->tx_count == 0) {
+               if (GT96100ETH_READ(gp, GT96100_ETH_PORT_STATUS) &
+                   psrTxLow) printk(KERN_WARNING
+                                    "%s: Tx count zero but Tx queue running!\n",
+                                    dev->name);
+               GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_COMM,
+                                sdcmrERD | sdcmrTXDL);
+       }
+       // increment count and stop queue if full
+       if (++gp->tx_count == TX_RING_SIZE)
+               netif_stop_queue(dev);
+
+       dev->trans_start = jiffies;
+       spin_unlock_irqrestore(&gp->lock, flags);
+
+       return 0;
+}
+
+
+static int gt96100_rx(struct net_device *dev, u32 status)
+{
+       struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+       struct sk_buff *skb;
+       int pkt_len, nextOut;
+       gt96100_rd_t *rd;
+       u32 cmdstat;
+
+       if (gt96100_debug > 2)
+               printk("%s: gt96100_rx: dev=%p, status = %x\n",
+                      dev->name, dev, status);
+
+       // Continue until we reach the current descriptor pointer
+       for (nextOut = gp->rx_next_out;
+            nextOut !=
+            (GT96100ETH_READ(gp, GT96100_ETH_CURR_RX_DESC_PTR0) -
+             gp->rx_ring_dma) / sizeof(gt96100_rd_t);
+            nextOut = (nextOut + 1) % RX_RING_SIZE) {
+
+               rd = &gp->rx_ring[nextOut];
+               cmdstat = dma32_to_cpu(rd->cmdstat);
+
+               if (cmdstat & (u32) rxOwn) {
+                       cmdstat &= ~((u32) rxOwn);
+                       rd->cmdstat = cpu_to_dma32(cmdstat);
+                       printk(KERN_ERR
+                              "%s: gt96100_rx: ownership bit wrong!\n",
+                              dev->name);
+               }
+               // must be first and last (ie only) buffer of packet
+               if (!(cmdstat & (u32) rxFirst)
+                   || !(cmdstat & (u32) rxLast)) {
+                       printk(KERN_ERR
+                              "%s: gt96100_rx: desc not first and last!\n",
+                              dev->name);
+                       continue;
+               }
+               // drop this received pkt if there were any errors
+               if ((cmdstat & (u32) rxErrorSummary)
+                   || (status & icrRxErrorQ0)) {
+                       // update the detailed rx error counters that are not covered
+                       // by the MIB counters.
+                       if (cmdstat & (u32) rxOverrun)
+                               gp->stats.rx_fifo_errors++;
+                       continue;
+               }
+
+               pkt_len = dma32_to_cpu(rd->buff_cnt_sz) & rdByteCntMask;
+
+               /* Create new skb. */
+               skb = dev_alloc_skb(pkt_len + 2);
+               if (skb == NULL) {
+                       printk(KERN_ERR
+                              "%s: Memory squeeze, dropping packet.\n",
+                              dev->name);
+                       gp->stats.rx_dropped++;
+                       continue;
+               }
+               skb->dev = dev;
+               skb_reserve(skb, 2);    /* 16 byte IP header align */
+               skb_put(skb, pkt_len);  /* Make room */
+               eth_copy_and_sum(skb, gp->rx_buff[nextOut], pkt_len, 0);
+               skb->protocol = eth_type_trans(skb, dev);
+               netif_rx(skb);  /* pass the packet to upper layers */
+
+               // now we can release ownership of this desc back to device
+               cmdstat |= (u32) rxOwn;
+               rd->cmdstat = cpu_to_dma32(cmdstat);
+
+               dev->last_rx = jiffies;
+       }
+
+       gp->rx_next_out = nextOut;
+       return 0;
+}
+
+
+static void gt96100_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *) dev_id;
+       struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+       u32 status;
+
+       if (dev == NULL) {
+               printk(KERN_ERR "%s: isr: null dev ptr\n", dev->name);
+               return;
+       }
+
+       status = GT96100ETH_READ(gp, GT96100_ETH_INT_CAUSE);
+       // ACK interrupts
+#if 0
+       GT96100ETH_CLRBIT(gp, GT96100_ETH_INT_CAUSE,
+                         icrEtherIntSum | icrRxBufferQ1 | icrRxBufferQ2 |
+                         icrRxBufferQ3 | icrRxBufferQ0 | icrTxBufferHigh |
+                         icrTxEndHigh | icrTxBufferLow | icrTxEndLow |
+                         icrTxErrorHigh | icrTxErrorLow | icrTxUdr);
+#else
+       GT96100ETH_WRITE(gp, GT96100_ETH_INT_CAUSE, 0);
+#endif
+
+       if ((status & icrEtherIntSum) == 0) {
+               // not our interrupt
+               //printk("%s: isr: no ints? icr=%x,cp0_cause=%x\n",
+               //       dev->name, status, read_32bit_cp0_register(CP0_CAUSE));
+               return;
+       }
+
+       if (gt96100_debug > 3)
+               printk("%s: isr: entry, icr=%x\n", dev->name, status);
+
+       if (status & (icrRxBufferQ1 | icrRxBufferQ2 | icrRxBufferQ3)) {
+               printk(KERN_ERR "%s: isr: Rx intr in unused queues!?\n",
+                      dev->name);
+       }
+
+       if (status & icrRxBufferQ0) {
+               gt96100_rx(dev, status);
+       }
+
+       if (status & (icrTxBufferHigh | icrTxEndHigh)) {
+               printk(KERN_ERR "%s: isr: Tx intr in unused queue!?\n",
+                      dev->name);
+       }
+
+       if (status & icrMIIPhySTC) {
+               u32 psr = GT96100ETH_READ(gp, GT96100_ETH_PORT_STATUS);
+               printk("%s: port status:\n", dev->name);
+               printk
+                   ("%s:     %s MBit/s, %s-duplex, flow-control %s, link is %s,\n",
+                    dev->name, psr & psrSpeed ? "100" : "10",
+                    psr & psrDuplex ? "full" : "half",
+                    psr & psrFctl ? "disabled" : "enabled",
+                    psr & psrLink ? "up" : "down");
+               printk
+                   ("%s:     TxLowQ is %s, TxHighQ is %s, Transmitter is %s\n",
+                    dev->name, psr & psrTxLow ? "running" : "stopped",
+                    psr & psrTxHigh ? "running" : "stopped",
+                    psr & psrTxInProg ? "on" : "off");
+               gp->last_psr = psr;
+       }
+
+       if (status & (icrTxBufferLow | icrTxEndLow)) {
+               int nextOut;
+               gt96100_td_t *td;
+               u32 cmdstat;
+
+               // Continue until we reach the current descriptor pointer
+               for (nextOut = gp->tx_next_out;
+                    nextOut !=
+                    (GT96100ETH_READ(gp, GT96100_ETH_CURR_TX_DESC_PTR0) -
+                     gp->tx_ring_dma) / sizeof(gt96100_td_t);
+                    nextOut = (nextOut + 1) % TX_RING_SIZE) {
+
+                       td = &gp->tx_ring[nextOut];
+                       cmdstat = dma32_to_cpu(td->cmdstat);
+
+                       if (gt96100_debug > 2)
+                               printk("%s: isr: Tx desc cmdstat=%x\n",
+                                      dev->name, cmdstat);
+
+                       if (cmdstat & (u32) txOwn) {
+                               cmdstat &= ~((u32) txOwn);
+                               td->cmdstat = cpu_to_dma32(cmdstat);
+                               printk(KERN_ERR
+                                      "%s: isr: Tx ownership bit wrong!\n",
+                                      dev->name);
+                       }
+                       // increment Tx error stats
+                       if (cmdstat & (u32) txErrorSummary) {
+                               if (gt96100_debug > 2)
+                                       printk
+                                           ("%s: gt96100_interrupt: Tx error, cmdstat = %x\n",
+                                            dev->name, cmdstat);
+                               gp->stats.tx_errors++;
+                               if (cmdstat & (u32) txReTxLimit)
+                                       gp->stats.collisions++;
+                               if (cmdstat & (u32) txUnderrun)
+                                       gp->stats.tx_fifo_errors++;
+                               if (cmdstat & (u32) txLateCollision)
+                                       gp->stats.tx_window_errors++;
+                       }
+                       // Wake the queue if the ring was full
+                       if (gp->tx_count == TX_RING_SIZE)
+                               netif_wake_queue(dev);
+
+                       // decrement tx ring buffer count
+                       if (gp->tx_count)
+                               gp->tx_count--;
+
+                       // free the skb
+                       if (gp->tx_skbuff[nextOut]) {
+                               if (gt96100_debug > 2)
+                                       printk
+                                           ("%s: isr: good Tx, skb=%p\n",
+                                            dev->name,
+                                            gp->tx_skbuff[nextOut]);
+                               dev_kfree_skb_irq(gp->tx_skbuff[nextOut]);
+                               gp->tx_skbuff[nextOut] = NULL;
+                       } else {
+                               printk(KERN_ERR "%s: isr: no skb!\n",
+                                      dev->name);
+                       }
+               }
+
+               if (gp->tx_count == 0 && nextOut != gp->tx_next_in) {
+                       // FIX! this should probably be a panic
+                       printk(KERN_ERR
+                              "%s: isr: warning! Tx queue inconsistent\n",
+                              dev->name);
+               }
+
+               gp->tx_next_out = nextOut;
+
+               if ((status & icrTxEndLow) && gp->tx_count != 0) {
+                       // we must restart the DMA
+                       if (gt96100_debug > 2)
+                               printk("%s: isr: Restarting Tx DMA\n",
+                                      dev->name);
+                       GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_COMM,
+                                        sdcmrERD | sdcmrTXDL);
+               }
+       }
+       // Now check TX errors (RX errors were handled in gt96100_rx)
+
+       if (status & icrTxErrorHigh) {
+               printk(KERN_ERR
+                      "%s: isr: Tx resource error in unused queue!?\n",
+                      dev->name);
+       }
+
+       if (status & icrTxErrorLow) {
+               printk(KERN_ERR "%s: isr: Tx resource error\n", dev->name);
+       }
+
+       if (status & icrTxUdr) {
+               printk(KERN_ERR "%s: isr: Tx underrun error\n", dev->name);
+       }
+
+       if (gt96100_debug > 3)
+               printk("%s: isr: exit, icr=%x\n",
+                      dev->name, GT96100ETH_READ(gp,
+                                                 GT96100_ETH_INT_CAUSE));
+}
+
+
+/*
+ * The Tx ring has been full longer than the watchdog timeout
+ * value, meaning that the interrupt routine has not been freeing
+ * up space in the Tx ring buffer.
+ */
+static void gt96100_tx_timeout(struct net_device *dev)
+{
+//    struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
+
+       printk(KERN_ERR "%s: gt96100_tx_timeout: dev=%p\n", dev->name,
+              dev);
+
+       // FIX! do something, like reset the device
+}
+
+
+static void gt96100_set_rx_mode(struct net_device *dev)
+{
+       struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+       unsigned long flags;
+       struct dev_mc_list *mcptr;
+
+       if (gt96100_debug > 2)
+               printk("%s: gt96100_set_rx_mode: dev=%p, flags=%x\n",
+                      dev->name, dev, dev->flags);
+
+       // stop the Receiver DMA
+       abort(dev, sdcmrAR);
+
+       spin_lock_irqsave(&gp->lock, flags);
+
+       if (dev->flags & IFF_PROMISC)
+               GT96100ETH_WRITE(gp, GT96100_ETH_PORT_CONFIG,
+                                pcrEN | pcrHS | pcrPM);
+
+       memset(gp->hash_table, 0, RX_HASH_TABLE_SIZE);  // clear hash table
+       // Add our ethernet address
+       gt96100_add_hash_entry(dev, dev->dev_addr);
+
+       if (dev->mc_count) {
+               for (mcptr = dev->mc_list; mcptr; mcptr = mcptr->next) {
+                       gt96100_add_hash_entry(dev, mcptr->dmi_addr);
+               }
+       }
+       // restart Rx DMA
+       GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_COMM, sdcmrERD);
+
+       spin_unlock_irqrestore(&gp->lock, flags);
+}
+
+static struct net_device_stats *gt96100_get_stats(struct net_device *dev)
+{
+       struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+       unsigned long flags;
+
+       if (gt96100_debug > 2)
+               printk("%s: gt96100_get_stats: dev=%p\n", dev->name, dev);
+
+       if (netif_device_present(dev)) {
+               spin_lock_irqsave(&gp->lock, flags);
+               update_stats(gp);
+               spin_unlock_irqrestore(&gp->lock, flags);
+       }
+
+       return &gp->stats;
+}
+
+module_init(gt96100_probe);
diff --git a/drivers/net/gt96100eth.h b/drivers/net/gt96100eth.h
new file mode 100644 (file)
index 0000000..2664aa1
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             stevel@mvista.com or support@mvista.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Ethernet driver definitions for the MIPS GT96100 Advanced
+ * Communication Controller.
+ * 
+ */
+#ifndef _GT96100ETH_H
+#define _GT96100ETH_H
+
+#include <linux/config.h>
+#include <asm/galileo-boards/gt96100.h>
+
+/* Keep the ring sizes a power of two for efficiency. */
+#define TX_RING_SIZE   16
+#define RX_RING_SIZE   32
+#define PKT_BUF_SZ     1536    /* Size of each temporary Rx buffer. */
+
+#define RX_HASH_TABLE_SIZE 16384
+#define HASH_HOP_NUMBER 12
+
+#define NUM_INTERFACES 2
+
+#define GT96100ETH_TX_TIMEOUT HZ
+
+#define GT96100_ETH0_BASE (MIPS_GT96100_BASE + GT96100_ETH_PORT_CONFIG)
+#define GT96100_ETH1_BASE (GT96100_ETH0_BASE + GT96100_ETH_IO_SIZE)
+
+#ifdef CONFIG_MIPS_EV96100
+#define GT96100_ETHER0_IRQ 4
+#define GT96100_ETHER1_IRQ 4
+#else
+#define GT96100_ETHER0_IRQ -1
+#define GT96100_ETHER1_IRQ -1
+#endif
+
+#define GT96100ETH_READ(gp, offset) \
+    GT96100_READ((gp->port_offset + offset))
+
+#define GT96100ETH_WRITE(gp, offset, data) \
+    GT96100_WRITE((gp->port_offset + offset), data)
+
+#define GT96100ETH_SETBIT(gp, offset, bits) {\
+    u32 val = GT96100ETH_READ(gp, offset); val |= (u32)(bits); \
+    GT96100ETH_WRITE(gp, offset, val); }
+
+#define GT96100ETH_CLRBIT(gp, offset, bits) {\
+    u32 val = GT96100ETH_READ(gp, offset); val &= (u32)(~(bits)); \
+    GT96100ETH_WRITE(gp, offset, val); }
+
+
+/* Bit definitions of the SMI Reg */
+enum {
+       smirDataMask = 0xffff,
+       smirPhyAdMask = 0x1f << 16,
+       smirPhyAdBit = 16,
+       smirRegAdMask = 0x1f << 21,
+       smirRegAdBit = 21,
+       smirOpCode = 1 << 26,
+       smirReadValid = 1 << 27,
+       smirBusy = 1 << 28
+};
+
+/* Bit definitions of the Port Config Reg */
+enum pcr_bits {
+       pcrPM = 1,
+       pcrRBM = 2,
+       pcrPBF = 4,
+       pcrEN = 1 << 7,
+       pcrLPBKMask = 0x3 << 8,
+       pcrLPBKBit = 8,
+       pcrFC = 1 << 10,
+       pcrHS = 1 << 12,
+       pcrHM = 1 << 13,
+       pcrHDM = 1 << 14,
+       pcrHD = 1 << 15,
+       pcrISLMask = 0x7 << 28,
+       pcrISLBit = 28,
+       pcrACCS = 1 << 31
+};
+
+/* Bit definitions of the Port Config Extend Reg */
+enum pcxr_bits {
+       pcxrIGMP = 1,
+       pcxrSPAN = 2,
+       pcxrPAR = 4,
+       pcxrPRIOtxMask = 0x7 << 3,
+       pcxrPRIOtxBit = 3,
+       pcxrPRIOrxMask = 0x3 << 6,
+       pcxrPRIOrxBit = 6,
+       pcxrPRIOrxOverride = 1 << 8,
+       pcxrDPLXen = 1 << 9,
+       pcxrFCTLen = 1 << 10,
+       pcxrFLP = 1 << 11,
+       pcxrFCTL = 1 << 12,
+       pcxrMFLMask = 0x3 << 14,
+       pcxrMFLBit = 14,
+       pcxrMIBclrMode = 1 << 16,
+       pcxrSpeed = 1 << 18,
+       pcxrSpeeden = 1 << 19,
+       pcxrRMIIen = 1 << 20,
+       pcxrDSCPen = 1 << 21
+};
+
+/* Bit definitions of the Port Command Reg */
+enum pcmr_bits {
+       pcmrFJ = 1 << 15
+};
+
+
+/* Bit definitions of the Port Status Reg */
+enum psr_bits {
+       psrSpeed = 1,
+       psrDuplex = 2,
+       psrFctl = 4,
+       psrLink = 8,
+       psrPause = 1 << 4,
+       psrTxLow = 1 << 5,
+       psrTxHigh = 1 << 6,
+       psrTxInProg = 1 << 7
+};
+
+/* Bit definitions of the SDMA Config Reg */
+enum sdcr_bits {
+       sdcrRCMask = 0xf << 2,
+       sdcrRCBit = 2,
+       sdcrBLMR = 1 << 6,
+       sdcrBLMT = 1 << 7,
+       sdcrPOVR = 1 << 8,
+       sdcrRIFB = 1 << 9,
+       sdcrBSZMask = 0x3 << 12,
+       sdcrBSZBit = 12
+};
+
+/* Bit definitions of the SDMA Command Reg */
+enum sdcmr_bits {
+       sdcmrERD = 1 << 7,
+       sdcmrAR = 1 << 15,
+       sdcmrSTDH = 1 << 16,
+       sdcmrSTDL = 1 << 17,
+       sdcmrTXDH = 1 << 23,
+       sdcmrTXDL = 1 << 24,
+       sdcmrAT = 1 << 31
+};
+
+/* Bit definitions of the Interrupt Cause Reg */
+enum icr_bits {
+       icrRxBuffer = 1,
+       icrTxBufferHigh = 1 << 2,
+       icrTxBufferLow = 1 << 3,
+       icrTxEndHigh = 1 << 6,
+       icrTxEndLow = 1 << 7,
+       icrRxError = 1 << 8,
+       icrTxErrorHigh = 1 << 10,
+       icrTxErrorLow = 1 << 11,
+       icrRxOVR = 1 << 12,
+       icrTxUdr = 1 << 13,
+       icrRxBufferQ0 = 1 << 16,
+       icrRxBufferQ1 = 1 << 17,
+       icrRxBufferQ2 = 1 << 18,
+       icrRxBufferQ3 = 1 << 19,
+       icrRxErrorQ0 = 1 << 20,
+       icrRxErrorQ1 = 1 << 21,
+       icrRxErrorQ2 = 1 << 22,
+       icrRxErrorQ3 = 1 << 23,
+       icrMIIPhySTC = 1 << 28,
+       icrSMIdone = 1 << 29,
+       icrEtherIntSum = 1 << 31
+};
+
+
+/* The Rx and Tx descriptor lists. */
+
+typedef struct {
+       u32 cmdstat;
+       u32 byte_cnt;
+       u32 buff_ptr;
+       u32 next;
+} gt96100_td_t;
+
+#define tdByteCntBit 16
+
+typedef struct {
+       u32 cmdstat;
+       u32 buff_cnt_sz;
+       u32 buff_ptr;
+       u32 next;
+} gt96100_rd_t;
+
+#define rdBuffSzBit 16
+#define rdByteCntMask 0xffff
+
+
+/* Values for the Tx command-status descriptor entry. */
+enum td_cmdstat {
+       txOwn = 1 << 31,
+       txAutoMode = 1 << 30,
+       txEI = 1 << 23,
+       txGenCRC = 1 << 22,
+       txPad = 1 << 18,
+       txFirst = 1 << 17,
+       txLast = 1 << 16,
+       txErrorSummary = 1 << 15,
+       txReTxCntMask = 0x0f << 10,
+       txReTxCntBit = 10,
+       txCollision = 1 << 9,
+       txReTxLimit = 1 << 8,
+       txUnderrun = 1 << 6,
+       txLateCollision = 1 << 5
+};
+
+#define TxReTxCntBit 10
+
+/* Values for the Rx command-status descriptor entry. */
+enum rd_cmdstat {
+       rxOwn = 1 << 31,
+       rxAutoMode = 1 << 30,
+       rxEI = 1 << 23,
+       rxFirst = 1 << 17,
+       rxLast = 1 << 16,
+       rxErrorSummary = 1 << 15,
+       rxIGMP = 1 << 14,
+       rxHashExpired = 1 << 13,
+       rxMissedFrame = 1 << 12,
+       rxFrameType = 1 << 11,
+       rxShortFrame = 1 << 8,
+       rxMaxFrameLen = 1 << 7,
+       rxOverrun = 1 << 6,
+       rxCollision = 1 << 4,
+       rxCRCError = 1
+};
+
+/* Bit fields of a Hash Table Entry */
+enum hash_table_entry {
+       hteValid = 1,
+       hteSkip = 2,
+       hteRD = 4
+};
+
+// The MIB counters
+typedef struct {
+       u32 byteReceived;
+       u32 byteSent;
+       u32 framesReceived;
+       u32 framesSent;
+       u32 totalByteReceived;
+       u32 totalFramesReceived;
+       u32 broadcastFramesReceived;
+       u32 multicastFramesReceived;
+       u32 cRCError;
+       u32 oversizeFrames;
+       u32 fragments;
+       u32 jabber;
+       u32 collision;
+       u32 lateCollision;
+       u32 frames64;
+       u32 frames65_127;
+       u32 frames128_255;
+       u32 frames256_511;
+       u32 frames512_1023;
+       u32 frames1024_MaxSize;
+       u32 macRxError;
+       u32 droppedFrames;
+       u32 outMulticastFrames;
+       u32 outBroadcastFrames;
+       u32 undersizeFrames;
+} mib_counters_t;
+
+
+struct gt96100_private {
+       gt96100_rd_t *rx_ring;
+       gt96100_td_t *tx_ring;
+       // The Rx and Tx rings must be 16-byte aligned
+       dma_addr_t rx_ring_dma;
+       dma_addr_t tx_ring_dma;
+       char *hash_table;
+       // The Hash Table must be 8-byte aligned
+       dma_addr_t hash_table_dma;
+       int hash_mode;
+
+       // The Rx buffers must be 8-byte aligned
+       char *rx_buff[RX_RING_SIZE];
+       // Tx buffers (tx_skbuff[i]->data) with less than 8 bytes
+       // of payload must be 8-byte aligned
+       struct sk_buff *tx_skbuff[TX_RING_SIZE];
+       int rx_next_out;        /* The next free ring entry to receive */
+       int tx_next_in;         /* The next free ring entry to send */
+       int tx_next_out;        /* The last ring entry the ISR processed */
+       int tx_count;           /* current # of pkts waiting to be sent in Tx ring */
+
+       mib_counters_t mib;
+       struct net_device_stats stats;
+
+       int io_size;
+       int port_num;           // 0 or 1
+       u32 port_offset;
+
+       int phy_addr;           // PHY address
+       u32 last_psr;           // last value of the port status register
+
+       int options;            /* User-settable misc. driver options. */
+       int drv_flags;
+       unsigned char phys[2];  /* MII device addresses. */
+       spinlock_t lock;        /* Serialise access to device */
+};
+
+#endif
index 98b9412..4d3fbcf 100644 (file)
@@ -711,10 +711,6 @@ static int __init sixpack_init_driver(void)
        /* Do sanity checks on maximum device parameter. */
        if (sixpack_maxdev < 4)
                sixpack_maxdev = 4;
-       if (sixpack_maxdev * sizeof(void*) >= KMALLOC_MAXSIZE) {
-               printk(msg_invparm);
-               return -ENFILE;
-       }
 
        printk(msg_banner, sixpack_maxdev);
 
index b1b3e8d..289d6d1 100644 (file)
@@ -179,12 +179,14 @@ static dev_link_t *awc_attach(void)
        link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
        if (!link)
                return NULL;
+       memset(link, 0, sizeof(struct dev_link_t));
+
        link->dev = kmalloc(sizeof(struct dev_node_t), GFP_KERNEL);
        if (!link->dev) {
                kfree(link);
                return NULL;
        }
-       memset(link, 0, sizeof(struct dev_link_t));
+
        memset(link->dev, 0, sizeof(struct dev_node_t));
 
        link->release.function = &awc_release;
diff --git a/drivers/net/saa9730.c b/drivers/net/saa9730.c
new file mode 100644 (file)
index 0000000..17d7b6b
--- /dev/null
@@ -0,0 +1,1082 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * SAA9730 ethernet driver.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/pci.h>
+
+#include <asm/addrspace.h>
+#include <asm/mips-boards/prom.h>
+
+#include "saa9730.h"
+
+#ifdef LAN_SAA9730_DEBUG
+int lan_saa9730_debug = LAN_SAA9730_DEBUG;
+#else
+int lan_saa9730_debug;
+#endif
+
+
+/* Non-zero only if the current card is a PCI with BIOS-set IRQ. */
+static unsigned int pci_irq_line = 0;
+
+#define INL(a)     inl((unsigned long)a)
+#define OUTL(x,a)  outl(x,(unsigned long)a)
+
+static void evm_saa9730_enable_lan_int(struct lan_saa9730_private *lp)
+{
+       OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT,
+            &lp->evm_saa9730_regs->InterruptBlock1);
+       OUTL(INL(&lp->evm_saa9730_regs->InterruptStatus1) | EVM_LAN_INT,
+            &lp->evm_saa9730_regs->InterruptStatus1);
+       OUTL(INL(&lp->evm_saa9730_regs->InterruptEnable1) | EVM_LAN_INT |
+            EVM_MASTER_EN, &lp->evm_saa9730_regs->InterruptEnable1);
+}
+static void evm_saa9730_disable_lan_int(struct lan_saa9730_private *lp)
+{
+       OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT,
+            &lp->evm_saa9730_regs->InterruptBlock1);
+       OUTL(INL(&lp->evm_saa9730_regs->InterruptEnable1) & ~EVM_LAN_INT,
+            &lp->evm_saa9730_regs->InterruptEnable1);
+}
+
+static void evm_saa9730_clear_lan_int(struct lan_saa9730_private *lp)
+{
+       OUTL(EVM_LAN_INT, &lp->evm_saa9730_regs->InterruptStatus1);
+}
+
+static void evm_saa9730_block_lan_int(struct lan_saa9730_private *lp)
+{
+       OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT,
+            &lp->evm_saa9730_regs->InterruptBlock1);
+}
+
+static void evm_saa9730_unblock_lan_int(struct lan_saa9730_private *lp)
+{
+       OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT,
+            &lp->evm_saa9730_regs->InterruptBlock1);
+}
+
+static void show_saa9730_regs(struct lan_saa9730_private *lp)
+{
+       int i, j;
+       printk("TxmBufferA = %x\n", lp->TxmBuffer[0][0]);
+       printk("TxmBufferB = %x\n", lp->TxmBuffer[1][0]);
+       printk("RcvBufferA = %x\n", lp->RcvBuffer[0][0]);
+       printk("RcvBufferB = %x\n", lp->RcvBuffer[1][0]);
+       for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
+               for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) {
+                       printk("TxmBuffer[%d][%d] = %x\n", i, j,
+                              le32_to_cpu(*(unsigned int *)
+                                          lp->TxmBuffer[i][j]));
+               }
+       }
+       for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
+               for (j = 0; j < LAN_SAA9730_RCV_Q_SIZE; j++) {
+                       printk("RcvBuffer[%d][%d] = %x\n", i, j,
+                              le32_to_cpu(*(unsigned int *)
+                                          lp->RcvBuffer[i][j]));
+               }
+       }
+       printk("lp->evm_saa9730_regs->InterruptBlock1 = %x\n",
+              INL(&lp->evm_saa9730_regs->InterruptBlock1));
+       printk("lp->evm_saa9730_regs->InterruptStatus1 = %x\n",
+              INL(&lp->evm_saa9730_regs->InterruptStatus1));
+       printk("lp->evm_saa9730_regs->InterruptEnable1 = %x\n",
+              INL(&lp->evm_saa9730_regs->InterruptEnable1));
+       printk("lp->lan_saa9730_regs->Ok2Use = %x\n",
+              INL(&lp->lan_saa9730_regs->Ok2Use));
+       printk("lp->NextTxmBufferIndex = %x\n", lp->NextTxmBufferIndex);
+       printk("lp->NextTxmPacketIndex = %x\n", lp->NextTxmPacketIndex);
+       printk("lp->PendingTxmBufferIndex = %x\n",
+              lp->PendingTxmBufferIndex);
+       printk("lp->PendingTxmPacketIndex = %x\n",
+              lp->PendingTxmPacketIndex);
+       printk("lp->lan_saa9730_regs->LanDmaCtl = %x\n",
+              INL(&lp->lan_saa9730_regs->LanDmaCtl));
+       printk("lp->lan_saa9730_regs->DmaStatus = %x\n",
+              INL(&lp->lan_saa9730_regs->DmaStatus));
+       printk("lp->lan_saa9730_regs->CamCtl = %x\n",
+              INL(&lp->lan_saa9730_regs->CamCtl));
+       printk("lp->lan_saa9730_regs->TxCtl = %x\n",
+              INL(&lp->lan_saa9730_regs->TxCtl));
+       printk("lp->lan_saa9730_regs->TxStatus = %x\n",
+              INL(&lp->lan_saa9730_regs->TxStatus));
+       printk("lp->lan_saa9730_regs->RxCtl = %x\n",
+              INL(&lp->lan_saa9730_regs->RxCtl));
+       printk("lp->lan_saa9730_regs->RxStatus = %x\n",
+              INL(&lp->lan_saa9730_regs->RxStatus));
+       for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) {
+               OUTL(i, &lp->lan_saa9730_regs->CamAddress);
+               printk("lp->lan_saa9730_regs->CamData = %x\n",
+                      INL(&lp->lan_saa9730_regs->CamData));
+       }
+       printk("lp->stats.tx_packets = %lx\n", lp->stats.tx_packets);
+       printk("lp->stats.tx_errors = %lx\n", lp->stats.tx_errors);
+       printk("lp->stats.tx_aborted_errors = %lx\n",
+              lp->stats.tx_aborted_errors);
+       printk("lp->stats.tx_window_errors = %lx\n",
+              lp->stats.tx_window_errors);
+       printk("lp->stats.tx_carrier_errors = %lx\n",
+              lp->stats.tx_carrier_errors);
+       printk("lp->stats.tx_fifo_errors = %lx\n",
+              lp->stats.tx_fifo_errors);
+       printk("lp->stats.tx_heartbeat_errors = %lx\n",
+              lp->stats.tx_heartbeat_errors);
+       printk("lp->stats.collisions = %lx\n", lp->stats.collisions);
+
+       printk("lp->stats.rx_packets = %lx\n", lp->stats.rx_packets);
+       printk("lp->stats.rx_errors = %lx\n", lp->stats.rx_errors);
+       printk("lp->stats.rx_dropped = %lx\n", lp->stats.rx_dropped);
+       printk("lp->stats.rx_crc_errors = %lx\n", lp->stats.rx_crc_errors);
+       printk("lp->stats.rx_frame_errors = %lx\n",
+              lp->stats.rx_frame_errors);
+       printk("lp->stats.rx_fifo_errors = %lx\n",
+              lp->stats.rx_fifo_errors);
+       printk("lp->stats.rx_length_errors = %lx\n",
+              lp->stats.rx_length_errors);
+
+       printk("lp->lan_saa9730_regs->DebugPCIMasterAddr = %x\n",
+              INL(&lp->lan_saa9730_regs->DebugPCIMasterAddr));
+       printk("lp->lan_saa9730_regs->DebugLanTxStateMachine = %x\n",
+              INL(&lp->lan_saa9730_regs->DebugLanTxStateMachine));
+       printk("lp->lan_saa9730_regs->DebugLanRxStateMachine = %x\n",
+              INL(&lp->lan_saa9730_regs->DebugLanRxStateMachine));
+       printk("lp->lan_saa9730_regs->DebugLanTxFifoPointers = %x\n",
+              INL(&lp->lan_saa9730_regs->DebugLanTxFifoPointers));
+       printk("lp->lan_saa9730_regs->DebugLanRxFifoPointers = %x\n",
+              INL(&lp->lan_saa9730_regs->DebugLanRxFifoPointers));
+       printk("lp->lan_saa9730_regs->DebugLanCtlStateMachine = %x\n",
+              INL(&lp->lan_saa9730_regs->DebugLanCtlStateMachine));
+}
+
+static void lan_saa9730_buffer_init(struct lan_saa9730_private *lp)
+{
+       int i, j;
+
+       /* Init RX buffers */
+       for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
+               for (j = 0; j < LAN_SAA9730_RCV_Q_SIZE; j++) {
+                       *(unsigned int *) lp->RcvBuffer[i][j] =
+                           cpu_to_le32(RXSF_READY <<
+                                       RX_STAT_CTL_OWNER_SHF);
+               }
+       }
+
+       /* Init TX buffers */
+       for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
+               for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) {
+                       *(unsigned int *) lp->TxmBuffer[i][j] =
+                           cpu_to_le32(TXSF_EMPTY <<
+                                       TX_STAT_CTL_OWNER_SHF);
+               }
+       }
+}
+
+static int lan_saa9730_allocate_buffers(struct lan_saa9730_private *lp)
+{
+       unsigned int mem_size;
+       void *Pa;
+       unsigned int i, j, RcvBufferSize, TxmBufferSize;
+       unsigned int buffer_start;
+
+       /* 
+        * Allocate all RX and TX packets in one chunk. 
+        * The Rx and Tx packets must be PACKET_SIZE aligned.
+        */
+       mem_size = ((LAN_SAA9730_RCV_Q_SIZE + LAN_SAA9730_TXM_Q_SIZE) *
+                   LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_BUFFERS) +
+           LAN_SAA9730_PACKET_SIZE;
+       buffer_start =
+           (unsigned int) kmalloc(mem_size, GFP_DMA | GFP_KERNEL);
+
+       /* 
+        * Set DMA buffer to kseg1 (uncached).
+        * Make sure to flush before using it uncached.
+        */
+       Pa = (void *) KSEG1ADDR((buffer_start + LAN_SAA9730_PACKET_SIZE) &
+                               ~(LAN_SAA9730_PACKET_SIZE - 1));
+       dma_cache_wback_inv((unsigned long) Pa, mem_size);
+
+       /* Initialize buffer space */
+       RcvBufferSize = LAN_SAA9730_PACKET_SIZE;
+       TxmBufferSize = LAN_SAA9730_PACKET_SIZE;
+       lp->DmaRcvPackets = LAN_SAA9730_RCV_Q_SIZE;
+       lp->DmaTxmPackets = LAN_SAA9730_TXM_Q_SIZE;
+
+       /* Init RX buffers */
+       for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
+               for (j = 0; j < LAN_SAA9730_RCV_Q_SIZE; j++) {
+                       *(unsigned int *) Pa =
+                           cpu_to_le32(RXSF_READY <<
+                                       RX_STAT_CTL_OWNER_SHF);
+                       lp->RcvBuffer[i][j] = (unsigned int) Pa;
+                       Pa += RcvBufferSize;
+               }
+       }
+
+       /* Init TX buffers */
+       for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
+               for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) {
+                       *(unsigned int *) Pa =
+                           cpu_to_le32(TXSF_EMPTY <<
+                                       TX_STAT_CTL_OWNER_SHF);
+                       lp->TxmBuffer[i][j] = (unsigned int) Pa;
+                       Pa += TxmBufferSize;
+               }
+       }
+
+       /* 
+        * Set rx buffer A and rx buffer B to point to the first two buffer 
+        * spaces.
+        */
+       OUTL(PHYSADDR(lp->RcvBuffer[0][0]),
+            &lp->lan_saa9730_regs->RxBuffA);
+       OUTL(PHYSADDR(lp->RcvBuffer[1][0]),
+            &lp->lan_saa9730_regs->RxBuffB);
+
+       /* Initialize Buffer Index */
+       lp->NextRcvPacketIndex = 0;
+       lp->NextRcvToUseIsA = 1;
+
+       /* Set current buffer index & next availble packet index */
+       lp->NextTxmPacketIndex = 0;
+       lp->NextTxmBufferIndex = 0;
+       lp->PendingTxmPacketIndex = 0;
+       lp->PendingTxmBufferIndex = 0;
+
+       /* 
+        * Set txm_buf_a and txm_buf_b to point to the first two buffer
+        * space 
+        */
+       OUTL(PHYSADDR(lp->TxmBuffer[0][0]),
+            &lp->lan_saa9730_regs->TxBuffA);
+       OUTL(PHYSADDR(lp->TxmBuffer[1][0]),
+            &lp->lan_saa9730_regs->TxBuffB);
+
+       /* Set packet number */
+       OUTL((lp->DmaRcvPackets << PK_COUNT_RX_A_SHF) |
+            (lp->DmaRcvPackets << PK_COUNT_RX_B_SHF) |
+            (lp->DmaTxmPackets << PK_COUNT_TX_A_SHF) |
+            (lp->DmaTxmPackets << PK_COUNT_TX_B_SHF),
+            &lp->lan_saa9730_regs->PacketCount);
+
+       return 0;
+}
+
+static int lan_saa9730_cam_load(struct lan_saa9730_private *lp)
+{
+       unsigned int i;
+       unsigned char *NetworkAddress;
+
+       NetworkAddress = (unsigned char *) &lp->PhysicalAddress[0][0];
+
+       for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) {
+               /* First set address to where data is written */
+               OUTL(i, &lp->lan_saa9730_regs->CamAddress);
+               OUTL((NetworkAddress[0] << 24) | (NetworkAddress[1] << 16)
+                    | (NetworkAddress[2] << 8) | NetworkAddress[3],
+                    &lp->lan_saa9730_regs->CamData);
+               NetworkAddress += 4;
+       }
+       return 0;
+}
+
+static int lan_saa9730_cam_init(struct net_device *dev)
+{
+       struct lan_saa9730_private *lp =
+           (struct lan_saa9730_private *) dev->priv;
+       unsigned int i;
+
+       /* Copy MAC-address into all entries. */
+       for (i = 0; i < LAN_SAA9730_CAM_ENTRIES; i++) {
+               memcpy((unsigned char *) lp->PhysicalAddress[i],
+                      (unsigned char *) dev->dev_addr, 6);
+       }
+
+       return 0;
+}
+
+static int lan_saa9730_mii_init(struct lan_saa9730_private *lp)
+{
+       int i, l;
+
+       /* Check link status, spin here till station is not busy. */
+       i = 0;
+       while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) & MD_CA_BUSY) {
+               i++;
+               if (i > 100) {
+                       printk("Error: lan_saa9730_mii_init: timeout\n");
+                       return -1;
+               }
+               udelay(1000);   /* wait 1 ms. */
+       }
+
+       /* Now set the control and address register. */
+       OUTL(MD_CA_BUSY | PHY_STATUS | PHY_ADDRESS << MD_CA_PHY_SHF,
+            &lp->lan_saa9730_regs->StationMgmtCtl);
+
+       /* check link status, spin here till station is not busy */
+       i = 0;
+       while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) & MD_CA_BUSY) {
+               i++;
+               if (i > 100) {
+                       printk("Error: lan_saa9730_mii_init: timeout\n");
+                       return -1;
+               }
+               udelay(1000);   /* wait 1 ms. */
+       }
+
+       /* Wait for 1 ms. */
+       udelay(1000);
+
+       /* Check the link status. */
+       if (INL(&lp->lan_saa9730_regs->StationMgmtData) &
+           PHY_STATUS_LINK_UP) {
+               /* Link is up. */
+               return 0;
+       } else {
+               /* Link is down, reset the PHY first. */
+
+               /* set PHY address = 'CONTROL' */
+               OUTL(PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | PHY_CONTROL,
+                    &lp->lan_saa9730_regs->StationMgmtCtl);
+
+               /* Wait for 1 ms. */
+               udelay(1000);
+
+               /* set 'CONTROL' = force reset and renegotiate */
+               OUTL(PHY_CONTROL_RESET | PHY_CONTROL_AUTO_NEG |
+                    PHY_CONTROL_RESTART_AUTO_NEG,
+                    &lp->lan_saa9730_regs->StationMgmtData);
+
+               /* Wait for 50 ms. */
+               udelay(50 * 1000);
+
+               /* set 'BUSY' to start operation */
+               OUTL(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR |
+                    PHY_CONTROL, &lp->lan_saa9730_regs->StationMgmtCtl);
+
+               /* await completion */
+               i = 0;
+               while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) &
+                      MD_CA_BUSY) {
+                       i++;
+                       if (i > 100) {
+                               printk
+                                   ("Error: lan_saa9730_mii_init: timeout\n");
+                               return -1;
+                       }
+                       udelay(1000);   /* wait 1 ms. */
+               }
+
+               /* Wait for 1 ms. */
+               udelay(1000);
+
+               for (l = 0; l < 2; l++) {
+                       /* set PHY address = 'STATUS' */
+                       OUTL(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF |
+                            PHY_STATUS,
+                            &lp->lan_saa9730_regs->StationMgmtCtl);
+
+                       /* await completion */
+                       i = 0;
+                       while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) &
+                              MD_CA_BUSY) {
+                               i++;
+                               if (i > 100) {
+                                       printk
+                                           ("Error: lan_saa9730_mii_init: timeout\n");
+                                       return -1;
+                               }
+                               udelay(1000);   /* wait 1 ms. */
+                       }
+
+                       /* wait for 3 sec. */
+                       udelay(3000 * 1000);
+
+                       /* check the link status */
+                       if (INL(&lp->lan_saa9730_regs->StationMgmtData) &
+                           PHY_STATUS_LINK_UP) {
+                               /* link is up */
+                               break;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int lan_saa9730_control_init(struct lan_saa9730_private *lp)
+{
+       /* Initialize DMA control register. */
+       OUTL((LANMB_ANY << DMA_CTL_MAX_XFER_SHF) |
+            (LANEND_LITTLE << DMA_CTL_ENDIAN_SHF) |
+            (LAN_SAA9730_RCV_Q_INT_THRESHOLD << DMA_CTL_RX_INT_COUNT_SHF)
+            | DMA_CTL_RX_INT_TO_EN | DMA_CTL_RX_INT_EN |
+            DMA_CTL_MAC_RX_INT_EN | DMA_CTL_MAC_TX_INT_EN,
+            &lp->lan_saa9730_regs->LanDmaCtl);
+
+       /* Initial MAC control register. */
+       OUTL((MACCM_MII << MAC_CONTROL_CONN_SHF) | MAC_CONTROL_FULL_DUP,
+            &lp->lan_saa9730_regs->MacCtl);
+
+       /* Initialize CAM control register. */
+       OUTL(CAM_CONTROL_COMP_EN | CAM_CONTROL_BROAD_ACC,
+            &lp->lan_saa9730_regs->CamCtl);
+
+       /* 
+        * Initialize CAM enable register, only turn on first entry, should
+        * contain own addr. 
+        */
+       OUTL(0x0001, &lp->lan_saa9730_regs->CamEnable);
+
+       /* Initialize Tx control register */
+       OUTL(TX_CTL_EN_COMP, &lp->lan_saa9730_regs->TxCtl);
+
+       /* Initialize Rcv control register */
+       OUTL(RX_CTL_STRIP_CRC, &lp->lan_saa9730_regs->RxCtl);
+
+       /* Reset DMA engine */
+       OUTL(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest);
+
+       return 0;
+}
+
+static int lan_saa9730_stop(struct lan_saa9730_private *lp)
+{
+       int i;
+
+       /* Stop DMA first */
+       OUTL(INL(&lp->lan_saa9730_regs->LanDmaCtl) &
+            ~(DMA_CTL_EN_TX_DMA | DMA_CTL_EN_RX_DMA),
+            &lp->lan_saa9730_regs->LanDmaCtl);
+
+       /* Set the SW Reset bits in DMA and MAC control registers */
+       OUTL(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest);
+       OUTL(INL(&lp->lan_saa9730_regs->MacCtl) | MAC_CONTROL_RESET,
+            &lp->lan_saa9730_regs->MacCtl);
+
+       /* 
+        * Wait for MAC reset to have finished. The reset bit is auto cleared
+        * when the reset is done.
+        */
+       i = 0;
+       while (INL(&lp->lan_saa9730_regs->MacCtl) & MAC_CONTROL_RESET) {
+               i++;
+               if (i > 100) {
+                       printk
+                           ("Error: lan_sa9730_stop: MAC reset timeout\n");
+                       return -1;
+               }
+               udelay(1000);   /* wait 1 ms. */
+       }
+
+       return 0;
+}
+
+static int lan_saa9730_dma_init(struct lan_saa9730_private *lp)
+{
+       /* Stop lan controller. */
+       lan_saa9730_stop(lp);
+
+       OUTL(LAN_SAA9730_DEFAULT_TIME_OUT_CNT,
+            &lp->lan_saa9730_regs->Timeout);
+
+       return 0;
+}
+
+static int lan_saa9730_start(struct lan_saa9730_private *lp)
+{
+       lan_saa9730_buffer_init(lp);
+
+       /* Initialize Rx Buffer Index */
+       lp->NextRcvPacketIndex = 0;
+       lp->NextRcvToUseIsA = 1;
+
+       /* Set current buffer index & next availble packet index */
+       lp->NextTxmPacketIndex = 0;
+       lp->NextTxmBufferIndex = 0;
+       lp->PendingTxmPacketIndex = 0;
+       lp->PendingTxmBufferIndex = 0;
+
+       OUTL(INL(&lp->lan_saa9730_regs->LanDmaCtl) | DMA_CTL_EN_TX_DMA |
+            DMA_CTL_EN_RX_DMA, &lp->lan_saa9730_regs->LanDmaCtl);
+
+       /* For Tx, turn on MAC then DMA */
+       OUTL(INL(&lp->lan_saa9730_regs->TxCtl) | TX_CTL_TX_EN,
+            &lp->lan_saa9730_regs->TxCtl);
+
+       /* For Rx, turn on DMA then MAC */
+       OUTL(INL(&lp->lan_saa9730_regs->RxCtl) | RX_CTL_RX_EN,
+            &lp->lan_saa9730_regs->RxCtl);
+
+       /* Set Ok2Use to let hardware owns the buffers */
+       OUTL(OK2USE_RX_A | OK2USE_RX_B | OK2USE_TX_A | OK2USE_TX_B,
+            &lp->lan_saa9730_regs->Ok2Use);
+
+       return 0;
+}
+
+static int lan_saa9730_restart(struct lan_saa9730_private *lp)
+{
+       lan_saa9730_stop(lp);
+       lan_saa9730_start(lp);
+
+       return 0;
+}
+
+static int lan_saa9730_tx(struct net_device *dev)
+{
+       struct lan_saa9730_private *lp =
+           (struct lan_saa9730_private *) dev->priv;
+       unsigned int *pPacket;
+       unsigned int tx_status;
+
+       if (lan_saa9730_debug > 5)
+               printk("lan_saa9730_tx interrupt\n");
+
+       /* Clear interrupt. */
+       OUTL(DMA_STATUS_MAC_TX_INT, &lp->lan_saa9730_regs->DmaStatus);
+
+       while (1) {
+               pPacket =
+                   (unsigned int *) lp->TxmBuffer[lp->
+                                                  PendingTxmBufferIndex]
+                   [lp->PendingTxmPacketIndex];
+
+               /* Get status of first packet transmitted. */
+               tx_status = le32_to_cpu(*pPacket);
+
+               /* Check ownership. */
+               if ((tx_status & TX_STAT_CTL_OWNER_MSK) !=
+                   (TXSF_HWDONE << TX_STAT_CTL_OWNER_SHF)) break;
+
+               /* Check for error. */
+               if (tx_status & TX_STAT_CTL_ERROR_MSK) {
+                       if (lan_saa9730_debug > 1)
+                               printk("lan_saa9730_tx: tx error = %x\n",
+                                      tx_status);
+
+                       lp->stats.tx_errors++;
+                       if (tx_status &
+                           (TX_STATUS_EX_COLL << TX_STAT_CTL_STATUS_SHF))
+                                   lp->stats.tx_aborted_errors++;
+                       if (tx_status &
+                           (TX_STATUS_LATE_COLL <<
+                            TX_STAT_CTL_STATUS_SHF)) lp->stats.
+            tx_window_errors++;
+                       if (tx_status &
+                           (TX_STATUS_L_CARR << TX_STAT_CTL_STATUS_SHF))
+                                   lp->stats.tx_carrier_errors++;
+                       if (tx_status &
+                           (TX_STATUS_UNDER << TX_STAT_CTL_STATUS_SHF))
+                                   lp->stats.tx_fifo_errors++;
+                       if (tx_status &
+                           (TX_STATUS_SQ_ERR << TX_STAT_CTL_STATUS_SHF))
+                                   lp->stats.tx_heartbeat_errors++;
+
+                       lp->stats.collisions +=
+                           tx_status & TX_STATUS_TX_COLL_MSK;
+               }
+
+               /* Free buffer. */
+               *pPacket =
+                   cpu_to_le32(TXSF_EMPTY << TX_STAT_CTL_OWNER_SHF);
+
+               /* Update pending index pointer. */
+               lp->PendingTxmPacketIndex++;
+               if (lp->PendingTxmPacketIndex >= LAN_SAA9730_TXM_Q_SIZE) {
+                       lp->PendingTxmPacketIndex = 0;
+                       lp->PendingTxmBufferIndex ^= 1;
+               }
+       }
+
+       /* Make sure A and B are available to hardware. */
+       OUTL(OK2USE_TX_A | OK2USE_TX_B, &lp->lan_saa9730_regs->Ok2Use);
+
+       if (netif_queue_stopped(dev)) {
+               /* The tx buffer is no longer full. */
+               netif_wake_queue(dev);
+       }
+
+       return 0;
+}
+
+static int lan_saa9730_rx(struct net_device *dev)
+{
+       struct lan_saa9730_private *lp =
+           (struct lan_saa9730_private *) dev->priv;
+       int len = 0;
+       struct sk_buff *skb = 0;
+       unsigned int rx_status;
+       int BufferIndex;
+       int PacketIndex;
+       unsigned int *pPacket;
+       unsigned char *pData;
+
+       if (lan_saa9730_debug > 5)
+               printk("lan_saa9730_rx interrupt\n");
+
+       /* Clear receive interrupts. */
+       OUTL(DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT |
+            DMA_STATUS_RX_TO_INT, &lp->lan_saa9730_regs->DmaStatus);
+
+       /* Address next packet */
+       if (lp->NextRcvToUseIsA)
+               BufferIndex = 0;
+       else
+               BufferIndex = 1;
+       PacketIndex = lp->NextRcvPacketIndex;
+       pPacket = (unsigned int *) lp->RcvBuffer[BufferIndex][PacketIndex];
+       rx_status = le32_to_cpu(*pPacket);
+
+       /* Process each packet. */
+       while ((rx_status & RX_STAT_CTL_OWNER_MSK) ==
+              (RXSF_HWDONE << RX_STAT_CTL_OWNER_SHF)) {
+               /* Check the rx status. */
+               if (rx_status & (RX_STATUS_GOOD << RX_STAT_CTL_STATUS_SHF)) {
+                       /* Received packet is good. */
+                       len = (rx_status & RX_STAT_CTL_LENGTH_MSK) >>
+                           RX_STAT_CTL_LENGTH_SHF;
+
+                       pData = (unsigned char *) pPacket;
+                       pData += 4;
+                       skb = dev_alloc_skb(len + 2);
+                       if (skb == 0) {
+                               printk
+                                   ("%s: Memory squeeze, deferring packet.\n",
+                                    dev->name);
+                               lp->stats.rx_dropped++;
+                       } else {
+                               lp->stats.rx_bytes += len;
+                               lp->stats.rx_packets++;
+                               skb->dev = dev;
+                               skb_reserve(skb, 2);    /* 16 byte align */
+                               skb_put(skb, len);      /* make room */
+                               eth_copy_and_sum(skb,
+                                                (unsigned char *) pData,
+                                                len, 0);
+                               skb->protocol = eth_type_trans(skb, dev);
+                               netif_rx(skb);
+                       }
+               } else {
+                       /* We got an error packet. */
+                       if (lan_saa9730_debug > 2)
+                               printk
+                                   ("lan_saa9730_rx: We got an error packet = %x\n",
+                                    rx_status);
+
+                       lp->stats.rx_errors++;
+                       if (rx_status &
+                           (RX_STATUS_CRC_ERR << RX_STAT_CTL_STATUS_SHF))
+                                   lp->stats.rx_crc_errors++;
+                       if (rx_status &
+                           (RX_STATUS_ALIGN_ERR <<
+                            RX_STAT_CTL_STATUS_SHF)) lp->stats.
+            rx_frame_errors++;
+                       if (rx_status &
+                           (RX_STATUS_OVERFLOW << RX_STAT_CTL_STATUS_SHF))
+                                   lp->stats.rx_fifo_errors++;
+                       if (rx_status &
+                           (RX_STATUS_LONG_ERR << RX_STAT_CTL_STATUS_SHF))
+                                   lp->stats.rx_length_errors++;
+               }
+
+               /* Indicate we have processed the buffer. */
+               *pPacket =
+                   cpu_to_le32(RXSF_READY << RX_STAT_CTL_OWNER_SHF);
+
+               /* Go to next packet in sequence. */
+               lp->NextRcvPacketIndex++;
+               if (lp->NextRcvPacketIndex >= LAN_SAA9730_RCV_Q_SIZE) {
+                       lp->NextRcvPacketIndex = 0;
+                       if (BufferIndex) {
+                               lp->NextRcvToUseIsA = 1;
+                       } else {
+                               lp->NextRcvToUseIsA = 0;
+                       }
+               }
+               OUTL(OK2USE_RX_A | OK2USE_RX_B,
+                    &lp->lan_saa9730_regs->Ok2Use);
+
+               /* Address next packet */
+               if (lp->NextRcvToUseIsA)
+                       BufferIndex = 0;
+               else
+                       BufferIndex = 1;
+               PacketIndex = lp->NextRcvPacketIndex;
+               pPacket =
+                   (unsigned int *) lp->
+                   RcvBuffer[BufferIndex][PacketIndex];
+               rx_status = le32_to_cpu(*pPacket);
+       }
+
+       /* Make sure A and B are available to hardware. */
+       OUTL(OK2USE_RX_A | OK2USE_RX_B, &lp->lan_saa9730_regs->Ok2Use);
+
+       return 0;
+}
+
+static void lan_saa9730_interrupt(const int irq, void *dev_id,
+                                 struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *) dev_id;
+       struct lan_saa9730_private *lp =
+           (struct lan_saa9730_private *) dev->priv;
+
+       if (lan_saa9730_debug > 5)
+               printk("lan_saa9730_interrupt\n");
+
+       /* Disable the EVM LAN interrupt. */
+       evm_saa9730_block_lan_int(lp);
+
+       /* Clear the EVM LAN interrupt. */
+       evm_saa9730_clear_lan_int(lp);
+
+       /* Service pending transmit interrupts. */
+       if (INL(&lp->lan_saa9730_regs->DmaStatus) & DMA_STATUS_MAC_TX_INT)
+               lan_saa9730_tx(dev);
+
+       /* Service pending receive interrupts. */
+       if (INL(&lp->lan_saa9730_regs->DmaStatus) &
+           (DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT |
+            DMA_STATUS_RX_TO_INT)) lan_saa9730_rx(dev);
+
+       /* Enable the EVM LAN interrupt. */
+       evm_saa9730_unblock_lan_int(lp);
+
+       return;
+}
+
+static int lan_saa9730_open_fail(struct net_device *dev)
+{
+       return -ENODEV;
+}
+
+static int lan_saa9730_open(struct net_device *dev)
+{
+       struct lan_saa9730_private *lp =
+           (struct lan_saa9730_private *) dev->priv;
+
+       /* Associate IRQ with lan_saa9730_interrupt */
+       if (request_irq(dev->irq, &lan_saa9730_interrupt, 0, "SAA9730 Eth",
+                       dev)) {
+               printk("lan_saa9730_open: Can't get irq %d\n", dev->irq);
+               return -EAGAIN;
+       }
+
+       /* Enable the Lan interrupt in the event manager. */
+       evm_saa9730_enable_lan_int(lp);
+
+       /* Start the LAN controller */
+       if (lan_saa9730_start(lp))
+               return -1;
+
+       netif_start_queue(dev);
+
+       return 0;
+}
+
+static int lan_saa9730_write(struct lan_saa9730_private *lp,
+                            struct sk_buff *skb, int skblen)
+{
+       unsigned char *pbData = skb->data;
+       unsigned int len = skblen;
+       unsigned char *pbPacketData;
+       unsigned int tx_status;
+       int BufferIndex;
+       int PacketIndex;
+
+       if (lan_saa9730_debug > 5)
+               printk("lan_saa9730_write: skb=%08x\n",
+                      (unsigned int) skb);
+
+       BufferIndex = lp->NextTxmBufferIndex;
+       PacketIndex = lp->NextTxmPacketIndex;
+
+       tx_status =
+           le32_to_cpu(*(unsigned int *) lp->
+                       TxmBuffer[BufferIndex][PacketIndex]);
+       if ((tx_status & TX_STAT_CTL_OWNER_MSK) !=
+           (TXSF_EMPTY << TX_STAT_CTL_OWNER_SHF)) {
+               if (lan_saa9730_debug > 4)
+                       printk
+                           ("lan_saa9730_write: Tx buffer not available: tx_status = %x\n",
+                            tx_status);
+               return -1;
+       }
+
+       lp->NextTxmPacketIndex++;
+       if (lp->NextTxmPacketIndex >= LAN_SAA9730_TXM_Q_SIZE) {
+               lp->NextTxmPacketIndex = 0;
+               lp->NextTxmBufferIndex ^= 1;
+       }
+
+       pbPacketData =
+           (unsigned char *) lp->TxmBuffer[BufferIndex][PacketIndex];
+       pbPacketData += 4;
+
+       /* copy the bits */
+       memcpy(pbPacketData, pbData, len);
+
+       /* Set transmit status for hardware */
+       *(unsigned int *) lp->TxmBuffer[BufferIndex][PacketIndex] =
+           cpu_to_le32((TXSF_READY << TX_STAT_CTL_OWNER_SHF) |
+                       (TX_STAT_CTL_INT_AFTER_TX << TX_STAT_CTL_FRAME_SHF)
+                       | (len << TX_STAT_CTL_LENGTH_SHF));
+
+       /* Set hardware tx buffer. */
+       OUTL(OK2USE_TX_A | OK2USE_TX_B, &lp->lan_saa9730_regs->Ok2Use);
+
+       return 0;
+}
+
+static void lan_saa9730_tx_timeout(struct net_device *dev)
+{
+       struct lan_saa9730_private *lp =
+           (struct lan_saa9730_private *) dev->priv;
+
+       /* Transmitter timeout, serious problems */
+       lp->stats.tx_errors++;
+       printk("%s: transmit timed out, reset\n", dev->name);
+       /*show_saa9730_regs(lp); */
+       lan_saa9730_restart(lp);
+
+       dev->trans_start = jiffies;
+       netif_start_queue(dev);
+}
+
+static int lan_saa9730_start_xmit(struct sk_buff *skb,
+                                 struct net_device *dev)
+{
+       struct lan_saa9730_private *lp =
+           (struct lan_saa9730_private *) dev->priv;
+       unsigned long flags;
+       int skblen;
+       int len;
+
+       if (lan_saa9730_debug > 4)
+               printk("Send packet: skb=%08x\n", (unsigned int) skb);
+
+       skblen = skb->len;
+       save_and_cli(flags);
+       len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
+
+       if (lan_saa9730_write(lp, skb, skblen)) {
+               restore_flags(flags);
+               printk
+                   ("Error when writing packet to controller: skb=%08x\n",
+                    (unsigned int) skb);
+               netif_stop_queue(dev);
+               return -1;
+       }
+
+       lp->stats.tx_bytes += len;
+       lp->stats.tx_packets++;
+
+       dev->trans_start = jiffies;
+       netif_start_queue(dev);
+       dev_kfree_skb(skb);
+
+       restore_flags(flags);
+
+       return 0;
+}
+
+static int lan_saa9730_close(struct net_device *dev)
+{
+       struct lan_saa9730_private *lp =
+           (struct lan_saa9730_private *) dev->priv;
+
+       if (lan_saa9730_debug > 1)
+               printk("lan_saa9730_close:\n");
+
+       netif_stop_queue(dev);
+
+       /* Disable the Lan interrupt in the event manager. */
+       evm_saa9730_disable_lan_int(lp);
+
+       /* Stop the controller */
+       if (lan_saa9730_stop(lp))
+               return -1;
+
+       free_irq(dev->irq, (void *) dev);
+
+       return 0;
+}
+
+static struct net_device_stats *lan_saa9730_get_stats(struct net_device
+                                                     *dev)
+{
+       struct lan_saa9730_private *lp =
+           (struct lan_saa9730_private *) dev->priv;
+
+       return &lp->stats;
+}
+
+static void lan_saa9730_set_multicast(struct net_device *dev)
+{
+       struct lan_saa9730_private *lp =
+           (struct lan_saa9730_private *) dev->priv;
+
+       /* Stop the controller */
+       lan_saa9730_stop(lp);
+
+       if (dev->flags & IFF_PROMISC) {
+               /* accept all packets */
+               OUTL(CAM_CONTROL_COMP_EN | CAM_CONTROL_STATION_ACC |
+                    CAM_CONTROL_GROUP_ACC | CAM_CONTROL_BROAD_ACC,
+                    &lp->lan_saa9730_regs->CamCtl);
+       } else {
+               if (dev->flags & IFF_ALLMULTI) {
+                       /* accept all multicast packets */
+                       OUTL(CAM_CONTROL_COMP_EN | CAM_CONTROL_GROUP_ACC |
+                            CAM_CONTROL_BROAD_ACC,
+                            &lp->lan_saa9730_regs->CamCtl);
+               } else {
+                       /* 
+                        * Will handle the multicast stuff later. -carstenl
+                        */
+               }
+       }
+
+       lan_saa9730_restart(lp);
+}
+
+static int lan_saa9730_init(struct net_device *dev, int ioaddr, int irq)
+{
+       struct lan_saa9730_private *lp;
+       unsigned char ethernet_addr[6];
+
+       dev = init_etherdev(dev, 0);
+
+       dev->open = lan_saa9730_open_fail;
+       if (get_ethernet_addr(ethernet_addr))
+               return -1;
+
+       memcpy(dev->dev_addr, ethernet_addr, 6);
+       dev->base_addr = ioaddr;
+       dev->irq = irq;
+
+       /* 
+        * Make certain the data structures used by the controller are aligned 
+        * and DMAble. 
+        */
+       lp = (struct lan_saa9730_private *) (((unsigned long)
+                                             kmalloc(sizeof(*lp) + 7,
+                                                     GFP_DMA | GFP_KERNEL)
+                                             + 7) & ~7);
+
+       dev->priv = lp;
+       memset(lp, 0, sizeof(*lp));
+
+       /* Set SAA9730 LAN base address. */
+       lp->lan_saa9730_regs = (t_lan_saa9730_regmap *) (ioaddr +
+                                                        SAA9730_LAN_REGS_ADDR);
+
+       /* Set SAA9730 EVM base address. */
+       lp->evm_saa9730_regs = (t_evm_saa9730_regmap *) (ioaddr +
+                                                        SAA9730_EVM_REGS_ADDR);
+
+       /* Allocate LAN RX/TX frame buffer space. */
+       if (lan_saa9730_allocate_buffers(lp))
+               return -1;
+
+       /* Stop LAN controller. */
+       if (lan_saa9730_stop(lp))
+               return -1;
+
+       /* Initialize CAM registers. */
+       if (lan_saa9730_cam_init(dev))
+               return -1;
+
+       /* Initialize MII registers. */
+       if (lan_saa9730_mii_init(lp))
+               return -1;
+
+       /* Initialize control registers. */
+       if (lan_saa9730_control_init(lp))
+               return -1;
+
+       /* Load CAM registers. */
+       if (lan_saa9730_cam_load(lp))
+               return -1;
+
+       /* Initialize DMA context registers. */
+       if (lan_saa9730_dma_init(lp))
+               return -1;
+
+       dev->open = lan_saa9730_open;
+       dev->hard_start_xmit = lan_saa9730_start_xmit;
+       dev->stop = lan_saa9730_close;
+       dev->get_stats = lan_saa9730_get_stats;
+       dev->set_multicast_list = lan_saa9730_set_multicast;
+       dev->tx_timeout = lan_saa9730_tx_timeout;
+       dev->watchdog_timeo = (HZ >> 1);
+       dev->dma = 0;
+
+       return 0;
+}
+
+
+static int __init saa9730_probe(void)
+{
+       struct net_device *dev = NULL;
+
+       if (pci_present()) {
+               struct pci_dev *pdev = NULL;
+               if (lan_saa9730_debug > 1)
+                       printk
+                           ("saa9730.c: PCI bios is present, checking for devices...\n");
+
+               while ((pdev = pci_find_device(PCI_VENDOR_ID_PHILIPS,
+                                              PCI_DEVICE_ID_PHILIPS_SAA9730,
+                                              pdev))) {
+                       unsigned int pci_ioaddr;
+
+                       pci_irq_line = pdev->irq;
+                       /* LAN base address in located at BAR 1. */
+
+                       pci_ioaddr = pci_resource_start(pdev, 1);
+                       pci_set_master(pdev);
+
+                       printk("Found SAA9730 (PCI) at %#x, irq %d.\n",
+                              pci_ioaddr, pci_irq_line);
+                       if (!lan_saa9730_init
+                           (dev, pci_ioaddr, pci_irq_line)) return 0;
+                       else
+                               printk("Lan init failed.\n");
+               }
+       }
+
+       return -ENODEV;
+}
+
+module_init(saa9730_probe);
diff --git a/drivers/net/saa9730.h b/drivers/net/saa9730.h
new file mode 100644 (file)
index 0000000..f71fadc
--- /dev/null
@@ -0,0 +1,370 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * SAA9730 ethernet driver description.
+ *
+ */
+#ifndef _SAA9730_H
+#define _SAA9730_H
+
+
+/* Number of 6-byte entries in the CAM. */
+#define LAN_SAA9730_CAM_ENTRIES              10
+#define        LAN_SAA9730_CAM_DWORDS               ((LAN_SAA9730_CAM_ENTRIES*6)/4)
+
+/* TX and RX packet size: fixed to 2048 bytes, according to HW requirements. */
+#define LAN_SAA9730_PACKET_SIZE                       2048
+
+/* 
+ * Number of TX buffers = number of RX buffers = 2, which is fixed according 
+ * to HW requirements. 
+ */
+#define LAN_SAA9730_BUFFERS                           2
+
+/* Number of RX packets per RX buffer. */
+#define LAN_SAA9730_RCV_Q_SIZE                        15
+
+/* Number of TX packets per TX buffer. */
+#define LAN_SAA9730_TXM_Q_SIZE                        15
+
+/*
+ * We get an interrupt for each LAN_SAA9730_DEFAULT_RCV_Q_INT_THRESHOLD 
+ * packets received. 
+ * If however we receive less than  LAN_SAA9730_DEFAULT_RCV_Q_INT_THRESHOLD
+ * packets, the hardware can timeout after a certain time and still tell 
+ * us packets have arrived.
+ * The timeout value in unit of 32 PCI clocks (33Mhz).
+ * The value 200 approximates 0.0002 seconds.
+ */
+#define LAN_SAA9730_RCV_Q_INT_THRESHOLD               1
+#define LAN_SAA9730_DEFAULT_TIME_OUT_CNT              10
+
+#define RXSF_NDIS                       0
+#define RXSF_READY                      2
+#define RXSF_HWDONE                     3
+
+#define TXSF_EMPTY                      0
+#define TXSF_READY                      2
+#define TXSF_HWDONE                     3
+
+#define LANEND_LITTLE                   0
+#define LANEND_BIG_2143                 1
+#define LANEND_BIG_4321                 2
+
+#define LANMB_ANY                       0
+#define LANMB_8                         1
+#define LANMB_32                        2
+#define LANMB_64                        3
+
+#define MACCM_AUTOMATIC                 0
+#define MACCM_10MB                      1
+#define MACCM_MII                       2
+
+/* 
+ * PHY definitions for Basic registers of QS6612 (used on MIPS ATLAS board) 
+ */
+#define PHY_CONTROL                     0x0
+#define PHY_STATUS                      0x1
+#define PHY_STATUS_LINK_UP              0x4
+#define PHY_CONTROL_RESET               0x8000
+#define PHY_CONTROL_AUTO_NEG            0x1000
+#define PHY_CONTROL_RESTART_AUTO_NEG    0x0200
+#define PHY_ADDRESS                     0x0
+
+/* PK_COUNT register. */
+#define PK_COUNT_TX_A_SHF               24
+#define PK_COUNT_TX_A_MSK               (0xff << PK_COUNT_TX_A_SHF)
+#define PK_COUNT_TX_B_SHF               16
+#define PK_COUNT_TX_B_MSK               (0xff << PK_COUNT_TX_B_SHF)
+#define PK_COUNT_RX_A_SHF               8
+#define PK_COUNT_RX_A_MSK               (0xff << PK_COUNT_RX_A_SHF)
+#define PK_COUNT_RX_B_SHF               0
+#define PK_COUNT_RX_B_MSK               (0xff << PK_COUNT_RX_B_SHF)
+
+/* OK2USE register. */
+#define OK2USE_TX_A                     0x8
+#define OK2USE_TX_B                     0x4
+#define OK2USE_RX_A                     0x2
+#define OK2USE_RX_B                     0x1
+
+/* LAN DMA CONTROL register. */
+#define DMA_CTL_BLK_INT                 0x80000000
+#define DMA_CTL_MAX_XFER_SHF            18
+#define DMA_CTL_MAX_XFER_MSK            (0x3 << LAN_DMA_CTL_MAX_XFER_SHF)
+#define DMA_CTL_ENDIAN_SHF              16
+#define DMA_CTL_ENDIAN_MSK              (0x3 << LAN_DMA_CTL_ENDIAN_SHF)
+#define DMA_CTL_RX_INT_COUNT_SHF        8
+#define DMA_CTL_RX_INT_COUNT_MSK        (0xff << LAN_DMA_CTL_RX_INT_COUNT_SHF)
+#define DMA_CTL_EN_TX_DMA               0x00000080
+#define DMA_CTL_EN_RX_DMA               0x00000040
+#define DMA_CTL_RX_INT_BUFFUL_EN        0x00000020
+#define DMA_CTL_RX_INT_TO_EN            0x00000010
+#define DMA_CTL_RX_INT_EN               0x00000008
+#define DMA_CTL_TX_INT_EN               0x00000004
+#define DMA_CTL_MAC_TX_INT_EN           0x00000002
+#define DMA_CTL_MAC_RX_INT_EN           0x00000001
+
+/* DMA STATUS register. */
+#define DMA_STATUS_BAD_ADDR_SHF         16
+#define DMA_STATUS_BAD_ADDR_MSK         (0xf << DMA_STATUS_BAD_ADDR_SHF)
+#define DMA_STATUS_RX_PKTS_RECEIVED_SHF 8
+#define DMA_STATUS_RX_PKTS_RECEIVED_MSK (0xff << DMA_STATUS_RX_PKTS_RECEIVED_SHF)
+#define DMA_STATUS_TX_EN_SYNC           0x00000080
+#define DMA_STATUS_RX_BUF_A_FUL         0x00000040
+#define DMA_STATUS_RX_BUF_B_FUL         0x00000020
+#define DMA_STATUS_RX_TO_INT            0x00000010
+#define DMA_STATUS_RX_INT               0x00000008
+#define DMA_STATUS_TX_INT               0x00000004
+#define DMA_STATUS_MAC_TX_INT           0x00000002
+#define DMA_STATUS_MAC_RX_INT           0x00000001
+
+/* DMA TEST/PANIC SWITHES register. */
+#define DMA_TEST_LOOPBACK               0x01000000
+#define DMA_TEST_SW_RESET               0x00000001
+
+/* MAC CONTROL register. */
+#define MAC_CONTROL_EN_MISS_ROLL        0x00002000
+#define MAC_CONTROL_MISS_ROLL           0x00000400
+#define MAC_CONTROL_LOOP10              0x00000080
+#define MAC_CONTROL_CONN_SHF            5
+#define MAC_CONTROL_CONN_MSK            (0x3 << MAC_CONTROL_CONN_SHF)
+#define MAC_CONTROL_MAC_LOOP            0x00000010
+#define MAC_CONTROL_FULL_DUP            0x00000008
+#define MAC_CONTROL_RESET               0x00000004
+#define MAC_CONTROL_HALT_IMM            0x00000002
+#define MAC_CONTROL_HALT_REQ            0x00000001
+
+/* CAM CONTROL register. */
+#define CAM_CONTROL_COMP_EN             0x00000010
+#define CAM_CONTROL_NEG_CAM             0x00000008
+#define CAM_CONTROL_BROAD_ACC           0x00000004
+#define CAM_CONTROL_GROUP_ACC           0x00000002
+#define CAM_CONTROL_STATION_ACC         0x00000001
+
+/* TRANSMIT CONTROL register. */
+#define TX_CTL_EN_COMP                  0x00004000
+#define TX_CTL_EN_TX_PAR                0x00002000
+#define TX_CTL_EN_LATE_COLL             0x00001000
+#define TX_CTL_EN_EX_COLL               0x00000800
+#define TX_CTL_EN_L_CARR                0x00000400
+#define TX_CTL_EN_EX_DEFER              0x00000200
+#define TX_CTL_EN_UNDER                 0x00000100
+#define TX_CTL_MII10                    0x00000080
+#define TX_CTL_SD_PAUSE                 0x00000040
+#define TX_CTL_NO_EX_DEF0               0x00000020
+#define TX_CTL_F_BACK                   0x00000010
+#define TX_CTL_NO_CRC                   0x00000008
+#define TX_CTL_NO_PAD                   0x00000004
+#define TX_CTL_TX_HALT                  0x00000002
+#define TX_CTL_TX_EN                    0x00000001
+
+/* TRANSMIT STATUS register. */
+#define TX_STATUS_SQ_ERR                0x00010000
+#define TX_STATUS_TX_HALTED             0x00008000
+#define TX_STATUS_COMP                  0x00004000
+#define TX_STATUS_TX_PAR                0x00002000
+#define TX_STATUS_LATE_COLL             0x00001000
+#define TX_STATUS_TX10_STAT             0x00000800
+#define TX_STATUS_L_CARR                0x00000400
+#define TX_STATUS_EX_DEFER              0x00000200
+#define TX_STATUS_UNDER                 0x00000100
+#define TX_STATUS_IN_TX                 0x00000080
+#define TX_STATUS_PAUSED                0x00000040
+#define TX_STATUS_TX_DEFERRED           0x00000020
+#define TX_STATUS_EX_COLL               0x00000010
+#define TX_STATUS_TX_COLL_SHF           0
+#define TX_STATUS_TX_COLL_MSK           (0xf << TX_STATUS_TX_COLL_SHF)
+
+/* RECEIVE CONTROL register. */
+#define RX_CTL_EN_GOOD                  0x00004000
+#define RX_CTL_EN_RX_PAR                0x00002000
+#define RX_CTL_EN_LONG_ERR              0x00000800
+#define RX_CTL_EN_OVER                  0x00000400
+#define RX_CTL_EN_CRC_ERR               0x00000200
+#define RX_CTL_EN_ALIGN                 0x00000100
+#define RX_CTL_IGNORE_CRC               0x00000040
+#define RX_CTL_PASS_CTL                 0x00000020
+#define RX_CTL_STRIP_CRC                0x00000010
+#define RX_CTL_SHORT_EN                 0x00000008
+#define RX_CTL_LONG_EN                  0x00000004
+#define RX_CTL_RX_HALT                  0x00000002
+#define RX_CTL_RX_EN                    0x00000001
+
+/* RECEIVE STATUS register. */
+#define RX_STATUS_RX_HALTED             0x00008000
+#define RX_STATUS_GOOD                  0x00004000
+#define RX_STATUS_RX_PAR                0x00002000
+#define RX_STATUS_LONG_ERR              0x00000800
+#define RX_STATUS_OVERFLOW              0x00000400
+#define RX_STATUS_CRC_ERR               0x00000200
+#define RX_STATUS_ALIGN_ERR             0x00000100
+#define RX_STATUS_RX10_STAT             0x00000080
+#define RX_STATUS_INT_RX                0x00000040
+#define RX_STATUS_CTL_RECD              0x00000020
+
+/* MD_CA register. */
+#define MD_CA_PRE_SUP                   0x00001000
+#define MD_CA_BUSY                      0x00000800
+#define MD_CA_WR                        0x00000400
+#define MD_CA_PHY_SHF                   5
+#define MD_CA_PHY_MSK                   (0x1f << MD_CA_PHY_SHF)
+#define MD_CA_ADDR_SHF                  0
+#define MD_CA_ADDR_MSK                  (0x1f << MD_CA_ADDR_SHF)
+
+/* Tx Status/Control. */
+#define TX_STAT_CTL_OWNER_SHF           30
+#define TX_STAT_CTL_OWNER_MSK           (0x3 << TX_STAT_CTL_OWNER_SHF)
+#define TX_STAT_CTL_FRAME_SHF           27
+#define TX_STAT_CTL_FRAME_MSK           (0x7 << TX_STAT_CTL_FRAME_SHF)
+#define TX_STAT_CTL_STATUS_SHF          11
+#define TX_STAT_CTL_STATUS_MSK          (0x1ffff << TX_STAT_CTL_STATUS_SHF)
+#define TX_STAT_CTL_LENGTH_SHF          0
+#define TX_STAT_CTL_LENGTH_MSK          (0x7ff << TX_STAT_CTL_LENGTH_SHF)
+
+#define TX_STAT_CTL_ERROR_MSK           ((TX_STATUS_SQ_ERR      |     \
+                                         TX_STATUS_TX_HALTED   |     \
+                                         TX_STATUS_TX_PAR      |     \
+                                         TX_STATUS_LATE_COLL   |     \
+                                         TX_STATUS_L_CARR      |     \
+                                         TX_STATUS_EX_DEFER    |     \
+                                         TX_STATUS_UNDER       |     \
+                                         TX_STATUS_PAUSED      |     \
+                                         TX_STATUS_TX_DEFERRED |     \
+                                         TX_STATUS_EX_COLL     |     \
+                                         TX_STATUS_TX_COLL_MSK)      \
+                                                    << TX_STAT_CTL_STATUS_SHF)
+#define TX_STAT_CTL_INT_AFTER_TX        0x4
+
+/* Rx Status/Control. */
+#define RX_STAT_CTL_OWNER_SHF           30
+#define RX_STAT_CTL_OWNER_MSK           (0x3 << RX_STAT_CTL_OWNER_SHF)
+#define RX_STAT_CTL_STATUS_SHF          11
+#define RX_STAT_CTL_STATUS_MSK          (0xffff << RX_STAT_CTL_STATUS_SHF)
+#define RX_STAT_CTL_LENGTH_SHF          0
+#define RX_STAT_CTL_LENGTH_MSK          (0x7ff << RX_STAT_CTL_LENGTH_SHF)
+
+
+
+/* The SAA9730 (LAN) controller register map, as seen via the PCI-bus. */
+#define SAA9730_LAN_REGS_ADDR   0x20400
+
+struct lan_saa9730_regmap {
+       volatile unsigned int TxBuffA;                  /* 0x20400 */
+       volatile unsigned int TxBuffB;                  /* 0x20404 */
+       volatile unsigned int RxBuffA;                  /* 0x20408 */
+       volatile unsigned int RxBuffB;                  /* 0x2040c */
+       volatile unsigned int PacketCount;              /* 0x20410 */
+       volatile unsigned int Ok2Use;                   /* 0x20414 */
+       volatile unsigned int LanDmaCtl;                /* 0x20418 */
+       volatile unsigned int Timeout;                  /* 0x2041c */
+       volatile unsigned int DmaStatus;                /* 0x20420 */
+       volatile unsigned int DmaTest;                  /* 0x20424 */
+       volatile unsigned char filler20428[0x20430 - 0x20428];
+       volatile unsigned int PauseCount;               /* 0x20430 */
+       volatile unsigned int RemotePauseCount;         /* 0x20434 */
+       volatile unsigned char filler20438[0x20440 - 0x20438];
+       volatile unsigned int MacCtl;                   /* 0x20440 */
+       volatile unsigned int CamCtl;                   /* 0x20444 */
+       volatile unsigned int TxCtl;                    /* 0x20448 */
+       volatile unsigned int TxStatus;                 /* 0x2044c */
+       volatile unsigned int RxCtl;                    /* 0x20450 */
+       volatile unsigned int RxStatus;                 /* 0x20454 */
+       volatile unsigned int StationMgmtData;          /* 0x20458 */
+       volatile unsigned int StationMgmtCtl;           /* 0x2045c */
+       volatile unsigned int CamAddress;               /* 0x20460 */
+       volatile unsigned int CamData;                  /* 0x20464 */
+       volatile unsigned int CamEnable;                /* 0x20468 */
+       volatile unsigned char filler2046c[0x20500 - 0x2046c];
+       volatile unsigned int DebugPCIMasterAddr;       /* 0x20500 */
+       volatile unsigned int DebugLanTxStateMachine;   /* 0x20504 */
+       volatile unsigned int DebugLanRxStateMachine;   /* 0x20508 */
+       volatile unsigned int DebugLanTxFifoPointers;   /* 0x2050c */
+       volatile unsigned int DebugLanRxFifoPointers;   /* 0x20510 */
+       volatile unsigned int DebugLanCtlStateMachine;  /* 0x20514 */
+};
+typedef volatile struct lan_saa9730_regmap t_lan_saa9730_regmap;
+
+
+/* EVM interrupt control registers. */
+#define EVM_LAN_INT                     0x00010000
+#define EVM_MASTER_EN                   0x00000001
+
+/* The SAA9730 (EVM) controller register map, as seen via the PCI-bus. */
+#define SAA9730_EVM_REGS_ADDR   0x02000
+
+struct evm_saa9730_regmap {
+       volatile unsigned int InterruptStatus1;         /* 0x2000 */
+       volatile unsigned int InterruptEnable1;         /* 0x2004 */
+       volatile unsigned int InterruptMonitor1;        /* 0x2008 */
+       volatile unsigned int Counter;                  /* 0x200c */
+       volatile unsigned int CounterThreshold;         /* 0x2010 */
+       volatile unsigned int CounterControl;           /* 0x2014 */
+       volatile unsigned int GpioControl1;             /* 0x2018 */
+       volatile unsigned int InterruptStatus2;         /* 0x201c */
+       volatile unsigned int InterruptEnable2;         /* 0x2020 */
+       volatile unsigned int InterruptMonitor2;        /* 0x2024 */
+       volatile unsigned int GpioControl2;             /* 0x2028 */
+       volatile unsigned int InterruptBlock1;          /* 0x202c */
+       volatile unsigned int InterruptBlock2;          /* 0x2030 */
+};
+typedef volatile struct evm_saa9730_regmap t_evm_saa9730_regmap;
+
+
+struct lan_saa9730_private {
+       /* Pointer for the SAA9730 LAN controller register set. */
+       t_lan_saa9730_regmap *lan_saa9730_regs;
+
+       /* Pointer to the SAA9730 EVM register. */
+       t_evm_saa9730_regmap *evm_saa9730_regs;
+
+       /* TRUE if the next buffer to write is RxBuffA,  FALSE if RxBuffB. */
+       unsigned char NextRcvToUseIsA;
+       /* Rcv buffer Index. */
+       unsigned char NextRcvPacketIndex;
+
+       /* Index of next packet to use in that buffer. */
+       unsigned char NextTxmPacketIndex;
+       /* Next buffer index. */
+       unsigned char NextTxmBufferIndex;
+
+       /* Index of first pending packet ready to send. */
+       unsigned char PendingTxmPacketIndex;
+       /* Pending buffer index. */
+       unsigned char PendingTxmBufferIndex;
+
+       unsigned char DmaRcvPackets;
+       unsigned char DmaTxmPackets;
+
+       unsigned char RcvAIndex;        /* index into RcvBufferSpace[] for Blk A */
+       unsigned char RcvBIndex;        /* index into RcvBufferSpace[] for Blk B */
+
+       unsigned int
+           TxmBuffer[LAN_SAA9730_BUFFERS][LAN_SAA9730_TXM_Q_SIZE];
+       unsigned int
+           RcvBuffer[LAN_SAA9730_BUFFERS][LAN_SAA9730_RCV_Q_SIZE];
+       unsigned int TxBufferFree[LAN_SAA9730_BUFFERS];
+
+       unsigned char PhysicalAddress[LAN_SAA9730_CAM_ENTRIES][6];
+
+       struct net_device_stats stats;
+};
+
+#endif /* _SAA9730_H */
index f656fc5..37df045 100644 (file)
@@ -5269,7 +5269,7 @@ static int smctr_set_phy_drop(struct net_device *dev, MAC_SUB_VECTOR *rsv)
         return (POSITIVE_ACK);
 }
 
-/* Reset the ring speed to the oposite of what it was. This auto-pilot
+/* Reset the ring speed to the opposite of what it was. This auto-pilot
  * mode requires a complete reset and re-init of the adapter.
  */
 static int smctr_set_ring_speed(struct net_device *dev)
index a4e79a6..09c5d6c 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_PROC_FS) += proc.o
 #
 obj-$(CONFIG_ALPHA) += setup-bus.o setup-irq.o
 obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o
+obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o
 
 ifndef CONFIG_X86
 obj-y += syscall.o
index d47fc8a..4ccc318 100644 (file)
  * Architecture : 
  * This driver is built around a Linux queue of commands waiting to 
  * be executed, and a shared Linux/NCR array of commands to start.  Commands
- * are transfered to the array  by the run_process_issue_queue() function 
+ * are transferred to the array  by the run_process_issue_queue() function 
  * which is called whenever a command completes.
  *
  * As commands are completed, the interrupt routine is triggered,
@@ -1077,19 +1077,18 @@ NCR53c7x0_init (struct Scsi_Host *host) {
     {
        printk("scsi%d : IRQ%d not free, detaching\n",
                host->host_no, host->irq);
-       scsi_unregister (host);
-       return -1;
+       goto err_unregister;
     } 
 
     if ((hostdata->run_tests && hostdata->run_tests(host) == -1) ||
         (hostdata->options & OPTION_DEBUG_TESTS_ONLY)) {
        /* XXX Should disable interrupts, etc. here */
-       scsi_unregister (host);
-       return -1;
+       goto err_free_irq;
     } else {
        if (host->io_port)  {
            host->n_io_port = 128;
-           request_region (host->io_port, host->n_io_port, "ncr53c7xx");
+           if (!request_region (host->io_port, host->n_io_port, "ncr53c7xx"))
+               goto err_free_irq;
        }
     }
     
@@ -1098,6 +1097,12 @@ NCR53c7x0_init (struct Scsi_Host *host) {
        hard_reset (host);
     }
     return 0;
+
+ err_free_irq:
+    free_irq(host->irq,  NCR53c7x0_intr);
+ err_unregister:
+    scsi_unregister(host);
+    return -1;
 }
 
 /* 
@@ -1206,8 +1211,11 @@ ncr53c7xx_init (Scsi_Host_Template *tpnt, int board, int chip,
     size += 256;
 #endif
     /* Size should be < 8K, so we can fit it in two pages. */
-    if (size > 8192)
-      panic("53c7xx: hostdata > 8K");
+    if (size > 8192) {
+      printk(KERN_ERR "53c7xx: hostdata > 8K\n");
+      return -1;
+    }
+
     instance = scsi_register (tpnt, 4);
     if (!instance)
     {
@@ -3091,8 +3099,10 @@ allocate_cmd (Scsi_Cmnd *cmd) {
 #endif
 /* FIXME: for ISA bus '7xx chips, we need to or GFP_DMA in here */
 
-        if (size > 4096)
-            panic ("53c7xx: allocate_cmd size > 4K");
+        if (size > 4096) {
+            printk (KERN_ERR "53c7xx: allocate_cmd size > 4K\n");
+           return NULL;
+       }
         real = get_free_page(GFP_ATOMIC);
         if (real == 0)
                return NULL;
@@ -3272,7 +3282,7 @@ create_cmd (Scsi_Cmnd *cmd) {
 
     /*
      * The saved data pointer is set up so that a RESTORE POINTERS message 
-     * will start the data transfer over at the begining.
+     * will start the data transfer over at the beginning.
      */
 
     tmp->saved_data_pointer = virt_to_bus (hostdata->script) + 
@@ -4965,7 +4975,7 @@ intr_dma (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
      * chances of this happening, and handle it if it occurs anyway.
      *
      * Simply continue with what we were doing, and control should
-     * be transfered to the schedule routine which will ultimately
+     * be transferred to the schedule routine which will ultimately
      * pass control onto the reselection or selection (not yet)
      * code.
      */
index 5f26cde..9c5694a 100644 (file)
@@ -1136,7 +1136,7 @@ command_complete_msgin:
 #if (CHIP == 710)
 #if defined(MVME16x_INTFLY)
 ; For MVME16x (ie CHIP=710) we will force an INTFLY by triggering a software
-; interupt (SW7).  We can use SCRATCH, as we are about to jump to
+; interrupt (SW7).  We can use SCRATCH, as we are about to jump to
 ; schedule, which corrupts it anyway.  Will probably remove this later,
 ; but want to check performance effects first.
 
index 3dab7e6..7989cbd 100644 (file)
@@ -75,7 +75,7 @@
  *     Changed megaraid_command to use wait_queue.
  *
  * Version 1.00:
- *     Checks to see if an irq ocurred while in isr, and runs through
+ *     Checks to see if an irq occurred while in isr, and runs through
  *       routine again.
  *     Copies mailbox to temp area before processing in isr
  *     Added barrier() in busy wait to fix volatility bug
  *     Left 2.0 support but removed 2.1.x support.
  *     Collected much of the compat glue into one spot
  *
+ *     Version 1.14g-ac2 - 22/03/01
+ *     Fixed a non obvious dereference after free in the driver unload path
+ *
  * BUGS:
  *     Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that
  *     fails to detect the controller as a pci device on the system.
@@ -392,17 +395,19 @@ static void WROUTDOOR (mega_host_config * megaCfg, ulong value)
 }
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)        /* 0x020200 */
+#include <linux/smp.h>
+#define cpuid smp_processor_id()
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)        /* 0x020100 */
 
 /*
- *     Linux 2.2 and higher
+ *     Linux 2.4 and higher
  *
  *     No driver private lock
  *     Use the io_request_lock not cli/sti
  *     queue task is a simple api without irq forms
  */
-#include <linux/smp.h>
-#define cpuid smp_processor_id()
 
 MODULE_AUTHOR ("American Megatrends Inc.");
 MODULE_DESCRIPTION ("AMI MegaRAID driver");
@@ -415,18 +420,42 @@ MODULE_DESCRIPTION ("AMI MegaRAID driver");
 #define IO_LOCK spin_lock_irqsave(&io_request_lock,io_flags);
 #define IO_UNLOCK spin_unlock_irqrestore(&io_request_lock,io_flags);
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) /* 0x020400 */
+#define queue_task_irq(a,b)     queue_task(a,b)
+#define queue_task_irq_off(a,b) queue_task(a,b)
+
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)      /* 0x020200 */
+
+/*
+ *     Linux 2.2 and higher
+ *
+ *     No driver private lock
+ *     Use the io_request_lock not cli/sti
+ *     No pci region api
+ *     queue_task is now a single simple API
+ */
+
+static char kernel_version[] = UTS_RELEASE;
+MODULE_AUTHOR ("American Megatrends Inc.");
+MODULE_DESCRIPTION ("AMI MegaRAID driver");
+
+#define DRIVER_LOCK_T
+#define DRIVER_LOCK_INIT(p)
+#define DRIVER_LOCK(p)
+#define DRIVER_UNLOCK(p)
+#define IO_LOCK_T unsigned long io_flags = 0;
+#define IO_LOCK spin_lock_irqsave(&io_request_lock,io_flags);
+#define IO_UNLOCK spin_unlock_irqrestore(&io_request_lock,io_flags);
+
 #define pci_free_consistent(a,b,c,d)
 #define pci_unmap_single(a,b,c,d,e)
 
 #define init_MUTEX_LOCKED(x)   ((x)=MUTEX_LOCKED)
 #define init_MUTEX(x)          ((x)=MUTEX)
 
-#define DECLARE_WAIT_QUEUE_HEAD(x)     struct wait_queue *x = NULL
-#endif
-
 #define queue_task_irq(a,b)     queue_task(a,b)
 #define queue_task_irq_off(a,b) queue_task(a,b)
+
+#define DECLARE_WAIT_QUEUE_HEAD(x)     struct wait_queue *x = NULL
 #else
 
 /*
@@ -2738,7 +2767,6 @@ static int megaraid_release (struct Scsi_Host *pSHost)
                             sizeof (mega_mailbox64),
                             (void *) megaCfg->mailbox64ptr,
                             megaCfg->dma_handle64);
-       scsi_unregister (pSHost);
 
 #ifdef CONFIG_PROC_FS
        if (megaCfg->controller_proc_dir_entry) {
@@ -2759,12 +2787,21 @@ static int megaraid_release (struct Scsi_Host *pSHost)
 #endif
 
        /*
+        *      Release the controller memory. A word of warning this frees
+        *      hostdata and that includes megaCfg-> so be careful what you
+        *      dereference beyond this point
+        */
+        
+       scsi_unregister (pSHost);
+
+       /*
         * Unregister the character device interface to the driver. Ideally this
         * should have been done in cleanup_module routine. Since this is hidden
         * in file "scsi_module.c", we do it here.
         * major is the major number of the character device returned by call to
         * register_chrdev() routine.
         */
+
        unregister_chrdev (major, "megadev");
        unregister_reboot_notifier (&mega_notifier);
 
@@ -4274,8 +4311,9 @@ megadev_close (struct inode *inode, struct file *filep)
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 static
-#endif
+#endif                         /* LINUX VERSION 2.4.XX */
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) || defined(MODULE)
 Scsi_Host_Template driver_template = MEGARAID;
+
 #include "scsi_module.c"
-#endif
+#endif                         /* LINUX VERSION 2.4.XX || MODULE */
index 11d230a..372ba7a 100644 (file)
@@ -27,7 +27,7 @@
 #define M_RD_IOCTL_CMD_NEW             0x81
 #define M_RD_DRIVER_IOCTL_INTERFACE    0x82
 
-#define MEGARAID_VERSION "v1.14g (Release Date: Feb 5, 2001; 11:42)"
+#define MEGARAID_VERSION "v1.14g-ac2 (Release Date: Mar 22, 2001; 19:34:02)"
 #define MEGARAID_IOCTL_VERSION         114
 
 /* Methods */
index c671ba7..07c4a36 100644 (file)
@@ -195,8 +195,8 @@ struct {
 #define FLASH_BIOS_ADDR        0x00
 #define FLASH_BIOS_DATA        0x02
 #define ISP_CTRL_STATUS        0x06    /* configuration register #1 */
-#define PCI_INTER_CTL  0x08    /* pci interupt control */
-#define PCI_INTER_STS  0x0a    /* pci interupt status */
+#define PCI_INTER_CTL  0x08    /* pci interrupt control */
+#define PCI_INTER_STS  0x0a    /* pci interrupt status */
 #define PCI_SEMAPHORE  0x0c    /* pci semaphore */
 #define PCI_NVRAM      0x0e    /* pci nvram interface */
 
@@ -227,7 +227,7 @@ struct {
 #define REQUEST_TRANSFER_ERROR         0x8003
 #define RESPONSE_TRANSFER_ERROR                0x8004
 #define REQUEST_QUEUE_WAKEUP           0x8005
-#define LIP_OCCURED                     0x8010
+#define LIP_OCCURRED                     0x8010
 #define LOOP_UP                         0x8011
 #define LOOP_DOWN                       0x8012
 #define LIP_RECEIVED                    0x8013
@@ -369,7 +369,7 @@ struct Status_Entry {
 #define STF_ABORTED                    0x0020
 #define STF_TIMEOUT                    0x0040
 
-/* interupt control commands */
+/* interrupt control commands */
 #define ISP_EN_INT                     0x8000
 #define ISP_EN_RISC                    0x0008
 
@@ -757,6 +757,10 @@ int isp2x00_detect(Scsi_Host_Template * tmpt)
                                continue;
 
                        host = scsi_register(tmpt, sizeof(struct isp2x00_hostdata));
+                       if (!host) {
+                               printk("qlogicfc%d : could not register host.\n", hostdata->host_id);
+                               continue;
+                       }
                        host->max_id = QLOGICFC_MAX_ID + 1;
                        host->max_lun = QLOGICFC_MAX_LUN;
                        host->hostt->use_new_eh_code = 1;
@@ -768,6 +772,7 @@ int isp2x00_detect(Scsi_Host_Template * tmpt)
 
                        if (!hostdata->res){
                                printk("qlogicfc%d : could not allocate memory for request and response queue.\n", hostdata->host_id);
+                               pci64_free_consistent(pdev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);
                                scsi_unregister(host);
                                continue;
                        }
@@ -813,7 +818,7 @@ int isp2x00_detect(Scsi_Host_Template * tmpt)
                                scsi_unregister(host);
                                continue;
                        }
-                       if (check_region(host->io_port, 0xff)) {
+                       if (!request_region(host->io_port, 0xff, "qlogicfc")) {
                                printk("qlogicfc%d : i/o region 0x%lx-0x%lx already "
                                       "in use\n",
                                       hostdata->host_id, host->io_port, host->io_port + 0xff);
@@ -822,7 +827,6 @@ int isp2x00_detect(Scsi_Host_Template * tmpt)
                                scsi_unregister(host);
                                continue;
                        }
-                       request_region(host->io_port, 0xff, "qlogicfc");
 
                        outw(0x0, host->io_port + PCI_SEMAPHORE);
                        outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
@@ -1520,7 +1524,7 @@ void isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
                        if (hostdata->adapter_state == AS_LOOP_GOOD)
                                hostdata->adapter_state = AS_REDO_FABRIC_PORTDB;
                        break;                  
-               case LIP_OCCURED:
+               case LIP_OCCURRED:
                case LIP_RECEIVED:
                        printk("qlogicfc%d : Loop Reinitialized\n", hostdata->host_id);
                        if (hostdata->adapter_state == AS_LOOP_GOOD)
index fe070f7..2b42fcd 100644 (file)
@@ -7,17 +7,13 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
-SUB_DIRS     :=
-MOD_SUB_DIRS := $(SUB_DIRS) char
-ALL_SUB_DIRS := $(SUB_DIRS) char
-
-
-L_OBJS   := 
 L_TARGET := sgi.a
 
+#
 # Character and Audio devices for SGI machines.
 #
-SUB_DIRS += char
-L_OBJS += char/sgichar.o
+subdir-y       += char
+subdir-m       += char
+obj-y          += char/sgichar.o
 
 include $(TOPDIR)/Rules.make
index 57761e4..b6fec19 100644 (file)
@@ -8,25 +8,12 @@
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
 O_TARGET := sgichar.o
-OX_OBJS := newport.o
-O_OBJS   := sgicons.o \
-       usema.o shmiq.o streamable.o
 
-ifeq ($(CONFIG_SGI_SERIAL),y)
-  O_OBJS += sgiserial.o
-endif
+export-objs    := newport.o shmiq.o sgicons.o usema.o
+obj-y          := newport.o shmiq.o sgicons.o usema.o streamable.o
 
-ifeq ($(CONFIG_SGI_DS1286),y)
-  O_OBJS += ds1286.o
-endif
-
-ifeq ($(CONFIG_SGI_NEWPORT_GFX),y)
-  O_OBJS +=  graphics.o rrm.o
-else 
-ifeq ($(CONFIG_SGI_NEWPORT_GFX),m)
-  OX_OBJS  +=  graphics_syms.o
-  MX_OBJS +=  graphics.o rrm.o
-endif
-endif
+obj-$(CONFIG_SGI_SERIAL)       += sgiserial.o
+obj-$(CONFIG_SGI_DS1286)       += ds1286.o
+obj-$(CONFIG_SGI_NEWPORT_GFX)  += graphics.o rrm.o
 
 include $(TOPDIR)/Rules.make
index 51fd933..9e15c10 100644 (file)
@@ -93,7 +93,7 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
    fi
    dep_tristate '    Aztech Sound Galaxy (non-PnP) cards' CONFIG_SOUND_SGALAXY $CONFIG_SOUND_OSS
    dep_tristate '    Adlib Cards' CONFIG_SOUND_ADLIB $CONFIG_SOUND_OSS
-   dep_tristate '    ACI mixer (miroPCM12)' CONFIG_SOUND_ACI_MIXER $CONFIG_SOUND_OSS
+   dep_tristate '    ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20)' CONFIG_SOUND_ACI_MIXER $CONFIG_SOUND_OSS
    dep_tristate '    Crystal CS4232 based (PnP) cards' CONFIG_SOUND_CS4232 $CONFIG_SOUND_OSS
    dep_tristate '    Ensoniq SoundScape support' CONFIG_SOUND_SSCAPE $CONFIG_SOUND_OSS
    dep_tristate '    Gravis Ultrasound support' CONFIG_SOUND_GUS $CONFIG_SOUND_OSS
@@ -171,8 +171,10 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
    fi
         
    if [ "$CONFIG_ARM" = "y" ]; then
-      dep_tristate '    VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS
-      dep_tristate '    Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS
+      if [ "$CONFIG_ARCH_ACORN" = "y" -o "$CONFIG_ARCH_CLPS7500" = "y" ]; then
+         dep_tristate '    VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS
+      fi
+      dep_tristate '    Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS $CONFIG_ARCH_NETWINDER
    fi
 
 fi
index baddec5..b2ba794 100644 (file)
@@ -10,7 +10,7 @@
 export-objs    :=  ad1848.o audio_syms.o midi_syms.o mpu401.o \
                    msnd.o opl3.o sb_common.o sequencer_syms.o \
                    sound_core.o sound_syms.o uart401.o \
-                   nm256_audio.o ac97.o ac97_codec.o
+                   nm256_audio.o ac97.o ac97_codec.o aci.o
 
 # Each configuration option enables a list of files.
 
@@ -29,7 +29,7 @@ obj-$(CONFIG_SOUND_MAD16)     += mad16.o ad1848.o sb_lib.o uart401.o
 obj-$(CONFIG_SOUND_CS4232)     += cs4232.o uart401.o
 obj-$(CONFIG_SOUND_OPL3SA2)    += opl3sa2.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_MSS)                += ad1848.o
-obj-$(CONFIG_SOUND_PAS)                += pas2.o sb_lib.o uart401.o
+obj-$(CONFIG_SOUND_PAS)                += pas2.o sb.o sb_lib.o uart401.o
 obj-$(CONFIG_SOUND_SB)         += sb.o sb_lib.o uart401.o
 obj-$(CONFIG_SOUND_WAVEFRONT)  += wavefront.o
 obj-$(CONFIG_SOUND_MAUI)       += maui.o mpu401.o
index 3e75448..f05ef40 100644 (file)
  * The main function of the ACI is to control the mixer and to get a
  * product identification. On the PCM20, ACI also controls the radio
  * tuner on this card, this is supported in the Video for Linux 
- * radio-miropcm20 driver.
- * 
- * This Voxware ACI driver currently only supports the ACI functions
- * on the miroSOUND PCM12 and PCM20 card. Support for miro sound cards 
- * with additional ACI functions can easily be added later.
+ * miropcm20 driver.
+ * -
+ * This is a fullfeatured implementation. Unsupported features
+ * are bugs... (:
+ *
+ * It is not longer necessary to load the mad16 module first. The
+ * user is currently responsible to set the mad16 mixer correctly.
  *
- * / NOTE / When compiling as a module, make sure to load the module 
- * after loading the mad16 module. The initialisation code expects the
- * MAD16 default mixer to be already available.
+ * To toggle the solo mode for full duplex operation just use the OSS
+ * record switch for the pcm ('wave') controller.           Robert
+ * -
  *
  * Revision history:
  *
  *   1998-08-18  Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
  *       Small modification to export ACI functions and 
  *       complete modularisation.
+ *   2000-06-20  Robert Siemer <Robert.Siemer@gmx.de>
+ *        Don't initialize the CS4231A mixer anymore, so the code is
+ *        working again, and other small changes to fit in todays
+ *        kernels.
+ *   2000-08-26  Robert Siemer
+ *        Clean up and rewrite for 2.4.x. Maybe it's SMP safe now... (:
+ *        ioctl bugfix, and integration of solo-mode into OSS-API,
+ *        added (OSS-limited) equalizer support, return value bugfix,
+ *        changed param aci_reset to reset, new params: ide, wss.
  */
 
-/*
- * Some driver specific information and features:
- *
- * This mixer driver identifies itself to applications as "ACI" in
- * mixer_info.id as retrieved by ioctl(fd, SOUND_MIXER_INFO, &mixer_info).
- *
- * Proprietary mixer features that go beyond the standard OSS mixer
- * interface are:
- * 
- * Full duplex solo configuration:
- *
- *   int solo_mode;
- *   ioctl(fd, SOUND_MIXER_PRIVATE1, &solo_mode);
- *
- *   solo_mode = 0: deactivate solo mode (default)
- *   solo_mode > 0: activate solo mode
- *                  With activated solo mode, the PCM input can not any
- *                  longer hear the signals produced by the PCM output.
- *                  Activating solo mode is important in duplex mode in order
- *                  to avoid feedback distortions.
- *   solo_mode < 0: do not change solo mode (just retrieve the status)
- *
- *   When the ioctl() returns 0, solo_mode contains the previous
- *   status (0 = deactivated, 1 = activated). If solo mode is not
- *   implemented on this card, ioctl() returns -1 and sets errno to
- *   EINVAL.
- *
- */
-
+#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h> 
-
+#include <linux/proc_fs.h>
+#include <linux/slab.h>
+#include <asm/semaphore.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
 #include "sound_config.h"
 
-#undef  DEBUG          /* if defined, produce a verbose report via syslog */
+int aci_port;  /* as determined by bit 4 in the OPTi 929 MC4 register */
+int aci_idcode[2];     /* manufacturer and product ID */
+int aci_version;       /* ACI firmware version */
+
+EXPORT_SYMBOL(aci_port);
+EXPORT_SYMBOL(aci_idcode);
+EXPORT_SYMBOL(aci_version);
 
-int aci_port = 0x354;  /* as determined by bit 4 in the OPTi 929 MC4 register */
-unsigned char aci_idcode[2] = {0, 0};  /* manufacturer and product ID */
-unsigned char aci_version = 0;         /* ACI firmware version */
-int aci_solo;          /* status bit of the card that can't be         *
+#include "aci.h"
+
+
+static int aci_solo=0; /* status bit of the card that can't be         *
+                        * checked with ACI versions prior to 0xb0      */
+static int aci_amp=0;   /* status bit for power-amp/line-out level
+                          but I have no docs about what is what... */
+static int aci_micpreamp=3; /* microphone preamp-level that can't be    *
                         * checked with ACI versions prior to 0xb0      */
 
-static int aci_present = 0;
+static int mixer_device;
+static struct semaphore aci_sem;
 
-#ifdef MODULE                  /* Whether the aci mixer is to be reset.    */
-int aci_reset = 0;             /* Default: don't reset if the driver is a  */
-MODULE_PARM(aci_reset,"i");
-#else                          /* module; use "insmod aci.o aci_reset=1" */
-int aci_reset = 1;             /* to override.                             */
+#ifdef MODULE
+static int reset = 0;
+MODULE_PARM(reset,"i");
+MODULE_PARM_DESC(reset,"When set to 1, reset aci mixer.");
+#else
+static int reset = 1;
 #endif
 
+static int ide=-1;
+MODULE_PARM(ide,"i");
+MODULE_PARM_DESC(ide,"1 enable, 0 disable ide-port - untested"
+                " default: do nothing");
+static int wss=-1;
+MODULE_PARM(wss,"i");
+MODULE_PARM_DESC(wss,"change between ACI/WSS-mixer; use 0 and 1 - untested"
+                " default: do nothing; for PCM1-pro only");
+
+static void print_bits(unsigned char c)
+{
+       int j;
+       printk(KERN_DEBUG "aci: ");
+
+       for (j=7; j>=0; j--) {
+               printk(KERN_DEBUG "%d", (c >> j) & 0x1);
+       }
 
-#define COMMAND_REGISTER    (aci_port)
-#define STATUS_REGISTER     (aci_port + 1)
-#define BUSY_REGISTER       (aci_port + 2)
+       printk(KERN_DEBUG "\n");
+}
 
 /*
- * Wait until the ACI microcontroller has set the READYFLAG in the
- * Busy/IRQ Source Register to 0. This is required to avoid
- * overrunning the sound card microcontroller. We do a busy wait here,
- * because the microcontroller is not supposed to signal a busy
- * condition for more than a few clock cycles. In case of a time-out,
- * this function returns -1.
- *
  * This busy wait code normally requires less than 15 loops and
  * practically always less than 100 loops on my i486/DX2 66 MHz.
  *
@@ -107,459 +115,476 @@ int aci_reset = 1;             /* to override.                             */
  * function can take a VERY long time, because the PCM12 does some kind
  * of fade-in effect. For this reason, access to the MUTE function has
  * not been implemented at all.
+ *
+ * - The OSS interface has no mute option. It takes about 3 seconds to
+ * fade-in on my PCM20. busy_wait() handles it great now...     Robert
  */
 
 static int busy_wait(void)
 {
+       #define MINTIME 500
        long timeout;
+       unsigned char byte;
 
-       for (timeout = 0; timeout < 10000000L; timeout++)
-               if ((inb_p(BUSY_REGISTER) & 1) == 0)
-                       return 0;
-
-#ifdef DEBUG
-       printk("ACI: READYFLAG timed out.\n");
-#endif
-
-       return -1;
-}
-
-
-/*
- * Read the GENERAL STATUS register.
- */
-
-static int read_general_status(void)
-{
-       unsigned long flags;
-       int status;
-
-       save_flags(flags);
-       cli();
-       
-       if (busy_wait()) {
-               restore_flags(flags);
-               return -1;
+       for (timeout = 1; timeout <= MINTIME+30; timeout++) {
+               if (((byte=inb(BUSY_REGISTER)) & 1) == 0) {
+                       if (timeout >= MINTIME)
+                               printk(KERN_DEBUG "aci: Got READYFLAG in round %ld.\n", timeout-MINTIME);
+                       return byte;
+               }
+               if (timeout >= MINTIME) {
+                       long out=10*HZ;
+                       switch (timeout-MINTIME) {
+                       case 0 ... 9:
+                               out /= 10;
+                       case 10 ... 19:
+                               out /= 10;
+                       case 20 ... 30:
+                               out /= 10;
+                       default:
+                               current->state=TASK_UNINTERRUPTIBLE;
+                               schedule_timeout(out);
+                               break;
+                       }
+               }
        }
-       
-       status = (unsigned) inb_p(STATUS_REGISTER);
-       restore_flags(flags);
-       return status;
+       printk(KERN_WARNING "aci: busy_wait() time out.\n");
+       return -EBUSY;
 }
 
+/* The four ACI command types are fucked up. [-:
+ * implied is: 1w      - special case for INIT
+ * write   is: 2w1r
+ * read    is: x(1w1r) where x is 1 or 2 (1 CHECK_SIG, 1 CHECK_STER,
+ *                                        1 VERSION, 2 IDCODE)
+ *  the command is only in the first write, rest is protocol overhead
+ *
+ * indexed is technically a write and used for STATUS
+ * and the special case for TUNE is: 3w1r
+ * 
+ * Here the new general sheme: TUNE --> aci_rw_cmd(x,  y,  z)
+ *                indexed and write --> aci_rw_cmd(x,  y, -1)
+ *           implied and read (x=1) --> aci_rw_cmd(x, -1, -1)
+ *
+ * Read (x>=2) is not implemented (only used during initialization).
+ * Use aci_idcode[2] and aci_version...                    Robert
+ */
 
-/*
- * The four ACI command types (implied, write, read and indexed) can
- * be sent to the microcontroller using the following four functions.
- * If a problem occurred, they return -1.
+/* Some notes for error detection: theoretically it is possible.
+ * But it doubles the I/O-traffic from ww(r) to wwwrw(r) in the normal 
+ * case and doesn't seem to be designed for that...        Robert
  */
 
-int aci_implied_cmd(unsigned char opcode)
+static inline int aci_rawwrite(unsigned char byte)
 {
-       unsigned long flags;
-
-#ifdef DEBUG
-       printk("ACI: aci_implied_cmd(0x%02x)\n", opcode);
+       if (busy_wait() >= 0) {
+#if DEBUG
+               printk(KERN_DEBUG "aci_rawwrite(%d)\n", byte);
 #endif
-
-       save_flags(flags);
-       cli();
-  
-       if (read_general_status() < 0 || busy_wait()) {
-               restore_flags(flags);
-               return -1;
-       }
-       
-       outb_p(opcode, COMMAND_REGISTER);
-
-       restore_flags(flags);
-       return 0;
+               outb(byte, COMMAND_REGISTER);
+               return 0;
+       } else
+               return -EBUSY;
 }
 
-
-int aci_write_cmd(unsigned char opcode, unsigned char parameter)
+static inline int aci_rawread(void)
 {
-       unsigned long flags;
-       int status;
+       unsigned char byte;
 
-#ifdef DEBUG
-       printk("ACI: aci_write_cmd(0x%02x, 0x%02x)\n", opcode, parameter);
+       if (busy_wait() >= 0) {
+               byte=inb(STATUS_REGISTER);
+#if DEBUG
+               printk(KERN_DEBUG "%d = aci_rawread()\n", byte);
 #endif
+               return byte;
+       } else
+               return -EBUSY;
+}
 
-       save_flags(flags);
-       cli();
-       
-       if (read_general_status() < 0 || busy_wait()) {
-               restore_flags(flags);
-               return -1;
-       }
 
-       outb_p(opcode, COMMAND_REGISTER);
-       if (busy_wait()) {
-               restore_flags(flags);
-               return -1;
-       }
+int aci_rw_cmd(int write1, int write2, int write3)
+{
+       int write[] = {write1, write2, write3};
+       int read, i;
 
-       outb_p(parameter, COMMAND_REGISTER);
+       if (down_interruptible(&aci_sem))
+               return -EINTR;
 
-       if ((status = read_general_status()) < 0) {
-               restore_flags(flags);
-               return -1;
+       for (i=0; i<3; i++) {
+               if (write[i]< 0 || write[i] > 255)
+                       break;
+               else
+                       if (aci_rawwrite(write[i])<0) {
+                               up(&aci_sem);
+                               return -EBUSY;
+                       }
        }
-
-       /* polarity of the INVALID flag depends on ACI version */
-       if ((aci_version <  0xb0 && (status & 0x40) != 0) ||
-         (aci_version >= 0xb0 && (status & 0x40) == 0)) {
-               restore_flags(flags);
-               printk("ACI: invalid write command 0x%02x, 0x%02x.\n",
-                       opcode, parameter);
-               return -1;
+       
+       if ((read=aci_rawread())<0) {
+               up(&aci_sem);
+               return -EBUSY;
        }
 
-       restore_flags(flags);
-       return 0;
+       up(&aci_sem);
+       return read;
 }
 
-/*
- * This write command send 2 parameters instead of one.
- * Only used in PCM20 radio frequency tuning control
- */
+EXPORT_SYMBOL(aci_rw_cmd);
 
-int aci_write_cmd_d(unsigned char opcode, unsigned char parameter, unsigned char parameter2)
+static int setvolume(caddr_t arg, 
+                    unsigned char left_index, unsigned char right_index)
 {
-       unsigned long flags;
-       int status;
+       int vol, ret, uservol, buf;
 
-#ifdef DEBUG
-       printk("ACI: aci_write_cmd_d(0x%02x, 0x%02x)\n", opcode, parameter, parameter2);
-#endif
+       __get_user(uservol, (int *)arg);
 
-       save_flags(flags);
-       cli();
-       
-       if (read_general_status() < 0 || busy_wait()) {
-               restore_flags(flags);
-               return -1;
-       }
+       /* left channel */
+       vol = uservol & 0xff;
+       if (vol > 100)
+               vol = 100;
+       vol = SCALE(100, 0x20, vol);
+       if ((buf=aci_write_cmd(left_index, 0x20 - vol))<0)
+               return buf;
+       ret = SCALE(0x20, 100, vol);
 
-       outb_p(opcode, COMMAND_REGISTER);
-       if (busy_wait()) {
-               restore_flags(flags);
-               return -1;
-       }
 
-       outb_p(parameter, COMMAND_REGISTER);
-       if (busy_wait()) {
-               restore_flags(flags);
-               return -1;
-       }
-       
-       outb_p(parameter2, COMMAND_REGISTER);
-       
-       if ((status = read_general_status()) < 0) {
-               restore_flags(flags);
-               return -1;
-       }
-       
-       /* polarity of the INVALID flag depends on ACI version */
-       if ((aci_version <  0xb0 && (status & 0x40) != 0) ||
-         (aci_version >= 0xb0 && (status & 0x40) == 0)) {
-               restore_flags(flags);
-#if 0  /* Frequency tuning works, but the INVALID flag is set ??? */
-               printk("ACI: invalid write (double) command 0x%02x, 0x%02x, 0x%02x.\n",
-                       opcode, parameter, parameter2);
-#endif
-               return -1;
-       }
-       
-       restore_flags(flags);
-       return 0;
-}
-
-int aci_read_cmd(unsigned char opcode, int length, unsigned char *parameter)
-{
-       unsigned long flags;
-       int i = 0;
-       
-       save_flags(flags);
-       cli();
+       /* right channel */
+       vol = (uservol >> 8) & 0xff;
+       if (vol > 100)
+               vol = 100;
+       vol = SCALE(100, 0x20, vol);
+       if ((buf=aci_write_cmd(right_index, 0x20 - vol))<0)
+               return buf;
+       ret |= SCALE(0x20, 100, vol) << 8;
  
-       if (read_general_status() < 0) {
-               restore_flags(flags);
-               return -1;
-       }
-       while (i < length) {
-               if (busy_wait()) {
-                       restore_flags(flags);
-                       return -1;
-               }
-                       
-               outb_p(opcode, COMMAND_REGISTER);
-               if (busy_wait()) {
-                       restore_flags(flags);
-                       return -1;
-               }
-                       
-               parameter[i++] = inb_p(STATUS_REGISTER);
-#ifdef DEBUG
-               if (i == 1)
-                       printk("ACI: aci_read_cmd(0x%02x, %d) = 0x%02x\n",
-                               opcode, length, parameter[i-1]);
-               else
-                       printk("ACI: aci_read_cmd cont.: 0x%02x\n", parameter[i-1]);
-#endif
-       }
+       __put_user(ret, (int *)arg);
 
-       restore_flags(flags);
        return 0;
 }
 
-
-int aci_indexed_cmd(unsigned char opcode, unsigned char index,
-                      unsigned char *parameter)
+static int getvolume(caddr_t arg,
+                    unsigned char left_index, unsigned char right_index)
 {
-       unsigned long flags;
-
-       save_flags(flags);
-       cli();
-  
-       if (read_general_status() < 0 || busy_wait()) {
-               restore_flags(flags);
-               return -1;
-       }
-       
-       outb_p(opcode, COMMAND_REGISTER);
-       if (busy_wait()) {
-               restore_flags(flags);
-               return -1;
-       }
-       
-       outb_p(index, COMMAND_REGISTER);
-       if (busy_wait()) {
-               restore_flags(flags);
-               return -1;
-       }
+       int vol;
+       int buf;
+
+       /* left channel */
+       if ((buf=aci_indexed_cmd(0xf0, left_index))<0)
+               return buf;
+       vol = SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0);
        
-       *parameter = inb_p(STATUS_REGISTER);
-#ifdef DEBUG
-       printk("ACI: aci_indexed_cmd(0x%02x, 0x%02x) = 0x%02x\n", opcode, index,
-               *parameter);
-#endif
+       /* right channel */
+       if ((buf=aci_indexed_cmd(0xf0, right_index))<0)
+               return buf;
+       vol |= SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0) << 8;
+
+       __put_user(vol, (int *)arg);
 
-       restore_flags(flags);
        return 0;
 }
 
 
-/*
- * The following macro SCALE can be used to scale one integer volume
- * value into another one using only integer arithmetic. If the input
- * value x is in the range 0 <= x <= xmax, then the result will be in
- * the range 0 <= SCALE(xmax,ymax,x) <= ymax.
- *
- * This macro has for all xmax, ymax > 0 and all 0 <= x <= xmax the
- * following nice properties:
- *
- * - SCALE(xmax,ymax,xmax) = ymax
- * - SCALE(xmax,ymax,0) = 0
- * - SCALE(xmax,ymax,SCALE(ymax,xmax,SCALE(xmax,ymax,x))) = SCALE(xmax,ymax,x)
- *
- * In addition, the rounding error is minimal and nicely distributed.
- * The proofs are left as an exercise to the reader.
+/* The equalizer is somewhat strange on the ACI. From -12dB to +12dB
+ * write:  0xff..down.to..0x80==0x00..up.to..0x7f
  */
 
-#define SCALE(xmax,ymax,x) (((x)*(ymax)+(xmax)/2)/(xmax))
+static inline unsigned int eq_oss2aci(unsigned int vol)
+{
+       int boost=0;
+       unsigned int ret;
+
+       if (vol > 100)
+               vol = 100;
+       if (vol > 50) {
+               vol -= 51;
+               boost=1;
+       }
+       if (boost)
+               ret=SCALE(49, 0x7e, vol)+1;
+       else
+               ret=0xff - SCALE(50, 0x7f, vol);
+       return ret;
+}
+
+static inline unsigned int eq_aci2oss(unsigned int vol)
+{
+       if (vol < 0x80)
+               return SCALE(0x7f, 50, vol) + 50;
+       else
+               return SCALE(0x7f, 50, 0xff-vol);
+}
 
 
-static int getvolume(caddr_t arg,
-                    unsigned char left_index, unsigned char right_index)
+static int setequalizer(caddr_t arg, 
+                       unsigned char left_index, unsigned char right_index)
 {
-       int vol;
-       unsigned char buf;
+       int buf;
+       unsigned int vol;
+
+       __get_user(vol, (int *)arg);
 
        /* left channel */
-       if (aci_indexed_cmd(0xf0, left_index, &buf))
-               return -EIO;
-       vol = SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0);
-       
+       if ((buf=aci_write_cmd(left_index, eq_oss2aci(vol & 0xff)))<0)
+               return buf;
+
        /* right channel */
-       if (aci_indexed_cmd(0xf0, right_index, &buf))
-               return -EIO;
-       vol |= SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0) << 8;
+       if ((buf=aci_write_cmd(right_index, eq_oss2aci((vol>>8) & 0xff)))<0)
+               return buf;
 
-       return (*(int *) arg = vol);
+       /* the ACI equalizer is more precise */
+       return 0;
 }
 
-
-static int setvolume(caddr_t arg, 
-                    unsigned char left_index, unsigned char right_index)
+static int getequalizer(caddr_t arg,
+                       unsigned char left_index, unsigned char right_index)
 {
-       int vol, ret;
+       int buf;
+       unsigned int vol;
 
        /* left channel */
-       vol = *(int *)arg & 0xff;
-       if (vol > 100)
-               vol = 100;
-       vol = SCALE(100, 0x20, vol);
-       if (aci_write_cmd(left_index, 0x20 - vol))
-               return -EIO;
-       ret = SCALE(0x20, 100, vol);
+       if ((buf=aci_indexed_cmd(0xf0, left_index))<0)
+               return buf;
+       vol = eq_aci2oss(buf);
+       
+       /* right channel */
+       if ((buf=aci_indexed_cmd(0xf0, right_index))<0)
+               return buf;
+       vol |= eq_aci2oss(buf) << 8;
 
+       __put_user(vol, (int *)arg);
 
-       /* right channel */
-       vol = (*(int *)arg >> 8) & 0xff;
-       if (vol > 100)
-               vol = 100;
-       vol = SCALE(100, 0x20, vol);
-       if (aci_write_cmd(right_index, 0x20 - vol))
-               return -EIO;
-       ret |= SCALE(0x20, 100, vol) << 8;
-       return (*(int *) arg = ret);
+       return 0;
 }
 
-
-static int
-aci_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
+static int aci_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
 {
-       int status, vol;
-       unsigned char buf;
-
-       /* handle solo mode control */
-       if (cmd == SOUND_MIXER_PRIVATE1) {
-               if (*(int *) arg >= 0) {
-                       aci_solo = !!*(int *) arg;
-                       if (aci_write_cmd(0xd2, aci_solo))
-                               return -EIO;
-               } else if (aci_version >= 0xb0) {
-                       if ((status = read_general_status()) < 0)
-                               return -EIO;
-                       return (*(int *) arg = (status & 0x20) == 0);
+       int vol, buf;
+
+       switch (cmd) {
+       case SOUND_MIXER_WRITE_VOLUME:
+               return setvolume(arg, 0x01, 0x00);
+       case SOUND_MIXER_WRITE_CD:
+               return setvolume(arg, 0x3c, 0x34);
+       case SOUND_MIXER_WRITE_MIC:
+               return setvolume(arg, 0x38, 0x30);
+       case SOUND_MIXER_WRITE_LINE:
+               return setvolume(arg, 0x39, 0x31);
+       case SOUND_MIXER_WRITE_SYNTH:
+               return setvolume(arg, 0x3b, 0x33);
+       case SOUND_MIXER_WRITE_PCM:
+               return setvolume(arg, 0x3a, 0x32);
+       case MIXER_WRITE(SOUND_MIXER_RADIO): /* fall through */
+       case SOUND_MIXER_WRITE_LINE1:  /* AUX1 or radio */
+               return setvolume(arg, 0x3d, 0x35);
+       case SOUND_MIXER_WRITE_LINE2:  /* AUX2 */
+               return setvolume(arg, 0x3e, 0x36);
+       case SOUND_MIXER_WRITE_BASS:   /* set band one and two */
+               if (aci_idcode[1]=='C') {
+                       if ((buf=setequalizer(arg, 0x48, 0x40)) || 
+                           (buf=setequalizer(arg, 0x49, 0x41)));
+                       return buf;
                }
-               
-               return (*(int *) arg = aci_solo);
-       }
-       
-       if (((cmd >> 8) & 0xff) == 'M') {
-               if (cmd & SIOC_IN)
-                       /* read and write */
-                       switch (cmd & 0xff) {
-                               case SOUND_MIXER_VOLUME:
-                                       return setvolume(arg, 0x01, 0x00);
-                               case SOUND_MIXER_CD:
-                                       return setvolume(arg, 0x3c, 0x34);
-                               case SOUND_MIXER_MIC:
-                                       return setvolume(arg, 0x38, 0x30);
-                               case SOUND_MIXER_LINE:
-                                       return setvolume(arg, 0x39, 0x31);
-                               case SOUND_MIXER_SYNTH:
-                                       return setvolume(arg, 0x3b, 0x33);
-                               case SOUND_MIXER_PCM:
-                                       return setvolume(arg, 0x3a, 0x32);
-                               case SOUND_MIXER_LINE1:  /* AUX1 */
-                                       return setvolume(arg, 0x3d, 0x35);
-                               case SOUND_MIXER_LINE2:  /* AUX2 */
-                                       return setvolume(arg, 0x3e, 0x36);
-                               case SOUND_MIXER_IGAIN:  /* MIC pre-amp */
-                                       vol = *(int *) arg & 0xff;
-                                       if (vol > 100)
-                                               vol = 100;
-                                       vol = SCALE(100, 3, vol);
-                                       if (aci_write_cmd(0x03, vol))
-                                               return -EIO;
-                                       vol = SCALE(3, 100, vol);
-                                       return (*(int *) arg = vol | (vol << 8));
-                               case SOUND_MIXER_RECSRC:
-                                       return (*(int *) arg = 0);
-                                       break;
-                               default:
-                                       return -EINVAL;
+               break;
+       case SOUND_MIXER_WRITE_TREBLE: /* set band six and seven */
+               if (aci_idcode[1]=='C') {
+                       if ((buf=setequalizer(arg, 0x4d, 0x45)) || 
+                           (buf=setequalizer(arg, 0x4e, 0x46)));
+                       return buf;
+               }
+               break;
+       case SOUND_MIXER_WRITE_IGAIN:  /* MIC pre-amp */
+               if (aci_idcode[1]=='B' || aci_idcode[1]=='C') {
+                       __get_user(vol, (int *)arg);
+                       vol = vol & 0xff;
+                       if (vol > 100)
+                               vol = 100;
+                       vol = SCALE(100, 3, vol);
+                       if ((buf=aci_write_cmd(0x03, vol))<0)
+                               return buf;
+                       aci_micpreamp = vol;
+                       vol = SCALE(3, 100, vol);
+                       vol |= (vol << 8);
+                       __put_user(vol, (int *)arg);
+                       return 0;
+               }
+               break;
+       case SOUND_MIXER_WRITE_OGAIN:  /* Power-amp/line-out level */
+               if (aci_idcode[1]=='A' || aci_idcode[1]=='B') {
+                       __get_user(buf, (int *)arg);
+                       buf = buf & 0xff;
+                       if (buf > 50)
+                               vol = 1;
+                       else
+                               vol = 0;
+                       if ((buf=aci_write_cmd(0x0f, vol))<0)
+                               return buf;
+                       aci_amp = vol;
+                       if (aci_amp)
+                               buf = (100 || 100<<8);
+                       else
+                               buf = 0;
+                       __put_user(buf, (int *)arg);
+                       return 0;
+               }
+               break;
+       case SOUND_MIXER_WRITE_RECSRC:
+               /* handle solo mode control */
+               __get_user(buf, (int *)arg);
+               /* unset solo when RECSRC for PCM is requested */
+               if (aci_idcode[1]=='B' || aci_idcode[1]=='C') {
+                       vol = !(buf & SOUND_MASK_PCM);
+                       if ((buf=aci_write_cmd(0xd2, vol))<0)
+                               return buf;
+                       aci_solo = vol;
+               }
+               buf = (SOUND_MASK_CD| SOUND_MASK_MIC| SOUND_MASK_LINE|
+                      SOUND_MASK_SYNTH| SOUND_MASK_LINE2);
+               if (aci_idcode[1] == 'C') /* PCM20 radio */
+                       buf |= SOUND_MASK_RADIO;
+               else
+                       buf |= SOUND_MASK_LINE1;
+               if (!aci_solo)
+                       buf |= SOUND_MASK_PCM;
+               __put_user(buf, (int *)arg);
+               return 0;
+       case SOUND_MIXER_READ_DEVMASK:
+               buf = (SOUND_MASK_VOLUME | SOUND_MASK_CD    |
+                      SOUND_MASK_MIC    | SOUND_MASK_LINE  |
+                      SOUND_MASK_SYNTH  | SOUND_MASK_PCM   |
+                      SOUND_MASK_LINE2);
+               switch (aci_idcode[1]) {
+               case 'C': /* PCM20 radio */
+                       buf |= (SOUND_MASK_RADIO | SOUND_MASK_IGAIN |
+                               SOUND_MASK_BASS  | SOUND_MASK_TREBLE);
+                       break;
+               case 'B': /* PCM12 */
+                       buf |= (SOUND_MASK_LINE1 | SOUND_MASK_IGAIN |
+                               SOUND_MASK_OGAIN);
+                       break;
+               case 'A': /* PCM1-pro */
+                       buf |= (SOUND_MASK_LINE1 | SOUND_MASK_OGAIN);
+                       break;
+               default:
+                       buf |= SOUND_MASK_LINE1;
+               }
+               __put_user(buf, (int *)arg);
+               return 0;
+       case SOUND_MIXER_READ_STEREODEVS:
+               buf = (SOUND_MASK_VOLUME | SOUND_MASK_CD    |
+                      SOUND_MASK_MIC    | SOUND_MASK_LINE  |
+                      SOUND_MASK_SYNTH  | SOUND_MASK_PCM   |
+                      SOUND_MASK_LINE2);
+               switch (aci_idcode[1]) {
+               case 'C': /* PCM20 radio */
+                       buf |= (SOUND_MASK_RADIO |
+                               SOUND_MASK_BASS  | SOUND_MASK_TREBLE);
+                       break;
+               default:
+                       buf |= SOUND_MASK_LINE1;
+               }
+               __put_user(buf, (int *)arg);
+               return 0;
+       case SOUND_MIXER_READ_RECMASK:
+               buf = (SOUND_MASK_CD| SOUND_MASK_MIC| SOUND_MASK_LINE|
+                      SOUND_MASK_SYNTH| SOUND_MASK_LINE2| SOUND_MASK_PCM);
+               if (aci_idcode[1] == 'C') /* PCM20 radio */
+                       buf |= SOUND_MASK_RADIO;
+               else
+                       buf |= SOUND_MASK_LINE1;
+
+               __put_user(buf, (int *)arg);
+               return 0;
+       case SOUND_MIXER_READ_RECSRC:
+               buf = (SOUND_MASK_CD    | SOUND_MASK_MIC   | SOUND_MASK_LINE  |
+                      SOUND_MASK_SYNTH | SOUND_MASK_LINE2);
+               /* do we need aci_solo or can I get it from the ACI? */
+               switch (aci_idcode[1]) {
+               case 'B': /* PCM12 */
+               case 'C': /* PCM20 radio */
+                       if (aci_version >= 0xb0) {
+                               if ((vol=aci_rw_cmd(0xf0, 0x00, -1))<0)
+                                       return vol;
+                               if (vol & 0x20)
+                                       buf |= SOUND_MASK_PCM;
                        }
+                       else
+                               if (!aci_solo)
+                                       buf |= SOUND_MASK_PCM;
+                       break;
+               default:
+                       buf |= SOUND_MASK_PCM;
+               }
+               if (aci_idcode[1] == 'C') /* PCM20 radio */
+                       buf |= SOUND_MASK_RADIO;
                else
-                       /* only read */
-                       switch (cmd & 0xff) {
-                               case SOUND_MIXER_DEVMASK:
-                                       return (*(int *) arg =
-                                SOUND_MASK_VOLUME | SOUND_MASK_CD    |
-                                SOUND_MASK_MIC    | SOUND_MASK_LINE  |
-                                SOUND_MASK_SYNTH  | SOUND_MASK_PCM   |
-#if 0
-                                SOUND_MASK_IGAIN  |
-#endif
-                                SOUND_MASK_LINE1  | SOUND_MASK_LINE2);
-                                       break;
-                               case SOUND_MIXER_STEREODEVS:
-                                       return (*(int *) arg =
-                                SOUND_MASK_VOLUME | SOUND_MASK_CD   |
-                                SOUND_MASK_MIC    | SOUND_MASK_LINE |
-                                SOUND_MASK_SYNTH  | SOUND_MASK_PCM  |
-                                SOUND_MASK_LINE1  | SOUND_MASK_LINE2);
-                                       break;
-                               case SOUND_MIXER_RECMASK:
-                                       return (*(int *) arg = 0);
-                                       break;
-                               case SOUND_MIXER_RECSRC:
-                                       return (*(int *) arg = 0);
-                                       break;
-                               case SOUND_MIXER_CAPS:
-                                       return (*(int *) arg = 0);
-                                       break;
-                               case SOUND_MIXER_VOLUME:
-                                       return getvolume(arg, 0x04, 0x03);
-                               case SOUND_MIXER_CD:
-                                       return getvolume(arg, 0x0a, 0x09);
-                               case SOUND_MIXER_MIC:
-                                       return getvolume(arg, 0x06, 0x05);
-                               case SOUND_MIXER_LINE:
-                                       return getvolume(arg, 0x08, 0x07);
-                               case SOUND_MIXER_SYNTH:
-                                       return getvolume(arg, 0x0c, 0x0b);
-                               case SOUND_MIXER_PCM:
-                                       return getvolume(arg, 0x0e, 0x0d);
-                               case SOUND_MIXER_LINE1:  /* AUX1 */
-                                       return getvolume(arg, 0x11, 0x10);
-                               case SOUND_MIXER_LINE2:  /* AUX2 */
-                                       return getvolume(arg, 0x13, 0x12);
-                               case SOUND_MIXER_IGAIN:  /* MIC pre-amp */
-                                       if (aci_indexed_cmd(0xf0, 0x21, &buf))
-                                               return -EIO;
-                                       vol = SCALE(3, 100, buf <= 3 ? buf : 3);
-                                       vol |= vol << 8;
-                                       return (*(int *) arg = vol);
-                               default:
-                                       return -EINVAL;
+                       buf |= SOUND_MASK_LINE1;
+
+               __put_user(buf, (int *)arg);
+               return 0;
+       case SOUND_MIXER_READ_CAPS:
+               __put_user(0, (int *)arg);
+               return 0;
+       case SOUND_MIXER_READ_VOLUME:
+               return getvolume(arg, 0x04, 0x03);
+       case SOUND_MIXER_READ_CD:
+               return getvolume(arg, 0x0a, 0x09);
+       case SOUND_MIXER_READ_MIC:
+               return getvolume(arg, 0x06, 0x05);
+       case SOUND_MIXER_READ_LINE:
+               return getvolume(arg, 0x08, 0x07);
+       case SOUND_MIXER_READ_SYNTH:
+               return getvolume(arg, 0x0c, 0x0b);
+       case SOUND_MIXER_READ_PCM:
+               return getvolume(arg, 0x0e, 0x0d);
+       case MIXER_READ(SOUND_MIXER_RADIO): /* fall through */
+       case SOUND_MIXER_READ_LINE1:  /* AUX1 */
+               return getvolume(arg, 0x11, 0x10);
+       case SOUND_MIXER_READ_LINE2:  /* AUX2 */
+               return getvolume(arg, 0x13, 0x12);
+       case SOUND_MIXER_READ_BASS:   /* get band one */
+               if (aci_idcode[1]=='C') {
+                       return getequalizer(arg, 0x23, 0x22);
+               }
+               break;
+       case SOUND_MIXER_READ_TREBLE: /* get band seven */
+               if (aci_idcode[1]=='C') {
+                       return getequalizer(arg, 0x2f, 0x2e);
+               }
+               break;
+       case SOUND_MIXER_READ_IGAIN:  /* MIC pre-amp */
+               if (aci_idcode[1]=='B' || aci_idcode[1]=='C') {
+                       /* aci_micpreamp or ACI? */
+                       if (aci_version >= 0xb0) {
+                               if ((buf=aci_indexed_cmd(0xf0, 0x21))<0)
+                                       return buf;
                        }
+                       else
+                               buf=aci_micpreamp;
+                       vol = SCALE(3, 100, buf <= 3 ? buf : 3);
+                       vol |= vol << 8;
+                       __put_user(vol, (int *)arg);
+                       return 0;
+               }
+               break;
+       case SOUND_MIXER_READ_OGAIN:
+               if (aci_amp)
+                       buf = (100 || 100<<8);
+               else
+                       buf = 0;
+               __put_user(buf, (int *)arg);
+               return 0;
        }
-       
        return -EINVAL;
 }
 
-
 static struct mixer_operations aci_mixer_operations =
 {
-       owner:  THIS_MODULE,
-       id:     "ACI",
-       name:   "ACI mixer",
-       ioctl:  aci_mixer_ioctl
+       owner: THIS_MODULE,
+       id:    "ACI",
+       ioctl: aci_mixer_ioctl
 };
 
-static unsigned char
-mad_read (int port)
-{
-       outb (0xE3, 0xf8f); /* Write MAD16 password */
-       return inb (port);  /* Read from port */
-}
-
-
 /*
- * Check, whether there actually is any ACI port operational and if
- * one was found, then initialize the ACI interface, reserve the I/O
- * addresses and attach the new mixer to the relevant VoxWare data
- * structures.
- *
- * Returns:  1   ACI mixer detected
- *           0   nothing there
- *
  * There is also an internal mixer in the codec (CS4231A or AD1845),
  * that deserves no purpose in an ACI based system which uses an
  * external ACI controlled stereo mixer. Make sure that this codec
@@ -570,153 +595,108 @@ mad_read (int port)
 
 static int __init attach_aci(void)
 {
-       char *boardname = "unknown";
-       int volume;
+       char *boardname;
+       int i;
 
-#define MC4_PORT       0xf90
+       init_MUTEX(&aci_sem);
 
-       aci_port =
-               (mad_read(MC4_PORT) & 0x10) ? 0x344 : 0x354;
+       outb(0xE3, 0xf8f); /* Write MAD16 password */
+       aci_port = (inb(0xf90) & 0x10) ?
+               0x344: 0x354; /* Get aci_port from MC4_PORT */
 
        if (check_region(aci_port, 3)) {
-#ifdef DEBUG
-               printk("ACI: I/O area 0x%03x-0x%03x already used.\n",
-                       aci_port, aci_port+2);
-#endif
-               return 0;
+               printk(KERN_NOTICE "aci: I/O area 0x%03x-0x%03x already used.\n",
+                      aci_port, aci_port+2);
+               return -EBUSY;
        }
-       
-       if (aci_read_cmd(0xf2, 2, aci_idcode)) {
-#ifdef DEBUG
-               printk("ACI: Failed to read idcode.\n");
-#endif
-               return 0;
+
+       /* force ACI into a known state */
+       for (i=0; i<3; i++)
+               if (aci_rw_cmd(0xdf, -1, -1)<0)
+                       return -EFAULT;
+
+       /* official this is one aci read call: */
+       if ((aci_idcode[0]=aci_rw_cmd(0xf2, -1, -1))<0 ||
+           (aci_idcode[1]=aci_rw_cmd(0xf2, -1, -1))<0) {
+               printk(KERN_ERR "aci: Failed to read idcode on 0x%03x.\n", aci_port);
+               return -EFAULT;
        }
-       
-       if (aci_read_cmd(0xf1, 1, &aci_version)) {
-#ifdef DEBUG
-               printk("ACI: Failed to read version.\n");
-#endif
-               return 0;
+
+       if ((aci_version=aci_rw_cmd(0xf1, -1, -1))<0) {
+               printk(KERN_ERR "aci: Failed to read version on 0x%03x.\n", aci_port);
+               return -EFAULT;
        }
 
-       if (aci_idcode[0] == 0x6d) {
+       if (aci_idcode[0] == 'm') {
                /* It looks like a miro sound card. */
                switch (aci_idcode[1]) {
-                       case 0x41:
-                               boardname = "PCM1 pro / early PCM12";
-                               break;
-                       case 0x42:
-                               boardname = "PCM12";
-                               break;
-                       case 0x43:
-                               boardname = "PCM20";
-                               break;
-                       default:
-                               boardname = "unknown miro";
+               case 'A':
+                       boardname = "PCM1 pro / early PCM12";
+                       break;
+               case 'B':
+                       boardname = "PCM12";
+                       break;
+               case 'C':
+                       boardname = "PCM20 radio";
+                       break;
+               default:
+                       boardname = "unknown miro";
                }
-       } else
-#ifndef DEBUG
-       return 0;
-#endif
-  
-       printk("<ACI %02x, id %02x %02x (%s)> at 0x%03x\n",
-               aci_version, aci_idcode[0], aci_idcode[1], boardname, aci_port);
-
-       if (aci_reset) {
-               /* initialize ACI mixer */
-               aci_implied_cmd(0xff);
-               aci_solo = 0;
+       } else {
+               printk(KERN_WARNING "aci: Warning: unsupported card! - "
+                      "no hardware, no specs...\n");
+               boardname = "unknown Cardinal Technologies";
        }
 
-       /* attach the mixer */
-       request_region(aci_port, 3, "sound mixer (ACI)");
-       if (num_mixers < MAX_MIXER_DEV) {
-               if (num_mixers > 0 &&
-                 !strncmp("MAD16 WSS", mixer_devs[num_mixers-1]->name, 9)) {
-                       /*
-                        * The previously registered mixer device is the CS4231A which
-                        * has no function on an ACI card. Make the ACI mixer the first
-                        * of the two mixer devices.
-                        */
-                       mixer_devs[num_mixers] = mixer_devs[num_mixers-1];
-                       mixer_devs[num_mixers-1] = &aci_mixer_operations;
-                       /*
-                        * Initialize the CS4231A mixer with reasonable values. It is
-                        * unlikely that the user ever will want to change these as all
-                        * channels can be mixed via ACI.
-                        */
-                       volume = 0x6464;
-                       mixer_devs[num_mixers]->ioctl(num_mixers,
-                               SOUND_MIXER_WRITE_PCM, (caddr_t) &volume);
-                       volume = 0x6464;
-                       mixer_devs[num_mixers]->ioctl(num_mixers,
-                               SOUND_MIXER_WRITE_IGAIN,   (caddr_t) &volume);
-                       volume = 0;
-                       mixer_devs[num_mixers]->ioctl(num_mixers,
-                               SOUND_MIXER_WRITE_SPEAKER, (caddr_t) &volume);
-                       volume = 0;
-                       mixer_devs[num_mixers]->ioctl(num_mixers,
-                               SOUND_MIXER_WRITE_MIC, (caddr_t) &volume);
-                       volume = 0;
-                       mixer_devs[num_mixers]->ioctl(num_mixers,
-                               SOUND_MIXER_WRITE_IMIX, (caddr_t) &volume);
-                       volume = 0;
-                       mixer_devs[num_mixers]->ioctl(num_mixers,
-                               SOUND_MIXER_WRITE_LINE1, (caddr_t) &volume);
-                       volume = 0;
-                       mixer_devs[num_mixers]->ioctl(num_mixers,
-                               SOUND_MIXER_WRITE_LINE2, (caddr_t) &volume);
-                       volume = 0;
-                       mixer_devs[num_mixers]->ioctl(num_mixers,
-                               SOUND_MIXER_WRITE_LINE3, (caddr_t) &volume);
-                       volume = SOUND_MASK_LINE1;
-                       mixer_devs[num_mixers]->ioctl(num_mixers,
-                               SOUND_MIXER_WRITE_RECSRC, (caddr_t) &volume);
-                       num_mixers++;
-               } else
-                       mixer_devs[num_mixers++] = &aci_mixer_operations;
+       printk(KERN_INFO "<ACI 0x%02x, id %02x/%02x \"%c/%c\", (%s)> at 0x%03x\n",
+              aci_version,
+              aci_idcode[0], aci_idcode[1],
+              aci_idcode[0], aci_idcode[1],
+              boardname, aci_port);
+
+       if (reset) {
+               /* first write()s after reset fail with my PCM20 */
+               if (aci_rw_cmd(0xff, -1, -1)<0 ||
+                   aci_rw_cmd(0xdf, 0xdf, 0xdf)<0 ||
+                   aci_rw_cmd(0xdf, 0xdf, 0xdf)<0)
+                       return -EBUSY;
        }
 
-       /* Just do something; otherwise the first write command fails, at
-        * least with my PCM20.
-        */
-       aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_READ_VOLUME, (caddr_t) &volume);
+       /* the PCM20 is muted after reset (and reboot) */
+       if (aci_rw_cmd(0x0d, 0x00, -1)<0)
+               return -EBUSY;
+
+       if (ide>=0)
+               if (aci_rw_cmd(0xd0, !ide, -1)<0)
+                       return -EBUSY;
        
-       if (aci_reset) {
-               /* Initialize ACI mixer with reasonable power-up values */
-               volume = 0x3232;
-               aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_VOLUME, (caddr_t) &volume);
-               volume = 0x3232;
-               aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_SYNTH,  (caddr_t) &volume);
-               volume = 0x3232;
-               aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_PCM,    (caddr_t) &volume);
-               volume = 0x3232;
-               aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_LINE,   (caddr_t) &volume);
-               volume = 0x3232;
-               aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_MIC,    (caddr_t) &volume);
-               volume = 0x3232;
-               aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_CD,     (caddr_t) &volume);
-               volume = 0x3232;
-               aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_LINE1,  (caddr_t) &volume);
-               volume = 0x3232;
-               aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_LINE2,  (caddr_t) &volume);
+       if (wss>=0 && aci_idcode[1]=='A')
+               if (aci_rw_cmd(0xd1, !!wss, -1)<0)
+                       return -EBUSY;
+
+       if (!request_region(aci_port, 3, "sound mixer (ACI)"))
+               return -ENOMEM;
+
+       if ((mixer_device = sound_install_mixer(MIXER_DRIVER_VERSION,
+                                               boardname,
+                                               &aci_mixer_operations,
+                                               sizeof(aci_mixer_operations),
+                                               NULL)) >= 0) {
+               /* Maybe initialize the CS4231A mixer here... */
+       } else {
+               printk(KERN_ERR "aci: Failed to install mixer.\n");
+               release_region(aci_port, 3);
+               return mixer_device;
        }
 
-       aci_present = 1;
-
-       return 1;
+       return 0;
 }
 
 static void __exit unload_aci(void)
 {
-       if (aci_present)
-               release_region(aci_port, 3);
+       sound_unload_mixerdev(mixer_device);
+       release_region(aci_port, 3);
 }
 
-EXPORT_SYMBOL(aci_write_cmd);
-EXPORT_SYMBOL(aci_indexed_cmd);
-EXPORT_SYMBOL(aci_write_cmd_d);
-
 module_init(attach_aci);
 module_exit(unload_aci);
diff --git a/drivers/sound/aci.h b/drivers/sound/aci.h
new file mode 100644 (file)
index 0000000..f192ccc
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef _ACI_H_
+#define _ACI_H_
+
+extern int aci_port;
+extern int aci_idcode[2];      /* manufacturer and product ID */
+extern int aci_version;                /* ACI firmware version */
+extern int aci_rw_cmd(int write1, int write2, int write3);
+
+extern char * aci_radio_name;
+extern int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize);
+
+#define aci_indexed_cmd(a, b) aci_rw_cmd(a, b, -1)
+#define aci_write_cmd(a, b)   aci_rw_cmd(a, b, -1)
+#define aci_read_cmd(a)       aci_rw_cmd(a,-1, -1)
+
+#define COMMAND_REGISTER    (aci_port)      /* write register */
+#define STATUS_REGISTER     (aci_port + 1)  /* read register */
+#define BUSY_REGISTER       (aci_port + 2)  /* also used for rds */
+
+#define RDS_REGISTER        BUSY_REGISTER
+
+#define RDS_STATUS      0x01
+#define RDS_STATIONNAME 0x02
+#define RDS_TEXT        0x03
+#define RDS_ALTFREQ     0x04
+#define RDS_TIMEDATE    0x05
+#define RDS_PI_CODE     0x06
+#define RDS_PTYTATP     0x07
+#define RDS_RESET       0x08
+#define RDS_RXVALUE     0x09
+
+/*
+ * The following macro SCALE can be used to scale one integer volume
+ * value into another one using only integer arithmetic. If the input
+ * value x is in the range 0 <= x <= xmax, then the result will be in
+ * the range 0 <= SCALE(xmax,ymax,x) <= ymax.
+ *
+ * This macro has for all xmax, ymax > 0 and all 0 <= x <= xmax the
+ * following nice properties:
+ *
+ * - SCALE(xmax,ymax,xmax) = ymax
+ * - SCALE(xmax,ymax,0) = 0
+ * - SCALE(xmax,ymax,SCALE(ymax,xmax,SCALE(xmax,ymax,x))) = SCALE(xmax,ymax,x)
+ *
+ * In addition, the rounding error is minimal and nicely distributed.
+ * The proofs are left as an exercise to the reader.
+ */
+
+#define SCALE(xmax,ymax,x) (((x)*(ymax)+(xmax)/2)/(xmax))
+
+extern void __exit unload_aci_rds(void);
+extern int __init attach_aci_rds(void);
+
+
+#endif  /* _ACI_H_ */
index 2dc2c51..2ac5efa 100644 (file)
 
 #define VERSION "1.3"          /* Version of Audio Excel DSP 16 driver */
 
-#undef AEDSP16_DEBUG 1         /* Define this to enable debug code     */
-#undef AEDSP16_DEBUG_MORE 1    /* Define this to enable more debug     */
-#undef AEDSP16_INFO  1         /* Define this to enable info code      */
+#undef AEDSP16_DEBUG           /* Define this to 1 to enable debug code     */
+#undef AEDSP16_DEBUG_MORE      /* Define this to 1 to enable more debug     */
+#undef AEDSP16_INFO            /* Define this to 1 to enable info code      */
 
 #if defined(AEDSP16_DEBUG)
 # define DBG(x)  printk x
index bd922c0..8404644 100644 (file)
@@ -34,6 +34,7 @@
 #define _CARDMI_H
 
 #include "icardmid.h"
+#include <linux/sched.h>
 #include <linux/interrupt.h>
 
 typedef enum
index 979576a..693e91f 100644 (file)
@@ -27,6 +27,7 @@
 #ifndef _TIMER_H
 #define _TIMER_H
 
+#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include "hwaccess.h"
 
diff --git a/drivers/sound/miroaci.h b/drivers/sound/miroaci.h
deleted file mode 100644 (file)
index ee4e01d..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-extern int aci_implied_cmd(unsigned char opcode);
-extern int aci_write_cmd(unsigned char opcode, unsigned char parameter);
-extern int aci_write_cmd_d(unsigned char opcode, unsigned char parameter, unsigned char parameter2);
-extern int aci_read_cmd(unsigned char opcode, int length, unsigned char *parameter);
-extern int aci_indexed_cmd(unsigned char opcode, unsigned char index, unsigned char *parameter);
index 50ac174..738873a 100644 (file)
@@ -17,6 +17,7 @@
  * We currently support a mixer device, but it is currently non-functional.
  */
 
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -82,6 +83,7 @@ static unsigned int   vidc_audio_volume_r;    /* right PCM vol, 0 - 65536 */
 static void    (*old_mksound)(unsigned int hz, unsigned int ticks);
 extern void    (*kd_mksound)(unsigned int hz, unsigned int ticks);
 extern void    vidc_update_filler(int bits, int channels);
+extern int     softoss_dev;
 
 static void
 vidc_mksound(unsigned int hz, unsigned int ticks)
@@ -214,8 +216,8 @@ static int vidc_audio_set_speed(int dev, int rate)
                        rate = VIDC_SOUND_CLOCK / hwrate;
                }
 
-               outl(0xb0000000 | (hwrate - 2), IO_VIDC_BASE);
-               outl(0xb1000000 | hwctrl, IO_VIDC_BASE);
+               vidc_writel(0xb0000000 | (hwrate - 2));
+               vidc_writel(0xb1000000 | hwctrl);
 
                newsize = (10000 / hwrate) & ~3;
                if (newsize < 208)
@@ -354,7 +356,7 @@ static void vidc_audio_trigger(int dev, int enable_bits)
 
                        dma_interrupt = vidc_audio_dma_interrupt;
                        vidc_sound_dma_irq(0, NULL, NULL);
-                       outb(DMA_CR_E | 0x10, IOMD_SD0CR);
+                       iomd_writeb(DMA_CR_E | 0x10, IOMD_SD0CR);
 
                        local_irq_restore(flags);
                }
@@ -473,6 +475,9 @@ static void __init attach_vidc(struct address_info *hw_config)
        vidc_adev = adev;
        vidc_mixer_set(SOUND_MIXER_VOLUME, (85 | 85 << 8));
 
+#if defined(CONFIG_SOUND_SOFTOSS) || defined(CONFIG_SOUND_SOFTOSS_MODULE)
+       softoss_dev = adev;
+#endif
        return;
 
 irq_failed:
index be7b9af..9b0dddd 100644 (file)
@@ -1824,7 +1824,7 @@ static int __init setup_waveartist(char *str)
        io      = ints[1];
        irq     = ints[2];
        dma     = ints[3];
-       dma16   = ints[4];
+       dma2    = ints[4];
 
        return 1;
 }
index 701214e..40c43ad 100644 (file)
@@ -7,27 +7,36 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
-SUB_DIRS     :=
-MOD_SUB_DIRS := 
-ALL_SUB_DIRS := 
-
-L_TARGET := tc.a
-L_OBJS   := tc.o
-
-# Nasty trick as nobody references tcsyms.o, but we still want it linked.
-# Stolen from pci Makefile
-ifeq ($(CONFIG_MODULES),y)
-O_TARGET = tc_syms.o
-OX_OBJS  = tcsyms.o
-O_OBJS   = tc.o
-L_OBJS   := tc_syms.o
-else
-L_OBJS   := tc.o
-endif
-
-ifdef CONFIG_ZS
-L_OBJS   += zs.o
-endif
+# All of the (potential) objects that export symbols.
+# This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
+
+export-objs    := tc.o
+
+# Object file lists.
+
+obj-y          :=
+obj-m          :=
+obj-n          :=
+obj-           :=
+
+obj-$(CONFIG_TC) += tc.o
+obj-$(CONFIG_ZS) += zs.o
+obj-$(CONFIG_VT) += lk201.o lk201-map.o lk201-remap.o
+
+# Files that are both resident and modular: remove from modular.
+
+obj-m          := $(filter-out $(obj-y), $(obj-m))
+
+# Translate to Rules.make lists.
+
+L_TARGET       := tc.a
+
+L_OBJS         := $(sort $(filter-out $(export-objs), $(obj-y)))
+LX_OBJS                := $(sort $(filter     $(export-objs), $(obj-y)))
+M_OBJS         := $(sort $(filter-out $(export-objs), $(obj-m)))
+MX_OBJS                := $(sort $(filter     $(export-objs), $(obj-m)))
 
 include $(TOPDIR)/Rules.make
 
+lk201-map.c: lk201-map.map
+       loadkeys --mktable lk201-map.map > lk201-map.c
index 3a1ec25..a62a2b7 100644 (file)
@@ -98,15 +98,12 @@ static void hub_irq(struct urb *urb)
        hub->nerrors = 0;
 
        /* Something happened, let khubd figure it out */
-       if (waitqueue_active(&khubd_wait)) {
-               /* Add the hub to the event queue */
-               spin_lock_irqsave(&hub_event_lock, flags);
-               if (list_empty(&hub->event_list)) {
-                       list_add(&hub->event_list, &hub_event_list);
-                       wake_up(&khubd_wait);
-               }
-               spin_unlock_irqrestore(&hub_event_lock, flags);
+       spin_lock_irqsave(&hub_event_lock, flags);
+       if (list_empty(&hub->event_list)) {
+               list_add(&hub->event_list, &hub_event_list);
+               wake_up(&khubd_wait);
        }
+       spin_unlock_irqrestore(&hub_event_lock, flags);
 }
 
 static void usb_hub_power_on(struct usb_hub *hub)
@@ -239,7 +236,6 @@ static int usb_hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor
 
 static void *hub_probe(struct usb_device *dev, unsigned int i,
                       const struct usb_device_id *id)
-
 {
        struct usb_interface_descriptor *interface;
        struct usb_endpoint_descriptor *endpoint;
@@ -293,7 +289,7 @@ static void *hub_probe(struct usb_device *dev, unsigned int i,
 
        INIT_LIST_HEAD(&hub->event_list);
        hub->dev = dev;
-       init_MUTEX(&hub->khubd_sem);
+       atomic_set(&hub->refcnt, 1);
 
        /* Record the new hub's existence */
        spin_lock_irqsave(&hub_event_lock, flags);
@@ -322,6 +318,29 @@ static void *hub_probe(struct usb_device *dev, unsigned int i,
        return NULL;
 }
 
+static void hub_get(struct usb_hub *hub)
+{
+       atomic_inc(&hub->refcnt);
+}
+
+static void hub_put(struct usb_hub *hub)
+{
+       if (atomic_dec_and_test(&hub->refcnt)) {
+               if (hub->urb) {
+                       usb_unlink_urb(hub->urb);
+                       usb_free_urb(hub->urb);
+                       hub->urb = NULL;
+               }
+
+               if (hub->descriptor) {
+                       kfree(hub->descriptor);
+                       hub->descriptor = NULL;
+               }
+
+               kfree(hub);
+       }
+}
+
 static void hub_disconnect(struct usb_device *dev, void *ptr)
 {
        struct usb_hub *hub = (struct usb_hub *)ptr;
@@ -337,22 +356,7 @@ static void hub_disconnect(struct usb_device *dev, void *ptr)
 
        spin_unlock_irqrestore(&hub_event_lock, flags);
 
-       down(&hub->khubd_sem); /* Wait for khubd to leave this hub alone. */
-       up(&hub->khubd_sem);
-
-       if (hub->urb) {
-               usb_unlink_urb(hub->urb);
-               usb_free_urb(hub->urb);
-               hub->urb = NULL;
-       }
-
-       if (hub->descriptor) {
-               kfree(hub->descriptor);
-               hub->descriptor = NULL;
-       }
-
-       /* Free the memory */
-       kfree(hub);
+       hub_put(hub);
 }
 
 static int hub_ioctl(struct usb_device *hub, unsigned int code, void *user_data)
@@ -406,6 +410,7 @@ static int usb_hub_reset(struct usb_hub *hub)
        if (usb_reset_device(dev))
                return -1;
 
+       hub->urb->dev = dev;                                                    
        if (usb_submit_urb(hub->urb))
                return -1;
 
@@ -663,7 +668,7 @@ static void usb_hub_events(void)
                list_del(tmp);
                INIT_LIST_HEAD(tmp);
 
-               down(&hub->khubd_sem); /* never blocks, we were on list */
+               hub_get(hub);
                spin_unlock_irqrestore(&hub_event_lock, flags);
 
                if (hub->error) {
@@ -672,7 +677,7 @@ static void usb_hub_events(void)
                        if (usb_hub_reset(hub)) {
                                err("error resetting hub %d - disconnecting", dev->devnum);
                                usb_hub_disconnect(dev);
-                               up(&hub->khubd_sem);
+                               hub_put(hub);
                                continue;
                        }
 
@@ -748,7 +753,7 @@ static void usb_hub_events(void)
                                usb_hub_power_on(hub);
                        }
                }
-               up(&hub->khubd_sem);
+               hub_put(hub);
         } /* end while (1) */
 
        spin_unlock_irqrestore(&hub_event_lock, flags);
index 5ed47de..724f3ce 100644 (file)
@@ -109,7 +109,7 @@ struct usb_hub {
 
        struct usb_hub_descriptor *descriptor;
 
-       struct semaphore khubd_sem;
+       atomic_t refcnt;
 };
 
 #endif
index e45be20..e9d5cbf 100644 (file)
@@ -98,6 +98,14 @@ if [ "$CONFIG_FB" = "y" ]; then
          bool '    CGsix (GX,TurboGX) support' CONFIG_FB_CGSIX
       fi
    fi
+   bool '  Epson 1355 framebuffer support' CONFIG_FB_E1355
+   if [ "$CONFIG_FB_E1355" = "y" ]; then
+      hex '    Register Base Address' CONFIG_E1355_REG_BASE a8000000
+      hex '    Framebuffer Base Address' CONFIG_E1355_FB_BASE a8200000
+   fi
+   if [ "$CONFIG_SH_DREAMCAST" = "y" ]; then
+      tristate '  Dreamcast Frame Buffer support' CONFIG_FB_DC
+   fi
    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
       if [ "$CONFIG_PCI" != "n" ]; then
         tristate '  Matrox acceleration (EXPERIMENTAL)' CONFIG_FB_MATROX
index 1ebd033..3cae285 100644 (file)
@@ -100,6 +100,8 @@ obj-$(CONFIG_FB_HGA)              += hgafb.o
 obj-$(CONFIG_FB_SA1100)           += sa1100fb.o
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o  
 obj-$(CONFIG_FB_HIT)              += hitfb.o fbgen.o
+obj-$(CONFIG_FB_E1355)            += epson1355fb.o fbgen.o
+obj-$(CONFIG_FB_DC)               += dcfb.o fbgen.o
 
 # Generic Low Level Drivers
 
diff --git a/drivers/video/dcfb.c b/drivers/video/dcfb.c
new file mode 100644 (file)
index 0000000..6b72ee1
--- /dev/null
@@ -0,0 +1,504 @@
+/*
+ *     $Id: dcfb.c,v 1.1 2001/04/01 15:02:51 yaegashi Exp $
+ *     SEGA Dreamcast framebuffer
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/nubus.h>
+#include <linux/init.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+
+#include <linux/fb.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb32.h>
+
+#define BORDERRGB      0xa05f8040
+#define DISPLAYMODE    0xa05f8044
+#define ALPHAMODE      0xa05f8048
+#define DISPLAYALIGN   0xa05f804c
+#define BASEOFFSET1    0xa05f8050
+#define BASEOFFSET2    0xa05f8054
+#define DISPLAYSIZE    0xa05f805c
+#define SYNCMODE       0xa05f80d0
+#define VERTICALRANGE  0xa05f80dc
+#define HORIZPOSITION  0xa05f80ec
+#define VERTPOSITION   0xa05f80f0
+#define PALETTEMODE    0xa05f8108
+#define VIDEOOUTPUT    0xa0702c00
+
+static unsigned long dc_parm_vga_16bpp[] = {
+    DISPLAYMODE,       0x00800005,
+    BASEOFFSET1,       0,
+    BASEOFFSET2,       640*2,
+    DISPLAYSIZE,       (1<<20)+((480-1)<<10)+(640*2/4-1),
+    SYNCMODE,          0x100,
+    VERTPOSITION,      0x00230023,
+    VERTICALRANGE,     0x00280208,
+    HORIZPOSITION,     0x00000090,
+    VIDEOOUTPUT,       0,
+    0, 0,
+};
+    
+static unsigned long dc_parm_vga_32bpp[] = {
+    DISPLAYMODE,       0x0080000d,
+    BASEOFFSET1,       0,
+    BASEOFFSET2,       640*4,
+    DISPLAYSIZE,       (1<<20)+((480-1)<<10)+(640*4/4-1),
+    SYNCMODE,          0x100,
+    VERTPOSITION,      0x00230023,
+    VERTICALRANGE,     0x00280208,
+    HORIZPOSITION,     0x00000090,
+    VIDEOOUTPUT,       0,
+    0, 0,
+};
+
+static unsigned long *dc_parm_vga[] = {
+    dc_parm_vga_16bpp,
+    dc_parm_vga_32bpp,
+};
+
+static unsigned long dc_parm_composite_16bpp[] = {
+    DISPLAYMODE,       0x00000005,
+    BASEOFFSET1,       0,
+    BASEOFFSET2,       640*2,
+    DISPLAYSIZE,       ((640*2/4+1)<<20)+((240-1)<<10)+(640*2/4-1),
+    SYNCMODE,          0x150,
+    VERTPOSITION,      0x00120012,
+    VERTICALRANGE,     0x00240204,
+    HORIZPOSITION,     0x000000a4,
+    VIDEOOUTPUT,       0x300,
+    0, 0,
+};
+    
+static unsigned long dc_parm_composite_32bpp[] = {
+    DISPLAYMODE,       0x0000000d,
+    BASEOFFSET1,       0,
+    BASEOFFSET2,       640*4,
+    DISPLAYSIZE,       ((640*4/4+1)<<20)+((240-1)<<10)+(640*4/4-1),
+    SYNCMODE,          0x150,
+    VERTPOSITION,      0x00120012,
+    VERTICALRANGE,     0x00240204,
+    HORIZPOSITION,     0x000000a4,
+    VIDEOOUTPUT,       0x300,
+    0, 0,
+};
+
+static unsigned long *dc_parm_composite[] = {
+    dc_parm_composite_16bpp,
+    dc_parm_composite_32bpp,
+};
+
+static unsigned long dc_parm_interlace_16bpp[] = {
+    DISPLAYMODE,       0x00000005,
+    BASEOFFSET1,       0,
+    BASEOFFSET2,       640*2,
+    DISPLAYSIZE,       ((640*2/4+1)<<20)+((240-1)<<10)+(640*2/4-1),
+    SYNCMODE,          0x150,
+    VERTPOSITION,      0x00120012,
+    VERTICALRANGE,     0x00240204,
+    HORIZPOSITION,     0x000000a4,
+    VIDEOOUTPUT,       0,
+    0, 0,
+};
+    
+static unsigned long dc_parm_interlace_32bpp[] = {
+    DISPLAYMODE,       0x0000000d,
+    BASEOFFSET1,       0,
+    BASEOFFSET2,       640*4,
+    DISPLAYSIZE,       ((640*4/4+1)<<20)+((240-1)<<10)+(640*4/4-1),
+    SYNCMODE,          0x150,
+    VERTPOSITION,      0x00120012,
+    VERTICALRANGE,     0x00240204,
+    HORIZPOSITION,     0x000000a4,
+    VIDEOOUTPUT,       0,
+    0, 0,
+};
+
+static unsigned long *dc_parm_interlace[] = {
+    dc_parm_interlace_16bpp,
+    dc_parm_interlace_32bpp,
+};
+
+struct dcfb_info {
+    struct fb_info_gen gen;
+};
+
+struct dcfb_par
+{
+    int x, y;
+    int bpp;
+};
+
+static struct dcfb_info fb_info;
+static struct dcfb_par current_par;
+static int current_par_valid = 0;
+static struct display disp;
+
+static union {
+#ifdef FBCON_HAS_CFB16
+    u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+    u32 cfb32[16];
+#endif
+} fbcon_cmap;
+
+static unsigned long **dc_parms;
+static unsigned long dc_videobase, dc_videosize;
+static struct fb_var_screeninfo default_var;
+
+int dcfb_init(void);
+
+static void dcfb_set_par(struct dcfb_par *par, const struct fb_info *info);
+static void dcfb_encode_var(struct fb_var_screeninfo *var, 
+                             struct dcfb_par *par,
+                             const struct fb_info *info);
+
+
+/*
+ *     Check cable type.
+ *     0: VGA, 2: RGB, 3: Composite
+ */
+
+#define        PCTRA   0xff80002c
+#define PDTRA  0xff800030
+
+static int dcfb_cable_check(void)
+{
+    unsigned long temp = ctrl_inl(PCTRA);
+    temp &= 0xfff0ffff;
+    temp |= 0x000a0000;
+    ctrl_outl(temp, PCTRA);
+    return (ctrl_inw(PDTRA)>>8)&3;
+}
+
+static void dcfb_detect(void)
+{
+    struct dcfb_par par;
+    int cable = dcfb_cable_check();
+    unsigned long **parm_list[4] = {
+       dc_parm_vga, dc_parm_vga, dc_parm_interlace, dc_parm_composite,
+    };
+    char *cable_name[] = { "VGA", "VGA", "Interlace", "Composite", };
+
+    dc_videobase = 0xa5000000;
+    dc_videosize = 0x00200000;
+
+    par.x = 640;
+    par.y = 480;
+    par.bpp = 32;
+    dc_parms = parm_list[cable];
+    printk(KERN_INFO "Dreamcast video cable detected: %s.\n", cable_name[cable]);
+
+    dcfb_set_par(&par, NULL);
+    dcfb_encode_var(&default_var, &par, NULL);
+}
+
+static int dcfb_encode_fix(struct fb_fix_screeninfo *fix,
+                           struct dcfb_par *par,
+                           const struct fb_info *info)
+{
+    memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+
+    strcpy(fix->id, "SEGA Dreamcast");
+    fix->smem_start = dc_videobase;
+    fix->smem_len = dc_videosize;
+    fix->type = FB_TYPE_PACKED_PIXELS;
+    fix->type_aux = 0;
+    fix->visual = FB_VISUAL_TRUECOLOR;
+    fix->xpanstep = 0;
+    fix->ypanstep = 0;
+    fix->ywrapstep = 0;
+
+    switch(par->bpp) {
+    default:
+    case 16:
+       fix->line_length = par->x*2;
+       break;
+    case 32:
+       fix->line_length = par->x*4;
+       break;
+    }
+
+    return 0;
+}
+
+
+static int dcfb_decode_var(struct fb_var_screeninfo *var,
+                           struct dcfb_par *par,
+                           const struct fb_info *info)
+{
+    par->x = var->xres;
+    par->y = var->yres;
+    par->bpp = var->bits_per_pixel;
+    return 0;
+}
+
+
+static void dcfb_encode_var(struct fb_var_screeninfo *var, 
+                            struct dcfb_par *par,
+                            const struct fb_info *info)
+{
+    memset(var, 0, sizeof(*var));
+
+    var->xres = par->x;
+    var->yres = par->y;
+    var->xres_virtual = var->xres;
+    var->yres_virtual = var->yres;
+    var->xoffset = 0;
+    var->yoffset = 0;
+    var->bits_per_pixel = par->bpp;
+    var->grayscale = 0;
+    var->transp.offset = 0;
+    var->transp.length = 0;
+    var->transp.msb_right = 0;
+    var->nonstd = 0;
+    var->activate = 0;
+    var->height = -1;
+    var->width = -1;
+    var->vmode = FB_VMODE_NONINTERLACED;
+    var->pixclock = 0;
+    var->sync = 0;
+    var->left_margin = 0;
+    var->right_margin = 0;
+    var->upper_margin = 0;
+    var->lower_margin = 0;
+    var->hsync_len = 0;
+    var->vsync_len = 0;
+
+    switch (var->bits_per_pixel) {
+
+       case 16:        /* RGB 565 */
+           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 = 0;
+           var->transp.length = 0;
+           break;
+
+    }
+
+    var->red.msb_right = 0;
+    var->green.msb_right = 0;
+    var->blue.msb_right = 0;
+    var->transp.msb_right = 0;
+}
+
+
+static void dcfb_get_par(struct dcfb_par *par, const struct fb_info *info)
+{
+    *par = current_par;
+}
+
+
+static void dcfb_set_par(struct dcfb_par *par, const struct fb_info *info)
+{
+    unsigned long a, d, *p;
+
+    current_par = *par;
+    current_par_valid = 1;
+
+    switch(par->bpp) {
+    default:
+    case 16:
+       p = dc_parms[0];
+       break;
+    case 32:
+       p = dc_parms[1];
+       break;
+    }
+
+    ctrl_outl(0, 0xa05f8008);  /* reset? */
+    ctrl_outl(0, BORDERRGB);
+
+    while(1) {
+       a = *p++; d = *p++;
+       if (!a) break;
+       ctrl_outl(d, a);
+    }
+
+}
+
+static struct {
+  u_int red, green, blue;
+} palette[256];
+
+static int dcfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+                         u_int *transp, struct fb_info *info)
+{
+    if (regno > 255)
+       return 1;       
+
+    *red = palette[regno].red;
+    *green = palette[regno].green;
+    *blue = palette[regno].blue;
+    *transp = 0;
+    
+    return 0;
+}
+
+
+static int dcfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                         u_int transp, struct fb_info *info)
+{
+    if (regno > 255)
+       return 1;
+
+    palette[regno].red = red;
+    palette[regno].green = green;
+    palette[regno].blue = blue;
+    
+    if(regno<16) {
+       switch(current_par.bpp) {
+#ifdef FBCON_HAS_CFB16
+       case 16:
+           fbcon_cmap.cfb16[regno] =
+               ((red   & 0xf800)      ) |
+               ((green & 0xfc00) >>  5) |
+               ((blue  & 0xf800) >> 11);
+           break;
+#endif
+#ifdef FBCON_HAS_CFB32
+       case 32:
+           fbcon_cmap.cfb32[regno] =
+               ((red   & 0xff00) <<  8) |
+               ((green & 0xff00)      ) |
+               ((blue  & 0xff00) >>  8);
+           break;
+#endif
+       }
+    }
+
+    return 0;
+}
+
+static int dcfb_blank(int blank_mode, const struct fb_info *info)
+{
+    return 0;
+}
+
+
+static void dcfb_set_disp(const void *par, struct display *disp,
+                          struct fb_info_gen *info)
+{
+    disp->screen_base = (void *)dc_videobase;
+    disp->scrollmode = SCROLL_YREDRAW;
+
+    switch(((struct dcfb_par *)par)->bpp) {
+#ifdef FBCON_HAS_CFB16
+    case 16:
+       disp->dispsw = &fbcon_cfb16;
+       disp->dispsw_data = fbcon_cmap.cfb16;
+       break;
+#endif
+#ifdef FBCON_HAS_CFB32
+    case 32:
+       disp->dispsw = &fbcon_cfb32;
+       disp->dispsw_data = fbcon_cmap.cfb32;
+       break;
+#endif
+    default:
+       disp->dispsw = &fbcon_dummy;
+    }
+}
+
+
+struct fbgen_hwswitch dcfb_switch = {
+    dcfb_detect,
+    dcfb_encode_fix,
+    dcfb_decode_var,
+    dcfb_encode_var,
+    dcfb_get_par,
+    dcfb_set_par,
+    dcfb_getcolreg,
+    dcfb_setcolreg,
+    NULL,
+    dcfb_blank,
+    dcfb_set_disp
+};
+
+static struct fb_ops dcfb_ops = {
+       owner:          THIS_MODULE,
+       fb_get_fix:     fbgen_get_fix,
+       fb_get_var:     fbgen_get_var,
+       fb_set_var:     fbgen_set_var,
+       fb_get_cmap:    fbgen_get_cmap,
+       fb_set_cmap:    fbgen_set_cmap,
+};
+
+
+int __init dcfb_init(void)
+{
+    strcpy(fb_info.gen.info.modename, "SEGA Dreamcast");
+    fb_info.gen.info.node = -1;
+    fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
+    fb_info.gen.info.fbops = &dcfb_ops;
+    fb_info.gen.info.disp = &disp;
+    fb_info.gen.info.changevar = NULL;
+    fb_info.gen.info.switch_con = &fbgen_switch;
+    fb_info.gen.info.updatevar = &fbgen_update_var;
+    fb_info.gen.info.blank = &fbgen_blank;
+    fb_info.gen.parsize = sizeof(struct dcfb_par);
+    fb_info.gen.fbhw = &dcfb_switch;
+    fb_info.gen.fbhw->detect();
+    
+    fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
+    disp.var.activate = FB_ACTIVATE_NOW;
+    fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
+    fbgen_set_disp(-1, &fb_info.gen);
+    fbgen_install_cmap(0, &fb_info.gen);
+    
+    if(register_framebuffer(&fb_info.gen.info)<0) return -EINVAL;
+    
+    printk(KERN_INFO "fb%d: %s frame buffer device\n",
+          GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename);
+    
+    return 0;
+}
+
+
+void dcfb_cleanup(struct fb_info *info)
+{
+    unregister_framebuffer(info);
+}
+
+
+#ifdef MODULE
+int init_module(void)
+{
+    return dcfb_init();
+}
+
+void cleanup_module(void)
+{
+    dcfb_cleanup(void);
+}
+#endif
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
new file mode 100644 (file)
index 0000000..465b566
--- /dev/null
@@ -0,0 +1,539 @@
+/*
+ * linux/drivers/video/epson1355fb.c
+ *     -- Support for the Epson SED1355 LCD/CRT controller
+ *
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ * based on linux/drivers/video/skeletonfb.c, which was
+ *  Created 28 Dec 1997 by Geert Uytterhoeven
+ *
+ * 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.
+ */
+/* TODO (roughly in order of priority):
+ * 16 bpp support
+ * crt support
+ * hw cursor support
+ * SwivelView
+ */
+
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/tty.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-mfb.h>
+#include <video/fbcon.h>
+
+/* Register defines.  The docs don't seem to provide nice mnemonic names
+ * so I made them up myself ... */
+
+#define E1355_PANEL    0x02
+#define E1355_DISPLAY  0x0D
+#define E1355_MISC     0x1B
+#define E1355_GPIO     0x20
+#define E1355_LUT_INDEX 0x24
+#define E1355_LUT_DATA 0x26
+
+#ifdef CONFIG_SUPERH
+#define E1355_REG_BASE CONFIG_E1355_REG_BASE
+#define E1355_FB_BASE  CONFIG_E1355_FB_BASE
+
+static inline u8 e1355_read_reg(int index)
+{
+       return ctrl_inb(E1355_REG_BASE + index);
+}
+
+static inline void e1355_write_reg(u8 data, int index)
+{
+       ctrl_outb(data, E1355_REG_BASE + index);
+}
+
+static inline u16 e1355_read_reg16(int index)
+{
+       return e1355_read_reg(index) + (e1355_read_reg(index+1) << 8);
+}
+
+static inline void e1355_write_reg16(u16 data, int index)
+{
+       e1355_write_reg((data&0xff), index);
+       e1355_write_reg(((data>>8)&0xff), index + 1);
+}
+#else
+#error unknown architecture
+#endif
+
+struct e1355fb_info {
+       struct fb_info_gen gen;
+};
+
+static int current_par_valid = 0;
+static struct display disp;
+
+static struct fb_var_screeninfo default_var;
+
+int e1355fb_init(void);
+int e1355fb_setup(char*);
+static int e1355_encode_var(struct fb_var_screeninfo *var, const void *par,
+                           struct fb_info_gen *info);
+/* ------------------- chipset specific functions -------------------------- */
+
+
+static void disable_hw_cursor(void)
+{
+       u8 curs;
+
+       curs = e1355_read_reg(0x27);
+       curs &= ~0xc0;
+       e1355_write_reg(curs, 0x27);
+}
+
+static void e1355_detect(void)
+{
+       u8 rev;
+
+       e1355_write_reg(0x00, E1355_MISC);
+
+       rev = e1355_read_reg(0x00);
+
+       if ((rev & 0xfc) != 0x0c) {
+               printk(KERN_WARNING "Epson 1355 not detected\n");
+       }
+
+       /* XXX */
+       disable_hw_cursor();
+
+       e1355_encode_var(&default_var, NULL, NULL);
+}
+
+struct e1355_par {
+       u32 xres;
+       u32 yres;
+
+       int bpp;
+       int mem_bpp;
+
+       u32 panel_xres;
+       u32 panel_yres;
+       
+       int panel_width;
+       int panel_ymul;
+};
+
+static int e1355_encode_fix(struct fb_fix_screeninfo *fix,
+                           const void *raw_par,
+                           struct fb_info_gen *info)
+{
+       const struct e1355_par *par = raw_par;
+       
+       memset(fix, 0, sizeof *fix);
+       
+       fix->type= FB_TYPE_PACKED_PIXELS;
+
+       if (!par)
+               BUG();
+
+       if (par->bpp == 1) {
+               fix->visual = FB_VISUAL_MONO10;
+       } else if (par->bpp <= 8) {
+               fix->visual = FB_VISUAL_PSEUDOCOLOR;
+       } else {
+               fix->visual = FB_VISUAL_TRUECOLOR;
+       }
+
+       return 0;
+}
+
+static int e1355_set_bpp(struct e1355_par *par, int bpp)
+{
+       int code;
+       u8 disp;
+       u16 bytes_per_line;
+
+       switch(bpp) {
+       case 1:
+               code = 0; break;
+       case 2:
+               code = 1; break;
+       case 4:
+               code = 2; break;
+       case 8:
+               code = 3; break;
+       case 16:
+               code = 5; break;
+       default:
+               return -EINVAL; break;
+       }
+
+       disp = e1355_read_reg(E1355_DISPLAY);
+       disp &= ~0x1c;
+       disp |= code << 2;
+       e1355_write_reg(disp, E1355_DISPLAY);
+       
+       bytes_per_line = (par->xres * bpp) >> 3;
+       
+       e1355_write_reg16(bytes_per_line, 0x16);
+
+       par->bpp = bpp;
+
+       return 0;
+}
+               
+static int e1355_decode_var(const struct fb_var_screeninfo *var,
+                           void *raw_par,
+                           struct fb_info_gen *info)
+{
+       struct e1355_par *par = raw_par;
+       int ret;
+
+       if (!par)
+               BUG();
+
+       /*
+        * Don't allow setting any of these yet: xres and yres don't
+        * make sense for LCD panels; xres_virtual and yres_virtual
+        * should be supported fine by our hardware though.
+        */
+       if (var->xres != par->xres ||
+           var->yres != par->yres ||
+           var->xres != var->xres_virtual ||
+           var->yres != var->yres_virtual ||
+           var->xoffset != 0 ||
+           var->yoffset != 0)
+               return -EINVAL;
+
+       if(var->bits_per_pixel != par->bpp) {
+               ret = e1355_set_bpp(par, var->bits_per_pixel);
+
+               if (ret)
+                       goto out_err;
+       }
+               
+       return 0;
+
+ out_err:
+       return ret;
+}
+
+static void dump_panel_data(void)
+{
+       u8 panel = e1355_read_reg(E1355_PANEL);
+       int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };
+
+       printk("%s %s %s panel, width %d bits\n",
+              panel & 2 ? "dual" : "single",
+              panel & 4 ? "color" : "mono",
+              panel & 1 ? "TFT" : "passive",
+              width[panel&1][(panel>>4)&3]);
+
+       printk("resolution %d x %d\n",
+              (e1355_read_reg(0x04) + 1) * 8,
+              ((e1355_read_reg16(0x08) + 1) * (1 + ((panel & 3) == 2))));
+}
+
+static int e1355_bpp_to_var(int bpp, struct fb_var_screeninfo *var)
+{
+       switch(bpp) {
+       case 1:
+       case 2:
+       case 4:
+       case 8:
+               var->bits_per_pixel = bpp;
+               var->red.offset = var->green.offset = var->blue.offset = 0;
+               var->red.length = var->green.length = var->blue.length = bpp;
+               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;
+               break;
+       }
+
+       return 0;
+}
+
+static int e1355_encode_var(struct fb_var_screeninfo *var, const void *raw_par,
+                           struct fb_info_gen *info)
+{
+       u8 panel, display;
+       u32 xres, xres_virtual, yres;
+       static int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };
+       static int bpp_tab[8] = { 1, 2, 4, 8, 15, 16 };
+       int bpp, hw_bpp;
+       int is_color, is_dual, is_tft;
+       int lcd_enabled, crt_enabled;
+
+       panel = e1355_read_reg(E1355_PANEL);
+       display = e1355_read_reg(E1355_DISPLAY);
+
+       is_color = (panel & 0x04) != 0;
+       is_dual  = (panel & 0x02) != 0;
+       is_tft   = (panel & 0x01) != 0;
+
+       bpp = bpp_tab[(display>>2)&7]; 
+       e1355_bpp_to_var(bpp, var);
+
+       crt_enabled = (display & 0x02) != 0;
+       lcd_enabled = (display & 0x02) != 0;
+
+       hw_bpp = width[is_tft][(panel>>4)&3];
+
+       xres = e1355_read_reg(0x04) + 1;
+       yres = e1355_read_reg16(0x08) + 1;
+       
+       xres *= 8;
+       /* talk about weird hardware .. */
+       yres *= (is_dual && !crt_enabled) ? 2 : 1;
+
+       xres_virtual = e1355_read_reg16(0x16);
+       /* it's in 2-byte words initially */
+       xres_virtual *= 16;
+       xres_virtual /= var->bits_per_pixel;
+
+       var->xres = xres;
+       var->yres = yres;
+       var->xres_virtual = xres_virtual;
+       var->yres_virtual = yres;
+
+       var->xoffset = var->yoffset = 0;
+
+       var->grayscale = !is_color;
+       
+       return 0;
+}
+
+#define is_dual(panel) (((panel)&3)==2)
+
+static void get_panel_data(struct e1355_par *par)
+{
+       u8 panel;
+       int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };
+
+       panel = e1355_read_reg(E1355_PANEL);
+
+       par->panel_width = width[panel&1][(panel>>4)&3];
+       par->panel_xres = (e1355_read_reg(0x04) + 1) * 8;
+       par->panel_ymul = is_dual(panel) ? 2 : 1;
+       par->panel_yres = ((e1355_read_reg16(0x08) + 1)
+                          * par->panel_ymul);
+}
+
+static void e1355_get_par(void *raw_par, struct fb_info_gen *info)
+{
+       struct e1355_par *par = raw_par;
+
+       get_panel_data(par);
+}
+
+static void e1355_set_par(const void *par, struct fb_info_gen *info)
+{
+}
+
+static int e1355_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+                          unsigned *blue, unsigned *transp,
+                          struct fb_info *info)
+{
+       u8 r, g, b;
+
+       e1355_write_reg(regno, E1355_LUT_INDEX);
+       r = e1355_read_reg(E1355_LUT_DATA);
+       g = e1355_read_reg(E1355_LUT_DATA);
+       b = e1355_read_reg(E1355_LUT_DATA);
+
+       *red = r << 8;
+       *green = g << 8;
+       *blue = b << 8;
+
+       return 0;
+}
+
+static int e1355_setcolreg(unsigned regno, unsigned red, unsigned green,
+                          unsigned blue, unsigned transp,
+                          struct fb_info *info)
+{
+       u8 r = (red >> 8) & 0xf0;
+       u8 g = (green>>8) & 0xf0;
+       u8 b = (blue>> 8) & 0xf0;
+
+       e1355_write_reg(regno, E1355_LUT_INDEX);
+       e1355_write_reg(r, E1355_LUT_DATA);
+       e1355_write_reg(g, E1355_LUT_DATA);
+       e1355_write_reg(b, E1355_LUT_DATA);
+       
+       return 0;
+}
+
+static int e1355_pan_display(const struct fb_var_screeninfo *var,
+                            struct fb_info_gen *info)
+{
+       BUG();
+       
+       return -EINVAL;
+}
+
+/*
+ * The AERO_HACKS parts disable/enable the backlight on the Compaq Aero 8000.
+ * I'm not sure they aren't dangerous to the hardware, so be warned.
+ */
+#undef AERO_HACKS
+
+static int e1355_blank(int blank_mode, struct fb_info_gen *info)
+{
+       u8 disp;
+
+       switch (blank_mode) {
+       case VESA_NO_BLANKING:
+               disp = e1355_read_reg(E1355_DISPLAY);
+               disp |= 1;
+               e1355_write_reg(disp, E1355_DISPLAY);
+               
+#ifdef AERO_HACKS
+               e1355_write_reg(0x6, 0x20);
+#endif
+               break;
+
+       case VESA_VSYNC_SUSPEND:
+       case VESA_HSYNC_SUSPEND:
+       case VESA_POWERDOWN:
+               disp = e1355_read_reg(E1355_DISPLAY);
+               disp &= ~1;
+               e1355_write_reg(disp, E1355_DISPLAY);
+
+#ifdef AERO_HACKS
+               e1355_write_reg(0x0, 0x20);
+#endif
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static struct display_switch e1355_dispsw;
+
+static void e1355_set_disp(const void *unused, struct display *disp,
+                          struct fb_info_gen *info)
+{
+       struct display_switch *d;
+
+       disp->screen_base = (void *)E1355_FB_BASE;
+       disp->dispsw = &e1355_dispsw;
+       
+       switch(disp->var.bits_per_pixel) {
+#ifdef FBCON_HAS_MFB
+       case 1:
+               d = &fbcon_mfb; break;
+#endif        
+#ifdef FBCON_HAS_CFB8
+       case 8:
+               d = &fbcon_cfb8; break;
+#endif
+       default:
+               BUG(); break;
+       }
+
+       memcpy(&e1355_dispsw, d, sizeof *d);
+
+       /* reading is terribly slow for us */
+#if 0 /* XXX: need to work out why this doesn't work */
+       e1355_dispsw.bmove = fbcon_redraw_bmove;
+#endif
+}
+
+/* ------------ Interfaces to hardware functions ------------ */
+
+
+struct fbgen_hwswitch e1355_switch = {
+       detect:         e1355_detect,
+       encode_fix:     e1355_encode_fix,
+       decode_var:     e1355_decode_var,
+       encode_var:     e1355_encode_var,
+       get_par:        e1355_get_par,
+       set_par:        e1355_set_par,
+       getcolreg:      e1355_getcolreg,
+       setcolreg:      e1355_setcolreg,
+       pan_display:    e1355_pan_display,
+       blank:          e1355_blank,
+       set_disp:       e1355_set_disp,
+};
+
+
+/* ------------ Hardware Independent Functions ------------ */
+
+
+static struct fb_ops e1355fb_ops = {
+       owner:          THIS_MODULE,
+       fb_get_fix:     fbgen_get_fix,
+       fb_get_var:     fbgen_get_var,
+       fb_set_var:     fbgen_set_var,
+       fb_get_cmap:    fbgen_get_cmap,
+       fb_set_cmap:    fbgen_set_cmap,
+       fb_pan_display: fbgen_pan_display,
+};
+
+static struct e1355fb_info fb_info;
+
+int __init e1355fb_setup(char *str)
+{
+       return 0;
+}
+
+int __init e1355fb_init(void)
+{
+       fb_info.gen.fbhw = &e1355_switch;
+       fb_info.gen.fbhw->detect();
+       strcpy(fb_info.gen.info.modename, "SED1355");
+       fb_info.gen.info.changevar = NULL;
+       fb_info.gen.info.node = -1;
+       fb_info.gen.info.fbops = &e1355fb_ops;
+       fb_info.gen.info.disp = &disp;
+       fb_info.gen.parsize = sizeof(struct e1355_par);
+       fb_info.gen.info.switch_con = &fbgen_switch;
+       fb_info.gen.info.updatevar = &fbgen_update_var;
+       fb_info.gen.info.blank = &fbgen_blank;
+       fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
+       /* This should give a reasonable default video mode */
+       fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
+       fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
+       fbgen_set_disp(-1, &fb_info.gen);
+       if (disp.var.bits_per_pixel > 1) 
+               fbgen_install_cmap(0, &fb_info.gen);
+       if (register_framebuffer(&fb_info.gen.info) < 0)
+               return -EINVAL;
+       printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node),
+              fb_info.gen.info.modename);
+
+       return 0;
+}
+
+
+    /*
+     *  Cleanup
+     */
+
+void e1355fb_cleanup(struct fb_info *info)
+{
+       /*
+        *  If your driver supports multiple boards, you should unregister and
+        *  clean up all instances.
+        */
+       
+       unregister_framebuffer(info);
+       /* ... */
+}
+
index 2241b4c..ebbd428 100644 (file)
@@ -120,7 +120,10 @@ extern int stifb_init(void);
 extern int stifb_setup(char*);
 extern int radeonfb_init(void);
 extern int radeonfb_setup(char*);
-
+extern int e1355fb_init(void);
+extern int e1355fb_setup(char*);
+extern int dcfb_init(void);
+  
 static struct {
        const char *name;
        int (*init)(void);
@@ -199,6 +202,9 @@ static struct {
 #ifdef CONFIG_FB_SIS
        { "sisfb", sisfb_init, sisfb_setup },
 #endif
+#ifdef CONFIG_FB_E1355
+       { "e1355fb", e1355fb_init, e1355fb_setup },
+#endif
 
        /*
         * Generic drivers that are used as fallbacks
@@ -264,6 +270,9 @@ static struct {
 #ifdef CONFIG_FB_HIT
        { "hitfb", hitfb_init, NULL },
 #endif
+#ifdef CONFIG_FB_DC
+       { "dcfb", dcfb_init, NULL },
+#endif
 
        /*
         * Generic drivers that don't use resource management (yet)
index b268543..5a49484 100644 (file)
@@ -3339,7 +3339,7 @@ static int devfsd_close (struct inode *inode, struct file *file)
 }   /*  End Function devfsd_close  */
 
 
-int __init init_devfs_fs (void)
+static int __init init_devfs_fs (void)
 {
     int err;
 
@@ -3369,3 +3369,5 @@ void __init mount_devfs_fs (void)
     if (err == 0) printk ("Mounted devfs on /dev\n");
     else printk ("Warning: unable to mount devfs, err: %d\n", err);
 }   /*  End Function mount_devfs_fs  */
+
+module_init(init_devfs_fs)
index 175a407..6d8ee90 100644 (file)
@@ -220,7 +220,7 @@ void devpts_pty_kill(int number)
        }
 }
 
-int __init init_devpts_fs(void)
+static int __init init_devpts_fs(void)
 {
        int err = register_filesystem(&devpts_fs_type);
        if (!err) {
@@ -228,28 +228,25 @@ int __init init_devpts_fs(void)
                err = PTR_ERR(devpts_mnt);
                if (!IS_ERR(devpts_mnt))
                        err = 0;
-       }
-       return err;
-}
-
 #ifdef MODULE
-
-int init_module(void)
-{
-       int err = init_devpts_fs();
-       if ( !err ) {
-               devpts_upcall_new  = devpts_pty_new;
-               devpts_upcall_kill = devpts_pty_kill;
+               if ( !err ) {
+                       devpts_upcall_new  = devpts_pty_new;
+                       devpts_upcall_kill = devpts_pty_kill;
+               }
+#endif
        }
        return err;
 }
 
-void cleanup_module(void)
+static void __exit exit_devpts_fs(void)
 {
+#ifdef MODULE
        devpts_upcall_new  = NULL;
        devpts_upcall_kill = NULL;
+#endif
        unregister_filesystem(&devpts_fs_type);
        kern_umount(devpts_mnt);
 }
 
-#endif
+module_init(init_devpts_fs)
+module_exit(exit_devpts_fs)
index 00da822..f93f72c 100644 (file)
@@ -7,37 +7,11 @@
  */
 
 #include <linux/config.h>
-#include <linux/fs.h>
-
-#include <linux/devfs_fs_kernel.h>
-#include <linux/nfs_fs.h>
-#include <linux/auto_fs.h>
-#include <linux/devpts_fs.h>
-#include <linux/major.h>
-#include <linux/smp.h>
+#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/module.h>
 #include <linux/nfsd/interface.h>
 
-#ifdef CONFIG_DEVPTS_FS
-extern int init_devpts_fs(void);
-#endif
-
-void __init filesystem_setup(void)
-{
-       init_devfs_fs();  /*  Header file may make this empty  */
-
-#ifdef CONFIG_NFS_FS
-       init_nfs_fs();
-#endif
-
-#ifdef CONFIG_DEVPTS_FS
-       init_devpts_fs();
-#endif
-}
-
 #if defined(CONFIG_NFSD_MODULE)
 struct nfsd_linkage *nfsd_linkage = NULL;
 
index abd08ee..b2d18fa 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/init.h>
 
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -1060,8 +1061,7 @@ extern int nfs_destroy_readpagecache(void);
 /*
  * Initialize NFS
  */
-int
-init_nfs_fs(void)
+static int __init init_nfs_fs(void)
 {
        int err;
 
@@ -1079,23 +1079,7 @@ init_nfs_fs(void)
         return register_filesystem(&nfs_fs_type);
 }
 
-/*
- * Every kernel module contains stuff like this.
- */
-#ifdef MODULE
-
-EXPORT_NO_SYMBOLS;
-/* Not quite true; I just maintain it */
-MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
-
-int
-init_module(void)
-{
-       return init_nfs_fs();
-}
-
-void
-cleanup_module(void)
+static void __exit exit_nfs_fs(void)
 {
        nfs_destroy_readpagecache();
        nfs_destroy_nfspagecache();
@@ -1104,4 +1088,10 @@ cleanup_module(void)
 #endif
        unregister_filesystem(&nfs_fs_type);
 }
-#endif
+
+EXPORT_NO_SYMBOLS;
+/* Not quite true; I just maintain it */
+MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
+
+module_init(init_nfs_fs)
+module_exit(exit_nfs_fs)
index e082843..1d2d795 100644 (file)
@@ -9,7 +9,7 @@
 
 O_TARGET := partitions.o
 
-export-objs := check.o
+export-objs := check.o ibm.o
 
 obj-y := check.o
 
index be3e7ea..f30f679 100644 (file)
@@ -1,14 +1,17 @@
 /*
  * File...........: linux/fs/partitions/ibm.c      
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ *                  Volker Sameske <sameske@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
 
  * History of changes (starts July 2000)
- * 07/10/00 Fixed detection of CMS formatted disks               
-
+ * 07/10/00 Fixed detection of CMS formatted disks     
+ * 02/13/00 VTOC partition support added
  */
 
+#include <linux/config.h>
+#include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/genhd.h>
 #include <linux/kernel.h>
 
 #include "ibm.h"
 #include "check.h"
+#include <asm/vtoc.h>
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
 /* We hook in when DASD is a module... */
 int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
+int (*genhd_dasd_fillgeo)(int,struct hd_geometry *) = NULL;
+EXPORT_SYMBOL(genhd_dasd_fillgeo);
+EXPORT_SYMBOL(genhd_dasd_name);
 #endif /* LINUX_IS_24 */
 
 typedef enum {
-  ibm_partition_none = 0,
-  ibm_partition_lnx1 = 1,
-  ibm_partition_vol1 = 3,
-  ibm_partition_cms1 = 4
+  ibm_partition_lnx1 = 0,
+  ibm_partition_vol1 = 1,
+  ibm_partition_cms1 = 2,
+  ibm_partition_none = 3
 } ibm_partition_t;
 
+static char* part_names[] = {   [ibm_partition_lnx1] = "LNX1",
+                            [ibm_partition_vol1] = "VOL1",
+                            [ibm_partition_cms1] = "CMS1",
+                            [ibm_partition_none] = "(nonl)"
+};
+
 static ibm_partition_t
 get_partition_type ( char * type )
 {
-        static char lnx[5]="LNX1";
-        static char vol[5]="VOL1";
-        static char cms[5]="CMS1";
-        if ( ! strncmp ( lnx, "LNX1",4 ) ) {
-                ASCEBC(lnx,4);
-                ASCEBC(vol,4);
-                ASCEBC(cms,4);
-        }
-        if ( ! strncmp (type,lnx,4) ||
-             ! strncmp (type,"LNX1",4) )
-                return ibm_partition_lnx1;
-        if ( ! strncmp (type,vol,4) )
-                return ibm_partition_vol1;
-        if ( ! strncmp (type,cms,4) )
-                return ibm_partition_cms1;
-        return ibm_partition_none;
+       int i;
+       for ( i = 0; i < 3; i ++) {
+               if ( ! strncmp (type,part_names[i],4) ) 
+                       break;
+       }
+        return i;
+}
+
+/*
+ * add the two default partitions
+ * - whole dasd
+ * - whole dasd without "offset"
+ */
+static inline void
+two_partitions(struct gendisk *hd,
+              int minor,
+              int blocksize,
+              int offset,
+              int size) {
+
+        add_gd_partition( hd, minor, 0,size);
+       add_gd_partition( hd, minor + 1, 
+                          offset * (blocksize >> 9),
+                          size-offset*(blocksize>>9));
+}
+
+
+/*
+ * compute the block number from a 
+ * cyl-cyl-head-head structure
+ */
+static inline int
+cchh2blk (cchh_t *ptr, struct hd_geometry *geo) {
+        return ptr->cc * geo->heads * geo->sectors +
+              ptr->hh * geo->sectors;
+}
+
+
+/*
+ * compute the block number from a 
+ * cyl-cyl-head-head-block structure
+ */
+static inline int
+cchhb2blk (cchhb_t *ptr, struct hd_geometry *geo) {
+        return ptr->cc * geo->heads * geo->sectors +
+               ptr->hh * geo->sectors +
+               ptr->b;
 }
 
 int 
 ibm_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int
 first_part_minor)
 {
-       struct buffer_head *bh;
+       struct buffer_head *bh, *buf;
        ibm_partition_t partition_type;
        char type[5] = {0,};
        char name[7] = {0,};
        struct hd_geometry geo;
-       mm_segment_t old_fs;
        int blocksize;
-       struct file *filp = NULL;
-       struct inode *inode = NULL;
-       int offset, size;
+       int offset=0, size=0, psize=0, counter=0;
+       unsigned int blk;
+       format1_label_t f1;
+       volume_label_t vlabel;
 
+       if ( first_sector != 0 ) {
+               BUG();
+       }
+       if ( !genhd_dasd_fillgeo ) {
+               return 0;
+       }
+       genhd_dasd_fillgeo(dev,&geo);
        blocksize = hardsect_size[MAJOR(dev)][MINOR(dev)];
        if ( blocksize <= 0 ) {
                return 0;
        }
-       set_blocksize(dev, blocksize);  /* OUCH !! */
 
-       /* find out offset of volume label (partn table) */
-       inode = get_empty_inode();
-       inode -> i_rdev = dev;
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
-       inode -> i_bdev = bdget(kdev_t_to_nr(dev));
-#endif /* KERNEL_VERSION */
-       filp = (struct file *)kmalloc (sizeof(struct file),GFP_KERNEL);
-       if (!filp)
-               return 0;
-       memset(filp,0,sizeof(struct file));
-       filp ->f_mode = 1; /* read only */
-       blkdev_open(inode,filp);
-       old_fs=get_fs();
-       set_fs(KERNEL_DS);
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
-       inode-> i_bdev -> bd_op->ioctl (inode, filp, HDIO_GETGEO, (unsigned long)(&geo));
-#else
-       filp->f_op->ioctl (inode, filp, HDIO_GETGEO, (unsigned long)(&geo));
-#endif /* KERNEL_VERSION */
-       set_fs(old_fs);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0))
-        blkdev_put(inode->i_bdev,BDEV_FILE);
-#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
-       blkdev_close(inode,filp);
-#else
-       blkdev_release(inode);
-#endif /* LINUX_VERSION_CODE */
-
-       size = hd -> sizes[MINOR(dev)]<<1;
+       set_blocksize(dev, blocksize);  /* OUCH !! */
        if ( ( bh = bread( dev, geo.start, blocksize) ) != NULL ) {
-               strncpy ( type,bh -> b_data, 4);
+               strncpy ( type,bh -> b_data + 0, 4);
                strncpy ( name,bh -> b_data + 4, 6);
+               memcpy (&vlabel, bh->b_data, sizeof(volume_label_t));
         } else {
                return 0;
        }
-       if ( (*(char *)bh -> b_data) & 0x80 ) {
-               EBCASC(name,6);
-       }
-       switch ( partition_type = get_partition_type(type) ) {
-       case ibm_partition_lnx1: 
-               offset = (geo.start + 1);
-               printk ( "(LNX1)/%6s:",name);
-               break;
-       case ibm_partition_vol1:
-               offset = 0;
-               size = 0;
-               printk ( "(VOL1)/%6s:",name);
-               break;
+       EBCASC(type,4);
+       EBCASC(name,6);
+
+       partition_type = get_partition_type(type);
+       printk ( "%6s/%6s:",part_names[partition_type],name);
+       switch ( partition_type ) {
        case ibm_partition_cms1:
-               printk ( "(CMS1)/%6s:",name);
-               if (* (((long *)bh->b_data) + 13) == 0) {
-                       /* disk holds a CMS filesystem */
-                       offset = (geo.start + 1);
-                       printk ("(CMS)");
-               } else {
+               if (* (((long *)bh->b_data) + 13) != 0) {
                        /* disk is reserved minidisk */
-                       // mdisk_setup_data.size[i] =
-                       // (label[7] - 1 - label[13]) *
-                       // (label[3] >> 9) >> 1;
                        long *label=(long*)bh->b_data;
                        blocksize = label[3];
                        offset = label[13];
                        size = (label[7]-1)*(blocksize>>9); 
                        printk ("(MDSK)");
+               } else {
+                       offset = (geo.start + 1);
+                       size = hd -> sizes[MINOR(dev)]<<1;
                }
+               two_partitions( hd, MINOR(dev), blocksize, 
+                               offset, size);
                break;
+       case ibm_partition_lnx1: 
        case ibm_partition_none:
-               printk ( "(nonl)/      :");
-               offset = (geo.start+1);
+               offset = (geo.start + 1);
+               size = hd -> sizes[MINOR(dev)]<<1;
+               two_partitions( hd, MINOR(dev), blocksize, 
+                               offset, size);
+               break;
+       case ibm_partition_vol1:
+               add_gd_partition(hd, MINOR(dev), 0, size);
+
+               /* get block number and read then first format1 label */
+               blk = cchhb2blk(&vlabel.vtoc, &geo) + 1;
+               if ((buf = bread( dev, blk, blocksize)) != NULL) {
+                       memcpy (&f1, buf->b_data, sizeof(format1_label_t));
+                       bforget(buf);
+               }
+
+               while (f1.DS1FMTID == _ascebc['1']) {
+                       offset = cchh2blk(&f1.DS1EXT1.llimit, &geo);
+                       psize  = cchh2blk(&f1.DS1EXT1.ulimit, &geo) - 
+                               offset + 1;
+                       
+                       counter++;
+                       add_gd_partition(hd, MINOR(dev) + counter, 
+                                         offset * (blocksize >> 9),
+                                         psize * (blocksize >> 9));
+                       
+                       blk++;
+                       if ((buf = bread( dev, blk, blocksize)) != NULL) {
+                               memcpy (&f1, buf->b_data, 
+                                       sizeof(format1_label_t));
+                               bforget(buf);
+                       }
+               }
                break;
        default:
-               offset = 0;
-               size = 0;
-               
+               add_gd_partition( hd, MINOR(dev), 0, 0);
+               add_gd_partition( hd, MINOR(dev) + 1, 0, 0);
        }
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
-       add_gd_partition( hd, MINOR(dev), 0,size);
-       add_gd_partition( hd, MINOR(dev) + 1, offset * (blocksize >> 9),
-                         size-offset*(blocksize>>9));
-#else
-       add_partition( hd, MINOR(dev), 0,size,0);
-       add_partition( hd, MINOR(dev) + 1, offset * (blocksize >> 9),
-                         size-offset*(blocksize>>9) ,0 );
-#endif /* LINUX_VERSION */
+
        printk ( "\n" );
        bforget(bh);
        return 1;
index 78ce6a0..d61d6b9 100644 (file)
@@ -274,8 +274,10 @@ static int kstat_read_proc(char *page, char **start, off_t off,
                user += kstat.per_cpu_user[cpu];
                nice += kstat.per_cpu_nice[cpu];
                system += kstat.per_cpu_system[cpu];
+#if !defined(CONFIG_ARCH_S390)
                for (j = 0 ; j < NR_IRQS ; j++)
                        sum += kstat.irqs[cpu][j];
+#endif
        }
 
        len = sprintf(page, "cpu  %u %u %u %lu\n", user, nice, system,
@@ -299,8 +301,10 @@ static int kstat_read_proc(char *page, char **start, off_t off,
                        kstat.pswpout,
                        sum
        );
+#if !defined(CONFIG_ARCH_S390)
        for (i = 0 ; i < NR_IRQS ; i++)
                len += sprintf(page + len, " %u", kstat_irqs(i));
+#endif
 
        len += sprintf(page + len, "\ndisk_io: ");
 
index f050e24..321c984 100644 (file)
@@ -479,7 +479,7 @@ static int get_num_ver (int mode, struct tree_balance * tb, int h,
     // do not count last 'end_bytes' units of 'end_item'-th item
     end_bytes = (to_bytes != -1) ? to_bytes : 0;
 
-    /* go through all item begining from the start_item-th item and ending by
+    /* go through all item beginning from the start_item-th item and ending by
        the end_item-th item. Do not count first 'start_bytes' units of
        'start_item'-th item and last 'end_bytes' of 'end_item'-th item */
     
index 40cabc5..1ae19cb 100644 (file)
@@ -259,14 +259,14 @@ void reiserfs_warning (const char * fmt, ...)
 {
   do_reiserfs_warning;
   /* console_print (error_buf); */
-  printk ("%s", error_buf);
+  printk (KERN_WARNING "%s", error_buf);
 }
 
 void reiserfs_debug (struct super_block *s, int level, const char * fmt, ...)
 {
 #ifdef CONFIG_REISERFS_CHECK
   do_reiserfs_warning;
-  printk ("%s", error_buf);
+  printk (KERN_DEBUG "%s", error_buf);
 #else
   ; 
 #endif
index 83c7cd8..19c3751 100644 (file)
@@ -380,7 +380,7 @@ inline      struct  key * get_rkey  (
     /* Parent at the path is not in the tree now. */
     if ( ! B_IS_IN_TREE(p_s_parent = PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset)) )
       return &MIN_KEY;
-    /* Check whether position in the parrent is correct. */
+    /* Check whether position in the parent is correct. */
     if ( (n_position = PATH_OFFSET_POSITION(p_s_chk_path, n_path_offset)) > B_NR_ITEMS(p_s_parent) )
       return &MIN_KEY;
     /* Check whether parent at the path really points to the child. */
index 2d35ffe..5c7be16 100644 (file)
@@ -412,6 +412,7 @@ static int read_old_super_block (struct super_block * s, int size)
     SB_BUFFER_WITH_SB (s) = bh;
     SB_DISK_SUPER_BLOCK (s) = rs;
     s->s_op = &reiserfs_sops;
+    s->s_maxbytes = MAX_NON_LFS;
     return 0;
 }
 #endif
index c9cdea9..df6eb97 100644 (file)
@@ -403,9 +403,11 @@ romfs_readpage(struct file *file, struct page * page)
        void *buf;
        int result = -EIO;
 
+       page_cache_get(page);
        lock_kernel();
-       get_page(page);
-       buf = page_address(page);
+       buf = kmap(page);
+       if (!buf)
+               goto err_out;
 
        /* 32 bit warning -- but not for us :) */
        offset = page->index << PAGE_CACHE_SHIFT;
@@ -428,7 +430,9 @@ romfs_readpage(struct file *file, struct page * page)
 
        UnlockPage(page);
 
-       __free_page(page);
+       kunmap(page);
+err_out:
+       page_cache_release(page);
        unlock_kernel();
 
        return result;
index 73dc857..ff8ddc0 100644 (file)
@@ -45,7 +45,7 @@ smb_ioctl(struct inode *inode, struct file *filp,
                if (!copy_from_user(&opt, (void *)arg, sizeof(opt)))
                        result = smb_newconn(server, &opt);
                break;
-       default:
+       default:;
        }
 
        return result;
index 4725ab7..b2f93c2 100644 (file)
@@ -697,7 +697,7 @@ smb_retry(struct smb_sb_info *server)
 #else
        /*
         * We don't want to be interrupted. For example, what if 'current'
-        * already has recieved a signal? sleep_on would terminate immediately
+        * already has received a signal? sleep_on would terminate immediately
         * and smbmount would not be able to re-establish connection.
         *
         * smbmount should be able to reconnect later, but it can't because
@@ -712,7 +712,7 @@ smb_retry(struct smb_sb_info *server)
        if (server->state == CONN_VALID) {
                /* This should be changed to VERBOSE, except many smbfs
                   problems is with the userspace daemon not reconnecting. */
-               PARANOIA("sucessful, new pid=%d, generation=%d\n",
+               PARANOIA("successful, new pid=%d, generation=%d\n",
                         server->conn_pid, server->generation);
                result = 1;
        }
index 3d7efa0..2669c73 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -25,7 +25,7 @@ do_revalidate(struct dentry *dentry)
 }
 
 
-#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(__s390__) && !defined(__hppa__)
+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__)
 
 /*
  * For backward compatibility?  Maybe this should be moved
@@ -38,7 +38,7 @@ static int cp_old_stat(struct inode * inode, struct __old_kernel_stat * statbuf)
 
        if (warncount > 0) {
                warncount--;
-               printk("VFS: Warning: %s using old stat() call. Recompile your binary.\n",
+               printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
                        current->comm);
        } else if (warncount < 0) {
                /* it's laughable, but... */
@@ -53,7 +53,7 @@ static int cp_old_stat(struct inode * inode, struct __old_kernel_stat * statbuf)
        SET_OLDSTAT_GID(tmp, inode->i_gid);
        tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
 #if BITS_PER_LONG == 32
-       if (inode->i_size > 0x7fffffff)
+       if (inode->i_size > MAX_NON_LFS)
                return -EOVERFLOW;
 #endif 
        tmp.st_size = inode->i_size;
@@ -79,7 +79,7 @@ static int cp_new_stat(struct inode * inode, struct stat * statbuf)
        SET_STAT_GID(tmp, inode->i_gid);
        tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
 #if BITS_PER_LONG == 32
-       if (inode->i_size > 0x7fffffff)
+       if (inode->i_size > MAX_NON_LFS)
                return -EOVERFLOW;
 #endif 
        tmp.st_size = inode->i_size;
index 97f4824..74fcbb6 100644 (file)
@@ -691,7 +691,7 @@ out:
  *     the request.
  */
  
-struct super_block *get_empty_super(void)
+static struct super_block *get_empty_super(void)
 {
        struct super_block *s;
 
@@ -738,6 +738,7 @@ static struct super_block * read_super(kdev_t dev, struct block_device *bdev,
        sema_init(&s->s_dquot.dqio_sem, 1);
        sema_init(&s->s_dquot.dqoff_sem, 1);
        s->s_dquot.flags = 0;
+       s->s_maxbytes = MAX_NON_LFS;
        lock_super(s);
        if (!type->read_super(s, data, silent))
                goto out_fail;
index a2c34d5..aad12cb 100644 (file)
@@ -162,6 +162,10 @@ void udf_fill_spartable(struct super_block *sb, struct udf_sparing_data *sdata,
                                        mapsize = (rtl * sizeof(Uint32)) +
                                                ((partlen/(1 << sdata->s_spar_pshift)) * sizeof(Uint8) * num);
                                        sdata->s_spar_map = kmalloc(mapsize, GFP_KERNEL);
+                                       if (!sdata->s_spar_map) {
+                                               printk("couldnt allocate UDF s_spar_map!\n");
+                                               return;
+                                       }
                                        sdata->s_spar_remap.s_spar_remap32 = &sdata->s_spar_map[rtl];
                                        memset(sdata->s_spar_map, 0xFF, mapsize);
                                }
index 3d2b515..7e929ec 100644 (file)
@@ -1,10 +1,6 @@
 #ifndef __ALPHA_IO_H
 #define __ALPHA_IO_H
 
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <asm/system.h>
-
 /* We don't use IO slowdowns on the Alpha, but.. */
 #define __SLOW_DOWN_IO do { } while (0)
 #define SLOW_DOWN_IO   do { } while (0)
@@ -19,6 +15,9 @@
 #endif
 
 #ifdef __KERNEL__
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <asm/system.h>
 #include <asm/machvec.h>
 
 /*
index 4c96cdd..2cad3d5 100644 (file)
 
 #define TIOCMIWAIT     0x545C  /* wait for a change on serial input line(s) */
 #define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
+#define TIOCGHAYESESP  0x545E  /* Get Hayes ESP configuration */
+#define TIOCSHAYESESP  0x545F  /* Set Hayes ESP configuration */
 
 #endif /* _ASM_ALPHA_IOCTLS_H */
index 7e377bd..3ab3874 100644 (file)
@@ -241,6 +241,9 @@ extern struct pgtable_cache_struct {
 #define pte_quicklist (quicklists.pte_cache)
 #define pgtable_cache_size (quicklists.pgtable_cache_sz)
 
+#define pmd_populate(mm, pmd, pte)     pmd_set(pmd, pte)
+#define pgd_populate(mm, pgd, pmd)     pgd_set(pgd, pmd)
+
 extern pgd_t *get_pgd_slow(void);
 
 static inline pgd_t *get_pgd_fast(void)
@@ -268,9 +271,15 @@ static inline void free_pgd_slow(pgd_t *pgd)
        free_page((unsigned long)pgd);
 }
 
-extern pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long address_premasked);
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+       pmd_t *ret = (pmd_t *)__get_free_page(GFP_KERNEL);
+       if (ret)
+               clear_page(ret);
+       return ret;
+}
 
-static inline pmd_t *get_pmd_fast(void)
+static inline pmd_t *pmd_alloc_one_fast(struct mm_struct *mm, unsigned long address)
 {
        unsigned long *ret;
 
@@ -282,21 +291,27 @@ static inline pmd_t *get_pmd_fast(void)
        return (pmd_t *)ret;
 }
 
-static inline void free_pmd_fast(pmd_t *pmd)
+static inline void pmd_free_fast(pmd_t *pmd)
 {
        *(unsigned long *)pmd = (unsigned long) pte_quicklist;
        pte_quicklist = (unsigned long *) pmd;
        pgtable_cache_size++;
 }
 
-static inline void free_pmd_slow(pmd_t *pmd)
+static inline void pmd_free_slow(pmd_t *pmd)
 {
        free_page((unsigned long)pmd);
 }
 
-extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
+static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+       pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL);
+       if (pte)
+               clear_page(pte);
+       return pte;
+}
 
-static inline pte_t *get_pte_fast(void)
+static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
 {
        unsigned long *ret;
 
@@ -308,67 +323,23 @@ static inline pte_t *get_pte_fast(void)
        return (pte_t *)ret;
 }
 
-static inline void free_pte_fast(pte_t *pte)
+static inline void pte_free_fast(pte_t *pte)
 {
        *(unsigned long *)pte = (unsigned long) pte_quicklist;
        pte_quicklist = (unsigned long *) pte;
        pgtable_cache_size++;
 }
 
-static inline void free_pte_slow(pte_t *pte)
+static inline void pte_free_slow(pte_t *pte)
 {
        free_page((unsigned long)pte);
 }
 
-extern void __bad_pte(pmd_t *pmd);
-extern void __bad_pmd(pgd_t *pgd);
-
-#define pte_free_kernel(pte)   free_pte_fast(pte)
-#define pte_free(pte)          free_pte_fast(pte)
-#define pmd_free_kernel(pmd)   free_pmd_fast(pmd)
-#define pmd_free(pmd)          free_pmd_fast(pmd)
+#define pte_free(pte)          pte_free_fast(pte)
+#define pmd_free(pmd)          pmd_free_fast(pmd)
 #define pgd_free(pgd)          free_pgd_fast(pgd)
 #define pgd_alloc()            get_pgd_fast()
 
-static inline pte_t * pte_alloc(pmd_t *pmd, unsigned long address)
-{
-       address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
-       if (pmd_none(*pmd)) {
-               pte_t *page = get_pte_fast();
-               
-               if (!page)
-                       return get_pte_slow(pmd, address);
-               pmd_set(pmd, page);
-               return page + address;
-       }
-       if (pmd_bad(*pmd)) {
-               __bad_pte(pmd);
-               return NULL;
-       }
-       return (pte_t *) pmd_page(*pmd) + address;
-}
-
-static inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address)
-{
-       address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1);
-       if (pgd_none(*pgd)) {
-               pmd_t *page = get_pmd_fast();
-               
-               if (!page)
-                       return get_pmd_slow(pgd, address);
-               pgd_set(pgd, page);
-               return page + address;
-       }
-       if (pgd_bad(*pgd)) {
-               __bad_pmd(pgd);
-               return NULL;
-       }
-       return (pmd_t *) pgd_page(*pgd) + address;
-}
-
-#define pte_alloc_kernel       pte_alloc
-#define pmd_alloc_kernel       pmd_alloc
-
 extern int do_check_pgt_cache(int, int);
 
 #endif /* _ALPHA_PGALLOC_H */
index b3f6e81..54341ff 100644 (file)
 #define _PAGE_FOW      0x0004  /* used for page protection (fault on write) */
 #define _PAGE_FOE      0x0008  /* used for page protection (fault on exec) */
 #define _PAGE_ASM      0x0010
-#if defined(CONFIG_ALPHA_EV6) && !defined(CONFIG_SMP)
-#define _PAGE_MBE      0x0080  /* MB disable bit for EV6.  */
-#else
-#define _PAGE_MBE      0x0000
-#endif
 #define _PAGE_KRE      0x0100  /* xxx - see below on the "accessed" bit */
 #define _PAGE_URE      0x0200  /* xxx */
 #define _PAGE_KWE      0x1000  /* used to do the dirty bit in software */
 #define _PFN_MASK      0xFFFFFFFF00000000
 
 #define _PAGE_TABLE    (_PAGE_VALID | __DIRTY_BITS | __ACCESS_BITS)
-#define _PAGE_CHG_MASK (_PFN_MASK | __DIRTY_BITS | __ACCESS_BITS | _PAGE_MBE)
+#define _PAGE_CHG_MASK (_PFN_MASK | __DIRTY_BITS | __ACCESS_BITS)
 
 /*
- * All the normal masks have the "page accessed" bits on, as any time they
- * are used, the page is accessed.  They are cleared only by the page-out
- * routines. 
+ * All the normal masks have the "page accessed" bits on, as any time they are used,
+ * the page is accessed. They are cleared only by the page-out routines
  */
 #define PAGE_NONE      __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOR | _PAGE_FOW | _PAGE_FOE)
 #define PAGE_SHARED    __pgprot(_PAGE_VALID | __ACCESS_BITS)
 #define PAGE_COPY      __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
 #define PAGE_READONLY  __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
-#define PAGE_KERNEL    __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE | _PAGE_MBE)
+#define PAGE_KERNEL    __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE)
 
-#define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_MBE | (x))
+#define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | (x))
 
 #define _PAGE_P(x) _PAGE_NORMAL((x) | (((x) & _PAGE_FOW)?0:_PAGE_FOW))
 #define _PAGE_S(x) _PAGE_NORMAL(x)
@@ -195,7 +189,6 @@ extern unsigned long __zero_page(void);
  * Conversion functions:  convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  */
-
 #define mk_pte(page, pgprot)                                           \
 ({                                                                     \
        pte_t pte;                                                      \
@@ -206,7 +199,7 @@ extern unsigned long __zero_page(void);
 })
 
 extern inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
-{ pte_t pte; pte_val(pte) = (PHYS_TWIDDLE(physpage) << (32-PAGE_SHIFT)) | (pgprot_val(pgprot) & ~_PAGE_MBE); return pte; }
+{ pte_t pte; pte_val(pte) = (PHYS_TWIDDLE(physpage) << (32-PAGE_SHIFT)) | pgprot_val(pgprot); return pte; }
 
 extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 { pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
index c2a511e..113851b 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/atomic.h>
 #include <asm/compiler.h>      /* __builtin_expect */
 #include <linux/wait.h>
+#include <linux/rwsem.h>
 
 #define DEBUG_SEMAPHORE 0
 #define DEBUG_RW_SEMAPHORE 0
@@ -223,151 +224,6 @@ extern inline void up(struct semaphore *sem)
 }
 #endif
 
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer
- * subtracts BIAS ands gets 0 for the case of an uncontended
- * lock.  Readers decrement by 1 and see a positive value
- * when uncontended, negative if there are writers waiting
- * (in which case it goes to sleep).
- *
- * The value 0x01000000 supports up to 128 processors and
- * lots of processes.  BIAS must be chosen such that subtracting
- * BIAS once per CPU will result in the int remaining
- * negative.
- * In terms of fairness, this should result in the lock
- * flopping back and forth between readers and writers
- * under heavy use.
- *
- *           -ben
- *
- * Once we start supporting machines with more than 128 CPUs,
- * we should go for using a 64bit atomic type instead of 32bit
- * as counter. We shall probably go for bias 0x80000000 then,
- * so that single sethi can set it.
- *
- *           -jj
- */
-
-#define RW_LOCK_BIAS           0x01000000
-
-struct rw_semaphore {
-       atomic_t                count;
-       /* bit 0 means read bias granted;
-          bit 1 means write bias granted.  */
-       unsigned                granted;
-       wait_queue_head_t       wait;
-       wait_queue_head_t       write_bias_wait;
-#if WAITQUEUE_DEBUG
-       long                    __magic;
-       atomic_t                readers;
-       atomic_t                writers;
-#endif
-};
-
-#if WAITQUEUE_DEBUG
-#define __RWSEM_DEBUG_INIT     , ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-#define __RWSEM_DEBUG_INIT     /* */
-#endif
-
-#define __RWSEM_INITIALIZER(name,count)                                        \
-       { ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-         __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait)         \
-         __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-       struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) \
-       __DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) \
-       __DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) \
-       __DECLARE_RWSEM_GENERIC(name, 0)
-
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-       atomic_set (&sem->count, RW_LOCK_BIAS);
-       sem->granted = 0;
-       init_waitqueue_head(&sem->wait);
-       init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-       sem->__magic = (long)&sem->__magic;
-       atomic_set(&sem->readers, 0);
-       atomic_set(&sem->writers, 0);
-#endif
-}
-
-extern void down_read(struct rw_semaphore *);
-extern void down_write(struct rw_semaphore *);
-extern void up_read(struct rw_semaphore *);
-extern void up_write(struct rw_semaphore *);
-extern void __down_read_failed(struct rw_semaphore *, int);
-extern void __down_write_failed(struct rw_semaphore *, int);
-extern void __rwsem_wake(struct rw_semaphore *, int);
-
-static inline void __down_read(struct rw_semaphore *sem)
-{
-       long count = atomic_dec_return(&sem->count);
-       if (__builtin_expect(count < 0, 0))
-               __down_read_failed(sem, count);
-}
-
-static inline void __down_write(struct rw_semaphore *sem)
-{
-       long count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
-       if (__builtin_expect(count != 0, 0))
-               __down_write_failed(sem, count);
-}
-
-/* When a reader does a release, the only significant case is when there
-   was a writer waiting, and we've bumped the count to 0, then we must
-   wake the writer up.  */
-
-static inline void __up_read(struct rw_semaphore *sem)
-{
-       long count;
-       mb();
-       count = atomic_inc_return(&sem->count);
-       if (__builtin_expect(count == 0, 0))
-               __rwsem_wake(sem, 0);
-}
-
-/* Releasing the writer is easy -- just release it and wake up
-   any sleepers.  */
-
-static inline void __up_write(struct rw_semaphore *sem)
-{
-       long count, wake;
-       mb();
-       count = atomic_add_return(RW_LOCK_BIAS, &sem->count);
-
-       /* Only do the wake if we were, but are no longer, negative.  */
-       wake = ((int)(count - RW_LOCK_BIAS) < 0) && count >= 0;
-       if (__builtin_expect(wake, 0))
-               __rwsem_wake(sem, count);
-}
-
-#if !WAITQUEUE_DEBUG && !DEBUG_RW_SEMAPHORE
-extern inline void down_read(struct rw_semaphore *sem)
-{
-       __down_read(sem);
-}
-extern inline void down_write(struct rw_semaphore *sem)
-{
-       __down_write(sem);
-}
-extern inline void up_read(struct rw_semaphore *sem)
-{
-       __up_read(sem);
-}
-extern inline void up_write(struct rw_semaphore *sem)
-{
-       __up_write(sem);
-}
 #endif
 
 #endif
index 0ce171a..adabfd7 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/linkage.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
+#include <linux/rwsem.h>
 
 #include <asm/atomic.h>
 #include <asm/proc/locks.h>
@@ -124,133 +125,4 @@ extern inline void up(struct semaphore * sem)
        __up_op(sem, __up_wakeup);
 }
 
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer
- * subtracts BIAS ands gets 0 for the case of an uncontended
- * lock.  Readers decrement by 1 and see a positive value
- * when uncontended, negative if there are writers waiting
- * (in which case it goes to sleep).
- *
- * In terms of fairness, this should result in the lock
- * flopping back and forth between readers and writers
- * under heavy use.
- *
- *              -ben
- */
-struct rw_semaphore {
-       atomic_t                count;
-       volatile unsigned char  write_bias_granted;
-       volatile unsigned char  read_bias_granted;
-       volatile unsigned char  pad1;
-       volatile unsigned char  pad2;
-       wait_queue_head_t       wait;
-       wait_queue_head_t       write_bias_wait;
-#if WAITQUEUE_DEBUG
-       long                    __magic;
-       atomic_t                readers;
-       atomic_t                writers;
-#endif
-};
-
-#if WAITQUEUE_DEBUG
-#define __RWSEM_DEBUG_INIT     , ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-#define __RWSEM_DEBUG_INIT     /* */
-#endif
-
-#define __RWSEM_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, 0, 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-       __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
-       __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-       struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
-
-extern inline void init_rwsem(struct rw_semaphore *sem)
-{
-       atomic_set(&sem->count, RW_LOCK_BIAS);
-       sem->read_bias_granted = 0;
-       sem->write_bias_granted = 0;
-       init_waitqueue_head(&sem->wait);
-       init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-       sem->__magic = (long)&sem->__magic;
-       atomic_set(&sem->readers, 0);
-       atomic_set(&sem->writers, 0);
-#endif
-}
-
-extern struct rw_semaphore *__down_read_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *__down_write_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *__rwsem_wake(struct rw_semaphore *sem);
-
-extern inline void down_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-       __down_op_read(sem, __down_read_failed);
-#if WAITQUEUE_DEBUG
-       if (sem->write_bias_granted)
-               BUG();
-       if (atomic_read(&sem->writers))
-               BUG();
-       atomic_inc(&sem->readers);
-#endif
-}
-
-extern inline void down_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-       __down_op_write(sem, __down_write_failed);
-#if WAITQUEUE_DEBUG
-       if (atomic_read(&sem->writers))
-               BUG();
-       if (atomic_read(&sem->readers))
-               BUG();
-       if (sem->read_bias_granted)
-               BUG();
-       if (sem->write_bias_granted)
-               BUG();
-       atomic_inc(&sem->writers);
-#endif
-}
-
-extern inline void up_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       if (sem->write_bias_granted)
-               BUG();
-       if (atomic_read(&sem->writers))
-               BUG();
-       atomic_dec(&sem->readers);
-#endif
-       __up_op_read(sem, __rwsem_wake);
-}
-
-extern inline void up_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       if (sem->read_bias_granted)
-               BUG();
-       if (sem->write_bias_granted)
-               BUG();
-       if (atomic_read(&sem->readers))
-               BUG();
-       if (atomic_read(&sem->writers) != 1)
-               BUG();
-       atomic_dec(&sem->writers);
-#endif
-       __up_op_write(sem, __rwsem_wake);
-}
-
 #endif
index cfa148a..963587e 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/wait.h>
 #include <linux/spinlock.h>
+#include <linux/rwsem.h>
 
 #include <asm/system.h>
 #include <asm/atomic.h>
@@ -157,165 +158,4 @@ extern inline void up(struct semaphore * sem)
        }
 }
 
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer
- * subtracts BIAS ands gets 0 for the case of an uncontended
- * lock.  Readers decrement by 1 and see a positive value
- * when uncontended, negative if there are writers waiting
- * (in which case it goes to sleep).
- *
- * In terms of fairness, this should result in the lock
- * flopping back and forth between readers and writers
- * under heavy use.
- *
- *              -ben
- */
-
-struct rw_semaphore {
-        atomic_t                count;
-       /* bit 0 means read bias granted;
-          bit 1 means write bias granted.  */
-        unsigned granted;
-        wait_queue_head_t       wait;
-        wait_queue_head_t       write_bias_wait;
-#if WAITQUEUE_DEBUG
-        long                    __magic;
-        atomic_t                readers;
-        atomic_t                writers;
-#endif
-};
-
-#if WAITQUEUE_DEBUG
-#define __RWSEM_DEBUG_INIT      , ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-#define __RWSEM_DEBUG_INIT      /* */
-#endif
-
-#define __RWSEM_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-        __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
-        __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-        struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
-
-extern inline void init_rwsem(struct rw_semaphore *sem)
-{
-        atomic_set(&sem->count, RW_LOCK_BIAS);
-        sem->granted = 0;
-        init_waitqueue_head(&sem->wait);
-        init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-        sem->__magic = (long)&sem->__magic;
-        atomic_set(&sem->readers, 0);
-        atomic_set(&sem->writers, 0);
-#endif
-}
-
-/* The expensive part is outlined.  */
-extern void __down_read(struct rw_semaphore *sem, int count);
-extern void __down_write(struct rw_semaphore *sem, int count);
-extern void __rwsem_wake(struct rw_semaphore *sem, unsigned long readers);
-
-extern inline void down_read(struct rw_semaphore *sem)
-{
-        int count;
-
-#if WAITQUEUE_DEBUG
-        CHECK_MAGIC(sem->__magic);
-#endif
-
-        count = atomic_dec_return(&sem->count);
-        if (count < 0) {
-                __down_read(sem, count);
-        }
-        mb();
-
-#if WAITQUEUE_DEBUG
-        if (sem->granted & 2)
-                BUG();
-        if (atomic_read(&sem->writers))
-                BUG();
-        atomic_inc(&sem->readers);
-#endif
-}
-
-extern inline void down_write(struct rw_semaphore *sem)
-{
-        int count;
-
-#if WAITQUEUE_DEBUG
-        CHECK_MAGIC(sem->__magic);
-#endif
-
-        count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
-        if (count) {
-                __down_write(sem, count);
-        }
-        mb();
-
-#if WAITQUEUE_DEBUG
-        if (atomic_read(&sem->writers))
-                BUG();
-        if (atomic_read(&sem->readers))
-                BUG();
-        if (sem->granted & 3)
-                BUG();
-        atomic_inc(&sem->writers);
-#endif
-}
-
-/* When a reader does a release, the only significant case is when
-   there was a writer waiting, and we've bumped the count to 0: we must
-   wake the writer up.  */
-
-extern inline void up_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-        CHECK_MAGIC(sem->__magic);
-        if (sem->granted & 2)
-                BUG();
-        if (atomic_read(&sem->writers))
-                BUG();
-        atomic_dec(&sem->readers);
-#endif
-
-        mb();
-        if (atomic_inc_return(&sem->count) == 0)
-                __rwsem_wake(sem, 0);
-}
-
-/*
- * Releasing the writer is easy -- just release it and wake up any sleepers.
- */
-extern inline void up_write(struct rw_semaphore *sem)
-{
-        int count;
-
-#if WAITQUEUE_DEBUG
-        CHECK_MAGIC(sem->__magic);
-        if (sem->granted & 3)
-                BUG();
-        if (atomic_read(&sem->readers))
-                BUG();
-        if (atomic_read(&sem->writers) != 1)
-                BUG();
-        atomic_dec(&sem->writers);
-#endif
-
-        mb();
-        count = atomic_add_return(RW_LOCK_BIAS, &sem->count);
-        if (count - RW_LOCK_BIAS < 0 && count >= 0) {
-                /* Only do the wake if we're no longer negative.  */
-                __rwsem_wake(sem, count);
-        }
-}
-
 #endif
index a3ed0b8..adf6163 100644 (file)
@@ -18,8 +18,6 @@
 
 #ifdef __KERNEL__
 
-#define CONFIG_USING_SPINLOCK_BASED_RWSEM 1
-
 /*
  * the semaphore definition
  */
index afdeda9..3263899 100644 (file)
@@ -1,4 +1,4 @@
-/* rwsem.h: R/W semaphores based on spinlocks
+/* rwsem.h: R/W semaphores optimised using i386 assembly
  *
  * Written by David Howells (dhowells@redhat.com).
  *
@@ -14,7 +14,6 @@
 
 #ifdef __KERNEL__
 
-#define __HAVE_ARCH_SPECIFIC_RWSEM_IMPLEMENTATION 1
 #ifdef CONFIG_X86_XADD
 #include <asm/rwsem-xadd.h> /* use XADD based semaphores if possible */
 #else
index bf95a54..a0b2c4b 100644 (file)
@@ -355,7 +355,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
                (granularity << IA32_SEG_G)                    |       \
                (((base >> 24) & 0xFF) << IA32_SEG_HIGH_BASE)) 
 
-#define IA32_IOBASE    0x2000000000000000 /* Virtual addres for I/O space */
+#define IA32_IOBASE    0x2000000000000000 /* Virtual address for I/O space */
 
 #define IA32_CR0       0x80000001      /* Enable PG and PE bits */
 #define IA32_CR4       0              /* No architectural extensions */
index d9c1e7c..e3e5a9d 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/wait.h>
+#include <linux/rwsem.h>
 
 #include <asm/atomic.h>
 
@@ -118,206 +119,4 @@ up (struct semaphore * sem)
                __up(sem);
 }
 
-/*
- * rw mutexes (should that be mutices? =) -- throw rw spinlocks and
- * semaphores together, and this is what we end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer subtracts BIAS
- * ands gets 0 for the case of an uncontended lock.  Readers decrement
- * by 1 and see a positive value when uncontended, negative if there
- * are writers waiting (in which case it goes to sleep).  BIAS must be
- * chosen such that subtracting BIAS once per CPU will result either
- * in zero (uncontended case) or in a negative value (contention
- * case).  On the other hand, BIAS must be at least as big as the
- * number of processes in the system.
- *
- * On IA-64, we use a BIAS value of 0x100000000, which supports up to
- * 2 billion (2^31) processors and 4 billion processes.
- *
- * In terms of fairness, when there is heavy use of the lock, we want
- * to see the lock being passed back and forth between readers and
- * writers (like in a producer/consumer style of communication).
- *
- *           -ben (with clarifications & IA-64 comments by davidm)
- */
-#define RW_LOCK_BIAS           0x100000000ul
-
-struct rw_semaphore {
-       volatile long           count;
-       volatile __u8           write_bias_granted;
-       volatile __u8           read_bias_granted;
-       __u16                   pad1;
-       __u32                   pad2;
-       wait_queue_head_t       wait;
-       wait_queue_head_t       write_bias_wait;
-#if WAITQUEUE_DEBUG
-       long                    __magic;
-       atomic_t                readers;
-       atomic_t                writers;
-#endif
-};
-
-#if WAITQUEUE_DEBUG
-# define __RWSEM_DEBUG_INIT    , ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-# define __RWSEM_DEBUG_INIT
-#endif
-
-#define __RWSEM_INITIALIZER(name,count)                                                \
-{                                                                              \
-       (count), 0, 0, 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),        \
-       __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait)                   \
-       __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT                               \
-}
-
-#define __DECLARE_RWSEM_GENERIC(name,count)                                    \
-       struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name)                    __DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name)                __DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS - 1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name)       __DECLARE_RWSEM_GENERIC(name, 0)
-
-extern void __down_read_failed (struct rw_semaphore *sem, long count);
-extern void __down_write_failed (struct rw_semaphore *sem, long count);
-extern void __rwsem_wake (struct rw_semaphore *sem, long count);
-
-static inline void
-init_rwsem (struct rw_semaphore *sem)
-{
-       sem->count = RW_LOCK_BIAS;
-       sem->read_bias_granted = 0;
-       sem->write_bias_granted = 0;
-       init_waitqueue_head(&sem->wait);
-       init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-       sem->__magic = (long)&sem->__magic;
-       atomic_set(&sem->readers, 0);
-       atomic_set(&sem->writers, 0);
-#endif
-}
-
-static inline void
-down_read (struct rw_semaphore *sem)
-{
-       long count;
-
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
-       count = ia64_fetch_and_add(-1, &sem->count);
-       if (count < 0)
-               __down_read_failed(sem, count);
-
-#if WAITQUEUE_DEBUG
-       if (sem->write_bias_granted)
-               BUG();
-       if (atomic_read(&sem->writers))
-               BUG();
-       atomic_inc(&sem->readers);
-#endif
-}
-
-static inline void
-down_write (struct rw_semaphore *sem)
-{
-       long old_count, new_count;
-
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
-       do {
-               old_count = sem->count;
-               new_count = old_count - RW_LOCK_BIAS;
-       } while (cmpxchg_acq(&sem->count, old_count, new_count) != old_count);
-
-       if (new_count != 0)
-               __down_write_failed(sem, new_count);
-#if WAITQUEUE_DEBUG
-       if (atomic_read(&sem->writers))
-               BUG();
-       if (atomic_read(&sem->readers))
-               BUG();
-       if (sem->read_bias_granted)
-               BUG();
-       if (sem->write_bias_granted)
-               BUG();
-       atomic_inc(&sem->writers);
-#endif
-}
-
-/*
- * When a reader does a release, the only significant
- * case is when there was a writer waiting, and we've
- * bumped the count to 0: we must wake the writer up.
- */
-static inline void
-__up_read (struct rw_semaphore *sem)
-{
-       long count;
-
-       count = ia64_fetch_and_add(1, &sem->count);
-       if (count == 0)
-               /*
-                * Other processes are blocked already; resolve
-                * contention by letting either a writer or a reader
-                * proceed...
-                */
-               __rwsem_wake(sem, count);
-}
-
-/*
- * Releasing the writer is easy -- just release it and
- * wake up any sleepers.
- */
-static inline void
-__up_write (struct rw_semaphore *sem)
-{
-       long old_count, new_count;
-
-       do {
-               old_count = sem->count;
-               new_count = old_count + RW_LOCK_BIAS;
-       } while (cmpxchg_rel(&sem->count, old_count, new_count) != old_count);
-
-       /*
-        * Note: new_count <u RW_LOCK_BIAS <=> old_count < 0 && new_count >= 0.
-        *       (where <u is "unsigned less-than").
-        */
-       if ((unsigned long) new_count < RW_LOCK_BIAS)
-               /* someone is blocked already, resolve contention... */
-               __rwsem_wake(sem, new_count);
-}
-
-static inline void
-up_read (struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       if (sem->write_bias_granted)
-               BUG();
-       if (atomic_read(&sem->writers))
-               BUG();
-       atomic_dec(&sem->readers);
-#endif
-       __up_read(sem);
-}
-
-static inline void
-up_write (struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       if (sem->read_bias_granted)
-               BUG();
-       if (sem->write_bias_granted)
-               BUG();
-       if (atomic_read(&sem->readers))
-               BUG();
-       if (atomic_read(&sem->writers) != 1)
-               BUG();
-       atomic_dec(&sem->writers);
-#endif
-       __up_write(sem);
-}
-
 #endif /* _ASM_IA64_SEMAPHORE_H */
index 0b76132..951c59c 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/linkage.h>
 #include <linux/wait.h>
 #include <linux/spinlock.h>
+#include <linux/rwsem.h>
 
 #include <asm/system.h>
 #include <asm/atomic.h>
@@ -185,201 +186,6 @@ extern inline void up(struct semaphore * sem)
                : "memory");
 }
 
-
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * m68k version by Roman Zippel
- */
-
-struct rw_semaphore {
-       atomic_t                count;
-       volatile unsigned char  write_bias_granted;
-       volatile unsigned char  read_bias_granted;
-       volatile unsigned char  pad1;
-       volatile unsigned char  pad2;
-       wait_queue_head_t       wait;
-       wait_queue_head_t       write_bias_wait;
-#if WAITQUEUE_DEBUG
-       long                    __magic;
-       atomic_t                readers;
-       atomic_t                writers;
-#endif
-};
-
-#if WAITQUEUE_DEBUG
-#define __RWSEM_DEBUG_INIT     , ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-#define __RWSEM_DEBUG_INIT     /* */
-#endif
-
-#define __RWSEM_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, 0, 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-       __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
-       __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-       struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
-
-extern inline void init_rwsem(struct rw_semaphore *sem)
-{
-       atomic_set(&sem->count, RW_LOCK_BIAS);
-       sem->read_bias_granted = 0;
-       sem->write_bias_granted = 0;
-       init_waitqueue_head(&sem->wait);
-       init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-       sem->__magic = (long)&sem->__magic;
-       atomic_set(&sem->readers, 0);
-       atomic_set(&sem->writers, 0);
-#endif
-}
-
-extern inline void down_read(struct rw_semaphore *sem)
-{
-       register struct rw_semaphore *__sem __asm__ ("%a1") = sem;
-
-#if WAITQUEUE_DEBUG
-       if (sem->__magic != (long)&sem->__magic)
-               BUG();
-#endif
-       __asm__ __volatile__(
-               "| atomic down_read operation\n\t"
-               "subql #1,%0@\n\t"
-               "jmi 2f\n"
-               "1:\n"
-               ".section .text.lock,\"ax\"\n"
-               ".even\n"
-               "2:\n\t"
-               "pea 1b\n\t"
-               "jbra __down_read_failed\n"
-               ".previous"
-               : /* no outputs */
-               : "a" (__sem)
-               : "memory");
-#if WAITQUEUE_DEBUG
-       if (sem->write_bias_granted)
-               BUG();
-       if (atomic_read(&sem->writers))
-               BUG();
-       atomic_inc(&sem->readers);
-#endif
-}
-
-extern inline void down_write(struct rw_semaphore *sem)
-{
-       register struct rw_semaphore *__sem __asm__ ("%a1") = sem;
-
-#if WAITQUEUE_DEBUG
-       if (sem->__magic != (long)&sem->__magic)
-               BUG();
-#endif
-       __asm__ __volatile__(
-               "| atomic down_write operation\n\t"
-               "subl %1,%0@\n\t"
-               "jne 2f\n"
-               "1:\n"
-               ".section .text.lock,\"ax\"\n"
-               ".even\n"
-               "2:\n\t"
-               "pea 1b\n\t"
-               "jbra __down_write_failed\n"
-               ".previous"
-               : /* no outputs */
-               : "a" (__sem), "id" (RW_LOCK_BIAS)
-               : "memory");
-#if WAITQUEUE_DEBUG
-       if (atomic_read(&sem->writers))
-               BUG();
-       if (atomic_read(&sem->readers))
-               BUG();
-       if (sem->read_bias_granted)
-               BUG();
-       if (sem->write_bias_granted)
-               BUG();
-       atomic_inc(&sem->writers);
-#endif
-}
-
-/* When a reader does a release, the only significant
- * case is when there was a writer waiting, and we've
- * bumped the count to 0: we must wake the writer up.
- */
-extern inline void __up_read(struct rw_semaphore *sem)
-{
-       register struct rw_semaphore *__sem __asm__ ("%a1") = sem;
-
-       __asm__ __volatile__(
-               "| atomic up_read operation\n\t"
-               "addql #1,%0@\n\t"
-               "jeq 2f\n"
-               "1:\n"
-               ".section .text.lock,\"ax\"\n"
-               ".even\n"
-               "2:\n\t"
-               "pea 1b\n\t"
-               "jbra __rwsem_wake\n"
-               ".previous"
-               : /* no outputs */
-               : "a" (__sem)
-               : "memory");
-}
-
-extern inline void up_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       if (sem->write_bias_granted)
-               BUG();
-       if (atomic_read(&sem->writers))
-               BUG();
-       atomic_dec(&sem->readers);
-#endif
-       __up_read(sem);
-}
-
-/* releasing the writer is easy -- just release it and
- * wake up any sleepers.
- */
-extern inline void __up_write(struct rw_semaphore *sem)
-{
-       register struct rw_semaphore *__sem __asm__ ("%a1") = sem;
-
-       __asm__ __volatile__(
-               "| atomic up_write operation\n\t"
-               "addl %1,%0@\n\t"
-               "jcs 2f\n"
-               "1:\n"
-               ".section .text.lock,\"ax\"\n"
-               ".even\n"
-               "2:\n\t"
-               "pea 1b\n\t"
-               "jbra __rwsem_wake\n"
-               ".previous"
-               : /* no outputs */
-               : "a" (__sem), "id" (RW_LOCK_BIAS)
-               : "memory");
-}
-
-extern inline void up_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       if (sem->read_bias_granted)
-               BUG();
-       if (sem->write_bias_granted)
-               BUG();
-       if (atomic_read(&sem->readers))
-               BUG();
-       if (atomic_read(&sem->writers) != 1)
-               BUG();
-       atomic_dec(&sem->writers);
-#endif
-       __up_write(sem);
-}
 #endif /* __ASSEMBLY__ */
 
 #endif
index 666f727..f1c30ec 100644 (file)
@@ -1,16 +1,13 @@
-/* $Id: bootinfo.h,v 1.11 2000/03/06 11:14:32 raiko Exp $
- *
- * bootinfo.h -- Definition of the Linux/MIPS boot information structure
- *
- * Copyright (C) 1995, 1996 by Ralf Baechle, Andreas Busse,
- *                             Stoned Elipot and Paul M. Antoine.
- *
+/*
  * 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) 1995, 1996 by Ralf Baechle, Andreas Busse,
+ *                             Stoned Elipot and Paul M. Antoine.
  */
-#ifndef __ASM_MIPS_BOOTINFO_H
-#define __ASM_MIPS_BOOTINFO_H
+#ifndef _ASM_BOOTINFO_H
+#define _ASM_BOOTINFO_H
 
 /*
  * Values for machgroup
  * Valid machtype for group NEC DDB
  */
 #define MACH_NEC_DDB5074        0      /* NEC DDB Vrc-5074 */
+#define MACH_NEC_DDB5476         1      /* NEC DDB Vrc-5476 */
 
-#define GROUP_NEC_DDB_NAMES { "Vrc-5074" }
+#define GROUP_NEC_DDB_NAMES { "Vrc-5074", "Vrc-5476"}
 
 /*
  * Valid machtype for group BAGET
diff --git a/include/asm-mips/it8172/it8172.h b/include/asm-mips/it8172/it8172.h
new file mode 100644 (file)
index 0000000..980d1d5
--- /dev/null
@@ -0,0 +1,406 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *     IT8172 system controller defines.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __IT8172__H__
+#define __IT8172__H__
+
+#include <asm/addrspace.h>
+
+#define IT8172_BASE                    0x18000000      
+#define IT8172_PCI_IO_BASE             0x14000000
+#define IT8172_PCI_MEM_BASE            0x10000000
+
+// System registers offsets from IT8172_BASE
+#define IT_CMFPCR                      0x0
+#define IT_DSRR                                0x2
+#define IT_PCDCR                       0x4
+#define IT_SPLLCR                      0x6
+#define IT_CIDR                                0x10
+#define IT_CRNR                                0x12
+#define IT_CPUTR                       0x14
+#define IT_CTCR                                0x16
+#define IT_SDPR                                0xF0
+
+// Power management register offset from IT8172_PCI_IO_BASE
+// Power Management Device Standby Register
+#define IT_PM_DSR              0x15800
+
+#define IT_PM_DSR_TMR0SB       0x0001
+#define IT_PM_DSR_TMR1SB       0x0002
+#define IT_PM_DSR_CIR0SB       0x0004
+#define IT_PM_DSR_CIR1SB       0x0008
+#define IT_PM_DSR_SCR0SB       0x0010
+#define IT_PM_DSR_SCR1SB       0x0020
+#define IT_PM_DSR_PPSB         0x0040
+#define IT_PM_DSR_I2CSB                0x0080
+#define IT_PM_DSR_UARTSB       0x0100
+#define IT_PM_DSR_IDESB                0x0200
+#define IT_PM_DSR_ACSB         0x0400
+#define IT_PM_DSR_M68KSB       0x0800
+
+// Power Management PCI Device Software Reset Register
+#define IT_PM_PCISR             0x15802
+
+#define IT_PM_PCISR_IDESR       0x0001
+#define IT_PM_PCISR_CDMASR      0x0002
+#define IT_PM_PCISR_USBSR       0x0004
+#define IT_PM_PCISR_DMASR       0x0008
+#define IT_PM_PCISR_ACSR        0x0010
+#define IT_PM_PCISR_MEMSR       0x0020
+#define IT_PM_PCISR_68KSR       0x0040
+
+
+// PCI Configuration address and data register offsets
+// from IT8172_BASE
+#define IT_CONFADDR                    0x4000
+#define IT_BUSNUM_SHF                   16
+#define IT_DEVNUM_SHF                   11
+#define IT_FUNCNUM_SHF                  8
+#define IT_REGNUM_SHF                   2
+
+#define IT_CONFDATA                    0x4004
+
+// PCI configuration header common register offsets
+#define IT_VID                         0x00
+#define IT_DID                         0x02
+#define IT_PCICMD                      0x04
+#define IT_PCISTS                      0x06
+#define IT_RID                         0x08
+#define IT_CLASSC                      0x09
+#define IT_HEADT                       0x0E
+#define IT_SERIRQC                     0x49
+
+// PCI to Internal/LPC Bus Bridge configuration header register offset
+#define IT_P2I_BCR                             0x4C
+#define IT_P2I_D0IOSC                          0x50 
+#define IT_P2I_D1IOSC                          0x54
+#define IT_P2I_D2IOSC                          0x58 
+#define IT_P2I_D3IOSC                          0x5C 
+#define IT_P2I_D4IOSC                          0x60 
+#define IT_P2I_D5IOSC                          0x64 
+#define IT_P2I_D6IOSC                          0x68 
+#define IT_P2I_D7IOSC                          0x6C 
+#define IT_P2I_D8IOSC                          0x70 
+#define IT_P2I_D9IOSC                          0x74 
+#define IT_P2I_D10IOSC                         0x78 
+#define IT_P2I_D11IOSC                         0x7C 
+
+// Memory controller register offsets from IT8172_BASE
+#define IT_MC_SDRMR                                    0x1000
+#define IT_MC_SDRTR                                    0x1004
+#define IT_MC_MCR                                      0x1008
+#define IT_MC_SDTYPE                                   0x100C
+#define IT_MC_WPBA                                     0x1010
+#define IT_MC_WPTA                                     0x1014
+#define IT_MC_HATR                                     0x1018
+#define IT_MC_PCICR                                    0x101C
+
+// Flash/ROM control register offsets from IT8172_BASE
+#define IT_FC_BRCR                                     0x2000
+#define IT_FC_FCR                                      0x2004
+#define IT_FC_DCR                                      0x2008
+
+// M68K interface bridge configuration header register offset
+#define IT_M68K_MBCSR                                  0x54
+#define IT_M68K_TMR                                    0x58
+#define IT_M68K_BCR                                    0x5C
+#define IT_M68K_BSR                                    0x5D
+#define IT_M68K_DTR                                    0x5F
+
+// Register offset from IT8172_PCI_IO_BASE 
+// These registers are accessible through 8172 PCI IO window.
+
+// INTC 
+#define IT_INTC_BASE                           0x10000
+#define IT_INTC_LBDNIRR                                0x10000
+#define IT_INTC_LBDNIMR                                0x10002
+#define IT_INTC_LBDNITR                                0x10004
+#define IT_INTC_LBDNIAR                                0x10006
+#define IT_INTC_LPCNIRR                                0x10010
+#define IT_INTC_LPCNIMR                                0x10012
+#define IT_INTC_LPCNITR                                0x10014
+#define IT_INTC_LPCNIAR                                0x10016
+#define IT_INTC_PDNIRR                         0x10020
+#define IT_INTC_PDNIMR                         0x10022
+#define IT_INTC_PDNITR                         0x10024
+#define IT_INTC_PDNIAR                         0x10026
+#define IT_INTC_UMNIRR                         0x10030
+#define IT_INTC_UMNITR                         0x10034
+#define IT_INTC_UMNIAR                         0x10036
+#define IT_INTC_TYPER                          0x107FE
+
+// IT8172 PCI device number
+#define IT_C2P_DEVICE                          0
+#define IT_AUDIO_DEVICE                                1
+#define IT_DMAC_DEVICE                         1
+#define IT_CDMAC_DEVICE                                1
+#define IT_USB_DEVICE                          1
+#define IT_P2I_DEVICE                          1
+#define IT_IDE_DEVICE                          1
+#define IT_M68K_DEVICE                         1
+
+// IT8172 PCI function number
+#define IT_C2P_FUNCION                         0
+#define IT_AUDIO_FUNCTION                      0
+#define IT_DMAC_FUNCTION                       1
+#define IT_CDMAC_FUNCTION                      2
+#define IT_USB_FUNCTION                                3
+#define IT_P2I_FUNCTION                                4
+#define IT_IDE_FUNCTION                                5
+#define IT_M68K_FUNCTION                       6
+
+// IT8172 GPIO
+#define IT_GPADR                               0x13800
+#define IT_GPBDR                               0x13808
+#define IT_GPCDR                               0x13810
+#define IT_GPACR                               0x13802
+#define IT_GPBCR                               0x1380A
+#define IT_GPCCR                               0x13812
+#define IT_GPAICR                              0x13804
+#define IT_GPBICR                              0x1380C
+#define IT_GPCICR                              0x13814
+#define IT_GPAISR                              0x13806
+#define IT_GPBISR                              0x1380E
+#define IT_GPCISR                              0x13816
+#define IT_GCR                                 0x13818
+
+// IT8172 RTC
+#define IT_RTC_BASE                            0x14800
+#define IT_RTC_RIR0                            0x00
+#define IT_RTC_RTR0                            0x01
+#define IT_RTC_RIR1                            0x02
+#define IT_RTC_RTR1                            0x03
+#define IT_RTC_RIR2                            0x04
+#define IT_RTC_RTR2                            0x05
+#define IT_RTC_RCTR                            0x08
+#define IT_RTC_RA                              0x0A
+#define IT_RTC_RB                              0x0B
+#define IT_RTC_RC                              0x0C
+#define IT_RTC_RD                              0x0D
+
+#define RTC_SEC_INDEX                          0x00
+#define RTC_MIN_INDEX                          0x02
+#define RTC_HOUR_INDEX                         0x04
+#define RTC_DAY_INDEX                          0x06
+#define RTC_DATE_INDEX                         0x07
+#define RTC_MONTH_INDEX                                0x08
+#define RTC_YEAR_INDEX                         0x09
+
+// IT8172 internal device registers
+#define IT_TIMER_BASE                          0x10800
+#define IT_CIR0_BASE                           0x11000
+#define IT_UART_BASE                           0x11800
+#define IT_SCR0_BASE                           0x12000
+#define IT_SCR1_BASE                           0x12800
+#define IT_PP_BASE                             0x13000
+#define IT_I2C_BASE                            0x14000
+#define IT_CIR1_BASE                           0x15000
+
+// IT8172 Smart Card Reader offsets from IT_SCR*_BASE
+#define IT_SCR_SFR                             0x08
+#define IT_SCR_SCDR                            0x09
+
+// IT8172 IT_SCR_SFR bit definition & mask
+#define        IT_SCR_SFR_GATE_UART                    0x40
+#define        IT_SCR_SFR_GATE_UART_BIT                6
+#define IT_SCR_SFR_GATE_UART_OFF               0
+#define        IT_SCR_SFR_GATE_UART_ON                 1
+#define        IT_SCR_SFR_FET_CHARGE                   0x30
+#define        IT_SCR_SFR_FET_CHARGE_BIT               4
+#define IT_SCR_SFR_FET_CHARGE_3_3_US           3
+#define IT_SCR_SFR_FET_CHARGE_13_US            2
+#define IT_SCR_SFR_FET_CHARGE_53_US            1
+#define IT_SCR_SFR_FET_CHARGE_213_US           0
+#define        IT_SCR_SFR_CARD_FREQ                    0x0C
+#define        IT_SCR_SFR_CARD_FREQ_BIT                2
+#define IT_SCR_SFR_CARD_FREQ_STOP              3
+#define IT_SCR_SFR_CARD_FREQ_3_5_MHZ           0
+#define IT_SCR_SFR_CARD_FREQ_7_1_MHZ           2
+#define IT_SCR_SFR_CARD_FREQ_96_DIV_MHZ                1
+#define        IT_SCR_SFR_FET_ACTIVE                   0x02
+#define        IT_SCR_SFR_FET_ACTIVE_BIT               1
+#define IT_SCR_SFR_FET_ACTIVE_INVERT           0
+#define IT_SCR_SFR_FET_ACTIVE_NONINVERT                1
+#define        IT_SCR_SFR_ENABLE                       0x01
+#define        IT_SCR_SFR_ENABLE_BIT                   0
+#define IT_SCR_SFR_ENABLE_OFF                  0
+#define IT_SCR_SFR_ENABLE_ON                   1
+
+// IT8172 IT_SCR_SCDR bit definition & mask
+#define        IT_SCR_SCDR_RESET_MODE                  0x80
+#define        IT_SCR_SCDR_RESET_MODE_BIT              7
+#define        IT_SCR_SCDR_RESET_MODE_ASYNC            0
+#define IT_SCR_SCDR_RESET_MODE_SYNC            1
+#define        IT_SCR_SCDR_DIVISOR                     0x7F
+#define        IT_SCR_SCDR_DIVISOR_BIT                 0
+#define        IT_SCR_SCDR_DIVISOR_STOP_VAL_1          0x00
+#define        IT_SCR_SCDR_DIVISOR_STOP_VAL_2          0x01
+#define        IT_SCR_SCDR_DIVISOR_STOP_VAL_3          0x7F
+
+// IT8172 DMA
+#define IT_DMAC_BASE                           0x16000
+#define IT_DMAC_BCAR0                          0x00
+#define IT_DMAC_BCAR1                          0x04
+#define IT_DMAC_BCAR2                          0x08
+#define IT_DMAC_BCAR3                          0x0C
+#define IT_DMAC_BCCR0                          0x02
+#define IT_DMAC_BCCR1                          0x06
+#define IT_DMAC_BCCR2                          0x0a
+#define IT_DMAC_BCCR3                          0x0e
+#define IT_DMAC_CR                             0x10
+#define IT_DMAC_SR                             0x12
+#define IT_DMAC_ESR                            0x13
+#define IT_DMAC_RQR                            0x14
+#define IT_DMAC_MR                             0x16
+#define IT_DMAC_EMR                            0x17
+#define IT_DMAC_MKR                            0x18
+#define IT_DMAC_PAR0                           0x20
+#define IT_DMAC_PAR1                           0x22
+#define IT_DMAC_PAR2                           0x24
+#define IT_DMAC_PAR3                           0x26
+
+// IT8172 IDE
+#define IT_IDE_BASE                            0x17800
+#define IT_IDE_STATUS                          0x1F7
+
+// IT8172 Audio Controller
+#define IT_AC_BASE                             0x17000
+#define        IT_AC_PCMOV                             0x00
+#define IT_AC_FMOV                             0x02
+#define        IT_AC_I2SV                              0x04
+#define IT_AC_DRSS                             0x06
+#define IT_AC_PCC                              0x08
+#define IT_AC_PCDL                             0x0A
+#define IT_AC_PCB1STA                          0x0C
+#define IT_AC_PCB2STA                          0x10
+#define IT_AC_CAPCC                            0x14
+#define IT_AC_CAPCDL                           0x16
+#define IT_AC_CAPB1STA                         0x18
+#define IT_AC_CAPB2STA                         0x1C
+#define IT_AC_CODECC                           0x22
+#define IT_AC_I2SMC                            0x24
+#define IT_AC_VS                               0x26
+#define IT_AC_SRCS                             0x28
+#define IT_AC_CIRCP                            0x2A
+#define IT_AC_CIRDP                            0x2C
+#define IT_AC_TM                               0x4A
+#define IT_AC_PFDP                             0x4C
+#define IT_AC_GC                               0x54
+#define IT_AC_IMC                              0x56
+#define IT_AC_ISC                              0x5B
+#define IT_AC_OPL3SR                           0x68
+#define IT_AC_OPL3DWDR                         0x69
+#define IT_AC_OPL3AB1W                         0x6A
+#define IT_AC_OPL3DW                           0x6B
+#define IT_AC_BPDC                             0x70
+
+// Audio : IT_AC_PCC bit definition & mask
+#define        PCC_SM                                  0x8000
+#define        PCC_SM_BIT                              15
+#define        PCC_SM_STEREO                           1
+#define PCC_SM_MONO                            0
+
+#define        PCC_DF                                  0x4000
+#define PCC_DF_BIT                             14
+#define        PCC_DF_8                                0
+#define PCC_DF_16                              1
+
+#define        PCC_CF                                  0x3000
+#define PCC_CF_BIT                             12
+#define        PCC_CF_2                                0
+#define PCC_CF_4                               1
+#define PCC_CF_6                               2
+
+#define PCC_SR                                 0x0F00
+#define PCC_SR_BIT                             8
+#define        PCC_SR_5500                             0
+#define        PCC_SR_8000                             1
+#define        PCC_SR_9600                             2
+#define        PCC_SR_11025                            3
+#define        PCC_SR_16000                            4
+#define        PCC_SR_19200                            5
+#define        PCC_SR_22050                            6
+#define        PCC_SR_32000                            7
+#define        PCC_SR_38400                            8
+#define        PCC_SR_44100                            9
+#define        PCC_SR_48000                            10
+
+#define PCC_CSP                                        0x0080
+#define PCC_CSP_BIT                            7
+#define PCC_CSP_STOP                           0
+#define PCC_CSP_STOP_NOW                       1
+
+#define PCC_CP                                 0x0040
+#define        PCC_CP_BIT                              6
+#define PCC_CP_NORMAL                          0
+#define PCC_CP_PAUSE                           1
+
+#define PCC_CA                                 0x0020
+#define PCC_CA_BIT                             5
+#define PCC_CA_NO_START                                0
+#define PCC_CA_START                           1
+
+#define PCC_CB2L                               0x0004
+#define PCC_CB2L_BIT                           2
+#define PCC_CB2L_NO                            0
+#define PCC_CB2L_YES                           1
+
+#define PCC_CB1L                               0x0002
+#define PCC_CB1L_BIT                           1
+#define PCC_CB1L_NO                            0
+#define PCC_CB1L_YES                           1
+
+#define PCC_DE                                 0x0001
+#define PCC_DE_BIT                             0
+#define PCC_DE_NOT_EMPTY                       0
+#define PCC_DE_EMPTY                           1
+
+// IT8172 Timer
+#define IT_TIMER_BASE                          0x10800
+#define        TIMER_TCVR0                             0x00
+#define TIMER_TRVR0                            0x02
+#define        TIMER_TCR0                              0x04
+#define TIMER_TIRR                             0x06
+#define        TIMER_TCVR1                             0x08
+#define TIMER_TRVR1                            0x0A
+#define        TIMER_TCR1                              0x0C
+#define TIMER_TIDR                             0x0E
+
+
+#define IT_WRITE(ofs, data) *(volatile u32 *)KSEG1ADDR((IT8172_BASE+ofs)) = data
+#define IT_READ(ofs, data)  data = *(volatile u32 *)KSEG1ADDR((IT8172_BASE+ofs))
+
+#define IT_IO_WRITE(ofs, data) *(volatile u32 *)KSEG1ADDR((IT8172_PCI_IO_BASE+ofs)) = data
+#define IT_IO_READ(ofs, data)  data = *(volatile u32 *)KSEG1ADDR((IT8172_PCI_IO_BASE+ofs))
+
+#define IT_IO_WRITE16(ofs, data) *(volatile u16 *)KSEG1ADDR((IT8172_PCI_IO_BASE+ofs)) = data
+#define IT_IO_READ16(ofs, data)  data = *(volatile u16 *)KSEG1ADDR((IT8172_PCI_IO_BASE+ofs))
+
+#endif
diff --git a/include/asm-mips/it8172/it8172_cir.h b/include/asm-mips/it8172/it8172_cir.h
new file mode 100644 (file)
index 0000000..3422d52
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *     IT8172 Consumer IR port defines.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define NUM_CIR_PORTS 2
+
+/* Master Control Register */
+#define CIR_RESET              0x1
+#define CIR_FIFO_CLEAR         0x2
+#define CIR_SET_FIFO_TL(x)     (((x)&0x3)<<2)
+#define CIR_ILE                0x10
+#define CIR_ILSEL              0x20
+
+/* Interrupt Enable Register */
+#define CIR_TLDLIE             0x1
+#define CIR_RDAIE              0x2
+#define CIR_RFOIE              0x4
+#define CIR_IEC                0x80
+
+/* Interrupt Identification Register */
+#define CIR_TLDLI              0x1
+#define CIR_RDAI               0x2
+#define CIR_RFOI               0x4
+#define CIR_NIP                0x80
+
+/* Carrier Frequency Register */
+#define CIR_SET_CF(x)          ((x)&0x1f)
+  #define CFQ_38_480           0xB       /* 38 KHz low, 480 KHz high */
+#define CIR_HCFS               0x20
+  #define CIR_SET_HS(x)        (((x)&0x1)<<5)
+    
+
+/* Receiver Control Register */
+#define CIR_SET_RXDCR(x)       ((x)&0x7)
+#define CIR_RXACT              0x8
+#define CIR_RXEND              0x10
+#define CIR_RDWOS              0x20
+  #define CIR_SET_RDWOS(x)     (((x)&0x1)<<5)
+#define CIR_RXEN               0x80
+
+/* Transmitter Control Register */
+#define CIR_SET_TXMPW(x)       ((x)&0x7)
+#define CIR_SET_TXMPM(x)       (((x)&0x3)<<3)
+#define CIR_TXENDF             0x20
+#define CIR_TXRLE              0x40
+
+/* Receiver FIFO Status Register */
+#define CIR_RXFBC_MASK         0x3f
+#define CIR_RXFTO              0x80
+
+/* Wakeup Code Length Register */
+#define CIR_SET_WCL            ((x)&0x3f)
+#define CIR_WCL_MASK(x)        ((x)&0x3f)
+
+/* Wakeup Power Control/Status Register */
+#define CIR_BTMON              0x2
+#define CIR_CIRON              0x4
+#define CIR_RCRST              0x10
+#define CIR_WCRST              0x20
+
+struct cir_port {
+       int port;
+       unsigned short baud_rate;
+       unsigned char fifo_tl;
+       unsigned char cfq;
+       unsigned char hcfs;
+       unsigned char rdwos;
+       unsigned char rxdcr;
+};
+
+struct it8172_cir_regs {
+       unsigned char dr;       /* data                        */
+       char pad;
+       unsigned char mstcr;    /* master control              */
+       char pad1;
+       unsigned char ier;      /* interrupt enable            */
+       char pad2;
+       unsigned char iir;      /* interrupt identification    */
+       char pad3;
+       unsigned char cfr;      /* carrier frequency           */
+       char pad4;
+       unsigned char rcr;      /* receiver control            */
+       char pad5;
+       unsigned char tcr;      /* transmitter control         */
+       char pad6;
+       char pad7;
+       char pad8;
+       unsigned char bdlr;     /* baud rate divisor low byte  */
+       char pad9;
+       unsigned char bdhr;     /* baud rate divisor high byte */
+       char pad10;
+       unsigned char tfsr;     /* tx fifo byte count          */
+       char pad11;
+       unsigned char rfsr;     /* rx fifo status              */
+       char pad12;
+       unsigned char wcl;      /* wakeup code length          */
+       char pad13;
+       unsigned char wcr;      /* wakeup code read/write      */
+       char pad14;
+       unsigned char wps;      /* wakeup power control/status */
+};
+
+int cir_port_init(struct cir_port *cir);
+extern void clear_fifo(struct cir_port *cir);
+extern void enable_receiver(struct cir_port *cir);
+extern void disable_receiver(struct cir_port *cir);
+extern void enable_rx_demodulation(struct cir_port *cir);
+extern void disable_rx_demodulation(struct cir_port *cir);
+extern void set_rx_active(struct cir_port *cir);
+extern void int_enable(struct cir_port *cir);
+extern void rx_int_enable(struct cir_port *cir);
+extern char get_int_status(struct cir_port *cir);
+extern int cir_get_rx_count(struct cir_port *cir);
+extern char cir_read_data(struct cir_port *cir);
diff --git a/include/asm-mips/it8172/it8172_dbg.h b/include/asm-mips/it8172/it8172_dbg.h
new file mode 100644 (file)
index 0000000..9af7ade
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *     Function prototypes for low level uart routines to 
+ *     directly access a 16550 uart.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+
+extern void putch(const unsigned char c);
+extern void puts(unsigned char *cp);
+extern void fputs(unsigned char *cp);
+extern void put64(uint64_t ul);
+extern void put32(unsigned u);
diff --git a/include/asm-mips/it8172/it8172_int.h b/include/asm-mips/it8172/it8172_int.h
new file mode 100644 (file)
index 0000000..f785c38
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *     ITE 8172 Interrupt Numbering
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _MIPS_ITEINT_H
+#define _MIPS_ITEINT_H
+
+/*
+ * Here's the "strategy":
+ * We number the LPC serial irqs from 0 to 15,
+ * the local bus irqs from 16 to 31,
+ * the pci dev register interrupts from 32 to 47,
+ * and the non-maskable ints from 48 to 53.
+ */
+
+#define IT8172_LPC_IRQ_BASE  0    /* first LPC int number */
+#define IT8172_SERIRQ_0      (IT8172_LPC_IRQ_BASE + 0)
+#define IT8172_SERIRQ_1      (IT8172_LPC_IRQ_BASE + 1)
+#define IT8172_SERIRQ_2      (IT8172_LPC_IRQ_BASE + 2)
+#define IT8172_SERIRQ_3      (IT8172_LPC_IRQ_BASE + 3)
+#define IT8172_SERIRQ_4      (IT8172_LPC_IRQ_BASE + 4)
+#define IT8172_SERIRQ_5      (IT8172_LPC_IRQ_BASE + 5)
+#define IT8172_SERIRQ_6      (IT8172_LPC_IRQ_BASE + 6)
+#define IT8172_SERIRQ_7      (IT8172_LPC_IRQ_BASE + 7)
+#define IT8172_SERIRQ_8      (IT8172_LPC_IRQ_BASE + 8)
+#define IT8172_SERIRQ_9      (IT8172_LPC_IRQ_BASE + 9)
+#define IT8172_SERIRQ_10     (IT8172_LPC_IRQ_BASE + 10)
+#define IT8172_SERIRQ_11     (IT8172_LPC_IRQ_BASE + 11)
+#define IT8172_SERIRQ_12     (IT8172_LPC_IRQ_BASE + 12)
+#define IT8172_SERIRQ_13     (IT8172_LPC_IRQ_BASE + 13)
+#define IT8172_SERIRQ_14     (IT8172_LPC_IRQ_BASE + 14)
+#define IT8172_SERIRQ_15     (IT8172_LPC_IRQ_BASE + 15)
+
+#define IT8172_LB_IRQ_BASE  16   /* first local bus int number */
+#define IT8172_PPR_IRQ          (IT8172_LB_IRQ_BASE + 0) /* parallel port */
+#define IT8172_TIMER0_IRQ       (IT8172_LB_IRQ_BASE + 1)
+#define IT8172_TIMER1_IRQ       (IT8172_LB_IRQ_BASE + 2)
+#define IT8172_I2C_IRQ          (IT8172_LB_IRQ_BASE + 3)
+#define IT8172_GPIO_IRQ         (IT8172_LB_IRQ_BASE + 4)
+#define IT8172_CIR0_IRQ         (IT8172_LB_IRQ_BASE + 5)
+#define IT8172_CIR1_IRQ         (IT8172_LB_IRQ_BASE + 6)
+#define IT8172_UART_IRQ         (IT8172_LB_IRQ_BASE + 7)
+#define IT8172_SCR0_IRQ         (IT8172_LB_IRQ_BASE + 8)
+#define IT8172_SCR1_IRQ         (IT8172_LB_IRQ_BASE + 9)
+#define IT8172_RTC_IRQ          (IT8172_LB_IRQ_BASE + 10)
+#define IT8172_IOCHK_IRQ        (IT8172_LB_IRQ_BASE + 11)
+/* 12 - 15 reserved */
+
+/*
+ * Note here that the pci dev registers includes bits for more than
+ * just the pci devices.
+ */
+#define IT8172_PCI_DEV_IRQ_BASE  32   /* first pci dev irq */
+#define IT8172_AC97_IRQ          (IT8172_PCI_DEV_IRQ_BASE + 0)
+#define IT8172_MC68K_IRQ         (IT8172_PCI_DEV_IRQ_BASE + 1)
+#define IT8172_IDE_IRQ           (IT8172_PCI_DEV_IRQ_BASE + 2)
+#define IT8172_USB_IRQ           (IT8172_PCI_DEV_IRQ_BASE + 3)
+#define IT8172_BRIDGE_MASTER_IRQ (IT8172_PCI_DEV_IRQ_BASE + 4)
+#define IT8172_BRIDGE_TARGET_IRQ (IT8172_PCI_DEV_IRQ_BASE + 5)
+#define IT8172_PCI_INTA_IRQ      (IT8172_PCI_DEV_IRQ_BASE + 6)
+#define IT8172_PCI_INTB_IRQ      (IT8172_PCI_DEV_IRQ_BASE + 7)
+#define IT8172_PCI_INTC_IRQ      (IT8172_PCI_DEV_IRQ_BASE + 8)
+#define IT8172_PCI_INTD_IRQ      (IT8172_PCI_DEV_IRQ_BASE + 9)
+#define IT8172_S_INTA_IRQ        (IT8172_PCI_DEV_IRQ_BASE + 10)
+#define IT8172_S_INTB_IRQ        (IT8172_PCI_DEV_IRQ_BASE + 11)
+#define IT8172_S_INTC_IRQ        (IT8172_PCI_DEV_IRQ_BASE + 12)
+#define IT8172_S_INTD_IRQ        (IT8172_PCI_DEV_IRQ_BASE + 13)
+#define IT8172_CDMA_IRQ          (IT8172_PCI_DEV_IRQ_BASE + 14)
+#define IT8172_DMA_IRQ           (IT8172_PCI_DEV_IRQ_BASE + 15)
+
+#define IT8172_NMI_IRQ_BASE      48
+#define IT8172_SER_NMI_IRQ       (IT8172_NMI_IRQ_BASE + 0)
+#define IT8172_PCI_NMI_IRQ       (IT8172_NMI_IRQ_BASE + 1)
+#define IT8172_RTC_NMI_IRQ       (IT8172_NMI_IRQ_BASE + 2)
+#define IT8172_CPUIF_NMI_IRQ     (IT8172_NMI_IRQ_BASE + 3)
+#define IT8172_PMER_NMI_IRQ      (IT8172_NMI_IRQ_BASE + 4)
+#define IT8172_POWER_NMI_IRQ     (IT8172_NMI_IRQ_BASE + 5)
+
+/* Finally, let's move over here the mips cpu timer interrupt.
+ * This is more or less strictly for statistics.
+ */
+#define MIPS_CPU_TIMER_IRQ       (IT8172_NMI_IRQ_BASE + 6)
+
+#define IT8172_INT_END           MIPS_CPU_TIMER_IRQ
+
+/* 
+ * IT8172 Interrupt Controller Registers
+ */
+struct it8172_intc_regs {
+        volatile unsigned short lb_req;      /* offset 0 */
+        volatile unsigned short lb_mask;
+        volatile unsigned short lb_trigger;
+        volatile unsigned short lb_level;
+       unsigned char pad0[8];
+
+        volatile unsigned short lpc_req;     /* offset 0x10 */
+        volatile unsigned short lpc_mask;
+        volatile unsigned short lpc_trigger;
+        volatile unsigned short lpc_level;
+       unsigned char pad1[8];
+
+        volatile unsigned short pci_req;     /* offset 0x20 */
+        volatile unsigned short pci_mask;
+        volatile unsigned short pci_trigger;
+        volatile unsigned short pci_level;
+       unsigned char pad2[8];
+
+        volatile unsigned short nmi_req;     /* offset 0x30 */
+        volatile unsigned short nmi_mask;
+        volatile unsigned short nmi_trigger;
+        volatile unsigned short nmi_level;
+       unsigned char pad3[6];
+
+        volatile unsigned short nmi_redir;   /* offset 0x3E */
+       unsigned char pad4[0xBE];
+
+        volatile unsigned short intstatus;    /* offset 0xFE */
+};
+
+#endif /* _MIPS_ITEINT_H */
diff --git a/include/asm-mips/it8172/it8172_lpc.h b/include/asm-mips/it8172/it8172_lpc.h
new file mode 100644 (file)
index 0000000..f3d4079
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *     IT8172 system controller defines.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
diff --git a/include/asm-mips/it8172/it8172_pci.h b/include/asm-mips/it8172/it8172_pci.h
new file mode 100644 (file)
index 0000000..042db29
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *     IT8172 system controller specific pci defines.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *             ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _8172PCI_H_
+#define _8172PCI_H_
+
+// PCI configuration space Type0
+#define        PCI_IDREG       0x00
+#define        PCI_CMDSTSREG   0x04
+#define        PCI_CLASSREG    0x08
+#define        PCI_BHLCREG     0x0C
+#define        PCI_BASE1REG    0x10
+#define        PCI_BASE2REG    0x14
+#define        PCI_BASE3REG    0x18
+#define        PCI_BASE4REG    0x1C
+#define        PCI_BASE5REG    0x20
+#define        PCI_BASE6REG    0x24
+#define        PCI_ROMBASEREG  0x30
+#define        PCI_INTRREG     0x3C
+
+// PCI configuration space Type1
+#define        PCI_BUSNOREG    0x18
+
+#define        IT_PCI_VENDORID(x)      ((x) & 0xFFFF)
+#define        IT_PCI_DEVICEID(x)      (((x)>>16) & 0xFFFF)
+
+// Command register
+#define        PCI_CMD_IOEN            0x00000001
+#define        PCI_CMD_MEMEN           0x00000002
+#define        PCI_CMD_BUSMASTER       0x00000004
+#define        PCI_CMD_SPCYCLE         0x00000008
+#define        PCI_CMD_WRINV           0x00000010
+#define        PCI_CMD_VGASNOOP        0x00000020
+#define        PCI_CMD_PERR            0x00000040
+#define        PCI_CMD_WAITCTRL        0x00000080
+#define        PCI_CMD_SERR            0x00000100
+#define        PCI_CMD_FAST_BACKTOBACK 0x00000200
+
+// Status register
+#define        PCI_STS_66MHZ           0x00200000
+#define        PCI_STS_SUPPORT_UDF     0x00400000
+#define        PCI_STS_FAST_BACKTOBACK 0x00800000
+#define        PCI_STS_DATA_PERR       0x01000000
+#define        PCI_STS_DEVSEL0         0x02000000
+#define        PCI_STS_DEVSEL1         0x04000000
+#define        PCI_STS_SIG_TGTABORT    0x08000000
+#define        PCI_STS_RCV_TGTABORT    0x10000000
+#define        PCI_STS_RCV_MSTABORT    0x20000000
+#define        PCI_STS_SYSERR          0x40000000
+#define        PCI_STS_DETCT_PERR      0x80000000
+
+#define        IT_PCI_CLASS(x)         (((x)>>24) & 0xFF)
+#define        IT_PCI_SUBCLASS(x)              (((x)>>16) & 0xFF)
+#define        IT_PCI_INTERFACE(x)     (((x)>>8) & 0xFF)
+#define        IT_PCI_REVISION(x)              ((x) & 0xFF)
+
+// PCI class code
+#define        PCI_CLASS_BRIDGE                        0x06
+
+// bridge subclass
+#define        PCI_SUBCLASS_BRIDGE_HOST                0x00
+#define        PCI_SUBCLASS_BRIDGE_PCI                 0x04
+
+// BHLCREG
+#define        IT_PCI_BIST(x)          (((x)>>24) & 0xFF)
+#define        IT_PCI_HEADERTYPE(x)    (((x)>>16) & 0xFF)
+#define        IT_PCI_LATENCYTIMER(x)  (((x)>>8) & 0xFF)
+#define        IT_PCI_CACHELINESIZE(x) ((x) & 0xFF)
+
+#define        PCI_MULTIFUNC   0x80
+
+// INTRREG
+#define        IT_PCI_MAXLAT(x)                (((x)>>24) & 0xFF)
+#define        IT_PCI_MINGNT(x)                (((x)>>16) & 0xFF)
+#define        IT_PCI_INTRPIN(x)               (((x)>>8) & 0xFF)
+#define        IT_PCI_INTRLINE(x)              ((x) & 0xFF)
+
+#define        PCI_VENDOR_NEC  0x1033
+#define PCI_VENDOR_DEC 0x1101
+
+#endif // _8172PCI_H_
diff --git a/include/asm-mips/it8712.h b/include/asm-mips/it8712.h
new file mode 100644 (file)
index 0000000..07ea965
--- /dev/null
@@ -0,0 +1,28 @@
+
+#ifndef __IT8712_H__
+#define __IT8712_H__
+
+#define LPC_BASE_ADDR  0x14000000
+
+// MB PnP configuration register 
+#define LPC_KEY_ADDR   0x1400002E
+#define LPC_DATA_ADDR  0x1400002F
+
+// Device LDN
+#define LDN_SERIAL1    0x01
+#define LDN_SERIAL2    0x02
+#define LDN_PARALLEL   0x03
+#define LDN_KEYBOARD   0x05
+#define LDN_MOUSE      0x06
+
+#define IT8712_UART1_PORT      0x3F8
+#define IT8712_UART2_PORT      0x2F8
+
+#ifndef ASM_ONLY
+
+void LPCSetConfig(char LdnNumber, char Index, char data);
+char LPCGetConfig(char LdnNumber, char Index);
+
+#endif
+
+#endif
index 303f989..7baed2d 100644 (file)
@@ -45,7 +45,7 @@ struct kbd_ops {
        void (*kbd_request_region)(void);
        int (*kbd_request_irq)(void (*handler)(int, void *, struct pt_regs *));
 
-       /* PSaux driver resource managment  */
+       /* PSaux driver resource management  */
        int (*aux_request_irq)(void (*handler)(int, void *, struct pt_regs *));
        void (*aux_free_irq)(void);
 
index f7a29a8..4991bab 100644 (file)
@@ -292,7 +292,7 @@ __BUILD_SET_CP0(config,CP0_CONFIG)
 /*
  * Bitfields and bit numbers in the coprocessor 0 cause register.
  *
- * Refer to to your MIPS R4xx0 manual, chapter 5 for explanation.
+ * Refer to your MIPS R4xx0 manual, chapter 5 for explanation.
  */
 #define  CAUSEB_EXCCODE                2
 #define  CAUSEF_EXCCODE                (31  <<  2)
index 77c99d3..809bded 100644 (file)
@@ -40,7 +40,7 @@ extern inline void pcibios_penalize_isa_irq(int irq)
 #include <linux/string.h>
 #include <asm/io.h>
 
-#ifdef CONFIG_DDB5074
+#if (defined(CONFIG_DDB5074) || defined(CONFIG_DDB5476))
 #undef PCIBIOS_MIN_IO
 #undef PCIBIOS_MIN_MEM
 #define PCIBIOS_MIN_IO         0x0100000
index 7e16025..decd449 100644 (file)
@@ -98,15 +98,20 @@ extern struct task_struct *last_task_used_math;
 #define NUM_FPU_REGS   32
 
 struct mips_fpu_hard_struct {
-       unsigned int fp_regs[NUM_FPU_REGS];
+       double fp_regs[NUM_FPU_REGS];
        unsigned int control;
-} __attribute__((aligned(8)));
+};
 
 /*
- * FIXME: no fpu emulator yet (but who cares anyway?)
+ * It would be nice to add some more fields for emulator statistics, but there
+ * are a number of fixed offsets in offset.h and elsewhere that would have to
+ * be recalculated by hand.  So the additional information will be private to
+ * the FPU emulator for now.  See asm-mips/fpu_emulator.h.
  */
+typedef u64 fpureg_t;
 struct mips_fpu_soft_struct {
-       long    dummy;
+       fpureg_t        regs[NUM_FPU_REGS];
+       unsigned int    sr;
 };
 
 union mips_fpu_union {
@@ -148,6 +153,21 @@ struct thread_struct {
        mm_segment_t current_ds;
        unsigned long irix_trampoline;  /* Wheee... */
        unsigned long irix_oldctx;
+
+       /*
+        * These are really only needed if the full FPU emulator is configured.
+        * Would be made conditional on MIPS_FPU_EMULATOR if it weren't for the
+        * fact that having offset.h rebuilt differently for different config
+        * options would be asking for trouble.
+        *
+        * Saved EPC during delay-slot emulation (see math-emu/cp1emu.c)
+        */
+       unsigned long dsemul_epc;
+
+       /*
+        * Pointer to instruction used to induce address error
+        */
+       unsigned long dsemul_aerpc;
 };
 
 #endif /* !defined (_LANGUAGE_ASSEMBLY) */
@@ -176,7 +196,12 @@ struct thread_struct {
        /* \
         * For now the default is to fix address errors \
         */ \
-       MF_FIXADE, { 0 }, 0, 0 \
+       MF_FIXADE, { 0 }, 0, 0, \
+       /* \
+        * dsemul_epc and dsemul_aerpc should never be used uninitialized, \
+        * but... \
+        */ \
+       0 ,0 \
 }
 
 #ifdef __KERNEL__
index f877402..baffb07 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/spinlock.h>
 #include <linux/wait.h>
 #include <linux/config.h>
+#include <linux/rwsem.h>
 
 struct semaphore {
 #ifdef __MIPSEB__
@@ -215,7 +216,7 @@ struct rw_semaphore {
        atomic_t                count;
        /* bit 0 means read bias granted;
           bit 1 means write bias granted.  */
-       unsigned                granted;
+       unsigned long           granted; /* pedant: long req'd for set_bit */
        wait_queue_head_t       wait;
        wait_queue_head_t       write_bias_wait;
 #if WAITQUEUE_DEBUG
index 8f11c13..3beb1cd 100644 (file)
@@ -200,7 +200,7 @@ struct sgimc_dma_ctrl {
        u32 _unused7;
        volatile u32 dmamode;     /* DMA mode config bit settings */
        u32 _unused8;
-       volatile u32 dmacount;    /* Zoom and byte count for DMA */
+       volatile u32 dmaccount;    /* Zoom and byte count for DMA */
        u32 _unused9;
        volatile u32 dmastart;    /* Pedal to the metal. */
        u32 _unused10;
index 931aeea..632d8aa 100644 (file)
@@ -146,7 +146,7 @@ struct shmiqsetcpos {
 /* get time since last event */
 #define QIOCGETITIME    _IOR('Q', 11, time_t)
 
-/* set curent screen */
+/* set current screen */
 #define QIOCSETSCRN     _IOW('Q',6,int)
 
 
index 7864a40..615ab3a 100644 (file)
  */
 #define ENOMEDIUM      159     /* No medium found */
 #define EMEDIUMTYPE    160     /* Wrong medium type */
-#define EHASHCOLLISION 125     /* Number of hash collisons exceeds maximum generation counter value.  */
 
 #define EDQUOT         1133    /* Quota exceeded */
 
index 067d06e..098c933 100644 (file)
@@ -44,7 +44,7 @@ struct kbd_ops {
        void (*kbd_request_region)(void);
        int (*kbd_request_irq)(void (*handler)(int, void *, struct pt_regs *));
 
-       /* PSaux driver resource managment  */
+       /* PSaux driver resource management  */
        int (*aux_request_irq)(void (*handler)(int, void *, struct pt_regs *));
        void (*aux_free_irq)(void);
 
index 7a9f12c..1b51b60 100644 (file)
@@ -216,7 +216,7 @@ __BUILD_SET_CP0(config,CP0_CONFIG)
 /*
  * Bitfields and bit numbers in the coprocessor 0 cause register.
  *
- * Refer to to your MIPS R4xx0 manual, chapter 5 for explanation.
+ * Refer to your MIPS R4xx0 manual, chapter 5 for explanation.
  */
 #define  CAUSEB_EXCCODE                2
 #define  CAUSEF_EXCCODE                (31  <<  2)
index 7b06e7a..c7d838b 100644 (file)
@@ -58,7 +58,7 @@ extern plat_pg_data_t *plat_node_data[];
 
 /*
  * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
- * and returns the the mem_map of that node.
+ * and returns the mem_map of that node.
  */
 #define ADDR_TO_MAPBASE(kaddr) \
                        NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(kaddr)))
index 1fc14c5..ef149f3 100644 (file)
@@ -276,7 +276,7 @@ typedef struct bridge_err_cmdword_s {
                                ds:2,           /* Data size      */
                                gbr:1,          /* GBR enable     */
                                vbpm:1,         /* VBPM message   */
-                               error:1,        /* Error occured  */
+                               error:1,        /* Error occurred  */
                                barr:1,         /* Barrier op     */
                                rsvd:8;
                } berr_st;
index 67c7b87..e9f8d78 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/atomic.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
+#include <linux/rwsem.h>
 
 struct semaphore {
 #ifdef __MIPSEB__
@@ -169,178 +170,4 @@ static inline void up(struct semaphore * sem)
                __up(sem);
 }
 
-/*
- * rw mutexes (should that be mutices? =) -- throw rw spinlocks and
- * semaphores together, and this is what we end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer subtracts BIAS ands
- * gets 0 for the case of an uncontended lock.  Readers decrement by 1 and
- * see a positive value when uncontended, negative if there are writers
- * waiting (in which case it goes to sleep).
- *
- * The value 0x01000000 supports up to 128 processors and lots of processes.
- * BIAS must be chosen such that subtracting BIAS once per CPU will result
- * in the int remaining negative.  In terms of fairness, this should result
- * in the lock flopping back and forth between readers and writers under
- * heavy use.
- *
- * Once we start supporting machines with more than 128 CPUs, we should go
- * for using a 64bit atomic type instead of 32bit as counter. We shall
- * probably go for bias 0x80000000 then, so that single sethi can set it.
- * */
-
-#define RW_LOCK_BIAS           0x01000000
-
-struct rw_semaphore {
-       atomic_t                count;
-       /* bit 0 means read bias granted;
-          bit 1 means write bias granted.  */
-       unsigned long           granted;
-       wait_queue_head_t       wait;
-       wait_queue_head_t       write_bias_wait;
-#if WAITQUEUE_DEBUG
-       long                    __magic;
-       atomic_t                readers;
-       atomic_t                writers;
-#endif
-};
-
-#if WAITQUEUE_DEBUG
-#define __RWSEM_DEBUG_INIT     , ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-#define __RWSEM_DEBUG_INIT     /* */
-#endif
-
-#define __RWSEM_INITIALIZER(name,count)                                        \
-       { ATOMIC_INIT(count), 0,                                        \
-         __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),                   \
-         __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait)         \
-         __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-       struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) \
-       __DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) \
-       __DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) \
-       __DECLARE_RWSEM_GENERIC(name, 0)
-
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-       atomic_set(&sem->count, RW_LOCK_BIAS);
-       sem->granted = 0;
-       init_waitqueue_head(&sem->wait);
-       init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-       sem->__magic = (long)&sem->__magic;
-       atomic_set(&sem->readers, 0);
-       atomic_set(&sem->writers, 0);
-#endif
-}
-
-/* The expensive part is outlined.  */
-extern void __down_read(struct rw_semaphore *sem, int count);
-extern void __down_write(struct rw_semaphore *sem, int count);
-extern void __rwsem_wake(struct rw_semaphore *sem, unsigned long readers);
-
-static inline void down_read(struct rw_semaphore *sem)
-{
-       int count;
-
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
-       count = atomic_dec_return(&sem->count);
-       if (count < 0) {
-               __down_read(sem, count);
-       }
-       mb();
-
-#if WAITQUEUE_DEBUG
-       if (sem->granted & 2)
-               BUG();
-       if (atomic_read(&sem->writers))
-               BUG();
-       atomic_inc(&sem->readers);
-#endif
-}
-
-static inline void down_write(struct rw_semaphore *sem)
-{
-       int count;
-
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
-       count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
-       if (count) {
-               __down_write(sem, count);
-       }
-       mb();
-
-#if WAITQUEUE_DEBUG
-       if (atomic_read(&sem->writers))
-               BUG();
-       if (atomic_read(&sem->readers))
-               BUG();
-       if (sem->granted & 3)
-               BUG();
-       atomic_inc(&sem->writers);
-#endif
-}
-
-/* When a reader does a release, the only significant case is when
-   there was a writer waiting, and we've bumped the count to 0: we must
-   wake the writer up.  */
-
-static inline void up_read(struct rw_semaphore *sem)
-{
-       int count;
-
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-       if (sem->granted & 2)
-               BUG();
-       if (atomic_read(&sem->writers))
-               BUG();
-       atomic_dec(&sem->readers);
-#endif
-
-       mb();
-       count = atomic_inc_return(&sem->count);
-       if (count == 0) {
-               __rwsem_wake(sem, 0);
-       }
-}
-
-/*
- * Releasing the writer is easy -- just release it and wake up any sleepers.
- */
-static inline void up_write(struct rw_semaphore *sem)
-{
-       int count;
-
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-       if (sem->granted & 3)
-               BUG();
-       if (atomic_read(&sem->readers))
-               BUG();
-       if (atomic_read(&sem->writers) != 1)
-               BUG();
-       atomic_dec(&sem->writers);
-#endif
-
-       mb();
-       count = atomic_add_return(RW_LOCK_BIAS, &sem->count);
-       if (count - RW_LOCK_BIAS < 0 && count >= 0) {
-               /* Only do the wake if we're no longer negative.  */
-               __rwsem_wake(sem, count);
-       }
-}
-
 #endif /* _ASM_SEMAPHORE_H */
index cbce272..199c549 100644 (file)
@@ -153,7 +153,7 @@ struct shmiqsetcpos {
 /* get time since last event */
 #define QIOCGETITIME    _IOR('Q', 11, time_t)
 
-/* set curent screen */
+/* set current screen */
 #define QIOCSETSCRN     _IOW('Q',6,int)
 
 
index 12deca8..54a8d54 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include <linux/spinlock.h>
+#include <linux/rwsem.h>
 
 #include <asm/system.h>
 #include <asm/atomic.h>
@@ -135,167 +136,4 @@ extern __inline__ void up(struct semaphore * sem)
                __up(sem);
 }
 
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer
- * subtracts BIAS ands gets 0 for the case of an uncontended
- * lock.  Readers decrement by 1 and see a positive value
- * when uncontended, negative if there are writers waiting
- * (in which case it goes to sleep).
- *
- * The value 0x01000000 supports up to 128 processors and
- * lots of processes.  BIAS must be chosen such that subl'ing
- * BIAS once per CPU will result in the long remaining
- * negative.
- *
- * In terms of fairness, this should result in the lock
- * flopping back and forth between readers and writers
- * under heavy use.
- *
- *              -ben
- */
-struct rw_semaphore {
-        atomic_t                count;
-        volatile unsigned char  write_bias_granted;
-        volatile unsigned char  read_bias_granted;
-        volatile unsigned char  pad1;
-        volatile unsigned char  pad2;
-        wait_queue_head_t       wait;
-        wait_queue_head_t       write_bias_wait;
-#if WAITQUEUE_DEBUG
-        long                    __magic;
-        atomic_t                readers;
-        atomic_t                writers;
-#endif
-};
-
-#if WAITQUEUE_DEBUG
-#define __RWSEM_DEBUG_INIT      , ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-#define __RWSEM_DEBUG_INIT      /* */
-#endif
-
-#define RW_LOCK_BIAS 0x01000000
-
-#define __RWSEM_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, 0, 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-        __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
-        __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-        struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
-
-extern inline void init_rwsem(struct rw_semaphore *sem)
-{
-        atomic_set(&sem->count, RW_LOCK_BIAS);
-        sem->read_bias_granted = 0;
-        sem->write_bias_granted = 0;
-        init_waitqueue_head(&sem->wait);
-        init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-        sem->__magic = (long)&sem->__magic;
-        atomic_set(&sem->readers, 0);
-        atomic_set(&sem->writers, 0);
-#endif
-}
-
-#ifdef FIXME_WILLY_FIXME_FOR_REAL_THIS_TIME
-extern struct rw_semaphore *__build_read_lock(struct rw_semaphore *sem, const char *what);
-extern struct rw_semaphore *__build_write_lock(struct rw_semaphore *sem, const char *what);
-#endif
-
-/* we use FASTCALL convention for the helpers */
-extern struct rw_semaphore *FASTCALL(__down_read_failed(struct rw_semaphore *sem));
-extern struct rw_semaphore *FASTCALL(__down_write_failed(struct rw_semaphore *sem));
-extern struct rw_semaphore *FASTCALL(__rwsem_wake(struct rw_semaphore *sem));
-
-extern inline void down_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-        if (sem->__magic != (long)&sem->__magic)
-                BUG();
-#endif
-#ifdef FIXME_WILLY_FIXME_FOR_REAL_THIS_TIME
-        __build_read_lock(sem, "__down_read_failed");
-#endif
-#if WAITQUEUE_DEBUG
-        if (sem->write_bias_granted)
-                BUG();
-        if (atomic_read(&sem->writers))
-                BUG();
-        atomic_inc(&sem->readers);
-#endif
-}
-
-extern inline void down_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-        if (sem->__magic != (long)&sem->__magic)
-                BUG();
-#endif
-#ifdef FIXME_WILLY_FIXME_FOR_REAL_THIS_TIME
-        __build_write_lock(sem, "__down_write_failed");
-#endif
-#if WAITQUEUE_DEBUG
-        if (atomic_read(&sem->writers))
-                BUG();
-        if (atomic_read(&sem->readers))
-                BUG();
-        if (sem->read_bias_granted)
-                BUG();
-        if (sem->write_bias_granted)
-                BUG();
-        atomic_inc(&sem->writers);
-#endif
-}
-
-/* When a reader does a release, the only significant
- * case is when there was a writer waiting, and we've
- * bumped the count to 0: we must wake the writer up.
- */
-extern inline void __up_read(struct rw_semaphore *sem)
-{
-}
-
-/* releasing the writer is easy -- just release it and
- * wake up any sleepers.
- */
-extern inline void __up_write(struct rw_semaphore *sem)
-{
-}
-
-extern inline void up_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-        if (sem->write_bias_granted)
-                BUG();
-        if (atomic_read(&sem->writers))
-                BUG();
-        atomic_dec(&sem->readers);
-#endif
-        __up_read(sem);
-}
-
-extern inline void up_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-        if (sem->read_bias_granted)
-                BUG();
-        if (sem->write_bias_granted)
-                BUG();
-        if (atomic_read(&sem->readers))
-                BUG();
-        if (atomic_read(&sem->writers) != 1)
-                BUG();
-        atomic_dec(&sem->writers);
-#endif
-        __up_write(sem);
-}
-
 #endif /* _ASM_PARISC_SEMAPHORE_H */
index da81ad2..4c196ea 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/atomic.h>
 #include <asm/system.h>
 #include <linux/wait.h>
+#include <linux/rwsem.h>
 
 struct semaphore {
        atomic_t count;
@@ -107,99 +108,6 @@ extern inline void up(struct semaphore * sem)
 }      
 
 
-/* RW spinlock-based semaphores */
-
-struct rw_semaphore
-{
-       spinlock_t lock;
-       int rd, wr;
-       wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-       long __magic;
-#endif
-};
-
-#define RW_LOCK_BIAS   2       /* XXX bogus */
-#define __RWSEM_INITIALIZER(name, count)               \
-{                                                      \
-       SPIN_LOCK_UNLOCKED,                             \
-       (count) == 1, (count) == 0,                     \
-       __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)      \
-       __SEM_DEBUG_INIT(name)                          \
-}
-
-#define __DECLARE_RWSEM_GENERIC(name, count)           \
-       struct rw_semaphore name = __RWSEM_INITIALIZER(name, count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name, 0)
-
-extern inline void init_rwsem(struct rw_semaphore *sem)
-{
-       spin_lock_init(&sem->lock);
-       sem->rd = sem->wr = 0;
-       init_waitqueue_head(&sem->wait);
-#if WAITQUEUE_DEBUG
-       sem->__magic = (long)&sem->__magic;
-#endif
-}
-
-#ifndef CHECK_MAGIC
-#define CHECK_MAGIC(x)
-#endif
-
-extern void down_read_failed(struct rw_semaphore *);
-extern void down_write_failed(struct rw_semaphore *);
-
-extern inline void down_read(struct rw_semaphore *sem)
-{
-       CHECK_MAGIC(sem->__magic);
-
-       spin_lock_irq(&sem->lock);
-       if (sem->wr)
-               down_read_failed(sem);
-       sem->rd++;
-       spin_unlock_irq(&sem->lock);
-}
-
-extern inline void down_write(struct rw_semaphore *sem)
-{
-       CHECK_MAGIC(sem->__magic);
-
-       spin_lock(&sem->lock);
-       if(sem->rd || sem->wr)
-               down_write_failed(sem);
-       sem->wr = 1;
-       spin_unlock(&sem->lock);
-}
-
-#define up_read(sem)                                                   \
-       do {                                                            \
-               unsigned long flags;                                    \
-                                                                       \
-               CHECK_MAGIC((sem)->__magic);                            \
-                                                                       \
-               spin_lock_irqsave(&(sem)->lock, flags);                 \
-               if (!--(sem)->rd && waitqueue_active(&(sem)->wait))     \
-                       wake_up(&(sem)->wait);                          \
-               spin_unlock_irqrestore(&(sem)->lock, flags);            \
-       } while (0)
-
-#define up_write(sem)                                                  \
-       do {                                                            \
-               unsigned long flags;                                    \
-                                                                       \
-               CHECK_MAGIC((sem)->__magic);                            \
-                                                                       \
-               spin_lock_irqsave(&(sem)->lock, flags);                 \
-               (sem)->wr = 0;                                          \
-               if (waitqueue_active(&(sem)->wait))                     \
-                       wake_up(&(sem)->wait);                          \
-               spin_unlock_irqrestore(&(sem)->lock, flags);            \
-       } while (0)
-
-
 #endif /* __KERNEL__ */
 
 #endif /* !(_PPC_SEMAPHORE_H) */
index dfd49e1..217b2ae 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/system.h>
 #include <asm/atomic.h>
 #include <linux/wait.h>
+#include <linux/rwsem.h>
 
 struct semaphore {
        atomic_t count;
@@ -91,101 +92,4 @@ static inline void up(struct semaphore * sem)
                __up(sem);
 }
 
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer
- * subtracts BIAS ands gets 0 for the case of an uncontended
- * lock.  Readers decrement by 1 and see a positive value
- * when uncontended, negative if there are writers waiting
- * (in which case it goes to sleep).
- *
- * The value 0x01000000 supports up to 128 processors and
- * lots of processes.  BIAS must be chosen such that subl'ing
- * BIAS once per CPU will result in the long remaining
- * negative.
- *
- * In terms of fairness, this should result in the lock
- * flopping back and forth between readers and writers
- * under heavy use.
- *
- *             -ben
- */
-struct rw_semaphore {
-       atomic_t                count;
-       volatile unsigned int   write_bias_granted;
-       volatile unsigned int   read_bias_granted;
-       wait_queue_head_t       wait;
-       wait_queue_head_t       write_bias_wait;
-};
-
-#define RW_LOCK_BIAS            0x01000000
-
-#define __RWSEM_DEBUG_INIT     /* */
-
-#define __RWSEM_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-       __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
-       __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-       struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
-
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-       atomic_set(&sem->count, RW_LOCK_BIAS);
-       sem->read_bias_granted = 0;
-       sem->write_bias_granted = 0;
-       init_waitqueue_head(&sem->wait);
-       init_waitqueue_head(&sem->write_bias_wait);
-}
-
-extern void __down_read_failed(int, struct rw_semaphore *);
-extern void __down_write_failed(int, struct rw_semaphore *);
-extern void __rwsem_wake(int, struct rw_semaphore *);
-
-static inline void down_read(struct rw_semaphore *sem)
-{
-       int count;
-       count = atomic_dec_return(&sem->count);
-       if (count < 0)
-               __down_read_failed(count, sem);
-}
-
-static inline void down_write(struct rw_semaphore *sem)
-{
-       int count;
-       count = atomic_add_return (-RW_LOCK_BIAS, &sem->count);
-       if (count < 0)
-               __down_write_failed(count, sem);
-}
-
-/* When a reader does a release, the only significant
- * case is when there was a writer waiting, and we've
- * bumped the count to 0: we must wake the writer up.
- */
-static inline void up_read(struct rw_semaphore *sem)
-{
-       int count;
-       count = atomic_inc_return(&sem->count);
-       if (count == 0)
-               __rwsem_wake(count, sem);
-}
-
-/* releasing the writer is easy -- just release it and
- * wake up any sleepers.
- */
-static inline void up_write(struct rw_semaphore *sem)
-{
-       int count;
-       count = atomic_add_return(RW_LOCK_BIAS, &sem->count);
-       if (count >= 0 && count < RW_LOCK_BIAS)
-               __rwsem_wake(count, sem);
-}
-
 #endif
index eda753c..504be16 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/system.h>
 #include <asm/atomic.h>
 #include <linux/wait.h>
+#include <linux/rwsem.h>
 
 struct semaphore {
        atomic_t count;
@@ -91,101 +92,4 @@ static inline void up(struct semaphore * sem)
                __up(sem);
 }
 
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer
- * subtracts BIAS ands gets 0 for the case of an uncontended
- * lock.  Readers decrement by 1 and see a positive value
- * when uncontended, negative if there are writers waiting
- * (in which case it goes to sleep).
- *
- * The value 0x01000000 supports up to 128 processors and
- * lots of processes.  BIAS must be chosen such that subl'ing
- * BIAS once per CPU will result in the long remaining
- * negative.
- *
- * In terms of fairness, this should result in the lock
- * flopping back and forth between readers and writers
- * under heavy use.
- *
- *             -ben
- */
-struct rw_semaphore {
-       atomic_t                count;
-       volatile unsigned int   write_bias_granted;
-       volatile unsigned int   read_bias_granted;
-       wait_queue_head_t       wait;
-       wait_queue_head_t       write_bias_wait;
-};
-
-#define RW_LOCK_BIAS            0x01000000
-
-#define __RWSEM_DEBUG_INIT     /* */
-
-#define __RWSEM_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-       __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
-       __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-       struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
-
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-       atomic_set(&sem->count, RW_LOCK_BIAS);
-       sem->read_bias_granted = 0;
-       sem->write_bias_granted = 0;
-       init_waitqueue_head(&sem->wait);
-       init_waitqueue_head(&sem->write_bias_wait);
-}
-
-extern void __down_read_failed(int, struct rw_semaphore *);
-extern void __down_write_failed(int, struct rw_semaphore *);
-extern void __rwsem_wake(int, struct rw_semaphore *);
-
-static inline void down_read(struct rw_semaphore *sem)
-{
-       int count;
-       count = atomic_dec_return(&sem->count);
-       if (count < 0)
-               __down_read_failed(count, sem);
-}
-
-static inline void down_write(struct rw_semaphore *sem)
-{
-       int count;
-       count = atomic_add_return (-RW_LOCK_BIAS, &sem->count);
-       if (count < 0)
-               __down_write_failed(count, sem);
-}
-
-/* When a reader does a release, the only significant
- * case is when there was a writer waiting, and we've
- * bumped the count to 0: we must wake the writer up.
- */
-static inline void up_read(struct rw_semaphore *sem)
-{
-       int count;
-       count = atomic_inc_return(&sem->count);
-       if (count == 0)
-               __rwsem_wake(count, sem);
-}
-
-/* releasing the writer is easy -- just release it and
- * wake up any sleepers.
- */
-static inline void up_write(struct rw_semaphore *sem)
-{
-       int count;
-       count = atomic_add_return(RW_LOCK_BIAS, &sem->count);
-       if (count >= 0 && count < RW_LOCK_BIAS)
-               __rwsem_wake(count, sem);
-}
-
 #endif
index 8b75e34..d338955 100644 (file)
@@ -13,6 +13,7 @@
  */
 
 #include <linux/spinlock.h>
+#include <linux/rwsem.h>
 
 #include <asm/system.h>
 #include <asm/atomic.h>
@@ -136,149 +137,4 @@ extern __inline__ void up(struct semaphore * sem)
                __up(sem);
 }
 
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * SuperH version by Niibe Yutaka
- */
-struct rw_semaphore {
-       atomic_t                count;
-       volatile unsigned char  write_bias_granted;
-       volatile unsigned char  read_bias_granted;
-       volatile unsigned char  pad1;
-       volatile unsigned char  pad2;
-       wait_queue_head_t       wait;
-       wait_queue_head_t       write_bias_wait;
-#if WAITQUEUE_DEBUG
-       long                    __magic;
-       atomic_t                readers;
-       atomic_t                writers;
-#endif
-};
-
-#define RW_LOCK_BIAS            0x01000000
-
-#if WAITQUEUE_DEBUG
-#define __RWSEM_DEBUG_INIT     , ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-#define __RWSEM_DEBUG_INIT     /* */
-#endif
-
-#define __RWSEM_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, 0, 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-       __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
-       __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-       struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
-
-extern inline void init_rwsem(struct rw_semaphore *sem)
-{
-       atomic_set(&sem->count, RW_LOCK_BIAS);
-       sem->read_bias_granted = 0;
-       sem->write_bias_granted = 0;
-       init_waitqueue_head(&sem->wait);
-       init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-       sem->__magic = (long)&sem->__magic;
-       atomic_set(&sem->readers, 0);
-       atomic_set(&sem->writers, 0);
-#endif
-}
-
-extern inline void down_read(struct rw_semaphore *sem)
-{
-       int saved = atomic_read(&sem->count), new;
-#if WAITQUEUE_DEBUG
-       if (sem->__magic != (long)&sem->__magic)
-               BUG();
-#endif
-       if ((new = atomic_dec_return(&sem->count)) < 0)
-               __down_read(sem, (new < 0 && saved >=0));
-#if WAITQUEUE_DEBUG
-       if (sem->write_bias_granted)
-               BUG();
-       if (atomic_read(&sem->writers))
-               BUG();
-       atomic_inc(&sem->readers);
-#endif
-}
-
-extern inline void down_write(struct rw_semaphore *sem)
-{
-       int saved = atomic_read(&sem->count), new;
-#if WAITQUEUE_DEBUG
-       if (sem->__magic != (long)&sem->__magic)
-               BUG();
-#endif
-       if ((new = atomic_sub_return(RW_LOCK_BIAS, &sem->count)) != 0)
-               __down_write(sem, (new < 0 && saved >=0));
-#if WAITQUEUE_DEBUG
-       if (atomic_read(&sem->writers))
-               BUG();
-       if (atomic_read(&sem->readers))
-               BUG();
-       if (sem->read_bias_granted)
-               BUG();
-       if (sem->write_bias_granted)
-               BUG();
-       atomic_inc(&sem->writers);
-#endif
-}
-
-/* When a reader does a release, the only significant
- * case is when there was a writer waiting, and we've
- * bumped the count to 0: we must wake the writer up.
- */
-extern inline void __up_read(struct rw_semaphore *sem)
-{
-       if (atomic_inc_return(&sem->count) == 0)
-               __rwsem_wake(sem);
-}
-
-/* releasing the writer is easy -- just release it and
- * wake up any sleepers.
- */
-extern inline void __up_write(struct rw_semaphore *sem)
-{
-       int saved = atomic_read(&sem->count), new;
-
-       new = atomic_add_return(RW_LOCK_BIAS, &sem->count);
-       if (saved < 0 && new >= 0)
-               __rwsem_wake(sem);
-}
-
-extern inline void up_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       if (sem->write_bias_granted)
-               BUG();
-       if (atomic_read(&sem->writers))
-               BUG();
-       atomic_dec(&sem->readers);
-#endif
-       __up_read(sem);
-}
-
-extern inline void up_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       if (sem->read_bias_granted)
-               BUG();
-       if (sem->write_bias_granted)
-               BUG();
-       if (atomic_read(&sem->readers))
-               BUG();
-       if (atomic_read(&sem->writers) != 1)
-               BUG();
-       atomic_dec(&sem->writers);
-#endif
-       __up_write(sem);
-}
-
 #endif /* __ASM_SH_SEMAPHORE_H */
index 5a5fc7c..c189f07 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <asm/atomic.h>
 #include <linux/wait.h>
+#include <linux/rwsem.h>
 
 struct semaphore {
        atomic_t count;
@@ -208,201 +209,6 @@ static inline void up(struct semaphore * sem)
        : "g3", "g4", "g7", "memory", "cc");
 }      
 
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer
- * subtracts BIAS ands gets 0 for the case of an uncontended
- * lock.  Readers decrement by 1 and see a positive value
- * when uncontended, negative if there are writers waiting
- * (in which case it goes to sleep).
- *
- * The value 0x01000000 supports up to 128 processors and
- * lots of processes.  BIAS must be chosen such that subtracting
- * BIAS once per CPU will result in the int remaining
- * negative.
- * In terms of fairness, this should result in the lock
- * flopping back and forth between readers and writers
- * under heavy use.
- *
- *           -ben
- */
-#define RW_LOCK_BIAS           0x01000000
-
-struct rw_semaphore {
-       int                     count;
-       unsigned char           lock;
-       unsigned char           read_not_granted;
-       unsigned char           write_not_granted;
-       wait_queue_head_t       wait;
-       wait_queue_head_t       write_bias_wait;
-#if WAITQUEUE_DEBUG
-       long                    __magic;
-       atomic_t                readers;
-       atomic_t                writers;
-#endif
-};
-
-#if WAITQUEUE_DEBUG
-#define __RWSEM_DEBUG_INIT     , ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-#define __RWSEM_DEBUG_INIT     /* */
-#endif
-
-#define __RWSEM_INITIALIZER(name,count) \
-{ (count), 0, 0xff, 0xff, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-  __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
-  __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-       struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
-
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-       sem->count = RW_LOCK_BIAS;
-       sem->lock = 0;
-       sem->read_not_granted = 0xff;
-       sem->write_not_granted = 0xff;
-       init_waitqueue_head(&sem->wait);
-       init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-       sem->__magic = (long)&sem->__magic;
-       atomic_set(&sem->readers, 0);
-       atomic_set(&sem->writers, 0);
-#endif
-}
-
-extern void ___down_read(/* Special calling convention */ void);
-extern void ___down_write(/* Special calling convention */ void);
-extern void ___up_read(/* Special calling convention */ void);
-extern void ___up_write(/* Special calling convention */ void);
-
-static inline void down_read(struct rw_semaphore *sem)
-{
-       register volatile int *ptr asm("g1");
-
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
-       ptr = &sem->count;
-
-       __asm__ __volatile__("
-       mov     %%o7, %%g4
-       call    %1
-        add    %%o7, 8, %%o7
-       "
-       :: "r" (ptr), "i" (___down_read)
-       : "g2", "g3", "g4", "g7", "memory", "cc");
-#if WAITQUEUE_DEBUG
-       if (!sem->write_not_granted)
-               BUG();
-       if (atomic_read(&sem->writers))
-               BUG();
-       atomic_inc(&sem->readers);
-#endif
-}
-
-static inline void down_write(struct rw_semaphore *sem)
-{
-       register volatile int *ptr asm("g1");
-
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-
-       ptr = &sem->count;
-
-       __asm__ __volatile__("
-       mov     %%o7, %%g4
-       call    %1
-        add    %%o7, 8, %%o7
-       "
-       :: "r" (ptr), "i" (___down_write)
-       : "g2", "g3", "g4", "g7", "memory", "cc");
-#if WAITQUEUE_DEBUG
-       if (atomic_read(&sem->writers))
-               BUG();
-       if (atomic_read(&sem->readers))
-               BUG();
-       if (!sem->read_not_granted)
-               BUG();
-       if (!sem->write_not_granted)
-               BUG();
-       atomic_inc(&sem->writers);
-#endif
-}
-
-/* When a reader does a release, the only significant
- * case is when there was a writer waiting, and we've
- * bumped the count to 0: we must wake the writer up.
- */
-static inline void __up_read(struct rw_semaphore *sem)
-{
-       register volatile int *ptr asm("g1");
-
-       ptr = &sem->count;
-
-       __asm__ __volatile__("
-       mov     %%o7, %%g4
-       call    %1
-        add    %%o7, 8, %%o7
-       "
-       :: "r" (ptr), "i" (___up_read)
-       : "g2", "g3", "g4", "g7", "memory", "cc");
-}
-
-/* releasing the writer is easy -- just release it and
- * wake up any sleepers.
- */
-static inline void __up_write(struct rw_semaphore *sem)
-{
-       register volatile int *ptr asm("g1");
-
-       ptr = &sem->count;
-
-       __asm__ __volatile__("
-       mov     %%o7, %%g4
-       call    %1
-        add    %%o7, 8, %%o7
-       "
-       :: "r" (ptr), "i" (___up_write)
-       : "g2", "g3", "g4", "g7", "memory", "cc");
-}
-
-static inline void up_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       if (!sem->write_not_granted)
-               BUG();
-       if (atomic_read(&sem->writers))
-               BUG();
-       atomic_dec(&sem->readers);
-#endif
-       __up_read(sem);
-}
-
-static inline void up_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       if (!sem->read_not_granted)
-               BUG();
-       if (!sem->write_not_granted)
-               BUG();
-       if (atomic_read(&sem->readers))
-               BUG();
-       if (atomic_read(&sem->writers) != 1)
-               BUG();
-       atomic_dec(&sem->writers);
-#endif
-       __up_write(sem);
-}
-
 #endif /* __KERNEL__ */
 
 #endif /* !(_SPARC_SEMAPHORE_H) */
index 26e3716..aad3ef9 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: bitops.h,v 1.31 2000/09/23 02:09:21 davem Exp $
+/* $Id: bitops.h,v 1.32 2001/04/14 01:12:16 davem Exp $
  * bitops.h: Bit string operations on the V9.
  *
  * Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -9,16 +9,24 @@
 
 #include <asm/byteorder.h>
 
-extern long __test_and_set_bit(unsigned long nr, volatile void *addr);
-extern long __test_and_clear_bit(unsigned long nr, volatile void *addr);
-extern long __test_and_change_bit(unsigned long nr, volatile void *addr);
-
-#define test_and_set_bit(nr,addr)      (__test_and_set_bit(nr,addr)!=0)
-#define test_and_clear_bit(nr,addr)    (__test_and_clear_bit(nr,addr)!=0)
-#define test_and_change_bit(nr,addr)   (__test_and_change_bit(nr,addr)!=0)
-#define set_bit(nr,addr)               ((void)__test_and_set_bit(nr,addr))
-#define clear_bit(nr,addr)             ((void)__test_and_clear_bit(nr,addr))
-#define change_bit(nr,addr)            ((void)__test_and_change_bit(nr,addr))
+extern long ___test_and_set_bit(unsigned long nr, volatile void *addr);
+extern long ___test_and_clear_bit(unsigned long nr, volatile void *addr);
+extern long ___test_and_change_bit(unsigned long nr, volatile void *addr);
+
+#define test_and_set_bit(nr,addr)      (___test_and_set_bit(nr,addr)!=0)
+#define test_and_clear_bit(nr,addr)    (___test_and_clear_bit(nr,addr)!=0)
+#define test_and_change_bit(nr,addr)   (___test_and_change_bit(nr,addr)!=0)
+#define set_bit(nr,addr)               ((void)___test_and_set_bit(nr,addr))
+#define clear_bit(nr,addr)             ((void)___test_and_clear_bit(nr,addr))
+#define change_bit(nr,addr)            ((void)___test_and_change_bit(nr,addr))
+
+/* "non-atomic" versions, nothing special for now... */
+#define __set_bit(X,Y)         set_bit(X,Y)
+#define __clear_bit(X,Y)       clear_bit(X,Y)
+#define __change_bit(X,Y)      change_bit(X,Y)
+#define __test_and_set_bit(X,Y)                test_and_set_bit(X,Y)
+#define __test_and_clear_bit(X,Y)      test_and_clear_bit(X,Y)
+#define __test_and_change_bit(X,Y)     test_and_change_bit(X,Y)
 
 #define smp_mb__before_clear_bit()     do { } while(0)
 #define smp_mb__after_clear_bit()      do { } while(0)
@@ -170,13 +178,13 @@ found_middle:
 #define find_first_zero_bit(addr, size) \
         find_next_zero_bit((addr), (size), 0)
 
-extern long __test_and_set_le_bit(int nr, volatile void *addr);
-extern long __test_and_clear_le_bit(int nr, volatile void *addr);
+extern long ___test_and_set_le_bit(int nr, volatile void *addr);
+extern long ___test_and_clear_le_bit(int nr, volatile void *addr);
 
-#define test_and_set_le_bit(nr,addr)   (__test_and_set_le_bit(nr,addr)!=0)
-#define test_and_clear_le_bit(nr,addr) (__test_and_clear_le_bit(nr,addr)!=0)
-#define set_le_bit(nr,addr)            ((void)__test_and_set_le_bit(nr,addr))
-#define clear_le_bit(nr,addr)          ((void)__test_and_clear_le_bit(nr,addr))
+#define test_and_set_le_bit(nr,addr)   (___test_and_set_le_bit(nr,addr)!=0)
+#define test_and_clear_le_bit(nr,addr) (___test_and_clear_le_bit(nr,addr)!=0)
+#define set_le_bit(nr,addr)            ((void)___test_and_set_le_bit(nr,addr))
+#define clear_le_bit(nr,addr)          ((void)___test_and_clear_le_bit(nr,addr))
 
 extern __inline__ int test_le_bit(int nr, __const__ void * addr)
 {
index 09c1bfd..614fec3 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.139 2001/03/27 02:36:37 davem Exp $
+/* $Id: pgtable.h,v 1.140 2001/04/12 22:41:15 davem Exp $
  * pgtable.h: SpitFire page table operations.
  *
  * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -254,12 +254,13 @@ extern inline pte_t mk_pte_io(unsigned long page, pgprot_t prot, int space)
 }
 
 /* Encode and de-code a swap entry */
-#define SWP_TYPE(entry)                (((entry).val >> PAGE_SHIFT) & 0xff)
-#define SWP_OFFSET(entry)      ((entry).val >> (PAGE_SHIFT + 8))
+#define SWP_TYPE(entry)                (((entry).val >> PAGE_SHIFT) & 0xffUL)
+#define SWP_OFFSET(entry)      ((entry).val >> (PAGE_SHIFT + 8UL))
 #define SWP_ENTRY(type, offset)        \
        ( (swp_entry_t) \
          { \
-               ((type << PAGE_SHIFT) | (offset << (PAGE_SHIFT + 8))) \
+               (((long)(type) << PAGE_SHIFT) | \
+                 ((long)(offset) << (PAGE_SHIFT + 8UL))) \
          } )
 #define pte_to_swp_entry(pte)          ((swp_entry_t) { pte_val(pte) })
 #define swp_entry_to_pte(x)            ((pte_t) { (x).val })
diff --git a/include/asm-sparc64/rwsem.h b/include/asm-sparc64/rwsem.h
new file mode 100644 (file)
index 0000000..3c6fd34
--- /dev/null
@@ -0,0 +1,11 @@
+/* $Id: rwsem.h,v 1.1 2001/04/14 01:12:16 davem Exp $ */
+#ifndef _SPARC64_RWSEM_H
+#define _SPARC64_RWSEM_H
+
+#ifndef _LINUX_RWSEM_H
+#error please dont include asm/rwsem.h directly, use linux/rwsem.h instead
+#endif
+
+#undef __HAVE_ARCH_SPECIFIC_RWSEM_IMPLEMENTATION
+
+#endif /* _SPARC64_RWSEM_H */
index 5a53d34..317586a 100644 (file)
@@ -8,6 +8,7 @@
 #include <asm/bitops.h>
 #include <asm/system.h>
 #include <linux/wait.h>
+#include <linux/rwsem.h>
 
 struct semaphore {
        atomic_t count;
@@ -201,268 +202,6 @@ extern __inline__ void up(struct semaphore * sem)
        : "g5", "g7", "memory", "cc");
 }
 
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer
- * subtracts BIAS ands gets 0 for the case of an uncontended
- * lock.  Readers decrement by 1 and see a positive value
- * when uncontended, negative if there are writers waiting
- * (in which case it goes to sleep).
- *
- * The value 0x01000000 supports up to 128 processors and
- * lots of processes.  BIAS must be chosen such that subtracting
- * BIAS once per CPU will result in the int remaining
- * negative.
- * In terms of fairness, this should result in the lock
- * flopping back and forth between readers and writers
- * under heavy use.
- *
- *           -ben
- *
- * Once we start supporting machines with more than 128 CPUs,
- * we should go for using a 64bit atomic type instead of 32bit
- * as counter. We shall probably go for bias 0x80000000 then,
- * so that single sethi can set it.
- *
- *           -jj
- */
-#define RW_LOCK_BIAS           0x01000000
-#define RW_LOCK_BIAS_STR       "0x01000000"
-
-struct rw_semaphore {
-       int                     count;
-       /* So that this does not have to be 64bit type,
-        * we'll use le bitops on it which use casa instead of casx.
-        * bit 0 means read bias granted
-        * bit 1 means write bias granted
-        */
-       unsigned                granted;
-       wait_queue_head_t       wait;
-       wait_queue_head_t       write_bias_wait;
-#if WAITQUEUE_DEBUG
-       long                    __magic;
-       atomic_t                readers;
-       atomic_t                writers;
-#endif
-};
-
-#if WAITQUEUE_DEBUG
-#define __RWSEM_DEBUG_INIT     , ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-#define __RWSEM_DEBUG_INIT     /* */
-#endif
-
-#define __RWSEM_INITIALIZER(name,count) \
-{ (count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-  __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
-  __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-       struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
-
-extern inline void init_rwsem(struct rw_semaphore *sem)
-{
-       sem->count = RW_LOCK_BIAS;
-       sem->granted = 0;
-       init_waitqueue_head(&sem->wait);
-       init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-       sem->__magic = (long)&sem->__magic;
-       atomic_set(&sem->readers, 0);
-       atomic_set(&sem->writers, 0);
-#endif
-}
-
-extern void __down_read_failed(/* Special calling convention */ void);
-extern void __down_write_failed(/* Special calling convention */ void);
-extern void __rwsem_wake(struct rw_semaphore *sem, unsigned long readers);
-
-extern inline void down_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-       __asm__ __volatile__("
-       1:      lduw    [%0], %%g5
-               subcc   %%g5, 1, %%g7
-               cas     [%0], %%g5, %%g7
-               bneg,pn %%icc, 3f
-                cmp    %%g5, %%g7
-               bne,pn  %%icc, 1b
-                membar #StoreStore
-       2:
-               .subsection 2
-       3:      bne,pn  %%icc, 1b
-                mov    %0, %%g7
-               save    %%sp, -160, %%sp
-               mov     %%g1, %%l1
-               mov     %%g2, %%l2
-               call    %1
-                mov    %%g3, %%l3
-               mov     %%l1, %%g1
-               mov     %%l2, %%g2
-               ba,pt   %%xcc, 2b
-                restore %%l3, %%g0, %%g3
-               .previous\n"
-       : : "r" (sem), "i" (__down_read_failed)
-       : "g5", "g7", "memory", "cc");
-#if WAITQUEUE_DEBUG
-       if (test_le_bit(1, &sem->granted))
-               BUG();
-       if (atomic_read(&sem->writers))
-               BUG();
-       atomic_inc(&sem->readers);
-#endif
-}
-
-extern inline void down_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       CHECK_MAGIC(sem->__magic);
-#endif
-       __asm__ __volatile__("
-       1:      lduw    [%0], %%g5
-               sethi   %%hi(" RW_LOCK_BIAS_STR "), %%g7
-               subcc   %%g5, %%g7, %%g7
-               cas     [%0], %%g5, %%g7
-               bne,pn  %%icc, 3f
-                cmp    %%g5, %%g7
-               bne,pn  %%icc, 1b
-                membar #StoreStore
-       2:
-               .subsection 2
-       3:      bne,pn  %%icc, 1b
-                mov    %0, %%g7
-               save    %%sp, -160, %%sp
-               mov     %%g1, %%l1
-               mov     %%g2, %%l2
-               call    %1
-                mov    %%g3, %%l3
-               mov     %%l1, %%g1
-               mov     %%l2, %%g2
-               ba,pt   %%xcc, 2b
-                restore %%l3, %%g0, %%g3
-               .previous\n"
-       : : "r" (sem), "i" (__down_write_failed)
-       : "g5", "g7", "memory", "cc");
-#if WAITQUEUE_DEBUG
-       if (atomic_read(&sem->writers))
-               BUG();
-       if (atomic_read(&sem->readers))
-               BUG();
-       if (test_le_bit(0, &sem->granted))
-               BUG();
-       if (test_le_bit(1, &sem->granted))
-               BUG();
-       atomic_inc(&sem->writers);
-#endif
-}
-
-/* When a reader does a release, the only significant
- * case is when there was a writer waiting, and we've
- * bumped the count to 0: we must wake the writer up.
- */
-extern inline void __up_read(struct rw_semaphore *sem)
-{
-       __asm__ __volatile__("
-               membar  #StoreLoad | #LoadLoad
-       1:      lduw    [%0], %%g5
-               addcc   %%g5, 1, %%g7
-               cas     [%0], %%g5, %%g7
-               be,pn   %%icc, 3f
-                cmp    %%g5, %%g7
-               bne,pn  %%icc, 1b
-                nop
-       2:
-               .subsection 2
-       3:      bne,pn  %%icc, 1b
-                mov    %0, %%g7
-               save    %%sp, -160, %%sp
-               mov     %%g1, %%l1
-               mov     %%g2, %%l2
-               clr     %%o1
-               mov     %%g7, %%o0
-               call    %1
-                mov    %%g3, %%l3
-               mov     %%l1, %%g1
-               mov     %%l2, %%g2
-               ba,pt   %%xcc, 2b
-                restore %%l3, %%g0, %%g3
-               .previous\n"
-       : : "r" (sem), "i" (__rwsem_wake)
-       : "g5", "g7", "memory", "cc");
-}
-
-/* releasing the writer is easy -- just release it and
- * wake up any sleepers.
- */
-extern inline void __up_write(struct rw_semaphore *sem)
-{
-       __asm__ __volatile__("
-               membar  #StoreLoad | #LoadLoad
-       1:      lduw    [%0], %%g5
-               sethi   %%hi(" RW_LOCK_BIAS_STR "), %%g7
-               add     %%g5, %%g7, %%g7
-               cas     [%0], %%g5, %%g7
-               cmp     %%g5, %%g7
-               bne,pn  %%icc, 1b
-                sethi  %%hi(" RW_LOCK_BIAS_STR "), %%g7
-               addcc   %%g5, %%g7, %%g5
-               bcs,pn  %%icc, 3f
-                nop
-       2:
-               .subsection 2
-       3:      mov     %0, %%g7
-               save    %%sp, -160, %%sp
-               mov     %%g1, %%l1
-               mov     %%g2, %%l2
-               srl     %%g5, 0, %%o1
-               mov     %%g7, %%o0
-               call    %1
-                mov    %%g3, %%l3
-               mov     %%l1, %%g1
-               mov     %%l2, %%g2
-               ba,pt   %%xcc, 2b
-                restore %%l3, %%g0, %%g3
-               .previous\n"
-       : : "r" (sem), "i" (__rwsem_wake)
-       : "g5", "g7", "memory", "cc");
-}
-
-extern inline void up_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       if (test_le_bit(1, &sem->granted))
-               BUG();
-       if (atomic_read(&sem->writers))
-               BUG();
-       atomic_dec(&sem->readers);
-#endif
-       __up_read(sem);
-}
-
-extern inline void up_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-       if (test_le_bit(0, &sem->granted))
-               BUG();
-       if (test_le_bit(1, &sem->granted))
-               BUG();
-       if (atomic_read(&sem->readers))
-               BUG();
-       if (atomic_read(&sem->writers) != 1)
-               BUG();
-       atomic_dec(&sem->writers);
-#endif
-       __up_write(sem);
-}
-
 #endif /* __KERNEL__ */
 
 #endif /* !(_SPARC64_SEMAPHORE_H) */
index 4db1520..268ea63 100644 (file)
@@ -96,7 +96,6 @@ extern void devfs_register_series (devfs_handle_t dir, const char *format,
                                   unsigned int minor_start,
                                   umode_t mode, void *ops, void *info);
 
-extern int init_devfs_fs (void);
 extern void mount_devfs_fs (void);
 extern void devfs_make_root (const char *name);
 #else  /*  CONFIG_DEVFS_FS  */
@@ -233,10 +232,6 @@ static inline void devfs_register_series (devfs_handle_t dir,
     return;
 }
 
-static inline int init_devfs_fs (void)
-{
-    return 0;
-}
 static inline void mount_devfs_fs (void)
 {
     return;
index 238c034..2664334 100644 (file)
@@ -1295,7 +1295,6 @@ extern int dcache_readdir(struct file *, void *, filldir_t);
 
 extern struct file_system_type *get_fs_type(const char *name);
 extern struct super_block *get_super(kdev_t);
-struct super_block *get_empty_super(void);
 extern void put_super(kdev_t);
 unsigned long generate_cluster(kdev_t, int b[], int);
 unsigned long generate_cluster_swab32(kdev_t, int b[], int);
index 396dbb5..bd774e0 100644 (file)
@@ -73,7 +73,7 @@
 #define ARPHRD_ECONET  782             /* Acorn Econet                 */
 #define ARPHRD_IRDA    783             /* Linux-IrDA                   */
 /* ARP works differently on different FC media .. so  */
-#define ARPHRD_FCPP    784             /* Point to point fibrechanel   */
+#define ARPHRD_FCPP    784             /* Point to point fibrechannel  */
 #define ARPHRD_FCAL    785             /* Fibrechannel arbitrated loop */
 #define ARPHRD_FCPL    786             /* Fibrechannel public loop     */
 #define ARPHRD_FCFABRIC        787             /* Fibrechannel fabric          */
index cc8abab..fc840c4 100644 (file)
@@ -137,7 +137,6 @@ unsigned long page_index(struct page *page)
  * linux/fs/nfs/inode.c
  */
 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 int nfs_inode_is_stale(struct inode *, struct nfs_fh *,
                                struct nfs_fattr *);
index 77d1695..6aad59b 100644 (file)
@@ -14,8 +14,6 @@
 
 #ifdef __KERNEL__
 
-#define CONFIG_USING_SPINLOCK_BASED_RWSEM 1
-
 /*
  * the semaphore definition
  */
index 966fe4c..c72a194 100644 (file)
 #include <asm/atomic.h>
 #include <linux/wait.h>
 
-#if RWSEM_DEBUG
-#define rwsemdebug(FMT, ARGS...) do { if (sem->debug) printk(FMT,##ARGS); } while(0)
+#ifdef CONFIG_RWSEM_GENERIC_SPINLOCK
+#include <linux/rwsem-spinlock.h> /* use a generic implementation */
 #else
-#define rwsemdebug(FMT, ARGS...)
+#include <asm/rwsem.h> /* use an arch-specific implementation */
 #endif
 
+/* defined contention handler functions for the generic case
+ * - these are also used for the exchange-and-add based algorithm
+ */
+#if defined(CONFIG_RWSEM_GENERIC) || defined(CONFIG_RWSEM_XCHGADD_ALGORITHM)
 /* we use FASTCALL convention for the helpers */
 extern struct rw_semaphore *FASTCALL(rwsem_down_read_failed(struct rw_semaphore *sem));
 extern struct rw_semaphore *FASTCALL(rwsem_down_write_failed(struct rw_semaphore *sem));
 extern struct rw_semaphore *FASTCALL(rwsem_wake(struct rw_semaphore *sem));
+#endif
 
-#include <asm/rwsem.h> /* find the arch specific bits */
-
-#ifndef __HAVE_ARCH_SPECIFIC_RWSEM_IMPLEMENTATION
-#include <linux/rwsem-spinlock.h>
+#ifndef rwsemtrace
+#if RWSEM_DEBUG
+#include <asm/current.h>
+#define rwsemtrace(SEM,FMT) do { if ((SEM)->debug) printk("[%d] "FMT"(count=%08lx)\n",current->pid,(SEM)->count); } while(0)
+#else
+#define rwsemtrace(SEM,FMT)
+#endif
 #endif
 
 /*
@@ -64,7 +72,7 @@ extern struct rw_semaphore *FASTCALL(rwsem_wake(struct rw_semaphore *sem));
  */
 static inline void down_read(struct rw_semaphore *sem)
 {
-       rwsemdebug("Entering down_read(count=%08lx)\n",sem->count);
+       rwsemtrace(sem,"Entering down_read");
 
 #if RWSEM_DEBUG_MAGIC
        if (sem->__magic != (long)&sem->__magic)
@@ -79,7 +87,7 @@ static inline void down_read(struct rw_semaphore *sem)
        atomic_inc(&sem->readers);
 #endif
 
-       rwsemdebug("Leaving down_read(count=%08lx)\n",sem->count);
+       rwsemtrace(sem,"Leaving down_read");
 }
 
 /*
@@ -87,7 +95,7 @@ static inline void down_read(struct rw_semaphore *sem)
  */
 static inline void down_write(struct rw_semaphore *sem)
 {
-       rwsemdebug("Entering down_write(count=%08lx)\n",sem->count);
+       rwsemtrace(sem,"Entering down_write");
 
 #if RWSEM_DEBUG_MAGIC
        if (sem->__magic != (long)&sem->__magic)
@@ -104,7 +112,7 @@ static inline void down_write(struct rw_semaphore *sem)
        atomic_inc(&sem->writers);
 #endif
 
-       rwsemdebug("Leaving down_write(count=%08lx)\n",sem->count);
+       rwsemtrace(sem,"Leaving down_write");
 }
 
 /*
@@ -112,7 +120,7 @@ static inline void down_write(struct rw_semaphore *sem)
  */
 static inline void up_read(struct rw_semaphore *sem)
 {
-       rwsemdebug("Entering up_read(count=%08lx)\n",sem->count);
+       rwsemtrace(sem,"Entering up_read");
 
 #if RWSEM_DEBUG_MAGIC
        if (atomic_read(&sem->writers))
@@ -121,7 +129,7 @@ static inline void up_read(struct rw_semaphore *sem)
 #endif
        __up_read(sem);
 
-       rwsemdebug("Leaving up_read(count=%08lx)\n",sem->count);
+       rwsemtrace(sem,"Leaving up_read");
 }
 
 /*
@@ -129,7 +137,7 @@ static inline void up_read(struct rw_semaphore *sem)
  */
 static inline void up_write(struct rw_semaphore *sem)
 {
-       rwsemdebug("Entering up_write(count=%08lx)\n",sem->count);
+       rwsemtrace(sem,"Entering up_write");
 
 #if RWSEM_DEBUG_MAGIC
        if (atomic_read(&sem->readers))
@@ -140,7 +148,7 @@ static inline void up_write(struct rw_semaphore *sem)
 #endif
        __up_write(sem);
 
-       rwsemdebug("Leaving up_write(count=%08lx)\n",sem->count);
+       rwsemtrace(sem,"Leaving up_write");
 }
 
 
index c6e6e40..e106bf9 100644 (file)
@@ -80,7 +80,7 @@ struct rpc_task {
        unsigned short          tk_lock;        /* Task lock counter */
        unsigned char           tk_active   : 1,/* Task has been activated */
                                tk_wakeup   : 1;/* Task waiting to wake up */
-       unsigned int            tk_runstate;    /* Task run status */
+       unsigned long           tk_runstate;    /* Task run status */
 #ifdef RPC_DEBUG
        unsigned short          tk_pid;         /* debugging aid */
 #endif
index 501ea07..ed20297 100644 (file)
@@ -2,22 +2,22 @@
 #define _LINUX_TTY_LDISC_H
 
 /*
- * This structure defines the interface between the tty line discpline
+ * This structure defines the interface between the tty line discipline
  * implementation and the tty routines.  The following routines can be
  * defined; unless noted otherwise, they are optional, and can be
  * filled in with a null pointer.
  *
  * int (*open)(struct tty_struct *);
  *
- *     This function is called when the line discpline is associated
- *     with the tty.  The line discpline can use this as an
+ *     This function is called when the line discipline is associated
+ *     with the tty.  The line discipline can use this as an
  *     opportunity to initialize any state needed by the ldisc routines.
  * 
  * void        (*close)(struct tty_struct *);
  *
- *     This function is called when the line discpline is being
+ *     This function is called when the line discipline is being
  *     shutdown, either because the tty is being closed or because
- *     the tty is being changed to use a new line discpline
+ *     the tty is being changed to use a new line discipline
  * 
  * void        (*flush_buffer)(struct tty_struct *tty);
  *
  * ssize_t (*chars_in_buffer)(struct tty_struct *tty);
  *
  *     This function returns the number of input characters the line
- *     iscpline may have queued up to be delivered to the user mode
+ *     discipline may have queued up to be delivered to the user mode
  *     process.
  * 
  * ssize_t (*read)(struct tty_struct * tty, struct file * file,
  *                unsigned char * buf, size_t nr);
  *
  *     This function is called when the user requests to read from
- *     the tty.  The line discpline will return whatever characters
+ *     the tty.  The line discipline will return whatever characters
  *     it has buffered up for the user.  If this function is not
  *     defined, the user will receive an EIO error.
  * 
@@ -43,7 +43,7 @@
  *                 const unsigned char * buf, size_t nr);
  *
  *     This function is called when the user requests to write to the
- *     tty.  The line discpline will deliver the characters to the
+ *     tty.  The line discipline will deliver the characters to the
  *     low-level tty device for transmission, optionally performing
  *     some processing on the characters first.  If this function is
  *     not defined, the user will receive an EIO error.
@@ -54,7 +54,7 @@
  *     This function is called when the user requests an ioctl which
  *     is not handled by the tty layer or the low-level tty driver.
  *     It is intended for ioctls which affect line discpline
- *     operation.  Not that the search order for ioctls is (1) tty
+ *     operation.  Note that the search order for ioctls is (1) tty
  *     layer, (2) tty low-level driver, (3) line discpline.  So a
  *     low-level driver can "grab" an ioctl request before the line
  *     discpline has a chance to see it.
@@ -62,7 +62,7 @@
  * void        (*set_termios)(struct tty_struct *tty, struct termios * old);
  *
  *     This function notifies the line discpline that a change has
- *     been made to the termios stucture.
+ *     been made to the termios structure.
  * 
  * int (*poll)(struct tty_struct * tty, struct file * file,
  *               poll_table *wait);
index bdbb348..6dc5d43 100644 (file)
@@ -5,6 +5,7 @@
 *
 * Author:      Nenad Corbic <ncorbic@sangoma.com>
 *              Gideon Hack     
+* Additions:   Arnaldo Melo
 *
 * Copyright:   (c) 1995-2000 Sangoma Technologies Inc.
 *
@@ -18,6 +19,8 @@
 * Jan 28, 2000  Nenad Corbic    Added support for the ASYNC protocol.
 * Oct 04, 1999  Nenad Corbic   Updated for 2.1.0 release
 * Jun 02, 1999  Gideon Hack    Added support for the S514 adapter.
+* May 23, 1999 Arnaldo Melo    Added local_addr to wanif_conf_t
+*                              WAN_DISCONNECTING state added
 * Jul 20, 1998 David Fong      Added Inverse ARP options to 'wanif_conf_t'
 * Jun 12, 1998 David Fong      Added Cisco HDLC support.
 * Dec 16, 1997 Jaspreet Singh  Moved 'enable_IPX' and 'network_number' to
@@ -423,6 +426,9 @@ typedef struct wanif_conf
        unsigned inarp_interval;        /* sec, between InARP requests */
        unsigned long network_number;   /* Network Number for IPX */
        char mc;                        /* Multicast on or off */
+       char local_addr[WAN_ADDRESS_SZ+1];/* local media address, ASCIIZ */
+       unsigned char port;             /* board port */
+       unsigned char protocol;         /* prococol used in this channel (TCPOX25 or X25) */
        char pap;                       /* PAP enabled or disabled */
        char chap;                      /* CHAP enabled or disabled */
        unsigned char userid[511];      /* List of User Id */
@@ -432,7 +438,6 @@ typedef struct wanif_conf
        unsigned char ignore_cts;       /*  Ignore these to determine */
        unsigned char ignore_keepalive; /*  link status (Yes or No) */
        unsigned char hdlc_streaming;   /*  Hdlc streaming mode (Y/N) */
-       unsigned char receive_only;     /*  no transmit buffering (Y/N) */
        unsigned keepalive_tx_tmr;      /* transmit keepalive timer */
        unsigned keepalive_rx_tmr;      /* receive  keepalive timer */
        unsigned keepalive_err_margin;  /* keepalive_error_tolerance */
@@ -462,7 +467,7 @@ typedef struct wanif_conf
        unsigned rx_complete_length;
        unsigned xon_char;
        unsigned xoff_char;
-
+       unsigned char receive_only;     /*  no transmit buffering (Y/N) */
 } wanif_conf_t;
 
 #ifdef __KERNEL__
@@ -508,11 +513,11 @@ typedef struct wan_device
                                        /****** status and statistics *******/
        char state;                     /* device state */
        char api_status;                /* device api status */
-      #if defined(LINUX_2_1) || defined(LINUX_2_4)
+#if defined(LINUX_2_1) || defined(LINUX_2_4)
        struct net_device_stats stats;  /* interface statistics */
-      #else
+#else
        struct enet_statistics stats;   /* interface statistics */
-      #endif
+#endif
        unsigned reserved[16];          /* reserved for future use */
        unsigned long critical;         /* critical section flag */
        spinlock_t lock;                /* Support for SMP Locking */
@@ -530,11 +535,11 @@ typedef struct wan_device
        struct wan_device* next;        /* -> next device */
        netdevice_t* dev;               /* list of network interfaces */
        unsigned ndev;                  /* number of interfaces */
-      #ifdef LINUX_2_4
+#ifdef LINUX_2_4
        struct proc_dir_entry *dent;    /* proc filesystem entry */
-      #else
+#else
        struct proc_dir_entry dent;     /* proc filesystem entry */
-      #endif
+#endif
 } wan_device_t;
 
 /* Public functions available for device drivers */
index 946e273..f417bc8 100644 (file)
@@ -96,7 +96,6 @@ extern int init_pcmcia_ds(void);
 extern void net_notifier_init(void);
 
 extern void free_initmem(void);
-extern void filesystem_setup(void);
 
 #ifdef CONFIG_TC
 extern void tc_init(void);
@@ -723,9 +722,6 @@ static void __init do_basic_setup(void)
        start_context_thread();
        do_initcalls();
 
-       /* .. filesystems .. */
-       filesystem_setup();
-
 #ifdef CONFIG_IRDA
        irda_device_init(); /* Must be done after protocol initialization */
 #endif
index 1848a57..868ad4a 100644 (file)
@@ -129,7 +129,6 @@ EXPORT_SYMBOL(def_blk_fops);
 EXPORT_SYMBOL(update_atime);
 EXPORT_SYMBOL(get_fs_type);
 EXPORT_SYMBOL(get_super);
-EXPORT_SYMBOL(get_empty_super);
 EXPORT_SYMBOL(getname);
 EXPORT_SYMBOL(names_cachep);
 EXPORT_SYMBOL(fput);
index bfa47bb..ce0aa6d 100644 (file)
@@ -8,9 +8,14 @@
 
 L_TARGET := lib.a
 
-export-objs := cmdline.o rwsem.o
+export-objs := cmdline.o
 
-obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o rwsem.o
+obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o
+
+ifneq ($(CONFIG_RWSEM_GENERIC_SPINLOCK)$(CONFIG_RWSEM_XCHGADD_ALGORITHM),nn)
+export-objs += rwsem.o
+obj-y += rwsem.o
+endif
 
 ifneq ($(CONFIG_HAVE_DEC_LOCK),y) 
   obj-y += dec_and_lock.o
index 1473682..d35a5e8 100644 (file)
@@ -18,7 +18,7 @@ struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem)
        DECLARE_WAITQUEUE(wait,tsk);
        signed long count;
 
-       rwsemdebug("[%d] Entering rwsem_down_read_failed(%08lx)\n",current->pid,sem->count);
+       rwsemtrace(sem,"Entering rwsem_down_read_failed");
 
        /* this waitqueue context flag will be cleared when we are granted the lock */
        __set_bit(RWSEM_WAITING_FOR_READ,&wait.flags);
@@ -28,7 +28,6 @@ struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem)
 
        /* note that we're now waiting on the lock, but no longer actively read-locking */
        count = rwsem_atomic_update(RWSEM_WAITING_BIAS-RWSEM_ACTIVE_BIAS,sem);
-       rwsemdebug("X(%08lx)\n",count);
 
        /* if there are no longer active locks, wake the front queued process(es) up
         * - it might even be this process, since the waker takes a more active part
@@ -47,8 +46,7 @@ struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem)
        remove_wait_queue(&sem->wait,&wait);
        tsk->state = TASK_RUNNING;
 
-       rwsemdebug("[%d] Leaving rwsem_down_read_failed(%08lx)\n",current->pid,sem->count);
-
+       rwsemtrace(sem,"Leaving rwsem_down_read_failed");
        return sem;
 }
 
@@ -61,7 +59,7 @@ struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem)
        DECLARE_WAITQUEUE(wait,tsk);
        signed long count;
 
-       rwsemdebug("[%d] Entering rwsem_down_write_failed(%08lx)\n",current->pid,sem->count);
+       rwsemtrace(sem,"Entering rwsem_down_write_failed");
 
        /* this waitqueue context flag will be cleared when we are granted the lock */
        __set_bit(RWSEM_WAITING_FOR_WRITE,&wait.flags);
@@ -71,7 +69,6 @@ struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem)
 
        /* note that we're waiting on the lock, but no longer actively locking */
        count = rwsem_atomic_update(-RWSEM_ACTIVE_BIAS,sem);
-       rwsemdebug("[%d] updated(%08lx)\n",current->pid,count);
 
        /* if there are no longer active locks, wake the front queued process(es) up
         * - it might even be this process, since the waker takes a more active part
@@ -90,8 +87,7 @@ struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem)
        remove_wait_queue(&sem->wait,&wait);
        tsk->state = TASK_RUNNING;
 
-       rwsemdebug("[%d] Leaving rwsem_down_write_failed(%08lx)\n",current->pid,sem->count);
-
+       rwsemtrace(sem,"Leaving rwsem_down_write_failed");
        return sem;
 }
 
@@ -106,7 +102,7 @@ struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem)
        signed long count;
        int woken;
 
-       rwsemdebug("[%d] Entering rwsem_wake(%08lx)\n",current->pid,sem->count);
+       rwsemtrace(sem,"Entering rwsem_wake");
 
  try_again:
        /* try to grab an 'activity' marker
@@ -115,7 +111,7 @@ struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem)
         * - be horribly naughty, and only deal with the LSW of the atomic counter
         */
        if (rwsem_cmpxchgw(sem,0,RWSEM_ACTIVE_BIAS)!=0) {
-               rwsemdebug("[%d] rwsem_wake: abort wakeup due to renewed activity\n",current->pid);
+               rwsemtrace(sem,"rwsem_wake: abort wakeup due to renewed activity");
                goto out;
        }
 
@@ -139,13 +135,13 @@ struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem)
        rwsem_atomic_update(woken,sem);
 
  out:
-       rwsemdebug("[%d] Leaving rwsem_wake(%08lx)\n",current->pid,sem->count);
+       rwsemtrace(sem,"Leaving rwsem_wake");
        return sem;
 
        /* come here if we need to correct the counter for odd SMP-isms */
  counter_correction:
        count = rwsem_atomic_update(-RWSEM_ACTIVE_BIAS,sem);
-       rwsemdebug("[%d] corrected(%08lx)\n",current->pid,count);
+       rwsemtrace(sem,"corrected count");
        if (!(count & RWSEM_ACTIVE_MASK))
                goto try_again;
        goto out;
index 52d42dc..0537365 100644 (file)
@@ -377,7 +377,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
  * sprintf - Format a string and place it in a buffer
  * @buf: The buffer to place the result into
  * @fmt: The format string to use
- * @args: Arguments for the format string
+ * @...: Arguments for the format string
  */
 int sprintf(char * buf, const char *fmt, ...)
 {
index e9e9ef7..0870a25 100644 (file)
@@ -176,6 +176,7 @@ restart_scan:
                preferred = 0;
                goto restart_scan;
        }
+       return NULL;
 found:
        if (start >= eidx)
                BUG();
@@ -316,7 +317,8 @@ void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned
        /*
         * Whoops, we cannot satisfy the allocation request.
         */
-       BUG();
+       printk(KERN_ALERT "bootmem alloc of %lu bytes failed!\n", size);
+       panic("Out of memory");
        return NULL;
 }
 
index 4fc772c..e01ffcc 100644 (file)
@@ -2456,12 +2456,13 @@ generic_file_write(struct file *file,const char *buf,size_t count,loff_t *ppos)
        unsigned long   written;
        long            status;
        int             err;
+       unsigned        bytes;
 
        cached_page = NULL;
 
        if (!access_ok(VERIFY_READ, buf, count))
                return -EFAULT;
-
+               
        down(&inode->i_sem);
 
        pos = *ppos;
@@ -2484,26 +2485,64 @@ generic_file_write(struct file *file,const char *buf,size_t count,loff_t *ppos)
         * Check whether we've reached the file size limit.
         */
        err = -EFBIG;
+       
        if (limit != RLIM_INFINITY) {
                if (pos >= limit) {
                        send_sig(SIGXFSZ, current, 0);
                        goto out;
                }
-               if (count > limit - pos) {
+               if (pos > 0xFFFFFFFFULL || count > limit - (u32)pos) {
+                       /* send_sig(SIGXFSZ, current, 0); */
+                       count = limit - (u32)pos;
+               }
+       }
+
+       /*
+        *      LFS rule 
+        */
+       if ( pos + count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) {
+               if (pos >= MAX_NON_LFS) {
                        send_sig(SIGXFSZ, current, 0);
-                       count = limit - pos;
+                       goto out;
+               }
+               if (count > MAX_NON_LFS - (u32)pos) {
+                       /* send_sig(SIGXFSZ, current, 0); */
+                       count = MAX_NON_LFS - (u32)pos;
                }
        }
 
-       status  = 0;
-       if (count) {
-               remove_suid(inode);
-               inode->i_ctime = inode->i_mtime = CURRENT_TIME;
-               mark_inode_dirty_sync(inode);
+       /*
+        *      Are we about to exceed the fs block limit ?
+        *
+        *      If we have written data it becomes a short write
+        *      If we have exceeded without writing data we send
+        *      a signal and give them an EFBIG.
+        *
+        *      Linus frestrict idea will clean these up nicely..
+        */
+        
+       if (pos > inode->i_sb->s_maxbytes)
+       {
+               send_sig(SIGXFSZ, current, 0);
+               err = -EFBIG;
+               goto out;       
        }
 
+       if (pos + count > inode->i_sb->s_maxbytes)
+               count = inode->i_sb->s_maxbytes - pos;
+
+       if (count == 0) {
+               err = 0;
+               goto out;
+       }
+
+       status  = 0;
+       remove_suid(inode);
+       inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+       mark_inode_dirty_sync(inode);
+
        while (count) {
-               unsigned long bytes, index, offset;
+               unsigned long index, offset;
                char *kaddr;
                int deactivate = 1;
 
index 7583931..bc5c71b 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -418,6 +418,8 @@ static inline unsigned long arch_get_unmapped_area(struct file *filp, unsigned l
                addr = vma->vm_end;
        }
 }
+#else
+extern unsigned long arch_get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 #endif 
 
 unsigned long get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags)
index fe2e538..90ecf12 100644 (file)
@@ -63,7 +63,7 @@ proc_dodebug(ctl_table *table, int write, struct file *file,
 {
        char            tmpbuf[20], *p, c;
        unsigned int    value;
-       int             left, len;
+       size_t          left, len;
 
        if ((file->f_pos && !write) || !*lenp) {
                *lenp = 0;