summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-24 00:12:35 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-24 00:12:35 +0000
commit482368b1a8e45430672c58c9a42e7d2004367126 (patch)
treece2a1a567d4d62dee7c2e71a46a99cf72cf1d606 /arch
parente4d0251c6f56ab2e191afb70f80f382793e23f74 (diff)
Merge with 2.3.47. Guys, this is buggy as shit. You've been warned.
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/kernel/Makefile2
-rw-r--r--arch/alpha/kernel/alpha_ksyms.c12
-rw-r--r--arch/alpha/kernel/core_mcpcia.c20
-rw-r--r--arch/alpha/kernel/core_polaris.c4
-rw-r--r--arch/alpha/kernel/core_pyxis.c105
-rw-r--r--arch/alpha/kernel/core_tsunami.c4
-rw-r--r--arch/alpha/kernel/entry.S2
-rw-r--r--arch/alpha/kernel/i8259.c95
-rw-r--r--arch/alpha/kernel/irq.c820
-rw-r--r--arch/alpha/kernel/irq_impl.h59
-rw-r--r--arch/alpha/kernel/pci.c6
-rw-r--r--arch/alpha/kernel/pci_iommu.c216
-rw-r--r--arch/alpha/kernel/process.c9
-rw-r--r--arch/alpha/kernel/proto.h11
-rw-r--r--arch/alpha/kernel/setup.c13
-rw-r--r--arch/alpha/kernel/smp.c32
-rw-r--r--arch/alpha/kernel/sys_alcor.c123
-rw-r--r--arch/alpha/kernel/sys_cabriolet.c105
-rw-r--r--arch/alpha/kernel/sys_dp264.c237
-rw-r--r--arch/alpha/kernel/sys_eb64p.c85
-rw-r--r--arch/alpha/kernel/sys_eiger.c93
-rw-r--r--arch/alpha/kernel/sys_jensen.c72
-rw-r--r--arch/alpha/kernel/sys_miata.c95
-rw-r--r--arch/alpha/kernel/sys_mikasa.c78
-rw-r--r--arch/alpha/kernel/sys_nautilus.c30
-rw-r--r--arch/alpha/kernel/sys_noritake.c102
-rw-r--r--arch/alpha/kernel/sys_rawhide.c109
-rw-r--r--arch/alpha/kernel/sys_ruffian.c188
-rw-r--r--arch/alpha/kernel/sys_rx164.c199
-rw-r--r--arch/alpha/kernel/sys_sable.c228
-rw-r--r--arch/alpha/kernel/sys_sio.c43
-rw-r--r--arch/alpha/kernel/sys_sx164.c109
-rw-r--r--arch/alpha/kernel/sys_takara.c91
-rw-r--r--arch/alpha/kernel/time.c76
-rw-r--r--arch/alpha/lib/csum_ipv6_magic.S2
-rw-r--r--arch/arm/kernel/armksyms.c7
-rw-r--r--arch/arm/kernel/entry-common.S51
-rw-r--r--arch/arm/kernel/irq.c12
-rw-r--r--arch/arm/kernel/semaphore.c171
-rw-r--r--arch/arm/mm/Makefile4
-rw-r--r--arch/arm/mm/consistent.c88
-rw-r--r--arch/arm/mm/init.c2
-rw-r--r--arch/arm/mm/proc-arm6,7.S6
-rw-r--r--arch/arm/mm/proc-sa110.S8
-rw-r--r--arch/arm/nwfpe/fpmodule.c36
-rw-r--r--arch/arm/nwfpe/fpsr.h10
-rw-r--r--arch/i386/boot/bootsect.S25
-rw-r--r--arch/i386/boot/setup.S11
-rw-r--r--arch/i386/config.in7
-rw-r--r--arch/i386/defconfig23
-rw-r--r--arch/i386/kernel/Makefile10
-rw-r--r--arch/i386/kernel/acpi.c1
-rw-r--r--arch/i386/kernel/apic.c2
-rw-r--r--arch/i386/kernel/apm.c416
-rw-r--r--arch/i386/kernel/i386_ksyms.c7
-rw-r--r--arch/i386/kernel/i8259.c4
-rw-r--r--arch/i386/kernel/io_apic.c51
-rw-r--r--arch/i386/kernel/irq.c1
-rw-r--r--arch/i386/kernel/microcode.c266
-rw-r--r--arch/i386/kernel/mpparse.c5
-rw-r--r--arch/i386/kernel/mtrr.c316
-rw-r--r--arch/i386/kernel/pci-dma.c18
-rw-r--r--arch/i386/kernel/pci-i386.c2
-rw-r--r--arch/i386/kernel/pci-pc.c81
-rw-r--r--arch/i386/kernel/process.c22
-rw-r--r--arch/i386/kernel/setup.c2
-rw-r--r--arch/i386/kernel/smp.c11
-rw-r--r--arch/i386/mm/init.c25
-rw-r--r--arch/ia64/config.in2
-rw-r--r--arch/ia64/ia32/ia32_entry.S2
-rw-r--r--arch/ia64/ia32/ia32_signal.c22
-rw-r--r--arch/ia64/ia32/sys_ia32.c57
-rw-r--r--arch/ia64/kernel/efi.c3
-rw-r--r--arch/ia64/kernel/entry.S33
-rw-r--r--arch/ia64/kernel/gate.S1
-rw-r--r--arch/ia64/kernel/head.S5
-rw-r--r--arch/ia64/kernel/irq.c18
-rw-r--r--arch/ia64/kernel/irq_lock.c2
-rw-r--r--arch/ia64/kernel/pci-dma.c15
-rw-r--r--arch/ia64/kernel/pci.c11
-rw-r--r--arch/ia64/kernel/smp.c8
-rw-r--r--arch/ia64/kernel/sys_ia64.c4
-rw-r--r--arch/ia64/lib/Makefile2
-rw-r--r--arch/ia64/tools/print_offsets.c1
-rw-r--r--arch/m68k/atari/joystick.c6
-rw-r--r--arch/m68k/atari/stram.c2
-rw-r--r--arch/m68k/config.in38
-rw-r--r--arch/m68k/kernel/Makefile2
-rw-r--r--arch/m68k/kernel/entry.S6
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c1
-rw-r--r--arch/m68k/mac/Makefile2
-rw-r--r--arch/m68k/mac/adb-bus.c2699
-rw-r--r--arch/m68k/mac/baboon.c124
-rw-r--r--arch/m68k/mac/config.c415
-rw-r--r--arch/m68k/mac/iop.c2
-rw-r--r--arch/m68k/mac/macints.c304
-rw-r--r--arch/m68k/mac/mackeyb.c762
-rw-r--r--arch/m68k/mac/misc.c689
-rw-r--r--arch/m68k/mac/oss.c38
-rw-r--r--arch/m68k/mac/psc.c16
-rw-r--r--arch/m68k/mac/via.c258
-rw-r--r--arch/m68k/mm/motorola.c2
-rw-r--r--arch/m68k/mm/sun3mmu.c2
-rw-r--r--arch/mips/config.in4
-rw-r--r--arch/mips/defconfig9
-rw-r--r--arch/mips/jazz/floppy-jazz.c21
-rw-r--r--arch/mips/kernel/mips_ksyms.c12
-rw-r--r--arch/mips/lib/floppy-std.c21
-rw-r--r--arch/mips/mm/Makefile4
-rw-r--r--arch/mips/mm/andes.c18
-rw-r--r--arch/mips/mm/loadmmu.c39
-rw-r--r--arch/mips/mm/r2300.c20
-rw-r--r--arch/mips/mm/r4xx0.c140
-rw-r--r--arch/mips/mm/r6000.c250
-rw-r--r--arch/mips/mm/tfp.c102
-rw-r--r--arch/mips/sni/dma.c20
-rw-r--r--arch/mips64/defconfig-ip2210
-rw-r--r--arch/mips64/kernel/mips64_ksyms.c12
-rw-r--r--arch/mips64/kernel/traps.c3
-rw-r--r--arch/mips64/mm/Makefile5
-rw-r--r--arch/mips64/mm/andes.c30
-rw-r--r--arch/mips64/mm/loadmmu.c46
-rw-r--r--arch/mips64/mm/r4xx0.c155
-rw-r--r--arch/mips64/mm/tfp.c157
-rw-r--r--arch/mips64/sgi-ip22/ip22-berr.c3
-rw-r--r--arch/ppc/coffboot/misc.S2
-rw-r--r--arch/ppc/config.in2
-rw-r--r--arch/ppc/configs/common_defconfig66
-rw-r--r--arch/ppc/configs/gemini_defconfig13
-rw-r--r--arch/ppc/defconfig66
-rw-r--r--arch/ppc/kernel/entry.S33
-rw-r--r--arch/ppc/kernel/head.S234
-rw-r--r--arch/ppc/kernel/irq.c23
-rw-r--r--arch/ppc/kernel/misc.S57
-rw-r--r--arch/ppc/kernel/mk_defs.c7
-rw-r--r--arch/ppc/kernel/open_pic.c6
-rw-r--r--arch/ppc/kernel/pci-dma.c18
-rw-r--r--arch/ppc/kernel/pmac_pic.c21
-rw-r--r--arch/ppc/kernel/pmac_setup.c5
-rw-r--r--arch/ppc/kernel/pmac_time.c4
-rw-r--r--arch/ppc/kernel/ppc_asm.h22
-rw-r--r--arch/ppc/kernel/ppc_asm.tmpl33
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c11
-rw-r--r--arch/ppc/kernel/process.c51
-rw-r--r--arch/ppc/kernel/prom.c63
-rw-r--r--arch/ppc/kernel/setup.c3
-rw-r--r--arch/ppc/kernel/smp.c1
-rw-r--r--arch/ppc/kernel/syscalls.c17
-rw-r--r--arch/ppc/kernel/traps.c42
-rw-r--r--arch/ppc/lib/string.S385
-rw-r--r--arch/ppc/mm/init.c4
-rw-r--r--arch/ppc/xmon/start.c61
-rw-r--r--arch/sparc/defconfig5
-rw-r--r--arch/sparc/kernel/ioport.c64
-rw-r--r--arch/sparc/kernel/pcic.c6
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c7
-rw-r--r--arch/sparc/kernel/sys_sparc.c97
-rw-r--r--arch/sparc/kernel/sys_sunos.c43
-rw-r--r--arch/sparc/kernel/systbls.S4
-rw-r--r--arch/sparc/lib/rwsem.S30
-rw-r--r--arch/sparc/mm/fault.c5
-rw-r--r--arch/sparc/mm/nosun4c.c7
-rw-r--r--arch/sparc/mm/srmmu.c15
-rw-r--r--arch/sparc/mm/sun4c.c16
-rw-r--r--arch/sparc/mm/swift.S6
-rw-r--r--arch/sparc64/config.in4
-rw-r--r--arch/sparc64/defconfig4
-rw-r--r--arch/sparc64/kernel/ioctl32.c1546
-rw-r--r--arch/sparc64/kernel/irq.c4
-rw-r--r--arch/sparc64/kernel/pci_iommu.c112
-rw-r--r--arch/sparc64/kernel/pci_psycho.c32
-rw-r--r--arch/sparc64/kernel/pci_sabre.c22
-rw-r--r--arch/sparc64/kernel/sbus.c57
-rw-r--r--arch/sparc64/kernel/smp.c4
-rw-r--r--arch/sparc64/kernel/sys_sparc.c114
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c38
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c18
-rw-r--r--arch/sparc64/kernel/systbls.S8
-rw-r--r--arch/sparc64/mm/ultra.S6
-rw-r--r--arch/sparc64/solaris/misc.c18
-rw-r--r--arch/sparc64/solaris/socksys.c14
181 files changed, 6958 insertions, 8409 deletions
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
index 7cf5dae80..fa9e06371 100644
--- a/arch/alpha/kernel/Makefile
+++ b/arch/alpha/kernel/Makefile
@@ -14,7 +14,7 @@
O_TARGET := kernel.o
O_OBJS := entry.o traps.o process.o osf_sys.o irq.o signal.o setup.o \
- ptrace.o time.o semaphore.o
+ ptrace.o time.o semaphore.o i8259.o
OX_OBJS := alpha_ksyms.o
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index 15c7afd8c..725dd4f51 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -36,6 +36,7 @@
extern struct hwrpb_struct *hwrpb;
extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
+extern spinlock_t kernel_flag;
/* these are C runtime functions with special calling conventions: */
extern void __divl (void);
@@ -51,6 +52,7 @@ EXPORT_SYMBOL(alpha_mv);
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(disable_irq_nosync);
+EXPORT_SYMBOL(probe_irq_mask);
EXPORT_SYMBOL(screen_info);
EXPORT_SYMBOL(perf_irq);
@@ -96,6 +98,13 @@ EXPORT_SYMBOL(__memset);
EXPORT_SYMBOL(__memsetw);
EXPORT_SYMBOL(__constant_c_memset);
+EXPORT_SYMBOL(pci_alloc_consistent);
+EXPORT_SYMBOL(pci_free_consistent);
+EXPORT_SYMBOL(pci_map_single);
+EXPORT_SYMBOL(pci_unmap_single);
+EXPORT_SYMBOL(pci_map_sg);
+EXPORT_SYMBOL(pci_unmap_sg);
+
EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(hwrpb);
@@ -158,13 +167,16 @@ EXPORT_SYMBOL_NOVERS(__rwsem_wake);
*/
#ifdef __SMP__
+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);
EXPORT_SYMBOL(__cpu_number_map);
+EXPORT_SYMBOL(smp_num_cpus);
EXPORT_SYMBOL(global_irq_holder);
EXPORT_SYMBOL(__global_cli);
EXPORT_SYMBOL(__global_sti);
diff --git a/arch/alpha/kernel/core_mcpcia.c b/arch/alpha/kernel/core_mcpcia.c
index 19ceb2241..ac97ce1fe 100644
--- a/arch/alpha/kernel/core_mcpcia.c
+++ b/arch/alpha/kernel/core_mcpcia.c
@@ -45,12 +45,6 @@
#define MCPCIA_MAX_HOSES 4
-/* Dodge has PCI0 and PCI1 at MID 4 and 5 respectively. Durango adds
- PCI2 and PCI3 at MID 6 and 7 respectively. */
-
-#define hose2mid(h) ((h) + 4)
-
-
/*
* Given a bus, device, and function number, compute resulting
* configuration space address and setup the MCPCIA_HAXR2 register
@@ -98,7 +92,7 @@ conf_read(unsigned long addr, unsigned char type1,
struct pci_controler *hose)
{
unsigned long flags;
- unsigned long mid = hose2mid(hose->index);
+ unsigned long mid = MCPCIA_HOSE2MID(hose->index);
unsigned int stat0, value, temp, cpu;
cpu = smp_processor_id();
@@ -146,7 +140,7 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1,
struct pci_controler *hose)
{
unsigned long flags;
- unsigned long mid = hose2mid(hose->index);
+ unsigned long mid = MCPCIA_HOSE2MID(hose->index);
unsigned int stat0, temp, cpu;
cpu = smp_processor_id();
@@ -297,7 +291,7 @@ void
mcpcia_pci_tbi(struct pci_controler *hose, dma_addr_t start, dma_addr_t end)
{
wmb();
- BUG();
+ *(vuip)MCPCIA_SG_TBIA(MCPCIA_HOSE2MID(hose->index)) = 0;
mb();
}
@@ -305,7 +299,7 @@ static int __init
mcpcia_probe_hose(int h)
{
int cpu = smp_processor_id();
- int mid = hose2mid(h);
+ int mid = MCPCIA_HOSE2MID(h);
unsigned int pci_rev;
/* Gotta be REAL careful. If hose is absent, we get an mcheck. */
@@ -340,7 +334,7 @@ mcpcia_new_hose(int h)
{
struct pci_controler *hose;
struct resource *io, *mem, *hae_mem;
- int mid = hose2mid(h);
+ int mid = MCPCIA_HOSE2MID(h);
hose = alloc_pci_controler();
io = alloc_resource();
@@ -387,7 +381,7 @@ mcpcia_pci_clr_err(int mid)
static void __init
mcpcia_startup_hose(struct pci_controler *hose)
{
- int mid = hose2mid(hose->index);
+ int mid = MCPCIA_HOSE2MID(hose->index);
unsigned int tmp;
mcpcia_pci_clr_err(mid);
@@ -578,7 +572,7 @@ mcpcia_machine_check(unsigned long vector, unsigned long la_ptr,
error was on? */
struct pci_controler *hose;
for (hose = hose_head; hose; hose = hose->next)
- mcpcia_pci_clr_err(hose2mid(hose->index));
+ mcpcia_pci_clr_err(MCPCIA_HOSE2MID(hose->index));
break;
}
case 1:
diff --git a/arch/alpha/kernel/core_polaris.c b/arch/alpha/kernel/core_polaris.c
index 0164a3e15..f76ac0654 100644
--- a/arch/alpha/kernel/core_polaris.c
+++ b/arch/alpha/kernel/core_polaris.c
@@ -107,7 +107,7 @@ polaris_read_config_word(struct pci_dev *dev, int where, u16 *value)
return PCIBIOS_SUCCESSFUL;
}
-static int
+int
polaris_read_config_dword(struct pci_dev *dev, int where, u32 *value)
{
unsigned long pci_addr;
@@ -150,7 +150,7 @@ polaris_write_config_word(struct pci_dev *dev, int where, u16 value)
return PCIBIOS_SUCCESSFUL;
}
-static int
+int
polaris_write_config_dword(struct pci_dev *dev, int where, u32 value)
{
unsigned long pci_addr;
diff --git a/arch/alpha/kernel/core_pyxis.c b/arch/alpha/kernel/core_pyxis.c
index cd81d5b91..80ee8ba7f 100644
--- a/arch/alpha/kernel/core_pyxis.c
+++ b/arch/alpha/kernel/core_pyxis.c
@@ -23,6 +23,7 @@
#include <asm/system.h>
#include "proto.h"
+#include "irq_impl.h"
#include "pci_impl.h"
@@ -286,6 +287,108 @@ struct pci_ops pyxis_pci_ops =
write_dword: pyxis_write_config_dword
};
+/* Note mask bit is true for ENABLED irqs. */
+static unsigned long cached_irq_mask;
+
+static inline void
+pyxis_update_irq_hw(unsigned long mask)
+{
+ *(vulp)PYXIS_INT_MASK = mask;
+ mb();
+ *(vulp)PYXIS_INT_MASK;
+}
+
+static inline void
+pyxis_enable_irq(unsigned int irq)
+{
+ pyxis_update_irq_hw(cached_irq_mask |= 1UL << (irq - 16));
+}
+
+static inline void
+pyxis_disable_irq(unsigned int irq)
+{
+ pyxis_update_irq_hw(cached_irq_mask &= ~(1UL << (irq - 16)));
+}
+
+static unsigned int
+pyxis_startup_irq(unsigned int irq)
+{
+ pyxis_enable_irq(irq);
+ return 0;
+}
+
+static void
+pyxis_mask_and_ack_irq(unsigned int irq)
+{
+ unsigned long bit = 1UL << (irq - 16);
+ unsigned long mask = cached_irq_mask &= ~bit;
+
+ /* Disable the interrupt. */
+ *(vulp)PYXIS_INT_MASK = mask;
+ wmb();
+ /* Ack PYXIS PCI interrupt. */
+ *(vulp)PYXIS_INT_REQ = bit;
+ mb();
+ /* Re-read to force both writes. */
+ *(vulp)PYXIS_INT_MASK;
+}
+
+static struct hw_interrupt_type pyxis_irq_type = {
+ typename: "PYXIS",
+ startup: pyxis_startup_irq,
+ shutdown: pyxis_disable_irq,
+ enable: pyxis_enable_irq,
+ disable: pyxis_disable_irq,
+ ack: pyxis_mask_and_ack_irq,
+ end: pyxis_enable_irq,
+};
+
+void
+pyxis_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
+ unsigned long pld;
+ unsigned int i;
+
+ /* Read the interrupt summary register of PYXIS */
+ pld = *(vulp)PYXIS_INT_REQ;
+ pld &= cached_irq_mask;
+
+ /*
+ * Now for every possible bit set, work through them and call
+ * the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+ if (i == 7)
+ isa_device_interrupt(vector, regs);
+ else
+ handle_irq(16+i, regs);
+ }
+}
+
+void __init
+init_pyxis_irqs(unsigned long ignore_mask)
+{
+ long i;
+
+ *(vulp)PYXIS_INT_MASK = 0; /* disable all */
+ *(vulp)PYXIS_INT_REQ = -1; /* flush all */
+ mb();
+
+ /* Send -INTA pulses to clear any pending interrupts ...*/
+ *(vuip) PYXIS_IACK_SC;
+
+ for (i = 16; i < 48; ++i) {
+ if ((ignore_mask >> i) & 1)
+ continue;
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].handler = &pyxis_irq_type;
+ }
+
+ setup_irq(16+7, &isa_cascade_irqaction);
+}
+
void
pyxis_pci_tbi(struct pci_controler *hose, dma_addr_t start, dma_addr_t end)
{
@@ -342,7 +445,7 @@ pyxis_broken_pci_tbi(struct pci_controler *hose,
__restore_flags(flags);
}
-static void
+static void __init
pyxis_enable_broken_tbi(struct pci_iommu_arena *arena)
{
void *page;
diff --git a/arch/alpha/kernel/core_tsunami.c b/arch/alpha/kernel/core_tsunami.c
index 0ad001b94..5fa112173 100644
--- a/arch/alpha/kernel/core_tsunami.c
+++ b/arch/alpha/kernel/core_tsunami.c
@@ -224,7 +224,7 @@ tsunami_pci_tbi(struct pci_controler *hose, dma_addr_t start, dma_addr_t end)
}
#ifdef NXM_MACHINE_CHECKS_ON_TSUNAMI
-static long
+static long __init
tsunami_probe_read(volatile unsigned long *vaddr)
{
long dont_care, probe_result;
@@ -246,7 +246,7 @@ tsunami_probe_read(volatile unsigned long *vaddr)
return probe_result;
}
-static long
+static long __init
tsunami_probe_write(volatile unsigned long *vaddr)
{
long true_contents, probe_result = 1;
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index cd8ce5c67..5f1a6f59a 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -573,7 +573,7 @@ entSys:
.align 3
ret_from_sys_call:
cmovne $26,0,$19 /* $19 = 0 => non-restartable */
- ldq $3,TASK_PROCESSOR($8)
+ ldl $3,TASK_PROCESSOR($8)
lda $4,softirq_state
sll $3,5,$3
addq $3,$4,$4
diff --git a/arch/alpha/kernel/i8259.c b/arch/alpha/kernel/i8259.c
new file mode 100644
index 000000000..ad545b98e
--- /dev/null
+++ b/arch/alpha/kernel/i8259.c
@@ -0,0 +1,95 @@
+/*
+ * linux/arch/alpha/kernel/i8259.c
+ *
+ * This is the 'legacy' 8259A Programmable Interrupt Controller,
+ * present in the majority of PC/AT boxes.
+ *
+ * Started hacking from linux-2.3.30pre6/arch/i386/kernel/i8259.c.
+ */
+
+#include <linux/init.h>
+#include <linux/cache.h>
+#include <linux/sched.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+
+#include "proto.h"
+#include "irq_impl.h"
+
+
+/* Note mask bit is true for DISABLED irqs. */
+static unsigned int cached_irq_mask = 0xffff;
+
+static inline void
+i8259_update_irq_hw(unsigned int irq, unsigned long mask)
+{
+ int port = 0x21;
+ if (irq & 8) mask >>= 8;
+ if (irq & 8) port = 0xA1;
+ outb(mask, port);
+}
+
+inline void
+i8259a_enable_irq(unsigned int irq)
+{
+ i8259_update_irq_hw(irq, cached_irq_mask &= ~(1 << irq));
+}
+
+inline void
+i8259a_disable_irq(unsigned int irq)
+{
+ i8259_update_irq_hw(irq, cached_irq_mask |= 1 << irq);
+}
+
+void
+i8259a_mask_and_ack_irq(unsigned int irq)
+{
+ i8259a_disable_irq(irq);
+
+ /* Ack the interrupt making it the lowest priority. */
+ if (irq >= 8) {
+ outb(0xE0 | (irq - 8), 0xa0); /* ack the slave */
+ irq = 2;
+ }
+ outb(0xE0 | irq, 0x20); /* ack the master */
+}
+
+unsigned int
+i8259a_startup_irq(unsigned int irq)
+{
+ i8259a_enable_irq(irq);
+ return 0; /* never anything pending */
+}
+
+struct hw_interrupt_type i8259a_irq_type = {
+ typename: "XT-PIC",
+ startup: i8259a_startup_irq,
+ shutdown: i8259a_disable_irq,
+ enable: i8259a_enable_irq,
+ disable: i8259a_disable_irq,
+ ack: i8259a_mask_and_ack_irq,
+ end: i8259a_enable_irq,
+};
+
+void __init
+init_i8259a_irqs(void)
+{
+ static struct irqaction cascade = {
+ handler: no_action,
+ name: "cascade",
+ };
+
+ long i;
+
+ outb(0xff, 0x21); /* mask all of 8259A-1 */
+ outb(0xff, 0xA1); /* mask all of 8259A-2 */
+
+ for (i = 0; i < 16; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].handler = &i8259a_irq_type;
+ }
+
+ setup_irq(2, &cascade);
+}
diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
index bae28a6a4..3d593acf3 100644
--- a/arch/alpha/kernel/irq.c
+++ b/arch/alpha/kernel/irq.c
@@ -17,32 +17,29 @@
#include <linux/kernel_stat.h>
#include <linux/signal.h>
#include <linux/sched.h>
-#include <linux/interrupt.h>
#include <linux/malloc.h>
#include <linux/random.h>
#include <linux/init.h>
#include <linux/delay.h>
-#include <linux/irq.h>
#include <asm/system.h>
#include <asm/io.h>
+#include <asm/dma.h>
#include <asm/bitops.h>
#include <asm/machvec.h>
#include "proto.h"
+#include "irq_impl.h"
#define vulp volatile unsigned long *
#define vuip volatile unsigned int *
/* Only uniprocessor needs this IRQ/BH locking depth, on SMP it lives
in the per-cpu structure for cache reasons. */
-#ifndef __SMP__
+#ifndef CONFIG_SMP
int __local_irq_count;
int __local_bh_count;
-#endif
-
-#if NR_IRQS > 128
-# error Unable to handle more than 128 irq levels.
+unsigned long __irq_attempt[NR_IRQS];
#endif
#ifdef CONFIG_ALPHA_GENERIC
@@ -51,39 +48,13 @@ int __local_bh_count;
#define ACTUAL_NR_IRQS NR_IRQS
#endif
-/* Reserved interrupts. These must NEVER be requested by any driver!
- IRQ 2 used by hw cascade */
-#define IS_RESERVED_IRQ(irq) ((irq)==2)
-
-
/*
- * Shadow-copy of masked interrupts.
+ * Performance counter hook. A module can override this to
+ * do something useful.
*/
-unsigned long _alpha_irq_masks[2] = { ~0UL, ~0UL };
-
-/*
- * The ack_irq routine used by 80% of the systems.
- */
-
-void
-common_ack_irq(unsigned long irq)
-{
- if (irq < 16) {
- /* Ack the interrupt making it the lowest priority */
- /* First the slave .. */
- if (irq > 7) {
- outb(0xE0 | (irq - 8), 0xa0);
- irq = 2;
- }
- /* .. then the master */
- outb(0xE0 | irq, 0x20);
- }
-}
-
-
-
-static void dummy_perf(unsigned long vector, struct pt_regs *regs)
+static void
+dummy_perf(unsigned long vector, struct pt_regs *regs)
{
printk(KERN_CRIT "Performance counter interrupt!\n");
}
@@ -94,7 +65,9 @@ void (*perf_irq)(unsigned long, struct pt_regs *) = dummy_perf;
* Dispatch device interrupts.
*/
-/* Handle ISA interrupt via the PICs. */
+/*
+ * Handle ISA interrupt via the PICs.
+ */
#if defined(CONFIG_ALPHA_GENERIC)
# define IACK_SC alpha_mv.iack_sc
@@ -112,15 +85,12 @@ void (*perf_irq)(unsigned long, struct pt_regs *) = dummy_perf;
# define IACK_SC POLARIS_IACK_SC
#elif defined(CONFIG_ALPHA_IRONGATE)
# define IACK_SC IRONGATE_IACK_SC
-#else
- /* This is bogus but necessary to get it to compile on all platforms. */
-# define IACK_SC 1L
#endif
+#if defined(IACK_SC)
void
-isa_device_interrupt(unsigned long vector, struct pt_regs * regs)
+isa_device_interrupt(unsigned long vector, struct pt_regs *regs)
{
-#if 1
/*
* Generate a PCI interrupt acknowledge cycle. The PIC will
* respond with the interrupt vector of the highest priority
@@ -135,8 +105,13 @@ isa_device_interrupt(unsigned long vector, struct pt_regs * regs)
return;
}
}
- handle_irq(j, j, regs);
-#else
+ handle_irq(j, regs);
+}
+#endif
+#if defined(CONFIG_ALPHA_GENERIC) || !defined(IACK_SC)
+void
+isa_no_iack_sc_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
unsigned long pic;
/*
@@ -153,131 +128,341 @@ isa_device_interrupt(unsigned long vector, struct pt_regs * regs)
* write only. This is not true.
*/
pic = inb(0x20) | (inb(0xA0) << 8); /* read isr */
- pic &= ~alpha_irq_mask; /* apply mask */
pic &= 0xFFFB; /* mask out cascade & hibits */
while (pic) {
int j = ffz(~pic);
pic &= pic - 1;
- handle_irq(j, j, regs);
+ handle_irq(j, regs);
}
+}
#endif
+
+/*
+ * Handle interrupts from the SRM, assuming no additional weirdness.
+ */
+
+static inline void
+srm_enable_irq(unsigned int irq)
+{
+ cserve_ena(irq - 16);
+}
+
+static void
+srm_disable_irq(unsigned int irq)
+{
+ cserve_dis(irq - 16);
}
-/* Handle interrupts from the SRM, assuming no additional weirdness. */
+static unsigned int
+srm_startup_irq(unsigned int irq)
+{
+ srm_enable_irq(irq);
+ return 0;
+}
+
+static struct hw_interrupt_type srm_irq_type = {
+ typename: "SRM",
+ startup: srm_startup_irq,
+ shutdown: srm_disable_irq,
+ enable: srm_enable_irq,
+ disable: srm_disable_irq,
+ ack: srm_disable_irq,
+ end: srm_enable_irq,
+};
void
srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
- int irq, ack;
+ int irq = (vector - 0x800) >> 4;
+ handle_irq(irq, regs);
+}
- ack = irq = (vector - 0x800) >> 4;
- handle_irq(irq, ack, regs);
+void __init
+init_srm_irqs(long max, unsigned long ignore_mask)
+{
+ long i;
+
+ for (i = 16; i < max; ++i) {
+ if (i < 64 && ((ignore_mask >> i) & 1))
+ continue;
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].handler = &srm_irq_type;
+ }
}
+/*
+ * The not-handled irq handler.
+ */
+
+static void
+noirq_enable_disable(unsigned int irq)
+{
+}
+
+static unsigned int
+noirq_startup(unsigned int irq)
+{
+ return 0;
+}
+
+static void
+noirq_ack(unsigned int irq)
+{
+ printk(KERN_CRIT "Unexpected IRQ %u\n", irq);
+}
+
+static struct hw_interrupt_type no_irq_type = {
+ typename: "none",
+ startup: noirq_startup,
+ shutdown: noirq_enable_disable,
+ enable: noirq_enable_disable,
+ disable: noirq_enable_disable,
+ ack: noirq_ack,
+ end: noirq_enable_disable,
+};
/*
- * Initial irq handlers.
+ * The special RTC interrupt type. The interrupt itself was
+ * processed by PALcode, and comes in via entInt vector 1.
*/
-static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL};
-spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED;
-irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { [0 ... NR_IRQS-1] = {0,} };
+static struct hw_interrupt_type rtc_irq_type = {
+ typename: "RTC",
+ startup: noirq_startup,
+ shutdown: noirq_enable_disable,
+ enable: noirq_enable_disable,
+ disable: noirq_enable_disable,
+ ack: noirq_enable_disable,
+ end: noirq_enable_disable,
+};
+void __init
+init_rtc_irq(void)
+{
+ irq_desc[RTC_IRQ].status = IRQ_DISABLED;
+ irq_desc[RTC_IRQ].handler = &rtc_irq_type;
+}
-static inline void
-mask_irq(unsigned long irq)
+/*
+ * Special irq handlers.
+ */
+
+void
+no_action(int cpl, void *dev_id, struct pt_regs *regs)
{
- set_bit(irq, _alpha_irq_masks);
- alpha_mv.update_irq_hw(irq, alpha_irq_mask, 0);
}
-static inline void
-unmask_irq(unsigned long irq)
+/*
+ * Common irq handlers.
+ */
+
+struct irqaction isa_cascade_irqaction = {
+ handler: no_action,
+ name: "isa-cascade"
+};
+
+struct irqaction timer_cascade_irqaction = {
+ handler: no_action,
+ name: "timer-cascade"
+};
+
+struct irqaction halt_switch_irqaction = {
+ handler: no_action,
+ name: "halt-switch"
+};
+
+
+spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED;
+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = {
+ [0 ... NR_IRQS-1] = { 0, &no_irq_type, }
+};
+
+int
+handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
+ struct irqaction *action)
{
- clear_bit(irq, _alpha_irq_masks);
- alpha_mv.update_irq_hw(irq, alpha_irq_mask, 1);
+ int status, cpu = smp_processor_id();
+ unsigned long ipl;
+
+ kstat.irqs[cpu][irq]++;
+ irq_enter(cpu, irq);
+
+ status = 1; /* Force the "do bottom halves" bit */
+ ipl = rdps() & 7;
+
+ do {
+ unsigned long newipl = (action->flags & SA_INTERRUPT ? 7 : 0);
+ if (newipl != ipl) {
+ swpipl(newipl);
+ ipl = newipl;
+ }
+
+ status |= action->flags;
+ action->handler(irq, action->dev_id, regs);
+ action = action->next;
+ } while (action);
+ if (status & SA_SAMPLE_RANDOM)
+ add_interrupt_randomness(irq);
+ if (ipl == 0)
+ __cli();
+
+ irq_exit(cpu, irq);
+
+ return status;
}
+/*
+ * Generic enable/disable code: this just calls
+ * down into the PIC-specific version for the actual
+ * hardware disable after having gotten the irq
+ * controller lock.
+ */
void
-disable_irq_nosync(unsigned int irq_nr)
+disable_irq_nosync(unsigned int irq)
{
unsigned long flags;
- save_and_cli(flags);
- mask_irq(irq_nr);
- restore_flags(flags);
+ spin_lock_irqsave(&irq_controller_lock, flags);
+ if (!irq_desc[irq].depth++) {
+ irq_desc[irq].status |= IRQ_DISABLED;
+ irq_desc[irq].handler->disable(irq);
+ }
+ spin_unlock_irqrestore(&irq_controller_lock, flags);
}
+/*
+ * Synchronous version of the above, making sure the IRQ is
+ * no longer running on any other IRQ..
+ */
void
-disable_irq(unsigned int irq_nr)
+disable_irq(unsigned int irq)
{
- /* This works non-SMP, and SMP until we write code to distribute
- interrupts to more that cpu 0. */
- disable_irq_nosync(irq_nr);
+ disable_irq_nosync(irq);
+
+ if (!local_irq_count(smp_processor_id())) {
+ do {
+ barrier();
+ } while (irq_desc[irq].status & IRQ_INPROGRESS);
+ }
}
void
-enable_irq(unsigned int irq_nr)
+enable_irq(unsigned int irq)
{
unsigned long flags;
- save_and_cli(flags);
- unmask_irq(irq_nr);
- restore_flags(flags);
+ spin_lock_irqsave(&irq_controller_lock, flags);
+ switch (irq_desc[irq].depth) {
+ case 1:
+ {
+ unsigned int status = irq_desc[irq].status & ~IRQ_DISABLED;
+ irq_desc[irq].status = status;
+ if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
+ irq_desc[irq].status = status | IRQ_REPLAY;
+
+ /* ??? We can't re-send on (most?) alpha hw.
+ hw_resend_irq(irq_desc[irq].handler,irq); */
+ }
+ irq_desc[irq].handler->enable(irq);
+ /* fall-through */
+ }
+ default:
+ irq_desc[irq].depth--;
+ break;
+ case 0:
+ printk(KERN_ERR "enable_irq() unbalanced from %p\n",
+ __builtin_return_address(0));
+ }
+ spin_unlock_irqrestore(&irq_controller_lock, flags);
}
int
-check_irq(unsigned int irq)
+setup_irq(unsigned int irq, struct irqaction * new)
{
- return irq_desc[irq].action ? -EBUSY : 0;
+ int shared = 0;
+ struct irqaction *old, **p;
+ unsigned long flags;
+
+ /*
+ * Some drivers like serial.c use request_irq() heavily,
+ * so we have to be careful not to interfere with a
+ * running system.
+ */
+ if (new->flags & SA_SAMPLE_RANDOM) {
+ /*
+ * This function might sleep, we want to call it first,
+ * outside of the atomic block.
+ * Yes, this might clear the entropy pool if the wrong
+ * driver is attempted to be loaded, without actually
+ * installing a new handler, but is this really a problem,
+ * only the sysadmin is able to do this.
+ */
+ rand_initialize_irq(irq);
+ }
+
+ /*
+ * The following block of code has to be executed atomically
+ */
+ spin_lock_irqsave(&irq_controller_lock,flags);
+ p = &irq_desc[irq].action;
+ if ((old = *p) != NULL) {
+ /* Can't share interrupts unless both agree to */
+ if (!(old->flags & new->flags & SA_SHIRQ)) {
+ spin_unlock_irqrestore(&irq_controller_lock,flags);
+ return -EBUSY;
+ }
+
+ /* add new interrupt at end of irq queue */
+ do {
+ p = &old->next;
+ old = *p;
+ } while (old);
+ shared = 1;
+ }
+
+ *p = new;
+
+ if (!shared) {
+ irq_desc[irq].depth = 0;
+ irq_desc[irq].status &= ~IRQ_DISABLED;
+ irq_desc[irq].handler->startup(irq);
+ }
+ spin_unlock_irqrestore(&irq_controller_lock,flags);
+ return 0;
}
int
request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags, const char * devname, void *dev_id)
{
- int shared = 0;
- struct irqaction * action, **p;
- unsigned long flags;
+ int retval;
+ struct irqaction * action;
if (irq >= ACTUAL_NR_IRQS)
return -EINVAL;
- if (IS_RESERVED_IRQ(irq))
- return -EINVAL;
if (!handler)
return -EINVAL;
- p = &irq_desc[irq].action;
- action = *p;
- if (action) {
- /* Can't share interrupts unless both agree to */
- if (!(action->flags & irqflags & SA_SHIRQ))
- return -EBUSY;
-
- /* Can't share interrupts unless both are same type */
- if ((action->flags ^ irqflags) & SA_INTERRUPT)
- return -EBUSY;
-
- /* Add new interrupt at end of irq queue */
- do {
- p = &action->next;
- action = *p;
- } while (action);
- shared = 1;
+#if 1
+ /*
+ * Sanity-check: shared interrupts should REALLY pass in
+ * a real dev-ID, otherwise we'll have trouble later trying
+ * to figure out which interrupt is which (messes up the
+ * interrupt freeing logic etc).
+ */
+ if ((irqflags & SA_SHIRQ) && !dev_id) {
+ printk(KERN_ERR
+ "Bad boy: %s (at %p) called us without a dev_id!\n",
+ devname, __builtin_return_address(0));
}
+#endif
- action = &timer_irq;
- if (irq != TIMER_IRQ) {
- action = (struct irqaction *)
+ action = (struct irqaction *)
kmalloc(sizeof(struct irqaction), GFP_KERNEL);
- }
if (!action)
return -ENOMEM;
- if (irqflags & SA_SAMPLE_RANDOM)
- rand_initialize_irq(irq);
-
action->handler = handler;
action->flags = irqflags;
action->mask = 0;
@@ -285,56 +470,66 @@ request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
action->next = NULL;
action->dev_id = dev_id;
- save_and_cli(flags);
- *p = action;
-
- if (!shared)
- unmask_irq(irq);
-
- restore_flags(flags);
- return 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;
+ struct irqaction **p;
unsigned long flags;
if (irq >= ACTUAL_NR_IRQS) {
- printk("Trying to free IRQ%d\n",irq);
- return;
- }
- if (IS_RESERVED_IRQ(irq)) {
- printk("Trying to free reserved IRQ %d\n", irq);
+ printk(KERN_CRIT "Trying to free IRQ%d\n", irq);
return;
}
- for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next) {
- if (action->dev_id != dev_id)
- continue;
- /* Found it - now free it */
- save_and_cli(flags);
- *p = action->next;
- if (!irq_desc[irq].action)
- mask_irq(irq);
- restore_flags(flags);
- kfree(action);
+ spin_lock_irqsave(&irq_controller_lock,flags);
+ p = &irq_desc[irq].action;
+ for (;;) {
+ struct irqaction * action = *p;
+ if (action) {
+ struct irqaction **pp = p;
+ p = &action->next;
+ if (action->dev_id != dev_id)
+ continue;
+
+ /* Found - now remove it from the list of entries. */
+ *pp = action->next;
+ if (!irq_desc[irq].action) {
+ irq_desc[irq].status |= IRQ_DISABLED;
+ irq_desc[irq].handler->shutdown(irq);
+ }
+ spin_unlock_irqrestore(&irq_controller_lock,flags);
+
+ /* Wait to make sure it's not being used on
+ another CPU. */
+ while (irq_desc[irq].status & IRQ_INPROGRESS)
+ barrier();
+ kfree(action);
+ return;
+ }
+ printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
+ spin_unlock_irqrestore(&irq_controller_lock,flags);
return;
}
- printk("Trying to free free IRQ%d\n",irq);
}
int get_irq_list(char *buf)
{
- int i;
+ int i, j;
struct irqaction * action;
char *p = buf;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
p += sprintf(p, " ");
for (i = 0; i < smp_num_cpus; i++)
p += sprintf(p, "CPU%d ", i);
+ for (i = 0; i < smp_num_cpus; i++)
+ p += sprintf(p, "TRY%d ", i);
*p++ = '\n';
#endif
@@ -343,16 +538,17 @@ int get_irq_list(char *buf)
if (!action)
continue;
p += sprintf(p, "%3d: ",i);
-#ifndef __SMP__
+#ifndef CONFIG_SMP
p += sprintf(p, "%10u ", kstat_irqs(i));
#else
- {
- int j;
- for (j = 0; j < smp_num_cpus; j++)
- p += sprintf(p, "%10u ",
- kstat.irqs[cpu_logical_map(j)][i]);
- }
+ for (j = 0; j < smp_num_cpus; j++)
+ p += sprintf(p, "%10u ",
+ kstat.irqs[cpu_logical_map(j)][i]);
+ for (j = 0; j < smp_num_cpus; j++)
+ p += sprintf(p, "%10lu ",
+ irq_attempt(cpu_logical_map(j), i));
#endif
+ p += sprintf(p, " %14s", irq_desc[i].handler->typename);
p += sprintf(p, " %c%s",
(action->flags & SA_INTERRUPT)?'+':' ',
action->name);
@@ -364,10 +560,17 @@ int get_irq_list(char *buf)
}
*p++ = '\n';
}
+#if CONFIG_SMP
+ p += sprintf(p, "LOC: ");
+ for (j = 0; j < smp_num_cpus; j++)
+ p += sprintf(p, "%10lu ",
+ cpu_data[cpu_logical_map(j)].smp_local_irq_count);
+ p += sprintf(p, "\n");
+#endif
return p - buf;
}
-#ifdef __SMP__
+#ifdef CONFIG_SMP
/* Who has global_irq_lock. */
int global_irq_holder = NO_PROC_ID;
@@ -527,7 +730,7 @@ __global_restore_flags(unsigned long flags)
__sti();
break;
default:
- printk("global_restore_flags: %08lx (%p)\n",
+ printk(KERN_ERR "global_restore_flags: %08lx (%p)\n",
flags, __builtin_return_address(0));
}
}
@@ -603,141 +806,195 @@ synchronize_irq(void)
}
#endif
}
-#endif /* __SMP__ */
-
-static void
-unexpected_irq(int irq, struct pt_regs * regs)
-{
-#if 0
-#if 1
- printk("device_interrupt: unexpected interrupt %d\n", irq);
-#else
- struct irqaction *action;
- int i;
-
- printk("IO device interrupt, irq = %d\n", irq);
- printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
- printk("Expecting: ");
- for (i = 0; i < ACTUAL_NR_IRQS; i++)
- if ((action = irq_desc[i].action))
- while (action->handler) {
- printk("[%s:%d] ", action->name, i);
- action = action->next;
- }
- printk("\n");
-#endif
-#endif
-
-#if defined(CONFIG_ALPHA_JENSEN)
- /* ??? Is all this just debugging, or are the inb's and outb's
- necessary to make things work? */
- printk("64=%02x, 60=%02x, 3fa=%02x 2fa=%02x\n",
- inb(0x64), inb(0x60), inb(0x3fa), inb(0x2fa));
- outb(0x0c, 0x3fc);
- outb(0x0c, 0x2fc);
- outb(0,0x61);
- outb(0,0x461);
-#endif
-}
+#endif /* CONFIG_SMP */
+/*
+ * do_IRQ handles all normal device IRQ's (the special
+ * SMP cross-CPU interrupts have their own specific
+ * handlers).
+ */
void
-handle_irq(int irq, int ack, struct pt_regs * regs)
-{
- struct irqaction * action;
+handle_irq(int irq, struct pt_regs * regs)
+{
+ /*
+ * We ack quickly, we don't want the irq controller
+ * thinking we're snobs just because some other CPU has
+ * disabled global interrupts (we have already done the
+ * INT_ACK cycles, it's too late to try to pretend to the
+ * controller that we aren't taking the interrupt).
+ *
+ * 0 return value means that this irq is already being
+ * handled by some other CPU. (or is disabled)
+ */
int cpu = smp_processor_id();
+ irq_desc_t *desc;
+ struct irqaction * action;
+ unsigned int status;
if ((unsigned) irq > ACTUAL_NR_IRQS) {
- printk("device_interrupt: illegal interrupt %d\n", irq);
+ printk(KERN_CRIT "device_interrupt: illegal interrupt %d\n",
+ irq);
return;
}
-#if 0
- /* A useful bit of code to find out if an interrupt is going wild. */
- {
- static unsigned int last_msg, last_cc;
- static int last_irq, count;
- unsigned int cc;
-
- __asm __volatile("rpcc %0" : "=r"(cc));
- ++count;
- if (cc - last_msg > 150000000 || irq != last_irq) {
- printk("handle_irq: irq %d count %d cc %u @ %p\n",
- irq, count, cc-last_cc, regs->pc);
- count = 0;
- last_msg = cc;
- last_irq = irq;
- }
- last_cc = cc;
- }
-#endif
+ irq_attempt(cpu, irq)++;
+ desc = irq_desc + irq;
+ spin_lock_irq(&irq_controller_lock); /* mask also the RTC */
+ desc->handler->ack(irq);
- irq_enter(cpu, irq);
- kstat.irqs[cpu][irq] += 1;
- action = irq_desc[irq].action;
+ /*
+ * REPLAY is when Linux resends an IRQ that was dropped earlier.
+ * WAITING is used by probe to mark irqs that are being tested.
+ */
+ status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
+ status |= IRQ_PENDING; /* we _want_ to handle it */
/*
- * For normal interrupts, we mask it out, and then ACK it.
- * This way another (more timing-critical) interrupt can
- * come through while we're doing this one.
- *
- * Note! An irq without a handler gets masked and acked, but
- * never unmasked. The autoirq stuff depends on this (it looks
- * at the masks before and after doing the probing).
+ * If the IRQ is disabled for whatever reason, we cannot
+ * use the action we have.
*/
- if (ack >= 0) {
- mask_irq(ack);
- alpha_mv.ack_irq(ack);
+ action = NULL;
+ if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+ action = desc->action;
+ status &= ~IRQ_PENDING; /* we commit to handling */
+ status |= IRQ_INPROGRESS; /* we are handling it */
}
- if (action) {
- if (action->flags & SA_SAMPLE_RANDOM)
- add_interrupt_randomness(irq);
- do {
- action->handler(irq, action->dev_id, regs);
- action = action->next;
- } while (action);
- if (ack >= 0)
- unmask_irq(ack);
- } else {
- unexpected_irq(irq, regs);
+ desc->status = status;
+ spin_unlock(&irq_controller_lock);
+
+ /*
+ * If there is no IRQ handler or it was disabled, exit early.
+ * Since we set PENDING, if another processor is handling
+ * a different instance of this same irq, the other processor
+ * will take care of it.
+ */
+ if (!action)
+ return;
+
+ /*
+ * Edge triggered interrupts need to remember pending events.
+ * This applies to any hw interrupts that allow a second
+ * instance of the same irq to arrive while we are in do_IRQ
+ * or in the handler. But the code here only handles the _second_
+ * instance of the irq, not the third or fourth. So it is mostly
+ * useful for irq hardware that does not mask cleanly in an
+ * SMP environment.
+ */
+ for (;;) {
+ handle_IRQ_event(irq, regs, action);
+ spin_lock(&irq_controller_lock);
+
+ if (!(desc->status & IRQ_PENDING)
+ || (desc->status & IRQ_LEVEL))
+ break;
+ desc->status &= ~IRQ_PENDING;
+ spin_unlock(&irq_controller_lock);
}
- irq_exit(cpu, irq);
+ desc->status &= ~IRQ_INPROGRESS;
+ if (!(desc->status & IRQ_DISABLED))
+ desc->handler->end(irq);
+ spin_unlock(&irq_controller_lock);
}
-
/*
- * Start listening for interrupts..
+ * IRQ autodetection code..
+ *
+ * This depends on the fact that any interrupt that
+ * comes in on to an unassigned handler will get stuck
+ * with "IRQ_WAITING" cleared and the interrupt
+ * disabled.
*/
-
unsigned long
probe_irq_on(void)
{
- struct irqaction * action;
- unsigned long irqs = 0;
+ int i;
unsigned long delay;
- unsigned int i;
-
- /* Handle only the first 64 IRQs here. This is enough for
- [E]ISA, which is the only thing that needs probing anyway. */
- for (i = (ACTUAL_NR_IRQS - 1) & 63; i > 0; i--) {
- if (!(PROBE_MASK & (1UL << i))) {
- continue;
- }
- action = irq_desc[i].action;
- if (!action) {
- enable_irq(i);
- irqs |= (1UL << i);
+ unsigned long val;
+
+ /* Something may have generated an irq long ago and we want to
+ flush such a longstanding irq before considering it as spurious. */
+ spin_lock_irq(&irq_controller_lock);
+ for (i = NR_IRQS-1; i >= 0; i--)
+ if (!irq_desc[i].action)
+ if(irq_desc[i].handler->startup(i))
+ irq_desc[i].status |= IRQ_PENDING;
+ spin_unlock_irq(&irq_controller_lock);
+
+ /* Wait for longstanding interrupts to trigger. */
+ for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
+ /* about 20ms delay */ synchronize_irq();
+
+ /* enable any unassigned irqs (we must startup again here because
+ if a longstanding irq happened in the previous stage, it may have
+ masked itself) first, enable any unassigned irqs. */
+ spin_lock_irq(&irq_controller_lock);
+ for (i = NR_IRQS-1; i >= 0; i--) {
+ if (!irq_desc[i].action) {
+ irq_desc[i].status |= IRQ_AUTODETECT | IRQ_WAITING;
+ if(irq_desc[i].handler->startup(i))
+ irq_desc[i].status |= IRQ_PENDING;
}
}
+ spin_unlock_irq(&irq_controller_lock);
+
+ /*
+ * Wait for spurious interrupts to trigger
+ */
+ for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
+ /* about 100ms delay */ synchronize_irq();
/*
- * Wait about 100ms for spurious interrupts to mask themselves
- * out again...
+ * Now filter out any obviously spurious interrupts
*/
- for (delay = jiffies + HZ/10; time_before(jiffies, delay); )
- barrier();
+ val = 0;
+ spin_lock_irq(&irq_controller_lock);
+ for (i=0; i<NR_IRQS; i++) {
+ unsigned int status = irq_desc[i].status;
- /* Now filter out any obviously spurious interrupts. */
- return irqs & ~alpha_irq_mask;
+ if (!(status & IRQ_AUTODETECT))
+ continue;
+
+ /* It triggered already - consider it spurious. */
+ if (!(status & IRQ_WAITING)) {
+ irq_desc[i].status = status & ~IRQ_AUTODETECT;
+ irq_desc[i].handler->shutdown(i);
+ continue;
+ }
+
+ if (i < 64)
+ val |= 1 << i;
+ }
+ spin_unlock_irq(&irq_controller_lock);
+
+ return val;
+}
+
+/*
+ * Return a mask of triggered interrupts (this
+ * can handle only legacy ISA interrupts).
+ */
+unsigned int probe_irq_mask(unsigned long val)
+{
+ int i;
+ unsigned int mask;
+
+ mask = 0;
+ spin_lock_irq(&irq_controller_lock);
+ for (i = 0; i < 16; i++) {
+ unsigned int status = irq_desc[i].status;
+
+ if (!(status & IRQ_AUTODETECT))
+ continue;
+
+ if (!(status & IRQ_WAITING))
+ mask |= 1 << i;
+
+ irq_desc[i].status = status & ~IRQ_AUTODETECT;
+ irq_desc[i].handler->shutdown(i);
+ }
+ spin_unlock_irq(&irq_controller_lock);
+
+ return mask & val;
}
/*
@@ -747,19 +1004,32 @@ probe_irq_on(void)
*/
int
-probe_irq_off(unsigned long irqs)
+probe_irq_off(unsigned long val)
{
- int i;
-
- /* Handle only the first 64 IRQs here. This is enough for
- [E]ISA, which is the only thing that needs probing anyway. */
- irqs &= alpha_irq_mask;
- if (!irqs)
- return 0;
- i = ffz(~irqs);
- if (irqs != (1UL << i))
- i = -i;
- return i;
+ int i, irq_found, nr_irqs;
+
+ nr_irqs = 0;
+ irq_found = 0;
+ spin_lock_irq(&irq_controller_lock);
+ for (i=0; i<NR_IRQS; i++) {
+ unsigned int status = irq_desc[i].status;
+
+ if (!(status & IRQ_AUTODETECT))
+ continue;
+
+ if (!(status & IRQ_WAITING)) {
+ if (!nr_irqs)
+ irq_found = i;
+ nr_irqs++;
+ }
+ irq_desc[i].status = status & ~IRQ_AUTODETECT;
+ irq_desc[i].handler->shutdown(i);
+ }
+ spin_unlock_irq(&irq_controller_lock);
+
+ if (nr_irqs > 1)
+ irq_found = -irq_found;
+ return irq_found;
}
@@ -774,15 +1044,21 @@ do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
{
switch (type) {
case 0:
-#ifdef __SMP__
+#ifdef CONFIG_SMP
handle_ipi(&regs);
return;
#else
- printk("Interprocessor interrupt? You must be kidding\n");
+ printk(KERN_CRIT "Interprocessor interrupt? "
+ "You must be kidding!\n");
#endif
break;
case 1:
- handle_irq(RTC_IRQ, -1, &regs);
+#ifdef CONFIG_SMP
+ cpu_data[smp_processor_id()].smp_local_irq_count++;
+ smp_percpu_timer_interrupt(&regs);
+ if (smp_processor_id() == smp_boot_cpuid)
+#endif
+ handle_irq(RTC_IRQ, &regs);
return;
case 2:
alpha_mv.machine_check(vector, la_ptr, &regs);
@@ -794,12 +1070,22 @@ do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
perf_irq(vector, &regs);
return;
default:
- printk("Hardware intr %ld %lx? Huh?\n", type, vector);
+ printk(KERN_CRIT "Hardware intr %ld %lx? Huh?\n",
+ type, vector);
}
printk("PC = %016lx PS=%04lx\n", regs.pc, regs.ps);
}
void __init
+common_init_isa_dma(void)
+{
+ outb(0, DMA1_RESET_REG);
+ outb(0, DMA2_RESET_REG);
+ outb(0, DMA1_CLR_MASK_REG);
+ outb(0, DMA2_CLR_MASK_REG);
+}
+
+void __init
init_IRQ(void)
{
wrent(entInt, 0);
@@ -817,7 +1103,7 @@ init_IRQ(void)
#define MCHK_K_OS_BUGCHECK 0x008A
#define MCHK_K_PAL_BUGCHECK 0x0090
-#ifndef __SMP__
+#ifndef CONFIG_SMP
struct mcheck_info __mcheck_info;
#endif
diff --git a/arch/alpha/kernel/irq_impl.h b/arch/alpha/kernel/irq_impl.h
new file mode 100644
index 000000000..ff8067a00
--- /dev/null
+++ b/arch/alpha/kernel/irq_impl.h
@@ -0,0 +1,59 @@
+/*
+ * linux/arch/alpha/kernel/irq_impl.h
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Copyright (C) 1998, 2000 Richard Henderson
+ *
+ * This file contains declarations and inline functions for interfacing
+ * with the IRQ handling routines in irq.c.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+
+#define RTC_IRQ 8
+
+extern void isa_device_interrupt(unsigned long, struct pt_regs *);
+extern void isa_no_iack_sc_device_interrupt(unsigned long, struct pt_regs *);
+extern void srm_device_interrupt(unsigned long, struct pt_regs *);
+extern void pyxis_device_interrupt(unsigned long, struct pt_regs *);
+
+extern struct irqaction isa_cascade_irqaction;
+extern struct irqaction timer_cascade_irqaction;
+extern struct irqaction halt_switch_irqaction;
+
+extern void init_srm_irqs(long, unsigned long);
+extern void init_pyxis_irqs(unsigned long);
+extern void init_rtc_irq(void);
+
+extern void common_init_isa_dma(void);
+
+extern void i8259a_enable_irq(unsigned int);
+extern void i8259a_disable_irq(unsigned int);
+extern void i8259a_mask_and_ack_irq(unsigned int);
+extern unsigned int i8259a_startup_irq(unsigned int);
+extern struct hw_interrupt_type i8259a_irq_type;
+extern void init_i8259a_irqs(void);
+
+extern void no_action(int cpl, void *dev_id, struct pt_regs *regs);
+extern void handle_irq(int irq, struct pt_regs * regs);
+
+static inline void
+alpha_do_profile(unsigned long pc)
+{
+ if (prof_buffer && current->pid) {
+ extern char _stext;
+
+ pc -= (unsigned long) &_stext;
+ pc >>= prof_shift;
+ /*
+ * Don't ignore out-of-bounds PC values silently,
+ * put them into the last histogram slot, so if
+ * present, they will show up as a sharp peak.
+ */
+ if (pc > prof_len - 1)
+ pc = prof_len - 1;
+ atomic_inc((atomic_t *)&prof_buffer[pc]);
+ }
+}
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index b62179b8d..12e3f0df9 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -109,7 +109,7 @@ struct pci_fixup pcibios_fixups[] __initdata = {
void
pcibios_align_resource(void *data, struct resource *res, unsigned long size)
{
- struct pci_dev * dev = data;
+ struct pci_dev *dev = data;
unsigned long alignto;
unsigned long start = res->start;
@@ -325,10 +325,10 @@ pcibios_fixup_pbus_ranges(struct pci_bus * bus,
ranges->mem_end -= bus->resource[1]->start;
}
-int __init
+int
pcibios_enable_device(struct pci_dev *dev)
{
- /* Not needed, since we enable all devices at startup. */
+ /* Nothing to do, since we enable all devices at startup. */
return 0;
}
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 8faa66901..72ce8bcb6 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -16,7 +16,6 @@
#define DEBUG_ALLOC 0
-
#if DEBUG_ALLOC > 0
# define DBGA(args...) printk(KERN_DEBUG ##args)
#else
@@ -122,10 +121,10 @@ iommu_arena_free(struct pci_iommu_arena *arena, long ofs, long n)
/* Map a single buffer of the indicate size for PCI DMA in streaming
mode. The 32-bit PCI bus mastering address to use is returned.
Once the device is given the dma address, the device owns this memory
- until either pci_unmap_single or pci_sync_single is performed. */
+ until either pci_unmap_single or pci_dma_sync_single is performed. */
dma_addr_t
-pci_map_single(struct pci_dev *pdev, void *cpu_addr, long size)
+pci_map_single(struct pci_dev *pdev, void *cpu_addr, long size, int direction)
{
struct pci_controler *hose = pdev ? pdev->sysdata : pci_isa_hose;
dma_addr_t max_dma = pdev ? pdev->dma_mask : 0x00ffffff;
@@ -173,10 +172,6 @@ pci_map_single(struct pci_dev *pdev, void *cpu_addr, long size)
ret = arena->dma_base + dma_ofs * PAGE_SIZE;
ret += (unsigned long)cpu_addr & ~PAGE_MASK;
- /* ??? This shouldn't have been needed, since the entries
- we've just modified were not in the iommu tlb. */
- alpha_mv.mv_pci_tbi(hose, ret, ret + size - 1);
-
DBGA("pci_map_single: [%p,%lx] np %ld -> sg %x from %p\n",
cpu_addr, size, npages, ret, __builtin_return_address(0));
@@ -191,7 +186,7 @@ pci_map_single(struct pci_dev *pdev, void *cpu_addr, long size)
wrote there. */
void
-pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, long size)
+pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, long size, int direction)
{
struct pci_controler *hose = pdev ? pdev->sysdata : pci_isa_hose;
struct pci_iommu_arena *arena;
@@ -239,11 +234,12 @@ void *
pci_alloc_consistent(struct pci_dev *pdev, long size, dma_addr_t *dma_addrp)
{
void *cpu_addr;
+ long order = get_order(size);
- cpu_addr = kmalloc(size, GFP_ATOMIC);
+ cpu_addr = (void *)__get_free_pages(GFP_ATOMIC, order);
if (! cpu_addr) {
- printk(KERN_INFO "dma_alloc_consistent: "
- "kmalloc failed from %p\n",
+ printk(KERN_INFO "pci_alloc_consistent: "
+ "get_free_pages failed from %p\n",
__builtin_return_address(0));
/* ??? Really atomic allocation? Otherwise we could play
with vmalloc and sg if we can't find contiguous memory. */
@@ -251,13 +247,13 @@ pci_alloc_consistent(struct pci_dev *pdev, long size, dma_addr_t *dma_addrp)
}
memset(cpu_addr, 0, size);
- *dma_addrp = pci_map_single(pdev, cpu_addr, size);
+ *dma_addrp = pci_map_single(pdev, cpu_addr, size, PCI_DMA_BIDIRECTIONAL);
if (*dma_addrp == 0) {
- kfree_s(cpu_addr, size);
+ free_pages((unsigned long)cpu_addr, order);
return NULL;
}
- DBGA2("dma_alloc_consistent: %lx -> [%p,%x] from %p\n",
+ DBGA2("pci_alloc_consistent: %lx -> [%p,%x] from %p\n",
size, cpu_addr, *dma_addrp, __builtin_return_address(0));
return cpu_addr;
@@ -274,33 +270,34 @@ void
pci_free_consistent(struct pci_dev *pdev, long size, void *cpu_addr,
dma_addr_t dma_addr)
{
- pci_unmap_single(pdev, dma_addr, size);
- kfree_s(cpu_addr, size);
+ pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL);
+ free_pages((unsigned long)cpu_addr, get_order(size));
- DBGA2("dma_free_consistent: [%x,%lx] from %p\n",
+ DBGA2("pci_free_consistent: [%x,%lx] from %p\n",
dma_addr, size, __builtin_return_address(0));
}
/* Classify the elements of the scatterlist. Write dma_address
of each element with:
- 0 : Not mergable.
- 1 : Followers all physically adjacent.
- [23]: Followers all virtually adjacent.
- -1 : Not leader.
+ 0 : Followers all physically adjacent.
+ 1 : Followers all virtually adjacent.
+ -1 : Not leader, physically adjacent to previous.
+ -2 : Not leader, virtually adjacent to previous.
Write dma_length of each leader with the combined lengths of
the mergable followers. */
static inline void
-sg_classify(struct scatterlist *sg, struct scatterlist *end)
+sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok)
{
unsigned long next_vaddr;
struct scatterlist *leader;
+ long leader_flag, leader_length;
leader = sg;
- leader->dma_address = 0;
- leader->dma_length = leader->length;
- next_vaddr = (unsigned long)leader->address + leader->length;
+ leader_flag = 0;
+ leader_length = leader->length;
+ next_vaddr = (unsigned long)leader->address + leader_length;
for (++sg; sg < end; ++sg) {
unsigned long addr, len;
@@ -309,20 +306,24 @@ sg_classify(struct scatterlist *sg, struct scatterlist *end)
if (next_vaddr == addr) {
sg->dma_address = -1;
- leader->dma_address |= 1;
- leader->dma_length += len;
- } else if (((next_vaddr | addr) & ~PAGE_MASK) == 0) {
- sg->dma_address = -1;
- leader->dma_address |= 2;
- leader->dma_length += len;
+ leader_length += len;
+ } else if (((next_vaddr | addr) & ~PAGE_MASK) == 0 && virt_ok) {
+ sg->dma_address = -2;
+ leader_flag = 1;
+ leader_length += len;
} else {
+ leader->dma_address = leader_flag;
+ leader->dma_length = leader_length;
leader = sg;
- leader->dma_address = 0;
- leader->dma_length = len;
+ leader_flag = 0;
+ leader_length = len;
}
next_vaddr = addr + len;
}
+
+ leader->dma_address = leader_flag;
+ leader->dma_length = leader_length;
}
/* Given a scatterlist leader, choose an allocation method and fill
@@ -334,21 +335,21 @@ sg_fill(struct scatterlist *leader, struct scatterlist *end,
dma_addr_t max_dma)
{
unsigned long paddr = virt_to_phys(leader->address);
- unsigned long size = leader->dma_length;
+ long size = leader->dma_length;
struct scatterlist *sg;
unsigned long *ptes;
long npages, dma_ofs, i;
/* If everything is physically contiguous, and the addresses
fall into the direct-map window, use it. */
- if (leader->dma_address < 2
+ if (leader->dma_address == 0
&& paddr + size + __direct_map_base - 1 <= max_dma
&& paddr + size <= __direct_map_size) {
out->dma_address = paddr + __direct_map_base;
out->dma_length = size;
- DBGA2("sg_fill: [%p,%lx] -> direct %x\n",
- leader->address, size, out->dma_address);
+ DBGA(" sg_fill: [%p,%lx] -> direct %x\n",
+ leader->address, size, out->dma_address);
return 0;
}
@@ -365,101 +366,119 @@ sg_fill(struct scatterlist *leader, struct scatterlist *end,
out->dma_address = arena->dma_base + dma_ofs*PAGE_SIZE + paddr;
out->dma_length = size;
- DBGA("sg_fill: [%p,%lx] -> sg %x\n",
- leader->address, size, out->dma_address);
+ DBGA(" sg_fill: [%p,%lx] -> sg %x np %ld\n",
+ leader->address, size, out->dma_address, npages);
ptes = &arena->ptes[dma_ofs];
sg = leader;
- do {
- paddr = virt_to_phys(sg->address);
- npages = calc_npages((paddr & ~PAGE_MASK) + sg->length);
-
- DBGA(" (%ld) [%p,%x]\n",
- sg - leader, sg->address, sg->length);
+ if (0 && leader->dma_address == 0) {
+ /* All physically contiguous. We already have the
+ length, all we need is to fill in the ptes. */
- paddr &= PAGE_MASK;
+ paddr = virt_to_phys(sg->address) & PAGE_MASK;
for (i = 0; i < npages; ++i, paddr += PAGE_SIZE)
*ptes++ = mk_iommu_pte(paddr);
- ++sg;
- } while (sg < end && sg->dma_address == -1);
+#if DEBUG_ALLOC > 0
+ DBGA(" (0) [%p,%x] np %ld\n",
+ sg->address, sg->length, npages);
+ for (++sg; sg < end && (int) sg->dma_address < 0; ++sg)
+ DBGA(" (%ld) [%p,%x] cont\n",
+ sg - leader, sg->address, sg->length);
+#endif
+ } else {
+ /* All virtually contiguous. We need to find the
+ length of each physically contiguous subsegment
+ to fill in the ptes. */
+ do {
+ struct scatterlist *last_sg = sg;
+
+ size = sg->length;
+ paddr = virt_to_phys(sg->address);
+
+ while (sg+1 < end && (int) sg[1].dma_address == -1) {
+ size += sg[1].length;
+ sg++;
+ }
+
+ npages = calc_npages((paddr & ~PAGE_MASK) + size);
+
+ paddr &= PAGE_MASK;
+ for (i = 0; i < npages; ++i, paddr += PAGE_SIZE)
+ *ptes++ = mk_iommu_pte(paddr);
+
+#if DEBUG_ALLOC > 0
+ DBGA(" (%ld) [%p,%x] np %ld\n",
+ last_sg - leader, last_sg->address,
+ last_sg->length, npages);
+ while (++last_sg <= sg) {
+ DBGA(" (%ld) [%p,%x] cont\n",
+ last_sg - leader, last_sg->address,
+ last_sg->length);
+ }
+#endif
+ } while (++sg < end && (int) sg->dma_address < 0);
+ }
return 1;
}
-/* TODO: Only use the iommu when it helps. Non-mergable scatterlist
- entries might as well use direct mappings. */
-
int
-pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents)
+pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, int direction)
{
struct scatterlist *start, *end, *out;
struct pci_controler *hose;
struct pci_iommu_arena *arena;
- dma_addr_t max_dma, fstart, fend;
-
- /* If pci_tbi is not available, we must not be able to control
- an iommu. Direct map everything, no merging. */
- if (! alpha_mv.mv_pci_tbi) {
- for (end = sg + nents; sg < end; ++sg) {
- sg->dma_address = virt_to_bus(sg->address);
- sg->dma_length = sg->length;
- }
- return nents;
- }
+ dma_addr_t max_dma;
/* Fast path single entry scatterlists. */
if (nents == 1) {
sg->dma_length = sg->length;
sg->dma_address
- = pci_map_single(pdev, sg->address, sg->length);
+ = pci_map_single(pdev, sg->address, sg->length, direction);
return sg->dma_address != 0;
}
- hose = pdev ? pdev->sysdata : pci_isa_hose;
- max_dma = pdev ? pdev->dma_mask : 0x00ffffff;
- arena = hose->sg_pci;
- if (!arena || arena->dma_base + arena->size > max_dma)
- arena = hose->sg_isa;
start = sg;
end = sg + nents;
- fstart = -1;
- fend = 0;
-
+
/* First, prepare information about the entries. */
- sg_classify(sg, end);
+ sg_classify(sg, end, alpha_mv.mv_pci_tbi != 0);
+
+ /* Second, figure out where we're going to map things. */
+ if (alpha_mv.mv_pci_tbi) {
+ hose = pdev ? pdev->sysdata : pci_isa_hose;
+ max_dma = pdev ? pdev->dma_mask : 0x00ffffff;
+ arena = hose->sg_pci;
+ if (!arena || arena->dma_base + arena->size > max_dma)
+ arena = hose->sg_isa;
+ } else {
+ max_dma = -1;
+ arena = NULL;
+ hose = NULL;
+ }
- /* Second, iterate over the scatterlist leaders and allocate
+ /* Third, iterate over the scatterlist leaders and allocate
dma space as needed. */
for (out = sg; sg < end; ++sg) {
int ret;
- if (sg->dma_address == -1)
+ if ((int) sg->dma_address < 0)
continue;
ret = sg_fill(sg, end, out, arena, max_dma);
if (ret < 0)
goto error;
- else if (ret > 0) {
- dma_addr_t ts, te;
-
- ts = out->dma_address;
- te = ts + out->dma_length - 1;
- if (fstart > ts)
- fstart = ts;
- if (fend < te)
- fend = te;
- }
out++;
}
- /* ??? This shouldn't have been needed, since the entries
- we've just modified were not in the iommu tlb. */
- if (fend)
- alpha_mv.mv_pci_tbi(hose, fstart, fend);
+ /* Mark the end of the list for pci_unmap_sg. */
+ if (out < end)
+ out->dma_length = 0;
if (out - start == 0)
printk(KERN_INFO "pci_map_sg failed: no entries?\n");
+ DBGA("pci_map_sg: %ld entries\n", out - start);
return out - start;
@@ -470,7 +489,7 @@ error:
/* Some allocation failed while mapping the scatterlist
entries. Unmap them now. */
if (out > start)
- pci_unmap_sg(pdev, start, out - start);
+ pci_unmap_sg(pdev, start, out - start, direction);
return 0;
}
@@ -480,7 +499,7 @@ error:
above. */
void
-pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents)
+pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, int direction)
{
struct pci_controler *hose;
struct pci_iommu_arena *arena;
@@ -496,23 +515,30 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents)
arena = hose->sg_pci;
if (!arena || arena->dma_base + arena->size > max_dma)
arena = hose->sg_isa;
+
fstart = -1;
fend = 0;
-
for (end = sg + nents; sg < end; ++sg) {
unsigned long addr, size;
addr = sg->dma_address;
size = sg->dma_length;
+ if (!size)
+ break;
+
if (addr >= __direct_map_base
&& addr < __direct_map_base + __direct_map_size) {
/* Nothing to do. */
- DBGA2("pci_unmap_sg: direct [%lx,%lx]\n", addr, size);
+ DBGA(" (%ld) direct [%lx,%lx]\n",
+ sg - end + nents, addr, size);
} else {
long npages, ofs;
dma_addr_t tend;
+ DBGA(" (%ld) sg [%lx,%lx]\n",
+ sg - end + nents, addr, size);
+
npages = calc_npages((addr & ~PAGE_MASK) + size);
ofs = (addr - arena->dma_base) >> PAGE_SHIFT;
iommu_arena_free(arena, ofs, npages);
@@ -522,10 +548,10 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents)
fstart = addr;
if (fend < tend)
fend = tend;
-
- DBGA2("pci_unmap_sg: sg [%lx,%lx]\n", addr, size);
}
}
if (fend)
alpha_mv.mv_pci_tbi(hose, fstart, fend);
+
+ DBGA("pci_unmap_sg: %d entries\n", nents - (end - sg));
}
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index e80282155..31a818209 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -30,10 +30,6 @@
#include <linux/reboot.h>
#include <linux/console.h>
-#ifdef CONFIG_RTC
-#include <linux/mc146818rtc.h>
-#endif
-
#include <asm/reg.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -139,11 +135,6 @@ common_shutdown(int mode, char *restart_cmd)
#endif
}
-#ifdef CONFIG_RTC
- /* Reset rtc to defaults. */
- rtc_kill_pit();
-#endif
-
if (alpha_mv.kill_arch)
alpha_mv.kill_arch(mode);
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
index fa92b3bc3..dd63de4d2 100644
--- a/arch/alpha/kernel/proto.h
+++ b/arch/alpha/kernel/proto.h
@@ -10,6 +10,7 @@ struct pt_regs;
struct task_struct;
struct pci_dev;
struct pci_controler;
+struct irqaction;
/* core_apecs.c */
extern struct pci_ops apecs_pci_ops;
@@ -46,6 +47,8 @@ extern void mcpcia_pci_tbi(struct pci_controler *, dma_addr_t, dma_addr_t);
/* core_polaris.c */
extern struct pci_ops polaris_pci_ops;
+extern int polaris_read_config_dword(struct pci_dev *, int, u32 *);
+extern int polaris_write_config_dword(struct pci_dev *, int, u32);
extern void polaris_init_arch(void);
extern void polaris_machine_check(u64, u64, struct pt_regs *);
#define polaris_pci_tbi ((void *)0)
@@ -84,9 +87,7 @@ extern int smp_boot_cpuid;
/* time.c */
extern void timer_interrupt(int irq, void *dev, struct pt_regs * regs);
-extern void rtc_init_pit(void);
-extern void rtc_kill_pit(void);
-extern void common_init_pit(void);
+extern void common_init_rtc(struct irqaction *);
extern unsigned long est_cycle_freq;
/* smc37c93x.c */
@@ -101,7 +102,7 @@ extern void es1888_init(void);
/* ns87312.c */
extern void ns87312_enable_ide(long ide_base);
-/* fpregs.c */
+/* ../lib/fpreg.c */
extern void alpha_write_fp_reg (unsigned long reg, unsigned long val);
extern unsigned long alpha_read_fp_reg (unsigned long reg);
@@ -134,7 +135,7 @@ extern void die_if_kernel(char *, struct pt_regs *, long, unsigned long *);
/* ../mm/init.c */
void srm_paging_stop(void);
-/* irq.h */
+/* irq.c */
#ifdef __SMP__
#define mcheck_expected(cpu) (cpu_data[cpu].mcheck_expected)
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index c92168195..112976bcb 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -30,9 +30,6 @@
#include <linux/ioport.h>
#include <linux/bootmem.h>
-#ifdef CONFIG_RTC
-#include <linux/timex.h>
-#endif
#ifdef CONFIG_BLK_DEV_INITRD
#include <linux/blk.h>
#endif
@@ -453,16 +450,6 @@ setup_arch(char **cmdline_p)
/* Reserve standard resources. */
reserve_std_resources();
- /* Initialize the timers. */
- /* ??? There is some circumstantial evidence that this needs
- to be done now rather than later in time_init, which would
- be more natural. Someone please explain or refute. */
-#if defined(CONFIG_RTC)
- rtc_init_pit();
-#else
- alpha_mv.init_pit();
-#endif
-
/*
* Give us a default console. TGA users will see nothing until
* chr_dev_init is called, rather late in the boot sequence.
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index 30ed75ead..e3ae30973 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -33,6 +33,7 @@
#include <asm/unistd.h>
#include "proto.h"
+#include "irq_impl.h"
#define DEBUG_SMP 0
@@ -62,6 +63,7 @@ spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
static unsigned long smp_secondary_alive;
unsigned long cpu_present_mask; /* Which cpus ids came online. */
+static unsigned long __cpu_present_mask __initdata = 0; /* cpu reported in the hwrpb */
static int max_cpus = -1; /* Command-line limitation. */
int smp_boot_cpuid; /* Which processor we booted from. */
@@ -506,7 +508,7 @@ setup_smp(void)
if ((cpu->flags & 0x1cc) == 0x1cc) {
smp_num_probed++;
/* Assume here that "whami" == index */
- cpu_present_mask |= (1L << i);
+ __cpu_present_mask |= (1L << i);
cpu->pal_revision = boot_cpu_palrev;
}
@@ -517,11 +519,12 @@ setup_smp(void)
}
} else {
smp_num_probed = 1;
- cpu_present_mask = (1L << smp_boot_cpuid);
+ __cpu_present_mask = (1L << smp_boot_cpuid);
}
+ cpu_present_mask = 1L << smp_boot_cpuid;
printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n",
- smp_num_probed, cpu_present_mask);
+ smp_num_probed, __cpu_present_mask);
}
/*
@@ -565,12 +568,13 @@ smp_boot_cpus(void)
if (i == smp_boot_cpuid)
continue;
- if (((cpu_present_mask >> i) & 1) == 0)
+ if (((__cpu_present_mask >> i) & 1) == 0)
continue;
if (smp_boot_one_cpu(i, cpu_count))
continue;
+ cpu_present_mask |= 1L << i;
cpu_count++;
}
@@ -623,7 +627,7 @@ smp_percpu_timer_interrupt(struct pt_regs *regs)
/* We need to make like a normal interrupt -- otherwise
timer interrupts ignore the global interrupt lock,
which would be a Bad Thing. */
- irq_enter(cpu, TIMER_IRQ);
+ irq_enter(cpu, RTC_IRQ);
update_one_process(current, 1, user, !user, cpu);
if (current->pid) {
@@ -647,7 +651,7 @@ smp_percpu_timer_interrupt(struct pt_regs *regs)
}
data->prof_counter = data->prof_multiplier;
- irq_exit(cpu, TIMER_IRQ);
+ irq_exit(cpu, RTC_IRQ);
}
}
@@ -868,6 +872,22 @@ smp_call_function (void (*func) (void *info), void *info, int retry, int wait)
}
static void
+ipi_imb(void *ignored)
+{
+ imb();
+}
+
+void
+smp_imb(void)
+{
+ /* Must wait other processors to flush their icache before continue. */
+ if (smp_call_function(ipi_imb, NULL, 1, 1))
+ printk(KERN_CRIT "smp_imb: timed out\n");
+
+ imb();
+}
+
+static void
ipi_flush_tlb_all(void *ignored)
{
tbia();
diff --git a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c
index 2a27bac5b..5498c72ec 100644
--- a/arch/alpha/kernel/sys_alcor.c
+++ b/arch/alpha/kernel/sys_alcor.c
@@ -27,49 +27,70 @@
#include <asm/core_cia.h>
#include "proto.h"
-#include <asm/hw_irq.h>
+#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
-static void
-alcor_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+/* Note mask bit is true for ENABLED irqs. */
+static unsigned long cached_irq_mask;
+
+static inline void
+alcor_update_irq_hw(unsigned long mask)
{
- if (irq >= 16) {
- /* On Alcor, at least, lines 20..30 are not connected and can
- generate spurrious interrupts if we turn them on while IRQ
- probing. So explicitly mask them out. */
- mask |= 0x7ff000000000UL;
-
- /* Note inverted sense of mask bits: */
- *(vuip)GRU_INT_MASK = ~(mask >> 16);
- mb();
- }
- else if (irq >= 8)
- outb(mask >> 8, 0xA1); /* ISA PIC2 */
- else
- outb(mask, 0x21); /* ISA PIC1 */
+ *(vuip)GRU_INT_MASK = mask;
+ mb();
+}
+
+static inline void
+alcor_enable_irq(unsigned int irq)
+{
+ alcor_update_irq_hw(cached_irq_mask |= 1UL << (irq - 16));
+}
+
+static inline void
+alcor_disable_irq(unsigned int irq)
+{
+ alcor_update_irq_hw(cached_irq_mask &= ~(1UL << (irq - 16)));
}
static void
-alcor_ack_irq(unsigned long irq)
+alcor_mask_and_ack_irq(unsigned int irq)
{
- if (irq < 16) {
- /* Ack the interrupt making it the lowest priority */
- /* First the slave .. */
- if (irq > 7) {
- outb(0xE0 | (irq - 8), 0xa0);
- irq = 2;
- }
- /* .. then the master */
- outb(0xE0 | irq, 0x20);
+ alcor_disable_irq(irq);
- /* On ALCOR/XLT, need to dismiss interrupt via GRU. */
- *(vuip)GRU_INT_CLEAR = 0x80000000; mb();
- *(vuip)GRU_INT_CLEAR = 0x00000000; mb();
- }
+ /* On ALCOR/XLT, need to dismiss interrupt via GRU. */
+ *(vuip)GRU_INT_CLEAR = 1 << (irq - 16); mb();
+ *(vuip)GRU_INT_CLEAR = 0; mb();
}
+static unsigned int
+alcor_startup_irq(unsigned int irq)
+{
+ alcor_enable_irq(irq);
+ return 0;
+}
+
+static void
+alcor_isa_mask_and_ack_irq(unsigned int irq)
+{
+ i8259a_mask_and_ack_irq(irq);
+
+ /* On ALCOR/XLT, need to dismiss interrupt via GRU. */
+ *(vuip)GRU_INT_CLEAR = 0x80000000; mb();
+ *(vuip)GRU_INT_CLEAR = 0; mb();
+}
+
+static struct hw_interrupt_type alcor_irq_type = {
+ typename: "ALCOR",
+ startup: alcor_startup_irq,
+ shutdown: alcor_disable_irq,
+ enable: alcor_enable_irq,
+ disable: alcor_disable_irq,
+ ack: alcor_mask_and_ack_irq,
+ end: alcor_enable_irq,
+};
+
static void
alcor_device_interrupt(unsigned long vector, struct pt_regs *regs)
{
@@ -89,26 +110,40 @@ alcor_device_interrupt(unsigned long vector, struct pt_regs *regs)
if (i == 31) {
isa_device_interrupt(vector, regs);
} else {
- handle_irq(16 + i, 16 + i, regs);
+ handle_irq(16 + i, regs);
}
}
}
-static void
+static void __init
alcor_init_irq(void)
{
- STANDARD_INIT_IRQ_PROLOG;
+ long i;
if (alpha_using_srm)
alpha_mv.device_interrupt = srm_device_interrupt;
- *(vuip)GRU_INT_MASK = ~(alpha_irq_mask >> 16); mb(); /* invert */
- *(vuip)GRU_INT_EDGE = 0U; mb(); /* all are level */
+ *(vuip)GRU_INT_MASK = 0; mb(); /* all disabled */
+ *(vuip)GRU_INT_EDGE = 0; mb(); /* all are level */
*(vuip)GRU_INT_HILO = 0x80000000U; mb(); /* ISA only HI */
- *(vuip)GRU_INT_CLEAR = 0UL; mb(); /* all clear */
+ *(vuip)GRU_INT_CLEAR = 0; mb(); /* all clear */
+
+ for (i = 16; i < 48; ++i) {
+ /* On Alcor, at least, lines 20..30 are not connected
+ and can generate spurrious interrupts if we turn them
+ on while IRQ probing. */
+ if (i >= 16+20 && i <= 16+30)
+ continue;
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].handler = &alcor_irq_type;
+ }
+ i8259a_irq_type.ack = alcor_isa_mask_and_ack_irq;
+
+ init_i8259a_irqs();
+ init_rtc_irq();
+ common_init_isa_dma();
- enable_irq(16 + 31); /* enable (E)ISA PIC cascade */
- enable_irq(2); /* enable cascade */
+ setup_irq(16+31, &isa_cascade_irqaction);
}
@@ -203,14 +238,11 @@ struct alpha_machine_vector alcor_mv __initmv = {
min_mem_address: CIA_DEFAULT_MEM_BASE,
nr_irqs: 48,
- irq_probe_mask: ALCOR_PROBE_MASK,
- update_irq_hw: alcor_update_irq_hw,
- ack_irq: alcor_ack_irq,
device_interrupt: alcor_device_interrupt,
init_arch: cia_init_arch,
init_irq: alcor_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: common_init_pci,
kill_arch: alcor_kill_arch,
pci_map_irq: alcor_map_irq,
@@ -236,14 +268,11 @@ struct alpha_machine_vector xlt_mv __initmv = {
min_mem_address: CIA_DEFAULT_MEM_BASE,
nr_irqs: 48,
- irq_probe_mask: ALCOR_PROBE_MASK,
- update_irq_hw: alcor_update_irq_hw,
- ack_irq: alcor_ack_irq,
device_interrupt: alcor_device_interrupt,
init_arch: cia_init_arch,
init_irq: alcor_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: common_init_pci,
kill_arch: alcor_kill_arch,
pci_map_irq: alcor_map_irq,
diff --git a/arch/alpha/kernel/sys_cabriolet.c b/arch/alpha/kernel/sys_cabriolet.c
index bc4d2c2ba..1432496d8 100644
--- a/arch/alpha/kernel/sys_cabriolet.c
+++ b/arch/alpha/kernel/sys_cabriolet.c
@@ -31,42 +31,50 @@
#include <asm/core_pyxis.h>
#include "proto.h"
-#include <asm/hw_irq.h>
+#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
-static void
-cabriolet_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+/* Note mask bit is true for DISABLED irqs. */
+static unsigned long cached_irq_mask = ~0UL;
+
+static inline void
+cabriolet_update_irq_hw(unsigned int irq, unsigned long mask)
{
- if (irq >= 16)
- outl(alpha_irq_mask >> 16, 0x804);
- else if (irq >= 8)
- outb(mask >> 8, 0xA1);
- else
- outb(mask, 0x21);
+ int ofs = (irq - 16) / 8;
+ outb(mask >> (16 + ofs*3), 0x804 + ofs);
}
-
-/* Under SRM console, we must use the CSERVE PALcode routine to manage
- the interrupt mask for us. Otherwise, the kernel/HW get out of
- sync with what the PALcode thinks it needs to deliver/ignore. */
+static inline void
+cabriolet_enable_irq(unsigned int irq)
+{
+ cabriolet_update_irq_hw(irq, cached_irq_mask &= ~(1UL << irq));
+}
static void
-cabriolet_srm_update_irq_hw(unsigned long irq, unsigned long mask, int unmaskp)
+cabriolet_disable_irq(unsigned int irq)
{
- if (irq >= 16) {
- if (unmaskp)
- cserve_ena(irq - 16);
- else
- cserve_dis(irq - 16);
- }
- else if (irq >= 8)
- outb(mask >> 8, 0xA1);
- else
- outb(mask, 0x21);
+ cabriolet_update_irq_hw(irq, cached_irq_mask |= 1UL << irq);
+}
+
+static unsigned int
+cabriolet_startup_irq(unsigned int irq)
+{
+ cabriolet_enable_irq(irq);
+ return 0; /* never anything pending */
}
+static struct hw_interrupt_type cabriolet_irq_type = {
+ typename: "CABRIOLET",
+ startup: cabriolet_startup_irq,
+ shutdown: cabriolet_disable_irq,
+ enable: cabriolet_enable_irq,
+ disable: cabriolet_disable_irq,
+ ack: cabriolet_disable_irq,
+ end: cabriolet_enable_irq,
+};
+
static void
cabriolet_device_interrupt(unsigned long v, struct pt_regs *r)
{
@@ -86,26 +94,36 @@ cabriolet_device_interrupt(unsigned long v, struct pt_regs *r)
if (i == 4) {
isa_device_interrupt(v, r);
} else {
- handle_irq(16 + i, 16 + i, r);
+ handle_irq(16 + i, r);
}
}
}
-static void
+static void __init
cabriolet_init_irq(void)
{
- STANDARD_INIT_IRQ_PROLOG;
+ init_i8259a_irqs();
+ init_rtc_irq();
if (alpha_using_srm) {
- alpha_mv.update_irq_hw = cabriolet_srm_update_irq_hw;
alpha_mv.device_interrupt = srm_device_interrupt;
+ init_srm_irqs(35, 0);
}
else {
- outl(alpha_irq_mask >> 16, 0x804);
+ long i;
+
+ outb(0xff, 0x804);
+ outb(0xff, 0x805);
+ outb(0xff, 0x806);
+
+ for (i = 16; i < 35; ++i) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].handler = &cabriolet_irq_type;
+ }
}
- enable_irq(16 + 4); /* enable SIO cascade */
- enable_irq(2); /* enable cascade */
+ common_init_isa_dma();
+ setup_irq(16+4, &isa_cascade_irqaction);
}
@@ -260,14 +278,11 @@ struct alpha_machine_vector cabriolet_mv __initmv = {
min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 35,
- irq_probe_mask: _PROBE_MASK(35),
- update_irq_hw: cabriolet_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: cabriolet_device_interrupt,
init_arch: apecs_init_arch,
init_irq: cabriolet_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: cabriolet_init_pci,
kill_arch: NULL,
pci_map_irq: cabriolet_map_irq,
@@ -289,14 +304,11 @@ struct alpha_machine_vector eb164_mv __initmv = {
min_mem_address: CIA_DEFAULT_MEM_BASE,
nr_irqs: 35,
- irq_probe_mask: _PROBE_MASK(35),
- update_irq_hw: cabriolet_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: cabriolet_device_interrupt,
init_arch: cia_init_arch,
init_irq: cabriolet_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: cabriolet_init_pci,
pci_map_irq: cabriolet_map_irq,
pci_swizzle: common_swizzle,
@@ -317,14 +329,11 @@ struct alpha_machine_vector eb66p_mv __initmv = {
min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 35,
- irq_probe_mask: _PROBE_MASK(35),
- update_irq_hw: cabriolet_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: cabriolet_device_interrupt,
init_arch: lca_init_arch,
init_irq: cabriolet_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: cabriolet_init_pci,
pci_map_irq: eb66p_map_irq,
pci_swizzle: common_swizzle,
@@ -345,14 +354,11 @@ struct alpha_machine_vector lx164_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 35,
- irq_probe_mask: _PROBE_MASK(35),
- update_irq_hw: cabriolet_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: cabriolet_device_interrupt,
init_arch: pyxis_init_arch,
init_irq: cabriolet_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: alphapc164_init_pci,
pci_map_irq: alphapc164_map_irq,
pci_swizzle: common_swizzle,
@@ -373,14 +379,11 @@ struct alpha_machine_vector pc164_mv __initmv = {
min_mem_address: CIA_DEFAULT_MEM_BASE,
nr_irqs: 35,
- irq_probe_mask: _PROBE_MASK(35),
- update_irq_hw: cabriolet_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: cabriolet_device_interrupt,
init_arch: cia_init_arch,
init_irq: cabriolet_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: alphapc164_init_pci,
pci_map_irq: alphapc164_map_irq,
pci_swizzle: common_swizzle,
diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
index f0ef47183..fbebdd5a5 100644
--- a/arch/alpha/kernel/sys_dp264.c
+++ b/arch/alpha/kernel/sys_dp264.c
@@ -8,6 +8,7 @@
* Code supporting the DP264 (EV6+TSUNAMI).
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mm.h>
@@ -27,72 +28,150 @@
#include <asm/hwrpb.h>
#include "proto.h"
-#include <asm/hw_irq.h>
+#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
-/*
- * HACK ALERT! only the boot cpu is used for interrupts.
- */
+static unsigned long cached_irq_mask;
+
+
+#define TSUNAMI_SET_IRQ_MASK(cpu, value) \
+do { \
+ volatile unsigned long *csr; \
+ csr = &TSUNAMI_cchip->dim##cpu##.csr; \
+ *csr = (value); \
+ mb(); \
+ *csr; \
+} while(0)
+
+static inline void
+do_flush_irq_mask(unsigned long value)
+{
+ switch (TSUNAMI_bootcpu) {
+ case 0:
+ TSUNAMI_SET_IRQ_MASK(0, value);
+ break;
+ case 1:
+ TSUNAMI_SET_IRQ_MASK(1, value);
+ break;
+ case 2:
+ TSUNAMI_SET_IRQ_MASK(2, value);
+ break;
+ case 3:
+ TSUNAMI_SET_IRQ_MASK(3, value);
+ break;
+ }
+}
+
+#ifdef CONFIG_SMP
+static inline void
+do_flush_smp_irq_mask(unsigned long value)
+{
+ extern unsigned long cpu_present_mask;
+ unsigned long other_cpus = cpu_present_mask & ~(1L << TSUNAMI_bootcpu);
+
+ if (other_cpus & 1)
+ TSUNAMI_SET_IRQ_MASK(0, value);
+ if (other_cpus & 2)
+ TSUNAMI_SET_IRQ_MASK(1, value);
+ if (other_cpus & 4)
+ TSUNAMI_SET_IRQ_MASK(2, value);
+ if (other_cpus & 8)
+ TSUNAMI_SET_IRQ_MASK(3, value);
+}
+#endif
static void
-dp264_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+dp264_flush_irq_mask(unsigned long mask)
{
- volatile unsigned long *csr;
+ unsigned long value;
- if (TSUNAMI_bootcpu < 2) {
- if (!TSUNAMI_bootcpu)
- csr = &TSUNAMI_cchip->dim0.csr;
- else
- csr = &TSUNAMI_cchip->dim1.csr;
- } else {
- if (TSUNAMI_bootcpu == 2)
- csr = &TSUNAMI_cchip->dim2.csr;
- else
- csr = &TSUNAMI_cchip->dim3.csr;
- }
+#ifdef CONFIG_SMP
+ do_flush_smp_irq_mask(mask);
+#endif
- *csr = ~mask;
- mb();
- *csr;
+ value = mask | (1UL << 55) | 0xffff; /* isa irqs always enabled */
+ do_flush_irq_mask(value);
+}
- if (irq < 16) {
- if (irq >= 8)
- outb(mask >> 8, 0xA1); /* ISA PIC2 */
- else
- outb(mask, 0x21); /* ISA PIC1 */
- }
+static void
+clipper_flush_irq_mask(unsigned long mask)
+{
+ unsigned long value;
+
+ value = mask >> 16;
+#ifdef CONFIG_SMP
+ do_flush_smp_irq_mask(value);
+#endif
+
+ value = value | (1UL << 55); /* master ISA enable */
+ do_flush_irq_mask(value);
+}
+
+static inline void
+dp264_enable_irq(unsigned int irq)
+{
+ cached_irq_mask |= 1UL << irq;
+ dp264_flush_irq_mask(cached_irq_mask);
}
static void
-clipper_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+dp264_disable_irq(unsigned int irq)
{
- if (irq >= 16) {
- volatile unsigned long *csr;
-
- if (TSUNAMI_bootcpu < 2)
- if (!TSUNAMI_bootcpu)
- csr = &TSUNAMI_cchip->dim0.csr;
- else
- csr = &TSUNAMI_cchip->dim1.csr;
- else
- if (TSUNAMI_bootcpu == 2)
- csr = &TSUNAMI_cchip->dim2.csr;
- else
- csr = &TSUNAMI_cchip->dim3.csr;
-
- *csr = (~mask >> 16) | (1UL << 55); /* master ISA enable */
- mb();
- *csr;
- }
- else if (irq >= 8)
- outb(mask >> 8, 0xA1); /* ISA PIC2 */
- else
- outb(mask, 0x21); /* ISA PIC1 */
+ cached_irq_mask &= ~(1UL << irq);
+ dp264_flush_irq_mask(cached_irq_mask);
+}
+
+static unsigned int
+dp264_startup_irq(unsigned int irq)
+{
+ dp264_enable_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static inline void
+clipper_enable_irq(unsigned int irq)
+{
+ cached_irq_mask |= 1UL << irq;
+ clipper_flush_irq_mask(cached_irq_mask);
}
static void
+clipper_disable_irq(unsigned int irq)
+{
+ cached_irq_mask &= ~(1UL << irq);
+ clipper_flush_irq_mask(cached_irq_mask);
+}
+
+static unsigned int
+clipper_startup_irq(unsigned int irq)
+{
+ clipper_enable_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type dp264_irq_type = {
+ typename: "DP264",
+ startup: dp264_startup_irq,
+ shutdown: dp264_disable_irq,
+ enable: dp264_enable_irq,
+ disable: dp264_disable_irq,
+ ack: dp264_disable_irq,
+ end: dp264_enable_irq,
+};
+
+static struct hw_interrupt_type clipper_irq_type = {
+ typename: "CLIPPER",
+ startup: clipper_startup_irq,
+ shutdown: clipper_disable_irq,
+ enable: clipper_enable_irq,
+ disable: clipper_disable_irq,
+ ack: clipper_disable_irq,
+ end: clipper_enable_irq,
+};
+
+static void
dp264_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
#if 1
@@ -126,9 +205,9 @@ dp264_device_interrupt(unsigned long vector, struct pt_regs * regs)
static void
dp264_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
- int irq, ack;
+ int irq;
- ack = irq = (vector - 0x800) >> 4;
+ irq = (vector - 0x800) >> 4;
/*
* The SRM console reports PCI interrupts with a vector calculated by:
@@ -142,17 +221,17 @@ dp264_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
* so we don't count them.
*/
if (irq >= 32)
- ack = irq = irq - 16;
+ irq -= 16;
- handle_irq(irq, ack, regs);
+ handle_irq(irq, regs);
}
static void
clipper_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
- int irq, ack;
+ int irq;
- ack = irq = (vector - 0x800) >> 4;
+ irq = (vector - 0x800) >> 4;
/*
* The SRM console reports PCI interrupts with a vector calculated by:
@@ -166,7 +245,19 @@ clipper_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
*
* Eg IRQ 24 is DRIR bit 8, etc, etc
*/
- handle_irq(irq, ack, regs);
+ handle_irq(irq, regs);
+}
+
+static void __init
+init_tsunami_irqs(struct hw_interrupt_type * ops)
+{
+ long i;
+
+ /* Only irqs between 16 and 47 are tsunami irqs. */
+ for (i = 16; i < 48; ++i) {
+ irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
+ irq_desc[i].handler = ops;
+ }
}
static void __init
@@ -180,10 +271,11 @@ dp264_init_irq(void)
if (alpha_using_srm)
alpha_mv.device_interrupt = dp264_srm_device_interrupt;
- dp264_update_irq_hw(16, alpha_irq_mask, 0);
+ dp264_flush_irq_mask(0UL);
- enable_irq(55); /* Enable ISA interrupt controller. */
- enable_irq(2);
+ init_i8259a_irqs();
+ init_rtc_irq();
+ init_tsunami_irqs(&dp264_irq_type);
}
static void __init
@@ -197,10 +289,11 @@ clipper_init_irq(void)
if (alpha_using_srm)
alpha_mv.device_interrupt = clipper_srm_device_interrupt;
- clipper_update_irq_hw(16, alpha_irq_mask, 0);
+ clipper_flush_irq_mask(0UL);
- enable_irq(55); /* Enable ISA interrupt controller. */
- enable_irq(2);
+ init_i8259a_irqs();
+ init_rtc_irq();
+ init_tsunami_irqs(&clipper_irq_type);
}
@@ -431,14 +524,11 @@ struct alpha_machine_vector dp264_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 64,
- irq_probe_mask: TSUNAMI_PROBE_MASK,
- update_irq_hw: dp264_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: dp264_device_interrupt,
init_arch: tsunami_init_arch,
init_irq: dp264_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: dp264_init_pci,
kill_arch: tsunami_kill_arch,
pci_map_irq: dp264_map_irq,
@@ -458,14 +548,11 @@ struct alpha_machine_vector monet_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 64,
- irq_probe_mask: TSUNAMI_PROBE_MASK,
- update_irq_hw: dp264_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: dp264_device_interrupt,
init_arch: tsunami_init_arch,
init_irq: dp264_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: monet_init_pci,
kill_arch: tsunami_kill_arch,
pci_map_irq: monet_map_irq,
@@ -484,14 +571,11 @@ struct alpha_machine_vector webbrick_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 64,
- irq_probe_mask: TSUNAMI_PROBE_MASK,
- update_irq_hw: dp264_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: dp264_device_interrupt,
init_arch: tsunami_init_arch,
init_irq: dp264_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: common_init_pci,
kill_arch: tsunami_kill_arch,
pci_map_irq: webbrick_map_irq,
@@ -510,14 +594,11 @@ struct alpha_machine_vector clipper_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 64,
- irq_probe_mask: TSUNAMI_PROBE_MASK,
- update_irq_hw: clipper_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: dp264_device_interrupt,
init_arch: tsunami_init_arch,
init_irq: clipper_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: common_init_pci,
kill_arch: tsunami_kill_arch,
pci_map_irq: clipper_map_irq,
diff --git a/arch/alpha/kernel/sys_eb64p.c b/arch/alpha/kernel/sys_eb64p.c
index e8e224715..0820bd5a0 100644
--- a/arch/alpha/kernel/sys_eb64p.c
+++ b/arch/alpha/kernel/sys_eb64p.c
@@ -28,25 +28,49 @@
#include <asm/core_lca.h>
#include "proto.h"
-#include <asm/hw_irq.h>
+#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
-static void
-eb64p_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+/* Note mask bit is true for DISABLED irqs. */
+static unsigned int cached_irq_mask = -1;
+
+static inline void
+eb64p_update_irq_hw(unsigned int irq, unsigned long mask)
{
- if (irq >= 16)
- if (irq >= 24)
- outb(mask >> 24, 0x27);
- else
- outb(mask >> 16, 0x26);
- else if (irq >= 8)
- outb(mask >> 8, 0xA1);
- else
- outb(mask, 0x21);
+ outb(mask >> (irq >= 24 ? 24 : 16), (irq >= 24 ? 0x27 : 0x26));
}
+static inline void
+eb64p_enable_irq(unsigned int irq)
+{
+ eb64p_update_irq_hw(irq, cached_irq_mask &= ~(1 << irq));
+}
+
+static inline void
+eb64p_disable_irq(unsigned int irq)
+{
+ eb64p_update_irq_hw(irq, cached_irq_mask |= 1 << irq);
+}
+
+static unsigned int
+eb64p_startup_irq(unsigned int irq)
+{
+ eb64p_enable_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type eb64p_irq_type = {
+ typename: "EB64P",
+ startup: eb64p_startup_irq,
+ shutdown: eb64p_disable_irq,
+ enable: eb64p_enable_irq,
+ disable: eb64p_disable_irq,
+ ack: eb64p_disable_irq,
+ end: eb64p_enable_irq,
+};
+
static void
eb64p_device_interrupt(unsigned long vector, struct pt_regs *regs)
{
@@ -55,6 +79,7 @@ eb64p_device_interrupt(unsigned long vector, struct pt_regs *regs)
/* Read the interrupt summary registers */
pld = inb(0x26) | (inb(0x27) << 8);
+
/*
* Now, for every possible bit set, work through
* them and call the appropriate interrupt handler.
@@ -66,7 +91,7 @@ eb64p_device_interrupt(unsigned long vector, struct pt_regs *regs)
if (i == 5) {
isa_device_interrupt(vector, regs);
} else {
- handle_irq(16 + i, 16 + i, regs);
+ handle_irq(16 + i, regs);
}
}
}
@@ -74,6 +99,8 @@ eb64p_device_interrupt(unsigned long vector, struct pt_regs *regs)
static void __init
eb64p_init_irq(void)
{
+ long i;
+
#ifdef CONFIG_ALPHA_GENERIC
/*
* CABRIO SRM may not set variation correctly, so here we test
@@ -82,21 +109,25 @@ eb64p_init_irq(void)
*/
if (inw(0x806) != 0xffff) {
extern struct alpha_machine_vector cabriolet_mv;
-#if 1
- printk("eb64p_init_irq: resetting for CABRIO\n");
-#endif
alpha_mv = cabriolet_mv;
alpha_mv.init_irq();
return;
}
#endif /* GENERIC */
- STANDARD_INIT_IRQ_PROLOG;
+ outb(0xff, 0x26);
+ outb(0xff, 0x27);
+
+ init_i8259a_irqs();
+ init_rtc_irq();
+
+ for (i = 16; i < 32; ++i) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].handler = &eb64p_irq_type;
+ }
- outb(alpha_irq_mask >> 16, 0x26);
- outb(alpha_irq_mask >> 24, 0x27);
- enable_irq(16 + 5); /* enable SIO cascade */
- enable_irq(2); /* enable cascade */
+ common_init_isa_dma();
+ setup_irq(16+5, &isa_cascade_irqaction);
}
/*
@@ -112,7 +143,7 @@ eb64p_init_irq(void)
* 3 Interrupt Line B from slot 1
* 4 Interrupt Line C from slot 0
* 5 Interrupt line from the two ISA PICs
- * 6 Tulip (slot
+ * 6 Tulip
* 7 NCR SCSI
*
* Summary @ 0x27
@@ -174,14 +205,11 @@ struct alpha_machine_vector eb64p_mv __initmv = {
min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 32,
- irq_probe_mask: _PROBE_MASK(32),
- update_irq_hw: eb64p_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: eb64p_device_interrupt,
init_arch: apecs_init_arch,
init_irq: eb64p_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: common_init_pci,
kill_arch: NULL,
pci_map_irq: eb64p_map_irq,
@@ -203,14 +231,11 @@ struct alpha_machine_vector eb66_mv __initmv = {
min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 32,
- irq_probe_mask: _PROBE_MASK(32),
- update_irq_hw: eb64p_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: eb64p_device_interrupt,
init_arch: lca_init_arch,
init_irq: eb64p_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: common_init_pci,
pci_map_irq: eb64p_map_irq,
pci_swizzle: common_swizzle,
diff --git a/arch/alpha/kernel/sys_eiger.c b/arch/alpha/kernel/sys_eiger.c
index 433abddfb..c4d120799 100644
--- a/arch/alpha/kernel/sys_eiger.c
+++ b/arch/alpha/kernel/sys_eiger.c
@@ -29,7 +29,7 @@
#include <asm/hwrpb.h>
#include "proto.h"
-#include <asm/hw_irq.h>
+#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
@@ -38,29 +38,54 @@
* HACK ALERT! only the boot cpu is used for interrupts.
*/
-static void
-eiger_update_irq_hw(unsigned long irq, unsigned long unused, int unmask_p)
+/* Note that this interrupt code is identical to TAKARA. */
+
+/* Note mask bit is true for DISABLED irqs. */
+static unsigned long cached_irq_mask[2] = { -1, -1 };
+
+static inline void
+eiger_update_irq_hw(unsigned long irq, unsigned long mask)
{
- unsigned int regaddr;
- unsigned long mask;
+ int regaddr;
- if (irq <= 15) {
- if (irq <= 7)
- outb(alpha_irq_mask, 0x21); /* ISA PIC1 */
- else
- outb(alpha_irq_mask >> 8, 0xA1); /* ISA PIC2 */
- } else {
- if (irq > 63)
- mask = _alpha_irq_masks[1] << 16;
- else
- mask = _alpha_irq_masks[0] >> ((irq - 16) & 0x30);
+ mask = (irq >= 64 ? mask << 16 : mask >> ((irq - 16) & 0x30));
+ regaddr = 0x510 + (((irq - 16) >> 2) & 0x0c);
+ outl(mask & 0xffff0000UL, regaddr);
+}
- regaddr = 0x510 + (((irq - 16) >> 2) & 0x0c);
+static inline void
+eiger_enable_irq(unsigned int irq)
+{
+ unsigned long mask;
+ mask = (cached_irq_mask[irq >= 64] &= ~(1UL << (irq & 63)));
+ eiger_update_irq_hw(irq, mask);
+}
- outl(mask & 0xffff0000UL, regaddr);
- }
+static void
+eiger_disable_irq(unsigned int irq)
+{
+ unsigned long mask;
+ mask = (cached_irq_mask[irq >= 64] |= 1UL << (irq & 63));
+ eiger_update_irq_hw(irq, mask);
+}
+
+static unsigned int
+eiger_startup_irq(unsigned int irq)
+{
+ eiger_enable_irq(irq);
+ return 0; /* never anything pending */
}
+static struct hw_interrupt_type eiger_irq_type = {
+ typename: "EIGER",
+ startup: eiger_startup_irq,
+ shutdown: eiger_disable_irq,
+ enable: eiger_enable_irq,
+ disable: eiger_disable_irq,
+ ack: eiger_disable_irq,
+ end: eiger_enable_irq,
+};
+
static void
eiger_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
@@ -89,25 +114,27 @@ eiger_device_interrupt(unsigned long vector, struct pt_regs * regs)
* despatch an interrupt if it's set.
*/
- if (intstatus & 8) handle_irq(16+3, 16+3, regs);
- if (intstatus & 4) handle_irq(16+2, 16+2, regs);
- if (intstatus & 2) handle_irq(16+1, 16+1, regs);
- if (intstatus & 1) handle_irq(16+0, 16+0, regs);
+ if (intstatus & 8) handle_irq(16+3, regs);
+ if (intstatus & 4) handle_irq(16+2, regs);
+ if (intstatus & 2) handle_irq(16+1, regs);
+ if (intstatus & 1) handle_irq(16+0, regs);
} else {
- isa_device_interrupt (vector, regs);
+ isa_device_interrupt(vector, regs);
}
}
static void
eiger_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
- int irq = (vector - 0x800) >> 4;
- handle_irq(irq, irq, regs);
+ int irq = (vector - 0x800) >> 4;
+ handle_irq(irq, regs);
}
static void __init
eiger_init_irq(void)
{
+ long i;
+
outb(0, DMA1_RESET_REG);
outb(0, DMA2_RESET_REG);
outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
@@ -116,9 +143,16 @@ eiger_init_irq(void)
if (alpha_using_srm)
alpha_mv.device_interrupt = eiger_srm_device_interrupt;
- eiger_update_irq_hw(16, alpha_irq_mask, 0);
+ for (i = 16; i < 128; i += 16)
+ eiger_update_irq_hw(i, -1);
- enable_irq(2);
+ init_i8259a_irqs();
+ init_rtc_irq();
+
+ for (i = 16; i < 128; ++i) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].handler = &eiger_irq_type;
+ }
}
static int __init
@@ -199,14 +233,11 @@ struct alpha_machine_vector eiger_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 128,
- irq_probe_mask: TSUNAMI_PROBE_MASK,
- update_irq_hw: eiger_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: eiger_device_interrupt,
init_arch: tsunami_init_arch,
init_irq: eiger_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: common_init_pci,
kill_arch: tsunami_kill_arch,
pci_map_irq: eiger_map_irq,
diff --git a/arch/alpha/kernel/sys_jensen.c b/arch/alpha/kernel/sys_jensen.c
index c2abe26f2..98dea0902 100644
--- a/arch/alpha/kernel/sys_jensen.c
+++ b/arch/alpha/kernel/sys_jensen.c
@@ -28,19 +28,10 @@
#include <asm/pgtable.h>
#include "proto.h"
-#include <asm/hw_irq.h>
+#include "irq_impl.h"
#include "machvec_impl.h"
-static void
-jensen_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
-{
- if (irq >= 8)
- outb(mask >> 8, 0xA1);
- else
- outb(mask, 0x21);
-}
-
/*
* Jensen is special: the vector is 0x8X0 for EISA interrupt X, and
* 0x9X0 for the local motherboard interrupts..
@@ -66,51 +57,71 @@ jensen_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
*/
static void
-handle_nmi(struct pt_regs * regs)
+jensen_local_ack(unsigned int irq)
{
- printk("Whee.. NMI received. Probable hardware error\n");
- printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
+ /* irq1 is supposed to be the keyboard, silly Jensen. */
+ if (irq == 7)
+ i8259a_mask_and_ack_irq(1);
}
+static struct hw_interrupt_type jensen_local_irq_type = {
+ typename: "LOCAL",
+ startup: i8259a_startup_irq,
+ shutdown: i8259a_disable_irq,
+ enable: i8259a_enable_irq,
+ disable: i8259a_disable_irq,
+ ack: jensen_local_ack,
+ end: i8259a_enable_irq,
+};
+
static void
jensen_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
- int irq, ack;
-
- ack = irq = (vector - 0x800) >> 4;
+ int irq;
switch (vector) {
- case 0x660: handle_nmi(regs); return;
+ case 0x660:
+ printk("Whee.. NMI received. Probable hardware error\n");
+ printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
+ return;
/* local device interrupts: */
- case 0x900: irq = 4, ack = -1; break; /* com1 -> irq 4 */
- case 0x920: irq = 3, ack = -1; break; /* com2 -> irq 3 */
- case 0x980: irq = 1, ack = -1; break; /* kbd -> irq 1 */
- case 0x990: irq = 9, ack = -1; break; /* mouse -> irq 9 */
+ case 0x900: irq = 4; break; /* com1 -> irq 4 */
+ case 0x920: irq = 3; break; /* com2 -> irq 3 */
+ case 0x980: irq = 1; break; /* kbd -> irq 1 */
+ case 0x990: irq = 9; break; /* mouse -> irq 9 */
+
default:
if (vector > 0x900) {
printk("Unknown local interrupt %lx\n", vector);
+ return;
}
- /* irq1 is supposed to be the keyboard, silly Jensen
- (is this really needed??) */
+ irq = (vector - 0x800) >> 4;
if (irq == 1)
irq = 7;
break;
}
- handle_irq(irq, ack, regs);
+ handle_irq(irq, regs);
}
-static void
+static void __init
jensen_init_irq(void)
{
- STANDARD_INIT_IRQ_PROLOG;
+ init_i8259a_irqs();
+ init_rtc_irq();
- enable_irq(2); /* enable cascade */
+ irq_desc[1].handler = &jensen_local_irq_type;
+ irq_desc[4].handler = &jensen_local_irq_type;
+ irq_desc[3].handler = &jensen_local_irq_type;
+ irq_desc[7].handler = &jensen_local_irq_type;
+ irq_desc[9].handler = &jensen_local_irq_type;
+
+ common_init_isa_dma();
}
-static void
+static void __init
jensen_init_arch(void)
{
__direct_map_base = 0;
@@ -140,14 +151,11 @@ struct alpha_machine_vector jensen_mv __initmv = {
rtc_port: 0x170,
nr_irqs: 16,
- irq_probe_mask: _PROBE_MASK(16),
- update_irq_hw: jensen_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: jensen_device_interrupt,
init_arch: jensen_init_arch,
init_irq: jensen_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: NULL,
kill_arch: NULL,
};
diff --git a/arch/alpha/kernel/sys_miata.c b/arch/alpha/kernel/sys_miata.c
index b2da23528..06457a0e8 100644
--- a/arch/alpha/kernel/sys_miata.c
+++ b/arch/alpha/kernel/sys_miata.c
@@ -25,71 +25,17 @@
#include <asm/core_pyxis.h>
#include "proto.h"
-#include <asm/hw_irq.h>
+#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
static void
-miata_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
-{
- if (irq >= 16) {
- /* Make CERTAIN none of the bogus ints get enabled... */
- *(vulp)PYXIS_INT_MASK =
- ~((long)mask >> 16) & ~0x400000000000063bUL;
- mb();
- /* ... and read it back to make sure it got written. */
- *(vulp)PYXIS_INT_MASK;
- }
- else if (irq >= 8)
- outb(mask >> 8, 0xA1); /* ISA PIC2 */
- else
- outb(mask, 0x21); /* ISA PIC1 */
-}
-
-static void
-miata_device_interrupt(unsigned long vector, struct pt_regs *regs)
-{
- unsigned long pld, tmp;
- unsigned int i;
-
- /* Read the interrupt summary register of PYXIS */
- pld = *(vulp)PYXIS_INT_REQ;
-
- /*
- * For now, AND off any bits we are not interested in:
- * HALT (2), timer (6), ISA Bridge (7), 21142/3 (8)
- * then all the PCI slots/INTXs (12-31).
- */
- /* Maybe HALT should only be used for SRM console boots? */
- pld &= 0x00000000fffff9c4UL;
-
- /*
- * Now for every possible bit set, work through them and call
- * the appropriate interrupt handler.
- */
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
- if (i == 7) {
- isa_device_interrupt(vector, regs);
- } else if (i == 6) {
- continue;
- } else {
- /* if not timer int */
- handle_irq(16 + i, 16 + i, regs);
- }
- *(vulp)PYXIS_INT_REQ = 1UL << i; mb();
- tmp = *(vulp)PYXIS_INT_REQ;
- }
-}
-
-static void
miata_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
- int irq, ack;
+ int irq;
- ack = irq = (vector - 0x800) >> 4;
+ irq = (vector - 0x800) >> 4;
/*
* I really hate to do this, but the MIATA SRM console ignores the
@@ -106,34 +52,36 @@ miata_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
* So, here's this grotty hack... :-(
*/
if (irq >= 16)
- ack = irq = irq + 8;
+ irq = irq + 8;
- handle_irq(irq, ack, regs);
+ handle_irq(irq, regs);
}
static void __init
miata_init_irq(void)
{
- STANDARD_INIT_IRQ_PROLOG;
-
if (alpha_using_srm)
alpha_mv.device_interrupt = miata_srm_device_interrupt;
- /* Note invert on MASK bits. */
- *(vulp)PYXIS_INT_MASK =
- ~((long)alpha_irq_mask >> 16) & ~0x400000000000063bUL; mb();
#if 0
/* These break on MiataGL so we'll try not to do it at all. */
*(vulp)PYXIS_INT_HILO = 0x000000B2UL; mb(); /* ISA/NMI HI */
*(vulp)PYXIS_RT_COUNT = 0UL; mb(); /* clear count */
#endif
- /* Clear upper timer. */
- *(vulp)PYXIS_INT_REQ = 0x4000000000000180UL; mb();
- enable_irq(16 + 2); /* enable HALT switch - SRM only? */
- enable_irq(16 + 6); /* enable timer */
- enable_irq(16 + 7); /* enable ISA PIC cascade */
- enable_irq(2); /* enable cascade */
+ init_i8259a_irqs();
+ init_rtc_irq();
+
+ /* Not interested in the bogus interrupts (3,10), Fan Fault (0),
+ NMI (1), or EIDE (9).
+
+ We also disable the risers (4,5), since we don't know how to
+ route the interrupts behind the bridge. */
+ init_pyxis_irqs(0x63b0000);
+
+ common_init_isa_dma();
+ setup_irq(16+2, &halt_switch_irqaction); /* SRM only? */
+ setup_irq(16+6, &timer_cascade_irqaction);
}
@@ -300,14 +248,11 @@ struct alpha_machine_vector miata_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 48,
- irq_probe_mask: _PROBE_MASK(48),
- update_irq_hw: miata_update_irq_hw,
- ack_irq: common_ack_irq,
- device_interrupt: miata_device_interrupt,
+ device_interrupt: pyxis_device_interrupt,
init_arch: pyxis_init_arch,
init_irq: miata_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: miata_init_pci,
kill_arch: miata_kill_arch,
pci_map_irq: miata_map_irq,
diff --git a/arch/alpha/kernel/sys_mikasa.c b/arch/alpha/kernel/sys_mikasa.c
index ac55371a6..936fa4f17 100644
--- a/arch/alpha/kernel/sys_mikasa.c
+++ b/arch/alpha/kernel/sys_mikasa.c
@@ -28,21 +28,49 @@
#include <asm/core_cia.h>
#include "proto.h"
-#include <asm/hw_irq.h>
+#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
-static void
-mikasa_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+
+/* Note mask bit is true for ENABLED irqs. */
+static int cached_irq_mask;
+
+static inline void
+mikasa_update_irq_hw(int mask)
+{
+ outw(mask, 0x536);
+}
+
+static inline void
+mikasa_enable_irq(unsigned int irq)
+{
+ mikasa_update_irq_hw(cached_irq_mask |= 1 << (irq - 16));
+}
+
+static inline void
+mikasa_disable_irq(unsigned int irq)
{
- if (irq >= 16)
- outw(~(mask >> 16), 0x536); /* note invert */
- else if (irq >= 8)
- outb(mask >> 8, 0xA1);
- else
- outb(mask, 0x21);
+ mikasa_update_irq_hw(cached_irq_mask &= ~(1 << (irq - 16)));
}
+static unsigned int
+mikasa_startup_irq(unsigned int irq)
+{
+ mikasa_enable_irq(irq);
+ return 0;
+}
+
+static struct hw_interrupt_type mikasa_irq_type = {
+ typename: "MIKASA",
+ startup: mikasa_startup_irq,
+ shutdown: mikasa_disable_irq,
+ enable: mikasa_enable_irq,
+ disable: mikasa_disable_irq,
+ ack: mikasa_disable_irq,
+ end: mikasa_enable_irq,
+};
+
static void
mikasa_device_interrupt(unsigned long vector, struct pt_regs *regs)
{
@@ -50,9 +78,9 @@ mikasa_device_interrupt(unsigned long vector, struct pt_regs *regs)
unsigned int i;
/* Read the interrupt summary registers */
- pld = (((unsigned long) (~inw(0x534)) & 0x0000ffffUL) << 16) |
- (((unsigned long) inb(0xa0)) << 8) |
- ((unsigned long) inb(0x20));
+ pld = (((~inw(0x534) & 0x0000ffffUL) << 16)
+ | (((unsigned long) inb(0xa0)) << 8)
+ | inb(0x20));
/*
* Now for every possible bit set, work through them and call
@@ -64,7 +92,7 @@ mikasa_device_interrupt(unsigned long vector, struct pt_regs *regs)
if (i < 16) {
isa_device_interrupt(vector, regs);
} else {
- handle_irq(i, i, regs);
+ handle_irq(i, regs);
}
}
}
@@ -72,13 +100,21 @@ mikasa_device_interrupt(unsigned long vector, struct pt_regs *regs)
static void __init
mikasa_init_irq(void)
{
- STANDARD_INIT_IRQ_PROLOG;
+ long i;
if (alpha_using_srm)
alpha_mv.device_interrupt = srm_device_interrupt;
- outw(~(alpha_irq_mask >> 16), 0x536); /* note invert */
- enable_irq(2); /* enable cascade */
+ mikasa_update_irq_hw(0);
+
+ for (i = 16; i < 32; ++i) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].handler = &mikasa_irq_type;
+ }
+
+ init_i8259a_irqs();
+ init_rtc_irq();
+ common_init_isa_dma();
}
@@ -185,14 +221,11 @@ struct alpha_machine_vector mikasa_mv __initmv = {
min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 32,
- irq_probe_mask: _PROBE_MASK(32),
- update_irq_hw: mikasa_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: mikasa_device_interrupt,
init_arch: apecs_init_arch,
init_irq: mikasa_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: common_init_pci,
kill_arch: NULL,
pci_map_irq: mikasa_map_irq,
@@ -214,14 +247,11 @@ struct alpha_machine_vector mikasa_primo_mv __initmv = {
min_mem_address: CIA_DEFAULT_MEM_BASE,
nr_irqs: 32,
- irq_probe_mask: _PROBE_MASK(32),
- update_irq_hw: mikasa_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: mikasa_device_interrupt,
init_arch: cia_init_arch,
init_irq: mikasa_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: common_init_pci,
pci_map_irq: mikasa_map_irq,
pci_swizzle: common_swizzle,
diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
index 423589924..621df72f8 100644
--- a/arch/alpha/kernel/sys_nautilus.c
+++ b/arch/alpha/kernel/sys_nautilus.c
@@ -45,34 +45,17 @@
#include <asm/hwrpb.h>
#include "proto.h"
-#include <asm/hw_irq.h>
+#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
-#define dev2hose(d) (bus2hose[(d)->bus->number]->pci_hose_index)
-
-static void
-nautilus_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
-{
- /* The timer is connected to PIC interrupt line also on Nautilus.
- The timer interrupt handler enables the PIC line, so in order
- not to get multiple timer interrupt sources, we mask it out
- at all times. */
-
- mask |= 0x100;
- if (irq >= 8)
- outb(mask >> 8, 0xA1);
- else
- outb(mask, 0x21);
-}
static void __init
nautilus_init_irq(void)
{
- STANDARD_INIT_IRQ_PROLOG;
-
- enable_irq(2); /* enable cascade */
- disable_irq(8);
+ init_i8259a_irqs();
+ init_rtc_irq();
+ common_init_isa_dma();
}
static int __init
@@ -534,14 +517,11 @@ struct alpha_machine_vector nautilus_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 16,
- irq_probe_mask: (_PROBE_MASK(16) & ~0x101UL),
- update_irq_hw: nautilus_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: isa_device_interrupt,
init_arch: irongate_init_arch,
init_irq: nautilus_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: common_init_pci,
kill_arch: nautilus_kill_arch,
pci_map_irq: nautilus_map_irq,
diff --git a/arch/alpha/kernel/sys_noritake.c b/arch/alpha/kernel/sys_noritake.c
index c1a793393..31eac0da4 100644
--- a/arch/alpha/kernel/sys_noritake.c
+++ b/arch/alpha/kernel/sys_noritake.c
@@ -29,25 +29,51 @@
#include <asm/core_cia.h>
#include "proto.h"
-#include <asm/hw_irq.h>
+#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
+/* Note mask bit is true for ENABLED irqs. */
+static int cached_irq_mask;
-static void
-noritake_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+static inline void
+noritake_update_irq_hw(int irq, int mask)
{
- if (irq <= 15)
- if (irq <= 7)
- outb(mask, 0x21); /* ISA PIC1 */
- else
- outb(mask >> 8, 0xA1); /* ISA PIC2 */
- else if (irq <= 31)
- outw(~(mask >> 16), 0x54a);
- else
- outw(~(mask >> 32), 0x54c);
+ int port = 0x54a;
+ if (irq >= 16) mask >>= 16;
+ if (irq >= 16) port = 0x54c;
+ outw(mask, port);
+}
+
+static inline void
+noritake_enable_irq(unsigned int irq)
+{
+ noritake_update_irq_hw(irq, cached_irq_mask |= 1 << (irq - 16));
+}
+
+static inline void
+noritake_disable_irq(unsigned int irq)
+{
+ noritake_update_irq_hw(irq, cached_irq_mask &= ~(1 << (irq - 16)));
}
+static unsigned int
+noritake_startup_irq(unsigned int irq)
+{
+ noritake_enable_irq(irq);
+ return 0;
+}
+
+static struct hw_interrupt_type noritake_irq_type = {
+ typename: "NORITAKE",
+ startup: noritake_startup_irq,
+ shutdown: noritake_disable_irq,
+ enable: noritake_enable_irq,
+ disable: noritake_disable_irq,
+ ack: noritake_disable_irq,
+ end: noritake_enable_irq,
+};
+
static void
noritake_device_interrupt(unsigned long vector, struct pt_regs *regs)
{
@@ -55,10 +81,10 @@ noritake_device_interrupt(unsigned long vector, struct pt_regs *regs)
unsigned int i;
/* Read the interrupt summary registers of NORITAKE */
- pld = ((unsigned long) inw(0x54c) << 32) |
- ((unsigned long) inw(0x54a) << 16) |
- ((unsigned long) inb(0xa0) << 8) |
- ((unsigned long) inb(0x20));
+ pld = (((unsigned long) inw(0x54c) << 32)
+ | ((unsigned long) inw(0x54a) << 16)
+ | ((unsigned long) inb(0xa0) << 8)
+ | inb(0x20));
/*
* Now for every possible bit set, work through them and call
@@ -70,7 +96,7 @@ noritake_device_interrupt(unsigned long vector, struct pt_regs *regs)
if (i < 16) {
isa_device_interrupt(vector, regs);
} else {
- handle_irq(i, i, regs);
+ handle_irq(i, regs);
}
}
}
@@ -78,36 +104,44 @@ noritake_device_interrupt(unsigned long vector, struct pt_regs *regs)
static void
noritake_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
- int irq, ack;
+ int irq;
- ack = irq = (vector - 0x800) >> 4;
+ irq = (vector - 0x800) >> 4;
/*
* I really hate to do this, too, but the NORITAKE SRM console also
- * reports PCI vectors *lower* than I expected from the bit numbers
- * in the documentation.
+ * reports PCI vectors *lower* than I expected from the bit numbers
+ * in the documentation.
* But I really don't want to change the fixup code for allocation
- * of IRQs, nor the alpha_irq_mask maintenance stuff, both of which
- * look nice and clean now.
+ * of IRQs, nor the alpha_irq_mask maintenance stuff, both of which
+ * look nice and clean now.
* So, here's this additional grotty hack... :-(
*/
if (irq >= 16)
- ack = irq = irq + 1;
+ irq = irq + 1;
- handle_irq(irq, ack, regs);
+ handle_irq(irq, regs);
}
static void __init
noritake_init_irq(void)
{
- STANDARD_INIT_IRQ_PROLOG;
+ long i;
if (alpha_using_srm)
alpha_mv.device_interrupt = noritake_srm_device_interrupt;
- outw(~(alpha_irq_mask >> 16), 0x54a); /* note invert */
- outw(~(alpha_irq_mask >> 32), 0x54c); /* note invert */
- enable_irq(2); /* enable cascade */
+ outw(0, 0x54a);
+ outw(0, 0x54c);
+
+ for (i = 16; i < 48; ++i) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].handler = &noritake_irq_type;
+ }
+
+ init_i8259a_irqs();
+ init_rtc_irq();
+ common_init_isa_dma();
}
@@ -245,14 +279,11 @@ struct alpha_machine_vector noritake_mv __initmv = {
min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 48,
- irq_probe_mask: _PROBE_MASK(48),
- update_irq_hw: noritake_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: noritake_device_interrupt,
init_arch: apecs_init_arch,
init_irq: noritake_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: common_init_pci,
kill_arch: NULL,
pci_map_irq: noritake_map_irq,
@@ -274,14 +305,11 @@ struct alpha_machine_vector noritake_primo_mv __initmv = {
min_mem_address: CIA_DEFAULT_MEM_BASE,
nr_irqs: 48,
- irq_probe_mask: _PROBE_MASK(48),
- update_irq_hw: noritake_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: noritake_device_interrupt,
init_arch: cia_init_arch,
init_irq: noritake_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: common_init_pci,
pci_map_irq: noritake_map_irq,
pci_swizzle: noritake_swizzle,
diff --git a/arch/alpha/kernel/sys_rawhide.c b/arch/alpha/kernel/sys_rawhide.c
index 0a0ce2267..f956626a4 100644
--- a/arch/alpha/kernel/sys_rawhide.c
+++ b/arch/alpha/kernel/sys_rawhide.c
@@ -25,53 +25,77 @@
#include <asm/core_mcpcia.h>
#include "proto.h"
-#include <asm/hw_irq.h>
+#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
+
+/*
+ * HACK ALERT! only the boot cpu is used for interrupts.
+ */
+
+
+/* Note mask bit is true for ENABLED irqs. */
+
static unsigned int hose_irq_masks[4] = {
0xff0000, 0xfe0000, 0xff0000, 0xff0000
};
+static unsigned int cached_irq_masks[4];
+static inline void
+rawhide_update_irq_hw(int hose, int mask)
+{
+ *(vuip)MCPCIA_INT_MASK0(MCPCIA_HOSE2MID(hose)) = mask;
+ mb();
+ *(vuip)MCPCIA_INT_MASK0(MCPCIA_HOSE2MID(hose));
+}
+
+static void
+rawhide_enable_irq(unsigned int irq)
+{
+ unsigned int mask, hose;
-/* Note that `mask' initially contains only the low 64 bits. */
+ irq -= 16;
+ hose = irq / 24;
+ irq -= hose * 24;
-static void
-rawhide_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+ mask = cached_irq_masks[hose] |= 1 << irq;
+ mask |= hose_irq_masks[hose];
+ rawhide_update_irq_hw(hose, mask);
+}
+
+static void
+rawhide_disable_irq(unsigned int irq)
{
- unsigned int saddle, hose, new_irq;
-
- if (irq < 16) {
- if (irq < 8)
- outb(mask, 0x21); /* ISA PIC1 */
- else
- outb(mask >> 8, 0xA1); /* ISA PIC2 */
- return;
- }
+ unsigned int mask, hose;
- saddle = (irq > 63);
- mask = _alpha_irq_masks[saddle];
+ irq -= 16;
+ hose = irq / 24;
+ irq -= hose * 24;
- if (saddle == 0) {
- /* Saddle 0 includes EISA interrupts. */
- mask >>= 16;
- new_irq = irq - 16;
- } else {
- new_irq = irq - 64;
- }
+ mask = cached_irq_masks[hose] &= ~(1 << irq);
+ mask |= hose_irq_masks[hose];
+ rawhide_update_irq_hw(hose, mask);
+}
- hose = saddle << 1;
- if (new_irq >= 24) {
- mask >>= 24;
- hose += 1;
- }
- *(vuip)MCPCIA_INT_MASK0(hose) =
- (~mask & 0x00ffffff) | hose_irq_masks[hose];
- mb();
- *(vuip)MCPCIA_INT_MASK0(hose);
+static unsigned int
+rawhide_startup_irq(unsigned int irq)
+{
+ rawhide_enable_irq(irq);
+ return 0;
}
+static struct hw_interrupt_type rawhide_irq_type = {
+ typename: "RAWHIDE",
+ startup: rawhide_startup_irq,
+ shutdown: rawhide_disable_irq,
+ enable: rawhide_enable_irq,
+ disable: rawhide_disable_irq,
+ ack: rawhide_disable_irq,
+ end: rawhide_enable_irq,
+};
+
static void
rawhide_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
@@ -97,28 +121,30 @@ rawhide_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
/* Adjust by which hose it is from. */
irq -= ((irq + 16) >> 2) & 0x38;
- handle_irq(irq, irq, regs);
+ handle_irq(irq, regs);
}
static void __init
rawhide_init_irq(void)
{
struct pci_controler *hose;
+ long i;
mcpcia_init_hoses();
- STANDARD_INIT_IRQ_PROLOG;
-
- /* HACK ALERT! Routing is only to CPU #0. */
for (hose = hose_head; hose; hose = hose->next) {
int h = hose->index;
+ rawhide_update_irq_hw(h, hose_irq_masks[h]);
+ }
- *(vuip)MCPCIA_INT_MASK0(h) = hose_irq_masks[h];
- mb();
- *(vuip)MCPCIA_INT_MASK0(h);
+ for (i = 16; i < 128; ++i) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].handler = &rawhide_irq_type;
}
- enable_irq(2);
+ init_i8259a_irqs();
+ init_rtc_irq();
+ common_init_isa_dma();
}
/*
@@ -191,14 +217,11 @@ struct alpha_machine_vector rawhide_mv __initmv = {
min_mem_address: MCPCIA_DEFAULT_MEM_BASE,
nr_irqs: 128,
- irq_probe_mask: _PROBE_MASK(128),
- update_irq_hw: rawhide_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: rawhide_srm_device_interrupt,
init_arch: mcpcia_init_arch,
init_irq: rawhide_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: common_init_pci,
kill_arch: NULL,
pci_map_irq: rawhide_map_irq,
diff --git a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c
index c03a91296..ae89e81b2 100644
--- a/arch/alpha/kernel/sys_ruffian.c
+++ b/arch/alpha/kernel/sys_ruffian.c
@@ -26,117 +26,17 @@
#include <asm/core_pyxis.h>
#include "proto.h"
-#include <asm/hw_irq.h>
+#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
-static void
-ruffian_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
-{
- if (irq >= 16) {
- /* Note inverted sense of mask bits: */
- /* Make CERTAIN none of the bogus ints get enabled... */
- *(vulp)PYXIS_INT_MASK =
- ~((long)mask >> 16) & 0x00000000ffffffbfUL;
- mb();
- /* ... and read it back to make sure it got written. */
- *(vulp)PYXIS_INT_MASK;
- }
- else if (irq >= 8)
- outb(mask >> 8, 0xA1); /* ISA PIC2 */
- else
- outb(mask, 0x21); /* ISA PIC1 */
-}
-
-static void
-ruffian_ack_irq(unsigned long irq)
-{
- if (irq < 16) {
- /* Ack PYXIS ISA interrupt. */
- *(vulp)PYXIS_INT_REQ = 1L << 7; mb();
- /* ... and read it back to make sure it got written. */
- *(vulp)PYXIS_INT_REQ;
- if (irq > 7) {
- outb(0x20, 0xa0);
- }
- outb(0x20, 0x20);
- } else {
- /* Ack PYXIS PCI interrupt. */
- *(vulp)PYXIS_INT_REQ = (1UL << (irq - 16)); mb();
- /* ... and read it back to make sure it got written. */
- *(vulp)PYXIS_INT_REQ;
- }
-}
-
-static void
-ruffian_device_interrupt(unsigned long vector, struct pt_regs *regs)
-{
- unsigned long pld;
- unsigned int i;
-
- /* Read the interrupt summary register of PYXIS */
- pld = *(vulp)PYXIS_INT_REQ;
-
- /* For now, AND off any bits we are not interested in:
- * HALT (2), timer (6), ISA Bridge (7), 21142 (8)
- * then all the PCI slots/INTXs (12-31)
- * flash(5) :DWH:
- */
- pld &= 0x00000000ffffff9fUL; /* was ffff7f */
-
- /*
- * Now for every possible bit set, work through them and call
- * the appropriate interrupt handler.
- */
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
- if (i == 7) { /* if ISA int */
- /* Ruffian does not have the RTC connected to
- the CPU timer interrupt. Instead, it uses the
- PIT connected to IRQ 0. So we must detect that
- and route that specifically to where we expected
- to find the timer interrupt come in. */
-
- /* Copy this code from isa_device_interrupt because
- we need to hook into int 0 for the timer. I
- refuse to soil device_interrupt with ifdefs. */
-
- /* Generate a PCI interrupt acknowledge cycle.
- The PIC will respond with the interrupt
- vector of the highest priority interrupt
- that is pending. The PALcode sets up the
- interrupts vectors such that irq level L
- generates vector L. */
-
- unsigned int j = *(vuip)PYXIS_IACK_SC & 0xff;
- if (j == 7 && !(inb(0x20) & 0x80)) {
- /* It's only a passive release... */
- } else if (j == 0) {
- handle_irq(TIMER_IRQ, -1, regs);
- ruffian_ack_irq(0);
- } else {
- handle_irq(j, j, regs);
- }
- } else { /* if not an ISA int */
- handle_irq(16 + i, 16 + i, regs);
- }
-
- *(vulp)PYXIS_INT_REQ = 1UL << i; mb();
- *(vulp)PYXIS_INT_REQ; /* read to force the write */
- }
-}
static void __init
ruffian_init_irq(void)
{
- STANDARD_INIT_IRQ_PROLOG;
-
/* Invert 6&7 for i82371 */
*(vulp)PYXIS_INT_HILO = 0x000000c0UL; mb();
*(vulp)PYXIS_INT_CNFG = 0x00002064UL; mb(); /* all clear */
- *(vulp)PYXIS_INT_MASK = 0x00000000UL; mb();
- *(vulp)PYXIS_INT_REQ = 0xffffffffUL; mb();
outb(0x11,0xA0);
outb(0x08,0xA1);
@@ -150,17 +50,54 @@ ruffian_init_irq(void)
outb(0x01,0x21);
outb(0xFF,0x21);
- /* Send -INTA pulses to clear any pending interrupts ...*/
- *(vuip) PYXIS_IACK_SC;
-
/* Finish writing the 82C59A PIC Operation Control Words */
outb(0x20,0xA0);
outb(0x20,0x20);
- /* Turn on the interrupt controller, the timer interrupt */
- enable_irq(16 + 7); /* enable ISA PIC cascade */
- enable_irq(0); /* enable timer */
- enable_irq(2); /* enable 2nd PIC cascade */
+ init_i8259a_irqs();
+
+ /* Not interested in the bogus interrupts (0,3,4,6),
+ NMI (1), HALT (2), flash (5), or 21142 (8). */
+ init_pyxis_irqs(0x17f0000);
+
+ common_init_isa_dma();
+}
+
+static void __init
+ruffian_init_rtc(struct irqaction *action)
+{
+ /* Ruffian does not have the RTC connected to the CPU timer
+ interrupt. Instead, it uses the PIT connected to IRQ 0. */
+
+ /* Setup interval timer. */
+ outb(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */
+ outb(LATCH & 0xff, 0x40); /* LSB */
+ outb(LATCH >> 8, 0x40); /* MSB */
+
+ outb(0xb6, 0x43); /* pit counter 2: speaker */
+ outb(0x31, 0x42);
+ outb(0x13, 0x42);
+
+ setup_irq(0, action);
+}
+
+static void
+ruffian_kill_arch (int mode)
+{
+#if 0
+ /* This only causes re-entry to ARCSBIOS */
+ /* Perhaps this works for other PYXIS as well? */
+ *(vuip) PYXIS_RESET = 0x0000dead;
+ mb();
+#endif
+}
+
+static int __init
+ruffian_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ /* We don't know anything about the PCI routing, so leave
+ the IRQ unchanged. */
+ return dev->irq;
}
@@ -203,34 +140,6 @@ ruffian_get_bank_size(unsigned long offset)
}
#endif /* BUILDING_FOR_MILO */
-static void
-ruffian_init_pit (void)
-{
- outb(0xb6, 0x43); /* pit counter 2: speaker */
- outb(0x31, 0x42);
- outb(0x13, 0x42);
-}
-
-static void
-ruffian_kill_arch (int mode)
-{
-#if 0
- /* This only causes re-entry to ARCSBIOS */
- /* Perhaps this works for other PYXIS as well? */
- *(vuip) PYXIS_RESET = 0x0000dead;
- mb();
-#endif
-}
-
-static int __init
-ruffian_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- /* We don't know anything about the PCI routing, so leave
- the IRQ unchanged. */
- return dev->irq;
-}
-
-
/*
* The System Vector
*/
@@ -247,14 +156,11 @@ struct alpha_machine_vector ruffian_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 48,
- irq_probe_mask: RUFFIAN_PROBE_MASK,
- update_irq_hw: ruffian_update_irq_hw,
- ack_irq: ruffian_ack_irq,
- device_interrupt: ruffian_device_interrupt,
+ device_interrupt: pyxis_device_interrupt,
init_arch: pyxis_init_arch,
init_irq: ruffian_init_irq,
- init_pit: ruffian_init_pit,
+ init_rtc: ruffian_init_rtc,
init_pci: common_init_pci,
kill_arch: ruffian_kill_arch,
pci_map_irq: ruffian_map_irq,
diff --git a/arch/alpha/kernel/sys_rx164.c b/arch/alpha/kernel/sys_rx164.c
index 969d3561f..d5299d008 100644
--- a/arch/alpha/kernel/sys_rx164.c
+++ b/arch/alpha/kernel/sys_rx164.c
@@ -26,121 +26,103 @@
#include <asm/core_polaris.h>
#include "proto.h"
-#include <asm/hw_irq.h>
+#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
-static void
-rx164_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+/* Note mask bit is true for ENABLED irqs. */
+static unsigned long cached_irq_mask;
+
+/* Bus 0, Device 0. Nothing else matters, since we invoke the
+ POLARIS routines directly. */
+static struct pci_dev rx164_system;
+
+static inline void
+rx164_update_irq_hw(unsigned long mask)
{
- if (irq >= 16) {
- unsigned int temp;
- pcibios_write_config_dword(0, 0, 0x74, ~mask >> 16);
- pcibios_read_config_dword(0, 0, 0x74, &temp);
- }
- else if (irq >= 8)
- outb(mask >> 8, 0xA1); /* ISA PIC2 */
- else
- outb(mask, 0x21); /* ISA PIC1 */
+ unsigned int temp;
+ polaris_write_config_dword(&rx164_system, 0x74, mask);
+ polaris_read_config_dword(&rx164_system, 0x74, &temp);
}
-#if 0
-static void
-rx164_srm_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+static inline void
+rx164_enable_irq(unsigned int irq)
{
- if (irq >= 16) {
- if (unmask_p)
- cserve_ena(irq - 16);
- else
- cserve_dis(irq - 16);
- }
- else if (irq >= 8)
- outb(mask >> 8, 0xA1); /* ISA PIC2 */
- else
- outb(mask, 0x21); /* ISA PIC1 */
+ rx164_update_irq_hw(cached_irq_mask |= 1UL << (irq - 16));
}
-#endif
static void
-rx164_isa_device_interrupt(unsigned long vector, struct pt_regs * regs)
+rx164_disable_irq(unsigned int irq)
+{
+ rx164_update_irq_hw(cached_irq_mask &= ~(1UL << (irq - 16)));
+}
+
+static unsigned int
+rx164_startup_irq(unsigned int irq)
{
- unsigned long pic;
-
- /*
- * It seems to me that the probability of two or more *device*
- * interrupts occurring at almost exactly the same time is
- * pretty low. So why pay the price of checking for
- * additional interrupts here if the common case can be
- * handled so much easier?
- */
- /*
- * The first read of the PIC gives you *all* interrupting lines.
- * Therefore, read the mask register and and out those lines
- * not enabled. Note that some documentation has 21 and a1
- * write only. This is not true.
- */
- pic = inb(0x20) | (inb(0xA0) << 8); /* read isr */
- pic &= ~alpha_irq_mask; /* apply mask */
- pic &= 0xFFFB; /* mask out cascade & hibits */
-
- while (pic) {
- int j = ffz(~pic);
- pic &= pic - 1;
- handle_irq(j, j, regs);
- }
+ rx164_enable_irq(irq);
+ return 0;
}
+static struct hw_interrupt_type rx164_irq_type = {
+ typename: "RX164",
+ startup: rx164_startup_irq,
+ shutdown: rx164_disable_irq,
+ enable: rx164_enable_irq,
+ disable: rx164_disable_irq,
+ ack: rx164_disable_irq,
+ end: rx164_enable_irq,
+};
+
static void
rx164_device_interrupt(unsigned long vector, struct pt_regs *regs)
{
+ unsigned int temp;
unsigned long pld;
- int i;
-
- /* Read the interrupt summary register. On Polaris,
- * this is the DIRR register in PCI config space (offset 0x84)
- */
- pld = 0;
- pcibios_read_config_dword(0, 0, 0x84, (unsigned int *)&pld);
-
-#if 0
- printk("PLD 0x%lx\n", pld);
-#endif
-
- if (pld & 0xffffffff00000000UL)
- pld &= 0x00000000ffffffffUL;
-
- /*
- * Now for every possible bit set, work through them and call
- * the appropriate interrupt handler.
- */
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
- if (i == 20) {
- rx164_isa_device_interrupt(vector, regs);
- } else {
- handle_irq(16+i, 16+i, regs);
- }
- }
+ long i;
+
+ /* Read the interrupt summary register. On Polaris, this is
+ the DIRR register in PCI config space (offset 0x84). */
+ polaris_read_config_dword(&rx164_system, 0x84, &temp);
+ pld = temp;
+
+ /*
+ * Now for every possible bit set, work through them and call
+ * the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+ if (i == 20) {
+ isa_no_iack_sc_device_interrupt(vector, regs);
+ } else {
+ handle_irq(16+i, regs);
+ }
+ }
}
-static void
+static void __init
rx164_init_irq(void)
{
- unsigned int temp;
+ long i;
- STANDARD_INIT_IRQ_PROLOG;
+ rx164_update_irq_hw(0);
+ for (i = 16; i < 40; ++i) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].handler = &rx164_irq_type;
+ }
- pcibios_write_config_dword(0, 0, 0x74, (~alpha_irq_mask >> 16));
- pcibios_read_config_dword(0, 0, 0x74, &temp);
+ init_i8259a_irqs();
+ init_rtc_irq();
+ common_init_isa_dma();
- enable_irq(16 + 20); /* enable ISA interrupts */
- enable_irq(2); /* enable cascade */
+ setup_irq(16+20, &isa_cascade_irqaction);
}
-/* The RX164 changed its interrupt routing between pass1 and pass2...
+/*
+ * The RX164 changed its interrupt routing between pass1 and pass2...
*
* PASS1:
*
@@ -176,29 +158,29 @@ static int __init
rx164_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
#if 0
- char irq_tab_pass1[6][5] = {
- /*INT INTA INTB INTC INTD */
- { 16+3, 16+3, 16+8, 16+13, 16+18}, /* IdSel 5, slot 2 */
- { 16+5, 16+5, 16+10, 16+15, 16+20}, /* IdSel 6, slot 0 */
- { 16+4, 16+4, 16+9, 16+14, 16+19}, /* IdSel 7, slot 1 */
- { -1, -1, -1, -1, -1}, /* IdSel 8, PCI/ISA bridge */
- { 16+2, 16+2, 16+7, 16+12, 16+17}, /* IdSel 9, slot 3 */
- { 16+1, 16+1, 16+6, 16+11, 16+16}, /* IdSel 10, slot 4 */
- };
+ static char irq_tab_pass1[6][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ { 16+3, 16+3, 16+8, 16+13, 16+18}, /* IdSel 5, slot 2 */
+ { 16+5, 16+5, 16+10, 16+15, 16+20}, /* IdSel 6, slot 0 */
+ { 16+4, 16+4, 16+9, 16+14, 16+19}, /* IdSel 7, slot 1 */
+ { -1, -1, -1, -1, -1}, /* IdSel 8, PCI/ISA bridge */
+ { 16+2, 16+2, 16+7, 16+12, 16+17}, /* IdSel 9, slot 3 */
+ { 16+1, 16+1, 16+6, 16+11, 16+16}, /* IdSel 10, slot 4 */
+ };
#else
- char irq_tab[6][5] = {
- /*INT INTA INTB INTC INTD */
- { 16+0, 16+0, 16+6, 16+11, 16+16}, /* IdSel 5, slot 0 */
- { 16+1, 16+1, 16+7, 16+12, 16+17}, /* IdSel 6, slot 1 */
- { -1, -1, -1, -1, -1}, /* IdSel 7, PCI/ISA bridge */
- { 16+2, 16+2, 16+8, 16+13, 16+18}, /* IdSel 8, slot 2 */
- { 16+3, 16+3, 16+9, 16+14, 16+19}, /* IdSel 9, slot 3 */
- { 16+4, 16+4, 16+10, 16+15, 16+5}, /* IdSel 10, PCI-PCI */
- };
+ static char irq_tab[6][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ { 16+0, 16+0, 16+6, 16+11, 16+16}, /* IdSel 5, slot 0 */
+ { 16+1, 16+1, 16+7, 16+12, 16+17}, /* IdSel 6, slot 1 */
+ { -1, -1, -1, -1, -1}, /* IdSel 7, PCI/ISA bridge */
+ { 16+2, 16+2, 16+8, 16+13, 16+18}, /* IdSel 8, slot 2 */
+ { 16+3, 16+3, 16+9, 16+14, 16+19}, /* IdSel 9, slot 3 */
+ { 16+4, 16+4, 16+10, 16+15, 16+5}, /* IdSel 10, PCI-PCI */
+ };
#endif
const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5;
- /* JRP - Need to figure out how to distinguish pass1 from pass2,
+ /* JRP - Need to figure out how to distinguish pass1 from pass2,
and use the correct table. */
return COMMON_TABLE_LOOKUP;
}
@@ -220,14 +202,11 @@ struct alpha_machine_vector rx164_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 40,
- irq_probe_mask: _PROBE_MASK(40),
- update_irq_hw: rx164_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: rx164_device_interrupt,
init_arch: polaris_init_arch,
init_irq: rx164_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: common_init_pci,
kill_arch: NULL,
pci_map_irq: rx164_map_irq,
diff --git a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c
index 53afe259b..e2a69b5c7 100644
--- a/arch/alpha/kernel/sys_sable.c
+++ b/arch/alpha/kernel/sys_sable.c
@@ -26,7 +26,7 @@
#include <asm/core_t2.h>
#include "proto.h"
-#include <asm/hw_irq.h>
+#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
@@ -38,15 +38,43 @@
* 0-7 (char at 536)
* 8-15 (char at 53a)
* 16-23 (char at 53c)
+ *
+ * Summary Registers (536/53a/53c):
+ *
+ * Bit Meaning Kernel IRQ
+ *------------------------------------------
+ * 0 PCI slot 0 34
+ * 1 NCR810 (builtin) 33
+ * 2 TULIP (builtin) 32
+ * 3 mouse 12
+ * 4 PCI slot 1 35
+ * 5 PCI slot 2 36
+ * 6 keyboard 1
+ * 7 floppy 6
+ * 8 COM2 3
+ * 9 parallel port 7
+ *10 EISA irq 3 -
+ *11 EISA irq 4 -
+ *12 EISA irq 5 5
+ *13 EISA irq 6 -
+ *14 EISA irq 7 -
+ *15 COM1 4
+ *16 EISA irq 9 9
+ *17 EISA irq 10 10
+ *18 EISA irq 11 11
+ *19 EISA irq 12 -
+ *20 EISA irq 13 -
+ *21 EISA irq 14 14
+ *22 NC 15
+ *23 IIC -
*/
-/* Note that the vector reported by the SRM PALcode corresponds to the
- interrupt mask bits, but we have to manage via more normal IRQs. */
-
static struct
{
char irq_to_mask[40];
char mask_to_irq[40];
+
+ /* Note mask bit is true for DISABLED irqs. */
unsigned long shadow_mask;
} sable_irq_swizzle = {
{
@@ -54,61 +82,103 @@ static struct
-1, 16, 17, 18, 3, -1, 21, 22, /* pseudo PIC 8-15 */
-1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 0-7 */
-1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 8-15 */
- 2, 1, 0, 4, 5, -1, -1, -1, /* pseudo PCI */
+ 2, 1, 0, 4, 5, -1, -1, -1, /* pseudo PCI */
},
{
34, 33, 32, 12, 35, 36, 1, 6, /* mask 0-7 */
- 3, 7, -1, -1, 5, -1, -1, 4, /* mask 8-15 */
- 9, 10, 11, -1, -1, 14, 15, -1, /* mask 16-23 */
+ 3, 7, -1, -1, 5, -1, -1, 4, /* mask 8-15 */
+ 9, 10, 11, -1, -1, 14, 15, -1, /* mask 16-23 */
},
- 0
+ -1
};
+static inline void
+sable_update_irq_hw(unsigned long bit, unsigned long mask)
+{
+ int port = 0x536;
+
+ if (bit >= 16) {
+ port = 0x53d;
+ mask >>= 16;
+ } else if (bit >= 8) {
+ port = 0x53b;
+ mask >>= 8;
+ }
-static void
-sable_update_irq_hw(unsigned long irq, unsigned long unused_mask, int unmask_p)
+ outb(mask, port);
+}
+
+static inline void
+sable_ack_irq_hw(unsigned long bit)
+{
+ int port, val1, val2;
+
+ if (bit >= 16) {
+ port = 0x53c;
+ val1 = 0xE0 | (bit - 16);
+ val2 = 0xE0 | 4;
+ } else if (bit >= 8) {
+ port = 0x53a;
+ val1 = 0xE0 | (bit - 8);
+ val2 = 0xE0 | 2;
+ } else {
+ port = 0x536;
+ val1 = 0xE0 | (bit - 0);
+ val2 = 0xE0 | 1;
+ }
+
+ outb(val1, port); /* ack the slave */
+ outb(val2, 0x534); /* ack the master */
+}
+
+static inline void
+sable_enable_irq(unsigned int irq)
{
unsigned long bit, mask;
- /* The "irq" argument is really the irq, but we need it to
- be the mask bit number. Convert it now. */
-
- irq = sable_irq_swizzle.irq_to_mask[irq];
- bit = 1UL << irq;
- mask = sable_irq_swizzle.shadow_mask | bit;
- if (unmask_p)
- mask &= ~bit;
- sable_irq_swizzle.shadow_mask = mask;
-
- /* The "irq" argument is now really the mask bit number. */
- if (irq <= 7)
- outb(mask, 0x537);
- else if (irq <= 15)
- outb(mask >> 8, 0x53b);
- else
- outb(mask >> 16, 0x53d);
+ bit = sable_irq_swizzle.irq_to_mask[irq];
+ mask = sable_irq_swizzle.shadow_mask &= ~(1UL << bit);
+ sable_update_irq_hw(bit, mask);
}
static void
-sable_ack_irq(unsigned long irq)
+sable_disable_irq(unsigned int irq)
{
- /* Note that the "irq" here is really the mask bit number */
- switch (irq) {
- case 0 ... 7:
- outb(0xE0 | (irq - 0), 0x536);
- outb(0xE0 | 1, 0x534); /* slave 0 */
- break;
- case 8 ... 15:
- outb(0xE0 | (irq - 8), 0x53a);
- outb(0xE0 | 3, 0x534); /* slave 1 */
- break;
- case 16 ... 24:
- outb(0xE0 | (irq - 16), 0x53c);
- outb(0xE0 | 4, 0x534); /* slave 2 */
- break;
- }
+ unsigned long bit, mask;
+
+ bit = sable_irq_swizzle.irq_to_mask[irq];
+ mask = sable_irq_swizzle.shadow_mask |= 1UL << bit;
+ sable_update_irq_hw(bit, mask);
}
+static unsigned int
+sable_startup_irq(unsigned int irq)
+{
+ sable_enable_irq(irq);
+ return 0;
+}
+
+static void
+sable_mask_and_ack_irq(unsigned int irq)
+{
+ unsigned long bit, mask;
+
+ bit = sable_irq_swizzle.irq_to_mask[irq];
+ mask = sable_irq_swizzle.shadow_mask |= 1UL << bit;
+ sable_update_irq_hw(bit, mask);
+ sable_ack_irq_hw(bit);
+}
+
+static struct hw_interrupt_type sable_irq_type = {
+ typename: "SABLE",
+ startup: sable_startup_irq,
+ shutdown: sable_disable_irq,
+ enable: sable_enable_irq,
+ disable: sable_disable_irq,
+ ack: sable_mask_and_ack_irq,
+ end: sable_enable_irq,
+};
+
static void
sable_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
@@ -116,64 +186,36 @@ sable_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
to the interrupt mask bits, but we have to manage via more
normal IRQs. */
- int irq, ack;
-
- ack = irq = (vector - 0x800) >> 4;
-
- irq = sable_irq_swizzle.mask_to_irq[(ack)];
-#if 0
- if (irq == 5 || irq == 9 || irq == 10 || irq == 11 ||
- irq == 14 || irq == 15)
- printk("srm_device_interrupt: vector=0x%lx ack=0x%x"
- " irq=0x%x\n", vector, ack, irq);
-#endif
+ int bit, irq;
- handle_irq(irq, ack, regs);
+ bit = (vector - 0x800) >> 4;
+ irq = sable_irq_swizzle.mask_to_irq[bit];
+ handle_irq(irq, regs);
}
static void __init
sable_init_irq(void)
{
- STANDARD_INIT_IRQ_PROLOG;
+ long i;
- outb(alpha_irq_mask , 0x537); /* slave 0 */
- outb(alpha_irq_mask >> 8, 0x53b); /* slave 1 */
- outb(alpha_irq_mask >> 16, 0x53d); /* slave 2 */
- outb(0x44, 0x535); /* enable cascades in master */
+ outb(-1, 0x537); /* slave 0 */
+ outb(-1, 0x53b); /* slave 1 */
+ outb(-1, 0x53d); /* slave 2 */
+ outb(0x44, 0x535); /* enable cascades in master */
+
+ for (i = 0; i < 40; ++i) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].handler = &sable_irq_type;
+ }
+
+ init_rtc_irq();
+ common_init_isa_dma();
}
/*
* PCI Fixup configuration for ALPHA SABLE (2100) - 2100A is different ??
*
- * Summary Registers (536/53a/53c):
- * Bit Meaning
- *-----------------
- * 0 PCI slot 0
- * 1 NCR810 (builtin)
- * 2 TULIP (builtin)
- * 3 mouse
- * 4 PCI slot 1
- * 5 PCI slot 2
- * 6 keyboard
- * 7 floppy
- * 8 COM2
- * 9 parallel port
- *10 EISA irq 3
- *11 EISA irq 4
- *12 EISA irq 5
- *13 EISA irq 6
- *14 EISA irq 7
- *15 COM1
- *16 EISA irq 9
- *17 EISA irq 10
- *18 EISA irq 11
- *19 EISA irq 12
- *20 EISA irq 13
- *21 EISA irq 14
- *22 NC
- *23 IIC
- *
* The device to slot mapping looks like:
*
* Slot Device
@@ -239,14 +281,11 @@ struct alpha_machine_vector sable_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 40,
- irq_probe_mask: _PROBE_MASK(40),
- update_irq_hw: sable_update_irq_hw,
- ack_irq: sable_ack_irq,
device_interrupt: sable_srm_device_interrupt,
init_arch: t2_init_arch,
init_irq: sable_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: common_init_pci,
kill_arch: NULL,
pci_map_irq: sable_map_irq,
@@ -274,14 +313,11 @@ struct alpha_machine_vector sable_gamma_mv __initmv = {
min_mem_address: DEFAULT_MEM_BASE,
nr_irqs: 40,
- irq_probe_mask: _PROBE_MASK(40),
- update_irq_hw: sable_update_irq_hw,
- ack_irq: sable_ack_irq,
device_interrupt: sable_srm_device_interrupt,
init_arch: t2_init_arch,
init_irq: sable_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: common_init_pci,
pci_map_irq: sable_map_irq,
pci_swizzle: common_swizzle,
diff --git a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c
index 2359755bf..ccdcf3bdb 100644
--- a/arch/alpha/kernel/sys_sio.c
+++ b/arch/alpha/kernel/sys_sio.c
@@ -30,28 +30,20 @@
#include <asm/core_lca.h>
#include "proto.h"
-#include <asm/hw_irq.h>
+#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
-static void
-sio_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
-{
- if (irq >= 8)
- outb(mask >> 8, 0xA1);
- else
- outb(mask, 0x21);
-}
static void __init
sio_init_irq(void)
{
- STANDARD_INIT_IRQ_PROLOG;
-
if (alpha_using_srm)
alpha_mv.device_interrupt = srm_device_interrupt;
-
- enable_irq(2); /* enable cascade */
+
+ init_i8259a_irqs();
+ init_rtc_irq();
+ common_init_isa_dma();
}
static inline void __init
@@ -270,14 +262,11 @@ struct alpha_machine_vector alphabook1_mv __initmv = {
min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 16,
- irq_probe_mask: _PROBE_MASK(16),
- update_irq_hw: sio_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: isa_device_interrupt,
init_arch: alphabook1_init_arch,
init_irq: sio_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: alphabook1_init_pci,
kill_arch: NULL,
pci_map_irq: noname_map_irq,
@@ -304,14 +293,11 @@ struct alpha_machine_vector avanti_mv __initmv = {
min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 16,
- irq_probe_mask: _PROBE_MASK(16),
- update_irq_hw: sio_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: isa_device_interrupt,
init_arch: apecs_init_arch,
init_irq: sio_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: noname_init_pci,
pci_map_irq: noname_map_irq,
pci_swizzle: common_swizzle,
@@ -336,14 +322,11 @@ struct alpha_machine_vector noname_mv __initmv = {
min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 16,
- irq_probe_mask: _PROBE_MASK(16),
- update_irq_hw: sio_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: srm_device_interrupt,
init_arch: lca_init_arch,
init_irq: sio_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: noname_init_pci,
pci_map_irq: noname_map_irq,
pci_swizzle: common_swizzle,
@@ -377,14 +360,11 @@ struct alpha_machine_vector p2k_mv __initmv = {
min_mem_address: APECS_AND_LCA_DEFAULT_MEM_BASE,
nr_irqs: 16,
- irq_probe_mask: P2K_PROBE_MASK,
- update_irq_hw: sio_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: srm_device_interrupt,
init_arch: lca_init_arch,
init_irq: sio_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: noname_init_pci,
pci_map_irq: p2k_map_irq,
pci_swizzle: common_swizzle,
@@ -409,14 +389,11 @@ struct alpha_machine_vector xl_mv __initmv = {
min_mem_address: XL_DEFAULT_MEM_BASE,
nr_irqs: 16,
- irq_probe_mask: _PROBE_MASK(16),
- update_irq_hw: sio_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: isa_device_interrupt,
init_arch: lca_init_arch,
init_irq: sio_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: noname_init_pci,
pci_map_irq: noname_map_irq,
pci_swizzle: common_swizzle,
diff --git a/arch/alpha/kernel/sys_sx164.c b/arch/alpha/kernel/sys_sx164.c
index 6ad08e442..806241a32 100644
--- a/arch/alpha/kernel/sys_sx164.c
+++ b/arch/alpha/kernel/sys_sx164.c
@@ -26,81 +26,12 @@
#include <asm/core_pyxis.h>
#include "proto.h"
-#include <asm/hw_irq.h>
+#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
-static void
-sx164_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
-{
- if (irq >= 16) {
- /* Make CERTAIN none of the bogus ints get enabled */
- *(vulp)PYXIS_INT_MASK =
- ~((long)mask >> 16) & ~0x000000000000003bUL;
- mb();
- /* ... and read it back to make sure it got written. */
- *(vulp)PYXIS_INT_MASK;
- }
- else if (irq >= 8)
- outb(mask >> 8, 0xA1); /* ISA PIC2 */
- else
- outb(mask, 0x21); /* ISA PIC1 */
-}
-
-static void
-sx164_srm_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
-{
- if (irq >= 16) {
- if (unmask_p)
- cserve_ena(irq - 16);
- else
- cserve_dis(irq - 16);
- }
- else if (irq >= 8)
- outb(mask >> 8, 0xA1); /* ISA PIC2 */
- else
- outb(mask, 0x21); /* ISA PIC1 */
-}
-
-static void
-sx164_device_interrupt(unsigned long vector, struct pt_regs *regs)
-{
- unsigned long pld, tmp;
- unsigned int i;
-
- /* Read the interrupt summary register of PYXIS */
- pld = *(vulp)PYXIS_INT_REQ;
-
- /*
- * For now, AND off any bits we are not interested in:
- * HALT (2), timer (6), ISA Bridge (7)
- * then all the PCI slots/INTXs (8-23)
- */
- /* Maybe HALT should only be used for SRM console boots? */
- pld &= 0x0000000000ffffc0UL;
-
- /*
- * Now for every possible bit set, work through them and call
- * the appropriate interrupt handler.
- */
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
- if (i == 7) {
- isa_device_interrupt(vector, regs);
- } else if (i == 6) {
- continue;
- } else {
- /* if not timer int */
- handle_irq(16 + i, 16 + i, regs);
- }
- *(vulp)PYXIS_INT_REQ = 1UL << i; mb();
- tmp = *(vulp)PYXIS_INT_REQ;
- }
-}
-
-static void
+static void __init
sx164_init_irq(void)
{
outb(0, DMA1_RESET_REG);
@@ -108,20 +39,20 @@ sx164_init_irq(void)
outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
outb(0, DMA2_MASK_REG);
- if (alpha_using_srm) {
- alpha_mv.update_irq_hw = sx164_srm_update_irq_hw;
+ if (alpha_using_srm)
alpha_mv.device_interrupt = srm_device_interrupt;
- }
- else {
- /* Note invert on MASK bits. */
- *(vulp)PYXIS_INT_MASK = ~((long)alpha_irq_mask >> 16);
- mb();
- *(vulp)PYXIS_INT_MASK;
- }
-
- enable_irq(16 + 6); /* enable timer */
- enable_irq(16 + 7); /* enable ISA PIC cascade */
- enable_irq(2); /* enable cascade */
+
+ init_i8259a_irqs();
+ init_rtc_irq();
+
+ /* Not interested in the bogus interrupts (0,3,4,5,40-47),
+ NMI (1), or HALT (2). */
+ if (alpha_using_srm)
+ init_srm_irqs(40, 0x3f0000);
+ else
+ init_pyxis_irqs(0xff00003f0000);
+
+ setup_irq(16+6, &timer_cascade_irqaction);
}
/*
@@ -160,7 +91,6 @@ sx164_init_irq(void)
* 7 64 bit PCI option slot 1
* 8 Cypress I/O
* 9 32 bit PCI option slot 3
- *
*/
static int __init
@@ -201,15 +131,12 @@ struct alpha_machine_vector sx164_mv __initmv = {
min_io_address: DEFAULT_IO_BASE,
min_mem_address: DEFAULT_MEM_BASE,
- nr_irqs: 40,
- irq_probe_mask: _PROBE_MASK(40),
- update_irq_hw: sx164_update_irq_hw,
- ack_irq: common_ack_irq,
- device_interrupt: sx164_device_interrupt,
+ nr_irqs: 48,
+ device_interrupt: pyxis_device_interrupt,
init_arch: pyxis_init_arch,
init_irq: sx164_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: sx164_init_pci,
kill_arch: NULL,
pci_map_irq: sx164_map_irq,
diff --git a/arch/alpha/kernel/sys_takara.c b/arch/alpha/kernel/sys_takara.c
index a17cd4de6..360f135b6 100644
--- a/arch/alpha/kernel/sys_takara.c
+++ b/arch/alpha/kernel/sys_takara.c
@@ -25,32 +25,58 @@
#include <asm/core_cia.h>
#include "proto.h"
-#include <asm/hw_irq.h>
+#include "irq_impl.h"
#include "pci_impl.h"
#include "machvec_impl.h"
-static void
-takara_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+/* Note mask bit is true for DISABLED irqs. */
+static unsigned long cached_irq_mask[2] = { -1, -1 };
+
+static inline void
+takara_update_irq_hw(unsigned long irq, unsigned long mask)
{
- unsigned int regaddr;
+ int regaddr;
- if (irq <= 15) {
- if (irq <= 7)
- outb(mask, 0x21); /* ISA PIC1 */
- else
- outb(mask >> 8, 0xA1); /* ISA PIC2 */
- } else {
- if (irq > 63)
- mask = _alpha_irq_masks[1] << 16;
- else
- mask = mask >> ((irq - 16) & 0x30);
- regaddr = 0x510 + (((irq - 16) >> 2) & 0x0c);
- outl(mask & 0xffff0000UL, regaddr);
- }
+ mask = (irq >= 64 ? mask << 16 : mask >> ((irq - 16) & 0x30));
+ regaddr = 0x510 + (((irq - 16) >> 2) & 0x0c);
+ outl(mask & 0xffff0000UL, regaddr);
+}
+
+static inline void
+takara_enable_irq(unsigned int irq)
+{
+ unsigned long mask;
+ mask = (cached_irq_mask[irq >= 64] &= ~(1UL << (irq & 63)));
+ takara_update_irq_hw(irq, mask);
}
static void
+takara_disable_irq(unsigned int irq)
+{
+ unsigned long mask;
+ mask = (cached_irq_mask[irq >= 64] |= 1UL << (irq & 63));
+ takara_update_irq_hw(irq, mask);
+}
+
+static unsigned int
+takara_startup_irq(unsigned int irq)
+{
+ takara_enable_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type takara_irq_type = {
+ typename: "TAKARA",
+ startup: takara_startup_irq,
+ shutdown: takara_disable_irq,
+ enable: takara_enable_irq,
+ disable: takara_disable_irq,
+ ack: takara_disable_irq,
+ end: takara_enable_irq,
+};
+
+static void
takara_device_interrupt(unsigned long vector, struct pt_regs *regs)
{
unsigned intstatus;
@@ -78,10 +104,10 @@ takara_device_interrupt(unsigned long vector, struct pt_regs *regs)
* despatch an interrupt if it's set.
*/
- if (intstatus & 8) handle_irq(16+3, 16+3, regs);
- if (intstatus & 4) handle_irq(16+2, 16+2, regs);
- if (intstatus & 2) handle_irq(16+1, 16+1, regs);
- if (intstatus & 1) handle_irq(16+0, 16+0, regs);
+ if (intstatus & 8) handle_irq(16+3, regs);
+ if (intstatus & 4) handle_irq(16+2, regs);
+ if (intstatus & 2) handle_irq(16+1, regs);
+ if (intstatus & 1) handle_irq(16+0, regs);
} else {
isa_device_interrupt (vector, regs);
}
@@ -91,13 +117,16 @@ static void
takara_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
int irq = (vector - 0x800) >> 4;
- handle_irq(irq, irq, regs);
+ handle_irq(irq, regs);
}
static void __init
takara_init_irq(void)
{
- STANDARD_INIT_IRQ_PROLOG;
+ long i;
+
+ init_i8259a_irqs();
+ init_rtc_irq();
if (alpha_using_srm) {
alpha_mv.device_interrupt = takara_srm_device_interrupt;
@@ -113,9 +142,18 @@ takara_init_irq(void)
outl(ctlreg, 0x500);
}
- enable_irq(2);
+ for (i = 16; i < 128; i += 16)
+ takara_update_irq_hw(i, -1);
+
+ for (i = 16; i < 128; ++i) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].handler = &takara_irq_type;
+ }
+
+ common_init_isa_dma();
}
+
/*
* The Takara has PCI devices 1, 2, and 3 configured to slots 20,
* 19, and 18 respectively, in the default configuration. They can
@@ -235,14 +273,11 @@ struct alpha_machine_vector takara_mv __initmv = {
min_mem_address: CIA_DEFAULT_MEM_BASE,
nr_irqs: 128,
- irq_probe_mask: _PROBE_MASK(48),
- update_irq_hw: takara_update_irq_hw,
- ack_irq: common_ack_irq,
device_interrupt: takara_device_interrupt,
init_arch: cia_init_arch,
init_irq: takara_init_irq,
- init_pit: common_init_pit,
+ init_rtc: common_init_rtc,
init_pci: takara_init_pci,
kill_arch: NULL,
pci_map_irq: takara_map_irq,
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index 6e528e08f..8211045e8 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -31,6 +31,8 @@
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -40,7 +42,7 @@
#include <linux/timex.h>
#include "proto.h"
-#include <asm/hw_irq.h>
+#include "irq_impl.h"
extern rwlock_t xtime_lock;
extern volatile unsigned long lost_ticks; /* kernel/sched.c */
@@ -88,13 +90,7 @@ void timer_interrupt(int irq, void *dev, struct pt_regs * regs)
__u32 now;
long nticks;
-#ifdef __SMP__
- /* When SMP, do this for *all* CPUs, but only do the rest for
- the boot CPU. */
- smp_percpu_timer_interrupt(regs);
- if (smp_processor_id() != smp_boot_cpuid)
- return;
-#else
+#ifndef __SMP__
/* Not SMP, do kernel PC profiling here. */
if (!user_mode(regs))
alpha_do_profile(regs->pc);
@@ -167,55 +163,8 @@ static inline unsigned long mktime(unsigned int year, unsigned int mon,
)*60 + sec; /* finally seconds */
}
-/*
- * Initialize Programmable Interval Timers with standard values. Some
- * drivers depend on them being initialized (e.g., joystick driver).
- */
-
-#ifdef CONFIG_RTC
void
-rtc_init_pit(void)
-{
- unsigned char control;
-
- /* Turn off RTC interrupts before /dev/rtc is initialized */
- control = CMOS_READ(RTC_CONTROL);
- control &= ~(RTC_PIE | RTC_AIE | RTC_UIE);
- CMOS_WRITE(control, RTC_CONTROL);
- (void) CMOS_READ(RTC_INTR_FLAGS);
-
- /* Setup interval timer. */
- outb(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */
- outb(LATCH & 0xff, 0x40); /* LSB */
- outb(LATCH >> 8, 0x40); /* MSB */
-
- outb(0xb6, 0x43); /* pit counter 2: speaker */
- outb(0x31, 0x42);
- outb(0x13, 0x42);
-}
-
-void
-rtc_kill_pit(void)
-{
- unsigned char control;
-
- cli();
-
- /* Reset periodic interrupt frequency. */
- CMOS_WRITE(0x26, RTC_FREQ_SELECT);
-
- /* Turn on periodic interrupts. */
- control = CMOS_READ(RTC_CONTROL);
- control |= RTC_PIE;
- CMOS_WRITE(control, RTC_CONTROL);
- CMOS_READ(RTC_INTR_FLAGS);
-
- sti();
-}
-#endif
-
-void
-common_init_pit (void)
+common_init_rtc(struct irqaction *action)
{
unsigned char x;
@@ -243,12 +192,19 @@ common_init_pit (void)
outb(0xb6, 0x43); /* pit counter 2: speaker */
outb(0x31, 0x42);
outb(0x13, 0x42);
+
+ setup_irq(RTC_IRQ, action);
}
void
time_init(void)
{
- void (*irq_handler)(int, void *, struct pt_regs *);
+ static struct irqaction timer_irqaction = {
+ handler: timer_interrupt,
+ flags: SA_INTERRUPT,
+ name: "timer",
+ };
+
unsigned int year, mon, day, hour, min, sec, cc1, cc2;
unsigned long cycle_freq, one_percent;
long diff;
@@ -336,10 +292,8 @@ time_init(void)
state.last_rtc_update = 0;
state.partial_tick = 0L;
- /* setup timer */
- irq_handler = timer_interrupt;
- if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL))
- panic("Could not allocate timer IRQ!");
+ /* Startup the timer source. */
+ alpha_mv.init_rtc(&timer_irqaction);
}
/*
diff --git a/arch/alpha/lib/csum_ipv6_magic.S b/arch/alpha/lib/csum_ipv6_magic.S
index 495375a1a..5a6e69c54 100644
--- a/arch/alpha/lib/csum_ipv6_magic.S
+++ b/arch/alpha/lib/csum_ipv6_magic.S
@@ -18,7 +18,7 @@ csum_ipv6_magic:
ldq $0,0($16) # e0 : load src & dst addr words
zapnot $20,15,$20 # .. e1 : zero extend incoming csum
- extqh $18,7,$4 # e0 : byte swap len & proto while we wait
+ extqh $18,1,$4 # e0 : byte swap len & proto while we wait
ldq $1,8($16) # .. e1 :
extbl $18,1,$5 # e0 :
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 0caf4bf26..63d4631a4 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -188,6 +188,10 @@ EXPORT_SYMBOL(uaccess_kernel);
EXPORT_SYMBOL(uaccess_user);
#endif
+EXPORT_SYMBOL(consistent_alloc);
+EXPORT_SYMBOL(consistent_free);
+EXPORT_SYMBOL(consistent_sync);
+
/* gcc lib functions */
EXPORT_SYMBOL_NOVERS(__gcc_bcmp);
EXPORT_SYMBOL_NOVERS(__ashldi3);
@@ -234,5 +238,8 @@ EXPORT_SYMBOL_NOVERS(__down_failed);
EXPORT_SYMBOL_NOVERS(__down_interruptible_failed);
EXPORT_SYMBOL_NOVERS(__down_trylock_failed);
EXPORT_SYMBOL_NOVERS(__up_wakeup);
+EXPORT_SYMBOL_NOVERS(__down_read_failed);
+EXPORT_SYMBOL_NOVERS(__down_write_failed);
+EXPORT_SYMBOL_NOVERS(__rwsem_wake);
EXPORT_SYMBOL(get_wchan);
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 2be1a6012..5dc61c6d7 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -15,26 +15,28 @@
#define HARVARD_CACHE
#endif
+ .macro get_softirq, rd
+#ifdef __SMP__
+#error SMP not supported
+#else
+ ldr \rd, __softirq_state
+#endif
+ .endm
+
.globl ret_from_sys_call
.align 5
fast_syscall_return:
- str r0, [sp, #S_R0 + S_OFF] @ returned r0
+ str r0, [sp, #S_R0 + S_OFF] @ returned r0
slow_syscall_return:
add sp, sp, #S_OFF
-ret_from_sys_call:
-#ifdef HARVARD_CACHE
- ldr r0, bh_data
- ldr r4, bh_data+4
-#else
- adr r0, bh_data
- ldmia r0, {r0, r4}
-#endif
- ldr r0, [r0]
- ldr r1, [r4]
+ret_from_sys_call: @ external entry
+ get_softirq r0
+ ldmia r0, {r0, r1}
+ mov r4, #1 @ flag this as being syscall return
tst r0, r1
- blne SYMBOL_NAME(do_bottom_half)
-ret_with_reschedule:
+ blne SYMBOL_NAME(do_softirq)
+ret_with_reschedule: @ external entry (__irq_usr)
get_current_task r5
ldr r0, [r5, #TSK_NEED_RESCHED]
ldr r1, [r5, #TSK_SIGPENDING]
@@ -43,30 +45,23 @@ ret_with_reschedule:
teq r1, #0 @ check for signals
bne ret_signal
-ret_from_all: restore_user_regs
+ret_from_all: restore_user_regs @ internal
-ret_signal: mov r1, sp
+ret_signal: mov r1, sp @ internal
adrsvc al, lr, ret_from_all
mov r2, r4
b SYMBOL_NAME(do_signal)
-ret_reschedule: adrsvc al, lr, ret_with_reschedule
+ret_reschedule: adrsvc al, lr, ret_with_reschedule @ internal
b SYMBOL_NAME(schedule)
.globl ret_from_exception
-ret_from_exception:
-#ifdef HARVARD_CACHE
- ldr r0, bh_data
- ldr r1, bh_data + 4
-#else
- adr r0, bh_data
+ret_from_exception: @ external entry
+ get_softirq r0
ldmia r0, {r0, r1}
-#endif
- ldr r0, [r0]
- ldr r1, [r1]
mov r4, #0
tst r0, r1
- blne SYMBOL_NAME(do_bottom_half)
+ blne SYMBOL_NAME(do_softirq)
ldr r0, [sp, #S_PSR]
tst r0, #3 @ returning to user mode?
beq ret_with_reschedule
@@ -147,8 +142,8 @@ vector_swi: save_user_regs
.align 5
-bh_data: .word SYMBOL_NAME(bh_mask)
- .word SYMBOL_NAME(bh_active)
+__softirq_state:
+ .word SYMBOL_NAME(softirq_state)
ENTRY(sys_call_table)
#include "calls.S"
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index f6c310905..6e3c863d5 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -237,16 +237,8 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
irq_exit(cpu, irq);
- /*
- * This should be conditional: we should really get
- * a return code from the irq handler to tell us
- * whether the handler wants us to do software bottom
- * half handling or not..
- */
- if (1) {
- if (bh_active & bh_mask)
- do_bottom_half();
- }
+ if (softirq_state[cpu].active & softirq_state[cpu].mask)
+ do_softirq();
}
#if defined(CONFIG_ARCH_ACORN)
diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c
index 71bf85e09..a2ec71526 100644
--- a/arch/arm/kernel/semaphore.c
+++ b/arch/arm/kernel/semaphore.c
@@ -164,6 +164,126 @@ int __down_trylock(struct semaphore * sem)
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 | TASK_EXCLUSIVE);
+ 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 | 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);
+ 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
@@ -174,30 +294,65 @@ int __down_trylock(struct semaphore * sem)
* registers (r0 to r3, ip and lr) except r0 in the cases where it
* is used as a return value..
*/
-asm(".align 5
+asm(" .section .text.lock, \"ax\"
+ .align 5
.globl __down_failed
__down_failed:
stmfd sp!, {r0 - r3, ip, lr}
bl __down
- ldmfd sp!, {r0 - r3, ip, pc}");
+ ldmfd sp!, {r0 - r3, ip, pc}
-asm(".align 5
+ .align 5
.globl __down_interruptible_failed
__down_interruptible_failed:
stmfd sp!, {r1 - r3, ip, lr}
bl __down_interruptible
- ldmfd sp!, {r1 - r3, ip, pc}");
+ ldmfd sp!, {r1 - r3, ip, pc}
-asm(".align 5
+ .align 5
.globl __down_trylock_failed
__down_trylock_failed:
stmfd sp!, {r1 - r3, ip, lr}
bl __down_trylock
- ldmfd sp!, {r1 - r3, ip, pc}");
+ ldmfd sp!, {r1 - r3, ip, pc}
-asm(".align 5
+ .align 5
.globl __up_wakeup
__up_wakeup:
stmfd sp!, {r0 - r3, ip, lr}
bl __up
- ldmfd sp!, {r0 - r3, ip, pc}");
+ ldmfd sp!, {r0 - r3, ip, pc}
+
+ .align 5
+ .globl __down_read_failed
+__down_read_failed:
+ stmfd sp!, {r0 - r3, ip, lr}
+ bcc 1f
+ bl down_read_failed_biased
+ ldmfd sp!, {r0 - r3, ip, pc}
+1: bl down_read_failed
+ /***/
+
+ .align 5
+ .globl __down_write_failed
+__down_write_failed:
+ stmfd sp!, {r0 - r3, ip, lr}
+ bcc 1f
+ bl down_write_failed_biased
+ ldmfd sp!, {r0 - r3, ip, pc}
+1: bl down_write_failed
+ /***/
+
+ .align 5
+ .globl __rwsem_wake
+__rwsem_wake:
+ stmfd sp!, {r0 - r3, ip, lr}
+ beq 1f
+ bl rwsem_wake_readers
+ ldmfd sp!, {r0 - r3, ip, pc}
+1: bl rwsem_wake_writer
+ ldmfd sp!, {r0 - r3, ip, pc}
+
+ .previous
+ ");
+
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index b9bffb7c9..1c02473bb 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -8,8 +8,8 @@
# Note 2! The CFLAGS definition is now in the main makefile...
O_TARGET := mm.o
-O_OBJS := init.o extable.o fault-$(PROCESSOR).o mm-$(PROCESSOR).o \
- small_page.o
+O_OBJS := consistent.o extable.o fault-$(PROCESSOR).o init.o \
+ mm-$(PROCESSOR).o small_page.o
ifeq ($(CONFIG_CPU_26),y)
O_OBJS += proc-arm2,3.o
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
new file mode 100644
index 000000000..8673d6c1d
--- /dev/null
+++ b/arch/arm/mm/consistent.c
@@ -0,0 +1,88 @@
+/*
+ * Dynamic DMA mapping support.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+
+/*
+ * This allocates one page of cache-coherent memory space and returns
+ * both the virtual and a "dma" address to that space. It is not clear
+ * whether this could be called from an interrupt context or not. For
+ * now, we expressly forbid it, especially as some of the stuff we do
+ * here is not interrupt context safe.
+ */
+void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
+{
+ int order;
+ unsigned long page;
+ struct vm_struct *area;
+ void *ret;
+
+ if (in_interrupt())
+ BUG();
+
+ order = get_order(size);
+
+ page = __get_free_pages(gfp, order);
+ if (!page)
+ goto no_page;
+
+ memset((void *)page, 0, PAGE_SIZE << order);
+ clean_cache_area(page, PAGE_SIZE << order);
+
+ *dma_handle = virt_to_bus((void *)page);
+
+ area = get_vm_area(size, VM_IOREMAP); /* maybe new type? */
+ if (!area)
+ goto no_area;
+
+ ret = __ioremap(virt_to_phys((void *)page), PAGE_SIZE << order, 0);
+ if (ret)
+ return ret;
+
+no_area:
+ free_pages(page, order);
+no_page:
+ BUG();
+ return NULL;
+}
+
+/*
+ * free a page as defined by the above mapping. We expressly forbid
+ * calling this from interrupt context.
+ */
+void consistent_free(void *vaddr)
+{
+ if (in_interrupt())
+ BUG();
+
+ __iounmap(vaddr);
+}
+
+/*
+ * make an area consistent.
+ */
+void consistent_sync(void *vaddr, size_t size, int rw)
+{
+ switch (rw) {
+ case 0:
+ BUG();
+ case 1: /* invalidate only */
+ dma_cache_inv(vaddr, size);
+ break;
+ case 2: /* writeback only */
+ dma_cache_wback(vaddr, size);
+ break;
+ case 3: /* writeback and invalidate */
+ dma_cache_wback_inv(vaddr, size);
+ break;
+ }
+}
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index db3ac5a4d..c58e66647 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -163,7 +163,7 @@ void show_mem(void)
void __init paging_init(void)
{
void *zero_page, *bad_page, *bad_table;
- unsigned int zone_size[MAX_NR_ZONES];
+ unsigned long zone_size[MAX_NR_ZONES];
int i;
#ifdef CONFIG_CPU_32
diff --git a/arch/arm/mm/proc-arm6,7.S b/arch/arm/mm/proc-arm6,7.S
index 23508c197..c6c776acf 100644
--- a/arch/arm/mm/proc-arm6,7.S
+++ b/arch/arm/mm/proc-arm6,7.S
@@ -30,6 +30,8 @@ ENTRY(cpu_arm6_flush_cache_entry)
ENTRY(cpu_arm7_flush_cache_entry)
ENTRY(cpu_arm6_flush_icache_area)
ENTRY(cpu_arm7_flush_icache_area)
+ENTRY(cpu_arm6_flush_icache_page)
+ENTRY(cpu_arm7_flush_icache_page)
ENTRY(cpu_arm6_cache_wback_area)
ENTRY(cpu_arm7_cache_wback_area)
ENTRY(cpu_arm6_cache_purge_area)
@@ -103,9 +105,9 @@ msg: .ascii "DA*%p=%p\n\0"
.align
ENTRY(cpu_arm6_data_abort)
-Ldata_simple:
ldr r4, [r0] @ read instruction causing problem
mov r2, r4, lsr #19 @ r2 b1 = L
+Ldata_simple:
and r2, r2, #2 @ check read/write bit
mrc p15, 0, r0, c6, c0, 0 @ get FAR
mrc p15, 0, r1, c5, c0, 0 @ get FSR
@@ -465,6 +467,7 @@ ENTRY(arm6_processor_functions)
.word cpu_arm6_cache_purge_area
.word cpu_arm6_flush_tlb_page
.word cpu_arm6_do_idle
+ .word cpu_arm6_flush_icache_page
.size arm6_processor_functions, . - arm6_processor_functions
/*
@@ -493,6 +496,7 @@ ENTRY(arm7_processor_functions)
.word cpu_arm7_cache_purge_area
.word cpu_arm7_flush_tlb_page
.word cpu_arm7_do_idle
+ .word cpu_arm7_flush_icache_page
.size arm7_processor_functions, . - arm7_processor_functions
.type cpu_arm6_info, #object
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index 5431f14a0..933408451 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -287,6 +287,12 @@ ENTRY(cpu_sa1100_flush_icache_area)
mcr p15, 0, r0, c7, c5, 0 @ flush I cache
mov pc, lr
+ .align 5
+ENTRY(cpu_sa110_flush_icache_page)
+ENTRY(cpu_sa1100_flush_icache_page)
+ mcr p15, 0, r0, c7, c5, 0 @ flush I cache
+ mov pc, lr
+
/*
* Function: sa110_data_abort ()
* Params : r0 = address of aborted instruction
@@ -504,6 +510,7 @@ ENTRY(sa110_processor_functions)
.word cpu_sa110_cache_purge_area
.word cpu_sa110_flush_tlb_page
.word cpu_sa110_do_idle
+ .word cpu_sa110_flush_icache_page
.size sa110_processor_functions, . - sa110_processor_functions
.type cpu_sa110_info, #object
@@ -535,6 +542,7 @@ ENTRY(sa1100_processor_functions)
.word cpu_sa1100_cache_purge_area
.word cpu_sa1100_flush_tlb_page
.word cpu_sa1100_do_idle
+ .word cpu_sa1100_flush_icache_page
.size sa1100_processor_functions, . - sa1100_processor_functions
cpu_sa1100_info:
diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c
index b9ca935eb..9d4f1570d 100644
--- a/arch/arm/nwfpe/fpmodule.c
+++ b/arch/arm/nwfpe/fpmodule.c
@@ -128,23 +128,41 @@ cumulative exceptions flag byte are set and we return.
void float_raise(signed char flags)
{
+ register unsigned int fpsr, cumulativeTraps;
+
#ifdef CONFIG_DEBUG_USER
printk(KERN_DEBUG "NWFPE: %s[%d] takes exception %08x at %p from %08x\n",
current->comm, current->pid, flags,
__builtin_return_address(0), userRegisters[15]);
#endif
+ /* Keep SoftFloat exception flags up to date. */
float_exception_flags |= flags;
- if (readFPSR() & (flags << 16))
- {
- /* raise exception */
+
+ /* Read fpsr and initialize the cumulativeTraps. */
+ fpsr = readFPSR();
+ cumulativeTraps = 0;
+
+ /* For each type of exception, the cumulative trap exception bit is only
+ set if the corresponding trap enable bit is not set. */
+ if ((!(fpsr & BIT_IXE)) && (flags & BIT_IXC))
+ cumulativeTraps |= BIT_IXC;
+ if ((!(fpsr & BIT_UFE)) && (flags & BIT_UFC))
+ cumulativeTraps |= BIT_UFC;
+ if ((!(fpsr & BIT_OFE)) && (flags & BIT_OFC))
+ cumulativeTraps |= BIT_OFC;
+ if ((!(fpsr & BIT_DZE)) && (flags & BIT_DZC))
+ cumulativeTraps |= BIT_DZC;
+ if ((!(fpsr & BIT_IOE)) && (flags & BIT_IOC))
+ cumulativeTraps |= BIT_IOC;
+
+ /* Set the cumulative exceptions flags. */
+ if (cumulativeTraps)
+ writeFPSR(fpsr | cumulativeTraps);
+
+ /* Raise an exception if necessary. */
+ if (fpsr & (flags << 16))
fp_send_sig(SIGFPE, current, 1);
- }
- else
- {
- /* set the cumulative exceptions flags */
- writeFPSR(flags);
- }
}
module_init(fpe_init);
diff --git a/arch/arm/nwfpe/fpsr.h b/arch/arm/nwfpe/fpsr.h
index f40f3872c..6dafb0f52 100644
--- a/arch/arm/nwfpe/fpsr.h
+++ b/arch/arm/nwfpe/fpsr.h
@@ -63,12 +63,12 @@ typedef unsigned int FPCR; /* type for floating point control register */
#define MASK_SYSTEM_CONTROL 0x0000ff00
#define MASK_TRAP_STRICT 0x00001f00
-#define BIT_AC 0x00100000 /* use alternative C-flag definition
+#define BIT_AC 0x00001000 /* use alternative C-flag definition
for compares */
-#define BIT_EP 0x00080000 /* use expanded packed decimal format */
-#define BIT_SO 0x00040000 /* select synchronous operation of FPA */
-#define BIT_NE 0x00020000 /* NaN exception bit */
-#define BIT_ND 0x00010000 /* no denormalized numbers bit */
+#define BIT_EP 0x00000800 /* use expanded packed decimal format */
+#define BIT_SO 0x00000400 /* select synchronous operation of FPA */
+#define BIT_NE 0x00000200 /* NaN exception bit */
+#define BIT_ND 0x00000100 /* no denormalized numbers bit */
/* CUMULATIVE EXCEPTION FLAGS BYTE
---------------------------------- */
diff --git a/arch/i386/boot/bootsect.S b/arch/i386/boot/bootsect.S
index 4a9d59908..f345ea100 100644
--- a/arch/i386/boot/bootsect.S
+++ b/arch/i386/boot/bootsect.S
@@ -106,9 +106,8 @@ go: movw $0x4000-12, %di # 0x4000 is an arbitrary value >=
pushw %ds
ldsw %fs:(%bx), %si # ds:si is source
movb $6, %cl # copy 12 bytes
- cld
pushw %di # di = 0x4000-12.
- rep
+ rep # don't need cld -> done on line 66
movsw
popw %di
popw %ds
@@ -140,20 +139,7 @@ load_setup:
jmp load_setup
ok_load_setup:
-# Get disk drive parameters, specifically nr of sectors/track.
-
-#if 0
-
-# bde - the Phoenix BIOS manual says function 0x08 only works for fixed
-# disks. It doesn't work for one of my BIOS's (1987 Award). It was
-# fatal not to check the error code.
-
- xorb %dl, %dl
- movb $0x08, %ah # AH=8 is get drive parameters
- int $0x13
- xorb %ch, %ch
-
-#else
+# Get disk drive parameters, specifically number of sectors/track.
# It seems that there is no BIOS call to get the number of sectors.
# Guess 36 sectors if sector 36 can be read, 18 sectors if sector 18
@@ -176,7 +162,6 @@ probe_loop:
movw $0x0201, %ax # service 2, 1 sector
int $0x13
jc probe_loop # try next value
-#endif
got_sectors:
movw $INITSEG, %ax
@@ -200,11 +185,11 @@ got_sectors:
# Otherwise, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8)
# depending on the number of sectors we pretend to know we have.
- movw %cs:root_dev, %ax
+ movw root_dev, %ax
orw %ax, %ax
jne root_defined
- movw %cs:sectors, %bx
+ movw sectors, %bx
movw $0x0208, %ax # /dev/ps0 - 1.2Mb
cmpw $15, %bx
je root_defined
@@ -219,7 +204,7 @@ got_sectors:
movb $0, %al # /dev/fd0 - autodetect
root_defined:
- movw %ax, %cs:root_dev
+ movw %ax, root_dev
# After that (everything loaded), we jump to the setup-routine
# loaded directly after the bootblock:
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
index 1a08bc3ab..7c50d54a8 100644
--- a/arch/i386/boot/setup.S
+++ b/arch/i386/boot/setup.S
@@ -436,7 +436,7 @@ no_mca:
movw $0xAA, (0x1ff) # device present
no_psmouse:
-#ifdef CONFIG_APM
+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
# Then check for an APM BIOS...
# %ds points to the bootsector
movw $0, 0x40 # version = 0 means no APM BIOS
@@ -455,7 +455,11 @@ no_psmouse:
xorw %bx, %bx
int $0x15 # ignore return code
movw $0x05303, %ax # 32 bit connect
- xorw %bx, %bx
+ xorl %ebx, %ebx
+ xorw %cx, %cx # paranoia :-)
+ xorw %dx, %dx # ...
+ xorl %esi, %esi # ...
+ xorw %di, %di # ...
int $0x15
jc no_32_apm_bios # Ack, error.
@@ -463,12 +467,13 @@ no_psmouse:
movl %ebx, (68) # BIOS entry point offset
movw %cx, (72) # BIOS 16 bit code segment
movw %dx, (74) # BIOS data segment
- movl %esi, (78) # BIOS code segment length
+ movl %esi, (78) # BIOS code segment lengths
movw %di, (82) # BIOS data segment length
# Redo the installation check as the 32 bit connect
# modifies the flags returned on some BIOSs
movw $0x05300, %ax # APM BIOS installation check
xorw %bx, %bx
+ xorw %cx, %cx # paranoia
int $0x15
jc apm_disconnect # error -> shouldn't happen
diff --git a/arch/i386/config.in b/arch/i386/config.in
index 2377c24b7..e074ea81d 100644
--- a/arch/i386/config.in
+++ b/arch/i386/config.in
@@ -49,6 +49,10 @@ if [ "$CONFIG_MK7" = "y" ]; then
define_bool CONFIG_X86_USE_3DNOW y
fi
+if [ "$CONFIG_PROC_FS" = "y" ]; then
+ tristate '/proc/driver/microcode - Intel P6 CPU microcode support' CONFIG_MICROCODE
+fi
+
choice 'High Memory Support' \
"off CONFIG_NOHIGHMEM \
4GB CONFIG_HIGHMEM4G \
@@ -144,7 +148,7 @@ if [ "$CONFIG_ACPI" != "n" ]; then
fi
fi
-bool 'Advanced Power Management BIOS support' CONFIG_APM
+tristate 'Advanced Power Management BIOS support' CONFIG_APM
if [ "$CONFIG_APM" != "n" ]; then
bool ' Ignore USER SUSPEND' CONFIG_APM_IGNORE_USER_SUSPEND
bool ' Enable PM at boot time' CONFIG_APM_DO_ENABLE
@@ -154,7 +158,6 @@ if [ "$CONFIG_APM" != "n" ]; then
bool ' Ignore multiple suspend/resume cycles' CONFIG_APM_IGNORE_SUSPEND_BOUNCE
bool ' RTC stores time in GMT' CONFIG_APM_RTC_IS_GMT
bool ' Allow interrupts during APM BIOS calls' CONFIG_APM_ALLOW_INTS
- bool ' Entry point offset fix (some Acer laptops)' CONFIG_APM_BAD_ENTRY_OFFSET
bool ' Use real mode APM BIOS call to power off' CONFIG_APM_REAL_MODE_POWER_OFF
fi
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index fcc962a11..4ca545255 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -27,6 +27,7 @@ CONFIG_X86_POPAD_OK=y
CONFIG_X86_TSC=y
CONFIG_X86_GOOD_APIC=y
CONFIG_X86_PGE=y
+# CONFIG_MICROCODE is not set
CONFIG_NOHIGHMEM=y
# CONFIG_HIGHMEM4G is not set
# CONFIG_HIGHMEM64G is not set
@@ -175,7 +176,6 @@ CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_SD_EXTRA_DEVS=40
# CONFIG_CHR_DEV_ST is not set
-CONFIG_ST_EXTRA_DEVS=2
# CONFIG_BLK_DEV_SR is not set
# CONFIG_CHR_DEV_SG is not set
@@ -238,6 +238,11 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
# CONFIG_SCSI_ULTRASTOR is not set
#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_SCSI_PCMCIA is not set
+
+#
# I2O device support
#
# CONFIG_I2O is not set
@@ -270,15 +275,15 @@ CONFIG_NET_ETHERNET=y
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_DEPCA is not set
# CONFIG_NET_ISA is not set
-CONFIG_NET_EISA=y
+CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
# CONFIG_APRICOT is not set
-# CONFIG_CS89x0 is not set
# CONFIG_DE4X5 is not set
# CONFIG_TULIP is not set
# CONFIG_DGRS is not set
-CONFIG_EEXPRESS_PRO100=y
+CONFIG_EEPRO100=y
# CONFIG_NE2K_PCI is not set
+# CONFIG_8139TOO is not set
# CONFIG_SIS900 is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
@@ -324,7 +329,6 @@ CONFIG_PCMCIA_PCNET=y
# CONFIG_ARCNET_COM20020_CS is not set
# CONFIG_PCMCIA_3C575 is not set
# CONFIG_PCMCIA_TULIP is not set
-# CONFIG_PCMCIA_EPIC100 is not set
CONFIG_NET_PCMCIA_RADIO=y
CONFIG_PCMCIA_RAYCS=y
# CONFIG_PCMCIA_NETWAVE is not set
@@ -423,7 +427,7 @@ CONFIG_PCMCIA_SERIAL=y
#
#
-# Filesystems
+# File systems
#
# CONFIG_QUOTA is not set
# CONFIG_AUTOFS_FS is not set
@@ -442,20 +446,17 @@ CONFIG_ISO9660_FS=y
# 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_DEBUG is not set
CONFIG_DEVPTS_FS=y
# 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
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 96be4dff6..3b7bb1258 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -40,6 +40,16 @@ else
endif
endif
+ifeq ($(CONFIG_PROC_FS),y)
+ifeq ($(CONFIG_MICROCODE),y)
+OX_OBJS += microcode.o
+else
+ ifeq ($(CONFIG_MICROCODE),m)
+ MX_OBJS += microcode.o
+ endif
+endif
+endif
+
ifeq ($(CONFIG_ACPI),y)
O_OBJS += acpi.o
else
diff --git a/arch/i386/kernel/acpi.c b/arch/i386/kernel/acpi.c
index 8ae8bc299..9bdd111d1 100644
--- a/arch/i386/kernel/acpi.c
+++ b/arch/i386/kernel/acpi.c
@@ -643,6 +643,7 @@ const static struct
{NULL,},
{acpi_init_piix4},
{acpi_init_via},
+ {acpi_init_via},
};
const static struct pci_device_id acpi_pci_tbl[] =
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index b8bca05c6..a5f72548f 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -3,6 +3,8 @@
*
* (c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
*
+ * Fixes
+ * Maciej W. Rozycki : Bits for genuine 82489DX timers
*/
#include <linux/config.h>
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index 81a813b05..4ec5e7993 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -1,6 +1,6 @@
/* -*- linux-c -*-
* APM BIOS driver for Linux
- * Copyright 1994-1999 Stephen Rothwell (sfr@linuxcare.com)
+ * Copyright 1994-2000 Stephen Rothwell (sfr@linuxcare.com)
*
* Initial development of this driver was funded by NEC Australia P/L
* and NEC Corporation
@@ -35,6 +35,8 @@
* Jan 1999, Version 1.9
* Oct 1999, Version 1.10
* Nov 1999, Version 1.11
+ * Jan 2000, Version 1.12
+ * Feb 2000, Version 1.13
*
* History:
* 0.6b: first version in official kernel, Linux 1.3.46
@@ -54,7 +56,7 @@
* The new replacment for it is, but Linux doesn't yet support this.
* Alan Cox Linux 2.1.55
* 1.3: Set up a valid data descriptor 0x40 for buggy BIOS's
- * 1.4: Upgraded to support APM 1.2. Integrated ThinkPad suspend patch by
+ * 1.4: Upgraded to support APM 1.2. Integrated ThinkPad suspend patch by
* Dean Gaudet <dgaudet@arctic.org>.
* C. Scott Ananian <cananian@alumni.princeton.edu> Linux 2.1.87
* 1.5: Fix segment register reloading (in case of bad segments saved
@@ -110,6 +112,26 @@
* (reported by Panos Katsaloulis <teras@writeme.com>).
* Real mode power off patch (Walter Hofmann
* <Walter.Hofmann@physik.stud.uni-erlangen.de>).
+ * 1.12: Remove CONFIG_SMP as the compiler will optimize
+ * the code away anyway (smp_num_cpus == 1 in UP)
+ * noted by Artur Skawina <skawina@geocities.com>.
+ * Make power off under SMP work again.
+ * Fix thinko with initial engaging of BIOS.
+ * Make sure power off only happens on CPU 0
+ * (Paul "Rusty" Russell <rusty@linuxcare.com>).
+ * Do error notification to user mode if BIOS calls fail.
+ * Move entrypoint offset fix to ...boot/setup.S
+ * where it belongs (Cosmos <gis88564@cis.nctu.edu.tw>).
+ * Remove smp-power-off. SMP users must now specify
+ * "apm=power-off" on the kernel command line. Suggested
+ * by Jim Avera <jima@hal.com>, modified by Alan Cox
+ * <alan@lxorguk.ukuu.org.uk>.
+ * Register the /proc/apm entry even on SMP so that
+ * scripts that check for it before doing power off
+ * work (Jim Avera <jima@hal.com>).
+ * 1.13: Changes for new pm_ interfaces (Andy Henroid
+ * <andy_henroid@yahoo.com>).
+ * Modularize the code.
*
* APM 1.1 Reference:
*
@@ -145,13 +167,12 @@
#include <linux/apm_bios.h>
#include <linux/init.h>
#include <linux/sched.h>
+#include <linux/pm.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/desc.h>
-#include <linux/pm.h>
-
extern unsigned long get_cmos_time(void);
extern void machine_real_restart(unsigned char *, int);
@@ -172,10 +193,10 @@ extern int (*console_blank_hook)(int);
* See Documentation/Config.help for the configuration options.
*
* Various options can be changed at boot time as follows:
+ * (We allow underscores for compatibility with the modules code)
* apm=on/off enable/disable APM
* [no-]debug log some debugging messages
- * [no-]power-off power off on shutdown
- * [no-]smp-power-off allow power off even for SMP
+ * [no-]power[-_]off power off on shutdown
*/
/* KNOWN PROBLEM MACHINES:
@@ -219,8 +240,8 @@ extern int (*console_blank_hook)(int);
/*
* Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend.
- * This patched by Chad Miller <cmiller@surfsouth.com>, orig code by David
- * Chen <chen@ctpa04.mit.edu>
+ * This patched by Chad Miller <cmiller@surfsouth.com>, original code by
+ * David Chen <chen@ctpa04.mit.edu>
*/
#undef INIT_TIMER_AFTER_SUSPEND
@@ -237,7 +258,7 @@ extern int (*console_blank_hook)(int);
/*
* If CONFIG_APM_IGNORE_SUSPEND_BOUNCE is defined then
- * ignore suspend events for this amount of time
+ * ignore suspend events for this amount of time after a resume
*/
#define BOUNCE_INTERVAL (3 * HZ)
@@ -248,14 +269,40 @@ extern int (*console_blank_hook)(int);
__asm__ __volatile__("movl %%" #seg ",%0" : "=m" (where))
/*
+ * Maximum number of events stored
+ */
+#define APM_MAX_EVENTS 20
+
+/*
+ * The per-file APM data
+ */
+struct apm_user {
+ int magic;
+ struct apm_user * next;
+ int suser: 1;
+ int suspend_wait: 1;
+ int suspend_result;
+ int suspends_pending;
+ int standbys_pending;
+ int suspends_read;
+ int standbys_read;
+ int event_head;
+ int event_tail;
+ apm_event_t events[APM_MAX_EVENTS];
+};
+
+/*
+ * The magic number in apm_user
+ */
+#define APM_BIOS_MAGIC 0x4101
+
+/*
* Local variables
*/
static struct {
unsigned long offset;
unsigned short segment;
} apm_bios_entry;
-static int apm_enabled = 0;
-static int smp_hack = 0;
#ifdef CONFIG_APM_CPU_IDLE
static int clock_slowed = 0;
#endif
@@ -274,12 +321,19 @@ static int got_clock_diff = 0;
#endif
static int debug = 0;
static int apm_disabled = 0;
-static int power_off_enabled = 1;
+#ifdef CONFIG_SMP
+static int power_off = 0;
+#else
+static int power_off = 1;
+#endif
+static int exit_kapmd = 0;
+static int kapmd_running = 0;
static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
-static struct apm_bios_struct * user_list = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
+static struct apm_user * user_list = NULL;
-static char driver_version[] = "1.11"; /* no spaces */
+static char driver_version[] = "1.12"; /* no spaces */
static char * apm_event_name[] = {
"system standby",
@@ -380,6 +434,10 @@ static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in,
__save_flags(flags);
APM_DO_CLI;
APM_DO_SAVE_SEGS;
+ /*
+ * N.B. We do NOT need a cld after the BIOS call
+ * because we always save and restore the flags.
+ */
__asm__ __volatile__(APM_DO_ZERO_SEGS
"pushl %%edi\n\t"
"pushl %%ebp\n\t"
@@ -413,10 +471,14 @@ static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax)
{
int cx, dx, si;
+ /*
+ * N.B. We do NOT need a cld after the BIOS call
+ * because we always save and restore the flags.
+ */
__asm__ __volatile__(APM_DO_ZERO_SEGS
"pushl %%edi\n\t"
"pushl %%ebp\n\t"
- "lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry)"\n\t"
+ "lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
"setc %%bl\n\t"
"popl %%ebp\n\t"
"popl %%edi\n\t"
@@ -499,6 +561,7 @@ static void apm_do_busy(void)
}
}
+#if 0
extern int hlt_counter;
/*
@@ -543,48 +606,63 @@ static void apm_cpu_idle(void)
}
}
#endif
+#endif
+
+#ifdef CONFIG_SMP
+static int apm_magic(void * unused)
+{
+ while (1)
+ schedule();
+}
+#endif
static void apm_power_off(void)
{
+#ifdef CONFIG_APM_REAL_MODE_POWER_OFF
+ unsigned char po_bios_call[] = {
+ 0xb8, 0x00, 0x10, /* movw $0x1000,ax */
+ 0x8e, 0xd0, /* movw ax,ss */
+ 0xbc, 0x00, 0xf0, /* movw $0xf000,sp */
+ 0xb8, 0x07, 0x53, /* movw $0x5307,ax */
+ 0xbb, 0x01, 0x00, /* movw $0x0001,bx */
+ 0xb9, 0x03, 0x00, /* movw $0x0003,cx */
+ 0xcd, 0x15 /* int $0x15 */
+ };
+#endif
+
/*
- * smp_hack == 2 means that we would have enabled APM support
- * except there is more than one processor and so most of
- * the APM stuff is unsafe. We will still try power down
- * because is is useful to some people and they know what
- * they are doing because they booted with the smp-power-off
- * kernel option.
+ * This may be called on an SMP machine.
*/
- if (apm_enabled || (smp_hack == 2)) {
+#ifdef CONFIG_SMP
+ /* Some bioses don't like being called from CPU != 0 */
+ while (cpu_number_map[smp_processor_id()] != 0) {
+ kernel_thread(apm_magic, NULL,
+ CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD);
+ schedule();
+ }
+#endif
#ifdef CONFIG_APM_REAL_MODE_POWER_OFF
- unsigned char po_bios_call[] = {
- 0xb8, 0x00, 0x10, /* movw $0x1000,ax */
- 0x8e, 0xd0, /* movw ax,ss */
- 0xbc, 0x00, 0xf0, /* movw $0xf000,sp */
- 0xb8, 0x07, 0x53, /* movw $0x5307,ax */
- 0xbb, 0x01, 0x00, /* movw $0x0001,bx */
- 0xb9, 0x03, 0x00, /* movw $0x0003,cx */
- 0xcd, 0x15 /* int $0x15 */
- };
-
- machine_real_restart(po_bios_call, sizeof(po_bios_call));
+ machine_real_restart(po_bios_call, sizeof(po_bios_call));
#else
- (void) apm_set_power_state(APM_STATE_OFF);
+ (void) apm_set_power_state(APM_STATE_OFF);
#endif
- }
}
-#ifdef CONFIG_APM_DO_ENABLE
-static int __init apm_enable_power_management(void)
+static int apm_enable_power_management(int enable)
{
u32 eax;
+ if ((enable == 0) && (apm_bios_info.flags & APM_BIOS_DISENGAGED))
+ return APM_NOT_ENGAGED;
if (apm_bios_call_simple(APM_FUNC_ENABLE_PM, APM_DEVICE_BALL,
- 1, &eax))
+ enable, &eax))
return (eax >> 8) & 0xff;
- apm_bios_info.flags &= ~APM_BIOS_DISABLED;
+ if (enable)
+ apm_bios_info.flags &= ~APM_BIOS_DISABLED;
+ else
+ apm_bios_info.flags |= APM_BIOS_DISABLED;
return APM_SUCCESS;
}
-#endif
static int apm_get_power_status(u_short *status, u_short *bat, u_short *life)
{
@@ -632,12 +710,21 @@ static int apm_get_battery_status(u_short which, u_short *status,
}
#endif
-static int __init apm_engage_power_management(u_short device)
+static int apm_engage_power_management(u_short device, int enable)
{
u32 eax;
- if (apm_bios_call_simple(APM_FUNC_ENGAGE_PM, device, 1, &eax))
+ if ((enable == 0) && (device == APM_DEVICE_ALL)
+ && (apm_bios_info.flags & APM_BIOS_DISABLED))
+ return APM_DISABLED;
+ if (apm_bios_call_simple(APM_FUNC_ENGAGE_PM, device, enable, &eax))
return (eax >> 8) & 0xff;
+ if (device == APM_DEVICE_ALL) {
+ if (enable)
+ apm_bios_info.flags &= ~APM_BIOS_DISENGAGED;
+ else
+ apm_bios_info.flags |= APM_BIOS_DISENGAGED;
+ }
return APM_SUCCESS;
}
@@ -655,7 +742,6 @@ static void apm_error(char *str, int err)
}
#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
-/* Called from console driver -- must make sure apm_enabled. */
static int apm_console_blank(int blank)
{
int error;
@@ -664,9 +750,13 @@ static int apm_console_blank(int blank)
state = blank ? APM_STATE_STANDBY : APM_STATE_READY;
/* Blank the first display device */
error = set_power_state(0x100, state);
- if (error != APM_SUCCESS)
+ if ((error != APM_SUCCESS) && (error != APM_NO_ERROR)) {
/* try to blank them all instead */
error = set_power_state(0x1ff, state);
+ if ((error != APM_SUCCESS) && (error != APM_NO_ERROR))
+ /* try to blank device one instead */
+ error = set_power_state(0x101, state);
+ }
if ((error == APM_SUCCESS) || (error == APM_NO_ERROR))
return 1;
apm_error("set display", error);
@@ -674,20 +764,20 @@ static int apm_console_blank(int blank)
}
#endif
-static int queue_empty(struct apm_bios_struct * as)
+static int queue_empty(struct apm_user *as)
{
return as->event_head == as->event_tail;
}
-static apm_event_t get_queued_event(struct apm_bios_struct * as)
+static apm_event_t get_queued_event(struct apm_user *as)
{
as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
return as->events[as->event_tail];
}
-static void queue_event(apm_event_t event, struct apm_bios_struct *sender)
+static void queue_event(apm_event_t event, struct apm_user *sender)
{
- struct apm_bios_struct * as;
+ struct apm_user * as;
if (user_list == NULL)
return;
@@ -751,18 +841,11 @@ static void get_time_diff(void)
#endif
}
-static void suspend(void)
+static void reinit_timer(void)
{
- int err;
#ifdef INIT_TIMER_AFTER_SUSPEND
unsigned long flags;
-#endif
- get_time_diff();
- err = apm_set_power_state(APM_STATE_SUSPEND);
- if ((err != APM_SUCCESS) && (err != APM_NO_ERROR))
- apm_error("suspend", err);
-#ifdef INIT_TIMER_AFTER_SUSPEND
save_flags(flags);
cli();
/* set the clock to 100 Hz */
@@ -774,7 +857,27 @@ static void suspend(void)
udelay(10);
restore_flags(flags);
#endif
+}
+
+static int suspend(void)
+{
+ int err;
+ int ret;
+ struct apm_user *as;
+
+ get_time_diff();
+ err = apm_set_power_state(APM_STATE_SUSPEND);
+ reinit_timer();
set_time();
+ ret = (err == APM_SUCCESS) || (err == APM_NO_ERROR);
+ if (!ret)
+ apm_error("suspend", err);
+ for (as = user_list; as != NULL; as = as->next) {
+ as->suspend_wait = 0;
+ as->suspend_result = (ret ? 0 : -EIO);
+ }
+ wake_up_interruptible(&apm_suspend_waitqueue);
+ return ret;
}
static void standby(void)
@@ -806,15 +909,14 @@ static apm_event_t get_event(void)
return 0;
}
-static int send_event(apm_event_t event, apm_event_t undo,
- struct apm_bios_struct *sender)
+static int send_event(apm_event_t event, struct apm_user *sender)
{
switch (event) {
case APM_SYS_SUSPEND:
case APM_CRITICAL_SUSPEND:
case APM_USER_SUSPEND:
/* map all suspends to ACPI D3 */
- if (pm_send_request(PM_SUSPEND, (void*) 3)) {
+ if (pm_send_request(PM_SUSPEND, (void *)3)) {
if (apm_bios_info.version > 0x100)
apm_set_power_state(APM_STATE_REJECT);
return 0;
@@ -823,11 +925,7 @@ static int send_event(apm_event_t event, apm_event_t undo,
case APM_NORMAL_RESUME:
case APM_CRITICAL_RESUME:
/* map all resumes to ACPI D0 */
- if (pm_send_request(PM_RESUME, 0)) {
- if (apm_bios_info.version > 0x100)
- apm_set_power_state(APM_STATE_REJECT);
- return 0;
- }
+ (void) pm_send_request(PM_RESUME, (void *)0);
break;
}
@@ -864,7 +962,7 @@ static void check_events(void)
if (waiting_for_resume)
break;
#endif
- if (send_event(event, APM_STANDBY_RESUME, NULL)) {
+ if (send_event(event, NULL)) {
#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
waiting_for_resume = 1;
#endif
@@ -888,12 +986,12 @@ static void check_events(void)
if (waiting_for_resume)
break;
#endif
- if (send_event(event, APM_NORMAL_RESUME, NULL)) {
+ if (send_event(event, NULL)) {
#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
waiting_for_resume = 1;
#endif
if (suspends_pending <= 0)
- suspend();
+ (void) suspend();
}
break;
@@ -908,13 +1006,13 @@ static void check_events(void)
ignore_bounce = 1;
#endif
set_time();
- send_event(event, 0, NULL);
+ send_event(event, NULL);
break;
case APM_CAPABILITY_CHANGE:
case APM_LOW_BATTERY:
case APM_POWER_STATUS_CHANGE:
- send_event(event, 0, NULL);
+ send_event(event, NULL);
break;
case APM_UPDATE_TIME:
@@ -922,7 +1020,7 @@ static void check_events(void)
break;
case APM_CRITICAL_SUSPEND:
- suspend();
+ (void) suspend();
break;
}
}
@@ -930,18 +1028,18 @@ static void check_events(void)
static void apm_event_handler(void)
{
- static int pending_count = 0;
+ static int pending_count = 4;
int err;
if ((standbys_pending > 0) || (suspends_pending > 0)) {
- if ((apm_bios_info.version > 0x100) && (pending_count-- <= 0)) {
+ if ((apm_bios_info.version > 0x100) && (pending_count-- < 0)) {
pending_count = 4;
err = apm_set_power_state(APM_STATE_BUSY);
if (err)
apm_error("busy", err);
}
} else
- pending_count = 0;
+ pending_count = 4;
check_events();
}
@@ -957,13 +1055,17 @@ static void apm_event_handler(void)
static void apm_mainloop(void)
{
DECLARE_WAITQUEUE(wait, current);
- apm_enabled = 1;
+
+ if (smp_num_cpus > 1)
+ return;
add_wait_queue(&apm_waitqueue, &wait);
current->state = TASK_INTERRUPTIBLE;
for (;;) {
/* Nothing to do, just sleep for the timeout */
schedule_timeout(APM_CHECK_TIMEOUT);
+ if (exit_kapmd)
+ break;
/*
* Ok, check all events, check for idle (and mark us sleeping
@@ -976,11 +1078,11 @@ static void apm_mainloop(void)
continue;
if (apm_do_idle()) {
unsigned long start = jiffies;
- do {
+ while (system_idle()) {
apm_do_idle();
if (jiffies - start > APM_CHECK_TIMEOUT)
break;
- } while (system_idle());
+ }
apm_do_busy();
apm_event_handler();
}
@@ -988,7 +1090,7 @@ static void apm_mainloop(void)
}
}
-static int check_apm_bios_struct(struct apm_bios_struct *as, const char *func)
+static int check_apm_user(struct apm_user *as, const char *func)
{
if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
printk(KERN_ERR "apm: %s passed bad filp", func);
@@ -999,13 +1101,13 @@ static int check_apm_bios_struct(struct apm_bios_struct *as, const char *func)
static ssize_t do_read(struct file *fp, char *buf, size_t count, loff_t *ppos)
{
- struct apm_bios_struct * as;
+ struct apm_user * as;
int i;
apm_event_t event;
DECLARE_WAITQUEUE(wait, current);
as = fp->private_data;
- if (check_apm_bios_struct(as, "read"))
+ if (check_apm_user(as, "read"))
return -EIO;
if (count < sizeof(apm_event_t))
return -EINVAL;
@@ -1053,10 +1155,10 @@ repeat:
static unsigned int do_poll(struct file *fp, poll_table * wait)
{
- struct apm_bios_struct * as;
+ struct apm_user * as;
as = fp->private_data;
- if (check_apm_bios_struct(as, "select"))
+ if (check_apm_user(as, "poll"))
return 0;
poll_wait(fp, &apm_waitqueue, wait);
if (!queue_empty(as))
@@ -1067,11 +1169,11 @@ static unsigned int do_poll(struct file *fp, poll_table * wait)
static int do_ioctl(struct inode * inode, struct file *filp,
u_int cmd, u_long arg)
{
- struct apm_bios_struct * as;
- int send_ok = 1;
+ struct apm_user * as;
+ DECLARE_WAITQUEUE(wait, current);
as = filp->private_data;
- if (check_apm_bios_struct(as, "ioctl"))
+ if (check_apm_user(as, "ioctl"))
return -EIO;
if (!as->suser)
return -EPERM;
@@ -1081,11 +1183,9 @@ static int do_ioctl(struct inode * inode, struct file *filp,
as->standbys_read--;
as->standbys_pending--;
standbys_pending--;
- }
- else
- send_ok = send_event(APM_USER_STANDBY,
- APM_STANDBY_RESUME, as);
- if (send_ok && (standbys_pending <= 0))
+ } else if (!send_event(APM_USER_STANDBY, as))
+ return -EAGAIN;
+ if (standbys_pending <= 0)
standby();
break;
case APM_IOC_SUSPEND:
@@ -1093,12 +1193,25 @@ static int do_ioctl(struct inode * inode, struct file *filp,
as->suspends_read--;
as->suspends_pending--;
suspends_pending--;
+ } else if (!send_event(APM_USER_SUSPEND, as))
+ return -EAGAIN;
+ if (suspends_pending <= 0) {
+ if (!suspend())
+ return -EIO;
+ } else {
+ as->suspend_wait = 1;
+ add_wait_queue(&apm_suspend_waitqueue, &wait);
+ while (1) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if ((as->suspend_wait == 0)
+ || signal_pending(current))
+ break;
+ schedule();
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&apm_suspend_waitqueue, &wait);
+ return as->suspend_result;
}
- else
- send_ok = send_event(APM_USER_SUSPEND,
- APM_NORMAL_RESUME, as);
- if (send_ok && (suspends_pending <= 0))
- suspend();
break;
default:
return -EINVAL;
@@ -1108,10 +1221,10 @@ static int do_ioctl(struct inode * inode, struct file *filp,
static int do_release(struct inode * inode, struct file * filp)
{
- struct apm_bios_struct * as;
+ struct apm_user * as;
as = filp->private_data;
- if (check_apm_bios_struct(as, "release"))
+ if (check_apm_user(as, "release"))
return 0;
filp->private_data = NULL;
if (as->standbys_pending > 0) {
@@ -1122,12 +1235,12 @@ static int do_release(struct inode * inode, struct file * filp)
if (as->suspends_pending > 0) {
suspends_pending -= as->suspends_pending;
if (suspends_pending <= 0)
- suspend();
+ (void) suspend();
}
if (user_list == as)
user_list = as->next;
else {
- struct apm_bios_struct * as1;
+ struct apm_user * as1;
for (as1 = user_list;
(as1 != NULL) && (as1->next != as);
@@ -1139,17 +1252,21 @@ static int do_release(struct inode * inode, struct file * filp)
as1->next = as->next;
}
kfree_s(as, sizeof(*as));
+ MOD_DEC_USE_COUNT;
return 0;
}
static int do_open(struct inode * inode, struct file * filp)
{
- struct apm_bios_struct * as;
+ struct apm_user * as;
- as = (struct apm_bios_struct *)kmalloc(sizeof(*as), GFP_KERNEL);
+ MOD_INC_USE_COUNT;
+
+ as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
if (as == NULL) {
printk(KERN_ERR "apm: cannot allocate struct of size %d bytes",
sizeof(*as));
+ MOD_DEC_USE_COUNT;
return -ENOMEM;
}
as->magic = APM_BIOS_MAGIC;
@@ -1184,11 +1301,10 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
int time_units = -1;
char *units = "?";
- if (!apm_enabled)
- return 0;
p = buf;
- if (!(error = apm_get_power_status(&bx, &cx, &dx))) {
+ if ((smp_num_cpus == 1) &&
+ !(error = apm_get_power_status(&bx, &cx, &dx))) {
ac_line_status = (bx >> 8) & 0xff;
battery_status = bx & 0xff;
if ((cx & 0xff) != 0xff)
@@ -1264,6 +1380,11 @@ static int apm(void *unused)
char * power_stat;
char * bat_stat;
+ kapmd_running = 1;
+
+ exit_files(current); /* daemonize doesn't do exit_files */
+ daemonize();
+
strcpy(current->comm, "kapmd");
sigfillset(&current->blocked);
@@ -1278,7 +1399,7 @@ static int apm(void *unused)
apm_bios_info.version = 0x100;
}
}
- if (debug) {
+ if (debug && (smp_num_cpus == 1)) {
printk(KERN_INFO "apm: Connection version %d.%d\n",
(apm_bios_info.version >> 8) & 0xff,
apm_bios_info.version & 0xff);
@@ -1328,32 +1449,51 @@ static int apm(void *unused)
* is booted with PM disabled but not in the docking station.
* Unfortunate ...
*/
- error = apm_enable_power_management();
+ error = apm_enable_power_management(1);
if (error) {
apm_error("enable power management", error);
return -1;
}
}
#endif
- if (((apm_bios_info.flags & APM_BIOS_DISENGAGED) == 0)
+ if ((apm_bios_info.flags & APM_BIOS_DISENGAGED)
&& (apm_bios_info.version > 0x0100)) {
- if (apm_engage_power_management(0x0001) == APM_SUCCESS)
- apm_bios_info.flags &= ~APM_BIOS_DISENGAGED;
+ error = apm_engage_power_management(APM_DEVICE_ALL, 1);
+ if (error) {
+ apm_error("engage power management", error);
+ return -1;
+ }
}
/* Install our power off handler.. */
- if (power_off_enabled)
+ if (power_off)
pm_power_off = apm_power_off;
#ifdef CONFIG_MAGIC_SYSRQ
sysrq_power_off = apm_power_off;
#endif
#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
- console_blank_hook = apm_console_blank;
+ if (smp_num_cpus == 1)
+ console_blank_hook = apm_console_blank;
#endif
pm_active = 1;
apm_mainloop();
+
+ pm_active = 0;
+
+#if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
+ if (smp_num_cpus == 1)
+ console_blank_hook = NULL;
+#endif
+#ifdef CONFIG_MAGIC_SYSRQ
+ sysrq_power_off = NULL;
+#endif
+ if (power_off)
+ pm_power_off = NULL;
+
+ kapmd_running = 0;
+
return 0;
}
@@ -1371,10 +1511,9 @@ static int __init apm_setup(char *str)
str += 3;
if (strncmp(str, "debug", 5) == 0)
debug = !invert;
- if (strncmp(str, "power-off", 9) == 0)
- power_off_enabled = !invert;
- if (strncmp(str, "smp-power-off", 13) == 0)
- smp_hack = !invert;
+ if ((strncmp(str, "power-off", 9) == 0) ||
+ (strncmp(str, "power_off", 9) == 0))
+ power_off = !invert;
str = strchr(str, ',');
if (str != NULL)
str += strspn(str, ", \t");
@@ -1394,7 +1533,7 @@ static struct file_operations apm_bios_fops = {
static struct miscdevice apm_device = {
APM_MINOR_DEV,
- "apm",
+ "apm_bios",
&apm_bios_fops
};
@@ -1455,7 +1594,10 @@ static int __init apm_init(void)
printk(KERN_NOTICE "apm: disabled on user request.\n");
APM_INIT_ERROR_RETURN;
}
-
+ if ((smp_num_cpus > 1) && !power_off) {
+ printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
+ APM_INIT_ERROR_RETURN;
+ }
if (PM_IS_ACTIVE()) {
printk(KERN_NOTICE "apm: overridden by ACPI.\n");
APM_INIT_ERROR_RETURN;
@@ -1472,9 +1614,6 @@ static int __init apm_init(void)
_set_limit((char *)&gdt[APM_40 >> 3], 4095 - (0x40 << 4));
apm_bios_entry.offset = apm_bios_info.offset;
-#ifdef CONFIG_APM_BAD_ENTRY_OFFSET
- apm_bios_entry.offset &= 0xffff;
-#endif
apm_bios_entry.segment = APM_CS;
set_base(gdt[APM_CS >> 3],
__va((unsigned long)apm_bios_info.cseg << 4));
@@ -1483,18 +1622,16 @@ static int __init apm_init(void)
set_base(gdt[APM_DS >> 3],
__va((unsigned long)apm_bios_info.dseg << 4));
#ifndef APM_RELAX_SEGMENTS
- if (apm_bios_info.version == 0x100)
+ if (apm_bios_info.version == 0x100) {
#endif
- {
/* For ASUS motherboard, Award BIOS rev 110 (and others?) */
_set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1);
/* For some unknown machine. */
_set_limit((char *)&gdt[APM_CS_16 >> 3], 64 * 1024 - 1);
/* For the DEC Hinote Ultra CT475 (and others?) */
_set_limit((char *)&gdt[APM_DS >> 3], 64 * 1024 - 1);
- }
#ifndef APM_RELAX_SEGMENTS
- else {
+ } else {
_set_limit((char *)&gdt[APM_CS >> 3],
(apm_bios_info.cseg_len - 1) & 0xffff);
_set_limit((char *)&gdt[APM_CS_16 >> 3],
@@ -1504,21 +1641,36 @@ static int __init apm_init(void)
}
#endif
-#ifdef CONFIG_SMP
+ create_proc_info_entry("apm", 0, NULL, apm_get_info);
+
+ kernel_thread(apm, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD);
+
if (smp_num_cpus > 1) {
- printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
- if (smp_hack)
- smp_hack = 2;
+ printk(KERN_NOTICE
+ "apm: disabled - APM is not SMP safe (power off active).\n");
APM_INIT_ERROR_RETURN;
}
-#endif
-
- create_proc_info_entry("apm", 0, 0, apm_get_info);
misc_register(&apm_device);
- kernel_thread(apm, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD);
return 0;
}
-__initcall(apm_init);
+static void __exit apm_exit(void)
+{
+ misc_deregister(&apm_device);
+ remove_proc_entry("apm", NULL);
+ exit_kapmd = 1;
+ while (kapmd_running)
+ schedule();
+}
+
+module_init(apm_init);
+module_exit(apm_exit);
+
+MODULE_AUTHOR("Stephen Rothwell");
+MODULE_DESCRIPTION("Advanced Power Management");
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Enable debug mode");
+
+EXPORT_NO_SYMBOLS;
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index f58e7485f..cad6ceb17 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -10,6 +10,7 @@
#include <linux/smp_lock.h>
#include <linux/pm.h>
#include <linux/pci.h>
+#include <linux/apm_bios.h>
#include <asm/semaphore.h>
#include <asm/processor.h>
@@ -20,6 +21,7 @@
#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/mmx.h>
+#include <asm/desc.h>
extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu(elf_fpregset_t *);
@@ -34,6 +36,8 @@ extern struct drive_info_struct drive_info;
EXPORT_SYMBOL(drive_info);
#endif
+extern unsigned long get_cmos_time(void);
+
/* platform dependent support */
EXPORT_SYMBOL(boot_cpu_data);
EXPORT_SYMBOL(EISA_bus);
@@ -51,6 +55,9 @@ EXPORT_SYMBOL(probe_irq_mask);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(pm_idle);
EXPORT_SYMBOL(pm_power_off);
+EXPORT_SYMBOL(get_cmos_time);
+EXPORT_SYMBOL(apm_bios_info);
+EXPORT_SYMBOL(gdt);
EXPORT_SYMBOL_NOVERS(__down_failed);
EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
index c62e5c2d2..d54f9b503 100644
--- a/arch/i386/kernel/i8259.c
+++ b/arch/i386/kernel/i8259.c
@@ -311,7 +311,7 @@ spurious_8259A_irq:
}
}
-void init_8259A(int auto_eoi)
+void __init init_8259A(int auto_eoi)
{
unsigned long flags;
@@ -384,7 +384,7 @@ static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL};
#endif
-void init_ISA_irqs (void)
+void __init init_ISA_irqs (void)
{
int i;
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 0037bebdd..75b2bfb9f 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -11,6 +11,9 @@
* Hidemi Kishimoto <kisimoto@css1.kbnes.nec.co.jp>,
* further tested and cleaned up by Zach Brown <zab@redhat.com>
* and Ingo Molnar <mingo@redhat.com>
+ *
+ * Fixes
+ * Maciej W. Rozycki : Bits for genuine 82489DX APICs
*/
#include <linux/mm.h>
@@ -249,7 +252,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pci_pin)
best_guess = irq;
}
}
- return -1;
+ return best_guess;
}
/*
@@ -906,40 +909,6 @@ void disable_IO_APIC(void)
}
}
-static void __init setup_ioapic_default_id(void)
-{
- struct IO_APIC_reg_00 reg_00;
-
- /*
- * 'default' mptable configurations mean a hardwired setup,
- * 2 CPUs, 16 APIC registers. IO-APIC ID is usually set to 0,
- * setting it to ID 2 should be fine.
- */
-
- /*
- * Sanity check, is ID 2 really free? Every APIC in the
- * system must have a unique ID or we get lots of nice
- * 'stuck on smp_invalidate_needed IPI wait' messages.
- */
- if (phys_cpu_present_map & (1<<0x2))
- panic("APIC ID 2 already used");
-
- /*
- * Set the ID
- */
- *(int *)&reg_00 = io_apic_read(0, 0);
- printk("...changing IO-APIC physical APIC ID to 2...\n");
- reg_00.ID = 0x2;
- io_apic_write(0, 0, *(int *)&reg_00);
-
- /*
- * Sanity check
- */
- *(int *)&reg_00 = io_apic_read(0, 0);
- if (reg_00.ID != 0x2)
- panic("could not set ID");
-}
-
/*
* function to set the IO-APIC physical IDs based on the
* values stored in the MPC table.
@@ -967,6 +936,15 @@ static void __init setup_ioapic_ids_from_mpc (void)
printk("...changing IO-APIC physical APIC ID to %d ...",
mp_ioapics[apic].mpc_apicid);
+ /*
+ * Sanity check, is the ID really free? Every APIC in the
+ * system must have a unique ID or we get lots of nice
+ * 'stuck on smp_invalidate_needed IPI wait' messages.
+ */
+ if (phys_cpu_present_map & (1<<mp_ioapics[apic].mpc_apicid))
+ panic("APIC ID %d already used",
+ mp_ioapics[apic].mpc_apicid);
+
reg_00.ID = mp_ioapics[apic].mpc_apicid;
io_apic_write(apic, 0, *(int *)&reg_00);
@@ -1021,7 +999,6 @@ static void __init construct_default_ISA_mptable(void)
mp_irqs[0].mpc_dstirq = 2;
}
- setup_ioapic_default_id();
}
/*
@@ -1264,6 +1241,7 @@ static inline void check_timer(void)
/*
* get/set the timer IRQ vector:
*/
+ disable_8259A_irq(0);
vector = assign_irq_vector(0);
set_intr_gate(vector, interrupt[0]);
@@ -1390,7 +1368,6 @@ void IO_APIC_init_uniprocessor (void)
{
if (!smp_found_config)
return;
- phys_cpu_present_map = 0xff;
setup_local_APIC();
setup_IO_APIC();
setup_APIC_clocks();
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index 6112ac036..9d4a81041 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -713,6 +713,7 @@ unsigned long probe_irq_on(void)
if (!(status & IRQ_WAITING)) {
irq_desc[i].status = status & ~IRQ_AUTODETECT;
irq_desc[i].handler->shutdown(i);
+ continue;
}
if (i < 32)
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
new file mode 100644
index 000000000..26b6525d8
--- /dev/null
+++ b/arch/i386/kernel/microcode.c
@@ -0,0 +1,266 @@
+/*
+ * CPU Microcode Update interface for Linux
+ *
+ * Copyright (C) 2000 Tigran Aivazian
+ *
+ * This driver allows to upgrade microcode on Intel processors
+ * belonging to P6 family - PentiumPro, Pentium II, Pentium III etc.
+ *
+ * Reference: Section 8.10 of Volume III, Intel Pentium III Manual,
+ * Order Number 243192 or download from:
+ *
+ * http://developer.intel.com/design/pentiumii/manuals/243192.htm
+ *
+ * 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.
+ *
+ * 1.0 16 February 2000, Tigran Aivazian <tigran@sco.com>
+ * Initial release.
+ * 1.01 18 February 2000, Tigran Aivazian <tigran@sco.com>
+ * Added read() support + cleanups.
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/smp_lock.h>
+#include <linux/proc_fs.h>
+
+#include <asm/msr.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+
+#define MICROCODE_VERSION "1.01"
+
+MODULE_DESCRIPTION("CPU (P6) microcode update driver");
+MODULE_AUTHOR("Tigran Aivazian <tigran@ocston.org>");
+EXPORT_NO_SYMBOLS;
+
+/* VFS interface */
+static int microcode_open(struct inode *, struct file *);
+static int microcode_release(struct inode *, struct file *);
+static ssize_t microcode_read(struct file *, char *, size_t, loff_t *);
+static ssize_t microcode_write(struct file *, const char *, size_t, loff_t *);
+
+
+/* internal helpers to do the work */
+static int do_microcode_update(void);
+static void do_update_one(void *);
+
+/*
+ * Bits in microcode_status. (31 bits of room for future expansion)
+ */
+#define MICROCODE_IS_OPEN 0 /* set if /dev/microcode is in use */
+static unsigned long microcode_status = 0;
+
+/* the actual array of microcode blocks, each 2048 bytes */
+static struct microcode * microcode = NULL;
+static unsigned int microcode_num = 0;
+static char *mc_applied = NULL; /* holds an array of applied microcode blocks */
+
+static struct file_operations microcode_fops = {
+ read: microcode_read,
+ write: microcode_write,
+ open: microcode_open,
+ release: microcode_release,
+};
+
+static struct inode_operations microcode_inops = {
+ default_file_ops: &microcode_fops,
+};
+
+static struct proc_dir_entry *proc_microcode;
+
+static int __init microcode_init(void)
+{
+ int size;
+
+ proc_microcode = create_proc_entry("microcode", S_IWUSR|S_IRUSR, proc_root_driver);
+ if (!proc_microcode) {
+ printk(KERN_ERR "microcode: can't create /proc/driver/microcode\n");
+ return -ENOMEM;
+ }
+ proc_microcode->ops = &microcode_inops;
+ size = smp_num_cpus * sizeof(struct microcode);
+ mc_applied = kmalloc(size, GFP_KERNEL);
+ if (!mc_applied) {
+ remove_proc_entry("microcode", proc_root_driver);
+ printk(KERN_ERR "microcode: can't allocate memory for saved microcode\n");
+ return -ENOMEM;
+ }
+ memset(mc_applied, 0, size); /* so that reading from offsets corresponding to failed
+ update makes this obvious */
+ printk(KERN_INFO "P6 Microcode Update Driver v%s registered\n", MICROCODE_VERSION);
+ return 0;
+}
+
+static void __exit microcode_exit(void)
+{
+ remove_proc_entry("microcode", proc_root_driver);
+ kfree(mc_applied);
+ printk(KERN_INFO "P6 Microcode Update Driver v%s unregistered\n", MICROCODE_VERSION);
+}
+
+module_init(microcode_init);
+module_exit(microcode_exit);
+
+/*
+ * We enforce only one user at a time here with open/close.
+ */
+static int microcode_open(struct inode *inode, struct file *file)
+{
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ /* one at a time, please */
+ if (test_and_set_bit(MICROCODE_IS_OPEN, &microcode_status))
+ return -EBUSY;
+
+ MOD_INC_USE_COUNT;
+
+ return 0;
+}
+
+static int microcode_release(struct inode *inode, struct file *file)
+{
+ MOD_DEC_USE_COUNT;
+
+ clear_bit(MICROCODE_IS_OPEN, &microcode_status);
+ return 0;
+}
+
+/* a pointer to 'struct update_req' is passed to the IPI hanlder = do_update_one()
+ * update_req[cpu].err is set to 1 if update failed on 'cpu', 0 otherwise
+ * if err==0, microcode[update_req[cpu].slot] points to applied block of microcode
+ */
+struct update_req {
+ int err;
+ int slot;
+} update_req[NR_CPUS];
+
+static int do_microcode_update(void)
+{
+ int i, error = 0, err;
+ struct microcode *m;
+
+ if (smp_call_function(do_update_one, (void *)update_req, 1, 1) != 0)
+ panic("do_microcode_update(): timed out waiting for other CPUs\n");
+ do_update_one((void *)update_req);
+
+ for (i=0; i<smp_num_cpus; i++) {
+ err = update_req[i].err;
+ error += err;
+ if (!err) {
+ m = (struct microcode *)mc_applied + i;
+ memcpy(m, &microcode[update_req[i].slot], sizeof(struct microcode));
+ }
+ }
+ return error ? -EIO : 0;
+}
+
+static void do_update_one(void *arg)
+{
+ struct update_req *req;
+ struct cpuinfo_x86 * c;
+ unsigned int pf = 0, val[2], rev, sig;
+ int i, cpu_num;
+
+ cpu_num = smp_processor_id();
+ c = cpu_data + cpu_num;
+ req = (struct update_req *)arg + cpu_num;
+ req->err = 1; /* be pessimistic */
+
+ if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6)
+ return;
+
+ sig = c->x86_mask + (c->x86_model<<4) + (c->x86<<8);
+
+ if (c->x86_model >= 5) {
+ /* get processor flags from BBL_CR_OVRD MSR (0x17) */
+ rdmsr(0x17, val[0], val[1]);
+ pf = 1 << ((val[1] >> 18) & 7);
+ }
+
+ for (i=0; i<microcode_num; i++)
+ if (microcode[i].sig == sig && microcode[i].pf == pf &&
+ microcode[i].ldrver == 1 && microcode[i].hdrver == 1) {
+
+ rdmsr(0x8B, val[0], rev);
+ if (microcode[i].rev <= rev) {
+ printk(KERN_ERR
+ "microcode: CPU%d not 'upgrading' to earlier revision"
+ " %d (current=%d)\n", cpu_num, microcode[i].rev, rev);
+ } else {
+ int sum = 0;
+ struct microcode *m = &microcode[i];
+ unsigned int *sump = (unsigned int *)(m+1);
+
+ while (--sump >= (unsigned int *)m)
+ sum += *sump;
+ if (sum != 0) {
+ printk(KERN_ERR "microcode: CPU%d aborting, "
+ "bad checksum\n", cpu_num);
+ break;
+ }
+
+ wrmsr(0x79, (unsigned int)(m->bits), 0);
+ __asm__ __volatile__ ("cpuid");
+ rdmsr(0x8B, val[0], val[1]);
+
+ req->err = 0;
+ req->slot = i;
+ printk(KERN_ERR "microcode: CPU%d microcode updated "
+ "from revision %d to %d, date=%08x\n",
+ cpu_num, rev, val[1], m->date);
+ }
+ break;
+ }
+}
+
+static ssize_t microcode_read(struct file *file, char *buf, size_t len, loff_t *ppos)
+{
+ size_t fsize = smp_num_cpus * sizeof(struct microcode);
+
+ if (!proc_microcode->size || *ppos >= fsize)
+ return 0; /* EOF */
+ if (*ppos + len > fsize)
+ len = fsize - *ppos;
+ if (copy_to_user(buf, mc_applied + *ppos, len))
+ return -EFAULT;
+ *ppos += len;
+ return len;
+}
+
+static ssize_t microcode_write(struct file *file, const char *buf, size_t len, loff_t *ppos)
+{
+ ssize_t ret;
+
+ if (len % sizeof(struct microcode) != 0) {
+ printk(KERN_ERR "microcode: can only write in N*%d bytes units\n",
+ sizeof(struct microcode));
+ return -EINVAL;
+ }
+ lock_kernel();
+ microcode_num = len/sizeof(struct microcode);
+ microcode = vmalloc(len);
+ if (!microcode) {
+ unlock_kernel();
+ return -ENOMEM;
+ }
+ if (copy_from_user(microcode, buf, len)) {
+ vfree(microcode);
+ unlock_kernel();
+ return -EFAULT;
+ }
+ ret = do_microcode_update();
+ if (!ret) {
+ proc_microcode->size = smp_num_cpus * sizeof(struct microcode);
+ ret = (ssize_t)len;
+ }
+ vfree(microcode);
+ unlock_kernel();
+ return ret;
+}
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index 977dd18ba..81685d2f5 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -9,7 +9,7 @@
* Erich Boleyn : MP v1.4 and additional changes.
* Alan Cox : Added EBDA scanning
* Ingo Molnar : various cleanups and rewrites
- * Maciej W. Rozycki : Bits for genuine 82489DX timers
+ * Maciej W. Rozycki : Bits for genuine 82489DX APICs
*/
#include <linux/mm.h>
@@ -339,6 +339,8 @@ static int __init smp_get_mpf(struct intel_mp_floating *mpf)
* Now see if we need to read further.
*/
if (mpf->mpf_feature1 != 0) {
+ printk("Default MP configuration #%d\n", mpf->mpf_feature1);
+
/*
* local APIC has default address
*/
@@ -352,6 +354,7 @@ static int __init smp_get_mpf(struct intel_mp_floating *mpf)
nr_ioapics = 1;
mp_ioapics[0].mpc_apicaddr = 0xFEC00000;
+ mp_ioapics[0].mpc_apicid = 2;
/*
* Save the default type number, we
* need it later to set the IO-APIC
diff --git a/arch/i386/kernel/mtrr.c b/arch/i386/kernel/mtrr.c
index 5caa4e477..a0a4ab851 100644
--- a/arch/i386/kernel/mtrr.c
+++ b/arch/i386/kernel/mtrr.c
@@ -1,6 +1,6 @@
/* Generic MTRR (Memory Type Range Register) driver.
- Copyright (C) 1997-1999 Richard Gooch
+ Copyright (C) 1997-2000 Richard Gooch
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -133,7 +133,7 @@
Fixed version numbering and history for v1.23 -> v1.24.
v1.26
19990118 Richard Gooch <rgooch@atnf.csiro.au>
- PLACEHOLDER.
+ Added devfs support.
v1.27
19990123 Richard Gooch <rgooch@atnf.csiro.au>
Changed locking to spin with reschedule.
@@ -178,7 +178,6 @@
Moved to linux/arch/i386/kernel/setup.c and
linux/include/asm-i386/bugs.h
19990228 Richard Gooch <rgooch@atnf.csiro.au>
- Added #ifdef CONFIG_DEVFS_FS
Added MTRRIOC_KILL_ENTRY ioctl(2)
Trap for counter underflow in <mtrr_file_del>.
Trap for 4 MiB aligned regions for PPro, stepping <= 7.
@@ -225,6 +224,10 @@
success.
19991008 Manfred Spraul <manfreds@colorfullife.com>
replaced spin_lock_reschedule() with a normal semaphore.
+ v1.36
+ 20000221 Richard Gooch <rgooch@atnf.csiro.au>
+ Compile fix if procfs and devfs not enabled.
+ Formatting changes.
*/
#include <linux/types.h>
#include <linux/errno.h>
@@ -241,6 +244,7 @@
#include <linux/fs.h>
#include <linux/ctype.h>
#include <linux/proc_fs.h>
+#include <linux/devfs_fs_kernel.h>
#include <linux/mm.h>
#include <linux/module.h>
#define MTRR_NEED_STRINGS
@@ -261,7 +265,7 @@
#include <asm/hardirq.h>
#include <linux/irq.h>
-#define MTRR_VERSION "1.35 (19990512)"
+#define MTRR_VERSION "1.36 (20000221)"
#define TRUE 1
#define FALSE 0
@@ -305,11 +309,15 @@ typedef u8 mtrr_type;
TRUE)
#endif
-#ifndef CONFIG_PROC_FS
+#if defined(CONFIG_PROC_FS) || defined(CONFIG_DEVFS_FS)
+# define USERSPACE_INTERFACE
+#endif
+
+#ifndef USERSPACE_INTERFACE
# define compute_ascii() while (0)
#endif
-#ifdef CONFIG_PROC_FS
+#ifdef USERSPACE_INTERFACE
static char *ascii_buffer = NULL;
static unsigned int ascii_buf_bytes = 0;
#endif
@@ -317,7 +325,7 @@ static unsigned int *usage_table = NULL;
static DECLARE_MUTEX(main_lock);
/* Private functions */
-#ifdef CONFIG_PROC_FS
+#ifdef USERSPACE_INTERFACE
static void compute_ascii (void);
#endif
@@ -480,8 +488,9 @@ static void intel_get_mtrr (unsigned int reg, unsigned long *base,
unsigned long dummy, mask_lo, base_lo;
rdmsr (MTRRphysMask_MSR(reg), mask_lo, dummy);
- if ((mask_lo & 0x800) == 0) {
- /* Invalid (i.e. free) range. */
+ if ( (mask_lo & 0x800) == 0 )
+ {
+ /* Invalid (i.e. free) range */
*base = 0;
*size = 0;
*type = 0;
@@ -537,22 +546,26 @@ static void cyrix_get_arr (unsigned int reg, unsigned long *base,
*size = 0;
/* Bit 0 is Cache Enable on ARR7, Cache Disable on ARR0-ARR6 */
- if (reg < 7) {
- switch (rcr) {
- case 1: *type = MTRR_TYPE_UNCACHABLE; break;
- case 8: *type = MTRR_TYPE_WRBACK; break;
- case 9: *type = MTRR_TYPE_WRCOMB; break;
- case 24:
- default: *type = MTRR_TYPE_WRTHROUGH; break;
- }
- } else {
- switch (rcr) {
- case 0: *type = MTRR_TYPE_UNCACHABLE; break;
- case 8: *type = MTRR_TYPE_WRCOMB; break;
- case 9: *type = MTRR_TYPE_WRBACK; break;
- case 25:
- default: *type = MTRR_TYPE_WRTHROUGH; break;
- }
+ if (reg < 7)
+ {
+ switch (rcr)
+ {
+ case 1: *type = MTRR_TYPE_UNCACHABLE; break;
+ case 8: *type = MTRR_TYPE_WRBACK; break;
+ case 9: *type = MTRR_TYPE_WRCOMB; break;
+ case 24:
+ default: *type = MTRR_TYPE_WRTHROUGH; break;
+ }
+ } else
+ {
+ switch (rcr)
+ {
+ case 0: *type = MTRR_TYPE_UNCACHABLE; break;
+ case 8: *type = MTRR_TYPE_WRCOMB; break;
+ case 9: *type = MTRR_TYPE_WRBACK; break;
+ case 25:
+ default: *type = MTRR_TYPE_WRTHROUGH; break;
+ }
}
} /* End Function cyrix_get_arr */
@@ -653,20 +666,24 @@ static void cyrix_set_arr_up (unsigned int reg, unsigned long base,
size &= 0x7fff; /* make sure arr_size <= 14 */
for(arr_size = 0; size; arr_size++, size >>= 1);
- if (reg<7) {
- switch (type) {
- case MTRR_TYPE_UNCACHABLE: arr_type = 1; break;
- case MTRR_TYPE_WRCOMB: arr_type = 9; break;
- case MTRR_TYPE_WRTHROUGH: arr_type = 24; break;
- default: arr_type = 8; break;
- }
- } else {
- switch (type) {
- case MTRR_TYPE_UNCACHABLE: arr_type = 0; break;
- case MTRR_TYPE_WRCOMB: arr_type = 8; break;
- case MTRR_TYPE_WRTHROUGH: arr_type = 25; break;
- default: arr_type = 9; break;
- }
+ if (reg<7)
+ {
+ switch (type) {
+ case MTRR_TYPE_UNCACHABLE: arr_type = 1; break;
+ case MTRR_TYPE_WRCOMB: arr_type = 9; break;
+ case MTRR_TYPE_WRTHROUGH: arr_type = 24; break;
+ default: arr_type = 8; break;
+ }
+ }
+ else
+ {
+ switch (type)
+ {
+ case MTRR_TYPE_UNCACHABLE: arr_type = 0; break;
+ case MTRR_TYPE_WRCOMB: arr_type = 8; break;
+ case MTRR_TYPE_WRTHROUGH: arr_type = 25; break;
+ default: arr_type = 9; break;
+ }
}
if (do_safe) set_mtrr_prepare (&ctxt);
@@ -779,16 +796,18 @@ static int __init set_mtrr_var_range_testing (unsigned int index,
int changed = FALSE;
rdmsr(MTRRphysBase_MSR(index), lo, hi);
- if ((vr->base_lo & 0xfffff0ffUL) != (lo & 0xfffff0ffUL)
- || (vr->base_hi & 0xfUL) != (hi & 0xfUL)) {
- wrmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi);
+ if ( (vr->base_lo & 0xfffff0ffUL) != (lo & 0xfffff0ffUL)
+ || (vr->base_hi & 0xfUL) != (hi & 0xfUL) )
+ {
+ wrmsr (MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi);
changed = TRUE;
}
- rdmsr(MTRRphysMask_MSR(index), lo, hi);
+ rdmsr (MTRRphysMask_MSR(index), lo, hi);
- if ((vr->mask_lo & 0xfffff800UL) != (lo & 0xfffff800UL)
- || (vr->mask_hi & 0xfUL) != (hi & 0xfUL)) {
+ if ( (vr->mask_lo & 0xfffff800UL) != (lo & 0xfffff800UL)
+ || (vr->mask_hi & 0xfUL) != (hi & 0xfUL) )
+ {
wrmsr(MTRRphysMask_MSR(index), vr->mask_lo, vr->mask_hi);
changed = TRUE;
}
@@ -816,22 +835,27 @@ static int __init set_fixed_ranges_testing(mtrr_type *frs)
unsigned long lo, hi;
rdmsr(MTRRfix64K_00000_MSR, lo, hi);
- if (p[0] != lo || p[1] != hi) {
- wrmsr(MTRRfix64K_00000_MSR, p[0], p[1]);
+ if (p[0] != lo || p[1] != hi)
+ {
+ wrmsr (MTRRfix64K_00000_MSR, p[0], p[1]);
changed = TRUE;
}
- for (i = 0; i < 2; i++) {
- rdmsr(MTRRfix16K_80000_MSR + i, lo, hi);
- if (p[2 + i*2] != lo || p[3 + i*2] != hi) {
- wrmsr(MTRRfix16K_80000_MSR + i, p[2 + i*2], p[3 + i*2]);
+ for (i = 0; i < 2; i++)
+ {
+ rdmsr (MTRRfix16K_80000_MSR + i, lo, hi);
+ if (p[2 + i*2] != lo || p[3 + i*2] != hi)
+ {
+ wrmsr (MTRRfix16K_80000_MSR + i, p[2 + i*2], p[3 + i*2]);
changed = TRUE;
}
}
- for (i = 0; i < 8; i++) {
- rdmsr(MTRRfix4K_C0000_MSR + i, lo, hi);
- if (p[6 + i*2] != lo || p[7 + i*2] != hi) {
+ for (i = 0; i < 8; i++)
+ {
+ rdmsr (MTRRfix4K_C0000_MSR + i, lo, hi);
+ if (p[6 + i*2] != lo || p[7 + i*2] != hi)
+ {
wrmsr(MTRRfix4K_C0000_MSR + i, p[6 + i*2], p[7 + i*2]);
changed = TRUE;
}
@@ -899,8 +923,8 @@ static unsigned long __init set_mtrr_state (struct mtrr_state *state,
change_mask |= MTRR_CHANGE_MASK_FIXED;
/* Set_mtrr_restore restores the old value of MTRRdefType,
so to set it we fiddle with the saved value */
- if ((ctxt->deftype_lo & 0xff) != state->def_type
- || ((ctxt->deftype_lo & 0xc00) >> 10) != state->enabled)
+ if ( (ctxt->deftype_lo & 0xff) != state->def_type
+ || ( (ctxt->deftype_lo & 0xc00) >> 10 ) != state->enabled)
{
ctxt->deftype_lo |= (state->def_type | state->enabled << 10);
change_mask |= MTRR_CHANGE_MASK_DEFTYPE;
@@ -1010,7 +1034,7 @@ static void init_table (void)
return;
}
for (i = 0; i < max; i++) usage_table[i] = 1;
-#ifdef CONFIG_PROC_FS
+#ifdef USERSPACE_INTERFACE
if ( ( ascii_buffer = kmalloc (max * LINE_SIZE, GFP_KERNEL) ) == NULL )
{
printk ("mtrr: could not allocate\n");
@@ -1053,11 +1077,14 @@ static int cyrix_get_free_region (unsigned long base, unsigned long size)
unsigned long lbase, lsize;
/* If we are to set up a region >32M then look at ARR7 immediately */
- if (size > 0x2000000UL) {
+ if (size > 0x2000000UL)
+ {
cyrix_get_arr (7, &lbase, &lsize, &ltype);
if (lsize < 1) return 7;
- /* else try ARR0-ARR6 first */
- } else {
+ /* Else try ARR0-ARR6 first */
+ }
+ else
+ {
for (i = 0; i < 7; i++)
{
cyrix_get_arr (i, &lbase, &lsize, &ltype);
@@ -1095,29 +1122,32 @@ int mtrr_add (unsigned long base, unsigned long size, unsigned int type,
switch (boot_cpu_data.x86_vendor)
{
case X86_VENDOR_AMD:
- if (boot_cpu_data.x86 < 6) { /* pre-Athlon CPUs */
- /* Apply the K6 block alignment and size rules
+ if (boot_cpu_data.x86 < 6)
+ { /* pre-Athlon CPUs */
+ /* Apply the K6 block alignment and size rules
In order
o Uncached or gathering only
o 128K or bigger block
o Power of 2 block
o base suitably aligned to the power
*/
- if (type > MTRR_TYPE_WRCOMB || size < (1 << 17) ||
- (size & ~(size-1))-size || (base & (size-1)))
- return -EINVAL;
+ if ( type > MTRR_TYPE_WRCOMB || size < (1 << 17) ||
+ (size & ~(size-1))-size || ( base & (size-1) ) )
+ return -EINVAL;
break;
- } /* else fall through */
+ }
+ /* Else fall through */
case X86_VENDOR_INTEL:
- /* Double check for Intel, we may run on Athlon. */
- if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
- /* For Intel PPro stepping <= 7, must be 4 MiB aligned */
- if ( (boot_cpu_data.x86 == 6) && (boot_cpu_data.x86_model == 1) &&
- (boot_cpu_data.x86_mask <= 7) && ( base & ( (1 << 22) - 1 ) ) )
- {
- printk ("mtrr: base(0x%lx) is not 4 MiB aligned\n", base);
- return -EINVAL;
- }
+ /* Double check for Intel, we may run on Athlon */
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+ {
+ /* For Intel PPro stepping <= 7, must be 4 MiB aligned */
+ if ( (boot_cpu_data.x86 == 6) && (boot_cpu_data.x86_model == 1) &&
+ (boot_cpu_data.x86_mask <= 7) && ( base & ( (1 << 22) -1 ) ) )
+ {
+ printk ("mtrr: base(0x%lx) is not 4 MiB aligned\n", base);
+ return -EINVAL;
+ }
}
/* Fall through */
case X86_VENDOR_CYRIX:
@@ -1232,7 +1262,7 @@ int mtrr_del (int reg, unsigned long base, unsigned long size)
if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return -ENODEV;
max = get_num_var_ranges ();
- down(&main_lock);
+ down (&main_lock);
if (reg < 0)
{
/* Search for existing MTRR */
@@ -1254,15 +1284,15 @@ int mtrr_del (int reg, unsigned long base, unsigned long size)
}
if (reg >= max)
{
- up(&main_lock);
+ up (&main_lock);
printk ("mtrr: register: %d too big\n", reg);
return -EINVAL;
}
if (boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX)
{
- if ((reg == 3) && arr3_protected)
+ if ( (reg == 3) && arr3_protected )
{
- up(&main_lock);
+ up (&main_lock);
printk ("mtrr: ARR3 cannot be changed\n");
return -EINVAL;
}
@@ -1270,23 +1300,23 @@ int mtrr_del (int reg, unsigned long base, unsigned long size)
(*get_mtrr) (reg, &lbase, &lsize, &ltype);
if (lsize < 1)
{
- up(&main_lock);
+ up (&main_lock);
printk ("mtrr: MTRR %d not used\n", reg);
return -EINVAL;
}
if (usage_table[reg] < 1)
{
- up(&main_lock);
+ up (&main_lock);
printk ("mtrr: reg: %d has count=0\n", reg);
return -EINVAL;
}
if (--usage_table[reg] < 1) set_mtrr (reg, 0, 0, 0);
compute_ascii ();
- up(&main_lock);
+ up (&main_lock);
return reg;
} /* End Function mtrr_del */
-#ifdef CONFIG_PROC_FS
+#ifdef USERSPACE_INTERFACE
static int mtrr_file_add (unsigned long base, unsigned long size,
unsigned int type, char increment, struct file *file)
@@ -1469,18 +1499,25 @@ static int mtrr_close (struct inode *ino, struct file *file)
static struct file_operations mtrr_fops =
{
- read: mtrr_read,
- write: mtrr_write,
- ioctl: mtrr_ioctl,
- release: mtrr_close,
+ read: mtrr_read,
+ write: mtrr_write,
+ ioctl: mtrr_ioctl,
+ release: mtrr_close,
};
-static struct inode_operations proc_mtrr_inode_operations = {
- &mtrr_fops, /* default property file-ops */
+# ifdef CONFIG_PROC_FS
+
+static struct inode_operations proc_mtrr_inode_operations =
+{
+ &mtrr_fops, /* default property file-ops */
};
static struct proc_dir_entry *proc_root_mtrr;
+# endif /* CONFIG_PROC_FS */
+
+static devfs_handle_t devfs_handle = NULL;
+
static void compute_ascii (void)
{
char factor;
@@ -1515,25 +1552,30 @@ static void compute_ascii (void)
ascii_buf_bytes += strlen (ascii_buffer + ascii_buf_bytes);
}
}
+ devfs_set_file_size (devfs_handle, ascii_buf_bytes);
+# ifdef CONFIG_PROC_FS
proc_root_mtrr->size = ascii_buf_bytes;
+# endif /* CONFIG_PROC_FS */
} /* End Function compute_ascii */
-#endif /* CONFIG_PROC_FS */
+#endif /* USERSPACE_INTERFACE */
EXPORT_SYMBOL(mtrr_add);
EXPORT_SYMBOL(mtrr_del);
#ifdef __SMP__
-typedef struct {
- unsigned long base;
- unsigned long size;
- mtrr_type type;
+typedef struct
+{
+ unsigned long base;
+ unsigned long size;
+ mtrr_type type;
} arr_state_t;
-arr_state_t arr_state[8] __initdata = {
- {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL},
- {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL}
+arr_state_t arr_state[8] __initdata =
+{
+ {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL},
+ {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL}
};
unsigned char ccr_state[7] __initdata = { 0, 0, 0, 0, 0, 0, 0 };
@@ -1591,31 +1633,35 @@ static void __init cyrix_arr_init(void)
ccr[5] = getCx86 (CX86_CCR5);
ccr[6] = getCx86 (CX86_CCR6);
- if (ccr[3] & 1) {
- ccrc[3] = 1;
- arr3_protected = 1;
- } else {
- /* Disable SMM mode (bit 1), access to SMM memory (bit 2) and
- * access to SMM memory through ARR3 (bit 7).
- */
- if (ccr[1] & 0x80) { ccr[1] &= 0x7f; ccrc[1] |= 0x80; }
- if (ccr[1] & 0x04) { ccr[1] &= 0xfb; ccrc[1] |= 0x04; }
- if (ccr[1] & 0x02) { ccr[1] &= 0xfd; ccrc[1] |= 0x02; }
- arr3_protected = 0;
- if (ccr[6] & 0x02) {
- ccr[6] &= 0xfd; ccrc[6] = 1; /* Disable write protection of ARR3. */
- setCx86 (CX86_CCR6, ccr[6]);
- }
- /* Disable ARR3. This is safe now that we disabled SMM. */
- /* cyrix_set_arr_up (3, 0, 0, 0, FALSE); */
+ if (ccr[3] & 1)
+ {
+ ccrc[3] = 1;
+ arr3_protected = 1;
+ }
+ else
+ {
+ /* Disable SMM mode (bit 1), access to SMM memory (bit 2) and
+ * access to SMM memory through ARR3 (bit 7).
+ */
+ if (ccr[1] & 0x80) { ccr[1] &= 0x7f; ccrc[1] |= 0x80; }
+ if (ccr[1] & 0x04) { ccr[1] &= 0xfb; ccrc[1] |= 0x04; }
+ if (ccr[1] & 0x02) { ccr[1] &= 0xfd; ccrc[1] |= 0x02; }
+ arr3_protected = 0;
+ if (ccr[6] & 0x02) {
+ ccr[6] &= 0xfd; ccrc[6] = 1; /* Disable write protection of ARR3 */
+ setCx86 (CX86_CCR6, ccr[6]);
+ }
+ /* Disable ARR3. This is safe now that we disabled SMM. */
+ /* cyrix_set_arr_up (3, 0, 0, 0, FALSE); */
}
/* If we changed CCR1 in memory, change it in the processor, too. */
if (ccrc[1]) setCx86 (CX86_CCR1, ccr[1]);
/* Enable ARR usage by the processor */
- if (!(ccr[5] & 0x20)) {
- ccr[5] |= 0x20; ccrc[5] = 1;
- setCx86 (CX86_CCR5, ccr[5]);
+ if (!(ccr[5] & 0x20))
+ {
+ ccr[5] |= 0x20; ccrc[5] = 1;
+ setCx86 (CX86_CCR5, ccr[5]);
}
#ifdef __SMP__
@@ -1667,11 +1713,14 @@ static void __init mtrr_setup(void)
switch (boot_cpu_data.x86_vendor)
{
case X86_VENDOR_AMD:
- if (boot_cpu_data.x86 < 6) { /* pre-Athlon CPUs */
- get_mtrr = amd_get_mtrr;
- set_mtrr_up = amd_set_mtrr_up;
- break;
- } /* else fall through */
+ if (boot_cpu_data.x86 < 6)
+ {
+ /* pre-Athlon CPUs */
+ get_mtrr = amd_get_mtrr;
+ set_mtrr_up = amd_set_mtrr_up;
+ break;
+ }
+ /* Else fall through */
case X86_VENDOR_INTEL:
get_mtrr = intel_get_mtrr;
set_mtrr_up = intel_set_mtrr_up;
@@ -1700,7 +1749,7 @@ void __init mtrr_init_boot_cpu(void)
switch (boot_cpu_data.x86_vendor)
{
case X86_VENDOR_AMD:
- if (boot_cpu_data.x86 < 6) break; /* pre-Athlon CPUs */
+ if (boot_cpu_data.x86 < 6) break; /* Pre-Athlon CPUs */
case X86_VENDOR_INTEL:
get_mtrr_state (&smp_mtrr_state);
break;
@@ -1738,7 +1787,7 @@ void __init mtrr_init_secondary_cpu(void)
switch (boot_cpu_data.x86_vendor)
{
case X86_VENDOR_AMD:
- /* Just for robustness: pre-Athlon CPUs cannot do SMP. */
+ /* Just for robustness: pre-Athlon CPUs cannot do SMP */
if (boot_cpu_data.x86 < 6) break;
case X86_VENDOR_INTEL:
intel_mtrr_init_secondary_cpu ();
@@ -1762,17 +1811,17 @@ void __init mtrr_init_secondary_cpu(void)
int __init mtrr_init(void)
{
if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return 0;
-# ifdef __SMP__
+#ifdef __SMP__
switch (boot_cpu_data.x86_vendor)
{
case X86_VENDOR_AMD:
- if (boot_cpu_data.x86 < 6) break; /* pre-Athlon CPUs */
+ if (boot_cpu_data.x86 < 6) break; /* Pre-Athlon CPUs */
case X86_VENDOR_INTEL:
finalize_mtrr_state (&smp_mtrr_state);
mtrr_state_warn (smp_changes_mask);
break;
}
-# else /* __SMP__ */
+#else /* __SMP__ */
mtrr_setup ();
switch (boot_cpu_data.x86_vendor)
{
@@ -1783,12 +1832,17 @@ int __init mtrr_init(void)
centaur_mcr_init ();
break;
}
-# endif /* !__SMP__ */
+#endif /* !__SMP__ */
-# ifdef CONFIG_PROC_FS
- proc_root_mtrr = create_proc_entry("mtrr", S_IWUSR|S_IRUGO, &proc_root);
+#ifdef CONFIG_PROC_FS
+ proc_root_mtrr = create_proc_entry ("mtrr", S_IWUSR | S_IRUGO, &proc_root);
proc_root_mtrr->ops = &proc_mtrr_inode_operations;
-#endif
+#endif
+#ifdev CONFIG_DEVFS_FS
+ devfs_handle = devfs_register (NULL, "cpu/mtrr", 0, DEVFS_FL_DEFAULT, 0, 0,
+ S_IFREG | S_IRUGO | S_IWUSR, 0, 0,
+ &mtrr_fops, NULL);
+#endif
init_table ();
return 0;
} /* End Function mtrr_init */
diff --git a/arch/i386/kernel/pci-dma.c b/arch/i386/kernel/pci-dma.c
index 18b203228..4bd1486fe 100644
--- a/arch/i386/kernel/pci-dma.c
+++ b/arch/i386/kernel/pci-dma.c
@@ -13,20 +13,6 @@
#include <linux/pci.h>
#include <asm/io.h>
-/* Pure 2^n version of get_order */
-extern __inline__ int __get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
dma_addr_t *dma_handle)
{
@@ -35,7 +21,7 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
if (hwdev == NULL || hwdev->dma_mask != 0xffffffff)
gfp |= GFP_DMA;
- ret = (void *)__get_free_pages(gfp, __get_order(size));
+ ret = (void *)__get_free_pages(gfp, get_order(size));
if (ret != NULL) {
memset(ret, 0, size);
@@ -47,5 +33,5 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
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));
+ free_pages((unsigned long)vaddr, get_order(size));
}
diff --git a/arch/i386/kernel/pci-i386.c b/arch/i386/kernel/pci-i386.c
index ee2edca1e..6dd0a4306 100644
--- a/arch/i386/kernel/pci-i386.c
+++ b/arch/i386/kernel/pci-i386.c
@@ -132,7 +132,7 @@ pcibios_align_resource(void *data, struct resource *res, unsigned long size)
/* 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) {
+ if (size > 0x100) {
printk(KERN_ERR "PCI: I/O Region %s/%d too large"
" (%ld bytes)\n", dev->slot_name,
dev->resource - res, size);
diff --git a/arch/i386/kernel/pci-pc.c b/arch/i386/kernel/pci-pc.c
index 590e01fd5..d5b2b0062 100644
--- a/arch/i386/kernel/pci-pc.c
+++ b/arch/i386/kernel/pci-pc.c
@@ -883,6 +883,18 @@ static void __init pci_fixup_i450nx(struct pci_dev *d)
}
}
+static void __init pci_fixup_i450gx(struct pci_dev *d)
+{
+ /*
+ * i450GX and i450KX -- Find and scan all secondary buses.
+ * (called separately for each PCI bridge found)
+ */
+ u8 busno;
+ pci_read_config_byte(d, 0x4a, &busno);
+ printk("PCI: i440KX/GX host bridge %s: secondary bus %02x\n", d->slot_name, busno);
+ pci_scan_bus(busno, pci_root_ops, NULL);
+}
+
static void __init pci_fixup_rcc(struct pci_dev *d)
{
/*
@@ -954,6 +966,7 @@ static void __init pci_fixup_ide_trash(struct pci_dev *d)
struct pci_fixup pcibios_fixups[] = {
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_RCC, PCI_DEVICE_ID_RCC_HE, pci_fixup_rcc },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_RCC, PCI_DEVICE_ID_RCC_LE, pci_fixup_rcc },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_6010, pci_fixup_compaq },
@@ -1036,6 +1049,18 @@ static void __init pcibios_irq_peer_trick(struct irq_routing_table *rt)
* table, but unfortunately we have to know the interrupt router chip.
*/
+/*
+ * Never use: 0, 1, 2 (timer, keyboard, and cascade)
+ * Avoid using: 13, 14 and 15 (FP error and IDE).
+ * Penalize: 3, 4, 7, 12 (known ISA uses: serial, parallel and mouse)
+ */
+static unsigned int pcibios_irq_mask = 0xfff8;
+
+static unsigned pcibios_irq_penalty[16] = {
+ 10000, 10000, 10000, 100, 100, 0, 0, 100,
+ 0, 0, 0, 0, 100, 1000, 1000, 1000
+};
+
static char *pcibios_lookup_irq(struct pci_dev *dev, struct irq_routing_table *rt, int pin, int assign)
{
struct irq_info *q;
@@ -1043,6 +1068,7 @@ static char *pcibios_lookup_irq(struct pci_dev *dev, struct irq_routing_table *r
int i, pirq, newirq;
u32 rtrid, mask;
u8 x;
+ char *msg = NULL;
pin--;
DBG("IRQ for %s(%d)", dev->slot_name, pin);
@@ -1066,10 +1092,15 @@ static char *pcibios_lookup_irq(struct pci_dev *dev, struct irq_routing_table *r
return NULL;
}
DBG(" -> PIRQ %02x, mask %04x", pirq, mask);
- if (!assign || (dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
- newirq = 0;
- else for(newirq = 13; newirq && !(mask & (1 << newirq)); newirq--)
- ;
+ newirq = 0;
+ if (assign && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
+ for (i = 0; i < 16; i++) {
+ if (!(mask & pcibios_irq_mask & (1 << i)))
+ continue;
+ if (pcibios_irq_penalty[i] < pcibios_irq_penalty[newirq])
+ newirq = i;
+ }
+ }
if (!(router = pci_find_slot(rt->rtr_bus, rt->rtr_devfn))) {
DBG(" -> router not found\n");
return NULL;
@@ -1094,27 +1125,30 @@ static char *pcibios_lookup_irq(struct pci_dev *dev, struct irq_routing_table *r
pci_read_config_byte(router, pirq, &x);
if (x < 16) {
DBG(" -> [PIIX] %02x\n", x);
- dev->irq = x;
- return "PIIX";
+ newirq = x;
+ msg = "PIIX";
} else if (newirq) {
DBG(" -> [PIIX] set to %02x\n", newirq);
pci_write_config_byte(router, pirq, newirq);
- dev->irq = newirq;
- return "PIIX-NEW";
- }
- DBG(" -> [PIIX] sink\n");
- return NULL;
+ msg = "PIIX-NEW";
+ } else
+ DBG(" -> [PIIX] sink\n");
+ break;
case ID(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533):
default:
DBG(" -> unknown router %04x/%04x\n", rt->rtr_vendor, rt->rtr_device);
if (newirq && mask == (1 << newirq)) {
/* Only one IRQ available -> use it */
- dev->irq = newirq;
- return "guess";
+ msg = "guess";
}
- return NULL;
}
#undef ID
+
+ if (msg) {
+ dev->irq = newirq;
+ pcibios_irq_penalty[newirq]++;
+ }
+ return msg;
}
static void __init pcibios_fixup_irqs(void)
@@ -1134,6 +1168,18 @@ static void __init pcibios_fixup_irqs(void)
pcibios_irq_peer_trick(rtable);
pci_for_each_dev(dev) {
+ /*
+ * If the BIOS has set an out of range IRQ number, just ignore it.
+ * Also keep track of which IRQ's are already in use.
+ */
+ if (dev->irq >= 16) {
+ DBG("%s: ignoring bogus IRQ %d\n", dev->slot_name, dev->irq);
+ dev->irq = 0;
+ }
+ pcibios_irq_penalty[dev->irq]++;
+ }
+
+ pci_for_each_dev(dev) {
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
#if defined(CONFIG_X86_IO_APIC)
/*
@@ -1171,10 +1217,8 @@ static void __init pcibios_fixup_irqs(void)
}
#endif
/*
- * Fix out-of-range IRQ numbers and missing IRQs.
+ * Still no IRQ? Try to assign one...
*/
- if (dev->irq >= NR_IRQS)
- dev->irq = 0;
if (pin && !dev->irq && pirq_table) {
char *msg = pcibios_lookup_irq(dev, pirq_table, pin, 0);
if (msg)
@@ -1280,6 +1324,9 @@ char * __init pcibios_setup(char *str)
} else if (!strcmp(str, "rom")) {
pci_probe |= PCI_ASSIGN_ROMS;
return NULL;
+ } else if (!strncmp(str, "irqmask=", 8)) {
+ pcibios_irq_mask = simple_strtol(str+8, NULL, 0);
+ return NULL;
}
return str;
}
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index c38e383e7..0f61ca543 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -48,16 +48,6 @@ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
int hlt_counter=0;
-void disable_hlt(void)
-{
- hlt_counter++;
-}
-
-void enable_hlt(void)
-{
- hlt_counter--;
-}
-
/*
* Powermanagement idle function, if any..
*/
@@ -68,6 +58,16 @@ void (*pm_idle)(void) = NULL;
*/
void (*pm_power_off)(void) = NULL;
+void disable_hlt(void)
+{
+ hlt_counter++;
+}
+
+void enable_hlt(void)
+{
+ hlt_counter--;
+}
+
/*
* We use this if we don't have any better
* idle routine..
@@ -293,7 +293,7 @@ void machine_real_restart(unsigned char *code, int length)
void machine_restart(char * __unused)
{
-#if __SMP__
+#if CONFIG_SMP
/*
* Stop all CPUs and turn off local APICs and the IO-APIC, so
* other OSs see a clean IRQ state.
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index e72f95160..cd2a3d8af 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -1515,7 +1515,7 @@ unsigned long cpu_initialized = 0;
* and IDT. We reload them nevertheless, this function acts as a
* 'CPU state barrier', nothing should get across.
*/
-void cpu_init (void)
+void __init cpu_init (void)
{
int nr = smp_processor_id();
struct tss_struct * t = &init_tss[nr];
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index 0b585513f..12f193c71 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -103,7 +103,7 @@
/* The 'big kernel lock' */
spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
-struct tlb_state cpu_tlbstate[NR_CPUS];
+struct tlb_state cpu_tlbstate[NR_CPUS] = {[0 ... NR_CPUS-1] = { &init_mm, 0 }};
/*
* the following functions deal with sending IPIs between CPUs.
@@ -347,12 +347,7 @@ asmlinkage void smp_invalidate_interrupt (void)
__flush_tlb_one(flush_va);
} else
leave_mm(cpu);
- } else {
- extern void show_stack (void *);
- printk("hm #1: %p, %p.\n", flush_mm, cpu_tlbstate[cpu].active_mm);
- show_stack(NULL);
}
- __flush_tlb();
ack_APIC_irq();
clear_bit(cpu, &flush_cpumask);
}
@@ -382,7 +377,7 @@ static void flush_tlb_others (unsigned long cpumask, struct mm_struct *mm,
* Temporarily this turns IRQs off, so that lockups are
* detected by the NMI watchdog.
*/
- spin_lock_irq(&tlbstate_lock);
+ spin_lock(&tlbstate_lock);
flush_mm = mm;
flush_va = va;
@@ -398,7 +393,7 @@ static void flush_tlb_others (unsigned long cpumask, struct mm_struct *mm,
flush_mm = NULL;
flush_va = 0;
- spin_unlock_irq(&tlbstate_lock);
+ spin_unlock(&tlbstate_lock);
}
void flush_tlb_current_task(void)
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 4ef25674f..c3991b056 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -307,27 +307,30 @@ static void __init pagetable_init(void)
pmd_t *pmd;
pte_t *pte;
int i, j, k;
- unsigned long vaddr;
- unsigned long end = (unsigned long)__va(max_low_pfn*PAGE_SIZE);
+ unsigned long vaddr, end;
- pgd_base = swapper_pg_dir;
+ end = (unsigned long)__va(max_low_pfn*PAGE_SIZE) - 1;
- vaddr = PAGE_OFFSET;
- i = __pgd_offset(vaddr);
+ i = __pgd_offset(PAGE_OFFSET);
+ pgd_base = swapper_pg_dir;
pgd = pgd_base + i;
- for (; (i < PTRS_PER_PGD) && (vaddr <= end); pgd++, i++) {
+ for (; i < PTRS_PER_PGD; pgd++, i++) {
vaddr = i*PGDIR_SIZE;
+ if (vaddr >= end)
+ break;
#if CONFIG_X86_PAE
- pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ pmd = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE);
set_pgd(pgd, __pgd(__pa(pmd) + 0x1));
#else
pmd = (pmd_t *)pgd;
#endif
if (pmd != pmd_offset(pgd, 0))
BUG();
- for (j = 0; (j < PTRS_PER_PMD) && (vaddr <= end); pmd++, j++) {
+ for (j = 0; j < PTRS_PER_PMD; pmd++, j++) {
vaddr = i*PGDIR_SIZE + j*PMD_SIZE;
+ if (vaddr >= end)
+ break;
if (cpu_has_pse) {
unsigned long __pe;
@@ -349,10 +352,10 @@ static void __init pagetable_init(void)
if (pte != pte_offset(pmd, 0))
BUG();
- for (k = 0;
- (k < PTRS_PER_PTE) && (vaddr <= end);
- pte++, k++) {
+ for (k = 0; k < PTRS_PER_PTE; pte++, k++) {
vaddr = i*PGDIR_SIZE + j*PMD_SIZE + k*PAGE_SIZE;
+ if (vaddr >= end)
+ break;
*pte = mk_pte_phys(__pa(vaddr), PAGE_KERNEL);
}
}
diff --git a/arch/ia64/config.in b/arch/ia64/config.in
index d006c1d05..2d2388590 100644
--- a/arch/ia64/config.in
+++ b/arch/ia64/config.in
@@ -3,6 +3,8 @@ mainmenu_name "Kernel configuration of Linux for IA-64 machines"
mainmenu_option next_comment
comment 'General setup'
+define_bool CONFIG_IA64 y
+
choice 'IA-64 system type' \
"Generic CONFIG_IA64_GENERIC \
HP-simulator CONFIG_IA64_HP_SIM \
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index 1342e64f0..82ba58129 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -144,7 +144,7 @@ ia32_syscall_table:
data8 sys32_settimeofday
data8 sys_getgroups /* 80 */
data8 sys_setgroups
- data8 sys_ni_syscall
+ data8 old_select
data8 sys_symlink
data8 sys_ni_syscall
data8 sys_readlink /* 85 */
diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c
index ed443ee66..2c2c53741 100644
--- a/arch/ia64/ia32/ia32_signal.c
+++ b/arch/ia64/ia32/ia32_signal.c
@@ -342,7 +342,16 @@ ia32_setup_frame1 (int sig, struct k_sigaction *ka, siginfo_t *info,
}
asmlinkage int
-sys32_sigreturn(int arg1, int arg2, int arg3, int arg4, int arg5, unsigned long stack)
+sys32_sigreturn(
+int arg0,
+int arg1,
+int arg2,
+int arg3,
+int arg4,
+int arg5,
+int arg6,
+int arg7,
+unsigned long stack)
{
struct pt_regs *regs = (struct pt_regs *) &stack;
struct sigframe_ia32 *frame = (struct sigframe_ia32 *)(regs->r12- 8);
@@ -375,7 +384,16 @@ badframe:
}
asmlinkage int
-sys32_rt_sigreturn(int arg1, int arg2, int arg3, int arg4, int arg5, unsigned long stack)
+sys32_rt_sigreturn(
+int arg0,
+int arg1,
+int arg2,
+int arg3,
+int arg4,
+int arg5,
+int arg6,
+int arg7,
+unsigned long stack)
{
struct pt_regs *regs = (struct pt_regs *) &stack;
struct rt_sigframe_ia32 *frame = (struct rt_sigframe_ia32 *)(regs->r12 - 4);
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index 7b4c4995e..d61f1cfe5 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -240,18 +240,29 @@ do_mmap_fake(struct file *file, unsigned long addr, unsigned long len,
return -EINVAL;
if (prot & PROT_WRITE)
prot |= PROT_EXEC;
+#ifdef DDD
+#else // DDD
+ prot |= PROT_WRITE;
+#endif // DDD
front = NULL;
back = NULL;
if ((baddr = (addr & PAGE_MASK)) != addr && get_user(c, (char *)baddr) == 0) {
front = kmalloc(addr - baddr, GFP_KERNEL);
memcpy(front, (void *)baddr, addr - baddr);
}
- if ((addr + len) & ~PAGE_MASK && get_user(c, (char *)(addr + len)) == 0) {
+#ifndef DDD
+ if (addr)
+#endif
+ if (((addr + len) & ~PAGE_MASK) && get_user(c, (char *)(addr + len)) == 0) {
back = kmalloc(PAGE_SIZE - ((addr + len) & ~PAGE_MASK), GFP_KERNEL);
memcpy(back, addr + len, PAGE_SIZE - ((addr + len) & ~PAGE_MASK));
}
if ((r = do_mmap(0, baddr, len + (addr - baddr), prot, flags | MAP_ANONYMOUS, 0)) < 0)
return(r);
+#ifndef DDD
+ if (addr == 0)
+ addr = r;
+#endif // DDD
if (back) {
memcpy(addr + len, back, PAGE_SIZE - ((addr + len) & ~PAGE_MASK));
kfree(back);
@@ -315,7 +326,11 @@ sys32_mmap(struct mmap_arg_struct *arg)
}
a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+#ifdef DDD
if ((a.flags & MAP_FIXED) && ((a.addr & ~PAGE_MASK) || (a.offset & ~PAGE_MASK))) {
+#else // DDD
+ if (1) {
+#endif // DDD
unlock_kernel();
up(&current->mm->mmap_sem);
error = do_mmap_fake(file, a.addr, a.len, a.prot, a.flags, a.offset);
@@ -665,7 +680,7 @@ struct dirent32 {
};
static void
-xlate_dirent(void *dirent, long n)
+xlate_dirent(void *dirent64, void *dirent32, long n)
{
long off;
struct dirent *dirp;
@@ -673,9 +688,9 @@ xlate_dirent(void *dirent, long n)
off = 0;
while (off < n) {
- dirp = (struct dirent *)(dirent + off);
+ dirp = (struct dirent *)(dirent64 + off);
+ dirp32 = (struct dirent32 *)(dirent32 + off);
off += dirp->d_reclen;
- dirp32 = (struct dirent32 *)dirp;
dirp32->d_ino = dirp->d_ino;
dirp32->d_off = (unsigned int)dirp->d_off;
dirp32->d_reclen = dirp->d_reclen;
@@ -685,26 +700,27 @@ xlate_dirent(void *dirent, long n)
}
asmlinkage long
-sys32_getdents(unsigned int fd, void * dirent, unsigned int count)
+sys32_getdents(unsigned int fd, void * dirent32, unsigned int count)
{
long n;
+ void *dirent64;
- if ((n = sys_getdents(fd, dirent, count)) < 0)
+ dirent64 = (unsigned long)(dirent32 + (sizeof(long) - 1)) & ~(sizeof(long) - 1);
+ if ((n = sys_getdents(fd, dirent64, count - (dirent64 - dirent32))) < 0)
return(n);
- xlate_dirent(dirent, n);
+ xlate_dirent(dirent64, dirent32, n);
return(n);
}
asmlinkage int
-sys32_readdir(unsigned int fd, void * dirent, unsigned int count)
+sys32_readdir(unsigned int fd, void * dirent32, unsigned int count)
{
int n;
- struct dirent *dirp;
+ struct dirent dirent64;
- if ((n = old_readdir(fd, dirent, count)) < 0)
+ if ((n = old_readdir(fd, &dirent64, count)) < 0)
return(n);
- dirp = (struct dirent *)dirent;
- xlate_dirent(dirent, dirp->d_reclen);
+ xlate_dirent(&dirent64, dirent32, dirent64.d_reclen);
return(n);
}
@@ -809,6 +825,23 @@ out_nofds:
return ret;
}
+struct sel_arg_struct {
+ unsigned int n;
+ unsigned int inp;
+ unsigned int outp;
+ unsigned int exp;
+ unsigned int tvp;
+};
+
+asmlinkage int old_select(struct sel_arg_struct *arg)
+{
+ struct sel_arg_struct a;
+
+ if (copy_from_user(&a, arg, sizeof(a)))
+ return -EFAULT;
+ return sys32_select(a.n, a.inp, a.outp, a.exp, a.tvp);
+}
+
struct rusage32 {
struct timeval32 ru_utime;
struct timeval32 ru_stime;
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index dd7de2ab0..6e0d09ea7 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -15,7 +15,6 @@
*
* Implemented EFI runtime services and virtual mode calls. --davidm
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
@@ -166,14 +165,12 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
case EFI_BOOT_SERVICES_CODE:
case EFI_BOOT_SERVICES_DATA:
case EFI_CONVENTIONAL_MEMORY:
-#ifndef CONFIG_IA64_VIRTUAL_MEM_MAP
if (md->phys_addr > 1024*1024*1024UL) {
printk("Warning: ignoring %luMB of memory above 1GB!\n",
md->num_pages >> 8);
md->type = EFI_UNUSABLE_MEMORY;
continue;
}
-#endif
curr.start = PAGE_OFFSET + md->phys_addr;
curr.end = curr.start + (md->num_pages << 12);
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 87e77c677..47b972cb4 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -496,18 +496,27 @@ ia64_ret_from_syscall:
(p7) br.cond.spnt.few handle_syscall_error // handle potential syscall failure
ia64_leave_kernel:
- // check & deliver software interrupts (bottom half handlers):
+ // check & deliver software interrupts:
- movl r2=bh_active // sheesh, why aren't these two in
- movl r3=bh_mask // a struct??
+#ifdef CONFIG_SMP
+ adds r2=IA64_TASK_PROCESSOR_OFFSET,r13
+ movl r3=softirq_state
;;
- ld8 r2=[r2]
- ld8 r3=[r3]
+ ld4 r2=[r2]
+ ;;
+ shladd r3=r2,3,r3
+#else
+ movl r3=softirq_state
+#endif
+ ;;
+ ld8 r2=[r3] // r3 is guaranteed to be 8-byte aligned!
+ ;;
+ shr r3=r2,32
;;
and r2=r2,r3
;;
- cmp.ne p6,p7=r2,r0 // any soft interrupts ready for delivery?
-(p6) br.call.dpnt.few rp=invoke_do_bottom_half
+ cmp4.ne p6,p7=r2,r0
+(p6) br.call.spnt.many rp=invoke_do_softirq
1:
(pKern) br.cond.dpnt.many restore_all // yup -> skip check for rescheduling & signal delivery
@@ -751,20 +760,20 @@ invoke_schedule_tail:
#endif /* CONFIG_SMP */
/*
- * Invoke do_bottom_half() while preserving in0-in7, which may be needed
+ * Invoke do_softirq() while preserving in0-in7, which may be needed
* in case a system call gets restarted.
*/
- .proc invoke_do_bottom_half
-invoke_do_bottom_half:
+ .proc invoke_do_softirq
+invoke_do_softirq:
alloc loc0=ar.pfs,8,2,0,0
mov loc1=rp
;;
- br.call.sptk.few rp=do_bottom_half
+ br.call.sptk.few rp=do_softirq
.ret9:
mov ar.pfs=loc0
mov rp=loc1
br.ret.sptk.many rp
- .endp invoke_do_bottom_half
+ .endp invoke_do_softirq
/*
* Invoke schedule() while preserving in0-in7, which may be needed
diff --git a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S
index 24dc10ee4..65de8e589 100644
--- a/arch/ia64/kernel/gate.S
+++ b/arch/ia64/kernel/gate.S
@@ -132,6 +132,7 @@ back_from_setup_rbs:
ld8 r8=[base0] // restore (perhaps modified) CFM0, EC0, and CPL0
cmp.ne p8,p0=r14,r15 // do we need to restore the rbs?
(p8) br.cond.spnt.few restore_rbs // yup -> (clobbers r14 and r16)
+ ;;
back_from_restore_rbs:
{
and r9=0x7f,r8 // r9 <- CFM0.sof
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
index 50d965e02..35a52628a 100644
--- a/arch/ia64/kernel/head.S
+++ b/arch/ia64/kernel/head.S
@@ -133,6 +133,7 @@ alive_msg:
#endif /* CONFIG_IA64_EARLY_PRINTK */
alloc r2=ar.pfs,8,0,2,0
+ ;;
#ifdef CONFIG_SMP
(isAP) br.call.sptk.few rp=smp_callin
.ret1:
@@ -174,7 +175,7 @@ ia64_save_debug_regs:
st8.nta [in0]=r16,8
st8.nta [r19]=r17,8
br.cloop.sptk.few 1b
-
+ ;;
mov ar.lc=r20 // restore ar.lc
br.ret.sptk.few b0
.endp ia64_save_debug_regs
@@ -197,7 +198,7 @@ ia64_load_debug_regs:
mov dbr[r18]=r16
mov ibr[r18]=r17
br.cloop.sptk.few 1b
-
+ ;;
mov ar.lc=r20 // restore ar.lc
br.ret.sptk.few b0
.endp ia64_load_debug_regs
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index 01c201137..5efe50164 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -128,6 +128,18 @@ get_irq_list (char *buf)
return p - buf;
}
+int usbfix;
+
+static int __init
+usbfix_option (char *str)
+{
+ printk("irq: enabling USB workaround\n");
+ usbfix = 1;
+ return 1;
+}
+
+__setup("usbfix", usbfix_option);
+
/*
* That's where the IVT branches when we get an external
* interrupt. This branches to the correct hardware IRQ handler via
@@ -146,7 +158,8 @@ ia64_handle_irq (unsigned long irq, struct pt_regs *regs)
unsigned long eoi_ptr;
# ifdef CONFIG_USB
- disable_usb();
+ if (usbfix)
+ disable_usb();
# endif
/*
* Stop IPIs by getting the ivr_read_lock
@@ -170,7 +183,8 @@ ia64_handle_irq (unsigned long irq, struct pt_regs *regs)
spin_unlock(&ivr_read_lock);
# ifdef CONFIG_USB
- reenable_usb();
+ if (usbfix)
+ reenable_usb();
# endif
# ifndef CONFIG_SMP
diff --git a/arch/ia64/kernel/irq_lock.c b/arch/ia64/kernel/irq_lock.c
index 9c512dd4e..4a2ead673 100644
--- a/arch/ia64/kernel/irq_lock.c
+++ b/arch/ia64/kernel/irq_lock.c
@@ -26,7 +26,7 @@ int global_irq_holder = NO_PROC_ID;
spinlock_t global_irq_lock;
atomic_t global_irq_count;
atomic_t global_bh_count;
-atomic_t global_bh_lock;
+spinlock_t global_bh_lock;
#define INIT_STUCK (1<<26)
diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c
index f86f45537..0bc110510 100644
--- a/arch/ia64/kernel/pci-dma.c
+++ b/arch/ia64/kernel/pci-dma.c
@@ -17,21 +17,6 @@
#include <asm/io.h>
-/* Pure 2^n version of get_order */
-extern __inline__ unsigned long
-get_order (unsigned long size)
-{
- unsigned long order = ia64_fls(size);
-
- printk ("get_order: size=%lu, order=%lu\n", size, order);
-
- if (order > PAGE_SHIFT)
- order -= PAGE_SHIFT;
- else
- order = 0;
- return order;
-}
-
void *
pci_alloc_consistent (struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)
{
diff --git a/arch/ia64/kernel/pci.c b/arch/ia64/kernel/pci.c
index 3bceeed8e..4acc7f041 100644
--- a/arch/ia64/kernel/pci.c
+++ b/arch/ia64/kernel/pci.c
@@ -226,14 +226,3 @@ void
pcibios_align_resource (void *data, struct resource *res, unsigned long size)
{
}
-
-#if 0 /*def CONFIG_PROC_FS*/
-/*
- * This is an ugly hack to get a (weak) unresolved reference to something that is
- * in drivers/pci/proc.c. Without this, the file does not get linked in at all
- * (I suspect the reason this isn't needed on Linux/x86 is that most people compile
- * with module support, in which case the EXPORT_SYMBOL() stuff will ensure the
- * code gets linked in. Sigh... --davidm 99/12/20.
- */
-asm ("data8 proc_bus_pci_add");
-#endif
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
index 48a3d68b4..ed5d594a6 100644
--- a/arch/ia64/kernel/smp.c
+++ b/arch/ia64/kernel/smp.c
@@ -57,7 +57,7 @@ spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
unsigned long cpu_online_map = 1;
#endif
-volatile int cpu_number_map[NR_CPUS] = { -1, }; /* SAPIC ID -> Logical ID */
+volatile int __cpu_number_map[NR_CPUS] = { -1, }; /* SAPIC ID -> Logical ID */
volatile int __cpu_logical_map[NR_CPUS] = { -1, }; /* logical ID -> SAPIC ID */
int smp_num_cpus = 1;
int bootstrap_processor = -1; /* SAPIC ID of BSP */
@@ -586,7 +586,7 @@ smp_boot_one_cpu(int cpuid, int cpunum)
alive:
/* Remember the AP data */
- cpu_number_map[cpuid] = cpunum;
+ __cpu_number_map[cpuid] = cpunum;
#ifdef CONFIG_KDB
cpu_online_map |= (1<<cpunum);
printk ("DEBUGGER: cpu_online_map = 0x%08x\n", cpu_online_map);
@@ -612,12 +612,12 @@ smp_boot_cpus(void)
extern int acpi_apic_map[32];
/* Take care of some initial bookkeeping. */
- memset(&cpu_number_map, -1, sizeof(cpu_number_map));
+ memset(&__cpu_number_map, -1, sizeof(__cpu_number_map));
memset(&__cpu_logical_map, -1, sizeof(__cpu_logical_map));
memset(&ipi_op, 0, sizeof(ipi_op));
/* Setup BSP mappings */
- cpu_number_map[bootstrap_processor] = 0;
+ __cpu_number_map[bootstrap_processor] = 0;
__cpu_logical_map[0] = bootstrap_processor;
current->processor = bootstrap_processor;
diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
index 18a498a09..f06d3bea8 100644
--- a/arch/ia64/kernel/sys_ia64.c
+++ b/arch/ia64/kernel/sys_ia64.c
@@ -2,8 +2,8 @@
* This file contains various system calls that have different calling
* conventions on different platforms.
*
- * Copyright (C) 1999 Hewlett-Packard Co
- * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1999-2000 Hewlett-Packard Co
+ * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
*/
#include <linux/config.h>
#include <linux/errno.h>
diff --git a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile
index 8a9581747..88a4aadd4 100644
--- a/arch/ia64/lib/Makefile
+++ b/arch/ia64/lib/Makefile
@@ -3,7 +3,7 @@
#
.S.o:
- $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $@
+ $(CC) -D__ASSEMBLY__ $(AFLAGS) -c $< -o $@
OBJS = __divdi3.o __divsi3.o __udivdi3.o __udivsi3.o \
__moddi3.o __modsi3.o __umoddi3.o __umodsi3.o \
diff --git a/arch/ia64/tools/print_offsets.c b/arch/ia64/tools/print_offsets.c
index 85b15aae1..f1b298e21 100644
--- a/arch/ia64/tools/print_offsets.c
+++ b/arch/ia64/tools/print_offsets.c
@@ -47,6 +47,7 @@ tab[] =
{ "IA64_TASK_FLAGS_OFFSET", offsetof (struct task_struct, flags) },
{ "IA64_TASK_SIGPENDING_OFFSET", offsetof (struct task_struct, sigpending) },
{ "IA64_TASK_NEED_RESCHED_OFFSET", offsetof (struct task_struct, need_resched) },
+ { "IA64_TASK_PROCESSOR_OFFSET", offsetof (struct task_struct, processor) },
{ "IA64_TASK_THREAD_OFFSET", offsetof (struct task_struct, thread) },
{ "IA64_TASK_THREAD_KSP_OFFSET", offsetof (struct task_struct, thread.ksp) },
{ "IA64_TASK_PID_OFFSET", offsetof (struct task_struct, pid) },
diff --git a/arch/m68k/atari/joystick.c b/arch/m68k/atari/joystick.c
index bf82e67ea..86bd24c73 100644
--- a/arch/m68k/atari/joystick.c
+++ b/arch/m68k/atari/joystick.c
@@ -12,6 +12,7 @@
#include <linux/major.h>
#include <linux/poll.h>
#include <linux/init.h>
+#include <linux/devfs_fs_kernel.h>
#include <asm/atarikb.h>
#include <asm/atari_joystick.h>
@@ -132,8 +133,11 @@ int __init atari_joystick_init(void)
init_waitqueue_head(&joystick[0].wait);
init_waitqueue_head(&joystick[1].wait);
- if (register_chrdev(MAJOR_NR, "Joystick", &atari_joystick_fops))
+ if (devfs_register_chrdev(MAJOR_NR, "Joystick", &atari_joystick_fops))
printk("unable to get major %d for joystick devices\n", MAJOR_NR);
+ devfs_register_series (NULL, "joysticks/digital%u", 2, DEVFS_FL_DEFAULT,
+ MAJOR_NR, 128, S_IFCHR | S_IRUSR | S_IWUSR, 0, 0,
+ &atari_joystick_fops, NULL);
return 0;
}
diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
index 77053421e..7406a8d02 100644
--- a/arch/m68k/atari/stram.c
+++ b/arch/m68k/atari/stram.c
@@ -1168,7 +1168,7 @@ static void do_stram_request( void )
{
unsigned long start, len;
- while( CURRENT ) {
+ while( !QUEUE_EMPTY ) {
if (MAJOR(CURRENT->rq_dev) != MAJOR_NR)
panic("stram: request list destroyed");
if (CURRENT->bh) {
diff --git a/arch/m68k/config.in b/arch/m68k/config.in
index ce8260504..5b12f470e 100644
--- a/arch/m68k/config.in
+++ b/arch/m68k/config.in
@@ -161,10 +161,17 @@ if [ "$CONFIG_SCSI" != "n" ]; then
comment 'SCSI support type (disk, tape, CD-ROM)'
dep_tristate ' SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
+ if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then
+ int 'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40
+ fi
dep_tristate ' SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
+ if [ "$CONFIG_BLK_DEV_ST" != "n" ]; then
+ int 'Maximum number of SCSI tapes that can be loaded as modules' CONFIG_ST_EXTRA_DEVS 2
+ fi
dep_tristate ' SCSI CD-ROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then
bool ' Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR
+ int 'Maximum number of CDROM devices that can be loaded as modules' CONFIG_SR_EXTRA_DEVS 2
fi
dep_tristate ' SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
@@ -273,9 +280,13 @@ if [ "$CONFIG_NET" = "y" ]; then
tristate ' Apollo 3c505 support' CONFIG_APOLLO_ELPLUS
fi
if [ "$CONFIG_MAC" = "y" ]; then
- bool ' Mac NS 8390 based ethernet cards' CONFIG_DAYNAPORT
-# bool ' Macintosh (AV) onboard MACE ethernet' CONFIG_MACMACE
- bool ' Macintosh (Quadra) onboard SONIC ethernet' CONFIG_MACSONIC
+ bool ' Macintosh NS 8390 based ethernet cards' CONFIG_MAC8390
+ tristate ' Macintosh SONIC based ethernet (onboard, NuBus, LC, CS)' CONFIG_MACSONIC
+ tristate ' Macintosh SMC 9194 based ethernet cards' CONFIG_SMC9194
+ tristate ' Macintosh CS89x0 based ethernet cards' CONFIG_MAC89x0
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ bool ' Macintosh (AV) onboard MACE ethernet (EXPERIMENTAL)' CONFIG_MACMACE
+ fi
fi
if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME147" = "y" ]; then
tristate ' MVME147 (Lance) Ethernet support' CONFIG_MVME147_NET
@@ -352,12 +363,6 @@ if [ "$CONFIG_ATARI" = "y" ]; then
define_bool CONFIG_BUSMOUSE y
fi
fi
-if [ "$CONFIG_MAC" = "y" ]; then
- bool 'Mac ADB mouse support' CONFIG_ADBMOUSE
- if [ "$CONFIG_ADBMOUSE" != "n" ]; then
- define_bool CONFIG_BUSMOUSE y
- fi
-fi
if [ "$CONFIG_ATARI" = "y" ]; then
tristate 'Atari MFP serial support' CONFIG_ATARI_MFPSER
tristate 'Atari SCC serial support' CONFIG_ATARI_SCC
@@ -384,7 +389,20 @@ if [ "$CONFIG_PARPORT" = "n" ]; then
fi
fi
if [ "$CONFIG_MAC" = "y" ]; then
- bool 'Mac SCC serial support' CONFIG_MAC_SCC
+ tristate 'Macintosh serial support' CONFIG_MAC_SCC
+ bool 'Apple Desktop Bus (ADB) support' CONFIG_ADB
+ if [ "$CONFIG_ADB" = "y" ]; then
+ bool ' Support for ADB keyboard' CONFIG_ADB_KEYBOARD
+ bool ' Support for ADB mouse' CONFIG_ADBMOUSE
+ bool ' Include Mac II ADB driver' CONFIG_ADB_MACII
+ bool ' Include Mac IIsi ADB driver' CONFIG_ADB_MACIISI
+ bool ' Include CUDA ADB driver' CONFIG_ADB_CUDA
+ bool ' Include IOP (IIfx/Quadra 9x0) ADB driver' CONFIG_ADB_IOP
+ bool ' Include PMU (Powerbook) ADB driver' CONFIG_ADB_PMU68K
+ fi
+ if [ "$CONFIG_ADBMOUSE" = "y" ]; then
+ define_bool CONFIG_BUSMOUSE y
+ fi
fi
if [ "$CONFIG_HP300" = "y" -a "$CONFIG_DIO" = "y" ]; then
tristate 'HP DCA serial support' CONFIG_HPDCA
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index 6d10ca35f..c51e43802 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -27,6 +27,8 @@ endif
head.o: head.S m68k_defs.h
+entry.o: entry.S m68k_defs.h
+
sun3-head.o: sun3-head.S m68k_defs.h
m68k_defs.h: m68k_defs.c m68k_defs.head
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 021652201..5f08ef216 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -236,12 +236,12 @@ SYMBOL_NAME_LABEL(ret_from_interrupt)
#endif
/* check if we need to do software interrupts */
- movel SYMBOL_NAME(bh_active),%d0
- andl SYMBOL_NAME(bh_mask),%d0
+ movel SYMBOL_NAME(softirq_state),%d0
+ andl SYMBOL_NAME(softirq_state)+4,%d0
jeq SYMBOL_NAME(ret_from_exception)
pea SYMBOL_NAME(ret_from_exception)
- jra SYMBOL_NAME(do_bottom_half)
+ jra SYMBOL_NAME(do_softirq)
/* Handler for uninitialized and spurious interrupts */
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index 790d153ab..6f8300422 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -18,7 +18,6 @@
#include <asm/checksum.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
-#include <asm/m68kserial.h>
asmlinkage long long __ashrdi3 (long long, int);
asmlinkage long long __lshrdi3 (long long, int);
diff --git a/arch/m68k/mac/Makefile b/arch/m68k/mac/Makefile
index 10613c0a4..f50cd262c 100644
--- a/arch/m68k/mac/Makefile
+++ b/arch/m68k/mac/Makefile
@@ -10,6 +10,6 @@
O_TARGET := mac.o
OX_OBJS := mac_ksyms.o
O_OBJS := config.o bootparse.o macints.o iop.o via.o oss.o psc.o \
- macboing.o debug.o misc.o
+ baboon.o macboing.o debug.o misc.o
include $(TOPDIR)/Rules.make
diff --git a/arch/m68k/mac/adb-bus.c b/arch/m68k/mac/adb-bus.c
deleted file mode 100644
index 23e98c048..000000000
--- a/arch/m68k/mac/adb-bus.c
+++ /dev/null
@@ -1,2699 +0,0 @@
-/*
- * MACII ADB keyboard handler.
- * Copyright (c) 1997 Alan Cox
- *
- * Derived from code
- * Copyright (C) 1996 Paul Mackerras.
- *
- * MSch (9/97) Partial rewrite of interrupt handler to MacII style
- * ADB handshake, based on:
- * - Guide to Mac Hardware
- * - Guido Koerber's session with a logic analyzer
- *
- * MSch (1/98) Integrated start of IIsi driver by Robert Thompson
- */
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/malloc.h>
-#include <linux/mm.h>
-#include "via6522.h"
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/adb.h>
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <asm/setup.h>
-#include <asm/macintosh.h>
-#include <asm/macints.h>
-
-
-#define MACII /* For now - will be a switch */
-
-/* Bits in B data register: all active low */
-#define TREQ 0x08 /* Transfer request (input) */
-#define TACK 0x10 /* Transfer acknowledge (output) */
-#define TIP 0x20 /* Transfer in progress (output) */
-
-/* Bits in B data register: ADB transaction states MacII */
-#define ST_MASK 0x30 /* mask for selecting ADB state bits */
-/* ADB transaction states according to GMHW */
-#define ST_CMD 0x00 /* ADB state: command byte */
-#define ST_EVEN 0x10 /* ADB state: even data byte */
-#define ST_ODD 0x20 /* ADB state: odd data byte */
-#define ST_IDLE 0x30 /* ADB state: idle, nothing to send */
-
-/* Bits in ACR */
-#define SR_CTRL 0x1c /* Shift register control bits */
-#ifdef USE_ORIG
-#define SR_EXT 0x1c /* Shift on external clock */
-#else
-#define SR_EXT 0x0c /* Shift on external clock */
-#endif
-#define SR_OUT 0x10 /* Shift out if 1 */
-
-/* Bits in IFR and IER */
-#define IER_SET 0x80 /* set bits in IER */
-#define IER_CLR 0 /* clear bits in IER */
-#define SR_INT 0x04 /* Shift register full/empty */
-#define SR_DATA 0x08 /* Shift register data */
-#define SR_CLOCK 0x10 /* Shift register clock */
-
-/* JRT */
-#define ADB_DELAY 150
-
-static struct adb_handler {
- void (*handler)(unsigned char *, int, struct pt_regs *);
-} adb_handler[16];
-
-static enum adb_state {
- idle,
- sent_first_byte,
- sending,
- reading,
- read_done,
- awaiting_reply
-} adb_state;
-
-static struct adb_request *current_req;
-static struct adb_request *last_req;
-static unsigned char cuda_rbuf[16];
-static unsigned char *reply_ptr;
-static int reply_len;
-static int reading_reply;
-static int data_index;
-static int first_byte;
-static int prefix_len;
-
-static int status = ST_IDLE|TREQ;
-static int last_status;
-
-static int driver_running = 0;
-
-/*static int adb_delay;*/
-int in_keybinit = 1;
-
-static void adb_start(void);
-extern void adb_interrupt(int irq, void *arg, struct pt_regs *regs);
-extern void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs);
-extern void adb_clock_interrupt(int irq, void *arg, struct pt_regs *regs);
-extern void adb_data_interrupt(int irq, void *arg, struct pt_regs *regs);
-static void adb_input(unsigned char *buf, int nb, struct pt_regs *regs);
-
-static void adb_hw_setup_IIsi(void);
-static void adb_hw_setup_cuda(void);
-
-/*
- * debug level 10 required for ADB logging (should be && debug_adb, ideally)
- */
-
-extern int console_loglevel;
-
-/*
- * Misc. defines for testing - should go to header :-(
- */
-
-#define ADBDEBUG_STATUS (1)
-#define ADBDEBUG_STATE (2)
-#define ADBDEBUG_READ (4)
-#define ADBDEBUG_WRITE (8)
-#define ADBDEBUG_START (16)
-#define ADBDEBUG_RETRY (32)
-#define ADBDEBUG_POLL (64)
-#define ADBDEBUG_INT (128)
-#define ADBDEBUG_PROT (256)
-#define ADBDEBUG_SRQ (512)
-#define ADBDEBUG_REQUEST (1024)
-#define ADBDEBUG_INPUT (2048)
-#define ADBDEBUG_DEVICE (4096)
-
-#define ADBDEBUG_IISI (8192)
-
-
-/*#define DEBUG_ADB*/
-
-#ifdef DEBUG_ADB
-#define ADBDEBUG (ADBDEBUG_INPUT | ADBDEBUG_READ | ADBDEBUG_START | ADBDEBUG_WRITE | ADBDEBUG_SRQ | ADBDEBUG_REQUEST)
-#else
-#define ADBDEBUG (0)
-#endif
-
-#define TRY_CUDA
-
-void adb_bus_init(void)
-{
- unsigned long flags;
- unsigned char c, i;
-
- save_flags(flags);
- cli();
-
- /*
- * Setup ADB
- */
-
- switch(macintosh_config->adb_type)
- {
-
- case MAC_ADB_II:
- printk("adb: MacII style keyboard/mouse driver.\n");
- /* Set the lines up. We want TREQ as input TACK|TIP as output */
- via_write(via1, vDirB, ((via_read(via1,vDirB)|TACK|TIP)&~TREQ));
- /*
- * Docs suggest TREQ should be output - that seems nuts
- * BSD agrees here :-)
- * Setup vPCR ??
- */
-
-#ifdef USE_ORIG
- /* Lower the bus signals (MacII is active low it seems ???) */
- via_write(via1, vBufB, via_read(via1, vBufB)&~TACK);
-#else
- /* Corresponding state: idle (clear state bits) */
- via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
- last_status = (via_read(via1, vBufB)&~ST_MASK);
-#endif
- /* Shift register on input */
- c=via_read(via1, vACR);
- c&=~SR_CTRL; /* Clear shift register bits */
- c|=SR_EXT; /* Shift on external clock; out or in? */
- via_write(via1, vACR, c);
- /* Wipe any pending data and int */
- via_read(via1, vSR);
-
- /* This is interrupts on enable SR for keyboard */
- via_write(via1, vIER, IER_SET|SR_INT);
- /* This clears the interrupt bit */
- via_write(via1, vIFR, SR_INT);
-
- /*
- * Ok we probably ;) have a ready to use adb bus. Its also
- * hopefully idle (Im assuming the mac didnt leave a half
- * complete transaction on booting us).
- */
-
- request_irq(IRQ_MAC_ADB, adb_interrupt, IRQ_FLG_LOCK,
- "adb interrupt", adb_interrupt);
- adb_state = idle;
- break;
- /*
- * Unsupported; but later code doesn't notice !!
- */
- case MAC_ADB_CUDA:
- printk("adb: CUDA interface.\n");
-#if 0
- /* don't know what to set up here ... */
- adb_state = idle;
- /* Set the lines up. We want TREQ as input TACK|TIP as output */
- via_write(via1, vDirB, ((via_read(via1,vDirB)|TACK|TIP)&~TREQ));
-#endif
- adb_hw_setup_cuda();
- adb_state = idle;
- request_irq(IRQ_MAC_ADB, adb_cuda_interrupt, IRQ_FLG_LOCK,
- "adb CUDA interrupt", adb_cuda_interrupt);
- break;
- case MAC_ADB_IISI:
- printk("adb: Using IIsi hardware.\n");
- printk("\tDEBUG_JRT\n");
- /* Set the lines up. We want TREQ as input TACK|TIP as output */
- via_write(via1, vDirB, ((via_read(via1,vDirB)|TACK|TIP)&~TREQ));
-
- /*
- * MSch: I'm pretty sure the setup is mildly wrong
- * for the IIsi.
- */
- /* Initial state: idle (clear state bits) */
- via_write(via1, vBufB, (via_read(via1, vBufB) & ~(TIP|TACK)) );
- last_status = (via_read(via1, vBufB)&~ST_MASK);
- /* Shift register on input */
- c=via_read(via1, vACR);
- c&=~SR_CTRL; /* Clear shift register bits */
- c|=SR_EXT; /* Shift on external clock; out or in? */
- via_write(via1, vACR, c);
- /* Wipe any pending data and int */
- via_read(via1, vSR);
-
- /* This is interrupts on enable SR for keyboard */
- via_write(via1, vIER, IER_SET|SR_INT);
- /* This clears the interrupt bit */
- via_write(via1, vIFR, SR_INT);
-
- /* get those pesky clock ticks we missed while booting */
- for ( i = 0; i < 60; i++) {
- udelay(ADB_DELAY);
- adb_hw_setup_IIsi();
- udelay(ADB_DELAY);
- if (via_read(via1, vBufB) & TREQ)
- break;
- }
- if (i == 60)
- printk("adb_IIsi: maybe bus jammed ??\n");
-
- /*
- * Ok we probably ;) have a ready to use adb bus. Its also
- */
- request_irq(IRQ_MAC_ADB, adb_cuda_interrupt, IRQ_FLG_LOCK,
- "adb interrupt", adb_cuda_interrupt);
- adb_state = idle;
- break;
- default:
- printk("adb: Unknown hardware interface.\n");
- nosupp:
- printk("adb: Interface unsupported.\n");
- restore_flags(flags);
- return;
- }
-
- /*
- * XXX: interrupt only registered if supported HW !!
- * -> unsupported HW will just time out on keyb_init!
- */
-#if 0
- request_irq(IRQ_MAC_ADB, adb_interrupt, IRQ_FLG_LOCK,
- "adb interrupt", adb_interrupt);
-#endif
-#ifdef DEBUG_ADB_INTS
- request_irq(IRQ_MAC_ADB_CL, adb_clock_interrupt, IRQ_FLG_LOCK,
- "adb clock interrupt", adb_clock_interrupt);
- request_irq(IRQ_MAC_ADB_SD, adb_data_interrupt, IRQ_FLG_LOCK,
- "adb data interrupt", adb_data_interrupt);
-#endif
-
- printk("adb: init done.\n");
- restore_flags(flags);
-}
-
-void adb_hw_setup_cuda(void)
-{
- int x;
- unsigned long flags;
-
- printk("CUDA: HW Setup:");
-
- save_flags(flags);
- cli();
-
- if (console_loglevel == 10)
- printk(" 1,");
-
- /* Set the direction of the cuda signals, TIP+TACK are output TREQ is an input */
- via_write( via1, vDirB, via_read( via1, vDirB ) | TIP | TACK );
- via_write( via1, vDirB, via_read( via1, vDirB ) & ~TREQ );
-
- if (console_loglevel == 10)
- printk("2,");
-
- /* Set the clock control. Set to shift data in by external clock CB1 */
- via_write( via1, vACR, ( via_read(via1, vACR ) | SR_EXT ) & ~SR_OUT );
-
- if (console_loglevel == 10)
- printk("3,");
-
- /* Clear any possible Cuda interrupt */
- x = via_read( via1, vSR );
-
- if (console_loglevel == 10)
- printk("4,");
-
- /* Terminate transaction and set idle state */
- via_write( via1, vBufB, via_read( via1, vBufB ) | TIP | TACK );
-
- if (console_loglevel == 10)
- printk("5,");
-
- /* Delay 4 mS for ADB reset to complete */
- udelay(4000);
-
- if (console_loglevel == 10)
- printk("6,");
-
- /* Clear pending interrupts... */
- x = via_read( via1, vSR );
-
- if (console_loglevel == 10)
- printk("7,");
- /* Issue a sync transaction, TACK asserted while TIP negated */
- via_write( via1, vBufB, via_read( via1, vBufB ) & ~TACK );
-
- if (console_loglevel == 10)
- printk("8,");
-
- /* Wait for the sync acknowledgement, Cuda to assert TREQ */
- while( ( via_read( via1, vBufB ) & TREQ ) != 0 )
- barrier();
-
- if (console_loglevel == 10)
- printk("9,");
-
- /* Wait for the sync acknowledment interrupt */
- while( ( via_read( via1, vIFR ) & SR_INT ) == 0 )
- barrier();
-
- if (console_loglevel == 10)
- printk("10,");
-
- /* Clear pending interrupts... */
- x = via_read( via1, vSR );
-
- if (console_loglevel == 10)
- printk("11,");
-
- /* Terminate the sync cycle by negating TACK */
- via_write( via1, vBufB, via_read( via1, vBufB ) | TACK );
-
- if (console_loglevel == 10)
- printk("12,");
-
- /* Wait for the sync termination acknowledgement, Cuda to negate TREQ */
- while( ( via_read( via1, vBufB ) & TREQ ) == 0 )
- barrier();
-
- if (console_loglevel == 10)
- printk("13,");
-
- /* Wait for the sync termination acknowledment interrupt */
- while( ( via_read( via1, vIFR ) & SR_INT ) == 0 )
- barrier();
-
- if (console_loglevel == 10)
- printk("14,");
-
- /* Terminate transaction and set idle state, TIP+TACK negate */
- via_write( via1, vBufB, via_read( via1, vBufB ) | TIP );
-
- if (console_loglevel == 10)
- printk("15 !");
-
- /* Clear pending interrupts... */
- x = via_read( via1, vSR );
-
- restore_flags(flags);
-
- printk("\nCUDA: HW Setup done!\n");
-}
-
-void adb_hw_setup_IIsi(void)
-{
- int dummy;
- long poll_timeout;
-
- printk("adb_IIsi: cleanup!\n");
-
- /* ??? */
- udelay(ADB_DELAY);
-
- /* disable SR int. */
- via_write(via1, vIER, IER_CLR|SR_INT);
- /* set SR to shift in */
- via_write(via1, vACR, via_read(via1, vACR ) & ~SR_OUT);
-
- /* this is required, especially on faster machines */
- udelay(ADB_DELAY);
-
- if (!(via_read(via1, vBufB) & TREQ)) { /* IRQ on */
- /* start frame */
- via_write(via1, vBufB,via_read(via1,vBufB) | TIP);
-
- while (1) {
- /* poll for ADB interrupt and watch for timeout */
- /* if time out, keep going in hopes of not hanging the
- * ADB chip - I think */
- poll_timeout = ADB_DELAY * 5;
- while ( !(via_read(via1, vIFR) & SR_INT)
- && (poll_timeout-- > 0) )
- dummy = via_read(via1, vBufB);
-
- dummy = via_read(via1, vSR); /* reset interrupt flag */
-
- /* perhaps put in a check here that ignores all data
- * after the first ADB_MAX_MSG_LENGTH bytes ??? */
-
- /* end of frame reached ?? */
- if (via_read(via1, vBufB) & TREQ)
- break;
-
- /* set ACK */
- via_write(via1,vBufB,via_read(via1, vBufB) | TACK);
- /* delay */
- udelay(ADB_DELAY);
- /* clear ACK */
- via_write(via1,vBufB,via_read(via1, vBufB) & ~TACK);
- }
- /* end frame */
- via_write(via1, vBufB,via_read(via1,vBufB) & ~TIP);
- /* probably don't need to delay this long */
- udelay(ADB_DELAY);
- }
- /* re-enable SR int. */
- via_write(via1, vIER, IER_SET|SR_INT);
-}
-
-#define WAIT_FOR(cond, what) \
- do { \
- for (x = 1000; !(cond); --x) { \
- if (x == 0) { \
- printk("Timeout waiting for " what); \
- return 0; \
- } \
- __delay(100*160); \
- } \
- } while (0)
-
-/*
- * Construct and send an adb request
- * This function is the main entry point into the ADB driver from
- * kernel code; it takes the request data supplied and populates the
- * adb_request structure.
- * In order to keep this interface independent from any assumption about
- * the underlying ADB hardware, we take requests in CUDA format here,
- * the ADB packet 'prefixed' with a packet type code.
- * Non-CUDA hardware is confused by this, so we strip the packet type
- * here depending on hardware type ...
- */
-int adb_request(struct adb_request *req, void (*done)(struct adb_request *),
- int nbytes, ...)
-{
- va_list list;
- int i, start;
-
- va_start(list, nbytes);
-
- /*
- * skip first byte if not CUDA
- */
- if (macintosh_config->adb_type == MAC_ADB_II) {
- start = va_arg(list, int);
- nbytes--;
- }
- req->nbytes = nbytes;
- req->done = done;
-#if (ADBDEBUG & ADBDEBUG_REQUEST)
- if (console_loglevel == 10)
- printk("adb_request, data bytes: ");
-#endif
- for (i = 0; i < nbytes; ++i) {
- req->data[i] = va_arg(list, int);
-#if (ADBDEBUG & ADBDEBUG_REQUEST)
- if (console_loglevel == 10)
- printk("%x ", req->data[i]);
-#endif
- }
-#if (ADBDEBUG & ADBDEBUG_REQUEST)
- if (console_loglevel == 10)
- printk(" !\n");
-#endif
- va_end(list);
- /*
- * XXX: This might be fatal if no reply is generated (i.e. Listen) !
- * Currently, the interrupt handler 'fakes' a reply on non-TALK
- * commands for this reason.
- * Also, we need a CUDA_AUTOPOLL emulation here for non-CUDA
- * Macs, and some mechanism to remember the last issued TALK
- * request for resending it repeatedly on timeout!
- */
- req->reply_expected = 1;
- return adb_send_request(req);
-}
-
-/*
- * Construct an adb request for later sending
- * This function only populates the adb_request structure, without
- * actually queueing it.
- * Reason: Poll requests and Talk requests need to be handled in a way
- * different from 'user' requests; no reply_expected is set and
- * Poll requests need to be placed at the head of the request queue.
- * Using adb_request results in implicit queueing at the tail of the
- * request queue (duplicating the Poll) with reply_expected set.
- * No adjustment of packet data is necessary, as this mechanisnm is not
- * used by CUDA hardware (Autopoll used instead).
- */
-int adb_build_request(struct adb_request *req, void (*done)(struct adb_request *),
- int nbytes, ...)
-{
- va_list list;
- int i;
-
- req->nbytes = nbytes;
- req->done = done;
- va_start(list, nbytes);
-#if (ADBDEBUG & ADBDEBUG_REQUEST)
- if (console_loglevel == 10)
- printk("adb__build_request, data bytes: ");
-#endif
- /*
- * skip first byte if not CUDA ?
- */
- for (i = 0; i < nbytes; ++i) {
- req->data[i] = va_arg(list, int);
-#if (ADBDEBUG & ADBDEBUG_REQUEST)
- if (console_loglevel == 10)
- printk("%x ", req->data[i]);
-#endif
- }
-#if (ADBDEBUG & ADBDEBUG_REQUEST)
- if (console_loglevel == 10)
- printk(" !\n");
-#endif
- va_end(list);
-
- req->reply_expected = 0;
- return 0;
-}
-
-/*
- * Send an ADB poll (Talk, tagged on the front of the request queue)
- */
-void adb_queue_poll(void)
-{
- static int pod=0;
- static int in_poll=0;
- static struct adb_request r;
- unsigned long flags;
-
- if(in_poll)
- printk("Double poll!\n");
-
- in_poll++;
- pod++;
- if(pod>7) /* 15 */
- pod=0;
-
-#if (ADBDEBUG & ADBDEBUG_POLL)
- if (console_loglevel == 10)
- printk("adb: Polling %d\n",pod);
-#endif
-
- if (macintosh_config->adb_type == MAC_ADB_II)
- /* XXX: that's a TALK, register 0, MacII version */
- adb_build_request(&r,NULL, 1, (pod<<4|0xC));
- else
- /* CUDA etc. version */
- adb_build_request(&r,NULL, 2, 0, (pod<<4|0xC));
-
- r.reply_expected=0;
- r.done=NULL;
- r.sent=0;
- r.got_reply=0;
- r.reply_len=0;
- save_flags(flags);
- cli();
- /* Poll inserted at head of queue ... */
- r.next=current_req;
- current_req=&r;
- restore_flags(flags);
- adb_start();
- in_poll--;
-}
-
-/*
- * Send an ADB retransmit (Talk, appended to the request queue)
- */
-void adb_retransmit(int device)
-{
- static int in_retransmit=0;
- static struct adb_request rt;
- unsigned long flags;
-
- if(in_retransmit)
- printk("Double retransmit!\n");
-
- in_retransmit++;
-
-#if (ADBDEBUG & ADBDEBUG_POLL)
- if (console_loglevel == 10)
- printk("adb: Sending retransmit: %d\n", device);
-#endif
-
- /* MacII version */
- adb_build_request(&rt,NULL, 1, (device<<4|0xC));
-
- rt.reply_expected = 0;
- rt.done = NULL;
- rt.sent = 0;
- rt.got_reply = 0;
- rt.reply_len = 0;
- rt.next = NULL;
-
- save_flags(flags);
- cli();
-
- /* Retransmit inserted at tail of queue ... */
-
- if (current_req != NULL)
- {
- last_req->next = &rt;
- last_req = &rt;
- }
- else
- {
- current_req = &rt;
- last_req = &rt;
- }
-
- /* always restart driver (send_retransmit used in place of adb_start!)*/
-
- if (adb_state == idle)
- adb_start();
-
- restore_flags(flags);
- in_retransmit--;
-}
-
-/*
- * Queue an ADB request; start ADB transfer if necessary
- */
-int adb_send_request(struct adb_request *req)
-{
- unsigned long flags;
-
- req->next = 0;
- req->sent = 0;
- req->got_reply = 0;
- req->reply_len = 0;
- save_flags(flags);
- cli();
-
- if (current_req != NULL)
- {
- last_req->next = req;
- last_req = req;
- }
- else
- {
- current_req = req;
- last_req = req;
- if (adb_state == idle)
- adb_start();
- }
-
- restore_flags(flags);
- return 0;
-}
-
-static int nclock, ndata;
-
-static int need_poll = 0;
-static int command_byte = 0;
-static int last_reply = 0;
-static int last_active = 0;
-
-static struct adb_request *retry_req;
-
-/*
- * Start sending ADB packet
- */
-static void adb_start(void)
-{
- unsigned long flags;
- struct adb_request *req;
-
- /*
- * We get here on three 'sane' conditions:
- * 1) called from send_adb_request, if adb_state == idle
- * 2) called from within adb_interrupt, if adb_state == idle
- * (after receiving, or after sending a LISTEN)
- * 3) called from within adb_interrupt, if adb_state == sending
- * and no reply is expected (immediate next command).
- * Maybe we get here on SRQ as well ??
- */
-
- /* get the packet to send */
- req = current_req;
- /* assert adb_state == idle */
- if (adb_state != idle) {
- printk("ADB: adb_start called while driver busy (%p %x %x)!\n",
- req, adb_state, via_read(via1, vBufB)&(ST_MASK|TREQ));
- return;
- }
- if (req == 0)
- return;
- save_flags(flags);
- cli();
-
-#if (ADBDEBUG & ADBDEBUG_START)
- if (console_loglevel == 10)
- printk("adb_start: request %p ", req);
-#endif
-
- nclock = 0;
- ndata = 0;
-
- /*
- * IRQ signaled ?? (means ADB controller wants to send, or might
- * be end of packet if we were reading)
- */
- if ((via_read(via1, vBufB) & TREQ) == 0)
- {
- switch(macintosh_config->adb_type)
- {
- /*
- * FIXME - we need to restart this on a timer
- * or a collision at boot hangs us.
- * Never set adb_state to idle here, or adb_start
- * won't be called again from send_request!
- * (need to re-check other cases ...)
- */
- case MAC_ADB_CUDA:
- /* printk("device busy - fail\n"); */
- restore_flags(flags);
- /* a byte is coming in from the CUDA */
- return;
- case MAC_ADB_IISI:
- printk("adb_start: device busy - fail\n");
- retry_req = req;
- restore_flags(flags);
- return;
- case MAC_ADB_II:
- /*
- * if the interrupt handler set the need_poll
- * flag, it's hopefully a SRQ poll or re-Talk
- * so we try to send here anyway
- */
- if (!need_poll) {
- printk("device busy - retry %p state %d status %x!\n",
- req, adb_state, via_read(via1, vBufB)&(ST_MASK|TREQ));
- retry_req = req;
- /* set ADB status here ? */
- restore_flags(flags);
- return;
- } else {
-#if (ADBDEBUG & ADBDEBUG_START)
- if (console_loglevel == 10)
- printk("device busy - polling; state %d status %x!\n",
- adb_state, via_read(via1, vBufB)&(ST_MASK|TREQ));
-#endif
- need_poll = 0;
- break;
- }
- }
- }
-
-#if 0
- /*
- * Bus idle ?? Not sure about this one; SRQ might need ST_CMD here!
- * OTOH: setting ST_CMD in the interrupt routine would make the
- * ADB contoller shift in before this routine starts shifting out ...
- */
- if ((via_read(via1, vBufB)&ST_MASK) != ST_IDLE)
- {
-#if (ADBDEBUG & ADBDEBUG_STATE)
- if (console_loglevel == 10)
- printk("ADB bus not idle (%x), retry later!\n",
- via_read(via1, vBufB)&(ST_MASK|TREQ));
-#endif
- retry_req = req;
- restore_flags(flags);
- return;
- }
-#endif
-
- /*
- * Another retry pending? (sanity check)
- */
- if (retry_req) {
-#if (ADBDEBUG & ADBDEBUG_RETRY)
- if (console_loglevel == 10)
- if (retry_req == req)
- /* new requests are appended at tail of request queue */
- printk("adb_start: retry %p pending ! \n", req);
- else
- /* poll requests are added to the head of queue */
- printk("adb_start: retry %p pending, req %p (poll?) current! \n",
- retry_req, req);
-#endif
- retry_req = NULL;
- }
-
- /*
- * Seems OK, go for it!
- */
- switch(macintosh_config->adb_type)
- {
- case MAC_ADB_CUDA:
- /* store command byte (first byte is 'type' byte) */
- command_byte = req->data[1];
- /* set the shift register to shift out and send a byte */
- via_write(via1, vACR, via_read(via1, vACR)|SR_OUT);
- via_write(via1, vSR, req->data[0]);
- via_write(via1, vBufB, via_read(via1, vBufB)&~TIP);
- break;
- case MAC_ADB_IISI:
- /* store command byte (first byte is 'type' byte) */
- command_byte = req->data[1];
- /* set ADB state to 'active' */
- via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
- /* switch ACK off (in case it was left on) */
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- /* set the shift register to shift out and send a byte */
- via_write(via1, vACR, via_read(via1, vACR) | SR_OUT);
- via_write(via1, vSR, req->data[0]);
- /* signal 'byte ready' */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- break;
- case MAC_ADB_II:
- /* store command byte */
- command_byte = req->data[0];
- /* Output mode */
- via_write(via1, vACR, via_read(via1, vACR)|SR_OUT);
- /* Load data */
- via_write(via1, vSR, req->data[0]);
-#ifdef USE_ORIG
- /* Turn off TIP/TACK - this should tell the external logic to
- start the external shift clock */
-/* via_write(via1, vBufB, via_read(via1, vBufB)&~(TIP|TACK));*/
- via_write(via1, vBufB, via_read(via1, vBufB)|(TIP|TACK));
-#else
- /* set ADB state to 'command' */
- via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_CMD);
-#endif
- break;
- }
- adb_state = sent_first_byte;
- data_index = 1;
-#if (ADBDEBUG & ADBDEBUG_START)
- if (console_loglevel == 10)
- printk("sent first byte of %d: %x, (%x %x) ... ",
- req->nbytes, req->data[0], adb_state,
- (via_read(via1, vBufB) & (ST_MASK|TREQ)) );
-#endif
- restore_flags(flags);
-}
-
-/*
- * Poll the ADB state (maybe obsolete now that interrupt-driven ADB runs)
- */
-void adb_poll(void)
-{
- unsigned char c;
- unsigned long flags;
- save_flags(flags);
- cli();
- c=via_read(via1, vIFR);
-#if (ADBDEBUG & ADBDEBUG_POLL)
-#ifdef DEBUG_ADB_INTS
- if (console_loglevel == 10) {
- printk("adb_poll: IFR %x state %x cl %d dat %d ",
- c, adb_state, nclock, ndata);
- if (c & (SR_CLOCK|SR_DATA)) {
- if (c & SR_CLOCK)
- printk("adb clock event ");
- if (c & SR_DATA)
- printk("adb data event ");
- }
- }
-#else
- if (console_loglevel == 10)
- printk("adb_poll: IFR %x state %x ",
- c, adb_state);
-#endif
- if (console_loglevel == 10)
- printk("\r");
-#endif
- if (c & SR_INT)
- {
-#if (ADBDEBUG & ADBDEBUG_POLL)
- if (console_loglevel == 10)
- printk("adb_poll: adb interrupt event\n");
-#endif
- adb_interrupt(0, 0, 0);
- }
- restore_flags(flags);
-}
-
-/*
- * Debugging gimmicks
- */
-void adb_clock_interrupt(int irq, void *arg, struct pt_regs *regs)
-{
- nclock++;
-}
-
-void adb_data_interrupt(int irq, void *arg, struct pt_regs *regs)
-{
- ndata++;
-}
-
-/*
- * The notorious ADB interrupt handler - does all of the protocol handling,
- * except for starting new send operations. Relies heavily on the ADB
- * controller sending and receiving data, thereby generating SR interrupts
- * for us. This means there has to be always activity on the ADB bus, otherwise
- * the whole process dies and has to be re-kicked by sending TALK requests ...
- * CUDA-based Macs seem to solve this with the autopoll option, for MacII-type
- * ADB the problem isn't solved yet (retransmit of the latest active TALK seems
- * a good choice; either on timeout or on a timer interrupt).
- *
- * The basic ADB state machine was left unchanged from the original MacII code
- * by Alan Cox, which was based on the CUDA driver for PowerMac.
- * The syntax of the ADB status lines seems to be totally different on MacII,
- * though. MacII uses the states Command -> Even -> Odd -> Even ->...-> Idle for
- * sending, and Idle -> Even -> Odd -> Even ->...-> Idle for receiving. Start
- * and end of a receive packet are signaled by asserting /IRQ on the interrupt
- * line. Timeouts are signaled by a sequence of 4 0xFF, with /IRQ asserted on
- * every other byte. SRQ is probably signaled by 3 or more 0xFF tacked on the
- * end of a packet. (Thanks to Guido Koerber for eavesdropping on the ADB
- * protocol with a logic analyzer!!)
- * CUDA seems to use /TIP -> /TIP | TACK -> /TIP -> /TIP | TACK ... -> TIP|TACK
- * for sending, and /TIP -> /TIP | TACK -> /TIP -> /TIP | TACK ... -> TIP for
- * receiving. No clue how timeouts are handled; SRQ seems to be sent as a
- * separate packet. Quite a few changes have been made outside the handshake
- * code, so I don't know if the CUDA code still behaves as before.
- *
- * Note: As of 21/10/97, the MacII ADB part works including timeout detection
- * and retransmit (Talk to the last active device). Cleanup of code and
- * testing of the CUDA functionality is required, though.
- * Note2: As of 13/12/97, CUDA support is definitely broken ...
- * Note3: As of 21/12/97, CUDA works on a P475. What was broken? The assumption
- * that Q700 and Q800 use CUDA :-(
- *
- * 27/01/98: IIsi driver implemented (thanks to Robert Thompson for the
- * initial bits). See adb_cuda_interrupts ...
- *
- * Next TODO: implementation of IIsi ADB protocol (maybe the USE_ORIG
- * conditionals can be a start?)
- */
-void adb_interrupt(int irq, void *arg, struct pt_regs *regs)
-{
- int x, adbdir;
- unsigned long flags;
- struct adb_request *req;
-
- last_status = status;
-
- /* prevent races due to SCSI enabling ints */
- save_flags(flags);
- cli();
-
- if (driver_running) {
- restore_flags(flags);
- return;
- }
-
- driver_running = 1;
-
-#ifdef USE_ORIG
- status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT);
-#else
- if (macintosh_config->adb_type==MAC_ADB_CUDA)
- status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT);
- else
- /* status bits (0x8->0x20) and direction (0x10 ??) CLASH !! */
- status = (via_read(via1, vBufB) & (ST_MASK|TREQ));
-#endif
- adbdir = (via_read(via1, vACR) & SR_OUT);
-#if (ADBDEBUG & ADBDEBUG_INT)
- if (console_loglevel == 10)
- printk("adb_interrupt: state=%d status=%x last=%x direction=%x\n",
- adb_state, status, last_status, adbdir);
-#endif
-
- switch (adb_state)
- {
- case idle:
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- /* CUDA has sent us the first byte of data - unsolicited */
- if (status != TREQ)
- printk("cuda: state=idle, status=%x\n", status);
- x = via_read(via1, vSR);
- via_write(via1, vBufB, via_read(via1,vBufB)&~TIP);
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- udelay(150);
- /* set SR to IN (??? no byte received else) */
- via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT);
- /* signal start of frame */
- via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
- /* read first byte */
- x = via_read(via1, vSR);
- first_byte = x;
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_macIIsi : receiving unsol. packet: %x (%x %x) ",
- x, adb_state, status);
-#endif
- /* ACK adb chip */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- udelay(150);
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- }
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
-#if (ADBDEBUG & ADBDEBUG_STATUS)
- if (status == TREQ && !adbdir)
- /* that's: not IRQ, idle, input -> weird */
- printk("adb_macII: idle, status=%x dir=%x\n",
- status, adbdir);
-#endif
- x = via_read(via1, vSR);
- first_byte = x;
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_macII: receiving unsol. packet: %x (%x %x) ",
- x, adb_state, status);
-#endif
- /* set ADB state = even for first data byte */
- via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN);
- }
- adb_state = reading;
- reply_ptr = cuda_rbuf;
- reply_len = 0;
- reading_reply = 0;
- prefix_len = 0;
- if (macintosh_config->adb_type==MAC_ADB_II) {
- *reply_ptr++ = ADB_PACKET;
- *reply_ptr++ = first_byte;
- *reply_ptr++ = command_byte; /*first_byte;*/
- reply_len = 3;
- prefix_len = 3;
- }
- break;
-
- case awaiting_reply:
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- /* CUDA has sent us the first byte of data of a reply */
- if (status != TREQ)
- printk("cuda: state=awaiting_reply, status=%x\n", status);
- x = via_read(via1, vSR);
- via_write(via1,vBufB,
- via_read(via1, vBufB)&~TIP);
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* set SR to IN */
- via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT);
- /* signal start of frame */
- via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
- /* read first byte */
- x = via_read(via1, vSR);
- first_byte = x;
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_macIIsi: reading reply: %x (%x %x) ",
- x, adb_state, status);
-#endif
-#if 0
- if( via_read(via1,vBufB) & TREQ)
- ending = 1;
- else
- ending = 0;
-#endif
- /* ACK adb chip */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- udelay(150);
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- }
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- /* handshake etc. for II ?? */
- x = via_read(via1, vSR);
- first_byte = x;
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_macII: reading reply: %x (%x %x) ",
- x, adb_state, status);
-#endif
- /* set ADB state = even for first data byte */
- via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN);
- }
- adb_state = reading;
- reply_ptr = current_req->reply;
- reading_reply = 1;
- reply_len = 0;
- prefix_len = 0;
- if (macintosh_config->adb_type==MAC_ADB_II) {
- *reply_ptr++ = ADB_PACKET;
- *reply_ptr++ = first_byte;
- *reply_ptr++ = first_byte; /* should be command byte */
- reply_len = 3;
- prefix_len = 3;
- }
- break;
-
- case sent_first_byte:
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk(" sending: %x (%x %x) ",
- current_req->data[1], adb_state, status);
-#endif
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- if (status == TREQ + TIP + SR_OUT)
- {
- /* collision */
- via_write(via1, vACR,
- via_read(via1, vACR)&~SR_OUT);
- x = via_read(via1, vSR);
- via_write(via1, vBufB,
- via_read(via1,vBufB)|TIP|TACK);
- adb_state = idle;
- }
- else
- {
- /* assert status == TIP + SR_OUT */
- if (status != TIP + SR_OUT)
- printk("cuda: state=sent_first_byte status=%x\n", status);
- via_write(via1,vSR,current_req->data[1]);
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- data_index = 2;
- adb_state = sending;
- }
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* switch ACK off */
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- if ( !(via_read(via1, vBufB) & TREQ) )
- {
- /* collision */
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk("adb_macIIsi: send collison, aborting!\n");
-#endif
- /* set shift in */
- via_write(via1, vACR,
- via_read(via1, vACR)&~SR_OUT);
- /* clear SR int. */
- x = via_read(via1, vSR);
- /* set ADB state to 'idle' */
- via_write(via1, vBufB,
- via_read(via1,vBufB) & ~(TIP|TACK));
- adb_state = idle;
- }
- else
- {
- /* delay */
- udelay(ADB_DELAY);
- /* set the shift register to shift out and send a byte */
-#if 0
- via_write(via1, vACR, via_read(via1, vACR) | SR_OUT);
-#endif
- via_write(via1, vSR, current_req->data[1]);
- /* signal 'byte ready' */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- data_index=2;
- adb_state = sending;
- }
- }
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- /* how to detect a collision here ?? */
- /* maybe we're already done (Talk, or Poll)? */
- if (data_index >= current_req->nbytes)
- {
- /* assert it's a Talk ?? */
- if ( (command_byte&0xc) != 0xc
- && console_loglevel == 10 )
- printk("ADB: single byte command, no Talk: %x!\n",
- command_byte);
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk(" -> end (%d of %d) (%x %x)!\n",
- data_index, current_req->nbytes, adb_state, status);
-#endif
- current_req->sent = 1;
- if (current_req->reply_expected)
- {
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk("ADB: reply expected on poll!\n");
-#endif
- adb_state = awaiting_reply;
- reading_reply = 0;
- } else {
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk("ADB: no reply for poll, not calling done()!\n");
-#endif
- req = current_req;
- current_req = req->next;
-#if 0 /* XXX Not sure about that one ... probably better enabled */
- if (req->done)
- (*req->done)(req);
-#endif
- adb_state = idle;
- reading_reply = 0;
- }
- /* set to shift in */
- via_write(via1, vACR,
- via_read(via1, vACR) & ~SR_OUT);
- x=via_read(via1, vSR);
- /* set ADB state idle - might get SRQ */
- via_write(via1, vBufB,
- (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
- break;
- }
-#if (ADBDEBUG & ADBDEBUG_STATUS)
- if(!(status==(ST_CMD|TREQ) && adbdir == SR_OUT))
- printk("adb_macII: sent_first_byte, weird status=%x dir=%x\n",
- status, adbdir);
-#endif
- /* SR already set to shift out; send byte */
- via_write(via1, vSR, current_req->data[1]);
- /* set state to ST_EVEN (first byte was: ST_CMD) */
- via_write(via1, vBufB,
- (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN);
- data_index=2;
- adb_state = sending;
- }
- break;
-
- case sending:
- req = current_req;
- if (data_index >= req->nbytes)
- {
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk(" -> end (%d of %d) (%x %x)!\n",
- data_index-1, req->nbytes, adb_state, status);
-#endif
- /* end of packet */
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- via_write(via1, vACR,
- via_read(via1, vACR)&~SR_OUT);
- x = via_read(via1, vSR);
- via_write(via1, vBufB,
- via_read(via1,vBufB)|TACK|TIP);
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* XXX maybe clear ACK here ??? */
- /* switch ACK off */
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- /* delay */
- udelay(ADB_DELAY);
- /* set the shift register to shift in */
- via_write(via1, vACR, via_read(via1, vACR)|SR_OUT);
- /* clear SR int. */
- x = via_read(via1, vSR);
- /* set ADB state 'idle' (end of frame) */
- via_write(via1, vBufB,
- via_read(via1,vBufB) & ~(TACK|TIP));
- }
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- /*
- * XXX Not sure: maybe only switch to
- * input mode on Talk ??
- */
- /* set to shift in */
- via_write(via1, vACR,
- via_read(via1, vACR) & ~SR_OUT);
- x=via_read(via1, vSR);
- /* set ADB state idle - might get SRQ */
- via_write(via1, vBufB,
- (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
- }
- req->sent = 1;
- if (req->reply_expected)
- {
- /*
- * maybe fake a reply here on Listen ??
- * Otherwise, a Listen hangs on success
- */
- if ( macintosh_config->adb_type==MAC_ADB_II
- && ((req->data[0]&0xc) == 0xc) )
- adb_state = awaiting_reply;
- else if ( macintosh_config->adb_type != MAC_ADB_II
- && ( req->data[0] == 0x0)
- && ((req->data[1]&0xc) == 0xc) )
- adb_state = awaiting_reply;
- else {
- /*
- * Reply expected, but none
- * possible -> fake reply.
- * Problem: sending next command
- * should probably be done
- * without setting bus to 'idle'!
- * (except if no more commands)
- */
-#if (ADBDEBUG & ADBDEBUG_PROT)
- printk("ADB: reply expected on Listen, faking reply\n");
-#endif
- /* make it look weird */
- /* XXX: return reply_len -1? */
- /* XXX: fake ADB header? */
- req->reply[0] = req->reply[1] = req->reply[2] = 0xFF;
- req->reply_len = 3;
- req->got_reply = 1;
- current_req = req->next;
- if (req->done)
- (*req->done)(req);
- /*
- * ready with this one, run
- * next command or repeat last
- * Talk (=idle on II)
- */
- /* set state to idle !! */
- adb_state = idle;
- if (current_req || retry_req)
- adb_start();
- }
- }
- else
- {
- current_req = req->next;
- if (req->done)
- (*req->done)(req);
- /* not sure about this */
- /*
- * MS: Must set idle, no new request
- * started else !
- */
- adb_state = idle;
- /*
- * requires setting ADB state to idle,
- * maybe read a byte ! (done above)
- */
- if (current_req || retry_req)
- adb_start();
- }
- }
- else
- {
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk(" %x (%x %x) ",
- req->data[data_index], adb_state, status);
-#endif
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- via_write(via1, vSR, req->data[data_index++]);
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* switch ACK off */
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- /* delay */
- udelay(ADB_DELAY);
- /* XXX: need to check for collision?? */
- /* set the shift register to shift out and send a byte */
-#if 0
- via_write(via1, vACR, via_read(via1, vACR)|SR_OUT);
-#endif
- via_write(via1, vSR, req->data[data_index++]);
- /* signal 'byte ready' */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- }
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- via_write(via1, vSR, req->data[data_index++]);
- /* invert state bits, toggle ODD/EVEN */
- x = via_read(via1, vBufB);
- via_write(via1, vBufB,
- (x&~ST_MASK)|~(x&ST_MASK));
- }
- }
- break;
-
- case reading:
-
- /* timeout / SRQ handling for II hw */
-#ifdef POLL_ON_TIMEOUT
- if((reply_len-prefix_len)==3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0)
-#else
- if( (first_byte == 0xFF && (reply_len-prefix_len)==2
- && memcmp(reply_ptr-2,"\xFF\xFF",2)==0) ||
- ((reply_len-prefix_len)==3
- && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0))
-#endif
- {
- /*
- * possible timeout (in fact, most probably a
- * timeout, since SRQ can't be signaled without
- * transfer on the bus).
- * The last three bytes seen were FF, together
- * with the starting byte (in case we started
- * on 'idle' or 'awaiting_reply') this probably
- * makes four. So this is mostl likely #5!
- * The timeout signal is a pattern 1 0 1 0 0..
- * on /INT, meaning we missed it :-(
- */
- x = via_read(via1, vSR);
- if (x != 0xFF)
- printk("ADB: mistaken timeout/SRQ!\n");
-
- /*
- * ADB status bits: either even or odd.
- * adb_state: need to set 'idle' here.
- * Maybe saner: set 'need_poll' or
- * 'need_resend' here, fall through to
- * read_done ??
- */
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk(" -> read aborted: %x (%x %x)!\n",
- x, adb_state, status);
-#endif
-
-#if 0 /* XXX leave status unchanged!! - need to check this again! */
- /* XXX Only touch status on II !!! */
- /* set ADB state to idle (required by adb_start()) */
- via_write(via1, vBufB,
- (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
-#endif
-
- /*
- * What if the timeout happens on reading a
- * reply ?? Assemble error reply and call
- * current_request->done()? Keep request
- * on queue?
- */
-
- /* prevent 'busy' in adb_start() */
- need_poll = 1;
-
- /*
- * Timeout: /IRQ alternates high/low during
- * 4 'FF' bytes (1 0 1 0 0...)
- * We're on byte 5, so we need one
- * more backlog here (TBI) ....
- */
- if ((status&TREQ) != (last_status&TREQ)) {
-#if (ADBDEBUG & ADBDEBUG_SRQ)
- if (console_loglevel == 10)
- printk("ADB: reply timeout, resending!\n");
-#endif
- /*
- * first byte received should be the
- * command byte timing out !!
- */
- if (first_byte != 0xff)
- command_byte = first_byte;
-
- /*
- * compute target for retransmit: if
- * last_active is set, use that one,
- * else use command_byte
- */
- if (last_active == -1)
- last_active = (command_byte&0xf0)>>4;
- adb_state = idle;
- /* resend if TALK, don't poll! */
- if (current_req)
- adb_start();
- else
- /*
- * XXX: need to count the timeouts ??
- * restart last active TALK ??
- * If no current_req, reuse old one!
- */
- adb_retransmit(last_active);
-
- } else {
- /*
- * SRQ: NetBSD suggests /IRQ is asserted!?
- */
- if (status&TREQ)
- printk("ADB: SRQ signature w/o /INT!\n");
-#if (ADBDEBUG & ADBDEBUG_SRQ)
- if (console_loglevel == 10)
- printk("ADB: empty SRQ packet!\n");
-#endif
- /* Terminate the SRQ packet and poll */
- adb_state = idle;
- adb_queue_poll();
- }
- /*
- * Leave ADB status lines unchanged (means /IRQ
- * will still be low when entering adb_start!)
- */
- break;
- }
- /* end timeout / SRQ handling for II hw. */
- if((reply_len-prefix_len)>3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0)
- {
- /* SRQ tacked on data packet */
- /* Check /IRQ here ?? */
-#if (ADBDEBUG & ADBDEBUG_SRQ)
- if (console_loglevel == 10)
- printk("\nADB: Packet with SRQ!\n");
-#endif
- /* Terminate the packet (SRQ never ends) */
- x = via_read(via1, vSR);
- adb_state = read_done;
- reply_len -= 3;
- reply_ptr -= 3;
- need_poll = 1;
- /* need to continue; next byte not seen else */
- /*
- * XXX: not at all sure here; maybe need to
- * send away the reply and poll immediately?
- */
- } else {
- /* Sanity check */
- if(reply_len>15)
- reply_len=0;
- /* read byte */
- *reply_ptr = via_read(via1, vSR);
- x = *reply_ptr;
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk(" %x (%x %x) ",
- *reply_ptr, adb_state, status);
-#endif
- reply_ptr++;
- reply_len++;
- }
- /* The usual handshake ... */
- if (macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- if (status == TIP)
- {
- /* that's all folks */
- via_write(via1, vBufB,
- via_read(via1, vBufB)|TACK|TIP);
- adb_state = read_done;
- }
- else
- {
- /* assert status == TIP | TREQ */
- if (status != TIP + TREQ)
- printk("cuda: state=reading status=%x\n", status);
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- }
- }
- else if (macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* ACK adb chip (maybe check for end first?) */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- udelay(150);
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- /* end of frame?? */
- if (status & TREQ)
- {
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_IIsi: end of frame!\n");
-#endif
- /* that's all folks */
- via_write(via1, vBufB,
- via_read(via1, vBufB) & ~(TACK|TIP));
- adb_state = read_done;
- /* maybe process read_done here?? Handshake anyway?? */
- }
- }
- else if (macintosh_config->adb_type==MAC_ADB_II)
- {
- /*
- * NetBSD hints that the next to last byte
- * is sent with IRQ !!
- * Guido found out it's the last one (0x0),
- * but IRQ should be asserted already.
- * Problem with timeout detection: First
- * transition to /IRQ might be second
- * byte of timeout packet!
- * Timeouts are signaled by 4x FF.
- */
- if(!(status&TREQ) && x == 0x00) /* != 0xFF */
- {
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk(" -> read done!\n");
-#endif
-#if 0 /* XXX: we take one more byte (why?), so handshake! */
- /* set ADB state to idle */
- via_write(via1, vBufB,
- (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
-#else
- /* invert state bits, toggle ODD/EVEN */
- x = via_read(via1, vBufB);
- via_write(via1, vBufB,
- (x&~ST_MASK)|~(x&ST_MASK));
-#endif
- /* adjust packet length */
- reply_len--;
- reply_ptr--;
- adb_state = read_done;
- }
- else
- {
-#if (ADBDEBUG & ADBDEBUG_STATUS)
- if(status!=TIP+TREQ)
- printk("macII_adb: state=reading status=%x\n", status);
-#endif
- /* not caught: ST_CMD */
- /* required for re-entry 'reading'! */
- if ((status&ST_MASK) == ST_IDLE) {
- /* (in)sanity check - set even */
- via_write(via1, vBufB,
- (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN);
- } else {
- /* invert state bits, toggle ODD/EVEN */
- x = via_read(via1, vBufB);
- via_write(via1, vBufB,
- (x&~ST_MASK)|~(x&ST_MASK));
- }
- }
- }
- break;
-
- case read_done:
- x = via_read(via1, vSR);
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("ADB: read done: %x (%x %x)!\n",
- x, adb_state, status);
-#endif
- if (reading_reply)
- {
- req = current_req;
- req->reply_len = reply_ptr - req->reply;
- req->got_reply = 1;
- current_req = req->next;
- if (req->done)
- (*req->done)(req);
- }
- else
- {
- adb_input(cuda_rbuf, reply_ptr - cuda_rbuf, regs);
- }
-
- /*
- * remember this device ID; it's the latest we got a
- * reply from!
- */
- last_reply = command_byte;
- last_active = (command_byte&0xf0)>>4;
-
- /*
- * Assert status = ST_IDLE ??
- */
- /*
- * SRQ seen before, initiate poll now
- */
- if (need_poll) {
-#if (ADBDEBUG & ADBDEBUG_POLL)
- if (console_loglevel == 10)
- printk("ADB: initiate poll!\n");
-#endif
- adb_state = idle;
- /*
- * set ADB status bits?? (unchanged above!)
- */
- adb_queue_poll();
- need_poll = 0;
- /* hope this is ok; queue_poll runs adb_start */
- break;
- }
-
- /*
- * /IRQ seen, so the ADB controller has data for us
- */
- if (!(status&TREQ))
- {
- /* set ADB state to idle */
- via_write(via1, vBufB,
- (via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
-
- adb_state = reading;
- reply_ptr = cuda_rbuf;
- reply_len = 0;
- prefix_len = 0;
- if (macintosh_config->adb_type==MAC_ADB_II) {
- *reply_ptr++ = ADB_PACKET;
- *reply_ptr++ = command_byte;
- reply_len = 2;
- prefix_len = 2;
- }
- reading_reply = 0;
- }
- else
- {
- /*
- * no IRQ, send next packet or wait
- */
- adb_state = idle;
- if (current_req)
- adb_start();
- else
- adb_retransmit(last_active);
- }
- break;
-
- default:
-#if (ADBDEBUG & ADBDEBUG_STATE)
- printk("adb_interrupt: unknown adb_state %d?\n", adb_state);
-#endif
- }
- /* reset mutex and interrupts */
- driver_running = 0;
- restore_flags(flags);
-}
-
-/*
- * Restart of CUDA support: please modify this interrupt handler while
- * working at the Quadra etc. ADB driver. We can try to merge them later, or
- * remove the CUDA stuff from the MacII handler
- *
- * MSch 27/01/98: Implemented IIsi driver based on initial code by Robert
- * Thompson and hints from the NetBSD driver. CUDA and IIsi seem more closely
- * related than to the MacII code, so merging all three might be a bad
- * idea.
- */
-
-void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
-{
- int x, status;
- struct adb_request *req;
- unsigned long flags;
-
- save_flags(flags);
- cli();
-
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT);
- else
- status = via_read(via1, vBufB) & (TIP|TREQ);
-
-#if (ADBDEBUG & ADBDEBUG_INT)
- if (console_loglevel == 10)
- printk("adb_interrupt: state=%d status=%x\n", adb_state, status);
-#endif
-
- switch (adb_state)
- {
- case idle:
- first_byte = 0;
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
-#if (ADBDEBUG & ADBDEBUG_STATUS)
- /* CUDA has sent us the first byte of data - unsolicited */
- if (status != TREQ)
- printk("cuda: state=idle, status=%x want=%x\n",
- status, TREQ);
-#endif
- x = via_read(via1, vSR);
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_cuda: receiving unsol. packet: %x (%x %x) ",
- x, adb_state, status);
-#endif
- via_write(via1, vBufB, via_read(via1,vBufB)&~TIP);
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- udelay(150);
- /* set SR to IN */
- via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT);
- /* signal start of frame */
- via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
- /* read first byte */
- x = via_read(via1, vSR);
- first_byte = x;
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_IIsi : receiving unsol. packet: %x (%x %x) ",
- x, adb_state, status);
-#endif
- /* ACK adb chip */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- udelay(150);
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- }
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- if (status != TREQ)
- printk("adb_macII: state=idle status=%x want=%x\n",
- status, TREQ);
- x = via_read(via1, vSR);
- via_write(via1, vBufB, via_read(via1, vBufB)&~(TIP|TACK));
- }
- adb_state = reading;
- reply_ptr = cuda_rbuf;
- reply_len = 0;
- reading_reply = 0;
- break;
-
- case awaiting_reply:
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- /* CUDA has sent us the first byte of data of a reply */
-#if (ADBDEBUG & ADBDEBUG_STATUS)
- if (status != TREQ)
- printk("cuda: state=awaiting_reply, status=%x want=%x\n",
- status, TREQ);
-#endif
- x = via_read(via1, vSR);
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_cuda: reading reply: %x (%x %x) ",
- x, adb_state, status);
-#endif
- via_write(via1,vBufB,
- via_read(via1, vBufB)&~TIP);
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* udelay(150);*/
- /* set SR to IN */
- via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT);
- /* signal start of frame */
- via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
- /* read first byte */
- x = via_read(via1, vSR);
- first_byte = x;
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_IIsi: reading reply: %x (%x %x) ",
- x, adb_state, status);
-#endif
-#if 0
- if( via_read(via1,vBufB) & TREQ)
- ending = 1;
- else
- ending = 0;
-#endif
- /* ACK adb chip */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- udelay(150);
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- }
- adb_state = reading;
- reply_ptr = current_req->reply;
- reading_reply = 1;
- reply_len = 0;
- break;
-
- case sent_first_byte:
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk(" sending: %x (%x %x) ",
- current_req->data[1], adb_state, status);
-#endif
- if (status == TREQ + TIP + SR_OUT)
- {
- /* collision */
- if (console_loglevel == 10)
- printk("adb_cuda: send collision!\n");
- via_write(via1, vACR,
- via_read(via1, vACR)&~SR_OUT);
- x = via_read(via1, vSR);
- via_write(via1, vBufB,
- via_read(via1,vBufB)|TIP|TACK);
- adb_state = idle;
- }
- else
- {
- /* assert status == TIP + SR_OUT */
-#if (ADBDEBUG & ADBDEBUG_STATUS)
- if (status != TIP + SR_OUT)
- printk("adb_cuda: state=sent_first_byte status=%x want=%x\n",
- status, TIP + SR_OUT);
-#endif
- via_write(via1,vSR,current_req->data[1]);
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- data_index = 2;
- adb_state = sending;
- }
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* switch ACK off */
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- if ( !(via_read(via1, vBufB) & TREQ) )
- {
- /* collision */
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk("adb_macIIsi: send collison, aborting!\n");
-#endif
- /* set shift in */
- via_write(via1, vACR,
- via_read(via1, vACR)&~SR_OUT);
- /* clear SR int. */
- x = via_read(via1, vSR);
- /* set ADB state to 'idle' */
- via_write(via1, vBufB,
- via_read(via1,vBufB) & ~(TIP|TACK));
- adb_state = idle;
- }
- else
- {
- /* delay */
- udelay(ADB_DELAY);
- /* set the shift register to shift out and send a byte */
-#if 0
- via_write(via1, vACR, via_read(via1, vACR) | SR_OUT);
-#endif
- via_write(via1, vSR, current_req->data[1]);
- /* signal 'byte ready' */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- data_index=2;
- adb_state = sending;
- }
- }
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- if(status!=TIP+SR_OUT)
- printk("adb_macII: state=send_first_byte status=%x want=%x\n",
- status, TIP+SR_OUT);
- via_write(via1, vSR, current_req->data[1]);
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- data_index=2;
- adb_state = sending;
- }
- break;
-
- case sending:
- req = current_req;
- if (data_index >= req->nbytes)
- {
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk(" -> end (%d of %d) (%x %x)!\n",
- data_index-1, req->nbytes, adb_state, status);
-#endif
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- via_write(via1, vACR,
- via_read(via1, vACR)&~SR_OUT);
- x = via_read(via1, vSR);
- via_write(via1, vBufB,
- via_read(via1,vBufB)|TACK|TIP);
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* XXX maybe clear ACK here ??? */
- /* switch ACK off */
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- /* delay */
- udelay(ADB_DELAY);
- /* set the shift register to shift in */
- via_write(via1, vACR, via_read(via1, vACR)|SR_OUT);
- /* clear SR int. */
- x = via_read(via1, vSR);
- /* set ADB state 'idle' (end of frame) */
- via_write(via1, vBufB,
- via_read(via1,vBufB) & ~(TACK|TIP));
- }
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- via_write(via1, vACR,
- via_read(via1, vACR) & ~SR_OUT);
- x=via_read(via1, vSR);
- via_write(via1, vBufB,
- via_read(via1, vBufB)|TACK|TIP);
- }
- req->sent = 1;
- if (req->reply_expected)
- {
- /*
- * maybe fake a reply here on Listen ??
- * Otherwise, a Listen hangs on success
- * CUDA+IIsi: only ADB Talk considered
- * RTC/PRAM read (0x1 0x3) to follow.
- */
- if ( (req->data[0] == 0x0) && ((req->data[1]&0xc) == 0xc) )
- adb_state = awaiting_reply;
- else {
- /*
- * Reply expected, but none
- * possible -> fake reply.
- */
-#if (ADBDEBUG & ADBDEBUG_PROT)
- printk("ADB: reply expected on Listen, faking reply\n");
-#endif
- /* make it look weird */
- /* XXX: return reply_len -1? */
- /* XXX: fake ADB header? */
- req->reply[0] = req->reply[1] = req->reply[2] = 0xFF;
- req->reply_len = 3;
- req->got_reply = 1;
- current_req = req->next;
- if (req->done)
- (*req->done)(req);
- /*
- * ready with this one, run
- * next command !
- */
- /* set state to idle !! */
- adb_state = idle;
- if (current_req || retry_req)
- adb_start();
- }
- }
- else
- {
- current_req = req->next;
- if (req->done)
- (*req->done)(req);
- /* not sure about this */
- adb_state = idle;
- adb_start();
- }
- }
- else
- {
-#if (ADBDEBUG & ADBDEBUG_WRITE)
- if (console_loglevel == 10)
- printk(" %x (%x %x) ",
- req->data[data_index], adb_state, status);
-#endif
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- via_write(via1, vSR, req->data[data_index++]);
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- }
- else if(macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* switch ACK off */
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- /* delay */
- udelay(ADB_DELAY);
- /* XXX: need to check for collision?? */
- /* set the shift register to shift out and send a byte */
-#if 0
- via_write(via1, vACR, via_read(via1, vACR)|SR_OUT);
-#endif
- via_write(via1, vSR, req->data[data_index++]);
- /* signal 'byte ready' */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- }
- else if(macintosh_config->adb_type==MAC_ADB_II)
- {
- via_write(via1, vSR, req->data[data_index++]);
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- }
- }
- break;
-
- case reading:
- if(reply_len==3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0)
- {
- /* Terminate the SRQ packet */
-#if (ADBDEBUG & ADBDEBUG_SRQ)
- if (console_loglevel == 10)
- printk("adb: Got an SRQ\n");
-#endif
- adb_state = idle;
- adb_queue_poll();
- break;
- }
- /* Sanity check - botched in orig. code! */
- if(reply_len>15) {
- printk("adb_cuda: reply buffer overrun!\n");
- /* wrap buffer */
- reply_len=0;
- if (reading_reply)
- reply_ptr = current_req->reply;
- else
- reply_ptr = cuda_rbuf;
- }
- *reply_ptr = via_read(via1, vSR);
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk(" %x (%x %x) ",
- *reply_ptr, adb_state, status);
-#endif
- reply_ptr++;
- reply_len++;
- if(macintosh_config->adb_type==MAC_ADB_CUDA)
- {
- if (status == TIP)
- {
- /* that's all folks */
- via_write(via1, vBufB,
- via_read(via1, vBufB)|TACK|TIP);
- adb_state = read_done;
- }
- else
- {
- /* assert status == TIP | TREQ */
-#if (ADBDEBUG & ADBDEBUG_STATUS)
- if (status != TIP + TREQ)
- printk("cuda: state=reading status=%x want=%x\n",
- status, TIP + TREQ);
-#endif
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- }
- }
- else if (macintosh_config->adb_type==MAC_ADB_IISI)
- {
- /* ACK adb chip (maybe check for end first?) */
- via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
- udelay(150);
- via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
- /* end of frame?? */
- if (status & TREQ)
- {
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb_IIsi: end of frame!\n");
-#endif
- /* that's all folks */
- via_write(via1, vBufB,
- via_read(via1, vBufB) & ~(TACK|TIP));
- adb_state = read_done;
- /* XXX maybe process read_done here??
- Handshake anyway?? */
- }
- }
- if(macintosh_config->adb_type==MAC_ADB_II)
- {
- if( status == TIP)
- {
- via_write(via1, vBufB,
- via_read(via1, vBufB)|TACK|TIP);
- adb_state = read_done;
- }
- else
- {
-#if (ADBDEBUG & ADBDEBUG_STATUS)
- if(status!=TIP+TREQ)
- printk("macII_adb: state=reading status=%x\n", status);
-#endif
- via_write(via1, vBufB,
- via_read(via1, vBufB)^TACK);
- }
- }
- /* fall through for IIsi on end of frame */
- if (macintosh_config->adb_type != MAC_ADB_IISI
- || adb_state != read_done)
- break;
-
- case read_done:
- x = via_read(via1, vSR);
-#if (ADBDEBUG & ADBDEBUG_READ)
- if (console_loglevel == 10)
- printk("adb: read done: %x (%x %x)!\n",
- x, adb_state, status);
-#endif
- if (reading_reply)
- {
- req = current_req;
- req->reply_len = reply_ptr - req->reply;
- req->got_reply = 1;
- current_req = req->next;
- if (req->done)
- (*req->done)(req);
- }
- else
- {
- adb_input(cuda_rbuf, reply_ptr - cuda_rbuf, regs);
- }
-
- if (macintosh_config->adb_type==MAC_ADB_CUDA
- && status & TREQ)
- {
- via_write(via1, vBufB,
- via_read(via1, vBufB)&~TIP);
- adb_state = reading;
- reply_ptr = cuda_rbuf;
- reading_reply = 0;
- }
- else if (macintosh_config->adb_type==MAC_ADB_IISI
- && !(status & TREQ))
- {
- udelay(150);
- via_write(via1, vBufB,
- via_read(via1, vBufB) | TIP);
- adb_state = reading;
- reply_ptr = cuda_rbuf;
- reading_reply = 0;
- }
- else
- {
- adb_state = idle;
- adb_start();
- }
- break;
-
- default:
- printk("adb_cuda_interrupt: unknown adb_state %d?\n", adb_state);
- }
-
- restore_flags(flags);
-
-}
-
-/*
- * The 'reply delivery' routine; determines which device sent the
- * request and calls the appropriate handler.
- * Reply data are expected in CUDA format (again, argh...) so we need
- * to fake this in the interrupt handler for MacII.
- * Only one handler per device ID is currently possible.
- * XXX: is the ID field here representing the default or real ID?
- */
-static void adb_input(unsigned char *buf, int nb, struct pt_regs *regs)
-{
- int i, id;
-
- switch (buf[0])
- {
- case ADB_PACKET:
- /* what's in buf[1] ?? */
- id = buf[2] >> 4;
-#if 0
- xmon_printf("adb packet: ");
- for (i = 0; i < nb; ++i)
- xmon_printf(" %x", buf[i]);
- xmon_printf(", id = %d\n", id);
-#endif
-#if (ADBDEBUG & ADBDEBUG_INPUT)
- if (console_loglevel == 10) {
- printk("adb_input: adb packet ");
- for (i = 0; i < nb; ++i)
- printk(" %x", buf[i]);
- printk(", id = %d\n", id);
- }
-#endif
- if (adb_handler[id].handler != 0)
- {
- (*adb_handler[id].handler)(buf, nb, regs);
- }
- break;
-
- default:
-#if (ADBDEBUG & ADBDEBUG_INPUT)
- if (console_loglevel == 10) {
- printk("adb_input: data from via (%d bytes):", nb);
- for (i = 0; i < nb; ++i)
- printk(" %.2x", buf[i]);
- printk("\n");
- }
-#endif
- }
-}
-
-/* Ultimately this should return the number of devices with
- the given default id. */
-
-int adb_register(int default_id,
- void (*handler)(unsigned char *, int, struct pt_regs *))
-{
- if (adb_handler[default_id].handler != 0)
- panic("Two handlers for ADB device %d\n", default_id);
- adb_handler[default_id].handler = handler;
- return 1;
-}
-
-/*
- * /dev/adb device driver.
- */
-
-#define ADB_MAJOR 56 /* major number for /dev/adb */
-
-#define ADB_MAX_MINOR 64 /* range of ADB minors */
-#define ADB_TYPE_SHIFT 4 /* # bits for device ID/type in subdevices */
-
-#define ADB_TYPE_RAW 0 /* raw device; unbuffered */
-#define ADB_TYPE_BUFF 1 /* raw device; buffered */
-#define ADB_TYPE_COOKED 2 /* 'cooked' device */
-
-
-extern void adbdev_init(void);
-
-struct adbdev_state {
- struct adb_request req;
-};
-
-static DECLARE_WAIT_QUEUE_HEAD(adb_wait);
-
-static int adb_wait_reply(struct adbdev_state *state, struct file *file)
-{
- int ret = 0;
- DECLARE_WAITQUEUE(wait,current);
-
- __set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&adb_wait, &wait);
-
- while (!state->req.got_reply) {
- if (file->f_flags & O_NONBLOCK) {
- ret = -EAGAIN;
- break;
- }
- if (signal_pending(current)) {
- ret = -ERESTARTSYS;
- break;
- }
- schedule();
- }
-
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&adb_wait, &wait);
-
- return ret;
-}
-
-static void adb_write_done(struct adb_request *req)
-{
- if (!req->got_reply) {
- req->reply_len = 0;
- req->got_reply = 1;
- }
- wake_up_interruptible(&adb_wait);
-}
-
-struct file_operations *adb_raw[16];
-struct file_operations *adb_buffered[16];
-struct file_operations *adb_cooked[16];
-
-static int adb_open(struct inode *inode, struct file *file)
-{
- int adb_type, adb_subtype;
- struct adbdev_state *state;
-
- if (MINOR(inode->i_rdev) > ADB_MAX_MINOR)
- return -ENXIO;
-
- switch (MINOR(inode->i_rdev) >> ADB_TYPE_SHIFT) {
- case ADB_TYPE_RAW:
- /* see code below */
- break;
- case ADB_TYPE_BUFF:
- /* TBI */
- return -ENXIO;
- case ADB_TYPE_COOKED:
- /* subtypes such as kbd, mouse, ... */
- adb_subtype = MINOR(inode->i_rdev) & ~ADB_TYPE_SHIFT;
- if ((file->f_op = adb_cooked[adb_subtype]))
- return file->f_op->open(inode,file);
- else
- return -ENODEV;
- }
-
- state = kmalloc(sizeof(struct adbdev_state), GFP_KERNEL);
- if (state == 0)
- return -ENOMEM;
- file->private_data = state;
- state->req.reply_expected = 0;
- return 0;
-}
-
-static void adb_release(struct inode *inode, struct file *file)
-{
- struct adbdev_state *state = file->private_data;
-
- if (state) {
- file->private_data = NULL;
- if (state->req.reply_expected && !state->req.got_reply)
- if (adb_wait_reply(state, file))
- return;
- kfree(state);
- }
- return;
-}
-
-static int adb_lseek(struct inode *inode, struct file *file,
- off_t offset, int origin)
-{
- return -ESPIPE;
-}
-
-static int adb_read(struct inode *inode, struct file *file,
- char *buf, int count)
-{
- int ret;
- struct adbdev_state *state = file->private_data;
-
- if (count < 2)
- return -EINVAL;
- if (count > sizeof(state->req.reply))
- count = sizeof(state->req.reply);
- ret = verify_area(VERIFY_WRITE, buf, count);
- if (ret)
- return ret;
-
- if (!state->req.reply_expected)
- return 0;
-
- ret = adb_wait_reply(state, file);
- if (ret)
- return ret;
-
- state->req.reply_expected = 0;
- ret = state->req.reply_len;
- copy_to_user(buf, state->req.reply, ret);
-
- return ret;
-}
-
-static int adb_write(struct inode *inode, struct file *file,
- const char *buf, int count)
-{
- int ret, i;
- struct adbdev_state *state = file->private_data;
-
- if (count < 2 || count > sizeof(state->req.data))
- return -EINVAL;
- ret = verify_area(VERIFY_READ, buf, count);
- if (ret)
- return ret;
-
- if (state->req.reply_expected && !state->req.got_reply) {
- /* A previous request is still being processed.
- Wait for it to finish. */
- ret = adb_wait_reply(state, file);
- if (ret)
- return ret;
- }
-
- state->req.nbytes = count;
- state->req.done = adb_write_done;
- state->req.got_reply = 0;
- copy_from_user(state->req.data, buf, count);
-#if 0
- switch (adb_hardware) {
- case ADB_NONE:
- return -ENXIO;
- case ADB_VIACUDA:
- state->req.reply_expected = 1;
- cuda_send_request(&state->req);
- break;
- default:
-#endif
- if (state->req.data[0] != ADB_PACKET)
- return -EINVAL;
- for (i = 1; i < state->req.nbytes; ++i)
- state->req.data[i] = state->req.data[i+1];
- state->req.reply_expected =
- ((state->req.data[0] & 0xc) == 0xc);
- adb_send_request(&state->req);
-#if 0
- break;
- }
-#endif
-
- return count;
-}
-
-static struct file_operations adb_fops = {
- llseek: adb_lseek,
- read: adb_read,
- write: adb_write,
- open: adb_open,
- release: adb_release,
-};
-
-int adbdev_register(int subtype, struct file_operations *fops)
-{
- if (subtype < 0 || subtype > 15)
- return -EINVAL;
- if (adb_cooked[subtype])
- return -EBUSY;
- adb_cooked[subtype] = fops;
- return 0;
-}
-
-int adbdev_unregister(int subtype)
-{
- if (subtype < 0 || subtype > 15)
- return -EINVAL;
- if (!adb_cooked[subtype])
- return -ENODEV;
- adb_cooked[subtype] = NULL;
- return 0;
-}
-
-void adbdev_init()
-{
- if (register_chrdev(ADB_MAJOR, "adb", &adb_fops))
- printk(KERN_ERR "adb: unable to get major %d\n", ADB_MAJOR);
-}
-
-
-#if 0 /* old ADB device */
-
-/*
- * Here are the file operations we export for /dev/adb.
- */
-
-#define ADB_MINOR 140 /* /dev/adb is c 10 140 */
-
-extern void adbdev_inits(void);
-
-struct adbdev_state {
- struct adb_request req;
-};
-
-static DECLARE_WAIT_QUEUE_HEAD(adb_wait);
-
-static int adb_wait_reply(struct adbdev_state *state, struct file *file)
-{
- int ret = 0;
- DECLARE_WAITQUEUE(wait, current);
-
-#if (ADBDEBUG & ADBDEBUG_DEVICE)
- printk("ADB request: wait_reply (blocking ... \n");
-#endif
-
- __set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&adb_wait, &wait);
-
- while (!state->req.got_reply) {
- if (file->f_flags & O_NONBLOCK) {
- ret = -EAGAIN;
- break;
- }
- if (signal_pending(current)) {
- ret = -ERESTARTSYS;
- break;
- }
- schedule();
- }
-
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&adb_wait, &wait);
-
- return ret;
-}
-
-static void adb_write_done(struct adb_request *req)
-{
- if (!req->got_reply) {
- req->reply_len = 0;
- req->got_reply = 1;
- }
- wake_up_interruptible(&adb_wait);
-}
-
-static int adb_open(struct inode *inode, struct file *file)
-{
- struct adbdev_state *state;
-
- state = kmalloc(sizeof(struct adbdev_state), GFP_KERNEL);
- if (state == 0)
- return -ENOMEM;
- file->private_data = state;
- state->req.reply_expected = 0;
- return 0;
-}
-
-static void adb_release(struct inode *inode, struct file *file)
-{
- struct adbdev_state *state = file->private_data;
-
- if (state) {
- file->private_data = NULL;
- if (state->req.reply_expected && !state->req.got_reply)
- if (adb_wait_reply(state, file))
- return;
- kfree(state);
- }
- return;
-}
-
-static int adb_lseek(struct inode *inode, struct file *file,
- off_t offset, int origin)
-{
- return -ESPIPE;
-}
-
-static int adb_read(struct inode *inode, struct file *file,
- char *buf, int count)
-{
- int ret;
- struct adbdev_state *state = file->private_data;
-
- if (count < 2)
- return -EINVAL;
- if (count > sizeof(state->req.reply))
- count = sizeof(state->req.reply);
- ret = verify_area(VERIFY_WRITE, buf, count);
- if (ret)
- return ret;
-
- if (!state->req.reply_expected)
- return 0;
-
- ret = adb_wait_reply(state, file);
- if (ret)
- return ret;
-
- ret = state->req.reply_len;
- memcpy_tofs(buf, state->req.reply, ret);
- state->req.reply_expected = 0;
-
- return ret;
-}
-
-static int adb_write(struct inode *inode, struct file *file,
- const char *buf, int count)
-{
- int ret;
- struct adbdev_state *state = file->private_data;
-
- if (count < 2 || count > sizeof(state->req.data))
- return -EINVAL;
- ret = verify_area(VERIFY_READ, buf, count);
- if (ret)
- return ret;
-
- if (state->req.reply_expected && !state->req.got_reply) {
- /* A previous request is still being processed.
- Wait for it to finish. */
- ret = adb_wait_reply(state, file);
- if (ret)
- return ret;
- }
-
- state->req.nbytes = count;
- state->req.done = adb_write_done;
- memcpy_fromfs(state->req.data, buf, count);
- state->req.reply_expected = 1;
- state->req.got_reply = 0;
- adb_send_request(&state->req);
-
- return count;
-}
-
-static struct file_operations adb_fops = {
- llseek: adb_lseek,
- read: adb_read,
- write: adb_write,
- open: adb_open,
- release: adb_release,
-};
-
-static struct miscdevice adb_dev = {
- ADB_MINOR,
- "adb",
- &adb_fops
-};
-
-void adbdev_init(void)
-{
- misc_register(&adb_dev);
-}
-
-#endif /* old ADB device */
diff --git a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c
new file mode 100644
index 000000000..445a99780
--- /dev/null
+++ b/arch/m68k/mac/baboon.c
@@ -0,0 +1,124 @@
+/*
+ * Baboon Custom IC Managment
+ *
+ * The Baboon custom IC controls the IDE, PCMCIA and media bay on the
+ * PowerBook 190. It multiplexes multiple interrupt sources onto the
+ * Nubus slot $C interrupt.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/traps.h>
+#include <asm/bootinfo.h>
+#include <asm/macintosh.h>
+#include <asm/macints.h>
+#include <asm/mac_baboon.h>
+
+/* #define DEBUG_BABOON /**/
+/* #define DEBUG_IRQS /**/
+
+int baboon_present,baboon_active;
+volatile struct baboon *baboon;
+
+void baboon_irq(int, void *, struct pt_regs *);
+
+extern int console_loglevel;
+
+extern int macide_ack_intr(ide_hwif_t *);
+
+/*
+ * Baboon initialization.
+ */
+
+void __init baboon_init(void)
+{
+ if (macintosh_config->ident != MAC_MODEL_PB190) {
+ baboon = NULL;
+ baboon_present = 0;
+ return;
+ }
+
+ baboon = (struct baboon *) BABOON_BASE;
+ baboon_present = 1;
+ baboon_active = 0;
+
+ printk("Baboon detected at %p\n", baboon);
+}
+
+/*
+ * Register the Baboon interrupt dispatcher on nubus slot $C.
+ */
+
+void __init baboon_register_interrupts(void)
+{
+ request_irq(IRQ_NUBUS_C, baboon_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
+ "baboon", (void *) baboon);
+}
+
+/*
+ * Baboon interrupt handler. This works a lot like a VIA.
+ */
+
+void baboon_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ int irq_bit,i;
+ unsigned char events;
+
+#ifdef DEBUG_IRQS
+ printk("baboon_irq: mb_control %02X mb_ifr %02X mb_status %02X active %02X\n",
+ (uint) baboon->mb_control, (uint) baboon->mb_ifr,
+ (uint) baboon->mb_status, baboon_active);
+#endif
+
+ if (!(events = baboon->mb_ifr & 0x07)) return;
+
+ for (i = 0, irq_bit = 1 ; i < 3 ; i++, irq_bit <<= 1) {
+ if (events & irq_bit/* & baboon_active*/) {
+ baboon_active &= ~irq_bit;
+ mac_do_irq_list(IRQ_BABOON_0 + i, regs);
+ baboon_active |= irq_bit;
+ baboon->mb_ifr &= ~irq_bit;
+ }
+ }
+#if 0
+ if (baboon->mb_ifr & 0x02) macide_ack_intr(NULL);
+ /* for now we need to smash all interrupts */
+ baboon->mb_ifr &= ~events;
+#endif
+}
+
+void baboon_irq_enable(int irq) {
+ int irq_idx = IRQ_IDX(irq);
+
+#ifdef DEBUG_IRQUSE
+ printk("baboon_irq_enable(%d)\n", irq);
+#endif
+ baboon_active |= (1 << irq_idx);
+}
+
+void baboon_irq_disable(int irq) {
+ int irq_idx = IRQ_IDX(irq);
+
+#ifdef DEBUG_IRQUSE
+ printk("baboon_irq_disable(%d)\n", irq);
+#endif
+ baboon_active &= ~(1 << irq_idx);
+}
+
+void baboon_irq_clear(int irq) {
+ int irq_idx = IRQ_IDX(irq);
+
+ baboon->mb_ifr &= ~(1 << irq_idx);
+}
+
+int baboon_irq_pending(int irq)
+{
+ int irq_idx = IRQ_IDX(irq);
+
+ return baboon->mb_ifr & (1 << irq_idx);
+}
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index b5057f6e8..c1154b6aa 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -42,16 +42,6 @@
#include <asm/mac_oss.h>
#include <asm/mac_psc.h>
-/* Offset between Unix time (1970-based) and Mac time (1904-based) */
-
-#define MAC_TIME_OFFSET 2082844800
-
-/*
- * hardware reset vector
- */
-
-static void (*rom_reset)(void);
-
/* Mac bootinfo struct */
struct mac_booter_data mac_bi_data = {0,};
@@ -76,10 +66,11 @@ extern int mackbd_init_hw(void);
extern void mackbd_leds(unsigned int leds);
/* Mac specific timer functions */
+extern void mac_gettod (int *, int *, int *, int *, int *, int *);
extern unsigned long mac_gettimeoffset (void);
-static void mac_gettod (int *, int *, int *, int *, int *, int *);
-static int mac_hwclk (int, struct hwclk_time *);
-static int mac_set_clock_mmss (unsigned long);
+extern int mac_hwclk (int, struct hwclk_time *);
+extern int mac_set_clock_mmss (unsigned long);
+extern int mac_get_irq_list(char *);
extern void iop_preinit(void);
extern void iop_init(void);
extern void via_init(void);
@@ -87,6 +78,7 @@ extern void via_init_clock(void (*func)(int, void *, struct pt_regs *));
extern void via_flush_cache(void);
extern void oss_init(void);
extern void psc_init(void);
+extern void baboon_init(void);
extern void (*kd_mksound)(unsigned int, unsigned int);
extern void mac_mksound(unsigned int, unsigned int);
@@ -99,18 +91,6 @@ extern void nubus_sweep_video(void);
extern void mac_debug_init(void);
extern void mac_debugging_long(int, long);
-/* poweroff functions */
-extern void via_poweroff(void);
-extern void oss_poweroff(void);
-extern void adb_poweroff(void);
-extern void adb_hwreset(void);
-
-/* pram functions */
-extern __u32 via_read_time(void);
-extern void via_write_time(__u32);
-extern __u32 adb_read_time(void);
-extern void adb_write_time(__u32);
-
#ifdef CONFIG_MAGIC_SYSRQ
static char mac_sysrq_xlate[128] =
"\000sdfghzxcv\000bqwer" /* 0x00 - 0x0f */
@@ -140,186 +120,6 @@ static void mac_sched_init(void (*vector)(int, void *, struct pt_regs *))
extern int console_loglevel;
-/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
- * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
- * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
- *
- * [For the Julian calendar (which was used in Russia before 1917,
- * Britain & colonies before 1752, anywhere else before 1582,
- * and is still in use by some communities) leave out the
- * -year/100+year/400 terms, and add 10.]
- *
- * This algorithm was first published by Gauss (I think).
- *
- * WARNING: this function will overflow on 2106-02-07 06:28:16 on
- * machines were long is 32-bit! (However, as time_t is signed, we
- * will already get problems at other places on 2038-01-19 03:14:08)
- */
-static unsigned long mktime(unsigned int year, unsigned int mon,
- unsigned int day, unsigned int hour,
- unsigned int min, unsigned int sec)
-{
- if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
- mon += 12; /* Puts Feb last since it has leap day */
- year -= 1;
- }
- return (((
- (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
- year*365 - 719499
- )*24 + hour /* now have hours */
- )*60 + min /* now have minutes */
- )*60 + sec; /* finally seconds */
-}
-
-/*
- * This function translates seconds since 1970 into a proper date.
- *
- * Algorithm cribbed from glibc2.1, __offtime().
- */
-#define SECS_PER_MINUTE (60)
-#define SECS_PER_HOUR (SECS_PER_MINUTE * 60)
-#define SECS_PER_DAY (SECS_PER_HOUR * 24)
-
-static void unmktime(unsigned long time, long offset,
- int *yearp, int *monp, int *dayp,
- int *hourp, int *minp, int *secp)
-{
- /* How many days come before each month (0-12). */
- static const unsigned short int __mon_yday[2][13] =
- {
- /* Normal years. */
- { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
- /* Leap years. */
- { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
- };
- long int days, rem, y, wday, yday;
- const unsigned short int *ip;
-
- days = time / SECS_PER_DAY;
- rem = time % SECS_PER_DAY;
- rem += offset;
- while (rem < 0) {
- rem += SECS_PER_DAY;
- --days;
- }
- while (rem >= SECS_PER_DAY) {
- rem -= SECS_PER_DAY;
- ++days;
- }
- *hourp = rem / SECS_PER_HOUR;
- rem %= SECS_PER_HOUR;
- *minp = rem / SECS_PER_MINUTE;
- *secp = rem % SECS_PER_MINUTE;
- /* January 1, 1970 was a Thursday. */
- wday = (4 + days) % 7; /* Day in the week. Not currently used */
- if (wday < 0) wday += 7;
- y = 1970;
-
-#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
-#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
-#define __isleap(year) \
- ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
-
- while (days < 0 || days >= (__isleap (y) ? 366 : 365))
- {
- /* Guess a corrected year, assuming 365 days per year. */
- long int yg = y + days / 365 - (days % 365 < 0);
-
- /* Adjust DAYS and Y to match the guessed year. */
- days -= ((yg - y) * 365
- + LEAPS_THRU_END_OF (yg - 1)
- - LEAPS_THRU_END_OF (y - 1));
- y = yg;
- }
- *yearp = y - 1900;
- yday = days; /* day in the year. Not currently used. */
- ip = __mon_yday[__isleap(y)];
- for (y = 11; days < (long int) ip[y]; --y)
- continue;
- days -= ip[y];
- *monp = y;
- *dayp = days + 1; /* day in the month */
- return;
-}
-
-/*
- * Return the boot time for use in initializing the kernel clock.
- *
- * I'd like to read the hardware clock here but many machines read
- * the PRAM through ADB, and interrupts aren't initialized when this
- * is called so ADB obviously won't work.
- */
-
-static void mac_gettod(int *yearp, int *monp, int *dayp,
- int *hourp, int *minp, int *secp)
-{
- /* Yes the GMT bias is backwards. It looks like Penguin is
- screwing up the boottime it gives us... This works for me
- in Canada/Eastern but it might be wrong everywhere else. */
- unmktime(mac_bi_data.boottime, -mac_bi_data.gmtbias * 60,
- yearp, monp, dayp, hourp, minp, secp);
- /* For some reason this is off by one */
- *monp = *monp + 1;
-}
-
-/*
- * Read/write the hardware clock.
- */
-
-static int mac_hwclk(int op, struct hwclk_time *t)
-{
- unsigned long now;
-
- if (!op) { /* read */
- if (macintosh_config->adb_type == MAC_ADB_II) {
- now = via_read_time();
- } else if ((macintosh_config->adb_type == MAC_ADB_IISI) ||
- (macintosh_config->adb_type == MAC_ADB_CUDA)) {
- now = adb_read_time();
- } else if (macintosh_config->adb_type == MAC_ADB_IOP) {
- now = via_read_time();
- } else {
- now = MAC_TIME_OFFSET;
- }
-
- now -= MAC_TIME_OFFSET;
-
- t->wday = 0;
- unmktime(now, 0,
- &t->year, &t->mon, &t->day,
- &t->hour, &t->min, &t->sec);
- } else { /* write */
- now = mktime(t->year + 1900, t->mon + 1, t->day,
- t->hour, t->min, t->sec) + MAC_TIME_OFFSET;
-
- if (macintosh_config->adb_type == MAC_ADB_II) {
- via_write_time(now);
- } else if ((macintosh_config->adb_type == MAC_ADB_IISI) ||
- (macintosh_config->adb_type == MAC_ADB_CUDA)) {
- adb_write_time(now);
- } else if (macintosh_config->adb_type == MAC_ADB_IOP) {
- via_write_time(now);
- }
- }
- return 0;
-}
-
-/*
- * Set minutes/seconds in the hardware clock
- */
-
-static int mac_set_clock_mmss (unsigned long nowtime)
-{
- struct hwclk_time now;
-
- mac_hwclk(0, &now);
- now.sec = nowtime % 60;
- now.min = (nowtime / 60) % 60;
- mac_hwclk(1, &now);
-
- return 0;
-}
-
#if 0
void mac_waitbut (void)
{
@@ -330,9 +130,23 @@ void mac_waitbut (void)
extern struct consw fb_con;
extern struct fb_info *mac_fb_init(long *);
- /*
- * Parse a Macintosh-specific record in the bootinfo
- */
+extern void mac_default_handler(int, void *, struct pt_regs *);
+
+void (*mac_handlers[8])(int, void *, struct pt_regs *)=
+{
+ mac_default_handler,
+ mac_default_handler,
+ mac_default_handler,
+ mac_default_handler,
+ mac_default_handler,
+ mac_default_handler,
+ mac_default_handler,
+ mac_default_handler
+};
+
+/*
+ * Parse a Macintosh-specific record in the bootinfo
+ */
int __init mac_parse_bootinfo(const struct bi_record *record)
{
@@ -384,9 +198,9 @@ int __init mac_parse_bootinfo(const struct bi_record *record)
}
/*
- * Flip into 24bit mode for an instant - flushes the L2 cache card. We
- * have to disable interrupts for this. Our IRQ handlers will crap
- * themselves if they take an IRQ in 24bit mode!
+ * Flip into 24bit mode for an instant - flushes the L2 cache card. We
+ * have to disable interrupts for this. Our IRQ handlers will crap
+ * themselves if they take an IRQ in 24bit mode!
*/
static void mac_cache_card_flush(int writeback)
@@ -414,6 +228,8 @@ void __init config_mac(void)
enable_irq = mac_enable_irq;
disable_irq = mac_disable_irq;
mach_get_model = mac_get_model;
+ mach_default_handler = &mac_handlers;
+ mach_get_irq_list = mac_get_irq_list;
mach_gettimeoffset = mac_gettimeoffset;
mach_gettod = mac_gettod;
mach_hwclk = mac_hwclk;
@@ -489,7 +305,6 @@ struct mac_model *macintosh_config;
static struct mac_model mac_data_table[]=
{
/*
- * The default machine, in case we get an unsupported one
* We'll pretend to be a Macintosh II, that's pretty safe.
*/
@@ -509,10 +324,6 @@ static struct mac_model mac_data_table[]=
* Weirdified MacII hardware - all subtley different. Gee thanks
* Apple. All these boxes seem to have VIA2 in a different place to
* the MacII (+1A000 rather than +4000)
- *
- * The IIfx apparently has different ADB hardware, and stuff
- * so zany nobody knows how to drive it.
- * Even so, with Marten's help we'll try to deal with it :-)
* CSA: see http://developer.apple.com/technotes/hw/hw_09.html
*/
@@ -584,28 +395,33 @@ static struct mac_model mac_data_table[]=
{ MAC_MODEL_C660, "Centris 660AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_MACE, MAC_NUBUS},
/*
- * Power books - seem similar to early Quadras ? (most have 030 though)
+ * The PowerBooks all the same "Combo" custom IC for SCSI and SCC
+ * and a PMU (in two variations?) for ADB. Most of them use the
+ * Quadra-style VIAs. A few models also have IDE from hell.
*/
- { MAC_MODEL_PB140, "PowerBook 140", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB145, "PowerBook 145", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_NONE, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- /* The PB150 has IDE, and IIci style VIA */
- { MAC_MODEL_PB150, "PowerBook 150", MAC_ADB_PB1, MAC_VIA_IIci, MAC_SCSI_NONE, MAC_IDE_PB, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB160, "PowerBook 160", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_NONE, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB165, "PowerBook 165", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_NONE, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB165C, "PowerBook 165c", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_NONE, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB170, "PowerBook 170", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB180, "PowerBook 180", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_NONE, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB180C, "PowerBook 180c", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_NONE, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_PB190, "PowerBook 190cs", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_NONE, MAC_IDE_PB, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
- /* These have onboard SONIC */
- { MAC_MODEL_PB520, "PowerBook 520", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_NONE, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
+ { MAC_MODEL_PB140, "PowerBook 140", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB145, "PowerBook 145", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB150, "PowerBook 150", MAC_ADB_PB1, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_PB, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB160, "PowerBook 160", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB165, "PowerBook 165", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB165C, "PowerBook 165c", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB170, "PowerBook 170", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB180, "PowerBook 180", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB180C, "PowerBook 180c", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB190, "PowerBook 190", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_BABOON, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_PB520, "PowerBook 520", MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
/*
- * Power book Duos - similar to Power books, I hope
+ * PowerBook Duos are pretty much like normal PowerBooks
+ * All of these probably have onboard SONIC in the Dock which
+ * means we'll have to probe for it eventually.
+ *
+ * Are these reallly MAC_VIA_IIci? The developer notes for the
+ * Duos show pretty much the same custom parts as in most of
+ * the other PowerBooks which would imply MAC_VIA_QUADRA.
*/
- /* All of these might have onboard SONIC in the Dock but I'm not quite sure */
{ MAC_MODEL_PB210, "PowerBook Duo 210", MAC_ADB_PB2, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
{ MAC_MODEL_PB230, "PowerBook Duo 230", MAC_ADB_PB2, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
{ MAC_MODEL_PB250, "PowerBook Duo 250", MAC_ADB_PB2, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
@@ -694,6 +510,7 @@ void mac_identify(void)
via_init();
oss_init();
psc_init();
+ baboon_init();
}
void mac_report_hardware(void)
@@ -706,137 +523,3 @@ static void mac_get_model(char *str)
strcpy(str,"Macintosh ");
strcat(str, macintosh_config->name);
}
-
-/*
- * The power switch - yes it's software!
- */
-
-void mac_poweroff(void)
-{
- /*
- * MAC_ADB_IISI may need to be moved up here if it doesn't actually
- * work using the ADB packet method. --David Kilzer
- */
-
- if (oss_present) {
- oss_poweroff();
- } else if (macintosh_config->adb_type == MAC_ADB_II) {
- via_poweroff();
- } else {
- adb_poweroff();
- }
-}
-
-/*
- * Not all Macs support software power down; for the rest, just
- * try the ROM reset vector ...
- */
-void mac_reset(void)
-{
- /*
- * MAC_ADB_IISI may need to be moved up here if it doesn't actually
- * work using the ADB packet method. --David Kilzer
- */
-
- if (macintosh_config->adb_type == MAC_ADB_II) {
- unsigned long cpu_flags;
-
- /* need ROMBASE in booter */
- /* indeed, plus need to MAP THE ROM !! */
-
- if (mac_bi_data.rombase == 0)
- mac_bi_data.rombase = 0x40800000;
-
- /* works on some */
- rom_reset = (void *) (mac_bi_data.rombase + 0xa);
-
- if (macintosh_config->ident == MAC_MODEL_SE30) {
- /*
- * MSch: Machines known to crash on ROM reset ...
- */
- printk("System halted.\n");
- while(1);
- } else {
- save_flags(cpu_flags);
- cli();
-
- rom_reset();
-
- restore_flags(cpu_flags);
- }
-
- /* We never make it this far... it usually panics above. */
- printk ("Restart failed. Please restart manually.\n");
-
- /* XXX - delay do we need to spin here ? */
- while(1); /* Just in case .. */
- } else if (macintosh_config->adb_type == MAC_ADB_IISI
- || macintosh_config->adb_type == MAC_ADB_CUDA) {
- adb_hwreset();
- } else if (CPU_IS_030) {
-
- /* 030-specific reset routine. The idea is general, but the
- * specific registers to reset are '030-specific. Until I
- * have a non-030 machine, I can't test anything else.
- * -- C. Scott Ananian <cananian@alumni.princeton.edu>
- */
-
- unsigned long rombase = 0x40000000;
-
- /* make a 1-to-1 mapping, using the transparent tran. reg. */
- unsigned long virt = (unsigned long) mac_reset;
- unsigned long phys = virt_to_phys(mac_reset);
- unsigned long offset = phys-virt;
- cli(); /* lets not screw this up, ok? */
- __asm__ __volatile__(".chip 68030\n\t"
- "pmove %0,%/tt0\n\t"
- ".chip 68k"
- : : "m" ((phys&0xFF000000)|0x8777));
- /* Now jump to physical address so we can disable MMU */
- __asm__ __volatile__(
- ".chip 68030\n\t"
- "lea %/pc@(1f),%/a0\n\t"
- "addl %0,%/a0\n\t"/* fixup target address and stack ptr */
- "addl %0,%/sp\n\t"
- "pflusha\n\t"
- "jmp %/a0@\n\t" /* jump into physical memory */
- "0:.long 0\n\t" /* a constant zero. */
- /* OK. Now reset everything and jump to reset vector. */
- "1:\n\t"
- "lea %/pc@(0b),%/a0\n\t"
- "pmove %/a0@, %/tc\n\t" /* disable mmu */
- "pmove %/a0@, %/tt0\n\t" /* disable tt0 */
- "pmove %/a0@, %/tt1\n\t" /* disable tt1 */
- "movel #0, %/a0\n\t"
- "movec %/a0, %/vbr\n\t" /* clear vector base register */
- "movec %/a0, %/cacr\n\t" /* disable caches */
- "movel #0x0808,%/a0\n\t"
- "movec %/a0, %/cacr\n\t" /* flush i&d caches */
- "movew #0x2700,%/sr\n\t" /* set up status register */
- "movel %1@(0x0),%/a0\n\t"/* load interrupt stack pointer */
- "movec %/a0, %/isp\n\t"
- "movel %1@(0x4),%/a0\n\t" /* load reset vector */
- "reset\n\t" /* reset external devices */
- "jmp %/a0@\n\t" /* jump to the reset vector */
- ".chip 68k"
- : : "r" (offset), "a" (rombase) : "a0");
-
- /* should never get here */
- sti(); /* sure, why not */
- printk ("030 Restart failed. Please restart manually.\n");
- while(1);
- } else {
- /* We never make it here... The above shoule handle all cases. */
- printk ("Restart failed. Please restart manually.\n");
-
- /* XXX - delay do we need to spin here ? */
- while(1); /* Just in case .. */
- }
-}
-
-/*
- * Local variables:
- * c-indent-level: 4
- * tab-width: 8
- * End:
- */
diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c
index 21969ce6f..3163e3ea3 100644
--- a/arch/m68k/mac/iop.c
+++ b/arch/m68k/mac/iop.c
@@ -319,7 +319,7 @@ void __init iop_register_interrupts(void)
{
if (iop_ism_present) {
if (oss_present) {
- request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
+ sys_request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
IRQ_FLG_LOCK, "ISM IOP",
(void *) IOP_NUM_ISM);
oss_irq_enable(IRQ_MAC_ADB);
diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c
index a795d82ed..febba1982 100644
--- a/arch/m68k/mac/macints.c
+++ b/arch/m68k/mac/macints.c
@@ -35,8 +35,8 @@
* 3 - unused (?)
*
* 4 - SCC (slot number determined by reading RR3 on the SSC itself)
- * - slot 0: SCC channel A
- * - slot 1: SCC channel B
+ * - slot 1: SCC channel A
+ * - slot 2: SCC channel B
*
* 5 - unused (?)
* [serial errors or special conditions seem to raise level 6
@@ -55,8 +55,8 @@
* - slot 5: Slot $E
*
* 4 - SCC IOP
- * - slot 0: SCC channel A
- * - slot 1: SCC channel B
+ * - slot 1: SCC channel A
+ * - slot 2: SCC channel B
*
* 5 - ISM IOP (ADB?)
*
@@ -100,19 +100,18 @@
* bits. The handlers for this new machspec interrupt number are then
* called. This puts Nubus interrupts into the range 56-62.
*
+ * - The Baboon interrupts (used on some PowerBooks) are an even more special
+ * case. They're hidden behind the Nubus slot $C interrupt thus adding a
+ * third layer of indirection. Why oh why did the Apple engineers do that?
+ *
* - We support "fast" and "slow" handlers, just like the Amiga port. The
* fast handlers are called first and with all interrupts disabled. They
* are expected to execute quickly (hence the name). The slow handlers are
* called last with interrupts enabled and the interrupt level restored.
* They must therefore be reentrant.
*
- * - Drivers should never try to request autovector interrupt numbers. It
- * won't work.
- *
* TODO:
*
- * o Perhaps build some intelligence into mac_SCC_handler(); we could check
- * the SCC ourselves and only call the handler for the appopriate channel.
*/
#include <linux/types.h>
@@ -125,6 +124,7 @@
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/traps.h>
+#include <asm/bootinfo.h>
#include <asm/machw.h>
#include <asm/macintosh.h>
#include <asm/mac_via.h>
@@ -133,6 +133,18 @@
#include <asm/macints.h>
/*
+ * The mac_irq_list array is an array of linked lists of irq_node_t nodes.
+ * Each node contains one handler to be called whenever the interrupt
+ * occurs, with fast handlers listed before slow handlers.
+ */
+
+irq_node_t *mac_irq_list[NUM_MAC_SOURCES];
+
+/* SCC interrupt mask */
+
+static int scc_mask;
+
+/*
* VIA/RBV hooks
*/
@@ -176,6 +188,26 @@ extern int psc_irq_pending(int);
extern void iop_register_interrupts(void);
/*
+ * Baboon hooks
+ */
+
+extern int baboon_present;
+
+extern void baboon_init(void);
+extern void baboon_register_interrupts(void);
+extern void baboon_irq_enable(int);
+extern void baboon_irq_disable(int);
+extern void baboon_irq_clear(int);
+extern int baboon_irq_pending(int);
+
+/*
+ * SCC interrupt routines
+ */
+
+static void scc_irq_enable(int);
+static void scc_irq_disable(int);
+
+/*
* console_loglevel determines NMI handler function
*/
@@ -184,17 +216,27 @@ extern int console_loglevel;
extern void mac_bang(int, void *, struct pt_regs *);
void mac_nmi_handler(int, void *, struct pt_regs *);
-void mac_SCC_handler(int, void *, struct pt_regs *);
+void mac_debug_handler(int, void *, struct pt_regs *);
/* #define DEBUG_MACINTS */
void mac_init_IRQ(void)
{
+ int i;
+
#ifdef DEBUG_MACINTS
printk("mac_init_IRQ(): Setting things up...\n");
#endif
+ /* Initialize the IRQ handler lists. Initially each list is empty, */
+
+ for (i = 0; i < NUM_MAC_SOURCES; i++) {
+ mac_irq_list[i] = NULL;
+ }
+
+ scc_mask = 0;
+
/*
- * Register the handlers for the the master IRQ handlers
+ * Now register the handlers for the the master IRQ handlers
* at levels 1-7. Most of the work is done elsewhere.
*/
@@ -204,8 +246,9 @@ void mac_init_IRQ(void)
via_register_interrupts();
}
if (psc_present) psc_register_interrupts();
+ if (baboon_present) baboon_register_interrupts();
iop_register_interrupts();
- request_irq(7, mac_nmi_handler, IRQ_FLG_LOCK, "NMI", mac_nmi_handler);
+ sys_request_irq(7, mac_nmi_handler, IRQ_FLG_LOCK, "NMI", mac_nmi_handler);
#ifdef DEBUG_MACINTS
printk("mac_init_IRQ(): Done!\n");
#endif
@@ -284,27 +327,20 @@ static inline void mac_delete_irq(irq_node_t **list, void *dev_id)
void mac_do_irq_list(int irq, struct pt_regs *fp)
{
- irq_node_t *node, *slow_nodes, **list = NULL;
+ irq_node_t *node, *slow_nodes;
unsigned long cpu_flags;
kstat.irqs[0][irq]++;
- if (irq < VIA1_SOURCE_BASE) {
- list = &autoirq_list[irq];
- } else if (irq < NUM_MAC_SOURCES) {
- list = &userirq_list[irq - VIA1_SOURCE_BASE];
- }
- if (!list) return;
-
#ifdef DEBUG_SPURIOUS
- if (!*list && (console_loglevel > 7)) {
+ if (!mac_irq_list[irq] && (console_loglevel > 7)) {
printk("mac_do_irq_list: spurious interrupt %d!\n", irq);
return;
}
#endif
/* serve first fast and normal handlers */
- for (node = *list;
+ for (node = mac_irq_list[irq];
node && (!(node->flags & IRQ_FLG_SLOW));
node = node->next)
node->handler(irq, node->dev_id, fp);
@@ -329,7 +365,9 @@ void mac_do_irq_list(int irq, struct pt_regs *fp)
void mac_enable_irq (unsigned int irq)
{
- switch(IRQ_SRC(irq)) {
+ int irq_src = IRQ_SRC(irq);
+
+ switch(irq_src) {
case 1: via_irq_enable(irq);
break;
case 2:
@@ -346,6 +384,12 @@ void mac_enable_irq (unsigned int irq)
psc_irq_enable(irq);
} else if (oss_present) {
oss_irq_enable(irq);
+ } else if (irq_src == 4) {
+ scc_irq_enable(irq);
+ }
+ break;
+ case 8: if (baboon_present) {
+ baboon_irq_enable(irq);
}
break;
}
@@ -353,12 +397,13 @@ void mac_enable_irq (unsigned int irq)
void mac_disable_irq (unsigned int irq)
{
- switch(IRQ_SRC(irq)) {
+ int irq_src = IRQ_SRC(irq);
+
+ switch(irq_src) {
case 1: via_irq_disable(irq);
break;
case 2:
- case 7:
- if (oss_present) {
+ case 7: if (oss_present) {
oss_irq_disable(irq);
} else {
via_irq_disable(irq);
@@ -371,6 +416,12 @@ void mac_disable_irq (unsigned int irq)
psc_irq_disable(irq);
} else if (oss_present) {
oss_irq_disable(irq);
+ } else if (irq_src == 4) {
+ scc_irq_disable(irq);
+ }
+ break;
+ case 8: if (baboon_present) {
+ baboon_irq_disable(irq);
}
break;
}
@@ -397,6 +448,10 @@ void mac_clear_irq( unsigned int irq )
oss_irq_clear(irq);
}
break;
+ case 8: if (baboon_present) {
+ baboon_irq_clear(irq);
+ }
+ break;
}
}
@@ -434,29 +489,37 @@ int mac_request_irq(unsigned int irq,
void (*handler)(int, void *, struct pt_regs *),
unsigned long flags, const char *devname, void *dev_id)
{
- int vec, ret;
+ irq_node_t *node;
#ifdef DEBUG_MACINTS
printk ("%s: irq %d requested for %s\n", __FUNCTION__, irq, devname);
#endif
if (irq < VIA1_SOURCE_BASE) {
- vec = VEC_SPUR + irq;
- } else if (irq < NUM_MAC_SOURCES) {
- vec = VEC_USER + irq - VIA1_SOURCE_BASE;
- } else {
+ return sys_request_irq(irq, handler, flags, devname, dev_id);
+ }
+
+ if (irq >= NUM_MAC_SOURCES) {
printk ("%s: unknown irq %d requested by %s\n",
__FUNCTION__, irq, devname);
- return -EAGAIN;
}
- ret = sys_request_listirq(vec, handler, flags, devname, dev_id);
- if (!ret) {
- vectors[vec] = autoirq_listhandler;
- mac_enable_irq(irq);
- }
+ /* Get a node and stick it onto the right list */
+
+ if (!(node = new_irq_node())) return -ENOMEM;
+
+ node->handler = handler;
+ node->flags = flags;
+ node->dev_id = dev_id;
+ node->devname = devname;
+ node->next = NULL;
+ mac_insert_irq(&mac_irq_list[irq], node);
+
+ /* Now enable the IRQ source */
+
+ mac_enable_irq(irq);
- return ret;
+ return 0;
}
/*
@@ -465,30 +528,120 @@ int mac_request_irq(unsigned int irq,
void mac_free_irq(unsigned int irq, void *dev_id)
{
- irq_node_t **list = NULL;
- int vec = 0;
-
#ifdef DEBUG_MACINTS
printk ("%s: irq %d freed by %p\n", __FUNCTION__, irq, dev_id);
#endif
if (irq < VIA1_SOURCE_BASE) {
- vec = VEC_SPUR + irq;
- list = &autoirq_list[irq];
- } else if (irq < NUM_MAC_SOURCES) {
- vec = VEC_USER + irq - VIA1_SOURCE_BASE;
- list = &userirq_list[irq - VIA1_SOURCE_BASE];
+ return sys_free_irq(irq, dev_id);
+ }
+
+ if (irq >= NUM_MAC_SOURCES) {
+ printk ("%s: unknown irq %d freed\n",
+ __FUNCTION__, irq);
+ return;
}
- if (!list) return;
- sys_free_irq(vec, dev_id);
+ mac_delete_irq(&mac_irq_list[irq], dev_id);
/* If the list for this interrupt is */
/* empty then disable the source. */
- if (!*list) {
+ if (!mac_irq_list[irq]) {
mac_disable_irq(irq);
- vectors[vec] = bad_interrupt;
+ }
+}
+
+/*
+ * Generate a pretty listing for /proc/interrupts
+ *
+ * By the time we're called the autovector interrupt list has already been
+ * generated, so we just need to do the machspec interrupts.
+ *
+ * 990506 (jmt) - rewritten to handle chained machspec interrupt handlers.
+ * Also removed display of num_spurious it is already
+ * displayed for us as autovector irq 0.
+ */
+
+int mac_get_irq_list (char *buf)
+{
+ int i, len = 0;
+ irq_node_t *node;
+ char *base;
+
+ /* Don't do Nubus interrupts in this loop; we do them separately */
+ /* below so that we can print slot numbers instead of IRQ numbers */
+
+ for (i = VIA1_SOURCE_BASE ; i < NUM_MAC_SOURCES ; ++i) {
+
+ /* Nonexistant interrupt or nothing registered; skip it. */
+
+ if ((node = mac_irq_list[i]) == NULL) continue;
+ if (node->flags & IRQ_FLG_STD) continue;
+
+ base = "";
+ switch(IRQ_SRC(i)) {
+ case 1: base = "via1";
+ break;
+ case 2: if (oss_present) {
+ base = "oss";
+ } else {
+ base = "via2";
+ }
+ break;
+ case 3:
+ case 4:
+ case 5:
+ case 6: if (psc_present) {
+ base = "psc";
+ } else if (oss_present) {
+ base = "oss";
+ } else {
+ if (IRQ_SRC(i) == 4) base = "scc";
+ }
+ break;
+ case 7: base = "nbus";
+ break;
+ case 8: base = "bbn";
+ break;
+ }
+ len += sprintf(buf+len, "%4s %2d: %10u ",
+ base, i, kstat.irqs[0][i]);
+
+ do {
+ if (node->flags & IRQ_FLG_FAST) {
+ len += sprintf(buf+len, "F ");
+ } else if (node->flags & IRQ_FLG_SLOW) {
+ len += sprintf(buf+len, "S ");
+ } else {
+ len += sprintf(buf+len, " ");
+ }
+ len += sprintf(buf+len, "%s\n", node->devname);
+ if ((node = node->next)) {
+ len += sprintf(buf+len, " ");
+ }
+ } while(node);
+
+ }
+ return len;
+}
+
+void mac_default_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+#ifdef DEBUG_SPURIOUS
+ if (console_loglevel > 6) {
+ printk("Unexpected IRQ %d on device %p\n", irq, dev_id);
+ }
+#endif
+}
+
+static int num_debug[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+void mac_debug_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+ if (num_debug[irq] < 10) {
+ printk("DEBUG: Unexpected IRQ %d\n", irq);
+ num_debug[irq]++;
}
}
@@ -543,12 +696,53 @@ void mac_nmi_handler(int irq, void *dev_id, struct pt_regs *fp)
}
/*
- * SCC master interrupt handler; sole purpose: pass the registered
- * async struct to the SCC handler proper.
+ * Simple routines for masking and unmasking
+ * SCC interrupts in cases where this can't be
+ * done in hardware (only the PSC can do that.)
+ */
+
+static void scc_irq_enable(int irq) {
+ int irq_idx = IRQ_IDX(irq);
+
+ scc_mask |= (1 << irq_idx);
+}
+
+static void scc_irq_disable(int irq) {
+ int irq_idx = IRQ_IDX(irq);
+
+ scc_mask &= ~(1 << irq_idx);
+}
+
+/*
+ * SCC master interrupt handler. We have to do a bit of magic here
+ * to figure out what channel gave us the interrupt; putting this
+ * here is cleaner than hacking it into drivers/char/macserial.c.
*/
-void mac_SCC_handler(int irq, void *dev_id, struct pt_regs *regs)
+void mac_scc_dispatch(int irq, void *dev_id, struct pt_regs *regs)
{
- mac_do_irq_list(IRQ_SCCA, regs);
- mac_do_irq_list(IRQ_SCCB, regs);
+ volatile unsigned char *scc = (unsigned char *) mac_bi_data.sccbase + 2;
+ unsigned char reg;
+ unsigned long cpu_flags;
+
+ /* Read RR3 from the chip. Always do this on channel A */
+ /* This must be an atomic operation so disable irqs. */
+
+ save_flags(cpu_flags); cli();
+ *scc = 3;
+ reg = *scc;
+ restore_flags(cpu_flags);
+
+ /* Now dispatch. Bits 0-2 are for channel B and */
+ /* bits 3-5 are for channel A. We can safely */
+ /* ignore the remaining bits here. */
+ /* */
+ /* Note that we're ignoring scc_mask for now. */
+ /* If we actually mask the ints then we tend to */
+ /* get hammered by very persistant SCC irqs, */
+ /* and since they're autovector interrupts they */
+ /* pretty much kill the system. */
+
+ if (reg & 0x38) mac_do_irq_list(IRQ_SCCA, regs);
+ if (reg & 0x07) mac_do_irq_list(IRQ_SCCB, regs);
}
diff --git a/arch/m68k/mac/mackeyb.c b/arch/m68k/mac/mackeyb.c
deleted file mode 100644
index 0d70357dc..000000000
--- a/arch/m68k/mac/mackeyb.c
+++ /dev/null
@@ -1,762 +0,0 @@
-/*
- * linux/arch/m68k/mac/mackeyb.c
- *
- * Keyboard driver for Macintosh computers.
- *
- * Adapted from drivers/macintosh/key_mac.c and arch/m68k/atari/akakeyb.c
- * (see that file for its authors and contributors).
- *
- * Copyright (C) 1997 Michael Schmitz.
- *
- * 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.
- */
-
-/*
- * misc. keyboard stuff (everything not in adb-bus.c or keyb_m68k.c)
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/kd.h>
-#include <linux/tty.h>
-#include <linux/console.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-/* keyb */
-#include <linux/keyboard.h>
-#include <linux/random.h>
-#include <linux/delay.h>
-/* keyb */
-
-#include <asm/setup.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/machdep.h>
-
-#include <asm/macintosh.h>
-#include <asm/macints.h>
-/* for keyboard_input stuff */
-#include <asm/adb.h>
-#define KEYB_KEYREG 0 /* register # for key up/down data */
-#define KEYB_LEDREG 2 /* register # for leds on ADB keyboard */
-#define MOUSE_DATAREG 0 /* reg# for movement/button codes from mouse */
-/* end keyboard_input stuff */
-
-#include <linux/kbd_kern.h>
-#include <linux/kbd_ll.h>
-
-static void kbd_repeat(unsigned long);
-static struct timer_list repeat_timer = { NULL, NULL, 0, 0, kbd_repeat };
-static int last_keycode;
-
-static void input_keycode(int, int);
-
-extern struct kbd_struct kbd_table[];
-
-extern void adb_bus_init(void);
-extern void handle_scancode(unsigned char, int);
-extern void put_queue(int);
-
-/* keyb */
-static void mac_leds_done(struct adb_request *);
-static void keyboard_input(unsigned char *, int, struct pt_regs *);
-static void mouse_input(unsigned char *, int, struct pt_regs *);
-
-#ifdef CONFIG_ADBMOUSE
-/* XXX: Hook for mouse driver */
-void (*adb_mouse_interrupt_hook)(unsigned char *, int);
-int adb_emulate_buttons = 0;
-int adb_button2_keycode = 0x7d; /* right control key */
-int adb_button3_keycode = 0x7c; /* right option key */
-#endif
-
-/* The mouse driver - for debugging */
-extern void adb_mouse_interrupt(char *, int);
-/* end keyb */
-
-/* this map indicates which keys shouldn't autorepeat. */
-static unsigned char dont_repeat[128] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* esc...option */
- 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /* num lock */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, /* scroll lock */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-/*
- * Mac private key maps
- */
-u_short mac_plain_map[NR_KEYS] __initdata = {
- 0xfb61, 0xfb73, 0xfb64, 0xfb66, 0xfb68, 0xfb67, 0xfb7a, 0xfb78,
- 0xfb63, 0xfb76, 0xf200, 0xfb62, 0xfb71, 0xfb77, 0xfb65, 0xfb72,
- 0xfb79, 0xfb74, 0xf031, 0xf032, 0xf033, 0xf034, 0xf036, 0xf035,
- 0xf03d, 0xf039, 0xf037, 0xf02d, 0xf038, 0xf030, 0xf05d, 0xfb6f,
- 0xfb75, 0xf05b, 0xfb69, 0xfb70, 0xf201, 0xfb6c, 0xfb6a, 0xf027,
- 0xfb6b, 0xf03b, 0xf05c, 0xf02c, 0xf02f, 0xfb6e, 0xfb6d, 0xf02e,
- 0xf009, 0xf020, 0xf060, 0xf07f, 0xf200, 0xf01b, 0xf702, 0xf703,
- 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200,
- 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208,
- 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200,
- 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305,
- 0xf306, 0xf307, 0xfb61, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200,
- 0xf104, 0xf105, 0xf106, 0xf102, 0xf107, 0xf108, 0xf200, 0xf10a,
- 0xf200, 0xf10c, 0xf200, 0xf209, 0xf200, 0xf109, 0xf200, 0xf10b,
- 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf103, 0xf117,
- 0xf101, 0xf119, 0xf100, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-};
-
-u_short mac_shift_map[NR_KEYS] __initdata = {
- 0xfb41, 0xfb53, 0xfb44, 0xfb46, 0xfb48, 0xfb47, 0xfb5a, 0xfb58,
- 0xfb43, 0xfb56, 0xf200, 0xfb42, 0xfb51, 0xfb57, 0xfb45, 0xfb52,
- 0xfb59, 0xfb54, 0xf021, 0xf040, 0xf023, 0xf024, 0xf05e, 0xf025,
- 0xf02b, 0xf028, 0xf026, 0xf05f, 0xf02a, 0xf029, 0xf07d, 0xfb4f,
- 0xfb55, 0xf07b, 0xfb49, 0xfb50, 0xf201, 0xfb4c, 0xfb4a, 0xf022,
- 0xfb4b, 0xf03a, 0xf07c, 0xf03c, 0xf03f, 0xfb4e, 0xfb4d, 0xf03e,
- 0xf009, 0xf020, 0xf07e, 0xf07f, 0xf200, 0xf01b, 0xf702, 0xf703,
- 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200,
- 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208,
- 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200,
- 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305,
- 0xf306, 0xf307, 0xfb41, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200,
- 0xf10e, 0xf10f, 0xf110, 0xf10c, 0xf111, 0xf112, 0xf200, 0xf10a,
- 0xf200, 0xf10c, 0xf200, 0xf203, 0xf200, 0xf113, 0xf200, 0xf10b,
- 0xf200, 0xf11d, 0xf115, 0xf114, 0xf20b, 0xf116, 0xf10d, 0xf117,
- 0xf10b, 0xf20a, 0xf10a, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-};
-
-u_short mac_altgr_map[NR_KEYS] __initdata = {
- 0xf914, 0xfb73, 0xf917, 0xf919, 0xfb68, 0xfb67, 0xfb7a, 0xfb78,
- 0xf916, 0xfb76, 0xf200, 0xf915, 0xfb71, 0xfb77, 0xf918, 0xfb72,
- 0xfb79, 0xfb74, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200,
- 0xf200, 0xf05d, 0xf07b, 0xf05c, 0xf05b, 0xf07d, 0xf07e, 0xfb6f,
- 0xfb75, 0xf200, 0xfb69, 0xfb70, 0xf201, 0xfb6c, 0xfb6a, 0xf200,
- 0xfb6b, 0xf200, 0xf200, 0xf200, 0xf200, 0xfb6e, 0xfb6d, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, 0xf703,
- 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200,
- 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208,
- 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200,
- 0xf200, 0xf200, 0xf90a, 0xf90b, 0xf90c, 0xf90d, 0xf90e, 0xf90f,
- 0xf910, 0xf911, 0xf914, 0xf912, 0xf913, 0xf200, 0xf200, 0xf200,
- 0xf510, 0xf511, 0xf512, 0xf50e, 0xf513, 0xf514, 0xf200, 0xf516,
- 0xf200, 0xf10c, 0xf200, 0xf202, 0xf200, 0xf515, 0xf200, 0xf517,
- 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf50f, 0xf117,
- 0xf50d, 0xf119, 0xf50c, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-};
-
-u_short mac_ctrl_map[NR_KEYS] __initdata = {
- 0xf001, 0xf013, 0xf004, 0xf006, 0xf008, 0xf007, 0xf01a, 0xf018,
- 0xf003, 0xf016, 0xf200, 0xf002, 0xf011, 0xf017, 0xf005, 0xf012,
- 0xf019, 0xf014, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01e, 0xf01d,
- 0xf200, 0xf200, 0xf01f, 0xf01f, 0xf07f, 0xf200, 0xf01d, 0xf00f,
- 0xf015, 0xf01b, 0xf009, 0xf010, 0xf201, 0xf00c, 0xf00a, 0xf007,
- 0xf00b, 0xf200, 0xf01c, 0xf200, 0xf07f, 0xf00e, 0xf00d, 0xf20e,
- 0xf200, 0xf000, 0xf000, 0xf008, 0xf200, 0xf200, 0xf702, 0xf703,
- 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200,
- 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208,
- 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200,
- 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305,
- 0xf306, 0xf307, 0xf001, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200,
- 0xf104, 0xf105, 0xf106, 0xf102, 0xf107, 0xf108, 0xf200, 0xf10a,
- 0xf200, 0xf10c, 0xf200, 0xf204, 0xf200, 0xf109, 0xf200, 0xf10b,
- 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf103, 0xf117,
- 0xf101, 0xf119, 0xf100, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-};
-
-u_short mac_shift_ctrl_map[NR_KEYS] __initdata = {
- 0xf001, 0xf013, 0xf004, 0xf006, 0xf008, 0xf007, 0xf01a, 0xf018,
- 0xf003, 0xf016, 0xf200, 0xf002, 0xf011, 0xf017, 0xf005, 0xf012,
- 0xf019, 0xf014, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200, 0xf00f,
- 0xf015, 0xf200, 0xf009, 0xf010, 0xf201, 0xf00c, 0xf00a, 0xf200,
- 0xf00b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf00e, 0xf00d, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, 0xf703,
- 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200,
- 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208,
- 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200,
- 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305,
- 0xf306, 0xf307, 0xf001, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf10c, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf200, 0xf117,
- 0xf200, 0xf119, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf20c,
-};
-
-u_short mac_alt_map[NR_KEYS] __initdata = {
- 0xf861, 0xf873, 0xf864, 0xf866, 0xf868, 0xf867, 0xf87a, 0xf878,
- 0xf863, 0xf876, 0xf200, 0xf862, 0xf871, 0xf877, 0xf865, 0xf872,
- 0xf879, 0xf874, 0xf831, 0xf832, 0xf833, 0xf834, 0xf836, 0xf835,
- 0xf83d, 0xf839, 0xf837, 0xf82d, 0xf838, 0xf830, 0xf85d, 0xf86f,
- 0xf875, 0xf85b, 0xf869, 0xf870, 0xf80d, 0xf86c, 0xf86a, 0xf827,
- 0xf86b, 0xf83b, 0xf85c, 0xf82c, 0xf82f, 0xf86e, 0xf86d, 0xf82e,
- 0xf809, 0xf820, 0xf860, 0xf87f, 0xf200, 0xf81b, 0xf702, 0xf703,
- 0xf700, 0xf207, 0xf701, 0xf210, 0xf211, 0xf600, 0xf603, 0xf200,
- 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208,
- 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200,
- 0xf200, 0xf200, 0xf900, 0xf901, 0xf902, 0xf903, 0xf904, 0xf905,
- 0xf906, 0xf907, 0xf861, 0xf908, 0xf909, 0xf200, 0xf200, 0xf200,
- 0xf504, 0xf505, 0xf506, 0xf502, 0xf507, 0xf508, 0xf200, 0xf50a,
- 0xf200, 0xf10c, 0xf200, 0xf209, 0xf200, 0xf509, 0xf200, 0xf50b,
- 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf503, 0xf117,
- 0xf501, 0xf119, 0xf500, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-};
-
-u_short mac_ctrl_alt_map[NR_KEYS] __initdata = {
- 0xf801, 0xf813, 0xf804, 0xf806, 0xf808, 0xf807, 0xf81a, 0xf818,
- 0xf803, 0xf816, 0xf200, 0xf802, 0xf811, 0xf817, 0xf805, 0xf812,
- 0xf819, 0xf814, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf80f,
- 0xf815, 0xf200, 0xf809, 0xf810, 0xf201, 0xf80c, 0xf80a, 0xf200,
- 0xf80b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf80e, 0xf80d, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf702, 0xf703,
- 0xf700, 0xf207, 0xf701, 0xf601, 0xf602, 0xf600, 0xf603, 0xf200,
- 0xf200, 0xf310, 0xf200, 0xf30c, 0xf200, 0xf30a, 0xf200, 0xf208,
- 0xf200, 0xf200, 0xf200, 0xf30d, 0xf30e, 0xf200, 0xf30b, 0xf200,
- 0xf200, 0xf200, 0xf300, 0xf301, 0xf302, 0xf303, 0xf304, 0xf305,
- 0xf306, 0xf307, 0xf801, 0xf308, 0xf309, 0xf200, 0xf200, 0xf200,
- 0xf504, 0xf505, 0xf506, 0xf502, 0xf507, 0xf508, 0xf200, 0xf50a,
- 0xf200, 0xf10c, 0xf200, 0xf200, 0xf200, 0xf509, 0xf200, 0xf50b,
- 0xf200, 0xf11d, 0xf115, 0xf114, 0xf118, 0xf116, 0xf503, 0xf117,
- 0xf501, 0xf119, 0xf500, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
-};
-
-extern unsigned int keymap_count;
-
-/*
- * Misc. defines for testing
- */
-
-extern int console_loglevel;
-
-static struct adb_request led_request;
-extern int in_keybinit;
-
-/*
- * machdep keyboard routines, interface and key repeat method modeled after
- * drivers/macintosh/keyb_mac.c
- */
-
-int mac_kbd_translate(unsigned char keycode, unsigned char *keycodep,
- char raw_mode)
-{
- if (!raw_mode) {
- /*
- * Convert R-shift/control/option to L version.
- * Remap keycode 0 (A) to the unused keycode 0x5a.
- * Other parts of the system assume 0 is not a valid keycode.
- */
- switch (keycode) {
- case 0x7b: keycode = 0x38; break; /* R-shift */
- case 0x7c: keycode = 0x3a; break; /* R-option */
- case 0x7d: keycode = 0x36; break; /* R-control */
- case 0: keycode = 0x5a; break; /* A */
- }
- }
- *keycodep = keycode;
- return 1;
-}
-
-int mac_kbd_unexpected_up(unsigned char keycode)
-{
- return 0x80;
-}
-
-static void
-keyboard_input(unsigned char *data, int nb, struct pt_regs *regs)
-{
- /* first check this is from register 0 */
- if (nb != 5 || (data[2] & 3) != KEYB_KEYREG)
- return; /* ignore it */
- kbd_pt_regs = regs;
- input_keycode(data[3], 0);
- if (!(data[4] == 0xff || (data[4] == 0x7f && data[3] == 0x7f)))
- input_keycode(data[4], 0);
-}
-
-static void
-input_keycode(int keycode, int repeat)
-{
- struct kbd_struct *kbd;
- int up_flag;
-
- kbd = kbd_table + fg_console;
- up_flag = (keycode & 0x80);
- keycode &= 0x7f;
-
- if (!repeat)
- del_timer(&repeat_timer);
-
-#ifdef CONFIG_ADBMOUSE
- /*
- * XXX: Add mouse button 2+3 fake codes here if mouse open.
- * As we only report up/down events, keep track of faked buttons.
- * Really messy; might need to check if keyboard is in
- * VC_RAW mode for X?.
- * Might also want to know how many buttons need to be emulated.
- * -> hide this as function in arch/m68k/mac ?
- * Current emulation buttons: right alt/option and control
- * (wanted: command and alt/option, or KP= and KP( ...)
- * Debug version; might be rewritten to be faster on normal keys.
- */
- if (adb_emulate_buttons
- && (adb_mouse_interrupt_hook || console_loglevel >= 8)) {
- unsigned char button, button2, button3, fake_event;
- static unsigned char button2state=0, button3state=0; /* up */
- /* faked ADB packet */
- static unsigned char data[4] = { 0, 0x80, 0x80, 0x80 };
-
- button = 0;
- fake_event = 0;
- if (keycode == adb_button2_keycode) { /* which 'button' ? */
- /* R-option */
- button2 = (!up_flag); /* new state */
- if (button2 != button2state) /* change ? */
- button = 2;
- button2state = button2; /* save state */
- fake_event = 2;
- } else if (keycode == adb_button3_keycode) {
- /* R-control */
- button3 = (!up_flag); /* new state */
- if (button3 != button3state) /* change ? */
- button = 3;
- button3state = button3; /* save state */
- fake_event = 3;
- }
-#ifdef DEBUG_ADBMOUSE
- if (fake_event && console_loglevel >= 8)
- printk("fake event: button2 %d button3 %d button %d\n",
- button2state, button3state, button);
-#endif
- if (button) { /* there's been a button state change */
- /* fake a mouse packet : send all bytes, change one! */
- data[button] = (up_flag ? 0x80 : 0);
- if (adb_mouse_interrupt_hook)
- adb_mouse_interrupt_hook(data, 4);
-#ifdef DEBUG_ADBMOUSE
- else
- printk("mouse_fake: data %2x %2x %2x buttons %2x \n",
- data[1], data[2], data[3],
- ~( (data[1] & 0x80 ? 0 : 4)
- | (data[2] & 0x80 ? 0 : 1)
- | (data[3] & 0x80 ? 0 : 2) )&7 );
-#endif
- }
- /*
- * for mouse 3-button emulation: don't process 'fake' keys!
- * Keys might autorepeat, and console state gets generally messed
- * up enough so that selection stops working.
- */
- if (fake_event)
- return;
- }
-#endif /* CONFIG_ADBMOUSE */
-
- /*
- * Convert R-shift/control/option to L version.
- */
- switch (keycode) {
- case 0x7b: keycode = 0x38; break; /* R-shift */
- case 0x7c: keycode = 0x3a; break; /* R-option */
- case 0x7d: keycode = 0x36; break; /* R-control */
- case 0x0: if (kbd->kbdmode != VC_RAW)
- keycode = 0x5a; /* A; keycode 0 deprecated */
- break;
- }
-
- if (kbd->kbdmode != VC_RAW) {
- if (!up_flag && !dont_repeat[keycode]) {
- last_keycode = keycode;
- repeat_timer.expires = jiffies + (repeat? HZ/15: HZ/2);
- add_timer(&repeat_timer);
- }
-
- /*
- * XXX fix caps-lock behaviour by turning the key-up
- * transition into a key-down transition.
- * MSch: need to turn each caps-lock event into a down-up
- * double event (keyboard code assumes caps-lock is a toggle)
- * 981127: fix LED behavior (kudos atong!)
- */
- switch (keycode) {
- case 0x39:
- handle_scancode(keycode, 1); /* down */
- up_flag = 0x80; /* see below ... */
- mark_bh(KEYBOARD_BH);
- break;
- case 0x47:
- mark_bh(KEYBOARD_BH);
- break;
- }
- }
-
- handle_scancode(keycode, !up_flag);
-}
-
-static void
-kbd_repeat(unsigned long xxx)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
- input_keycode(last_keycode, 1);
- restore_flags(flags);
-}
-
- /* [ACA:23-Mar-97] Three button mouse support. This is designed to
- function with MkLinux DR-2.1 style X servers. It only works with
- three-button mice that conform to Apple's multi-button mouse
- protocol. */
-
- /*
- The X server for MkLinux DR2.1 uses the following unused keycodes to
- read the mouse:
-
- 0x7e This indicates that the next two keycodes should be interpreted
- as mouse information. The first following byte's high bit
- represents the state of the left button. The lower seven bits
- represent the x-axis acceleration. The lower seven bits of the
- second byte represent y-axis acceleration.
-
- 0x3f The x server interprets this keycode as a middle button
- release.
-
- 0xbf The x server interprets this keycode as a middle button
- depress.
-
- 0x40 The x server interprets this keycode as a right button
- release.
-
- 0xc0 The x server interprets this keycode as a right button
- depress.
-
- NOTES: There should be a better way of handling mice in the X server.
- The MOUSE_ESCAPE code (0x7e) should be followed by three bytes instead
- of two. The three mouse buttons should then, in the X server, be read
- as the high-bits of all three bytes. The x and y motions can still be
- in the first two bytes. Maybe I'll do this...
- */
-
- /*
- Handler 4 -- Apple Extended mouse protocol.
-
- For Apple's 3-button mouse protocol the data array will contain the
- following values:
-
- BITS COMMENTS
- data[0] = 0000 0000 ADB packet identifer.
- data[1] = 0100 0000 Extended protocol register.
- Bits 6-7 are the device id, which should be 1.
- Bits 4-5 are resolution which is in "units/inch".
- The Logitech MouseMan returns these bits clear but it has
- 200/300cpi resolution.
- Bits 0-3 are unique vendor id.
- data[2] = 0011 1100 Bits 0-1 should be zero for a mouse device.
- Bits 2-3 should be 8 + 4.
- Bits 4-7 should be 3 for a mouse device.
- data[3] = bxxx xxxx Left button and x-axis motion.
- data[4] = byyy yyyy Second button and y-axis motion.
- data[5] = byyy bxxx Third button and fourth button. Y is additional
- high bits of y-axis motion. XY is additional
- high bits of x-axis motion.
-
- NOTE: data[0] and data[2] are confirmed by the parent function and
- need not be checked here.
- */
-
- /*
- Handler 1 -- 100cpi original Apple mouse protocol.
- Handler 2 -- 200cpi original Apple mouse protocol.
-
- For Apple's standard one-button mouse protocol the data array will
- contain the following values:
-
- BITS COMMENTS
- data[0] = 0000 0000 ADB packet identifer.
- data[1] = ???? ???? (?)
- data[2] = ???? ??00 Bits 0-1 should be zero for a mouse device.
- data[3] = bxxx xxxx First button and x-axis motion.
- data[4] = byyy yyyy Second button and y-axis motion.
-
- NOTE: data[0] is confirmed by the parent function and need not be
- checked here.
- */
-
-static void
-mouse_input(unsigned char *data, int nb, struct pt_regs *regs)
-{
- struct kbd_struct *kbd;
- int i;
-
- if (nb < 5 || nb > 6 || (data[2] & 3) != MOUSE_DATAREG) {
- printk("data from mouse:");
- for (i = 0; i < nb; ++i)
- printk(" %x", data[i]);
- printk("\n");
- return;
- }
-
- if (adb_mouse_interrupt_hook) {
- adb_mouse_interrupt_hook(data+2, nb-2);
- /*
- * passing the mouse data to i.e. the X server as done for
- * Xpmac will confuse applications on a sane X server :-)
- */
- return;
- }
-#ifdef DEBUG_ADBMOUSE
- else
- if (console_loglevel >= 8)
- printk("mouse_input: data %x %x %x buttons %x dx %d dy %d \n",
- data[3], data[4], data[5],
- ~((data[3] & 0x80 ? 0 : 4)
- | (data[4] & 0x80 ? 0 : 1)
- | (data[5] & 0x80 ? 0 : 2))&7,
- ((data[4]&0x7f) < 64 ? (data[4]&0x7f) : (data[4]&0x7f)-128 ),
- ((data[3]&0x7f) < 64 ? -(data[3]&0x7f) : 128-(data[3]&0x7f) ) );
-#endif
-
-
- kbd = kbd_table + fg_console;
-
-#if 0 /* The entirely insane way of MkLinux handling mouse input */
- /* Requires put_queue which is static in keyboard.c :-( */
- /* Only send mouse codes when keyboard is in raw mode. */
- if (kbd->kbdmode == VC_RAW) {
- static unsigned char uch_ButtonStateSecond = 0;
- unsigned char uchButtonSecond;
-
- /* Send first button, second button and movement. */
- put_queue( 0x7e );
- put_queue( data[3] );
- put_queue( data[4] );
-
- /* [ACA: Are there any two-button ADB mice that use handler 1 or 2?] */
-
- /* Store the button state. */
- uchButtonSecond = (data[4] & 0x80);
-
- /* Send second button. */
- if (uchButtonSecond != uch_ButtonStateSecond) {
- put_queue( 0x3f | uchButtonSecond );
- uch_ButtonStateSecond = uchButtonSecond;
- }
-
- /* Macintosh 3-button mouse (handler 4). */
- if ((nb == 6) && (data[1] & 0x40)) {
- static unsigned char uch_ButtonStateThird = 0;
- unsigned char uchButtonThird;
-
- /* Store the button state for speed. */
- uchButtonThird = (data[5] & 0x80);
-
- /* Send third button. */
- if (uchButtonThird != uch_ButtonStateThird) {
- put_queue( 0x40 | uchButtonThird );
- uch_ButtonStateThird = uchButtonThird;
- }
- }
- }
-#endif /* insane MkLinux mouse hack */
-}
-
-/* Map led flags as defined in kbd_kern.h to bits for Apple keyboard. */
-static unsigned char mac_ledmap[8] = {
- 0, /* none */
- 4, /* scroll lock */
- 1, /* num lock */
- 5, /* scroll + num lock */
- 2, /* caps lock */
- 6, /* caps + scroll lock */
- 3, /* caps + num lock */
- 7, /* caps + num + scroll lock */
-};
-
-static int leds_pending;
-
-void mac_kbd_leds(unsigned int leds)
-{
- if (led_request.got_reply) {
-#ifdef DEBUG_ADB
- if (console_loglevel == 10)
- printk("mac_kbd_leds: got reply, sending request!\n");
-#endif
- adb_request(&led_request, mac_leds_done, 4, ADB_PACKET,
- ADB_WRITEREG(ADB_KEYBOARD, KEYB_LEDREG),
- 0xff, ~mac_ledmap[leds]);
- } else
- leds_pending = leds | 0x100;
-}
-
-static void mac_leds_done(struct adb_request *req)
-{
- int leds;
-
- if (leds_pending) {
- leds = leds_pending & 0xff;
- leds_pending = 0;
- mac_kbd_leds(leds);
- }
- mark_bh(KEYBOARD_BH);
-}
-
-int mac_kbdrate(struct kbd_repeat *k)
-{
- return 0;
-}
-
-int __init mac_keyb_init(void)
-{
- static struct adb_request autopoll_req, confcod_req, mouse_req, readkey_req;
- volatile int ct;
-
- /* setup key map */
- memcpy(key_maps[0], mac_plain_map, sizeof(plain_map));
- memcpy(key_maps[1], mac_shift_map, sizeof(plain_map));
- memcpy(key_maps[2], mac_altgr_map, sizeof(plain_map));
- memcpy(key_maps[4], mac_ctrl_map, sizeof(plain_map));
- memcpy(key_maps[5], mac_shift_ctrl_map, sizeof(plain_map));
- memcpy(key_maps[8], mac_alt_map, sizeof(plain_map));
- memcpy(key_maps[12], mac_ctrl_alt_map, sizeof(plain_map));
-
- /* initialize mouse interrupt hook */
- adb_mouse_interrupt_hook = NULL;
-
- /*
- * Might put that someplace else, possibly ....
- */
- adb_bus_init();
-
- /* the input functions ... */
- adb_register(ADB_KEYBOARD, keyboard_input);
- adb_register(ADB_MOUSE, mouse_input);
-
- /* turn on ADB auto-polling in the CUDA */
-
- /*
- * Older boxes don't support CUDA_* targets and CUDA commands
- * instead we emulate them in the adb_request hook to make
- * the code interfaces saner.
- *
- * Note XXX: the Linux PMac and this code both assume the
- * devices are at their primary ids and do not do device
- * assignment. This isn't ideal. We should fix it to follow
- * the reassignment specs.
- */
-
- if (macintosh_config->adb_type == MAC_ADB_CUDA) {
- printk("CUDA autopoll on ...\n");
- adb_request(&autopoll_req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1);
- ct=0;
- while (!autopoll_req.got_reply && ++ct<1000)
- {
- udelay(10);
- }
- if(ct==1000) {
- printk("Keyboard timed out.\n");
- autopoll_req.got_reply = 1;
- }
- }
-
- /*
- * XXX: all ADB requests now in CUDA format; adb_request takes
- * care of that for other Macs.
- */
-
- printk("Configuring keyboard:\n");
-
- udelay(3000);
-
- /*
- * turn on all leds - the keyboard driver will turn them back off
- * via mac_kbd_leds if everything works ok!
- */
- printk("leds on ...\n");
- adb_request(&led_request, NULL, 4, ADB_PACKET,
- ADB_WRITEREG(ADB_KEYBOARD, KEYB_LEDREG), 0xff, ~7);
-
- /*
- * The polling stuff should go away as soon as the ADB driver is stable
- */
- ct = 0;
- while (!led_request.got_reply && ++ct<1000)
- {
- udelay(10);
- }
- if(ct==1000) {
- printk("keyboard timed out.\n");
- led_request.got_reply = 1;
- }
-
-#if 1
- printk("configuring coding mode ...\n");
-
- udelay(3000);
-
- /*
- * get the keyboard to send separate codes for
- * left and right shift, control, option keys.
- */
- adb_request(&confcod_req, NULL, 4, ADB_PACKET,
- ADB_WRITEREG(ADB_KEYBOARD, 3), 0, 3);
-
- ct=0;
- while (!confcod_req.got_reply && ++ct<1000)
- {
- udelay(10);
- }
- if(ct==1000) {
- printk("keyboard timed out.\n");
- confcod_req.got_reply = 1;
- }
-#endif
-
-#if 0 /* seems to hurt, at least Geert's Mac */
- printk("Configuring mouse (3-button mode) ...\n");
-
- udelay(3000);
-
- /*
- * XXX: taken from the PPC driver again ...
- * Try to switch the mouse (id 3) to handler 4, for three-button
- * mode. (0x20 is Service Request Enable, 0x03 is Device ID).
- */
- adb_request(&mouse_req, NULL, 4, ADB_PACKET,
- ADB_WRITEREG(ADB_MOUSE, 3), 0x23, 4 );
-
- ct=0;
- while (!mouse_req.got_reply && ++ct<1000)
- {
- udelay(10);
- }
- if(ct==1000)
- printk("Mouse timed out.\n");
-#endif
-
-#if 0
- printk("Start polling keyboard ...\n");
-
- /*
- * get the keyboard to send data back, via the adb_input hook
- * XXX: was never used properly, and the driver takes care
- * of polling and timeout retransmits now.
- * Might be of use if we want to start talking to a specific
- * device here...
- */
- adb_request(&readkey_req, NULL, 2, ADB_PACKET,
- ADB_READREG(ADB_KEYBOARD, KEYB_KEYREG));
-#endif
-
- in_keybinit = 0;
- printk("keyboard init done\n");
-
- return 0;
-}
diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c
new file mode 100644
index 000000000..a14f25c56
--- /dev/null
+++ b/arch/m68k/mac/misc.c
@@ -0,0 +1,689 @@
+/*
+ * Miscellaneous Mac68K-specific stuff
+ */
+
+#include <stdarg.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/malloc.h>
+#include <linux/kd.h>
+#include <linux/mm.h>
+
+#include <linux/adb.h>
+#include <linux/cuda.h>
+#include <linux/pmu.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/setup.h>
+#include <asm/macintosh.h>
+#include <asm/mac_via.h>
+#include <asm/mac_oss.h>
+
+#define BOOTINFO_COMPAT_1_0
+#include <asm/bootinfo.h>
+#include <asm/machdep.h>
+
+/* Offset between Unix time (1970-based) and Mac time (1904-based) */
+
+#define RTC_OFFSET 2082844800
+
+extern struct mac_booter_data mac_bi_data;
+static void (*rom_reset)(void);
+
+/*
+ * Return the current time as the number of seconds since January 1, 1904.
+ */
+
+static long adb_read_time(void)
+{
+ volatile struct adb_request req;
+ long time;
+
+ adb_request((struct adb_request *) &req, NULL,
+ ADBREQ_RAW|ADBREQ_SYNC,
+ 2, CUDA_PACKET, CUDA_GET_TIME);
+
+ time = (req.reply[3] << 24) | (req.reply[4] << 16)
+ | (req.reply[5] << 8) | req.reply[6];
+ return time - RTC_OFFSET;
+}
+
+/*
+ * Set the current system time
+ */
+
+static void adb_write_time(long data)
+{
+ volatile struct adb_request req;
+
+ data += RTC_OFFSET;
+
+ adb_request((struct adb_request *) &req, NULL,
+ ADBREQ_RAW|ADBREQ_SYNC,
+ 6, CUDA_PACKET, CUDA_SET_TIME,
+ (data >> 24) & 0xFF, (data >> 16) & 0xFF,
+ (data >> 8) & 0xFF, data & 0xFF);
+}
+
+/*
+ * Get a byte from the NVRAM
+ */
+
+static __u8 adb_read_pram(int offset)
+{
+ volatile struct adb_request req;
+
+ adb_request((struct adb_request *) &req, NULL,
+ ADBREQ_RAW|ADBREQ_SYNC,
+ 4, CUDA_PACKET, CUDA_GET_PRAM,
+ (offset >> 8) & 0xFF, offset & 0xFF);
+ return req.reply[3];
+}
+
+/*
+ * Write a byte to the NVRAM
+ */
+
+static void adb_write_pram(int offset, __u8 data)
+{
+ volatile struct adb_request req;
+
+ adb_request((struct adb_request *) &req, NULL,
+ ADBREQ_RAW|ADBREQ_SYNC,
+ 5, CUDA_PACKET, CUDA_SET_PRAM,
+ (offset >> 8) & 0xFF, offset & 0xFF,
+ data);
+}
+
+/*
+ * VIA PRAM/RTC access routines
+ *
+ * Must be called with interrupts disabled and
+ * the RTC should be enabled.
+ */
+
+static __u8 via_pram_readbyte(void)
+{
+ int i,reg;
+ __u8 data;
+
+ reg = via1[vBufB] & ~VIA1B_vRTCClk;
+
+ /* Set the RTC data line to be an input. */
+
+ via1[vDirB] &= ~VIA1B_vRTCData;
+
+ /* The bits of the byte come out in MSB order */
+
+ data = 0;
+ for (i = 0 ; i < 8 ; i++) {
+ via1[vBufB] = reg;
+ via1[vBufB] = reg | VIA1B_vRTCClk;
+ data = (data << 1) | (via1[vBufB] & VIA1B_vRTCData);
+ }
+
+ /* Return RTC data line to output state */
+
+ via1[vDirB] |= VIA1B_vRTCData;
+
+ return data;
+}
+
+static void via_pram_writebyte(__u8 data)
+{
+ int i,reg,bit;
+
+ reg = via1[vBufB] & ~(VIA1B_vRTCClk | VIA1B_vRTCData);
+
+ /* The bits of the byte go in in MSB order */
+
+ for (i = 0 ; i < 8 ; i++) {
+ bit = data & 0x80? 1 : 0;
+ data <<= 1;
+ via1[vBufB] = reg | bit;
+ via1[vBufB] = reg | bit | VIA1B_vRTCClk;
+ }
+}
+
+/*
+ * Execute a VIA PRAM/RTC command. For read commands
+ * data should point to a one-byte buffer for the
+ * resulting data. For write commands it should point
+ * to the data byte to for the command.
+ *
+ * This function disables all interrupts while running.
+ */
+
+static void via_pram_command(int command, __u8 *data)
+{
+ unsigned long cpu_flags;
+ int is_read;
+
+ save_flags(cpu_flags);
+ cli();
+
+ /* Enable the RTC and make sure the strobe line is high */
+
+ via1[vBufB] = (via1[vBufB] | VIA1B_vRTCClk) & ~VIA1B_vRTCEnb;
+
+ if (command & 0xFF00) { /* extended (two-byte) command */
+ via_pram_writebyte((command & 0xFF00) >> 8);
+ via_pram_writebyte(command & 0xFF);
+ is_read = command & 0x8000;
+ } else { /* one-byte command */
+ via_pram_writebyte(command);
+ is_read = command & 0x80;
+ }
+ if (is_read) {
+ *data = via_pram_readbyte();
+ } else {
+ via_pram_writebyte(*data);
+ }
+
+ /* All done, disable the RTC */
+
+ via1[vBufB] |= VIA1B_vRTCEnb;
+
+ restore_flags(cpu_flags);
+}
+
+static __u8 via_read_pram(int offset)
+{
+ return 0;
+}
+
+static void via_write_pram(int offset, __u8 data)
+{
+}
+
+/*
+ * Return the current time in seconds since January 1, 1904.
+ *
+ * This only works on machines with the VIA-based PRAM/RTC, which
+ * is basically any machine with Mac II-style ADB.
+ */
+
+static long via_read_time(void)
+{
+ union {
+ __u8 cdata[4];
+ long idata;
+ } result, last_result;
+ int ct;
+
+ /*
+ * The NetBSD guys say to loop until you get the same reading
+ * twice in a row.
+ */
+
+ ct = 0;
+ do {
+ if (++ct > 10) {
+ printk("via_read_time: couldn't get valid time, "
+ "last read = 0x%08X and 0x%08X\n", last_result.idata,
+ result.idata);
+ break;
+ }
+
+ last_result.idata = result.idata;
+ result.idata = 0;
+
+ via_pram_command(0x81, &result.cdata[3]);
+ via_pram_command(0x85, &result.cdata[2]);
+ via_pram_command(0x89, &result.cdata[1]);
+ via_pram_command(0x8D, &result.cdata[0]);
+ } while (result.idata != last_result.idata);
+
+ return result.idata - RTC_OFFSET;
+}
+
+/*
+ * Set the current time to a number of seconds since January 1, 1904.
+ *
+ * This only works on machines with the VIA-based PRAM/RTC, which
+ * is basically any machine with Mac II-style ADB.
+ */
+
+static void via_write_time(long time)
+{
+ union {
+ __u8 cdata[4];
+ long idata;
+ } data;
+ __u8 temp;
+
+ /* Clear the write protect bit */
+
+ temp = 0x55;
+ via_pram_command(0x35, &temp);
+
+ data.idata = time + RTC_OFFSET;
+ via_pram_command(0x01, &data.cdata[3]);
+ via_pram_command(0x05, &data.cdata[2]);
+ via_pram_command(0x09, &data.cdata[1]);
+ via_pram_command(0x0D, &data.cdata[0]);
+
+ /* Set the write protect bit */
+
+ temp = 0xD5;
+ via_pram_command(0x35, &temp);
+}
+
+static void via_shutdown(void)
+{
+ if (rbv_present) {
+ via2[rBufB] &= ~0x04;
+ } else {
+ /* Direction of vDirB is output */
+ via2[vDirB] |= 0x04;
+ /* Send a value of 0 on that line */
+ via2[vBufB] &= ~0x04;
+ mdelay(1000);
+ }
+}
+
+/*
+ * FIXME: not sure how this is supposed to work exactly...
+ */
+
+static void oss_shutdown(void)
+{
+ oss->rom_ctrl = OSS_POWEROFF;
+}
+
+#ifdef CONFIG_ADB_CUDA
+
+static void cuda_restart(void)
+{
+ adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
+ 2, CUDA_PACKET, CUDA_RESET_SYSTEM);
+}
+
+static void cuda_shutdown(void)
+{
+ adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
+ 2, CUDA_PACKET, CUDA_POWERDOWN);
+}
+
+#endif /* CONFIG_ADB_CUDA */
+
+#ifdef CONFIG_ADB_PMU
+
+void pmu_restart(void)
+{
+ adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
+ 3, PMU_PACKET, PMU_SET_INTR_MASK,
+ PMU_INT_ADB|PMU_INT_TICK);
+
+ adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
+ 2, PMU_PACKET, PMU_RESET);
+}
+
+void pmu_shutdown(void)
+{
+ adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
+ 3, PMU_PACKET, PMU_SET_INTR_MASK,
+ PMU_INT_ADB|PMU_INT_TICK);
+
+ adb_request(NULL, NULL, ADBREQ_RAW|ADBREQ_SYNC,
+ 6, PMU_PACKET, PMU_SHUTDOWN,
+ 'M', 'A', 'T', 'T');
+}
+
+#endif /* CONFIG_ADB_PMU */
+
+/*
+ *-------------------------------------------------------------------
+ * Below this point are the generic routines; they'll dispatch to the
+ * correct routine for the hardware on which we're running.
+ *-------------------------------------------------------------------
+ */
+
+void mac_pram_read(int offset, __u8 *buffer, int len)
+{
+ __u8 (*func)(int) = NULL;
+ int i;
+
+ if (macintosh_config->adb_type == MAC_ADB_IISI ||
+ macintosh_config->adb_type == MAC_ADB_PB1 ||
+ macintosh_config->adb_type == MAC_ADB_PB2 ||
+ macintosh_config->adb_type == MAC_ADB_CUDA) {
+ func = adb_read_pram;
+ } else {
+ func = via_read_pram;
+ }
+ for (i = 0 ; i < len ; i++) {
+ buffer[i] = (*func)(offset++);
+ }
+}
+
+void mac_pram_write(int offset, __u8 *buffer, int len)
+{
+ void (*func)(int, __u8) = NULL;
+ int i;
+
+ if (macintosh_config->adb_type == MAC_ADB_IISI ||
+ macintosh_config->adb_type == MAC_ADB_PB1 ||
+ macintosh_config->adb_type == MAC_ADB_PB2 ||
+ macintosh_config->adb_type == MAC_ADB_CUDA) {
+ func = adb_write_pram;
+ } else {
+ func = via_write_pram;
+ }
+ for (i = 0 ; i < len ; i++) {
+ (*func)(offset++, buffer[i]);
+ }
+}
+
+void mac_poweroff(void)
+{
+ /*
+ * MAC_ADB_IISI may need to be moved up here if it doesn't actually
+ * work using the ADB packet method. --David Kilzer
+ */
+
+ if (oss_present) {
+ oss_shutdown();
+ } else if (macintosh_config->adb_type == MAC_ADB_II) {
+ via_shutdown();
+#ifdef CONFIG_ADB_CUDA
+ } else if (macintosh_config->adb_type == MAC_ADB_CUDA) {
+ cuda_shutdown();
+#endif
+#ifdef CONFIG_ADB_PMU
+ } else if (macintosh_config->adb_type == MAC_ADB_PB1
+ || macintosh_config->adb_type == MAC_ADB_PB2) {
+ pmu_shutdown();
+#endif
+ }
+ sti();
+ printk("It is now safe to turn off your Macintosh.\n");
+ while(1);
+}
+
+void mac_reset(void)
+{
+ if (macintosh_config->adb_type == MAC_ADB_II) {
+ unsigned long cpu_flags;
+
+ /* need ROMBASE in booter */
+ /* indeed, plus need to MAP THE ROM !! */
+
+ if (mac_bi_data.rombase == 0)
+ mac_bi_data.rombase = 0x40800000;
+
+ /* works on some */
+ rom_reset = (void *) (mac_bi_data.rombase + 0xa);
+
+ if (macintosh_config->ident == MAC_MODEL_SE30) {
+ /*
+ * MSch: Machines known to crash on ROM reset ...
+ */
+ } else {
+ save_flags(cpu_flags);
+ cli();
+
+ rom_reset();
+
+ restore_flags(cpu_flags);
+ }
+#ifdef CONFIG_ADB_CUDA
+ } else if (macintosh_config->adb_type == MAC_ADB_CUDA) {
+ cuda_restart();
+#endif
+#ifdef CONFIG_ADB_PMU
+ } else if (macintosh_config->adb_type == MAC_ADB_PB1
+ || macintosh_config->adb_type == MAC_ADB_PB2) {
+ pmu_restart();
+#endif
+ } else if (CPU_IS_030) {
+
+ /* 030-specific reset routine. The idea is general, but the
+ * specific registers to reset are '030-specific. Until I
+ * have a non-030 machine, I can't test anything else.
+ * -- C. Scott Ananian <cananian@alumni.princeton.edu>
+ */
+
+ unsigned long rombase = 0x40000000;
+
+ /* make a 1-to-1 mapping, using the transparent tran. reg. */
+ unsigned long virt = (unsigned long) mac_reset;
+ unsigned long phys = virt_to_phys(mac_reset);
+ unsigned long offset = phys-virt;
+ cli(); /* lets not screw this up, ok? */
+ __asm__ __volatile__(".chip 68030\n\t"
+ "pmove %0,%/tt0\n\t"
+ ".chip 68k"
+ : : "m" ((phys&0xFF000000)|0x8777));
+ /* Now jump to physical address so we can disable MMU */
+ __asm__ __volatile__(
+ ".chip 68030\n\t"
+ "lea %/pc@(1f),%/a0\n\t"
+ "addl %0,%/a0\n\t"/* fixup target address and stack ptr */
+ "addl %0,%/sp\n\t"
+ "pflusha\n\t"
+ "jmp %/a0@\n\t" /* jump into physical memory */
+ "0:.long 0\n\t" /* a constant zero. */
+ /* OK. Now reset everything and jump to reset vector. */
+ "1:\n\t"
+ "lea %/pc@(0b),%/a0\n\t"
+ "pmove %/a0@, %/tc\n\t" /* disable mmu */
+ "pmove %/a0@, %/tt0\n\t" /* disable tt0 */
+ "pmove %/a0@, %/tt1\n\t" /* disable tt1 */
+ "movel #0, %/a0\n\t"
+ "movec %/a0, %/vbr\n\t" /* clear vector base register */
+ "movec %/a0, %/cacr\n\t" /* disable caches */
+ "movel #0x0808,%/a0\n\t"
+ "movec %/a0, %/cacr\n\t" /* flush i&d caches */
+ "movew #0x2700,%/sr\n\t" /* set up status register */
+ "movel %1@(0x0),%/a0\n\t"/* load interrupt stack pointer */
+ "movec %/a0, %/isp\n\t"
+ "movel %1@(0x4),%/a0\n\t" /* load reset vector */
+ "reset\n\t" /* reset external devices */
+ "jmp %/a0@\n\t" /* jump to the reset vector */
+ ".chip 68k"
+ : : "r" (offset), "a" (rombase) : "a0");
+ }
+
+ /* should never get here */
+ sti();
+ printk ("Restart failed. Please restart manually.\n");
+ while(1);
+}
+
+/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
+ * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
+ * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
+ *
+ * [For the Julian calendar (which was used in Russia before 1917,
+ * Britain & colonies before 1752, anywhere else before 1582,
+ * and is still in use by some communities) leave out the
+ * -year/100+year/400 terms, and add 10.]
+ *
+ * This algorithm was first published by Gauss (I think).
+ *
+ * WARNING: this function will overflow on 2106-02-07 06:28:16 on
+ * machines were long is 32-bit! (However, as time_t is signed, we
+ * will already get problems at other places on 2038-01-19 03:14:08)
+ */
+static unsigned long mktime(unsigned int year, unsigned int mon,
+ unsigned int day, unsigned int hour,
+ unsigned int min, unsigned int sec)
+{
+ if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
+ mon += 12; /* Puts Feb last since it has leap day */
+ year -= 1;
+ }
+ return (((
+ (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
+ year*365 - 719499
+ )*24 + hour /* now have hours */
+ )*60 + min /* now have minutes */
+ )*60 + sec; /* finally seconds */
+}
+
+/*
+ * This function translates seconds since 1970 into a proper date.
+ *
+ * Algorithm cribbed from glibc2.1, __offtime().
+ */
+#define SECS_PER_MINUTE (60)
+#define SECS_PER_HOUR (SECS_PER_MINUTE * 60)
+#define SECS_PER_DAY (SECS_PER_HOUR * 24)
+
+static void unmktime(unsigned long time, long offset,
+ int *yearp, int *monp, int *dayp,
+ int *hourp, int *minp, int *secp)
+{
+ /* How many days come before each month (0-12). */
+ static const unsigned short int __mon_yday[2][13] =
+ {
+ /* Normal years. */
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+ /* Leap years. */
+ { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+ };
+ long int days, rem, y, wday, yday;
+ const unsigned short int *ip;
+
+ days = time / SECS_PER_DAY;
+ rem = time % SECS_PER_DAY;
+ rem += offset;
+ while (rem < 0) {
+ rem += SECS_PER_DAY;
+ --days;
+ }
+ while (rem >= SECS_PER_DAY) {
+ rem -= SECS_PER_DAY;
+ ++days;
+ }
+ *hourp = rem / SECS_PER_HOUR;
+ rem %= SECS_PER_HOUR;
+ *minp = rem / SECS_PER_MINUTE;
+ *secp = rem % SECS_PER_MINUTE;
+ /* January 1, 1970 was a Thursday. */
+ wday = (4 + days) % 7; /* Day in the week. Not currently used */
+ if (wday < 0) wday += 7;
+ y = 1970;
+
+#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
+#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
+#define __isleap(year) \
+ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
+
+ while (days < 0 || days >= (__isleap (y) ? 366 : 365))
+ {
+ /* Guess a corrected year, assuming 365 days per year. */
+ long int yg = y + days / 365 - (days % 365 < 0);
+
+ /* Adjust DAYS and Y to match the guessed year. */
+ days -= ((yg - y) * 365
+ + LEAPS_THRU_END_OF (yg - 1)
+ - LEAPS_THRU_END_OF (y - 1));
+ y = yg;
+ }
+ *yearp = y - 1900;
+ yday = days; /* day in the year. Not currently used. */
+ ip = __mon_yday[__isleap(y)];
+ for (y = 11; days < (long int) ip[y]; --y)
+ continue;
+ days -= ip[y];
+ *monp = y;
+ *dayp = days + 1; /* day in the month */
+ return;
+}
+
+/*
+ * Return the boot time for use in initializing the kernel clock.
+ *
+ * I'd like to read the hardware clock here but many machines read
+ * the PRAM through ADB, and interrupts aren't initialized when this
+ * is called so ADB obviously won't work.
+ */
+
+void mac_gettod(int *yearp, int *monp, int *dayp,
+ int *hourp, int *minp, int *secp)
+{
+ /* Yes the GMT bias is backwards. It looks like Penguin is
+ screwing up the boottime it gives us... This works for me
+ in Canada/Eastern but it might be wrong everywhere else. */
+ unmktime(mac_bi_data.boottime, -mac_bi_data.gmtbias * 60,
+ yearp, monp, dayp, hourp, minp, secp);
+ /* For some reason this is off by one */
+ *monp = *monp + 1;
+}
+
+/*
+ * Read/write the hardware clock.
+ */
+
+int mac_hwclk(int op, struct hwclk_time *t)
+{
+ unsigned long now;
+
+ if (!op) { /* read */
+ if (macintosh_config->adb_type == MAC_ADB_II) {
+ now = via_read_time();
+ } else if ((macintosh_config->adb_type == MAC_ADB_IISI) ||
+ (macintosh_config->adb_type == MAC_ADB_PB1) ||
+ (macintosh_config->adb_type == MAC_ADB_PB2) ||
+ (macintosh_config->adb_type == MAC_ADB_CUDA)) {
+ now = adb_read_time();
+ } else if (macintosh_config->adb_type == MAC_ADB_IOP) {
+ now = via_read_time();
+ } else {
+ now = 0;
+ }
+
+ t->wday = 0;
+ unmktime(now, 0,
+ &t->year, &t->mon, &t->day,
+ &t->hour, &t->min, &t->sec);
+ printk("mac_hwclk: read %04d-%02d-%-2d %02d:%02d:%02d\n",
+ t->year + 1900, t->mon + 1, t->day, t->hour, t->min, t->sec);
+ } else { /* write */
+ printk("mac_hwclk: tried to write %04d-%02d-%-2d %02d:%02d:%02d\n",
+ t->year + 1900, t->mon + 1, t->day, t->hour, t->min, t->sec);
+
+#if 0 /* it trashes my rtc */
+ now = mktime(t->year + 1900, t->mon + 1, t->day,
+ t->hour, t->min, t->sec);
+
+ if (macintosh_config->adb_type == MAC_ADB_II) {
+ via_write_time(now);
+ } else if ((macintosh_config->adb_type == MAC_ADB_IISI) ||
+ (macintosh_config->adb_type == MAC_ADB_PB1) ||
+ (macintosh_config->adb_type == MAC_ADB_PB2) ||
+ (macintosh_config->adb_type == MAC_ADB_CUDA)) {
+ adb_write_time(now);
+ } else if (macintosh_config->adb_type == MAC_ADB_IOP) {
+ via_write_time(now);
+ }
+#endif
+ }
+ return 0;
+}
+
+/*
+ * Set minutes/seconds in the hardware clock
+ */
+
+int mac_set_clock_mmss (unsigned long nowtime)
+{
+ struct hwclk_time now;
+
+ mac_hwclk(0, &now);
+ now.sec = nowtime % 60;
+ now.min = (nowtime / 60) % 60;
+ mac_hwclk(1, &now);
+
+ return 0;
+}
diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c
index 442d72802..c405fc0da 100644
--- a/arch/m68k/mac/oss.c
+++ b/arch/m68k/mac/oss.c
@@ -34,7 +34,7 @@ void oss_irq(int, void *, struct pt_regs *);
void oss_nubus_irq(int, void *, struct pt_regs *);
extern void via1_irq(int, void *, struct pt_regs *);
-extern void mac_SCC_handler(int, void *, struct pt_regs *);
+extern void mac_scc_dispatch(int, void *, struct pt_regs *);
extern int console_loglevel;
/*
@@ -68,16 +68,16 @@ void __init oss_init(void)
void __init oss_register_interrupts(void)
{
- request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
- "OSS SCSI Dispatch", (void *) oss);
- request_irq(OSS_IRQLEV_IOPSCC, mac_SCC_handler, IRQ_FLG_LOCK,
- "SCC Dispatch", mac_SCC_handler);
- request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
- "Nubus Dispatch", (void *) oss);
- request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
- "OSS Sound Dispatch", (void *) oss);
- request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
- "VIA1 Dispatch", (void *) via1);
+ sys_request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
+ "scsi", (void *) oss);
+ sys_request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK,
+ "scc", mac_scc_dispatch);
+ sys_request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
+ "nubus", (void *) oss);
+ sys_request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
+ "sound", (void *) oss);
+ sys_request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
+ "via1", (void *) via1);
}
/*
@@ -89,22 +89,6 @@ void __init oss_nubus_init(void)
}
/*
- * Turn off the power via the ROM control register
- *
- * FIXME: not sure how this is supposed to work exactly...
- */
-
-void oss_poweroff(void)
-{
- oss->rom_ctrl = OSS_POWEROFF;
-
- /* We should never make it this far... */
-
- printk ("It is now safe to switch off your machine.\n");
- while(1);
-}
-
-/*
* Handle miscellaneous OSS interrupts. Right now that's just sound
* and SCSI; everything else is routed to its own autovector IRQ.
*/
diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c
index 45825b113..86bbf72cc 100644
--- a/arch/m68k/mac/psc.c
+++ b/arch/m68k/mac/psc.c
@@ -119,14 +119,14 @@ void __init psc_init(void)
void __init psc_register_interrupts(void)
{
- request_irq(3, psc_irq, IRQ_FLG_LOCK, "PSC Dispatch",
- (void *) 0x30);
- request_irq(4, psc_irq, IRQ_FLG_LOCK, "PSC Dispatch",
- (void *) 0x40);
- request_irq(5, psc_irq, IRQ_FLG_LOCK, "PSC Dispatch",
- (void *) 0x50);
- request_irq(6, psc_irq, IRQ_FLG_LOCK, "PSC Dispatch",
- (void *) 0x60);
+ sys_request_irq(3, psc_irq, IRQ_FLG_LOCK, "psc3",
+ (void *) 0x30);
+ sys_request_irq(4, psc_irq, IRQ_FLG_LOCK, "psc4",
+ (void *) 0x40);
+ sys_request_irq(5, psc_irq, IRQ_FLG_LOCK, "psc5",
+ (void *) 0x50);
+ sys_request_irq(6, psc_irq, IRQ_FLG_LOCK, "psc6",
+ (void *) 0x60);
}
/*
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index 2205b226c..af001907d 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -24,6 +24,8 @@
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/ide.h>
+
#include <asm/traps.h>
#include <asm/bootinfo.h>
#include <asm/macintosh.h>
@@ -60,7 +62,7 @@ static int gIER,gIFR,gBufA,gBufB;
#define MAC_CLOCK_LOW (MAC_CLOCK_TICK&0xFF)
#define MAC_CLOCK_HIGH (MAC_CLOCK_TICK>>8)
-static int nubus_active;
+static int nubus_active = 0;
void via_debug_dump(void);
void via1_irq(int, void *, struct pt_regs *);
@@ -71,7 +73,7 @@ void via_irq_disable(int irq);
void via_irq_clear(int irq);
extern void mac_bang(int, void *, struct pt_regs *);
-extern void mac_SCC_handler(int, void *, struct pt_regs *);
+extern void mac_scc_dispatch(int, void *, struct pt_regs *);
extern int console_loglevel;
extern int oss_present;
@@ -260,28 +262,28 @@ void __init via_init_clock(void (*func)(int, void *, struct pt_regs *))
void __init via_register_interrupts(void)
{
if (via_alt_mapping) {
- request_irq(IRQ_AUTO_1, via1_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
- "Software IRQ", (void *) via1);
- request_irq(IRQ_AUTO_6, via1_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
- "VIA1 Dispatch", (void *) via1);
+ sys_request_irq(IRQ_AUTO_1, via1_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
+ "software", (void *) via1);
+ sys_request_irq(IRQ_AUTO_6, via1_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
+ "via1", (void *) via1);
} else {
- request_irq(IRQ_AUTO_1, via1_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
- "VIA1 Dispatch", (void *) via1);
+ sys_request_irq(IRQ_AUTO_1, via1_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
+ "via1", (void *) via1);
#if 0 /* interferes with serial on some machines */
if (!psc_present) {
- request_irq(IRQ_AUTO_6, mac_bang, IRQ_FLG_LOCK,
+ sys_request_irq(IRQ_AUTO_6, mac_bang, IRQ_FLG_LOCK,
"Off Switch", mac_bang);
}
#endif
}
- request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
- "VIA2 Dispatch", (void *) via2);
+ sys_request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
+ "via2", (void *) via2);
if (!psc_present) {
- request_irq(IRQ_AUTO_4, mac_SCC_handler, IRQ_FLG_LOCK,
- "SCC Dispatch", mac_SCC_handler);
+ sys_request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK,
+ "scc", mac_scc_dispatch);
}
request_irq(IRQ_MAC_NUBUS, via_nubus_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
- "Nubus Dispatch", (void *) via2);
+ "nubus", (void *) via2);
}
/*
@@ -361,34 +363,13 @@ int via_get_cache_disable(void)
}
/*
- * VIA-based power switch, for machines that support it.
- */
-
-void via_poweroff(void)
-{
- if (rbv_present) {
- via2[rBufB] &= ~0x04;
- } else {
- /* Direction of vDirB is output */
- via2[vDirB] |= 0x04;
- /* Send a value of 0 on that line */
- via2[vBufB] &= ~0x04;
- /* Otherwise it prints "It is now.." then shuts off */
- mdelay(1000);
- }
-
- /* We should never make it this far... */
- printk ("It is now safe to switch off your machine.\n");
- while(1);
-}
-
-/*
* Initialize VIA2 for Nubus access
*/
void __init via_nubus_init(void)
{
- nubus_active = 0;
+ /* don't set nubus_active = 0 here, it kills the Baboon */
+ /* interrupt that we've already registered. */
/* unlock nubus transactions */
@@ -396,14 +377,22 @@ void __init via_nubus_init(void)
/* set the line to be an output on non-RBV machines */
via2[vDirB] |= 0x02;
}
- via2[gBufB] |= 0x02;
+
+ /* this seems to be an ADB bit on PMU machines */
+ /* according to MkLinux. -- jmt */
+
+ if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
+ (macintosh_config->adb_type != MAC_ADB_PB2)) {
+ via2[gBufB] |= 0x02;
+ }
/* disable nubus slot interrupts. */
if (rbv_present) {
- via2[rSIER] = 0x7F; /* like VIA; bit 7=clr,set */
+ via2[rSIER] = 0x7F;
+ via2[rSIER] = nubus_active | 0x80;
} else {
- via2[vBufA] = 0xFF; /* active low irqs, force high */
- via2[vDirA] = 0xFF; /* ddr to output. */
+ via2[vBufA] = 0xFF;
+ via2[vDirA] = ~nubus_active;
}
}
@@ -478,7 +467,7 @@ void via_nubus_irq(int irq, void *dev_id, struct pt_regs *regs)
int irq_bit, i;
unsigned char events;
- if (!(events = ~via2[gBufA] & nubus_active)) return;
+ if (!(events = ~via2[gBufA] & nubus_active)) return;
for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) {
if (events & irq_bit) {
@@ -587,188 +576,3 @@ int via_irq_pending(int irq)
}
return 0;
}
-
-void via_scsi_clear(void)
-{
- volatile unsigned char deep_magic;
-
-#ifdef DEBUG_IRQUSE
- printk("via_scsi_clear()\n");
-#endif
-
- /* We handle this in oss.c , but this gets called in mac_scsinew.c */
- if(oss_present) return;
-
- if (rbv_present) {
- via2[rIFR] = (1<<3) | (1<<0) | rbv_clear;
- deep_magic = via2[rBufB];
- } else {
- deep_magic = via2[vBufB];
- }
- mac_enable_irq(IRQ_MAC_SCSI);
-}
-
-/*
- * PRAM/RTC access routines
- *
- * Must be called with interrupts disabled and
- * the RTC should be enabled.
- */
-
-static __u8 via_pram_readbyte(void)
-{
- int i,reg;
- __u8 data;
-
- reg = via1[vBufB] & ~VIA1B_vRTCClk;
-
- /* Set the RTC data line to be an input. */
-
- via1[vDirB] &= ~VIA1B_vRTCData;
-
- /* The bits of the byte come out in MSB order */
-
- data = 0;
- for (i = 0 ; i < 8 ; i++) {
- via1[vBufB] = reg;
- via1[vBufB] = reg | VIA1B_vRTCClk;
- data = (data << 1) | (via1[vBufB] & VIA1B_vRTCData);
- }
-
- /* Return RTC data line to output state */
-
- via1[vDirB] |= VIA1B_vRTCData;
-
- return data;
-}
-
-static void via_pram_writebyte(__u8 data)
-{
- int i,reg,bit;
-
- reg = via1[vBufB] & ~(VIA1B_vRTCClk | VIA1B_vRTCData);
-
- /* The bits of the byte go in in MSB order */
-
- for (i = 0 ; i < 8 ; i++) {
- bit = data & 0x80? 1 : 0;
- data <<= 1;
- via1[vBufB] = reg | bit;
- via1[vBufB] = reg | bit | VIA1B_vRTCClk;
- }
-}
-
-/*
- * Execute a PRAM/RTC command. For read commands
- * data should point to a one-byte buffer for the
- * resulting data. For write commands it should point
- * to the data byte to for the command.
- *
- * This function disables all interrupts while running.
- */
-
-void via_pram_command(int command, __u8 *data)
-{
- unsigned long cpu_flags;
- int is_read;
-
- save_flags(cpu_flags);
- cli();
-
- /* Enable the RTC and make sure the strobe line is high */
-
- via1[vBufB] = (via1[vBufB] | VIA1B_vRTCClk) & ~VIA1B_vRTCEnb;
-
- if (command & 0xFF00) { /* extended (two-byte) command */
- via_pram_writebyte((command & 0xFF00) >> 8);
- via_pram_writebyte(command & 0xFF);
- is_read = command & 0x8000;
- } else { /* one-byte command */
- via_pram_writebyte(command);
- is_read = command & 0x80;
- }
- if (is_read) {
- *data = via_pram_readbyte();
- } else {
- via_pram_writebyte(*data);
- }
-
- /* All done, disable the RTC */
-
- via1[vBufB] |= VIA1B_vRTCEnb;
-
- restore_flags(cpu_flags);
-}
-
-/*
- * Return the current time in seconds since January 1, 1904.
- *
- * This only works on machines with the VIA-based PRAM/RTC, which
- * is basically any machine with Mac II-style ADB.
- */
-
-__u32 via_read_time(void)
-{
- union {
- __u8 cdata[4];
- __u32 idata;
- } result, last_result;
- int ct;
-
- /*
- * The NetBSD guys say to loop until you get the same reading
- * twice in a row.
- */
-
- ct = 0;
- do {
- if (++ct > 10) {
- printk("via_read_time: couldn't get valid time, "
- "last read = 0x%08X and 0x%08X\n", last_result.idata,
- result.idata);
- break;
- }
-
- last_result.idata = result.idata;
- result.idata = 0;
-
- via_pram_command(0x81, &result.cdata[3]);
- via_pram_command(0x85, &result.cdata[2]);
- via_pram_command(0x89, &result.cdata[1]);
- via_pram_command(0x8D, &result.cdata[0]);
- } while (result.idata != last_result.idata);
-
- return result.idata;
-}
-
-/*
- * Set the current time to a number of seconds since January 1, 1904.
- *
- * This only works on machines with the VIA-based PRAM/RTC, which
- * is basically any machine with Mac II-style ADB.
- */
-
-void via_write_time(__u32 time)
-{
- union {
- __u8 cdata[4];
- __u32 idata;
- } data;
- __u8 temp;
-
- /* Clear the write protect bit */
-
- temp = 0x55;
- via_pram_command(0x35, &temp);
-
- data.idata = time;
- via_pram_command(0x01, &data.cdata[3]);
- via_pram_command(0x05, &data.cdata[2]);
- via_pram_command(0x09, &data.cdata[1]);
- via_pram_command(0x0D, &data.cdata[0]);
-
- /* Set the write protect bit */
-
- temp = 0xD5;
- via_pram_command(0x35, &temp);
-}
diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c
index 456520a64..146dc7279 100644
--- a/arch/m68k/mm/motorola.c
+++ b/arch/m68k/mm/motorola.c
@@ -207,7 +207,7 @@ void __init paging_init(void)
{
int chunk;
unsigned long mem_avail = 0;
- unsigned int zones_size[3] = { 0, };
+ unsigned long zones_size[3] = { 0, };
#ifdef DEBUG
{
diff --git a/arch/m68k/mm/sun3mmu.c b/arch/m68k/mm/sun3mmu.c
index bd59fecba..8d6632d2f 100644
--- a/arch/m68k/mm/sun3mmu.c
+++ b/arch/m68k/mm/sun3mmu.c
@@ -30,7 +30,7 @@
extern void mmu_emu_init (void);
-extern unsigned long free_area_init(unsigned long, unsigned long);
+extern unsigned long free_area_init(unsigned long *zones_size);
const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
diff --git a/arch/mips/config.in b/arch/mips/config.in
index 91b4c6675..b6551a29e 100644
--- a/arch/mips/config.in
+++ b/arch/mips/config.in
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.40 2000/02/21 15:05:48 ralf Exp $
+# $Id: config.in,v 1.41 2000/02/23 00:41:00 ralf Exp $
# For a description of the syntax of this configuration file,
# see the Configure script.
#
@@ -64,12 +64,10 @@ comment 'CPU selection'
if [ "$CONFIG_CPU_ADVANCED" = "y" ]; then
choice 'CPU core' \
"R3000 CONFIG_CPU_R3000 \
- R6000 CONFIG_CPU_R6000 \
R4300 CONFIG_CPU_R4300 \
R4x00 CONFIG_CPU_R4X00 \
R5000 CONFIG_CPU_R5000 \
R56x0 CONFIG_CPU_NEVADA \
- R8000 CONFIG_CPU_R8000 \
R10000 CONFIG_CPU_R10000" R4x00
bool ' ll/sc Instructions available' CONFIG_CPU_HAS_LLSC
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index 7b1bc7f4c..5516700c1 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -296,7 +296,7 @@ CONFIG_PSMOUSE=y
#
#
-# Filesystems
+# File systems
#
# CONFIG_QUOTA is not set
CONFIG_AUTOFS_FS=y
@@ -315,20 +315,17 @@ CONFIG_ISO9660_FS=y
# 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_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
diff --git a/arch/mips/jazz/floppy-jazz.c b/arch/mips/jazz/floppy-jazz.c
index 92c1f9506..76f39e52a 100644
--- a/arch/mips/jazz/floppy-jazz.c
+++ b/arch/mips/jazz/floppy-jazz.c
@@ -1,4 +1,4 @@
-/* $Id: floppy-jazz.c,v 1.1 1998/05/07 18:38:29 ralf Exp $
+/* $Id: floppy-jazz.c,v 1.2 1998/10/18 13:18:25 tsbogend 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
@@ -94,26 +94,11 @@ static unsigned long jazz_fd_getfdaddr1(void)
return JAZZ_FDC_BASE;
}
-/* Pure 2^n version of get_order */
-extern inline int __get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
static unsigned long jazz_fd_dma_mem_alloc(unsigned long size)
{
- int order = __get_order(size);
unsigned long mem;
- mem = __get_dma_pages(GFP_KERNEL, order);
+ mem = __get_dma_pages(GFP_KERNEL, get_order(size));
if(!mem)
return 0;
vdma_alloc(PHYSADDR(mem), size); /* XXX error checking */
@@ -125,7 +110,7 @@ static void jazz_fd_dma_mem_free(unsigned long addr,
unsigned long size)
{
vdma_free(vdma_phys2log(PHYSADDR(addr)));
- free_pages(addr, __get_order(size));
+ free_pages(addr, get_order(size));
}
static unsigned long jazz_fd_drive_type(unsigned long n)
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index 57e9bedfb..f1c65805f 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -1,4 +1,4 @@
-/* $Id: mips_ksyms.c,v 1.23 2000/01/29 01:41:59 ralf Exp $
+/* $Id: mips_ksyms.c,v 1.24 2000/02/04 07:40:23 ralf Exp $
*
* Export MIPS-specific functions needed for loadable modules.
*
@@ -55,7 +55,7 @@ EXPORT_SYMBOL_NOVERS(strrchr);
EXPORT_SYMBOL_NOVERS(strtok);
EXPORT_SYMBOL_NOVERS(strpbrk);
-EXPORT_SYMBOL(clear_page);
+EXPORT_SYMBOL(_clear_page);
EXPORT_SYMBOL(local_bh_count);
EXPORT_SYMBOL(local_irq_count);
EXPORT_SYMBOL(enable_irq);
@@ -81,10 +81,10 @@ EXPORT_SYMBOL(csum_partial_copy);
/*
* Functions to control caches.
*/
-EXPORT_SYMBOL(flush_page_to_ram);
-EXPORT_SYMBOL(flush_cache_all);
-EXPORT_SYMBOL(dma_cache_wback_inv);
-EXPORT_SYMBOL(dma_cache_inv);
+EXPORT_SYMBOL(_flush_page_to_ram);
+EXPORT_SYMBOL(_flush_cache_all);
+EXPORT_SYMBOL(_dma_cache_wback_inv);
+EXPORT_SYMBOL(_dma_cache_inv);
EXPORT_SYMBOL(invalid_pte_table);
diff --git a/arch/mips/lib/floppy-std.c b/arch/mips/lib/floppy-std.c
index 3d1c95feb..ada280d55 100644
--- a/arch/mips/lib/floppy-std.c
+++ b/arch/mips/lib/floppy-std.c
@@ -1,4 +1,4 @@
-/* $Id: floppy-std.c,v 1.3 1998/10/28 12:38:13 ralf Exp $
+/* $Id: floppy-std.c,v 1.2 1999/01/04 16:03:51 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
@@ -102,33 +102,18 @@ static unsigned long std_fd_getfdaddr1(void)
return 0x3f0;
}
-/* Pure 2^n version of get_order */
-static int __get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
static unsigned long std_fd_dma_mem_alloc(unsigned long size)
{
- int order = __get_order(size);
unsigned long mem;
- mem = __get_dma_pages(GFP_KERNEL,order);
+ mem = __get_dma_pages(GFP_KERNEL,get_order(size));
return mem;
}
static void std_fd_dma_mem_free(unsigned long addr, unsigned long size)
{
- free_pages(addr, __get_order(size));
+ free_pages(addr, get_order(size));
}
static unsigned long std_fd_drive_type(unsigned long n)
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index f0d34b0d6..d8929b93c 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -30,10 +30,6 @@ ifdef CONFIG_CPU_NEVADA
O_OBJS += r4xx0.o
endif
-ifdef CONFIG_CPU_R6000
-O_OBJS += r6000.o
-endif
-
ifdef CONFIG_SGI_IP22
O_OBJS += umap.o
endif
diff --git a/arch/mips/mm/andes.c b/arch/mips/mm/andes.c
index ab1715be3..d76b5f141 100644
--- a/arch/mips/mm/andes.c
+++ b/arch/mips/mm/andes.c
@@ -1,4 +1,4 @@
-/* $Id: andes.c,v 1.9 2000/01/27 01:05:23 ralf Exp $
+/* $Id: andes.c,v 1.10 2000/02/13 20:52:05 harald Exp $
*
* andes.c: MMU and cache operations for the R10000 (ANDES).
*
@@ -163,15 +163,15 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
void __init ld_mmu_andes(void)
{
- clear_page = andes_clear_page;
- copy_page = andes_copy_page;
+ _clear_page = andes_clear_page;
+ _copy_page = andes_copy_page;
- flush_cache_all = andes_flush_cache_all;
- flush_cache_mm = andes_flush_cache_mm;
- flush_cache_range = andes_flush_cache_range;
- flush_cache_page = andes_flush_cache_page;
- flush_cache_sigtramp = andes_flush_cache_sigtramp;
- flush_page_to_ram = andes_flush_page_to_ram;
+ _flush_cache_all = andes_flush_cache_all;
+ _flush_cache_mm = andes_flush_cache_mm;
+ _flush_cache_range = andes_flush_cache_range;
+ _flush_cache_page = andes_flush_cache_page;
+ _flush_cache_sigtramp = andes_flush_cache_sigtramp;
+ _flush_page_to_ram = andes_flush_page_to_ram;
flush_cache_all();
flush_tlb_all();
diff --git a/arch/mips/mm/loadmmu.c b/arch/mips/mm/loadmmu.c
index cf4816889..afbbef5eb 100644
--- a/arch/mips/mm/loadmmu.c
+++ b/arch/mips/mm/loadmmu.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
*
- * $Id: loadmmu.c,v 1.13 1999/10/09 00:00:58 ralf Exp $
+ * $Id: loadmmu.c,v 1.14 2000/01/27 01:05:23 ralf Exp $
*/
#include <linux/init.h>
#include <linux/kernel.h>
@@ -17,22 +17,22 @@
#include <asm/sgialib.h>
/* memory functions */
-void (*clear_page)(void * page);
-void (*copy_page)(void * to, void * from);
+void (*_clear_page)(void * page);
+void (*_copy_page)(void * to, void * from);
/* Cache operations. */
-void (*flush_cache_all)(void);
-void (*flush_cache_mm)(struct mm_struct *mm);
-void (*flush_cache_range)(struct mm_struct *mm, unsigned long start,
+void (*_flush_cache_all)(void);
+void (*_flush_cache_mm)(struct mm_struct *mm);
+void (*_flush_cache_range)(struct mm_struct *mm, unsigned long start,
unsigned long end);
-void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page);
-void (*flush_cache_sigtramp)(unsigned long addr);
-void (*flush_page_to_ram)(struct page * page);
+void (*_flush_cache_page)(struct vm_area_struct *vma, unsigned long page);
+void (*_flush_cache_sigtramp)(unsigned long addr);
+void (*_flush_page_to_ram)(struct page * page);
/* DMA cache operations. */
-void (*dma_cache_wback_inv)(unsigned long start, unsigned long size);
-void (*dma_cache_wback)(unsigned long start, unsigned long size);
-void (*dma_cache_inv)(unsigned long start, unsigned long size);
+void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size);
+void (*_dma_cache_wback)(unsigned long start, unsigned long size);
+void (*_dma_cache_inv)(unsigned long start, unsigned long size);
#ifdef CONFIG_CPU_R3000
extern void ld_mmu_r2300(void);
@@ -85,21 +85,6 @@ void __init loadmmu(void)
break;
#endif
-#ifdef CONFIG_CPU_R6000
- case CPU_R6000:
- case CPU_R6000A:
- printk("Loading R6000 MMU routines.\n");
- ld_mmu_r6000();
- break;
-#endif
-
-#ifdef CONFIG_CPU_R8000
- case CPU_R8000:
- printk("Loading TFP MMU routines.\n");
- ld_mmu_tfp();
- break;
-#endif
-
#ifdef CONFIG_CPU_R10000
case CPU_R10000:
printk("Loading R10000 MMU routines.\n");
diff --git a/arch/mips/mm/r2300.c b/arch/mips/mm/r2300.c
index 6c7126425..63d9b1f7b 100644
--- a/arch/mips/mm/r2300.c
+++ b/arch/mips/mm/r2300.c
@@ -7,7 +7,7 @@
* Copyright (C) 1998, 2000 Harald Koerfgen
* Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
*
- * $Id: r2300.c,v 1.13 2000/01/27 01:05:23 ralf Exp $
+ * $Id: r2300.c,v 1.14 2000/02/13 20:52:05 harald Exp $
*/
#include <linux/init.h>
#include <linux/kernel.h>
@@ -636,20 +636,20 @@ void __init ld_mmu_r2300(void)
{
printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID));
- clear_page = r3k_clear_page;
- copy_page = r3k_copy_page;
+ _clear_page = r3k_clear_page;
+ _copy_page = r3k_copy_page;
probe_icache();
probe_dcache();
- flush_cache_all = r3k_flush_cache_all;
- flush_cache_mm = r3k_flush_cache_mm;
- flush_cache_range = r3k_flush_cache_range;
- flush_cache_page = r3k_flush_cache_page;
- flush_cache_sigtramp = r3k_flush_cache_sigtramp;
- flush_page_to_ram = r3k_flush_page_to_ram;
+ _flush_cache_all = r3k_flush_cache_all;
+ _flush_cache_mm = r3k_flush_cache_mm;
+ _flush_cache_range = r3k_flush_cache_range;
+ _flush_cache_page = r3k_flush_cache_page;
+ _flush_cache_sigtramp = r3k_flush_cache_sigtramp;
+ _flush_page_to_ram = r3k_flush_page_to_ram;
- dma_cache_wback_inv = r3k_dma_cache_wback_inv;
+ _dma_cache_wback_inv = r3k_dma_cache_wback_inv;
flush_tlb_all();
}
diff --git a/arch/mips/mm/r4xx0.c b/arch/mips/mm/r4xx0.c
index 2896ddea9..bb377fb16 100644
--- a/arch/mips/mm/r4xx0.c
+++ b/arch/mips/mm/r4xx0.c
@@ -1,4 +1,4 @@
-/* $Id: r4xx0.c,v 1.27 2000/01/27 01:05:23 ralf Exp $
+/* $Id: r4xx0.c,v 1.28 2000/02/13 20:52:05 harald 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
@@ -2636,36 +2636,36 @@ static void __init setup_noscache_funcs(void)
switch(dc_lsize) {
case 16:
- clear_page = r4k_clear_page_d16;
- copy_page = r4k_copy_page_d16;
- flush_cache_all = r4k_flush_cache_all_d16i16;
- flush_cache_mm = r4k_flush_cache_mm_d16i16;
- flush_cache_range = r4k_flush_cache_range_d16i16;
- flush_cache_page = r4k_flush_cache_page_d16i16;
- flush_page_to_ram = r4k_flush_page_to_ram_d16i16;
+ _clear_page = r4k_clear_page_d16;
+ _copy_page = r4k_copy_page_d16;
+ _flush_cache_all = r4k_flush_cache_all_d16i16;
+ _flush_cache_mm = r4k_flush_cache_mm_d16i16;
+ _flush_cache_range = r4k_flush_cache_range_d16i16;
+ _flush_cache_page = r4k_flush_cache_page_d16i16;
+ _flush_page_to_ram = r4k_flush_page_to_ram_d16i16;
break;
case 32:
prid = read_32bit_cp0_register(CP0_PRID) & 0xfff0;
if (prid == 0x2010) { /* R4600 V1.7 */
- clear_page = r4k_clear_page_r4600_v1;
- copy_page = r4k_copy_page_r4600_v1;
+ _clear_page = r4k_clear_page_r4600_v1;
+ _copy_page = r4k_copy_page_r4600_v1;
} else if (prid == 0x2020) { /* R4600 V2.0 */
- clear_page = r4k_clear_page_r4600_v2;
- copy_page = r4k_copy_page_r4600_v2;
+ _clear_page = r4k_clear_page_r4600_v2;
+ _copy_page = r4k_copy_page_r4600_v2;
} else {
- clear_page = r4k_clear_page_d32;
- copy_page = r4k_copy_page_d32;
+ _clear_page = r4k_clear_page_d32;
+ _copy_page = r4k_copy_page_d32;
}
- flush_cache_all = r4k_flush_cache_all_d32i32;
- flush_cache_mm = r4k_flush_cache_mm_d32i32;
- flush_cache_range = r4k_flush_cache_range_d32i32;
- flush_cache_page = r4k_flush_cache_page_d32i32;
- flush_page_to_ram = r4k_flush_page_to_ram_d32i32;
+ _flush_cache_all = r4k_flush_cache_all_d32i32;
+ _flush_cache_mm = r4k_flush_cache_mm_d32i32;
+ _flush_cache_range = r4k_flush_cache_range_d32i32;
+ _flush_cache_page = r4k_flush_cache_page_d32i32;
+ _flush_page_to_ram = r4k_flush_page_to_ram_d32i32;
break;
}
- dma_cache_wback_inv = r4k_dma_cache_wback_inv_pc;
- dma_cache_wback = r4k_dma_cache_wback;
- dma_cache_inv = r4k_dma_cache_inv_pc;
+ _dma_cache_wback_inv = r4k_dma_cache_wback_inv_pc;
+ _dma_cache_wback = r4k_dma_cache_wback;
+ _dma_cache_inv = r4k_dma_cache_inv_pc;
}
static void __init setup_scache_funcs(void)
@@ -2674,82 +2674,82 @@ static void __init setup_scache_funcs(void)
case 16:
switch(dc_lsize) {
case 16:
- flush_cache_all = r4k_flush_cache_all_s16d16i16;
- flush_cache_mm = r4k_flush_cache_mm_s16d16i16;
- flush_cache_range = r4k_flush_cache_range_s16d16i16;
- flush_cache_page = r4k_flush_cache_page_s16d16i16;
- flush_page_to_ram = r4k_flush_page_to_ram_s16d16i16;
+ _flush_cache_all = r4k_flush_cache_all_s16d16i16;
+ _flush_cache_mm = r4k_flush_cache_mm_s16d16i16;
+ _flush_cache_range = r4k_flush_cache_range_s16d16i16;
+ _flush_cache_page = r4k_flush_cache_page_s16d16i16;
+ _flush_page_to_ram = r4k_flush_page_to_ram_s16d16i16;
break;
case 32:
panic("Invalid cache configuration detected");
};
- clear_page = r4k_clear_page_s16;
- copy_page = r4k_copy_page_s16;
+ _clear_page = r4k_clear_page_s16;
+ _copy_page = r4k_copy_page_s16;
break;
case 32:
switch(dc_lsize) {
case 16:
- flush_cache_all = r4k_flush_cache_all_s32d16i16;
- flush_cache_mm = r4k_flush_cache_mm_s32d16i16;
- flush_cache_range = r4k_flush_cache_range_s32d16i16;
- flush_cache_page = r4k_flush_cache_page_s32d16i16;
- flush_page_to_ram = r4k_flush_page_to_ram_s32d16i16;
+ _flush_cache_all = r4k_flush_cache_all_s32d16i16;
+ _flush_cache_mm = r4k_flush_cache_mm_s32d16i16;
+ _flush_cache_range = r4k_flush_cache_range_s32d16i16;
+ _flush_cache_page = r4k_flush_cache_page_s32d16i16;
+ _flush_page_to_ram = r4k_flush_page_to_ram_s32d16i16;
break;
case 32:
- flush_cache_all = r4k_flush_cache_all_s32d32i32;
- flush_cache_mm = r4k_flush_cache_mm_s32d32i32;
- flush_cache_range = r4k_flush_cache_range_s32d32i32;
- flush_cache_page = r4k_flush_cache_page_s32d32i32;
- flush_page_to_ram = r4k_flush_page_to_ram_s32d32i32;
+ _flush_cache_all = r4k_flush_cache_all_s32d32i32;
+ _flush_cache_mm = r4k_flush_cache_mm_s32d32i32;
+ _flush_cache_range = r4k_flush_cache_range_s32d32i32;
+ _flush_cache_page = r4k_flush_cache_page_s32d32i32;
+ _flush_page_to_ram = r4k_flush_page_to_ram_s32d32i32;
break;
};
- clear_page = r4k_clear_page_s32;
- copy_page = r4k_copy_page_s32;
+ _clear_page = r4k_clear_page_s32;
+ _copy_page = r4k_copy_page_s32;
break;
case 64:
switch(dc_lsize) {
case 16:
- flush_cache_all = r4k_flush_cache_all_s64d16i16;
- flush_cache_mm = r4k_flush_cache_mm_s64d16i16;
- flush_cache_range = r4k_flush_cache_range_s64d16i16;
- flush_cache_page = r4k_flush_cache_page_s64d16i16;
- flush_page_to_ram = r4k_flush_page_to_ram_s64d16i16;
+ _flush_cache_all = r4k_flush_cache_all_s64d16i16;
+ _flush_cache_mm = r4k_flush_cache_mm_s64d16i16;
+ _flush_cache_range = r4k_flush_cache_range_s64d16i16;
+ _flush_cache_page = r4k_flush_cache_page_s64d16i16;
+ _flush_page_to_ram = r4k_flush_page_to_ram_s64d16i16;
break;
case 32:
- flush_cache_all = r4k_flush_cache_all_s64d32i32;
- flush_cache_mm = r4k_flush_cache_mm_s64d32i32;
- flush_cache_range = r4k_flush_cache_range_s64d32i32;
- flush_cache_page = r4k_flush_cache_page_s64d32i32;
- flush_page_to_ram = r4k_flush_page_to_ram_s64d32i32;
+ _flush_cache_all = r4k_flush_cache_all_s64d32i32;
+ _flush_cache_mm = r4k_flush_cache_mm_s64d32i32;
+ _flush_cache_range = r4k_flush_cache_range_s64d32i32;
+ _flush_cache_page = r4k_flush_cache_page_s64d32i32;
+ _flush_page_to_ram = r4k_flush_page_to_ram_s64d32i32;
break;
};
- clear_page = r4k_clear_page_s64;
- copy_page = r4k_copy_page_s64;
+ _clear_page = r4k_clear_page_s64;
+ _copy_page = r4k_copy_page_s64;
break;
case 128:
switch(dc_lsize) {
case 16:
- flush_cache_all = r4k_flush_cache_all_s128d16i16;
- flush_cache_mm = r4k_flush_cache_mm_s128d16i16;
- flush_cache_range = r4k_flush_cache_range_s128d16i16;
- flush_cache_page = r4k_flush_cache_page_s128d16i16;
- flush_page_to_ram = r4k_flush_page_to_ram_s128d16i16;
+ _flush_cache_all = r4k_flush_cache_all_s128d16i16;
+ _flush_cache_mm = r4k_flush_cache_mm_s128d16i16;
+ _flush_cache_range = r4k_flush_cache_range_s128d16i16;
+ _flush_cache_page = r4k_flush_cache_page_s128d16i16;
+ _flush_page_to_ram = r4k_flush_page_to_ram_s128d16i16;
break;
case 32:
- flush_cache_all = r4k_flush_cache_all_s128d32i32;
- flush_cache_mm = r4k_flush_cache_mm_s128d32i32;
- flush_cache_range = r4k_flush_cache_range_s128d32i32;
- flush_cache_page = r4k_flush_cache_page_s128d32i32;
- flush_page_to_ram = r4k_flush_page_to_ram_s128d32i32;
+ _flush_cache_all = r4k_flush_cache_all_s128d32i32;
+ _flush_cache_mm = r4k_flush_cache_mm_s128d32i32;
+ _flush_cache_range = r4k_flush_cache_range_s128d32i32;
+ _flush_cache_page = r4k_flush_cache_page_s128d32i32;
+ _flush_page_to_ram = r4k_flush_page_to_ram_s128d32i32;
break;
};
- clear_page = r4k_clear_page_s128;
- copy_page = r4k_copy_page_s128;
+ _clear_page = r4k_clear_page_s128;
+ _copy_page = r4k_copy_page_s128;
break;
}
- dma_cache_wback_inv = r4k_dma_cache_wback_inv_sc;
- dma_cache_wback = r4k_dma_cache_wback;
- dma_cache_inv = r4k_dma_cache_inv_sc;
+ _dma_cache_wback_inv = r4k_dma_cache_wback_inv_sc;
+ _dma_cache_wback = r4k_dma_cache_wback;
+ _dma_cache_inv = r4k_dma_cache_inv_sc;
}
typedef int (*probe_func_t)(unsigned long);
@@ -2788,12 +2788,12 @@ void __init ld_mmu_r4xx0(void)
case CPU_R4700:
case CPU_R5000:
case CPU_NEVADA:
- flush_cache_page = r4k_flush_cache_page_d32i32_r4600;
+ _flush_cache_page = r4k_flush_cache_page_d32i32_r4600;
}
flush_cache_sigtramp = r4k_flush_cache_sigtramp;
if ((read_32bit_cp0_register(CP0_PRID) & 0xfff0) == 0x2020) {
- flush_cache_sigtramp = r4600v20k_flush_cache_sigtramp;
+ _flush_cache_sigtramp = r4600v20k_flush_cache_sigtramp;
}
flush_cache_all();
diff --git a/arch/mips/mm/r6000.c b/arch/mips/mm/r6000.c
deleted file mode 100644
index 364901d4d..000000000
--- a/arch/mips/mm/r6000.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/* $Id: r6000.c,v 1.9 2000/01/27 01:05:23 ralf Exp $
- *
- * r6000.c: MMU and cache routines for the R6000 processors.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-
-#include <asm/cacheops.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/sgialib.h>
-#include <asm/mmu_context.h>
-
-__asm__(".set mips2"); /* because we know... */
-
-/* page functions */
-void r6000_clear_page(void * page)
-{
- __asm__ __volatile__(
- ".set\tnoreorder\n\t"
- ".set\tnoat\n\t"
- "addiu\t$1,%0,%2\n"
- "1:\tsw\t$0,(%0)\n\t"
- "sw\t$0,4(%0)\n\t"
- "sw\t$0,8(%0)\n\t"
- "sw\t$0,12(%0)\n\t"
- "addiu\t%0,32\n\t"
- "sw\t$0,-16(%0)\n\t"
- "sw\t$0,-12(%0)\n\t"
- "sw\t$0,-8(%0)\n\t"
- "bne\t$1,%0,1b\n\t"
- "sw\t$0,-4(%0)\n\t"
- ".set\tat\n\t"
- ".set\treorder"
- :"=r" (page)
- :"0" (page),
- "I" (PAGE_SIZE)
- :"$1","memory");
-}
-
-static void r6000_copy_page(void * to, void * from)
-{
- unsigned long dummy1, dummy2;
- unsigned long reg1, reg2, reg3, reg4;
-
- __asm__ __volatile__(
- ".set\tnoreorder\n\t"
- ".set\tnoat\n\t"
- "addiu\t$1,%0,%8\n"
- "1:\tlw\t%2,(%1)\n\t"
- "lw\t%3,4(%1)\n\t"
- "lw\t%4,8(%1)\n\t"
- "lw\t%5,12(%1)\n\t"
- "sw\t%2,(%0)\n\t"
- "sw\t%3,4(%0)\n\t"
- "sw\t%4,8(%0)\n\t"
- "sw\t%5,12(%0)\n\t"
- "lw\t%2,16(%1)\n\t"
- "lw\t%3,20(%1)\n\t"
- "lw\t%4,24(%1)\n\t"
- "lw\t%5,28(%1)\n\t"
- "sw\t%2,16(%0)\n\t"
- "sw\t%3,20(%0)\n\t"
- "sw\t%4,24(%0)\n\t"
- "sw\t%5,28(%0)\n\t"
- "addiu\t%0,64\n\t"
- "addiu\t%1,64\n\t"
- "lw\t%2,-32(%1)\n\t"
- "lw\t%3,-28(%1)\n\t"
- "lw\t%4,-24(%1)\n\t"
- "lw\t%5,-20(%1)\n\t"
- "sw\t%2,-32(%0)\n\t"
- "sw\t%3,-28(%0)\n\t"
- "sw\t%4,-24(%0)\n\t"
- "sw\t%5,-20(%0)\n\t"
- "lw\t%2,-16(%1)\n\t"
- "lw\t%3,-12(%1)\n\t"
- "lw\t%4,-8(%1)\n\t"
- "lw\t%5,-4(%1)\n\t"
- "sw\t%2,-16(%0)\n\t"
- "sw\t%3,-12(%0)\n\t"
- "sw\t%4,-8(%0)\n\t"
- "bne\t$1,%0,1b\n\t"
- "sw\t%5,-4(%0)\n\t"
- ".set\tat\n\t"
- ".set\treorder"
- :"=r" (dummy1), "=r" (dummy2),
- "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
- :"0" (to), "1" (from),
- "I" (PAGE_SIZE));
-}
-
-/* Cache operations. XXX Write these dave... */
-static inline void r6000_flush_cache_all(void)
-{
- /* XXX */
-}
-
-static void r6000_flush_cache_mm(struct mm_struct *mm)
-{
- /* XXX */
-}
-
-static void r6000_flush_cache_range(struct mm_struct *mm,
- unsigned long start,
- unsigned long end)
-{
- /* XXX */
-}
-
-static void r6000_flush_cache_page(struct vm_area_struct *vma,
- unsigned long page)
-{
- /* XXX */
-}
-
-static void r6000_flush_page_to_ram(struct page * page)
-{
- /* XXX */
-}
-
-static void r6000_flush_cache_sigtramp(unsigned long page)
-{
- /* XXX */
-}
-
-/* TLB operations. XXX Write these dave... */
-void flush_tlb_all(void)
-{
- /* XXX */
-}
-
-void flush_tlb_mm(struct mm_struct *mm)
-{
- /* XXX */
-}
-
-void flush_tlb_range(struct mm_struct *mm, unsigned long start,
- unsigned long end)
-{
- /* XXX */
-}
-
-void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
-{
- /* XXX */
-}
-
-void load_pgd(unsigned long pg_dir)
-{
-}
-
-void pgd_init(unsigned long page)
-{
- unsigned long dummy1, dummy2;
-
- /*
- * The plain and boring version for the R3000. No cache flushing
- * stuff is implemented since the R3000 has physical caches.
- */
- __asm__ __volatile__(
- ".set\tnoreorder\n"
- "1:\tsw\t%2,(%0)\n\t"
- "sw\t%2,4(%0)\n\t"
- "sw\t%2,8(%0)\n\t"
- "sw\t%2,12(%0)\n\t"
- "sw\t%2,16(%0)\n\t"
- "sw\t%2,20(%0)\n\t"
- "sw\t%2,24(%0)\n\t"
- "sw\t%2,28(%0)\n\t"
- "subu\t%1,1\n\t"
- "bnez\t%1,1b\n\t"
- "addiu\t%0,32\n\t"
- ".set\treorder"
- :"=r" (dummy1),
- "=r" (dummy2)
- :"r" ((unsigned long) invalid_pte_table),
- "0" (page),
- "1" (PAGE_SIZE/(sizeof(pmd_t)*8)));
-}
-
-void update_mmu_cache(struct vm_area_struct * vma,
- unsigned long address, pte_t pte)
-{
- r6000_flush_tlb_page(vma, address);
- /*
- * FIXME: We should also reload a new entry into the TLB to
- * avoid unnecessary exceptions.
- */
-}
-
-void show_regs(struct pt_regs * regs)
-{
- /*
- * Saved main processor registers
- */
- printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
- 0, (unsigned long) regs->regs[1], (unsigned long) regs->regs[2],
- (unsigned long) regs->regs[3], (unsigned long) regs->regs[4],
- (unsigned long) regs->regs[5], (unsigned long) regs->regs[6],
- (unsigned long) regs->regs[7]);
- printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
- (unsigned long) regs->regs[8], (unsigned long) regs->regs[9],
- (unsigned long) regs->regs[10], (unsigned long) regs->regs[11],
- (unsigned long) regs->regs[12], (unsigned long) regs->regs[13],
- (unsigned long) regs->regs[14], (unsigned long) regs->regs[15]);
- printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
- (unsigned long) regs->regs[16], (unsigned long) regs->regs[17],
- (unsigned long) regs->regs[18], (unsigned long) regs->regs[19],
- (unsigned long) regs->regs[20], (unsigned long) regs->regs[21],
- (unsigned long) regs->regs[22], (unsigned long) regs->regs[23]);
- printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx\n",
- (unsigned long) regs->regs[24], (unsigned long) regs->regs[25],
- (unsigned long) regs->regs[28], (unsigned long) regs->regs[29],
- (unsigned long) regs->regs[30], (unsigned long) regs->regs[31]);
-
- /*
- * Saved cp0 registers
- */
- printk("epc : %08lx\nStatus: %08x\nCause : %08x\n",
- (unsigned long) regs->cp0_epc, (unsigned int) regs->cp0_status,
- (unsigned int) regs->cp0_cause);
-}
-
-void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
- unsigned long entryhi, unsigned long pagemask)
-{
- /* XXX */
-}
-
-void __init ld_mmu_r6000(void)
-{
- clear_page = r6000_clear_page;
- copy_page = r6000_copy_page;
-
- flush_cache_all = r6000_flush_cache_all;
- flush_cache_mm = r6000_flush_cache_mm;
- flush_cache_range = r6000_flush_cache_range;
- flush_cache_page = r6000_flush_cache_page;
- flush_cache_sigtramp = r6000_flush_cache_sigtramp;
- flush_page_to_ram = r6000_flush_page_to_ram;
-
- flush_cache_all();
- flush_tlb_all();
-}
diff --git a/arch/mips/mm/tfp.c b/arch/mips/mm/tfp.c
deleted file mode 100644
index 2aa0e91a5..000000000
--- a/arch/mips/mm/tfp.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/* $Id: tfp.c,v 1.9 2000/01/27 01:05:23 ralf Exp $
- *
- * tfp.c: MMU and cache routines specific to the r8000 (TFP).
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/sgialib.h>
-#include <asm/mmu_context.h>
-
-extern unsigned long mips_tlb_entries;
-
-/* Cache operations. XXX Write these dave... */
-static inline void tfp_flush_cache_all(void)
-{
- /* XXX */
-}
-
-static void tfp_flush_cache_mm(struct mm_struct *mm)
-{
- /* XXX */
-}
-
-static void tfp_flush_cache_range(struct mm_struct *mm,
- unsigned long start,
- unsigned long end)
-{
- /* XXX */
-}
-
-static void tfp_flush_cache_page(struct vm_area_struct *vma,
- unsigned long page)
-{
- /* XXX */
-}
-
-static void tfp_flush_page_to_ram(struct page * page)
-{
- /* XXX */
-}
-
-static void tfp_flush_cache_sigtramp(unsigned long page)
-{
- /* XXX */
-}
-
-/* TLB operations. XXX Write these dave... */
-void flush_tlb_all(void)
-{
- /* XXX */
-}
-
-void flush_tlb_mm(struct mm_struct *mm)
-{
- /* XXX */
-}
-
-void flush_tlb_range(struct mm_struct *mm, unsigned long start,
- unsigned long end)
-{
- /* XXX */
-}
-
-void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
-{
- /* XXX */
-}
-
-void load_pgd(unsigned long pg_dir)
-{
-}
-
-void pgd_init(unsigned long page)
-{
-}
-
-void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
- unsigned long entryhi, unsigned long pagemask)
-{
- /* XXX */
-}
-
-void __init ld_mmu_tfp(void)
-{
- flush_cache_all = tfp_flush_cache_all;
- flush_cache_mm = tfp_flush_cache_mm;
- flush_cache_range = tfp_flush_cache_range;
- flush_cache_page = tfp_flush_cache_page;
- flush_cache_sigtramp = tfp_flush_cache_sigtramp;
- flush_page_to_ram = tfp_flush_page_to_ram;
-
- flush_cache_all();
- flush_tlb_all();
-}
diff --git a/arch/mips/sni/dma.c b/arch/mips/sni/dma.c
index 26a7c0f0b..2f092abf4 100644
--- a/arch/mips/sni/dma.c
+++ b/arch/mips/sni/dma.c
@@ -1,4 +1,4 @@
-/* $Id: dma.c,v 1.1 2000/02/16 21:21:58 ralf Exp $
+/* $Id: dma.c,v 1.1 2000/02/18 00:24:30 ralf Exp $
*
* Dynamic DMA mapping support.
*
@@ -16,26 +16,12 @@
#include <linux/pci.h>
#include <asm/io.h>
-/* Pure 2^n version of get_order */
-extern __inline__ int __get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
dma_addr_t *dma_handle)
{
void *ret;
int gfp = GFP_ATOMIC;
- int order = __get_order(size);
+ int order = get_order(size);
if (hwdev == NULL || hwdev->dma_mask != 0xffffffff)
gfp |= GFP_DMA;
@@ -52,5 +38,5 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
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));
+ free_pages((unsigned long)vaddr, get_order(size));
}
diff --git a/arch/mips64/defconfig-ip22 b/arch/mips64/defconfig-ip22
index 1d8f9c8f6..9c6687735 100644
--- a/arch/mips64/defconfig-ip22
+++ b/arch/mips64/defconfig-ip22
@@ -246,7 +246,7 @@ CONFIG_VT_CONSOLE=y
# CONFIG_USB is not set
#
-# Filesystems
+# File systems
#
# CONFIG_QUOTA is not set
# CONFIG_AUTOFS_FS is not set
@@ -265,20 +265,17 @@ CONFIG_VT_CONSOLE=y
# 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_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
@@ -287,7 +284,6 @@ CONFIG_EXT2_FS=y
CONFIG_NFS_FS=y
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
diff --git a/arch/mips64/kernel/mips64_ksyms.c b/arch/mips64/kernel/mips64_ksyms.c
index 4fc755e39..eb1317ca3 100644
--- a/arch/mips64/kernel/mips64_ksyms.c
+++ b/arch/mips64/kernel/mips64_ksyms.c
@@ -1,4 +1,4 @@
-/* $Id: mips64_ksyms.c,v 1.6 2000/01/29 01:41:59 ralf Exp $
+/* $Id: mips64_ksyms.c,v 1.7 2000/02/04 07:40:24 ralf Exp $
*
* Export MIPS64-specific functions needed for loadable modules.
*
@@ -55,7 +55,7 @@ EXPORT_SYMBOL_NOVERS(strrchr);
EXPORT_SYMBOL_NOVERS(strtok);
EXPORT_SYMBOL_NOVERS(strpbrk);
-EXPORT_SYMBOL(clear_page);
+EXPORT_SYMBOL(_clear_page);
EXPORT_SYMBOL(local_bh_count);
EXPORT_SYMBOL(local_irq_count);
EXPORT_SYMBOL(enable_irq);
@@ -81,10 +81,10 @@ EXPORT_SYMBOL(csum_partial_copy);
/*
* Functions to control caches.
*/
-EXPORT_SYMBOL(flush_page_to_ram);
-EXPORT_SYMBOL(flush_cache_all);
-EXPORT_SYMBOL(dma_cache_wback_inv);
-EXPORT_SYMBOL(dma_cache_inv);
+EXPORT_SYMBOL(_flush_page_to_ram);
+EXPORT_SYMBOL(_flush_cache_all);
+EXPORT_SYMBOL(_dma_cache_wback_inv);
+EXPORT_SYMBOL(_dma_cache_inv);
EXPORT_SYMBOL(invalid_pte_table);
diff --git a/arch/mips64/kernel/traps.c b/arch/mips64/kernel/traps.c
index 825562342..5fe51a31c 100644
--- a/arch/mips64/kernel/traps.c
+++ b/arch/mips64/kernel/traps.c
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.10 1999/11/23 17:12:49 ralf Exp $
+/* $Id: traps.c,v 1.4 2000/01/20 23:50: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
@@ -22,6 +22,7 @@
#include <asm/pgtable.h>
#include <asm/io.h>
#include <asm/bootinfo.h>
+#include <asm/ptrace.h>
#include <asm/watch.h>
#include <asm/system.h>
#include <asm/uaccess.h>
diff --git a/arch/mips64/mm/Makefile b/arch/mips64/mm/Makefile
index db898cad4..fe95aff18 100644
--- a/arch/mips64/mm/Makefile
+++ b/arch/mips64/mm/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.3 1999/12/04 03:59:00 ralf Exp $
+# $Id: Makefile,v 1.4 2000/01/17 23:32:46 ralf Exp $
#
# Makefile for the Linux/MIPS-specific parts of the memory manager.
#
@@ -18,9 +18,6 @@ endif
ifdef CONFIG_CPU_NEVADA
O_OBJS += r4xx0.o
endif
-ifdef CONFIG_CPU_R8000
-O_OBJS += tfp.o
-endif
ifdef CONFIG_CPU_R10000
O_OBJS += andes.o
endif
diff --git a/arch/mips64/mm/andes.c b/arch/mips64/mm/andes.c
index 895e5db4a..401e07472 100644
--- a/arch/mips64/mm/andes.c
+++ b/arch/mips64/mm/andes.c
@@ -1,4 +1,4 @@
-/* $Id: andes.c,v 1.4 2000/01/17 23:32:46 ralf Exp $
+/* $Id: andes.c,v 1.5 2000/01/27 01:05:24 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
@@ -436,25 +436,25 @@ void __init ld_mmu_andes(void)
printk("Secondary cache sized at %ldK, linesize %ld\n",
scache_size() >> 10, sc_lsize());
- clear_page = andes_clear_page;
- copy_page = andes_copy_page;
+ _clear_page = andes_clear_page;
+ _copy_page = andes_copy_page;
- flush_cache_all = andes_flush_cache_all;
- flush_cache_mm = andes_flush_cache_mm;
- flush_cache_range = andes_flush_cache_range;
- flush_cache_page = andes_flush_cache_page;
- flush_cache_sigtramp = andes_flush_cache_sigtramp;
- flush_page_to_ram = andes_flush_page_to_ram;
+ _flush_cache_all = andes_flush_cache_all;
+ _flush_cache_mm = andes_flush_cache_mm;
+ _flush_cache_range = andes_flush_cache_range;
+ _flush_cache_page = andes_flush_cache_page;
+ _flush_cache_sigtramp = andes_flush_cache_sigtramp;
+ _flush_page_to_ram = andes_flush_page_to_ram;
- flush_tlb_all = andes_flush_tlb_all;
- flush_tlb_mm = andes_flush_tlb_mm;
- flush_tlb_range = andes_flush_tlb_range;
- flush_tlb_page = andes_flush_tlb_page;
+ _flush_tlb_all = andes_flush_tlb_all;
+ _flush_tlb_mm = andes_flush_tlb_mm;
+ _flush_tlb_range = andes_flush_tlb_range;
+ _flush_tlb_page = andes_flush_tlb_page;
update_mmu_cache = andes_update_mmu_cache;
- show_regs = andes_show_regs;
- user_mode = andes_user_mode;
+ _show_regs = andes_show_regs;
+ _user_mode = andes_user_mode;
flush_cache_all();
write_32bit_cp0_register(CP0_WIRED, 0);
diff --git a/arch/mips64/mm/loadmmu.c b/arch/mips64/mm/loadmmu.c
index b2dd9e11e..69f661c0b 100644
--- a/arch/mips64/mm/loadmmu.c
+++ b/arch/mips64/mm/loadmmu.c
@@ -1,4 +1,4 @@
-/* $Id: loadmmu.c,v 1.4 2000/01/17 23:32:46 ralf Exp $
+/* $Id: loadmmu.c,v 1.5 2000/01/27 01:05:24 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
@@ -21,40 +21,39 @@
#include <asm/sgialib.h>
/* memory functions */
-void (*clear_page)(void * page);
-void (*copy_page)(void * to, void * from);
+void (*_clear_page)(void * page);
+void (*_copy_page)(void * to, void * from);
/* Cache operations. */
-void (*flush_cache_all)(void);
-void (*flush_cache_mm)(struct mm_struct *mm);
-void (*flush_cache_range)(struct mm_struct *mm, unsigned long start,
- unsigned long end);
-void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page);
-void (*flush_cache_sigtramp)(unsigned long addr);
-void (*flush_page_to_ram)(struct page * page);
+void (*_flush_cache_all)(void);
+void (*_flush_cache_mm)(struct mm_struct *mm);
+void (*_flush_cache_range)(struct mm_struct *mm, unsigned long start,
+ unsigned long end);
+void (*_flush_cache_page)(struct vm_area_struct *vma, unsigned long page);
+void (*_flush_cache_sigtramp)(unsigned long addr);
+void (*_flush_page_to_ram)(struct page * page);
/* DMA cache operations. */
-void (*dma_cache_wback_inv)(unsigned long start, unsigned long size);
-void (*dma_cache_wback)(unsigned long start, unsigned long size);
-void (*dma_cache_inv)(unsigned long start, unsigned long size);
+void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size);
+void (*_dma_cache_wback)(unsigned long start, unsigned long size);
+void (*_dma_cache_inv)(unsigned long start, unsigned long size);
/* TLB operations. */
-void (*flush_tlb_all)(void);
-void (*flush_tlb_mm)(struct mm_struct *mm);
-void (*flush_tlb_range)(struct mm_struct *mm, unsigned long start,
+void (*_flush_tlb_all)(void);
+void (*_flush_tlb_mm)(struct mm_struct *mm);
+void (*_flush_tlb_range)(struct mm_struct *mm, unsigned long start,
unsigned long end);
-void (*flush_tlb_page)(struct vm_area_struct *vma, unsigned long page);
+void (*_flush_tlb_page)(struct vm_area_struct *vma, unsigned long page);
/* Miscellaneous. */
void (*update_mmu_cache)(struct vm_area_struct * vma,
unsigned long address, pte_t pte);
-void (*show_regs)(struct pt_regs *);
+void (*_show_regs)(struct pt_regs *);
-int (*user_mode)(struct pt_regs *);
+int (*_user_mode)(struct pt_regs *);
extern void ld_mmu_r4xx0(void);
-extern void ld_mmu_tfp(void);
extern void ld_mmu_andes(void);
void __init load_mmu(void)
@@ -84,13 +83,6 @@ void __init load_mmu(void)
break;
#endif
-#if defined (CONFIG_CPU_R8000)
- case CPU_R8000:
- printk("Loading TFP MMU routines.\n");
- ld_mmu_tfp();
- break;
-#endif
-
#if defined (CONFIG_CPU_R10000)
case CPU_R10000:
printk("Loading R10000 MMU routines.\n");
diff --git a/arch/mips64/mm/r4xx0.c b/arch/mips64/mm/r4xx0.c
index 4c85d6ba1..e8f19d4a5 100644
--- a/arch/mips64/mm/r4xx0.c
+++ b/arch/mips64/mm/r4xx0.c
@@ -1,4 +1,4 @@
-/* $Id: r4xx0.c,v 1.6 2000/01/17 23:32:46 ralf Exp $
+/* $Id: r4xx0.c,v 1.7 2000/01/27 01:05:24 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
@@ -2352,36 +2352,36 @@ static void __init setup_noscache_funcs(void)
switch(dc_lsize) {
case 16:
- clear_page = r4k_clear_page_d16;
- copy_page = r4k_copy_page_d16;
- flush_cache_all = r4k_flush_cache_all_d16i16;
- flush_cache_mm = r4k_flush_cache_mm_d16i16;
- flush_cache_range = r4k_flush_cache_range_d16i16;
- flush_cache_page = r4k_flush_cache_page_d16i16;
- flush_page_to_ram = r4k_flush_page_to_ram_d16i16;
+ _clear_page = r4k_clear_page_d16;
+ _copy_page = r4k_copy_page_d16;
+ _flush_cache_all = r4k_flush_cache_all_d16i16;
+ _flush_cache_mm = r4k_flush_cache_mm_d16i16;
+ _flush_cache_range = r4k_flush_cache_range_d16i16;
+ _flush_cache_page = r4k_flush_cache_page_d16i16;
+ _flush_page_to_ram = r4k_flush_page_to_ram_d16i16;
break;
case 32:
prid = read_32bit_cp0_register(CP0_PRID) & 0xfff0;
if (prid == 0x2010) { /* R4600 V1.7 */
- clear_page = r4k_clear_page_r4600_v1;
- copy_page = r4k_copy_page_r4600_v1;
+ _clear_page = r4k_clear_page_r4600_v1;
+ _copy_page = r4k_copy_page_r4600_v1;
} else if (prid == 0x2020) { /* R4600 V2.0 */
- clear_page = r4k_clear_page_r4600_v2;
- copy_page = r4k_copy_page_r4600_v2;
+ _clear_page = r4k_clear_page_r4600_v2;
+ _copy_page = r4k_copy_page_r4600_v2;
} else {
- clear_page = r4k_clear_page_d32;
- copy_page = r4k_copy_page_d32;
+ _clear_page = r4k_clear_page_d32;
+ _copy_page = r4k_copy_page_d32;
}
- flush_cache_all = r4k_flush_cache_all_d32i32;
- flush_cache_mm = r4k_flush_cache_mm_d32i32;
- flush_cache_range = r4k_flush_cache_range_d32i32;
- flush_cache_page = r4k_flush_cache_page_d32i32;
- flush_page_to_ram = r4k_flush_page_to_ram_d32i32;
+ _flush_cache_all = r4k_flush_cache_all_d32i32;
+ _flush_cache_mm = r4k_flush_cache_mm_d32i32;
+ _flush_cache_range = r4k_flush_cache_range_d32i32;
+ _flush_cache_page = r4k_flush_cache_page_d32i32;
+ _flush_page_to_ram = r4k_flush_page_to_ram_d32i32;
break;
}
- dma_cache_wback_inv = r4k_dma_cache_wback_inv_pc;
- dma_cache_wback = r4k_dma_cache_wback;
- dma_cache_inv = r4k_dma_cache_inv_pc;
+ _dma_cache_wback_inv = r4k_dma_cache_wback_inv_pc;
+ _dma_cache_wback = r4k_dma_cache_wback;
+ _dma_cache_inv = r4k_dma_cache_inv_pc;
}
static void __init setup_scache_funcs(void)
@@ -2390,82 +2390,82 @@ static void __init setup_scache_funcs(void)
case 16:
switch(dc_lsize) {
case 16:
- flush_cache_all = r4k_flush_cache_all_s16d16i16;
- flush_cache_mm = r4k_flush_cache_mm_s16d16i16;
- flush_cache_range = r4k_flush_cache_range_s16d16i16;
- flush_cache_page = r4k_flush_cache_page_s16d16i16;
- flush_page_to_ram = r4k_flush_page_to_ram_s16d16i16;
+ _flush_cache_all = r4k_flush_cache_all_s16d16i16;
+ _flush_cache_mm = r4k_flush_cache_mm_s16d16i16;
+ _flush_cache_range = r4k_flush_cache_range_s16d16i16;
+ _flush_cache_page = r4k_flush_cache_page_s16d16i16;
+ _flush_page_to_ram = r4k_flush_page_to_ram_s16d16i16;
break;
case 32:
panic("Invalid cache configuration detected");
};
- clear_page = r4k_clear_page_s16;
- copy_page = r4k_copy_page_s16;
+ _clear_page = r4k_clear_page_s16;
+ _copy_page = r4k_copy_page_s16;
break;
case 32:
switch(dc_lsize) {
case 16:
- flush_cache_all = r4k_flush_cache_all_s32d16i16;
- flush_cache_mm = r4k_flush_cache_mm_s32d16i16;
- flush_cache_range = r4k_flush_cache_range_s32d16i16;
- flush_cache_page = r4k_flush_cache_page_s32d16i16;
- flush_page_to_ram = r4k_flush_page_to_ram_s32d16i16;
+ _flush_cache_all = r4k_flush_cache_all_s32d16i16;
+ _flush_cache_mm = r4k_flush_cache_mm_s32d16i16;
+ _flush_cache_range = r4k_flush_cache_range_s32d16i16;
+ _flush_cache_page = r4k_flush_cache_page_s32d16i16;
+ _flush_page_to_ram = r4k_flush_page_to_ram_s32d16i16;
break;
case 32:
- flush_cache_all = r4k_flush_cache_all_s32d32i32;
- flush_cache_mm = r4k_flush_cache_mm_s32d32i32;
- flush_cache_range = r4k_flush_cache_range_s32d32i32;
- flush_cache_page = r4k_flush_cache_page_s32d32i32;
- flush_page_to_ram = r4k_flush_page_to_ram_s32d32i32;
+ _flush_cache_all = r4k_flush_cache_all_s32d32i32;
+ _flush_cache_mm = r4k_flush_cache_mm_s32d32i32;
+ _flush_cache_range = r4k_flush_cache_range_s32d32i32;
+ _flush_cache_page = r4k_flush_cache_page_s32d32i32;
+ _flush_page_to_ram = r4k_flush_page_to_ram_s32d32i32;
break;
};
- clear_page = r4k_clear_page_s32;
- copy_page = r4k_copy_page_s32;
+ _clear_page = r4k_clear_page_s32;
+ _copy_page = r4k_copy_page_s32;
break;
case 64:
switch(dc_lsize) {
case 16:
- flush_cache_all = r4k_flush_cache_all_s64d16i16;
- flush_cache_mm = r4k_flush_cache_mm_s64d16i16;
- flush_cache_range = r4k_flush_cache_range_s64d16i16;
- flush_cache_page = r4k_flush_cache_page_s64d16i16;
- flush_page_to_ram = r4k_flush_page_to_ram_s64d16i16;
+ _flush_cache_all = r4k_flush_cache_all_s64d16i16;
+ _flush_cache_mm = r4k_flush_cache_mm_s64d16i16;
+ _flush_cache_range = r4k_flush_cache_range_s64d16i16;
+ _flush_cache_page = r4k_flush_cache_page_s64d16i16;
+ _flush_page_to_ram = r4k_flush_page_to_ram_s64d16i16;
break;
case 32:
- flush_cache_all = r4k_flush_cache_all_s64d32i32;
- flush_cache_mm = r4k_flush_cache_mm_s64d32i32;
- flush_cache_range = r4k_flush_cache_range_s64d32i32;
- flush_cache_page = r4k_flush_cache_page_s64d32i32;
- flush_page_to_ram = r4k_flush_page_to_ram_s64d32i32;
+ _flush_cache_all = r4k_flush_cache_all_s64d32i32;
+ _flush_cache_mm = r4k_flush_cache_mm_s64d32i32;
+ _flush_cache_range = r4k_flush_cache_range_s64d32i32;
+ _flush_cache_page = r4k_flush_cache_page_s64d32i32;
+ _flush_page_to_ram = r4k_flush_page_to_ram_s64d32i32;
break;
};
- clear_page = r4k_clear_page_s64;
- copy_page = r4k_copy_page_s64;
+ _clear_page = r4k_clear_page_s64;
+ _copy_page = r4k_copy_page_s64;
break;
case 128:
switch(dc_lsize) {
case 16:
- flush_cache_all = r4k_flush_cache_all_s128d16i16;
- flush_cache_mm = r4k_flush_cache_mm_s128d16i16;
- flush_cache_range = r4k_flush_cache_range_s128d16i16;
- flush_cache_page = r4k_flush_cache_page_s128d16i16;
- flush_page_to_ram = r4k_flush_page_to_ram_s128d16i16;
+ _flush_cache_all = r4k_flush_cache_all_s128d16i16;
+ _flush_cache_mm = r4k_flush_cache_mm_s128d16i16;
+ _flush_cache_range = r4k_flush_cache_range_s128d16i16;
+ _flush_cache_page = r4k_flush_cache_page_s128d16i16;
+ _flush_page_to_ram = r4k_flush_page_to_ram_s128d16i16;
break;
case 32:
- flush_cache_all = r4k_flush_cache_all_s128d32i32;
- flush_cache_mm = r4k_flush_cache_mm_s128d32i32;
- flush_cache_range = r4k_flush_cache_range_s128d32i32;
- flush_cache_page = r4k_flush_cache_page_s128d32i32;
- flush_page_to_ram = r4k_flush_page_to_ram_s128d32i32;
+ _flush_cache_all = r4k_flush_cache_all_s128d32i32;
+ _flush_cache_mm = r4k_flush_cache_mm_s128d32i32;
+ _flush_cache_range = r4k_flush_cache_range_s128d32i32;
+ _flush_cache_page = r4k_flush_cache_page_s128d32i32;
+ _flush_page_to_ram = r4k_flush_page_to_ram_s128d32i32;
break;
};
- clear_page = r4k_clear_page_s128;
- copy_page = r4k_copy_page_s128;
+ _clear_page = r4k_clear_page_s128;
+ _copy_page = r4k_copy_page_s128;
break;
}
- dma_cache_wback_inv = r4k_dma_cache_wback_inv_sc;
- dma_cache_wback = r4k_dma_cache_wback;
- dma_cache_inv = r4k_dma_cache_inv_sc;
+ _dma_cache_wback_inv = r4k_dma_cache_wback_inv_sc;
+ _dma_cache_wback = r4k_dma_cache_wback;
+ _dma_cache_inv = r4k_dma_cache_inv_sc;
}
typedef int (*probe_func_t)(unsigned long);
@@ -2509,24 +2509,23 @@ void __init ld_mmu_r4xx0(void)
case CPU_R4700:
case CPU_R5000:
case CPU_NEVADA:
- flush_cache_page = r4k_flush_cache_page_d32i32_r4600;
+ _flush_cache_page = r4k_flush_cache_page_d32i32_r4600;
}
- flush_cache_sigtramp = r4k_flush_cache_sigtramp;
+ _flush_cache_sigtramp = r4k_flush_cache_sigtramp;
if ((read_32bit_cp0_register(CP0_PRID) & 0xfff0) == 0x2020) {
- flush_cache_sigtramp = r4600v20k_flush_cache_sigtramp;
+ _flush_cache_sigtramp = r4600v20k_flush_cache_sigtramp;
}
- flush_tlb_all = r4k_flush_tlb_all;
- flush_tlb_mm = r4k_flush_tlb_mm;
- flush_tlb_range = r4k_flush_tlb_range;
- flush_tlb_page = r4k_flush_tlb_page;
+ _flush_tlb_all = r4k_flush_tlb_all;
+ _flush_tlb_mm = r4k_flush_tlb_mm;
+ _flush_tlb_range = r4k_flush_tlb_range;
+ _flush_tlb_page = r4k_flush_tlb_page;
update_mmu_cache = r4k_update_mmu_cache;
- show_regs = r4k_show_regs;
-
- user_mode = r4k_user_mode;
+ _show_regs = r4k_show_regs;
+ _user_mode = r4k_user_mode;
flush_cache_all();
write_32bit_cp0_register(CP0_WIRED, 0);
diff --git a/arch/mips64/mm/tfp.c b/arch/mips64/mm/tfp.c
deleted file mode 100644
index ac38d97c8..000000000
--- a/arch/mips64/mm/tfp.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/* $Id: tfp.c,v 1.5 2000/01/17 23:32:46 ralf Exp $
- *
- * tfp.c: MMU and cache routines specific to the r8000 (TFP).
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/sgialib.h>
-#include <asm/mmu_context.h>
-
-static void tfp_clear_page(void * page)
-{
- __asm__ __volatile__(
- ".set\tnoreorder\n\t"
- ".set\tnoat\n\t"
- "daddiu\t$1,%0,%2\n"
- "1:\tsd\t$0,(%0)\n\t"
- "sd\t$0,8(%0)\n\t"
- "sd\t$0,16(%0)\n\t"
- "sd\t$0,24(%0)\n\t"
- "daddiu\t%0,64\n\t"
- "sd\t$0,-32(%0)\n\t"
- "sd\t$0,-24(%0)\n\t"
- "sd\t$0,-16(%0)\n\t"
- "bne\t$1,%0,1b\n\t"
- "sd\t$0,-8(%0)\n\t"
- ".set\tat\n\t"
- ".set\treorder"
- :"=r" (page)
- :"0" (page), "I" (PAGE_SIZE)
- :"$1", "memory");
-}
-
-static void tfp_copy_page(void * to, void * from)
-{
- unsigned long dummy1, dummy2, reg1, reg2;
-
- __asm__ __volatile__(
- ".set\tnoreorder\n\t"
- ".set\tnoat\n\t"
- "daddiu\t$1,%0,%6\n"
- "1:\tld\t%2,(%1)\n\t"
- "ld\t%3,8(%1)\n\t"
- "sd\t%2,(%0)\n\t"
- "sd\t%3,8(%0)\n\t"
- "ld\t%2,16(%1)\n\t"
- "ld\t%3,24(%1)\n\t"
- "sd\t%2,16(%0)\n\t"
- "sd\t%3,24(%0)\n\t"
- "daddiu\t%0,64\n\t"
- "daddiu\t%1,64\n\t"
- "ld\t%2,-32(%1)\n\t"
- "ld\t%3,-24(%1)\n\t"
- "sd\t%2,-32(%0)\n\t"
- "sd\t%3,-24(%0)\n\t"
- "ld\t%2,-16(%1)\n\t"
- "ld\t%3,-8(%1)\n\t"
- "sd\t%2,-16(%0)\n\t"
- "bne\t$1,%0,1b\n\t"
- " sd\t%3,-8(%0)\n\t"
- ".set\tat\n\t"
- ".set\treorder"
- :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2)
- :"0" (to), "1" (from), "I" (PAGE_SIZE));
-}
-
-/* Cache operations. XXX Write these dave... */
-static inline void tfp_flush_cache_all(void)
-{
- /* XXX */
-}
-
-static void tfp_flush_cache_mm(struct mm_struct *mm)
-{
- /* XXX */
-}
-
-static void tfp_flush_cache_range(struct mm_struct *mm,
- unsigned long start,
- unsigned long end)
-{
- /* XXX */
-}
-
-static void tfp_flush_cache_page(struct vm_area_struct *vma,
- unsigned long page)
-{
- /* XXX */
-}
-
-static void tfp_flush_page_to_ram(struct page * page)
-{
- /* XXX */
-}
-
-static void tfp_flush_cache_sigtramp(unsigned long page)
-{
- /* XXX */
-}
-
-/* TLB operations. XXX Write these dave... */
-static inline void tfp_flush_tlb_all(void)
-{
- /* XXX */
-}
-
-static void tfp_flush_tlb_mm(struct mm_struct *mm)
-{
- /* XXX */
-}
-
-static void tfp_flush_tlb_range(struct mm_struct *mm, unsigned long start,
- unsigned long end)
-{
- /* XXX */
-}
-
-static void tfp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
-{
- /* XXX */
-}
-
-static int tfp_user_mode(struct pt_regs *regs)
-{
- return (regs->cp0_status & ST0_KSU) == KSU_USER;
-}
-
-void __init ld_mmu_tfp(void)
-{
- clear_page = tfp_clear_page;
- copy_page = tfp_copy_page;
-
- flush_cache_all = tfp_flush_cache_all;
- flush_cache_mm = tfp_flush_cache_mm;
- flush_cache_range = tfp_flush_cache_range;
- flush_cache_page = tfp_flush_cache_page;
- flush_cache_sigtramp = tfp_flush_cache_sigtramp;
- flush_page_to_ram = tfp_flush_page_to_ram;
-
- flush_tlb_all = tfp_flush_tlb_all;
- flush_tlb_mm = tfp_flush_tlb_mm;
- flush_tlb_range = tfp_flush_tlb_range;
- flush_tlb_page = tfp_flush_tlb_page;
-
- user_mode = tfp_user_mode;
-
- flush_cache_all();
- flush_tlb_all();
-}
diff --git a/arch/mips64/sgi-ip22/ip22-berr.c b/arch/mips64/sgi-ip22/ip22-berr.c
index 32797fcf4..ecc3af198 100644
--- a/arch/mips64/sgi-ip22/ip22-berr.c
+++ b/arch/mips64/sgi-ip22/ip22-berr.c
@@ -1,4 +1,4 @@
-/* $Id: ip22-berr.c,v 1.1 2000/01/21 21:35:46 ralf Exp $
+/* $Id: ip22-berr.c,v 1.1 2000/01/21 22:34:03 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
@@ -12,6 +12,7 @@
#include <asm/uaccess.h>
#include <asm/paccess.h>
#include <asm/addrspace.h>
+#include <asm/ptrace.h>
extern asmlinkage void handle_ibe(void);
extern asmlinkage void handle_dbe(void);
diff --git a/arch/ppc/coffboot/misc.S b/arch/ppc/coffboot/misc.S
index 7defc69e8..05639bdd1 100644
--- a/arch/ppc/coffboot/misc.S
+++ b/arch/ppc/coffboot/misc.S
@@ -9,7 +9,7 @@
.text
/*
- * Use the BAT0 registers to map the 1st 8MB of RAM to
+ * Use the BAT3 registers to map the 1st 8MB of RAM to
* the address given as the 1st argument.
*/
.globl setup_bats
diff --git a/arch/ppc/config.in b/arch/ppc/config.in
index 8ea7e9000..8bb23afa2 100644
--- a/arch/ppc/config.in
+++ b/arch/ppc/config.in
@@ -97,7 +97,7 @@ fi
if [ "$CONFIG_6xx" = "y" -a "$CONFIG_APUS" != "y" ]; then
define_bool CONFIG_PCI y
fi
-if [ "$CONFIG_PREP" = "y" -o "$CONFIG_PMAC" = "y" -o "$CONFIG_CHRP" = "y" -o "$CONFIG_ALL_PPC" = "y"]; then
+if [ "$CONFIG_PREP" = "y" -o "$CONFIG_PMAC" = "y" -o "$CONFIG_CHRP" = "y" -o "$CONFIG_ALL_PPC" = "y" ]; then
define_bool CONFIG_PCI y
fi
diff --git a/arch/ppc/configs/common_defconfig b/arch/ppc/configs/common_defconfig
index ac258f16e..17217702f 100644
--- a/arch/ppc/configs/common_defconfig
+++ b/arch/ppc/configs/common_defconfig
@@ -24,7 +24,7 @@ CONFIG_ALL_PPC=y
# CONFIG_GEMINI is not set
# CONFIG_APUS is not set
# CONFIG_SMP is not set
-# CONFIG_ALTIVEC is not set
+CONFIG_ALTIVEC=y
#
# Loadable module support
@@ -76,7 +76,7 @@ CONFIG_BOOTX_TEXT=y
#
# Block devices
#
-CONFIG_BLK_DEV_FD=y
+# CONFIG_BLK_DEV_FD is not set
CONFIG_BLK_DEV_IDE=y
#
@@ -178,9 +178,12 @@ CONFIG_SCSI=y
# SCSI support type (disk, tape, CD-ROM)
#
CONFIG_BLK_DEV_SD=y
+CONFIG_SD_EXTRA_DEVS=40
CONFIG_CHR_DEV_ST=y
+CONFIG_ST_EXTRA_DEVS=2
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_SR_EXTRA_DEVS=2
CONFIG_CHR_DEV_SG=y
#
@@ -239,6 +242,7 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
# CONFIG_SCSI_QLOGIC_FAS is not set
# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_SEAGATE is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_T128 is not set
@@ -275,6 +279,7 @@ CONFIG_NETDEVICES=y
CONFIG_NET_ETHERNET=y
CONFIG_MACE=y
CONFIG_BMAC=y
+CONFIG_GMAC=y
# CONFIG_NCR885E is not set
# CONFIG_OAKNET is not set
# CONFIG_NET_VENDOR_3COM is not set
@@ -472,6 +477,7 @@ CONFIG_USB=y
# USB Controllers
#
# CONFIG_USB_UHCI is not set
+# CONFIG_USB_UHCI_ALT is not set
CONFIG_USB_OHCI=y
#
@@ -491,8 +497,7 @@ CONFIG_USB_OHCI=y
# CONFIG_USB_IBMCAM is not set
# CONFIG_USB_OV511 is not set
# CONFIG_USB_DC2XX is not set
-CONFIG_USB_SCSI=m
-CONFIG_USB_SCSI_DEBUG=y
+# CONFIG_USB_STORAGE is not set
# CONFIG_USB_DABUSB is not set
#
@@ -513,11 +518,15 @@ CONFIG_USB_MOUSE=y
#
# CONFIG_QUOTA is not set
CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS4_FS is not set
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
+CONFIG_HFS_FS=y
# CONFIG_BFS_FS is not set
-# CONFIG_FAT_FS is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_UMSDOS_FS is not set
+CONFIG_VFAT_FS=y
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
CONFIG_ISO9660_FS=y
@@ -549,10 +558,51 @@ CONFIG_LOCKD=y
#
# Partition Types
#
-# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
CONFIG_MAC_PARTITION=y
CONFIG_MSDOS_PARTITION=y
-# CONFIG_NLS is not set
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
#
# Sound
diff --git a/arch/ppc/configs/gemini_defconfig b/arch/ppc/configs/gemini_defconfig
index 6fe267c9a..90cc5b71f 100644
--- a/arch/ppc/configs/gemini_defconfig
+++ b/arch/ppc/configs/gemini_defconfig
@@ -24,7 +24,7 @@ CONFIG_6xx=y
CONFIG_GEMINI=y
# CONFIG_APUS is not set
# CONFIG_SMP is not set
-# CONFIG_ALTIVEC is not set
+CONFIG_ALTIVEC=y
CONFIG_MACH_SPECIFIC=y
#
@@ -87,7 +87,6 @@ CONFIG_KERNEL_ELF=y
# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_XD is not set
# CONFIG_BLK_DEV_DAC960 is not set
-CONFIG_PARIDE_PARPORT=y
# CONFIG_PARIDE is not set
# CONFIG_BLK_DEV_IDE_MODES is not set
# CONFIG_BLK_DEV_HD is not set
@@ -151,9 +150,12 @@ CONFIG_SCSI=y
# SCSI support type (disk, tape, CD-ROM)
#
CONFIG_BLK_DEV_SD=y
+CONFIG_SD_EXTRA_DEVS=40
# CONFIG_CHR_DEV_ST is not set
+CONFIG_ST_EXTRA_DEVS=2
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_SR_EXTRA_DEVS=2
# CONFIG_CHR_DEV_SG is not set
#
@@ -208,6 +210,7 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
# CONFIG_SCSI_QLOGIC_FAS is not set
# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_SEAGATE is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_T128 is not set
@@ -216,6 +219,7 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_MESH is not set
# CONFIG_SCSI_MAC53C94 is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
#
# IEEE 1394 (FireWire) support
@@ -242,6 +246,7 @@ CONFIG_NETDEVICES=y
CONFIG_NET_ETHERNET=y
# CONFIG_MACE is not set
# CONFIG_BMAC is not set
+# CONFIG_GMAC is not set
CONFIG_NCR885E=y
# CONFIG_OAKNET is not set
# CONFIG_NET_VENDOR_3COM is not set
@@ -369,6 +374,7 @@ CONFIG_UNIX98_PTY_COUNT=256
#
# CONFIG_QUOTA is not set
# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
@@ -405,10 +411,7 @@ CONFIG_LOCKD=y
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MAC_PARTITION=y
CONFIG_MSDOS_PARTITION=y
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
# CONFIG_NLS is not set
#
diff --git a/arch/ppc/defconfig b/arch/ppc/defconfig
index ac258f16e..17217702f 100644
--- a/arch/ppc/defconfig
+++ b/arch/ppc/defconfig
@@ -24,7 +24,7 @@ CONFIG_ALL_PPC=y
# CONFIG_GEMINI is not set
# CONFIG_APUS is not set
# CONFIG_SMP is not set
-# CONFIG_ALTIVEC is not set
+CONFIG_ALTIVEC=y
#
# Loadable module support
@@ -76,7 +76,7 @@ CONFIG_BOOTX_TEXT=y
#
# Block devices
#
-CONFIG_BLK_DEV_FD=y
+# CONFIG_BLK_DEV_FD is not set
CONFIG_BLK_DEV_IDE=y
#
@@ -178,9 +178,12 @@ CONFIG_SCSI=y
# SCSI support type (disk, tape, CD-ROM)
#
CONFIG_BLK_DEV_SD=y
+CONFIG_SD_EXTRA_DEVS=40
CONFIG_CHR_DEV_ST=y
+CONFIG_ST_EXTRA_DEVS=2
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_SR_EXTRA_DEVS=2
CONFIG_CHR_DEV_SG=y
#
@@ -239,6 +242,7 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
# CONFIG_SCSI_QLOGIC_FAS is not set
# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
# CONFIG_SCSI_SEAGATE is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_T128 is not set
@@ -275,6 +279,7 @@ CONFIG_NETDEVICES=y
CONFIG_NET_ETHERNET=y
CONFIG_MACE=y
CONFIG_BMAC=y
+CONFIG_GMAC=y
# CONFIG_NCR885E is not set
# CONFIG_OAKNET is not set
# CONFIG_NET_VENDOR_3COM is not set
@@ -472,6 +477,7 @@ CONFIG_USB=y
# USB Controllers
#
# CONFIG_USB_UHCI is not set
+# CONFIG_USB_UHCI_ALT is not set
CONFIG_USB_OHCI=y
#
@@ -491,8 +497,7 @@ CONFIG_USB_OHCI=y
# CONFIG_USB_IBMCAM is not set
# CONFIG_USB_OV511 is not set
# CONFIG_USB_DC2XX is not set
-CONFIG_USB_SCSI=m
-CONFIG_USB_SCSI_DEBUG=y
+# CONFIG_USB_STORAGE is not set
# CONFIG_USB_DABUSB is not set
#
@@ -513,11 +518,15 @@ CONFIG_USB_MOUSE=y
#
# CONFIG_QUOTA is not set
CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS4_FS is not set
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
+CONFIG_HFS_FS=y
# CONFIG_BFS_FS is not set
-# CONFIG_FAT_FS is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_UMSDOS_FS is not set
+CONFIG_VFAT_FS=y
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not set
CONFIG_ISO9660_FS=y
@@ -549,10 +558,51 @@ CONFIG_LOCKD=y
#
# Partition Types
#
-# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
CONFIG_MAC_PARTITION=y
CONFIG_MSDOS_PARTITION=y
-# CONFIG_NLS is not set
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
#
# Sound
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 2d1238a6b..013812afc 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -176,7 +176,7 @@ ret_from_syscall_2:
7: .string "syscall %d(%x, %x, %x, %x, %x, "
77: .string "%x, %x), current=%p\n"
79: .string " -> %x\n"
- .align 2
+ .align 2,0
#endif
/*
@@ -209,6 +209,9 @@ _GLOBAL(_switch)
mflr r20 /* Return to switch caller */
mfmsr r22
li r0,MSR_FP /* Disable floating-point */
+#ifdef CONFIG_ALTIVEC
+ oris r0,r0,MSR_VEC@h
+#endif /* CONFIG_ALTIVEC */
andc r22,r22,r0
stw r20,_NIP(r1)
stw r22,_MSR(r1)
@@ -274,7 +277,7 @@ _GLOBAL(_switch)
SYNC
rfi
-#ifdef __SMP__
+#ifdef CONFIG_SMP
.globl ret_from_smpfork
ret_from_smpfork:
bl schedule_tail
@@ -310,22 +313,32 @@ ret_from_except:
lwz r5,_MSR(r1)
andi. r5,r5,MSR_EE
beq 2f
+ .globl lost_irq_ret
+lost_irq_ret:
3: lis r4,ppc_n_lost_interrupts@ha
lwz r4,ppc_n_lost_interrupts@l(r4)
cmpi 0,r4,0
beq+ 1f
addi r3,r1,STACK_FRAME_OVERHEAD
bl do_IRQ
- .globl lost_irq_ret
-lost_irq_ret:
b 3b
-1: lis r4,bh_mask@ha
- lwz r4,bh_mask@l(r4)
- lis r5,bh_active@ha
- lwz r5,bh_active@l(r5)
- and. r4,r4,r5
+1: lis r4,softirq_state@ha
+ addi r4,r4,softirq_state@l
+#ifdef CONFIG_SMP
+ /* get processor # */
+ lwz r3,PROCESSOR(r2)
+#ifndef CONFIG_PPC64
+ slwi r3,r3,5
+#else
+#error not 64-bit ready
+#endif
+ add r4,r4,r3
+#endif /* CONFIG_SMP */
+ lwz r5,0(r4)
+ lwz r4,4(r4)
+ and. r5,r5,r4
beq+ 2f
- bl do_bottom_half
+ bl do_softirq
.globl do_bottom_half_ret
do_bottom_half_ret:
2: /* disable interrupts */
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index 8b56c635c..dd16b8c27 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -460,8 +460,24 @@ SystemCall:
STD_EXCEPTION(0xd00, SingleStep, SingleStepException)
STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
-#ifdef CONFIG_ALTIVEC
- STD_EXCEPTION(0xf20, AltiVec, AltiVecUnavailable)
+#ifndef CONFIG_ALTIVEC
+ STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+#else
+/*
+ * The Altivec unavailable trap is at 0x0f20. Foo.
+ * We effectively remap it to 0x3000.
+ */
+ . = 0xf00
+ b Trap_0f
+trap_0f_cont:
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r20,MSR_KERNEL
+ bl transfer_to_handler
+ .long UnknownException
+ .long ret_from_except
+
+ . = 0xf20
+ b AltiVecUnavailable
#endif /* CONFIG_ALTIVEC */
/*
@@ -674,6 +690,21 @@ DataStoreTLBMiss:
. = 0x3000
+#ifdef CONFIG_ALTIVEC
+AltiVecUnavailable:
+ EXCEPTION_PROLOG
+ bne load_up_altivec /* if from user, just load it up */
+ li r20,MSR_KERNEL
+ bl transfer_to_handler /* if from kernel, take a trap */
+ .long KernelAltiVec
+ .long ret_from_except
+
+/* here are the bits of trap 0xf00 which got displaced */
+Trap_0f:
+ EXCEPTION_PROLOG
+ b trap_0f_cont
+#endif /* CONFIG_ALTIVEC */
+
/*
* This code finishes saving the registers to the exception frame
* and jumps to the appropriate handler for the exception, turning
@@ -813,72 +844,134 @@ KernelFP:
86: .string "floating point used in kernel (task=%p, pc=%x)\n"
.align 4
+#ifdef CONFIG_ALTIVEC
+/* Note that the AltiVec support is closely modeled after the FP
+ * support. Changes to one are likely to be applicable to the
+ * other! */
+load_up_altivec:
/*
- * Take away the altivec regs.
- *
- * For now, ignore the vrsave regs and save them all
- * -- Cort
+ * Disable AltiVec for the task which had AltiVec previously,
+ * and save its AltiVec registers in its thread_struct.
+ * Enables AltiVec for use in the kernel on return.
+ * On SMP we know the AltiVec units are free, since we give it up every
+ * switch. -- Kumar
*/
- .globl giveup_altivec
-giveup_altivec:
-#ifdef CONFIG_ALTIVEC
- /* check for altivec */
- mfspr r4,PVR
- srwi r4,r4,16
- cmpi 0,r4,12
- bnelr
-
- /* enable altivec so we can save */
- mfmsr r4
- oris r4,r4,MSR_VEC@h
- mtmsr r4
+ mfmsr r5
+ oris r5,r5,MSR_VEC@h
+ SYNC
+ mtmsr r5 /* enable use of AltiVec now */
+ SYNC
+/*
+ * For SMP, we don't do lazy AltiVec switching because it just gets too
+ * horrendously complex, especially when a task switches from one CPU
+ * to another. Instead we call giveup_altivec in switch_to.
+ */
+#ifndef __SMP__
+#ifndef CONFIG_APUS
+ lis r6,-KERNELBASE@h
+#else
+ lis r6,CYBERBASEp@h
+ lwz r6,0(r6)
+#endif
+ addis r3,r6,last_task_used_altivec@ha
+ lwz r4,last_task_used_altivec@l(r3)
+ cmpi 0,r4,0
+ beq 1f
+ add r4,r4,r6
+ addi r4,r4,THREAD /* want THREAD of last_task_used_altivec */
+ SAVE_32VR(0,r20,r4)
+ MFVSCR(vr0)
+ li r20,THREAD_VSCR
+ STVX(vr0,r20,r4)
+ lwz r5,PT_REGS(r4)
+ add r5,r5,r6
+ lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+ lis r20,MSR_VEC@h
+ andc r4,r4,r20 /* disable altivec for previous task */
+ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#endif /* __SMP__ */
+ /* enable use of AltiVec after return */
+ oris r23,r23,MSR_VEC@h
+ mfspr r5,SPRG3 /* current task's THREAD (phys) */
+ li r20,THREAD_VSCR
+ LVX(vr0,r20,r5)
+ MTVSCR(vr0)
+ REST_32VR(0,r20,r5)
+#ifndef __SMP__
+ subi r4,r5,THREAD
+ sub r4,r4,r6
+ stw r4,last_task_used_altivec@l(r3)
+#endif /* __SMP__ */
+ /* restore registers and return */
+ lwz r3,_CCR(r21)
+ lwz r4,_LINK(r21)
+ mtcrf 0xff,r3
+ mtlr r4
+ REST_GPR(1, r21)
+ REST_4GPRS(3, r21)
+ /* we haven't used ctr or xer */
+ mtspr SRR1,r23
+ mtspr SRR0,r22
+ REST_GPR(20, r21)
+ REST_2GPRS(22, r21)
+ lwz r21,GPR21(r21)
+ SYNC
+ rfi
- /* make sure our tsk pointer is valid */
- cmpi 0,r3,0
- beqlr
+/*
+ * AltiVec unavailable trap from kernel - print a message, but let
+ * the task use AltiVec in the kernel until it returns to user mode.
+ */
+KernelAltiVec:
+ lwz r3,_MSR(r1)
+ oris r3,r3,MSR_VEC@h
+ stw r3,_MSR(r1) /* enable use of AltiVec after return */
+ lis r3,87f@h
+ ori r3,r3,87f@l
+ mr r4,r2 /* current */
+ lwz r5,_NIP(r1)
+ bl printk
+ b ret_from_except
+87: .string "AltiVec used in kernel (task=%p, pc=%x) \n"
+ .align 4
- /* save altivec regs */
- addi r4,r3,THREAD+THREAD_VRSAVE
- mfspr r5,256 /* vrsave */
- stw r5,0(r4)
-
- /* get regs for the task */
- addi r4,r3,THREAD+PT_REGS
- /* turn off the altivec bit in the tasks regs */
- lwz r5,_MSR(r4)
- lis r6,MSR_VEC@h
- andi. r5,r5,r6
- stw r5,_MSR(r4)
-
- /* we've given up the altivec - clear the pointer */
- li r3,0
- lis r4,last_task_used_altivec@h
- stw r3,last_task_used_altivec@l(r4)
-#endif /* CONFIG_ALTIVEC */
- blr
-
- .globl load_up_altivec
-load_up_altivec:
-#ifdef CONFIG_ALTIVEC
- /* check for altivec */
- mfspr r4,PVR
- srwi r4,r4,16
- cmpi 0,r4,12
- bnelr
-
- /* restore altivec regs */
- addi r4,r3,THREAD+THREAD_VRSAVE
- lwz r5,0(r4)
- mtspr 256,r5 /* vrsave */
-
- /* get regs for the task */
- addi r4,r3,THREAD+PT_REGS
- /* turn on the altivec bit in the tasks regs */
- lwz r5,_MSR(r4)
+/*
+ * giveup_altivec(tsk)
+ * Disable AltiVec for the task given as the argument,
+ * and save the AltiVec registers in its thread_struct.
+ * Enables AltiVec for use in the kernel on return.
+ */
+
+ .globl giveup_altivec
+giveup_altivec:
+ mfmsr r5
oris r5,r5,MSR_VEC@h
- stw r5,_MSR(r4)
-#endif /* CONFIG_ALTIVEC */
+ SYNC
+ mtmsr r5 /* enable use of AltiVec now */
+ SYNC
+ cmpi 0,r3,0
+ beqlr- /* if no previous owner, done */
+ addi r3,r3,THREAD /* want THREAD of task */
+ lwz r5,PT_REGS(r3)
+ cmpi 0,r5,0
+ SAVE_32VR(0, r4, r3)
+ MFVSCR(vr0)
+ li r4,THREAD_VSCR
+ STVX(vr0, r4, r3)
+ beq 1f
+ lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+ lis r3,MSR_VEC@h
+ andc r4,r4,r3 /* disable AltiVec for previous task */
+ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
+#ifndef __SMP__
+ li r5,0
+ lis r4,last_task_used_altivec@ha
+ stw r5,last_task_used_altivec@l(r4)
+#endif /* __SMP__ */
blr
+#endif /* CONFIG_ALTIVEC */
/*
* giveup_fpu(tsk)
@@ -1437,17 +1530,16 @@ mmu_off:
#if 0 /* That's useful debug stuff */
setup_screen_bat:
+ li r3,0
+ mtspr DBAT1U,r3
+ mtspr IBAT1U,r3
lis r3, 0x9100
-#ifdef __SMP__
- ori r3,r3,0x12
-#else
- ori r3,r3,0x2
-#endif
- mtspr DBAT1L, r3
- mtspr IBAT1L, r3
+ ori r4,r3,0x2a
+ mtspr DBAT1L,r4
+ mtspr IBAT1L,r4
ori r3,r3,(BL_8M<<2)|0x2 /* set up BAT registers for 604 */
- mtspr DBAT1U, r3
- mtspr IBAT1U, r3
+ mtspr DBAT1U,r3
+ mtspr IBAT1U,r3
blr
#endif
diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
index 8b5f590fb..fd77fbc36 100644
--- a/arch/ppc/kernel/irq.c
+++ b/arch/ppc/kernel/irq.c
@@ -74,8 +74,8 @@ volatile unsigned char *chrp_int_ack_special;
irq_desc_t irq_desc[NR_IRQS];
int ppc_spurious_interrupts = 0;
-unsigned int ppc_local_bh_count[NR_CPUS];
-unsigned int ppc_local_irq_count[NR_CPUS];
+unsigned int local_bh_count[NR_CPUS];
+unsigned int local_irq_count[NR_CPUS];
struct irqaction *ppc_irq_action[NR_IRQS];
unsigned int ppc_cached_irq_mask[NR_MASK_WORDS];
unsigned int ppc_lost_interrupts[NR_MASK_WORDS];
@@ -350,7 +350,6 @@ unsigned volatile int global_irq_lock;
atomic_t global_irq_count;
atomic_t global_bh_count;
-atomic_t global_bh_lock;
static void show(char * str)
{
@@ -361,12 +360,12 @@ static void show(char * str)
printk("\n%s, CPU %d:\n", str, cpu);
printk("irq: %d [%d %d]\n",
atomic_read(&global_irq_count),
- ppc_local_irq_count[0],
- ppc_local_irq_count[1]);
+ local_irq_count[0],
+ local_irq_count[1]);
printk("bh: %d [%d %d]\n",
atomic_read(&global_bh_count),
- ppc_local_bh_count[0],
- ppc_local_bh_count[1]);
+ local_bh_count[0],
+ local_bh_count[1]);
stack = (unsigned long *) &str;
for (i = 40; i ; i--) {
unsigned long x = *++stack;
@@ -401,7 +400,7 @@ static inline void wait_on_irq(int cpu)
* already executing in one..
*/
if (!atomic_read(&global_irq_count)) {
- if (ppc_local_bh_count[cpu]
+ if (local_bh_count[cpu]
|| !atomic_read(&global_bh_count))
break;
}
@@ -423,7 +422,7 @@ static inline void wait_on_irq(int cpu)
continue;
if (global_irq_lock)
continue;
- if (!ppc_local_bh_count[cpu]
+ if (!local_bh_count[cpu]
&& atomic_read(&global_bh_count))
continue;
if (!test_and_set_bit(0,&global_irq_lock))
@@ -514,7 +513,7 @@ void __global_cli(void)
if (flags & (1 << 15)) {
int cpu = smp_processor_id();
__cli();
- if (!ppc_local_irq_count[cpu])
+ if (!local_irq_count[cpu])
get_irqlock(cpu);
}
}
@@ -523,7 +522,7 @@ void __global_sti(void)
{
int cpu = smp_processor_id();
- if (!ppc_local_irq_count[cpu])
+ if (!local_irq_count[cpu])
release_irqlock(cpu);
__sti();
}
@@ -547,7 +546,7 @@ unsigned long __global_save_flags(void)
retval = 2 + local_enabled;
/* check for global flags if we're not in an interrupt */
- if (!ppc_local_irq_count[smp_processor_id()]) {
+ if (!local_irq_count[smp_processor_id()]) {
if (local_enabled)
retval = 1;
if (global_irq_holder == (unsigned char) smp_processor_id())
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index fde7112c7..50f63eeb4 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -229,7 +229,7 @@ _GLOBAL(flush_dcache_range)
blr
/*
- * Flush a particular page from the DATA cache
+ * Flush a particular page from the data cache to RAM.
* Note: this is necessary because the instruction cache does *not*
* snoop from the data cache.
* This is a no-op on the 601 which has a unified cache.
@@ -241,18 +241,31 @@ _GLOBAL(__flush_page_to_ram)
rlwinm r5,r5,16,16,31
cmpi 0,r5,1
beqlr /* for 601, do nothing */
- li r4,0x0FFF
- andc r3,r3,r4 /* Get page base address */
li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
mtctr r4
- mr r6,r3
0: dcbst 0,r3 /* Write line to ram */
addi r3,r3,CACHE_LINE_SIZE
bdnz 0b
sync
+ blr
+
+/*
+ * Flush a particular page from the instruction cache.
+ * Note: this is necessary because the instruction cache does *not*
+ * snoop from the data cache.
+ * This is a no-op on the 601 which has a unified cache.
+ *
+ * void __flush_icache_page(void *page)
+ */
+_GLOBAL(__flush_icache_page)
+ mfspr r5,PVR
+ rlwinm r5,r5,16,16,31
+ cmpi 0,r5,1
+ beqlr /* for 601, do nothing */
+ li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
mtctr r4
-1: icbi 0,r6
- addi r6,r6,CACHE_LINE_SIZE
+1: icbi 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
bdnz 1b
sync
isync
@@ -272,6 +285,38 @@ _GLOBAL(clear_page)
blr
/*
+ * Copy a whole page. We use the dcbz instruction on the destination
+ * to reduce memory traffic (it eliminates the unnecessary reads of
+ * the destination into cache). This requires that the destination
+ * is cacheable.
+ */
+_GLOBAL(copy_page)
+ li r0,4096/CACHE_LINE_SIZE
+ mtctr r0
+ addi r3,r3,-4
+ addi r4,r4,-4
+ li r5,4
+1: dcbz r5,r3
+ lwz r6,4(r4)
+ lwz r7,8(r4)
+ lwz r8,12(r4)
+ lwzu r9,16(r4)
+ stw r6,4(r3)
+ stw r7,8(r3)
+ stw r8,12(r3)
+ stwu r9,16(r3)
+ lwz r6,4(r4)
+ lwz r7,8(r4)
+ lwz r8,12(r4)
+ lwzu r9,16(r4)
+ stw r6,4(r3)
+ stw r7,8(r3)
+ stw r8,12(r3)
+ stwu r9,16(r3)
+ bdnz 1b
+ blr
+
+/*
* Atomic [test&set] exchange
*
* unsigned long xchg_u32(void *ptr, unsigned long val)
diff --git a/arch/ppc/kernel/mk_defs.c b/arch/ppc/kernel/mk_defs.c
index 34682bd2a..4f3c6834d 100644
--- a/arch/ppc/kernel/mk_defs.c
+++ b/arch/ppc/kernel/mk_defs.c
@@ -9,6 +9,7 @@
*/
#include <stddef.h>
+#include <linux/config.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -48,9 +49,11 @@ main(void)
DEFINE(NEED_RESCHED, offsetof(struct task_struct, need_resched));
DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr));
- DEFINE(THREAD_VRF, offsetof(struct thread_struct, vrf));
- DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr));
+#ifdef CONFIG_ALTIVEC
+ DEFINE(THREAD_VR0, offsetof(struct thread_struct, vr[0]));
DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave));
+ DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr));
+#endif /* CONFIG_ALTIVEC */
/* Interrupt register frame */
DEFINE(TASK_UNION_SIZE, sizeof(union task_union));
DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
diff --git a/arch/ppc/kernel/open_pic.c b/arch/ppc/kernel/open_pic.c
index d4dbe05e5..301a82ba8 100644
--- a/arch/ppc/kernel/open_pic.c
+++ b/arch/ppc/kernel/open_pic.c
@@ -279,7 +279,7 @@ void __init openpic_init(int main_pic)
/* Initialize the spurious interrupt */
if ( ppc_md.progress ) ppc_md.progress("openpic spurious",0x3bd);
openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
- if ( !(_machine && (_MACH_gemini|_MACH_Pmac)) )
+ if ( !(_machine & (_MACH_gemini|_MACH_Pmac)) )
{
if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
"82c59 cascade", NULL))
@@ -490,7 +490,7 @@ void openpic_enable_irq(u_int irq)
/* make sure mask gets to controller before we return to user */
do {
mb(); /* sync is probably useless here */
- } while(openpic_readfield(&OpenPIC->Source[irq].Vector_Priority,
+ } while(openpic_readfield(&ISU[irq - open_pic_irq_offset].Vector_Priority,
OPENPIC_MASK));
}
@@ -501,7 +501,7 @@ void openpic_disable_irq(u_int irq)
/* make sure mask gets to controller before we return to user */
do {
mb(); /* sync is probably useless here */
- } while(!openpic_readfield(&OpenPIC->Source[irq].Vector_Priority,
+ } while(!openpic_readfield(&ISU[irq - open_pic_irq_offset].Vector_Priority,
OPENPIC_MASK));
}
diff --git a/arch/ppc/kernel/pci-dma.c b/arch/ppc/kernel/pci-dma.c
index 089566908..174de223f 100644
--- a/arch/ppc/kernel/pci-dma.c
+++ b/arch/ppc/kernel/pci-dma.c
@@ -14,20 +14,6 @@
#include <linux/pci.h>
#include <asm/io.h>
-/* Pure 2^n version of get_order */
-extern __inline__ int __get_order(unsigned long size)
-{
- int order;
-
- size = (size-1) >> (PAGE_SHIFT-1);
- order = -1;
- do {
- size >>= 1;
- order++;
- } while (size);
- return order;
-}
-
void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
dma_addr_t *dma_handle)
{
@@ -36,7 +22,7 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
if (hwdev == NULL || hwdev->dma_mask != 0xffffffff)
gfp |= GFP_DMA;
- ret = (void *)__get_free_pages(gfp, __get_order(size));
+ ret = (void *)__get_free_pages(gfp, get_order(size));
if (ret != NULL) {
memset(ret, 0, size);
@@ -48,5 +34,5 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
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));
+ free_pages((unsigned long)vaddr, get_order(size));
}
diff --git a/arch/ppc/kernel/pmac_pic.c b/arch/ppc/kernel/pmac_pic.c
index d2d5e6b25..d13875c9f 100644
--- a/arch/ppc/kernel/pmac_pic.c
+++ b/arch/ppc/kernel/pmac_pic.c
@@ -31,8 +31,6 @@ static int max_irqs;
static int max_real_irqs;
static int has_openpic = 0;
-#define MAXCOUNT 10000000
-
#define GATWICK_IRQ_POOL_SIZE 10
static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE];
@@ -187,25 +185,6 @@ pmac_get_irq(struct pt_regs *regs)
smp_message_recv();
return -2; /* ignore, already handled */
}
-
- {
- unsigned int loops = MAXCOUNT;
- while (test_bit(0, &global_irq_lock)) {
- if (smp_processor_id() == global_irq_holder) {
- printk("uh oh, interrupt while we hold global irq lock!\n");
-#ifdef CONFIG_XMON
- xmon(0);
-#endif
- break;
- }
- if (loops-- == 0) {
- printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
-#ifdef CONFIG_XMON
- xmon(0);
-#endif
- }
- }
- }
#endif /* __SMP__ */
/* Yeah, I know, this could be a separate do_IRQ function */
diff --git a/arch/ppc/kernel/pmac_setup.c b/arch/ppc/kernel/pmac_setup.c
index e1c1815ac..5fef07e89 100644
--- a/arch/ppc/kernel/pmac_setup.c
+++ b/arch/ppc/kernel/pmac_setup.c
@@ -60,6 +60,7 @@
#include <asm/machdep.h>
#include <asm/keyboard.h>
#include <asm/dma.h>
+#include <asm/bootx.h>
#include "time.h"
#include "local_irq.h"
@@ -440,6 +441,7 @@ kdev_t __init find_ide_boot(void)
{
char *p;
int n;
+ kdev_t __init pmac_find_ide_boot(char *bootdevice, int n);
if (bootdevice == NULL)
return 0;
@@ -695,9 +697,12 @@ pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
#ifdef CONFIG_BOOTX_TEXT
extern void drawchar(char c);
extern void drawstring(const char *c);
+extern boot_infos_t *disp_bi;
void
pmac_progress(char *s, unsigned short hex)
{
+ if (disp_bi == 0)
+ return;
drawstring(s);
drawchar('\n');
}
diff --git a/arch/ppc/kernel/pmac_time.c b/arch/ppc/kernel/pmac_time.c
index 1c935a625..3b7dd283f 100644
--- a/arch/ppc/kernel/pmac_time.c
+++ b/arch/ppc/kernel/pmac_time.c
@@ -71,8 +71,8 @@ unsigned long pmac_get_rtc_time(void)
if (req.reply_len != 7)
printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
req.reply_len);
- return (unsigned long)(req.reply[1] << 24) + (req.reply[2] << 16)
- + (req.reply[3] << 8) + (unsigned long)req.reply[4] - RTC_OFFSET;
+ return (req.reply[3] << 24) + (req.reply[4] << 16)
+ + (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET;
#endif /* CONFIG_ADB_CUDA */
#ifdef CONFIG_ADB_PMU
case SYS_CTRLER_PMU:
diff --git a/arch/ppc/kernel/ppc_asm.h b/arch/ppc/kernel/ppc_asm.h
index 2b999ab36..d9093c9e1 100644
--- a/arch/ppc/kernel/ppc_asm.h
+++ b/arch/ppc/kernel/ppc_asm.h
@@ -44,6 +44,28 @@
#define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, base)
#define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n+16, base)
+/*
+ * Once a version of gas that understands the AltiVec instructions
+ * is freely available, we can do this the normal way... - paulus
+ */
+#define LVX(r,a,b) .long (31<<26)+((r)<<21)+((a)<<16)+((b)<<11)+(103<<1)
+#define STVX(r,a,b) .long (31<<26)+((r)<<21)+((a)<<16)+((b)<<11)+(231<<1)
+#define MFVSCR(r) .long (4<<26)+((r)<<21)+(1540<<1)
+#define MTVSCR(r) .long (4<<26)+((r)<<11)+(802<<1)
+
+#define SAVE_VR(n,b,base) li b,THREAD_VR0+(16*(n)); STVX(n,b,base)
+#define SAVE_2VR(n,b,base) SAVE_VR(n,b,base); SAVE_VR(n+1,b,base)
+#define SAVE_4VR(n,b,base) SAVE_2VR(n,b,base); SAVE_2VR(n+2,b,base)
+#define SAVE_8VR(n,b,base) SAVE_4VR(n,b,base); SAVE_4VR(n+4,b,base)
+#define SAVE_16VR(n,b,base) SAVE_8VR(n,b,base); SAVE_8VR(n+8,b,base)
+#define SAVE_32VR(n,b,base) SAVE_16VR(n,b,base); SAVE_16VR(n+16,b,base)
+#define REST_VR(n,b,base) li b,THREAD_VR0+(16*(n)); LVX(n,b,base)
+#define REST_2VR(n,b,base) REST_VR(n,b,base); REST_VR(n+1,b,base)
+#define REST_4VR(n,b,base) REST_2VR(n,b,base); REST_2VR(n+2,b,base)
+#define REST_8VR(n,b,base) REST_4VR(n,b,base); REST_4VR(n+4,b,base)
+#define REST_16VR(n,b,base) REST_8VR(n,b,base); REST_8VR(n+8,b,base)
+#define REST_32VR(n,b,base) REST_16VR(n,b,base); REST_16VR(n+16,b,base)
+
#define SYNC \
sync; \
isync
diff --git a/arch/ppc/kernel/ppc_asm.tmpl b/arch/ppc/kernel/ppc_asm.tmpl
index 94a5bd74c..c35192bb4 100644
--- a/arch/ppc/kernel/ppc_asm.tmpl
+++ b/arch/ppc/kernel/ppc_asm.tmpl
@@ -80,3 +80,36 @@
#define fr29 29
#define fr30 30
#define fr31 31
+
+#define vr0 0
+#define vr1 1
+#define vr2 2
+#define vr3 3
+#define vr4 4
+#define vr5 5
+#define vr6 6
+#define vr7 7
+#define vr8 8
+#define vr9 9
+#define vr10 10
+#define vr11 11
+#define vr12 12
+#define vr13 13
+#define vr14 14
+#define vr15 15
+#define vr16 16
+#define vr17 17
+#define vr18 18
+#define vr19 19
+#define vr20 20
+#define vr21 21
+#define vr22 22
+#define vr23 23
+#define vr24 24
+#define vr25 25
+#define vr26 26
+#define vr27 27
+#define vr28 28
+#define vr29 29
+#define vr30 30
+#define vr31 31
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 9a5444a51..757715512 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -11,6 +11,7 @@
#include <linux/spinlock.h>
#include <linux/console.h>
#include <linux/irq.h>
+#include <linux/pci.h>
#include <asm/page.h>
#include <asm/semaphore.h>
@@ -72,8 +73,8 @@ EXPORT_SYMBOL(do_lost_interrupts);
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(disable_irq_nosync);
-EXPORT_SYMBOL(ppc_local_irq_count);
-EXPORT_SYMBOL(ppc_local_bh_count);
+EXPORT_SYMBOL(local_irq_count);
+EXPORT_SYMBOL(local_bh_count);
#ifdef __SMP__
EXPORT_SYMBOL(kernel_flag);
#endif /* __SMP__ */
@@ -171,6 +172,11 @@ EXPORT_SYMBOL(chrp_ide_regbase);
EXPORT_SYMBOL(chrp_ide_probe);
#endif
+#ifdef CONFIG_PCI
+EXPORT_SYMBOL(pci_alloc_consistent);
+EXPORT_SYMBOL(pci_free_consistent);
+#endif /* CONFIG_PCI */
+
EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(kernel_thread);
@@ -272,4 +278,3 @@ EXPORT_SYMBOL(ppc_irq_dispatch_handler);
EXPORT_SYMBOL(decrementer_count);
EXPORT_SYMBOL(get_wchan);
EXPORT_SYMBOL(console_drivers);
-EXPORT_SYMBOL(do_bottom_half);
diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
index ed98ba6f0..41382b2d7 100644
--- a/arch/ppc/kernel/process.c
+++ b/arch/ppc/kernel/process.c
@@ -19,6 +19,7 @@
*
*/
+#include <linux/config.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -140,15 +141,31 @@ int check_stack(struct task_struct *tsk)
}
#endif /* defined(CHECK_STACK) */
+#ifdef CONFIG_ALTIVEC
int
-dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs)
+dump_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
{
- if (regs->msr & MSR_FP)
- giveup_fpu(current);
- memcpy(fpregs, &current->thread.fpr[0], sizeof(*fpregs));
+ if (regs->msr & MSR_VEC)
+ giveup_altivec(current);
+ memcpy(vrregs, &current->thread.vr[0], sizeof(*vrregs));
return 1;
}
+void
+enable_kernel_altivec(void)
+{
+#ifdef __SMP__
+ if (current->thread.regs && (current->thread.regs->msr & MSR_VEC))
+ giveup_altivec(current);
+ else
+ giveup_altivec(NULL): /* just enable AltiVec for kernel - force */
+#else
+ giveup_altivec(last_task_used_altivec);
+#endif /* __SMP __ */
+ printk("MSR_VEC in enable_altivec_kernel\n");
+}
+#endif /* CONFIG_ALTIVEC */
+
void
enable_kernel_fp(void)
{
@@ -162,6 +179,15 @@ enable_kernel_fp(void)
#endif /* __SMP__ */
}
+int
+dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs)
+{
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
+ memcpy(fpregs, &current->thread.fpr[0], sizeof(*fpregs));
+ return 1;
+}
+
void
_switch_to(struct task_struct *prev, struct task_struct *new,
struct task_struct **last)
@@ -194,6 +220,7 @@ _switch_to(struct task_struct *prev, struct task_struct *new,
*/
if ( prev->thread.regs && (prev->thread.regs->msr & MSR_FP) )
giveup_fpu(prev);
+#ifdef CONFIG_ALTIVEC
/*
* If the previous thread 1) has some altivec regs it wants saved
* (has bits in vrsave set) and 2) used altivec in the last quantum
@@ -206,6 +233,7 @@ _switch_to(struct task_struct *prev, struct task_struct *new,
if ( (prev->thread.regs && (prev->thread.regs->msr & MSR_VEC)) &&
prev->thread.vrsave )
giveup_altivec(prev);
+#endif /* CONFIG_ALTIVEC */
prev->last_processor = prev->processor;
current_set[smp_processor_id()] = new;
#endif /* __SMP__ */
@@ -337,13 +365,18 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
p->thread.fpscr = current->thread.fpscr;
childregs->msr &= ~MSR_FP;
+#ifdef CONFIG_ALTIVEC
+ /*
+ * copy altiVec info - assume lazy altiVec switch
+ * - kumar
+ */
if (regs->msr & MSR_VEC)
giveup_altivec(current);
- if ( p->thread.vrsave )
- memcpy(&p->thread.vrf, &current->thread.vrf, sizeof(p->thread.vrf));
+
+ memcpy(&p->thread.vr, &current->thread.vr, sizeof(p->thread.vr));
p->thread.vscr = current->thread.vscr;
- p->thread.vrsave = current->thread.vrsave;
childregs->msr &= ~MSR_VEC;
+#endif /* CONFIG_ALTIVEC */
#ifdef __SMP__
p->last_processor = NO_PROC_ID;
@@ -463,6 +496,10 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
goto out;
if (regs->msr & MSR_FP)
giveup_fpu(current);
+#ifdef CONFIG_ALTIVEC
+ if (regs->msr & MSR_VEC)
+ giveup_altivec(current);
+#endif /* CONFIG_ALTIVEC */
error = do_execve(filename, (char **) a1, (char **) a2, regs);
putname(filename);
out:
diff --git a/arch/ppc/kernel/prom.c b/arch/ppc/kernel/prom.c
index a52bdd804..b86e2a153 100644
--- a/arch/ppc/kernel/prom.c
+++ b/arch/ppc/kernel/prom.c
@@ -802,42 +802,19 @@ setup_disp_fake_bi(ihandle dp)
{
unsigned int len;
int width = 640, height = 480, depth = 8, pitch;
- unsigned address;
+ unsigned address;
boot_infos_t* bi;
unsigned long offset = reloc_offset();
- prom_print(RELOC("Initing fake screen\n"));
+ prom_print(RELOC("Initializing fake screen\n"));
- len = 0;
+ call_prom(RELOC("getprop"), 4, 1, dp, RELOC("width"), &width, sizeof(width));
+ call_prom(RELOC("getprop"), 4, 1, dp, RELOC("height"), &height, sizeof(height));
call_prom(RELOC("getprop"), 4, 1, dp, RELOC("depth"), &len, sizeof(len));
- if (len == 0)
- prom_print(RELOC("Warning: assuming display depth = 8\n"));
- else
- depth = len;
- width = len = 0;
- call_prom(RELOC("getprop"), 4, 1, dp, RELOC("width"), &len, sizeof(len));
- width = len;
- if (width == 0) {
- prom_print(RELOC("Failed to get width\n"));
- return;
- }
- height = len = 0;
- call_prom(RELOC("getprop"), 4, 1, dp, RELOC("height"), &len, sizeof(len));
- height = len;
- if (height == 0) {
- prom_print(RELOC("Failed to get height\n"));
- return;
- }
- pitch = len = 0;
+ pitch = width * ((depth + 7) / 8);
call_prom(RELOC("getprop"), 4, 1, dp, RELOC("linebytes"), &len, sizeof(len));
- pitch = len;
- if (pitch == 0) {
- prom_print(RELOC("Failed to get pitch\n"));
- return;
- }
- address = len = 0;
+ address = 0;
call_prom(RELOC("getprop"), 4, 1, dp, RELOC("address"), &len, sizeof(len));
- address = len;
if (address == 0) {
prom_print(RELOC("Failed to get address\n"));
return;
@@ -846,22 +823,22 @@ setup_disp_fake_bi(ihandle dp)
/* kludge for valkyrie */
if (strcmp(dp->name, "valkyrie") == 0)
address += 0x1000;
- }
#endif
- RELOC(disp_bi) = &fake_bi;
- bi = PTRRELOC((&fake_bi));
- RELOC(g_loc_X) = 0;
- RELOC(g_loc_Y) = 0;
- RELOC(g_max_loc_X) = width / 8;
- RELOC(g_max_loc_Y) = height / 16;
- bi->logicalDisplayBase = (unsigned char *)address;
- bi->dispDeviceBase = (unsigned char *)address;
- bi->dispDeviceRowBytes = pitch;
- bi->dispDeviceDepth = depth;
- bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0;
- bi->dispDeviceRect[2] = width;
- bi->dispDeviceRect[3] = height;
+ RELOC(disp_bi) = &fake_bi;
+ bi = PTRRELOC((&fake_bi));
+ RELOC(g_loc_X) = 0;
+ RELOC(g_loc_Y) = 0;
+ RELOC(g_max_loc_X) = width / 8;
+ RELOC(g_max_loc_Y) = height / 16;
+ bi->logicalDisplayBase = (unsigned char *)address;
+ bi->dispDeviceBase = (unsigned char *)address;
+ bi->dispDeviceRowBytes = pitch;
+ bi->dispDeviceDepth = depth;
+ bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0;
+ bi->dispDeviceRect[2] = width;
+ bi->dispDeviceRect[3] = height;
+ RELOC(disp_bi) = 0;
}
#endif
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 19ce0a25e..7502ad08e 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -221,7 +221,7 @@ int get_cpuinfo(char *buffer)
if ( i )
len += sprintf(len+buffer,"\n");
len += sprintf(len+buffer,"processor\t: %lu\n",i);
- len += sprintf(len+buffer,"cpu\t\t: ");
+ len += sprintf(len+buffer,"cpu\t\t: ");
pvr = GET_PVR;
@@ -656,7 +656,6 @@ void __init setup_arch(char **cmdline_p)
#ifdef CONFIG_BOOTX_TEXT
map_bootx_text();
- prom_print("identify machine\n");
#endif
#ifdef CONFIG_XMON
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index 386764ddd..83dff9246 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -53,7 +53,6 @@ unsigned int prof_counter[NR_CPUS];
cycles_t cacheflush_time;
/* all cpu mappings are 1-1 -- Cort */
-int cpu_number_map[NR_CPUS] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,};
volatile unsigned long cpu_callin_map[NR_CPUS] = {0,};
int start_secondary(void *);
diff --git a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c
index e1a3fdcbb..e31b34cc9 100644
--- a/arch/ppc/kernel/syscalls.c
+++ b/arch/ppc/kernel/syscalls.c
@@ -252,14 +252,13 @@ asmlinkage int sys_pause(void)
asmlinkage int sys_uname(struct old_utsname * name)
{
- int err;
-
- if (!name)
- return -EFAULT;
+ int err = -EFAULT;
+
down_read(&uts_sem);
- err = copy_to_user(name, &system_utsname, sizeof (*name));
- up(&uts_sem);
- return err ? -EFAULT : 0;
+ if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
+ err = 0;
+ up_read(&uts_sem);
+ return err;
}
asmlinkage int sys_olduname(struct oldold_utsname * name)
@@ -282,8 +281,8 @@ asmlinkage int sys_olduname(struct oldold_utsname * name)
error -= __put_user(0,name->version+__OLD_UTS_LEN);
error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
error = __put_user(0,name->machine+__OLD_UTS_LEN);
- error = error ? -EFAULT : 0;
- up(&uts_sem);
+ up_read(&uts_sem);
+ error = error ? -EFAULT : 0;
return error;
}
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index 5cc34c5a5..ac7f47602 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -118,11 +118,11 @@ MachineCheckException(struct pt_regs *regs)
default:
printk("Unknown values in msr\n");
}
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
debugger(regs);
#endif
- show_regs(regs);
- print_backtrace((unsigned long *)regs->gpr[1]);
panic("machine check");
}
_exception(SIGSEGV, regs);
@@ -142,44 +142,6 @@ SMIException(struct pt_regs *regs)
panic("System Management Interrupt");
}
-#if defined(CONFIG_ALTIVEC)
-void
-AltiVecUnavailable(struct pt_regs *regs)
-{
- /*
- * This should be changed so we don't take a trap if coming
- * back when last_task_used_altivec == current. We should also
- * allow the kernel to use the altivec regs on UP to store tasks
- * regs during switch
- * -- Cort
- */
- if ( regs->msr & MSR_VEC )
- {
- show_regs(regs);
- panic("AltiVec trap with Altivec enabled!\n");
- }
-
- if ( !user_mode(regs) )
- {
- show_regs(regs);
- panic("Kernel Used Altivec with MSR_VEC off!\n");
- }
-
- if ( last_task_used_altivec != current )
- {
- if ( last_task_used_altivec )
- giveup_altivec(current);
- load_up_altivec(current);
- /* on SMP we always save/restore on switch */
-#ifndef __SMP__
- last_task_used_altivec = current;
-#endif
- }
- /* enable altivec for the task on return */
- regs->msr |= MSR_VEC;
-}
-#endif /* CONFIG_ALTIVEC */
-
void
UnknownException(struct pt_regs *regs)
{
diff --git a/arch/ppc/lib/string.S b/arch/ppc/lib/string.S
index 4ab90f8b7..1c4f1f78e 100644
--- a/arch/ppc/lib/string.S
+++ b/arch/ppc/lib/string.S
@@ -12,6 +12,11 @@
#include <asm/processor.h>
#include <asm/errno.h>
+CACHELINE_BYTES = 32
+LG_CACHELINE_BYTES = 5
+CACHELINE_MASK = 0x1f
+CACHELINE_WORDS = 8
+
.globl strcpy
strcpy:
addi r5,r3,-1
@@ -70,6 +75,55 @@ strlen:
subf r3,r3,r4
blr
+/*
+ * Use dcbz on the complete cache lines in the destination
+ * to set them to zero. This requires that the destination
+ * area is cacheable. -- paulus
+ */
+ .globl cacheable_memzero
+cacheable_memzero:
+ mr r5,r4
+ li r4,0
+ addi r6,r3,-4
+ cmplwi 0,r5,4
+ blt 7f
+ stwu r4,4(r6)
+ beqlr
+ andi. r0,r6,3
+ add r5,r0,r5
+ subf r6,r0,r6
+ clrlwi r7,r6,32-LG_CACHELINE_BYTES
+ add r8,r7,r5
+ srwi r9,r8,LG_CACHELINE_BYTES
+ addic. r9,r9,-1 /* total number of complete cachelines */
+ ble 2f
+ xori r0,r7,CACHELINE_MASK & ~3
+ srwi. r0,r0,2
+ beq 3f
+ mtctr r0
+4: stwu r4,4(r6)
+ bdnz 4b
+3: mtctr r9
+ li r7,4
+10: dcbz r7,r6
+ addi r6,r6,CACHELINE_BYTES
+ bdnz 10b
+ clrlwi r5,r8,32-LG_CACHELINE_BYTES
+ addi r5,r5,4
+2: srwi r0,r5,2
+ mtctr r0
+ bdz 6f
+1: stwu r4,4(r6)
+ bdnz 1b
+6: andi. r5,r5,3
+7: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r6,r6,3
+8: stbu r4,1(r6)
+ bdnz 8b
+ blr
+
.globl memset
memset:
rlwimi r4,r4,8,16,23
@@ -82,7 +136,7 @@ memset:
andi. r0,r6,3
add r5,r0,r5
subf r6,r0,r6
- rlwinm r0,r5,32-2,2,31
+ srwi r0,r5,2
mtctr r0
bdz 6f
1: stwu r4,4(r6)
@@ -103,6 +157,87 @@ bcopy:
mr r4,r6
b memcpy
+/*
+ * This version uses dcbz on the complete cache lines in the
+ * destination area to reduce memory traffic. This requires that
+ * the destination area is cacheable.
+ * We only use this version if the source and dest don't overlap.
+ * -- paulus.
+ */
+ .global cacheable_memcpy
+cacheable_memcpy:
+ add r7,r3,r5 /* test if the src & dst overlap */
+ add r8,r4,r5
+ cmplw 0,r4,r7
+ cmplw 1,r3,r8
+ crand 0,0,4 /* cr0.lt &= cr1.lt */
+ blt memcpy /* if regions overlap */
+
+ addi r4,r4,-4
+ addi r6,r3,-4
+ neg r0,r3
+ andi. r0,r0,CACHELINE_MASK /* # bytes to start of cache line */
+ beq 58f
+
+ cmplw 0,r5,r0 /* is this more than total to do? */
+ blt 63f /* if not much to do */
+ andi. r8,r0,3 /* get it word-aligned first */
+ subf r5,r0,r5
+ mtctr r8
+ beq+ 61f
+70: lbz r9,4(r4) /* do some bytes */
+ stb r9,4(r6)
+ addi r4,r4,1
+ addi r6,r6,1
+ bdnz 70b
+61: srwi. r0,r0,2
+ mtctr r0
+ beq 58f
+72: lwzu r9,4(r4) /* do some words */
+ stwu r9,4(r6)
+ bdnz 72b
+
+58: srwi. r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */
+ clrlwi r5,r5,32-LG_CACHELINE_BYTES
+ li r11,4
+ mtctr r0
+ beq 63f
+53: dcbz r11,r6
+ lwz r7,4(r4)
+ lwz r8,8(r4)
+ lwz r9,12(r4)
+ lwzu r10,16(r4)
+ stw r7,4(r6)
+ stw r8,8(r6)
+ stw r9,12(r6)
+ stwu r10,16(r6)
+ lwz r7,4(r4)
+ lwz r8,8(r4)
+ lwz r9,12(r4)
+ lwzu r10,16(r4)
+ stw r7,4(r6)
+ stw r8,8(r6)
+ stw r9,12(r6)
+ stwu r10,16(r6)
+ bdnz 53b
+
+63: srwi. r0,r5,2
+ mtctr r0
+ beq 64f
+30: lwzu r0,4(r4)
+ stwu r0,4(r6)
+ bdnz 30b
+
+64: andi. r0,r5,3
+ mtctr r0
+ beq+ 65f
+40: lbz r0,4(r4)
+ stb r0,4(r6)
+ addi r4,r4,1
+ addi r6,r6,1
+ bdnz 40b
+65: blr
+
.globl memmove
memmove:
cmplw 0,r3,r4
@@ -111,7 +246,7 @@ memmove:
.globl memcpy
memcpy:
- rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
+ srwi. r7,r5,3
addi r6,r3,-4
addi r4,r4,-4
beq 2f /* if less than 8 bytes to do */
@@ -218,106 +353,167 @@ memchr:
.globl __copy_tofrom_user
__copy_tofrom_user:
- srwi. r7,r5,3
- addi r6,r3,-4
addi r4,r4,-4
- li r3,0 /* success return value */
- beq 2f /* if less than 8 bytes to do */
- andi. r0,r6,3 /* get dest word aligned */
- mtctr r7
- bne 5f
-1: lwz r7,4(r4)
-11: lwzu r8,8(r4)
-12: stw r7,4(r6)
-13: stwu r8,8(r6)
- bdnz 1b
- andi. r5,r5,7
-2: cmplwi 0,r5,4
- blt 3f
-14: lwzu r0,4(r4)
- addi r5,r5,-4
-15: stwu r0,4(r6)
-3: cmpwi 0,r5,0 /* do 1 byte at a time for the remainder */
- beqlr
- mtctr r5
- addi r4,r4,3
- addi r6,r6,3
-4: lbzu r0,1(r4)
-16: stbu r0,1(r6)
- bdnz 4b
- blr
-5: subfic r0,r0,4 /* copy bytes until we have the */
- mtctr r0 /* destination 4-byte aligned */
- subf r5,r0,r5
-6: lbz r7,4(r4)
+ addi r6,r3,-4
+ neg r0,r3
+ andi. r0,r0,CACHELINE_MASK /* # bytes to start of cache line */
+ beq 58f
+
+ cmplw 0,r5,r0 /* is this more than total to do? */
+ blt 63f /* if not much to do */
+ andi. r8,r0,3 /* get it word-aligned first */
+ mtctr r8
+ beq+ 61f
+70: lbz r9,4(r4) /* do some bytes */
+71: stb r9,4(r6)
addi r4,r4,1
-17: stb r7,4(r6)
addi r6,r6,1
- bdnz 6b
- srwi. r7,r5,3
- beq 2b
- mtctr r7
- b 1b
-/* we come here on a fault in the 8-byte-at-a-time loop */
-88: subi r4,r4,8 /* compensate for the lwzu */
-98: mfctr r0
- rlwimi r5,r0,3,0,28 /* use the byte-at-a-time loop to */
- b 3b /* copy up to the byte at fault */
-/* here on a write fault in the single-word copy */
-96: subi r4,r4,4
- b 3b
-/* here on a read fault in the initial single-byte copy */
-90: mfctr r3
- add r3,r3,r5
- b 70f
-/* here on a read fault in the final single-byte copy */
-99: mfctr r3
- subi r6,r6,3
-/* clear out the rest of the destination: r3 bytes starting at 4(r6) */
-70: li r0,0
- mr. r5,r3
- beq 76f
-71: andi. r4,r6,3
- beq 72f
-77: stb r0,4(r6)
+ bdnz 70b
+61: subf r5,r0,r5
+ srwi. r0,r0,2
+ mtctr r0
+ beq 58f
+72: lwzu r9,4(r4) /* do some words */
+73: stwu r9,4(r6)
+ bdnz 72b
+
+58: srwi. r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */
+ clrlwi r5,r5,32-LG_CACHELINE_BYTES
+ li r11,4
+ mtctr r0
+ beq 63f
+53: dcbz r11,r6
+10: lwz r7,4(r4)
+11: lwz r8,8(r4)
+12: lwz r9,12(r4)
+13: lwzu r10,16(r4)
+14: stw r7,4(r6)
+15: stw r8,8(r6)
+16: stw r9,12(r6)
+17: stwu r10,16(r6)
+20: lwz r7,4(r4)
+21: lwz r8,8(r4)
+22: lwz r9,12(r4)
+23: lwzu r10,16(r4)
+24: stw r7,4(r6)
+25: stw r8,8(r6)
+26: stw r9,12(r6)
+27: stwu r10,16(r6)
+ bdnz 53b
+
+63: srwi. r0,r5,2
+ mtctr r0
+ beq 64f
+30: lwzu r0,4(r4)
+31: stwu r0,4(r6)
+ bdnz 30b
+
+64: andi. r0,r5,3
+ mtctr r0
+ beq+ 65f
+40: lbz r0,4(r4)
+41: stb r0,4(r6)
+ addi r4,r4,1
addi r6,r6,1
- addic. r5,r5,-1
- bne 71b
-72: srwi. r7,r5,2
- beq 73f
- mtctr r7
-74: stwu r0,4(r6)
- bdnz 74b
-73: andi. r5,r5,3
- beq 76f
- mtctr r5
- addi r6,r6,3
-75: stbu r0,1(r6)
- bdnz 75b
-76: blr
-/* here on a write fault in the initial single-byte copy */
-80: mfctr r3
- add r3,r3,r5
- blr
-/* here on a write fault in the final single-byte copy */
-81: mfctr r3
+ bdnz 40b
+65: li r3,0
blr
+/* read fault, initial single-byte copy */
+100: li r4,0
+ b 90f
+/* write fault, initial single-byte copy */
+101: li r4,1
+90: subf r5,r8,r5
+ li r3,0
+ b 99f
+/* read fault, initial word copy */
+102: li r4,0
+ b 91f
+/* write fault, initial word copy */
+103: li r4,1
+91: li r3,2
+ b 99f
+/* read fault in 2nd half of cacheline loop */
+106: addi r5,r5,-16
+/* read fault in 1st half of cacheline loop */
+104: li r4,0
+ b 92f
+/* write fault in 2nd half of cacheline loop */
+107: addi r5,r5,-16
+/* fault on dcbz (effectively a write fault) */
+/* or write fault in 1st half of cacheline loop */
+105: li r4,1
+92: li r3,LG_CACHELINE_BYTES
+ b 99f
+/* read fault in final word loop */
+108: li r4,0
+ b 93f
+/* write fault in final word loop */
+109: li r4,1
+93: andi. r5,r5,3
+ li r3,2
+ b 99f
+/* read fault in final byte loop */
+110: li r4,0
+ b 94f
+/* write fault in final byte loop */
+111: li r4,1
+94: li r5,0
+ li r3,0
+/*
+ * At this stage the number of bytes not copied is
+ * r5 + (ctr << r3), and r4 is 0 for read or 1 for write.
+ */
+99: mfctr r0
+ slw r3,r0,r3
+ add r3,r3,r5
+ cmpwi 0,r4,0
+ bne 120f
+/* for read fault, clear out the destination: r3 bytes starting at 4(r6) */
+ srwi. r0,r3,2
+ li r9,0
+ mtctr r0
+ beq 113f
+112: stwu r9,4(r6)
+ bdnz 112b
+113: andi. r0,r3,3
+ mtctr r0
+ beq 120f
+114: stb r9,4(r6)
+ addi r6,r6,1
+ bdnz 114b
+120: blr
+
.section __ex_table,"a"
.align 2
- .long 1b,98b
- .long 11b,98b
- .long 12b,88b
- .long 13b,88b
- .long 14b,3b
- .long 15b,96b
- .long 4b,99b
- .long 16b,81b
- .long 6b,90b
- .long 17b,80b
- .long 77b,76b
- .long 74b,76b
- .long 75b,76b
+ .long 70b,100b
+ .long 71b,101b
+ .long 72b,102b
+ .long 73b,103b
+ .long 53b,105b
+ .long 10b,104b
+ .long 11b,104b
+ .long 12b,104b
+ .long 13b,104b
+ .long 14b,105b
+ .long 15b,105b
+ .long 16b,105b
+ .long 17b,105b
+ .long 20b,106b
+ .long 21b,106b
+ .long 22b,106b
+ .long 23b,106b
+ .long 24b,107b
+ .long 25b,107b
+ .long 26b,107b
+ .long 27b,107b
+ .long 30b,108b
+ .long 31b,109b
+ .long 40b,110b
+ .long 41b,111b
+ .long 112b,120b
+ .long 114b,120b
.text
.globl __clear_user
@@ -334,7 +530,6 @@ __clear_user:
andi. r0,r6,3
add r4,r0,r4
subf r6,r0,r6
- /*rlwinm r0,r4,32-2,2,31*/
srwi r0,r4,2
mtctr r0
bdz 6f
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index 216527e34..25d728fdd 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -1107,7 +1107,7 @@ unsigned long __init find_available_memory(void)
*/
void __init paging_init(void)
{
- unsigned int zones_size[MAX_NR_ZONES], i;
+ unsigned long zones_size[MAX_NR_ZONES], i;
/*
* Grab some memory for bad_page and bad_pagetable to use.
@@ -1197,7 +1197,7 @@ unsigned long __init *pmac_find_end_of_memory(void)
unsigned long a, total;
/* max amount of RAM we allow -- Cort */
-#define RAM_LIMIT (64<<20)
+#define RAM_LIMIT (768<<20)
memory_node = find_devices("memory");
if (memory_node == NULL) {
diff --git a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c
index f25060c94..8e924699f 100644
--- a/arch/ppc/xmon/start.c
+++ b/arch/ppc/xmon/start.c
@@ -115,42 +115,41 @@ extern void pmu_poll(void);
int
xmon_write(void *handle, void *ptr, int nb)
{
- char *p = ptr;
- int i, c, ct;
+ char *p = ptr;
+ int i, c, ct;
#ifdef CONFIG_BOOTX_TEXT
- if (use_screen) {
- /* write it on the screen */
- for (i = 0; i < nb; ++i)
- drawchar(*p++);
- return nb;
- }
+ if (use_screen) {
+ /* write it on the screen */
+ for (i = 0; i < nb; ++i)
+ drawchar(*p++);
+ return nb;
+ }
#endif
- if (!scc_initialized)
- xmon_init_scc();
- for (i = 0; i < nb; ++i) {
- ct = 0;
- while ((*sccc & TXRDY) == 0)
+ if (!scc_initialized)
+ xmon_init_scc();
+ ct = 0;
+ for (i = 0; i < nb; ++i) {
+ while ((*sccc & TXRDY) == 0) {
#ifdef CONFIG_ADB
- if (sys_ctrler == SYS_CTRLER_PMU)
- pmu_poll();
-#else
- ;
+ if (sys_ctrler == SYS_CTRLER_PMU)
+ pmu_poll();
#endif /* CONFIG_ADB */
- c = p[i];
- if (c == '\n' && !ct) {
- c = '\r';
- ct = 1;
- --i;
- } else {
- if (console)
- printk("%c", c);
- ct = 0;
+ }
+ c = p[i];
+ if (c == '\n' && !ct) {
+ c = '\r';
+ ct = 1;
+ --i;
+ } else {
+ if (console)
+ printk("%c", c);
+ ct = 0;
+ }
+ buf_access();
+ *sccd = c;
}
- buf_access();
- *sccd = c;
- }
- return i;
+ return i;
}
int xmon_wants_key;
@@ -285,7 +284,7 @@ xmon_init_scc()
{
int i, x;
- if (macio_node != 0) {
+ if (via_modem && macio_node != 0) {
unsigned int t0;
feature_set(macio_node, FEATURE_Modem_power);
diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig
index 6db042563..7589958c8 100644
--- a/arch/sparc/defconfig
+++ b/arch/sparc/defconfig
@@ -259,18 +259,17 @@ CONFIG_ISO9660_FS=m
# CONFIG_JOLIET is not set
CONFIG_MINIX_FS=m
# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
CONFIG_HPFS_FS=m
CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
CONFIG_ROMFS_FS=m
CONFIG_EXT2_FS=y
CONFIG_SYSV_FS=m
# CONFIG_SYSV_FS_WRITE is not set
# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 336ae208f..8c8903d26 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -1,4 +1,4 @@
-/* $Id: ioport.c,v 1.31 2000/02/06 22:55:32 zaitcev Exp $
+/* $Id: ioport.c,v 1.34 2000/02/18 13:48:48 davem Exp $
* ioport.c: Simple io mapping allocator.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -44,7 +44,6 @@
#include <asm/pgtable.h>
struct resource *_sparc_find_resource(struct resource *r, unsigned long);
-int _sparc_len2order(unsigned long len);
static void *_sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz);
static void *_sparc_alloc_io(unsigned int busno, unsigned long phys,
@@ -280,7 +279,7 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, long len, u32 *dma_addrp)
return NULL;
}
- order = _sparc_len2order(len_total);
+ order = get_order(len_total);
va = __get_free_pages(GFP_KERNEL, order);
if (va == 0) {
/*
@@ -341,7 +340,7 @@ void sbus_free_consistent(struct sbus_dev *sdev, long n, void *p, u32 ba)
pgp = (unsigned long) phys_to_virt(mmu_translate_dvma(ba));
mmu_unmap_dma_area(ba, n);
- free_pages(pgp, _sparc_len2order(n));
+ free_pages(pgp, get_order(n));
}
/*
@@ -349,7 +348,7 @@ void sbus_free_consistent(struct sbus_dev *sdev, long n, void *p, u32 ba)
* CPU view of this memory may be inconsistent with
* a device view and explicit flushing is necessary.
*/
-u32 sbus_map_single(struct sbus_dev *sdev, void *va, long len)
+u32 sbus_map_single(struct sbus_dev *sdev, void *va, long len, int direction)
{
#if 0 /* This is the version that abuses consistent space */
unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK;
@@ -396,7 +395,7 @@ u32 sbus_map_single(struct sbus_dev *sdev, void *va, long len)
#endif
}
-void sbus_unmap_single(struct sbus_dev *sdev, u32 ba, long n)
+void sbus_unmap_single(struct sbus_dev *sdev, u32 ba, long n, int direction)
{
#if 0 /* This is the version that abuses consistent space */
struct resource *res;
@@ -425,7 +424,7 @@ void sbus_unmap_single(struct sbus_dev *sdev, u32 ba, long n)
#endif
}
-int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n)
+int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction)
{
mmu_get_scsi_sgl(sg, n, sdev->bus);
@@ -436,14 +435,14 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n)
return n;
}
-void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n)
+void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction)
{
mmu_release_scsi_sgl(sg, n, sdev->bus);
}
/*
*/
-void sbus_dma_sync_single(struct sbus_dev *sdev, u32 ba, long size)
+void sbus_dma_sync_single(struct sbus_dev *sdev, u32 ba, long size, int direction)
{
unsigned long va;
struct resource *res;
@@ -457,7 +456,7 @@ void sbus_dma_sync_single(struct sbus_dev *sdev, u32 ba, long size)
mmu_inval_dma_area(va, (size + PAGE_SIZE-1) & PAGE_MASK);
}
-void sbus_dma_sync_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n)
+void sbus_dma_sync_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction)
{
printk("sbus_dma_sync_sg: not implemented yet\n");
}
@@ -482,7 +481,7 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t len, dma_addr_t *pba)
return NULL;
}
- order = _sparc_len2order(len_total);
+ order = get_order(len_total);
va = __get_free_pages(GFP_KERNEL, order);
if (va == 0) {
printk("pci_alloc_consistent: no %ld pages\n", len_total>>PAGE_SHIFT);
@@ -562,14 +561,14 @@ void pci_free_consistent(struct pci_dev *pdev, size_t n, void *p, dma_addr_t ba)
{
int x;
for (x = 0; x < n; x += PAGE_SIZE) {
- (*_sparc_unmapioaddr)(p + n);
+ (*_sparc_unmapioaddr)((unsigned long)p + n);
}
}
release_resource(res);
kfree(res);
- free_pages(pgp, _sparc_len2order(n));
+ free_pages(pgp, get_order(n));
}
/* Map a single buffer of the indicated size for DMA in streaming mode.
@@ -578,8 +577,10 @@ void pci_free_consistent(struct pci_dev *pdev, size_t n, void *p, dma_addr_t ba)
* Once the device is given the dma address, the device owns this memory
* until either pci_unmap_single or pci_dma_sync_single is performed.
*/
-dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size)
+dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
{
+ if (direction == PCI_DMA_NONE)
+ BUG();
return virt_to_bus(ptr);
}
@@ -590,8 +591,10 @@ dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size)
* After this call, reads by the cpu to the buffer are guarenteed to see
* whatever the device wrote there.
*/
-void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size)
+void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size, int direction)
{
+ if (direction == PCI_DMA_NONE)
+ BUG();
/* Nothing to do... */
}
@@ -610,9 +613,13 @@ void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size)
* Device ownership issues as mentioned above for pci_map_single are
* the same here.
*/
-int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents)
+int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction)
{
int n;
+
+ if (direction == PCI_DMA_NONE)
+ BUG();
+
for (n = 0; n < nents; n++) {
sg->dvma_address = virt_to_bus(sg->address);
sg->dvma_length = sg->length;
@@ -625,8 +632,10 @@ int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents)
* Again, cpu read rules concerning calls here are the same as for
* pci_unmap_single() above.
*/
-void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nhwents)
+void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nhwents, int direction)
{
+ if (direction == PCI_DMA_NONE)
+ BUG();
/* Nothing to do... */
}
@@ -639,8 +648,10 @@ void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nhwents)
* next point you give the PCI dma address back to the card, the
* device again owns the buffer.
*/
-void pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t ba, size_t size)
+void pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t ba, size_t size, int direction)
{
+ if (direction == PCI_DMA_NONE)
+ BUG();
mmu_inval_dma_area((unsigned long)bus_to_virt(ba),
(size + PAGE_SIZE-1) & PAGE_MASK);
}
@@ -651,8 +662,10 @@ void pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t ba, size_t size)
* The same as pci_dma_sync_single but for a scatter-gather list,
* same rules and usage.
*/
-void pci_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents)
+void pci_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction)
{
+ if (direction == PCI_DMA_NONE)
+ BUG();
while (nents) {
--nents;
mmu_inval_dma_area((unsigned long)sg->address,
@@ -739,19 +752,6 @@ _sparc_find_resource(struct resource *root, unsigned long hit)
return NULL;
}
-int
-_sparc_len2order(unsigned long len)
-{
- int order;
-
- for (order = 0; order < 7; order++) /* 2^6 pages == 256K */
- if ((1 << (order + PAGE_SHIFT)) >= len)
- return order;
- printk("len2order: from %p: len %lu(0x%lx) yields order >=7.\n",
- __builtin_return_address(0), len, len);
- return 1;
-}
-
/*
* Necessary boot time initializations.
*/
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index b504e2412..335eba208 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -1,4 +1,4 @@
-/* $Id: pcic.c,v 1.12 2000/01/22 07:35:25 zaitcev Exp $
+/* $Id: pcic.c,v 1.13 2000/02/12 03:05:37 zaitcev Exp $
* pcic.c: Sparc/PCI controller support
*
* Copyright (C) 1998 V. Roganov and G. Raiko
@@ -784,6 +784,7 @@ void __init pci_time_init(void)
static __inline__ unsigned long do_gettimeoffset(void)
{
+ struct tasklet_struct *t;
unsigned long offset = 0;
/*
@@ -794,7 +795,8 @@ static __inline__ unsigned long do_gettimeoffset(void)
readl(pcic0.pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW;
count = ((count/100)*USECS_PER_JIFFY) / (TICK_TIMER_LIMIT/100);
- if(test_bit(TIMER_BH, &bh_active))
+ t = &bh_task_vec[TIMER_BH];
+ if (test_bit(TASKLET_STATE_SCHED, &t->state))
offset = 1000000;
return offset + count;
}
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index d1b3eca63..cdc1f0751 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -1,4 +1,4 @@
-/* $Id: sparc_ksyms.c,v 1.89 2000/02/09 11:15:03 davem Exp $
+/* $Id: sparc_ksyms.c,v 1.91 2000/02/18 20:23:24 davem Exp $
* arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -145,11 +145,8 @@ EXPORT_SYMBOL(kernel_flag);
EXPORT_SYMBOL(global_irq_holder);
EXPORT_SYMBOL(global_irq_lock);
EXPORT_SYMBOL(global_bh_lock);
-EXPORT_SYMBOL(global_bh_count);
-EXPORT_SYMBOL(sparc_bh_lock);
EXPORT_SYMBOL(global_irq_count);
EXPORT_SYMBOL(synchronize_irq);
-EXPORT_SYMBOL(synchronize_bh);
#endif
EXPORT_SYMBOL(local_irq_count);
EXPORT_SYMBOL(local_bh_count);
@@ -193,6 +190,8 @@ EXPORT_SYMBOL(sbus_map_sg);
EXPORT_SYMBOL(sbus_unmap_sg);
EXPORT_SYMBOL(sbus_dma_sync_single);
EXPORT_SYMBOL(sbus_dma_sync_sg);
+EXPORT_SYMBOL(sbus_iounmap);
+EXPORT_SYMBOL(sbus_ioremap);
#endif
#if CONFIG_PCI
/* We do not have modular drivers for PCI devices yet. */
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
index fde9bccfd..5beb3adf0 100644
--- a/arch/sparc/kernel/sys_sparc.c
+++ b/arch/sparc/kernel/sys_sparc.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.60 2000/02/08 20:24:18 davem Exp $
+/* $Id: sys_sparc.c,v 1.61 2000/02/16 07:31:29 davem Exp $
* linux/arch/sparc/kernel/sys_sparc.c
*
* This file contains various random system calls that
@@ -34,12 +34,39 @@ asmlinkage unsigned long sys_getpagesize(void)
return PAGE_SIZE; /* Possibly older binaries want 8192 on sun4's? */
}
+unsigned long get_unmapped_area(unsigned long addr, unsigned long len)
+{
+ struct vm_area_struct * vmm;
+
+ /* See asm-sparc/uaccess.h */
+ if (len > TASK_SIZE - PAGE_SIZE)
+ return 0;
+ if (ARCH_SUN4C_SUN4 && len > 0x20000000)
+ return 0;
+ if (!addr)
+ addr = TASK_UNMAPPED_BASE;
+ addr = PAGE_ALIGN(addr);
+
+ for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
+ /* At this point: (!vmm || addr < vmm->vm_end). */
+ if (ARCH_SUN4C_SUN4 && addr < 0xe0000000 && 0x20000000 - len < addr) {
+ addr = PAGE_OFFSET;
+ vmm = find_vma(current->mm, PAGE_OFFSET);
+ }
+ if (TASK_SIZE - PAGE_SIZE - len < addr)
+ return 0;
+ if (!vmm || addr + len <= vmm->vm_start)
+ return addr;
+ addr = vmm->vm_end;
+ }
+}
+
extern asmlinkage unsigned long sys_brk(unsigned long brk);
asmlinkage unsigned long sparc_brk(unsigned long brk)
{
if(ARCH_SUN4C_SUN4) {
- if(brk >= 0x20000000 && brk < 0xe0000000)
+ if ((brk & 0xe0000000) != (current->mm->brk & 0xe0000000))
return current->mm->brk;
}
return sys_brk(brk);
@@ -190,24 +217,16 @@ static unsigned long do_mmap2(unsigned long addr, unsigned long len,
down(&current->mm->mmap_sem);
lock_kernel();
- retval = -ENOMEM;
+ retval = -EINVAL;
len = PAGE_ALIGN(len);
- if(!(flags & MAP_FIXED) &&
- (!addr || (ARCH_SUN4C_SUN4 &&
- (addr >= 0x20000000 && addr < 0xe0000000)))) {
- addr = get_unmapped_area(0, len);
- if(!addr)
- goto out_putf;
- if (ARCH_SUN4C_SUN4 &&
- (addr >= 0x20000000 && addr < 0xe0000000)) {
- retval = -EINVAL;
- goto out_putf;
- }
- }
+ if (ARCH_SUN4C_SUN4 &&
+ (len > 0x20000000 ||
+ ((flags & MAP_FIXED) &&
+ addr < 0xe0000000 && addr + len > 0x20000000)))
+ goto out_putf;
/* See asm-sparc/uaccess.h */
- retval = -EINVAL;
- if((len > (TASK_SIZE - PAGE_SIZE)) || (addr > (TASK_SIZE-len-PAGE_SIZE)))
+ if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE)
goto out_putf;
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
@@ -238,6 +257,50 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
return do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
}
+extern unsigned long do_mremap(unsigned long addr,
+ unsigned long old_len, unsigned long new_len,
+ unsigned long flags, unsigned long new_addr);
+
+asmlinkage unsigned long sparc_mremap(unsigned long addr,
+ unsigned long old_len, unsigned long new_len,
+ unsigned long flags, unsigned long new_addr)
+{
+ unsigned long ret = -EINVAL;
+ if (ARCH_SUN4C_SUN4) {
+ if (old_len > 0x20000000 || new_len > 0x20000000)
+ goto out;
+ if (addr < 0xe0000000 && addr + old_len > 0x20000000)
+ goto out;
+ }
+ if (old_len > TASK_SIZE - PAGE_SIZE ||
+ new_len > TASK_SIZE - PAGE_SIZE)
+ goto out;
+ down(&current->mm->mmap_sem);
+ if (flags & MREMAP_FIXED) {
+ if (ARCH_SUN4C_SUN4 &&
+ new_addr < 0xe0000000 &&
+ new_addr + new_len > 0x20000000)
+ goto out_sem;
+ if (new_addr + new_len > TASK_SIZE - PAGE_SIZE)
+ goto out_sem;
+ } else if ((ARCH_SUN4C_SUN4 && addr < 0xe0000000 &&
+ addr + new_len > 0x20000000) ||
+ addr + new_len > TASK_SIZE - PAGE_SIZE) {
+ ret = -ENOMEM;
+ if (!(flags & MREMAP_MAYMOVE))
+ goto out_sem;
+ new_addr = get_unmapped_area (addr, new_len);
+ if (!new_addr)
+ goto out_sem;
+ flags |= MREMAP_FIXED;
+ }
+ ret = do_mremap(addr, old_len, new_len, flags, new_addr);
+out_sem:
+ up(&current->mm->mmap_sem);
+out:
+ return ret;
+}
+
/* we come to here via sys_nis_syscall so it can setup the regs argument */
asmlinkage unsigned long
c_sys_nis_syscall (struct pt_regs *regs)
diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
index bb3a5ad36..82b5ac653 100644
--- a/arch/sparc/kernel/sys_sunos.c
+++ b/arch/sparc/kernel/sys_sunos.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.112 2000/01/29 07:40:11 davem Exp $
+/* $Id: sys_sunos.c,v 1.113 2000/02/16 07:31:29 davem Exp $
* sys_sunos.c: SunOS specific syscall compatibility support.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -71,8 +71,10 @@ asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len,
lock_kernel();
current->personality |= PER_BSD;
if(flags & MAP_NORESERVE) {
- printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n",
- current->comm);
+ static int cnt;
+ if (cnt++ < 10)
+ printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n",
+ current->comm);
flags &= ~MAP_NORESERVE;
}
retval = -EBADF;
@@ -84,19 +86,7 @@ asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len,
goto out;
}
- retval = -ENOMEM;
- if(!(flags & MAP_FIXED) &&
- (!addr || (ARCH_SUN4C_SUN4 &&
- (addr >= 0x20000000 && addr < 0xe0000000)))) {
- addr = get_unmapped_area(0, len);
- if(!addr)
- goto out_putf;
- if (ARCH_SUN4C_SUN4 &&
- (addr >= 0x20000000 && addr < 0xe0000000)) {
- retval = -EINVAL;
- goto out_putf;
- }
- }
+ retval = -EINVAL;
/* If this is ld.so or a shared library doing an mmap
* of /dev/zero, transform it into an anonymous mapping.
* SunOS is so stupid some times... hmph!
@@ -105,18 +95,27 @@ asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len,
if(MAJOR(file->f_dentry->d_inode->i_rdev) == MEM_MAJOR &&
MINOR(file->f_dentry->d_inode->i_rdev) == 5) {
flags |= MAP_ANONYMOUS;
+ fput(file);
file = 0;
}
}
- if(!(flags & MAP_FIXED))
- addr = 0;
ret_type = flags & _MAP_NEW;
flags &= ~_MAP_NEW;
- /* See asm-sparc/uaccess.h */
- retval = -EINVAL;
- if((len > (TASK_SIZE - PAGE_SIZE)) || (addr > (TASK_SIZE-len-PAGE_SIZE)))
- goto out_putf;
+ if(!(flags & MAP_FIXED))
+ addr = 0;
+ else {
+ if (ARCH_SUN4C_SUN4 &&
+ (len > 0x20000000 ||
+ ((flags & MAP_FIXED) &&
+ addr < 0xe0000000 && addr + len > 0x20000000)))
+ goto out_putf;
+
+ /* See asm-sparc/uaccess.h */
+ if (len > TASK_SIZE - PAGE_SIZE ||
+ addr + len > TASK_SIZE - PAGE_SIZE)
+ goto out_putf;
+ }
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
retval = do_mmap(file, addr, len, prot, flags, off);
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
index 174522d03..8746958d7 100644
--- a/arch/sparc/kernel/systbls.S
+++ b/arch/sparc/kernel/systbls.S
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.93 2000/01/29 16:41:18 jj Exp $
+/* $Id: systbls.S,v 1.94 2000/02/16 07:31:30 davem Exp $
* systbls.S: System call entry point tables for OS compatibility.
* The native Linux system call table lives here also.
*
@@ -69,7 +69,7 @@ sys_call_table:
/*235*/ .long sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
/*240*/ .long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
/*245*/ .long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
-/*250*/ .long sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
+/*250*/ .long sparc_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
/*255*/ .long sys_nis_syscall, sys_nis_syscall
#ifdef CONFIG_SUNOS_EMUL
diff --git a/arch/sparc/lib/rwsem.S b/arch/sparc/lib/rwsem.S
index 0d5f74139..0396bf2bc 100644
--- a/arch/sparc/lib/rwsem.S
+++ b/arch/sparc/lib/rwsem.S
@@ -1,4 +1,4 @@
-/* $Id: rwsem.S,v 1.2 2000/01/05 01:00:38 davem Exp $
+/* $Id: rwsem.S,v 1.4 2000/02/13 07:59:39 anton Exp $
* Assembly part of rw semaphores.
*
* Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
@@ -26,16 +26,19 @@ ___down_read:
tst %g7
bne 1b
ld [%g1], %g7
- subcc %g7, 1, %g7
+ sub %g7, 1, %g7
st %g7, [%g1]
stb %g0, [%g1 + 4]
#else
ld [%g1], %g7
- subcc %g7, 1, %g7
+ sub %g7, 1, %g7
st %g7, [%g1]
#endif
wr %g3, 0, %psr
+ add %g7, 1, %g7
nop
+ nop
+ subcc %g7, 1, %g7
bneg 3f
nop
2: jmpl %o7, %g0
@@ -74,16 +77,19 @@ ___down_write:
tst %g7
bne 1b
ld [%g1], %g7
- subcc %g7, %g2, %g7
+ sub %g7, %g2, %g7
st %g7, [%g1]
stb %g0, [%g1 + 4]
#else
ld [%g1], %g7
- subcc %g7, %g2, %g7
+ sub %g7, %g2, %g7
st %g7, [%g1]
#endif
wr %g3, 0, %psr
+ add %g7, %g2, %g7
+ nop
nop
+ subcc %g7, %g2, %g7
bne 3f
nop
2: jmpl %o7, %g0
@@ -122,16 +128,19 @@ ___up_read:
tst %g7
bne 1b
ld [%g1], %g7
- addcc %g7, 1, %g7
+ add %g7, 1, %g7
st %g7, [%g1]
stb %g0, [%g1 + 4]
#else
ld [%g1], %g7
- addcc %g7, 1, %g7
+ add %g7, 1, %g7
st %g7, [%g1]
#endif
wr %g3, 0, %psr
nop
+ nop
+ nop
+ cmp %g7, 0
be 3f
nop
2: jmpl %o7, %g0
@@ -164,16 +173,19 @@ ___up_write:
tst %g7
bne 1b
ld [%g1], %g7
- addcc %g7, %g2, %g7
+ add %g7, %g2, %g7
st %g7, [%g1]
stb %g0, [%g1 + 4]
#else
ld [%g1], %g7
- addcc %g7, %g2, %g7
+ add %g7, %g2, %g7
st %g7, [%g1]
#endif
wr %g3, 0, %psr
+ sub %g7, %g2, %g7
+ nop
nop
+ addcc %g7, %g2, %g7
bcs 3f
nop
2: jmpl %o7, %g0
diff --git a/arch/sparc/mm/fault.c b/arch/sparc/mm/fault.c
index d9981e68b..909c46447 100644
--- a/arch/sparc/mm/fault.c
+++ b/arch/sparc/mm/fault.c
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.113 2000/01/21 11:38:47 jj Exp $
+/* $Id: fault.c,v 1.114 2000/02/14 04:52:36 jj Exp $
* fault.c: Page fault handlers for the Sparc.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -342,7 +342,6 @@ asmlinkage void do_sun4c_fault(struct pt_regs *regs, int text_fault, int write,
{
extern void sun4c_update_mmu_cache(struct vm_area_struct *,
unsigned long,pte_t);
- extern pgd_t *sun4c_pgd_offset(struct mm_struct *,unsigned long);
extern pte_t *sun4c_pte_offset(pmd_t *,unsigned long);
struct task_struct *tsk = current;
struct mm_struct *mm = tsk->mm;
@@ -362,7 +361,7 @@ asmlinkage void do_sun4c_fault(struct pt_regs *regs, int text_fault, int write,
}
}
- pgdp = sun4c_pgd_offset(mm, address);
+ pgdp = pgd_offset(mm, address);
ptep = sun4c_pte_offset((pmd_t *) pgdp, address);
if (pgd_val(*pgdp)) {
diff --git a/arch/sparc/mm/nosun4c.c b/arch/sparc/mm/nosun4c.c
index 05aa87b98..8ed9dcf00 100644
--- a/arch/sparc/mm/nosun4c.c
+++ b/arch/sparc/mm/nosun4c.c
@@ -1,4 +1,4 @@
-/* $Id: nosun4c.c,v 1.2 1999/08/31 06:54:36 davem Exp $
+/* $Id: nosun4c.c,v 1.3 2000/02/14 04:52:36 jj Exp $
* nosun4c.c: This file is a bunch of dummies for SMP compiles,
* so that it does not need sun4c and avoid ifdefs.
*
@@ -52,11 +52,6 @@ void sun4c_complete_all_stores(void)
{
}
-pgd_t *sun4c_pgd_offset(struct mm_struct * mm, unsigned long address)
-{
- return NULL;
-}
-
pte_t *sun4c_pte_offset(pmd_t * dir, unsigned long address)
{
return NULL;
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index d46b45378..96aee65d6 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.206 2000/02/08 07:45:59 davem Exp $
+/* $Id: srmmu.c,v 1.208 2000/02/14 04:52:33 jj Exp $
* srmmu.c: SRMMU specific routines for memory management.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -201,7 +201,7 @@ static inline pte_t srmmu_pte_modify(pte_t pte, pgprot_t newprot)
}
/* to find an entry in a top-level page table... */
-static inline pgd_t *srmmu_pgd_offset(struct mm_struct * mm, unsigned long address)
+extern inline pgd_t *srmmu_pgd_offset(struct mm_struct * mm, unsigned long address)
{
return mm->pgd + (address >> SRMMU_PGDIR_SHIFT);
}
@@ -1366,7 +1366,7 @@ static void srmmu_vac_update_mmu_cache(struct vm_area_struct * vma,
if((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED)) {
struct vm_area_struct *vmaring;
struct file *file;
- struct inode *inode;
+ struct address_space *mapping;
unsigned long flags, offset, vaddr, start;
int alias_found = 0;
pgd_t *pgdp;
@@ -1378,10 +1378,10 @@ static void srmmu_vac_update_mmu_cache(struct vm_area_struct * vma,
file = vma->vm_file;
if (!file)
goto done;
- inode = file->f_dentry->d_inode;
+ mapping = file->f_dentry->d_inode->i_mapping;
offset = (address & PAGE_MASK) - vma->vm_start;
- spin_lock(&inode->i_shared_lock);
- vmaring = inode->i_mmap;
+ spin_lock(&mapping->i_shared_lock);
+ vmaring = mapping->i_mmap;
do {
/* Do not mistake ourselves as another mapping. */
if(vmaring == vma)
@@ -1414,7 +1414,7 @@ static void srmmu_vac_update_mmu_cache(struct vm_area_struct * vma,
}
}
} while ((vmaring = vmaring->vm_next_share) != NULL);
- spin_unlock(&inode->i_shared_lock);
+ spin_unlock(&mapping->i_shared_lock);
if(alias_found && ((pte_val(pte) & SRMMU_CACHE) != 0)) {
pgdp = srmmu_pgd_offset(vma->vm_mm, address);
@@ -2337,7 +2337,6 @@ void __init ld_mmu_srmmu(void)
BTFIXUPSET_CALL(pgd_set, srmmu_pgd_set, BTFIXUPCALL_NORM);
BTFIXUPSET_INT(pte_modify_mask, SRMMU_CHG_MASK);
- BTFIXUPSET_CALL(pgd_offset, srmmu_pgd_offset, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(pmd_offset, srmmu_pmd_offset, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(pte_offset, srmmu_pte_offset, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(pte_free_kernel, srmmu_pte_free, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index 715bdb864..6e93111ae 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -1,4 +1,4 @@
-/* $Id: sun4c.c,v 1.187 2000/02/08 07:46:01 davem Exp $
+/* $Id: sun4c.c,v 1.190 2000/02/14 04:52:34 jj Exp $
* sun4c.c: Doing in software what should be done in hardware.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -591,7 +591,7 @@ static unsigned long sun4c_translate_dvma(unsigned long busa)
return (pte << PAGE_SHIFT) + PAGE_OFFSET;
}
-static unsigned long sun4c_unmap_dma_area(unsigned long busa, int len)
+static void sun4c_unmap_dma_area(unsigned long busa, int len)
{
/* Fortunately for us, bus_addr == uncached_virt in sun4c. */
/* XXX Implement this */
@@ -2185,7 +2185,7 @@ static unsigned long sun4c_pgd_page(pgd_t pgd)
}
/* to find an entry in a page-table-directory */
-pgd_t *sun4c_pgd_offset(struct mm_struct * mm, unsigned long address)
+extern inline pgd_t *sun4c_pgd_offset(struct mm_struct * mm, unsigned long address)
{
return mm->pgd + (address >> SUN4C_PGDIR_SHIFT);
}
@@ -2273,7 +2273,7 @@ extern __inline__ pgd_t *sun4c_get_pgd_fast(void)
ret = (unsigned long *)__get_free_page(GFP_KERNEL);
memset (ret, 0, (KERNBASE / SUN4C_PGDIR_SIZE) * sizeof(pgd_t));
- init = pgd_offset(&init_mm, 0);
+ init = sun4c_pgd_offset(&init_mm, 0);
memcpy (((pgd_t *)ret) + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
}
@@ -2418,11 +2418,12 @@ static void sun4c_vac_alias_fixup(struct vm_area_struct *vma, unsigned long addr
if(dentry)
inode = dentry->d_inode;
if(inode) {
+ struct address_space *mapping = inode->i_mapping;
unsigned long offset = (address & PAGE_MASK) - vma->vm_start;
struct vm_area_struct *vmaring;
int alias_found = 0;
- spin_lock(&inode->i_shared_lock);
- vmaring = inode->i_mmap;
+ spin_lock(&mapping->i_shared_lock);
+ vmaring = mapping->i_mmap;
do {
unsigned long vaddr = vmaring->vm_start + offset;
unsigned long start;
@@ -2453,7 +2454,7 @@ static void sun4c_vac_alias_fixup(struct vm_area_struct *vma, unsigned long addr
}
}
} while ((vmaring = vmaring->vm_next_share) != NULL);
- spin_unlock(&inode->i_shared_lock);
+ spin_unlock(&mapping->i_shared_lock);
if (alias_found && !(pte_val(pte) & _SUN4C_PAGE_NOCACHE)) {
pgdp = sun4c_pgd_offset(vma->vm_mm, address);
@@ -2695,7 +2696,6 @@ void __init ld_mmu_sun4c(void)
BTFIXUPSET_CALL(mk_pte_io, sun4c_mk_pte_io, BTFIXUPCALL_NORM);
BTFIXUPSET_INT(pte_modify_mask, _SUN4C_PAGE_CHG_MASK);
- BTFIXUPSET_CALL(pgd_offset, sun4c_pgd_offset, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(pmd_offset, sun4c_pmd_offset, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(pte_offset, sun4c_pte_offset, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(pte_free_kernel, sun4c_pte_free_kernel, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/mm/swift.S b/arch/sparc/mm/swift.S
index e9fe43293..914f3071d 100644
--- a/arch/sparc/mm/swift.S
+++ b/arch/sparc/mm/swift.S
@@ -1,4 +1,4 @@
-/* $Id: swift.S,v 1.3 1999/11/14 06:13:56 zaitcev Exp $
+/* $Id: swift.S,v 1.4 2000/02/12 03:08:47 zaitcev Exp $
* swift.S: MicroSparc-II mmu/cache operations.
*
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -41,10 +41,10 @@ swift_flush_chunk:
swift_flush_page_to_ram:
sethi %hi(0x2000), %o0
1: subcc %o0, 0x10, %o0
- sta %g0, [%o0] ASI_M_TXTC_TAG
+ add %o0, %o0, %o1
sta %g0, [%o0] ASI_M_DATAC_TAG
bne 1b
- nop
+ sta %g0, [%o1] ASI_M_TXTC_TAG
retl
nop
#else
diff --git a/arch/sparc64/config.in b/arch/sparc64/config.in
index 6aebbfcc8..bee2a5574 100644
--- a/arch/sparc64/config.in
+++ b/arch/sparc64/config.in
@@ -226,9 +226,9 @@ if [ "$CONFIG_NET" = "y" ]; then
if [ "$CONFIG_PCI" = "y" ]; then
tristate 'Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
tristate '3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX
- tristate 'RealTek 8129/8139 (not 8019/8029!) support' CONFIG_RTL8139
+ tristate 'RealTek RTL-8139 support' CONFIG_8139TOO
tristate 'PCI NE2000 support' CONFIG_NE2K_PCI
- tristate 'EtherExpressPro/100 support' CONFIG_EEXPRESS_PRO100
+ tristate 'EtherExpressPro/100 support' CONFIG_EEPRO100
tristate 'Adaptec Starfire support' CONFIG_ADAPTEC_STARFIRE
fi
endmenu
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 747ded255..917bb5e74 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -318,12 +318,12 @@ CONFIG_ISO9660_FS=m
# CONFIG_JOLIET is not set
CONFIG_MINIX_FS=m
# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
CONFIG_HPFS_FS=m
CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
CONFIG_ROMFS_FS=m
CONFIG_EXT2_FS=y
CONFIG_SYSV_FS=m
diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
index 04a5b6f7f..39a000ef3 100644
--- a/arch/sparc64/kernel/ioctl32.c
+++ b/arch/sparc64/kernel/ioctl32.c
@@ -1,7 +1,7 @@
-/* $Id: ioctl32.c,v 1.79 2000/02/08 20:24:25 davem Exp $
+/* $Id: ioctl32.c,v 1.80 2000/02/17 06:45:09 jj Exp $
* ioctl32.c: Conversion between 32bit and 64bit native ioctls.
*
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
* Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
*
* These routines maintain argument size conversion between 32bit and 64bit
@@ -42,6 +42,7 @@
#include <linux/netdevice.h>
#include <linux/raw.h>
#include <linux/smb_fs.h>
+#include <linux/blkpg.h>
#include <scsi/scsi.h>
/* Ugly hack. */
@@ -435,7 +436,7 @@ struct ifconf32 {
__kernel_caddr_t32 ifcbuf;
};
-static int dev_ifname32(unsigned int fd, unsigned long arg)
+static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct net_device *dev;
struct ifreq32 ifr32;
@@ -454,7 +455,7 @@ static int dev_ifname32(unsigned int fd, unsigned long arg)
return (err ? -EFAULT : 0);
}
-static inline int dev_ifconf(unsigned int fd, unsigned long arg)
+static inline int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct ifconf32 ifc32;
struct ifconf ifc;
@@ -671,7 +672,7 @@ struct hd_geometry32 {
u32 start;
};
-static inline int hdio_getgeo(unsigned int fd, unsigned long arg)
+static inline int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg)
{
mm_segment_t old_fs = get_fs();
struct hd_geometry geo;
@@ -1024,8 +1025,8 @@ struct floppy_write_errors32 {
unsigned int badness;
};
-#define FDSETPRM32 _IOW(2, 0x42, struct floppy_struct32)
-#define FDDEFPRM32 _IOW(2, 0x43, struct floppy_struct32)
+#define FDSETPRM32 _IOW(2, 0x42, struct floppy_struct32)
+#define FDDEFPRM32 _IOW(2, 0x43, struct floppy_struct32)
#define FDGETPRM32 _IOR(2, 0x04, struct floppy_struct32)
#define FDSETDRVPRM32 _IOW(2, 0x90, struct floppy_drive_params32)
#define FDGETDRVPRM32 _IOR(2, 0x11, struct floppy_drive_params32)
@@ -1648,7 +1649,7 @@ struct consolefontdesc32 {
u32 chardata; /* font data in expanded form */
};
-static int do_fontx_ioctl(struct file *file, int cmd, struct consolefontdesc32 *user_cfd)
+static int do_fontx_ioctl(unsigned int fd, int cmd, struct consolefontdesc32 *user_cfd, struct file *file)
{
struct consolefontdesc cfdarg;
struct console_font_op op;
@@ -1657,7 +1658,7 @@ static int do_fontx_ioctl(struct file *file, int cmd, struct consolefontdesc32 *
perm = vt_check(file);
if (perm < 0) return perm;
- if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc32)))
+ if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc32)))
return -EFAULT;
cfdarg.chardata = (unsigned char *)A(((struct consolefontdesc32 *)&cfdarg)->chardata);
@@ -1703,7 +1704,7 @@ struct console_font_op32 {
u32 data; /* font data with height fixed to 32 */
};
-static int do_kdfontop_ioctl(struct file *file, struct console_font_op32 *fontop)
+static int do_kdfontop_ioctl(unsigned int fd, unsigned int cmd, struct console_font_op32 *fontop, struct file *file)
{
struct console_font_op op;
int perm = vt_check(file), i;
@@ -1731,7 +1732,7 @@ struct unimapdesc32 {
u32 entries;
};
-static int do_unimap_ioctl(struct file *file, int cmd, struct unimapdesc32 *user_ud)
+static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, struct unimapdesc32 *user_ud, struct file *file)
{
struct unimapdesc32 tmp;
int perm = vt_check(file);
@@ -1978,768 +1979,813 @@ static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg)
return -EINVAL;
}
-asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+static int ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg)
{
- struct file * filp;
- int error = -EBADF;
+ return -EINVAL;
+}
- lock_kernel();
- filp = fget(fd);
- if(!filp)
- goto out2;
+static int broken_blkgetsize(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ /* The mkswap binary hard codes it to Intel value :-((( */
+ return w_long(fd, BLKGETSIZE, arg);
+}
- if (!filp->f_op || !filp->f_op->ioctl) {
- error = sys_ioctl (fd, cmd, arg);
- goto out;
- }
- switch (cmd) {
- case SIOCGIFNAME:
- error = dev_ifname32(fd, arg);
- goto out;
+struct blkpg_ioctl_arg32 {
+ int op;
+ int flags;
+ int datalen;
+ u32 data;
+};
+
+static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, struct blkpg_ioctl_arg32 *arg)
+{
+ struct blkpg_ioctl_arg a;
+ struct blkpg_partition p;
+ int err;
+ mm_segment_t old_fs = get_fs();
+
+ err = get_user(a.op, &arg->op);
+ err |= __get_user(a.flags, &arg->flags);
+ err |= __get_user(a.datalen, &arg->datalen);
+ err |= __get_user((long)a.data, &arg->data);
+ if (err) return err;
+ switch (a.op) {
+ case BLKPG_ADD_PARTITION:
+ case BLKPG_DEL_PARTITION:
+ if (a.datalen < sizeof(struct blkpg_partition))
+ return -EINVAL;
+ if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
+ return -EFAULT;
+ a.data = &p;
+ set_fs (KERNEL_DS);
+ err = sys_ioctl(fd, cmd, (unsigned long)&a);
+ set_fs (old_fs);
+ default:
+ return -EINVAL;
+ }
+ return err;
+}
- case SIOCGIFCONF:
- error = dev_ifconf(fd, arg);
- goto out;
-
- case SIOCGIFFLAGS:
- case SIOCSIFFLAGS:
- case SIOCGIFMETRIC:
- case SIOCSIFMETRIC:
- case SIOCGIFMTU:
- case SIOCSIFMTU:
- case SIOCGIFMEM:
- case SIOCSIFMEM:
- case SIOCGIFHWADDR:
- case SIOCSIFHWADDR:
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- case SIOCGIFINDEX:
- case SIOCGIFMAP:
- case SIOCSIFMAP:
- case SIOCGIFADDR:
- case SIOCSIFADDR:
- case SIOCGIFBRDADDR:
- case SIOCSIFBRDADDR:
- case SIOCGIFDSTADDR:
- case SIOCSIFDSTADDR:
- case SIOCGIFNETMASK:
- case SIOCSIFNETMASK:
- case SIOCSIFPFLAGS:
- case SIOCGIFPFLAGS:
- case SIOCGPPPSTATS:
- case SIOCGPPPCSTATS:
- case SIOCGPPPVER:
- case SIOCGIFTXQLEN:
- case SIOCSIFTXQLEN:
- case SIOCETHTOOL:
- error = dev_ifsioc(fd, cmd, arg);
- goto out;
-
- case SIOCADDRT:
- case SIOCDELRT:
- error = routing_ioctl(fd, cmd, arg);
- goto out;
+static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg);
+}
- case SIOCRTMSG: /* Note SIOCRTMSG is no longer, so this is safe and
- * the user would have seen just an -EINVAL anyways.
- */
- error = -EINVAL;
- goto out;
+struct ioctl_trans {
+ unsigned int cmd;
+ unsigned int handler;
+ unsigned int next;
+};
- case SIOCGSTAMP:
- /* Sorry, timeval in the kernel is different now. */
- error = do_siocgstamp(fd, cmd, arg);
- goto out;
+#define COMPATIBLE_IOCTL(cmd) asm volatile(".word %0, sys_ioctl, 0" : : "i" (cmd));
+#define HANDLE_IOCTL(cmd,handler) asm volatile(".word %0, %1, 0" : : "i" (cmd), "i" (handler));
+#define IOCTL_TABLE_START void ioctl32_foo(void) { asm volatile(".data\nioctl_translations:");
+#define IOCTL_TABLE_END asm volatile("\nioctl_translations_end:\n\t.previous"); }
- case HDIO_GETGEO:
- error = hdio_getgeo(fd, arg);
- goto out;
-
- case BLKRAGET:
- case BLKGETSIZE:
- case 0x1260:
- /* The mkswap binary hard codes it to Intel value :-((( */
- if(cmd == 0x1260)
- cmd = BLKGETSIZE;
- error = w_long(fd, cmd, arg);
- goto out;
-
- case FBIOPUTCMAP32:
- case FBIOGETCMAP32:
- error = fbiogetputcmap(fd, cmd, arg);
- goto out;
-
- case FBIOSCURSOR32:
- error = fbiogscursor(fd, cmd, arg);
- goto out;
+IOCTL_TABLE_START
+/* List here exlicitly which ioctl's are known to have
+ * compatable types passed or none at all...
+ */
+/* Big T */
+COMPATIBLE_IOCTL(TCGETA)
+COMPATIBLE_IOCTL(TCSETA)
+COMPATIBLE_IOCTL(TCSETAW)
+COMPATIBLE_IOCTL(TCSETAF)
+COMPATIBLE_IOCTL(TCSBRK)
+COMPATIBLE_IOCTL(TCXONC)
+COMPATIBLE_IOCTL(TCFLSH)
+COMPATIBLE_IOCTL(TCGETS)
+COMPATIBLE_IOCTL(TCSETS)
+COMPATIBLE_IOCTL(TCSETSW)
+COMPATIBLE_IOCTL(TCSETSF)
+COMPATIBLE_IOCTL(TIOCLINUX)
+/* Little t */
+COMPATIBLE_IOCTL(TIOCGETD)
+COMPATIBLE_IOCTL(TIOCSETD)
+COMPATIBLE_IOCTL(TIOCEXCL)
+COMPATIBLE_IOCTL(TIOCNXCL)
+COMPATIBLE_IOCTL(TIOCCONS)
+COMPATIBLE_IOCTL(TIOCGSOFTCAR)
+COMPATIBLE_IOCTL(TIOCSSOFTCAR)
+COMPATIBLE_IOCTL(TIOCSWINSZ)
+COMPATIBLE_IOCTL(TIOCGWINSZ)
+COMPATIBLE_IOCTL(TIOCMGET)
+COMPATIBLE_IOCTL(TIOCMBIC)
+COMPATIBLE_IOCTL(TIOCMBIS)
+COMPATIBLE_IOCTL(TIOCMSET)
+COMPATIBLE_IOCTL(TIOCPKT)
+COMPATIBLE_IOCTL(TIOCNOTTY)
+COMPATIBLE_IOCTL(TIOCSTI)
+COMPATIBLE_IOCTL(TIOCOUTQ)
+COMPATIBLE_IOCTL(TIOCSPGRP)
+COMPATIBLE_IOCTL(TIOCGPGRP)
+COMPATIBLE_IOCTL(TIOCSCTTY)
+COMPATIBLE_IOCTL(TIOCGPTN)
+COMPATIBLE_IOCTL(TIOCSPTLCK)
+COMPATIBLE_IOCTL(TIOCGSERIAL)
+COMPATIBLE_IOCTL(TIOCSSERIAL)
+COMPATIBLE_IOCTL(TIOCSERGETLSR)
+/* Big F */
+COMPATIBLE_IOCTL(FBIOGTYPE)
+COMPATIBLE_IOCTL(FBIOSATTR)
+COMPATIBLE_IOCTL(FBIOGATTR)
+COMPATIBLE_IOCTL(FBIOSVIDEO)
+COMPATIBLE_IOCTL(FBIOGVIDEO)
+COMPATIBLE_IOCTL(FBIOGCURSOR32) /* This is not implemented yet. Later it should be converted... */
+COMPATIBLE_IOCTL(FBIOSCURPOS)
+COMPATIBLE_IOCTL(FBIOGCURPOS)
+COMPATIBLE_IOCTL(FBIOGCURMAX)
+COMPATIBLE_IOCTL(FBIOGET_VSCREENINFO)
+COMPATIBLE_IOCTL(FBIOPUT_VSCREENINFO)
+COMPATIBLE_IOCTL(FBIOPAN_DISPLAY)
+COMPATIBLE_IOCTL(FBIOGET_FCURSORINFO)
+COMPATIBLE_IOCTL(FBIOGET_VCURSORINFO)
+COMPATIBLE_IOCTL(FBIOPUT_VCURSORINFO)
+COMPATIBLE_IOCTL(FBIOGET_CURSORSTATE)
+COMPATIBLE_IOCTL(FBIOPUT_CURSORSTATE)
+COMPATIBLE_IOCTL(FBIOGET_CON2FBMAP)
+COMPATIBLE_IOCTL(FBIOPUT_CON2FBMAP)
+/* Little f */
+COMPATIBLE_IOCTL(FIOCLEX)
+COMPATIBLE_IOCTL(FIONCLEX)
+COMPATIBLE_IOCTL(FIOASYNC)
+COMPATIBLE_IOCTL(FIONBIO)
+COMPATIBLE_IOCTL(FIONREAD) /* This is also TIOCINQ */
+/* 0x00 */
+COMPATIBLE_IOCTL(FIBMAP)
+COMPATIBLE_IOCTL(FIGETBSZ)
+/* 0x03 -- HD/IDE ioctl's used by hdparm and friends.
+ * Some need translations, these do not.
+ */
+COMPATIBLE_IOCTL(HDIO_GET_IDENTITY)
+COMPATIBLE_IOCTL(HDIO_SET_DMA)
+COMPATIBLE_IOCTL(HDIO_SET_KEEPSETTINGS)
+COMPATIBLE_IOCTL(HDIO_SET_UNMASKINTR)
+COMPATIBLE_IOCTL(HDIO_SET_NOWERR)
+COMPATIBLE_IOCTL(HDIO_SET_32BIT)
+COMPATIBLE_IOCTL(HDIO_SET_MULTCOUNT)
+COMPATIBLE_IOCTL(HDIO_DRIVE_CMD)
+COMPATIBLE_IOCTL(HDIO_SET_PIO_MODE)
+COMPATIBLE_IOCTL(HDIO_SCAN_HWIF)
+COMPATIBLE_IOCTL(HDIO_SET_NICE)
+/* 0x02 -- Floppy ioctls */
+COMPATIBLE_IOCTL(FDMSGON)
+COMPATIBLE_IOCTL(FDMSGOFF)
+COMPATIBLE_IOCTL(FDSETEMSGTRESH)
+COMPATIBLE_IOCTL(FDFLUSH)
+COMPATIBLE_IOCTL(FDWERRORCLR)
+COMPATIBLE_IOCTL(FDSETMAXERRS)
+COMPATIBLE_IOCTL(FDGETMAXERRS)
+COMPATIBLE_IOCTL(FDGETDRVTYP)
+COMPATIBLE_IOCTL(FDEJECT)
+COMPATIBLE_IOCTL(FDCLRPRM)
+COMPATIBLE_IOCTL(FDFMTBEG)
+COMPATIBLE_IOCTL(FDFMTEND)
+COMPATIBLE_IOCTL(FDRESET)
+COMPATIBLE_IOCTL(FDTWADDLE)
+COMPATIBLE_IOCTL(FDFMTTRK)
+COMPATIBLE_IOCTL(FDRAWCMD)
+/* 0x12 */
+COMPATIBLE_IOCTL(BLKROSET)
+COMPATIBLE_IOCTL(BLKROGET)
+COMPATIBLE_IOCTL(BLKRRPART)
+COMPATIBLE_IOCTL(BLKFLSBUF)
+COMPATIBLE_IOCTL(BLKRASET)
+COMPATIBLE_IOCTL(BLKFRASET)
+COMPATIBLE_IOCTL(BLKSECTSET)
+COMPATIBLE_IOCTL(BLKSSZGET)
- case FBIOGET_FSCREENINFO:
- case FBIOGETCMAP:
- case FBIOPUTCMAP:
- error = fb_ioctl_trans(fd, cmd, arg);
- goto out;
- case HDIO_GET_KEEPSETTINGS:
- case HDIO_GET_UNMASKINTR:
- case HDIO_GET_DMA:
- case HDIO_GET_32BIT:
- case HDIO_GET_MULTCOUNT:
- case HDIO_GET_NOWERR:
- case HDIO_GET_NICE:
- error = hdio_ioctl_trans(fd, cmd, arg);
- goto out;
+#if 0 /* New RAID code is being merged, fix up to handle
+ * new RAID ioctls when fully merged in 2.3.x -DaveM
+ */
+/* 0x09 */
+COMPATIBLE_IOCTL(REGISTER_DEV)
+COMPATIBLE_IOCTL(REGISTER_DEV_NEW)
+COMPATIBLE_IOCTL(START_MD)
+COMPATIBLE_IOCTL(STOP_MD)
+#endif
+
+/* Big K */
+COMPATIBLE_IOCTL(PIO_FONT)
+COMPATIBLE_IOCTL(GIO_FONT)
+COMPATIBLE_IOCTL(KDSIGACCEPT)
+COMPATIBLE_IOCTL(KDGETKEYCODE)
+COMPATIBLE_IOCTL(KDSETKEYCODE)
+COMPATIBLE_IOCTL(KIOCSOUND)
+COMPATIBLE_IOCTL(KDMKTONE)
+COMPATIBLE_IOCTL(KDGKBTYPE)
+COMPATIBLE_IOCTL(KDSETMODE)
+COMPATIBLE_IOCTL(KDGETMODE)
+COMPATIBLE_IOCTL(KDSKBMODE)
+COMPATIBLE_IOCTL(KDGKBMODE)
+COMPATIBLE_IOCTL(KDSKBMETA)
+COMPATIBLE_IOCTL(KDGKBMETA)
+COMPATIBLE_IOCTL(KDGKBENT)
+COMPATIBLE_IOCTL(KDSKBENT)
+COMPATIBLE_IOCTL(KDGKBSENT)
+COMPATIBLE_IOCTL(KDSKBSENT)
+COMPATIBLE_IOCTL(KDGKBDIACR)
+COMPATIBLE_IOCTL(KDSKBDIACR)
+COMPATIBLE_IOCTL(KDGKBLED)
+COMPATIBLE_IOCTL(KDSKBLED)
+COMPATIBLE_IOCTL(KDGETLED)
+COMPATIBLE_IOCTL(KDSETLED)
+COMPATIBLE_IOCTL(GIO_SCRNMAP)
+COMPATIBLE_IOCTL(PIO_SCRNMAP)
+COMPATIBLE_IOCTL(GIO_UNISCRNMAP)
+COMPATIBLE_IOCTL(PIO_UNISCRNMAP)
+COMPATIBLE_IOCTL(PIO_FONTRESET)
+COMPATIBLE_IOCTL(PIO_UNIMAPCLR)
+/* Little k */
+COMPATIBLE_IOCTL(KIOCTYPE)
+COMPATIBLE_IOCTL(KIOCLAYOUT)
+COMPATIBLE_IOCTL(KIOCGTRANS)
+COMPATIBLE_IOCTL(KIOCTRANS)
+COMPATIBLE_IOCTL(KIOCCMD)
+COMPATIBLE_IOCTL(KIOCSDIRECT)
+COMPATIBLE_IOCTL(KIOCSLED)
+COMPATIBLE_IOCTL(KIOCGLED)
+COMPATIBLE_IOCTL(KIOCSRATE)
+COMPATIBLE_IOCTL(KIOCGRATE)
+/* Big S */
+COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN)
+COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK)
+COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK)
+COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY)
+COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_ENABLE)
+COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_DISABLE)
+COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER)
+COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND)
+/* Big V */
+COMPATIBLE_IOCTL(VT_SETMODE)
+COMPATIBLE_IOCTL(VT_GETMODE)
+COMPATIBLE_IOCTL(VT_GETSTATE)
+COMPATIBLE_IOCTL(VT_OPENQRY)
+COMPATIBLE_IOCTL(VT_ACTIVATE)
+COMPATIBLE_IOCTL(VT_WAITACTIVE)
+COMPATIBLE_IOCTL(VT_RELDISP)
+COMPATIBLE_IOCTL(VT_DISALLOCATE)
+COMPATIBLE_IOCTL(VT_RESIZE)
+COMPATIBLE_IOCTL(VT_RESIZEX)
+COMPATIBLE_IOCTL(VT_LOCKSWITCH)
+COMPATIBLE_IOCTL(VT_UNLOCKSWITCH)
+/* Little v */
+COMPATIBLE_IOCTL(VUIDSFORMAT)
+COMPATIBLE_IOCTL(VUIDGFORMAT)
+/* Little v, the video4linux ioctls */
+COMPATIBLE_IOCTL(VIDIOCGCAP)
+COMPATIBLE_IOCTL(VIDIOCGCHAN)
+COMPATIBLE_IOCTL(VIDIOCSCHAN)
+COMPATIBLE_IOCTL(VIDIOCGPICT)
+COMPATIBLE_IOCTL(VIDIOCSPICT)
+COMPATIBLE_IOCTL(VIDIOCCAPTURE)
+COMPATIBLE_IOCTL(VIDIOCKEY)
+COMPATIBLE_IOCTL(VIDIOCGAUDIO)
+COMPATIBLE_IOCTL(VIDIOCSAUDIO)
+COMPATIBLE_IOCTL(VIDIOCSYNC)
+COMPATIBLE_IOCTL(VIDIOCMCAPTURE)
+COMPATIBLE_IOCTL(VIDIOCGMBUF)
+COMPATIBLE_IOCTL(VIDIOCGUNIT)
+COMPATIBLE_IOCTL(VIDIOCGCAPTURE)
+COMPATIBLE_IOCTL(VIDIOCSCAPTURE)
+/* BTTV specific... */
+COMPATIBLE_IOCTL(_IOW('v', BASE_VIDIOCPRIVATE+0, char [256]))
+COMPATIBLE_IOCTL(_IOR('v', BASE_VIDIOCPRIVATE+1, char [256]))
+COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int))
+COMPATIBLE_IOCTL(_IOW('v' , BASE_VIDIOCPRIVATE+3, char [16])) /* struct bttv_pll_info */
+COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+4, int))
+COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+5, int))
+COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+6, int))
+COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+7, int))
+/* Little p (/dev/rtc, /dev/envctrl, etc.) */
+COMPATIBLE_IOCTL(RTCGET)
+COMPATIBLE_IOCTL(RTCSET)
+COMPATIBLE_IOCTL(I2CIOCSADR)
+COMPATIBLE_IOCTL(I2CIOCGADR)
+/* Little m */
+COMPATIBLE_IOCTL(MTIOCTOP)
+/* OPENPROMIO, SunOS/Solaris only, the NetBSD one's have
+ * embedded pointers in the arg which we'd need to clean up...
+ */
+COMPATIBLE_IOCTL(OPROMGETOPT)
+COMPATIBLE_IOCTL(OPROMSETOPT)
+COMPATIBLE_IOCTL(OPROMNXTOPT)
+COMPATIBLE_IOCTL(OPROMSETOPT2)
+COMPATIBLE_IOCTL(OPROMNEXT)
+COMPATIBLE_IOCTL(OPROMCHILD)
+COMPATIBLE_IOCTL(OPROMGETPROP)
+COMPATIBLE_IOCTL(OPROMNXTPROP)
+COMPATIBLE_IOCTL(OPROMU2P)
+COMPATIBLE_IOCTL(OPROMGETCONS)
+COMPATIBLE_IOCTL(OPROMGETFBNAME)
+COMPATIBLE_IOCTL(OPROMGETBOOTARGS)
+COMPATIBLE_IOCTL(OPROMSETCUR)
+COMPATIBLE_IOCTL(OPROMPCI2NODE)
+COMPATIBLE_IOCTL(OPROMPATH2NODE)
+/* Socket level stuff */
+COMPATIBLE_IOCTL(FIOSETOWN)
+COMPATIBLE_IOCTL(SIOCSPGRP)
+COMPATIBLE_IOCTL(FIOGETOWN)
+COMPATIBLE_IOCTL(SIOCGPGRP)
+COMPATIBLE_IOCTL(SIOCATMARK)
+COMPATIBLE_IOCTL(SIOCSIFLINK)
+COMPATIBLE_IOCTL(SIOCSIFENCAP)
+COMPATIBLE_IOCTL(SIOCGIFENCAP)
+COMPATIBLE_IOCTL(SIOCSIFBR)
+COMPATIBLE_IOCTL(SIOCGIFBR)
+COMPATIBLE_IOCTL(SIOCSARP)
+COMPATIBLE_IOCTL(SIOCGARP)
+COMPATIBLE_IOCTL(SIOCDARP)
+#if 0 /* XXX No longer exist in new routing code. XXX */
+COMPATIBLE_IOCTL(OLD_SIOCSARP)
+COMPATIBLE_IOCTL(OLD_SIOCGARP)
+COMPATIBLE_IOCTL(OLD_SIOCDARP)
+#endif
+COMPATIBLE_IOCTL(SIOCSRARP)
+COMPATIBLE_IOCTL(SIOCGRARP)
+COMPATIBLE_IOCTL(SIOCDRARP)
+COMPATIBLE_IOCTL(SIOCADDDLCI)
+COMPATIBLE_IOCTL(SIOCDELDLCI)
+/* SG stuff */
+COMPATIBLE_IOCTL(SG_SET_TIMEOUT)
+COMPATIBLE_IOCTL(SG_GET_TIMEOUT)
+COMPATIBLE_IOCTL(SG_EMULATED_HOST)
+COMPATIBLE_IOCTL(SG_SET_TRANSFORM)
+COMPATIBLE_IOCTL(SG_GET_TRANSFORM)
+/* PPP stuff */
+COMPATIBLE_IOCTL(PPPIOCGFLAGS)
+COMPATIBLE_IOCTL(PPPIOCSFLAGS)
+COMPATIBLE_IOCTL(PPPIOCGASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCSASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCGUNIT)
+COMPATIBLE_IOCTL(PPPIOCGRASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCSRASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCGMRU)
+COMPATIBLE_IOCTL(PPPIOCSMRU)
+COMPATIBLE_IOCTL(PPPIOCSMAXCID)
+COMPATIBLE_IOCTL(PPPIOCGXASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCSXASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCXFERUNIT)
+COMPATIBLE_IOCTL(PPPIOCGNPMODE)
+COMPATIBLE_IOCTL(PPPIOCSNPMODE)
+COMPATIBLE_IOCTL(PPPIOCGDEBUG)
+COMPATIBLE_IOCTL(PPPIOCSDEBUG)
+COMPATIBLE_IOCTL(PPPIOCNEWUNIT)
+COMPATIBLE_IOCTL(PPPIOCATTACH)
+COMPATIBLE_IOCTL(PPPIOCDETACH)
+/* CDROM stuff */
+COMPATIBLE_IOCTL(CDROMPAUSE)
+COMPATIBLE_IOCTL(CDROMRESUME)
+COMPATIBLE_IOCTL(CDROMPLAYMSF)
+COMPATIBLE_IOCTL(CDROMPLAYTRKIND)
+COMPATIBLE_IOCTL(CDROMREADTOCHDR)
+COMPATIBLE_IOCTL(CDROMREADTOCENTRY)
+COMPATIBLE_IOCTL(CDROMSTOP)
+COMPATIBLE_IOCTL(CDROMSTART)
+COMPATIBLE_IOCTL(CDROMEJECT)
+COMPATIBLE_IOCTL(CDROMVOLCTRL)
+COMPATIBLE_IOCTL(CDROMSUBCHNL)
+COMPATIBLE_IOCTL(CDROMEJECT_SW)
+COMPATIBLE_IOCTL(CDROMMULTISESSION)
+COMPATIBLE_IOCTL(CDROM_GET_MCN)
+COMPATIBLE_IOCTL(CDROMRESET)
+COMPATIBLE_IOCTL(CDROMVOLREAD)
+COMPATIBLE_IOCTL(CDROMSEEK)
+COMPATIBLE_IOCTL(CDROMPLAYBLK)
+COMPATIBLE_IOCTL(CDROMCLOSETRAY)
+COMPATIBLE_IOCTL(CDROM_SET_OPTIONS)
+COMPATIBLE_IOCTL(CDROM_CLEAR_OPTIONS)
+COMPATIBLE_IOCTL(CDROM_SELECT_SPEED)
+COMPATIBLE_IOCTL(CDROM_SELECT_DISC)
+COMPATIBLE_IOCTL(CDROM_MEDIA_CHANGED)
+COMPATIBLE_IOCTL(CDROM_DRIVE_STATUS)
+COMPATIBLE_IOCTL(CDROM_DISC_STATUS)
+COMPATIBLE_IOCTL(CDROM_CHANGER_NSLOTS)
+COMPATIBLE_IOCTL(CDROM_LOCKDOOR)
+COMPATIBLE_IOCTL(CDROM_DEBUG)
+COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY)
+/* Big L */
+COMPATIBLE_IOCTL(LOOP_SET_FD)
+COMPATIBLE_IOCTL(LOOP_CLR_FD)
+/* Big A */
+COMPATIBLE_IOCTL(AUDIO_GETINFO)
+COMPATIBLE_IOCTL(AUDIO_SETINFO)
+COMPATIBLE_IOCTL(AUDIO_DRAIN)
+COMPATIBLE_IOCTL(AUDIO_GETDEV)
+COMPATIBLE_IOCTL(AUDIO_GETDEV_SUNOS)
+COMPATIBLE_IOCTL(AUDIO_FLUSH)
+/* Big Q for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_SEQ_RESET)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_SYNC)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_INFO)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_CTRLRATE)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_GETOUTCOUNT)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_GETINCOUNT)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_PERCMODE)
+COMPATIBLE_IOCTL(SNDCTL_FM_LOAD_INSTR)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_TESTMIDI)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_RESETSAMPLES)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_NRSYNTHS)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_NRMIDIS)
+COMPATIBLE_IOCTL(SNDCTL_MIDI_INFO)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_THRESHOLD)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_MEMAVL)
+COMPATIBLE_IOCTL(SNDCTL_FM_4OP_ENABLE)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_PANIC)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_OUTOFBAND)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_GETTIME)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_ID)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_CONTROL)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_REMOVESAMPLE)
+/* Big T for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_TMR_TIMEBASE)
+COMPATIBLE_IOCTL(SNDCTL_TMR_START)
+COMPATIBLE_IOCTL(SNDCTL_TMR_STOP)
+COMPATIBLE_IOCTL(SNDCTL_TMR_CONTINUE)
+COMPATIBLE_IOCTL(SNDCTL_TMR_TEMPO)
+COMPATIBLE_IOCTL(SNDCTL_TMR_SOURCE)
+COMPATIBLE_IOCTL(SNDCTL_TMR_METRONOME)
+COMPATIBLE_IOCTL(SNDCTL_TMR_SELECT)
+/* Little m for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_MIDI_PRETIME)
+COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUMODE)
+COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUCMD)
+/* Big P for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_DSP_RESET)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SYNC)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SPEED)
+COMPATIBLE_IOCTL(SNDCTL_DSP_STEREO)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETBLKSIZE)
+COMPATIBLE_IOCTL(SNDCTL_DSP_CHANNELS)
+COMPATIBLE_IOCTL(SOUND_PCM_WRITE_FILTER)
+COMPATIBLE_IOCTL(SNDCTL_DSP_POST)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SUBDIVIDE)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETFRAGMENT)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETFMTS)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETFMT)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETOSPACE)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETISPACE)
+COMPATIBLE_IOCTL(SNDCTL_DSP_NONBLOCK)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETCAPS)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETTRIGGER)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETTRIGGER)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETIPTR)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETOPTR)
+/* SNDCTL_DSP_MAPINBUF, XXX needs translation */
+/* SNDCTL_DSP_MAPOUTBUF, XXX needs translation */
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETSYNCRO)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETDUPLEX)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETODELAY)
+COMPATIBLE_IOCTL(SNDCTL_DSP_PROFILE)
+COMPATIBLE_IOCTL(SOUND_PCM_READ_RATE)
+COMPATIBLE_IOCTL(SOUND_PCM_READ_CHANNELS)
+COMPATIBLE_IOCTL(SOUND_PCM_READ_BITS)
+COMPATIBLE_IOCTL(SOUND_PCM_READ_FILTER)
+/* Big C for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_COPR_RESET)
+COMPATIBLE_IOCTL(SNDCTL_COPR_LOAD)
+COMPATIBLE_IOCTL(SNDCTL_COPR_RDATA)
+COMPATIBLE_IOCTL(SNDCTL_COPR_RCODE)
+COMPATIBLE_IOCTL(SNDCTL_COPR_WDATA)
+COMPATIBLE_IOCTL(SNDCTL_COPR_WCODE)
+COMPATIBLE_IOCTL(SNDCTL_COPR_RUN)
+COMPATIBLE_IOCTL(SNDCTL_COPR_HALT)
+COMPATIBLE_IOCTL(SNDCTL_COPR_SENDMSG)
+COMPATIBLE_IOCTL(SNDCTL_COPR_RCVMSG)
+/* Big M for sound/OSS */
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_VOLUME)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_BASS)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_TREBLE)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_SYNTH)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_PCM)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_SPEAKER)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_MIC)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_CD)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_IMIX)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_ALTPCM)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECLEV)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_IGAIN)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_OGAIN)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE1)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE2)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE3)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_MUTE)
+/* SOUND_MIXER_READ_ENHANCE, same value as READ_MUTE */
+/* SOUND_MIXER_READ_LOUD, same value as READ_MUTE */
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECSRC)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_DEVMASK)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECMASK)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_STEREODEVS)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_CAPS)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_VOLUME)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_BASS)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_TREBLE)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SYNTH)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_PCM)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SPEAKER)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MIC)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_CD)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IMIX)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_ALTPCM)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECLEV)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IGAIN)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_OGAIN)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE1)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE2)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE3)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MUTE)
+/* SOUND_MIXER_WRITE_ENHANCE, same value as WRITE_MUTE */
+/* SOUND_MIXER_WRITE_LOUD, same value as WRITE_MUTE */
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECSRC)
+COMPATIBLE_IOCTL(SOUND_MIXER_INFO)
+COMPATIBLE_IOCTL(SOUND_OLD_MIXER_INFO)
+COMPATIBLE_IOCTL(SOUND_MIXER_ACCESS)
+COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE1)
+COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE2)
+COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE3)
+COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE4)
+COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE5)
+COMPATIBLE_IOCTL(SOUND_MIXER_GETLEVELS)
+COMPATIBLE_IOCTL(SOUND_MIXER_SETLEVELS)
+COMPATIBLE_IOCTL(OSS_GETVERSION)
+/* AUTOFS */
+COMPATIBLE_IOCTL(AUTOFS_IOC_READY)
+COMPATIBLE_IOCTL(AUTOFS_IOC_FAIL)
+COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC)
+COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER)
+COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE)
+/* Raw devices */
+COMPATIBLE_IOCTL(RAW_SETBIND)
+COMPATIBLE_IOCTL(RAW_GETBIND)
+/* SMB ioctls which do not need any translations */
+COMPATIBLE_IOCTL(SMB_IOC_NEWCONN)
+/* Little a */
+COMPATIBLE_IOCTL(ATMSIGD_CTRL)
+COMPATIBLE_IOCTL(ATMARPD_CTRL)
+COMPATIBLE_IOCTL(ATMLEC_CTRL)
+COMPATIBLE_IOCTL(ATMLEC_MCAST)
+COMPATIBLE_IOCTL(ATMLEC_DATA)
+COMPATIBLE_IOCTL(ATM_SETSC)
+COMPATIBLE_IOCTL(SIOCSIFATMTCP)
+COMPATIBLE_IOCTL(SIOCMKCLIP)
+COMPATIBLE_IOCTL(ATMARP_MKIP)
+COMPATIBLE_IOCTL(ATMARP_SETENTRY)
+COMPATIBLE_IOCTL(ATMARP_ENCAP)
+COMPATIBLE_IOCTL(ATMTCP_CREATE)
+COMPATIBLE_IOCTL(ATMTCP_REMOVE)
+COMPATIBLE_IOCTL(ATMMPC_CTRL)
+COMPATIBLE_IOCTL(ATMMPC_DATA)
+/* And these ioctls need translation */
+HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32)
+HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf)
+HANDLE_IOCTL(SIOCGIFFLAGS, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFFLAGS, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFMETRIC, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFMETRIC, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFMTU, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFMTU, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFMEM, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFMEM, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFHWADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFHWADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCADDMULTI, dev_ifsioc)
+HANDLE_IOCTL(SIOCDELMULTI, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFINDEX, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFMAP, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFMAP, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFBRDADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFBRDADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFDSTADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFDSTADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFNETMASK, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFNETMASK, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFPFLAGS, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFPFLAGS, dev_ifsioc)
+HANDLE_IOCTL(SIOCGPPPSTATS, dev_ifsioc)
+HANDLE_IOCTL(SIOCGPPPCSTATS, dev_ifsioc)
+HANDLE_IOCTL(SIOCGPPPVER, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFTXQLEN, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc)
+HANDLE_IOCTL(SIOCETHTOOL, dev_ifsioc)
+HANDLE_IOCTL(SIOCADDRT, routing_ioctl)
+HANDLE_IOCTL(SIOCDELRT, routing_ioctl)
+/* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */
+HANDLE_IOCTL(SIOCRTMSG, ret_einval)
+HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp)
+HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo)
+HANDLE_IOCTL(BLKRAGET, w_long)
+HANDLE_IOCTL(BLKGETSIZE, w_long)
+HANDLE_IOCTL(0x1260, broken_blkgetsize)
+HANDLE_IOCTL(BLKFRAGET, w_long)
+HANDLE_IOCTL(BLKSECTGET, w_long)
+HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans)
+HANDLE_IOCTL(FBIOPUTCMAP32, fbiogetputcmap)
+HANDLE_IOCTL(FBIOGETCMAP32, fbiogetputcmap)
+HANDLE_IOCTL(FBIOSCURSOR32, fbiogscursor)
+HANDLE_IOCTL(FBIOGET_FSCREENINFO, fb_ioctl_trans)
+HANDLE_IOCTL(FBIOGETCMAP, fb_ioctl_trans)
+HANDLE_IOCTL(FBIOPUTCMAP, fb_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_UNMASKINTR, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_DMA, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_32BIT, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_MULTCOUNT, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_NOWERR, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_NICE, hdio_ioctl_trans)
+HANDLE_IOCTL(FDSETPRM32, fd_ioctl_trans)
+HANDLE_IOCTL(FDDEFPRM32, fd_ioctl_trans)
+HANDLE_IOCTL(FDGETPRM32, fd_ioctl_trans)
+HANDLE_IOCTL(FDSETDRVPRM32, fd_ioctl_trans)
+HANDLE_IOCTL(FDGETDRVPRM32, fd_ioctl_trans)
+HANDLE_IOCTL(FDGETDRVSTAT32, fd_ioctl_trans)
+HANDLE_IOCTL(FDPOLLDRVSTAT32, fd_ioctl_trans)
+HANDLE_IOCTL(FDGETFDCSTAT32, fd_ioctl_trans)
+HANDLE_IOCTL(FDWERRORGET32, fd_ioctl_trans)
+HANDLE_IOCTL(PPPIOCGIDLE32, ppp_ioctl_trans)
+HANDLE_IOCTL(PPPIOCSCOMPRESS32, ppp_ioctl_trans)
+HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans)
+HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans)
+HANDLE_IOCTL(MTIOCGETCONFIG32, mt_ioctl_trans)
+HANDLE_IOCTL(MTIOCSETCONFIG32, mt_ioctl_trans)
+HANDLE_IOCTL(CDROMREADMODE2, cdrom_ioctl_trans)
+HANDLE_IOCTL(CDROMREADMODE1, cdrom_ioctl_trans)
+HANDLE_IOCTL(CDROMREADRAW, cdrom_ioctl_trans)
+HANDLE_IOCTL(CDROMREADCOOKED, cdrom_ioctl_trans)
+HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans)
+HANDLE_IOCTL(CDROMREADALL, cdrom_ioctl_trans)
+HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans)
+HANDLE_IOCTL(LOOP_SET_STATUS, loop_status)
+HANDLE_IOCTL(LOOP_GET_STATUS, loop_status)
+#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
+HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout)
+HANDLE_IOCTL(PIO_FONTX, do_fontx_ioctl)
+HANDLE_IOCTL(GIO_FONTX, do_fontx_ioctl)
+HANDLE_IOCTL(PIO_UNIMAP, do_unimap_ioctl)
+HANDLE_IOCTL(GIO_UNIMAP, do_unimap_ioctl)
+HANDLE_IOCTL(KDFONTOP, do_kdfontop_ioctl)
+HANDLE_IOCTL(EXT2_IOC32_GETFLAGS, do_ext2_ioctl)
+HANDLE_IOCTL(EXT2_IOC32_SETFLAGS, do_ext2_ioctl)
+HANDLE_IOCTL(EXT2_IOC32_GETVERSION, do_ext2_ioctl)
+HANDLE_IOCTL(EXT2_IOC32_SETVERSION, do_ext2_ioctl)
+HANDLE_IOCTL(VIDIOCGTUNER32, do_video_ioctl)
+HANDLE_IOCTL(VIDIOCSTUNER32, do_video_ioctl)
+HANDLE_IOCTL(VIDIOCGWIN32, do_video_ioctl)
+HANDLE_IOCTL(VIDIOCSWIN32, do_video_ioctl)
+HANDLE_IOCTL(VIDIOCGFBUF32, do_video_ioctl)
+HANDLE_IOCTL(VIDIOCSFBUF32, do_video_ioctl)
+HANDLE_IOCTL(VIDIOCGFREQ32, do_video_ioctl)
+HANDLE_IOCTL(VIDIOCSFREQ32, do_video_ioctl)
+/* One SMB ioctl needs translations. */
+#define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, __kernel_uid_t32)
+HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid)
+HANDLE_IOCTL(ATM_GETLINKRATE32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETNAMES32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETTYPE32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETESI32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETADDR32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_RSTADDR32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_ADDADDR32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_DELADDR32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETCIRANGE32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_SETCIRANGE32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_SETESI32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_SETESIF32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETSTAT32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETSTATZ32, do_atm_ioctl)
+HANDLE_IOCTL(SUNI_GETLOOP, do_atm_ioctl)
+HANDLE_IOCTL(SUNI_SETLOOP, do_atm_ioctl)
+HANDLE_IOCTL(SONET_GETSTAT, do_atm_ioctl)
+HANDLE_IOCTL(SONET_GETSTATZ, do_atm_ioctl)
+HANDLE_IOCTL(SONET_GETDIAG, do_atm_ioctl)
+HANDLE_IOCTL(SONET_SETDIAG, do_atm_ioctl)
+HANDLE_IOCTL(SONET_CLRDIAG, do_atm_ioctl)
+HANDLE_IOCTL(SONET_SETFRAMING, do_atm_ioctl)
+HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl)
+HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl)
+IOCTL_TABLE_END
+
+unsigned int ioctl32_hash_table[1024];
+
+extern inline unsigned long ioctl32_hash(unsigned long cmd)
+{
+ return ((cmd >> 6) ^ (cmd >> 4) ^ cmd) & 0x3ff;
+}
- case FDSETPRM32:
- case FDDEFPRM32:
- case FDGETPRM32:
- case FDSETDRVPRM32:
- case FDGETDRVPRM32:
- case FDGETDRVSTAT32:
- case FDPOLLDRVSTAT32:
- case FDGETFDCSTAT32:
- case FDWERRORGET32:
- error = fd_ioctl_trans(fd, cmd, arg);
- goto out;
+static void ioctl32_insert_translation(struct ioctl_trans *trans)
+{
+ unsigned long hash;
+ struct ioctl_trans *t;
+
+ hash = ioctl32_hash (trans->cmd);
+ if (!ioctl32_hash_table[hash])
+ ioctl32_hash_table[hash] = (u32)(long)trans;
+ else {
+ t = (struct ioctl_trans *)(long)ioctl32_hash_table[hash];
+ while (t->next)
+ t = (struct ioctl_trans *)(long)t->next;
+ trans->next = 0;
+ t->next = (u32)(long)trans;
+ }
+}
- case PPPIOCGIDLE32:
- case PPPIOCSCOMPRESS32:
- error = ppp_ioctl_trans(fd, cmd, arg);
- goto out;
+static int __init init_sys32_ioctl(void)
+{
+ int i;
+ extern struct ioctl_trans ioctl_translations[], ioctl_translations_end[];
- case MTIOCGET32:
- case MTIOCPOS32:
- case MTIOCGETCONFIG32:
- case MTIOCSETCONFIG32:
- error = mt_ioctl_trans(fd, cmd, arg);
- goto out;
+ for (i = 0; &ioctl_translations[i] < &ioctl_translations_end[0]; i++)
+ ioctl32_insert_translation(&ioctl_translations[i]);
+ return 0;
+}
- case CDROMREADMODE2:
- case CDROMREADMODE1:
- case CDROMREADRAW:
- case CDROMREADCOOKED:
- case CDROMREADAUDIO:
- case CDROMREADALL:
- case CDROM_SEND_PACKET:
- error = cdrom_ioctl_trans(fd, cmd, arg);
- goto out;
-
- case LOOP_SET_STATUS:
- case LOOP_GET_STATUS:
- error = loop_status(fd, cmd, arg);
- goto out;
+__initcall(init_sys32_ioctl);
-#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
- case AUTOFS_IOC_SETTIMEOUT32:
- error = rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg);
- goto out;
-
- case PIO_FONTX:
- case GIO_FONTX:
- error = do_fontx_ioctl(filp, cmd, (struct consolefontdesc32 *)arg);
- goto out;
-
- case PIO_UNIMAP:
- case GIO_UNIMAP:
- error = do_unimap_ioctl(filp, cmd, (struct unimapdesc32 *)arg);
- goto out;
+static struct ioctl_trans *additional_ioctls;
- case KDFONTOP:
- error = do_kdfontop_ioctl(filp, (struct console_font_op32 *)arg);
- goto out;
-
- case EXT2_IOC32_GETFLAGS:
- case EXT2_IOC32_SETFLAGS:
- case EXT2_IOC32_GETVERSION:
- case EXT2_IOC32_SETVERSION:
- error = do_ext2_ioctl(fd, cmd, arg);
- goto out;
-
- case VIDIOCGTUNER32:
- case VIDIOCSTUNER32:
- case VIDIOCGWIN32:
- case VIDIOCSWIN32:
- case VIDIOCGFBUF32:
- case VIDIOCSFBUF32:
- case VIDIOCGFREQ32:
- case VIDIOCSFREQ32:
- error = do_video_ioctl(fd, cmd, arg);
- goto out;
+/* Always call these with kernel lock held! */
- /* One SMB ioctl needs translations. */
- case _IOR('u', 1, __kernel_uid_t32): /* SMB_IOC_GETMOUNTUID */
- error = do_smb_getmountuid(fd, cmd, arg);
- goto out;
+int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *))
+{
+ int i;
+ if (!additional_ioctls) {
+ additional_ioctls = module_map(PAGE_SIZE);
+ if (!additional_ioctls) return -ENOMEM;
+ }
+ for (i = 0; i < PAGE_SIZE/sizeof(struct ioctl_trans); i++)
+ if (!additional_ioctls[i].cmd)
+ break;
+ if (i == PAGE_SIZE/sizeof(struct ioctl_trans))
+ return -ENOMEM;
+ additional_ioctls[i].cmd = cmd;
+ if (!handler)
+ additional_ioctls[i].handler = (u32)(long)sys_ioctl;
+ else
+ additional_ioctls[i].handler = (u32)(long)handler;
+ ioctl32_insert_translation(&additional_ioctls[i]);
+ return 0;
+}
- case ATM_GETLINKRATE32:
- case ATM_GETNAMES32:
- case ATM_GETTYPE32:
- case ATM_GETESI32:
- case ATM_GETADDR32:
- case ATM_RSTADDR32:
- case ATM_ADDADDR32:
- case ATM_DELADDR32:
- case ATM_GETCIRANGE32:
- case ATM_SETCIRANGE32:
- case ATM_SETESI32:
- case ATM_SETESIF32:
- case ATM_GETSTAT32:
- case ATM_GETSTATZ32:
- case SUNI_GETLOOP:
- case SUNI_SETLOOP:
- case SONET_GETSTAT:
- case SONET_GETSTATZ:
- case SONET_GETDIAG:
- case SONET_SETDIAG:
- case SONET_CLRDIAG:
- case SONET_SETFRAMING:
- case SONET_GETFRAMING:
- case SONET_GETFRSENSE:
- error = do_atm_ioctl(fd, cmd, arg);
- goto out;
-
- /* List here exlicitly which ioctl's are known to have
- * compatable types passed or none at all...
- */
+int unregister_ioctl32_conversion(unsigned int cmd)
+{
+ unsigned long hash = ioctl32_hash(cmd);
+ struct ioctl_trans *t, *t1;
+
+ t = (struct ioctl_trans *)(long)ioctl32_hash_table[hash];
+ if (!t) return -EINVAL;
+ if (t->cmd == cmd && t >= additional_ioctls &&
+ (unsigned long)t < ((unsigned long)additional_ioctls) + PAGE_SIZE) {
+ ioctl32_hash_table[hash] = t->next;
+ t->cmd = 0;
+ return 0;
+ } else while (t->next) {
+ t1 = (struct ioctl_trans *)(long)t->next;
+ if (t1->cmd == cmd && t1 >= additional_ioctls &&
+ (unsigned long)t1 < ((unsigned long)additional_ioctls) + PAGE_SIZE) {
+ t1->cmd = 0;
+ t->next = t1->next;
+ return 0;
+ }
+ t = t1;
+ }
+ return -EINVAL;
+}
- /* Big T */
- case TCGETA:
- case TCSETA:
- case TCSETAW:
- case TCSETAF:
- case TCSBRK:
- case TCXONC:
- case TCFLSH:
- case TCGETS:
- case TCSETS:
- case TCSETSW:
- case TCSETSF:
- case TIOCLINUX:
-
- /* Little t */
- case TIOCGETD:
- case TIOCSETD:
- case TIOCEXCL:
- case TIOCNXCL:
- case TIOCCONS:
- case TIOCGSOFTCAR:
- case TIOCSSOFTCAR:
- case TIOCSWINSZ:
- case TIOCGWINSZ:
- case TIOCMGET:
- case TIOCMBIC:
- case TIOCMBIS:
- case TIOCMSET:
- case TIOCPKT:
- case TIOCNOTTY:
- case TIOCSTI:
- case TIOCOUTQ:
- case TIOCSPGRP:
- case TIOCGPGRP:
- case TIOCSCTTY:
- case TIOCGPTN:
- case TIOCSPTLCK:
- case TIOCGSERIAL:
- case TIOCSSERIAL:
- case TIOCSERGETLSR:
-
- /* Big F */
- case FBIOGTYPE:
- case FBIOSATTR:
- case FBIOGATTR:
- case FBIOSVIDEO:
- case FBIOGVIDEO:
- case FBIOGCURSOR32: /* This is not implemented yet. Later it should be converted... */
- case FBIOSCURPOS:
- case FBIOGCURPOS:
- case FBIOGCURMAX:
-
- case FBIOGET_VSCREENINFO:
- case FBIOPUT_VSCREENINFO:
- case FBIOPAN_DISPLAY:
- case FBIOGET_FCURSORINFO:
- case FBIOGET_VCURSORINFO:
- case FBIOPUT_VCURSORINFO:
- case FBIOGET_CURSORSTATE:
- case FBIOPUT_CURSORSTATE:
- case FBIOGET_CON2FBMAP:
- case FBIOPUT_CON2FBMAP:
-
- /* Little f */
- case FIOCLEX:
- case FIONCLEX:
- case FIOASYNC:
- case FIONBIO:
- case FIONREAD: /* This is also TIOCINQ */
-
- /* 0x00 */
- case FIBMAP:
- case FIGETBSZ:
-
- /* 0x03 -- HD/IDE ioctl's used by hdparm and friends.
- * Some need translations, these do not.
- */
- case HDIO_GET_IDENTITY:
- case HDIO_SET_DMA:
- case HDIO_SET_KEEPSETTINGS:
- case HDIO_SET_UNMASKINTR:
- case HDIO_SET_NOWERR:
- case HDIO_SET_32BIT:
- case HDIO_SET_MULTCOUNT:
- case HDIO_DRIVE_CMD:
- case HDIO_SET_PIO_MODE:
- case HDIO_SCAN_HWIF:
- case HDIO_SET_NICE:
- case BLKROSET:
- case BLKROGET:
-
- /* 0x02 -- Floppy ioctls */
- case FDMSGON:
- case FDMSGOFF:
- case FDSETEMSGTRESH:
- case FDFLUSH:
- case FDWERRORCLR:
- case FDSETMAXERRS:
- case FDGETMAXERRS:
- case FDGETDRVTYP:
- case FDEJECT:
- case FDCLRPRM:
- case FDFMTBEG:
- case FDFMTEND:
- case FDRESET:
- case FDTWADDLE:
- case FDFMTTRK:
- case FDRAWCMD:
-
- /* 0x12 */
- case BLKRRPART:
- case BLKFLSBUF:
- case BLKRASET:
+asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ struct file * filp;
+ int error = -EBADF;
+ int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
+ struct ioctl_trans *t;
-#if 0 /* New RAID code is being merged, fix up to handle
- * new RAID ioctls when fully merged in 2.3.x -DaveM
- */
- /* 0x09 */
- case REGISTER_DEV:
- case REGISTER_DEV_NEW:
- case START_MD:
- case STOP_MD:
-#endif
-
- /* Big K */
- case PIO_FONT:
- case GIO_FONT:
- case KDSIGACCEPT:
- case KDGETKEYCODE:
- case KDSETKEYCODE:
- case KIOCSOUND:
- case KDMKTONE:
- case KDGKBTYPE:
- case KDSETMODE:
- case KDGETMODE:
- case KDSKBMODE:
- case KDGKBMODE:
- case KDSKBMETA:
- case KDGKBMETA:
- case KDGKBENT:
- case KDSKBENT:
- case KDGKBSENT:
- case KDSKBSENT:
- case KDGKBDIACR:
- case KDSKBDIACR:
- case KDGKBLED:
- case KDSKBLED:
- case KDGETLED:
- case KDSETLED:
- case GIO_SCRNMAP:
- case PIO_SCRNMAP:
- case GIO_UNISCRNMAP:
- case PIO_UNISCRNMAP:
- case PIO_FONTRESET:
- case PIO_UNIMAPCLR:
-
- /* Little k */
- case KIOCTYPE:
- case KIOCLAYOUT:
- case KIOCGTRANS:
- case KIOCTRANS:
- case KIOCCMD:
- case KIOCSDIRECT:
- case KIOCSLED:
- case KIOCGLED:
- case KIOCSRATE:
- case KIOCGRATE:
-
- /* Big S */
- case SCSI_IOCTL_GET_IDLUN:
- case SCSI_IOCTL_DOORLOCK:
- case SCSI_IOCTL_DOORUNLOCK:
- case SCSI_IOCTL_TEST_UNIT_READY:
- case SCSI_IOCTL_TAGGED_ENABLE:
- case SCSI_IOCTL_TAGGED_DISABLE:
- case SCSI_IOCTL_GET_BUS_NUMBER:
- case SCSI_IOCTL_SEND_COMMAND:
-
- /* Big V */
- case VT_SETMODE:
- case VT_GETMODE:
- case VT_GETSTATE:
- case VT_OPENQRY:
- case VT_ACTIVATE:
- case VT_WAITACTIVE:
- case VT_RELDISP:
- case VT_DISALLOCATE:
- case VT_RESIZE:
- case VT_RESIZEX:
- case VT_LOCKSWITCH:
- case VT_UNLOCKSWITCH:
-
- /* Little v */
- case VUIDSFORMAT:
- case VUIDGFORMAT:
-
- /* Little v, the video4linux ioctls */
- case VIDIOCGCAP:
- case VIDIOCGCHAN:
- case VIDIOCSCHAN:
- case VIDIOCGPICT:
- case VIDIOCSPICT:
- case VIDIOCCAPTURE:
- case VIDIOCKEY:
- case VIDIOCGAUDIO:
- case VIDIOCSAUDIO:
- case VIDIOCSYNC:
- case VIDIOCMCAPTURE:
- case VIDIOCGMBUF:
- case VIDIOCGUNIT:
- case VIDIOCGCAPTURE:
- case VIDIOCSCAPTURE:
-
- /* BTTV specific... */
- case _IOW('v', BASE_VIDIOCPRIVATE+0, char [256]):
- case _IOR('v', BASE_VIDIOCPRIVATE+1, char [256]):
- case _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int):
- case _IOW('v' , BASE_VIDIOCPRIVATE+3, char [16]): /* struct bttv_pll_info */
- case _IOR('v' , BASE_VIDIOCPRIVATE+4, int):
- case _IOR('v' , BASE_VIDIOCPRIVATE+5, int):
- case _IOR('v' , BASE_VIDIOCPRIVATE+6, int):
- case _IOR('v' , BASE_VIDIOCPRIVATE+7, int):
-
- /* Little p (/dev/rtc, /dev/envctrl, etc.) */
- case RTCGET:
- case RTCSET:
- case I2CIOCSADR:
- case I2CIOCGADR:
-
- /* Little m */
- case MTIOCTOP:
-
- /* OPENPROMIO, SunOS/Solaris only, the NetBSD one's have
- * embedded pointers in the arg which we'd need to clean up...
- */
- case OPROMGETOPT:
- case OPROMSETOPT:
- case OPROMNXTOPT:
- case OPROMSETOPT2:
- case OPROMNEXT:
- case OPROMCHILD:
- case OPROMGETPROP:
- case OPROMNXTPROP:
- case OPROMU2P:
- case OPROMGETCONS:
- case OPROMGETFBNAME:
- case OPROMGETBOOTARGS:
- case OPROMSETCUR:
- case OPROMPCI2NODE:
- case OPROMPATH2NODE:
-
- /* Socket level stuff */
- case FIOSETOWN:
- case SIOCSPGRP:
- case FIOGETOWN:
- case SIOCGPGRP:
- case SIOCATMARK:
- case SIOCSIFLINK:
- case SIOCSIFENCAP:
- case SIOCGIFENCAP:
- case SIOCSIFBR:
- case SIOCGIFBR:
- case SIOCSARP:
- case SIOCGARP:
- case SIOCDARP:
-#if 0 /* XXX No longer exist in new routing code. XXX */
- case OLD_SIOCSARP:
- case OLD_SIOCGARP:
- case OLD_SIOCDARP:
-#endif
- case SIOCSRARP:
- case SIOCGRARP:
- case SIOCDRARP:
- case SIOCADDDLCI:
- case SIOCDELDLCI:
-
- /* SG stuff */
- case SG_SET_TIMEOUT:
- case SG_GET_TIMEOUT:
- case SG_EMULATED_HOST:
- case SG_SET_TRANSFORM:
- case SG_GET_TRANSFORM:
-
- /* PPP stuff */
- case PPPIOCGFLAGS:
- case PPPIOCSFLAGS:
- case PPPIOCGASYNCMAP:
- case PPPIOCSASYNCMAP:
- case PPPIOCGUNIT:
- case PPPIOCGRASYNCMAP:
- case PPPIOCSRASYNCMAP:
- case PPPIOCGMRU:
- case PPPIOCSMRU:
- case PPPIOCSMAXCID:
- case PPPIOCGXASYNCMAP:
- case PPPIOCSXASYNCMAP:
- case PPPIOCXFERUNIT:
- case PPPIOCGNPMODE:
- case PPPIOCSNPMODE:
- case PPPIOCGDEBUG:
- case PPPIOCSDEBUG:
- case PPPIOCNEWUNIT:
- case PPPIOCATTACH:
- case PPPIOCDETACH:
-
- /* CDROM stuff */
- case CDROMPAUSE:
- case CDROMRESUME:
- case CDROMPLAYMSF:
- case CDROMPLAYTRKIND:
- case CDROMREADTOCHDR:
- case CDROMREADTOCENTRY:
- case CDROMSTOP:
- case CDROMSTART:
- case CDROMEJECT:
- case CDROMVOLCTRL:
- case CDROMSUBCHNL:
- case CDROMEJECT_SW:
- case CDROMMULTISESSION:
- case CDROM_GET_MCN:
- case CDROMRESET:
- case CDROMVOLREAD:
- case CDROMSEEK:
- case CDROMPLAYBLK:
- case CDROMCLOSETRAY:
- case CDROM_SET_OPTIONS:
- case CDROM_CLEAR_OPTIONS:
- case CDROM_SELECT_SPEED:
- case CDROM_SELECT_DISC:
- case CDROM_MEDIA_CHANGED:
- case CDROM_DRIVE_STATUS:
- case CDROM_DISC_STATUS:
- case CDROM_CHANGER_NSLOTS:
- case CDROM_LOCKDOOR:
- case CDROM_DEBUG:
- case CDROM_GET_CAPABILITY:
-
- /* Big L */
- case LOOP_SET_FD:
- case LOOP_CLR_FD:
-
- /* Big A */
- case AUDIO_GETINFO:
- case AUDIO_SETINFO:
- case AUDIO_DRAIN:
- case AUDIO_GETDEV:
- case AUDIO_GETDEV_SUNOS:
- case AUDIO_FLUSH:
-
- /* Big Q for sound/OSS */
- case SNDCTL_SEQ_RESET:
- case SNDCTL_SEQ_SYNC:
- case SNDCTL_SYNTH_INFO:
- case SNDCTL_SEQ_CTRLRATE:
- case SNDCTL_SEQ_GETOUTCOUNT:
- case SNDCTL_SEQ_GETINCOUNT:
- case SNDCTL_SEQ_PERCMODE:
- case SNDCTL_FM_LOAD_INSTR:
- case SNDCTL_SEQ_TESTMIDI:
- case SNDCTL_SEQ_RESETSAMPLES:
- case SNDCTL_SEQ_NRSYNTHS:
- case SNDCTL_SEQ_NRMIDIS:
- case SNDCTL_MIDI_INFO:
- case SNDCTL_SEQ_THRESHOLD:
- case SNDCTL_SYNTH_MEMAVL:
- case SNDCTL_FM_4OP_ENABLE:
- case SNDCTL_SEQ_PANIC:
- case SNDCTL_SEQ_OUTOFBAND:
- case SNDCTL_SEQ_GETTIME:
- case SNDCTL_SYNTH_ID:
- case SNDCTL_SYNTH_CONTROL:
- case SNDCTL_SYNTH_REMOVESAMPLE:
-
- /* Big T for sound/OSS */
- case SNDCTL_TMR_TIMEBASE:
- case SNDCTL_TMR_START:
- case SNDCTL_TMR_STOP:
- case SNDCTL_TMR_CONTINUE:
- case SNDCTL_TMR_TEMPO:
- case SNDCTL_TMR_SOURCE:
- case SNDCTL_TMR_METRONOME:
- case SNDCTL_TMR_SELECT:
-
- /* Little m for sound/OSS */
- case SNDCTL_MIDI_PRETIME:
- case SNDCTL_MIDI_MPUMODE:
- case SNDCTL_MIDI_MPUCMD:
-
- /* Big P for sound/OSS */
- case SNDCTL_DSP_RESET:
- case SNDCTL_DSP_SYNC:
- case SNDCTL_DSP_SPEED:
- case SNDCTL_DSP_STEREO:
- case SNDCTL_DSP_GETBLKSIZE:
- case SNDCTL_DSP_CHANNELS:
- case SOUND_PCM_WRITE_FILTER:
- case SNDCTL_DSP_POST:
- case SNDCTL_DSP_SUBDIVIDE:
- case SNDCTL_DSP_SETFRAGMENT:
- case SNDCTL_DSP_GETFMTS:
- case SNDCTL_DSP_SETFMT:
- case SNDCTL_DSP_GETOSPACE:
- case SNDCTL_DSP_GETISPACE:
- case SNDCTL_DSP_NONBLOCK:
- case SNDCTL_DSP_GETCAPS:
- case SNDCTL_DSP_GETTRIGGER:
- case SNDCTL_DSP_SETTRIGGER:
- case SNDCTL_DSP_GETIPTR:
- case SNDCTL_DSP_GETOPTR:
- /* case SNDCTL_DSP_MAPINBUF: XXX needs translation */
- /* case SNDCTL_DSP_MAPOUTBUF: XXX needs translation */
- case SNDCTL_DSP_SETSYNCRO:
- case SNDCTL_DSP_SETDUPLEX:
- case SNDCTL_DSP_GETODELAY:
- case SNDCTL_DSP_PROFILE:
-
- case SOUND_PCM_READ_RATE:
- case SOUND_PCM_READ_CHANNELS:
- case SOUND_PCM_READ_BITS:
- case SOUND_PCM_READ_FILTER:
-
- /* Big C for sound/OSS */
- case SNDCTL_COPR_RESET:
- case SNDCTL_COPR_LOAD:
- case SNDCTL_COPR_RDATA:
- case SNDCTL_COPR_RCODE:
- case SNDCTL_COPR_WDATA:
- case SNDCTL_COPR_WCODE:
- case SNDCTL_COPR_RUN:
- case SNDCTL_COPR_HALT:
- case SNDCTL_COPR_SENDMSG:
- case SNDCTL_COPR_RCVMSG:
-
- /* Big M for sound/OSS */
- case SOUND_MIXER_READ_VOLUME:
- case SOUND_MIXER_READ_BASS:
- case SOUND_MIXER_READ_TREBLE:
- case SOUND_MIXER_READ_SYNTH:
- case SOUND_MIXER_READ_PCM:
- case SOUND_MIXER_READ_SPEAKER:
- case SOUND_MIXER_READ_LINE:
- case SOUND_MIXER_READ_MIC:
- case SOUND_MIXER_READ_CD:
- case SOUND_MIXER_READ_IMIX:
- case SOUND_MIXER_READ_ALTPCM:
- case SOUND_MIXER_READ_RECLEV:
- case SOUND_MIXER_READ_IGAIN:
- case SOUND_MIXER_READ_OGAIN:
- case SOUND_MIXER_READ_LINE1:
- case SOUND_MIXER_READ_LINE2:
- case SOUND_MIXER_READ_LINE3:
- case SOUND_MIXER_READ_MUTE:
- /* case SOUND_MIXER_READ_ENHANCE: same value as READ_MUTE */
- /* case SOUND_MIXER_READ_LOUD: same value as READ_MUTE */
- case SOUND_MIXER_READ_RECSRC:
- case SOUND_MIXER_READ_DEVMASK:
- case SOUND_MIXER_READ_RECMASK:
- case SOUND_MIXER_READ_STEREODEVS:
- case SOUND_MIXER_READ_CAPS:
-
- case SOUND_MIXER_WRITE_VOLUME:
- case SOUND_MIXER_WRITE_BASS:
- case SOUND_MIXER_WRITE_TREBLE:
- case SOUND_MIXER_WRITE_SYNTH:
- case SOUND_MIXER_WRITE_PCM:
- case SOUND_MIXER_WRITE_SPEAKER:
- case SOUND_MIXER_WRITE_LINE:
- case SOUND_MIXER_WRITE_MIC:
- case SOUND_MIXER_WRITE_CD:
- case SOUND_MIXER_WRITE_IMIX:
- case SOUND_MIXER_WRITE_ALTPCM:
- case SOUND_MIXER_WRITE_RECLEV:
- case SOUND_MIXER_WRITE_IGAIN:
- case SOUND_MIXER_WRITE_OGAIN:
- case SOUND_MIXER_WRITE_LINE1:
- case SOUND_MIXER_WRITE_LINE2:
- case SOUND_MIXER_WRITE_LINE3:
- case SOUND_MIXER_WRITE_MUTE:
- /* case SOUND_MIXER_WRITE_ENHANCE: same value as WRITE_MUTE */
- /* case SOUND_MIXER_WRITE_LOUD: same value as WRITE_MUTE */
- case SOUND_MIXER_WRITE_RECSRC:
-
- case SOUND_MIXER_INFO:
- case SOUND_OLD_MIXER_INFO:
- case SOUND_MIXER_ACCESS:
- case SOUND_MIXER_PRIVATE1:
- case SOUND_MIXER_PRIVATE2:
- case SOUND_MIXER_PRIVATE3:
- case SOUND_MIXER_PRIVATE4:
- case SOUND_MIXER_PRIVATE5:
- case SOUND_MIXER_GETLEVELS:
- case SOUND_MIXER_SETLEVELS:
-
- case OSS_GETVERSION:
-
- /* AUTOFS */
- case AUTOFS_IOC_READY:
- case AUTOFS_IOC_FAIL:
- case AUTOFS_IOC_CATATONIC:
- case AUTOFS_IOC_PROTOVER:
- case AUTOFS_IOC_EXPIRE:
-
- /* Raw devices */
- case RAW_SETBIND:
- case RAW_GETBIND:
-
- /* SMB ioctls which do not need any translations */
- case SMB_IOC_NEWCONN:
-
- /* Little a */
- case ATMSIGD_CTRL:
- case ATMARPD_CTRL:
- case ATMLEC_CTRL:
- case ATMLEC_MCAST:
- case ATMLEC_DATA:
- case ATM_SETSC:
- case SIOCSIFATMTCP:
- case SIOCMKCLIP:
- case ATMARP_MKIP:
- case ATMARP_SETENTRY:
- case ATMARP_ENCAP:
- case ATMTCP_CREATE:
- case ATMTCP_REMOVE:
- case ATMMPC_CTRL:
- case ATMMPC_DATA:
-
+ lock_kernel();
+ filp = fget(fd);
+ if(!filp)
+ goto out2;
+
+ if (!filp->f_op || !filp->f_op->ioctl) {
error = sys_ioctl (fd, cmd, arg);
goto out;
+ }
- default:
- do {
- static int count = 0;
- if (++count <= 20)
- printk("sys32_ioctl: Unknown cmd fd(%d) "
- "cmd(%08x) arg(%08x)\n",
- (int)fd, (unsigned int)cmd, (unsigned int)arg);
- } while(0);
+ t = (struct ioctl_trans *)(long)ioctl32_hash_table [ioctl32_hash (cmd)];
+
+ while (t && t->cmd != cmd)
+ t = (struct ioctl_trans *)(long)t->next;
+ if (t) {
+ handler = (void *)(long)t->handler;
+ error = handler(fd, cmd, arg, filp);
+ } else {
+ static int count = 0;
+ if (++count <= 20)
+ printk("sys32_ioctl: Unknown cmd fd(%d) "
+ "cmd(%08x) arg(%08x)\n",
+ (int)fd, (unsigned int)cmd, (unsigned int)arg);
error = -EINVAL;
- break;
}
out:
fput(filp);
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index a09303971..cb659b655 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.82 2000/02/09 11:15:07 davem Exp $
+/* $Id: irq.c,v 1.83 2000/02/11 06:57:17 jj Exp $
* irq.c: UltraSparc IRQ handling/init/registry.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -57,7 +57,7 @@ struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (64)));
#ifndef __SMP__
unsigned int __up_workvec[16] __attribute__ ((aligned (64)));
-#define irq_work(__cpu, __pil) &(__up_workvec[(__pil)])
+#define irq_work(__cpu, __pil) &(__up_workvec[(void)(__cpu), (__pil)])
#else
#define irq_work(__cpu, __pil) &(cpu_data[(__cpu)].irq_worklists[(__pil)])
#endif
diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c
index 409a44897..00f635ab3 100644
--- a/arch/sparc64/kernel/pci_iommu.c
+++ b/arch/sparc64/kernel/pci_iommu.c
@@ -1,4 +1,4 @@
-/* $Id: pci_iommu.c,v 1.8 2000/01/28 13:41:59 jj Exp $
+/* $Id: pci_iommu.c,v 1.10 2000/02/18 13:48:54 davem Exp $
* pci_iommu.c: UltraSparc PCI controller IOM/STC support.
*
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -99,13 +99,12 @@ static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long
return NULL;
}
-#define IOPTE_CONSISTANT(CTX, PADDR) \
- (IOPTE_VALID | IOPTE_CACHE | IOPTE_WRITE | \
- (((CTX) << 47) & IOPTE_CONTEXT) | \
- ((PADDR) & IOPTE_PAGE))
+#define IOPTE_CONSISTENT(CTX) \
+ (IOPTE_VALID | IOPTE_CACHE | \
+ (((CTX) << 47) & IOPTE_CONTEXT))
-#define IOPTE_STREAMING(CTX, PADDR) \
- (IOPTE_CONSISTANT(CTX, PADDR) | IOPTE_STBUF)
+#define IOPTE_STREAMING(CTX) \
+ (IOPTE_CONSISTENT(CTX) | IOPTE_STBUF)
#define IOPTE_INVALID 0UL
@@ -123,18 +122,10 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_ad
int npages;
size = PAGE_ALIGN(size);
- for (order = 0; order < 10; order++) {
- if ((PAGE_SIZE << order) >= size)
- break;
- }
- if (order == 10)
+ order = get_order(size);
+ if (order >= 10)
return NULL;
- /* We still don't support devices which don't recognize at least 30 bits
- of bus address. Bug me to code it (is pretty easy actually). -jj */
- if ((pdev->dma_mask & 0x3fffffff) != 0x3fffffff)
- BUG();
-
first_page = __get_free_pages(GFP_ATOMIC, order);
if (first_page == 0UL)
return NULL;
@@ -160,7 +151,9 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_ad
ctx = iommu->iommu_cur_ctx++;
first_page = __pa(first_page);
while (npages--) {
- iopte_val(*iopte) = IOPTE_CONSISTANT(ctx, first_page);
+ iopte_val(*iopte) = (IOPTE_CONSISTENT(ctx) |
+ IOPTE_WRITE |
+ (first_page & IOPTE_PAGE));
iopte++;
first_page += PAGE_SIZE;
}
@@ -210,10 +203,7 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_
spin_unlock_irqrestore(&iommu->lock, flags);
- for (order = 0; order < 10; order++) {
- if ((PAGE_SIZE << order) >= size)
- break;
- }
+ order = get_order(size);
if (order < 10)
free_pages((unsigned long)cpu, order);
}
@@ -221,7 +211,7 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_
/* Map a single buffer at PTR of SZ bytes for PCI DMA
* in streaming mode.
*/
-dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz)
+dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
@@ -230,14 +220,13 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz)
unsigned long flags, npages, oaddr;
unsigned long i, base_paddr, ctx;
u32 bus_addr, ret;
+ unsigned long iopte_protection;
pcp = pdev->sysdata;
iommu = &pcp->pbm->parent->iommu;
strbuf = &pcp->pbm->stc;
- /* We still don't support devices which don't recognize at least 30 bits
- of bus address. Bug me to code it (is pretty easy actually). -jj */
- if ((pdev->dma_mask & 0x3fffffff) != 0x3fffffff)
+ if (direction == PCI_DMA_NONE)
BUG();
oaddr = (unsigned long)ptr;
@@ -254,13 +243,15 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz)
ctx = 0;
if (iommu->iommu_ctxflush)
ctx = iommu->iommu_cur_ctx++;
- if (strbuf->strbuf_enabled) {
- for (i = 0; i < npages; i++, base++, base_paddr += PAGE_SIZE)
- iopte_val(*base) = IOPTE_STREAMING(ctx, base_paddr);
- } else {
- for (i = 0; i < npages; i++, base++, base_paddr += PAGE_SIZE)
- iopte_val(*base) = IOPTE_CONSISTANT(ctx, base_paddr);
- }
+ if (strbuf->strbuf_enabled)
+ iopte_protection = IOPTE_STREAMING(ctx);
+ else
+ iopte_protection = IOPTE_CONSISTENT(ctx);
+ if (direction != PCI_DMA_TODEVICE)
+ iopte_protection |= IOPTE_WRITE;
+
+ for (i = 0; i < npages; i++, base++, base_paddr += PAGE_SIZE)
+ iopte_val(*base) = iopte_protection | base_paddr;
/* Flush the IOMMU TLB. */
if (iommu->iommu_ctxflush) {
@@ -276,7 +267,7 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz)
}
/* Unmap a single streaming mode DMA translation. */
-void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz)
+void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
@@ -284,6 +275,9 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz)
iopte_t *base;
unsigned long flags, npages, i, ctx;
+ if (direction == PCI_DMA_NONE)
+ BUG();
+
pcp = pdev->sysdata;
iommu = &pcp->pbm->parent->iommu;
strbuf = &pcp->pbm->stc;
@@ -341,7 +335,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz)
spin_unlock_irqrestore(&iommu->lock, flags);
}
-static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused, unsigned long ctx, int streaming)
+static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused, unsigned long iopte_protection)
{
struct scatterlist *dma_sg = sg;
int i;
@@ -381,10 +375,7 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused, un
sg++;
}
- if (streaming)
- pteval = IOPTE_STREAMING(ctx, pteval);
- else
- pteval = IOPTE_CONSISTANT(ctx, pteval);
+ pteval = iopte_protection | (pteval & IOPTE_PAGE);
while (len > 0) {
*iopte++ = __iopte(pteval);
pteval += PAGE_SIZE;
@@ -419,12 +410,12 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused, un
* When making changes here, inspect the assembly output. I was having
* hard time to kepp this routine out of using stack slots for holding variables.
*/
-int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
+int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct pci_strbuf *strbuf;
- unsigned long flags, ctx, i, npages;
+ unsigned long flags, ctx, i, npages, iopte_protection;
iopte_t *base;
u32 dma_base;
struct scatterlist *sgtmp;
@@ -432,7 +423,7 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
/* Fast path single entry scatterlists. */
if (nelems == 1) {
- sglist->dvma_address = pci_map_single(pdev, sglist->address, sglist->length);
+ sglist->dvma_address = pci_map_single(pdev, sglist->address, sglist->length, direction);
sglist->dvma_length = sglist->length;
return 1;
}
@@ -441,9 +432,7 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
iommu = &pcp->pbm->parent->iommu;
strbuf = &pcp->pbm->stc;
- /* We still don't support devices which don't recognize at least 30 bits
- of bus address. Bug me to code it (is pretty easy actually). -jj */
- if ((pdev->dma_mask & 0x3fffffff) != 0x3fffffff)
+ if (direction == PCI_DMA_NONE)
BUG();
/* Step 1: Prepare scatter list. */
@@ -474,7 +463,13 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
ctx = iommu->iommu_cur_ctx++;
/* Step 5: Create the mappings. */
- fill_sg (base, sglist, used, ctx, strbuf->strbuf_enabled);
+ if (strbuf->strbuf_enabled)
+ iopte_protection = IOPTE_STREAMING(ctx);
+ else
+ iopte_protection = IOPTE_CONSISTENT(ctx);
+ if (direction != PCI_DMA_TODEVICE)
+ iopte_protection |= IOPTE_WRITE;
+ fill_sg (base, sglist, used, iopte_protection);
#ifdef VERIFY_SG
verify_sglist(sglist, nelems, base, npages);
#endif
@@ -493,7 +488,7 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
}
/* Unmap a set of streaming mode DMA translations. */
-void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
+void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
@@ -502,6 +497,9 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
unsigned long flags, ctx, i, npages;
u32 bus_addr;
+ if (direction == PCI_DMA_NONE)
+ BUG();
+
pcp = pdev->sysdata;
iommu = &pcp->pbm->parent->iommu;
strbuf = &pcp->pbm->stc;
@@ -568,7 +566,7 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
/* Make physical memory consistent for a single
* streaming mode DMA translation after a transfer.
*/
-void pci_dma_sync_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz)
+void pci_dma_sync_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
@@ -629,7 +627,7 @@ void pci_dma_sync_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz)
/* Make physical memory consistent for a set of streaming
* mode DMA translations after a transfer.
*/
-void pci_dma_sync_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
+void pci_dma_sync_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
@@ -690,3 +688,19 @@ void pci_dma_sync_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelem
spin_unlock_irqrestore(&iommu->lock, flags);
}
+
+int pci_dma_supported(struct pci_dev *pdev, dma_addr_t device_mask)
+{
+ struct pcidev_cookie *pcp = pdev->sysdata;
+ u32 dma_addr_mask;
+
+ if (pdev == NULL) {
+ dma_addr_mask = 0xffffffff;
+ } else {
+ struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
+
+ dma_addr_mask = iommu->dma_addr_mask;
+ }
+
+ return (device_mask & dma_addr_mask) == dma_addr_mask;
+}
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index c9bd41c19..b3248de39 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -1,4 +1,4 @@
-/* $Id: pci_psycho.c,v 1.11 2000/02/08 05:11:32 jj Exp $
+/* $Id: pci_psycho.c,v 1.13 2000/02/18 13:48:54 davem Exp $
* pci_psycho.c: PSYCHO/U2P specific PCI controller support.
*
* Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -1264,6 +1264,7 @@ static void __init psycho_iommu_init(struct pci_controller_info *p)
p->iommu.page_table = (iopte_t *)tsbbase;
p->iommu.page_table_sz_bits = 17;
p->iommu.page_table_map_base = 0xc0000000;
+ p->iommu.dma_addr_mask = 0xffffffff;
memset((char *)tsbbase, 0, PAGE_SIZE << 7);
/* Make sure DMA address 0 is never returned just to allow catching
@@ -1344,9 +1345,7 @@ static void psycho_pbm_strbuf_init(struct pci_controller_info *p,
int is_pbm_a)
{
unsigned long base = p->controller_regs;
-
- /* Currently we don't even use it. */
- pbm->stc.strbuf_enabled = 0;
+ u64 control;
if (is_pbm_a) {
pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_A;
@@ -1368,14 +1367,29 @@ static void psycho_pbm_strbuf_init(struct pci_controller_info *p,
pbm->stc.strbuf_flushflag_pa = (unsigned long)
__pa(pbm->stc.strbuf_flushflag);
-#if 0
- /* And when we do enable it, these are the sorts of things
- * we'll do.
+ /* Enable the streaming buffer. We have to be careful
+ * just in case OBP left it with LRU locking enabled.
+ *
+ * It is possible to control if PBM will be rerun on
+ * line misses. Currently I just retain whatever setting
+ * OBP left us with. All checks so far show it having
+ * a value of zero.
*/
+#undef PSYCHO_STRBUF_RERUN_ENABLE
+#undef PSYCHO_STRBUF_RERUN_DISABLE
control = psycho_read(pbm->stc.strbuf_control);
- control |= PSYCHO_SBUFCTRL_SB_EN;
- psycho_write(pbm->stc.strbuf_control, control);
+ control |= PSYCHO_STRBUF_CTRL_ENAB;
+ control &= ~(PSYCHO_STRBUF_CTRL_LENAB | PSYCHO_STRBUF_CTRL_LPTR);
+#ifdef PSYCHO_STRBUF_RERUN_ENABLE
+ control &= ~(PSYCHO_STRBUF_CTRL_RRDIS);
+#else
+#ifdef PSYCHO_STRBUF_RERUN_DISABLE
+ control |= PSYCHO_STRBUF_CTRL_RRDIS;
#endif
+#endif
+ psycho_write(pbm->stc.strbuf_control, control);
+
+ pbm->stc.strbuf_enabled = 1;
}
#define PSYCHO_IOSPACE_A 0x002000000UL
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index bbf10cac1..e96af490d 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -1,4 +1,4 @@
-/* $Id: pci_sabre.c,v 1.12 2000/02/08 05:11:33 jj Exp $
+/* $Id: pci_sabre.c,v 1.14 2000/02/18 13:48:55 davem Exp $
* pci_sabre.c: Sabre specific PCI controller support.
*
* Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -1105,7 +1105,8 @@ static void __init sabre_scan_bus(struct pci_controller_info *p)
}
static void __init sabre_iommu_init(struct pci_controller_info *p,
- int tsbsize, unsigned long dvma_offset)
+ int tsbsize, unsigned long dvma_offset,
+ u32 dma_mask)
{
unsigned long tsbbase, i, order;
u64 control;
@@ -1133,16 +1134,14 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
control &= ~(SABRE_IOMMUCTRL_DENAB);
sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control);
- for(order = 0;; order++)
- if((PAGE_SIZE << order) >= ((tsbsize * 1024) * 8))
- break;
- tsbbase = __get_free_pages(GFP_KERNEL, order);
+ tsbbase = __get_free_pages(GFP_KERNEL, order = get_order(tsbsize * 1024 * 8));
if (!tsbbase) {
prom_printf("SABRE_IOMMU: Error, gfp(tsb) failed.\n");
prom_halt();
}
p->iommu.page_table = (iopte_t *)tsbbase;
p->iommu.page_table_map_base = dvma_offset;
+ p->iommu.dma_addr_mask = dma_mask;
memset((char *)tsbbase, 0, PAGE_SIZE << order);
/* Make sure DMA address 0 is never returned just to allow catching
@@ -1315,7 +1314,7 @@ void __init sabre_init(int pnode)
int tsbsize, err;
u32 busrange[2];
u32 vdma[2];
- u32 upa_portid;
+ u32 upa_portid, dma_mask;
int bus;
p = kmalloc(sizeof(*p), GFP_ATOMIC);
@@ -1375,12 +1374,19 @@ void __init sabre_init(int pnode)
prom_halt();
}
+ dma_mask = vdma[0];
switch(vdma[1]) {
case 0x20000000:
+ dma_mask |= 0x1fffffff;
tsbsize = 64;
break;
case 0x40000000:
+ dma_mask |= 0x3fffffff;
+ tsbsize = 128;
+ break;
+
case 0x80000000:
+ dma_mask |= 0x7fffffff;
tsbsize = 128;
break;
default:
@@ -1388,7 +1394,7 @@ void __init sabre_init(int pnode)
prom_halt();
}
- sabre_iommu_init(p, tsbsize, vdma[0]);
+ sabre_iommu_init(p, tsbsize, vdma[0], dma_mask);
printk("SABRE: DVMA at %08x [%08x]\n", vdma[0], vdma[1]);
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index 38e731f37..1b454fa2c 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -1,4 +1,4 @@
-/* $Id: sbus.c,v 1.7 2000/01/28 13:41:58 jj Exp $
+/* $Id: sbus.c,v 1.9 2000/02/18 13:48:57 davem Exp $
* sbus.c: UltraSparc SBUS controller support.
*
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -255,11 +255,8 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, size_t size, dma_addr_t *dvma
return NULL;
size = PAGE_ALIGN(size);
- for (order = 0; order < 10; order++) {
- if ((PAGE_SIZE << order) >= size)
- break;
- }
- if (order == 10)
+ order = get_order(size);
+ if (order >= 10)
return NULL;
first_page = __get_free_pages(GFP_KERNEL, order);
if (first_page == 0UL)
@@ -306,20 +303,21 @@ void sbus_free_consistent(struct sbus_dev *sdev, size_t size, void *cpu, dma_add
free_consistent_cluster(iommu, dvma, npages);
spin_unlock_irq(&iommu->lock);
- for (order = 0; order < 10; order++) {
- if ((PAGE_SIZE << order) >= size)
- break;
- }
+ order = get_order(size);
if (order < 10)
free_pages((unsigned long)cpu, order);
}
-dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t size)
+dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t size, int dir)
{
struct sbus_iommu *iommu = sdev->bus->iommu;
unsigned long npages, phys_base, flags;
iopte_t *iopte;
u32 dma_base, offset;
+ unsigned long iopte_bits;
+
+ if (dir == SBUS_DMA_NONE)
+ BUG();
phys_base = (unsigned long) ptr;
offset = (u32) (phys_base & ~PAGE_MASK);
@@ -331,10 +329,11 @@ dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t size)
iopte = alloc_streaming_cluster(iommu, npages);
dma_base = MAP_BASE + ((iopte - iommu->page_table) << PAGE_SHIFT);
npages = size >> PAGE_SHIFT;
+ iopte_bits = IOPTE_VALID | IOPTE_STBUF | IOPTE_CACHE;
+ if (dir != SBUS_DMA_TODEVICE)
+ iopte_bits |= IOPTE_WRITE;
while (npages--) {
- *iopte++ = __iopte(IOPTE_VALID | IOPTE_STBUF |
- IOPTE_CACHE | IOPTE_WRITE |
- (phys_base & IOPTE_PAGE));
+ *iopte++ = __iopte(iopte_bits | (phys_base & IOPTE_PAGE));
phys_base += PAGE_SIZE;
}
npages = size >> PAGE_SHIFT;
@@ -344,7 +343,7 @@ dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t size)
return (dma_base | offset);
}
-void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size)
+void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size, int direction)
{
struct sbus_iommu *iommu = sdev->bus->iommu;
u32 dma_base = dma_addr & PAGE_MASK;
@@ -358,7 +357,7 @@ void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size)
spin_unlock_irqrestore(&iommu->lock, flags);
}
-static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused)
+static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused, unsigned long iopte_bits)
{
struct scatterlist *dma_sg = sg;
int i;
@@ -398,9 +397,7 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused)
sg++;
}
- pteval = ((pteval & IOPTE_PAGE) |
- IOPTE_VALID | IOPTE_STBUF |
- IOPTE_CACHE | IOPTE_WRITE);
+ pteval = ((pteval & IOPTE_PAGE) | iopte_bits);
while (len > 0) {
*iopte++ = __iopte(pteval);
pteval += PAGE_SIZE;
@@ -430,7 +427,7 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused)
}
}
-int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents)
+int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int dir)
{
struct sbus_iommu *iommu = sdev->bus->iommu;
unsigned long flags, npages;
@@ -438,10 +435,14 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents)
u32 dma_base;
struct scatterlist *sgtmp;
int used;
+ unsigned long iopte_bits;
+
+ if (dir == SBUS_DMA_NONE)
+ BUG();
/* Fast path single entry scatterlists. */
if (nents == 1) {
- sg->dvma_address = sbus_map_single(sdev, sg->address, sg->length);
+ sg->dvma_address = sbus_map_single(sdev, sg->address, sg->length, dir);
sg->dvma_length = sg->length;
return 1;
}
@@ -463,7 +464,11 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents)
}
used = nents - used;
- fill_sg(iopte, sg, used);
+ iopte_bits = IOPTE_VALID | IOPTE_STBUF | IOPTE_CACHE;
+ if (dir != SBUS_DMA_TODEVICE)
+ iopte_bits |= IOPTE_WRITE;
+
+ fill_sg(iopte, sg, used, iopte_bits);
#ifdef VERIFY_SG
verify_sglist(sg, nents, iopte, npages);
#endif
@@ -473,7 +478,7 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents)
return used;
}
-void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents)
+void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int direction)
{
unsigned long size, flags;
struct sbus_iommu *iommu;
@@ -482,7 +487,7 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents)
/* Fast path single entry scatterlists. */
if (nents == 1) {
- sbus_unmap_single(sdev, sg->dvma_address, sg->dvma_length);
+ sbus_unmap_single(sdev, sg->dvma_address, sg->dvma_length, direction);
return;
}
@@ -501,7 +506,7 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents)
spin_unlock_irqrestore(&iommu->lock, flags);
}
-void sbus_dma_sync_single(struct sbus_dev *sdev, dma_addr_t base, size_t size)
+void sbus_dma_sync_single(struct sbus_dev *sdev, dma_addr_t base, size_t size, int direction)
{
struct sbus_iommu *iommu = sdev->bus->iommu;
unsigned long flags;
@@ -513,7 +518,7 @@ void sbus_dma_sync_single(struct sbus_dev *sdev, dma_addr_t base, size_t size)
spin_unlock_irqrestore(&iommu->lock, flags);
}
-void sbus_dma_sync_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents)
+void sbus_dma_sync_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int direction)
{
struct sbus_iommu *iommu = sdev->bus->iommu;
unsigned long flags, size;
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 6e8899435..273c12de1 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -753,9 +753,7 @@ static void __init smp_tune_scheduling (void)
"ecache-size", (512 * 1024));
if (ecache_size > (4 * 1024 * 1024))
ecache_size = (4 * 1024 * 1024);
- for (order = 0UL; (PAGE_SIZE << order) < ecache_size; order++)
- ;
- flush_base = __get_free_pages(GFP_KERNEL, order);
+ flush_base = __get_free_pages(GFP_KERNEL, order = get_order(ecache_size));
if (flush_base != 0UL) {
__save_and_cli(flags);
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index be2638ec9..81b4c4de1 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.35 2000/01/29 07:40:12 davem Exp $
+/* $Id: sys_sparc.c,v 1.36 2000/02/16 07:31:35 davem Exp $
* linux/arch/sparc64/kernel/sys_sparc.c
*
* This file contains various random system calls that
@@ -39,17 +39,49 @@ asmlinkage unsigned long sys_getpagesize(void)
return PAGE_SIZE;
}
+unsigned long get_unmapped_area(unsigned long addr, unsigned long len)
+{
+ struct vm_area_struct * vmm;
+ unsigned long task_size = TASK_SIZE;
+
+ if (current->thread.flags & SPARC_FLAG_32BIT)
+ task_size = 0xf0000000UL;
+ if (len > task_size || len > -PAGE_OFFSET)
+ return 0;
+ if (!addr)
+ addr = TASK_UNMAPPED_BASE;
+ addr = PAGE_ALIGN(addr);
+
+ task_size -= len;
+
+ for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
+ /* At this point: (!vmm || addr < vmm->vm_end). */
+ if (addr < PAGE_OFFSET && -PAGE_OFFSET - len < addr) {
+ addr = PAGE_OFFSET;
+ vmm = find_vma(current->mm, PAGE_OFFSET);
+ }
+ if (task_size < addr)
+ return 0;
+ if (!vmm || addr + len <= vmm->vm_start)
+ return addr;
+ addr = vmm->vm_end;
+ }
+}
+
extern asmlinkage unsigned long sys_brk(unsigned long brk);
asmlinkage unsigned long sparc_brk(unsigned long brk)
{
- if((brk >= 0x80000000000UL && brk < PAGE_OFFSET) ||
- (brk - current->mm->brk > 0x80000000000UL &&
- brk - current->mm->brk < PAGE_OFFSET)) /* VM hole */
+ /* People could try to be nasty and use ta 0x6d in 32bit programs */
+ if ((current->thread.flags & SPARC_FLAG_32BIT) &&
+ brk >= 0xf0000000UL)
+ return current->mm->brk;
+
+ if ((current->mm->brk & PAGE_OFFSET) != (brk & PAGE_OFFSET))
return current->mm->brk;
return sys_brk(brk);
}
-
+
/*
* sys_pipe() is the normal C calling standard for creating
* a pipe. It's not the way unix traditionally does this, though.
@@ -164,30 +196,21 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
goto out;
}
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
- retval = -ENOMEM;
len = PAGE_ALIGN(len);
+ retval = -EINVAL;
+
down(&current->mm->mmap_sem);
lock_kernel();
- if(!(flags & MAP_FIXED) && !addr) {
- addr = get_unmapped_area(addr, len);
- if(!addr)
- goto out_putf;
- }
- retval = -EINVAL;
if (current->thread.flags & SPARC_FLAG_32BIT) {
- if (len > 0xf0000000UL || addr > 0xf0000000UL - len)
+ if (len > 0xf0000000UL ||
+ ((flags & MAP_FIXED) && addr > 0xf0000000UL - len))
goto out_putf;
} else {
- if (len >= 0x80000000000UL ||
- (addr < 0x80000000000UL &&
- addr > 0x80000000000UL-len))
+ if (len > -PAGE_OFFSET ||
+ ((flags & MAP_FIXED) &&
+ addr < PAGE_OFFSET && addr + len > -PAGE_OFFSET))
goto out_putf;
- if (addr >= 0x80000000000UL && addr < PAGE_OFFSET) {
- /* VM hole */
- retval = current->mm->brk;
- goto out_putf;
- }
}
retval = do_mmap(file, addr, len, prot, flags, off);
@@ -201,6 +224,55 @@ out:
return retval;
}
+asmlinkage long sys64_munmap(unsigned long addr, size_t len)
+{
+ long ret;
+
+ if (len > -PAGE_OFFSET ||
+ (addr < PAGE_OFFSET && addr + len > -PAGE_OFFSET))
+ return -EINVAL;
+ down(&current->mm->mmap_sem);
+ ret = do_munmap(addr, len);
+ up(&current->mm->mmap_sem);
+ return ret;
+}
+
+extern unsigned long do_mremap(unsigned long addr,
+ unsigned long old_len, unsigned long new_len,
+ unsigned long flags, unsigned long new_addr);
+
+asmlinkage unsigned long sys64_mremap(unsigned long addr,
+ unsigned long old_len, unsigned long new_len,
+ unsigned long flags, unsigned long new_addr)
+{
+ unsigned long ret = -EINVAL;
+ if (current->thread.flags & SPARC_FLAG_32BIT)
+ goto out;
+ if (old_len > -PAGE_OFFSET || new_len > -PAGE_OFFSET)
+ goto out;
+ if (addr < PAGE_OFFSET && addr + old_len > -PAGE_OFFSET)
+ goto out;
+ down(&current->mm->mmap_sem);
+ if (flags & MREMAP_FIXED) {
+ if (new_addr < PAGE_OFFSET &&
+ new_addr + new_len > -PAGE_OFFSET)
+ goto out_sem;
+ } else if (addr < PAGE_OFFSET && addr + new_len > -PAGE_OFFSET) {
+ ret = -ENOMEM;
+ if (!(flags & MREMAP_MAYMOVE))
+ goto out_sem;
+ new_addr = get_unmapped_area (addr, new_len);
+ if (!new_addr)
+ goto out_sem;
+ flags |= MREMAP_FIXED;
+ }
+ ret = do_mremap(addr, old_len, new_len, flags, new_addr);
+out_sem:
+ up(&current->mm->mmap_sem);
+out:
+ return ret;
+}
+
/* we come to here via sys_nis_syscall so it can setup the regs argument */
asmlinkage unsigned long
c_sys_nis_syscall (struct pt_regs *regs)
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 61b9a3397..1ebb7772c 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.131 2000/01/21 11:38:54 jj Exp $
+/* $Id: sys_sparc32.c,v 1.132 2000/02/16 07:31:35 davem Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -44,6 +44,7 @@
#include <linux/filter.h>
#include <linux/highmem.h>
#include <linux/highuid.h>
+#include <linux/mman.h>
#include <asm/types.h>
#include <asm/ipc.h>
@@ -4190,3 +4191,38 @@ out_error:
fd = error;
goto out;
}
+
+extern unsigned long do_mremap(unsigned long addr,
+ unsigned long old_len, unsigned long new_len,
+ unsigned long flags, unsigned long new_addr);
+
+asmlinkage unsigned long sys32_mremap(unsigned long addr,
+ unsigned long old_len, unsigned long new_len,
+ unsigned long flags, u32 __new_addr)
+{
+ unsigned long ret = -EINVAL;
+ unsigned long new_addr = AA(__new_addr);
+
+ if (old_len > 0xf0000000UL || new_len > 0xf0000000UL)
+ goto out;
+ if (addr > 0xf0000000UL - old_len)
+ goto out;
+ down(&current->mm->mmap_sem);
+ if (flags & MREMAP_FIXED) {
+ if (new_addr > 0xf0000000UL - new_len)
+ goto out_sem;
+ } else if (addr > 0xf0000000UL - new_len) {
+ ret = -ENOMEM;
+ if (!(flags & MREMAP_MAYMOVE))
+ goto out_sem;
+ new_addr = get_unmapped_area (addr, new_len);
+ if (!new_addr)
+ goto out_sem;
+ flags |= MREMAP_FIXED;
+ }
+ ret = do_mremap(addr, old_len, new_len, flags, new_addr);
+out_sem:
+ up(&current->mm->mmap_sem);
+out:
+ return ret;
+}
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index 62058ffcf..c5101248a 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.38 2000/01/29 07:40:13 davem Exp $
+/* $Id: sys_sunos32.c,v 1.39 2000/02/16 07:31:37 davem Exp $
* sys_sunos32.c: SunOS binary compatability layer on sparc64.
*
* Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -71,8 +71,10 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of
lock_kernel();
current->personality |= PER_BSD;
if(flags & MAP_NORESERVE) {
- printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n",
- current->comm);
+ static int cnt;
+ if (cnt++ < 10)
+ printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n",
+ current->comm);
flags &= ~MAP_NORESERVE;
}
retval = -EBADF;
@@ -93,15 +95,11 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of
}
}
- retval = -ENOMEM;
- if(!(flags & MAP_FIXED) && !addr) {
- unsigned long attempt = get_unmapped_area(addr, len);
- if(!attempt || (attempt >= 0xf0000000UL))
- goto out_putf;
- addr = (u32) attempt;
- }
+ retval = -EINVAL;
if(!(flags & MAP_FIXED))
addr = 0;
+ else if (len > 0xf0000000 || addr > 0xf0000000 - len)
+ goto out_putf;
ret_type = flags & _MAP_NEW;
flags &= ~_MAP_NEW;
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 10effccae..1f7ab3fef 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.67 2000/01/29 16:41:21 jj Exp $
+/* $Id: systbls.S,v 1.68 2000/02/16 07:31:38 davem Exp $
* systbls.S: System call entry point tables for OS compatibility.
* The native Linux system call table lives here also.
*
@@ -69,7 +69,7 @@ sys_call_table32:
.word sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
/*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
.word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys32_sched_rr_get_interval, sys32_nanosleep
-/*250*/ .word sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl
+/*250*/ .word sys32_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl
.word sys_aplib
/* Now the 64-bit native Linux syscall table. */
@@ -92,7 +92,7 @@ sys_call_table:
.word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve
/*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_nis_syscall, sys_getpagesize
.word sys_msync, sys_vfork, sys_pread, sys_pwrite, sys_nis_syscall
-/*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_munmap, sys_mprotect
+/*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys64_munmap, sys_mprotect
.word sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys_getgroups
/*80*/ .word sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_nis_syscall
.word sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall
@@ -128,7 +128,7 @@ sys_call_table:
.word sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
/*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
.word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
-/*250*/ .word sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
+/*250*/ .word sys64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
.word sys_aplib
#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S
index cb281a659..0825b0585 100644
--- a/arch/sparc64/mm/ultra.S
+++ b/arch/sparc64/mm/ultra.S
@@ -1,4 +1,4 @@
-/* $Id: ultra.S,v 1.36 1999/12/15 15:45:18 davem Exp $
+/* $Id: ultra.S,v 1.37 2000/02/14 02:52:04 davem Exp $
* ultra.S: Don't expand these all over the place...
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -132,8 +132,8 @@ __flush_tlb_range_pbp_slow:
wrpr %g1, 0x0, %pstate
.align 32
- .globl flush_icache_page
-flush_icache_page: /* %o0 = phys_page */
+ .globl __flush_icache_page
+__flush_icache_page: /* %o0 = phys_page */
sethi %hi(1 << 13), %o2 ! IC_set bit
mov 1, %g1
srlx %o0, 5, %o0
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
index 46dbfb241..9e2bd4118 100644
--- a/arch/sparc64/solaris/misc.c
+++ b/arch/sparc64/solaris/misc.c
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.21 2000/01/29 07:40:15 davem Exp $
+/* $Id: misc.c,v 1.22 2000/02/16 07:31:41 davem Exp $
* misc.c: Miscelaneous syscall emulation for Solaris
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -83,27 +83,25 @@ static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 o
}
}
- down(&current->mm->mmap_sem);
- retval = -ENOMEM;
- if(!(flags & MAP_FIXED) && !addr) {
- unsigned long attempt = get_unmapped_area(addr, len);
- if(!attempt || (attempt >= 0xf0000000UL))
- goto out_putf;
- addr = (u32) attempt;
- }
+ retval = -EINVAL;
+ len = PAGE_ALIGN(len);
if(!(flags & MAP_FIXED))
addr = 0;
+ else if (len > 0xf0000000UL || addr > 0xf0000000UL - len)
+ goto out_putf;
ret_type = flags & _MAP_NEW;
flags &= ~_MAP_NEW;
+ down(&current->mm->mmap_sem);
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
retval = do_mmap(file,
(unsigned long) addr, (unsigned long) len,
(unsigned long) prot, (unsigned long) flags, off);
+ up(&current->mm->mmap_sem);
if(!ret_type)
retval = ((retval < 0xf0000000) ? 0 : retval);
+
out_putf:
- up(&current->mm->mmap_sem);
if (file)
fput(file);
out:
diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c
index b5f76d400..89f771609 100644
--- a/arch/sparc64/solaris/socksys.c
+++ b/arch/sparc64/solaris/socksys.c
@@ -1,4 +1,4 @@
-/* $Id: socksys.c,v 1.11 2000/02/09 22:32:17 davem Exp $
+/* $Id: socksys.c,v 1.12 2000/02/17 05:50:11 davem Exp $
* socksys.c: /dev/inet/ stuff for Solaris emulation.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/malloc.h>
+#include <linux/devfs_fs_kernel.h>
#include <asm/uaccess.h>
#include <asm/termios.h>
@@ -157,6 +158,8 @@ static struct file_operations socksys_fops = {
release: socksys_release,
};
+static devfs_handle_t devfs_handle = NULL;
+
int __init
init_socksys(void)
{
@@ -167,7 +170,7 @@ init_socksys(void)
int (*sys_close)(unsigned int) =
(int (*)(unsigned int))SYS(close);
- ret = register_chrdev (30, "socksys", &socksys_fops);
+ ret = devfs_register_chrdev (30, "socksys", &socksys_fops);
if (ret < 0) {
printk ("Couldn't register socksys character device\n");
return ret;
@@ -177,6 +180,10 @@ init_socksys(void)
printk ("Couldn't create socket\n");
return ret;
}
+ devfs_handle = devfs_register (NULL, "socksys", 0, DEVFS_FL_NONE,
+ 30, 0,
+ S_IFCHR | S_IRUSR | S_IWUSR, 0, 0,
+ &socksys_fops, NULL);
file = fcheck(ret);
/* N.B. Is this valid? Suppose the f_ops are in a module ... */
socksys_file_ops = *file->f_op;
@@ -190,6 +197,7 @@ init_socksys(void)
void
cleanup_socksys(void)
{
- if (unregister_chrdev (30, "socksys"))
+ if (devfs_unregister_chrdev(30, "socksys"))
printk ("Couldn't unregister socksys character device\n");
+ devfs_unregister (devfs_handle);
}