!C99Shell v. 1.0 pre-release build #13!

Software: Apache/2.0.54 (Unix) mod_perl/1.99_09 Perl/v5.8.0 mod_ssl/2.0.54 OpenSSL/0.9.7l DAV/2 FrontPage/5.0.2.2635 PHP/4.4.0 mod_gzip/2.0.26.1a 

uname -a: Linux snow.he.net 4.4.276-v2-mono-1 #1 SMP Wed Jul 21 11:21:17 PDT 2021 i686 

uid=99(nobody) gid=98(nobody) groups=98(nobody) 

Safe-mode: OFF (not secure)

/usr/src/linux-2.4.18-xfs-1.1/arch/ppc/kernel/   drwxr-xr-x
Free 318.37 GB of 458.09 GB (69.5%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     irq.c (24.38 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
 * BK Id: SCCS/s.irq.c 1.34 12/01/01 20:09:06 benh
 */
/*
 *  arch/ppc/kernel/irq.c
 *
 *  Derived from arch/i386/kernel/irq.c
 *    Copyright (C) 1992 Linus Torvalds
 *  Adapted from arch/i386 by Gary Thomas
 *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
 *  Updated and modified by Cort Dougan <cort@fsmlabs.com>
 *    Copyright (C) 1996-2001 Cort Dougan
 *  Adapted for Power Macintosh by Paul Mackerras
 *    Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
 *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
 *  
 * This file contains the code used by various IRQ handling routines:
 * asking for different IRQ's should be done through these routines
 * instead of just grabbing them. Thus setups with different IRQ numbers
 * shouldn't result in any weird surprises, and installing new handlers
 * should be easier.
 *
 * The MPC8xx has an interrupt mask in the SIU.  If a bit is set, the
 * interrupt is _enabled_.  As expected, IRQ0 is bit 0 in the 32-bit
 * mask register (of which only 16 are defined), hence the weird shifting
 * and compliment of the cached_irq_mask.  I want to be able to stuff
 * this right into the SIU SMASK register.
 * Many of the prep/chrp functions are conditional compiled on CONFIG_8xx
 * to reduce code space and undefined function references.
 */


#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/threads.h>
#include <linux/kernel_stat.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
#include <linux/config.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/proc_fs.h>
#include <linux/random.h>

#include <asm/uaccess.h>
#include <asm/bitops.h>
#include <asm/hydra.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/gg2.h>
#include <asm/cache.h>
#include <asm/prom.h>
#include <asm/amigaints.h>
#include <asm/amigahw.h>
#include <asm/amigappc.h>
#include <asm/ptrace.h>

#include "local_irq.h"

extern atomic_t ipi_recv;
extern atomic_t ipi_sent;
void enable_irq(unsigned int irq_nr);
void disable_irq(unsigned int irq_nr);

static void register_irq_proc (unsigned int irq);

#define MAXCOUNT 10000000

irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned =
    { [0 ... NR_IRQS-1] = { 0, NULL, NULL, 0, SPIN_LOCK_UNLOCKED}};
    
int ppc_spurious_interrupts = 0;
struct irqaction *ppc_irq_action[NR_IRQS];
unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
atomic_t ppc_n_lost_interrupts;

/* nasty hack for shared irq's since we need to do kmalloc calls but
 * can't very early in the boot when we need to do a request irq.
 * this needs to be removed.
 * -- Cort
 */
#define IRQ_KMALLOC_ENTRIES 8
static int cache_bitmask = 0;
static struct irqaction malloc_cache[IRQ_KMALLOC_ENTRIES];
extern int mem_init_done;

#if defined(CONFIG_TAU_INT)
extern int tau_interrupts(unsigned long cpu);
extern int tau_initialized;
#endif

void *irq_kmalloc(size_t size, int pri)
{
    unsigned int i;
    if ( mem_init_done )
        return kmalloc(size,pri);
    for ( i = 0; i < IRQ_KMALLOC_ENTRIES ; i++ )
        if ( ! ( cache_bitmask & (1<<i) ) )
        {
            cache_bitmask |= (1<<i);
            return (void *)(&malloc_cache[i]);
        }
    return 0;
}

void irq_kfree(void *ptr)
{
    unsigned int i;
    for ( i = 0 ; i < IRQ_KMALLOC_ENTRIES ; i++ )
        if ( ptr == &malloc_cache[i] )
        {
            cache_bitmask &= ~(1<<i);
            return;
        }
    kfree(ptr);
}

int
setup_irq(unsigned int irq, struct irqaction * new)
{
    int shared = 0;
    unsigned long flags;
    struct irqaction *old, **p;
    irq_desc_t *desc = irq_desc + irq;

    /*
     * Some drivers like serial.c use request_irq() heavily,
     * so we have to be careful not to interfere with a
     * running system.
     */
    if (new->flags & SA_SAMPLE_RANDOM) {
        /*
         * This function might sleep, we want to call it first,
         * outside of the atomic block.
         * Yes, this might clear the entropy pool if the wrong
         * driver is attempted to be loaded, without actually
         * installing a new handler, but is this really a problem,
         * only the sysadmin is able to do this.
         */
        rand_initialize_irq(irq);
    }

    /*
     * The following block of code has to be executed atomically
     */
    spin_lock_irqsave(&desc->lock,flags);
    p = &desc->action;
    if ((old = *p) != NULL) {
        /* Can't share interrupts unless both agree to */
        if (!(old->flags & new->flags & SA_SHIRQ)) {
            spin_unlock_irqrestore(&desc->lock,flags);
            return -EBUSY;
        }

        /* add new interrupt at end of irq queue */
        do {
            p = &old->next;
            old = *p;
        } while (old);
        shared = 1;
    }

    *p = new;

    if (!shared) {
        desc->depth = 0;
        desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING);
        unmask_irq(irq);
    }
    spin_unlock_irqrestore(&desc->lock,flags);

    register_irq_proc(irq);
    return 0;
}

#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
/* Name change so we can catch standard drivers that potentially mess up
 * the internal interrupt controller on 8xx and 8260.  Just bear with me,
 * I don't like this either and I am searching a better solution.  For
 * now, this is what I need. -- Dan
 */
#define request_irq    request_8xxirq
#elif defined(CONFIG_APUS)
#define request_irq    request_sysirq
#define free_irq    sys_free_irq
#endif

void free_irq(unsigned int irq, void* dev_id)
{
    irq_desc_t *desc;
    struct irqaction **p;
    unsigned long flags;

    desc = irq_desc + irq;
    spin_lock_irqsave(&desc->lock,flags);
    p = &desc->action;
    for (;;) {
        struct irqaction * action = *p;
        if (action) {
            struct irqaction **pp = p;
            p = &action->next;
            if (action->dev_id != dev_id)
                continue;

            /* Found it - now remove it from the list of entries */
            *pp = action->next;
            if (!desc->action) {
                desc->status |= IRQ_DISABLED;
                mask_irq(irq);
            }
            spin_unlock_irqrestore(&desc->lock,flags);

#ifdef CONFIG_SMP
            /* Wait to make sure it's not being used on another CPU */
            while (desc->status & IRQ_INPROGRESS)
                barrier();
#endif
            irq_kfree(action);
            return;
        }
        printk("Trying to free free IRQ%d\n",irq);
        spin_unlock_irqrestore(&desc->lock,flags);
        break;
    }
    return;
}

int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
    unsigned long irqflags, const char * devname, void *dev_id)
{
    struct irqaction *action;
    int retval;

    if (irq >= NR_IRQS)
        return -EINVAL;
    if (!handler)
    {
        /*
         * free_irq() used to be implemented as a call to
         * request_irq() with handler being NULL.  Now we have
         * a real free_irq() but need to allow the old behavior
         * for old code that hasn't caught up yet.
         *  -- Cort <cort@fsmlabs.com>
         */
        free_irq(irq, dev_id);
        return 0;
    }
    
    action = (struct irqaction *)
        irq_kmalloc(sizeof(struct irqaction), GFP_KERNEL);
    if (!action) {
        printk(KERN_ERR "irq_kmalloc() failed for irq %d !\n", irq);
        return -ENOMEM;
    }
    
    action->handler = handler;
    action->flags = irqflags;                    
    action->mask = 0;
    action->name = devname;
    action->dev_id = dev_id;
    action->next = NULL;
    
    retval = setup_irq(irq, action);
    if (retval)
    {
        kfree(action);
        return retval;
    }
        
    return 0;
}

