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

Annotation of sys/arch/aviion/aviion/av400_machdep.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: av400_machdep.c,v 1.5 2007/05/12 20:02:12 miod Exp $  */
        !             2: /*
        !             3:  * Copyright (c) 2006, Miodrag Vallat.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  *
        !            14:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            15:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            16:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        !            17:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
        !            18:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        !            19:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        !            20:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            21:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            22:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
        !            23:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            24:  * POSSIBILITY OF SUCH DAMAGE.
        !            25:  */
        !            26: /*
        !            27:  * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr.
        !            28:  * Copyright (c) 1996 Nivas Madhur
        !            29:  * All rights reserved.
        !            30:  *
        !            31:  * Redistribution and use in source and binary forms, with or without
        !            32:  * modification, are permitted provided that the following conditions
        !            33:  * are met:
        !            34:  * 1. Redistributions of source code must retain the above copyright
        !            35:  *    notice, this list of conditions and the following disclaimer.
        !            36:  * 2. Redistributions in binary form must reproduce the above copyright
        !            37:  *    notice, this list of conditions and the following disclaimer in the
        !            38:  *    documentation and/or other materials provided with the distribution.
        !            39:  * 3. All advertising materials mentioning features or use of this software
        !            40:  *    must display the following acknowledgement:
        !            41:  *      This product includes software developed by Nivas Madhur.
        !            42:  * 4. The name of the author may not be used to endorse or promote products
        !            43:  *    derived from this software without specific prior written permission
        !            44:  *
        !            45:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            46:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            47:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            48:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            49:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            50:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            51:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            52:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            53:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            54:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            55:  *
        !            56:  */
        !            57: /*
        !            58:  * Copyright (c) 1999 Steve Murphree, Jr.
        !            59:  * Copyright (c) 1995 Theo de Raadt
        !            60:  *
        !            61:  * Redistribution and use in source and binary forms, with or without
        !            62:  * modification, are permitted provided that the following conditions
        !            63:  * are met:
        !            64:  * 1. Redistributions of source code must retain the above copyright
        !            65:  *    notice, this list of conditions and the following disclaimer.
        !            66:  * 2. Redistributions in binary form must reproduce the above copyright
        !            67:  *    notice, this list of conditions and the following disclaimer in the
        !            68:  *    documentation and/or other materials provided with the distribution.
        !            69:  *
        !            70:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
        !            71:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            72:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            73:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
        !            74:  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            75:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            76:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            77:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            78:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            79:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            80:  * SUCH DAMAGE.
        !            81:  *
        !            82:  * Copyright (c) 1992, 1993
        !            83:  *     The Regents of the University of California.  All rights reserved.
        !            84:  * Copyright (c) 1995 Nivas Madhur
        !            85:  * Copyright (c) 1994 Gordon W. Ross
        !            86:  * Copyright (c) 1993 Adam Glass
        !            87:  *
        !            88:  * This software was developed by the Computer Systems Engineering group
        !            89:  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
        !            90:  * contributed to Berkeley.
        !            91:  *
        !            92:  * All advertising materials mentioning features or use of this software
        !            93:  * must display the following acknowledgement:
        !            94:  *     This product includes software developed by the University of
        !            95:  *     California, Lawrence Berkeley Laboratory.
        !            96:  *
        !            97:  * Redistribution and use in source and binary forms, with or without
        !            98:  * modification, are permitted provided that the following conditions
        !            99:  * are met:
        !           100:  * 1. Redistributions of source code must retain the above copyright
        !           101:  *    notice, this list of conditions and the following disclaimer.
        !           102:  * 2. Redistributions in binary form must reproduce the above copyright
        !           103:  *    notice, this list of conditions and the following disclaimer in the
        !           104:  *    documentation and/or other materials provided with the distribution.
        !           105:  * 3. Neither the name of the University nor the names of its contributors
        !           106:  *    may be used to endorse or promote products derived from this software
        !           107:  *    without specific prior written permission.
        !           108:  *
        !           109:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !           110:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !           111:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !           112:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !           113:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !           114:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !           115:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !           116:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !           117:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !           118:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !           119:  * SUCH DAMAGE.
        !           120:  *
        !           121:  *     @(#)clock.c     8.1 (Berkeley) 6/11/93
        !           122:  */
        !           123: /*
        !           124:  * Mach Operating System
        !           125:  * Copyright (c) 1993-1991 Carnegie Mellon University
        !           126:  * Copyright (c) 1991 OMRON Corporation
        !           127:  * All Rights Reserved.
        !           128:  *
        !           129:  * Permission to use, copy, modify and distribute this software and its
        !           130:  * documentation is hereby granted, provided that both the copyright
        !           131:  * notice and this permission notice appear in all copies of the
        !           132:  * software, derivative works or modified versions, and any portions
        !           133:  * thereof, and that both notices appear in supporting documentation.
        !           134:  *
        !           135:  */
        !           136:
        !           137: #include <sys/param.h>
        !           138: #include <sys/systm.h>
        !           139: #include <sys/kernel.h>
        !           140: #include <sys/errno.h>
        !           141:
        !           142: #include <uvm/uvm_extern.h>
        !           143:
        !           144: #include <machine/asm_macro.h>
        !           145: #include <machine/board.h>
        !           146: #include <machine/cmmu.h>
        !           147: #include <machine/cpu.h>
        !           148: #include <machine/reg.h>
        !           149: #include <machine/trap.h>
        !           150:
        !           151: #include <machine/m88100.h>
        !           152: #include <machine/m8820x.h>
        !           153: #include <machine/avcommon.h>
        !           154: #include <machine/av400.h>
        !           155: #include <machine/prom.h>
        !           156:
        !           157: #include <aviion/dev/sysconreg.h>
        !           158:
        !           159: u_int  safe_level(u_int mask, u_int curlevel);
        !           160:
        !           161: const pmap_table_entry
        !           162: av400_ptable[] = {
        !           163:        { AV400_PROM,   AV400_PROM,     AV400_PROM_SIZE,
        !           164:          UVM_PROT_RW,  CACHE_INH },
        !           165: #if 0  /* mapped by the hardcoded BATC entries */
        !           166:        { AV400_UTILITY,AV400_UTILITY,  AV400_UTILITY_SIZE,
        !           167:          UVM_PROT_RW,  CACHE_INHIBIT },
        !           168: #endif
        !           169:        { 0, 0, (vsize_t)-1, 0, 0 }
        !           170: };
        !           171:
        !           172: const struct board board_av400 = {
        !           173:        "100/200/300/400/3000/4000/4300 series",
        !           174:        av400_bootstrap,
        !           175:        av400_memsize,
        !           176:        av400_startup,
        !           177:        av400_intr,
        !           178:        av400_init_clocks,
        !           179:        av400_getipl,
        !           180:        av400_setipl,
        !           181:        av400_raiseipl,
        !           182:        av400_ptable
        !           183: };
        !           184:
        !           185: /*
        !           186:  * The MVME188 interrupt arbiter has 25 orthogonal interrupt sources.
        !           187:  * On the AViiON machines, there are even more interrupt sources in use,
        !           188:  * but differences are minimal.
        !           189:  * We fold this model in the 8-level spl model this port uses, enforcing
        !           190:  * priorities manually with the interrupt masks.
        !           191:  */
        !           192:
        !           193: /*
        !           194:  * Copy of the interrupt enable register for each CPU.
        !           195:  * Note that, on the AV400 design, the interrupt enable registers are
        !           196:  * write-only and read back as 0xffffffff.
        !           197:  */
        !           198: unsigned int int_mask_reg[] = { 0, 0, 0, 0 };
        !           199:
        !           200: u_int av400_curspl[] = { 0, 0, 0, 0 };
        !           201:
        !           202: /*
        !           203:  * external interrupt masks per spl.
        !           204:  */
        !           205: const unsigned int int_mask_val[INT_LEVEL] = {
        !           206:        MASK_LVL_0,
        !           207:        MASK_LVL_1,
        !           208:        MASK_LVL_2,
        !           209:        MASK_LVL_3,
        !           210:        MASK_LVL_4,
        !           211:        MASK_LVL_5,
        !           212:        MASK_LVL_6,
        !           213:        MASK_LVL_7
        !           214: };
        !           215:
        !           216: /*
        !           217:  * Figure out how much memory is available, by asking the PROM.
        !           218:  */
        !           219: vaddr_t
        !           220: av400_memsize()
        !           221: {
        !           222:        vaddr_t memsize;
        !           223:
        !           224:        memsize = scm_memsize(1);
        !           225:
        !           226:        /*
        !           227:         * What we got is the ``top of memory'', i.e. the largest addressable
        !           228:         * word address, ending in 0xffc. Round up to a multiple of a page.
        !           229:         */
        !           230:        memsize = round_page(memsize);
        !           231:
        !           232:        return (memsize);
        !           233: }
        !           234:
        !           235: void
        !           236: av400_startup()
        !           237: {
        !           238: }
        !           239:
        !           240: int32_t cpuid, sysid;
        !           241:
        !           242: void
        !           243: av400_bootstrap()
        !           244: {
        !           245:        extern struct cmmu_p cmmu8820x;
        !           246:        extern u_char hostaddr[6];
        !           247:
        !           248:        /*
        !           249:         * These are the fixed assignments on AV400 designs.
        !           250:         */
        !           251:        cmmu = &cmmu8820x;
        !           252:        m8820x_cmmu[0].cmmu_regs = (void *)AV400_CMMU_I0;
        !           253:        m8820x_cmmu[1].cmmu_regs = (void *)AV400_CMMU_D0;
        !           254:        m8820x_cmmu[2].cmmu_regs = (void *)AV400_CMMU_I1;
        !           255:        m8820x_cmmu[3].cmmu_regs = (void *)AV400_CMMU_D1;
        !           256:        m8820x_cmmu[4].cmmu_regs = (void *)AV400_CMMU_I2;
        !           257:        m8820x_cmmu[5].cmmu_regs = (void *)AV400_CMMU_D2;
        !           258:        m8820x_cmmu[6].cmmu_regs = (void *)AV400_CMMU_I3;
        !           259:        m8820x_cmmu[7].cmmu_regs = (void *)AV400_CMMU_D3;
        !           260:
        !           261:        /* clear and disable all interrupts */
        !           262:        *(volatile u_int32_t *)AV_IENALL = 0;
        !           263:
        !           264:        /*
        !           265:         * Get all the information we'll need later from the PROM, while
        !           266:         * we can still use it.
        !           267:         */
        !           268:        scm_getenaddr(hostaddr);
        !           269:        cpuid = scm_cpuid();
        !           270:        sysid = scm_sysid();
        !           271: }
        !           272:
        !           273: /*
        !           274:  * return next safe spl to reenable interrupts.
        !           275:  */
        !           276: u_int
        !           277: safe_level(u_int mask, u_int curlevel)
        !           278: {
        !           279:        int i;
        !           280:
        !           281:        for (i = curlevel; i < INT_LEVEL; i++)
        !           282:                if ((int_mask_val[i] & mask) == 0)
        !           283:                        return i;
        !           284:
        !           285:        return (INT_LEVEL - 1);
        !           286: }
        !           287:
        !           288: u_int
        !           289: av400_getipl(void)
        !           290: {
        !           291:        return av400_curspl[cpu_number()];
        !           292: }
        !           293:
        !           294: u_int
        !           295: av400_setipl(u_int level)
        !           296: {
        !           297:        u_int32_t mask, curspl;
        !           298:        u_int cpu = cpu_number();
        !           299:
        !           300:        curspl = av400_curspl[cpu];
        !           301:
        !           302:        mask = int_mask_val[level];
        !           303: #ifdef MULTIPROCESSOR
        !           304:        if (cpu != master_cpu)
        !           305:                mask &= ~SLAVE_MASK;
        !           306: #endif
        !           307:
        !           308:        *(u_int32_t *)AV_IEN(cpu) = int_mask_reg[cpu] = mask;
        !           309:        av400_curspl[cpu] = level;
        !           310:
        !           311:        return curspl;
        !           312: }
        !           313:
        !           314: u_int
        !           315: av400_raiseipl(u_int level)
        !           316: {
        !           317:        u_int32_t mask, curspl;
        !           318:        u_int cpu = cpu_number();
        !           319:
        !           320:        curspl = av400_curspl[cpu];
        !           321:        if (curspl < level) {
        !           322:                mask = int_mask_val[level];
        !           323: #ifdef MULTIPROCESSOR
        !           324:                if (cpu != master_cpu)
        !           325:                        mask &= ~SLAVE_MASK;
        !           326: #endif
        !           327:
        !           328:                *(u_int32_t *)AV_IEN(cpu) = int_mask_reg[cpu] = mask;
        !           329:                av400_curspl[cpu] = level;
        !           330:        }
        !           331:        return curspl;
        !           332: }
        !           333:
        !           334: /*
        !           335:  * Device interrupt handler for AV400
        !           336:  */
        !           337:
        !           338: /*
        !           339:  * Hard coded vector table for onboard devices and hardware failure
        !           340:  * interrupts.
        !           341:  */
        !           342: const unsigned int obio_vec[32] = {
        !           343:        0,              /* SWI0 */
        !           344:        0,              /* SWI1 */
        !           345:        0,
        !           346:        0,
        !           347:        0,              /* VME1 */
        !           348:        SYSCV_SCSI,     /* SCI */
        !           349:        0,              /* VME2 */
        !           350:        0,
        !           351:        0,
        !           352:        0,              /* DVB */
        !           353:        0,              /* VME3 */
        !           354:        0,              /* DWP */
        !           355:        0,              /* VME4 */
        !           356:        0,              /* DTC */
        !           357:        0,              /* VME5 */
        !           358:        SYSCV_LE,       /* ECI */
        !           359:        SYSCV_SCC2,     /* DI2 */
        !           360:        SYSCV_SCC,      /* DI1 */
        !           361:        0,              /* PPI */
        !           362:        0,              /* VME6 */
        !           363:        SYSCV_SYSF,     /* SF */
        !           364:        SYSCV_TIMER2,   /* CIOI */
        !           365:        0,              /* KBD */
        !           366:        0,              /* VME7 */
        !           367:        0,              /* PAR */
        !           368:        0,              /* VID */
        !           369:        0,              /* ZBUF */
        !           370:        0,
        !           371:        0,
        !           372:        0,              /* ARBTO */     /* no vector, but always masked */
        !           373:        SYSCV_ACF,      /* ACF */
        !           374:        SYSCV_ABRT      /* ABORT */
        !           375: };
        !           376:
        !           377: #define VME_VECTOR_MASK                0x1ff   /* mask into VIACK register */
        !           378: #define VME_BERR_MASK          0x100   /* timeout during VME IACK cycle */
        !           379:
        !           380: void
        !           381: av400_intr(u_int v, struct trapframe *eframe)
        !           382: {
        !           383:        int cpu = cpu_number();
        !           384:        unsigned int cur_mask, ign_mask;
        !           385:        unsigned int level, old_spl;
        !           386:        struct intrhand *intr;
        !           387:        intrhand_t *list;
        !           388:        int ret, intbit;
        !           389:        vaddr_t ivec;
        !           390:        u_int vec;
        !           391:        int unmasked = 0;
        !           392: #ifdef DIAGNOSTIC
        !           393:        static int problems = 0;
        !           394: #endif
        !           395:
        !           396:        cur_mask = ISR_GET_CURRENT_MASK(cpu);
        !           397:        ign_mask = 0;
        !           398:        old_spl = av400_curspl[cpu];
        !           399:        eframe->tf_mask = old_spl;
        !           400:
        !           401:        if (cur_mask == 0) {
        !           402:                /*
        !           403:                 * Spurious interrupts - may be caused by debug output clearing
        !           404:                 * DUART interrupts.
        !           405:                 */
        !           406:                flush_pipeline();
        !           407:                goto out;
        !           408:        }
        !           409:
        !           410:        uvmexp.intrs++;
        !           411:
        !           412:        /*
        !           413:         * We want to service all interrupts marked in the IST register
        !           414:         * They are all valid because the mask would have prevented them
        !           415:         * from being generated otherwise.  We will service them in order of
        !           416:         * priority.
        !           417:         */
        !           418:        do {
        !           419:                level = safe_level(cur_mask, old_spl);
        !           420:                setipl(level);
        !           421:
        !           422:                /*
        !           423:                 * Do not enable interrupts yet if we know, from cur_mask,
        !           424:                 * that we have not cleared enough conditions yet.
        !           425:                 * For now, only the timer interrupt requires its condition
        !           426:                 * to be cleared before interrupts are enabled.
        !           427:                 */
        !           428:                if (unmasked == 0 /* && (cur_mask & whatever) == 0 */) {
        !           429:                        set_psr(get_psr() & ~PSR_IND);
        !           430:                        unmasked = 1;
        !           431:                }
        !           432:
        !           433:                /* find the first bit set in the current mask */
        !           434:                intbit = ff1(cur_mask);
        !           435:                if (OBIO_INTERRUPT_MASK & (1 << intbit)) {
        !           436:                        vec = obio_vec[intbit];
        !           437:                        if (vec == 0) {
        !           438:                                panic("unknown onboard interrupt: mask = 0x%b",
        !           439:                                    1 << intbit, IST_STRING);
        !           440:                        }
        !           441:                        vec += SYSCON_VECT;
        !           442:                } else if (HW_FAILURE_MASK & (1 << intbit)) {
        !           443:                        vec = obio_vec[intbit];
        !           444:                        if (vec == 0) {
        !           445:                                panic("unknown hardware failure: mask = 0x%b",
        !           446:                                    1 << intbit, IST_STRING);
        !           447:                        }
        !           448:                        vec += SYSCON_VECT;
        !           449:                } else if (VME_INTERRUPT_MASK & (1 << intbit)) {
        !           450:                        ivec = AV400_VIRQLV + (level << 2);
        !           451:                        vec = *(volatile u_int32_t *)ivec & VME_VECTOR_MASK;
        !           452:                        if (vec & VME_BERR_MASK) {
        !           453:                                printf("%s: timeout getting VME "
        !           454:                                    "interrupt vector, "
        !           455:                                    "level %d, mask 0x%b\n",
        !           456:                                    __func__, level,
        !           457:                                    cur_mask, IST_STRING);
        !           458:                                ign_mask |= 1 << intbit;
        !           459:                                continue;
        !           460:                        }
        !           461:                        if (vec == 0) {
        !           462:                                panic("%s: invalid VME interrupt vector, "
        !           463:                                    "level %d, mask 0x%b",
        !           464:                                    __func__, level, cur_mask, IST_STRING);
        !           465:                        }
        !           466:                } else {
        !           467:                        panic("%s: unexpected interrupt source, "
        !           468:                            "level %d, mask 0x%b",
        !           469:                            __func__, level, cur_mask, IST_STRING);
        !           470:                }
        !           471:
        !           472:                list = &intr_handlers[vec];
        !           473:                if (SLIST_EMPTY(list)) {
        !           474:                        printf("%s: spurious interrupt, "
        !           475:                            "level %d, vec 0x%x, mask 0x%b\n",
        !           476:                            __func__, level, vec, cur_mask, IST_STRING);
        !           477:                        ign_mask |= 1 << intbit;
        !           478:                } else {
        !           479:                        /*
        !           480:                         * Walk through all interrupt handlers in the chain
        !           481:                         * for the given vector, calling each handler in turn,
        !           482:                         * till some handler returns a value != 0.
        !           483:                         */
        !           484:                        ret = 0;
        !           485:                        SLIST_FOREACH(intr, list, ih_link) {
        !           486:                                if (intr->ih_wantframe != 0)
        !           487:                                        ret = (*intr->ih_fn)((void *)eframe);
        !           488:                                else
        !           489:                                        ret = (*intr->ih_fn)(intr->ih_arg);
        !           490:                                if (ret != 0) {
        !           491:                                        intr->ih_count.ec_count++;
        !           492:                                        break;
        !           493:                                }
        !           494:                        }
        !           495:                        if (ret == 0) {
        !           496:                                panic("%s: unclaimed interrupt, "
        !           497:                                    "level %d, vec %x, mask 0x%b"
        !           498:                                    __func__, level, vec, cur_mask, IST_STRING);
        !           499:                                ign_mask |= 1 << intbit;
        !           500:                                break;
        !           501:                        }
        !           502:                }
        !           503:        } while (((cur_mask = ISR_GET_CURRENT_MASK(cpu)) & ~ign_mask) != 0);
        !           504:
        !           505: #ifdef DIAGNOSTIC
        !           506:        if (ign_mask != 0) {
        !           507:                if (++problems >= 10)
        !           508:                        panic("%s: broken interrupt behaviour", __func__);
        !           509:        } else
        !           510:                problems = 0;
        !           511: #endif
        !           512:
        !           513: out:
        !           514:        /*
        !           515:         * process any remaining data access exceptions before
        !           516:         * returning to assembler
        !           517:         */
        !           518:        if (eframe->tf_dmt0 & DMT_VALID)
        !           519:                m88100_trap(T_DATAFLT, eframe);
        !           520:
        !           521:        /*
        !           522:         * Disable interrupts before returning to assembler, the spl will
        !           523:         * be restored later.
        !           524:         */
        !           525:        set_psr(get_psr() | PSR_IND);
        !           526: }
        !           527:
        !           528: /*
        !           529:  * Clock routines
        !           530:  */
        !           531:
        !           532: void   av400_cio_init(unsigned);
        !           533: u_int  read_cio(int);
        !           534: void   write_cio(int, u_int);
        !           535:
        !           536: struct intrhand        clock_ih;
        !           537:
        !           538: int    av400_clockintr(void *);
        !           539:
        !           540: struct simplelock av400_cio_lock;
        !           541:
        !           542: #define        CIO_LOCK        simple_lock(&av400_cio_lock)
        !           543: #define        CIO_UNLOCK      simple_unlock(&av400_cio_lock)
        !           544:
        !           545: /*
        !           546:  * Statistics clock interval and variance, in usec.  Variance must be a
        !           547:  * power of two.  Since this gives us an even number, not an odd number,
        !           548:  * we discard one case and compensate.  That is, a variance of 4096 would
        !           549:  * give us offsets in [0..4095].  Instead, we take offsets in [1..4095].
        !           550:  * This is symmetric about the point 2048, or statvar/2, and thus averages
        !           551:  * to that value (assuming uniform random numbers).
        !           552:  */
        !           553: int statvar = 8192;
        !           554: int statmin;                   /* statclock interval - 1/2*variance */
        !           555:
        !           556: /*
        !           557:  * Notes on the AV400 clock usage:
        !           558:  *
        !           559:  * Unlike the MVME188 design, we only have access to three counter/timers
        !           560:  * in the Zilog Z8536 (since we can not receive the DUART timer interrupts).
        !           561:  *
        !           562:  * Clock is run on a Z8536 counter, kept in counter mode and retriggered
        !           563:  * every interrupt (when using the Z8536 in timer mode, it _seems_ that it
        !           564:  * resets at 0xffff instead of the initial count value...)
        !           565:  *
        !           566:  * It should be possible to run statclock on the Z8536 counter #2, but
        !           567:  * this would make interrupt handling more tricky, in the case both
        !           568:  * counters interrupt at the same time...
        !           569:  */
        !           570:
        !           571: void
        !           572: av400_init_clocks(void)
        !           573: {
        !           574:
        !           575:        simple_lock_init(&av400_cio_lock);
        !           576:
        !           577: #ifdef DIAGNOSTIC
        !           578:        if (1000000 % hz) {
        !           579:                printf("cannot get %d Hz clock; using 100 Hz\n", hz);
        !           580:                hz = 100;
        !           581:        }
        !           582: #endif
        !           583:        tick = 1000000 / hz;
        !           584:
        !           585:        av400_cio_init(tick);
        !           586:
        !           587:        stathz = 0;
        !           588:
        !           589:        clock_ih.ih_fn = av400_clockintr;
        !           590:        clock_ih.ih_arg = 0;
        !           591:        clock_ih.ih_wantframe = 1;
        !           592:        clock_ih.ih_ipl = IPL_CLOCK;
        !           593:        sysconintr_establish(SYSCV_TIMER2, &clock_ih, "clock");
        !           594: }
        !           595:
        !           596: int
        !           597: av400_clockintr(void *eframe)
        !           598: {
        !           599:        CIO_LOCK;
        !           600:        write_cio(CIO_CSR1, CIO_GCB | CIO_CIP);  /* Ack the interrupt */
        !           601:
        !           602:        hardclock(eframe);
        !           603:
        !           604:        /* restart counter */
        !           605:        write_cio(CIO_CSR1, CIO_GCB | CIO_TCB | CIO_IE);
        !           606:        CIO_UNLOCK;
        !           607:
        !           608:        return (1);
        !           609: }
        !           610:
        !           611: /* Write CIO register */
        !           612: void
        !           613: write_cio(int reg, u_int val)
        !           614: {
        !           615:        int s;
        !           616:        volatile int i;
        !           617:        volatile u_int32_t * cio_ctrl = (volatile u_int32_t *)CIO_CTRL;
        !           618:
        !           619:        s = splclock();
        !           620:        CIO_LOCK;
        !           621:
        !           622:        i = *cio_ctrl;                          /* goto state 1 */
        !           623:        *cio_ctrl = 0;                          /* take CIO out of RESET */
        !           624:        i = *cio_ctrl;                          /* reset CIO state machine */
        !           625:
        !           626:        *cio_ctrl = (reg & 0xff);               /* select register */
        !           627:        *cio_ctrl = (val & 0xff);               /* write the value */
        !           628:
        !           629:        CIO_UNLOCK;
        !           630:        splx(s);
        !           631: }
        !           632:
        !           633: /* Read CIO register */
        !           634: u_int
        !           635: read_cio(int reg)
        !           636: {
        !           637:        int c, s;
        !           638:        volatile int i;
        !           639:        volatile u_int32_t * cio_ctrl = (volatile u_int32_t *)CIO_CTRL;
        !           640:
        !           641:        s = splclock();
        !           642:        CIO_LOCK;
        !           643:
        !           644:        /* select register */
        !           645:        *cio_ctrl = (reg & 0xff);
        !           646:        /* delay for a short time to allow 8536 to settle */
        !           647:        for (i = 0; i < 100; i++)
        !           648:                ;
        !           649:        /* read the value */
        !           650:        c = *cio_ctrl;
        !           651:        CIO_UNLOCK;
        !           652:        splx(s);
        !           653:        return (c & 0xff);
        !           654: }
        !           655:
        !           656: /*
        !           657:  * Initialize the CTC (8536)
        !           658:  * Only the counter/timers are used - the IO ports are un-comitted.
        !           659:  */
        !           660: void
        !           661: av400_cio_init(unsigned period)
        !           662: {
        !           663:        volatile int i;
        !           664:
        !           665:        CIO_LOCK;
        !           666:
        !           667:        /* Start by forcing chip into known state */
        !           668:        read_cio(CIO_MICR);
        !           669:        write_cio(CIO_MICR, CIO_MICR_RESET);    /* Reset the CTC */
        !           670:        for (i = 0; i < 1000; i++)              /* Loop to delay */
        !           671:                ;
        !           672:
        !           673:        /* Clear reset and start init seq. */
        !           674:        write_cio(CIO_MICR, 0x00);
        !           675:
        !           676:        /* Wait for chip to come ready */
        !           677:        while ((read_cio(CIO_MICR) & CIO_MICR_RJA) == 0)
        !           678:                ;
        !           679:
        !           680:        /* Initialize the 8536 for real */
        !           681:        write_cio(CIO_MICR,
        !           682:            CIO_MICR_MIE /* | CIO_MICR_NV */ | CIO_MICR_RJA | CIO_MICR_DLC);
        !           683:        write_cio(CIO_CTMS1, CIO_CTMS_CSC);     /* Continuous count */
        !           684:        write_cio(CIO_PDCB, 0xff);              /* set port B to input */
        !           685:
        !           686:        period <<= 1;   /* CT#1 runs at PCLK/2, hence 2MHz */
        !           687:        write_cio(CIO_CT1MSB, period >> 8);
        !           688:        write_cio(CIO_CT1LSB, period);
        !           689:        /* enable counter #1 */
        !           690:        write_cio(CIO_MCCR, CIO_MCCR_CT1E | CIO_MCCR_PBE);
        !           691:        write_cio(CIO_CSR1, CIO_GCB | CIO_TCB | CIO_IE);
        !           692:
        !           693:        CIO_UNLOCK;
        !           694: }

CVSweb