USB HUB AND UHCI DRIVERS
P: Johannes Erdfelt
M: jerdfelt@sventech.com
-L: linux-usb@peloncho.fis.ucm.es
+L: linux-usb@suse.com
S: Maintained
USB OHCI DRIVER
P: Gregory P. Smith
M: greg@electricrain.com
M: greg@suitenine.com
-L: linux-usb@peloncho.fis.ucm.es
+L: linux-usb@suse.com
S: Maintained (not yet usable)
W: http://suitenine.com/usb/
struct inode *inode;
struct osf_dirent_callback buf;
+ lock_kernel();
error = -EBADF;
file = fget(fd);
if (!file)
out_putf:
fput(file);
out:
+ unlock_kernel();
return error;
}
goto out;
if (!(a.flags & MAP_ANONYMOUS)) {
error = -EBADF;
- if (a.fd >= current->files->max_fds ||
- !(file = current->files->fd[a.fd]))
+ file = fget(a.fd);
+ if (!file)
goto out;
}
a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset);
+ if (file)
+ fput(file);
out:
unlock_kernel();
return error;
# Note 2! The CFLAGS definition is now in the main makefile...
all: lib first_rule
-ifeq ($(MACHINE),a5k)
-MMARCH=arc
-else
-MMARCH=$(MACHINE)
-endif
O_TARGET := mm.o
-O_OBJS := init.o extable.o fault-$(PROCESSOR).o mm-$(MMARCH).o
+O_OBJS := init.o extable.o fault-$(PROCESSOR).o small_page.o
ifeq ($(PROCESSOR),armo)
O_OBJS += proc-arm2,3.o
endif
ifeq ($(PROCESSOR),armv)
- O_OBJS += small_page.o proc-arm6,7.o proc-sa110.o
+ O_OBJS += mm-$(MACHINE).o proc-arm6,7.o proc-sa110.o ioremap.o
endif
include $(TOPDIR)/Rules.make
-proc-arm2,3.o: ../lib/constants.h
-proc-arm6,7.o: ../lib/constants.h
-proc-sa110.o: ../lib/constants.h
-
%.o: %.S
-ifneq ($(CONFIG_BINUTILS_NEW),y)
- $(CC) $(CFLAGS) -D__ASSEMBLY__ -E $< | tr ';$$' '\n#' > ..$@.tmp.s
- $(CC) $(CFLAGS:-pipe=) -c -o $@ ..$@.tmp.s
- $(RM) ..$@.tmp.s
-else
$(CC) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $<
-endif
.PHONY: lib
lib:; @$(MAKE) -C ../lib constants.h
+
+# Special dependencies
+fault-armv.o: fault-common.c
+fault-armo.o: fault-common.c
+proc-arm2,3.o: ../lib/constants.h
+proc-arm6,7.o: ../lib/constants.h
+proc-sa110.o: ../lib/constants.h
+
/*
- * linux/arch/arm/mm/fault.c
+ * linux/arch/arm/mm/fault-armo.c
*
* Copyright (C) 1995 Linus Torvalds
- * Modifications for ARM processor (c) 1995, 1996 Russell King
+ * Modifications for ARM processor (c) 1995-1999 Russell King
*/
-#include <linux/config.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#define FAULT_CODE_WRITE 0x02
#define FAULT_CODE_USER 0x01
-struct pgtable_cache_struct quicklists;
+#define DO_COW(m) ((m) & (FAULT_CODE_WRITE|FAULT_CODE_FORCECOW))
+#define READ_FAULT(m) (!((m) & FAULT_CODE_WRITE))
-void __bad_pmd(pmd_t *pmd)
+#include "fault-common.c"
+
+static void *alloc_table(int size, int prio)
{
- printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
-#ifdef CONFIG_DEBUG_ERRORS
- __backtrace();
-#endif
- set_pmd(pmd, mk_pmd(BAD_PAGETABLE));
+ if (size != 128)
+ printk("invalid table size\n");
+ return (void *)get_page_8k(prio);
}
-void __bad_pmd_kernel(pmd_t *pmd)
+void free_table(void *table)
{
- printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd));
-#ifdef CONFIG_DEBUG_ERRORS
- __backtrace();
-#endif
- set_pmd(pmd, mk_pmd(BAD_PAGETABLE));
+ free_page_8k((unsigned long)table);
}
pgd_t *get_pgd_slow(void)
{
- pgd_t *pgd = (pgd_t *) kmalloc(PTRS_PER_PGD * BYTES_PER_PTR, GFP_KERNEL);
+ pgd_t *pgd = (pgd_t *)alloc_table(PTRS_PER_PGD * BYTES_PER_PTR, GFP_KERNEL);
pgd_t *init;
-
+
if (pgd) {
init = pgd_offset(&init_mm, 0);
- memzero (pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR);
- memcpy (pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
+ memzero(pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR);
+ memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
(PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR);
}
return pgd;
{
pte_t *pte;
- pte = (pte_t *) kmalloc (PTRS_PER_PTE * BYTES_PER_PTR, GFP_KERNEL);
+ pte = (pte_t *)alloc_table(PTRS_PER_PTE * BYTES_PER_PTR, GFP_KERNEL);
if (pmd_none(*pmd)) {
if (pte) {
- memzero (pte, PTRS_PER_PTE * BYTES_PER_PTR);
+ memzero(pte, PTRS_PER_PTE * BYTES_PER_PTR);
set_pmd(pmd, mk_pmd(pte));
return pte + offset;
}
set_pmd(pmd, mk_pmd(BAD_PAGETABLE));
return NULL;
}
- kfree (pte);
+ free_table((void *)pte);
if (pmd_bad(*pmd)) {
__bad_pmd(pmd);
return NULL;
return (pte_t *) pmd_page(*pmd) + offset;
}
-extern void die_if_kernel(char *msg, struct pt_regs *regs, unsigned int err, unsigned int ret);
-
-static void kernel_page_fault (unsigned long addr, int mode, struct pt_regs *regs,
- struct task_struct *tsk, struct mm_struct *mm)
-{
- /*
- * Oops. The kernel tried to access some bad page. We'll have to
- * terminate things with extreme prejudice.
- */
- pgd_t *pgd;
- if (addr < PAGE_SIZE)
- printk (KERN_ALERT "Unable to handle kernel NULL pointer dereference");
- else
- printk (KERN_ALERT "Unable to handle kernel paging request");
- printk (" at virtual address %08lx\n", addr);
- printk (KERN_ALERT "current->tss.memmap = %08lX\n", tsk->tss.memmap);
- pgd = pgd_offset (mm, addr);
- printk (KERN_ALERT "*pgd = %08lx", pgd_val (*pgd));
- if (!pgd_none (*pgd)) {
- pmd_t *pmd;
- pmd = pmd_offset (pgd, addr);
- printk (", *pmd = %08lx", pmd_val (*pmd));
- if (!pmd_none (*pmd))
- printk (", *pte = %08lx", pte_val (*pte_offset (pmd, addr)));
- }
- printk ("\n");
- die_if_kernel ("Oops", regs, mode, SIGKILL);
- do_exit (SIGKILL);
-}
-
-static void
-handle_dataabort (unsigned long addr, int mode, struct pt_regs *regs)
-{
- struct task_struct *tsk;
- struct mm_struct *mm;
- struct vm_area_struct *vma;
- unsigned long fixup;
-
- lock_kernel();
- tsk = current;
- mm = tsk->mm;
-
- down(&mm->mmap_sem);
- vma = find_vma (mm, addr);
- if (!vma)
- goto bad_area;
- if (addr >= vma->vm_start)
- goto good_area;
- if (!(vma->vm_flags & VM_GROWSDOWN) || expand_stack (vma, addr))
- goto bad_area;
-
- /*
- * Ok, we have a good vm_area for this memory access, so
- * we can handle it..
- */
-good_area:
- if (!(mode & FAULT_CODE_WRITE)) { /* write? */
- if (!(vma->vm_flags & (VM_READ|VM_EXEC)))
- goto bad_area;
- } else {
- if (!(vma->vm_flags & VM_WRITE))
- goto bad_area;
- }
- handle_mm_fault (tsk, vma, addr, mode & (FAULT_CODE_WRITE|FAULT_CODE_FORCECOW));
- up(&mm->mmap_sem);
- goto out;
-
- /*
- * Something tried to access memory that isn't in our memory map..
- * Fix it, but check if it's kernel or user first..
- */
-bad_area:
- up(&mm->mmap_sem);
- if (mode & FAULT_CODE_USER) {
-//extern int console_loglevel;
-//cli();
- tsk->tss.error_code = mode;
- tsk->tss.trap_no = 14;
-//console_loglevel = 9;
- printk ("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n",
- tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode);
-//#ifdef DEBUG
- show_regs (regs);
- c_backtrace (regs->ARM_fp, 0);
-//#endif
- force_sig(SIGSEGV, tsk);
-//while (1);
- goto out;
- }
-
- /* Are we prepared to handle this kernel fault? */
- if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) {
- printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n",
- tsk->comm, regs->ARM_pc, addr, fixup);
- regs->ARM_pc = fixup;
- goto out;
- }
-
-
- kernel_page_fault (addr, mode, regs, tsk, mm);
-out:
- unlock_kernel();
-}
-
/*
* Handle a data abort. Note that we have to handle a range of addresses
* on ARM2/3 for ldm. If both pages are zero-mapped, then we have to force
- * a copy-on-write
+ * a copy-on-write. However, on the second page, we always force COW.
*/
asmlinkage void
-do_DataAbort (unsigned long min_addr, unsigned long max_addr, int mode, struct pt_regs *regs)
+do_DataAbort(unsigned long min_addr, unsigned long max_addr, int mode, struct pt_regs *regs)
{
- handle_dataabort (min_addr, mode, regs);
+ do_page_fault(min_addr, mode, regs);
if ((min_addr ^ max_addr) >> PAGE_SHIFT)
- handle_dataabort (max_addr, mode | FAULT_CODE_FORCECOW, regs);
+ do_page_fault(max_addr, mode | FAULT_CODE_FORCECOW, regs);
}
asmlinkage int
-do_PrefetchAbort (unsigned long addr, int mode, struct pt_regs *regs)
+do_PrefetchAbort(unsigned long addr, struct pt_regs *regs)
{
#if 0
if (the memc mapping for this page exists - can check now...) {
return 0;
}
#endif
- handle_dataabort (addr, mode, regs);
+ do_page_fault(addr, FAULT_CODE_USER|FAULT_CODE_PREFETCH, regs);
return 1;
}
/*
- * linux/arch/arm/mm/fault.c
+ * linux/arch/arm/mm/fault-armv.c
*
* Copyright (C) 1995 Linus Torvalds
- * Modifications for ARM processor (c) 1995, 1996 Russell King
+ * Modifications for ARM processor (c) 1995-1999 Russell King
*/
+#include <linux/config.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
+#include <asm/unaligned.h>
#define FAULT_CODE_READ 0x02
#define FAULT_CODE_USER 0x01
-struct pgtable_cache_struct quicklists;
+#define DO_COW(m) (!((m) & FAULT_CODE_READ))
+#define READ_FAULT(m) ((m) & FAULT_CODE_READ)
-void __bad_pmd(pmd_t *pmd)
-{
- printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
- set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE));
-}
-
-void __bad_pmd_kernel(pmd_t *pmd)
-{
- printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
- set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE));
-}
+#include "fault-common.c"
pgd_t *get_pgd_slow(void)
{
/*
* need to get a 16k page for level 1
*/
- pgd_t *pgd = (pgd_t *) __get_free_pages(GFP_KERNEL,2);
+ pgd_t *pgd = (pgd_t *)__get_free_pages(GFP_KERNEL,2);
pgd_t *init;
-
+
if (pgd) {
init = pgd_offset(&init_mm, 0);
- memzero ((void *)pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR);
- memcpy (pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
+ memzero(pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR);
+ memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
(PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR);
+ clean_cache_area(pgd, PTRS_PER_PGD * BYTES_PER_PTR);
}
return pgd;
}
{
pte_t *pte;
- pte = (pte_t *) get_small_page(GFP_KERNEL);
+ pte = (pte_t *)get_page_2k(GFP_KERNEL);
if (pmd_none(*pmd)) {
if (pte) {
- memzero (pte, PTRS_PER_PTE * BYTES_PER_PTR);
+ memzero(pte, 2 * PTRS_PER_PTE * BYTES_PER_PTR);
+ clean_cache_area(pte, PTRS_PER_PTE * BYTES_PER_PTR);
+ pte += PTRS_PER_PTE;
set_pmd(pmd, mk_user_pmd(pte));
return pte + offset;
}
set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE));
return NULL;
}
- free_small_page ((unsigned long) pte);
+ free_page_2k((unsigned long)pte);
if (pmd_bad(*pmd)) {
__bad_pmd(pmd);
return NULL;
{
pte_t *pte;
- pte = (pte_t *) get_small_page(GFP_KERNEL);
+ pte = (pte_t *)get_page_2k(GFP_KERNEL);
if (pmd_none(*pmd)) {
if (pte) {
- memzero (pte, PTRS_PER_PTE * BYTES_PER_PTR);
+ memzero(pte, 2 * PTRS_PER_PTE * BYTES_PER_PTR);
+ clean_cache_area(pte, PTRS_PER_PTE * BYTES_PER_PTR);
+ pte += PTRS_PER_PTE;
set_pmd(pmd, mk_kernel_pmd(pte));
return pte + offset;
}
set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE));
return NULL;
}
- free_small_page ((unsigned long) pte);
+ free_page_2k((unsigned long)pte);
if (pmd_bad(*pmd)) {
__bad_pmd_kernel(pmd);
return NULL;
return (pte_t *) pmd_page(*pmd) + offset;
}
-extern void die_if_kernel(char *msg, struct pt_regs *regs, unsigned int err, unsigned int ret);
-
#ifdef DEBUG
-static int sp_valid (unsigned long *sp)
+static int sp_valid(unsigned long *sp)
{
unsigned long addr = (unsigned long) sp;
}
#endif
-static void kernel_page_fault (unsigned long addr, int mode, struct pt_regs *regs,
- struct task_struct *tsk, struct mm_struct *mm)
+#ifdef CONFIG_ALIGNMENT_TRAP
+/*
+ * 32-bit misaligned trap handler (c) 1998 San Mehat (CCC) -July 1998
+ * /proc/sys/debug/alignment, modified and integrated into
+ * Linux 2.1 by Russell King
+ *
+ * NOTE!!! This is not portable onto the ARM6/ARM7 processors yet. Also,
+ * it seems to give a severe performance impact (1 abort/ms - NW runs at
+ * ARM6 speeds) with GCC 2.7.2.2 - needs checking with a later GCC/EGCS.
+ *
+ * IMHO, I don't think that the trap handler is advantageous on ARM6,7
+ * processors (they'll run like an ARM3). We'll see.
+ */
+#define CODING_BITS(i) (i & 0x0e000000)
+
+#define LDST_I_BIT(i) (i & (1 << 26)) /* Immediate constant */
+#define LDST_P_BIT(i) (i & (1 << 24)) /* Preindex */
+#define LDST_U_BIT(i) (i & (1 << 23)) /* Add offset */
+#define LDST_W_BIT(i) (i & (1 << 21)) /* Writeback */
+#define LDST_L_BIT(i) (i & (1 << 20)) /* Load */
+
+#define LDSTH_I_BIT(i) (i & (1 << 22)) /* half-word immed */
+#define LDM_S_BIT(i) (i & (1 << 22)) /* write CPSR from SPSR */
+
+#define RN_BITS(i) ((i >> 16) & 15) /* Rn */
+#define RD_BITS(i) ((i >> 12) & 15) /* Rd */
+#define RM_BITS(i) (i & 15) /* Rm */
+
+#define REGMASK_BITS(i) (i & 0xffff)
+#define OFFSET_BITS(i) (i & 0x0fff)
+
+#define IS_SHIFT(i) (i & 0x0ff0)
+#define SHIFT_BITS(i) ((i >> 7) & 0x1f)
+#define SHIFT_TYPE(i) (i & 0x60)
+#define SHIFT_LSL 0x00
+#define SHIFT_LSR 0x20
+#define SHIFT_ASR 0x40
+#define SHIFT_RORRRX 0x60
+
+static unsigned long ai_user;
+static unsigned long ai_sys;
+static unsigned long ai_skipped;
+static unsigned long ai_half;
+static unsigned long ai_word;
+static unsigned long ai_multi;
+
+static int proc_alignment_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
{
- /*
- * Oops. The kernel tried to access some bad page. We'll have to
- * terminate things with extreme prejudice.
- */
- pgd_t *pgd;
- if (addr < PAGE_SIZE)
- printk (KERN_ALERT "Unable to handle kernel NULL pointer dereference");
- else
- printk (KERN_ALERT "Unable to handle kernel paging request");
- printk (" at virtual address %08lx\n", addr);
- printk (KERN_ALERT "current->tss.memmap = %08lX\n", tsk->tss.memmap);
- pgd = pgd_offset (mm, addr);
- printk (KERN_ALERT "*pgd = %08lx", pgd_val (*pgd));
- if (!pgd_none (*pgd)) {
- pmd_t *pmd;
- pmd = pmd_offset (pgd, addr);
- printk (", *pmd = %08lx", pmd_val (*pmd));
- if (!pmd_none (*pmd))
- printk (", *pte = %08lx", pte_val (*pte_offset (pmd, addr)));
- }
- printk ("\n");
- die_if_kernel ("Oops", regs, mode, SIGKILL);
- do_exit (SIGKILL);
+ char *p = page;
+ int len;
+
+ p += sprintf(p, "User:\t\t%li\n", ai_user);
+ p += sprintf(p, "System:\t\t%li\n", ai_sys);
+ p += sprintf(p, "Skipped:\t%li\n", ai_skipped);
+ p += sprintf(p, "Half:\t\t%li\n", ai_half);
+ p += sprintf(p, "Word:\t\t%li\n", ai_word);
+ p += sprintf(p, "Multi:\t\t%li\n", ai_multi);
+
+ len = (p - page) - off;
+ if (len < 0)
+ len = 0;
+
+ *eof = (len <= count) ? 1 : 0;
+ *start = page + off;
+
+ return len;
}
-static void page_fault (unsigned long addr, int mode, struct pt_regs *regs)
+/*
+ * This needs to be done after sysctl_init, otherwise sys/
+ * will be overwritten.
+ */
+void __init alignment_init(void)
{
- struct task_struct *tsk;
- struct mm_struct *mm;
- struct vm_area_struct *vma;
- unsigned long fixup;
-
- lock_kernel();
- tsk = current;
- mm = tsk->mm;
-
- down(&mm->mmap_sem);
- vma = find_vma (mm, addr);
- if (!vma)
- goto bad_area;
- if (vma->vm_start <= addr)
- goto good_area;
- if (!(vma->vm_flags & VM_GROWSDOWN) || expand_stack (vma, addr))
- goto bad_area;
+ struct proc_dir_entry *e;
- /*
- * Ok, we have a good vm_area for this memory access, so
- * we can handle it..
- */
-good_area:
- if (mode & FAULT_CODE_READ) { /* read? */
- if (!(vma->vm_flags & (VM_READ|VM_EXEC)))
- goto bad_area;
- } else {
- if (!(vma->vm_flags & VM_WRITE))
- goto bad_area;
+ e = create_proc_entry("sys/debug/alignment", S_IFREG | S_IRUGO, NULL);
+
+ if (e)
+ e->read_proc = proc_alignment_read;
+}
+
+static int
+do_alignment_exception(struct pt_regs *regs)
+{
+ unsigned int instr, rd, rn, correction, nr_regs, regbits;
+ unsigned long eaddr;
+ union { unsigned long un; signed long sn; } offset;
+
+ if (user_mode(regs)) {
+ set_cr(cr_no_alignment);
+ ai_user += 1;
+ return 0;
}
- handle_mm_fault (tsk, vma, addr & PAGE_MASK, !(mode & FAULT_CODE_READ));
- up(&mm->mmap_sem);
- goto out;
- /*
- * Something tried to access memory that isn't in our memory map..
- * Fix it, but check if it's kernel or user first..
- */
-bad_area:
- up(&mm->mmap_sem);
- if (mode & FAULT_CODE_USER) {
- tsk->tss.error_code = mode;
- tsk->tss.trap_no = 14;
- printk ("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n",
- tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode);
-#ifdef DEBUG
- {
- unsigned int i, j;
- unsigned long *sp = (unsigned long *) (regs->ARM_sp - 128);
- for (j = 0; j < 20 && sp_valid (sp); j++) {
- printk ("%p: ", sp);
- for (i = 0; i < 8 && sp_valid (sp); i += 1, sp++)
- printk ("%08lx ", *sp);
- printk ("\n");
+ ai_sys += 1;
+
+ instr = *(unsigned long *)instruction_pointer(regs);
+ correction = 4; /* sometimes 8 on ARMv3 */
+ regs->ARM_pc += correction + 4;
+
+ rd = RD_BITS(instr);
+ rn = RN_BITS(instr);
+ eaddr = regs->uregs[rn];
+
+ switch(CODING_BITS(instr)) {
+ case 0x00000000:
+ if ((instr & 0x0ff00ff0) == 0x01000090) {
+ ai_skipped += 1;
+ printk(KERN_ERR "Unaligned trap: not handling swp instruction\n");
+ return 1;
+ }
+
+ if (((instr & 0x0e000090) == 0x00000090) && (instr & 0x60) != 0) {
+ ai_half += 1;
+ if (LDSTH_I_BIT(instr))
+ offset.un = (instr & 0xf00) >> 4 | (instr & 15);
+ else
+ offset.un = regs->uregs[RM_BITS(instr)];
+
+ if (LDST_P_BIT(instr)) {
+ if (LDST_U_BIT(instr))
+ eaddr += offset.un;
+ else
+ eaddr -= offset.un;
}
+
+ if (LDST_L_BIT(instr))
+ regs->uregs[rd] = get_unaligned((unsigned short *)eaddr);
+ else
+ put_unaligned(regs->uregs[rd], (unsigned short *)eaddr);
+
+ /* signed half-word? */
+ if (instr & 0x40)
+ regs->uregs[rd] = (long)((short) regs->uregs[rd]);
+
+ if (!LDST_P_BIT(instr)) {
+ if (LDST_U_BIT(instr))
+ eaddr += offset.un;
+ else
+ eaddr -= offset.un;
+ regs->uregs[rn] = eaddr;
+ } else if (LDST_W_BIT(instr))
+ regs->uregs[rn] = eaddr;
+ break;
}
- show_regs (regs);
- c_backtrace (regs->ARM_fp, regs->ARM_cpsr);
-#endif
- force_sig(SIGSEGV, tsk);
- goto out;
- }
- /* Are we prepared to handle this kernel fault? */
- if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) {
- printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n",
- tsk->comm, regs->ARM_pc, addr, fixup);
- regs->ARM_pc = fixup;
- goto out;
+ default:
+ ai_skipped += 1;
+ panic("Alignment trap: not handling instruction %08X at %08lX",
+ instr, regs->ARM_pc - correction - 4);
+ break;
+
+ case 0x04000000:
+ offset.un = OFFSET_BITS(instr);
+ goto ldr_str;
+
+ case 0x06000000:
+ offset.un = regs->uregs[RM_BITS(instr)];
+
+ if (IS_SHIFT(instr)) {
+ unsigned int shiftval = SHIFT_BITS(instr);
+
+ switch(SHIFT_TYPE(instr)) {
+ case SHIFT_LSL:
+ offset.un <<= shiftval;
+ break;
+
+ case SHIFT_LSR:
+ offset.un >>= shiftval;
+ break;
+
+ case SHIFT_ASR:
+ offset.sn >>= shiftval;
+ break;
+
+ case SHIFT_RORRRX:
+ if (shiftval == 0) {
+ offset.un >>= 1;
+ if (regs->ARM_cpsr & CC_C_BIT)
+ offset.un |= 1 << 31;
+ } else
+ offset.un = offset.un >> shiftval |
+ offset.un << (32 - shiftval);
+ break;
+ }
+ }
+
+ ldr_str:
+ ai_word += 1;
+ if (LDST_P_BIT(instr)) {
+ if (LDST_U_BIT(instr))
+ eaddr += offset.un;
+ else
+ eaddr -= offset.un;
+ } else {
+ if (LDST_W_BIT(instr)) {
+ printk(KERN_ERR "Not handling ldrt/strt correctly\n");
+ return 1;
+ }
+ }
+
+ if (LDST_L_BIT(instr)) {
+ regs->uregs[rd] = get_unaligned((unsigned long *)eaddr);
+ if (rd == 15)
+ correction = 0;
+ } else
+ put_unaligned(regs->uregs[rd], (unsigned long *)eaddr);
+
+ if (!LDST_P_BIT(instr)) {
+ if (LDST_U_BIT(instr))
+ eaddr += offset.un;
+ else
+ eaddr -= offset.un;
+
+ regs->uregs[rn] = eaddr;
+ } else if (LDST_W_BIT(instr))
+ regs->uregs[rn] = eaddr;
+ break;
+
+ case 0x08000000:
+ if (LDM_S_BIT(instr))
+ panic("Alignment trap: not handling LDM with s-bit\n");
+ ai_multi += 1;
+
+ for (regbits = REGMASK_BITS(instr), nr_regs = 0; regbits; regbits >>= 1)
+ nr_regs += 4;
+
+ if (!LDST_U_BIT(instr))
+ eaddr -= nr_regs;
+
+ if ((LDST_U_BIT(instr) == 0 && LDST_P_BIT(instr) == 0) ||
+ (LDST_U_BIT(instr) && LDST_P_BIT(instr)))
+ eaddr += 4;
+
+ for (regbits = REGMASK_BITS(instr), rd = 0; regbits; regbits >>= 1, rd += 1)
+ if (regbits & 1) {
+ if (LDST_L_BIT(instr)) {
+ regs->uregs[rd] = get_unaligned((unsigned long *)eaddr);
+ if (rd == 15)
+ correction = 0;
+ } else
+ put_unaligned(regs->uregs[rd], (unsigned long *)eaddr);
+ eaddr += 4;
+ }
+
+ if (LDST_W_BIT(instr)) {
+ if (LDST_P_BIT(instr) && !LDST_U_BIT(instr))
+ eaddr -= nr_regs;
+ else if (LDST_P_BIT(instr))
+ eaddr -= 4;
+ else if (!LDST_U_BIT(instr))
+ eaddr -= 4 + nr_regs;
+ regs->uregs[rn] = eaddr;
+ }
+ break;
}
- kernel_page_fault (addr, mode, regs, tsk, mm);
-out:
- unlock_kernel();
+ regs->ARM_pc -= correction;
+
+ return 0;
}
-/*
- * Handle a data abort. Note that we have to handle a range of addresses
- * on ARM2/3 for ldm. If both pages are zero-mapped, then we have to force
- * a copy-on-write
- */
+#endif
+
asmlinkage void
-do_DataAbort (unsigned long addr, int fsr, int error_code, struct pt_regs *regs)
+do_DataAbort(unsigned long addr, int fsr, int error_code, struct pt_regs *regs)
{
if (user_mode(regs))
error_code |= FAULT_CODE_USER;
+
#define DIE(signr,nam)\
force_sig(signr, current);\
- die_if_kernel(nam, regs, fsr, signr);\
- break;
+ die(nam, regs, fsr);\
+ do_exit(signr);\
+ break
switch (fsr & 15) {
- case 2:
- DIE(SIGKILL, "Terminal exception")
+ /*
+ * 0 - vector exception
+ */
case 0:
- DIE(SIGSEGV, "Vector exception")
+ force_sig(SIGSEGV, current);
+ if (!user_mode(regs)) {
+ die("vector exception", regs, fsr);
+ do_exit(SIGSEGV);
+ }
+ break;
+
+ /*
+ * 15 - permission fault on page
+ * 5 - page-table entry descriptor fault
+ * 7 - first-level descriptor fault
+ */
+ case 15: case 5: case 7:
+ do_page_fault(addr, error_code, regs);
+ break;
+
+ /*
+ * 13 - permission fault on section
+ */
+ case 13:
+ force_sig(SIGSEGV, current);
+ if (!user_mode(regs)) {
+ die("section permission fault", regs, fsr);
+ do_exit(SIGSEGV);
+ } else {
+#ifdef CONFIG_DEBUG_USER
+ printk("%s: permission fault on section, "
+ "address=0x%08lx, code %d\n",
+ current->comm, addr, error_code);
+#ifdef DEBUG
+ {
+ unsigned int i, j;
+ unsigned long *sp;
+
+ sp = (unsigned long *) (regs->ARM_sp - 128);
+ for (j = 0; j < 20 && sp_valid(sp); j++) {
+ printk("%p: ", sp);
+ for (i = 0; i < 8 && sp_valid(sp); i += 1, sp++)
+ printk("%08lx ", *sp);
+ printk("\n");
+ }
+ show_regs(regs);
+ c_backtrace(regs->ARM_fp, regs->ARM_cpsr);
+ }
+#endif
+#endif
+ }
+ break;
+
case 1:
case 3:
- DIE(SIGBUS, "Alignment exception")
+#ifdef CONFIG_ALIGNMENT_TRAP
+ if (!do_alignment_exception(regs))
+ break;
+#endif
+ /*
+ * this should never happen
+ */
+ DIE(SIGBUS, "Alignment exception");
+ break;
+
+ case 2:
+ DIE(SIGKILL, "Terminal exception");
case 12:
case 14:
- DIE(SIGBUS, "External abort on translation")
+ DIE(SIGBUS, "External abort on translation");
case 9:
case 11:
- DIE(SIGSEGV, "Domain fault")
- case 13:/* permission fault on section */
-#ifdef DEBUG
- {
- unsigned int i, j;
- unsigned long *sp;
-
- printk ("%s: section permission fault (bad address=0x%08lx, code %d)\n",
- current->comm, addr, error_code);
- sp = (unsigned long *) (regs->ARM_sp - 128);
- for (j = 0; j < 20 && sp_valid (sp); j++) {
- printk ("%p: ", sp);
- for (i = 0; i < 8 && sp_valid (sp); i += 1, sp++)
- printk ("%08lx ", *sp);
- printk ("\n");
- }
- show_regs (regs);
- c_backtrace(regs->ARM_fp, regs->ARM_cpsr);
- }
-#endif
- DIE(SIGSEGV, "Permission fault")
+ DIE(SIGSEGV, "Domain fault");
- case 15:/* permission fault on page */
- case 5: /* page-table entry descriptor fault */
- case 7: /* first-level descriptor fault */
- page_fault (addr, error_code, regs);
- break;
case 4:
case 6:
- DIE(SIGBUS, "External abort on linefetch")
+ DIE(SIGBUS, "External abort on linefetch");
case 8:
case 10:
- DIE(SIGBUS, "External abort on non-linefetch")
+ DIE(SIGBUS, "External abort on non-linefetch");
}
}
asmlinkage int
-do_PrefetchAbort (unsigned long addr, struct pt_regs *regs)
+do_PrefetchAbort(unsigned long addr, struct pt_regs *regs)
{
-#if 0
- /* does this still apply ? */
- if (the memc mapping for this page exists - can check now...) {
- printk ("Page in, but got abort (undefined instruction?)\n");
- return 0;
- }
-#endif
- page_fault (addr, FAULT_CODE_USER|FAULT_CODE_READ, regs);
+ do_page_fault(addr, FAULT_CODE_USER|FAULT_CODE_READ, regs);
return 1;
}
-
--- /dev/null
+/*
+ * linux/arch/arm/mm/fault-common.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Modifications for ARM processor (c) 1995-1999 Russell King
+ */
+#include <linux/config.h>
+
+extern void die(char *msg, struct pt_regs *regs, unsigned int err);
+
+void __bad_pmd(pmd_t *pmd)
+{
+ printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+#ifdef CONFIG_DEBUG_ERRORS
+ __backtrace();
+#endif
+ set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE));
+}
+
+void __bad_pmd_kernel(pmd_t *pmd)
+{
+ printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd));
+#ifdef CONFIG_DEBUG_ERRORS
+ __backtrace();
+#endif
+ set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE));
+}
+
+static void
+kernel_page_fault(unsigned long addr, int mode, struct pt_regs *regs,
+ struct task_struct *tsk, struct mm_struct *mm)
+{
+ char *reason;
+ /*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
+ pgd_t *pgd;
+
+ if (addr < PAGE_SIZE)
+ reason = "NULL pointer dereference";
+ else
+ reason = "paging request";
+
+ printk(KERN_ALERT "Unable to handle kernel %s at virtual address %08lx\n",
+ reason, addr);
+ printk(KERN_ALERT "memmap = %08lX, pgd = %p\n", tsk->tss.memmap, mm->pgd);
+ pgd = pgd_offset(mm, addr);
+ printk(KERN_ALERT "*pgd = %08lx", pgd_val(*pgd));
+
+ do {
+ pmd_t *pmd;
+ pte_t *pte;
+
+ if (pgd_none(*pgd))
+ break;
+
+ if (pgd_bad(*pgd)) {
+ printk("(bad)\n");
+ break;
+ }
+
+ pmd = pmd_offset(pgd, addr);
+ printk(", *pmd = %08lx", pmd_val(*pmd));
+
+ if (pmd_none(*pmd))
+ break;
+
+ if (pmd_bad(*pmd)) {
+ printk("(bad)\n");
+ break;
+ }
+
+ pte = pte_offset(pmd, addr);
+ printk(", *pte = %08lx", pte_val(*pte));
+ printk(", *ppte = %08lx", pte_val(pte[-PTRS_PER_PTE]));
+ } while(0);
+
+ printk("\n");
+ die("Oops", regs, mode);
+
+ do_exit(SIGKILL);
+}
+
+static void do_page_fault(unsigned long addr, int mode, struct pt_regs *regs)
+{
+ struct task_struct *tsk;
+ struct mm_struct *mm;
+ struct vm_area_struct *vma;
+ unsigned long fixup;
+
+ tsk = current;
+ mm = tsk->mm;
+
+ /*
+ * If we're in an interrupt or have no user
+ * context, we must not take the fault..
+ */
+ if (in_interrupt() || mm == &init_mm)
+ goto no_context;
+
+ down(&mm->mmap_sem);
+ vma = find_vma(mm, addr);
+ if (!vma)
+ goto bad_area;
+ if (vma->vm_start <= addr)
+ goto good_area;
+ if (!(vma->vm_flags & VM_GROWSDOWN) || expand_stack(vma, addr))
+ goto bad_area;
+
+ /*
+ * Ok, we have a good vm_area for this memory access, so
+ * we can handle it..
+ */
+good_area:
+ if (READ_FAULT(mode)) { /* read? */
+ if (!(vma->vm_flags & (VM_READ|VM_EXEC)))
+ goto bad_area;
+ } else {
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+ }
+
+ /*
+ * If for any reason at all we couldn't handle the fault,
+ * make sure we exit gracefully rather than endlessly redo
+ * the fault.
+ */
+ if (!handle_mm_fault(tsk, vma, addr & PAGE_MASK, DO_COW(mode)))
+ goto do_sigbus;
+
+ up(&mm->mmap_sem);
+ return;
+
+ /*
+ * Something tried to access memory that isn't in our memory map..
+ * Fix it, but check if it's kernel or user first..
+ */
+bad_area:
+ up(&mm->mmap_sem);
+
+ /* User mode accesses just cause a SIGSEGV */
+ if (mode & FAULT_CODE_USER) {
+ tsk->tss.error_code = mode;
+ tsk->tss.trap_no = 14;
+#ifdef CONFIG_DEBUG_USER
+ printk("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n",
+ tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode);
+#endif
+ force_sig(SIGSEGV, tsk);
+ return;
+ }
+
+no_context:
+ /* Are we prepared to handle this kernel fault? */
+ if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) {
+#ifdef DEBUG
+ printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n",
+ tsk->comm, regs->ARM_pc, addr, fixup);
+#endif
+ regs->ARM_pc = fixup;
+ return;
+ }
+
+ kernel_page_fault(addr, mode, regs, tsk, mm);
+ return;
+
+do_sigbus:
+ /*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+ up(&mm->mmap_sem);
+
+ /*
+ * Send a sigbus, regardless of whether we were in kernel
+ * or user mode.
+ */
+ tsk->tss.error_code = mode;
+ tsk->tss.trap_no = 14;
+ force_sig(SIGBUS, tsk);
+
+ /* Kernel mode? Handle exceptions or die */
+ if (!(mode & FAULT_CODE_USER))
+ goto no_context;
+}
+
+
#include <asm/proc/mm-init.h>
pgd_t swapper_pg_dir[PTRS_PER_PGD];
+#ifndef CONFIG_NO_PGT_CACHE
+struct pgtable_cache_struct quicklists;
+#endif
extern char _etext, _stext, _edata, __bss_start, _end;
extern char __init_begin, __init_end;
int do_check_pgt_cache(int low, int high)
{
int freed = 0;
+#ifndef CONFIG_NO_PGT_CACHE
if(pgtable_cache_size > high) {
do {
if(pgd_quicklist)
free_pte_slow(get_pte_fast()), freed++;
} while(pgtable_cache_size > low);
}
+#endif
return freed;
}
* data and COW.
*/
#if PTRS_PER_PTE != 1
-unsigned long *empty_bad_page_table;
+pte_t *empty_bad_page_table;
pte_t *__bad_pagetable(void)
{
- int i;
pte_t bad_page;
+ int i;
bad_page = BAD_PAGE;
for (i = 0; i < PTRS_PER_PTE; i++)
- empty_bad_page_table[i] = (unsigned long)pte_val(bad_page);
- return (pte_t *) empty_bad_page_table;
+ set_pte(empty_bad_page_table + i, bad_page);
+
+ return empty_bad_page_table;
}
#endif
empty_bad_page = (unsigned long *)start_mem;
start_mem += PAGE_SIZE;
#if PTRS_PER_PTE != 1
- empty_bad_page_table = (unsigned long *)start_mem;
- start_mem += PTRS_PER_PTE * sizeof (void *);
+#ifdef CONFIG_CPU_32
+ start_mem += PTRS_PER_PTE * BYTES_PER_PTR;
+#endif
+ empty_bad_page_table = (pte_t *)start_mem;
+ start_mem += PTRS_PER_PTE * BYTES_PER_PTR;
#endif
memzero (empty_zero_page, PAGE_SIZE);
start_mem = setup_pagetables (start_mem, end_mem);
flush_tlb_all();
update_memc_all();
+ end_mem &= PAGE_MASK;
+ high_memory = (void *)end_mem;
+
return free_area_init(start_mem, end_mem);
}
/* mark usable pages in the mem_map[] */
mark_usable_memory_areas(&start_mem, end_mem);
+#define BETWEEN(w,min,max) ((w) >= (unsigned long)(min) && \
+ (w) < (unsigned long)(max))
+
for (tmp = PAGE_OFFSET; tmp < end_mem ; tmp += PAGE_SIZE) {
if (PageReserved(mem_map+MAP_NR(tmp))) {
- if (tmp >= KERNTOPHYS(_stext) &&
- tmp < KERNTOPHYS(_edata)) {
- if (tmp < KERNTOPHYS(_etext))
- codepages++;
- else
- datapages++;
- } else if (tmp >= KERNTOPHYS(__init_begin)
- && tmp < KERNTOPHYS(__init_end))
+ if (BETWEEN(tmp, &__init_begin, &__init_end))
initpages++;
- else if (tmp >= KERNTOPHYS(__bss_start)
- && tmp < (unsigned long) start_mem)
+ else if (BETWEEN(tmp, &_stext, &_etext))
+ codepages++;
+ else if (BETWEEN(tmp, &_etext, &_edata))
+ datapages++;
+ else if (BETWEEN(tmp, &__bss_start, start_mem))
datapages++;
else
reservedpages++;
}
atomic_set(&mem_map[MAP_NR(tmp)].count, 1);
#ifdef CONFIG_BLK_DEV_INITRD
- if (!initrd_start || (tmp < initrd_start || tmp >= initrd_end))
+ if (!initrd_start || !BETWEEN(tmp, initrd_start, initrd_end))
#endif
free_page(tmp);
}
- printk ("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
+
+#undef BETWEEN
+
+ printk ("Memory: %luk/%luM available (%dk code, %dk reserved, %dk data, %dk init)\n",
(unsigned long) nr_free_pages << (PAGE_SHIFT-10),
- max_mapnr << (PAGE_SHIFT-10),
+ max_mapnr >> (20 - PAGE_SHIFT),
codepages << (PAGE_SHIFT-10),
reservedpages << (PAGE_SHIFT-10),
datapages << (PAGE_SHIFT-10),
#endif
}
-void free_initmem (void)
+static void free_area(unsigned long addr, unsigned long end, char *s)
{
- unsigned long addr;
+ unsigned int size = (end - addr) >> 10;
- addr = (unsigned long)(&__init_begin);
- for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+ for (; addr < end; addr += PAGE_SIZE) {
mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
atomic_set(&mem_map[MAP_NR(addr)].count, 1);
free_page(addr);
}
- printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
+
+ if (size)
+ printk(" %dk %s", size, s);
+}
+
+void free_initmem (void)
+{
+ printk("Freeing unused kernel memory:");
+
+ free_area((unsigned long)(&__init_begin),
+ (unsigned long)(&__init_end),
+ "init");
+
+#ifdef CONFIG_FOOTBRIDGE
+ {
+ extern int __netwinder_begin, __netwinder_end, __ebsa285_begin, __ebsa285_end;
+
+ if (!machine_is_netwinder())
+ free_area((unsigned long)(&__netwinder_begin),
+ (unsigned long)(&__netwinder_end),
+ "netwinder");
+
+ if (!machine_is_ebsa285() && !machine_is_cats())
+ free_area((unsigned long)(&__ebsa285_begin),
+ (unsigned long)(&__ebsa285_end),
+ "ebsa285/cats");
+ }
+#endif
+
+ printk("\n");
}
void si_meminfo(struct sysinfo *val)
--- /dev/null
+/*
+ * arch/arm/mm/ioremap.c
+ *
+ * Re-map IO memory to kernel address space so that we can access it.
+ *
+ * (C) Copyright 1995 1996 Linus Torvalds
+ *
+ * Hacked for ARM by Phil Blundell <philb@gnu.org>
+ * Hacked to allow all architectures to build, and various cleanups
+ * by Russell King
+ */
+
+/*
+ * This allows a driver to remap an arbitrary region of bus memory into
+ * virtual space. One should *only* use readl, writel, memcpy_toio and
+ * so on with such remapped areas.
+ *
+ * Because the ARM only has a 32-bit address space we can't address the
+ * whole of the (physical) PCI space at once. PCI huge-mode addressing
+ * allows us to circumvent this restriction by splitting PCI space into
+ * two 2GB chunks and mapping only one at a time into processor memory.
+ * We use MMU protection domains to trap any attempt to access the bank
+ * that is not currently mapped. (This isn't fully implemented yet.)
+ *
+ * DC21285 currently has a bug in that the PCI address extension
+ * register affects the address of any writes waiting in the outbound
+ * FIFO. Unfortunately, it is not possible to tell the DC21285 to
+ * flush this - flushing the area causes the bus to lock.
+ */
+
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+
+static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
+ unsigned long phys_addr, pgprot_t pgprot)
+{
+ unsigned long end;
+
+ address &= ~PMD_MASK;
+ end = address + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ do {
+ if (!pte_none(*pte))
+ printk("remap_area_pte: page already exists\n");
+ set_pte(pte, mk_pte_phys(phys_addr, pgprot));
+ address += PAGE_SIZE;
+ phys_addr += PAGE_SIZE;
+ pte++;
+ } while (address < end);
+}
+
+static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
+ unsigned long phys_addr, unsigned long flags)
+{
+ unsigned long end;
+ pgprot_t pgprot;
+
+ address &= ~PGDIR_MASK;
+ end = address + size;
+
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+
+ phys_addr -= address;
+ pgprot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_WRITE | flags);
+ do {
+ pte_t * pte = pte_alloc_kernel(pmd, address);
+ if (!pte)
+ return -ENOMEM;
+ remap_area_pte(pte, address, end - address, address + phys_addr, pgprot);
+ address = (address + PMD_SIZE) & PMD_MASK;
+ pmd++;
+ } while (address < end);
+ return 0;
+}
+
+static int remap_area_pages(unsigned long address, unsigned long phys_addr,
+ unsigned long size, unsigned long flags)
+{
+ pgd_t * dir;
+ unsigned long end = address + size;
+
+ phys_addr -= address;
+ dir = pgd_offset(&init_mm, address);
+ flush_cache_all();
+ while (address < end) {
+ pmd_t *pmd = pmd_alloc_kernel(dir, address);
+ if (!pmd)
+ return -ENOMEM;
+ if (remap_area_pmd(pmd, address, end - address,
+ phys_addr + address, flags))
+ return -ENOMEM;
+ set_pgdir(address, *dir);
+ address = (address + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+ }
+ flush_tlb_all();
+ return 0;
+}
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ *
+ * 'flags' are the extra L_PTE_ flags that you want to specify for this
+ * mapping. See include/asm-arm/proc-armv/pgtable.h for more information.
+ */
+void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+{
+ void * addr;
+ struct vm_struct * area;
+ unsigned long offset;
+
+ /*
+ * Mappings have to be page-aligned
+ */
+ offset = phys_addr & ~PAGE_MASK;
+ size = PAGE_ALIGN(size + offset);
+
+ /*
+ * Don't allow mappings that wrap..
+ */
+ if (!size || size > phys_addr + size)
+ return NULL;
+
+ /*
+ * Ok, go for it..
+ */
+ area = get_vm_area(size);
+ if (!area)
+ return NULL;
+ addr = area->addr;
+ if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
+ vfree(addr);
+ return NULL;
+ }
+ return (void *) (offset + (char *)addr);
+}
+
+void iounmap(void *addr)
+{
+ return vfree((void *) (PAGE_MASK & (unsigned long) addr));
+}
+++ /dev/null
-/*
- * arch/arm/mm/mm-arc.c
- *
- * Extra MM routines for the Archimedes architecture
- *
- * Copyright (C) 1998 Russell King
- */
-#include <linux/init.h>
-#include <asm/hardware.h>
-#include <asm/pgtable.h>
-
-unsigned long phys_screen_end;
-
-/*
- * This routine needs more work to make it dynamically release/allocate mem!
- */
-__initfunc(unsigned long map_screen_mem(unsigned long log_start, unsigned long kmem, int update))
-{
- static int updated = 0;
-
- if (updated)
- return 0;
-
- updated = update;
-
- if (update) {
- unsigned long address = log_start, offset;
- pgd_t *pgdp;
-
- kmem = (kmem + 3) & ~3;
-
- pgdp = pgd_offset (&init_mm, address); /* +31 */
- offset = SCREEN_START;
- while (address < SCREEN1_END) {
- unsigned long addr_pmd, end_pmd;
- pmd_t *pmdp;
-
- /* if (pgd_none (*pgdp)) alloc pmd */
- pmdp = pmd_offset (pgdp, address); /* +0 */
- addr_pmd = address & ~PGDIR_MASK; /* 088000 */
- end_pmd = addr_pmd + SCREEN1_END - address; /* 100000 */
- if (end_pmd > PGDIR_SIZE)
- end_pmd = PGDIR_SIZE;
-
- do {
- unsigned long addr_pte, end_pte;
- pte_t *ptep;
-
- if (pmd_none (*pmdp)) {
- pte_t *new_pte = (pte_t *)kmem;
- kmem += PTRS_PER_PTE * BYTES_PER_PTR;
- memzero (new_pte, PTRS_PER_PTE * BYTES_PER_PTR);
- set_pmd (pmdp, mk_pmd(new_pte));
- }
-
- ptep = pte_offset (pmdp, addr_pmd); /* +11 */
- addr_pte = addr_pmd & ~PMD_MASK; /* 088000 */
- end_pte = addr_pte + end_pmd - addr_pmd; /* 100000 */
- if (end_pte > PMD_SIZE)
- end_pte = PMD_SIZE;
-
- do {
- set_pte (ptep, mk_pte(offset, PAGE_KERNEL));
- addr_pte += PAGE_SIZE;
- offset += PAGE_SIZE;
- ptep++;
- } while (addr_pte < end_pte);
-
- pmdp++;
- addr_pmd = (addr_pmd + PMD_SIZE) & PMD_MASK;
- } while (addr_pmd < end_pmd);
-
- address = (address + PGDIR_SIZE) & PGDIR_MASK;
- pgdp ++;
- }
-
- phys_screen_end = offset;
- flush_tlb_all ();
- update_memc_all ();
- }
- return kmem;
-}
virtual = mp->virtual;
physical = mp->physical;
length = mp->length;
- prot = (mp->prot_read ? PTE_AP_READ : 0) | (mp->prot_write ? PTE_AP_WRITE : 0);
+ prot = (mp->prot_read ? L_PTE_USER : 0) | (mp->prot_write ? L_PTE_WRITE : 0)
+ | L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY;
while ((virtual & 1048575 || physical & 1048575) && length >= PAGE_SIZE) {
alloc_init_page(&start_mem, virtual, physical, mp->domain, prot);
physical += 1048576;
}
- prot = (mp->prot_read ? PTE_AP_READ : 0) | (mp->prot_write ? PTE_AP_WRITE : 0);
+ prot = (mp->prot_read ? L_PTE_USER : 0) | (mp->prot_write ? L_PTE_WRITE : 0)
+ | L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY;
while (length >= PAGE_SIZE) {
alloc_init_page(&start_mem, virtual, physical, mp->domain, prot);
+++ /dev/null
-/*
- * arch/arm/mm/mm-ebsa285.c
- *
- * Extra MM routines for the EBSA285 architecture
- *
- * Copyright (C) 1998 Russell King, Dave Gilbert.
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/proc/mm-init.h>
-#include <asm/dec21285.h>
-
-/*
- * This is to allow us to fiddle with the EEPROM
- * This entry will go away in time, once the fmu
- * can mmap() the flash.
- *
- * These ones are so that we can fiddle
- * with the various cards (eg VGA)
- * until we're happy with them...
- */
-#define MAPPING \
- { 0xd8000000, DC21285_FLASH, 0x00400000, DOMAIN_USER, 1, 1 }, /* EEPROM */ \
- { 0xdc000000, 0x7c000000, 0x00100000, DOMAIN_USER, 1, 1 }, /* VGA */ \
- { 0xe0000000, DC21285_PCI_MEM, 0x18000000, DOMAIN_USER, 1, 1 }, /* VGA */ \
- { 0xf8000000, DC21285_PCI_TYPE_0_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 0 Config */ \
- { 0xf9000000, DC21285_PCI_TYPE_1_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 1 Config */ \
- { PCI_IACK, DC21285_PCI_IACK, 0x01000000, DOMAIN_IO , 0, 1 }, /* PCI IACK */ \
- { 0xfd000000, DC21285_OUTBOUND_WRITE_FLUSH, 0x01000000, DOMAIN_IO , 0, 1 }, /* Out wrflsh */ \
- { 0xfe000000, DC21285_ARMCSR_BASE, 0x01000000, DOMAIN_IO , 0, 1 }, /* CSR */ \
- { 0xffe00000, DC21285_PCI_IO, 0x00100000, DOMAIN_IO , 0, 1 }, /* PCI I/O */ \
- { 0xfff00000, 0x40000000, 0x00100000, DOMAIN_IO , 0, 1 }, /* X-Bus */
-
-#include "mm-armv.c"
--- /dev/null
+/*
+ * arch/arm/mm/mm-ebsa285.c
+ *
+ * Extra MM routines for the EBSA285 architecture
+ *
+ * Copyright (C) 1998 Russell King, Dave Gilbert.
+ */
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/proc/mm-init.h>
+#include <asm/dec21285.h>
+
+/*
+ * The first entry allows us to fiddle with the EEPROM from user-space.
+ * This entry will go away in time, once the fmu32 can mmap() the
+ * flash. It can't at the moment.
+ *
+ * If you want to fiddle with PCI VGA cards from user space, then
+ * change the '0, 1 }' for the PCI MEM and PCI IO to '1, 1 }'
+ * You can then access the PCI bus at 0xe0000000 and 0xffe00000.
+ */
+
+#ifdef CONFIG_HOST_FOOTBRIDGE
+
+/*
+ * The mapping when the footbridge is in host mode.
+ */
+#define MAPPING \
+ { FLASH_BASE, DC21285_FLASH, FLASH_SIZE, DOMAIN_IO, 0, 1 }, \
+ { PCIMEM_BASE, DC21285_PCI_MEM, PCIMEM_SIZE, DOMAIN_IO, 0, 1 }, \
+ { PCICFG0_BASE, DC21285_PCI_TYPE_0_CONFIG, PCICFG0_SIZE, DOMAIN_IO, 0, 1 }, \
+ { PCICFG1_BASE, DC21285_PCI_TYPE_1_CONFIG, PCICFG1_SIZE, DOMAIN_IO, 0, 1 }, \
+ { PCIIACK_BASE, DC21285_PCI_IACK, PCIIACK_SIZE, DOMAIN_IO, 0, 1 }, \
+ { WFLUSH_BASE, DC21285_OUTBOUND_WRITE_FLUSH, WFLUSH_SIZE, DOMAIN_IO, 0, 1 }, \
+ { ARMCSR_BASE, DC21285_ARMCSR_BASE, ARMCSR_SIZE, DOMAIN_IO, 0, 1 }, \
+ { PCIO_BASE, DC21285_PCI_IO, PCIO_SIZE, DOMAIN_IO, 0, 1 }, \
+ { XBUS_BASE, 0x40000000, XBUS_SIZE, DOMAIN_IO, 0, 1 }
+
+#else
+
+/*
+ * These two functions convert virtual addresses to PCI addresses
+ * and PCI addresses to virtual addresses. Note that it is only
+ * legal to use these on memory obtained via get_free_page or
+ * kmalloc.
+ */
+unsigned long __virt_to_bus(unsigned long res)
+{
+#ifdef CONFIG_DEBUG_ERRORS
+ if (res < PAGE_OFFSET || res >= (unsigned long)high_memory) {
+ printk("__virt_to_phys: invalid virtual address 0x%08lx\n", res);
+ __backtrace();
+ }
+#endif
+ return (res - PAGE_OFFSET) + (*CSR_PCISDRAMBASE & 0xfffffff0);
+}
+
+unsigned long __bus_to_virt(unsigned long res)
+{
+ res -= (*CSR_PCISDRAMBASE & 0xfffffff0);
+ res += PAGE_OFFSET;
+
+#ifdef CONFIG_DEBUG_ERRORS
+ if (res < PAGE_OFFSET || res >= (unsigned long)high_memory) {
+ printk("__phys_to_virt: invalid virtual address 0x%08lx\n", res);
+ __backtrace();
+ }
+#endif
+ return res;
+}
+
+/*
+ * The mapping when the footbridge is in add-in mode.
+ */
+#define MAPPING \
+ { PCIO_BASE, DC21285_PCI_IO, PCIO_SIZE, DOMAIN_IO, 0, 1 }, \
+ { XBUS_BASE, 0x40000000, XBUS_SIZE, DOMAIN_IO, 0, 1 }, \
+ { ARMCSR_BASE, DC21285_ARMCSR_BASE, ARMCSR_SIZE, DOMAIN_IO, 0, 1 }, \
+ { WFLUSH_BASE, DC21285_OUTBOUND_WRITE_FLUSH, WFLUSH_SIZE, DOMAIN_IO, 0, 1 }, \
+ { FLASH_BASE, DC21285_FLASH, FLASH_SIZE, DOMAIN_IO, 0, 1 }, \
+ { PCIMEM_BASE, DC21285_PCI_MEM, PCIMEM_SIZE, DOMAIN_IO, 0, 1 }
+
+#endif
+
+#include "mm-armv.c"
+++ /dev/null
-/*
- * arch/arm/mm/mm-vnc.c
- *
- * Extra MM routines for the Corel VNC architecture
- *
- * Copyright (C) 1998 Russell King
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/proc/mm-init.h>
-#include <asm/dec21285.h>
-
-/* Table describing the MMU translation mapping
- * mainly used to set up the I/O mappings.
- */
-#define MAPPING \
- { 0xd0000000, DC21285_FLASH, 0x00800000, DOMAIN_IO , 0, 1 }, /* Flash */ \
- { 0xe0000000, DC21285_PCI_MEM, 0x18000000, DOMAIN_IO , 0, 1 }, /* PCI Mem */ \
- { 0xf8000000, DC21285_PCI_TYPE_0_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 0 Config */ \
- { 0xf9000000, DC21285_PCI_TYPE_1_CONFIG, 0x01000000, DOMAIN_IO , 0, 1 }, /* Type 1 Config */ \
- { PCI_IACK, DC21285_PCI_IACK, 0x01000000, DOMAIN_IO , 0, 1 }, /* PCI IACK */ \
- { 0xfd000000, DC21285_OUTBOUND_WRITE_FLUSH, 0x01000000, DOMAIN_IO , 0, 1 }, /* Out wrflsh */ \
- { 0xfe000000, DC21285_ARMCSR_BASE, 0x01000000, DOMAIN_IO , 0, 1 }, /* CSR */ \
- { 0xffe00000, DC21285_PCI_IO, 0x00100000, DOMAIN_IO , 0, 1 }, /* PCI I/O */ \
-
-#include "mm-armv.c"
movs pc, lr
_arm2_3_check_bugs:
- movs pc, lr
+ bics pc, lr, #0x04000000 @ Clear FIQ disable bit
/*
* Processor specific - ARM2
* Params : prev Old task structure
* : next New task structure for process to run
*
+ * Returns : prev
+ *
* Purpose : Perform a task switch, saving the old processes state, and restoring
* the new.
*
str sp, [r0, #TSS_SAVE] @ Save sp_SVC
ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC
mov r4, r1
- add r0, r1, #TSS_MEMCMAP @ Remap MEMC
+ add r7, r1, #TSS_MEMCMAP @ Remap MEMC
ldr r1, LC0
ldr r1, [r1]
-1: ldmia r0!, {r2, r3, r5, r6}
+1: ldmia r7!, {r2, r3, r5, r6}
strb r2, [r2]
strb r3, [r3]
strb r5, [r5]
strb r6, [r6]
- ldmia r0!, {r2, r3, r5, r6}
+ ldmia r7!, {r2, r3, r5, r6}
strb r2, [r2]
strb r3, [r3]
strb r5, [r5]
* Params : prev Old task structure
* : next New task structure for process to run
*
+ * Returns : prev
+ *
* Purpose : Perform a task switch, saving the old processes state, and restoring
* the new.
*
str sp, [r0, #TSS_SAVE] @ Save sp_SVC
ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC
mov r4, r1
- add r0, r1, #TSS_MEMCMAP @ Remap MEMC
+ add r7, r1, #TSS_MEMCMAP @ Remap MEMC
ldr r1, LC0
ldr r1, [r1]
-1: ldmia r0!, {r2, r3, r5, r6}
+1: ldmia r7!, {r2, r3, r5, r6}
strb r2, [r2]
strb r3, [r3]
strb r5, [r5]
strb r6, [r6]
- ldmia r0!, {r2, r3, r5, r6}
+ ldmia r7!, {r2, r3, r5, r6}
strb r2, [r2]
strb r3, [r3]
strb r5, [r5]
strb r6, [r6]
subs r1, r1, #8
bhi 1b
- mcr p15, 0, r0, c1, c0, 0 @ flush cache
+ mcr p15, 0, r7, c1, c0, 0 @ flush cache
ldmfd sp!, {r4 - r9, fp, pc}^ @ Load all regs saved previously
/*
* Function: arm3_remap_memc (struct task_struct *tsk)
blt 1b
mov pc, lr
-@LC0: .word _current
/*
* Function: arm6_7_switch_to (struct task_struct *prev, struct task_struct *next)
*
* Params : prev Old task structure
* : next New task structure for process to run
*
+ * Returns : prev
+ *
* Purpose : Perform a task switch, saving the old processes state, and restoring
* the new.
*
stmfd sp!, {ip} @ Save cpsr_SVC
str sp, [r0, #TSS_SAVE] @ Save sp_SVC
ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC
- ldr r0, [r1, #TSK_ADDR_LIMIT]
- teq r0, #0
- moveq r0, #DOM_KERNELDOMAIN
- movne r0, #DOM_USERDOMAIN
- mcr p15, 0, r0, c3, c0 @ Set domain reg
- ldr r0, [r1, #TSS_MEMMAP] @ Page table pointer
+ ldr r2, [r1, #TSK_ADDR_LIMIT]
+ teq r2, #0
+ moveq r2, #DOM_KERNELDOMAIN
+ movne r2, #DOM_USERDOMAIN
+ mcr p15, 0, r2, c3, c0 @ Set domain reg
+ ldr r2, [r1, #TSS_MEMMAP] @ Page table pointer
mov r1, #0
mcr p15, 0, r1, c7, c0, 0 @ flush cache
- mcr p15, 0, r0, c2, c0, 0 @ update page table ptr
+ mcr p15, 0, r2, c2, c0, 0 @ update page table ptr
mcr p15, 0, r1, c5, c0, 0 @ flush TLBs
ldmfd sp!, {ip}
msr spsr, ip @ Save tasks CPSR into SPSR for this return
str r1, [r0]
mov pc, lr
+/*
+ * Function: arm6_7_set_pte(pte_t *ptep, pte_t pte)
+ * Params : r0 = Address to set
+ * : r1 = value to set
+ * Purpose : Set a PTE and flush it out of any WB cache
+ */
+ .align 5
+_arm6_7_set_pte:
+ str r1, [r0], #-1024 @ linux version
+
+ bic r2, r1, #0xff0
+ bic r2, r2, #3
+ orr r2, r2, #HPTE_TYPE_SMALL
+
+ tst r1, #LPTE_USER | LPTE_EXEC
+ orrne r2, r2, #HPTE_AP_READ
+
+ tst r1, #LPTE_WRITE
+ tstne r1, #LPTE_DIRTY
+ orrne r2, r2, #HPTE_AP_WRITE
+
+ tst r1, #LPTE_PRESENT
+ tstne r1, #LPTE_YOUNG
+ moveq r2, #0
+
+ str r2, [r0] @ hardware version
+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns)
+ mov pc, lr
+
/*
* Function: _arm6_7_reset
*
.word _arm6_7_flush_tlb_all @ 44
.word _arm6_7_flush_tlb_area @ 48
.word _arm6_set_pmd @ 52
- .word _arm6_7_reset @ 54
- .word _arm6_7_flush_cache @ 58
+ .word _arm6_7_set_pte @ 56
+ .word _arm6_7_reset @ 60
+ .word _arm6_7_flush_cache @ 64
+
+ .word _arm6_7_flush_cache @ 68
+ .word _arm6_7_flush_cache @ 72
/*
* Purpose : Function pointers used to access above functions - all calls
.word _arm6_7_flush_tlb_all @ 44
.word _arm6_7_flush_tlb_area @ 48
.word _arm7_set_pmd @ 52
- .word _arm6_7_reset @ 56
- .word _arm6_7_flush_cache @ 60
-
+ .word _arm6_7_set_pte @ 56
+ .word _arm6_7_reset @ 60
.word _arm6_7_flush_cache @ 64
+
.word _arm6_7_flush_cache @ 68
+ .word _arm6_7_flush_cache @ 72
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
+#include <asm/hardware.h>
#include "../lib/constants.h"
/* This is the maximum size of an area which will be flushed. If the area
/*
* Function: sa110_flush_cache_all (void)
- *
* Purpose : Flush all cache lines
*/
.align 5
ands r1, r1, #1
eor r1, r1, #1
str r1, [r3]
- ldr ip, =0xdf000000
+ ldr ip, =FLUSH_BASE
addne ip, ip, #32768
add r1, ip, #16384 @ only necessary for 16k
1: ldr r3, [ip], #32
/*
* Function: sa110_flush_cache_area (unsigned long address, int end, int flags)
- *
* Params : address Area start address
* : end Area end address
* : flags b0 = I cache as well
- *
* Purpose : clean & flush all cache lines associated with this area of memory
*/
.align 5
/*
* Function: sa110_cache_wback_area(unsigned long address, unsigned long end)
- *
* Params : address Area start address
* : end Area end address
- *
* Purpose : ensure all dirty cachelines in the specified area have been
* written out to memory (for DMA)
*/
/*
* Function: sa110_cache_purge_area(unsigned long address, unsigned long end)
- *
* Params : address Area start address
* : end Area end address
- *
* Purpose : throw away all D-cached data in specified region without
- * an obligation to write it ack.
- *
+ * an obligation to write it back.
* Note : Must clean the D-cached entries around the boundaries if the
* start and/or end address are not cache aligned.
*/
/*
* Function: sa110_flush_cache_entry (unsigned long address)
- *
* Params : address Address of cache line to flush
- *
* Purpose : clean & flush an entry
*/
.align 5
mov pc, lr
/*
- * Function: sa110_flush_cache_pte (unsigned long address)
- *
+ * Function: sa110_clean_cache_area(unsigned long start, unsigned long size)
* Params : address Address of cache line to clean
- *
* Purpose : Ensure that physical memory reflects cache at this location
* for page table purposes.
*/
-_sa110_flush_cache_pte:
- mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns)
+_sa110_clean_cache_area:
+1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns)
+ add r0, r0, #32
+ subs r1, r1, #32
+ bhi 1b
mov pc, lr
/*
* Function: sa110_flush_ram_page (unsigned long page)
- *
* Params : address Area start address
* : size size of area
* : flags b0 = I cache as well
- *
* Purpose : clean & flush all cache lines associated with this area of memory
*/
.align 5
/*
* Function: sa110_flush_tlb_all (void)
- *
* Purpose : flush all TLB entries in all caches
*/
.align 5
/*
* Function: sa110_flush_tlb_area (unsigned long address, unsigned long end, int flags)
- *
* Params : address Area start address
* : end Area end address
* : flags b0 = I cache as well
- *
* Purpose : flush a TLB entry
*/
.align 5
.align 5
_sa110_flush_icache_area:
- mov r3, #0
1: mcr p15, 0, r0, c7, c10, 1 @ Clean D entry
add r0, r0, #32
- cmp r0, r1
- blt 1b
+ subs r1, r1, #32
+ bhi 1b
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
mcr p15, 0, r0, c7, c5, 0 @ flush I cache
mov pc, lr
/*
* Function: sa110_switch_to (struct task_struct *prev, struct task_struct *next)
- *
* Params : prev Old task structure
* : next New task structure for process to run
- *
+ * Returns : prev
* Purpose : Perform a task switch, saving the old processes state, and restoring
* the new.
- *
* Notes : We don't fiddle with the FP registers here - we postpone this until
* the new task actually uses FP. This way, we don't swap FP for tasks
* that do not require it.
stmfd sp!, {r4 - r9, fp, lr} @ Store most regs on stack
mrs ip, cpsr
stmfd sp!, {ip} @ Save cpsr_SVC
+ ldr r2, [r0, #TSS_MEMMAP] @ Get old page tables
str sp, [r0, #TSS_SAVE] @ Save sp_SVC
ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC
- ldr r0, [r1, #TSK_ADDR_LIMIT]
- teq r0, #0
- moveq r0, #DOM_KERNELDOMAIN
- movne r0, #DOM_USERDOMAIN
- mcr p15, 0, r0, c3, c0 @ Set segment
- ldr r0, [r1, #TSS_MEMMAP] @ Page table pointer
+ ldr r4, [r1, #TSK_ADDR_LIMIT]
+ teq r4, #0
+ moveq r4, #DOM_KERNELDOMAIN
+ movne r4, #DOM_USERDOMAIN
+ mcr p15, 0, r4, c3, c0 @ Set segment
+ ldr r4, [r1, #TSS_MEMMAP] @ Page table pointer
+/*
+ * Flushing the cache is nightmarishly slow, so we take any excuse
+ * to get out of it. If the old page table is the same as the new,
+ * this is a CLONE_VM relative of the old task and there is no need
+ * to flush. The overhead of the tests isn't even on the radar
+ * compared to the cost of the flush itself.
+ */
+ teq r4, r2
+ beq 2f
ldr r3, =Lclean_switch
ldr r2, [r3]
ands r2, r2, #1
eor r2, r2, #1
str r2, [r3]
- ldr r2, =0xdf000000
+ ldr r2, =FLUSH_BASE
addne r2, r2, #32768
add r1, r2, #16384 @ only necessary for 16k
1: ldr r3, [r2], #32
mov r1, #0
mcr p15, 0, r1, c7, c5, 0 @ flush I cache
mcr p15, 0, r1, c7, c10, 4 @ drain WB
- mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
+ mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
mcr p15, 0, r1, c8, c7, 0 @ flush TLBs
- ldmfd sp!, {ip}
+2: ldmfd sp!, {ip}
msr spsr, ip @ Save tasks CPSR into SPSR for this return
ldmfd sp!, {r4 - r9, fp, pc}^ @ Load all regs saved previously
/*
* Function: sa110_data_abort ()
- *
* Params : r0 = address of aborted instruction
- *
* Purpose : obtain information about current aborted instruction
- *
* Returns : r0 = address of abort
* : r1 = FSR
* : r2 != 0 if writing
mov pc, lr
/*
- * Function: sa110_set_pmd ()
- *
+ * Function: sa110_set_pmd(pmd_t *pmdp, pmd_t pmd)
* Params : r0 = Address to set
* : r1 = value to set
- *
- * Purpose : Set a PMD and flush it out of any WB cache
+ * Purpose : Set a PMD and flush it out
*/
.align 5
_sa110_set_pmd: str r1, [r0]
mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns)
mov pc, lr
+/*
+ * Function: sa110_set_pte(pte_t *ptep, pte_t pte)
+ * Params : r0 = Address to set
+ * : r1 = value to set
+ * Purpose : Set a PTE and flush it out
+ */
+ .align 5
+_sa110_set_pte: str r1, [r0], #-1024 @ linux version
+
+ eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
+
+ bic r2, r1, #0xff0
+ bic r2, r2, #3
+ orr r2, r2, #HPTE_TYPE_SMALL
+
+ tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
+ orrne r2, r2, #HPTE_AP_READ
+
+ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
+ orreq r2, r2, #HPTE_AP_WRITE
+
+ tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young?
+ movne r2, #0
+
+ str r2, [r0] @ hardware version
+ mov r0, r0
+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns)
+ mov pc, lr
+
/*
* Function: sa110_check_bugs (void)
* : sa110_proc_init (void)
* : sa110_proc_fin (void)
- *
* Notes : This processor does not require these
*/
_sa110_check_bugs:
mrs ip, cpsr
bic ip, ip, #F_BIT
msr cpsr, ip
+
_sa110_proc_init:
_sa110_proc_fin:
mov pc, lr
/*
* Function: sa110_reset
- *
* Notes : This sets up everything for a reset
*/
_sa110_reset: mrs r1, cpsr
.word _sa110_flush_cache_all @ 24
.word _sa110_flush_cache_area @ 28
.word _sa110_flush_cache_entry @ 32
- .word _sa110_flush_cache_pte @ 36
+ .word _sa110_clean_cache_area @ 36
.word _sa110_flush_ram_page @ 40
.word _sa110_flush_tlb_all @ 44
.word _sa110_flush_tlb_area @ 48
.word _sa110_set_pmd @ 52
- .word _sa110_reset @ 56
- .word _sa110_flush_icache_area @ 60
+ .word _sa110_set_pte @ 56
+ .word _sa110_reset @ 60
+ .word _sa110_flush_icache_area @ 64
- .word _sa110_cache_wback_area @ 64
- .word _sa110_cache_purge_area @ 68
+ .word _sa110_cache_wback_area @ 68
+ .word _sa110_cache_purge_area @ 72
*
* Changelog:
* 26/01/1996 RMK Cleaned up various areas to make little more generic
+ * 07/02/1999 RMK Support added for 16K and 32K page sizes
+ * containing 8K blocks
*/
#include <linux/signal.h>
#include <linux/swap.h>
#include <linux/smp.h>
-#define SMALL_ALLOC_SHIFT (10)
+#if PAGE_SIZE == 4096
+/* 2K blocks */
+#define SMALL_ALLOC_SHIFT (11)
+#define NAME(x) x##_2k
+#elif PAGE_SIZE == 32768 || PAGE_SIZE == 16384
+/* 8K blocks */
+#define SMALL_ALLOC_SHIFT (13)
+#define NAME(x) x##_8k
+#endif
+
#define SMALL_ALLOC_SIZE (1 << SMALL_ALLOC_SHIFT)
#define NR_BLOCKS (PAGE_SIZE / SMALL_ALLOC_SIZE)
+#define BLOCK_MASK ((1 << NR_BLOCKS) - 1)
-#if NR_BLOCKS != 4
-#error I only support 4 blocks per page!
-#endif
-
-#define USED(pg) ((atomic_read(&(pg)->count) >> 8) & 15)
+#define USED(pg) ((atomic_read(&(pg)->count) >> 8) & BLOCK_MASK)
#define SET_USED(pg,off) (atomic_read(&(pg)->count) |= 256 << off)
#define CLEAR_USED(pg,off) (atomic_read(&(pg)->count) &= ~(256 << off))
+#define ALL_USED BLOCK_MASK
#define IS_FREE(pg,off) (!(atomic_read(&(pg)->count) & (256 << off)))
-#define PAGE_PTR(page,block) ((struct free_small_page *)((page) + \
+#define SM_PAGE_PTR(page,block) ((struct free_small_page *)((page) + \
((block) << SMALL_ALLOC_SHIFT)))
+#if NR_BLOCKS != 2 && NR_BLOCKS != 4
+#error I only support 2 or 4 blocks per page
+#endif
+
struct free_small_page {
unsigned long next;
unsigned long prev;
1, /* 0001 */
0, /* 0010 */
2, /* 0011 */
+#if NR_BLOCKS == 4
0, /* 0100 */
1, /* 0101 */
0, /* 0110 */
1, /* 1101 */
0, /* 1110 */
4 /* 1111 */
+#endif
};
static inline void clear_page_links(unsigned long page)
int i;
for (i = 0; i < NR_BLOCKS; i++) {
- fsp = PAGE_PTR(page, i);
+ fsp = SM_PAGE_PTR(page, i);
fsp->next = fsp->prev = 0;
}
}
for (i = 0; i < NR_BLOCKS; i++) {
if (mask & (1 << i))
continue;
- fsp = PAGE_PTR(page, i);
+ fsp = SM_PAGE_PTR(page, i);
fsp->prev = prev;
}
}
for (i = 0; i < NR_BLOCKS; i++) {
if (mask & (1 << i))
continue;
- fsp = PAGE_PTR(page, i);
+ fsp = SM_PAGE_PTR(page, i);
fsp->next = next;
}
}
-unsigned long get_small_page(int priority)
+unsigned long NAME(get_page)(int priority)
{
struct free_small_page *fsp;
unsigned long new_page;
page = mem_map + MAP_NR(small_page_ptr);
offset = offsets[USED(page)];
SET_USED(page, offset);
- new_page = (unsigned long)PAGE_PTR(small_page_ptr, offset);
- if (USED(page) == 15) {
+ new_page = (unsigned long)SM_PAGE_PTR(small_page_ptr, offset);
+ if (USED(page) == ALL_USED) {
fsp = (struct free_small_page *)new_page;
set_page_links_prev (fsp->next, 0);
small_page_ptr = fsp->next;
goto again;
}
-void free_small_page(unsigned long spage)
+void NAME(free_page)(unsigned long spage)
{
struct free_small_page *ofsp, *cfsp;
unsigned long flags;
struct page *page;
int offset, oldoffset;
+ if (!spage)
+ goto none;
+
offset = (spage >> SMALL_ALLOC_SHIFT) & (NR_BLOCKS - 1);
spage -= offset << SMALL_ALLOC_SHIFT;
page = mem_map + MAP_NR(spage);
- if (!PageReserved(page) || !USED(page)) {
- printk ("Trying to free non-small page from %p\n", __builtin_return_address(0));
- return;
- }
- if (IS_FREE(page, offset)) {
- printk ("Trying to free free small page from %p\n", __builtin_return_address(0));
- return;
- }
+ if (!PageReserved(page) || !USED(page))
+ goto non_small;
+
+ if (IS_FREE(page, offset))
+ goto free;
+
save_flags_cli (flags);
oldoffset = offsets[USED(page)];
CLEAR_USED(page, offset);
- ofsp = PAGE_PTR(spage, oldoffset);
- cfsp = PAGE_PTR(spage, offset);
+ ofsp = SM_PAGE_PTR(spage, oldoffset);
+ cfsp = SM_PAGE_PTR(spage, offset);
if (oldoffset == NR_BLOCKS) { /* going from totally used to mostly used */
cfsp->prev = 0;
} else
*cfsp = *ofsp;
restore_flags(flags);
+ return;
+
+non_small:
+ printk ("Trying to free non-small page from %p\n", __builtin_return_address(0));
+ return;
+free:
+ printk ("Trying to free free small page from %p\n", __builtin_return_address(0));
+none:
+ return;
}
{
struct file *filp;
- if(fd >= NR_OPEN || !(filp = current->files->fd[fd]))
+ file = fcheck(fd);
+ if(!file)
return ((struct tty_struct *) 0);
if(filp->private_data) {
struct tty_struct *ttyp = (struct tty_struct *) filp->private_data;
- if(ttyp->magic == TTY_MAGIC)
+ if(ttyp->magic == TTY_MAGIC) {
return ttyp;
+ }
}
return ((struct tty_struct *) 0);
}
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/utsname.h>
+#include <linux/file.h>
#include <asm/ptrace.h>
#include <asm/page.h>
int error, i;
/* We don't support this feature yet. */
+ lock_kernel();
if(fs_type) {
error = -EINVAL;
goto out;
asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs *buf)
{
- struct dentry *dentry;
struct inode *inode;
struct statfs kbuf;
mm_segment_t old_fs;
error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statfs));
if (error)
goto out;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ if (!(file = fget(fd))) {
error = -EBADF;
goto out;
}
- if (!(dentry = file->f_dentry)) {
+
+ if (!(inode = file->f_dentry->d_inode)) {
error = -ENOENT;
- goto out;
- }
- if (!(inode = dentry->d_inode)) {
- error = -ENOENT;
- goto out;
+ goto out_f;
}
if (!inode->i_sb) {
error = -ENODEV;
- goto out;
+ goto out_f;
}
if (!inode->i_sb->s_op->statfs) {
error = -ENOSYS;
- goto out;
+ goto out_f;
}
old_fs = get_fs(); set_fs(get_ds());
sizeof(struct statfs));
set_fs(old_fs);
if (error)
- goto out;
+ goto out_f;
__put_user(kbuf.f_type, &buf->f_type);
__put_user(kbuf.f_bsize, &buf->f_bsize);
__put_user(0, &buf->f_fname[i]);
__put_user(0, &buf->f_fpack[i]);
}
- error = 0;
- dput(dentry);
+out_f:
+ fput(file);
out:
unlock_kernel();
return error;
lock_kernel();
if(!(flags & MAP_ANONYMOUS)) {
- if(fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ if(!(file = fget(fd))) {
retval = -EBADF;
goto out;
}
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
retval = do_mmap(file, addr, len, prot, flags, offset);
+ if (file)
+ fput(file);
out:
unlock_kernel();
asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf)
{
- struct dentry *dentry;
struct inode *inode;
mm_segment_t old_fs;
struct statfs kbuf;
error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
if (error)
goto out;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ if (!(file = fget(fd))) {
error = -EBADF;
goto out;
}
- if (!(dentry = file->f_dentry)) {
+ if (!(inode = file->f_dentry->d_inode)) {
error = -ENOENT;
- goto out;
+ goto out_f;
}
- if (!(inode = dentry->d_inode)) {
- error = -ENOENT;
- goto out;
+ if (!inode->i_sb) {
+ error = -ENODEV;
+ goto out_f;
}
if (!inode->i_sb->s_op->statfs) {
error = -ENOSYS;
- goto out;
+ goto out_f;
}
old_fs = get_fs(); set_fs(get_ds());
sizeof(struct statfs));
set_fs(old_fs);
if (error)
- goto out;
+ goto out_f;
__put_user(kbuf.f_bsize, &buf->f_bsize);
__put_user(kbuf.f_frsize, &buf->f_frsize);
for(i = 0; i < 32; i++)
__put_user(0, &buf->f_fstr[i]);
- error = 0;
-
- dput(dentry);
+out_f:
+ fput(file);
out:
unlock_kernel();
return error;
}
if(!(flags & MAP_ANONYMOUS)) {
- if(fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ if(!(file = fcheck(fd))) {
error = -EBADF;
goto out;
}
struct statfs kbuf;
int error, i;
+ lock_kernel();
printk("[%s:%ld] Wheee.. irix_statvfs(%s,%p)\n",
current->comm, current->pid, fname, buf);
error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf)
{
- struct dentry *dentry;
struct inode *inode;
mm_segment_t old_fs;
struct statfs kbuf;
error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
if (error)
goto out;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ if (!(file = fget(fd))) {
error = -EBADF;
goto out;
}
- if (!(dentry = file->f_dentry)) {
+ if (!(inode = file->f_dentry->d_inode)) {
error = -ENOENT;
- goto out;
+ goto out_f;
}
- if (!(inode = dentry->d_inode)) {
- error = -ENOENT;
- goto out;
+ if (!inode->i_sb) {
+ error = -ENODEV;
+ goto out_f;
}
if (!inode->i_sb->s_op->statfs) {
error = -ENOSYS;
- goto out;
+ goto out_f;
}
old_fs = get_fs(); set_fs(get_ds());
sizeof(struct statfs));
set_fs(old_fs);
if (error)
- goto out;
+ goto out_f;
__put_user(kbuf.f_bsize, &buf->f_bsize);
__put_user(kbuf.f_frsize, &buf->f_frsize);
__put_user(kbuf.f_namelen, &buf->f_namemax);
for(i = 0; i < 32; i++)
__put_user(0, &buf->f_fstr[i]);
-
- error = 0;
-
- dput(dentry);
+out_f:
+ fput(file);
out:
unlock_kernel();
return error;
unsigned short reclen = ROUND_UP32(NAME_OFFSET32(dirent) + namlen + 1);
int retval;
- lock_kernel();
#ifdef DEBUG_GETDENTS
printk("\nirix_filldir32[reclen<%d>namlen<%d>count<%d>]",
reclen, namlen, buf->count);
retval = 0;
out:
- unlock_kernel();
return retval;
}
asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count, int *eob)
{
struct file *file;
- struct dentry *dentry;
struct inode *inode;
struct irix_dirent32 *lastdirent;
struct irix_dirent32_callback buf;
current->pid, fd, dirent, count, eob);
#endif
error = -EBADF;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ file = fget(fd);
+ if (!file)
goto out;
- dentry = file->f_dentry;
- if (!dentry)
- goto out;
+ inode = file->f_dentry->d_inode;
+ if (!inode)
+ goto out_putf;
inode = dentry->d_inode;
if (!inode)
- goto out;
+ goto out_putf;
- error = -ENOTDIR;
- if (!file->f_op || !file->f_op->readdir)
- goto out;
-
- error = -EFAULT;
- if(!access_ok(VERIFY_WRITE, dirent, count) ||
- !access_ok(VERIFY_WRITE, eob, sizeof(*eob)))
- goto out;
-
- __put_user(0, eob);
buf.current_dir = (struct irix_dirent32 *) dirent;
buf.previous = NULL;
buf.count = count;
buf.error = 0;
+ error = -ENOTDIR;
+ if (!file->f_op || !file->f_op->readdir)
+ goto out_putf;
+
+ /*
+ * Get the inode's semaphore to prevent changes
+ * to the directory while we read it.
+ */
+ down(&inode->i_sem);
error = file->f_op->readdir(file, &buf, irix_filldir32);
+ up(&inode->i_sem);
if (error < 0)
- goto out;
+ goto out_putf;
+ error = buf.error;
lastdirent = buf.previous;
- if (!lastdirent) {
- error = buf.error;
- goto out;
+ if (lastdirent) {
+ put_user(file->f_pos, &lastdirent->d_off);
+ error = count - buf.count;
}
- lastdirent->d_off = (u32) file->f_pos;
+
+ if (put_user(0, eob) < 0) {
+ error = EFAULT;
+ goto out_putf;
+ }
+
+
#ifdef DEBUG_GETDENTS
printk("eob=%d returning %d\n", *eob, count - buf.count);
#endif
error = count - buf.count;
+out_putf:
+ fput(file);
out:
unlock_kernel();
return error;
unsigned short reclen = ROUND_UP64(NAME_OFFSET64(dirent) + namlen + 1);
int retval;
- lock_kernel();
buf->error = -EINVAL; /* only used if we fail.. */
if (reclen > buf->count) {
retval = -EINVAL;
retval = 0;
out:
- unlock_kernel();
return retval;
}
asmlinkage int irix_getdents64(int fd, void *dirent, int cnt)
{
struct file *file;
- struct dentry *dentry;
struct inode *inode;
struct irix_dirent64 *lastdirent;
struct irix_dirent64_callback buf;
current->pid, fd, dirent, cnt);
#endif
error = -EBADF;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
- goto out;
-
- dentry = file->f_dentry;
- if (!dentry)
+ if (!(file = fget(fd)))
goto out;
- inode = dentry->d_inode;
+ inode = file->f_dentry->d_inode;
if (!inode)
- goto out;
+ goto out_f;
error = -ENOTDIR;
if (!file->f_op || !file->f_op->readdir)
- goto out;
+ goto out_f;
error = -EFAULT;
if(!access_ok(VERIFY_WRITE, dirent, cnt))
- goto out;
+ goto out_f;
error = -EINVAL;
if(cnt < (sizeof(struct irix_dirent64) + 255))
- goto out;
+ goto out_f;
buf.curr = (struct irix_dirent64 *) dirent;
buf.previous = NULL;
buf.count = cnt;
buf.error = 0;
+ down(&inode->i_sem);
error = file->f_op->readdir(file, &buf, irix_filldir64);
+ up(&inode->i_sem);
if (error < 0)
- goto out;
+ goto out_f;
lastdirent = buf.previous;
if (!lastdirent) {
error = buf.error;
- goto out;
+ goto out_f;
}
lastdirent->d_off = (u64) file->f_pos;
#ifdef DEBUG_GETDENTS
#endif
error = cnt - buf.count;
+out_f:
+ fput(file);
out:
unlock_kernel();
return error;
asmlinkage int irix_ngetdents64(int fd, void *dirent, int cnt, int *eob)
{
struct file *file;
- struct dentry *dentry;
struct inode *inode;
struct irix_dirent64 *lastdirent;
struct irix_dirent64_callback buf;
current->pid, fd, dirent, cnt);
#endif
error = -EBADF;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
- goto out;
-
- dentry = file->f_dentry;
- if (!dentry)
+ if (!(file = fget(fd)))
goto out;
- inode = dentry->d_inode;
+ inode = file->f_dentry->d_inode;
if (!inode)
- goto out;
+ goto out_f;
error = -ENOTDIR;
if (!file->f_op || !file->f_op->readdir)
- goto out;
+ goto out_f;
error = -EFAULT;
if(!access_ok(VERIFY_WRITE, dirent, cnt) ||
!access_ok(VERIFY_WRITE, eob, sizeof(*eob)))
- goto out;
+ goto out_f;
error = -EINVAL;
if(cnt < (sizeof(struct irix_dirent64) + 255))
- goto out;
+ goto out_f;
*eob = 0;
buf.curr = (struct irix_dirent64 *) dirent;
buf.previous = NULL;
buf.count = cnt;
buf.error = 0;
+ down(&inode->i_sem);
error = file->f_op->readdir(file, &buf, irix_filldir64);
+ up(&inode->i_sem);
if (error < 0)
- goto out;
+ goto out_f;
lastdirent = buf.previous;
if (!lastdirent) {
error = buf.error;
- goto out;
+ goto out_f;
}
lastdirent->d_off = (u64) file->f_pos;
#ifdef DEBUG_GETDENTS
#endif
error = cnt - buf.count;
+out_f:
+ fput(file);
out:
unlock_kernel();
return error;
lock_kernel();
if (!(flags & MAP_ANONYMOUS)) {
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ file = fget(fd);
+ if (!file)
goto out;
}
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
ret = do_mmap(file, addr, len, prot, flags, offset);
+ if (file)
+ fput(file);
out:
unlock_kernel();
return ret;
to determine this in advance other than by trial and error and common
sense, e.g. call a BNC connectored port 'BNC', not '10Mb'.
- TO DO:
+ Changed the bus probing. EISA used to be done first, followed by PCI.
+ Most people probably don't even know what a de425 is today and the EISA
+ probe has messed up some SCSI cards in the past, so now PCI is always
+ probed first followed by EISA if a) the architecture allows EISA and
+ either b) there have been no PCI cards detected or c) an EISA probe is
+ forced by the user. To force a probe include "force_eisa" in your
+ insmod "args" line; for built-in kernels either change the driver to do
+ this automatically or include #define DE4X5_FORCE_EISA on or before
+ line 1040 in the driver.
+
+ TO DO:
------
- o check what revision numbers the 21142 and 21143 have
- o
-
Revision History
----------------
access traps. This flag is merely for log messages:
should do something more definitive though...
0.543 30-Dec-98 Add SMP spin locking.
-
+ 0.544 8-May-99 Fix for buggy SROM in Motorola embedded boards using
+ a 21143 by <mmporter@home.com>.
+ Change PCI/EISA bus probing order.
+
=========================================================================
*/
-static const char *version = "de4x5.c:V0.543 1998/12/30 davies@maniac.ultranet.com\n";
+static const char *version = "de4x5.c:V0.544 1999/5/8 davies@maniac.ultranet.com\n";
#include <linux/config.h>
#include <linux/module.h>
#if !defined(__sparc_v9__) && !defined(__powerpc__) && !defined(__alpha__)
static u_char de4x5_irq[] = EISA_ALLOWED_IRQ_LIST;
static int lastEISA = 0;
-#else
-static int lastEISA = MAX_EISA_SLOTS; /* Only PCI probes */
+# ifdef DE4X5_FORCE_EISA /* Force an EISA bus probe or not */
+static int forceEISA = 1;
+# else
+static int forceEISA = 0;
+# endif
#endif
static int num_de4x5s = 0;
static int cfrv = 0, useSROM = 0;
{
u_long iobase = dev->base_addr;
+ pci_probe(dev, iobase);
#if !defined(__sparc_v9__) && !defined(__powerpc__) && !defined(__alpha__)
- eisa_probe(dev, iobase);
-#endif
- if (lastEISA == MAX_EISA_SLOTS) {
- pci_probe(dev, iobase);
+ if ((lastPCI == NO_MORE_PCI) && ((num_de4x5s == 0) || forceEISA)) {
+ eisa_probe(dev, iobase);
}
+#endif
return (dev->priv ? 0 : -ENODEV);
}
if ((tmp = (void *)kmalloc(RX_BUFF_SZ * NUM_RX_DESC + ALIGN,
GFP_KERNEL)) == NULL) {
kfree(lp->cache.priv);
+ lp->cache.priv = NULL;
return -ENOMEM;
}
}
for (status = -ENODEV; (i<maxSlots) && (dev!=NULL); i++, iobase+=EISA_SLOT_INC) {
- if (EISA_signature(name, EISA_ID)) {
- cfid = (u32) inl(PCI_CFID);
- cfrv = (u_short) inl(PCI_CFRV);
- device = (cfid >> 8) & 0x00ffff00;
- vendor = (u_short) cfid;
+ if (check_region(iobase, DE4X5_EISA_TOTAL_SIZE)) continue;
+ if (!EISA_signature(name, EISA_ID)) continue;
+
+ cfid = (u32) inl(PCI_CFID);
+ cfrv = (u_short) inl(PCI_CFRV);
+ device = (cfid >> 8) & 0x00ffff00;
+ vendor = (u_short) cfid;
- /* Read the EISA Configuration Registers */
- irq = inb(EISA_REG0);
- irq = de4x5_irq[(irq >> 1) & 0x03];
+ /* Read the EISA Configuration Registers */
+ irq = inb(EISA_REG0);
+ irq = de4x5_irq[(irq >> 1) & 0x03];
- if (is_DC2114x) {
- device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);
- }
- lp->chipset = device;
+ if (is_DC2114x) {
+ device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);
+ }
+ lp->chipset = device;
- /* Write the PCI Configuration Registers */
- outl(PCI_COMMAND_IO | PCI_COMMAND_MASTER, PCI_CFCS);
- outl(0x00006000, PCI_CFLT);
- outl(iobase, PCI_CBIO);
+ /* Write the PCI Configuration Registers */
+ outl(PCI_COMMAND_IO | PCI_COMMAND_MASTER, PCI_CFCS);
+ outl(0x00006000, PCI_CFLT);
+ outl(iobase, PCI_CBIO);
- DevicePresent(EISA_APROM);
- if (check_region(iobase, DE4X5_EISA_TOTAL_SIZE) == 0) {
- dev->irq = irq;
- if ((status = de4x5_hw_init(dev, iobase)) == 0) {
- num_de4x5s++;
- if (loading_module) link_modules(lastModule, dev);
- lastEISA = i;
- return;
- }
- } else if (ioaddr != 0) {
- printk("%s: region already allocated at 0x%04lx.\n", dev->name,iobase);
- }
+ DevicePresent(EISA_APROM);
+
+ dev->irq = irq;
+ if ((status = de4x5_hw_init(dev, iobase)) == 0) {
+ num_de4x5s++;
+ if (loading_module) link_modules(lastModule, dev);
+ lastEISA = i;
+ return;
}
}
if (lp->state == INITIALISED) {
lp->ibn = 3;
lp->active = *p++;
+ if (MOTO_SROM_BUG) lp->active = 0;
lp->phy[lp->active].gep = (*p ? p : 0); p += (2 * (*p) + 1);
lp->phy[lp->active].rst = (*p ? p : 0); p += (2 * (*p) + 1);
lp->phy[lp->active].mc = TWIDDLE(p); p += 2;
t = *q;
*q = '\0';
+#if !defined(__sparc_v9__) && !defined(__powerpc__) && !defined(__alpha__)
+ if (strstr(p, "force_eisa") || strstr(p, "FORCE_EISA")) forceEISA = 1;
+#endif
if (strstr(p, "fdx") || strstr(p, "FDX")) lp->params.fdx = 1;
if (strstr(p, "autosense") || strstr(p, "AUTOSENSE")) {
release_region(p->base_addr, (lp->bus == PCI ?
DE4X5_PCI_TOTAL_SIZE :
DE4X5_EISA_TOTAL_SIZE));
+ if (lp->cache.buf) { /* MAC buffers allocated? */
+ kfree(lp->cache.buf); /* Free the MAC buffers */
+ }
+ if (lp->cache.priv) { /* Private area allocated? */
+ kfree(lp->cache.priv); /* Free the private area */
+ }
}
kfree(p);
} else {
if (lp->cache.buf) { /* MAC buffers allocated? */
kfree(lp->cache.buf); /* Free the MAC buffers */
}
- kfree(lp->cache.priv); /* Free the private area */
release_region(p->base_addr, (lp->bus == PCI ?
DE4X5_PCI_TOTAL_SIZE :
DE4X5_EISA_TOTAL_SIZE));
+ kfree(lp->cache.priv); /* Free the private area */
}
unregister_netdev(p);
kfree(p); /* Free the device structure */
* Local variables:
* compile-command: "gcc -D__KERNEL__ -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c de4x5.c"
*
- * compile-command: "gcc -D__KERNEL__ -DMODULE -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c de4x5.c"
+ * Delete -D__SMP__ below if you didn't define this in your kernel
+ * Delete -DMODVERSIONS below if you didn't define this in your kernel
+ *
+ * compile-command: "gcc -D__KERNEL__ -DMODULE -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -DMODVERSIONS -include /linux/include/linux/modversions.h -c de4x5.c"
* End:
*/
#define DE4X5_GET_REG 0x0e /* Get the DE4X5 Registers */
#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+
+#define MOTO_SROM_BUG ((lp->active == 8) && ((*((s32 *)le32_to_cpu(get_unaligned(dev->dev_addr)))&0x00ffffff)==0x3e0008))
* yet completely filled in, and revalidate has to delay such
* lookups..
*/
-static int autofs_revalidate(struct dentry * dentry)
+static int autofs_revalidate(struct dentry * dentry, int flags)
{
struct inode * dir = dentry->d_parent->d_inode;
struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
d_add(dentry, NULL);
up(&dir->i_sem);
- autofs_revalidate(dentry);
+ autofs_revalidate(dentry, 0);
down(&dir->i_sem);
/*
static int coda_readdir(struct file *file, void *dirent, filldir_t filldir);
/* dentry ops */
-static int coda_dentry_revalidate(struct dentry *de);
+static int coda_dentry_revalidate(struct dentry *de, int);
static void coda_dentry_delete(struct dentry *);
/* support routines */
}
/* called when a cache lookup succeeds */
-static int coda_dentry_revalidate(struct dentry *de)
+static int coda_dentry_revalidate(struct dentry *de, int flags)
{
int valid = 1;
struct inode *inode = de->d_inode;
static int devpts_root_readdir(struct file *,void *,filldir_t);
static struct dentry *devpts_root_lookup(struct inode *,struct dentry *);
-static int devpts_revalidate(struct dentry *);
+static int devpts_revalidate(struct dentry *, int);
static struct file_operations devpts_root_operations = {
NULL, /* llseek */
* the pty really does still exist. Never revalidate negative dentries;
* for simplicity (fix later?)
*/
-static int devpts_revalidate(struct dentry * dentry)
+static int devpts_revalidate(struct dentry * dentry, int flags)
{
struct devpts_sb_info *sbi;
case Q_GETSTATS:
break;
case Q_GETQUOTA:
- if (((type == USRQUOTA && current->uid != id) ||
- (type == GRPQUOTA && current->gid != id)) &&
+ if (((type == USRQUOTA && current->euid != id) ||
+ (type == GRPQUOTA && current->egid != id)) &&
!capable(CAP_SYS_RESOURCE))
goto out;
break;
#include <linux/hfs_fs_i.h>
#include <linux/hfs_fs.h>
-static int hfs_revalidate_dentry(struct dentry *);
+static int hfs_revalidate_dentry(struct dentry *, int);
static int hfs_hash_dentry(struct dentry *, struct qstr *);
static int hfs_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
static void hfs_dentry_iput(struct dentry *, struct inode *);
iput(inode);
}
-static int hfs_revalidate_dentry(struct dentry *dentry)
+static int hfs_revalidate_dentry(struct dentry *dentry, int flags)
{
struct inode *inode = dentry->d_inode;
int diff;
#include <asm/page.h>
#include <asm/pgtable.h>
-/*
- * The bitmask for a lookup event:
- * - follow links at the end
- * - require a directory
- * - ending slashes ok even for nonexistent files
- * - internal "there are more path compnents" flag
- */
-#define LOOKUP_FOLLOW (1)
-#define LOOKUP_DIRECTORY (2)
-#define LOOKUP_SLASHOK (4)
-#define LOOKUP_CONTINUE (8)
-
#include <asm/namei.h>
/* This can be removed after the beta phase. */
/*
* Internal lookup() using the new generic dcache.
*/
-static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name)
+static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
{
struct dentry * dentry = d_lookup(parent, name);
if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- if (!dentry->d_op->d_revalidate(dentry) && !d_invalidate(dentry)) {
+ if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
dput(dentry);
dentry = NULL;
}
* We get the directory semaphore, and after getting that we also
* make sure that nobody added the entry to the dcache in the meantime..
*/
-static struct dentry * real_lookup(struct dentry * parent, struct qstr * name)
+static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
{
struct dentry * result;
struct inode *dir = parent->d_inode;
* FIXME! This could use version numbering or similar to
* avoid unnecessary cache lookups.
*/
- result = cached_lookup(parent, name);
+ result = cached_lookup(parent, name, flags);
if (!result) {
struct dentry * dentry = d_alloc(parent, name);
result = ERR_PTR(-ENOMEM);
/* This does the actual lookups.. */
dentry = reserved_lookup(base, &this);
if (!dentry) {
- dentry = cached_lookup(base, &this);
+ dentry = cached_lookup(base, &this, flags);
if (!dentry) {
- dentry = real_lookup(base, &this);
+ dentry = real_lookup(base, &this, flags);
if (IS_ERR(dentry))
break;
}
/*
* Dentry operations routines
*/
-static int ncp_lookup_validate(struct dentry *);
+static int ncp_lookup_validate(struct dentry *, int);
static int ncp_hash_dentry(struct dentry *, struct qstr *);
static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *);
static void ncp_delete_dentry(struct dentry *);
struct dentry_operations ncp_dentry_operations =
{
- ncp_lookup_validate, /* d_validate(struct dentry *) */
+ ncp_lookup_validate, /* d_revalidate(struct dentry *, int) */
ncp_hash_dentry, /* d_hash */
ncp_compare_dentry, /* d_compare */
ncp_delete_dentry /* d_delete(struct dentry *) */
static int
-ncp_lookup_validate(struct dentry * dentry)
+ncp_lookup_validate(struct dentry * dentry, int flags)
{
struct ncp_server *server;
struct inode *dir = dentry->d_parent->d_inode;
NULL, /* select - default */
NULL, /* ioctl - default */
NULL, /* mmap */
- nfs_open, /* open - revalidate the inode */
+ nfs_open, /* open */
NULL, /* flush */
- NULL, /* no special release code */
+ nfs_release, /* release */
NULL /* fsync */
};
dentry->d_time = jiffies;
}
-#define NFS_REVALIDATE_INTERVAL (5*HZ)
+static inline int nfs_dentry_force_reval(struct dentry *dentry, int flags)
+{
+ struct inode *inode = dentry->d_inode;
+ unsigned long timeout = NFS_ATTRTIMEO(inode);
+
+ /*
+ * If it's the last lookup in a series, we use a stricter
+ * cache consistency check!
+ */
+ if (!(flags & LOOKUP_CONTINUE))
+ timeout = 0;
+
+ return time_after(jiffies,dentry->d_time + timeout);
+}
+
+/*
+ * We judge how long we want to trust negative
+ * dentries by looking at the parent inode mtime.
+ *
+ * If mtime is close to present time, we revalidate
+ * more often.
+ */
+static inline int nfs_neg_need_reval(struct dentry *dentry)
+{
+ unsigned long timeout = 30 * HZ;
+ struct inode *dir = dentry->d_parent->d_inode;
+
+ if (dir) {
+ /* Modified in the last two minutes? */
+ long diff = CURRENT_TIME - dir->i_mtime;
+ if (diff < 2*60)
+ timeout = 1 * HZ;
+ }
+
+ return time_after(jiffies, dentry->d_time + timeout);
+}
+
/*
* This is called every time the dcache has a lookup hit,
* and we should check whether we can really trust that
* we do a new lookup and verify that the dentry is still
* correct.
*/
-static int nfs_lookup_revalidate(struct dentry * dentry)
+static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
{
struct dentry * parent = dentry->d_parent;
struct inode * inode = dentry->d_inode;
struct nfs_fattr fattr;
/*
- * If we don't have an inode, let's just assume
- * a 5-second "live" time for negative dentries.
+ * If we don't have an inode, let's look at the parent
+ * directory mtime to get a hint about how often we
+ * should validate things..
*/
if (!inode) {
- if (time_after(jiffies, dentry->d_time + NFS_REVALIDATE_INTERVAL))
+ if (nfs_neg_need_reval(dentry))
goto out_bad;
goto out_valid;
}
goto out_bad;
}
- if (time_before(jiffies,dentry->d_time+NFS_ATTRTIMEO(inode)))
+ if (IS_ROOT(dentry))
goto out_valid;
- if (IS_ROOT(dentry))
+ if (!nfs_dentry_force_reval(dentry, flags))
goto out_valid;
/*
* Do a new lookup and check the dentry attributes.
*/
- error = nfs_proc_lookup(NFS_DSERVER(parent), NFS_FH(parent),
+ error = nfs_proc_lookup(NFS_DSERVER(parent), NFS_FH(parent),
dentry->d_name.name, &fhandle, &fattr);
if (error)
goto out_bad;
}
struct dentry_operations nfs_dentry_operations = {
- nfs_lookup_revalidate, /* d_validate(struct dentry *) */
+ nfs_lookup_revalidate, /* d_revalidate(struct dentry *, int) */
NULL, /* d_hash */
NULL, /* d_compare */
nfs_dentry_delete, /* d_delete(struct dentry *) */
NULL, /* select - default */
NULL, /* ioctl - default */
nfs_file_mmap, /* mmap */
- nfs_open, /* open - revalidate the inode */
+ nfs_open, /* open */
nfs_file_flush, /* flush */
- NULL, /* release */
+ nfs_release, /* release */
nfs_fsync, /* fsync */
NULL, /* fasync */
NULL, /* check_media_change */
}
/*
- * Revalidate the file on open (this
- * is separate from the path-revalidation
- * that we do on any lookup).
- *
- * When we actually open a file, we want
- * fairly strict consistency: make sure that
- * we've updated the attributes within the
- * last second or so..
+ * These are probably going to contain hooks for
+ * allocating and releasing RPC credentials for
+ * the file. I'll have to think about Tronds patch
+ * a bit more..
*/
int nfs_open(struct inode *inode, struct file *filp)
{
- int retval = 0;
+ return 0;
+}
- if (time_after(jiffies, NFS_READTIME(inode) + HZ/2)) {
- struct dentry *dentry = filp->f_dentry;
- struct nfs_server *server = NFS_DSERVER(dentry);
- retval = _nfs_revalidate_inode(server, dentry);
- }
- return retval;
+int nfs_release(struct inode *inode, struct file *filp)
+{
+ return 0;
}
/*
/*
* Dentry operations routines
*/
-static int smb_lookup_validate(struct dentry *);
+static int smb_lookup_validate(struct dentry *, int);
static int smb_hash_dentry(struct dentry *, struct qstr *);
static int smb_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
static void smb_delete_dentry(struct dentry *);
static struct dentry_operations smbfs_dentry_operations =
{
- smb_lookup_validate, /* d_validate(struct dentry *) */
+ smb_lookup_validate, /* d_revalidate(struct dentry *) */
smb_hash_dentry, /* d_hash */
smb_compare_dentry, /* d_compare */
smb_delete_dentry /* d_delete(struct dentry *) */
* This is the callback when the dcache has a lookup hit.
*/
static int
-smb_lookup_validate(struct dentry * dentry)
+smb_lookup_validate(struct dentry * dentry, int flags)
{
struct inode * inode = dentry->d_inode;
unsigned long age = jiffies - dentry->d_time;
*/
/* nothing for now ... */
-static int umsdos_dentry_validate(struct dentry *dentry)
+static int umsdos_dentry_validate(struct dentry *dentry, int flags)
{
return 1;
}
struct dentry_operations umsdos_dentry_operations =
{
- umsdos_dentry_validate, /* d_validate(struct dentry *) */
+ umsdos_dentry_validate, /* d_revalidate(struct dentry *, int) */
NULL, /* d_hash */
NULL, /* d_compare */
umsdos_dentry_dput, /* d_delete(struct dentry *) */
static int vfat_hash(struct dentry *parent, struct qstr *qstr);
static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);
-static int vfat_revalidate(struct dentry *dentry);
+static int vfat_revalidate(struct dentry *dentry, int);
static struct dentry_operations vfat_dentry_ops[4] = {
{
MOD_DEC_USE_COUNT;
}
-static int vfat_revalidate(struct dentry *dentry)
+static int vfat_revalidate(struct dentry *dentry, int flags)
{
PRINTK1(("vfat_revalidate: %s\n", dentry->d_name.name));
if (dentry->d_time == dentry->d_parent->d_inode->i_version) {
#define M_ARM 103
+#ifdef __KERNEL__
#include <asm/arch/a.out.h>
+#endif
#ifndef LIBRARY_START_TEXT
#define LIBRARY_START_TEXT (0x00c00000)
/*
* linux/include/asm-arm/arch-arc/a.out.h
*
- * Copyright (C) 1996 Russell King
- *
- * Acorn Archimedes/A5000 a.out.h specs
+ * Copyright (C) 1996-1999 Russell King
*/
#ifndef __ASM_ARCH_A_OUT_H
#define __ASM_ARCH_A_OUT_H
-#ifdef __KERNEL__
-#define STACK_TOP (0x01a00000)
-#endif
+#include <asm/arch/memory.h>
+
+#define STACK_TOP TASK_SIZE
#endif
/*
* linux/include/asm-arm/arch-arc/hardware.h
*
- * Copyright (C) 1996 Russell King.
+ * Copyright (C) 1996-1999 Russell King.
*
* This file contains the hardware definitions of the
* Acorn Archimedes/A5000 machines.
* Modifications:
* 04-04-1998 PJB/RMK Merged arc and a5k versions
*/
-
#ifndef __ASM_ARCH_HARDWARE_H
#define __ASM_ARCH_HARDWARE_H
#include <linux/config.h>
+#include <asm/arch/memory.h>
+
/*
* What hardware must be present - these can be tested by the kernel
* source.
*/
#define HAS_IOC
-#include <asm/ioc.h>
#define HAS_MEMC
#include <asm/memc.h>
-#define HAS_MEMC1A
#define HAS_VIDC
/*
* for use with inb/outb
*/
#define IO_VIDC_BASE 0x80100000
+#ifdef CONFIG_ARCH_A5K
+#define IOEB_VID_CTL 0x800d4012
+#define IOEB_PRESENT 0x800d4014
+#define IOEB_PSCLR 0x800d4016
+#define IOEB_MONTYPE 0x800d401c
+#endif
#ifdef CONFIG_ARCH_ARC
#define LATCHAADDR 0x80094010
#define LATCHBADDR 0x80094006
#define IO_EC_IOC_BASE 0x80090000
#define IO_EC_MEMC_BASE 0x80000000
+#ifdef CONFIG_ARCH_ARC
+/* A680 hardware */
+#define WD1973_BASE 0x03290000
+#define WD1973_LATCH 0x03350000
+#define Z8530_BASE 0x032b0008
+#define SCSI_BASE 0x03100000
+#endif
+
/*
* IO definitions
*/
/*
* RAM definitions
*/
-#define MAPTOPHYS(a) (((unsigned long)a & 0x007fffff) + PAGE_OFFSET)
-#define KERNTOPHYS(a) ((((unsigned long)(&a)) & 0x007fffff) + PAGE_OFFSET)
#define GET_MEMORY_END(p) (PAGE_OFFSET + (p->u1.s.page_size) * (p->u1.s.nr_pages))
#define PARAMS_BASE (PAGE_OFFSET + 0x7c000)
-#define KERNEL_BASE (PAGE_OFFSET + 0x80000)
#else
* 11-01-1998 RMK Added mask_and_ack_irq
* 22-08-1998 RMK Restructured IRQ routines
*/
+#include <asm/ioc.h>
+
+#define fixup_irq(x) (x)
static void arc_mask_irq_ack_a(unsigned int irq)
{
outb(0, IOC_FIQMASK);
for (irq = 0; irq < NR_IRQS; irq++) {
- switch (irq & 0xf8) {
+ switch (irq) {
case 0 ... 6:
irq_desc[irq].probe_ok = 1;
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].mask_ack = arc_mask_irq_ack_a;
+ irq_desc[irq].mask = arc_mask_irq_a;
+ irq_desc[irq].unmask = arc_unmask_irq_a;
+ break;
+
case 7:
+ irq_desc[irq].noautoenable = 1;
irq_desc[irq].valid = 1;
irq_desc[irq].mask_ack = arc_mask_irq_ack_a;
irq_desc[irq].mask = arc_mask_irq_a;
#define NR_SCANCODES 128
-extern int a5kkbd_translate(unsigned char scancode, unsigned char *keycode_p, char *up_flag_p);
extern void a5kkbd_leds(unsigned char leds);
extern void a5kkbd_init_hw(void);
extern unsigned char a5kkbd_sysrq_xlate[NR_SCANCODES];
#define kbd_setkeycode(sc,kc) (-EINVAL)
#define kbd_getkeycode(sc) (-EINVAL)
-/* Prototype: int kbd_translate(scancode, *keycode, *up_flag, raw_mode)
- * Returns : 0 to ignore scancode, *keycode set to keycode, *up_flag
- * set to 0200 if scancode indicates release
- */
-#define kbd_translate(sc, kcp, ufp, rm) a5kkbd_translate(sc, kcp, ufp)
+#define kbd_translate(sc, kcp, rm) ({ *(kcp) = (sc); 1; })
#define kbd_unexpected_up(kc) (0200)
#define kbd_leds(leds) a5kkbd_leds(leds)
#define kbd_init_hw() a5kkbd_init_hw()
--- /dev/null
+/*
+ * linux/include/asm-arm/arch-arc/memory.h
+ *
+ * Copyright (c) 1996-1999 Russell King.
+ *
+ * Changelog:
+ * 22-Nov-1996 RMK Created
+ * 21-Mar-1999 RMK Renamed to memory.h
+ * RMK Moved PAGE_OFFSET and TASK_SIZE here
+ */
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * User space: 26MB
+ */
+#define TASK_SIZE (0x01a00000UL)
+
+/*
+ * Page offset: 32MB
+ */
+#define PAGE_OFFSET (0x02000000UL)
+
+#define __virt_to_phys__is_a_macro
+#define __virt_to_phys(vpage) vpage
+#define __phys_to_virt__is_a_macro
+#define __phys_to_virt(ppage) ppage
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ * address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ * to an address that the kernel can use.
+ */
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x) (x)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x) (x)
+
+#endif
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-arc/mmu.h
- *
- * Copyright (c) 1996 Russell King.
- *
- * Changelog:
- * 22-11-1996 RMK Created
- */
-#ifndef __ASM_ARCH_MMU_H
-#define __ASM_ARCH_MMU_H
-
-#define __virt_to_phys__is_a_macro
-#define __virt_to_phys(vpage) vpage
-#define __phys_to_virt__is_a_macro
-#define __phys_to_virt(ppage) ppage
-
-/*
- * Virtual view <-> DMA view memory address translations
- * virt_to_bus: Used to translate the virtual address to an
- * address suitable to be passed to set_dma_addr
- * bus_to_virt: Used to convert an address for DMA operations
- * to an address that the kernel can use.
- */
-#define __virt_to_bus__is_a_macro
-#define __virt_to_bus(x) (x)
-#define __bus_to_virt__is_a_macro
-#define __bus_to_virt(x) (x)
-
-#endif
/* newval=(oldval & mask)|newdata */
void oldlatch_aupdate(unsigned char mask,unsigned char newdata);
+void oldlatch_init(void);
+
#elif defined(CONFIG_ARCH_A5K)
#ifdef __need_oldlatches
/*
* linux/include/asm-arm/arch-arc/processor.h
*
- * Copyright (c) 1996 Russell King.
+ * Copyright (c) 1996-1999 Russell King.
*
* Changelog:
- * 10-09-1996 RMK Created
+ * 10-Sep-1996 RMK Created
+ * 21-Mar-1999 RMK Added asm/arch/memory.h
*/
#ifndef __ASM_ARCH_PROCESSOR_H
#define __ASM_ARCH_PROCESSOR_H
+#include <asm/arch/memory.h>
+
/*
* Bus types
*/
#define MCA_bus 0
#define MCA_bus__is_a_macro /* for versions in ksyms.c */
-/*
- * User space: 26MB
- */
-#define TASK_SIZE (0x01a00000UL)
-
/* This decides where the kernel will search for a free chunk of vm
* space during mmap's.
*/
#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#define INIT_MMAP \
-{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
-
#endif
* 10-Oct-1996 RMK Brought up to date with arch-sa110eval
* 04-Dec-1997 RMK Updated for new arch/arm/time.c
*/
+#include <asm/ioc.h>
+
+static long last_rtc_update = 0; /* last time the cmos clock got updated */
extern __inline__ unsigned long gettimeoffset (void)
{
return offset;
}
-/*
- * No need to reset the timer at every irq
- */
-#define reset_timer() 1
+extern int iic_control (unsigned char, int, char *, int);
-/*
- * Updating of the RTC. We don't currently write the time to the
- * CMOS clock.
- */
-#define update_rtc()
+static int set_rtc_time(unsigned long nowtime)
+{
+ char buf[5], ctrl;
+
+ if (iic_control(0xa1, 0, &ctrl, 1) != 0)
+ printk("RTC: failed to read control reg\n");
+
+ /*
+ * Reset divider
+ */
+ ctrl |= 0x80;
+
+ if (iic_control(0xa0, 0, &ctrl, 1) != 0)
+ printk("RTC: failed to stop the clock\n");
+
+ /*
+ * We only set the time - we don't set the date.
+ * This means that there is the possibility once
+ * a day for the correction to disrupt the date.
+ * We really ought to write the time and date, or
+ * nothing at all.
+ */
+ buf[0] = 0;
+ buf[1] = nowtime % 60; nowtime /= 60;
+ buf[2] = nowtime % 60; nowtime /= 60;
+ buf[3] = nowtime % 24;
+
+ BIN_TO_BCD(buf[1]);
+ BIN_TO_BCD(buf[2]);
+ BIN_TO_BCD(buf[3]);
+
+ if (iic_control(0xa0, 1, buf, 4) != 0)
+ printk("RTC: Failed to set the time\n");
+
+ /*
+ * Re-enable divider
+ */
+ ctrl &= ~0x80;
+
+ if (iic_control(0xa0, 0, &ctrl, 1) != 0)
+ printk("RTC: failed to start the clock\n");
+
+ return 0;
+}
+
+extern __inline__ unsigned long get_rtc_time(void)
+{
+ unsigned int year, i;
+ char buf[8];
+
+ /*
+ * The year is not part of the RTC counter
+ * registers, and is stored in RAM. This
+ * means that it will not be automatically
+ * updated.
+ */
+ if (iic_control(0xa1, 0xc0, buf, 1) != 0)
+ printk("RTC: failed to read the year\n");
+
+ /*
+ * If the year is before 1970, then the year
+ * is actually 100 in advance. This gives us
+ * a year 2070 bug...
+ */
+ year = 1900 + buf[0];
+ if (year < 1970)
+ year += 100;
+
+ /*
+ * Read the time and date in one go - this
+ * will ensure that we don't get any effects
+ * due to carry (the RTC latches the counters
+ * during a read).
+ */
+ if (iic_control(0xa1, 2, buf, 5) != 0) {
+ printk("RTC: failed to read the time and date\n");
+ memset(buf, 0, sizeof(buf));
+ }
+
+ /*
+ * The RTC combines years with date and weekday
+ * with month. We need to mask off this extra
+ * information before converting the date to
+ * binary.
+ */
+ buf[4] &= 0x1f;
+ buf[3] &= 0x3f;
+
+ for (i = 0; i < 5; i++)
+ BCD_TO_BIN(buf[i]);
+
+ return mktime(year, buf[4], buf[3], buf[2], buf[1], buf[0]);
+}
+
+static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ do_timer(regs);
+
+ /* If we have an externally synchronized linux clock, then update
+ * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+ * called as close as possible to 500 ms before the new second starts.
+ */
+ if ((time_status & STA_UNSYNC) == 0 &&
+ xtime.tv_sec > last_rtc_update + 660 &&
+ xtime.tv_usec >= 50000 - (tick >> 1) &&
+ xtime.tv_usec < 50000 + (tick >> 1)) {
+ if (set_rtc_time(xtime.tv_sec) == 0)
+ last_rtc_update = xtime.tv_sec;
+ else
+ last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+ }
+}
+
+static struct irqaction timerirq = {
+ timer_interrupt,
+ 0,
+ 0,
+ "timer",
+ NULL,
+ NULL
+};
/*
* Set up timer interrupt, and return the current time in seconds.
*/
-extern __inline__ unsigned long setup_timer (void)
+extern __inline__ void setup_timer(void)
{
- extern int iic_control (unsigned char, int, char *, int);
- unsigned int year, mon, day, hour, min, sec;
- char buf[8];
-
outb(LATCH & 255, IOC_T0LTCHL);
outb(LATCH >> 8, IOC_T0LTCHH);
outb(0, IOC_T0GO);
- iic_control (0xa0, 0xc0, buf, 1);
- year = buf[0];
- if ((year += 1900) < 1970)
- year += 100;
+ xtime.tv_sec = get_rtc_time();
- iic_control (0xa0, 2, buf, 5);
- mon = buf[4] & 0x1f;
- day = buf[3] & 0x3f;
- hour = buf[2];
- min = buf[1];
- sec = buf[0];
- BCD_TO_BIN(mon);
- BCD_TO_BIN(day);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(min);
- BCD_TO_BIN(sec);
-
- return mktime(year, mon, day, hour, min, sec);
+ setup_arm_irq(IRQ_TIMER, &timerirq);
}
*/
#define VIDMEM ((char *)0x02000000)
-#include "../arch/arm/drivers/char/font.h"
-
int video_num_columns, video_num_lines, video_size_row;
int white, bytes_per_char_h;
extern unsigned long con_charconvtable[256];
/*
* linux/include/asm-arm/arch-ebsa110/a.out.h
*
- * Copyright (C) 1996 Russell King
+ * Copyright (C) 1996-1999 Russell King
*/
-
#ifndef __ASM_ARCH_A_OUT_H
#define __ASM_ARCH_A_OUT_H
-#ifdef __KERNEL__
-#define STACK_TOP ((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#endif
+#include <asm/arch/memory.h>
+
+#define STACK_TOP \
+ ((current->personality == PER_LINUX_32BIT) ? \
+ TASK_SIZE : 0x04000000)
#endif
/*
* linux/include/asm-arm/arch-ebsa110/hardware.h
*
- * Copyright (C) 1996,1997,1998 Russell King.
+ * Copyright (C) 1996-1999 Russell King.
*
* This file contains the hardware definitions of the EBSA-110.
*/
-
#ifndef __ASM_ARCH_HARDWARE_H
#define __ASM_ARCH_HARDWARE_H
-/*
- * What hardware must be present
- */
-#define HAS_PCIO
-
#ifndef __ASSEMBLER__
/*
#define PIT_T2 ((volatile unsigned char *)0xf2000009)
#define PIT_T1 ((volatile unsigned char *)0xf2000005)
#define PIT_T0 ((volatile unsigned char *)0xf2000001)
-#define PCIO_BASE 0xf0000000
/*
* Mapping areas
*/
#define IO_BASE 0xe0000000
-#define IO_SIZE 0x20000000
-#define IO_START 0xe0000000
/*
* RAM definitions
*/
-#define MAPTOPHYS(a) ((unsigned long)(a) - PAGE_OFFSET)
-#define KERNTOPHYS(a) ((unsigned long)(&a))
-#define KERNEL_BASE (0xc0008000)
#define FLUSH_BASE_PHYS 0x40000000
#else
-#define PCIO_BASE 0xf0000000
#define IO_BASE 0
#endif
+
+#define IO_SIZE 0x20000000
+#define IO_START 0xe0000000
+
+#define FLUSH_BASE 0xdf000000
+#define PCIO_BASE 0xf0000000
+
#endif
#define IRQ_MSET ((volatile unsigned char *)0xf2c00000)
#define IRQ_MASK ((volatile unsigned char *)0xf2c00000)
+#define fixup_irq(x) (x)
+
static void ebsa110_mask_and_ack_irq(unsigned int irq)
{
*IRQ_MCLR = 1 << irq;
--- /dev/null
+/*
+ * linux/include/asm-arm/arch-ebsa110/memory.h
+ *
+ * Copyright (c) 1996-1999 Russell King.
+ *
+ * Changelog:
+ * 20-Oct-1996 RMK Created
+ * 31-Dec-1997 RMK Fixed definitions to reduce warnings
+ * 21-Mar-1999 RMK Renamed to memory.h
+ * RMK Moved TASK_SIZE and PAGE_OFFSET here
+ */
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Task size: 3GB
+ */
+#define TASK_SIZE (0xc0000000UL)
+
+/*
+ * Page offset: 3GB
+ */
+#define PAGE_OFFSET (0xc0000000UL)
+
+#define __virt_to_phys__is_a_macro
+#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET)
+#define __phys_to_virt__is_a_macro
+#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET)
+
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x) __virt_to_phys(x)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x) __phys_to_virt(x)
+
+#endif
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-ebsa110/mmap.h
- *
- * Copyright (C) 1996,1997,1998 Russell King
- */
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-ebsa110/mmu.h
- *
- * Copyright (c) 1996,1997,1998 Russell King.
- *
- * Changelog:
- * 20-10-1996 RMK Created
- * 31-12-1997 RMK Fixed definitions to reduce warnings
- */
-#ifndef __ASM_ARCH_MMU_H
-#define __ASM_ARCH_MMU_H
-
-#define __virt_to_phys__is_a_macro
-#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET)
-#define __phys_to_virt__is_a_macro
-#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET)
-
-#define __virt_to_bus__is_a_macro
-#define __virt_to_bus(x) __virt_to_phys(x)
-#define __bus_to_virt__is_a_macro
-#define __bus_to_virt(x) __phys_to_virt(x)
-
-#endif
+++ /dev/null
-/*
- * Dummy oldlatches.h
- *
- * Copyright (C) 1996 Russell King
- */
-
-#ifdef __need_oldlatches
-#error "Old latches not present in this (rpc) machine"
-#endif
/*
* linux/include/asm-arm/arch-ebsa110/processor.h
*
- * Copyright (C) 1996,1997,1998 Russell King
+ * Copyright (C) 1996-1999 Russell King
+ *
+ * Changelog:
+ * 21-Mar-1999 RMK Added asm/arch/memory.h
*/
#ifndef __ASM_ARCH_PROCESSOR_H
#define __ASM_ARCH_PROCESSOR_H
+#include <asm/arch/memory.h>
+
/*
* Bus types
*/
#define MCA_bus 0
#define MCA_bus__is_a_macro /* for versions in ksyms.c */
-/*
- * User space: 3GB
- */
-#define TASK_SIZE (0xc0000000UL)
-
/* This decides where the kernel will search for a free chunk of vm
* space during mmap's.
*/
#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#define INIT_MMAP \
-{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
-
#endif
return 0;
}
-#ifndef DIVISOR
-extern __inline__ int reset_timer (void)
+static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
*PIT_T1 = (PIT1_COUNT) & 0xff;
*PIT_T1 = (PIT1_COUNT) >> 8;
- return 1;
-}
-#else
-extern __inline__ int reset_timer (void)
-{
- static unsigned int divisor;
-#ifdef CONFIG_LEDS
- static int count = 50;
-#endif
-
- *PIT_T1 = (PIT1_COUNT) & 0xff;
- *PIT_T1 = (PIT1_COUNT) >> 8;
#ifdef CONFIG_LEDS
- if (--count == 0) {
- count = 50;
- leds_event(led_timer);
+ {
+ static int count = 50;
+ if (--count == 0) {
+ count = 50;
+ leds_event(led_timer);
+ }
}
#endif
- if (divisor == 0) {
- divisor = DIVISOR - 1;
- return 1;
+ {
+#ifdef DIVISOR
+ static unsigned int divisor;
+
+ if (divisor-- == 0) {
+ divisor = DIVISOR - 1;
+#else
+ {
+#endif
+ do_timer(regs);
+ }
}
- divisor -= 1;
- return 0;
}
-#endif
-/*
- * We don't have a RTC to update!
- */
-#define update_rtc()
+static struct irqaction timerirq = {
+ timer_interrupt,
+ 0,
+ 0,
+ "timer",
+ NULL,
+ NULL
+};
/*
* Set up timer interrupt, and return the current time in seconds.
*/
-extern __inline__ unsigned long setup_timer (void)
+extern __inline__ void setup_timer(void)
{
/*
* Timer 1, mode 0, 16-bit, autoreload
*/
*PIT_CTRL = 0x70;
+
/*
* Refresh counter clocked at 47.8MHz/7 = 146.4ns
* We want centi-second interrupts
*/
- reset_timer ();
+ *PIT_T1 = (PIT1_COUNT) & 0xff;
+ *PIT_T1 = (PIT1_COUNT) >> 8;
+
/*
* Default the date to 1 Jan 1970 0:0:0
* You will have to run a time daemon to set the
* clock correctly at bootup
*/
- return mktime(1970, 1, 1, 0, 0, 0);
+ xtime.tv_sec = mktime(1970, 1, 1, 0, 0, 0);
+
+ setup_arm_irq(IRQ_TIMER, &timerirq);
}
/*
* linux/include/asm-arm/arch-ebsa110/a.out.h
*
- * Copyright (C) 1996 Russell King
+ * Copyright (C) 1996-1999 Russell King
*/
-
#ifndef __ASM_ARCH_A_OUT_H
#define __ASM_ARCH_A_OUT_H
-#ifdef __KERNEL__
-#define STACK_TOP ((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#endif
+#include <asm/arch/memory.h>
+
+#define STACK_TOP \
+ ((current->personality == PER_LINUX_32BIT) ? \
+ TASK_SIZE : 0x04000000)
#endif
*
* Architecture DMA routines
*
- * Copyright (C) 1998 Russell King
- * Copyright (C) 1998 Philip Blundell
+ * Copyright (C) 1998,1999 Russell King
+ * Copyright (C) 1998,1999 Philip Blundell
*/
#ifndef __ASM_ARCH_DMA_H
#define __ASM_ARCH_DMA_H
#define MAX_DMA_ADDRESS 0xffffffff
/*
- * The 21285 has two internal DMA channels; we call these 0 and 1.
+ * The 21285 has two internal DMA channels; we call these 8 and 9.
* On CATS hardware we have an additional eight ISA dma channels
- * numbered 2..9.
+ * numbered 0..7.
*/
+#define _ISA_DMA(x) (0+(x))
+#define _DC21285_DMA(x) (8+(x))
+
#define MAX_DMA_CHANNELS 10
-#define DMA_ISA_BASE 2
-#define DMA_FLOPPY (DMA_ISA_BASE + 2)
+
+#define DMA_FLOPPY _ISA_DMA(2)
+#define DMA_ISA_CASCADE _ISA_DMA(4)
#endif /* _ASM_ARCH_DMA_H */
/*
* linux/include/asm-arm/arch-ebsa285/hardware.h
*
- * Copyright (C) 1998 Russell King.
+ * Copyright (C) 1998-1999 Russell King.
*
* This file contains the hardware definitions of the EBSA-285.
*/
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+#include <linux/config.h>
+#include <asm/arch/memory.h>
-/* Logical Physical
+#ifdef CONFIG_HOST_FOOTBRIDGE
+/* Virtual Physical
* 0xfff00000 0x40000000 X-Bus
- * 0xffe00000 0x7c000000 PCI I/O space
+ * 0xff000000 0x7c000000 PCI I/O space
*
* 0xfe000000 0x42000000 CSR
* 0xfd000000 0x78000000 Outbound write flush
* 0xfc000000 0x79000000 PCI IACK/special space
*
- * 0xf9000000 0x7a010000 PCI Config type 1
- * 0xf8000000 0x7b010000 PCI Config type 0
+ * 0xf9000000 0x7a000000 PCI Config type 1
+ * 0xf8000000 0x7b000000 PCI Config type 0
*
*/
+#define XBUS_SIZE 0x00100000
+#define XBUS_BASE 0xfff00000
-#include <asm/dec21285.h>
-
-#define IO_BASE 0xe0000000
-#define PCIO_BASE 0xffe00000
-#define PCI_IACK 0xfc000000
+#define PCIO_SIZE 0x00100000
+#define PCIO_BASE 0xff000000
-#define XBUS_LEDS ((volatile unsigned char *)0xfff12000)
+#define ARMCSR_SIZE 0x01000000
+#define ARMCSR_BASE 0xfe000000
+
+#define WFLUSH_SIZE 0x01000000
+#define WFLUSH_BASE 0xfd000000
+
+#define PCIIACK_SIZE 0x01000000
+#define PCIIACK_BASE 0xfc000000
+
+#define PCICFG1_SIZE 0x01000000
+#define PCICFG1_BASE 0xf9000000
+
+#define PCICFG0_SIZE 0x01000000
+#define PCICFG0_BASE 0xf8000000
+
+#define PCIMEM_SIZE 0x18000000
+#define PCIMEM_BASE 0xe0000000
+
+#define FLUSH_SIZE 0x00100000
+#define FLUSH_BASE 0xdf000000
+
+#define FLASH_SIZE 0x00400000
+#define FLASH_BASE 0xd8000000
+
+#elif defined(CONFIG_ARCH_CO285)
+
+#define PCIMEM_SIZE 0x80000000
+#define PCIMEM_BASE 0x80000000
+
+#define FLASH_SIZE 0x01000000
+#define FLASH_BASE 0x7f000000
+
+#define FLUSH_SIZE 0x00100000
+#define FLUSH_BASE 0x7e000000
+
+#define WFLUSH_SIZE 0x01000000
+#define WFLUSH_BASE 0x7d000000
+
+#define ARMCSR_SIZE 0x00100000
+#define ARMCSR_BASE 0x7cf00000
+
+#define XBUS_SIZE 0x00020000
+#define XBUS_BASE 0x7cee0000
+
+#define PCIO_SIZE 0x00010000
+#define PCIO_BASE 0x7ced0000
+
+#else
+
+#error Add your add-in architecture here
+
+#endif
+
+#define XBUS_LEDS ((volatile unsigned char *)(XBUS_BASE + 0x12000))
#define XBUS_LED_AMBER (1 << 0)
#define XBUS_LED_GREEN (1 << 1)
#define XBUS_LED_RED (1 << 2)
#define XBUS_LED_TOGGLE (1 << 8)
-#define XBUS_SWITCH ((volatile unsigned char *)0xfff12000)
+#define XBUS_SWITCH ((volatile unsigned char *)(XBUS_BASE + 0x12000))
#define XBUS_SWITCH_SWITCH ((*XBUS_SWITCH) & 15)
#define XBUS_SWITCH_J17_13 ((*XBUS_SWITCH) & (1 << 4))
#define XBUS_SWITCH_J17_11 ((*XBUS_SWITCH) & (1 << 5))
#define XBUS_SWITCH_J17_9 ((*XBUS_SWITCH) & (1 << 6))
-#define KERNTOPHYS(a) ((unsigned long)(&a))
-
#define PARAMS_OFFSET 0x0100
#define PARAMS_BASE (PAGE_OFFSET + PARAMS_OFFSET)
#define FLUSH_BASE_PHYS 0x50000000
+
+/* PIC irq control */
+#define PIC_LO 0x20
+#define PIC_MASK_LO 0x21
+#define PIC_HI 0xA0
+#define PIC_MASK_HI 0xA1
+
+/* GPIO pins */
+#define GPIO_CCLK 0x800
+#define GPIO_DSCLK 0x400
+#define GPIO_E2CLK 0x200
+#define GPIO_IOLOAD 0x100
+#define GPIO_RED_LED 0x080
+#define GPIO_WDTIMER 0x040
+#define GPIO_DATA 0x020
+#define GPIO_IOCLK 0x010
+#define GPIO_DONE 0x008
+#define GPIO_FAN 0x004
+#define GPIO_GREEN_LED 0x002
+#define GPIO_RESET 0x001
+
+/* CPLD pins */
+#define CPLD_DSRESET 8
+#define CPLD_UNMUTE 2
+
+#ifndef __ASSEMBLY__
+extern void gpio_modify_op(int mask, int set);
+extern void gpio_modify_io(int mask, int in);
+extern int gpio_read(void);
+extern void cpld_modify(int mask, int set);
+#endif
+
+#endif
* has the constant-optimised IO
*/
#undef ARCH_IO_DELAY
+#define ARCH_READWRITE
/*
* Dynamic IO functions - let the compiler
* optimize the expressions
*/
-#define DECLARE_DYN_OUT(fnsuffix,instr,typ) \
-extern __inline__ void __out##fnsuffix (unsigned int value, unsigned int port) \
-{ \
- __asm__ __volatile__( \
- "str%?" ##instr## " %0, [%1, %2] @ out"###fnsuffix \
- : \
- : "r" (value), "r" (PCIO_BASE), typ (port)); \
+#define DECLARE_DYN_OUT(fnsuffix,instr,typ) \
+extern __inline__ void \
+__out##fnsuffix (unsigned int value, unsigned int port) \
+{ \
+ __asm__ __volatile__( \
+ "str%?" ##instr## " %0, [%1, %2] @ out"###fnsuffix \
+ : \
+ : "r" (value), "r" (PCIO_BASE), typ (port)); \
}
-#define DECLARE_DYN_IN(sz,fnsuffix,instr,typ) \
-extern __inline__ unsigned sz __in##fnsuffix (unsigned int port) \
-{ \
- unsigned long value; \
- __asm__ __volatile__( \
- "ldr%?" ##instr## " %0, [%1, %2] @ in"###fnsuffix \
- : "=&r" (value) \
- : "r" (PCIO_BASE), typ (port)); \
- return (unsigned sz)value; \
+#define DECLARE_DYN_IN(sz,fnsuffix,instr,typ) \
+extern __inline__ unsigned sz \
+__in##fnsuffix (unsigned int port) \
+{ \
+ unsigned long value; \
+ __asm__ __volatile__( \
+ "ldr%?" ##instr## " %0, [%1, %2] @ in"###fnsuffix \
+ : "=&r" (value) \
+ : "r" (PCIO_BASE), typ (port)); \
+ return (unsigned sz)value; \
}
-extern __inline__ unsigned int __ioaddr (unsigned int port) \
-{ \
- return (unsigned int)(PCIO_BASE + port); \
+extern __inline__ unsigned int __ioaddr (unsigned int port) \
+{ \
+ return (unsigned int)(PCIO_BASE + port); \
}
#define DECLARE_IO(sz,fnsuffix,instr,typ) \
* These have to be macros for the 'J' constraint to work -
* +/-4096 immediate operand.
*/
-#define __outbc(value,port) \
-({ \
- __asm__ __volatile__( \
- "str%?b %0, [%1, %2] @ outbc" \
- : \
- : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \
+#define __outbc(value,port) \
+({ \
+ __asm__ __volatile__( \
+ "str%?b %0, [%1, %2] @ outbc" \
+ : \
+ : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \
})
-#define __inbc(port) \
-({ \
- unsigned char result; \
- __asm__ __volatile__( \
- "ldr%?b %0, [%1, %2] @ inbc" \
- : "=r" (result) \
- : "r" (PCIO_BASE), "Jr" (port)); \
- result; \
+#define __inbc(port) \
+({ \
+ unsigned char result; \
+ __asm__ __volatile__( \
+ "ldr%?b %0, [%1, %2] @ inbc" \
+ : "=r" (result) \
+ : "r" (PCIO_BASE), "Jr" (port)); \
+ result; \
})
-#define __outwc(value,port) \
-({ \
- __asm__ __volatile__( \
- "str%?h %0, [%1, %2] @ outwc" \
- : \
- : "r" (value), "r" (PCIO_BASE), "r" (port)); \
+#define __outwc(value,port) \
+({ \
+ __asm__ __volatile__( \
+ "str%?h %0, [%1, %2] @ outwc" \
+ : \
+ : "r" (value), "r" (PCIO_BASE), "r" (port)); \
})
-#define __inwc(port) \
-({ \
- unsigned short result; \
- __asm__ __volatile__( \
- "ldr%?h %0, [%1, %2] @ inwc" \
- : "=r" (result) \
- : "r" (PCIO_BASE), "r" (port)); \
- result & 0xffff; \
+#define __inwc(port) \
+({ \
+ unsigned short result; \
+ __asm__ __volatile__( \
+ "ldr%?h %0, [%1, %2] @ inwc" \
+ : "=r" (result) \
+ : "r" (PCIO_BASE), "r" (port)); \
+ result & 0xffff; \
})
-#define __outlc(value,port) \
-({ \
- __asm__ __volatile__( \
- "str%? %0, [%1, %2] @ outlc" \
- : \
- : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \
+#define __outlc(value,port) \
+({ \
+ __asm__ __volatile__( \
+ "str%? %0, [%1, %2] @ outlc" \
+ : \
+ : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \
})
-#define __inlc(port) \
-({ \
- unsigned long result; \
- __asm__ __volatile__( \
- "ldr%? %0, [%1, %2] @ inlc" \
- : "=r" (result) \
- : "r" (PCIO_BASE), "Jr" (port)); \
- result; \
+#define __inlc(port) \
+({ \
+ unsigned long result; \
+ __asm__ __volatile__( \
+ "ldr%? %0, [%1, %2] @ inlc" \
+ : "=r" (result) \
+ : "r" (PCIO_BASE), "Jr" (port)); \
+ result; \
})
-#define __ioaddrc(port) \
-({ \
- unsigned long addr; \
- addr = PCIO_BASE + port; \
- addr; \
+#define __ioaddrc(port) \
+({ \
+ unsigned long addr; \
+ addr = PCIO_BASE + port; \
+ addr; \
})
/*
*
* IO address has already been translated to a virtual address
*/
-#define outb_t(v,p) \
+#define outb_t(v,p) \
(*(volatile unsigned char *)(p) = (v))
-#define inb_t(p) \
+#define inb_t(p) \
(*(volatile unsigned char *)(p))
-#define outl_t(v,p) \
+#define outl_t(v,p) \
(*(volatile unsigned long *)(p) = (v))
-#define inl_t(p) \
+#define inl_t(p) \
(*(volatile unsigned long *)(p))
/*
- * ioremap support
+ * ioremap support - validate a PCI memory address,
+ * and convert a PCI memory address to a physical
+ * address for the page tables.
*/
#define valid_ioaddr(iomem,size) ((iomem) < 0x80000000 && (iomem) + (size) <= 0x80000000)
#define io_to_phys(iomem) ((iomem) + DC21285_PCI_MEM)
* is using read*() and so on with addresses they didn't get from ioremap
* this can go away.
*/
-#define IO_FUDGE_FACTOR 0xe0000000
+#define IO_FUDGE_FACTOR PCIMEM_BASE
-extern inline void *ioremap(unsigned long iomem_addr, unsigned long size)
-{
- unsigned long phys_addr;
-
- if (!valid_ioaddr(iomem_addr, size))
- return NULL;
-
- phys_addr = io_to_phys(iomem_addr & PAGE_MASK);
-
- return (void *)((unsigned long)__ioremap(phys_addr, size, 0)
- - IO_FUDGE_FACTOR);
-}
+/*
+ * ioremap takes a PCI memory address, as specified in
+ * linux/Documentation/IO-mapping.txt
+ */
+#define ioremap(iomem_addr,size) \
+({ \
+ unsigned long _addr = (iomem_addr), _size = (size); \
+ void *_ret = NULL; \
+ if (valid_ioaddr(_addr, _size)) { \
+ _addr = io_to_phys(_addr); \
+ _ret = __ioremap(_addr, _size, 0) - IO_FUDGE_FACTOR; \
+ } \
+ _ret; })
#define ioremap_nocache(iomem_addr,size) ioremap((iomem_addr),(size))
extern void iounmap(void *addr);
-/*
- * We'd probably be better off with these as macros rather than functions.
- * Firstly that would be more efficient and secondly we could do with the
- * ability to stop GCC whinging about type conversions. --philb
- */
-static inline void writeb(unsigned char b, unsigned int addr)
-{
- *(volatile unsigned char *)(IO_FUDGE_FACTOR + (addr)) = b;
-}
-
-static inline unsigned char readb(unsigned int addr)
-{
- return *(volatile unsigned char *)(IO_FUDGE_FACTOR + (addr));
+#define DECLARE_PCI_WRITE(typ,fnsuffix) \
+static inline void write##fnsuffix(unsigned typ val, unsigned int addr) \
+{ \
+ *(volatile unsigned typ *)(IO_FUDGE_FACTOR + addr) = val; \
}
-static inline void writew(unsigned short b, unsigned int addr)
-{
- *(volatile unsigned short *)(IO_FUDGE_FACTOR + (addr)) = b;
+#define DECLARE_PCI_READ(typ,fnsuffix) \
+static inline unsigned typ read##fnsuffix (unsigned int addr) \
+{ \
+ return *(volatile unsigned typ *)(IO_FUDGE_FACTOR + addr); \
}
-static inline unsigned short readw(unsigned int addr)
-{
- return *(volatile unsigned short *)(IO_FUDGE_FACTOR + (addr));
-}
+#define DECLARE_PCI(typ,fnsuffix) \
+ DECLARE_PCI_WRITE(typ,fnsuffix) \
+ DECLARE_PCI_READ(typ,fnsuffix)
-static inline void writel(unsigned long b, unsigned int addr)
-{
- *(volatile unsigned long *)(IO_FUDGE_FACTOR + (addr)) = b;
-}
+DECLARE_PCI(char,b)
+DECLARE_PCI(short,w)
+DECLARE_PCI(long,l)
-static inline unsigned short readl(unsigned int addr)
-{
- return *(volatile unsigned long *)(IO_FUDGE_FACTOR + (addr));
-}
+#undef DECLARE_PCI
+#undef DECLARE_PCI_READ
+#undef DECLARE_PCI_WRITE
#endif
* Copyright (C) 1996-1998 Russell King
*
* Changelog:
- * 22-08-1998 RMK Restructured IRQ routines
- * 03-09-1998 PJB Merged CATS support
+ * 22-Aug-1998 RMK Restructured IRQ routines
+ * 03-Sep-1998 PJB Merged CATS support
+ * 20-Jan-1998 RMK Started merge of EBSA286, CATS and NetWinder
+ * 26-Jan-1999 PJB Don't use IACK on CATS
+ * 16-Mar-1999 RMK Added autodetect of ISA PICs
*/
-#include <linux/config.h>
+#include <asm/hardware.h>
+#include <asm/dec21285.h>
+#include <asm/irq.h>
-static void ebsa285_mask_irq(unsigned int irq)
+/*
+ * Footbridge IRQ translation table
+ * Converts from our IRQ numbers into FootBridge masks
+ */
+static int dc21285_irq_mask[] = {
+ IRQ_MASK_UART_RX, /* 0 */
+ IRQ_MASK_UART_TX, /* 1 */
+ IRQ_MASK_TIMER1, /* 2 */
+ IRQ_MASK_TIMER2, /* 3 */
+ IRQ_MASK_TIMER3, /* 4 */
+ IRQ_MASK_IN0, /* 5 */
+ IRQ_MASK_IN1, /* 6 */
+ IRQ_MASK_IN2, /* 7 */
+ IRQ_MASK_IN3, /* 8 */
+ IRQ_MASK_DOORBELLHOST, /* 9 */
+ IRQ_MASK_DMA1, /* 10 */
+ IRQ_MASK_DMA2, /* 11 */
+ IRQ_MASK_PCI, /* 12 */
+ IRQ_MASK_SDRAMPARITY, /* 13 */
+ IRQ_MASK_I2OINPOST, /* 14 */
+ IRQ_MASK_PCI_ERR /* 15 */
+};
+
+static int isa_irq = -1;
+
+static inline int fixup_irq(unsigned int irq)
{
- *CSR_IRQ_DISABLE = 1 << irq;
+#ifdef CONFIG_HOST_FOOTBRIDGE
+ if (irq == isa_irq)
+ irq = *(unsigned char *)PCIIACK_BASE;
+#endif
+
+ return irq;
}
-static void ebsa285_unmask_irq(unsigned int irq)
+static void dc21285_mask_irq(unsigned int irq)
{
- *CSR_IRQ_ENABLE = 1 << irq;
+ *CSR_IRQ_DISABLE = dc21285_irq_mask[irq & 15];
}
-#ifdef CONFIG_CATS
+static void dc21285_unmask_irq(unsigned int irq)
+{
+ *CSR_IRQ_ENABLE = dc21285_irq_mask[irq & 15];
+}
-/*
- * This contains the irq mask for both 8259A irq controllers,
- */
-static unsigned int isa_irq_mask = 0xffff;
+static void isa_mask_pic_lo_irq(unsigned int irq)
+{
+ unsigned int mask = 1 << (irq & 7);
+
+ outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
+}
-#define cached_21 (isa_irq_mask & 0xff)
-#define cached_A1 ((isa_irq_mask >> 8) & 0xff)
+static void isa_mask_ack_pic_lo_irq(unsigned int irq)
+{
+ unsigned int mask = 1 << (irq & 7);
-#define update_8259(_irq) \
- if ((_irq) & 8) \
- outb(cached_A1, 0xa1); \
- else \
- outb(cached_21, 0x21);
+ outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
+ outb(0x20, PIC_LO);
+}
-static void isa_interrupt(int irq, void *h, struct pt_regs *regs)
+static void isa_unmask_pic_lo_irq(unsigned int irq)
{
- asmlinkage void do_IRQ(int irq, struct pt_regs * regs);
- unsigned int irqbits = inb(0x20) | (inb(0xa0) << 8), irqnr = 0;
- irqbits &= ~(1<<2); /* don't try to service the cascade */
- while (irqbits) {
- if (irqbits & 1)
- do_IRQ(32 + irqnr, regs);
- irqbits >>= 1;
- irqnr++;
- }
+ unsigned int mask = 1 << (irq & 7);
+
+ outb(inb(PIC_MASK_LO) & ~mask, PIC_MASK_LO);
}
-static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
+static void isa_mask_pic_hi_irq(unsigned int irq)
+{
+ unsigned int mask = 1 << (irq & 7);
-static struct irqaction irq_isa =
- { isa_interrupt, SA_INTERRUPT, 0, "ISA PIC", NULL, NULL };
-static struct irqaction irq_cascade =
- { no_action, 0, 0, "cascade", NULL, NULL };
+ outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
+}
-static void cats_mask_and_ack_isa_irq(unsigned int irq)
+static void isa_mask_ack_pic_hi_irq(unsigned int irq)
{
- isa_irq_mask |= (1 << (irq - 32));
- update_8259(irq);
- if (irq & 8) {
- inb(0xA1); /* DUMMY */
- outb(cached_A1,0xA1);
- outb(0x62,0x20); /* Specific EOI to cascade */
- outb(0x20,0xA0);
- } else {
- inb(0x21); /* DUMMY */
- outb(cached_21,0x21);
- outb(0x20,0x20);
- }
+ unsigned int mask = 1 << (irq & 7);
+
+ outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
+ outb(0x62, PIC_LO);
+ outb(0x20, PIC_HI);
}
-static void cats_mask_isa_irq(unsigned int irq)
+static void isa_unmask_pic_hi_irq(unsigned int irq)
{
- isa_irq_mask |= (1 << (irq - 32));
- update_8259(irq);
+ unsigned int mask = 1 << (irq & 7);
+
+ outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI);
}
-static void cats_unmask_isa_irq(unsigned int irq)
+static void no_action(int cpl, void *dev_id, struct pt_regs *regs)
{
- isa_irq_mask &= ~(1 << (irq - 32));
- update_8259(irq);
}
-
-#endif
+
+static struct irqaction irq_cascade = { no_action, 0, 0, "cascade", NULL, NULL };
static __inline__ void irq_init_irq(void)
{
int irq;
+ /*
+ * setup DC21285 IRQs
+ */
*CSR_IRQ_DISABLE = -1;
*CSR_FIQ_DISABLE = -1;
- for (irq = 0; irq < NR_IRQS; irq++) {
+ for (irq = _DC21285_IRQ(0); irq < _DC21285_IRQ(16); irq++) {
irq_desc[irq].valid = 1;
irq_desc[irq].probe_ok = 1;
-#ifdef CONFIG_CATS
- if (machine_is_cats() && IRQ_IS_ISA(irq)) {
- irq_desc[irq].mask_ack = cats_mask_and_ack_isa_irq;
- irq_desc[irq].mask = cats_mask_isa_irq;
- irq_desc[irq].unmask = cats_unmask_isa_irq;
+ irq_desc[irq].mask_ack = dc21285_mask_irq;
+ irq_desc[irq].mask = dc21285_mask_irq;
+ irq_desc[irq].unmask = dc21285_unmask_irq;
+ }
+
+ /*
+ * Determine the ISA settings for
+ * the machine we're running on.
+ */
+ switch (machine_arch_type) {
+ default:
+ isa_irq = -1;
+ break;
+
+ case MACH_TYPE_EBSA285:
+ /* The following is dependent on which slot
+ * you plug the Southbridge card into. We
+ * currently assume that you plug it into
+ * the right-hand most slot.
+ */
+ isa_irq = IRQ_PCI;
+ break;
+
+ case MACH_TYPE_CATS:
+ isa_irq = IRQ_IN2;
+ break;
+
+ case MACH_TYPE_NETWINDER:
+ isa_irq = IRQ_IN3;
+ break;
+ }
+
+ if (isa_irq != -1) {
+ /*
+ * Setup, and then probe for an ISA PIC
+ */
+ outb(0x11, PIC_LO);
+ outb(_ISA_IRQ(0), PIC_MASK_LO); /* IRQ number */
+ outb(0x04, PIC_MASK_LO); /* Slave on Ch2 */
+ outb(0x01, PIC_MASK_LO); /* x86 */
+ outb(0xf5, PIC_MASK_LO); /* pattern: 11110101 */
+
+ outb(0x11, PIC_HI);
+ outb(_ISA_IRQ(8), PIC_MASK_HI); /* IRQ number */
+ outb(0x02, PIC_MASK_HI); /* Slave on Ch1 */
+ outb(0x01, PIC_MASK_HI); /* x86 */
+ outb(0xfa, PIC_MASK_HI); /* pattern: 11111010 */
+
+// outb(0x68, PIC_LO); /* enable special mode */
+// outb(0x68, PIC_HI); /* enable special mode */
+ outb(0x0b, PIC_LO);
+ outb(0x0b, PIC_HI);
+
+ if (inb(PIC_MASK_LO) == 0xf5 && inb(PIC_MASK_HI) == 0xfa) {
+ outb(0xff, PIC_MASK_LO);/* mask all IRQs */
+ outb(0xff, PIC_MASK_HI);/* mask all IRQs */
} else
-#endif
- {
- irq_desc[irq].mask_ack = ebsa285_mask_irq;
- irq_desc[irq].mask = ebsa285_mask_irq;
- irq_desc[irq].unmask = ebsa285_unmask_irq;
- }
+ isa_irq = -1;
}
-#ifdef CONFIG_CATS
- if (machine_is_cats()) {
- request_region(0x20, 2, "pic1");
- request_region(0xa0, 2, "pic2");
-
- /* set up master 8259 */
- outb(0x11, 0x20);
- outb(0, 0x21);
- outb(1<<2, 0x21);
- outb(0x1, 0x21);
- outb(0xff, 0x21);
- outb(0x68, 0x20);
- outb(0xa, 0x20);
-
- /* set up slave 8259 */
- outb(0x11, 0xa0);
- outb(0, 0xa1);
- outb(2, 0xa1);
- outb(0x1, 0xa1);
- outb(0xff, 0xa1);
- outb(0x68, 0xa0);
- outb(0xa, 0xa0);
-
- setup_arm_irq(IRQ_ISA_PIC, &irq_isa);
+ if (isa_irq != -1) {
+ for (irq = _ISA_IRQ(0); irq < _ISA_IRQ(8); irq++) {
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].probe_ok = 1;
+ irq_desc[irq].mask_ack = isa_mask_ack_pic_lo_irq;
+ irq_desc[irq].mask = isa_mask_pic_lo_irq;
+ irq_desc[irq].unmask = isa_unmask_pic_lo_irq;
+ }
+
+ for (irq = _ISA_IRQ(8); irq < _ISA_IRQ(16); irq++) {
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].probe_ok = 1;
+ irq_desc[irq].mask_ack = isa_mask_ack_pic_hi_irq;
+ irq_desc[irq].mask = isa_mask_pic_hi_irq;
+ irq_desc[irq].unmask = isa_unmask_pic_hi_irq;
+ }
+
+ request_region(PIC_LO, 2, "pic1");
+ request_region(PIC_HI, 2, "pic2");
setup_arm_irq(IRQ_ISA_CASCADE, &irq_cascade);
+ setup_arm_irq(isa_irq, &irq_cascade);
}
-#endif
}
*
* Copyright (C) 1998 Russell King
* Copyright (C) 1998 Phil Blundell
+ *
+ * Changelog:
+ * 20-Jan-1998 RMK Started merge of EBSA286, CATS and NetWinder
+ * 01-Feb-1999 PJB ISA IRQs start at 0 not 16
*/
-#define NR_IRQS 48
+#define NR_IRQS 32
+#define NR_DC21285_IRQS 16
+
+#define _ISA_IRQ(x) (0 + (x))
+#define _DC21285_IRQ(x) (16 + (x))
/*
* This is a list of all interrupts that the 21285
- * can generate
+ * can generate and we handle.
*/
-#define IRQ_RESERVED 0
-#define IRQ_SOFTIRQ 1
-#define IRQ_CONRX 2
-#define IRQ_CONTX 3
-#define IRQ_TIMER1 4
-#define IRQ_TIMER2 5
-#define IRQ_TIMER3 6
-#define IRQ_TIMER4 7
-#define IRQ_IN0 8
-#define IRQ_IN1 9
-#define IRQ_IN2 10
-#define IRQ_IN3 11
-#define IRQ_XCS0 12
-#define IRQ_XCS1 13
-#define IRQ_XCS2 14
-#define IRQ_DOORBELLHOST 15
-#define IRQ_DMA1 16
-#define IRQ_DMA2 17
-#define IRQ_PCI 18
-#define IRQ_BIST 22
-#define IRQ_SERR 23
-#define IRQ_SDRAMPARITY 24
-#define IRQ_I2OINPOST 25
-#define IRQ_DISCARDTIMER 27
-#define IRQ_PCIDATAPARITY 28
-#define IRQ_PCIMASTERABORT 29
-#define IRQ_PCITARGETABORT 30
-#define IRQ_PCIPARITY 31
-
-/* IRQs 32-47 are the 16 ISA interrupts on a CATS board. */
-#define IRQ_ISA_PIC IRQ_IN2
-#define IRQ_IS_ISA(_x) (((_x) >= 32) && ((_x) <= 47))
-#define IRQ_ISA(_x) ((_x) + 0x20)
-#define IRQ_ISA_CASCADE IRQ_ISA(2)
+#define IRQ_CONRX _DC21285_IRQ(0)
+#define IRQ_CONTX _DC21285_IRQ(1)
+#define IRQ_TIMER1 _DC21285_IRQ(2)
+#define IRQ_TIMER2 _DC21285_IRQ(3)
+#define IRQ_TIMER3 _DC21285_IRQ(4)
+#define IRQ_IN0 _DC21285_IRQ(5)
+#define IRQ_IN1 _DC21285_IRQ(6)
+#define IRQ_IN2 _DC21285_IRQ(7)
+#define IRQ_IN3 _DC21285_IRQ(8)
+#define IRQ_DOORBELLHOST _DC21285_IRQ(9)
+#define IRQ_DMA1 _DC21285_IRQ(10)
+#define IRQ_DMA2 _DC21285_IRQ(11)
+#define IRQ_PCI _DC21285_IRQ(12)
+#define IRQ_SDRAMPARITY _DC21285_IRQ(13)
+#define IRQ_I2OINPOST _DC21285_IRQ(14)
+#define IRQ_PCI_ERR _DC21285_IRQ(15)
+
+#define IRQ_ISA_TIMER _ISA_IRQ(0)
+#define IRQ_ISA_KEYBOARD _ISA_IRQ(1)
+#define IRQ_ISA_CASCADE _ISA_IRQ(2)
+#define IRQ_ISA_UART2 _ISA_IRQ(3)
+#define IRQ_ISA_UART _ISA_IRQ(4)
+#define IRQ_ISA_FLOPPY _ISA_IRQ(6)
+#define IRQ_ISA_PRINTER _ISA_IRQ(7)
+#define IRQ_ISA_RTC_ALARM _ISA_IRQ(8)
+#define IRQ_ISA_2 _ISA_IRQ(9)
+#define IRQ_ISA_PS2MOUSE _ISA_IRQ(12)
+#define IRQ_ISA_HARDDISK1 _ISA_IRQ(14)
+#define IRQ_ISA_HARDDISK2 _ISA_IRQ(15)
+
+#define IRQ_MASK_UART_RX (1 << 2)
+#define IRQ_MASK_UART_TX (1 << 3)
+#define IRQ_MASK_TIMER1 (1 << 4)
+#define IRQ_MASK_TIMER2 (1 << 5)
+#define IRQ_MASK_TIMER3 (1 << 6)
+#define IRQ_MASK_IN0 (1 << 8)
+#define IRQ_MASK_IN1 (1 << 9)
+#define IRQ_MASK_IN2 (1 << 10)
+#define IRQ_MASK_IN3 (1 << 11)
+#define IRQ_MASK_DOORBELLHOST (1 << 15)
+#define IRQ_MASK_DMA1 (1 << 16)
+#define IRQ_MASK_DMA2 (1 << 17)
+#define IRQ_MASK_PCI (1 << 18)
+#define IRQ_MASK_SDRAMPARITY (1 << 24)
+#define IRQ_MASK_I2OINPOST (1 << 25)
+#define IRQ_MASK_PCI_ERR ((1 <<23) | (1 << 27) | (1 << 28) | (1 << 29) | (1 << 30) | (1 << 31))
/*
- * Now map them to the Linux interrupts
+ * Netwinder interrupt allocations
*/
-#define IRQ_TIMER IRQ_TIMER1
-#define IRQ_FLOPPYDISK IRQ_ISA(6)
-#define IRQ_HARDDISK IRQ_ISA(14)
-#define IRQ_HARDDISK_SECONDARY IRQ_ISA(15)
+#define IRQ_NETWINDER_ETHER10 IRQ_IN0
+#define IRQ_NETWINDER_ETHER100 IRQ_IN1
+#define IRQ_NETWINDER_VIDCOMP IRQ_IN2
+#define IRQ_NETWINDER_PS2MOUSE _ISA_IRQ(5)
+#define IRQ_NETWINDER_IR _ISA_IRQ(6)
+#define IRQ_NETWINDER_BUTTON _ISA_IRQ(10)
+#define IRQ_NETWINDER_VGA _ISA_IRQ(11)
+#define IRQ_NETWINDER_SOUND _ISA_IRQ(12)
+
+#undef RTC_IRQ
+#define RTC_IRQ IRQ_ISA_RTC_ALARM
+#undef AUX_IRQ
+#define AUX_IRQ (machine_is_netwinder() ? IRQ_NETWINDER_PS2MOUSE : IRQ_ISA_PS2MOUSE)
+#define IRQ_FLOPPYDISK IRQ_ISA_FLOPPY
-#define irq_cannonicalize(_i) (((_i) == IRQ_ISA_CASCADE) ? IRQ_ISA(9) : _i)
+#define irq_cannonicalize(_i) (((_i) == IRQ_ISA_CASCADE) ? IRQ_ISA_2 : _i)
* (C) 1998 Russell King
* (C) 1998 Phil Blundell
*/
-
-#include <linux/config.h>
#include <asm/irq.h>
#include <asm/system.h>
-#define NR_SCANCODES 128
-
-#ifdef CONFIG_CATS
-
-#define KEYBOARD_IRQ IRQ_ISA(1)
+extern int have_isa_bridge;
extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
extern int pckbd_getkeycode(unsigned int scancode);
extern void pckbd_init_hw(void);
extern unsigned char pckbd_sysrq_xlate[128];
-#define kbd_setkeycode pckbd_setkeycode
-#define kbd_getkeycode pckbd_getkeycode
-#define kbd_translate(sc, kcp, ufp, rm) ({ *ufp = sc & 0200; \
- pckbd_translate(sc & 0x7f, kcp, rm);})
+#define KEYBOARD_IRQ IRQ_ISA_KEYBOARD
-#define kbd_unexpected_up pckbd_unexpected_up
-#define kbd_leds pckbd_leds
-#define kbd_init_hw() \
- do { if (machine_is_cats()) pckbd_init_hw(); } while (0)
-#define kbd_sysrq_xlate pckbd_sysrq_xlate
-#define kbd_disable_irq()
-#define kbd_enable_irq()
+#define NR_SCANCODES 128
-#define SYSRQ_KEY 0x54
+#define kbd_setkeycode(sc,kc) \
+ ({ \
+ int __ret; \
+ if (have_isa_bridge) \
+ __ret = pckbd_setkeycode(sc,kc);\
+ else \
+ __ret = -EINVAL; \
+ __ret; \
+ })
-#else
+#define kbd_getkeycode(sc) \
+ ({ \
+ int __ret; \
+ if (have_isa_bridge) \
+ __ret = pckbd_getkeycode(sc); \
+ else \
+ __ret = -EINVAL; \
+ __ret; \
+ })
-/* Dummy keyboard definitions */
+#define kbd_translate(sc, kcp, rm) \
+ ({ \
+ pckbd_translate(sc, kcp, rm); \
+ })
-#define kbd_setkeycode(sc,kc) (-EINVAL)
-#define kbd_getkeycode(sc) (-EINVAL)
+#define kbd_unexpected_up pckbd_unexpected_up
+
+#define kbd_leds(leds) \
+ do { \
+ if (have_isa_bridge) \
+ pckbd_leds(leds); \
+ } while (0)
+
+#define kbd_init_hw() \
+ do { \
+ if (have_isa_bridge) \
+ pckbd_init_hw(); \
+ } while (0)
+
+#define kbd_sysrq_xlate pckbd_sysrq_xlate
-/* Prototype: int kbd_translate(scancode, *keycode, *up_flag, raw_mode)
- * Returns : 0 to ignore scancode, *keycode set to keycode, *up_flag
- * set to 0200 if scancode indicates release
- */
-#define kbd_translate(sc, kcp, ufp, rm) (1)
-#define kbd_unexpected_up(kc) (0200)
-#define kbd_leds(leds)
-#define kbd_init_hw()
-//#define kbd_sysrq_xlate ps2kbd_sysrq_xlate
#define kbd_disable_irq()
#define kbd_enable_irq()
-#define SYSRQ_KEY 13
-
-#endif
+#define SYSRQ_KEY 0x54
--- /dev/null
+/*
+ * linux/include/asm-arm/arch-ebsa285/memory.h
+ *
+ * Copyright (c) 1996-1999 Russell King.
+ *
+ * Changelog:
+ * 20-Oct-1996 RMK Created
+ * 31-Dec-1997 RMK Fixed definitions to reduce warnings.
+ * 17-May-1998 DAG Added __virt_to_bus and __bus_to_virt functions.
+ * 21-Nov-1998 RMK Changed __virt_to_bus and __bus_to_virt to macros.
+ * 21-Mar-1999 RMK Added PAGE_OFFSET for co285 architecture.
+ * Renamed to memory.h
+ * Moved PAGE_OFFSET and TASK_SIZE here
+ */
+#ifndef __ASM_ARCH_MMU_H
+#define __ASM_ARCH_MMU_H
+
+#if defined(CONFIG_HOST_FOOTBRIDGE)
+
+/*
+ * Task size: 3GB
+ */
+#define TASK_SIZE (0xc0000000UL)
+
+/*
+ * Page offset: 3GB
+ */
+#define PAGE_OFFSET (0xc0000000UL)
+
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x) ((x) - 0xe0000000)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x) ((x) + 0xe0000000)
+
+#elif defined(CONFIG_ADDIN_FOOTBRIDGE)
+
+#if defined(CONFIG_ARCH_CO285)
+
+/*
+ * Task size: 1.5GB
+ */
+#define TASK_SIZE (0x60000000UL)
+
+/*
+ * Page offset: 1.5GB
+ */
+#define PAGE_OFFSET (0x60000000UL)
+
+#else
+
+#error Add in your architecture here
+
+#endif
+
+#ifndef __ASSEMBLY__
+extern unsigned long __virt_to_bus(unsigned long);
+extern unsigned long __bus_to_virt(unsigned long);
+#endif
+
+#endif
+
+/*
+ * On Footbridge machines, the dram is contiguous.
+ * On Host Footbridge, these conversions are constant.
+ * On an add-in footbridge, these depend on register settings.
+ */
+#define __virt_to_phys__is_a_macro
+#define __virt_to_phys(vpage) ((unsigned long)(vpage) - PAGE_OFFSET)
+#define __phys_to_virt__is_a_macro
+#define __phys_to_virt(ppage) ((unsigned long)(ppage) + PAGE_OFFSET)
+
+#endif
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-ebsa110/mmap.h
- *
- * Copyright (C) 1996,1997,1998 Russell King
- */
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-ebsa285/mmu.h
- *
- * Copyright (c) 1996,1997,1998 Russell King.
- *
- * Changelog:
- * 20-10-1996 RMK Created
- * 31-12-1997 RMK Fixed definitions to reduce warnings
- * 17-05-1998 DAG Added __virt_to_bus and __bus_to_virt functions.
- * 21-11-1998 RMK Changed __virt_to_bus and __bus_to_virt to macros.
- */
-#ifndef __ASM_ARCH_MMU_H
-#define __ASM_ARCH_MMU_H
-
-/*
- * On ebsa285, the dram is contiguous
- */
-#define __virt_to_phys__is_a_macro
-#define __virt_to_phys(vpage) ((unsigned long)(vpage) - PAGE_OFFSET)
-#define __phys_to_virt__is_a_macro
-#define __phys_to_virt(ppage) ((unsigned long)(ppage) + PAGE_OFFSET)
-
-#define __virt_to_bus__is_a_macro
-#define __virt_to_bus(x) ((x) - 0xe0000000)
-#define __bus_to_virt__is_a_macro
-#define __bus_to_virt(x) ((x) + 0xe0000000)
-
-#endif
+++ /dev/null
-/*
- * Dummy oldlatches.h
- *
- * Copyright (C) 1996 Russell King
- */
-
-#ifdef __need_oldlatches
-#error "Old latches not present in this (rpc) machine"
-#endif
/*
* linux/include/asm-arm/arch-ebsa110/processor.h
*
- * Copyright (C) 1996,1997,1998 Russell King
+ * Copyright (C) 1996-1999 Russell King
+ *
+ * Changelog:
+ * 21-Mar-1999 RMK Added asm/arch/memory.h
*/
#ifndef __ASM_ARCH_PROCESSOR_H
#define __ASM_ARCH_PROCESSOR_H
+#include <asm/arch/memory.h>
+
/*
* Bus types
*/
#define MCA_bus 0
#define MCA_bus__is_a_macro /* for versions in ksyms.c */
-/*
- * User space: 3GB
- */
-#define TASK_SIZE (0xc0000000UL)
-
/* This decides where the kernel will search for a free chunk of vm
* space during mmap's.
*/
#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#define INIT_MMAP \
-{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
-
#endif
#ifndef __ASM_ARCH_SERIAL_H
#define __ASM_ARCH_SERIAL_H
-#include <linux/config.h>
-
#include <asm/irq.h>
/*
*/
#define BASE_BAUD (1843200 / 16)
-#ifdef CONFIG_CATS
-#define _SER_IRQ0 IRQ_ISA(4)
-#define _SER_IRQ1 IRQ_ISA(3)
-#else
-#define _SER_IRQ0 0
-#define _SER_IRQ1 0
-#endif
+#define _SER_IRQ0 IRQ_ISA_UART
+#define _SER_IRQ1 IRQ_ISA_UART2
#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
*
* Copyright (c) 1996,1997,1998 Russell King.
*/
+#include <asm/dec21285.h>
+#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/leds.h>
mov r0, #0x130
mcr p15, 0, r0, c1, c0 @ MMU off
mcr p15, 0, ip, c7, c7 @ flush caches
- mov pc, lr");
+ mov pc, lr" : : : "cc");
} else {
- /* To reboot, we set up the 21285 watchdog and enable it.
- * We then wait for it to timeout.
- */
- *CSR_TIMER4_LOAD = 0x8000;
- *CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
- *CSR_SA110_CNTL |= 1 << 13;
+ if (machine_is_ebsa285() || machine_is_co285()) {
+ /* To reboot, we set up the 21285 watchdog and
+ * enable it. We then wait for it to timeout.
+ */
+ *CSR_TIMER4_LOAD = 0x8000;
+ *CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE |
+ TIMER_CNTL_AUTORELOAD |
+ TIMER_CNTL_DIV16;
+ *CSR_SA110_CNTL |= 1 << 13;
+ } else if (machine_is_netwinder()) {
+ /* open up the SuperIO chip
+ */
+ outb(0x87, 0x370);
+ outb(0x87, 0x370);
+
+ /* aux function group 1 (logical device 7)
+ */
+ outb(0x07, 0x370);
+ outb(0x07, 0x371);
+
+ /* set GP16 for WD-TIMER output
+ */
+ outb(0xe6, 0x370);
+ outb(0x00, 0x371);
+
+ /* set a RED LED and toggle WD_TIMER for rebooting
+ */
+ outb(0xc4, 0x338);
+ }
}
}
* 21-Mar-1998 RMK Created
* 27-Aug-1998 PJB CATS support
* 28-Dec-1998 APH Made leds optional
+ * 20-Jan-1999 RMK Started merge of EBSA285, CATS and NetWinder
+ * 16-Mar-1999 RMK More support for EBSA285-like machines with RTCs in
*/
-#define RTC_PORT(x) (0x72+(x))
-#define RTC_ALWAYS_BCD 1
+#define RTC_PORT(x) (rtc_base+(x))
+#define RTC_ALWAYS_BCD 0
#include <linux/config.h>
+#include <linux/mc146818rtc.h>
+
+#include <asm/dec21285.h>
#include <asm/leds.h>
#include <asm/system.h>
-#include <linux/mc146818rtc.h>
-extern __inline__ unsigned long gettimeoffset (void)
+static int rtc_base;
+static unsigned long (*gettimeoffset)(void);
+static int (*set_rtc_mmss)(unsigned long nowtime);
+static long last_rtc_update = 0; /* last time the cmos clock got updated */
+
+#ifdef CONFIG_LEDS
+static void do_leds(void)
+{
+ static unsigned int count = 50;
+ static int last_pid;
+
+ if (current->pid != last_pid) {
+ last_pid = current->pid;
+ if (last_pid)
+ leds_event(led_idle_end);
+ else
+ leds_event(led_idle_start);
+ }
+
+ if (--count == 0) {
+ count = 50;
+ leds_event(led_timer);
+ }
+}
+#else
+#define do_leds()
+#endif
+
+#define mSEC_10_from_14 ((14318180 + 100) / 200)
+
+static unsigned long isa_gettimeoffset(void)
+{
+ int count;
+
+ static int count_p = (mSEC_10_from_14/6); /* for the first call after boot */
+ static unsigned long jiffies_p = 0;
+
+ /*
+ * cache volatile jiffies temporarily; we have IRQs turned off.
+ */
+ unsigned long jiffies_t;
+
+ /* timer count may underflow right here */
+ outb_p(0x00, 0x43); /* latch the count ASAP */
+
+ count = inb_p(0x40); /* read the latched count */
+
+ /*
+ * We do this guaranteed double memory access instead of a _p
+ * postfix in the previous port access. Wheee, hackady hack
+ */
+ jiffies_t = jiffies;
+
+ count |= inb_p(0x40) << 8;
+
+ /* Detect timer underflows. If we haven't had a timer tick since
+ the last time we were called, and time is apparently going
+ backwards, the counter must have wrapped during this routine. */
+ if ((jiffies_t == jiffies_p) && (count > count_p))
+ count -= (mSEC_10_from_14/6);
+ else
+ jiffies_p = jiffies_t;
+
+ count_p = count;
+
+ count = (((mSEC_10_from_14/6)-1) - count) * tick;
+ count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6);
+
+ return count;
+}
+
+static void isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ if (machine_is_netwinder())
+ do_leds();
+
+ do_timer(regs);
+
+ /* If we have an externally synchronized linux clock, then update
+ * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+ * called as close as possible to 500 ms before the new second starts.
+ */
+ if ((time_status & STA_UNSYNC) == 0 &&
+ xtime.tv_sec > last_rtc_update + 660 &&
+ xtime.tv_usec > 50000 - (tick >> 1) &&
+ xtime.tv_usec < 50000 + (tick >> 1)) {
+ if (set_rtc_mmss(xtime.tv_sec) == 0)
+ last_rtc_update = xtime.tv_sec;
+ else
+ last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+ }
+}
+
+static struct irqaction isa_timer_irq = {
+ isa_timer_interrupt,
+ 0,
+ 0,
+ "timer",
+ NULL,
+ NULL
+};
+
+__initfunc(static unsigned long
+get_isa_cmos_time(void))
+{
+ unsigned int year, mon, day, hour, min, sec;
+ int i;
+
+ // check to see if the RTC makes sense.....
+ if ((CMOS_READ(RTC_VALID) & RTC_VRT) == 0)
+ return mktime(1970, 1, 1, 0, 0, 0);
+
+ /* The Linux interpretation of the CMOS clock register contents:
+ * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+ * RTC registers show the second which has precisely just started.
+ * Let's hope other operating systems interpret the RTC the same way.
+ */
+ /* read RTC exactly on falling edge of update flag */
+ for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
+ if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+ break;
+
+ for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
+ if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+ break;
+
+ do { /* Isn't this overkill ? UIP above should guarantee consistency */
+ sec = CMOS_READ(RTC_SECONDS);
+ min = CMOS_READ(RTC_MINUTES);
+ hour = CMOS_READ(RTC_HOURS);
+ day = CMOS_READ(RTC_DAY_OF_MONTH);
+ mon = CMOS_READ(RTC_MONTH);
+ year = CMOS_READ(RTC_YEAR);
+ } while (sec != CMOS_READ(RTC_SECONDS));
+
+ if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+ }
+ if ((year += 1900) < 1970)
+ year += 100;
+ return mktime(year, mon, day, hour, min, sec);
+}
+
+static int
+set_isa_cmos_time(unsigned long nowtime)
+{
+ int retval = 0;
+ int real_seconds, real_minutes, cmos_minutes;
+ unsigned char save_control, save_freq_select;
+
+ save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
+ CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+ save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
+ CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+ cmos_minutes = CMOS_READ(RTC_MINUTES);
+ if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+ BCD_TO_BIN(cmos_minutes);
+
+ /*
+ * since we're only adjusting minutes and seconds,
+ * don't interfere with hour overflow. This avoids
+ * messing with unknown time zones but requires your
+ * RTC not to be off by more than 15 minutes
+ */
+ real_seconds = nowtime % 60;
+ real_minutes = nowtime / 60;
+ if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+ real_minutes += 30; /* correct for half hour time zone */
+ real_minutes %= 60;
+
+ if (abs(real_minutes - cmos_minutes) < 30) {
+ if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+ BIN_TO_BCD(real_seconds);
+ BIN_TO_BCD(real_minutes);
+ }
+ CMOS_WRITE(real_seconds,RTC_SECONDS);
+ CMOS_WRITE(real_minutes,RTC_MINUTES);
+ } else
+ retval = -1;
+
+ /* The following flags have to be released exactly in this order,
+ * otherwise the DS12887 (popular MC146818A clone with integrated
+ * battery and quartz) will not reset the oscillator and will not
+ * update precisely 500 ms later. You won't find this mentioned in
+ * the Dallas Semiconductor data sheets, but who believes data
+ * sheets anyway ... -- Markus Kuhn
+ */
+ CMOS_WRITE(save_control, RTC_CONTROL);
+ CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+
+ return retval;
+}
+
+
+
+static unsigned long __ebsa285_text timer1_gettimeoffset (void)
{
unsigned long value = LATCH - *CSR_TIMER1_VALUE;
return (tick * value) / LATCH;
}
-extern __inline__ int reset_timer (void)
+static void __ebsa285_text timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
*CSR_TIMER1_CLR = 0;
-#ifdef CONFIG_LEDS
- /*
- * Do the LEDs thing on EBSA-285 hardware.
+ /* Do the LEDs things on non-CATS hardware.
*/
- if (!machine_is_cats()) {
- static unsigned int count = 50;
- static int last_pid;
-
- if (current->pid != last_pid) {
- last_pid = current->pid;
- if (last_pid)
- leds_event(led_idle_end);
- else
- leds_event(led_idle_start);
- }
-
- if (--count == 0) {
- count = 50;
- leds_event(led_timer);
- }
+ if (!machine_is_cats())
+ do_leds();
+
+ do_timer(regs);
+
+ /* If we have an externally synchronized linux clock, then update
+ * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+ * called as close as possible to 500 ms before the new second starts.
+ */
+ if ((time_status & STA_UNSYNC) == 0 &&
+ xtime.tv_sec > last_rtc_update + 660 &&
+ xtime.tv_usec > 50000 - (tick >> 1) &&
+ xtime.tv_usec < 50000 + (tick >> 1)) {
+ if (set_rtc_mmss(xtime.tv_sec) == 0)
+ last_rtc_update = xtime.tv_sec;
+ else
+ last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
}
-#endif
-
- return 1;
}
-/*
- * We don't have a RTC to update!
- */
-#define update_rtc()
+static struct irqaction __ebsa285_data timer1_irq = {
+ timer1_interrupt,
+ 0,
+ 0,
+ "timer",
+ NULL,
+ NULL
+};
+
+static int
+set_dummy_time(unsigned long secs)
+{
+ return 1;
+}
/*
* Set up timer interrupt, and return the current time in seconds.
*/
-extern __inline__ unsigned long setup_timer (void)
+extern __inline__ void setup_timer(void)
{
- int year, mon, day, hour, min, sec;
+ switch(machine_arch_type) {
+ case MACH_TYPE_CO285:
+ /*
+ * Add-in 21285s shouldn't access the RTC
+ */
+ rtc_base = 0;
+ break;
- /*
- * Default the date to 1 Jan 1970 0:0:0
- */
- year = 1970; mon = 1; day = 1;
- hour = 0; min = 0; sec = 0;
+ default:
+ rtc_base = 0x70;
+ break;
+ }
+
+ if (rtc_base) {
+ int reg_d, reg_b;
- *CSR_TIMER1_CLR = 0;
- *CSR_TIMER1_LOAD = LATCH;
- *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
+ reg_d = CMOS_READ(RTC_REG_D);
- if (machine_is_cats())
- {
- int i;
/*
- * Read the real time from the Dallas chip. (Code borrowed
- * from arch/i386/kernel/time.c).
+ * make sure the divider is set
*/
-
- /* The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
+ CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_REG_A);
+
+ /*
+ * Set control reg B
+ * (24 hour mode, update enabled)
*/
+ reg_b = CMOS_READ(RTC_REG_B) & 0x7f;
+ reg_b |= 2;
+ CMOS_WRITE(reg_b, RTC_REG_B);
- /* read RTC exactly on falling edge of update flag */
- for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
- break;
- for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
- if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
- break;
- do { /* Isn't this overkill ? UIP above should guarantee consistency */
- sec = CMOS_READ(RTC_SECONDS);
- min = CMOS_READ(RTC_MINUTES);
- hour = CMOS_READ(RTC_HOURS);
- day = CMOS_READ(RTC_DAY_OF_MONTH);
- mon = CMOS_READ(RTC_MONTH);
- year = CMOS_READ(RTC_YEAR);
- } while (sec != CMOS_READ(RTC_SECONDS));
- if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
- {
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
- }
- if ((year += 1900) < 1970)
- year += 100;
+ if ((CMOS_READ(RTC_REG_A) & 0x7f) == RTC_REF_CLCK_32KHZ &&
+ CMOS_READ(RTC_REG_B) == reg_b) {
+
+ /*
+ * Check the battery
+ */
+ if ((reg_d & 0x80) == 0)
+ printk(KERN_WARNING "RTC: *** warning: CMOS battery bad\n");
+
+ xtime.tv_sec = get_isa_cmos_time();
+ set_rtc_mmss = set_isa_cmos_time;
+ } else
+ rtc_base = 0;
}
- return mktime(year, mon, day, hour, min, sec);
+ if (!rtc_base) {
+ /*
+ * Default the date to 1 Jan 1970 0:0:0
+ */
+ xtime.tv_sec = mktime(1970, 1, 1, 0, 0, 0);
+ set_rtc_mmss = set_dummy_time;
+ }
+
+ if (machine_is_ebsa285()) {
+ gettimeoffset = timer1_gettimeoffset;
+
+ *CSR_TIMER1_CLR = 0;
+ *CSR_TIMER1_LOAD = LATCH;
+ *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
+
+ setup_arm_irq(IRQ_TIMER1, &timer1_irq);
+ } else {
+ /* enable PIT timer */
+ /* set for periodic (4) and LSB/MSB write (0x30) */
+ outb(0x34, 0x43);
+ outb((mSEC_10_from_14/6) & 0xFF, 0x40);
+ outb((mSEC_10_from_14/6) >> 8, 0x40);
+
+ gettimeoffset = isa_gettimeoffset;
+
+ setup_arm_irq(IRQ_ISA_TIMER, &isa_timer_irq);
+ }
}
*/
/*
- * On the EBSA, the clock ticks at weird rates.
- * This is therefore not used to calculate the
- * divisor.
+ * On EBSA285 boards, the clock runs at 50MHz and is
+ * divided by a 4-bit prescaler. Other boards use an
+ * ISA derived timer, and this is unused.
*/
#define CLOCK_TICK_RATE (50000000 / 16)
/*
- * linux/include/asm-arm/arch-ebsa110/uncompress.h
+ * linux/include/asm-arm/arch-ebsa285/uncompress.h
*
* Copyright (C) 1996,1997,1998 Russell King
*/
+/*
+ * Note! This could cause problems on the NetWinder
+ */
#define BASE 0x42000160
static __inline__ void putc(char c)
/*
* linux/include/asm-arm/arch-nexuspci/a.out.h
*
- * Copyright (C) 1996 Russell King
+ * Copyright (C) 1996-1999 Russell King
*/
-
#ifndef __ASM_ARCH_A_OUT_H
#define __ASM_ARCH_A_OUT_H
-#ifdef __KERNEL__
-#define STACK_TOP ((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#endif
+#include <asm/arch/memory.h>
+
+#define STACK_TOP \
+ ((current->personality == PER_LINUX_32BIT) ? \
+ TASK_SIZE : 0x04000000)
#endif
/*
* linux/include/asm-arm/arch-nexuspci/hardware.h
*
- * Copyright (C) 1998 Philip Blundell
+ * Copyright (C) 1998-1999 Philip Blundell
*
* This file contains the hardware definitions of the Nexus PCI card.
*/
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
/* Logical Physical
* 0xfff00000 0x10000000 SCC2691 DUART
* 0xffc00000 0x60000000 PLX registers
* 0xfe000000 0x70000000 PCI I/O
*/
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-/*
- * What hardware must be present
- */
-
-#define HAS_PCIO
-#define PCIO_BASE 0xfe000000
/*
* Mapping areas
*/
-#define IO_BASE 0xfe000000
+#define PCIO_BASE 0xfe000000
+#define FLUSH_BASE 0xdf000000
/*
* RAM definitions
*/
#define RAM_BASE 0x40000000
-#define KERNTOPHYS(a) ((unsigned long)(&a))
#define FLUSH_BASE_PHYS 0x40000000
#endif
#include <asm/io.h>
+#define fixup_irq(x) (x)
+
#define INTCONT 0xffe00000
extern unsigned long soft_irq_mask;
--- /dev/null
+/*
+ * linux/include/asm-arm/arch-nexuspci/memory.h
+ *
+ * Copyright (c) 1997, 1998 Philip Blundell.
+ * Copyright (c) 1999 Russell King
+ *
+ */
+#ifndef __ASM_ARCH_MMU_H
+#define __ASM_ARCH_MMU_H
+
+/*
+ * Task size: 3GB
+ */
+#define TASK_SIZE (0xc0000000UL)
+
+/*
+ * Page offset: 3GB
+ */
+#define PAGE_OFFSET (0xc0000000UL)
+
+/*
+ * On NexusPCI, the DRAM is contiguous
+ */
+#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + 0x40000000)
+#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - 0x40000000)
+#define __virt_to_phys__is_a_macro
+#define __phys_to_virt__is_a_macro
+
+/*
+ * On the PCI bus the DRAM appears at address 0
+ */
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x) ((x) - PAGE_OFFSET)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x) ((x) + PAGE_OFFSET)
+
+#endif
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-nexuspci/mmap.h
- *
- * Copyright (C) 1998 Philip Blundell
- */
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-nexuspci/mmu.h
- *
- * Copyright (c) 1997, 1998 Philip Blundell.
- *
- */
-#ifndef __ASM_ARCH_MMU_H
-#define __ASM_ARCH_MMU_H
-
-/*
- * On NexusPCI, the DRAM is contiguous
- */
-#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + 0x40000000)
-#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - 0x40000000)
-#define __virt_to_phys__is_a_macro
-#define __phys_to_virt__is_a_macro
-
-/*
- * On the PCI bus the DRAM appears at address 0
- */
-#define __virt_to_bus__is_a_macro
-#define __virt_to_bus(x) ((x) - PAGE_OFFSET)
-#define __bus_to_virt__is_a_macro
-#define __bus_to_virt(x) ((x) + PAGE_OFFSET)
-
-#endif
/*
- * linux/include/asm-arm/arch-ebsa110/processor.h
+ * linux/include/asm-arm/arch-nexuspci/processor.h
* from linux/include/asm-arm/arch-ebsa110/processor.h
*
- * Copyright (C) 1996,1997,1998 Russell King
+ * Copyright (C) 1996-1999 Russell King
+ *
+ * Changelog:
+ * 21-Mar-1999 RMK Added asm/arch/memory.h
*/
#ifndef __ASM_ARCH_PROCESSOR_H
#define __ASM_ARCH_PROCESSOR_H
+#include <asm/arch/memory.h>
+
/*
* Bus types
*/
#define MCA_bus 0
#define MCA_bus__is_a_macro /* for versions in ksyms.c */
-/*
- * User space: 3GB
- */
-#define TASK_SIZE (0xc0000000UL)
-
/* This decides where the kernel will search for a free chunk of vm
* space during mmap's.
*/
#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#define INIT_MMAP \
-{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
-
#endif
return 0;
}
-extern __inline__ int reset_timer (void)
+static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
static int count = 50;
+
writeb(0x90, UART_BASE + 8);
- if (--count == 0)
- {
+
+ if (--count == 0) {
static int state = 1;
state ^= 1;
writeb(0x1a + state, INTCONT);
count = 50;
}
+
readb(UART_BASE + 0x14);
readb(UART_BASE + 0x14);
readb(UART_BASE + 0x14);
readb(UART_BASE + 0x14);
readb(UART_BASE + 0x14);
readb(UART_BASE + 0x14);
- return 1;
+
+ do_timer(regs);
}
-extern __inline__ unsigned long setup_timer (void)
+static struct irqaction timerirq = {
+ timer_interrupt,
+ 0,
+ 0,
+ "timer",
+ NULL,
+ NULL
+};
+
+extern __inline__ void setup_timer(void)
{
int tick = 3686400 / 16 / 2 / 100;
+
writeb(tick & 0xff, UART_BASE + 0x1c);
writeb(tick >> 8, UART_BASE + 0x18);
writeb(0x80, UART_BASE + 8);
writeb(0x10, UART_BASE + 0x14);
+
/*
* Default the date to 1 Jan 1970 0:0:0
* You will have to run a time daemon to set the
* clock correctly at bootup
*/
- return mktime(1970, 1, 1, 0, 0, 0);
+ xtime.tv_sec = mktime(1970, 1, 1, 0, 0, 0);
+
+ setup_arm_irq(IRQ_TIMER, &timerirq);
}
/*
* linux/include/asm-arm/arch-rpc/a.out.h
*
- * Copyright (C) 1996 Russell King
+ * Copyright (C) 1996-1999 Russell King
*/
-
#ifndef __ASM_ARCH_A_OUT_H
#define __ASM_ARCH_A_OUT_H
-#ifdef __KERNEL__
-#define STACK_TOP ((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#endif
+#include <asm/arch/memory.h>
+
+#define STACK_TOP \
+ ((current->personality == PER_LINUX_32BIT) ? \
+ TASK_SIZE : 0x04000000)
#endif
/*
* linux/include/asm-arm/arch-rpc/hardware.h
*
- * Copyright (C) 1996 Russell King.
+ * Copyright (C) 1996-1999 Russell King.
*
* This file contains the hardware definitions of the RiscPC series machines.
*/
-
#ifndef __ASM_ARCH_HARDWARE_H
#define __ASM_ARCH_HARDWARE_H
+#include <asm/arch/memory.h>
+
/*
* What hardware must be present
*/
#define HAS_IOMD
-#include <asm/iomd.h>
#define HAS_VIDC20
/* Hardware addresses of major areas.
#define EASI_SIZE 0x08000000 /* EASI I/O */
#define EASI_START 0x08000000
-#define EASI_BASE 0xe8000000
+#define EASI_BASE 0xe5000000
#define IO_START 0x03000000 /* I/O */
#define IO_SIZE 0x01000000
#define SCREEN1_END 0xd8000000
#define SCREEN1_BASE 0xd0000000
+#define FLUSH_BASE 0xdf000000
+
#ifndef __ASSEMBLER__
#define IO_VIDC_AUDIO_BASE 0x80140000
#define IO_VIDC_BASE 0x80100000
#define IO_IOMD_BASE 0x80080000
+#define IOC_BASE 0x80080000
-#define IO_EC_EASI_BASE 0x82000000
+#define IO_EC_EASI_BASE 0x81400000
#define IO_EC_IOC4_BASE 0x8009c000
#define IO_EC_IOC_BASE 0x80090000
#define IO_EC_MEMC8_BASE 0x8000ac00
*/
#define EXPMASK_BASE ((volatile unsigned char *)0xe0360000)
#define IOEB_BASE ((volatile unsigned char *)0xe0350050)
-#define IOC_BASE ((volatile unsigned char *)0xe0200000)
#define PCIO_FLOPPYDMABASE ((volatile unsigned char *)0xe002a000)
#define PCIO_BASE 0xe0010000
* Offsets from RAM base
*/
#define PARAMS_OFFSET 0x0100
-#define KERNEL_OFFSET 0x8000
/*
* RAM definitions
*/
-#define MAPTOPHYS(x) (x)
-#define KERNTOPHYS(x) ((unsigned long)(&x))
#define GET_MEMORY_END(p) (PAGE_OFFSET + p->u1.s.page_size * \
(p->u1.s.pages_in_bank[0] + \
p->u1.s.pages_in_bank[1] + \
p->u1.s.pages_in_bank[2] + \
p->u1.s.pages_in_bank[3]))
-#define KERNEL_BASE (PAGE_OFFSET + KERNEL_OFFSET)
#define PARAMS_BASE (PAGE_OFFSET + PARAMS_OFFSET)
#define Z_PARAMS_BASE (RAM_START + PARAMS_OFFSET)
-#define SAFE_ADDR 0x00000000 /* ROM */
+#define FLUSH_BASE_PHYS 0x00000000 /* ROM */
#else
* 10-10-1996 RMK Brought up to date with arch-sa110eval
* 22-08-1998 RMK Restructured IRQ routines
*/
+#include <asm/iomd.h>
+
+#define fixup_irq(x) (x)
static void rpc_mask_irq_ack_a(unsigned int irq)
{
#define NR_SCANCODES 128
-extern int ps2kbd_translate(unsigned char scancode, unsigned char *keycode_p, char *up_flag_p);
extern void ps2kbd_leds(unsigned char leds);
extern void ps2kbd_init_hw(void);
extern unsigned char ps2kbd_sysrq_xlate[NR_SCANCODES];
#define kbd_setkeycode(sc,kc) (-EINVAL)
#define kbd_getkeycode(sc) (-EINVAL)
-/* Prototype: int kbd_translate(scancode, *keycode, *up_flag, raw_mode)
- * Returns : 0 to ignore scancode, *keycode set to keycode, *up_flag
- * set to 0200 if scancode indicates release
- */
-#ifdef NEW_KEYBOARD
-#define kbd_translate(sc, kcp, ufp, rm) ps2kbd_translate(sc, kcp, ufp)
-#else
-#define kbd_translate(sc, kcp, rm) ({ unsigned int up_flag; ps2kbd_translate(sc, kcp, &up_flag); })
-#endif
+#define kbd_translate(sc, kcp, rm) ({ *(kcp) = (sc); 1; })
#define kbd_unexpected_up(kc) (0200)
#define kbd_leds(leds) ps2kbd_leds(leds)
#define kbd_init_hw() ps2kbd_init_hw()
--- /dev/null
+/*
+ * linux/include/asm-arm/arch-rpc/memory.h
+ *
+ * Copyright (c) 1996,1997,1998 Russell King.
+ *
+ * Changelog:
+ * 20-Oct-1996 RMK Created
+ * 31-Dec-1997 RMK Fixed definitions to reduce warnings
+ * 11-Jan-1998 RMK Uninlined to reduce hits on cache
+ * 08-Feb-1998 RMK Added __virt_to_bus and __bus_to_virt
+ * 21-Mar-1999 RMK Renamed to memory.h
+ * RMK Added TASK_SIZE and PAGE_OFFSET
+ */
+#ifndef __ASM_ARCH_MMU_H
+#define __ASM_ARCH_MMU_H
+
+/*
+ * Task size: 3GB
+ */
+#define TASK_SIZE (0xc0000000UL)
+
+/*
+ * Page offset: 3GB
+ */
+#define PAGE_OFFSET (0xc0000000UL)
+
+#ifndef __ASSEMBLY__
+extern unsigned long __virt_to_phys(unsigned long vpage);
+extern unsigned long __phys_to_virt(unsigned long ppage);
+#endif
+
+/*
+ * These are exactly the same on the RiscPC as the
+ * physical memory view.
+ */
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x) __virt_to_phys(x)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x) __phys_to_virt(x)
+
+#endif
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-rpc/mmu.h
- *
- * Copyright (c) 1996,1997,1998 Russell King.
- *
- * Changelog:
- * 20-10-1996 RMK Created
- * 31-12-1997 RMK Fixed definitions to reduce warnings
- * 11-01-1998 RMK Uninlined to reduce hits on cache
- * 08-02-1998 RMK Added __virt_to_bus and __bus_to_virt
- */
-#ifndef __ASM_ARCH_MMU_H
-#define __ASM_ARCH_MMU_H
-
-extern unsigned long __virt_to_phys(unsigned long vpage);
-extern unsigned long __phys_to_virt(unsigned long ppage);
-
-/*
- * These are exactly the same on the RiscPC as the
- * physical memory view.
- */
-#define __virt_to_bus__is_a_macro
-#define __virt_to_bus(x) __virt_to_phys(x)
-#define __bus_to_virt__is_a_macro
-#define __bus_to_virt(x) __phys_to_virt(x)
-
-#endif
+++ /dev/null
-/*
- * Dummy oldlatches.h
- *
- * Copyright (C) 1996 Russell King
- */
-
-#ifdef __need_oldlatches
-#error "Old latches not present in this (rpc) machine"
-#endif
/*
* linux/include/asm-arm/arch-rpc/processor.h
*
- * Copyright (c) 1996 Russell King.
+ * Copyright (c) 1996-1999 Russell King.
*
* Changelog:
- * 10-09-1996 RMK Created
+ * 10-Sep-1996 RMK Created
+ * 21-Mar-1999 RMK Added asm/arch/memory.h
*/
#ifndef __ASM_ARCH_PROCESSOR_H
#define __ASM_ARCH_PROCESSOR_H
+#include <asm/arch/memory.h>
+
/*
* Bus types
*/
#define MCA_bus 0
#define MCA_bus__is_a_macro /* for versions in ksyms.c */
-/*
- * User space: 3GB
- */
-#define TASK_SIZE (0xc0000000UL)
-
/* This decides where the kernel will search for a free chunk of vm
* space during mmap's.
*/
#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#define INIT_MMAP \
-{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
-
#endif
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
-#include <asm/proc-fns.h>
+#include <asm/iomd.h>
#define arch_reset(mode) { \
extern void ecard_reset (int card); \
* 10-Oct-1996 RMK Brought up to date with arch-sa110eval
* 04-Dec-1997 RMK Updated for new arch/arm/time.c
*/
+#include <asm/iomd.h>
+
+static long last_rtc_update = 0; /* last time the cmos clock got updated */
extern __inline__ unsigned long gettimeoffset (void)
{
return offset;
}
-/*
- * No need to reset the timer at every irq
- */
-#define reset_timer() 1
+extern int iic_control(unsigned char, int, char *, int);
-/*
- * Updating of the RTC. We don't currently write the time to the
- * CMOS clock.
- */
-#define update_rtc()
+static int set_rtc_time(unsigned long nowtime)
+{
+ char buf[5], ctrl;
+
+ if (iic_control(0xa1, 0, &ctrl, 1) != 0)
+ printk("RTC: failed to read control reg\n");
+
+ /*
+ * Reset divider
+ */
+ ctrl |= 0x80;
+
+ if (iic_control(0xa0, 0, &ctrl, 1) != 0)
+ printk("RTC: failed to stop the clock\n");
+
+ /*
+ * We only set the time - we don't set the date.
+ * This means that there is the possibility once
+ * a day for the correction to disrupt the date.
+ * We really ought to write the time and date, or
+ * nothing at all.
+ */
+ buf[0] = 0;
+ buf[1] = nowtime % 60; nowtime /= 60;
+ buf[2] = nowtime % 60; nowtime /= 60;
+ buf[3] = nowtime % 24;
+
+ BIN_TO_BCD(buf[1]);
+ BIN_TO_BCD(buf[2]);
+ BIN_TO_BCD(buf[3]);
+
+ if (iic_control(0xa0, 1, buf, 4) != 0)
+ printk("RTC: Failed to set the time\n");
+
+ /*
+ * Re-enable divider
+ */
+ ctrl &= ~0x80;
+
+ if (iic_control(0xa0, 0, &ctrl, 1) != 0)
+ printk("RTC: failed to start the clock\n");
+
+ return 0;
+}
+
+extern __inline__ unsigned long get_rtc_time(void)
+{
+ unsigned int year, i;
+ char buf[8];
+
+ /*
+ * The year is not part of the RTC counter
+ * registers, and is stored in RAM. This
+ * means that it will not be automatically
+ * updated.
+ */
+ if (iic_control(0xa1, 0xc0, buf, 1) != 0)
+ printk("RTC: failed to read the year\n");
+
+ /*
+ * If the year is before 1970, then the year
+ * is actually 100 in advance. This gives us
+ * a year 2070 bug...
+ */
+ year = 1900 + buf[0];
+ if (year < 1970)
+ year += 100;
+
+ /*
+ * Read the time and date in one go - this
+ * will ensure that we don't get any effects
+ * due to carry (the RTC latches the counters
+ * during a read).
+ */
+ if (iic_control(0xa1, 2, buf, 5) != 0) {
+ printk("RTC: failed to read the time and date\n");
+ memset(buf, 0, sizeof(buf));
+ }
+
+ /*FIXME:
+ * This doesn't seem to work. Does RISC OS
+ * actually use the RTC year? It doesn't
+ * seem to. In that case, how does it update
+ * the CMOS year?
+ */
+ /*year += (buf[3] >> 6) & 3;*/
+
+ /*
+ * The RTC combines years with date and weekday
+ * with month. We need to mask off this extra
+ * information before converting the date to
+ * binary.
+ */
+ buf[4] &= 0x1f;
+ buf[3] &= 0x3f;
+printk("Year %4d mon %02X day %02X hour %02X min %02X sec %02X\n", year, buf[4], buf[3], buf[2], buf[1], buf[0]);
+ for (i = 0; i < 5; i++)
+ BCD_TO_BIN(buf[i]);
+
+ return mktime(year, buf[4], buf[3], buf[2], buf[1], buf[0]);
+}
+
+static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ do_timer(regs);
+
+ /* If we have an externally synchronized linux clock, then update
+ * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+ * called as close as possible to 500 ms before the new second starts.
+ */
+ if ((time_status & STA_UNSYNC) == 0 &&
+ xtime.tv_sec > last_rtc_update + 660 &&
+ xtime.tv_usec >= 50000 - (tick >> 1) &&
+ xtime.tv_usec < 50000 + (tick >> 1)) {
+ if (set_rtc_time(xtime.tv_sec) == 0)
+ last_rtc_update = xtime.tv_sec;
+ else
+ last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+ }
+}
+
+static struct irqaction timerirq = {
+ timer_interrupt,
+ 0,
+ 0,
+ "timer",
+ NULL,
+ NULL
+};
/*
* Set up timer interrupt, and return the current time in seconds.
*/
-extern __inline__ unsigned long setup_timer (void)
+extern __inline__ void setup_timer(void)
{
- extern int iic_control (unsigned char, int, char *, int);
- unsigned int year, mon, day, hour, min, sec;
- char buf[8];
-
outb(LATCH & 255, IOMD_T0LTCHL);
outb(LATCH >> 8, IOMD_T0LTCHH);
outb(0, IOMD_T0GO);
- iic_control (0xa0, 0xc0, buf, 1);
- year = buf[0];
- if ((year += 1900) < 1970)
- year += 100;
+ xtime.tv_sec = get_rtc_time();
- iic_control (0xa0, 2, buf, 5);
- mon = buf[4] & 0x1f;
- day = buf[3] & 0x3f;
- hour = buf[2];
- min = buf[1];
- sec = buf[0];
- BCD_TO_BIN(mon);
- BCD_TO_BIN(day);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(min);
- BCD_TO_BIN(sec);
-
- return mktime(year, mon, day, hour, min, sec);
+ setup_arm_irq(IRQ_TIMER, &timerirq);
}
*/
#define VIDMEM ((char *)SCREEN_START)
-#include "../arch/arm/drivers/char/font.h"
#include <asm/hardware.h>
#include <asm/io.h>
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-ebsa110/a.out.h
- *
- * Copyright (C) 1996 Russell King
- */
-
-#ifndef __ASM_ARCH_A_OUT_H
-#define __ASM_ARCH_A_OUT_H
-
-#ifdef __KERNEL__
-#define STACK_TOP ((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#endif
-
-#endif
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-ebsa110/dma.h
- *
- * Architecture DMA routes
- *
- * Copyright (C) 1997.1998 Russell King
- */
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-/*
- * This is the maximum DMA address that can be DMAd to.
- * There should not be more than (0xd0000000 - 0xc0000000)
- * bytes of RAM.
- */
-#define MAX_DMA_ADDRESS 0xd0000000
-#define MAX_DMA_CHANNELS 8
-
-#endif /* _ASM_ARCH_DMA_H */
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-vnc/hardware.h
- *
- * Copyright (C) 1998 Corel Computer/Russell King.
- *
- * This file contains the hardware definitions of the VNC.
- */
-
-/* Logical Physical
- * 0xffe00000 0x7c000000 PCI I/O space
- * 0xfe000000 0x42000000 CSR
- * 0xfd000000 0x78000000 Outbound write flush
- * 0xfc000000 0x79000000 PCI IACK/special space
- * 0xf9000000 0x7a000000 PCI Config type 1
- * 0xf8000000 0x7b000000 PCI Config type 0
- *
- */
-
-#include <asm/dec21285.h>
-
-#define IO_BASE_ARM_CSR 0xfe000000
-#define PCI_IACK 0xfc000000
-
-/* LEDs */
-#define XBUS_LEDS ((volatile unsigned char *)0xfff12000)
-#define XBUS_LED_AMBER (1 << 0)
-#define XBUS_LED_GREEN (1 << 1)
-#define XBUS_LED_RED (1 << 2)
-#define XBUS_LED_TOGGLE (1 << 8)
-
-/* PIC irq control */
-#define PIC_LO 0x20
-#define PIC_MASK_LO 0x21
-#define PIC_HI 0xA0
-#define PIC_MASK_HI 0xA1
-
-#define IO_END 0xffffffff
-#define IO_BASE 0xe0000000
-#define IO_SIZE (IO_END - IO_BASE)
-
-#define HAS_PCIO
-#define PCIO_BASE 0xffe00000
-
-#define KERNTOPHYS(a) ((unsigned long)(&a))
-
-//#define PARAMS_OFFSET 0x0100
-//#define PARAMS_BASE (PAGE_OFFSET + PARAMS_OFFSET)
-
-#define FLUSH_BASE_PHYS 0x50000000
-
-/* GPIO pins */
-#define GPIO_CCLK 0x800
-#define GPIO_DSCLK 0x400
-#define GPIO_E2CLK 0x200
-#define GPIO_IOLOAD 0x100
-#define GPIO_RED_LED 0x080
-#define GPIO_WDTIMER 0x040
-#define GPIO_DATA 0x020
-#define GPIO_IOCLK 0x010
-#define GPIO_DONE 0x008
-#define GPIO_FAN 0x004
-#define GPIO_GREEN_LED 0x002
-#define GPIO_RESET 0x001
-
-/* CPLD pins */
-#define CPLD_DSRESET 8
-#define CPLD_UNMUTE 2
-
-#ifndef __ASSEMBLY__
-extern void gpio_modify_op(int mask, int set);
-extern void gpio_modify_io(int mask, int in);
-extern int gpio_read(void);
-extern void cpld_modify(int mask, int set);
-#endif
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-vnc/ide.h
- *
- * Copyright (c) 1998 Russell King
- *
- * Modifications:
- * 29-07-1998 RMK Major re-work of IDE architecture specific code
- */
-#include <asm/irq.h>
-
-/*
- * Set up a hw structure for a specified data port, control port and IRQ.
- * This should follow whatever the default interface uses.
- */
-static __inline__ void
-ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
-{
- ide_ioreg_t reg = (ide_ioreg_t) data_port;
- int i;
-
- memset(hw, 0, sizeof(*hw));
-
- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
- hw->io_ports[i] = reg;
- reg += 1;
- }
- hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
- hw->irq = irq;
-}
-
-/*
- * This registers the standard ports for this architecture with the IDE
- * driver.
- */
-static __inline__ void
-ide_init_default_hwifs(void)
-{
- hw_regs_t hw;
-
- ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, IRQ_HARDDISK);
- ide_register_hw(&hw, NULL);
-}
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-ebsa110/io.h
- *
- * Copyright (C) 1997,1998 Russell King
- *
- * Modifications:
- * 06-Dec-1997 RMK Created.
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-/*
- * This architecture does not require any delayed IO, and
- * has the constant-optimised IO
- */
-#undef ARCH_IO_DELAY
-
-/*
- * Dynamic IO functions - let the compiler
- * optimize the expressions
- */
-#define DECLARE_DYN_OUT(fnsuffix,instr,typ) \
-extern __inline__ void __out##fnsuffix (unsigned int value, unsigned int port) \
-{ \
- __asm__ __volatile__( \
- "str%?" ##instr## " %0, [%1, %2] @ out"###fnsuffix \
- : \
- : "r" (value), "r" (PCIO_BASE), typ (port)); \
-}
-
-#define DECLARE_DYN_IN(sz,fnsuffix,instr,typ) \
-extern __inline__ unsigned sz __in##fnsuffix (unsigned int port) \
-{ \
- unsigned long value; \
- __asm__ __volatile__( \
- "ldr%?" ##instr## " %0, [%1, %2] @ in"###fnsuffix \
- : "=&r" (value) \
- : "r" (PCIO_BASE), typ (port)); \
- return (unsigned sz)value; \
-}
-
-extern __inline__ unsigned int __ioaddr (unsigned int port) \
-{ \
- return (unsigned int)(PCIO_BASE + port); \
-}
-
-#define DECLARE_IO(sz,fnsuffix,instr,typ) \
- DECLARE_DYN_OUT(fnsuffix,instr,typ) \
- DECLARE_DYN_IN(sz,fnsuffix,instr,typ)
-
-DECLARE_IO(char,b,"b","Jr")
-DECLARE_IO(short,w,"h","r")
-DECLARE_IO(long,l,"","Jr")
-
-#undef DECLARE_IO
-#undef DECLARE_DYN_OUT
-#undef DECLARE_DYN_IN
-
-/*
- * Constant address IO functions
- *
- * These have to be macros for the 'J' constraint to work -
- * +/-4096 immediate operand.
- */
-#define __outbc(value,port) \
-({ \
- __asm__ __volatile__( \
- "strb %0, [%1, %2] @ outbc" \
- : \
- : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \
-})
-
-#define __inbc(port) \
-({ \
- unsigned char result; \
- __asm__ __volatile__( \
- "ldrb %0, [%1, %2] @ inbc" \
- : "=r" (result) \
- : "r" (PCIO_BASE), "Jr" (port)); \
- result; \
-})
-
-#define __outwc(value,port) \
-({ \
- __asm__ __volatile__( \
- "strh %0, [%1, %2] @ outwc" \
- : \
- : "r" (value), "r" (PCIO_BASE), "r" (port)); \
-})
-
-#define __inwc(port) \
-({ \
- unsigned short result; \
- __asm__ __volatile__( \
- "ldrh %0, [%1, %2] @ inwc" \
- : "=r" (result) \
- : "r" (PCIO_BASE), "r" (port)); \
- result & 0xffff; \
-})
-
-#define __outlc(value,port) \
-({ \
- __asm__ __volatile__( \
- "str %0, [%1, %2] @ outlc" \
- : \
- : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \
-})
-
-#define __inlc(port) \
-({ \
- unsigned long result; \
- __asm__ __volatile__( \
- "ldr %0, [%1, %2] @ inlc" \
- : "=r" (result) \
- : "r" (PCIO_BASE), "Jr" (port)); \
- result; \
-})
-
-#define __ioaddrc(port) \
-({ \
- unsigned long addr; \
- addr = PCIO_BASE + port; \
- addr; \
-})
-
-/*
- * Translated address IO functions
- *
- * IO address has already been translated to a virtual address
- */
-#define outb_t(v,p) \
- (*(volatile unsigned char *)(p) = (v))
-
-#define inb_t(p) \
- (*(volatile unsigned char *)(p))
-
-#define outl_t(v,p) \
- (*(volatile unsigned long *)(p) = (v))
-
-#define inl_t(p) \
- (*(volatile unsigned long *)(p))
-
-/*
- * This is not sufficient... (and it's a hack anyway)
- */
-static inline void writeb(unsigned char b, unsigned int addr)
-{
- *(volatile unsigned char *)(0xe0000000 + (addr)) = b;
-}
-
-static inline unsigned char readb(unsigned int addr)
-{
- return *(volatile unsigned char *)(0xe0000000 + (addr));
-}
-
-static inline void writew(unsigned short b, unsigned int addr)
-{
- *(volatile unsigned short *)(0xe0000000 + (addr)) = b;
-}
-
-static inline unsigned short readw(unsigned int addr)
-{
- return *(volatile unsigned short *)(0xe0000000 + (addr));
-}
-
-static inline void writel(unsigned long b, unsigned int addr)
-{
- *(volatile unsigned long *)(0xe0000000 + (addr)) = b;
-}
-
-static inline unsigned long readl(unsigned int addr)
-{
- return *(volatile unsigned long *)(0xe0000000 + (addr));
-}
-
-#endif
+++ /dev/null
-/*
- * include/asm-arm/arch-vnc/irq.h
- *
- * Copyright (C) 1998 Russell King
- *
- * Changelog:
- * 22-08-1998 RMK Restructured IRQ routines
- */
-
-#include <asm/dec21285.h>
-#include <asm/irq.h>
-
-/*
- * FootBridge IRQ translation table
- * Converts form our IRQ numbers into FootBridge masks (defined in irqs.h)
- */
-static int fb_irq_mask[16] = {
- 0,
- IRQ_MASK_SOFTIRQ,
- IRQ_MASK_UART_DEBUG,
- 0,
- IRQ_MASK_TIMER0,
- IRQ_MASK_TIMER1,
- IRQ_MASK_TIMER2,
- IRQ_MASK_WATCHDOG,
- IRQ_MASK_ETHER10,
- IRQ_MASK_ETHER100,
- IRQ_MASK_VIDCOMP,
- IRQ_MASK_EXTERN_IRQ,
- IRQ_MASK_DMA1,
- 0,
- 0,
- IRQ_MASK_PCI_ERR
-};
-
-static void vnc_mask_csr_irq(unsigned int irq)
-{
- *CSR_IRQ_DISABLE = fb_irq_mask[irq];
-}
-
-static void vnc_unmask_csr_irq(unsigned int irq)
-{
- *CSR_IRQ_ENABLE = fb_irq_mask[irq];
-}
-
-static void vnc_mask_pic_lo_irq(unsigned int irq)
-{
- unsigned int mask = 1 << (irq & 7);
-
- outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
-}
-
-static void vnc_mask_ack_pic_lo_irq(unsigned int irq)
-{
- unsigned int mask = 1 << (irq & 7);
-
- outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
- outb(0x20, PIC_LO);
-}
-
-static void vnc_unmask_pic_lo_irq(unsigned int irq)
-{
- unsigned int mask = ~(1 << (irq & 7));
-
- outb(inb(PIC_MASK_LO) & mask, PIC_MASK_LO);
-}
-
-static void vnc_mask_pic_hi_irq(unsigned int irq)
-{
- unsigned int mask = 1 << (irq & 7);
-
- outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
-}
-
-static void vnc_mask_ack_pic_hi_irq(unsigned int irq)
-{
- unsigned int mask = 1 << (irq & 7);
-
- outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
- outb(0x62, PIC_LO);
- outb(0x20, PIC_HI);
-}
-
-static void vnc_unmask_pic_hi_irq(unsigned int irq)
-{
- unsigned int mask = 1 << (irq & 7);
-
- outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI);
-}
-
-static void no_action(int irq, void *dev_id, struct pt_regs *regs)
-{
-}
-
-static struct irqaction irq_cascade = { no_action, 0, 0, "cascade", NULL, NULL };
-
-static __inline__ void irq_init_irq(void)
-{
- unsigned int irq;
-
- outb(0x11, PIC_LO);
- outb(0x10, PIC_MASK_LO);
- outb(0x04, PIC_MASK_LO);
- outb(1, PIC_MASK_LO);
-
- outb(0x11, PIC_HI);
- outb(0x18, PIC_MASK_HI);
- outb(0x02, PIC_MASK_HI);
- outb(1, PIC_MASK_HI);
-
- *CSR_IRQ_DISABLE = ~IRQ_MASK_EXTERN_IRQ;
- *CSR_IRQ_ENABLE = IRQ_MASK_EXTERN_IRQ;
- *CSR_FIQ_DISABLE = -1;
-
- for (irq = 0; irq < NR_IRQS; irq++) {
- irq_desc[irq].valid = 1;
- irq_desc[irq].probe_ok = 1;
-
- if (irq < 16) {
- irq_desc[irq].mask_ack = vnc_mask_csr_irq;
- irq_desc[irq].mask = vnc_mask_csr_irq;
- irq_desc[irq].unmask = vnc_unmask_csr_irq;
- } else if (irq < 24) {
-irq_desc[irq].probe_ok = 0;
- irq_desc[irq].mask_ack = vnc_mask_ack_pic_lo_irq;
- irq_desc[irq].mask = vnc_mask_pic_lo_irq;
- irq_desc[irq].unmask = vnc_unmask_pic_lo_irq;
- } else {
-irq_desc[irq].probe_ok = 0;
- irq_desc[irq].mask_ack = vnc_mask_ack_pic_hi_irq;
- irq_desc[irq].mask = vnc_mask_pic_hi_irq;
- irq_desc[irq].unmask = vnc_unmask_pic_hi_irq;
- }
- }
-
- irq_desc[0].probe_ok = 0;
- irq_desc[IRQ_SOFTIRQ].probe_ok = 0;
- irq_desc[IRQ_CONRX].probe_ok = 0;
- irq_desc[IRQ_CONTX].probe_ok = 0;
- irq_desc[IRQ_TIMER0].probe_ok = 0;
- irq_desc[IRQ_TIMER1].probe_ok = 0;
- irq_desc[IRQ_TIMER2].probe_ok = 0;
- irq_desc[IRQ_WATCHDOG].probe_ok = 0;
- irq_desc[IRQ_DMA1].probe_ok = 0;
- irq_desc[13].probe_ok = 0;
- irq_desc[14].probe_ok = 0;
- irq_desc[IRQ_PCI_ERR].probe_ok = 0;
- irq_desc[IRQ_PIC_HI].probe_ok = 0;
- irq_desc[29].probe_ok = 0;
- irq_desc[31].probe_ok = 0;
-
- outb(0xff, PIC_MASK_LO);
- outb(0xff, PIC_MASK_HI);
-
- setup_arm_irq(IRQ_PIC_HI, &irq_cascade);
-}
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-vnc/irqs.h
- *
- * Copyright (C) 1998 Russell King
- */
-
-#define NR_IRQS 32
-
-/*
- * This is a list of all interrupts that the 21285
- * can generate
- */
-#define IRQ_SOFTIRQ 1 /* from FB.1 */
-#define IRQ_CONRX 2 /* from FB.2 */
-#define IRQ_CONTX 3 /* from FB.3 */
-#define IRQ_TIMER0 4 /* from FB.4 */
-#define IRQ_TIMER1 5 /* from FB.5 */
-#define IRQ_TIMER2 6 /* from FB.6 */
-#define IRQ_WATCHDOG 7 /* from FB.7 */
-#define IRQ_ETHER10 8 /* from FB.8 */
-#define IRQ_ETHER100 9 /* from FB.9 */
-#define IRQ_VIDCOMP 10 /* from FB.10 */
-#define IRQ_EXTERN_IRQ 11 /* from FB.11: chain to IDE irq's */
-#define IRQ_DMA1 12 /* from future */
-#define IRQ_PCI_ERR 15 /* from FB.[28:31] */
-
-#define IRQ_TIMER4 16 /* from 553.0 */
-#define IRQ_KEYBOARD 17 /* from 553.1 */
-#define IRQ_PIC_HI 18 /* from 533.2: chained to 553.[8:15] */
-#define IRQ_UART2 19 /* from 553.3 */
-#define IRQ_UART 20 /* from 553.4 */
-#define IRQ_MOUSE 21 /* from 553.5 */
-#define IRQ_UART_IR 22 /* from 553.6 */
-#define IRQ_PRINTER 23 /* from 553.7 */
-#define IRQ_RTC_ALARM 24 /* from 553.8 */
-#define IRQ_POWERLOW 26 /* from 553.10 */
-#define IRQ_VGA 27 /* from 553.11 */
-#define IRQ_SOUND 28 /* from 553.12 */
-#define IRQ_HARDDISK 30 /* from 553.14 */
-
-/* These defines handle the translation from the above FB #defines
- * into physical bits for the FootBridge IRQ registers
- */
-#define IRQ_MASK_SOFTIRQ 0x00000002
-#define IRQ_MASK_UART_DEBUG 0x0000000C
-#define IRQ_MASK_TIMER0 0x00000010
-#define IRQ_MASK_TIMER1 0x00000020
-#define IRQ_MASK_TIMER2 0x00000040
-#define IRQ_MASK_WATCHDOG 0x00000080
-#define IRQ_MASK_ETHER10 0x00000100
-#define IRQ_MASK_ETHER100 0x00000200
-#define IRQ_MASK_VIDCOMP 0x00000400
-#define IRQ_MASK_EXTERN_IRQ 0x00000800
-#define IRQ_MASK_DMA1 0x00030000
-#define IRQ_MASK_PCI_ERR 0xf8800000
-
-/*
- * Now map them to the Linux interrupts
- */
-#undef IRQ_TIMER
-#define IRQ_TIMER IRQ_TIMER0
-#undef RTC_IRQ
-#define RTC_IRQ IRQ_RTC_ALARM
-#undef AUX_IRQ
-#define AUX_IRQ IRQ_MOUSE
-
-#define irq_cannonicalize(i) (i)
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-vnc/keyboard.h
- *
- * Keyboard driver definitions for VNC architecture
- *
- * (C) 1998 Russell King
- */
-
-#include <asm/irq.h>
-
-#define NR_SCANCODES 128
-
-#define KEYBOARD_IRQ IRQ_KEYBOARD
-
-extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int pckbd_getkeycode(unsigned int scancode);
-extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
- char raw_mode);
-extern char pckbd_unexpected_up(unsigned char keycode);
-extern void pckbd_leds(unsigned char leds);
-extern void pckbd_init_hw(void);
-extern unsigned char pckbd_sysrq_xlate[128];
-
-#define kbd_setkeycode pckbd_setkeycode
-#define kbd_getkeycode pckbd_getkeycode
-#define kbd_translate(sc, kcp, ufp, rm) ({ *ufp = sc & 0200; \
- pckbd_translate(sc & 0x7f, kcp, rm);})
-
-#define kbd_unexpected_up pckbd_unexpected_up
-#define kbd_leds pckbd_leds
-#define kbd_init_hw() pckbd_init_hw()
-#define kbd_sysrq_xlate pckbd_sysrq_xlate
-#define kbd_disable_irq()
-#define kbd_enable_irq()
-
-#define SYSRQ_KEY 0x54
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-ebsa110/mmap.h
- *
- * Copyright (C) 1996,1997,1998 Russell King
- */
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-ebsa110/mmu.h
- *
- * Copyright (c) 1996,1997,1998 Russell King.
- *
- * Changelog:
- * 20-10-1996 RMK Created
- * 31-12-1997 RMK Fixed definitions to reduce warnings
- */
-#ifndef __ASM_ARCH_MMU_H
-#define __ASM_ARCH_MMU_H
-
-/*
- * On ebsa, the dram is contiguous
- */
-#define __virt_to_phys__is_a_macro
-#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET)
-#define __phys_to_virt__is_a_macro
-#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET)
-
-#define __virt_to_bus__is_a_macro
-#define __virt_to_bus(x) (x - 0xe0000000)
-#define __bus_to_virt__is_a_macro
-#define __bus_to_virt(x) (x + 0xe0000000)
-
-#endif
+++ /dev/null
-/*
- * Dummy oldlatches.h
- *
- * Copyright (C) 1996 Russell King
- */
-
-#ifdef __need_oldlatches
-#error "Old latches not present in this (rpc) machine"
-#endif
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-vnc/param.h
- *
- * Copyright (C) 1996 Russell King
- * Copyright (C) 1998 Philip Blundell
- */
-
-#define HZ 100
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-vnc/processor.h
- *
- * Copyright (C) 1996,1997,1998 Russell King
- */
-
-#ifndef __ASM_ARCH_PROCESSOR_H
-#define __ASM_ARCH_PROCESSOR_H
-
-/*
- * Bus types
- */
-#define EISA_bus 0
-#define EISA_bus__is_a_macro /* for versions in ksyms.c */
-#define MCA_bus 0
-#define MCA_bus__is_a_macro /* for versions in ksyms.c */
-
-/*
- * User space: 3GB
- */
-#define TASK_SIZE (0xc0000000UL)
-
-/* This decides where the kernel will search for a free chunk of vm
- * space during mmap's.
- */
-#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-
-#define INIT_MMAP \
-{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
-
-#endif
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-vnc/serial.h
- *
- * Copyright (c) 1996 Russell King.
- *
- * Changelog:
- * 15-10-1996 RMK Created
- * 03-05-1998 RMK Modified for Corel Video NC
- */
-#ifndef __ASM_ARCH_SERIAL_H
-#define __ASM_ARCH_SERIAL_H
-
-#include <asm/irq.h>
-
-/*
- * This assumes you have a 1.8432 MHz clock for your UART.
- *
- * It'd be nice if someone built a serial card with a 24.576 MHz
- * clock, since the 16550A is capable of handling a top speed of 1.5
- * megabits/second; but this requires the faster clock.
- */
-#define BASE_BAUD (1843200 / 16)
-
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-
- /* UART CLK PORT IRQ FLAGS */
-#define SERIAL_PORT_DFNS \
- { 0, BASE_BAUD, 0x3F8, IRQ_UART , STD_COM_FLAGS }, /* ttyS0 */ \
- { 0, BASE_BAUD, 0x2F8, IRQ_UART2, STD_COM_FLAGS }, /* ttyS1 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS2 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS3 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS4 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS5 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS6 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS7 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS8 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS9 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS10 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS11 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS12 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS13 */
-
-#endif
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-ebsa110/shmparam.h
- *
- * Copyright (c) 1996 Russell King.
- */
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-vnc/system.h
- *
- * Copyright (c) 1996,1997,1998 Russell King.
- * Copyright (c) 1998 Corel Computer Corp.
- */
-#include <asm/hardware.h>
-#include <asm/dec21285.h>
-#include <asm/leds.h>
-#include <asm/io.h>
-
-extern __inline__ void arch_reset(char mode)
-{
- cli();
-
- /* open up the SuperIO chip
- */
- outb(0x87, 0x370);
- outb(0x87, 0x370);
-
- /* aux function group 1 (Logical Device 7)
- */
- outb(0x07, 0x370);
- outb(0x07, 0x371);
-
- /* set GP16 for WD-TIMER output
- */
- outb(0xE6, 0x370);
- outb(0x00, 0x371);
-
- /* set a RED LED and toggle WD_TIMER for rebooting...
- */
- outb(0xC4, 0x338);
-}
-
-#define arch_start_idle() leds_event(led_idle_start)
-#define arch_end_idle() leds_event(led_idle_end)
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-vnc/time.h
- *
- * Copyright (c) 1997 Corel Computer Corp.
- * Slight modifications to bring in line with ebsa285 port.
- * -- Russell King.
- * Added LED driver (based on the ebsa285 code) - Alex Holden 28/12/98.
- */
-
-#include <linux/config.h>
-#include <linux/mc146818rtc.h>
-
-#include <asm/leds.h>
-#include <asm/system.h>
-
-#undef IRQ_TIMER
-#define IRQ_TIMER IRQ_TIMER4
-
-#define mSEC_10_from_14 ((14318180 + 100) / 200)
-
-extern __inline__ unsigned long gettimeoffset (void)
-{
- int count;
-
- static int count_p = (mSEC_10_from_14/6); /* for the first call after boot */
- static unsigned long jiffies_p = 0;
-
- /*
- * cache volatile jiffies temporarily; we have IRQs turned off.
- */
- unsigned long jiffies_t;
-
- /* timer count may underflow right here */
- outb_p(0x00, 0x43); /* latch the count ASAP */
-
- count = inb_p(0x40); /* read the latched count */
-
- /*
- * We do this guaranteed double memory access instead of a _p
- * postfix in the previous port access. Wheee, hackady hack
- */
- jiffies_t = jiffies;
-
- count |= inb_p(0x40) << 8;
-
- /* Detect timer underflows. If we haven't had a timer tick since
- the last time we were called, and time is apparently going
- backwards, the counter must have wrapped during this routine. */
- if ((jiffies_t == jiffies_p) && (count > count_p))
- count -= (mSEC_10_from_14/6);
- else
- jiffies_p = jiffies_t;
-
- count_p = count;
-
- count = (((mSEC_10_from_14/6)-1) - count) * tick;
- count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6);
-
- return count;
-}
-
-extern __inline__ int reset_timer (void)
-{
-#ifdef CONFIG_LEDS
- static unsigned int count = 50;
- static int last_pid;
-
- if (current->pid != last_pid) {
- last_pid = current->pid;
- if (last_pid)
- leds_event(led_idle_end);
- else
- leds_event(led_idle_start);
- }
-
- if (--count == 0) {
- count = 50;
- leds_event(led_timer);
- }
-#endif
- return 1;
-}
-
-unsigned long set_rtc_mmss(unsigned long nowtime)
-{
- int retval = 0;
- int real_seconds, real_minutes, cmos_minutes;
- unsigned char save_control, save_freq_select;
-
- save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
- CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
-
- save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
- CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
-
- cmos_minutes = CMOS_READ(RTC_MINUTES);
- if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
- BCD_TO_BIN(cmos_minutes);
-
- /*
- * since we're only adjusting minutes and seconds,
- * don't interfere with hour overflow. This avoids
- * messing with unknown time zones but requires your
- * RTC not to be off by more than 15 minutes
- */
- real_seconds = nowtime % 60;
- real_minutes = nowtime / 60;
- if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
- real_minutes += 30; /* correct for half hour time zone */
- real_minutes %= 60;
-
- if (abs(real_minutes - cmos_minutes) < 30) {
- if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
- BIN_TO_BCD(real_seconds);
- BIN_TO_BCD(real_minutes);
- }
- CMOS_WRITE(real_seconds,RTC_SECONDS);
- CMOS_WRITE(real_minutes,RTC_MINUTES);
- } else
- retval = -1;
-
- /* The following flags have to be released exactly in this order,
- * otherwise the DS12887 (popular MC146818A clone with integrated
- * battery and quartz) will not reset the oscillator and will not
- * update precisely 500 ms later. You won't find this mentioned in
- * the Dallas Semiconductor data sheets, but who believes data
- * sheets anyway ... -- Markus Kuhn
- */
- CMOS_WRITE(save_control, RTC_CONTROL);
- CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
-
- return retval;
-}
-
-/*
- * We don't have a RTC to update!
- */
-extern __inline__ void update_rtc(void)
-{
- static long last_rtc_update = 0; /* last time the cmos clock got updated */
-
- /* If we have an externally synchronized linux clock, then update
- * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
- * called as close as possible to 500 ms before the new second starts.
- */
- if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
- xtime.tv_usec > 50000 - (tick >> 1) &&
- xtime.tv_usec < 50000 + (tick >> 1)) {
- if (set_rtc_mmss(xtime.tv_sec) == 0)
- last_rtc_update = xtime.tv_sec;
- else
- last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
- }
-}
-
-extern __inline__ unsigned long get_cmos_time(void)
-{
- unsigned int year, mon, day, hour, min, sec;
- int i;
-
- // check to see if the RTC makes sense.....
- if ((CMOS_READ(RTC_VALID) & RTC_VRT) == 0)
- return mktime(1970, 1, 1, 0, 0, 0);
-
- /* The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
- /* read RTC exactly on falling edge of update flag */
- for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
- break;
-
- for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
- if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
- break;
-
- do { /* Isn't this overkill ? UIP above should guarantee consistency */
- sec = CMOS_READ(RTC_SECONDS);
- min = CMOS_READ(RTC_MINUTES);
- hour = CMOS_READ(RTC_HOURS);
- day = CMOS_READ(RTC_DAY_OF_MONTH);
- mon = CMOS_READ(RTC_MONTH);
- year = CMOS_READ(RTC_YEAR);
- } while (sec != CMOS_READ(RTC_SECONDS));
-
- if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
- }
- if ((year += 1900) < 1970)
- year += 100;
- return mktime(year, mon, day, hour, min, sec);
-}
-
-/*
- * Set up timer interrupt, and return the current time in seconds.
- */
-extern __inline__ unsigned long setup_timer (void)
-{
- unsigned int c;
-
- /* Turn on the RTC */
- outb(13, 0x70);
- if ((inb(0x71) & 0x80) == 0)
- printk("RTC: *** warning: CMOS battery bad\n");
-
- outb(10, 0x70); /* select control reg */
- outb(32, 0x71); /* make sure the divider is set */
- outb(11, 0x70); /* select other control reg */
- c = inb(0x71) & 0xfb; /* read it */
- outb(11, 0x70);
- outb(c | 2, 0x71); /* turn on BCD counting and 24 hour clock mode */
-
- /* enable PIT timer */
- /* set for periodic (4) and LSB/MSB write (0x30) */
- outb(0x34, 0x43);
- outb((mSEC_10_from_14/6) & 0xFF, 0x40);
- outb((mSEC_10_from_14/6) >> 8, 0x40);
-
- /*
- * Default the date to 1 Jan 1970 00:00:00
- * You will have to run a time daemon to set the
- * clock correctly at bootup
- */
- return get_cmos_time();
-}
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-vnc/timex.h
- *
- * Corel Video NC architecture timex specifications
- *
- * Copyright (C) 1998 Corel Computer/Russell King
- */
-
-/*
- * On the VNC, the clock runs at 66MHz and is divided
- * by a 4-bit prescaler.
- */
-#define CLOCK_TICK_RATE (66000000 / 16)
+++ /dev/null
-/*
- * linux/include/asm-arm/arch-ebsa110/uncompress.h
- *
- * Copyright (C) 1996,1997,1998 Russell King
- */
-
-/*
- * This does not append a newline
- */
-static void puts(const char *s)
-{
- __asm__ __volatile__("
- ldrb %0, [%2], #1
- teq %0, #0
- beq 3f
-1: strb %0, [%3]
-2: ldrb %1, [%3, #0x14]
- and %1, %1, #0x60
- teq %1, #0x60
- bne 2b
- teq %0, #'\n'
- moveq %0, #'\r'
- beq 1b
- ldrb %0, [%2], #1
- teq %0, #0
- bne 1b
-3: " : : "r" (0), "r" (0), "r" (s), "r" (0xf0000be0) : "cc");
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
-#define arch_decomp_wdog()
#define DC21285_PCI_MEM 0x80000000
#ifndef __ASSEMBLY__
-#define DC21285_IO(x) ((volatile unsigned long *)(0xfe000000+(x)))
+#include <asm/arch/hardware.h>
+#define DC21285_IO(x) ((volatile unsigned long *)(ARMCSR_BASE+(x)))
#else
#define DC21285_IO(x) (x)
#endif
#define CSR_PCICMD DC21285_IO(0x0004)
+#define CSR_CLASSREV DC21285_IO(0x0008)
#define CSR_PCICACHELINESIZE DC21285_IO(0x000c)
#define CSR_PCICSRBASE DC21285_IO(0x0010)
#define CSR_PCICSRIOBASE DC21285_IO(0x0014)
#define CSR_PCISDRAMBASE DC21285_IO(0x0018)
#define CSR_PCIROMBASE DC21285_IO(0x0030)
+#define CSR_ROMWRITEREG DC21285_IO(0x0068)
#define CSR_CSRBASEMASK DC21285_IO(0x00f8)
#define CSR_CSRBASEOFFSET DC21285_IO(0x00fc)
#define CSR_SDRAMBASEMASK DC21285_IO(0x0100)
#define CSR_I2O_OUTPOSTCOUNT DC21285_IO(0x0134)
#define CSR_I2O_INPOSTCOUNT DC21285_IO(0x0138)
#define CSR_SA110_CNTL DC21285_IO(0x013c)
+#define SA110_CNTL_INITCMPLETE (1 << 0)
+#define SA110_CNTL_ASSERTSERR (1 << 1)
+#define SA110_CNTL_RXSERR (1 << 3)
+#define SA110_CNTL_SA110DRAMPARITY (1 << 4)
+#define SA110_CNTL_PCISDRAMPARITY (1 << 5)
+#define SA110_CNTL_DMASDRAMPARITY (1 << 6)
+#define SA110_CNTL_DISCARDTIMER (1 << 8)
+#define SA110_CNTL_PCINRESET (1 << 9)
+#define SA110_CNTL_I2O_256 (0 << 10)
+#define SA110_CNTL_I20_512 (1 << 10)
+#define SA110_CNTL_I2O_1024 (2 << 10)
+#define SA110_CNTL_I2O_2048 (3 << 10)
+#define SA110_CNTL_I2O_4096 (4 << 10)
+#define SA110_CNTL_I2O_8192 (5 << 10)
+#define SA110_CNTL_I2O_16384 (6 << 10)
+#define SA110_CNTL_I2O_32768 (7 << 10)
+#define SA110_CNTL_WATCHDOG (1 << 13)
+#define SA110_CNTL_ROMWIDTH_UNDEF (0 << 14)
+#define SA110_CNTL_ROMWIDTH_16 (1 << 14)
+#define SA110_CNTL_ROMWIDTH_32 (2 << 14)
+#define SA110_CNTL_ROMWIDTH_8 (3 << 14)
+#define SA110_CNTL_ROMACCESSTIME(x) ((x)<<16)
+#define SA110_CNTL_ROMBURSTTIME(x) ((x)<<20)
+#define SA110_CNTL_ROMTRISTATETIME(x) ((x)<<24)
+#define SA110_CNTL_XCSDIR(x) ((x)<<28)
+#define SA110_CNTL_PCICFN (1 << 31)
+
#define CSR_PCIADDR_EXTN DC21285_IO(0x0140)
#define CSR_PREFETCHMEMRANGE DC21285_IO(0x0144)
#define CSR_XBUS_CYCLE DC21285_IO(0x0148)
#include <linux/config.h>
#include <linux/kernel.h>
#include <asm/irq.h>
-#include <asm/system.h>
#include <asm/spinlock.h>
#include <asm/arch/dma.h>
/*
- * DMA modes - we have two, IN and OUT
+ * DMA modes
*/
typedef unsigned int dmamode_t;
-#define DMA_MODE_MASK 1
+#define DMA_MODE_MASK 3
-#define DMA_MODE_READ 0
-#define DMA_MODE_WRITE 1
-#define DMA_AUTOINIT 2
+#define DMA_MODE_READ 0
+#define DMA_MODE_WRITE 1
+#define DMA_MODE_CASCADE 2
+#define DMA_AUTOINIT 4
typedef struct {
unsigned long address;
#define MANU_ICS 0x003c
#define PROD_ICS_IDE 0x00ae
+#define MANU_ICS2 0x003d
+#define PROD_ICS2_IDE 0x00ae
+
#define MANU_SERPORT 0x003f
#define PROD_SERPORT_DSPORT 0x00b9
#define CONST const
#endif
-#define MAX_ECARDS 8
+#define MAX_ECARDS 9
typedef enum { /* Cards address space */
ECARD_IOC,
typedef struct { /* Card handler routines */
void (*irqenable)(ecard_t *ec, int irqnr);
void (*irqdisable)(ecard_t *ec, int irqnr);
+ int (*irqpending)(ecard_t *ec);
void (*fiqenable)(ecard_t *ec, int fiqnr);
void (*fiqdisable)(ecard_t *ec, int fiqnr);
+ int (*fiqpending)(ecard_t *ec);
} expansioncard_ops_t;
/*
* This contains all the info needed on an expansion card
*/
struct expansion_card {
+ struct expansion_card *next;
+
/* Public data */
volatile unsigned char *irqaddr; /* address of IRQ register */
volatile unsigned char *fiqaddr; /* address of FIQ register */
void *fiq_data; /* Data for use for FIQ by card */
expansioncard_ops_t *ops; /* Enable/Disable Ops for card */
- CONST unsigned char slot_no; /* Slot number */
- CONST unsigned char dma; /* DMA number (for request_dma) */
- CONST unsigned char irq; /* IRQ number (for request_irq) */
- CONST unsigned char fiq; /* FIQ number (for request_irq) */
+ CONST unsigned int slot_no; /* Slot number */
+ CONST unsigned int dma; /* DMA number (for request_dma) */
+ CONST unsigned int irq; /* IRQ number (for request_irq) */
+ CONST unsigned int fiq; /* FIQ number (for request_irq) */
CONST card_type_t type; /* Type of card */
CONST struct in_ecid cid; /* Card Identification */
extern void release_fiq(struct fiq_handler *f);
extern void set_fiq_handler(void *start, unsigned int length);
extern void set_fiq_regs(struct pt_regs *regs);
+extern void get_fiq_regs(struct pt_regs *regs);
#endif
#define FLOPPY_MOTOR_MASK 0xf0
#define CROSS_64KB(a,s) (0)
+
+/*
+ * This allows people to reverse the order of
+ * fd0 and fd1, in case their hardware is
+ * strangely connected (as some RiscPCs
+ * and A5000s seem to be).
+ */
+static void driveswap(int *ints, int dummy, int dummy2)
+{
+ floppy_selects[0][0] ^= floppy_selects[0][1];
+ floppy_selects[0][1] ^= floppy_selects[0][0];
+ floppy_selects[0][0] ^= floppy_selects[0][1];
+}
+
+#define EXTRA_FLOPPY_PARAMS ,{ "driveswap", &driveswap, NULL, 0, 0 }
#endif
#include <asm/arch/hardware.h>
-#ifndef FLUSH_BASE
-#define FLUSH_BASE 0xdf000000
-#endif
-
#ifdef HAS_EXPMASK
#ifndef __ASSEMBLER__
#define __EXPMASK(offset) (((volatile unsigned char *)EXPMASK_BASE)[offset])
/* C routines */
-#ifdef CONFIG_TEXT_INIT_SECTION
+#ifdef CONFIG_TEXT_SECTIONS
#define __init __attribute__ ((__section__ (".text.init")))
#define __initfunc(__arginit) \
* constant addresses and variable addresses.
* 04-Dec-1997 RMK Moved a lot of this stuff to the new architecture
* specific IO header files.
+ * 27-Mar-1999 PJB Second parameter of memcpy_toio is const..
+ * 04-Apr-1999 PJB Added check_signature.
*/
#ifndef __ASM_ARM_IO_H
#define __ASM_ARM_IO_H
+#ifdef __KERNEL__
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
+
+/*
+ * String version of IO memory access ops:
+ */
+extern void _memcpy_fromio(void *, unsigned long, unsigned long);
+extern void _memcpy_toio(unsigned long, const void *, unsigned long);
+extern void _memset_io(unsigned long, int, unsigned long);
+
+#define memcpy_fromio(to,from,len) _memcpy_fromio((to),(unsigned long)(from),(len))
+#define memcpy_toio(to,from,len) _memcpy_toio((unsigned long)(to),(from),(len))
+#define memset_io(addr,c,len) _memset_io((unsigned long)(addr),(c),(len))
+
+#endif
+
#include <asm/hardware.h>
-#include <asm/arch/mmu.h>
+#include <asm/arch/memory.h>
#include <asm/arch/io.h>
#include <asm/proc/io.h>
#endif
-#undef ARCH_IO_DELAY
-#undef ARCH_IO_CONSTANT
+#ifndef ARCH_READWRITE
-#ifdef __KERNEL__
+/* for panic */
+#include <linux/kernel.h>
-extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
+#define readb(p) (panic("readb called, but not implemented"),0)
+#define readw(p) (panic("readw called, but not implemented"),0)
+#define readl(p) (panic("readl called, but not implemented"),0)
+#define writeb(v,p) panic("writeb called, but not implemented")
+#define writew(v,p) panic("writew called, but not implemented")
+#define writel(v,p) panic("writel called, but not implemented")
+
+#endif
/*
- * String version of IO memory access ops:
+ * This isn't especially architecture dependent so it seems like it
+ * might as well go here as anywhere.
*/
-extern void _memcpy_fromio(void *, unsigned long, unsigned long);
-extern void _memcpy_toio(unsigned long, void *, unsigned long);
-extern void _memset_io(unsigned long, int, unsigned long);
-
-#define memcpy_fromio(to,from,len) _memcpy_fromio((to),(unsigned long)(from),(len))
-#define memcpy_toio(to,from,len) _memcpy_toio((unsigned long)(to),(from),(len))
-#define memset_io(addr,c,len) _memset_io((unsigned long)(addr),(c),(len))
-
-#endif
+static inline int check_signature(unsigned long io_addr,
+ const unsigned char *signature, int length)
+{
+ int retval = 0;
+ do {
+ if (readb(io_addr) != *signature)
+ goto out;
+ io_addr++;
+ signature++;
+ length--;
+ } while (length);
+ retval = 1;
+out:
+ return retval;
+}
+
+#undef ARCH_READWRITE
+#undef ARCH_IO_DELAY
+#undef ARCH_IO_CONSTANT
#endif
* read/write.
*/
+#ifndef IOC_CONTROL
+
#ifndef __ASSEMBLER__
#define __IOC(offset) (IOC_BASE + (offset >> 2))
#else
#define IOC_T3GO __IOC(0x78)
#define IOC_T3LATCH __IOC(0x7c)
+#endif
#define DMA_ST_OFL 4
#define DMA_ST_INT 2
#define DMA_ST_AB 1
+
+#ifndef IOC_CONTROL
/*
* IOC compatability
*/
#define IOC_T1LTCHH IOMD_T1LTCHH
#define IOC_T1GO IOMD_T1GO
#define IOC_T1LATCH IOMD_T1LATCH
+#endif
/*
* DMA (MEMC) compatability
* capability
*/
#ifndef NO_IRQ
-#define NO_IRQ 255
+#define NO_IRQ ((unsigned int)(-1))
#endif
+#define disable_irq_nosync(i) disable_irq(i)
+
extern void disable_irq(unsigned int);
extern void enable_irq(unsigned int);
#ifndef ASM_ARM_LEDS_H
#define ASM_ARM_LEDS_H
+#include <linux/config.h>
+
typedef enum {
led_idle_start,
led_idle_end,
led_timer,
led_start,
- led_stop
+ led_stop,
+ led_claim, /* override idle & timer leds */
+ led_release, /* restore idle & timer leds */
+ led_green_on,
+ led_green_off,
+ led_amber_on,
+ led_amber_off,
+ led_red_on,
+ led_red_off
} led_event_t;
/* Use this routine to handle LEDs */
-extern void leds_event(led_event_t);
+
+#ifdef CONFIG_LEDS
+extern void (*leds_event)(led_event_t);
+#define set_leds_event(r) leds_event = r
+#else
+#define leds_event(e)
+#define set_leds_event(r)
+#endif
#endif
#define VDMA_START 1
#define VDMA_END 2
+#ifndef __ASSEMBLER__
+extern void memc_write(unsigned int reg, unsigned long val);
+
#define video_set_dma(start,end,offset) \
do { \
memc_write (VDMA_START, (start >> 2)); \
memc_write (VDMA_INIT, (offset >> 2)); \
} while (0)
+#endif
+++ /dev/null
-/*
- * linux/include/asm-arm/mm-init.h
- *
- * Copyright (C) 1997,1998 Russell King
- *
- * Contained within are structures to describe how to set up the
- * initial memory map. It includes both a processor-specific header
- * for parsing these structures, and an architecture-specific header
- * to fill out the structures.
- */
-#ifndef __ASM_MM_INIT_H
-#define __ASM_MM_INIT_H
-
-typedef enum {
- // physical address is absolute
- init_mem_map_absolute,
- /* physical address is relative to start_mem
- * as passed in paging_init
- */
- init_mem_map_relative_start_mem
-} init_memmap_type_t;
-
-typedef struct {
- init_memmap_type_t type;
- unsigned long physical_address;
- unsigned long virtual_address;
- unsigned long size;
-} init_memmap_t;
-
-#define INIT_MEM_MAP_SENTINEL { init_mem_map_absolute, 0, 0, 0 }
-#define INIT_MEM_MAP_ABSOLUTE(p,l,s) { init_mem_map_absolute,p,l,s }
-#define INIT_MEM_MAP_RELATIVE(o,l,s) { init_mem_map_relative_start_mem,o,l,s }
-
-/*
- * Within this file, initialise an array of init_mem_map_t's
- * to describe your initial memory mapping structure.
- */
-#include <asm/arch/mm-init.h>
-
-/*
- * Contained within this file is code to read the array
- * of init_mem_map_t's created above.
- */
-#include <asm/proc/mm-init.h>
-
-#endif
#ifndef _ASMARM_PAGE_H
#define _ASMARM_PAGE_H
-#include <asm/arch/mmu.h>
+#include <asm/arch/memory.h>
#include <asm/proc/page.h>
#ifdef __KERNEL__
#define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
#define free_user_page(page, addr) free_page(addr)
-#define clear_page(page) memzero((void *)(page), PAGE_SIZE)
-#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+#define clear_page(page) memzero((void *)(page), PAGE_SIZE)
+#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE)
#endif
#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
} __kernel_fsid_t;
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
#undef __FD_SET
#define __FD_SET(fd, fdsetp) \
(((fd_set *)fdsetp)->fds_bits[fd >> 5] |= (1<<(fd & 31)))
(memset (fdsetp, 0, sizeof (*(fd_set *)fdsetp)))
#endif
+
+#endif
+++ /dev/null
-/*
- * linux/include/asm-arm/proc-armo/mmap.h
- *
- * Copyright (C) 1996 Russell King
- *
- * This contains the code to setup the memory map on an ARM2/ARM250/ARM3
- * machine. This is both processor & architecture specific, and requires
- * some more work to get it to fit into our separate processor and
- * architecture structure.
- */
-
-static unsigned long phys_screen_end;
-int page_nr;
-
-#define setup_processor_functions()
-
-/*
- * This routine needs more work to make it dynamically release/allocate mem!
- */
-unsigned long map_screen_mem(unsigned long log_start, unsigned long kmem, int update)
-{
- static int updated = 0;
- unsigned long address = SCREEN_START, i;
- pgd_t *pg_dir;
- pmd_t *pm_dir;
- pte_t *pt_entry;
-
- if (updated)
- return 0;
- updated = update;
-
- pg_dir = swapper_pg_dir + (SCREEN1_BASE >> PGDIR_SHIFT);
- pm_dir = pmd_offset(pg_dir, SCREEN1_BASE);
- pt_entry = pte_offset(pm_dir, SCREEN1_BASE);
-
- for (i = SCREEN1_BASE; i < SCREEN1_END; i += PAGE_SIZE) {
- if (i >= log_start) {
- *pt_entry = mk_pte(address, __pgprot(_PAGE_PRESENT));
- address += PAGE_SIZE;
- } else
- *pt_entry = mk_pte(0, __pgprot(0));
- pt_entry++;
- }
- phys_screen_end = address;
- if (update)
- flush_tlb_all ();
- return kmem;
-}
-
-static inline unsigned long setup_pagetables(unsigned long start_mem, unsigned long end_mem)
-{
- unsigned long address;
- unsigned int spi;
-
- page_nr = MAP_NR(end_mem);
-
- /* Allocate zero page */
- address = PAGE_OFFSET + 480*1024;
- for (spi = 0; spi < 32768 >> PAGE_SHIFT; spi++) {
- pgd_val(swapper_pg_dir[spi]) = pte_val(mk_pte(address, PAGE_READONLY));
- address += PAGE_SIZE;
- }
-
- while (spi < (PAGE_OFFSET >> PGDIR_SHIFT))
- pgd_val(swapper_pg_dir[spi++]) = 0;
-
- map_screen_mem (SCREEN1_END - 480*1024, 0, 0);
- return start_mem;
-}
-
-static inline void mark_usable_memory_areas(unsigned long *start_mem, unsigned long end_mem)
-{
- unsigned long smem = PAGE_ALIGN(*start_mem);
-
- while (smem < end_mem) {
- clear_bit(PG_reserved, &mem_map[MAP_NR(smem)].flags);
- smem += PAGE_SIZE;
- }
-
- for (smem = phys_screen_end; smem < SCREEN2_END; smem += PAGE_SIZE)
- clear_bit(PG_reserved, &mem_map[MAP_NR(smem)].flags);
-}
* some more work to get it to fit into our separate processor and
* architecture structure.
*/
-extern unsigned long phys_screen_end;
-extern unsigned long map_screen_mem(unsigned long log_start, unsigned long kmem, int update);
+#include <asm/arch/memory.h>
+
int page_nr;
#define setup_processor_functions()
set_pmd (pmd_offset (swapper_pg_dir + index, 0), mk_pmd (ptep));
}
-static inline unsigned long setup_pagetables(unsigned long start_mem, unsigned long end_mem)
+static inline unsigned long
+setup_pagetables(unsigned long start_mem, unsigned long end_mem)
{
unsigned int i;
- union {unsigned long l; pte_t *pte; } u;
+ union { unsigned long l; pte_t *pte; } u;
page_nr = MAP_NR(end_mem);
for (i = 1; i < PTRS_PER_PGD; i++)
pgd_val(swapper_pg_dir[i]) = 0;
- /* now map screen mem in */
- phys_screen_end = SCREEN2_END;
- map_screen_mem (SCREEN1_END - 480*1024, 0, 0);
-
return start_mem;
}
-static inline void mark_usable_memory_areas(unsigned long *start_mem, unsigned long end_mem)
+static inline void
+mark_usable_memory_areas(unsigned long *start_mem, unsigned long end_mem)
{
unsigned long smem;
clear_bit(PG_reserved, &mem_map[MAP_NR(smem)].flags);
smem += PAGE_SIZE;
}
-
- for (smem = phys_screen_end; smem < SCREEN2_END; smem += PAGE_SIZE)
- clear_bit(PG_reserved, &mem_map[MAP_NR(smem)].flags);
}
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
/* This handles the memory map.. */
-#define PAGE_OFFSET 0x02000000
#define MAP_NR(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT)
#endif /* __KERNEL__ */
+++ /dev/null
-/*
- * linux/include/asm-arm/proc-armo/pgtable.h
- *
- * Copyright (C) 1995, 1996 Russell King
- */
-#ifndef __ASM_PROC_PGTABLE_H
-#define __ASM_PROC_PGTABLE_H
-
-#include <asm/arch/mmu.h>
-
-#define LIBRARY_TEXT_START 0x0c000000
-
-/*
- * Cache flushing...
- */
-#define flush_cache_all() do { } while (0)
-#define flush_cache_mm(mm) do { } while (0)
-#define flush_cache_range(mm,start,end) do { } while (0)
-#define flush_cache_page(vma,vmaddr) do { } while (0)
-#define flush_page_to_ram(page) do { } while (0)
-
-/*
- * TLB flushing:
- *
- * - flush_tlb() flushes the current mm struct TLBs
- * - flush_tlb_all() flushes all processes TLBs
- * - flush_tlb_mm(mm) flushes the specified mm context TLB's
- * - flush_tlb_page(vma, vmaddr) flushes one page
- * - flush_tlb_range(mm, start, end) flushes a range of pages
- */
-
-#define flush_tlb() flush_tlb_mm(current->mm)
-
-extern __inline__ void flush_tlb_all(void)
-{
- struct task_struct *p;
-
- p = &init_task;
- do {
- processor.u.armv2._update_map(p);
- p = p->next_task;
- } while (p != &init_task);
-
- processor.u.armv2._remap_memc (current);
-}
-
-extern __inline__ void flush_tlb_mm(struct mm_struct *mm)
-{
- struct task_struct *p;
-
- p = &init_task;
- do {
- if (p->mm == mm)
- processor.u.armv2._update_map(p);
- p = p->next_task;
- } while (p != &init_task);
-
- if (current->mm == mm)
- processor.u.armv2._remap_memc (current);
-}
-
-#define flush_tlb_range(mm, start, end) flush_tlb_mm(mm)
-#define flush_tlb_page(vma, vmaddr) flush_tlb_mm(vma->vm_mm)
-
-#define __flush_entry_to_ram(entry)
-
-/* Certain architectures need to do special things when pte's
- * within a page table are directly modified. Thus, the following
- * hook is made available.
- */
-#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
-
-/* PMD_SHIFT determines the size of the area a second-level page table can map */
-#define PMD_SHIFT PAGE_SHIFT
-#define PMD_SIZE (1UL << PMD_SHIFT)
-#define PMD_MASK (~(PMD_SIZE-1))
-
-/* PGDIR_SHIFT determines what a third-level page table entry can map */
-#define PGDIR_SHIFT PAGE_SHIFT
-#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
-#define PGDIR_MASK (~(PGDIR_SIZE-1))
-
-/*
- * entries per page directory level: the arm3 is one-level, so
- * we don't really have any PMD or PTE directory physically.
- */
-#define PTRS_PER_PTE 1
-#define PTRS_PER_PMD 1
-#define PTRS_PER_PGD 1024
-
-/* Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts. That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_START 0x01a00000
-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
-
-#define _PAGE_PRESENT 0x001
-#define _PAGE_RW 0x002
-#define _PAGE_USER 0x004
-#define _PAGE_PCD 0x010
-#define _PAGE_ACCESSED 0x020
-#define _PAGE_DIRTY 0x040
-
-#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
-#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
-
-#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
-#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
-#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
-#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
-#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
-
-/*
- * The arm can't do page protection for execute, and considers that the same are read.
- * Also, write permissions imply read permissions. This is the closest we can get..
- */
-#define __P000 PAGE_NONE
-#define __P001 PAGE_READONLY
-#define __P010 PAGE_COPY
-#define __P011 PAGE_COPY
-#define __P100 PAGE_READONLY
-#define __P101 PAGE_READONLY
-#define __P110 PAGE_COPY
-#define __P111 PAGE_COPY
-
-#define __S000 PAGE_NONE
-#define __S001 PAGE_READONLY
-#define __S010 PAGE_SHARED
-#define __S011 PAGE_SHARED
-#define __S100 PAGE_READONLY
-#define __S101 PAGE_READONLY
-#define __S110 PAGE_SHARED
-#define __S111 PAGE_SHARED
-
-#undef TEST_VERIFY_AREA
-
-/*
- * BAD_PAGE is used for a bogus page.
- *
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-extern pte_t __bad_page(void);
-extern unsigned long *empty_zero_page;
-
-#define BAD_PAGE __bad_page()
-#define ZERO_PAGE ((unsigned long) empty_zero_page)
-
-/* number of bits that fit into a memory pointer */
-#define BYTES_PER_PTR (sizeof(unsigned long))
-#define BITS_PER_PTR (8*BYTES_PER_PTR)
-
-/* to align the pointer to a pointer address */
-#define PTR_MASK (~(sizeof(void*)-1))
-
-/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
-#define SIZEOF_PTR_LOG2 2
-
-/* to find an entry in a page-table */
-#define PAGE_PTR(address) \
-((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
-
-/* to set the page-dir */
-#define SET_PAGE_DIR(tsk,pgdir) \
-do { \
- tsk->tss.memmap = (unsigned long)pgdir; \
- processor.u.armv2._update_map(tsk); \
- if ((tsk) == current) \
- processor.u.armv2._remap_memc (current); \
-} while (0)
-
-extern unsigned long physical_start;
-extern unsigned long physical_end;
-
-extern inline int pte_none(pte_t pte) { return !pte_val(pte); }
-extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; }
-extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; }
-
-extern inline int pmd_none(pmd_t pmd) { return 0; }
-extern inline int pmd_bad(pmd_t pmd) { return 0; }
-extern inline int pmd_present(pmd_t pmd) { return 1; }
-extern inline void pmd_clear(pmd_t * pmdp) { }
-
-/*
- * The "pgd_xxx()" functions here are trivial for a folded two-level
- * setup: the pgd is never bad, and a pmd always exists (as it's folded
- * into the pgd entry)
- */
-extern inline int pgd_none(pgd_t pgd) { return 0; }
-extern inline int pgd_bad(pgd_t pgd) { return 0; }
-extern inline int pgd_present(pgd_t pgd) { return 1; }
-extern inline void pgd_clear(pgd_t * pgdp) { }
-
-/*
- * The following only work if pte_present() is true.
- * Undefined behaviour if not..
- */
-extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
-extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
-extern inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
-extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
-extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
-#define pte_cacheable(pte) 1
-
-extern inline pte_t pte_nocache(pte_t pte) { return pte; }
-extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_RW; return pte; }
-extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; }
-extern inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; }
-extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
-extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_RW; return pte; }
-extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; }
-extern inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; }
-extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
-extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
-
-/*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
- */
-extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot)
-{ pte_t pte; pte_val(pte) = virt_to_phys(page) | pgprot_val(pgprot); return pte; }
-
-extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
-{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
-
-extern inline unsigned long pte_page(pte_t pte)
-{ return phys_to_virt(pte_val(pte) & PAGE_MASK); }
-
-extern inline unsigned long pmd_page(pmd_t pmd)
-{ return phys_to_virt(pmd_val(pmd) & PAGE_MASK); }
-
-/* to find an entry in a page-table-directory */
-extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
-{
- return mm->pgd + (address >> PGDIR_SHIFT);
-}
-
-/* Find an entry in the second-level page table.. */
-#define pmd_offset(dir, address) ((pmd_t *)(dir))
-
-/* Find an entry in the third-level page table.. */
-#define pte_offset(dir, address) ((pte_t *)(dir))
-
-/*
- * Allocate and free page tables. The xxx_kernel() versions are
- * used to allocate a kernel page table - this turns on ASN bits
- * if any.
- */
-extern inline void pte_free_kernel(pte_t * pte)
-{
- pte_val(*pte) = 0;
-}
-
-extern inline pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address)
-{
- return (pte_t *) pmd;
-}
-
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-#define pmd_free_kernel(pmdp)
-#define pmd_alloc_kernel(pgd,address) ((pmd_t *)(pgd))
-
-#define pte_free(ptep)
-#define pte_alloc(pmd,address) ((pte_t *)(pmd))
-
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-#define pmd_free(pmd)
-#define pmd_alloc(pgd,address) ((pmd_t *)(pgd))
-
-extern inline void pgd_free(pgd_t * pgd)
-{
- extern void kfree(void *);
- kfree((void *)pgd);
-}
-
-extern inline pgd_t * pgd_alloc(void)
-{
- pgd_t *pgd;
- extern void *kmalloc(unsigned int, int);
-
- pgd = (pgd_t *) kmalloc(PTRS_PER_PGD * BYTES_PER_PTR, GFP_KERNEL);
- if (pgd)
- memset(pgd, 0, PTRS_PER_PGD * BYTES_PER_PTR);
- return pgd;
-}
-
-extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
-
-#define update_mmu_cache(vma,address,pte) processor.u.armv2._update_mmu_cache(vma,address,pte)
-
-#define SWP_TYPE(entry) (((entry) >> 1) & 0x7f)
-#define SWP_OFFSET(entry) ((entry) >> 8)
-#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
-
-#endif /* __ASM_PROC_PAGE_H */
-
#ifndef __ASM_PROC_PGTABLE_H
#define __ASM_PROC_PGTABLE_H
-#include <asm/arch/mmu.h>
+#include <linux/config.h>
#include <linux/slab.h>
-#include <asm/arch/processor.h> /* For TASK_SIZE */
+#include <asm/arch/memory.h> /* For TASK_SIZE */
#define LIBRARY_TEXT_START 0x0c000000
return __phys_to_virt(pte_val(pte) & PAGE_MASK);
}
-extern __inline__ pmd_t mk_pmd (pte_t *ptep)
+extern __inline__ pmd_t mk_pmd(pte_t *ptep)
{
pmd_t pmd;
pmd_val(pmd) = __virt_to_phys((unsigned long)ptep) | _PAGE_TABLE;
return pmd;
}
+/* these are aliases for the above function */
+#define mk_user_pmd(ptep) mk_pmd(ptep)
+#define mk_kernel_pmd(ptep) mk_pmd(ptep)
+
#define set_pmd(pmdp,pmd) ((*(pmdp)) = (pmd))
extern __inline__ unsigned long pmd_page(pmd_t pmd)
*/
#ifndef __SMP__
+#ifndef CONFIG_NO_PGT_CACHE
extern struct pgtable_cache_struct {
unsigned long *pgd_cache;
unsigned long *pte_cache;
#define pte_quicklist (quicklists.pte_cache)
#define pgd_quicklist (quicklists.pgd_cache)
#define pgtable_cache_size (quicklists.pgtable_cache_sz)
+#endif
#else
#error Pgtable caches have to be per-CPU, so that no locking is needed.
#endif
extern pgd_t *get_pgd_slow(void);
+extern void free_table(void *table);
+#ifndef CONFIG_NO_PGT_CACHE
extern __inline__ pgd_t *get_pgd_fast(void)
{
unsigned long *ret;
pgd_quicklist = (unsigned long *) pgd;
pgtable_cache_size++;
}
+#endif
+/* keep this as an inline so we get type checking */
extern __inline__ void free_pgd_slow(pgd_t *pgd)
{
- kfree(pgd);
+ free_table((void *)pgd);
}
extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
+#ifndef CONFIG_NO_PGT_CACHE
extern __inline__ pte_t *get_pte_fast(void)
{
unsigned long *ret;
pte_quicklist = (unsigned long *) pte;
pgtable_cache_size++;
}
+#endif
+/* keep this as an inline so we get type checking */
extern __inline__ void free_pte_slow(pte_t *pte)
{
- kfree(pte);
+ free_table((void *)pte);
}
/* We don't use pmd cache, so this is a dummy routine */
extern void __bad_pmd(pmd_t *pmd);
extern void __bad_pmd_kernel(pmd_t *pmd);
+#ifdef CONFIG_NO_PGT_CACHE
+#define pte_free_kernel(pte) free_pte_slow(pte)
+#define pte_free(pte) free_pte_slow(pte)
+#define pgd_free(pgd) free_pgd_slow(pgd)
+#define pgd_alloc() get_pgd_slow()
+
+extern __inline__ pte_t *pte_alloc(pmd_t * pmd, unsigned long address)
+{
+ address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+
+ if (pmd_none (*pmd)) {
+ return get_pte_slow(pmd, address);
+ }
+ if (pmd_bad (*pmd)) {
+ __bad_pmd(pmd);
+ return NULL;
+ }
+ return (pte_t *) pmd_page(*pmd) + address;
+}
+#else
#define pte_free_kernel(pte) free_pte_fast(pte)
#define pte_free(pte) free_pte_fast(pte)
#define pgd_free(pgd) free_pgd_fast(pgd)
}
return (pte_t *) pmd_page(*pmd) + address;
}
+#endif
/*
* allocating and freeing a pmd is trivial: the 1-entry pmd is
extern __inline__ void set_pgdir(unsigned long address, pgd_t entry)
{
struct task_struct * p;
- pgd_t *pgd;
read_lock(&tasklist_lock);
for_each_task(p) {
*pgd_offset(p->mm,address) = entry;
}
read_unlock(&tasklist_lock);
- for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
- pgd[address >> PGDIR_SHIFT] = entry;
+#ifndef CONFIG_NO_PGT_CACHE
+ {
+ pgd_t *pgd;
+ for (pgd = (pgd_t *)pgd_quicklist; pgd;
+ pgd = (pgd_t *)*(unsigned long *)pgd)
+ pgd[address >> PGDIR_SHIFT] = entry;
+ }
+#endif
}
extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
#ifndef __ASM_PROC_PROCESSOR_H
#define __ASM_PROC_PROCESSOR_H
-#ifdef __KERNEL__
-
#include <asm/assembler.h>
#include <linux/string.h>
unsigned long pc;
};
+#define INIT_CSS (struct context_save_struct){ 0, 0, 0, 0, 0, 0, 0, SVC26_MODE }
+
typedef struct {
void (*put_byte)(void); /* Special calling convention */
void (*get_byte)(void); /* Special calling convention */
#define EXTRA_THREAD_STRUCT \
uaccess_t *uaccess; /* User access functions*/ \
- struct context_save_struct *save; \
- unsigned long memmap; \
unsigned long memcmap[256];
#define EXTRA_THREAD_STRUCT_INIT \
- &uaccess_kernel, \
- 0, \
- (unsigned long) swapper_pg_dir, \
+ ,&uaccess_kernel, \
{ 0, }
-DECLARE_THREAD_STRUCT;
-
-/*
- * Return saved PC of a blocked thread.
- */
-extern __inline__ unsigned long thread_saved_pc (struct thread_struct *t)
-{
- if (t->save)
- return t->save->pc & ~PCMASK;
- else
- return 0;
-}
-
-extern __inline__ unsigned long get_css_fp (struct thread_struct *t)
-{
- if (t->save)
- return t->save->fp;
- else
- return 0;
-}
-
-asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call");
-
-extern __inline__ void copy_thread_css (struct context_save_struct *save)
-{
- save->r4 =
- save->r5 =
- save->r6 =
- save->r7 =
- save->r8 =
- save->r9 =
- save->fp = 0;
- save->pc = ((unsigned long)ret_from_sys_call) | SVC26_MODE;
-}
+#define SWAPPER_PG_DIR ((unsigned long)swapper_pg_dir)
#define start_thread(regs,pc,sp) \
({ \
regs->ARM_r2 = stack[2]; /* r2 (envp) */ \
regs->ARM_r1 = stack[1]; /* r1 (argv) */ \
regs->ARM_r0 = stack[0]; /* r0 (argc) */ \
- flush_tlb_mm(current->mm); \
})
/* Allocation and freeing of basic task resources. */
/*
* NOTE! The task struct and the stack go together
*/
-#define alloc_task_struct() \
- ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
-#define free_task_struct(p) free_pages((unsigned long)(p),1)
+extern unsigned long get_page_8k(int priority);
+extern void free_page_8k(unsigned long page);
-
-#endif
+#define ll_alloc_task_struct() ((struct task_struct *)get_page_8k(GFP_KERNEL))
+#define ll_free_task_struct(p) free_page_8k((unsigned long)(p))
#endif
/* Are the current registers suitable for user mode?
* (used to maintain security in signal handlers)
*/
-#define valid_user_regs(regs) \
- (user_mode(regs) && ((regs)->ARM_sp & 3) == 0)
+static inline int valid_user_regs(struct pt_regs *regs)
+{
+ if (!user_mode(regs) || regs->ARM_pc & (F_BIT | I_BIT))
+ return 1;
+
+ return 0;
+}
#endif
__asm__ __volatile__ ("
@ atomic down operation
mov r0, pc
- orr r1, r0, #0x08000000
+ orr lr, r0, #0x08000000
and r0, r0, #0x0c000003
- teqp r1, #0
- ldr r1, [%0]
- subs r1, r1, #1
- str r1, [%0]
- mov r1, pc, lsr #28
- teqp r0, r1, lsl #28
+ teqp lr, #0
+ ldr lr, [%0]
+ subs lr, lr, #1
+ str lr, [%0]
+ mov lr, pc, lsr #28
+ teqp r0, lr, lsl #28
movmi r0, %0
- blmi " SYMBOL_NAME_STR(__down)
- : : "r" (sem) : "r0", "r1", "r2", "r3", "ip", "lr", "cc");
+ blmi " SYMBOL_NAME_STR(__down_failed)
+ :
+ : "r" (sem)
+ : "r0", "lr", "cc");
}
/*
__asm__ __volatile__ ("
@ atomic down operation
mov r0, pc
- orr r1, r0, #0x08000000
+ orr lr, r0, #0x08000000
and r0, r0, #0x0c000003
- teqp r1, #0
- ldr r1, [%1]
- subs r1, r1, #1
- str r1, [%1]
- mov r1, pc, lsr #28
+ teqp lr, #0
+ ldr lr, [%1]
+ subs lr, lr, #1
+ str lr, [%1]
+ mov lr, pc, lsr #28
orrmi r0, r0, #0x80000000 @ set N
- teqp r0, r1, lsl #28
+ teqp r0, lr, lsl #28
movmi r0, %1
movpl r0, #0
- blmi " SYMBOL_NAME_STR(__down_interruptible) "
+ blmi " SYMBOL_NAME_STR(__down_interruptible_failed) "
mov %0, r0"
: "=r" (result)
: "r" (sem)
- : "r0", "r1", "r2", "r3", "ip", "lr", "cc");
+ : "r0", "lr", "cc");
+ return result;
+}
+
+extern inline int down_trylock(struct semaphore * sem)
+{
+ int result;
+ __asm__ __volatile__ ("
+ @ atomic down operation
+ mov r0, pc
+ orr lr, r0, #0x08000000
+ and r0, r0, #0x0c000003
+ teqp lr, #0
+ ldr lr, [%1]
+ subs lr, lr, #1
+ str lr, [%1]
+ mov lr, pc, lsr #28
+ orrmi r0, r0, #0x80000000 @ set N
+ teqp r0, lr, lsl #28
+ movmi r0, %1
+ movpl r0, #0
+ blmi " SYMBOL_NAME_STR(__down_trylock_failed) "
+ mov %0, r0"
+ : "=r" (result)
+ : "r" (sem)
+ : "r0", "lr", "cc");
return result;
}
__asm__ __volatile__ ("
@ atomic up operation
mov r0, pc
- orr r1, r0, #0x08000000
+ orr lr, r0, #0x08000000
and r0, r0, #0x0c000003
- teqp r1, #0
- ldr r1, [%0]
- adds r1, r1, #1
- str r1, [%0]
- mov r1, pc, lsr #28
+ teqp lr, #0
+ ldr lr, [%0]
+ adds lr, lr, #1
+ str lr, [%0]
+ mov lr, pc, lsr #28
orrls r0, r0, #0x80000000 @ set N
- teqp r0, r1, lsl #28
+ teqp r0, lr, lsl #28
movmi r0, %0
- blmi " SYMBOL_NAME_STR(__up)
- : : "r" (sem) : "r0", "r1", "r2", "r3", "ip", "lr", "cc");
+ blmi " SYMBOL_NAME_STR(__up_wakeup)
+ :
+ : "r" (sem)
+ : "r0", "lr", "cc");
}
#endif
#include <asm/proc-fns.h>
-extern inline void dma_cache_inv(unsigned long start, unsigned long size)
-{
- processor.u.armv3v4._cache_purge_area(start, start + size);
-}
+#define dma_cache_inv(start, size) \
+ do { processor.u.armv3v4._cache_purge_area((unsigned long)(start), \
+ ((unsigned long)(start)+(size))); } while (0)
-extern inline void dma_cache_wback(unsigned long start, unsigned long size)
-{
- processor.u.armv3v4._cache_wback_area(start, start + size);
-}
+#define dma_cache_wback(start, size) \
+ do { processor.u.armv3v4._cache_wback_area((unsigned long)(start), \
+ ((unsigned long)(start)+(size))); } while (0)
-extern inline void dma_cache_wback_inv(unsigned long start, unsigned long size)
-{
- processor.u.armv3v4._flush_cache_area(start, start + size, 0);
-}
+#define dma_cache_wback_inv(start, size) \
+ do { processor.u.armv3v4._flush_cache_area((unsigned long)(start), \
+ ((unsigned long)(start)+(size)), 0); } while (0)
*/
#include <asm/pgtable.h>
-#define PTE_SIZE (PTRS_PER_PTE * 4)
+#define PTE_SIZE (PTRS_PER_PTE * BYTES_PER_PTR)
extern unsigned long setup_io_pagetables(unsigned long start_mem);
alloc_init_page(unsigned long *mem, unsigned long virt, unsigned long phys, int domain, int prot)
{
pgd_t *pgdp;
- pmd_t *pmdp, pmd;
+ pmd_t *pmdp;
pte_t *ptep;
pgdp = pgd_offset_k(virt);
ptep = (pte_t *)memory;
memzero(ptep, PTE_SIZE);
+ memory += PTE_SIZE;
- pmd_val(pmd) = __virt_to_phys(memory) | PMD_TYPE_TABLE | PMD_DOMAIN(domain);
- set_pmd(pmdp, pmd);
+ ptep = (pte_t *)memory;
+ memzero(ptep, PTE_SIZE);
+
+ set_pmd(pmdp, __mk_pmd(ptep, PMD_TYPE_TABLE | PMD_DOMAIN(domain)));
*mem = memory + PTE_SIZE;
}
ptep = pte_offset(pmdp, virt);
- pte_val(*ptep) = phys | prot | PTE_TYPE_SMALL;
+ set_pte(ptep, mk_pte_phys(phys, __pgprot(prot)));
}
static inline unsigned long
setup_pagetables(unsigned long start_mem, unsigned long end_mem)
{
- unsigned long address;
-
- /*
- * map in zero page
- */
- alloc_init_page(&start_mem, 0, __virt_to_phys(PAGE_OFFSET), DOMAIN_USER, PTE_CACHEABLE);
-
- /*
- * ensure no mappings in user space
- */
- for (address = PGDIR_SIZE; address < PAGE_OFFSET; address += PGDIR_SIZE)
- free_init_section(address);
-
- /*
- * map in physical ram & kernel
- */
- for (address = PAGE_OFFSET; address < end_mem; address += PGDIR_SIZE)
- alloc_init_section(&start_mem, address, __virt_to_phys(address), DOMAIN_KERNEL,
- PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE | PMD_SECT_AP_WRITE);
-
- /*
- * unmap everything else
- */
- for (address = end_mem; address; address += PGDIR_SIZE)
- free_init_section(address);
+ unsigned long address = 0;
+
+ do {
+ if (address >= PAGE_OFFSET && address < end_mem)
+ /*
+ * map in physical ram & kernel
+ */
+ alloc_init_section(&start_mem, address, __virt_to_phys(address), DOMAIN_KERNEL,
+ PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE | PMD_SECT_AP_WRITE);
+ else
+ /*
+ * unmap everything else
+ */
+ free_init_section(address);
+
+ address += PGDIR_SIZE;
+ } while (address != 0);
/*
* An area to invalidate the cache
*/
start_mem = setup_io_pagetables(start_mem);
+ /*
+ * map in zero page
+ */
+ alloc_init_page(&start_mem, 0, __virt_to_phys(PAGE_OFFSET),
+ DOMAIN_USER, L_PTE_CACHEABLE | L_PTE_YOUNG | L_PTE_PRESENT);
+
flush_cache_all();
return start_mem;
*start_mem = smem = PAGE_ALIGN(*start_mem);
+ /*
+ * Mark all of memory from the end of kernel to end of memory
+ */
while (smem < end_mem) {
- clear_bit(PG_reserved, &mem_map[MAP_NR(smem)].flags);
- smem += PAGE_SIZE;
+ clear_bit(PG_reserved, &mem_map[MAP_NR(smem)].flags);
+ smem += PAGE_SIZE;
+ }
+
+ /*
+ * Mark memory from page 1 to start of the swapper page directory
+ */
+ smem = PAGE_OFFSET + PAGE_SIZE;
+ while (smem < (unsigned long)&swapper_pg_dir) {
+ clear_bit(PG_reserved, &mem_map[MAP_NR(smem)].flags);
+ smem += PAGE_SIZE;
}
}
*
* Copyright (C) 1995, 1996, 1997 Russell King
*
- * 12-01-1997 RMK Altered flushing routines to use function pointers
+ * 12-Jan-1997 RMK Altered flushing routines to use function pointers
* now possible to combine ARM6, ARM7 and StrongARM versions.
+ * 17-Apr-1999 RMK Now pass an area size to clean_cache_area and
+ * flush_icache_area.
*/
#ifndef __ASM_PROC_PGTABLE_H
#define __ASM_PROC_PGTABLE_H
-#include <asm/arch/mmu.h>
-#include <asm/arch/processor.h> /* For TASK_SIZE */
+#include <asm/arch/memory.h> /* For TASK_SIZE */
#define LIBRARY_TEXT_START 0x0c000000
((_vma)->vm_flags & VM_EXEC) ? 1 : 0); \
} while (0)
+#define clean_cache_range(_start,_end) \
+ do { \
+ unsigned long _s, _sz; \
+ _s = (unsigned long)_start; \
+ _sz = (unsigned long)_end - _s; \
+ processor.u.armv3v4._clean_cache_area(_s, _sz); \
+ } while (0)
+
+#define clean_cache_area(_start,_size) \
+ do { \
+ unsigned long _s; \
+ _s = (unsigned long)_start; \
+ processor.u.armv3v4._clean_cache_area(_s, _size); \
+ } while (0)
+
#define flush_icache_range(_start,_end) \
- processor.u.armv3v4._flush_icache_area((_start), (_end))
+ processor.u.armv3v4._flush_icache_area((_start), (_end) - (_start))
/*
* We don't have a MEMC chip...
#define flush_page_to_ram(_page) \
processor.u.armv3v4._flush_ram_page ((_page) & PAGE_MASK);
-/*
- * Make the page uncacheable (must flush page beforehand).
- */
-#define uncache_page(_page) \
- processor.u.armv3v4._flush_ram_page ((_page) & PAGE_MASK);
-
/*
* TLB flushing:
*
} while (0)
/*
- * Since the page tables are in cached memory, we need to flush the dirty
- * data cached entries back before we flush the tlb... This is also useful
- * to flush out the SWI instruction for signal handlers...
+ * PMD_SHIFT determines the size of the area a second-level page table can map
*/
-#define __flush_entry_to_ram(entry) \
- processor.u.armv3v4._flush_cache_entry((unsigned long)(entry))
-
-#define __flush_pte_to_ram(entry) \
- processor.u.armv3v4._flush_cache_pte((unsigned long)(entry))
-
-/* PMD_SHIFT determines the size of the area a second-level page table can map */
#define PMD_SHIFT 20
#define PMD_SIZE (1UL << PMD_SHIFT)
#define PMD_MASK (~(PMD_SIZE-1))
-/* PGDIR_SHIFT determines what a third-level page table entry can map */
+/*
+ * PGDIR_SHIFT determines what a third-level page table entry can map
+ */
#define PGDIR_SHIFT 20
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
#define PGDIR_MASK (~(PGDIR_SIZE-1))
#define PTRS_PER_PGD 4096
#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
+
/* Just any arbitrary offset to the start of the vmalloc VM area: the
* current 8MB value just means that there will be a 8MB "hole" after the
* physical memory until the kernel virtual memory starts. That means that
#define VMALLOC_VMADDR(x) ((unsigned long)(x))
#define VMALLOC_END (PAGE_OFFSET + 0x10000000)
-/* PMD types (actually level 1 descriptor) */
-#define PMD_TYPE_MASK 0x0003
-#define PMD_TYPE_FAULT 0x0000
-#define PMD_TYPE_TABLE 0x0001
-#define PMD_TYPE_SECT 0x0002
-#define PMD_UPDATABLE 0x0010
-#define PMD_SECT_CACHEABLE 0x0008
-#define PMD_SECT_BUFFERABLE 0x0004
-#define PMD_SECT_AP_WRITE 0x0400
-#define PMD_SECT_AP_READ 0x0800
-#define PMD_DOMAIN(x) ((x) << 5)
-/* PTE types (actially level 2 descriptor) */
-#define PTE_TYPE_MASK 0x0003
-#define PTE_TYPE_FAULT 0x0000
-#define PTE_TYPE_LARGE 0x0001
-#define PTE_TYPE_SMALL 0x0002
-#define PTE_AP_READ 0x0aa0
-#define PTE_AP_WRITE 0x0550
-#define PTE_CACHEABLE 0x0008
-#define PTE_BUFFERABLE 0x0004
-
-/* Domains */
+/*
+ * Domains
+ */
#define DOMAIN_USER 0
#define DOMAIN_KERNEL 1
#define DOMAIN_TABLE 1
#define DOMAIN_IO 2
-#define _PAGE_CHG_MASK (0xfffff00c | PTE_TYPE_MASK)
-/*
- * We define the bits in the page tables as follows:
- * PTE_BUFFERABLE page is dirty
- * PTE_AP_WRITE page is writable
- * PTE_AP_READ page is a young (unsetting this causes faults for any access)
- * PTE_CACHEABLE page is readable
- *
- * A page will not be made writable without the dirty bit set.
- * It is not legal to have a writable non-dirty page though (it breaks).
- *
- * A readable page is marked as being cacheable.
- * Youngness is indicated by hardware read. If the page is old,
- * then we will fault and make the page young again.
- */
-#define _PTE_YOUNG PTE_AP_READ
-#define _PTE_DIRTY PTE_BUFFERABLE
-#define _PTE_READ PTE_CACHEABLE
-#define _PTE_WRITE PTE_AP_WRITE
-#define PAGE_NONE __pgprot(PTE_TYPE_SMALL | _PTE_YOUNG)
-#define PAGE_SHARED __pgprot(PTE_TYPE_SMALL | _PTE_YOUNG | _PTE_READ | _PTE_WRITE)
-#define PAGE_COPY __pgprot(PTE_TYPE_SMALL | _PTE_YOUNG | _PTE_READ)
-#define PAGE_READONLY __pgprot(PTE_TYPE_SMALL | _PTE_YOUNG | _PTE_READ)
-#define PAGE_KERNEL __pgprot(PTE_TYPE_SMALL | _PTE_READ | _PTE_DIRTY | _PTE_WRITE)
-
-#define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_USER))
-#define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL))
+#undef TEST_VERIFY_AREA
/*
- * The arm can't do page protection for execute, and considers that the same are read.
- * Also, write permissions imply read permissions. This is the closest we can get..
+ * The sa110 doesn't have any external MMU info: the kernel page
+ * tables contain all the necessary information.
*/
-#define __P000 PAGE_NONE
-#define __P001 PAGE_READONLY
-#define __P010 PAGE_COPY
-#define __P011 PAGE_COPY
-#define __P100 PAGE_READONLY
-#define __P101 PAGE_READONLY
-#define __P110 PAGE_COPY
-#define __P111 PAGE_COPY
-
-#define __S000 PAGE_NONE
-#define __S001 PAGE_READONLY
-#define __S010 PAGE_SHARED
-#define __S011 PAGE_SHARED
-#define __S100 PAGE_READONLY
-#define __S101 PAGE_READONLY
-#define __S110 PAGE_SHARED
-#define __S111 PAGE_SHARED
+extern __inline__ void update_mmu_cache(struct vm_area_struct * vma,
+ unsigned long address, pte_t pte)
+{
+}
-#undef TEST_VERIFY_AREA
/*
* BAD_PAGETABLE is used when we need a bogus page-table, while
extern pte_t * __bad_pagetable(void);
extern unsigned long *empty_zero_page;
-#define BAD_PAGETABLE __bad_pagetable()
-#define BAD_PAGE __bad_page()
-#define ZERO_PAGE ((unsigned long) empty_zero_page)
+#define BAD_PAGETABLE __bad_pagetable()
+#define BAD_PAGE __bad_page()
+#define ZERO_PAGE ((unsigned long) empty_zero_page)
/* number of bits that fit into a memory pointer */
-#define BYTES_PER_PTR (sizeof(unsigned long))
-#define BITS_PER_PTR (8*BYTES_PER_PTR)
+#define BYTES_PER_PTR (sizeof(unsigned long))
+#define BITS_PER_PTR (8*BYTES_PER_PTR)
/* to align the pointer to a pointer address */
-#define PTR_MASK (~(sizeof(void*)-1))
+#define PTR_MASK (~(sizeof(void*)-1))
/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
-#define SIZEOF_PTR_LOG2 2
+#define SIZEOF_PTR_LOG2 2
/* to find an entry in a page-table */
#define PAGE_PTR(address) \
((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
-/* to set the page-dir */
+/* to set the page-dir
+ * Note that we need to flush the cache and TLBs
+ * if we are affecting the current task.
+ */
#define SET_PAGE_DIR(tsk,pgdir) \
do { \
tsk->tss.memmap = __virt_to_phys((unsigned long)pgdir); \
- if ((tsk) == current) \
+ if ((tsk) == current) { \
+ flush_cache_all(); \
__asm__ __volatile__( \
"mcr%? p15, 0, %0, c2, c0, 0\n" \
: : "r" (tsk->tss.memmap)); \
+ flush_tlb_all(); \
+ } \
} while (0)
-extern __inline__ int pte_none(pte_t pte)
-{
- return !pte_val(pte);
-}
-
-#define pte_clear(ptep) set_pte(ptep, __pte(0))
-
-extern __inline__ int pte_present(pte_t pte)
-{
-#if 0
- /* This is what it really does, the else
- part is just to make it easier for the compiler */
- switch (pte_val(pte) & PTE_TYPE_MASK) {
- case PTE_TYPE_LARGE:
- case PTE_TYPE_SMALL:
- return 1;
- default:
- return 0;
- }
-#else
- return ((pte_val(pte) + 1) & 2);
-#endif
-}
-
-extern __inline__ int pmd_none(pmd_t pmd)
-{
- return !pmd_val(pmd);
-}
-
-#define pmd_clear(pmdp) set_pmd(pmdp, __pmd(0))
-
-extern __inline__ int pmd_bad(pmd_t pmd)
-{
-#if 0
- /* This is what it really does, the else
- part is just to make it easier for the compiler */
- switch (pmd_val(pmd) & PMD_TYPE_MASK) {
- case PMD_TYPE_FAULT:
- case PMD_TYPE_TABLE:
- return 0;
- default:
- return 1;
- }
-#else
- return pmd_val(pmd) & 2;
-#endif
-}
-
-extern __inline__ int pmd_present(pmd_t pmd)
-{
-#if 0
- /* This is what it really does, the else
- part is just to make it easier for the compiler */
- switch (pmd_val(pmd) & PMD_TYPE_MASK) {
- case PMD_TYPE_TABLE:
- return 1;
- default:
- return 0;
- }
-#else
- return ((pmd_val(pmd) + 1) & 2);
-#endif
-}
/*
* The "pgd_xxx()" functions here are trivial for a folded two-level
#define pgd_present(pgd) (1)
#define pgd_clear(pgdp)
-/*
- * The following only work if pte_present() is true.
- * Undefined behaviour if not..
- */
-#define pte_read(pte) (1)
-#define pte_exec(pte) (1)
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
-extern __inline__ int pte_write(pte_t pte)
+/* to find an entry in a page-table-directory */
+extern __inline__ pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
{
- return pte_val(pte) & _PTE_WRITE;
+ return mm->pgd + (address >> PGDIR_SHIFT);
}
-extern __inline__ int pte_dirty(pte_t pte)
-{
- return pte_val(pte) & _PTE_DIRTY;
-}
+extern unsigned long get_page_2k(int priority);
+extern void free_page_2k(unsigned long page);
-extern __inline__ int pte_young(pte_t pte)
-{
- return pte_val(pte) & _PTE_YOUNG;
-}
+/*
+ * Allocate and free page tables. The xxx_kernel() versions are
+ * used to allocate a kernel page table - this turns on ASN bits
+ * if any.
+ */
-extern __inline__ pte_t pte_wrprotect(pte_t pte)
-{
- pte_val(pte) &= ~_PTE_WRITE;
- return pte;
-}
+#ifndef __SMP__
+extern struct pgtable_cache_struct {
+ unsigned long *pgd_cache;
+ unsigned long *pte_cache;
+ unsigned long pgtable_cache_sz;
+} quicklists;
-extern __inline__ pte_t pte_nocache(pte_t pte)
-{
- pte_val(pte) &= ~PTE_CACHEABLE;
- return pte;
-}
+#define pgd_quicklist (quicklists.pgd_cache)
+#define pmd_quicklist ((unsigned long *)0)
+#define pte_quicklist (quicklists.pte_cache)
+#define pgtable_cache_size (quicklists.pgtable_cache_sz)
+#else
+#error Pgtable caches have to be per-CPU, so that no locking is needed.
+#endif
-extern __inline__ pte_t pte_mkclean(pte_t pte)
-{
- pte_val(pte) &= ~_PTE_DIRTY;
- return pte;
-}
+extern pgd_t *get_pgd_slow(void);
-extern __inline__ pte_t pte_mkold(pte_t pte)
+extern __inline__ pgd_t *get_pgd_fast(void)
{
- pte_val(pte) &= ~_PTE_YOUNG;
- return pte;
+ unsigned long *ret;
+
+ if((ret = pgd_quicklist) != NULL) {
+ pgd_quicklist = (unsigned long *)(*ret);
+ ret[0] = ret[1];
+ clean_cache_area(ret, 4);
+ pgtable_cache_size--;
+ } else
+ ret = (unsigned long *)get_pgd_slow();
+ return (pgd_t *)ret;
}
-extern __inline__ pte_t pte_mkwrite(pte_t pte)
+extern __inline__ void free_pgd_fast(pgd_t *pgd)
{
- pte_val(pte) |= _PTE_WRITE;
- return pte;
+ *(unsigned long *)pgd = (unsigned long) pgd_quicklist;
+ pgd_quicklist = (unsigned long *) pgd;
+ pgtable_cache_size++;
}
-extern __inline__ pte_t pte_mkdirty(pte_t pte)
+extern __inline__ void free_pgd_slow(pgd_t *pgd)
{
- pte_val(pte) |= _PTE_DIRTY;
- return pte;
+ free_pages((unsigned long) pgd, 2);
}
-extern __inline__ pte_t pte_mkyoung(pte_t pte)
+#define pgd_free(pgd) free_pgd_fast(pgd)
+#define pgd_alloc() get_pgd_fast()
+
+extern __inline__ void set_pgdir(unsigned long address, pgd_t entry)
{
- pte_val(pte) |= _PTE_YOUNG;
- return pte;
+ struct task_struct * p;
+ pgd_t *pgd;
+
+ read_lock(&tasklist_lock);
+ for_each_task(p) {
+ if (!p->mm)
+ continue;
+ *pgd_offset(p->mm,address) = entry;
+ }
+ read_unlock(&tasklist_lock);
+ for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
+ pgd[address >> PGDIR_SHIFT] = entry;
}
-/*
- * The following are unable to be implemented on this MMU
- */
-#if 0
-extern __inline__ pte_t pte_rdprotect(pte_t pte)
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
+/****************
+* PMD functions *
+****************/
+
+/* PMD types (actually level 1 descriptor) */
+#define PMD_TYPE_MASK 0x0003
+#define PMD_TYPE_FAULT 0x0000
+#define PMD_TYPE_TABLE 0x0001
+#define PMD_TYPE_SECT 0x0002
+#define PMD_UPDATABLE 0x0010
+#define PMD_SECT_CACHEABLE 0x0008
+#define PMD_SECT_BUFFERABLE 0x0004
+#define PMD_SECT_AP_WRITE 0x0400
+#define PMD_SECT_AP_READ 0x0800
+#define PMD_DOMAIN(x) ((x) << 5)
+
+#define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_USER))
+#define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL))
+
+#define pmd_none(pmd) (!pmd_val(pmd))
+#define pmd_clear(pmdp) set_pmd(pmdp, __pmd(0))
+#define pmd_bad(pmd) (pmd_val(pmd) & 2)
+#define mk_user_pmd(ptep) __mk_pmd(ptep, _PAGE_USER_TABLE)
+#define mk_kernel_pmd(ptep) __mk_pmd(ptep, _PAGE_KERNEL_TABLE)
+#define set_pmd(pmdp,pmd) processor.u.armv3v4._set_pmd(pmdp,pmd)
+
+/* Find an entry in the second-level page table.. */
+#define pmd_offset(dir, address) ((pmd_t *)(dir))
+
+extern __inline__ int pmd_present(pmd_t pmd)
{
- pte_val(pte) &= ~(PTE_CACHEABLE|PTE_AP_READ);
- return pte;
+ return ((pmd_val(pmd) + 1) & 2);
}
-extern __inline__ pte_t pte_exprotect(pte_t pte)
+/* We don't use pmd cache, so this is a dummy routine */
+extern __inline__ pmd_t *get_pmd_fast(void)
{
- pte_val(pte) &= ~(PTE_CACHEABLE|PTE_AP_READ);
- return pte;
+ return (pmd_t *)0;
}
-extern __inline__ pte_t pte_mkread(pte_t pte)
+extern __inline__ void free_pmd_fast(pmd_t *pmd)
{
- pte_val(pte) |= PTE_CACHEABLE;
- return pte;
}
-extern __inline__ pte_t pte_mkexec(pte_t pte)
+extern __inline__ void free_pmd_slow(pmd_t *pmd)
{
- pte_val(pte) |= PTE_CACHEABLE;
- return pte;
}
-#endif
+
+extern void __bad_pmd(pmd_t *pmd);
+extern void __bad_pmd_kernel(pmd_t *pmd);
/*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
*/
-extern __inline__ pte_t mk_pte(unsigned long page, pgprot_t pgprot)
+extern __inline__ void pmd_free(pmd_t *pmd)
{
- pte_t pte;
- pte_val(pte) = __virt_to_phys(page) | pgprot_val(pgprot);
- return pte;
}
-/* This takes a physical page address that is used by the remapping functions */
-extern __inline__ pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
+extern __inline__ pmd_t *pmd_alloc(pgd_t *pgd, unsigned long address)
{
- pte_t pte;
- pte_val(pte) = physpage + pgprot_val(pgprot);
- return pte;
+ return (pmd_t *) pgd;
}
-extern __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot)
-{
- pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
- return pte;
-}
+#define pmd_free_kernel pmd_free
+#define pmd_alloc_kernel pmd_alloc
-extern __inline__ void set_pte(pte_t *pteptr, pte_t pteval)
+extern __inline__ pmd_t __mk_pmd(pte_t *ptep, unsigned long prot)
{
- *pteptr = pteval;
- __flush_pte_to_ram(pteptr);
-}
+ unsigned long pte_ptr = (unsigned long)ptep;
+ pmd_t pmd;
-extern __inline__ unsigned long pte_page(pte_t pte)
-{
- return __phys_to_virt(pte_val(pte) & PAGE_MASK);
-}
+ pte_ptr -= PTRS_PER_PTE * BYTES_PER_PTR;
-extern __inline__ pmd_t mk_user_pmd(pte_t *ptep)
-{
- pmd_t pmd;
- pmd_val(pmd) = __virt_to_phys((unsigned long)ptep) | _PAGE_USER_TABLE;
- return pmd;
-}
+ /*
+ * The pmd must be loaded with the physical
+ * address of the PTE table
+ */
+ pmd_val(pmd) = __virt_to_phys(pte_ptr) | prot;
-extern __inline__ pmd_t mk_kernel_pmd(pte_t *ptep)
-{
- pmd_t pmd;
- pmd_val(pmd) = __virt_to_phys((unsigned long)ptep) | _PAGE_KERNEL_TABLE;
return pmd;
}
-#if 1
-#define set_pmd(pmdp,pmd) processor.u.armv3v4._set_pmd(pmdp,pmd)
-#else
-extern __inline__ void set_pmd(pmd_t *pmdp, pmd_t pmd)
-{
- *pmdp = pmd;
- __flush_pte_to_ram(pmdp);
-}
-#endif
-
extern __inline__ unsigned long pmd_page(pmd_t pmd)
{
- return __phys_to_virt(pmd_val(pmd) & 0xfffffc00);
-}
+ unsigned long ptr;
-/* to find an entry in a kernel page-table-directory */
-#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+ ptr = pmd_val(pmd) & ~(PTRS_PER_PTE * BYTES_PER_PTR - 1);
-/* to find an entry in a page-table-directory */
-extern __inline__ pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
-{
- return mm->pgd + (address >> PGDIR_SHIFT);
+ ptr += PTRS_PER_PTE * BYTES_PER_PTR;
+
+ return __phys_to_virt(ptr);
}
-/* Find an entry in the second-level page table.. */
-#define pmd_offset(dir, address) ((pmd_t *)(dir))
-/* Find an entry in the third-level page table.. */
-extern __inline__ pte_t * pte_offset(pmd_t * dir, unsigned long address)
-{
- return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
-}
+/****************
+* PTE functions *
+****************/
-extern unsigned long get_small_page(int priority);
-extern void free_small_page(unsigned long page);
+/* PTE types (actially level 2 descriptor) */
+#define PTE_TYPE_MASK 0x0003
+#define PTE_TYPE_FAULT 0x0000
+#define PTE_TYPE_LARGE 0x0001
+#define PTE_TYPE_SMALL 0x0002
+#define PTE_AP_READ 0x0aa0
+#define PTE_AP_WRITE 0x0550
+#define PTE_CACHEABLE 0x0008
+#define PTE_BUFFERABLE 0x0004
+
+#define pte_none(pte) (!pte_val(pte))
+#define pte_clear(ptep) set_pte(ptep, __pte(0))
/*
- * Allocate and free page tables. The xxx_kernel() versions are
- * used to allocate a kernel page table - this turns on ASN bits
- * if any.
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
*/
-
-#ifndef __SMP__
-extern struct pgtable_cache_struct {
- unsigned long *pgd_cache;
- unsigned long *pte_cache;
- unsigned long pgtable_cache_sz;
-} quicklists;
-
-#define pgd_quicklist (quicklists.pgd_cache)
-#define pmd_quicklist ((unsigned long *)0)
-#define pte_quicklist (quicklists.pte_cache)
-#define pgtable_cache_size (quicklists.pgtable_cache_sz)
-#else
-#error Pgtable caches have to be per-CPU, so that no locking is needed.
-#endif
-
-extern pgd_t *get_pgd_slow(void);
-
-extern __inline__ pgd_t *get_pgd_fast(void)
+extern __inline__ pte_t mk_pte(unsigned long page, pgprot_t pgprot)
{
- unsigned long *ret;
-
- if((ret = pgd_quicklist) != NULL) {
- pgd_quicklist = (unsigned long *)(*ret);
- ret[0] = ret[1];
- pgtable_cache_size--;
- } else
- ret = (unsigned long *)get_pgd_slow();
- return (pgd_t *)ret;
+ pte_t pte;
+ pte_val(pte) = __virt_to_phys(page) | pgprot_val(pgprot);
+ return pte;
}
-extern __inline__ void free_pgd_fast(pgd_t *pgd)
+/* This takes a physical page address that is used by the remapping functions */
+extern __inline__ pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
{
- *(unsigned long *)pgd = (unsigned long) pgd_quicklist;
- pgd_quicklist = (unsigned long *) pgd;
- pgtable_cache_size++;
+ pte_t pte;
+ pte_val(pte) = physpage + pgprot_val(pgprot);
+ return pte;
}
-extern __inline__ void free_pgd_slow(pgd_t *pgd)
+#define set_pte(ptep, pte) processor.u.armv3v4._set_pte(ptep,pte)
+
+extern __inline__ unsigned long pte_page(pte_t pte)
{
- free_pages((unsigned long) pgd, 2);
+ return __phys_to_virt(pte_val(pte) & PAGE_MASK);
}
extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
if((ret = (unsigned long *)pte_quicklist) != NULL) {
pte_quicklist = (unsigned long *)(*ret);
ret[0] = ret[1];
+ clean_cache_area(ret, 4);
pgtable_cache_size--;
}
return (pte_t *)ret;
extern __inline__ void free_pte_slow(pte_t *pte)
{
- free_small_page((unsigned long)pte);
+ free_page_2k((unsigned long)(pte - PTRS_PER_PTE));
}
-/* We don't use pmd cache, so this is a dummy routine */
-extern __inline__ pmd_t *get_pmd_fast(void)
-{
- return (pmd_t *)0;
-}
+#define pte_free_kernel(pte) free_pte_fast(pte)
+#define pte_free(pte) free_pte_fast(pte)
-extern __inline__ void free_pmd_fast(pmd_t *pmd)
+/*###############################################################################
+ * New PageTableEntry stuff...
+ */
+/* We now keep two sets of ptes - the physical and the linux version.
+ * This gives us many advantages, and allows us greater flexibility.
+ *
+ * The Linux pte's contain:
+ * bit meaning
+ * 0 page present
+ * 1 young
+ * 2 bufferable - matches physical pte
+ * 3 cacheable - matches physical pte
+ * 4 user
+ * 5 write
+ * 6 execute
+ * 7 dirty
+ * 8-11 unused
+ * 12-31 virtual page address
+ *
+ * These are stored at the pte pointer; the physical PTE is at -1024bytes
+ */
+#define L_PTE_PRESENT (1 << 0)
+#define L_PTE_YOUNG (1 << 1)
+#define L_PTE_BUFFERABLE (1 << 2)
+#define L_PTE_CACHEABLE (1 << 3)
+#define L_PTE_USER (1 << 4)
+#define L_PTE_WRITE (1 << 5)
+#define L_PTE_EXEC (1 << 6)
+#define L_PTE_DIRTY (1 << 7)
+
+/*
+ * The following macros handle the cache and bufferable bits...
+ */
+#define _L_PTE_DEFAULT L_PTE_PRESENT | L_PTE_YOUNG
+#define _L_PTE_READ L_PTE_USER | L_PTE_CACHEABLE
+#define _L_PTE_EXEC _L_PTE_READ | L_PTE_EXEC
+
+#define PAGE_NONE __pgprot(_L_PTE_DEFAULT)
+#define PAGE_COPY __pgprot(_L_PTE_DEFAULT | _L_PTE_READ | L_PTE_BUFFERABLE)
+#define PAGE_SHARED __pgprot(_L_PTE_DEFAULT | _L_PTE_READ | L_PTE_BUFFERABLE | L_PTE_WRITE)
+#define PAGE_READONLY __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
+#define PAGE_KERNEL __pgprot(_L_PTE_DEFAULT | L_PTE_CACHEABLE | L_PTE_BUFFERABLE | L_PTE_DIRTY | L_PTE_WRITE)
+
+#define _PAGE_CHG_MASK (PAGE_MASK | L_PTE_DIRTY | L_PTE_YOUNG)
+
+/*
+ * The table below defines the page protection levels that we insert into our
+ * Linux page table version. These get translated into the best that the
+ * architecture can perform. Note that on most ARM hardware:
+ * 1) We cannot do execute protection
+ * 2) If we could do execute protection, then read is implied
+ * 3) write implies read permissions
+ */
+#define __P000 PAGE_NONE
+#define __P001 PAGE_READONLY
+#define __P010 PAGE_COPY
+#define __P011 PAGE_COPY
+#define __P100 PAGE_READONLY
+#define __P101 PAGE_READONLY
+#define __P110 PAGE_COPY
+#define __P111 PAGE_COPY
+
+#define __S000 PAGE_NONE
+#define __S001 PAGE_READONLY
+#define __S010 PAGE_SHARED
+#define __S011 PAGE_SHARED
+#define __S100 PAGE_READONLY
+#define __S101 PAGE_READONLY
+#define __S110 PAGE_SHARED
+#define __S111 PAGE_SHARED
+
+
+
+#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT)
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+#define pte_read(pte) (pte_val(pte) & L_PTE_USER)
+#define pte_write(pte) (pte_val(pte) & L_PTE_WRITE)
+#define pte_exec(pte) (pte_val(pte) & L_PTE_EXEC)
+#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY)
+#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG)
+
+#define PTE_BIT_FUNC(fn,op) \
+extern inline pte_t fn##(pte_t pte) { pte_val(pte) op##; return pte; }
+
+//PTE_BIT_FUNC(pte_rdprotect, &= ~L_PTE_USER);
+PTE_BIT_FUNC(pte_wrprotect, &= ~L_PTE_WRITE);
+PTE_BIT_FUNC(pte_exprotect, &= ~L_PTE_EXEC);
+PTE_BIT_FUNC(pte_mkclean, &= ~L_PTE_DIRTY);
+PTE_BIT_FUNC(pte_mkold, &= ~L_PTE_YOUNG);
+//PTE_BIT_FUNC(pte_mkread, |= L_PTE_USER);
+PTE_BIT_FUNC(pte_mkwrite, |= L_PTE_WRITE);
+PTE_BIT_FUNC(pte_mkexec, |= L_PTE_EXEC);
+PTE_BIT_FUNC(pte_mkdirty, |= L_PTE_DIRTY);
+PTE_BIT_FUNC(pte_mkyoung, |= L_PTE_YOUNG);
+PTE_BIT_FUNC(pte_nocache, &= ~L_PTE_CACHEABLE);
+
+extern __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
+ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
+ return pte;
}
-extern __inline__ void free_pmd_slow(pmd_t *pmd)
+/* Find an entry in the third-level page table.. */
+extern __inline__ pte_t * pte_offset(pmd_t * dir, unsigned long address)
{
+ return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
}
-extern void __bad_pmd(pmd_t *pmd);
-extern void __bad_pmd_kernel(pmd_t *pmd);
-
-#define pte_free_kernel(pte) free_pte_fast(pte)
-#define pte_free(pte) free_pte_fast(pte)
-#define pgd_free(pgd) free_pgd_fast(pgd)
-#define pgd_alloc() get_pgd_fast()
-
extern __inline__ pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address)
{
address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
return (pte_t *) pmd_page(*pmd) + address;
}
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-extern __inline__ void pmd_free(pmd_t *pmd)
-{
-}
-
-extern __inline__ pmd_t *pmd_alloc(pgd_t *pgd, unsigned long address)
-{
- return (pmd_t *) pgd;
-}
-
-#define pmd_free_kernel pmd_free
-#define pmd_alloc_kernel pmd_alloc
-
-extern __inline__ void set_pgdir(unsigned long address, pgd_t entry)
-{
- struct task_struct * p;
- pgd_t *pgd;
-
- read_lock(&tasklist_lock);
- for_each_task(p) {
- if (!p->mm)
- continue;
- *pgd_offset(p->mm,address) = entry;
- }
- read_unlock(&tasklist_lock);
- for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
- pgd[address >> PGDIR_SHIFT] = entry;
-}
-
-extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
-
-/*
- * The sa110 doesn't have any external MMU info: the kernel page
- * tables contain all the necessary information.
- */
-extern __inline__ void update_mmu_cache(struct vm_area_struct * vma,
- unsigned long address, pte_t pte)
-{
-}
-
#define SWP_TYPE(entry) (((entry) >> 2) & 0x7f)
#define SWP_OFFSET(entry) ((entry) >> 9)
#define SWP_ENTRY(type,offset) (((type) << 2) | ((offset) << 9))
#ifndef __ASM_PROC_PROCESSOR_H
#define __ASM_PROC_PROCESSOR_H
-#ifdef __KERNEL__
-
#define KERNEL_STACK_SIZE PAGE_SIZE
struct context_save_struct {
unsigned long pc;
};
-#define EXTRA_THREAD_STRUCT \
- struct context_save_struct *save; \
- unsigned long memmap;
+#define INIT_CSS (struct context_save_struct){ SVC_MODE, 0, 0, 0, 0, 0, 0, 0, 0 }
-#define EXTRA_THREAD_STRUCT_INIT \
- 0, \
- ((unsigned long) swapper_pg_dir) - PAGE_OFFSET
-
-DECLARE_THREAD_STRUCT;
-
-/*
- * Return saved PC of a blocked thread.
- */
-extern __inline__ unsigned long thread_saved_pc (struct thread_struct *t)
-{
- if (t->save)
- return t->save->pc;
- else
- return 0;
-}
-
-extern __inline__ unsigned long get_css_fp (struct thread_struct *t)
-{
- if (t->save)
- return t->save->fp;
- else
- return 0;
-}
-
-asmlinkage void ret_from_sys_call(void) __asm__ ("ret_from_sys_call");
-
-extern __inline__ void copy_thread_css (struct context_save_struct *save)
-{
- save->cpsr = SVC_MODE;
- save->r4 =
- save->r5 =
- save->r6 =
- save->r7 =
- save->r8 =
- save->r9 =
- save->fp = 0;
- save->pc = (unsigned long) ret_from_sys_call;
-}
+#define EXTRA_THREAD_STRUCT
+#define EXTRA_THREAD_STRUCT_INIT
+#define SWAPPER_PG_DIR (((unsigned long)swapper_pg_dir) - PAGE_OFFSET)
#define start_thread(regs,pc,sp) \
({ \
unsigned long *stack = (unsigned long *)sp; \
set_fs(USER_DS); \
memzero(regs->uregs, sizeof(regs->uregs)); \
- if (current->personality == PER_LINUX_32BIT) \
+ if (current->personality & ADDR_LIMIT_32BIT) \
regs->ARM_cpsr = USR_MODE; \
else \
regs->ARM_cpsr = USR26_MODE; \
/*
* NOTE! The task struct and the stack go together
*/
-#define alloc_task_struct() \
- ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
-#define free_task_struct(p) free_pages((unsigned long)(p),1)
-
-#endif
+#define ll_alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
+#define ll_free_task_struct(p) free_pages((unsigned long)(p),1)
#endif
#define CC_Z_BIT (1 << 30)
#define CC_N_BIT (1 << 31)
+#if 0 /* GCC/egcs should be able to optimise this, IMHO */
#define user_mode(regs) \
((((regs)->ARM_cpsr & MODE_MASK) == USR_MODE) || \
(((regs)->ARM_cpsr & MODE_MASK) == USR26_MODE))
+#else
+#define user_mode(regs) \
+ (((regs)->ARM_cpsr & 0xf) == 0)
+#endif
#define processor_mode(regs) \
((regs)->ARM_cpsr & MODE_MASK)
/* Are the current registers suitable for user mode?
* (used to maintain security in signal handlers)
*/
-#define valid_user_regs(regs) \
- (user_mode(regs) && ((regs)->ARM_sp & 3) == 0)
+static inline int valid_user_regs(struct pt_regs *regs)
+{
+ if ((regs->ARM_cpsr & 0xf) == 0 ||
+ (regs->ARM_cpsr & (F_BIT|I_BIT)))
+ return 1;
+
+ /*
+ * Force CPSR to something logical...
+ */
+ regs->ARM_cpsr &= (CC_V_BIT|CC_C_BIT|CC_Z_BIT|CC_N_BIT|0x10);
+
+ return 0;
+}
#endif
return temp;
}
+extern inline int down_trylock(struct semaphore *sem)
+{
+ unsigned int cpsr, temp;
+
+ __asm__ __volatile__ ("
+ @ atomic down try lock operation
+ mrs %0, cpsr
+ orr %1, %0, #128 @ disable IRQs
+ bic %0, %0, #0x80000000 @ clear N
+ msr cpsr, %1
+ ldr %1, [%2]
+ subs %1, %1, #1
+ orrmi %0, %0, #0x80000000 @ set N
+ str %1, [%2]
+ msr cpsr, %0
+ movmi r0, %2
+ movpl r0, #0
+ blmi " SYMBOL_NAME_STR(__down_trylock_failed) "
+ mov %1, r0"
+ : "=&r" (cpsr), "=&r" (temp)
+ : "r" (sem)
+ : "r0", "lr", "cc");
+
+ return temp;
+}
+
/*
* Note! This is subtle. We jump to wake people up only if
* the semaphore was negative (== somebody was waiting on it).
" .section .fixup,\"ax\"\n" \
" .align 2\n" \
"3: mvn %0, %3\n" \
+ " mov %1, #0\n" \
" b 2b\n" \
" .previous\n" \
" .section __ex_table,\"a\"\n" \
" .section .fixup,\"ax\"\n" \
" .align 2\n" \
"4: mvn %0, %5\n" \
+ " mov %1, #0\n" \
" b 3b\n" \
" .previous\n" \
" .section __ex_table,\"a\"\n" \
" .section .fixup,\"ax\"\n" \
" .align 2\n" \
"3: mvn %0, %3\n" \
+ " mov %1, #0\n" \
" b 2b\n" \
" .previous\n" \
" .section __ex_table,\"a\"\n" \
#include <asm/page.h>
#ifdef __KERNEL__
+
+/* forward-decare task_struct */
+struct task_struct;
+
/*
* Don't change this structure
*/
*
* flush caches for task switch
*/
- void (*_switch_to)(void *prev, void *next);
+ struct task_struct *(*_switch_to)(struct task_struct *prev, struct task_struct *next);
/*
* get data abort address/flags
*/
*/
void (*_flush_cache_entry)(unsigned long address);
/*
- * flush a virtual address used for a page table
- * note D-cache only!
+ * clean a virtual address range from the
+ * D-cache without flushing the cache.
*/
- void (*_flush_cache_pte)(unsigned long address);
+ void (*_clean_cache_area)(unsigned long start, unsigned long size);
/*
* flush a page to RAM
*/
* Set a PMD (handling IMP bit 4)
*/
void (*_set_pmd)(pmd_t *pmdp, pmd_t pmd);
+ /*
+ * Set a PTE
+ */
+ void (*_set_pte)(pte_t *ptep, pte_t pte);
/*
* Special stuff for a reset
*/
/*
* flush an icached page
*/
- void (*_flush_icache_area)(unsigned long start, unsigned long end);
+ void (*_flush_icache_area)(unsigned long start, unsigned long size);
/*
* write back dirty cached data
*/
#ifndef __ASM_ARM_PROCESSOR_H
#define __ASM_ARM_PROCESSOR_H
+#define FP_SIZE 35
+
struct fp_hard_struct {
- unsigned int save[140/4]; /* as yet undefined */
+ unsigned int save[FP_SIZE]; /* as yet undefined */
};
struct fp_soft_struct {
- unsigned int save[140/4]; /* undefined information */
+ unsigned int save[FP_SIZE]; /* undefined information */
};
union fp_state {
typedef unsigned long mm_segment_t; /* domain register */
-#define NR_DEBUGS 5
+#ifdef __KERNEL__
-#define DECLARE_THREAD_STRUCT \
-struct thread_struct { \
- unsigned long address; /* Address of fault */ \
- unsigned long trap_no; /* Trap number */ \
- unsigned long error_code; /* Error code of trap */ \
- union fp_state fpstate; /* FPE save state */ \
- unsigned long debug[NR_DEBUGS]; /* Debug/ptrace */ \
- EXTRA_THREAD_STRUCT \
-}
+#include <asm/assembler.h>
+
+#define NR_DEBUGS 5
#include <asm/arch/processor.h>
#include <asm/proc/processor.h>
-#define INIT_TSS { \
- 0, \
- 0, \
- 0, \
- { { { 0, }, }, }, \
- { 0, }, \
- EXTRA_THREAD_STRUCT_INIT \
+struct thread_struct {
+ unsigned long address; /* Address of fault */
+ unsigned long trap_no; /* Trap number */
+ unsigned long error_code; /* Error code of trap */
+ union fp_state fpstate; /* FPE save state */
+ unsigned long debug[NR_DEBUGS]; /* Debug/ptrace */
+ struct context_save_struct *save; /* context save */
+ unsigned long memmap; /* page tables */
+ EXTRA_THREAD_STRUCT
+};
+
+#define INIT_MMAP \
+{ &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
+
+#define INIT_TSS { \
+ 0, \
+ 0, \
+ 0, \
+ { { { 0, }, }, }, \
+ { 0, }, \
+ (struct context_save_struct *)0, \
+ SWAPPER_PG_DIR \
+ EXTRA_THREAD_STRUCT_INIT \
+}
+
+/*
+ * Return saved PC of a blocked thread.
+ */
+extern __inline__ unsigned long thread_saved_pc(struct thread_struct *t)
+{
+ return t->save ? t->save->pc & ~PCMASK : 0;
+}
+
+extern __inline__ unsigned long get_css_fp(struct thread_struct *t)
+{
+ return t->save ? t->save->fp : 0;
+}
+
+asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call");
+
+extern __inline__ void init_thread_css(struct context_save_struct *save)
+{
+ *save = INIT_CSS;
+ save->pc |= (unsigned long)ret_from_sys_call;
}
/* Forward declaration, a strange C thing */
#define release_segments(mm) do { } while (0)
#define forget_segments() do { } while (0)
+extern struct task_struct *alloc_task_struct(void);
+extern void free_task_struct(struct task_struct *);
+
#define init_task (init_task_union.task)
#define init_stack (init_task_union.stack)
+#endif
+
#endif /* __ASM_ARM_PROCESSOR_H */
--- /dev/null
+#ifndef ASMARM_SEMAPHORE_HELPER_H
+#define ASMARM_SEMAPHORE_HELPER_H
+
+/*
+ * These two _must_ execute atomically wrt each other.
+ */
+static inline void wake_one_more(struct semaphore * sem)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&semaphore_wake_lock, flags);
+ if (atomic_read(&sem->count) <= 0)
+ sem->waking++;
+ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+}
+
+static inline int waking_non_zero(struct semaphore *sem)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&semaphore_wake_lock, flags);
+ if (sem->waking > 0) {
+ sem->waking--;
+ ret = 1;
+ }
+ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+ return ret;
+}
+
+/*
+ * waking non zero interruptible
+ * 1 got the lock
+ * 0 go to sleep
+ * -EINTR interrupted
+ *
+ * We must undo the sem->count down_interruptible() increment while we are
+ * protected by the spinlock in order to make this atomic_inc() with the
+ * atomic_read() in wake_one_more(), otherwise we can race. -arca
+ */
+static inline int waking_non_zero_interruptible(struct semaphore *sem,
+ struct task_struct *tsk)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&semaphore_wake_lock, flags);
+ if (sem->waking > 0) {
+ sem->waking--;
+ ret = 1;
+ } else if (signal_pending(tsk)) {
+ atomic_inc(&sem->count);
+ ret = -EINTR;
+ }
+ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+ return ret;
+}
+
+/*
+ * waking_non_zero_try_lock:
+ * 1 failed to lock
+ * 0 got the lock
+ *
+ * We must undo the sem->count down_interruptible() increment while we are
+ * protected by the spinlock in order to make this atomic_inc() with the
+ * atomic_read() in wake_one_more(), otherwise we can race. -arca
+ */
+static inline int waking_non_zero_trylock(struct semaphore *sem)
+{
+ unsigned long flags;
+ int ret = 1;
+
+ spin_lock_irqsave(&semaphore_wake_lock, flags);
+ if (sem->waking <= 0)
+ atomic_inc(&sem->count);
+ else {
+ sem->waking--;
+ ret = 0;
+ }
+ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+ return ret;
+}
+
+#endif
asmlinkage void __down_failed (void /* special register calling convention */);
asmlinkage int __down_interruptible_failed (void /* special register calling convention */);
+asmlinkage int __down_failed_trylock(void /* params in registers */);
asmlinkage void __up_wakeup (void /* special register calling convention */);
extern void __down(struct semaphore * sem);
extern int __down_interruptible(struct semaphore * sem);
+extern int __down_trylock(struct semaphore * sem);
extern void __up(struct semaphore * sem);
#define sema_init(sem, val) atomic_set(&((sem)->count), (val))
-/*
- * These two _must_ execute atomically wrt each other.
- *
- * This is trivially done with load_locked/store_cond,
- * but on the x86 we need an external synchronizer.
- * Currently this is just the global interrupt lock,
- * bah. Go for a smaller spinlock some day.
- *
- * (On the other hand this shouldn't be in any critical
- * path, so..)
- */
-static inline void wake_one_more(struct semaphore * sem)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
- sem->waking++;
- restore_flags(flags);
-}
-
-static inline int waking_non_zero(struct semaphore *sem, struct task_struct *tsk)
-{
- unsigned long flags;
- int ret = 0;
-
- save_flags(flags);
- cli();
- if (sem->waking > 0) {
- sem->waking--;
- ret = 1;
- }
- restore_flags(flags);
- return ret;
-}
-
#include <asm/proc/semaphore.h>
#endif
#ifndef __ASM_ARM_SYSTEM_H
#define __ASM_ARM_SYSTEM_H
+#include <linux/kernel.h>
+
+#ifdef __KERNEL__
+
#include <linux/config.h>
+#define __ebsa285_data __attribute__((__section__(".data.ebsa285")))
+#define __netwinder_data __attribute__((__section__(".data.netwinder")))
+
+#ifdef CONFIG_TEXT_SECTIONS
+#define __ebsa285_text __attribute__((__section__(".text.ebsa285")))
+#define __netwinder_text __attribute__((__section__(".text.netwinder")))
+#else
+#define __ebsa285_text
+#define __netwinder_text
+#endif
+
/* The type of machine we're running on */
-extern unsigned int machine_type;
+extern unsigned int __machine_arch_type;
+
#define MACH_TYPE_EBSA110 0
#define MACH_TYPE_RISCPC 1
#define MACH_TYPE_NEXUSPCI 3
#define MACH_TYPE_NETWINDER 5
#define MACH_TYPE_CATS 6
#define MACH_TYPE_TBOX 7
+#define MACH_TYPE_CO285 8
+#define MACH_TYPE_CLPS7110 9
+#define MACH_TYPE_ARCHIMEDES 10
+#define MACH_TYPE_A5K 11
+
+/*
+ * Sort out a definition for machine_arch_type
+ * The rules basically are:
+ * 1. If one architecture is selected, then all machine_is_xxx()
+ * are constant.
+ * 2. If two or more architectures are selected, then the selected
+ * machine_is_xxx() are variable, and the unselected machine_is_xxx()
+ * are constant zero.
+ */
+#ifdef CONFIG_ARCH_EBSA110
+# ifdef machine_arch_type
+# undef machine_arch_type
+# define machine_arch_type __machine_arch_type
+# else
+# define machine_arch_type MACH_TYPE_EBSA110
+# endif
+# define machine_is_ebsa110() (machine_arch_type == MACH_TYPE_EBSA110)
+#else
+# define machine_is_ebsa110() (0)
+#endif
+
+#ifdef CONFIG_ARCH_RPC
+# ifdef machine_arch_type
+# undef machine_arch_type
+# define machine_arch_type __machine_arch_type
+# else
+# define machine_arch_type MACH_TYPE_RISCPC
+# endif
+# define machine_is_riscpc() (machine_arch_type == MACH_TYPE_RISCPC)
+#else
+# define machine_is_riscpc() (0)
+#endif
#ifdef CONFIG_ARCH_EBSA285
-#define machine_is_ebsa285() (1)
+# ifdef machine_arch_type
+# undef machine_arch_type
+# define machine_arch_type __machine_arch_type
+# else
+# define machine_arch_type MACH_TYPE_EBSA285
+# endif
+# define machine_is_ebsa285() (machine_arch_type == MACH_TYPE_EBSA285)
#else
-#define machine_is_ebsa285() (0)
+# define machine_is_ebsa285() (0)
#endif
-#ifdef CONFIG_ARCH_VNC
-#define machine_is_netwinder() (1)
+#ifdef CONFIG_ARCH_NETWINDER
+# ifdef machine_arch_type
+# undef machine_arch_type
+# define machine_arch_type __machine_arch_type
+# else
+# define machine_arch_type MACH_TYPE_NETWINDER
+# endif
+# define machine_is_netwinder() (machine_arch_type == MACH_TYPE_NETWINDER)
#else
-#define machine_is_netwinder() (0)
+# define machine_is_netwinder() (0)
#endif
-#if defined(CONFIG_CATS)
-#define machine_is_cats() (machine_type == MACH_TYPE_CATS)
+#ifdef CONFIG_CATS
+# ifdef machine_arch_type
+# undef machine_arch_type
+# define machine_arch_type __machine_arch_type
+# else
+# define machine_arch_type MACH_TYPE_CATS
+# endif
+# define machine_is_cats() (machine_arch_type == MACH_TYPE_CATS)
#else
-#define machine_is_cats() (0)
+# define machine_is_cats() (0)
#endif
-#if 0
-#define machine_is_ebsa285() (machine_type == MACH_TYPE_EBSA285)
-#define machine_is_netwinder() (machine_type == MACH_TYPE_NETWINDER)
+#ifdef CONFIG_ARCH_CO285
+# ifdef machine_arch_type
+# undef machine_arch_type
+# define machine_arch_type __machine_arch_type
+# else
+# define machine_arch_type MACH_TYPE_CO285
+# endif
+# define machine_is_co285() (machine_arch_type == MACH_TYPE_CO285)
+#else
+# define machine_is_co285() (0)
#endif
-#include <linux/kernel.h>
+#ifndef machine_arch_type
+#define machine_arch_type __machine_arch_type
+#endif
+
+/*
+ * task_struct isn't always declared - forward-declare it here.
+ */
+struct task_struct;
+
#include <asm/proc-fns.h>
extern void arm_malalignedptr(const char *, void *, volatile void *);
*
* `next' and `prev' should be struct task_struct, but it isn't always defined
*/
-#define switch_to(prev,next) processor._switch_to(prev,next)
+#define switch_to(prev,next,last) do { last = processor._switch_to(prev,next); } while (0)
/*
* Include processor dependent parts
#include <asm/arch/system.h>
#define mb() __asm__ __volatile__ ("" : : : "memory")
-#define nop() __asm__ __volatile__("mov r0,r0\n\t");
+#define rmb() mb()
+#define wmb() mb()
+#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
extern asmlinkage void __backtrace(void);
#endif
+#endif
#define __NR_capset (__NR_SYSCALL_BASE+185)
#define __NR_sigaltstack (__NR_SYSCALL_BASE+186)
#define __NR_sendfile (__NR_SYSCALL_BASE+187)
+ /* 188 reserved */
+ /* 189 reserved */
+#define __NR_vfork (__NR_SYSCALL_BASE+190)
#define __sys2(x) #x
#define __sys1(x) __sys2(x)
static inline int _exit(int exitcode)
{
- extern int sys_exit(int);
+ extern int sys_exit(int) __attribute__((noreturn));
return sys_exit(exitcode);
}
static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp);
/*
- * This is the mechanism for creating a new kernel thread.
- *
- * NOTE! Only a kernel-only process(ie the swapper or direct descendants
- * who haven't done an "execve()") should use this: it will work within
- * a system call from a "real" process, but the process memory space will
- * not be free'd until both the parent and the child have exited.
+ * Create a new kernel thread
*/
-static inline pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
- long retval;
-
- __asm__ __volatile__("
- mov r0,%1
- mov r1,%2
- "__syscall(clone)"
- teq r0, #0
- bne 1f
- mov r0,%4
- mov lr, pc
- mov pc, %3
- "__syscall(exit)"
-1: mov %0,r0"
- : "=r" (retval)
- : "Ir" (flags | CLONE_VM), "Ir" (NULL), "r" (fn), "Ir" (arg)
- : "r0","r1","r2","r3","lr");
-
- return retval;
-}
+extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
#endif
-
#endif /* __ASM_ARM_UNISTD_H */
#ifndef ASMARM_VGA_H
#define ASMARM_VGA_H
+#include <asm/hardware.h>
#include <asm/io.h>
-#define VGA_MAP_MEM(x) (0xe0000000 + (x))
+#define VGA_MAP_MEM(x) (PCIMEM_BASE + (x))
#define vga_readb(x) (*(x))
#define vga_writeb(x,y) (*(y) = (x))
};
struct dentry_operations {
- int (*d_revalidate)(struct dentry *);
+ int (*d_revalidate)(struct dentry *, int);
int (*d_hash) (struct dentry *, struct qstr *);
int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
void (*d_delete)(struct dentry *);
#define PTR_ERR(ptr) ((long)(ptr))
#define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000))
+/*
+ * The bitmask for a lookup event:
+ * - follow links at the end
+ * - require a directory
+ * - ending slashes ok even for nonexistent files
+ * - internal "there are more path compnents" flag
+ */
+#define LOOKUP_FOLLOW (1)
+#define LOOKUP_DIRECTORY (2)
+#define LOOKUP_SLASHOK (4)
+#define LOOKUP_CONTINUE (8)
+
extern struct dentry * lookup_dentry(const char *, struct dentry *, unsigned int);
extern struct dentry * __namei(const char *, unsigned int);
+++ /dev/null
-/* mc146818rtc.h - register definitions for the Real-Time-Clock / CMOS RAM
- * Copyright Torsten Duwe <duwe@informatik.uni-erlangen.de> 1993
- * derived from Data Sheet, Copyright Motorola 1984 (!).
- * It was written to be part of the Linux operating system.
- */
-/* permission is hereby granted to copy, modify and redistribute this code
- * in terms of the GNU Library General Public License, Version 2 or later,
- * at your option.
- */
-
-#ifndef _MC146818RTC_H
-#define _MC146818RTC_H
-#include <asm/io.h>
-
-#ifndef RTC_PORT
-#define RTC_PORT(x) (0x70 + (x))
-#define RTC_ALWAYS_BCD 1
-#endif
-
-#define CMOS_READ(addr) ({ \
-outb_p((addr),RTC_PORT(0)); \
-inb_p(RTC_PORT(1)); \
-})
-#define CMOS_WRITE(val, addr) ({ \
-outb_p((addr),RTC_PORT(0)); \
-outb_p((val),RTC_PORT(1)); \
-})
-
-/**********************************************************************
- * register summary
- **********************************************************************/
-#define RTC_SECONDS 0
-#define RTC_SECONDS_ALARM 1
-#define RTC_MINUTES 2
-#define RTC_MINUTES_ALARM 3
-#define RTC_HOURS 4
-#define RTC_HOURS_ALARM 5
-/* RTC_*_alarm is always true if 2 MSBs are set */
-# define RTC_ALARM_DONT_CARE 0xC0
-
-#define RTC_DAY_OF_WEEK 6
-#define RTC_DAY_OF_MONTH 7
-#define RTC_MONTH 8
-#define RTC_YEAR 9
-
-/* control registers - Moto names
- */
-#define RTC_REG_A 10
-#define RTC_REG_B 11
-#define RTC_REG_C 12
-#define RTC_REG_D 13
-
-/**********************************************************************
- * register details
- **********************************************************************/
-#define RTC_FREQ_SELECT RTC_REG_A
-
-/* update-in-progress - set to "1" 244 microsecs before RTC goes off the bus,
- * reset after update (may take 1.984ms @ 32768Hz RefClock) is complete,
- * totalling to a max high interval of 2.228 ms.
- */
-# define RTC_UIP 0x80
-# define RTC_DIV_CTL 0x70
- /* divider control: refclock values 4.194 / 1.049 MHz / 32.768 kHz */
-# define RTC_REF_CLCK_4MHZ 0x00
-# define RTC_REF_CLCK_1MHZ 0x10
-# define RTC_REF_CLCK_32KHZ 0x20
- /* 2 values for divider stage reset, others for "testing purposes only" */
-# define RTC_DIV_RESET1 0x60
-# define RTC_DIV_RESET2 0x70
- /* Periodic intr. / Square wave rate select. 0=none, 1=32.8kHz,... 15=2Hz */
-# define RTC_RATE_SELECT 0x0F
-
-/**********************************************************************/
-#define RTC_CONTROL RTC_REG_B
-# define RTC_SET 0x80 /* disable updates for clock setting */
-# define RTC_PIE 0x40 /* periodic interrupt enable */
-# define RTC_AIE 0x20 /* alarm interrupt enable */
-# define RTC_UIE 0x10 /* update-finished interrupt enable */
-# define RTC_SQWE 0x08 /* enable square-wave output */
-# define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
-# define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */
-# define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */
-
-/**********************************************************************/
-#define RTC_INTR_FLAGS RTC_REG_C
-/* caution - cleared by read */
-# define RTC_IRQF 0x80 /* any of the following 3 is active */
-# define RTC_PF 0x40
-# define RTC_AF 0x20
-# define RTC_UF 0x10
-
-/**********************************************************************/
-#define RTC_VALID RTC_REG_D
-# define RTC_VRT 0x80 /* valid RAM and time */
-/**********************************************************************/
-
-/* example: !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
- * determines if the following two #defines are needed
- */
-#ifndef BCD_TO_BIN
-#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
-#endif
-
-#ifndef BIN_TO_BCD
-#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
-#endif
-
-/*
- * The struct used to pass data via the following ioctl. Similar to the
- * struct tm in <time.h>, but it needs to be here so that the kernel
- * source is self contained, allowing cross-compiles, etc. etc.
- */
-
-struct rtc_time {
- int tm_sec;
- int tm_min;
- int tm_hour;
- int tm_mday;
- int tm_mon;
- int tm_year;
- int tm_wday;
- int tm_yday;
- int tm_isdst;
-};
-
-/*
- * ioctl calls that are permitted to the /dev/rtc interface, if
- * CONFIG_RTC was enabled.
- */
-
-#define RTC_AIE_ON _IO('p', 0x01) /* Alarm int. enable on */
-#define RTC_AIE_OFF _IO('p', 0x02) /* ... off */
-#define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */
-#define RTC_UIE_OFF _IO('p', 0x04) /* ... off */
-#define RTC_PIE_ON _IO('p', 0x05) /* Periodic int. enable on */
-#define RTC_PIE_OFF _IO('p', 0x06) /* ... off */
-
-#define RTC_ALM_SET _IOW('p', 0x07, struct rtc_time) /* Set alarm time */
-#define RTC_ALM_READ _IOR('p', 0x08, struct rtc_time) /* Read alarm time */
-#define RTC_RD_TIME _IOR('p', 0x09, struct rtc_time) /* Read RTC time */
-#define RTC_SET_TIME _IOW('p', 0x0a, struct rtc_time) /* Set RTC time */
-#define RTC_IRQP_READ _IOR('p', 0x0b, unsigned long) /* Read IRQ rate */
-#define RTC_IRQP_SET _IOW('p', 0x0c, unsigned long) /* Set IRQ rate */
-#define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */
-#define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */
-
-
-#endif /* _MC146818RTC_H */
extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
extern int nfs_revalidate(struct dentry *);
extern int nfs_open(struct inode *, struct file *);
+extern int nfs_release(struct inode *, struct file *);
extern int _nfs_revalidate_inode(struct nfs_server *, struct dentry *);
/*