/*
 * Generic enable/disable code: this just calls
 * down into the PIC-specific version for the actual
 * hardware disable after having gotten the irq
 * controller lock. 
 */
 
/**
 *    disable_irq_nosync - disable an irq without waiting
 *    @irq: Interrupt to disable
 *
 *    Disable the selected interrupt line. Disables of an interrupt
 *    stack. Unlike disable_irq(), this function does not ensure existing
 *    instances of the IRQ handler have completed before returning.
 *
 *    This function may be called from IRQ context.
 */
 
 void disable_irq_nosync(unsigned int irq)
{
    irq_desc_t *desc = irq_desc + irq;
    unsigned long flags;

    spin_lock_irqsave(&desc->lock, flags);
    if (!desc->depth++) {
        if (!(desc->status & IRQ_PER_CPU))
            desc->status |= IRQ_DISABLED;
        mask_irq(irq);
    }
    spin_unlock_irqrestore(&desc->lock, flags);
}

/**
 *    disable_irq - disable an irq and wait for completion
 *    @irq: Interrupt to disable
 *
 *    Disable the selected interrupt line. Disables of an interrupt
 *    stack. That is for two disables you need two enables. This
 *    function waits for any pending IRQ handlers for this interrupt
 *    to complete before returning. If you use this function while
 *    holding a resource the IRQ handler may need you will deadlock.
 *
 *    This function may be called - with care - from IRQ context.
 */
 
