S: USA
N: James Banks
-E: james.banks@caldera.com
+E: james@sovereign.org
D: TLAN network driver
-S: Caldera, Inc.
-S: 633 South 550 East
-S: Provo, Utah 84606
-S: USA
+D: Logitech Busmouse driver
N: Paul Barton-Davis
E: pbd@op.net
S: United Kingdom
N: Ron Holt
-E: ron@caldera.com
+E: ron@sovereign.org
W: http://www.holt.org/
P: 1024/1FD44539 DF 4B EB 9F 5B 68 38 9A 40 E3 FB 71 D1 C8 0B 56
D: Kernel development
is no need for the legitimate users to change their TCP/IP software;
SYN cookies work transparently to them. For technical information
about SYN cookies, check out
- ftp://koobera.math.uic.edu/pub/docs/syncookies-archive.
+ ftp://koobera.math.uic.edu/syncookies.html .
If you are SYN flooded, the source address reported by the kernel is
likely to have been forged by the attacker; it is only reported as
* Title: "Linux Kernel Module Programming Guide"
Author: Ori Pomerantz.
- URL:
- http://www.leo.org/pub/comp/os/unix/linux/sunsite/docs/linux-doc-p
- roject/module-programming-guide/index.html
- Keywords: modules, free book, /proc, ioctls, system calls,
+ URL: http://www.linuxdoc.org/LDP/lkmpg/mpg.html
+ Keywords: modules, GPL book, /proc, ioctls, system calls,
interrupt handlers .
- Description: Very nice 92 pages free book on the topic of modules
+ Description: Very nice 92 pages GPL book on the topic of modules
programming. Lots of examples.
* Title: "Device File System (devfs) Overview"
produced during the week. Published every Thursday.
* Name: Kernel Traffic.
- URL: http://lwn.net
+ URL: http://kt.linuxcare.com
Keywords: linux-kernel mailing list, weekly kernel news.
Description: Weekly newsletter covering the most relevant
discussions of the linux-kernel mailing list.
dcache.
_________________________________________________________________
- Document last updated on Wed Oct 27 17:14:03 CEST 1999
+ Document last updated on Tue Nov 30 11:20:00 CET 1999
-TLAN driver for Linux, version 1.0
-README
-Well, I'm back. The TLAN driver seems pretty stable, so I'm
-declaring this cycle of development finished, and calling the
-driver 1.0. I will, of course continue to work on improving
-the driver, and work towards a 2.0 release.
+I haven't had any time to do anything for a long time, and this isn't
+likely to change. So there's a driver here for anyone looking to
+carry forward a project :)
+
+For those who are looking for help, I can't. I haven't looked at
+a kernel since the early 2.0 series, so I won't know what's going on.
+Your best chance at help would be joining the TLAN mailing list and
+posting your question there.
+
+You can join by sending "subscribe tlan" in the body of an email to
+majordomo@vuser.vu.union.edu.
+
+Thanks to those who have (and who will ;) put work in to keep the TLAN
+driver working as the kernel moves on.
James
james@sovereign.org
+TLAN driver for Linux, version 1.0
+README
+
I. Supported Devices.
S: Maintained
TLAN NETWORK DRIVER
-P: James Banks
-M: james@sovereign.org
L: tlan@vuser.vu.union.edu
-S: Maintained
+S: Orphan
TOKEN-RING NETWORK DRIVER
P: Paul Norton
VERSION = 2
PATCHLEVEL = 2
SUBLEVEL = 14
-EXTRAVERSION = pre9
+EXTRAVERSION = pre10
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
+++ /dev/null
-/* ld script to make i386 Linux kernel
- * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
- */
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-ENTRY(_start)
-SECTIONS
-{
- . = 0xC0000000 + 0x100000;
- _text = .; /* Text and read-only data */
- .text : {
- *(.text)
- *(.fixup)
- *(.gnu.warning)
- } = 0x9090
- .text.lock : { *(.text.lock) } /* out-of-line lock text */
- .rodata : { *(.rodata) }
- .kstrtab : { *(.kstrtab) }
-
- . = ALIGN(16); /* Exception table */
- __start___ex_table = .;
- __ex_table : { *(__ex_table) }
- __stop___ex_table = .;
-
- __start___ksymtab = .; /* Kernel symbol table */
- __ksymtab : { *(__ksymtab) }
- __stop___ksymtab = .;
-
- _etext = .; /* End of text section */
-
- .data : { /* Data */
- *(.data)
- CONSTRUCTORS
- }
-
- _edata = .; /* End of data section */
-
- . = ALIGN(8192); /* init_task */
- .data.init_task : { *(.data.init_task) }
-
- . = ALIGN(4096); /* Init code and data */
- __init_begin = .;
- .text.init : { *(.text.init) }
- .data.init : { *(.data.init) }
- . = ALIGN(4096);
- __init_end = .;
-
- . = ALIGN(32);
- .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
- . = ALIGN(4096);
- .data.page_aligned : { *(.data.idt) }
-
-
- __bss_start = .; /* BSS */
- .bss : {
- *(.bss)
- }
- _end = . ;
-
- /* Stabs debugging sections. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
- .stab.indexstr 0 : { *(.stab.indexstr) }
- .comment 0 : { *(.comment) }
-}
cp zImage.initrd $(TFTPIMAGE)
clean:
- rm -f vmlinux* zvmlinux* mkprep zImage*
+ rm -f vmlinux* zvmlinux* mkprep zImage* sImage*
fastdep:
$(TOPDIR)/scripts/mkdep *.[Sch] > .depend
+++ /dev/null
-/*
- * String handling functions for PowerPC.
- *
- * Copyright (C) 1996 Paul Mackerras.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#define r0 0
-#define r3 3
-#define r4 4
-#define r5 5
-#define r6 6
-#define r7 7
-#define r8 8
-
- .globl strcpy
-strcpy:
- addi r5,r3,-1
- addi r4,r4,-1
-1: lbzu r0,1(r4)
- cmpwi 0,r0,0
- stbu r0,1(r5)
- bne 1b
- blr
-
- .globl strncpy
-strncpy:
- cmpwi 0,r5,0
- beqlr
- mtctr r5
- addi r6,r3,-1
- addi r4,r4,-1
-1: lbzu r0,1(r4)
- cmpwi 0,r0,0
- stbu r0,1(r6)
- bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
- blr
-
- .globl strcat
-strcat:
- addi r5,r3,-1
- addi r4,r4,-1
-1: lbzu r0,1(r5)
- cmpwi 0,r0,0
- bne 1b
- addi r5,r5,-1
-1: lbzu r0,1(r4)
- cmpwi 0,r0,0
- stbu r0,1(r5)
- bne 1b
- blr
-
- .globl strcmp
-strcmp:
- addi r5,r3,-1
- addi r4,r4,-1
-1: lbzu r3,1(r5)
- cmpwi 1,r3,0
- lbzu r0,1(r4)
- subf. r3,r0,r3
- beqlr 1
- beq 1b
- blr
-
- .globl strlen
-strlen:
- addi r4,r3,-1
-1: lbzu r0,1(r4)
- cmpwi 0,r0,0
- bne 1b
- subf r3,r3,r4
- blr
-
- .globl memset
-memset:
- rlwimi r4,r4,8,16,23
- rlwimi r4,r4,16,0,15
- addi r6,r3,-4
- cmplwi 0,r5,4
- blt 7f
- stwu r4,4(r6)
- beqlr
- andi. r0,r6,3
- add r5,r0,r5
- subf r6,r0,r6
- rlwinm r0,r5,32-2,2,31
- mtctr r0
- bdz 6f
-1: stwu r4,4(r6)
- bdnz 1b
-6: andi. r5,r5,3
-7: cmpwi 0,r5,0
- beqlr
- mtctr r5
- addi r6,r6,3
-8: stbu r4,1(r6)
- bdnz 8b
- blr
-
- .globl bcopy
-bcopy:
- mr r6,r3
- mr r3,r4
- mr r4,r6
- b memcpy
-
- .globl memmove
-memmove:
- cmplw 0,r3,r4
- bgt backwards_memcpy
- /* fall through */
-
- .globl memcpy
-memcpy:
- rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
- addi r6,r3,-4
- addi r4,r4,-4
- beq 2f /* if less than 8 bytes to do */
- andi. r0,r6,3 /* get dest word aligned */
- mtctr r7
- bne 5f
-1: lwz r7,4(r4)
- lwzu r8,8(r4)
- stw r7,4(r6)
- stwu r8,8(r6)
- bdnz 1b
- andi. r5,r5,7
-2: cmplwi 0,r5,4
- blt 3f
- lwzu r0,4(r4)
- addi r5,r5,-4
- stwu r0,4(r6)
-3: cmpwi 0,r5,0
- beqlr
- mtctr r5
- addi r4,r4,3
- addi r6,r6,3
-4: lbzu r0,1(r4)
- stbu r0,1(r6)
- bdnz 4b
- blr
-5: subfic r0,r0,4
- mtctr r0
-6: lbz r7,4(r4)
- addi r4,r4,1
- stb r7,4(r6)
- addi r6,r6,1
- bdnz 6b
- subf r5,r0,r5
- rlwinm. r7,r5,32-3,3,31
- beq 2b
- mtctr r7
- b 1b
-
- .globl backwards_memcpy
-backwards_memcpy:
- rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
- add r6,r3,r5
- add r4,r4,r5
- beq 2f
- andi. r0,r6,3
- mtctr r7
- bne 5f
-1: lwz r7,-4(r4)
- lwzu r8,-8(r4)
- stw r7,-4(r6)
- stwu r8,-8(r6)
- bdnz 1b
- andi. r5,r5,7
-2: cmplwi 0,r5,4
- blt 3f
- lwzu r0,-4(r4)
- subi r5,r5,4
- stwu r0,-4(r6)
-3: cmpwi 0,r5,0
- beqlr
- mtctr r5
-4: lbzu r0,-1(r4)
- stbu r0,-1(r6)
- bdnz 4b
- blr
-5: mtctr r0
-6: lbzu r7,-1(r4)
- stbu r7,-1(r6)
- bdnz 6b
- subf r5,r0,r5
- rlwinm. r7,r5,32-3,3,31
- beq 2b
- mtctr r7
- b 1b
-
- .globl memcmp
-memcmp:
- cmpwi 0,r5,0
- blelr
- mtctr r5
- addi r6,r3,-1
- addi r4,r4,-1
-1: lbzu r3,1(r6)
- lbzu r0,1(r4)
- subf. r3,r0,r3
- bdnzt 2,1b
- blr
}
}
#endif /* __SMP__ */
-
- irq = openpic_irq(0);
+
+ irq = openpic_irq(smp_processor_id());
if (irq == IRQ_8259_CASCADE)
{
/*
/*
* Acknowledge as soon as possible to allow i8259
* interrupt nesting */
- openpic_eoi(0);
+ openpic_eoi(smp_processor_id());
openpic_eoi_done = 1;
}
if (irq == OPENPIC_VEC_SPURIOUS)
}
out:
if (!openpic_eoi_done)
- openpic_eoi(0);
+ openpic_eoi(smp_processor_id());
}
__initfunc(void
open_pic.irq_offset = 16;
for ( i = 16 ; i < NR_IRQS ; i++ )
irq_desc[i].ctl = &open_pic;
- /* openpic knows that it's at irq 16 offset
- * so we don't need to set it in the pic structure
- * -- Cort
- */
openpic_init(1);
for ( i = 0 ; i < 16 ; i++ )
irq_desc[i].ctl = &i8259_pic;
xmon_irq, 0, "NMI", 0);
#endif /* CONFIG_XMON */
#ifdef __SMP__
- request_irq(openpic_to_irq(OPENPIC_VEC_IPI),
- openpic_ipi_action, 0, "IPI0", 0);
+ request_irq(OPENPIC_VEC_IPI, openpic_ipi_action,
+ 0, "IPI0", 0);
+ request_irq(OPENPIC_VEC_IPI+1, openpic_ipi_action,
+ 0, "IPI1 (invalidate TLB)", 0);
+ request_irq(OPENPIC_VEC_IPI+2, openpic_ipi_action,
+ 0, "IPI2 (stop CPU)", 0);
+ request_irq(OPENPIC_VEC_IPI+3, openpic_ipi_action,
+ 0, "IPI3 (reschedule)", 0);
#endif /* __SMP__ */
}
{
adb_init();
- /* Should this be here? - Corey */
pmac_nvram_init();
#ifdef CONFIG_VT
gemini_do_IRQ(struct pt_regs *regs, int cpu, int isfake)
{
int irq, openpic_eoi_done = 0;
- unsigned long bits = 0;
-
#ifdef __SMP__
- if (cpu != 0) {
- if (!isfake) {
- smp_message_recv();
- goto out;
- }
- goto out;
- }
-
{
unsigned int loops = 1000000;
while(test_bit(0, &global_irq_lock)) {
irq = openpic_irq(cpu);
- if (irq == OPENPIC_VEC_SPURIOUS) {
+ if (irq == OPENPIC_VEC_SPURIOUS ) {
ppc_spurious_interrupts++;
openpic_eoi_done = 1;
goto out;
}
-
- bits = 1UL<<irq;
- irq -= OPENPIC_VEC_SOURCE;
-
+
if (irq < 0) {
printk(KERN_DEBUG "Bogus interrupt %d from pc=%lx\n", irq,
regs->nip);
ppc_irq_dispatch_handler(regs, irq);
out:
if (!openpic_eoi_done)
- openpic_eoi(0);
+ openpic_eoi(smp_processor_id());
}
static inline unsigned long _get_HID1(void)
/* gemini has no 8259 */
open_pic.irq_offset = 0;
- for( i=0; i < OPENPIC_VEC_SPURIOUS; i++ )
+ for( i=0; i < NR_IRQS; i++ )
irq_desc[i].ctl = &open_pic;
openpic_init(1);
#ifdef __SMP__
- request_irq(OPENPIC_VEC_IPI, openpic_ipi_action, 0, "IPI0", 0);
+ request_irq(OPENPIC_VEC_IPI, openpic_ipi_action,
+ 0, "IPI0", 0);
+ request_irq(OPENPIC_VEC_IPI+1, openpic_ipi_action,
+ 0, "IPI1 (invalidate TLB)", 0);
+ request_irq(OPENPIC_VEC_IPI+2, openpic_ipi_action,
+ 0, "IPI2 (stop CPU)", 0);
+ request_irq(OPENPIC_VEC_IPI+3, openpic_ipi_action,
+ 0, "IPI3 (reschedule)", 0);
#endif /* __SMP__ */
}
.globl __secondary_start
__secondary_start:
/* Switch MMU off, clear BATs and flush TLB */
- bl mmu_off
+ bl mmu_off
bl clear_bats
bl flush_tlbs
li r2,8 /* PTEs/group */
bne 10f /* no PTE: go look for an empty slot */
tlbie r3 /* invalidate TLB entry */
-
/* Search the primary PTEG for a PTE whose 1st word matches r5 */
mtctr r2
addi r3,r4,-8
stw r4,TSS+KSP(r2) /* save kernel stack pointer */
tophys(r3,r1,r3)
mtspr SPRG2,r3 /* phys exception stack pointer */
-10: lwz r2,_CTR(r1)
+10:
+#ifdef CONFIG_SMP
+ /* see smp_invalidate_tlb_cpu for explanation */
+ mfspr r3,PVR
+ rlwinm r3,r3,16,16,31
+ cmpi 0,r3,8
+ bne 1010f
+ bl smp_invalidate_tlb_cpu
+1010:
+#endif /* CONFIG_SMP */
+ lwz r2,_CTR(r1)
lwz r0,_LINK(r1)
mtctr r2
mtlr r0
* this needs to be removed.
* -- Cort
*/
-static char cache_bitmask = 0;
-static struct irqaction malloc_cache[8];
+static unsigned long cache_bitmask[1];
+static struct irqaction malloc_cache[32];
extern int mem_init_done;
void *irq_kmalloc(size_t size, int pri)
unsigned int i;
if ( mem_init_done )
return kmalloc(size,pri);
- for ( i = 0; i <= 3 ; i++ )
- if ( ! ( cache_bitmask & (1<<i) ) )
+ for ( i = 0; i < 32 ; i++ )
+ if ( ! (test_bit(i, (void *)cache_bitmask)) )
{
- cache_bitmask |= (1<<i);
+ set_bit(i,(void *)cache_bitmask);
return (void *)(&malloc_cache[i]);
}
return 0;
void irq_kfree(void *ptr)
{
unsigned int i;
- for ( i = 0 ; i <= 3 ; i++ )
+ for ( i = 0 ; i < 32 ; i++ )
if ( ptr == &malloc_cache[i] )
{
- cache_bitmask &= ~(1<<i);
+ clear_bit( i, (void *)cache_bitmask );
return;
}
kfree(ptr);
#ifdef __SMP__
void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
{
- smp_message_recv();
+ smp_message_recv(cpl-OPENPIC_VEC_IPI);
}
#endif /* __SMP__ */
extern struct hw_interrupt_type open_pic;
void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs);
+void openpic_enable_IPI(u_int ipi);
+void do_openpic_setup_cpu(void);
#endif /* _PPC_KERNEL_OPEN_PIC_H */
*
* Copyright (C) 1997 Geert Uytterhoeven
*
+ * Fixed up IPI and restructured a bit
+ * Cort Dougan <cort@ppc.kernel.org>
+ *
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*/
-
-/*
- * Note: Interprocessor Interrupt (IPI) and Timer support is incomplete
- */
-
-
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm/signal.h>
#include <asm/io.h>
#include <asm/irq.h>
-
+#include "open_pic.h"
#define REGISTER_DEBUG
#undef REGISTER_DEBUG
-
volatile struct OpenPIC *OpenPIC = NULL;
u_int OpenPIC_NumInitSenses __initdata = 0;
u_char *OpenPIC_InitSenses __initdata = NULL;
static u_int NumProcessors;
static u_int NumSources;
-
- /*
- * Accesses to the current processor's registers
- */
-
#ifndef __powerpc__
#define THIS_CPU Private
#define CHECK_THIS_CPU do {} while (0)
#define CHECK_THIS_CPU check_arg_cpu(cpu)
#endif
-
- /*
- * Sanity checks
- */
-
#if 1
#define check_arg_ipi(ipi) \
if (ipi < 0 || ipi >= OPENPIC_NUM_IPI) \
#define check_arg_pri(pri) \
if (pri < 0 || pri >= OPENPIC_NUM_PRI) \
printk("openpic.c:%d: illegal priority %d\n", __LINE__, pri);
+/*
+ * I changed this to return to keep us from from trying to use irq #'s
+ * that we're using for IPI's.
+ * -- Cort
+ */
#define check_arg_irq(irq) \
if (irq < 0 || irq >= NumSources) \
- printk("openpic.c:%d: illegal irq %d\n", __LINE__, irq);
+ /*printk("openpic.c:%d: illegal irq %d\n", __LINE__, irq);*/return;
#define check_arg_cpu(cpu) \
if (cpu < 0 || cpu >= NumProcessors) \
printk("openpic.c:%d: illegal cpu %d\n", __LINE__, cpu);
#define check_arg_cpu(cpu) do {} while (0)
#endif
-
- /*
- * Dummy interrupt handler
- */
-
static void no_action(int ir1, void *dev, struct pt_regs *regs)
{}
-
- /*
- * I/O functions
- */
-
+/*
+ * I/O functions
+ */
#ifdef __i386__
static inline u_int ld_le32(volatile u_int *addr)
{
- return *addr;
+ return *addr;
}
static inline void out_le32(volatile u_int *addr, u_int val)
{
- *addr = val;
+ *addr = val;
}
#endif
u_int openpic_read(volatile u_int *addr)
{
- u_int val;
+ u_int val;
- val = ld_le32(addr);
+ val = ld_le32(addr);
#ifdef REGISTER_DEBUG
- printk("openpic_read(0x%08x) = 0x%08x\n", (u_int)addr, val);
+ printk("openpic_read(0x%08x) = 0x%08x\n", (u_int)addr, val);
#endif
- return val;
+ return val;
}
static inline void openpic_write(volatile u_int *addr, u_int val)
{
#ifdef REGISTER_DEBUG
- printk("openpic_write(0x%08x, 0x%08x)\n", (u_int)addr, val);
+ printk("openpic_write(0x%08x, 0x%08x)\n", (u_int)addr, val);
#endif
- out_le32(addr, val);
+ out_le32(addr, val);
}
-
static inline u_int openpic_readfield(volatile u_int *addr, u_int mask)
{
- u_int val = openpic_read(addr);
- return val & mask;
+ u_int val = openpic_read(addr);
+ return val & mask;
}
inline void openpic_writefield(volatile u_int *addr, u_int mask,
- u_int field)
+ u_int field)
{
- u_int val = openpic_read(addr);
- openpic_write(addr, (val & ~mask) | (field & mask));
+ u_int val = openpic_read(addr);
+ openpic_write(addr, (val & ~mask) | (field & mask));
}
static inline void openpic_clearfield(volatile u_int *addr, u_int mask)
{
- openpic_writefield(addr, mask, 0);
+ openpic_writefield(addr, mask, 0);
}
static inline void openpic_setfield(volatile u_int *addr, u_int mask)
{
- openpic_writefield(addr, mask, mask);
+ openpic_writefield(addr, mask, mask);
}
-
- /*
- * Update a Vector/Priority register in a safe manner. The interrupt will
- * be disabled.
- */
-
+/*
+ * Update a Vector/Priority register in a safe manner. The interrupt will
+ * be disabled.
+ */
static void openpic_safe_writefield(volatile u_int *addr, u_int mask,
u_int field)
{
- openpic_setfield(addr, OPENPIC_MASK);
- /* wait until it's not in use */
- while (openpic_read(addr) & OPENPIC_ACTIVITY);
- openpic_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
+ openpic_setfield(addr, OPENPIC_MASK);
+ /* wait until it's not in use */
+ while (openpic_read(addr) & OPENPIC_ACTIVITY);
+ openpic_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
}
-
-/* -------- Global Operations ---------------------------------------------- */
-
-
- /*
- * Initialize the OpenPIC
- */
-
+/*
+ * Initialize the OpenPIC
+ */
__initfunc(void openpic_init(int main_pic))
{
- u_int t, i;
- u_int timerfreq;
- const char *version;
+ u_int t, i;
+ u_int timerfreq;
+ const char *version;
- if (!OpenPIC)
- panic("No OpenPIC found");
+ if (!OpenPIC)
+ panic("No OpenPIC found");
- t = openpic_read(&OpenPIC->Global.Feature_Reporting0);
- switch (t & OPENPIC_FEATURE_VERSION_MASK) {
+ t = openpic_read(&OpenPIC->Global.Feature_Reporting0);
+ switch (t & OPENPIC_FEATURE_VERSION_MASK) {
case 1:
- version = "1.0";
- break;
+ version = "1.0";
+ break;
case 2:
- version = "1.2";
- break;
+ version = "1.2";
+ break;
case 3:
- version = "1.3";
- break;
+ version = "1.3";
+ break;
default:
- version = "?";
- break;
- }
- NumProcessors = ((t & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
- OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1;
- NumSources = ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >>
- OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1;
- printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at %p\n", version,
- NumProcessors, NumSources, OpenPIC);
- timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency);
- printk("OpenPIC timer frequency is ");
- if (timerfreq)
- printk("%d Hz\n", timerfreq);
- else
- printk("not set\n");
-
- if ( main_pic )
- {
- /* Initialize timer interrupts */
- for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
- /* Disabled, Priority 0 */
- openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i);
- /* No processor */
- openpic_maptimer(i, 0);
- }
+ version = "?";
+ break;
+ }
+ NumProcessors = ((t & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
+ OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1;
+ NumSources = ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >>
+ OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1;
+ printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at %p\n", version,
+ NumProcessors, NumSources, OpenPIC);
+ timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency);
+ printk("OpenPIC timer frequency is ");
+ if (timerfreq)
+ printk("%d Hz\n", timerfreq);
+ else
+ printk("not set\n");
+
+ if ( main_pic )
+ {
+ /* Initialize timer interrupts */
+ for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
+ /* Disabled, Priority 0 */
+ openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i);
+ /* No processor */
+ openpic_maptimer(i, 0);
+ }
- /* Initialize IPI interrupts */
- for (i = 0; i < OPENPIC_NUM_IPI; i++) {
- /* Disabled, Priority 0 */
- openpic_initipi(i, 0, OPENPIC_VEC_IPI+i);
- }
+ /* Initialize IPI interrupts */
+ for (i = 0; i < OPENPIC_NUM_IPI; i++) {
+ openpic_initipi(i, 10, OPENPIC_VEC_IPI+i);
+ }
- /* Initialize external interrupts */
- /* SIOint (8259 cascade) is special */
- openpic_initirq(0, 8, OPENPIC_VEC_SOURCE, 1, 1);
- /* Processor 0 */
- openpic_mapirq(0, 1<<0);
- for (i = 1; i < NumSources; i++) {
- /* Enabled, Priority 8 */
- openpic_initirq(i, 8, OPENPIC_VEC_SOURCE+i, 0,
- i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1);
- /* Processor 0 */
- openpic_mapirq(i, 1<<0);
- }
+ /* Initialize external interrupts */
+ for (i = 0; i < NumSources; i++) {
+ /* Enabled, Priority 8 */
+ openpic_initirq(i, 8, open_pic.irq_offset+i, 0,
+ i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1);
+ /* Processor 0 */
+ openpic_mapirq(i, 1<<0);
+ }
- /* Initialize the spurious interrupt */
- openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
-
- if ( _machine != _MACH_gemini )
- {
- if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
- "82c59 cascade", NULL))
- printk("Unable to get OpenPIC IRQ 0 for cascade\n");
- }
- openpic_set_priority(0, 0);
- openpic_disable_8259_pass_through();
- }
+ /* Initialize the spurious interrupt */
+ openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
+
+ /* Gemini has no i8259 */
+ if ( _machine != _MACH_gemini )
+ {
+ /* SIOint (8259 cascade) is special */
+ openpic_initirq(0, 8, open_pic.irq_offset, 1, 1);
+ openpic_mapirq(0, 1<<0);
+ if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
+ "82c59 cascade", NULL))
+ printk("Unable to get OpenPIC IRQ 0 for cascade\n");
+ }
+ openpic_set_priority(0, 0);
+ openpic_disable_8259_pass_through();
+ }
}
- /*
- * Reset the OpenPIC
- */
-
+/*
+ * Reset the OpenPIC
+ */
void openpic_reset(void)
{
- openpic_setfield(&OpenPIC->Global.Global_Configuration0,
- OPENPIC_CONFIG_RESET);
+ openpic_setfield(&OpenPIC->Global.Global_Configuration0,
+ OPENPIC_CONFIG_RESET);
}
- /*
- * Enable/disable 8259 Pass Through Mode
- */
-
+/*
+ * Enable/disable 8259 Pass Through Mode
+ */
void openpic_enable_8259_pass_through(void)
{
- openpic_clearfield(&OpenPIC->Global.Global_Configuration0,
- OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
+ openpic_clearfield(&OpenPIC->Global.Global_Configuration0,
+ OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
}
void openpic_disable_8259_pass_through(void)
{
- openpic_setfield(&OpenPIC->Global.Global_Configuration0,
- OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
+ openpic_setfield(&OpenPIC->Global.Global_Configuration0,
+ OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
}
-
#ifndef __i386__
- /*
- * Find out the current interrupt
- */
-
+/*
+ * Find out the current interrupt
+ */
u_int openpic_irq(u_int cpu)
{
- u_int vec;
-
- check_arg_cpu(cpu);
- vec = openpic_readfield(&OpenPIC->THIS_CPU.Interrupt_Acknowledge,
- OPENPIC_VECTOR_MASK);
-#if 0
-if (vec != 22 /* SCSI */)
-printk("++openpic_irq: %d\n", vec);
-#endif
- return vec;
+ u_int vec;
+
+ check_arg_cpu(cpu);
+ vec = openpic_readfield(&OpenPIC->THIS_CPU.Interrupt_Acknowledge,
+ OPENPIC_VECTOR_MASK);
+ return vec;
}
#endif
- /*
- * Signal end of interrupt (EOI) processing
- */
-
+/*
+ * Signal end of interrupt (EOI) processing
+ */
#ifndef __powerpc__
void openpic_eoi(void)
#else
void openpic_eoi(u_int cpu)
#endif
{
- check_arg_cpu(cpu);
- openpic_write(&OpenPIC->THIS_CPU.EOI, 0);
+ check_arg_cpu(cpu);
+ openpic_write(&OpenPIC->THIS_CPU.EOI, 0);
}
- /*
- * Get/set the current task priority
- */
-
+/*
+ * Get/set the current task priority
+ */
#ifndef __powerpc__
u_int openpic_get_priority(void)
#else
u_int openpic_get_priority(u_int cpu)
#endif
{
- CHECK_THIS_CPU;
- return openpic_readfield(&OpenPIC->THIS_CPU.Current_Task_Priority,
- OPENPIC_CURRENT_TASK_PRIORITY_MASK);
+ CHECK_THIS_CPU;
+ return openpic_readfield(&OpenPIC->THIS_CPU.Current_Task_Priority,
+ OPENPIC_CURRENT_TASK_PRIORITY_MASK);
}
#ifndef __powerpc__
void openpic_set_priority(u_int cpu, u_int pri)
#endif
{
- CHECK_THIS_CPU;
- check_arg_pri(pri);
- openpic_writefield(&OpenPIC->THIS_CPU.Current_Task_Priority,
- OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri);
+ CHECK_THIS_CPU;
+ check_arg_pri(pri);
+ openpic_writefield(&OpenPIC->THIS_CPU.Current_Task_Priority,
+ OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri);
}
- /*
- * Get/set the spurious vector
- */
-
+/*
+ * Get/set the spurious vector
+ */
u_int openpic_get_spurious(void)
{
- return openpic_readfield(&OpenPIC->Global.Spurious_Vector,
- OPENPIC_VECTOR_MASK);
+ return openpic_readfield(&OpenPIC->Global.Spurious_Vector,
+ OPENPIC_VECTOR_MASK);
}
void openpic_set_spurious(u_int vec)
{
- check_arg_vec(vec);
- openpic_writefield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK,
- vec);
+ check_arg_vec(vec);
+ openpic_writefield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK,
+ vec);
}
-
- /*
- * Initialize one or more CPUs
- */
-
+/*
+ * Initialize one or more CPUs
+ */
void openpic_init_processor(u_int cpumask)
{
- openpic_write(&OpenPIC->Global.Processor_Initialization, cpumask);
+ openpic_write(&OpenPIC->Global.Processor_Initialization, cpumask);
}
-/* -------- Interprocessor Interrupts -------------------------------------- */
-
-
- /*
- * Initialize an interprocessor interrupt (and disable it)
- *
- * ipi: OpenPIC interprocessor interrupt number
- * pri: interrupt source priority
- * vec: the vector it will produce
- */
-
+/*
+ * Initialize an interprocessor interrupt (and disable it)
+ *
+ * ipi: OpenPIC interprocessor interrupt number
+ * pri: interrupt source priority
+ * vec: the vector it will produce
+ */
void openpic_initipi(u_int ipi, u_int pri, u_int vec)
{
- check_arg_timer(ipi);
- check_arg_pri(pri);
- check_arg_vec(vec);
- openpic_safe_writefield(&OpenPIC->Global.IPI_Vector_Priority(ipi),
- OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
- (pri << OPENPIC_PRIORITY_SHIFT) | vec);
+ check_arg_timer(ipi);
+ check_arg_pri(pri);
+ check_arg_vec(vec);
+ openpic_safe_writefield(&OpenPIC->Global.IPI_Vector_Priority(ipi),
+ OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
+ (pri << OPENPIC_PRIORITY_SHIFT) | vec);
}
-
- /*
- * Send an IPI to one or more CPUs
- */
-
+/*
+ * Send an IPI to one or more CPUs
+ */
#ifndef __powerpc__
void openpic_cause_IPI(u_int ipi, u_int cpumask)
#else
void openpic_cause_IPI(u_int cpu, u_int ipi, u_int cpumask)
#endif
{
- CHECK_THIS_CPU;
- check_arg_ipi(ipi);
- openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi), cpumask);
+ CHECK_THIS_CPU;
+ check_arg_ipi(ipi);
+ openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi), cpumask);
}
+void openpic_enable_IPI(u_int ipi)
+{
+ check_arg_ipi(ipi);
+ openpic_clearfield(&OpenPIC->Global.IPI_Vector_Priority(ipi),
+ OPENPIC_MASK);
+}
-/* -------- Timer Interrupts ----------------------------------------------- */
-
-
- /*
- * Initialize a timer interrupt (and disable it)
- *
- * timer: OpenPIC timer number
- * pri: interrupt source priority
- * vec: the vector it will produce
- */
+/*
+ * Do per-cpu setup for SMP systems.
+ *
+ * Get IPI's working and start taking interrupts.
+ * -- Cort
+ */
+void do_openpic_setup_cpu(void)
+{
+ int i;
+
+ for ( i = 0; i < OPENPIC_NUM_IPI ; i++ )
+ openpic_enable_IPI(i);
+#if 0
+ /* let the openpic know we want intrs */
+ for ( i = 0; i < NumSources ; i++ )
+ openpic_mapirq(i, openpic_read(&OpenPIC->Source[i].Destination)
+ | (1<<smp_processor_id()) );
+#endif
+ openpic_set_priority(smp_processor_id(), 0);
+}
+/*
+ * Initialize a timer interrupt (and disable it)
+ *
+ * timer: OpenPIC timer number
+ * pri: interrupt source priority
+ * vec: the vector it will produce
+ */
void openpic_inittimer(u_int timer, u_int pri, u_int vec)
{
- check_arg_timer(timer);
- check_arg_pri(pri);
- check_arg_vec(vec);
- openpic_safe_writefield(&OpenPIC->Global.Timer[timer].Vector_Priority,
- OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
- (pri << OPENPIC_PRIORITY_SHIFT) | vec);
+ check_arg_timer(timer);
+ check_arg_pri(pri);
+ check_arg_vec(vec);
+ openpic_safe_writefield(&OpenPIC->Global.Timer[timer].Vector_Priority,
+ OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
+ (pri << OPENPIC_PRIORITY_SHIFT) | vec);
}
- /*
- * Map a timer interrupt to one or more CPUs
- */
-
+/*
+ * Map a timer interrupt to one or more CPUs
+ */
void openpic_maptimer(u_int timer, u_int cpumask)
{
- check_arg_timer(timer);
- openpic_write(&OpenPIC->Global.Timer[timer].Destination, cpumask);
+ check_arg_timer(timer);
+ openpic_write(&OpenPIC->Global.Timer[timer].Destination, cpumask);
}
-
-/* -------- Interrupt Sources ---------------------------------------------- */
-
-
- /*
- * Enable/disable an interrupt source
- */
-
+/*
+ * Enable/disable an interrupt source
+ */
void openpic_enable_irq(u_int irq)
{
- check_arg_irq(irq);
- openpic_clearfield(&OpenPIC->Source[irq].Vector_Priority, OPENPIC_MASK);
+ check_arg_irq(irq);
+ openpic_clearfield(&OpenPIC->Source[irq].Vector_Priority, OPENPIC_MASK);
}
void openpic_disable_irq(u_int irq)
{
- check_arg_irq(irq);
- openpic_setfield(&OpenPIC->Source[irq].Vector_Priority, OPENPIC_MASK);
+ check_arg_irq(irq);
+ openpic_setfield(&OpenPIC->Source[irq].Vector_Priority, OPENPIC_MASK);
}
-
- /*
- * Initialize an interrupt source (and disable it!)
- *
- * irq: OpenPIC interrupt number
- * pri: interrupt source priority
- * vec: the vector it will produce
- * pol: polarity (1 for positive, 0 for negative)
- * sense: 1 for level, 0 for edge
- */
-
+/*
+ * Initialize an interrupt source (and disable it!)
+ *
+ * irq: OpenPIC interrupt number
+ * pri: interrupt source priority
+ * vec: the vector it will produce
+ * pol: polarity (1 for positive, 0 for negative)
+ * sense: 1 for level, 0 for edge
+ */
void openpic_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
{
- check_arg_irq(irq);
- check_arg_pri(pri);
- check_arg_vec(vec);
- openpic_safe_writefield(&OpenPIC->Source[irq].Vector_Priority,
- OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
- OPENPIC_SENSE_POLARITY | OPENPIC_SENSE_LEVEL,
- (pri << OPENPIC_PRIORITY_SHIFT) | vec |
- (pol ? OPENPIC_SENSE_POLARITY : 0) |
- (sense ? OPENPIC_SENSE_LEVEL : 0));
+ check_arg_irq(irq);
+ check_arg_pri(pri);
+ check_arg_vec(vec);
+ openpic_safe_writefield(&OpenPIC->Source[irq].Vector_Priority,
+ OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
+ OPENPIC_SENSE_POLARITY | OPENPIC_SENSE_LEVEL,
+ (pri << OPENPIC_PRIORITY_SHIFT) | vec |
+ (pol ? OPENPIC_SENSE_POLARITY : 0) |
+ (sense ? OPENPIC_SENSE_LEVEL : 0));
}
-
- /*
- * Map an interrupt source to one or more CPUs
- */
-
+/*
+ * Map an interrupt source to one or more CPUs
+ */
void openpic_mapirq(u_int irq, u_int cpumask)
{
- check_arg_irq(irq);
- openpic_write(&OpenPIC->Source[irq].Destination, cpumask);
+ check_arg_irq(irq);
+ openpic_write(&OpenPIC->Source[irq].Destination, cpumask);
}
-
- /*
- * Set the sense for an interrupt source (and disable it!)
- *
- * sense: 1 for level, 0 for edge
- */
-
+/*
+ * Set the sense for an interrupt source (and disable it!)
+ *
+ * sense: 1 for level, 0 for edge
+ */
void openpic_set_sense(u_int irq, int sense)
{
- check_arg_irq(irq);
- openpic_safe_writefield(&OpenPIC->Source[irq].Vector_Priority,
- OPENPIC_SENSE_LEVEL,
- (sense ? OPENPIC_SENSE_LEVEL : 0));
-}
-
-void openpic_enable_IPI(u_int ipi)
-{
- check_arg_ipi(ipi);
- openpic_clearfield(&OpenPIC->Global.IPI_Vector_Priority(ipi),
- OPENPIC_MASK);
+ check_arg_irq(irq);
+ openpic_safe_writefield(&OpenPIC->Source[irq].Vector_Priority,
+ OPENPIC_SENSE_LEVEL,
+ (sense ? OPENPIC_SENSE_LEVEL : 0));
}
if (xmon_2nd)
xmon(regs);
#endif
- smp_message_recv();
+ pmac_smp_message_recv();
goto out;
}
/* could be here due to a do_fake_interrupt call but we don't
prev->last_processor = prev->processor;
current_set[smp_processor_id()] = new;
-#ifdef CONFIG_GEMINI
- /*
- * Force a context change on every processor switch for 750's.
- * This prevents some corruption problems I was finding on the gemini.
- * -- Cort
- */
- if ( /*(new->processor != new->last_processor) &&*/ ((_get_PVR()>>16) == 8) )
- {
- init_new_context(new->mm);
- get_mmu_context(new);
- }
-#endif /* CONFIG_GEMINI */
#endif /* __SMP__ */
new_tss = &new->tss;
old_tss = ¤t->tss;
node = call_prom(RELOC("finddevice"), 1, 1, RELOC("/"));
if ( (int)call_prom(RELOC("getprop"), 4, 1, node,
RELOC("device_type"),type, sizeof(type)) <= 0)
- return;
+ return phys;
/* copy the holding pattern code to someplace safe (8M) */
memcpy( (void *)(8<<20), RELOC(__secondary_hold), 0x100 );
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
unsigned long tmp;
-
- if ((addr & 3) || addr < 0 || addr > (PT_FPSCR << 2)) {
- ret = -EIO;
+
+ ret = -EIO;
+ if ((addr & 3) || addr < 0 || addr > (PT_FPSCR << 2))
goto out;
- }
tmp = 0; /* Default return condition */
addr = addr >> 2; /* temporary hack. */
tmp = ((long *)child->tss.fpr)[addr - PT_FPR0];
}
else
- ret = -EIO;
- if (!ret)
- ret = put_user(tmp, (unsigned long *) data);
+ goto out;
+ ret = put_user(tmp, (unsigned long *) data);
goto out;
}
/* Whee! Actually deliver the signal. */
handle_signal(signr, ka, &info, oldset, regs, &newsp, frame);
- setup_frame(regs, (struct sigregs *) frame, newsp);
- return 1;
+ break;
}
if (regs->trap == 0x0C00 /* System Call! */ &&
regs->result = 0;
}
- return 0; /* no signals delivered */
+ if (newsp == frame)
+ return 0; /* no signals delivered */
+
+ setup_frame(regs, (struct sigregs *) frame, newsp);
+ return 1;
}
#include <asm/gemini.h>
#include "time.h"
+#include "open_pic.h"
+
int first_cpu_booted = 0;
int smp_threads_ready = 0;
volatile int smp_commenced = 0;
}
}
-/*
- * Dirty hack to get smp message passing working.
- *
- * As it is now, if we're sending two message at the same time
- * we have race conditions. The PowerSurge doesn't easily
- * allow us to send IPI messages so we put the messages in
- * smp_message[].
- *
- * This is because don't have several IPI's on the PowerSurge even though
- * we do on the chrp. It would be nice to use the actual IPI's on the chrp
- * rather than this but having two methods of doing IPI isn't a good idea
- * right now.
- * -- Cort
- */
-int smp_message[NR_CPUS];
-void smp_message_recv(void)
+void smp_message_recv(int msg)
{
- int msg = smp_message[smp_processor_id()];
-
- if ( _machine == _MACH_Pmac )
- {
- /* clear interrupt */
- out_be32(PSURGE_INTR, ~0);
- }
-
- /* make sure msg is for us */
- if ( msg == -1 ) return;
-
ipi_count++;
switch( msg )
__cli();
while (1) ;
break;
- case MSG_RESCHEDULE:
+ case MSG_RESCHEDULE:
current->need_resched = 1;
break;
- case 0xf0f0: /* syncing time bases - just return */
+ case MSG_INVALIDATE_TLB:
+ _tlbia();
+ case 0xf0f0: /* pmac syncing time bases - just return */
break;
default:
printk("SMP %d: smp_message_recv(): unknown msg %d\n",
smp_processor_id(), msg);
break;
}
+}
+
+/*
+ * As it is now, if we're sending two message at the same time
+ * we have race conditions on Pmac. The PowerSurge doesn't easily
+ * allow us to send IPI messages so we put the messages in
+ * smp_message[].
+ *
+ * This is because don't have several IPI's on the PowerSurge even though
+ * we do on the chrp. It would be nice to use actual IPI's such as with openpic
+ * rather than this.
+ * -- Cort
+ */
+int pmac_smp_message[NR_CPUS];
+void pmac_smp_message_recv(void)
+{
+ int msg = pmac_smp_message[smp_processor_id()];
+
+ /* clear interrupt */
+ out_be32(PSURGE_INTR, ~0);
+
+ /* make sure msg is for us */
+ if ( msg == -1 ) return;
+
+ smp_message_recv(msg);
+
/* reset message */
- smp_message[smp_processor_id()] = -1;
+ pmac_smp_message[smp_processor_id()] = -1;
+}
+
+
+/*
+ * 750's don't broadcast tlb invalidates so
+ * we have to emulate that behavior.
+ * -- Cort
+ */
+void smp_send_tlb_invalidate(int cpu)
+{
+ if ( (_get_PVR()>>16) == 8 )
+ smp_message_pass(MSG_ALL_BUT_SELF, MSG_INVALIDATE_TLB, 0, 0);
}
void smp_send_reschedule(int cpu)
{
- /* This is only used if `cpu' is running an idle task,
- so it will reschedule itself anyway... */
- /*smp_message_pass(cpu, MSG_RESCHEDULE, 0, 0);*/
+ /*
+ * This is only used if `cpu' is running an idle task,
+ * so it will reschedule itself anyway...
+ *
+ * This isn't the case anymore since the other CPU could be
+ * sleeping and won't reschedule until the next interrupt (such
+ * as the timer).
+ * -- Cort
+ */
+ smp_message_pass(cpu, MSG_RESCHEDULE, 0, 0);
}
void smp_send_stop(void)
smp_message_pass(MSG_ALL_BUT_SELF, MSG_STOP_CPU, 0, 0);
}
-spinlock_t mesg_pass_lock = SPIN_LOCK_UNLOCKED;
void smp_message_pass(int target, int msg, unsigned long data, int wait)
{
int i;
+
if ( !(_machine & (_MACH_Pmac|_MACH_chrp|_MACH_prep|_MACH_gemini)) )
return;
- spin_lock(&mesg_pass_lock);
-
- /*
- * We assume here that the msg is not -1. If it is,
- * the recipient won't know the message was destined
- * for it. -- Cort
- */
-
- switch( target )
- {
- case MSG_ALL:
- smp_message[smp_processor_id()] = msg;
- /* fall through */
- case MSG_ALL_BUT_SELF:
- for ( i = 0 ; i < smp_num_cpus ; i++ )
- if ( i != smp_processor_id () )
- smp_message[i] = msg;
- break;
- default:
- smp_message[target] = msg;
- break;
- }
-
switch (_machine) {
case _MACH_Pmac:
+ /*
+ * IPI's on the Pmac are a hack but without reasonable
+ * IPI hardware SMP on Pmac is a hack.
+ *
+ * We assume here that the msg is not -1. If it is,
+ * the recipient won't know the message was destined
+ * for it. -- Cort
+ */
+ for ( i = 0; i <= smp_num_cpus ; i++ )
+ pmac_smp_message[i] = -1;
+ switch( target )
+ {
+ case MSG_ALL:
+ pmac_smp_message[smp_processor_id()] = msg;
+ /* fall through */
+ case MSG_ALL_BUT_SELF:
+ for ( i = 0 ; i < smp_num_cpus ; i++ )
+ if ( i != smp_processor_id () )
+ pmac_smp_message[i] = msg;
+ break;
+ default:
+ pmac_smp_message[target] = msg;
+ break;
+ }
/* interrupt secondary processor */
out_be32(PSURGE_INTR, ~0);
out_be32(PSURGE_INTR, 0);
/* interrupt primary */
/**(volatile unsigned long *)(0xf3019000);*/
break;
-
case _MACH_chrp:
case _MACH_prep:
- /*
- * There has to be some way of doing this better -
- * perhaps a sent-to-all or send-to-all-but-self
- * in the openpic. This gets us going for now, though.
- * -- Cort
- */
+ case _MACH_gemini:
+ /* make sure we're sending something that translates to an IPI */
+ if ( msg > 0x3 )
+ break;
switch ( target )
{
case MSG_ALL:
- for ( i = 0 ; i < smp_num_cpus ; i++ )
- openpic_cause_IPI(i, 0, 0xffffffff );
+ openpic_cause_IPI(smp_processor_id(), msg, 0xffffffff);
break;
case MSG_ALL_BUT_SELF:
- for ( i = 0 ; i < smp_num_cpus ; i++ )
- if ( i != smp_processor_id () )
- openpic_cause_IPI(i, 0,
- 0xffffffff & ~(1 << smp_processor_id()));
+ openpic_cause_IPI(smp_processor_id(), msg,
+ 0xffffffff & ~(1 << smp_processor_id()));
break;
default:
- openpic_cause_IPI(target, 0, 1U << target);
+ openpic_cause_IPI(smp_processor_id(), msg, 1<<target);
break;
}
break;
}
-
- spin_unlock(&mesg_pass_lock);
}
void __init smp_boot_cpus(void)
break;
}
case _MACH_gemini:
- for ( i = 0; i < 4 ; i++ )
- openpic_enable_IPI(i);
cpu_nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK)>>2;
cpu_nr = (cpu_nr == 0) ? 4 : cpu_nr;
break;
case _MACH_chrp:
*(unsigned long *)KERNELBASE = i;
asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
-#if 0
- device = find_type_devices("cpu");
- /* assume cpu device list is in order, find the ith cpu */
- for ( a = i; device && a; device = device->next, a-- )
- ;
- if ( !device )
- break;
- printk( "Starting %s (%lu): ", device->full_name,
- *(ulong *)get_property(device, "reg", NULL) );
- call_rtas( "start-cpu", 3, 1, NULL,
- *(ulong *)get_property(device, "reg", NULL),
- __pa(__secondary_start_chrp), i);
-#endif
break;
case _MACH_prep:
*MotSave_SmpIar = (unsigned long)__secondary_start_psurge - KERNELBASE;
}
}
+ if ( _machine & (_MACH_gemini|_MACH_chrp|_MACH_prep) )
+ do_openpic_setup_cpu();
if ( _machine == _MACH_Pmac )
{
/* reset the entry point so if we get another intr we won't
#endif
init_idle();
cpu_callin_map[current->processor] = 1;
+ /*
+ * Each processor has to do this and this is the best
+ * place to stick it for now.
+ * -- Cort
+ */
+ if ( _machine & (_MACH_gemini|_MACH_chrp|_MACH_prep) )
+ do_openpic_setup_cpu();
while(!smp_commenced)
barrier();
__sti();
void __init smp_store_cpu_info(int id)
{
struct cpuinfo_PPC *c = &cpu_data[id];
-
/* assume bogomips are same for everything */
c->loops_per_sec = loops_per_sec;
c->pvr = _get_PVR();
}
+
static void append_mem_piece(struct mem_pieces *, unsigned, unsigned);
extern struct task_struct *current_set[NR_CPUS];
+unsigned long cpu_invalidate_tlb[NR_CPUS];
PTE *Hash, *Hash_end;
unsigned long Hash_size, Hash_mask;
#ifndef CONFIG_8xx
__clear_user(Hash, Hash_size);
_tlbia();
+#ifdef __SMP__
+ smp_send_tlb_invalidate(0);
+#endif
#else
asm volatile ("tlbia" : : );
#endif
mm->context = NO_CONTEXT;
if (mm == current->mm)
activate_context(current);
+#ifdef __SMP__
+ smp_send_tlb_invalidate(0);
+#endif
#else
asm volatile ("tlbia" : : );
#endif
flush_hash_page(vma->vm_mm->context, vmaddr);
else
flush_hash_page(0, vmaddr);
+#ifdef __SMP__
+ smp_send_tlb_invalidate(0);
+#endif
#else
asm volatile ("tlbia" : : );
#endif
{
flush_hash_page(mm->context, start);
}
+#ifdef __SMP__
+ smp_send_tlb_invalidate(0);
+#endif
#else
asm volatile ("tlbia" : : );
#endif
}
read_unlock(&tasklist_lock);
flush_hash_segments(0x10, 0xffffff);
+#ifdef __SMP__
+ smp_send_tlb_invalidate(0);
+#endif
atomic_set(&next_mmu_context, 0);
/* make sure current always has a context */
current->mm->context = MUNGE_CONTEXT(atomic_inc_return(&next_mmu_context));
-/* $Id: head.S,v 1.95.2.3 1999/11/12 15:45:45 davem Exp $
+/* $Id: head.S,v 1.95.2.5 1999/12/02 11:51:56 davem Exp $
* head.S: The initial boot code for the Sparc port of Linux.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
t_bad9b:BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) BAD_TRAP(0x9f)
t_getcc:GETCC_TRAP /* Get Condition Codes */
t_setcc:SETCC_TRAP /* Set Condition Codes */
-t_bada2:BAD_TRAP(0xa2) BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+t_getpsr:GETPSR_TRAP /* Get PSR Register */
+t_bada3:BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
t_slowi:INDIRECT_SOLARIS_SYSCALL(156)
t_bada8:BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
t_badac:BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
- BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP
- BAD_TRAP(0xa2) BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+ BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
+ BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
INDIRECT_SOLARIS_SYSCALL(156) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
- BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP
- BAD_TRAP(0xa2) BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+ BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
+ BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
INDIRECT_SOLARIS_SYSCALL(156) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
- BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP
- BAD_TRAP(0xa2) BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+ BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
+ BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
INDIRECT_SOLARIS_SYSCALL(156) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
-/* $Id: traps.c,v 1.58.2.1 1999/08/19 01:11:16 davem Exp $
+/* $Id: traps.c,v 1.58.2.2 1999/12/01 23:55:43 davem Exp $
* arch/sparc64/kernel/traps.c
*
* Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
#include <asm/uaccess.h>
#include <asm/fpumacro.h>
#include <asm/lsu.h>
+#include <asm/psrcompat.h>
#ifdef CONFIG_KMOD
#include <linux/kmod.h>
#endif
}
#endif
+void do_getpsr(struct pt_regs *regs)
+{
+ regs->u_regs[UREG_I0] = tstate_to_psr(regs->tstate);
+ regs->tpc = regs->tnpc;
+ regs->tnpc += 4;
+}
+
void trap_init(void)
{
}
-/* $Id: ttable.S,v 1.28.2.1 1999/08/19 01:11:14 davem Exp $
+/* $Id: ttable.S,v 1.28.2.2 1999/12/01 23:55:44 davem Exp $
* ttable.S: Sparc V9 Trap Table(s) with SpitFire extensions.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
tl0_resv11e: TRAP_UTRAP(UT_TRAP_INSTRUCTION_30,0x11e) TRAP_UTRAP(UT_TRAP_INSTRUCTION_31,0x11f)
tl0_getcc: GETCC_TRAP
tl0_setcc: SETCC_TRAP
-tl0_resv122: BTRAP(0x122) BTRAP(0x123) BTRAP(0x124) BTRAP(0x125) BTRAP(0x126)
+tl0_getpsr: TRAP(do_getpsr)
+tl0_resv123: BTRAP(0x123) BTRAP(0x124) BTRAP(0x125) BTRAP(0x126)
tl0_solindir: INDIRECT_SOLARIS_SYSCALL(156)
tl0_resv128: BTRAP(0x128) BTRAP(0x129) BTRAP(0x12a) BTRAP(0x12b) BTRAP(0x12c)
tl0_resv12d: BTRAP(0x12d) BTRAP(0x12e) BTRAP(0x12f) BTRAP(0x130) BTRAP(0x131)
switch (cmd) {
case BLKFLSBUF:
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
- invalidate_buffers(inode->i_rdev);
+ /* special: we want to release the ramdisk memory,
+ it's not like with the other blockdevices where
+ this ioctl only flushes away the buffer cache. */
+ destroy_buffers(inode->i_rdev);
break;
case BLKGETSIZE: /* Return device size */
int i;
for (i = 0 ; i < NUM_RAMDISKS; i++)
- invalidate_buffers(MKDEV(MAJOR_NR, i));
+ destroy_buffers(MKDEV(MAJOR_NR, i));
unregister_blkdev( MAJOR_NR, "ramdisk" );
blk_dev[MAJOR_NR].request_fn = 0;
endif
endif
-
# DBGDEF = \
-# -DDEBUG \
-# -DSK_DEBUG_CHKMOD=0x00010000L \
-# -DSK_DEBUG_CHKCAT=0xffff0000L
+# -DDEBUG
+
+ifdef DEBUG
+DBGDEF += \
+-DSK_DEBUG_CHKMOD=0x00000000L \
+-DSK_DEBUG_CHKCAT=0x00000000L
+endif
# **** possible debug modules for SK_DEBUG_CHKMOD *****************
#ifdef DEBUG
#define SK_DBG_PRINTF printk
+#ifndef SK_DEBUG_CHKMOD
+#define SK_DEBUG_CHKMOD 0
+#endif
+#ifndef SK_DEBUG_CHKCAT
+#define SK_DEBUG_CHKCAT 0
+#endif
/* those come from the makefile */
#define SK_DBG_CHKMOD(pAC) (SK_DEBUG_CHKMOD)
#define SK_DBG_CHKCAT(pAC) (SK_DEBUG_CHKCAT)
-/* $Id: advansys.c,v 1.68 1999/11/19 01:57:47 bobf Exp bobf $ */
-#define ASC_VERSION "3.2L" /* AdvanSys Driver Version */
+/* $Id: advansys.c,v 1.69 1999/11/29 18:37:53 bobf Exp bobf $ */
+#define ASC_VERSION "3.2M" /* AdvanSys Driver Version */
/*
* advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
at line 7475. The reqp->sgblkp pointer must be initialized
to NULL in adv_get_sglist().
+ 3.2M (11/29/99):
+ 1. Really fix bug in adv_get_sglist().
+ 2. Incorporate v2.3.29 changes into driver.
+
J. Known Problems/Fix List (XXX)
1. Need to add memory mapping workaround. Test the memory mapping.
/* BIOS start address. */
if (ASC_NARROW_BOARD(boardp)) {
- shp->base = (char *) ((ulong) AscGetChipBiosAddress(
- asc_dvc_varp->iop_base,
- asc_dvc_varp->bus_type));
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,3,29)
+ shp->base =
+#else /* version >= v2.3.29 */
+ shp->base = (char *)
+#endif /* version < v2.3.29 */
+ ((ulong) AscGetChipBiosAddress(
+ asc_dvc_varp->iop_base,
+ asc_dvc_varp->bus_type));
} else {
/*
* Fill-in BIOS board variables. The Wide BIOS saves
* Convert x86 realmode code segment to a linear
* address by shifting left 4.
*/
- shp->base = (uchar *) ((ulong) boardp->bios_codeseg << 4);
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,3,29)
+ shp->base =
+#else /* version >= v2.3.29 */
+ shp->base = (char *)
+#endif /* version < v2.3.29 */
+ ((ulong) boardp->bios_codeseg << 4);
} else {
shp->base = 0;
}
slp = (struct scatterlist *) scp->request_buffer;
sg_elem_cnt = scp->use_sg;
prev_sg_block = NULL;
- reqp->sgblkp == NULL;
+ reqp->sgblkp = NULL;
do
{
-/* $Id: advansys.h,v 1.17 1998/01/08 21:23:49 bobf Exp bobf $ */
+/* $Id: advansys.h,v 1.18 1999/11/29 21:47:16 bobf Exp bobf $ */
/*
* advansys.h - Linux Host Driver for AdvanSys SCSI Adapters
int advansys_biosparam(Disk *, int, int[]);
#else /* version >= v1.3.0 */
int advansys_biosparam(Disk *, kdev_t, int[]);
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,3,28)
extern struct proc_dir_entry proc_scsi_advansys;
+#endif /* version < v2.3.28 */
int advansys_proc_info(char *, char **, off_t, int, int, int);
#endif /* version >= v1.3.0 */
*/ \
ENABLE_CLUSTERING, /* unsigned use_clustering:1 */ \
}
-#else /* version >= v2.1.75 */
+#elif LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,3,28)
#define ADVANSYS { \
proc_dir: &proc_scsi_advansys, \
proc_info: advansys_proc_info, \
queuecommand: advansys_queuecommand, \
abort: advansys_abort, \
reset: advansys_reset, \
- bios_param: advansys_biosparam, \
+ bios_param: advansys_biosparam, \
/* \
* Because the driver may control an ISA adapter 'unchecked_isa_dma' \
* must be set. The flag will be cleared in advansys_detect for non-ISA \
*/ \
use_clustering: ENABLE_CLUSTERING, \
}
-#endif /* version >= v2.1.75 */
+#else /* version >= v2.3.28 */
+#define ADVANSYS { \
+ proc_name: "advansys", \
+ proc_info: advansys_proc_info, \
+ name: "advansys", \
+ detect: advansys_detect, \
+ release: advansys_release, \
+ info: advansys_info, \
+ command: advansys_command, \
+ queuecommand: advansys_queuecommand, \
+ abort: advansys_abort, \
+ reset: advansys_reset, \
+ bios_param: advansys_biosparam, \
+ /* \
+ * Because the driver may control an ISA adapter 'unchecked_isa_dma' \
+ * must be set. The flag will be cleared in advansys_detect for non-ISA \
+ * adapters. Refer to the comment in scsi_module.c for more information. \
+ */ \
+ unchecked_isa_dma: 1, \
+ /* \
+ * All adapters controlled by this driver are capable of large \
+ * scatter-gather lists. According to the mid-level SCSI documentation \
+ * this obviates any performance gain provided by setting \
+ * 'use_clustering'. But empirically while CPU utilization is increased \
+ * by enabling clustering, I/O throughput increases as well. \
+ */ \
+ use_clustering: ENABLE_CLUSTERING, \
+}
+#endif /* version >= v2.3.28 */
#endif /* _ADVANSYS_H */
extern const char *atp870u_info(struct Scsi_Host *);
extern int atp870u_proc_info(char *, char **, off_t, int, int, int);
+extern struct proc_dir_entry proc_scsi_atp870u;
#define ATP870U { \
next: NULL, \
#define MAX_SCSI_DEVICE_CODE 14
extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
+extern spinlock_t scsi_malloc_lock;
#ifdef DEBUG
#define SCSI_TIMEOUT (5*HZ)
* - RMK
*/
+/* invalidate_buffers/set_blocksize/sync_dev race conditions and
+ fs corruption fixes, 1999, Andrea Arcangeli <andrea@suse.de> */
+
#include <linux/malloc.h>
#include <linux/locks.h>
#include <linux/errno.h>
void sync_dev(kdev_t dev)
{
- sync_buffers(dev, 0);
sync_supers(dev);
sync_inodes(dev);
- sync_buffers(dev, 0);
DQUOT_SYNC(dev);
+ /* sync all the dirty buffers out to disk only _after_ all the
+ high level layers finished generated buffer dirty data
+ (or we'll return with some buffer still dirty on the blockdevice
+ so breaking the semantics of this call) */
+ sync_buffers(dev, 0);
/*
* FIXME(eric) we need to sync the physical devices here.
* This is because some (scsi) controllers have huge amounts of
return err;
}
-void invalidate_buffers(kdev_t dev)
-{
- int i;
- int nlist;
- struct buffer_head * bh;
-
- for(nlist = 0; nlist < NR_LIST; nlist++) {
- bh = lru_list[nlist];
- for (i = nr_buffers_type[nlist]*2 ; --i > 0 ; bh = bh->b_next_free) {
- if (bh->b_dev != dev)
- continue;
- wait_on_buffer(bh);
- if (bh->b_dev != dev)
- continue;
- if (bh->b_count)
- continue;
- bh->b_flushtime = 0;
- clear_bit(BH_Protected, &bh->b_state);
- clear_bit(BH_Uptodate, &bh->b_state);
- clear_bit(BH_Dirty, &bh->b_state);
- clear_bit(BH_Req, &bh->b_state);
- }
- }
-}
-
/* After several hours of tedious analysis, the following hash
* function won. Do not mess with it... -DaveM
*/
remove_from_lru_list(bh);
}
-static inline void put_last_free(struct buffer_head * bh)
+static void put_last_free(struct buffer_head * bh)
{
if (bh) {
struct buffer_head **bhp = &free_list[BUFSIZE_INDEX(bh->b_size)];
+ bh->b_count = 0;
+ bh->b_state = 0;
+ remove_from_queues(bh);
bh->b_dev = B_FREE; /* So it is obvious we are on the free list. */
/* Add to back of free list. */
{
/* put at end of free list */
if(bh->b_dev == B_FREE) {
- put_last_free(bh);
+ panic("B_FREE inserted into queues");
} else {
struct buffer_head **bhp = &lru_list[bh->b_list];
return 0;
}
+/* If invalidate_buffers() will trash dirty buffers, it means some kind
+ of fs corruption is going on. Trashing dirty data always imply losing
+ information that was supposed to be just stored on the physical layer
+ by the user.
+
+ Thus invalidate_buffers in general usage is not allwowed to trash dirty
+ buffers. For example ioctl(FLSBLKBUF) expects dirty data to be preserved.
+
+ NOTE: In the case where the user removed a removable-media-disk even if
+ there's still dirty data not synced on disk (due a bug in the device driver
+ or due an error of the user), by not destroying the dirty buffers we could
+ generate corruption also on the next media inserted, thus a parameter is
+ necessary to handle this case in the most safe way possible (trying
+ to not corrupt also the new disk inserted with the data belonging to
+ the old now corrupted disk). Also for the ramdisk the natural thing
+ to do in order to release the ramdisk memory is to destroy dirty buffers.
+
+ These are two special cases. Normal usage imply the device driver
+ to issue a sync on the device (without waiting I/O completation) and
+ then an invalidate_buffers call that doesn't trashes dirty buffers. */
+void __invalidate_buffers(kdev_t dev, int destroy_dirty_buffers)
+{
+ int i, nlist, slept;
+ struct buffer_head * bh, * bhnext;
+
+ again:
+ slept = 0;
+ for(nlist = 0; nlist < NR_LIST; nlist++) {
+ bh = lru_list[nlist];
+ if (!bh)
+ continue;
+ for (i = nr_buffers_type[nlist] ; i > 0 ;
+ bh = bhnext, i--)
+ {
+ bhnext = bh->b_next_free;
+ if (bh->b_dev != dev)
+ continue;
+ if (buffer_locked(bh))
+ {
+ slept = 1;
+ __wait_on_buffer(bh);
+ }
+ if (!bh->b_count &&
+ (destroy_dirty_buffers || !buffer_dirty(bh)))
+ put_last_free(bh);
+ if (slept)
+ goto again;
+ }
+ }
+}
+
void set_blocksize(kdev_t dev, int size)
{
extern int *blksize_size[];
- int i, nlist;
+ int i, nlist, slept;
struct buffer_head * bh, *bhnext;
if (!blksize_size[MAJOR(dev)])
/* We need to be quite careful how we do this - we are moving entries
* around on the free list, and we can get in a loop if we are not careful.
*/
- for(nlist = 0; nlist < NR_LIST; nlist++) {
+ again:
+ slept = 0;
+ for(nlist = 0; nlist < NR_LIST; nlist++) {
bh = lru_list[nlist];
- for (i = nr_buffers_type[nlist]*2 ; --i > 0 ; bh = bhnext) {
- if(!bh)
- break;
-
- bhnext = bh->b_next_free;
- if (bh->b_dev != dev)
- continue;
- if (bh->b_size == size)
- continue;
- bhnext->b_count++;
- wait_on_buffer(bh);
- bhnext->b_count--;
- if (bh->b_dev == dev && bh->b_size != size) {
- clear_bit(BH_Dirty, &bh->b_state);
- clear_bit(BH_Uptodate, &bh->b_state);
- clear_bit(BH_Req, &bh->b_state);
- bh->b_flushtime = 0;
+ if (!bh)
+ continue;
+ for (i = nr_buffers_type[nlist] ; i > 0 ;
+ bh = bhnext, i--)
+ {
+ bhnext = bh->b_next_free;
+ if (bh->b_dev != dev || bh->b_size == size)
+ continue;
+ if (buffer_dirty(bh))
+ printk(KERN_ERR "set_blocksize: dev %s buffer_dirty %lu size %lu\n", kdevname(dev), bh->b_blocknr, bh->b_size);
+ if (buffer_locked(bh))
+ {
+ slept = 1;
+ wait_on_buffer(bh);
}
- remove_from_hash_queue(bh);
+ if (!bh->b_count)
+ put_last_free(bh);
+ else
+ printk(KERN_ERR
+ "set_blocksize: "
+ "b_count %d, dev %s, block %lu!\n",
+ bh->b_count, bdevname(bh->b_dev),
+ bh->b_blocknr);
+ if (slept)
+ goto again;
}
}
}
__brelse(buf);
return;
}
- buf->b_count = 0;
- buf->b_state = 0;
- remove_from_queues(buf);
put_last_free(buf);
}
if (sb && invalidate_inodes(sb))
printk("VFS: busy inodes on changed media.\n");
- invalidate_buffers(dev);
+ /* special: trash all dirty data as well as the media is changed */
+ destroy_buffers(dev);
if (fops->revalidate)
fops->revalidate(dev);
__constant_htonl(HFS_HDR_VERSION_1), /* version */
5, /* entries */
{ /* descr[] */
- {HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name), ~0},
- {HFS_HDR_COMNT, offsetof(struct hfs_dbl_hdr, comment), 0},
- {HFS_HDR_OLDI, offsetof(struct hfs_dbl_hdr, create_time), 16},
- {HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo), 32},
+ {HFS_HDR_FNAME, offsetof(struct hfs_nat_hdr, real_name), ~0},
+ {HFS_HDR_COMNT, offsetof(struct hfs_nat_hdr, comment), 0},
+ {HFS_HDR_OLDI, offsetof(struct hfs_nat_hdr, old_info), 16},
+ {HFS_HDR_FINFO, offsetof(struct hfs_nat_hdr, finderinfo), 32},
{HFS_HDR_RSRC, HFS_NAT_HDR_LEN, ~0},
},
{ /* order[] */
nfs_invalidate_dircache(dir);
error = nfs_proc_mkdir(NFS_DSERVER(dentry), NFS_FH(dentry->d_parent),
dentry->d_name.name, &sattr, &fhandle, &fattr);
+ if (!error)
+ dir->i_nlink++;
return error;
}
/* Update i_nlink and invalidate dentry. */
if (!error) {
d_drop(dentry);
- if (dentry->d_inode->i_nlink)
- dentry->d_inode->i_nlink --;
+ if (dir->i_nlink)
+ dir->i_nlink--;
}
return error;
umount_error = do_umount(old_root_dev,1, 0);
if (!umount_error) {
printk("okay\n");
- invalidate_buffers(old_root_dev);
+ /* special: the old device driver is going to be
+ a ramdisk and the point of this call is to free its
+ protected memory (even if dirty). */
+ destroy_buffers(old_root_dev);
return 0;
}
printk(KERN_ERR "error %d\n",umount_error);
extern void smp_message_pass(int target, int msg, unsigned long data, int wait);
extern void smp_store_cpu_info(int id);
-extern void smp_message_recv(void);
+extern void smp_message_recv(int);
+extern void smp_send_tlb_invalidate(int);
#define NO_PROC_ID 0xFF /* No processor magic marker */
#define PROC_CHANGE_PENALTY 20
-/* $Id: head.h,v 1.36.2.1 1999/09/22 11:37:45 jj Exp $ */
+/* $Id: head.h,v 1.36.2.2 1999/12/01 23:55:47 davem Exp $ */
#ifndef __SPARC_HEAD_H
#define __SPARC_HEAD_H
#define SETCC_TRAP \
b setcc_trap_handler; mov %psr, %l0; nop; nop;
+/* The Get PSR software trap for userland. */
+#define GETPSR_TRAP \
+ mov %psr, %o0; jmpl %l2, %g0; rett %l2 + 4; nop;
+
/* This is for hard interrupts from level 1-14, 15 is non-maskable (nmi) and
* gets handled with another macro.
*/
-/* $Id: ioctl.h,v 1.5 1996/05/17 03:31:09 davem Exp $ */
+/* $Id: ioctl.h,v 1.5.12.1 1999/12/01 23:57:52 davem Exp $ */
#ifndef _SPARC_IOCTL_H
#define _SPARC_IOCTL_H
#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
+/* ...and for the PCMCIA... */
+
+#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT)
+#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT)
+#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
+#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT)
+#define IOCSIZE_SHIFT (_IOC_SIZESHIFT)
+
#endif /* !(_SPARC_IOCTL_H) */
extern int check_disk_change(kdev_t dev);
extern int invalidate_inodes(struct super_block * sb);
extern void invalidate_inode_pages(struct inode *);
-extern void invalidate_buffers(kdev_t dev);
+#define invalidate_buffers(dev) __invalidate_buffers((dev), 0)
+#define destroy_buffers(dev) __invalidate_buffers((dev), 1)
+extern void __invalidate_buffers(kdev_t dev, int);
extern int floppy_is_wp(int minor);
extern void sync_inodes(kdev_t dev);
extern void write_inode_now(struct inode *inode);
*order[HFS_HDR_MAX]; /* 'descr' ordered by offset */
};
+/* header layout for netatalk's v1 appledouble file format */
+struct hfs_nat_hdr {
+ hfs_lword_t magic;
+ hfs_lword_t version;
+ hfs_byte_t homefs[16];
+ hfs_word_t entries;
+ hfs_byte_t descrs[12*5];
+ hfs_byte_t real_name[255]; /* id=3 */
+ hfs_byte_t comment[200]; /* id=4 XXX: not yet implemented */
+ hfs_byte_t old_info[16]; /* id=7 */
+ hfs_u8 finderinfo[32]; /* id=9 */
+};
+
/*
* Default header layout for Netatalk and AppleDouble
*/
hfs_u8 prodosi[8]; /* id=11 */
};
-
/* finder metadata for CAP */
struct hfs_cap_info {
hfs_byte_t fi_fndr[32]; /* Finder's info */
* Vector numbers
*/
-#define OPENPIC_VEC_SOURCE 0x10 /* and up */
-#define OPENPIC_VEC_TIMER 0x40 /* and up */
-#define OPENPIC_VEC_IPI 0x50 /* and up */
-#define OPENPIC_VEC_SPURIOUS 99
+#define OPENPIC_VEC_TIMER 64 /* and up */
+#define OPENPIC_VEC_IPI 70 /* and up */
+#define OPENPIC_VEC_SPURIOUS 127
/*
* SCSI opcodes
*/
-extern spinlock_t scsi_malloc_lock;
-
#define TEST_UNIT_READY 0x00
#define REZERO_UNIT 0x01
#define REQUEST_SENSE 0x03
EXPORT_SYMBOL(fput);
EXPORT_SYMBOL(put_filp);
EXPORT_SYMBOL(check_disk_change);
-EXPORT_SYMBOL(invalidate_buffers);
+EXPORT_SYMBOL(__invalidate_buffers);
EXPORT_SYMBOL(invalidate_inodes);
EXPORT_SYMBOL(invalidate_inode_pages);
EXPORT_SYMBOL(truncate_inode_pages);
if (dst == NULL) {
struct flowi fl;
- struct dst_entry *dst;
/* BUGGG_FUTURE: Again, it is not clear how
to handle rthdr case. Ignore this complexity