1 /* $NetBSD: pic_soft.c,v 1.2 2007/10/17 19:56:46 garbled Exp $ */
4 * Copyright (c) 2007 Matt Thomas
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of The NetBSD Foundation nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: pic_soft.c,v 1.2 2007/10/17 19:56:46 garbled Exp $");
35 #include <sys/param.h>
36 #include <sys/malloc.h>
37 #include <sys/kernel.h>
39 #include <uvm/uvm_extern.h>
41 #include <machine/intr.h>
42 #include <arch/powerpc/pic/picvar.h>
45 #define SOFTMASK ((1 << IPL_SOFTCLOCK) |\
48 (1 << IPL_SOFTSERIAL))
50 static void softpic_enable_irq(struct pic_ops
*, int, int);
51 static void softpic_disable_irq(struct pic_ops
*, int);
52 static int softpic_get_irq(struct pic_ops
*);
53 static void softpic_source_name(struct pic_ops
*, int, char *, size_t);
55 static struct softpic_ops
{
62 .pic_enable_irq
= softpic_enable_irq
,
63 .pic_reenable_irq
= softpic_enable_irq
,
64 .pic_disable_irq
= softpic_disable_irq
,
65 .pic_get_irq
= softpic_get_irq
,
66 .pic_source_name
= softpic_source_name
,
74 struct pic_ops
* const pic
= &softpic
.pic
;
78 intr_establish(pic
->pic_intrbase
+ IPL_SOFTCLOCK
, IST_SOFT
,
79 IPL_SOFTCLOCK
, (int (*)(void *))softintr__run
,
80 (void *)IPL_SOFTCLOCK
);
81 intr_establish(pic
->pic_intrbase
+ IPL_SOFTNET
, IST_SOFT
,
82 IPL_SOFTNET
, (int (*)(void *))softintr__run
,
84 intr_establish(pic
->pic_intrbase
+ IPL_SOFTI2C
, IST_SOFT
,
85 IPL_SOFTI2C
, (int (*)(void *))softintr__run
,
87 intr_establish(pic
->pic_intrbase
+ IPL_SOFTSERIAL
, IST_SOFT
,
88 IPL_SOFTSERIAL
, (int (*)(void *))softintr__run
,
89 (void *)IPL_SOFTSERIAL
);
93 softpic_source_name(struct pic_ops
*pic
, int irq
, char *name
, size_t len
)
96 case IPL_SOFTSERIAL
: strlcpy(name
, "serial", len
); break;
97 case IPL_SOFTNET
: strlcpy(name
, "net", len
); break;
98 case IPL_SOFTI2C
: strlcpy(name
, "i2c", len
); break;
99 case IPL_SOFTCLOCK
: strlcpy(name
, "clock", len
); break;
104 softpic_enable_irq(struct pic_ops
*pic
, int irq
, int type
)
106 struct softpic_ops
* const soft
= (void *) pic
;
107 soft
->enable_mask
|= 1 << irq
;
108 if (soft
->pending
& soft
->enable_mask
)
109 pic_mark_pending(pic
->pic_intrbase
+ irq
);
113 softpic_disable_irq(struct pic_ops
*pic
, int irq
)
115 struct softpic_ops
* const soft
= (void *) pic
;
116 soft
->enable_mask
&= ~(1 << irq
);
120 softpic_get_irq(struct pic_ops
*pic
)
122 struct softpic_ops
* const soft
= (void *) pic
;
126 while (((old
= soft
->pending
) & soft
->enable_mask
) != 0) {
127 /* use cntlzw instead of ffs since we want higher IPLs first */
128 ipl
= 32 - __builtin_clz(old
& soft
->enable_mask
);
131 new = old
& ~(1 << ipl
);
132 if (cas32(&soft
->pending
, old
, new))
142 KASSERT((1 << ipl
) & SOFTMASK
);
145 uint32_t old
= softpic
.pending
;
146 uint32_t new = old
| (1 << ipl
);
147 if (cas32(&softpic
.pending
, old
, new)) {
148 pic_handle_intr(&softpic
);