void disable_irq(unsigned int irq)
{
    disable_irq_nosync(irq);

    if (!local_irq_count(smp_processor_id())) {
        do {
            barrier();
        } while (irq_desc[irq].status & IRQ_INPROGRESS);
    }
}

/**
 *    enable_irq - enable interrupt handling on an irq
 *    @irq: Interrupt to enable
 *
 *    Re-enables the processing of interrupts on this IRQ line
 *    providing no disable_irq calls are now in effect.
 *
 *    This function may be called from IRQ context.
 */
 
void enable_irq(unsigned int irq)
{
    irq_desc_t *desc = irq_desc + irq;
    unsigned long flags;

    spin_lock_irqsave(&desc->lock, flags);
    switch (desc->depth) {
    case 1: {
        unsigned int status = desc->status & ~IRQ_DISABLED;
        desc->status = status;
        if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
            desc->status = status | IRQ_REPLAY;
            hw_resend_irq(desc->handler,irq);
        }
        unmask_irq(irq);
        /* fall-through */
    }
    default:
        desc->depth--;
        break;
    case 0:
        printk("enable_irq(%u) unbalanced\n", irq);
    }
    spin_unlock_irqrestore(&desc->lock, flags);
}

int get_irq_list(char *buf)
{
#ifdef CONFIG_APUS
    return apus_get_irq_list (buf);
#else
    int i, len = 0, j;
    struct irqaction * action;

    len += sprintf(buf+len, "           ");
    for (j=0; j<smp_num_cpus; j++)
        len += sprintf(buf+len, "CPU%d       ",j);
    *(char *)(buf+len++) = '\n';

    for (i = 0 ; i < NR_IRQS ; i++) {
        action = irq_desc[i].action;
        if ( !action || !action->handler )
            continue;
        len += sprintf(buf+len, "%3d: ", i);        
#ifdef CONFIG_SMP
        for (j = 0; j < smp_num_cpus; j++)
            len += sprintf(buf+len, "%10u ",
                kstat.irqs[cpu_logical_map(j)][i]);
#else        
        len += sprintf(buf+len, "%10u ", kstat_irqs(i));
#endif /* CONFIG_SMP */
        if ( irq_desc[i].handler )        
            len += sprintf(buf+len, " %s ", irq_desc[i].handler->typename );
        else
            len += sprintf(buf+len, "  None      ");
        len += sprintf(buf+len, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge  ");
        len += sprintf(buf+len, "    %s",action->name);
        for (action=action->next; action; action = action->next) {
            len += sprintf(buf+len, ", %s", action->name);
        }
        len += sprintf(buf+len, "\n");
    }
#ifdef CONFIG_TAU_INT
    if (tau_initialized){
        len += sprintf(buf+len, "TAU: ");
        for (j = 0; j < smp_num_cpus; j++)
            len += sprintf(buf+len, "%10u ",
                    tau_interrupts(j));
        len += sprintf(buf+len, "  PowerPC             Thermal Assist (cpu temp)\n");
    }
#endif
#ifdef CONFIG_SMP
    /* should this be per processor send/receive? */
    len += sprintf(buf+len, "IPI (recv/sent): %10u/%u\n",
               atomic_read(&ipi_recv), atomic_read(&ipi_sent));
#endif        
    len += sprintf(buf+len, "BAD: %10u\n", ppc_spurious_interrupts);
    return len;
#endif /* CONFIG_APUS */
}

static inline void
handle_irq_event(int irq, struct pt_regs *regs, struct irqaction *action)
{
    int status = 0;

    if (!(action->flags & SA_INTERRUPT))
        __sti();

    do {
        status |= action->flags;
        action->handler(irq, action->dev_id, regs);
        action = action->next;
    } while (action);
    if (status & SA_SAMPLE_RANDOM)
        add_interrupt_randomness(irq);
    __cli();
}

/*
 * Eventually, this should take an array of interrupts and an array size
 * so it can dispatch multiple interrupts.
 */
void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
{
    int status;
    struct irqaction *action;
    int cpu = smp_processor_id();
    irq_desc_t *desc = irq_desc + irq;

    kstat.irqs[cpu][irq]++;
    spin_lock(&desc->lock);
    ack_irq(irq);    
    /*
       REPLAY is when Linux resends an IRQ that was dropped earlier
       WAITING is used by probe to mark irqs that are being tested
       */
    status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
    if (!(status & IRQ_PER_CPU))
        status |= IRQ_PENDING; /* we _want_ to handle it */

    /*
     * If the IRQ is disabled for whatever reason, we cannot
     * use the action we have.
     */
    action = NULL;
    if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
        action = desc->action;
        if (!action || !action->handler) {
            ppc_spurious_interrupts++;
            printk(KERN_DEBUG "Unhandled interrupt %x, disabled\n", irq);
            /* We can't call disable_irq here, it would deadlock */
            ++desc->depth;
            desc->status |= IRQ_DISABLED;
            mask_irq(irq);
            /* This is a real interrupt, we have to eoi it,
               so we jump to out */
            goto out;
        }
        status &= ~IRQ_PENDING; /* we commit to handling */
        if (!(status & IRQ_PER_CPU))
            status |= IRQ_INPROGRESS; /* we are handling it */
    }
    desc->status = status;

    /*
     * If there is no IRQ handler or it was disabled, exit early.
       Since we set PENDING, if another processor is handling
       a different instance of this same irq, the other processor
       will take care of it.
     */
    if (!action)
        goto out;


    /*
     * Edge triggered interrupts need to remember
     * pending events.
     * This applies to any hw interrupts that allow a second
     * instance of the same irq to arrive while we are in do_IRQ
     * or in the handler. But the code here only handles the _second_
     * instance of the irq, not the third or fourth. So it is mostly
     * useful for irq hardware that does not mask cleanly in an
     * SMP environment.
     */
    for (;;) {
        spin_unlock(&desc->lock);
        handle_irq_event(irq, regs, action);
        spin_lock(&desc->lock);
        
        if (!(desc->status & IRQ_PENDING))
            break;
        desc->status &= ~IRQ_PENDING;
    }
    desc->status &= ~IRQ_INPROGRESS;
out:
    /*
     * The ->end() handler has to deal with interrupts which got
     * disabled while the handler was running.
     */
    if (irq_desc[irq].handler) {
        if (irq_desc[irq].handler->end)
            irq_desc[irq].handler->end(irq);
        else if (irq_desc[irq].handler->enable)
            irq_desc[irq].handler->enable(irq);
    }
    spin_unlock(&desc->lock);
}

