[BACK]Return to intr.c CVS log [TXT][DIR] Up to [local] / sys / arch / hppa / hppa

Annotation of sys/arch/hppa/hppa/intr.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: intr.c,v 1.23 2007/05/27 16:36:07 kettenis Exp $      */
                      2:
                      3: /*
                      4:  * Copyright (c) 2002-2004 Michael Shalayeff
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     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:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     19:  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
                     20:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     21:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     22:  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     24:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
                     25:  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
                     26:  * THE POSSIBILITY OF SUCH DAMAGE.
                     27:  */
                     28:
                     29: #include <sys/param.h>
                     30: #include <sys/systm.h>
                     31: #include <sys/kernel.h>
                     32: #include <sys/device.h>
                     33: #include <sys/evcount.h>
                     34: #include <sys/malloc.h>
                     35:
                     36: #include <net/netisr.h>
                     37:
                     38: #include <uvm/uvm_extern.h>    /* for uvmexp */
                     39:
                     40: #include <machine/autoconf.h>
                     41: #include <machine/frame.h>
                     42: #include <machine/reg.h>
                     43:
                     44: void softnet(void);
                     45: void softtty(void);
                     46:
                     47: struct hppa_iv {
                     48:        char pri;
                     49:        char irq;
                     50:        char flags;
                     51: #define        HPPA_IV_CALL    0x01
                     52: #define        HPPA_IV_SOFT    0x02
                     53:        char pad;
                     54:        int pad2;
                     55:        int (*handler)(void *);
                     56:        void *arg;
                     57:        u_int bit;
                     58:        struct hppa_iv *share;
                     59:        struct hppa_iv *next;
                     60:        struct evcount *cnt;
                     61: } __packed;
                     62:
                     63: register_t kpsw = PSL_Q | PSL_P | PSL_C | PSL_D;
                     64: volatile int cpu_inintr, cpl = IPL_NESTED;
                     65: u_long cpu_mask;
                     66: struct hppa_iv intr_store[8*2*CPU_NINTS] __attribute__ ((aligned(32))),
                     67:     *intr_more = intr_store, *intr_list;
                     68: struct hppa_iv intr_table[CPU_NINTS] __attribute__ ((aligned(32))) = {
                     69:        { IPL_SOFTCLOCK, 0, HPPA_IV_SOFT, 0, 0, (int (*)(void *))&softclock },
                     70:        { IPL_SOFTNET  , 0, HPPA_IV_SOFT, 0, 0, (int (*)(void *))&softnet },
                     71:        { 0 }, { 0 },
                     72:        { IPL_SOFTTTY  , 0, HPPA_IV_SOFT, 0, 0, (int (*)(void *))&softtty }
                     73: };
                     74: volatile u_long ipending, imask[NIPL] = {
                     75:        0,
                     76:        1 << (IPL_SOFTCLOCK - 1),
                     77:        1 << (IPL_SOFTNET - 1),
                     78:        0, 0,
                     79:        1 << (IPL_SOFTTTY - 1)
                     80: };
                     81:
                     82: #ifdef DIAGNOSTIC
                     83: void
                     84: splassert_check(int wantipl, const char *func)
                     85: {
                     86:        if (cpl < wantipl) {
                     87:                splassert_fail(wantipl, cpl, func);
                     88:        }
                     89: }
                     90: #endif
                     91:
                     92: void
                     93: softnet(void)
                     94: {
                     95:        int ni;
                     96:
                     97:        /* use atomic "load & clear" */
                     98:        __asm __volatile(
                     99:            "ldcws      0(%2), %0": "=&r" (ni), "+m" (netisr): "r" (&netisr));
                    100: #define DONETISR(m,c) if (ni & (1 << (m))) c()
                    101: #include <net/netisr_dispatch.h>
                    102: }
                    103:
                    104: void
                    105: softtty(void)
                    106: {
                    107:
                    108: }
                    109:
                    110: void
                    111: cpu_intr_init(void)
                    112: {
                    113:        u_long mask = cpu_mask | SOFTINT_MASK;
                    114:        struct hppa_iv *iv;
                    115:        int level, bit;
                    116:
                    117:        /* map the shared ints */
                    118:        while (intr_list) {
                    119:                iv = intr_list;
                    120:                intr_list = iv->next;
                    121:                bit = ffs(imask[(int)iv->pri]);
                    122:                if (!bit--) {
                    123:                        bit = ffs(~mask);
                    124:                        if (!bit--)
                    125:                                panic("cpu_intr_init: out of bits");
                    126:
                    127:                        iv->next = NULL;
                    128:                        iv->bit = 1 << bit;
                    129:                        intr_table[bit] = *iv;
                    130:                        mask |= (1 << bit);
                    131:                        imask[(int)iv->pri] |= (1 << bit);
                    132:                } else {
                    133:                        iv->bit = 1 << bit;
                    134:                        iv->next = intr_table[bit].next;
                    135:                        intr_table[bit].next = iv;
                    136:                }
                    137:        }
                    138:
                    139:        for (level = 0; level < NIPL - 1; level++)
                    140:                imask[level + 1] |= imask[level];
                    141:
                    142:        printf("biomask 0x%lx netmask 0x%lx ttymask 0x%lx\n",
                    143:            imask[IPL_BIO], imask[IPL_NET], imask[IPL_TTY]);
                    144:
                    145:        /* XXX the whacky trick is to prevent hardclock from happenning */
                    146:        mfctl(CR_ITMR, mask);
                    147:        mtctl(mask - 1, CR_ITMR);
                    148:
                    149:        mtctl(cpu_mask, CR_EIEM);
                    150:        /* ack the unwanted interrupts */
                    151:        mfctl(CR_EIRR, mask);
                    152:        mtctl(mask & (1 << 31), CR_EIRR);
                    153:
                    154:        /* in spl*() we trust, clock is started in initclocks() */
                    155:        kpsw |= PSL_I;
                    156:        ssm(PSL_I, mask);
                    157: }
                    158:
                    159: int
                    160: cpu_intr_findirq(void)
                    161: {
                    162:        int irq;
                    163:
                    164:        for (irq = 0; irq < CPU_NINTS; irq++)
                    165:                if (intr_table[irq].handler == NULL)
                    166:                        return irq;
                    167:
                    168:        return -1;
                    169: }
                    170:
                    171: void *
                    172: cpu_intr_map(void *v, int pri, int irq, int (*handler)(void *), void *arg,
                    173:     const char *name)
                    174: {
                    175:        struct hppa_iv *iv, *pv = v, *ivb = pv->next;
                    176:        struct evcount *cnt;
                    177:
                    178:        if (irq < 0 || irq >= CPU_NINTS)
                    179:                return (NULL);
                    180:
                    181:        MALLOC(cnt, struct evcount *, sizeof *cnt, M_DEVBUF, M_NOWAIT);
                    182:        if (!cnt)
                    183:                return (NULL);
                    184:
                    185:        iv = &ivb[irq];
                    186:        if (iv->handler) {
                    187:                if (!pv->share) {
                    188:                        FREE(cnt, M_DEVBUF);
                    189:                        return (NULL);
                    190:                } else {
                    191:                        iv = pv->share;
                    192:                        pv->share = iv->share;
                    193:                        iv->share = ivb[irq].share;
                    194:                        ivb[irq].share = iv;
                    195:                }
                    196:        }
                    197:
                    198:        evcount_attach(cnt, name, NULL, &evcount_intr);
                    199:        iv->pri = pri;
                    200:        iv->irq = irq;
                    201:        iv->flags = 0;
                    202:        iv->handler = handler;
                    203:        iv->arg = arg;
                    204:        iv->cnt = cnt;
                    205:        iv->next = intr_list;
                    206:        intr_list = iv;
                    207:
                    208:        return (iv);
                    209: }
                    210:
                    211: void *
                    212: cpu_intr_establish(int pri, int irq, int (*handler)(void *), void *arg,
                    213:     const char *name)
                    214: {
                    215:        struct hppa_iv *iv, *ev;
                    216:        struct evcount *cnt;
                    217:
                    218:        if (irq < 0 || irq >= CPU_NINTS || intr_table[irq].handler)
                    219:                return (NULL);
                    220:
                    221:        MALLOC(cnt, struct evcount *, sizeof *cnt, M_DEVBUF, M_NOWAIT);
                    222:        if (!cnt)
                    223:                return (NULL);
                    224:
                    225:        cpu_mask |= (1 << irq);
                    226:        imask[pri] |= (1 << irq);
                    227:
                    228:        iv = &intr_table[irq];
                    229:        iv->pri = pri;
                    230:        iv->irq = irq;
                    231:        iv->bit = 1 << irq;
                    232:        iv->flags = 0;
                    233:        iv->handler = handler;
                    234:        iv->arg = arg;
                    235:        iv->cnt = cnt;
                    236:        iv->next = NULL;
                    237:        iv->share = NULL;
                    238:
                    239:        if (pri == IPL_NESTED) {
                    240:                iv->flags = HPPA_IV_CALL;
                    241:                iv->next = intr_more;
                    242:                intr_more += 2 * CPU_NINTS;
                    243:                for (ev = iv->next + CPU_NINTS; ev < intr_more; ev++)
                    244:                        ev->share = iv->share, iv->share = ev;
                    245:                FREE(cnt, M_DEVBUF);
                    246:                iv->cnt = NULL;
                    247:        } else
                    248:                evcount_attach(cnt, name, NULL, &evcount_intr);
                    249:
                    250:        return (iv);
                    251: }
                    252:
                    253: int
                    254: fls(u_int mask)
                    255: {
                    256:        int bit;
                    257:
                    258:        bit = 32;
                    259:        if (!(mask & 0xffff0000)) {
                    260:                bit -= 16;
                    261:                mask <<= 16;
                    262:        }
                    263:
                    264:        if (!(mask & 0xff000000)) {
                    265:                bit -= 8;
                    266:                mask <<= 8;
                    267:        }
                    268:
                    269:        if (!(mask & 0xf0000000)) {
                    270:                bit -= 4;
                    271:                mask <<= 4;
                    272:        }
                    273:
                    274:        if (!(mask & 0xc0000000)) {
                    275:                bit -= 2;
                    276:                mask <<= 2;
                    277:        }
                    278:
                    279:        if (!(mask & 0x80000000)) {
                    280:                bit -= 1;
                    281:                mask <<= 1;
                    282:        }
                    283:
                    284:        return mask? bit : 0;
                    285: }
                    286:
                    287: void
                    288: cpu_intr(void *v)
                    289: {
                    290:        struct trapframe *frame = v;
                    291:        u_long mask;
                    292:        int s = cpl;
                    293:
                    294:        if (cpu_inintr++)
                    295:                frame->tf_flags |= TFF_INTR;
                    296:
                    297:        while ((mask = ipending & ~imask[s])) {
                    298:                int r, bit = fls(mask) - 1;
                    299:                struct hppa_iv *iv = &intr_table[bit];
                    300:
                    301:                ipending &= ~(1L << bit);
                    302:                if (iv->flags & HPPA_IV_CALL)
                    303:                        continue;
                    304:
                    305:                uvmexp.intrs++;
                    306:                if (iv->flags & HPPA_IV_SOFT)
                    307:                        uvmexp.softs++;
                    308:
                    309:                cpl = iv->pri;
                    310:                mtctl(frame->tf_eiem, CR_EIEM);
                    311:                for (r = iv->flags & HPPA_IV_SOFT;
                    312:                    iv && iv->handler; iv = iv->next)
                    313:                        /* no arg means pass the frame */
                    314:                        if ((iv->handler)(iv->arg? iv->arg : v) == 1) {
                    315:                                if (iv->cnt)
                    316:                                        iv->cnt->ec_count++;
                    317:                                r |= 1;
                    318:                        }
                    319: #if 0  /* XXX this does not work, lasi gives us double ints */
                    320:                if (!r) {
                    321:                        cpl = 0;
                    322:                        printf("stray interrupt %d\n", bit);
                    323:                }
                    324: #endif
                    325:                mtctl(0, CR_EIEM);
                    326:        }
                    327:        cpu_inintr--;
                    328:        cpl = s;
                    329: }

CVSweb