From: Andy P. <at...@us...> - 2002-04-10 18:36:15
|
Update of /cvsroot/linux-vax/kernel-2.4/arch/m68k/sun3 In directory usw-pr-cvs1:/tmp/cvs-serv13561/m68k/sun3 Modified Files: Makefile config.c dvma.c idprom.c intersil.c mmu_emu.c sbus.c sun3_ksyms.c sun3ints.c Added Files: sun3dvma.c Log Message: synch 2.4.15 commit 37 --- NEW FILE --- /* * linux/arch/m68k/mm/sun3dvma.c * * Copyright (C) 2000 Sam Creasey * * Contains common routines for sun3/sun3x DVMA management. */ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/list.h> #include <asm/page.h> #include <asm/pgtable.h> #include <asm/dvma.h> #ifdef CONFIG_SUN3X extern void dvma_unmap_iommu(unsigned long baddr, int len); #else static inline void dvma_unmap_iommu(unsigned long a, int b) { } #endif unsigned long iommu_use[IOMMU_TOTAL_ENTRIES]; #define dvma_index(baddr) ((baddr - DVMA_START) >> DVMA_PAGE_SHIFT) #define dvma_entry_use(baddr) (iommu_use[dvma_index(baddr)]) struct hole { unsigned long start; unsigned long end; unsigned long size; struct list_head list; }; static struct list_head hole_list; static struct list_head hole_cache; static struct hole initholes[64]; static inline int refill(void) { struct hole *hole; struct hole *prev = NULL; struct list_head *cur; int ret = 0; list_for_each(cur, &hole_list) { hole = list_entry(cur, struct hole, list); if(!prev) { prev = hole; continue; } if(hole->end == prev->start) { hole->size += prev->size; hole->end = prev->end; list_del(&(prev->list)); list_add(&(prev->list), &hole_cache); ret++; } } return ret; } static inline struct hole *rmcache(void) { struct hole *ret; if(list_empty(&hole_cache)) { if(!refill()) { printk("out of dvma hole cache!\n"); BUG(); } } ret = list_entry(hole_cache.next, struct hole, list); list_del(&(ret->list)); return ret; } static inline unsigned long get_baddr(int len, unsigned long align) { struct list_head *cur; struct hole *hole; if(list_empty(&hole_list)) { printk("out of dvma holes!\n"); BUG(); } list_for_each(cur, &hole_list) { unsigned long newlen; hole = list_entry(cur, struct hole, list); if(align > DVMA_PAGE_SIZE) newlen = len + ((hole->end - len) & (align-1)); else newlen = len; if(hole->size > newlen) { hole->end -= newlen; hole->size -= newlen; dvma_entry_use(hole->end) = newlen; return hole->end; } else if(hole->size == newlen) { list_del(&(hole->list)); list_add(&(hole->list), &hole_cache); dvma_entry_use(hole->start) = newlen; return hole->start; } } printk("unable to find dvma hole!\n"); BUG(); return 0; } static inline int free_baddr(unsigned long baddr) { unsigned long len; struct hole *hole; struct list_head *cur; unsigned long orig_baddr; orig_baddr = baddr; len = dvma_entry_use(baddr); dvma_entry_use(baddr) = 0; baddr &= DVMA_PAGE_MASK; dvma_unmap_iommu(baddr, len); list_for_each(cur, &hole_list) { hole = list_entry(cur, struct hole, list); if(hole->end == baddr) { hole->end += len; hole->size += len; return 0; } else if(hole->start == (baddr + len)) { hole->start = baddr; hole->size += len; return 0; } } hole = rmcache(); hole->start = baddr; hole->end = baddr + len; hole->size = len; // list_add_tail(&(hole->list), cur); list_add(&(hole->list), cur); return 0; } void dvma_init(void) { struct hole *hole; int i; INIT_LIST_HEAD(&hole_list); INIT_LIST_HEAD(&hole_cache); /* prepare the hole cache */ for(i = 0; i < 64; i++) list_add(&(initholes[i].list), &hole_cache); hole = rmcache(); hole->start = DVMA_START; hole->end = DVMA_END; hole->size = DVMA_SIZE; list_add(&(hole->list), &hole_list); memset(iommu_use, 0, sizeof(iommu_use)); dvma_unmap_iommu(DVMA_START, DVMA_SIZE); #ifdef CONFIG_SUN3 sun3_dvma_init(); #endif } inline unsigned long dvma_map_align(unsigned long kaddr, int len, int align) { unsigned long baddr; unsigned long off; if(!len) len = 0x800; if(!kaddr || !len) { // printk("error: kaddr %lx len %x\n", kaddr, len); // *(int *)4 = 0; return 0; } #ifdef DEBUG printk("dvma_map request %08lx bytes from %08lx\n", len, kaddr); #endif off = kaddr & ~DVMA_PAGE_MASK; kaddr &= PAGE_MASK; len += off; len = ((len + (DVMA_PAGE_SIZE-1)) & DVMA_PAGE_MASK); if(align == 0) align = DVMA_PAGE_SIZE; else align = ((align + (DVMA_PAGE_SIZE-1)) & DVMA_PAGE_MASK); baddr = get_baddr(len, align); // printk("using baddr %lx\n", baddr); if(!dvma_map_iommu(kaddr, baddr, len)) return (baddr + off); printk("dvma_map failed kaddr %lx baddr %lx len %x\n", kaddr, baddr, len); BUG(); return 0; } void dvma_unmap(void *baddr) { free_baddr((unsigned long)baddr); return; } void *dvma_malloc_align(unsigned long len, unsigned long align) { unsigned long kaddr; unsigned long baddr; unsigned long vaddr; if(!len) return NULL; #ifdef DEBUG printk("dvma_malloc request %lx bytes\n", len); #endif len = ((len + (DVMA_PAGE_SIZE-1)) & DVMA_PAGE_MASK); if((kaddr = __get_free_pages(GFP_ATOMIC, get_order(len))) == 0) return NULL; if((baddr = (unsigned long)dvma_map_align(kaddr, len, align)) == 0) { free_pages(kaddr, get_order(len)); return NULL; } vaddr = dvma_btov(baddr); if(dvma_map_cpu(kaddr, vaddr, len) < 0) { dvma_unmap((void *)baddr); free_pages(kaddr, get_order(len)); return NULL; } #ifdef DEBUG printk("mapped %08lx bytes %08lx kern -> %08lx bus\n", len, kaddr, baddr); #endif return (void *)vaddr; } void dvma_free(void *vaddr) { return; } Index: Makefile =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/m68k/sun3/Makefile,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- Makefile 14 Jan 2001 19:42:22 -0000 1.1.1.1 +++ Makefile 10 Apr 2002 14:34:37 -0000 1.2 @@ -14,7 +14,9 @@ export-objs := sun3_ksyms.o -obj-y := config.o idprom.o mmu_emu.o sun3ints.o leds.o dvma.o \ - sbus.o intersil.o sun3_ksyms.o +obj-y := sun3_ksyms.o sun3ints.o sun3dvma.o sbus.o + +obj-$(CONFIG_SUN3) += config.o idprom.o mmu_emu.o leds.o dvma.o \ + intersil.o include $(TOPDIR)/Rules.make Index: config.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/m68k/sun3/config.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- config.c 14 Jan 2001 19:42:23 -0000 1.1.1.1 +++ config.c 10 Apr 2002 14:34:37 -0000 1.2 @@ -8,13 +8,10 @@ * for more details. */ -#include <stdarg.h> - #include <linux/config.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/mm.h> -#include <linux/kd.h> #include <linux/tty.h> #include <linux/console.h> #include <linux/init.h> @@ -27,10 +24,12 @@ #include <asm/pgtable.h> #include <asm/sun3-head.h> #include <asm/sun3mmu.h> +#include <asm/rtc.h> #include <asm/machdep.h> #include <asm/intersil.h> #include <asm/irq.h> #include <asm/segment.h> +#include <asm/sun3ints.h> extern char _text, _end; @@ -39,15 +38,6 @@ extern unsigned long sun3_gettimeoffset(void); extern int sun3_get_irq_list (char *); extern void sun3_sched_init(void (*handler)(int, void *, struct pt_regs *)); -extern void sun3_init_IRQ (void); -extern void (*sun3_default_handler[]) (int, void *, struct pt_regs *); -extern int sun3_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id); -extern void sun3_free_irq (unsigned int irq, void *dev_id); -extern void sun3_enable_irq (unsigned int); -extern void sun3_disable_irq (unsigned int); -extern void sun3_enable_interrupts (void); -extern void sun3_disable_interrupts (void); extern void sun3_get_model (char* model); extern void idprom_init (void); extern void sun3_gettod (int *yearp, int *monp, int *dayp, @@ -56,7 +46,7 @@ extern void sun_serial_setup(void); volatile char* clock_va; -extern unsigned char* sun3_intreg; +extern volatile unsigned char* sun3_intreg; extern unsigned long availmem; unsigned long num_pages; @@ -76,7 +66,7 @@ prom_init((void *)LINUX_OPPROM_BEGVM); GET_CONTROL_BYTE(AC_SENABLE,enable_register); - enable_register |= 0x40; /* Enable FPU */ + enable_register |= 0x50; /* Enable FPU */ SET_CONTROL_BYTE(AC_SENABLE,enable_register); GET_CONTROL_BYTE(AC_SENABLE,enable_register); @@ -154,6 +144,7 @@ // mach_keyb_init = sun3_keyb_init; enable_irq = sun3_enable_irq; disable_irq = sun3_disable_irq; + mach_process_int = sun3_process_int; mach_get_irq_list = sun3_get_irq_list; mach_gettod = sun3_gettod; mach_reset = sun3_reboot; @@ -161,7 +152,7 @@ mach_get_model = sun3_get_model; mach_hwclk = sun3_hwclk; mach_halt = sun3_halt; -#ifndef CONFIG_SERIAL_CONSOLE +#if !defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_FB) conswitchp = &dummy_con; #endif Index: dvma.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/m68k/sun3/dvma.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- dvma.c 14 Jan 2001 19:42:23 -0000 1.1.1.1 +++ dvma.c 10 Apr 2002 14:34:37 -0000 1.2 @@ -4,42 +4,62 @@ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/bootmem.h> +#include <linux/list.h> #include <asm/page.h> #include <asm/pgtable.h> #include <asm/sun3mmu.h> #include <asm/dvma.h> -unsigned long dvma_next_free = DVMA_START; -unsigned long dvma_region_end = DVMA_START + (DVMA_RESERVED_PMEGS * SUN3_PMEG_SIZE); +static unsigned long ptelist[120]; -/* reserve such dma memory as we see fit */ -void sun3_dvma_init(void) +inline unsigned long dvma_page(unsigned long kaddr, unsigned long vaddr) { - unsigned long dvma_phys_start; - - dvma_phys_start = (sun3_get_pte(DVMA_START) & - SUN3_PAGE_PGNUM_MASK); - dvma_phys_start <<= PAGE_SHIFT; + unsigned long pte; + unsigned long j; + pte_t ptep; - reserve_bootmem(dvma_phys_start, - (DVMA_RESERVED_PMEGS * SUN3_PMEG_SIZE)); + j = *(volatile unsigned long *)kaddr; + *(volatile unsigned long *)kaddr = j; -} + ptep = __mk_pte(kaddr, PAGE_KERNEL); + pte = pte_val(ptep); +// printk("dvma_remap: addr %lx -> %lx pte %08lx len %x\n", +// kaddr, vaddr, pte, len); + if(ptelist[(vaddr & 0xff000) >> PAGE_SHIFT] != pte) { + sun3_put_pte(vaddr, pte); + ptelist[(vaddr & 0xff000) >> PAGE_SHIFT] = pte; + } -/* get needed number of free dma pages, or panic if not enough */ + return (vaddr + (kaddr & ~PAGE_MASK)); -void *sun3_dvma_malloc(int len) +} + +int dvma_map_iommu(unsigned long kaddr, unsigned long baddr, + int len) { + + unsigned long end; unsigned long vaddr; - if((dvma_next_free + len) > dvma_region_end) - panic("sun3_dvma_malloc: out of dvma pages"); + vaddr = dvma_btov(baddr); + + end = vaddr + len; - vaddr = dvma_next_free; - dvma_next_free = DVMA_ALIGN(dvma_next_free + len); + while(vaddr < end) { + dvma_page(kaddr, vaddr); + kaddr += PAGE_SIZE; + vaddr += PAGE_SIZE; + } + + return 0; - return (void *)vaddr; } - +void sun3_dvma_init(void) +{ + + memset(ptelist, 0, sizeof(ptelist)); + + +} Index: idprom.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/m68k/sun3/idprom.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 Index: intersil.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/m68k/sun3/intersil.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- intersil.c 14 Jan 2001 19:42:26 -0000 1.1.1.1 +++ intersil.c 10 Apr 2002 14:34:37 -0000 1.2 @@ -11,9 +11,9 @@ */ #include <linux/kernel.h> -#include <linux/kd.h> #include <asm/system.h> +#include <asm/rtc.h> #include <asm/intersil.h> @@ -30,7 +30,7 @@ void sun3_gettod (int *yearp, int *monp, int *dayp, int *hourp, int *minp, int *secp) { - u_char wday; + unsigned char wday; volatile struct intersil_dt* todintersil; unsigned long flags; Index: mmu_emu.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/m68k/sun3/mmu_emu.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- mmu_emu.c 14 Jan 2001 19:42:26 -0000 1.1.1.1 +++ mmu_emu.c 10 Apr 2002 14:34:37 -0000 1.2 @@ -29,6 +29,7 @@ extern void prom_reboot (char *) __attribute__ ((__noreturn__)); #undef DEBUG_MMU_EMU +#define DEBUG_PROM_MAPS /* ** Defines @@ -157,9 +158,12 @@ j = 0; for (num=0, seg=0x0F800000; seg<0x10000000; seg+=16*PAGE_SIZE) { if (sun3_get_segmap (seg) != SUN3_INVALID_PMEG) { -#ifdef DEBUG_MMU_EMU - printk ("mapped:"); - print_pte_vaddr (seg); +#ifdef DEBUG_PROM_MAPS + for(i = 0; i < 16; i++) { + printk ("mapped:"); + print_pte_vaddr (seg + (i*PAGE_SIZE)); + break; + } #endif // the lowest mapping here is the end of our // vmalloc region @@ -174,7 +178,7 @@ } - sun3_dvma_init(); + dvma_init(); /* blank everything below the kernel, and we've got the base Index: sbus.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/m68k/sun3/sbus.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sbus.c 14 Jan 2001 19:42:26 -0000 1.1.1.1 +++ sbus.c 10 Apr 2002 14:34:37 -0000 1.2 @@ -12,8 +12,12 @@ #include <linux/types.h> #include <linux/init.h> +extern void rs_init(void); + void __init sbus_init(void) { + + rs_init(); } Index: sun3_ksyms.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/m68k/sun3/sun3_ksyms.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sun3_ksyms.c 14 Jan 2001 19:42:26 -0000 1.1.1.1 +++ sun3_ksyms.c 10 Apr 2002 14:34:37 -0000 1.2 @@ -6,5 +6,8 @@ /* * Add things here when you find the need for it. */ -EXPORT_SYMBOL(sun3_dvma_malloc); +EXPORT_SYMBOL(dvma_map_align); +EXPORT_SYMBOL(dvma_unmap); +EXPORT_SYMBOL(dvma_malloc_align); +EXPORT_SYMBOL(dvma_free); EXPORT_SYMBOL(idprom); Index: sun3ints.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/m68k/sun3/sun3ints.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- sun3ints.c 14 Jan 2001 19:42:26 -0000 1.1.1.1 +++ sun3ints.c 10 Apr 2002 14:34:37 -0000 1.2 @@ -1,5 +1,5 @@ /* - * linux/arch/m68k/sun3/sun3ints.c -- Sun-3 Linux interrupt handling code + * linux/arch/m68k/sun3/sun3ints.c -- Sun-3(x) Linux interrupt handling code * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive @@ -35,7 +35,7 @@ ~(0x10), ~(0x08) }; -unsigned char* sun3_intreg; +volatile unsigned char* sun3_intreg; void sun3_insert_irq(irq_node_t **list, irq_node_t *node) { @@ -45,10 +45,6 @@ { } -void sun3_free_irq(unsigned int irq, void *dev_id) -{ -} - void sun3_enable_irq(unsigned int irq) { *sun3_intreg |= (1<<irq); @@ -71,41 +67,54 @@ return 0; } +static void sun3_int7(int irq, void *dev_id, struct pt_regs *fp) +{ + sun3_do_irq(irq,fp); + if(!(kstat.irqs[0][SYS_IRQS + irq] % 2000)) + sun3_leds(led_pattern[(kstat.irqs[0][SYS_IRQS+irq]%16000)/2000]); +} + static void sun3_int5(int irq, void *dev_id, struct pt_regs *fp) { kstat.irqs[0][SYS_IRQS + irq]++; - *sun3_intreg &= ~(1<<irq); +#ifdef CONFIG_SUN3 intersil_clear(); +#endif + *sun3_intreg &= ~(1<<irq); *sun3_intreg |= (1<<irq); +#ifdef CONFIG_SUN3 + intersil_clear(); +#endif do_timer(fp); if(!(kstat.irqs[0][SYS_IRQS + irq] % 20)) sun3_leds(led_pattern[(kstat.irqs[0][SYS_IRQS+irq]%160) /20]); } -static void sun3_int7(int irq, void *dev_id, struct pt_regs *fp) -{ - sun3_do_irq(irq,fp); - if(!(kstat.irqs[0][SYS_IRQS + irq] % 2000)) - sun3_leds(led_pattern[(kstat.irqs[0][SYS_IRQS+irq]%16000)/2000]); -} - /* handle requested ints, excepting 5 and 7, which always do the same thing */ static void *dev_ids[SYS_IRQS]; -static void (*inthandler[SYS_IRQS])(int, void *, struct pt_regs *) = { +static void (*sun3_inthandler[SYS_IRQS])(int, void *, struct pt_regs *) = { NULL, NULL, NULL, NULL, NULL, sun3_int5, NULL, sun3_int7 }; +static void (*sun3_vechandler[192])(int, void *, struct pt_regs *); +static void *vec_ids[192]; +static char *vec_names[192]; static void sun3_inthandle(int irq, void *dev_id, struct pt_regs *fp) { - if(inthandler[irq] == NULL) + if(sun3_inthandler[irq] == NULL) panic ("bad interrupt %d received (id %p)\n",irq, dev_id); kstat.irqs[0][SYS_IRQS + irq]++; *sun3_intreg &= ~(1<<irq); - inthandler[irq](irq, dev_ids[irq], fp); + sun3_inthandler[irq](irq, dev_ids[irq], fp); +} + +static void sun3_vec255(int irq, void *dev_id, struct pt_regs *fp) +{ +// intersil_clear(); } void (*sun3_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = { @@ -120,6 +129,8 @@ { int i; + *sun3_intreg = 1; + for(i = 0; i < SYS_IRQS; i++) { if(dev_names[i]) @@ -127,25 +138,94 @@ 0, dev_names[i], NULL); } + for(i = 0; i < 192; i++) + sun3_vechandler[i] = NULL; + + sun3_vechandler[191] = sun3_vec255; } int sun3_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) { - if(inthandler[irq] != NULL) { - printk("sun3_request_irq: request for irq %d -- already taken!\n", irq); - return -1; - } - inthandler[irq] = handler; - dev_ids[irq] = dev_id; - dev_names[irq] = devname; + if(irq < SYS_IRQS) { + if(sun3_inthandler[irq] != NULL) { + printk("sun3_request_irq: request for irq %d -- already taken!\n", irq); + return 1; + } + + sun3_inthandler[irq] = handler; + dev_ids[irq] = dev_id; + dev_names[irq] = devname; + + /* setting devname would be nice */ + sys_request_irq(irq, sun3_default_handler[irq], 0, devname, NULL); + + return 0; + } else { + if((irq >= 64) && (irq <= 255)) { + int vec; + + vec = irq - 64; + if(sun3_vechandler[vec] != NULL) { + printk("sun3_request_irq: request for vec %d -- already taken!\n", irq); + return 1; + } + + sun3_vechandler[vec] = handler; + vec_ids[vec] = dev_id; + vec_names[vec] = devname; + + return 0; + } + } - /* setting devname would be nice */ - - sys_request_irq(irq, sun3_default_handler[irq], 0, devname, NULL); - + printk("sun3_request_irq: invalid irq %d\n", irq); + return 1; - return 0; } +void sun3_free_irq(unsigned int irq, void *dev_id) +{ + + if(irq < SYS_IRQS) { + if(sun3_inthandler[irq] == NULL) + panic("sun3_free_int: attempt to free unused irq %d\n", irq); + if(dev_ids[irq] != dev_id) + panic("sun3_free_int: incorrect dev_id for irq %d\n", irq); + + sun3_inthandler[irq] = NULL; + return; + } else if((irq >= 64) && (irq <= 255)) { + int vec; + + vec = irq - 64; + if(sun3_vechandler[vec] == NULL) + panic("sun3_free_int: attempt to free unused vector %d\n", irq); + if(vec_ids[irq] != dev_id) + panic("sun3_free_int: incorrect dev_id for vec %d\n", irq); + + sun3_vechandler[vec] = NULL; + return; + } else { + panic("sun3_free_irq: invalid irq %d\n", irq); + } +} + +void sun3_process_int(int irq, struct pt_regs *regs) +{ + + if((irq >= 64) && (irq <= 255)) { + int vec; + + vec = irq - 64; + if(sun3_vechandler[vec] == NULL) + panic ("bad interrupt vector %d received\n",irq); + + sun3_vechandler[vec](irq, vec_ids[vec], regs); + return; + } else { + panic("sun3_process_int: unable to handle interrupt vector %d\n", + irq); + } +} |