int do_IRQ(struct pt_regs *regs)
{
    int cpu = smp_processor_id();
    int irq, first = 1;
        hardirq_enter( cpu );

    for (;;) {
        /*
         * Every arch is required to implement ppc_md.get_irq.
         * This function will either return an irq number or -1 to
         * indicate there are no more pending.  But the first time
         * through the loop this means there wasn't and IRQ pending.
         * The value -2 is for buggy hardware and means that this IRQ
         * has already been handled. -- Tom
         */
        irq = ppc_md.get_irq( regs );

        if (irq >= 0)
            ppc_irq_dispatch_handler( regs, irq );
        else {
            if (irq != -2 && first)
                /* That's not SMP safe ... but who cares ? */
                ppc_spurious_interrupts++;
            break;
        }
        first = 0;
    }
        hardirq_exit( cpu );

    if (softirq_pending(cpu))
        do_softirq();
    return 1; /* lets ret_from_int know we can do checks */
}

unsigned long probe_irq_on (void)
{
    return 0;
}

int probe_irq_off (unsigned long irqs)
{
    return 0;
}

unsigned int probe_irq_mask(unsigned long irqs)
{
    return 0;
}

void __init init_IRQ(void)
{
    static int once = 0;

    if ( once )
        return;
    else
        once++;
    
    ppc_md.init_IRQ();
}

