From 3d513c3e7a92e15b1b6712f552bd0ca6b0b6d103 Mon Sep 17 00:00:00 2001 From: toshii Date: Tue, 22 May 2001 17:25:15 +0000 Subject: [PATCH] Implement generic soft interrupt for hpcarm. --- sys/arch/hpcarm/conf/files.hpcarm | 3 +- sys/arch/hpcarm/hpcarm/intr.c | 5 +- sys/arch/hpcarm/hpcarm/softintr.c | 183 ++++++++++++++++++++++++++++++ sys/arch/hpcarm/hpcarm/stubs.c | 30 ++++- sys/arch/hpcarm/include/intr.h | 8 +- 5 files changed, 225 insertions(+), 4 deletions(-) create mode 100644 sys/arch/hpcarm/hpcarm/softintr.c diff --git a/sys/arch/hpcarm/conf/files.hpcarm b/sys/arch/hpcarm/conf/files.hpcarm index 77c646870b1e..999b43fb1cf0 100644 --- a/sys/arch/hpcarm/conf/files.hpcarm +++ b/sys/arch/hpcarm/conf/files.hpcarm @@ -1,4 +1,4 @@ -# $NetBSD: files.hpcarm,v 1.15 2001/05/06 18:31:15 bjh21 Exp $ +# $NetBSD: files.hpcarm,v 1.16 2001/05/22 17:25:15 toshii Exp $ # # First try for arm-specific configuration info # @@ -38,6 +38,7 @@ file arch/hpcarm/hpcarm/process_machdep.c file arch/hpcarm/hpcarm/procfs_machdep.c procfs file arch/hpcarm/hpcarm/setcpsr.S file arch/hpcarm/hpcarm/setstack.S +file arch/hpcarm/hpcarm/softintr.c file arch/hpcarm/hpcarm/spl.S file arch/hpcarm/hpcarm/stubs.c file arch/hpcarm/hpcarm/vm_machdep.c diff --git a/sys/arch/hpcarm/hpcarm/intr.c b/sys/arch/hpcarm/hpcarm/intr.c index 23f16650e0fb..468c519dcbd1 100644 --- a/sys/arch/hpcarm/hpcarm/intr.c +++ b/sys/arch/hpcarm/hpcarm/intr.c @@ -1,4 +1,4 @@ -/* $NetBSD: intr.c,v 1.2 2001/04/30 15:54:28 toshii Exp $ */ +/* $NetBSD: intr.c,v 1.3 2001/05/22 17:25:16 toshii Exp $ */ /* * Copyright (c) 1994-1998 Mark Brinicombe. @@ -52,6 +52,7 @@ u_int soft_interrupts = 0; extern int current_spl_level; +extern int softintr_dispatch(int); /* Generate soft interrupt counts if IRQSTATS is defined */ #ifdef IRQSTATS @@ -119,6 +120,8 @@ dosoftints() u_int softints; int s; + softintr_dispatch(current_spl_level); + softints = soft_interrupts & spl_smasks[current_spl_level]; if (softints == 0) return; diff --git a/sys/arch/hpcarm/hpcarm/softintr.c b/sys/arch/hpcarm/hpcarm/softintr.c new file mode 100644 index 000000000000..4a377ec2abcd --- /dev/null +++ b/sys/arch/hpcarm/hpcarm/softintr.c @@ -0,0 +1,183 @@ +/* $NetBSD: softintr.c,v 1.1 2001/05/22 17:25:16 toshii Exp $ */ + +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by IWAMOTO Toshihiro. + * + * 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 the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``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 FOUNDATION 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 +#include +#include +#include + +#include +#include +#include + +extern int ipl_to_spl(int); +int softintr_free(void *); + +struct softintr_handler { + struct softintr_handler *sh_vlink; /* vertical link */ + struct softintr_handler *sh_hlink; /* horizontal link */ + + int (*sh_fun)(void *); + void *sh_arg; + int sh_level; + + int sh_pending; +}; + +struct softintr_handler *softintrs; +struct softintr_handler *softintr_pending; + +void * +softintr_establish(int level, int (*fun)(void *), void *arg) +{ + struct softintr_handler *sh; + + sh = malloc(sizeof(*sh), M_DEVBUF, M_NOWAIT); + if (sh == NULL) + return(NULL); + + sh->sh_fun = fun; + sh->sh_level = ipl_to_spl(level); + sh->sh_arg = arg; + sh->sh_pending = 0; + + return sh; +} + +void +softintr_disestablish(void *cookie) +{ + struct softintr_handler *sh = cookie; + u_int saved_cpsr; + + saved_cpsr = SetCPSR(I32_bit, I32_bit); + if (sh->sh_pending) { + sh->sh_fun = softintr_free; + sh->sh_arg = sh; + SetCPSR(I32_bit, I32_bit & saved_cpsr); + } else { + SetCPSR(I32_bit, I32_bit & saved_cpsr); + free(sh, M_DEVBUF); + } +} + +int +softintr_free(void *arg) +{ + + free(arg, M_DEVBUF); + return 0; +} + +void +softintr_schedule(void *cookie) +{ + struct softintr_handler **p, *sh = cookie; + register int pending; + u_int saved_cpsr; + + pending = 1; + asm("swp %0, %0, [%1]" : "+r" (pending) : "r" (&sh->sh_pending)); + + if (pending) + return; + + sh->sh_vlink = NULL; + sh->sh_hlink = NULL; + + saved_cpsr = SetCPSR(I32_bit, I32_bit); + p = &softintr_pending; + + for (;; p = &(*p)->sh_vlink) { + if (*p == NULL) { + *p = sh; + SetCPSR(I32_bit, I32_bit & saved_cpsr); + return; + } + if ((*p)->sh_level <= sh->sh_level) + break; + } + + if ((*p)->sh_level == sh->sh_level) { + sh->sh_hlink = *p; + sh->sh_vlink = (*p)->sh_vlink; + (*p)->sh_vlink = NULL; + *p = sh; + SetCPSR(I32_bit, I32_bit & saved_cpsr); + return; + } + + sh->sh_vlink = *p; + *p = sh; + SetCPSR(I32_bit, I32_bit & saved_cpsr); + return; +} + +void +softintr_dispatch(int s) +{ + struct softintr_handler *sh, *sh1; + u_int saved_cpsr; + + while (1) { + /* Protect list operation from interrupts */ + saved_cpsr = SetCPSR(I32_bit, I32_bit); + + if (softintr_pending == NULL || + softintr_pending->sh_level <= s) { + SetCPSR(I32_bit, I32_bit & saved_cpsr); + return; + } + sh = softintr_pending; + softintr_pending = softintr_pending->sh_vlink; + SetCPSR(I32_bit, I32_bit & saved_cpsr); + + s = raisespl(sh->sh_level); + while (1) { + /* The order is important */ + sh1 = sh->sh_hlink; + sh->sh_pending = 0; + + (sh->sh_fun)(sh->sh_arg); + if (sh1 == NULL) + break; + sh = sh1; + } + splx(s); + } +} diff --git a/sys/arch/hpcarm/hpcarm/stubs.c b/sys/arch/hpcarm/hpcarm/stubs.c index 8609b88a0d81..f4a9aa92b87e 100644 --- a/sys/arch/hpcarm/hpcarm/stubs.c +++ b/sys/arch/hpcarm/hpcarm/stubs.c @@ -1,4 +1,4 @@ -/* $NetBSD: stubs.c,v 1.3 2001/05/22 17:01:16 toshii Exp $ */ +/* $NetBSD: stubs.c,v 1.4 2001/05/22 17:25:16 toshii Exp $ */ /* * Copyright (c) 1994-1998 Mark Brinicombe. @@ -278,6 +278,34 @@ set_spl_masks() spl_smasks[loop] |= SOFTIRQ_BIT(SOFTIRQ_CLOCK); } +int +ipl_to_spl(ipl) + int ipl; +{ + + switch(ipl) { + case IPL_BIO: + return _SPL_BIO; + case IPL_NET: + return _SPL_NET; + case IPL_TTY: + return _SPL_TTY; + case IPL_IMP: + return _SPL_IMP; + case IPL_AUDIO: + return _SPL_AUDIO; + case IPL_CLOCK: + return _SPL_CLOCK; + case IPL_HIGH: + return _SPL_HIGH; + case IPL_SERIAL: + return _SPL_SERIAL; + + default: + panic("bogus ipl\n"); + } +} + #ifdef DIAGNOSTIC void dump_spl_masks() diff --git a/sys/arch/hpcarm/include/intr.h b/sys/arch/hpcarm/include/intr.h index 8d08061293a0..524b78d11e1b 100644 --- a/sys/arch/hpcarm/include/intr.h +++ b/sys/arch/hpcarm/include/intr.h @@ -1,4 +1,4 @@ -/* $NetBSD: intr.h,v 1.3 2001/05/15 16:15:22 toshii Exp $ */ +/* $NetBSD: intr.h,v 1.4 2001/05/22 17:25:16 toshii Exp $ */ /* * Copyright (c) 1997 Mark Brinicombe. @@ -69,4 +69,10 @@ #include #include +#ifndef _LOCORE +void *softintr_establish(int, int (*)(void *), void *); +void softintr_disestablish(void *); +void softintr_schedule(void *); +#endif + #endif /* _HPCARM_INTR_H */