diff options
| author | rearnsha <rearnsha@NetBSD.org> | 2003-09-06 12:36:29 +0000 |
|---|---|---|
| committer | rearnsha <rearnsha@NetBSD.org> | 2003-09-06 12:36:29 +0000 |
| commit | b548db68460d059054081e4d142993a1d162dbe0 (patch) | |
| tree | cbd75c41915f875af82d6881ce75d14d84d2dbb5 | |
| parent | f88ed86b14c12bac8176379c7d59eae872acc95c (diff) | |
Obsolete.
| -rw-r--r-- | sys/arch/evbarm/ifpga/ifpga_irq.S | 542 | ||||
| -rw-r--r-- | sys/arch/evbarm/ifpga/ifpga_irqhandler.c | 468 |
2 files changed, 0 insertions, 1010 deletions
diff --git a/sys/arch/evbarm/ifpga/ifpga_irq.S b/sys/arch/evbarm/ifpga/ifpga_irq.S deleted file mode 100644 index 527801c9dd6..00000000000 --- a/sys/arch/evbarm/ifpga/ifpga_irq.S +++ /dev/null @@ -1,542 +0,0 @@ -/* $NetBSD: ifpga_irq.S,v 1.4 2003/01/02 23:54:43 thorpej Exp $ - -/* - * Copyright (c) 1998 Mark Brinicombe. - * Copyright (c) 1998 Causality Limited - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Mark Brinicombe - * for the NetBSD Project. - * 4. The name of the company nor the name of the author may be used to - * endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "opt_irqstats.h" -#include "assym.h" - -#include <machine/asm.h> -#include <machine/cpu.h> -#include <machine/frame.h> -#include <evbarm/ifpga/ifpgamem.h> -#include <evbarm/ifpga/ifpgareg.h> - - - .text - .align 0 -/* - * ffs table used for servicing irq's quickly must be here otherwise adr can't - * reach it - * The algorithm for ffs was devised by D. Seal and posted to - * comp.sys.arm on 16 Feb 1994. - */ -.type Lirq_ffs_table, _ASM_TYPE_OBJECT; -Lirq_ffs_table: -/* same as ffs table but all nums are -1 from that */ -/* 0 1 2 3 4 5 6 7 */ - .byte 0, 0, 1, 12, 2, 6, 0, 13 /* 0- 7 */ - .byte 3, 0, 7, 0, 0, 0, 0, 14 /* 8-15 */ - .byte 10, 4, 0, 0, 8, 0, 0, 25 /* 16-23 */ - .byte 0, 0, 0, 0, 0, 21, 27, 15 /* 24-31 */ - .byte 31, 11, 5, 0, 0, 0, 0, 0 /* 32-39 */ - .byte 9, 0, 0, 24, 0, 0, 20, 26 /* 40-47 */ - .byte 30, 0, 0, 0, 0, 23, 0, 19 /* 48-55 */ - .byte 29, 0, 22, 18, 28, 17, 16, 0 /* 56-63 */ - -/* - * - * irq_entry - * - * Main entry point for the IRQ vector - * - * This function reads the IRQ request register in the 21285 - * and then calls the installed handlers for each bit that is set. - * The function stray_irqhandler is called if a handler is not defined - * for a particular interrupt. - * If a interrupt handler is found then it is called with r0 containing - * the argument defined in the handler structure. If the field ih_arg - * is zero then a pointer to the IRQ frame on the stack is passed instead. - */ - -Lintr_disabled_mask: - .word _C_LABEL(intr_disabled_mask) - -Lintr_claimed_mask: - .word _C_LABEL(intr_claimed_mask) - -Lcurrent_spl_level: - .word _C_LABEL(current_spl_level) - -Lcurrent_intr_depth: - .word _C_LABEL(current_intr_depth) - -Lspl_masks: - .word _C_LABEL(spl_masks) - -Lirq_vbase: - .word _C_LABEL(ifpga_irq_vbase) - -/* - * Register usage - * - * r5 - Address of ffs table - * r6 - Address of current handler - * r7 - Pointer to handler pointer list - * r8 - Current IRQ requests. - * r10 - Base address of IOMD - * r11 - IRQ requests still to service. - */ - -ASENTRY_NP(irq_entry) - sub lr, lr, #0x00000004 /* Adjust the lr */ - - PUSHFRAMEINSVC /* Push an interrupt frame */ - - /* - * Note that we have entered the IRQ handler. - * We are in SVC mode so we cannot use the processor mode - * to determine if we are in an IRQ. Instead we will count the - * each time the interrupt handler is nested. - */ - ldr r0, Lcurrent_intr_depth - ldr r1, [r0] - add r1, r1, #1 - str r1, [r0] - - /* Load r8 with the IFPGA interrupt requests */ - ldr r10, Lirq_vbase - ldr r10, [r10] - ldr r8, [r10, #(IFPGA_INTR_STATUS)] - - /* This condition needs further examination */ - teq r8, #0 - beq irq_unknown - - /* Block the current requested interrupts */ - ldr r1, Lintr_disabled_mask - ldr r0, [r1] - stmfd sp!, {r0} - orr r0, r0, r8 - - /* - * Need to block all interrupts at the IPL or lower for - * all asserted interrupts. - * This basically emulates hardware interrupt priority levels. - * Means we need to go through the interrupt mask and for - * every asserted interrupt we need to mask out all other - * interrupts at the same or lower IPL. - * If only we could wait until the main loop but we need to sort - * this out first so interrupts can be re-enabled. - * - * This would benefit from a special ffs type routine - */ - mov r9, #(_SPL_LEVELS - 1) - ldr r7, Lspl_masks - -Lfind_highest_ipl: - ldr r2, [r7, r9, lsl #2] - tst r8, r2 - subeq r9, r9, #1 - beq Lfind_highest_ipl - - /* r9 = SPL level of highest priority interrupt */ - add r9, r9, #1 - ldr r2, [r7, r9, lsl #2] - mvn r2, r2 - orr r0, r0, r2 - - str r0, [r1] /* store new disabled mask */ - - ldr r2, Lcurrent_spl_level - ldr r1, [r2] - str r9, [r2] - stmfd sp!, {r1} - - ldr r7, Lintr_claimed_mask /* get claimed mask */ - ldr r6, [r7] - bic r6, r6, r0 /* mask out disabled */ - ldr r7, Lintr_current_mask /* get claimed mask */ - str r6, [r7] /* new current mask */ - - ldr r7, Lirq_vbase - - /* Update the IFPGA irq masks */ - bl _C_LABEL(irq_setmasks_nointr) - - ldr r7, [r7] /* Ensure irq pin has time to update */ -Lstill_pending: - ldr r0, [r7, #(IFPGA_INTR_STATUS)] - tst r0, r8 - bne Lstill_pending - - mrs r0, cpsr_all /* Enable IRQ's */ - bic r0, r0, #I32_bit - msr cpsr_all, r0 - - ldr r7, Lirqhandlers - - /* take a copy of the irq mask so we can alter it */ - mov r11, r8 - - /* ffs routine to find first irq to service */ - /* standard trick to isolate bottom bit in a0 or 0 if a0 = 0 on entry */ - rsb r4, r11, #0 - ands r10, r11, r4 - - /* - * now r10 has at most 1 set bit, call this X - * if X = 0, branch to exit code - */ - beq exitirq - adr r5, Lirq_ffs_table -irqloop: - /* - * at this point: - * r5 = address of ffs table - * r7 = address of irq handlers table - * r8 = irq request - * r10 = bit of irq to be serviced - * r11 = bitmask of IRQ's to service - */ - - /* find the set bit */ - orr r9, r10, r10, lsl #4 /* X * 0x11 */ - orr r9, r9, r9, lsl #6 /* X * 0x451 */ - rsb r9, r9, r9, lsl #16 /* X * 0x0450fbaf */ - /* fetch the bit number */ - ldrb r9, [r5, r9, lsr #26 ] - - /* - * r9 = irq to service - */ - - /* apologies for the dogs dinner of code here, but it's in an attempt - * to minimise stalling on SA's, hence lots of things happen here: - * - getting address of handler, if it doesn't exist we call - * stray_irqhandler this is assumed to be rare so we don't - * care about performance for it - * - statinfo is updated - * - unsetting of the irq bit in r11 - * - irq stats (if enabled) also get put in the mix - */ - ldr r4, Lcnt /* Stat info A */ - ldr r6, [r7, r9, lsl #2] /* Get address of first handler structure */ - - ldr r1, [r4, #(V_INTR)] /* Stat info B */ - - teq r6, #0x00000000 /* Do we have a handler */ - moveq r0, r8 /* IRQ requests as arg 0 */ - adreq lr, nextirq /* return address */ - bic r11, r11, r10 /* clear the IRQ bit */ - beq _C_LABEL(stray_irqhandler) /* call special handler */ - -#ifdef IRQSTATS - ldr r2, Lintrcnt - ldr r3, [r6, #(IH_NUM)] -#endif - /* stat info C */ - add r1, r1, #0x00000001 - -#ifdef IRQSTATS - ldr r3, [r2, r3, lsl #2]! -#endif - /* stat info D */ - str r1, [r4, #(V_INTR)] - -#ifdef IRQSTATS - add r3, r3, #0x00000001 - str r3, [r2] -#endif /* IRQSTATS */ - -irqchainloop: - ldr r0, [r6, #(IH_ARG)] /* Get argument pointer */ - teq r0, #0x00000000 /* If arg is zero pass stack frame */ - addeq r0, sp, #8 /* ... stack frame [XXX needs care] */ - mov lr, pc /* return address */ - ldr pc, [r6, #(IH_FUNC)] /* Call handler */ - -nextinchain: - ldr r6, [r6, #(IH_NEXT)] /* fetch next handler */ -#if 0 - teq r0, #0x00000001 /* Was the irq serviced ? */ -#endif - /* if it was it'll just fall through this: */ - teq r6, #0x00000000 - bne irqchainloop -nextirq: - /* Check for next irq */ - rsb r4, r11, #0 - ands r10, r11, r4 - /* check if there are anymore irq's to service */ - bne irqloop - -exitirq: - ldmfd sp!, {r2, r3} - ldr r1, Lcurrent_spl_level - ldr r9, Lintr_disabled_mask - ldr r7, Lspl_masks - ldr r8, Lspl_mask - ldr r7, [r7, r2, lsl #2] /* Mask for new spl level */ - str r2, [r1] /* store current spl level */ - str r7, [r8] /* Restore the spl_mask */ - - ldr r1, Lintr_claimed_mask /* get claimed mask */ - - str r3, [r9] /* store disabled mask */ - - ldr r0, [r1] - ldr r9, Lintr_current_mask /* get claimed mask */ - bic r0, r0, r3 /* mask out disabled */ - str r0, [r9] /* new current mask */ - bl _C_LABEL(irq_setmasks) - - bl _C_LABEL(dosoftints) /* Handle the soft interrupts */ - - /* Manage AST's. Maybe this should be done as a soft interrupt ? */ - ldr r0, [sp] /* Get the SPSR from stack */ - - and r0, r0, #(PSR_MODE) /* Test for USR32 mode before the IRQ */ - teq r0, #(PSR_USR32_MODE) - ldreq r0, Lastpending /* Do we have an AST pending ? */ - ldreq r1, [r0] - teqeq r1, #0x00000001 - - beq irqast /* call the AST handler */ - - /* Kill IRQ's in preparation for exit */ - mrs r0, cpsr_all - orr r0, r0, #(I32_bit) - msr cpsr_all, r0 - -irq_unknown: - /* Decrement the nest count */ - ldr r0, Lcurrent_intr_depth - ldr r1, [r0] - sub r1, r1, #1 - str r1, [r0] - - PULLFRAMEFROMSVCANDEXIT - - movs pc, lr /* Exit */ - - /* - * Ok, snag with current intr depth ... - * If ast() calls mi_sleep() the current_intr_depth will not be - * decremented until the process is woken up. This can result - * in the system believing it is still in the interrupt handler. - * If we are calling ast() then correct the current_intr_depth - * before the call. - */ -irqast: - mov r1, #0x00000000 /* Clear ast_pending */ - str r1, [r0] - - /* Kill IRQ's so we atomically decrement current_intr_depth */ - mrs r2, cpsr_all - orr r3, r2, #(I32_bit) - msr cpsr_all, r3 - - /* Decrement the nest count */ - ldr r0, Lcurrent_intr_depth - ldr r1, [r0] - sub r1, r1, #1 - str r1, [r0] - - /* Restore IRQ's */ - msr cpsr_all, r2 - - mov r0, sp - bl _C_LABEL(ast) - -/* Kill IRQ's in preparation for exit */ - - mrs r0, cpsr_all - orr r0, r0, #(I32_bit) - msr cpsr_all, r0 - - PULLFRAMEFROMSVCANDEXIT - - movs pc, lr /* Exit */ - -Lcnt: - .word _C_LABEL(uvmexp) - -Lintrcnt: - .word _C_LABEL(intrcnt) - -Lirqhandlers: - .word _C_LABEL(irqhandlers) /* Pointer to array of irqhandlers */ - -Lastpending: - .word _C_LABEL(astpending) - -Lspl_mask: - .word _C_LABEL(spl_mask) /* irq's allowed at current spl level */ - -Lintr_current_mask: - .word _C_LABEL(intr_current_mask) - - -ENTRY(irq_setmasks) - /* Disable interrupts */ - mrs r3, cpsr_all - orr r1, r3, #(I32_bit) - msr cpsr_all, r1 - - /* Calculate IFPGA interrupt mask */ - ldr r1, Lintr_current_mask /* All the enabled interrupts */ - ldr r2, Lspl_mask /* Block due to current spl level */ - ldr r0, Lirq_vbase /* Virtual address of irq ctrlr */ - ldr r1, [r1] - ldr r2, [r2] - ldr r0, [r0] - and r1, r1, r2 - - str r1, [r0, #(IFPGA_INTR_ENABLESET)] - mvn r1, r1 - str r1, [r0, #(IFPGA_INTR_ENABLECLR)] - - /* Restore old cpsr and exit */ - msr cpsr_all, r3 - mov pc, lr - -ENTRY(irq_setmasks_nointr) - /* Calculate IFPGA interrupt mask */ - ldr r1, Lintr_current_mask /* All the enabled interrupts */ - ldr r2, Lspl_mask /* Block due to current spl level */ - ldr r0, Lirq_vbase - ldr r1, [r1] - ldr r2, [r2] - ldr r0, [r0] - and r1, r1, r2 - - str r1, [r0, #(IFPGA_INTR_ENABLESET)] - mvn r1, r1 - str r1, [r0, #(IFPGA_INTR_ENABLECLR)] - mov pc, lr - -#ifdef IRQSTATS - /* These symbols are used by vmstat */ - - .text - .global _C_LABEL(_intrnames) -_C_LABEL(_intrnames): - .word _C_LABEL(intrnames) - - .data - .align 0 - .global _C_LABEL(intrnames), _C_LABEL(sintrnames), _C_LABEL(eintrnames) - .global _C_LABEL(intrcnt), _C_LABEL(sintrcnt), _C_LABEL(eintrcnt) -_C_LABEL(intrnames): - .asciz "interrupt 0 " - .asciz "interrupt 1 " - .asciz "interrupt 2 " - .asciz "interrupt 3 " - .asciz "interrupt 4 " - .asciz "interrupt 5 " - .asciz "interrupt 6 " - .asciz "interrupt 7 " - .asciz "interrupt 8 " - .asciz "interrupt 9 " - .asciz "interrupt 10 " - .asciz "interrupt 11 " - .asciz "interrupt 12 " - .asciz "interrupt 13 " - .asciz "interrupt 14 " - .asciz "interrupt 15 " - .asciz "interrupt 16 " - .asciz "interrupt 17 " - .asciz "interrupt 18 " - .asciz "interrupt 19 " - .asciz "interrupt 20 " - .asciz "interrupt 21 " - .asciz "interrupt 22 " - .asciz "interrupt 23 " - .asciz "interrupt 24 " - .asciz "interrupt 25 " - .asciz "interrupt 26 " - .asciz "interrupt 27 " - .asciz "interrupt 28 " - .asciz "interrupt 29 " - .asciz "interrupt 30 " - .asciz "interrupt 31 " -_C_LABEL(sintrnames): - .asciz "soft int 0 " - .asciz "soft int 1 " - .asciz "soft int 2 " - .asciz "soft int 3 " - .asciz "soft int 4 " - .asciz "soft int 5 " - .asciz "soft int 6 " - .asciz "soft int 7 " - .asciz "soft int 8 " - .asciz "soft int 9 " - .asciz "soft int 10 " - .asciz "soft int 11 " - .asciz "soft int 12 " - .asciz "soft int 13 " - .asciz "soft int 14 " - .asciz "soft int 15 " - .asciz "soft int 16 " - .asciz "soft int 17 " - .asciz "soft int 18 " - .asciz "soft int 19 " - .asciz "soft int 20 " - .asciz "soft int 21 " - .asciz "soft int 22 " - .asciz "soft int 23 " - .asciz "soft int 24 " - .asciz "soft int 25 " - .asciz "soft int 26 " - .asciz "soft int 27 " - .asciz "soft int 28 " - .asciz "soft int 29 " - .asciz "soft int 30 " - .asciz "soft int 31 " -_C_LABEL(eintrnames): - - .bss - .align 0 - .global _C_LABEL(intrcnt), _C_LABEL(sintrcnt), _C_LABEL(eintrcnt) -_C_LABEL(intrcnt): - .space 32*4 /* XXX Should be linked to number of interrupts */ -_C_LABEL(sintrcnt): - .space 32*4 /* XXX Should be linked to number of soft ints */ -_C_LABEL(eintrcnt): - -#else /* IRQSTATS */ - /* Dummy entries to keep vmstat happy */ - - .text - .globl _C_LABEL(intrnames), _C_LABEL(eintrnames), _C_LABEL(intrcnt), _C_LABEL(eintrcnt) -_C_LABEL(intrnames): - .long 0 -_C_LABEL(eintrnames): - -_C_LABEL(intrcnt): - .long 0 -_C_LABEL(eintrcnt): -#endif /* IRQSTATS */ - diff --git a/sys/arch/evbarm/ifpga/ifpga_irqhandler.c b/sys/arch/evbarm/ifpga/ifpga_irqhandler.c deleted file mode 100644 index b62b22f3f32..00000000000 --- a/sys/arch/evbarm/ifpga/ifpga_irqhandler.c +++ /dev/null @@ -1,468 +0,0 @@ -/* $NetBSD: ifpga_irqhandler.c,v 1.5 2003/07/15 00:24:59 lukem Exp $ */ - -/* - * Copyright (c) 1994-1998 Mark Brinicombe. - * Copyright (c) 1997 Causality Limited - * Copyright (c) 1994 Brini. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Mark Brinicombe - * for the NetBSD Project. - * 4. The name of the company nor the name of the author may be used to - * endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: iomd_irqhandler.c,v 1.16 $ - */ - -#include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ifpga_irqhandler.c,v 1.5 2003/07/15 00:24:59 lukem Exp $"); - -#include "opt_irqstats.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/syslog.h> -#include <sys/malloc.h> -#include <uvm/uvm_extern.h> - -#include <machine/intr.h> -#include <evbarm/ifpga/irqhandler.h> /* XXX XXX XXX */ -#include <machine/cpu.h> - -irqhandler_t *irqhandlers[NIRQS]; - -int current_intr_depth; /* Depth of interrupt nesting */ -u_int intr_claimed_mask; /* Interrupts that are claimed */ -u_int intr_disabled_mask; /* Interrupts that are temporarily disabled */ -u_int intr_current_mask; /* Interrupts currently allowable */ -u_int spl_mask; -u_int irqmasks[NIPL]; -u_int irqblock[NIRQS]; - -extern u_int soft_interrupts; /* Only so we can initialise it */ - -extern char *_intrnames; -extern void set_spl_masks __P((void)); - -void -irq_init(void) -{ - int loop; - - /* Clear all the IRQ handlers and the irq block masks */ - for (loop = 0; loop < NIRQS; ++loop) { - irqhandlers[loop] = NULL; - irqblock[loop] = 0; - } - - /* - * Setup the irqmasks for the different Interrupt Priority Levels - * We will start with no bits set and these will be updated as handlers - * are installed at different IPL's. - */ - for (loop = 0; loop < NIPL; ++loop) - irqmasks[loop] = 0; - - current_intr_depth = 0; - intr_claimed_mask = 0x00000000; - intr_disabled_mask = 0x00000000; - intr_current_mask = 0x00000000; - spl_mask = 0x00000000; - soft_interrupts = 0x00000000; - - set_spl_masks(); -} - -/* Run the irq initialization code that can't be done until the IRQ - controller is mapped. */ -void -irq_postinit() -{ - irq_setmasks(); - - /* Enable IRQ's and FIQ's */ - enable_interrupts(I32_bit | F32_bit); -} - -void stray_irqhandler(void); /* only called from ifpga_irq.S */ - -void -stray_irqhandler() -{ - panic("stray irq"); -} - -/* - * void disable_irq(int irq) - * - * Disables a specific irq. The irq is removed from the master irq mask - * - * Use of this function outside this file is deprecated. - */ - -void -disable_irq(irq) - int irq; -{ - int oldirqstate; - - oldirqstate = disable_interrupts(I32_bit); - intr_claimed_mask &= ~(1 << irq); - intr_current_mask = intr_claimed_mask & ~intr_disabled_mask; - irq_setmasks(); - restore_interrupts(oldirqstate); -} - - -/* - * void enable_irq(int irq) - * - * Enables a specific irq. The irq is added to the master irq mask - * This routine should be used with caution. A handler should already - * be installed. - * - * Use of this function outside this file is deprecated. - */ - -void -enable_irq(irq) - int irq; -{ - u_int oldirqstate; - - oldirqstate = disable_interrupts(I32_bit); - intr_claimed_mask |= (1 << irq); - intr_current_mask = intr_claimed_mask & ~intr_disabled_mask; - irq_setmasks(); - restore_interrupts(oldirqstate); -} - -/* - * int irq_claim(int irq, irqhandler_t *handler) - * - * Enable an IRQ and install a handler for it. - */ - -int -irq_claim(irq, handler) - int irq; - irqhandler_t *handler; -{ - int level; - int loop; - -#ifdef DIAGNOSTIC - /* Sanity check */ - if (handler == NULL) - panic("NULL interrupt handler"); - if (handler->ih_func == NULL) - panic("Interrupt handler does not have a function"); -#endif /* DIAGNOSTIC */ - - /* - * IRQ_INSTRUCT indicates that we should get the irq number - * from the irq structure - */ - if (irq == IRQ_INSTRUCT) - irq = handler->ih_num; - - /* Make sure the irq number is valid */ - if (irq < 0 || irq >= NIRQS) - return(-1); - - /* Make sure the level is valid */ - if (handler->ih_level < 0 || handler->ih_level >= NIPL) - return(-1); - - /* Attach handler at top of chain */ - handler->ih_next = irqhandlers[irq]; - irqhandlers[irq] = handler; - - /* - * Reset the flags for this handler. - * As the handler is now in the chain mark it as active. - */ - handler->ih_flags = 0 | IRQ_FLAG_ACTIVE; - - /* - * Record the interrupt number for accounting. - * Done here as the accounting number may not be the same as the IRQ number - * though for the moment they are - */ - handler->ih_num = irq; - -#ifdef IRQSTATS - /* Get the interrupt name from the head of the list */ - if (handler->ih_name) { - char *ptr = _intrnames + (irq * 14); - strcpy(ptr, " "); - strncpy(ptr, handler->ih_name, - min(strlen(handler->ih_name), 13)); - } else { - char *ptr = _intrnames + (irq * 14); - sprintf(ptr, "irq %2d ", irq); - } -#endif /* IRQSTATS */ - - /* - * Update the irq masks. - * If ih_level is out of range then don't bother to update - * the masks. - */ - if (handler->ih_level >= 0 && handler->ih_level < NIPL) { - irqhandler_t *ptr; - - /* - * Find the lowest interrupt priority on the irq chain. - * Interrupt is allowable at priorities lower than this. - */ - ptr = irqhandlers[irq]; - if (ptr) { - level = ptr->ih_level - 1; - while (ptr) { - if (ptr->ih_level - 1 < level) - level = ptr->ih_level - 1; - ptr = ptr->ih_next; - } - for (loop = 0; loop < NIPL; ++loop) { - if (level >= loop) - irqmasks[loop] |= (1 << irq); - else - irqmasks[loop] &= ~(1 << irq); - } - } - -#include "sl.h" -#include "ppp.h" -#if NSL > 0 || NPPP > 0 - /* In the presence of SLIP or PPP, splimp > spltty. */ - irqmasks[IPL_NET] &= irqmasks[IPL_TTY]; -#endif - } - - /* - * We now need to update the irqblock array. This array indicates - * what other interrupts should be blocked when interrupt is asserted - * This basically emulates hardware interrupt priorities e.g. by blocking - * all other IPL_BIO interrupts with an IPL_BIO interrupt is asserted. - * For each interrupt we find the highest IPL and set the block mask to - * the interrupt mask for that level. - */ - for (loop = 0; loop < NIRQS; ++loop) { - irqhandler_t *ptr; - - ptr = irqhandlers[loop]; - if (ptr) { - /* There is at least 1 handler so scan the chain */ - level = ptr->ih_level; - while (ptr) { - if (ptr->ih_level > level) - level = ptr->ih_level; - ptr = ptr->ih_next; - } - irqblock[loop] = ~irqmasks[level]; - } else - /* No handlers for this irq so nothing to block */ - irqblock[loop] = 0; - } - - enable_irq(irq); - set_spl_masks(); - - return(0); -} - - -/* - * int irq_release(int irq, irqhandler_t *handler) - * - * Disable an IRQ and remove a handler for it. - */ - -int -irq_release(irq, handler) - int irq; - irqhandler_t *handler; -{ - int level; - int loop; - irqhandler_t *irqhand; - irqhandler_t **prehand; -#ifdef IRQSTATS - extern char *_intrnames; -#endif /* IRQSTATS */ - /* - * IRQ_INSTRUCT indicates that we should get the irq number - * from the irq structure - */ - if (irq == IRQ_INSTRUCT) - irq = handler->ih_num; - - /* Make sure the irq number is valid */ - if (irq < 0 || irq >= NIRQS) - return(-1); - - /* Locate the handler */ - irqhand = irqhandlers[irq]; - prehand = &irqhandlers[irq]; - - while (irqhand && handler != irqhand) { - prehand = &irqhand->ih_next; - irqhand = irqhand->ih_next; - } - - /* Remove the handler if located */ - if (irqhand) - *prehand = irqhand->ih_next; - else - return(-1); - - /* Now the handler has been removed from the chain mark is as inactive */ - irqhand->ih_flags &= ~IRQ_FLAG_ACTIVE; - - /* Make sure the head of the handler list is active */ - if (irqhandlers[irq]) - irqhandlers[irq]->ih_flags |= IRQ_FLAG_ACTIVE; - -#ifdef IRQSTATS - /* Get the interrupt name from the head of the list */ - if (irqhandlers[irq] && irqhandlers[irq]->ih_name) { - char *ptr = _intrnames + (irq * 14); - strcpy(ptr, " "); - strncpy(ptr, irqhandlers[irq]->ih_name, - min(strlen(irqhandlers[irq]->ih_name), 13)); - } else { - char *ptr = _intrnames + (irq * 14); - sprintf(ptr, "irq %2d ", irq); - } -#endif /* IRQSTATS */ - - /* - * Update the irq masks. - * If ih_level is out of range then don't bother to update - * the masks. - */ - if (handler->ih_level >= 0 && handler->ih_level < NIPL) { - irqhandler_t *ptr; - - /* - * Find the lowest interrupt priority on the irq chain. - * Interrupt is allowable at priorities lower than this. - */ - ptr = irqhandlers[irq]; - if (ptr) { - level = ptr->ih_level - 1; - while (ptr) { - if (ptr->ih_level - 1 < level) - level = ptr->ih_level - 1; - ptr = ptr->ih_next; - } - for (loop = 0; loop < NIPL; ++loop) { - if (level >= loop) - irqmasks[loop] |= (1 << irq); - else - irqmasks[loop] &= ~(1 << irq); - } - } - } - - /* - * We now need to update the irqblock array. This array indicates - * what other interrupts should be blocked when interrupt is asserted - * This basically emulates hardware interrupt priorities e.g. by - * blocking all other IPL_BIO interrupts with an IPL_BIO interrupt - * is asserted. For each interrupt we find the highest IPL and set - * the block mask to the interrupt mask for that level. - */ - for (loop = 0; loop < NIRQS; ++loop) { - irqhandler_t *ptr; - - ptr = irqhandlers[loop]; - if (ptr) { - /* There is at least 1 handler so scan the chain */ - level = ptr->ih_level; - while (ptr) { - if (ptr->ih_level > level) - level = ptr->ih_level; - ptr = ptr->ih_next; - } - irqblock[loop] = ~irqmasks[level]; - } else - /* No handlers for this irq so nothing to block */ - irqblock[loop] = 0; - } - - /* - * Disable the appropriate mask bit if there are no handlers left for - * this IRQ. - */ - if (irqhandlers[irq] == NULL) - disable_irq(irq); - - set_spl_masks(); - - return(0); -} - - -void * -intr_claim(irq, level, name, ih_func, ih_arg) - int irq; - int level; - const char *name; - int (*ih_func) __P((void *)); - void *ih_arg; -{ - irqhandler_t *ih; - - ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT); - if (!ih) - panic("intr_claim(): Cannot malloc handler memory"); - - ih->ih_level = level; - ih->ih_name = name; - ih->ih_func = ih_func; - ih->ih_arg = ih_arg; - ih->ih_flags = 0; - - if (irq_claim(irq, ih) != 0) - return(NULL); - return(ih); -} - - -int -intr_release(arg) - void *arg; -{ - irqhandler_t *ih = (irqhandler_t *)arg; - - if (irq_release(ih->ih_num, ih) == 0) { - free(ih, M_DEVBUF); - return(0); - } - return(1); -} |