#ifdef CONFIG_SMP
unsigned char global_irq_holder = NO_PROC_ID;
unsigned volatile long global_irq_lock; /* pendantic :long for set_bit--RR*/
atomic_t global_irq_count;

atomic_t global_bh_count;

static void show(char * str)
{
    int i;
    unsigned long *stack;
    int cpu = smp_processor_id();

    printk("\n%s, CPU %d:\n", str, cpu);
    printk("irq:  %d [%d %d]\n",
           atomic_read(&global_irq_count),
           local_irq_count(0),
           local_irq_count(1));
    printk("bh:   %d [%d %d]\n",
           atomic_read(&global_bh_count),
           local_bh_count(0),
           local_bh_count(1));
    stack = (unsigned long *) &str;
    for (i = 40; i ; i--) {
        unsigned long x = *++stack;
        if (x > (unsigned long) &init_task_union && x < (unsigned long) &vsprintf) {
            printk("<[%08lx]> ", x);
        }
    }
}

static inline void wait_on_bh(void)
{
    int count = MAXCOUNT;
    do {
        if (!--count) {
            show("wait_on_bh");
            count = ~0;
        }
        /* nothing .. wait for the other bh's to go away */
    } while (atomic_read(&global_bh_count) != 0);
}


static inline void wait_on_irq(int cpu)
{
    int count = MAXCOUNT;

    for (;;) {

        /*
         * Wait until all interrupts are gone. Wait
         * for bottom half handlers unless we're
         * already executing in one..
         */
        if (!atomic_read(&global_irq_count)) {
            if (local_bh_count(cpu)
                || !atomic_read(&global_bh_count))
                break;
        }

        /* Duh, we have to loop. Release the lock to avoid deadlocks */
        clear_bit(0,&global_irq_lock);

        for (;;) {
            if (!--count) {
                show("wait_on_irq");
                count = ~0;
            }
            __sti();
            /* don't worry about the lock race Linus found
             * on intel here. -- Cort
             */
            __cli();
            if (atomic_read(&global_irq_count))
                continue;
            if (global_irq_lock)
                continue;
            if (!local_bh_count(cpu)
                && atomic_read(&global_bh_count))
                continue;
            if (!test_and_set_bit(0,&global_irq_lock))
                break;
        }
    }
}

/*
 * This is called when we want to synchronize with
 * bottom half handlers. We need to wait until
 * no other CPU is executing any bottom half handler.
 *
 * Don't wait if we're already running in an interrupt
 * context or are inside a bh handler.
 */
void synchronize_bh(void)
{
    if (atomic_read(&global_bh_count) && !in_interrupt())
        wait_on_bh();
}

/*
 * This is called when we want to synchronize with
 * interrupts. We may for example tell a device to
 * stop sending interrupts: but to make sure there
 * are no interrupts that are executing on another
 * CPU we need to call this function.
 */
void synchronize_irq(void)
{
    if (atomic_read(&global_irq_count)) {
        /* Stupid approach */
        cli();
        sti();
    }
}

static inline void get_irqlock(int cpu)
{
    unsigned int loops = MAXCOUNT;

    if (test_and_set_bit(0,&global_irq_lock)) {
        /* do we already hold the lock? */
        if ((unsigned char) cpu == global_irq_holder)
            return;
        /* Uhhuh.. Somebody else got it. Wait.. */
        do {
            do {
                if (loops-- == 0) {
                    printk("get_irqlock(%d) waiting, global_irq_holder=%d\n", cpu, global_irq_holder);
#ifdef CONFIG_XMON
                    xmon(0);
#endif
                }
            } while (test_bit(0,&global_irq_lock));
        } while (test_and_set_bit(0,&global_irq_lock));        
    }
    /* 
     * We also need to make sure that nobody else is running
     * in an interrupt context. 
     */
    wait_on_irq(cpu);

    /*
     * Ok, finally..
     */
    global_irq_holder = cpu;
}

/*
 * A global "cli()" while in an interrupt context
 * turns into just a local cli(). Interrupts
 * should use spinlocks for the (very unlikely)
 * case that they ever want to protect against
 * each other.
 *
 * If we already have local interrupts disabled,
 * this will not turn a local disable into a
 * global one (problems with spinlocks: this makes
 * save_flags+cli+sti usable inside a spinlock).
 */
void __global_cli(void)
{
    unsigned long flags;
    
    __save_flags(flags);
    if (flags & (1 << 15)) {
        int cpu = smp_processor_id();
        __cli();
        if (!local_irq_count(cpu))
            get_irqlock(cpu);
    }
}

void __global_sti(void)
{
    int cpu = smp_processor_id();

    if (!local_irq_count(cpu))
        release_irqlock(cpu);
    __sti();
}

/*
 * SMP flags value to restore to:
 * 0 - global cli
 * 1 - global sti
 * 2 - local cli
 * 3 - local sti
 */
unsigned long __global_save_flags(void)
{
    int retval;
    int local_enabled;
    unsigned long flags;

    __save_flags(flags);
    local_enabled = (flags >> 15) & 1;
    /* default to local */
    retval = 2 + local_enabled;

    /* check for global flags if we're not in an interrupt */
    if (!local_irq_count(smp_processor_id())) {
        if (local_enabled)
            retval = 1;
        if (global_irq_holder == (unsigned char) smp_processor_id())
            retval = 0;
    }
    return retval;
}

int
tb(long vals[],
   int  max_size)
{
   register unsigned long *orig_sp __asm__ ("r1");
   register unsigned long lr __asm__ ("r3");
   unsigned long *sp;
   int i;

   asm volatile ("mflr 3");
   vals[0] = lr;
   sp = (unsigned long *) *orig_sp;
   sp = (unsigned long *) *sp;
   for (i=1; i<max_size; i++) {
      if (sp == 0) {
         break;
      }

      vals[i] = *(sp+1);
      sp = (unsigned long *) *sp;
   }

   return i;
}

void __global_restore_flags(unsigned long flags)
{
    switch (flags) {
    case 0:
        __global_cli();
        break;
    case 1:
        __global_sti();
        break;
    case 2:
        __cli();
        break;
    case 3:
        __sti();
        break;
    default:
    {
        unsigned long trace[5];
                int           count;
                int           i;

        printk("global_restore_flags: %08lx (%08lx)\n",
            flags, (&flags)[-1]);
                count = tb(trace, 5);
                printk("tb:");
                for(i=0; i<count; i++) {
            printk(" %8.8lx", trace[i]);
        }
        printk("\n");
    }
    }
}
#endif /* CONFIG_SMP */

static struct proc_dir_entry *root_irq_dir;
static struct proc_dir_entry *irq_dir[NR_IRQS];
static struct proc_dir_entry *smp_affinity_entry[NR_IRQS];

#ifdef CONFIG_IRQ_ALL_CPUS
#define DEFAULT_CPU_AFFINITY 0xffffffff
#else
#define DEFAULT_CPU_AFFINITY 0x00000001
#endif

unsigned int irq_affinity [NR_IRQS] =
    { [0 ... NR_IRQS-1] = DEFAULT_CPU_AFFINITY };

#define HEX_DIGITS 8

static int irq_affinity_read_proc (char *page, char **start, off_t off,
            int count, int *eof, void *data)
{
    if (count < HEX_DIGITS+1)
        return -EINVAL;
    return sprintf (page, "%08x\n", irq_affinity[(int)data]);
}

static unsigned int parse_hex_value (const char *buffer,
        unsigned long count, unsigned long *ret)
{
    unsigned char hexnum [HEX_DIGITS];
    unsigned long value;
    int i;

    if (!count)
        return -EINVAL;
    if (count > HEX_DIGITS)
        count = HEX_DIGITS;
    if (copy_from_user(hexnum, buffer, count))
        return -EFAULT;

    /*
     * Parse the first 8 characters as a hex string, any non-hex char
     * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same.
     */
    value = 0;

    for (i = 0; i < count; i++) {
        unsigned int c = hexnum[i];

        switch (c) {
            case '0' ... '9': c -= '0'; break;
            case 'a' ... 'f': c -= 'a'-10; break;
            case 'A' ... 'F': c -= 'A'-10; break;
        default:
            goto out;
        }
        value = (value << 4) | c;
    }
out:
    *ret = value;
    return 0;
}

static int irq_affinity_write_proc (struct file *file, const char *buffer,
                    unsigned long count, void *data)
{
    int irq = (int) data, full_count = count, err;
    unsigned long new_value;

    if (!irq_desc[irq].handler->set_affinity)
        return -EIO;

    err = parse_hex_value(buffer, count, &new_value);

    /*
     * Do not allow disabling IRQs completely - it's a too easy
     * way to make the system unusable accidentally :-) At least
     * one online CPU still has to be targeted.
     *
     * We assume a 1-1 logical<->physical cpu mapping here.  If
     * we assume that the cpu indices in /proc/irq/../smp_affinity
     * are actually logical cpu #'s then we have no problem.
     *  -- Cort <cort@fsmlabs.com>
     */
    if (!(new_value & cpu_online_map))
        return -EINVAL;

    irq_affinity[irq] = new_value;
    irq_desc[irq].handler->set_affinity(irq, new_value);

    return full_count;
}

static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
            int count, int *eof, void *data)
{
    unsigned long *mask = (unsigned long *) data;
    if (count < HEX_DIGITS+1)
        return -EINVAL;
    return sprintf (page, "%08lx\n", *mask);
}

static int prof_cpu_mask_write_proc (struct file *file, const char *buffer,
                    unsigned long count, void *data)
{
    unsigned long *mask = (unsigned long *) data, full_count = count, err;
    unsigned long new_value;

    err = parse_hex_value(buffer, count, &new_value);
    if (err)
        return err;

    *mask = new_value;
    return full_count;
}

#define MAX_NAMELEN 10

static void register_irq_proc (unsigned int irq)
{
    struct proc_dir_entry *entry;
    char name [MAX_NAMELEN];

    if (!root_irq_dir || (irq_desc[irq].handler == NULL))
        return;

    memset(name, 0, MAX_NAMELEN);
    sprintf(name, "%d", irq);

    /* create /proc/irq/1234 */
    irq_dir[irq] = proc_mkdir(name, root_irq_dir);

    /* create /proc/irq/1234/smp_affinity */
    entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);

    entry->nlink = 1;
    entry->data = (void *)irq;
    entry->read_proc = irq_affinity_read_proc;
    entry->write_proc = irq_affinity_write_proc;

    smp_affinity_entry[irq] = entry;
}

unsigned long prof_cpu_mask = -1;

void init_irq_proc (void)
{
    struct proc_dir_entry *entry;
    int i;

    /* create /proc/irq */
    root_irq_dir = proc_mkdir("irq", 0);

    /* create /proc/irq/prof_cpu_mask */
    entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);

    entry->nlink = 1;
    entry->data = (void *)&prof_cpu_mask;
    entry->read_proc = prof_cpu_mask_read_proc;
    entry->write_proc = prof_cpu_mask_write_proc;

    /*
     * Create entries for all existing IRQs.
     */
    for (i = 0; i < NR_IRQS; i++) {
        if (irq_desc[i].handler == NULL)
            continue;
        register_irq_proc(i);
    }
}

void no_action(int irq, void *dev, struct pt_regs *regs)
{
}

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 1.0 pre-release build #13 powered by Captain Crunch Security Team | http://ccteam.ru | Generation time: 0.0334 ]--