[BACK]Return to pcc.c CVS log [TXT][DIR] Up to [local] / sys / arch / mvme68k / dev

Annotation of sys/arch/mvme68k/dev/pcc.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: pcc.c,v 1.15 2005/11/24 22:43:16 miod Exp $ */
                      2:
                      3: /*
                      4:  * Copyright (c) 1995 Theo de Raadt
                      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 BE LIABLE FOR ANY DIRECT, INDIRECT,
                     20:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     21:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     22:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     23:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     24:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     25:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     26:  */
                     27:
                     28: /*
                     29:  * VME147 peripheral channel controller
                     30:  */
                     31: #include <sys/param.h>
                     32: #include <sys/conf.h>
                     33: #include <sys/ioctl.h>
                     34: #include <sys/proc.h>
                     35: #include <sys/user.h>
                     36: #include <sys/tty.h>
                     37: #include <sys/uio.h>
                     38: #include <sys/systm.h>
                     39: #include <sys/kernel.h>
                     40: #include <sys/syslog.h>
                     41: #include <sys/fcntl.h>
                     42: #include <sys/device.h>
                     43: #include <machine/cpu.h>
                     44: #include <machine/autoconf.h>
                     45: #include <dev/cons.h>
                     46:
                     47: #include <mvme68k/dev/pccreg.h>
                     48:
                     49: struct pccsoftc {
                     50:        struct device   sc_dev;
                     51:        vaddr_t         sc_vaddr;
                     52:        paddr_t         sc_paddr;
                     53:        struct pccreg   *sc_pcc;
                     54:        struct intrhand sc_nmiih;
                     55: };
                     56:
                     57: void pccattach(struct device *, struct device *, void *);
                     58: int  pccmatch(struct device *, void *, void *);
                     59: int  pccabort(void *);
                     60: int  pcc_print(void *, const char *);
                     61: int  pcc_scan(struct device *, void *, void *);
                     62:
                     63: struct cfattach pcc_ca = {
                     64:        sizeof(struct pccsoftc), pccmatch, pccattach
                     65: };
                     66:
                     67: struct cfdriver pcc_cd = {
                     68:        NULL, "pcc", DV_DULL
                     69: };
                     70:
                     71: struct pccreg *sys_pcc = NULL;
                     72:
                     73: int
                     74: pccmatch(parent, vcf, args)
                     75:        struct device *parent;
                     76:        void *vcf, *args;
                     77: {
                     78:        struct confargs *ca = args;
                     79:
                     80:        /* the pcc only exist on vme147's */
                     81:        if (cputyp != CPU_147)
                     82:                return (0);
                     83:        return (!badvaddr(IIOV(ca->ca_paddr) + PCCSPACE_PCCCHIP_OFF, 1));
                     84: }
                     85:
                     86: int
                     87: pcc_print(args, bus)
                     88:        void *args;
                     89:        const char *bus;
                     90: {
                     91:        struct confargs *ca = args;
                     92:
                     93:        if (ca->ca_offset != -1)
                     94:                printf(" offset 0x%x", ca->ca_offset);
                     95:        if (ca->ca_ipl > 0)
                     96:                printf(" ipl %d", ca->ca_ipl);
                     97:        return (UNCONF);
                     98: }
                     99:
                    100: int
                    101: pcc_scan(parent, child, args)
                    102:        struct device *parent;
                    103:        void *child, *args;
                    104: {
                    105:        struct cfdata *cf = child;
                    106:        struct pccsoftc *sc = (struct pccsoftc *)parent;
                    107:        struct confargs oca;
                    108:
                    109:        bzero(&oca, sizeof oca);
                    110:        oca.ca_offset = cf->cf_loc[0];
                    111:        oca.ca_ipl = cf->cf_loc[1];
                    112:        if (oca.ca_offset != -1) {
                    113:                oca.ca_vaddr = sc->sc_vaddr + oca.ca_offset;
                    114:                oca.ca_paddr = sc->sc_paddr + oca.ca_offset;
                    115:        } else {
                    116:                oca.ca_vaddr = (vaddr_t)-1;
                    117:                oca.ca_paddr = (paddr_t)-1;
                    118:        }
                    119:        oca.ca_bustype = BUS_PCC;
                    120:        oca.ca_name = cf->cf_driver->cd_name;
                    121:        if ((*cf->cf_attach->ca_match)(parent, cf, &oca) == 0)
                    122:                return (0);
                    123:        config_attach(parent, cf, &oca, pcc_print);
                    124:        return (1);
                    125: }
                    126:
                    127: void
                    128: pccattach(parent, self, args)
                    129:        struct device *parent, *self;
                    130:        void *args;
                    131: {
                    132:        struct confargs *ca = args;
                    133:        struct pccsoftc *sc = (struct pccsoftc *)self;
                    134:
                    135:        if (sys_pcc)
                    136:                panic("pcc already attached!");
                    137:
                    138:        /*
                    139:         * since we know ourself to land in intiobase land,
                    140:         * we must adjust our address
                    141:         */
                    142:        sc->sc_paddr = ca->ca_paddr;
                    143:        sc->sc_vaddr = IIOV(sc->sc_paddr);
                    144:        sc->sc_pcc = (struct pccreg *)(sc->sc_vaddr + PCCSPACE_PCCCHIP_OFF);
                    145:        sys_pcc = sc->sc_pcc;
                    146:
                    147:        printf(": rev %d\n", sc->sc_pcc->pcc_chiprev);
                    148:
                    149:        sc->sc_nmiih.ih_fn = pccabort;
                    150:        sc->sc_nmiih.ih_ipl = 7;
                    151:        sc->sc_nmiih.ih_wantframe = 1;
                    152:        pccintr_establish(PCCV_ABORT, &sc->sc_nmiih, self->dv_xname);
                    153:
                    154:        sc->sc_pcc->pcc_vecbase = PCC_VECBASE;
                    155:        sc->sc_pcc->pcc_abortirq = PCC_ABORT_IEN | PCC_ABORT_ACK;
                    156:        sc->sc_pcc->pcc_genctl |= PCC_GENCTL_IEN;
                    157:
                    158:        /* XXX further init of PCC chip? */
                    159:
                    160:        config_search(pcc_scan, self, args);
                    161: }
                    162:
                    163: /*
                    164:  * PCC interrupts land in a PCC_NVEC sized hole starting at PCC_VECBASE
                    165:  */
                    166: int
                    167: pccintr_establish(vec, ih, name)
                    168:        int vec;
                    169:        struct intrhand *ih;
                    170:        const char *name;
                    171: {
                    172: #ifdef DIAGNOSTIC
                    173:        if (vec < 0 || vec >= PCC_NVEC)
                    174:                panic("pccintr_establish: illegal vector for %s: 0x%x",
                    175:                    name, vec);
                    176: #endif
                    177:
                    178:        return intr_establish(PCC_VECBASE + vec, ih, name);
                    179: }
                    180:
                    181: int
                    182: pccabort(frame)
                    183:        void *frame;
                    184: {
                    185: #if 0
                    186:        /* XXX wait for it to debounce -- there is something wrong here */
                    187:        while (sys_pcc->pcc_abortirq & PCC_ABORT_ABS)
                    188:                ;
                    189:        delay(2);
                    190: #endif
                    191:        sys_pcc->pcc_abortirq = PCC_ABORT_IEN | PCC_ABORT_ACK;
                    192:        nmihand(frame);
                    193:        return (1);
                    194: }
                    195:
                    196: int
                    197: pccspeed(pcc)
                    198:        struct pccreg *pcc;
                    199: {
                    200:        volatile u_short lim = pcc_timer_us2lim(400);
                    201:        volatile u_short tmp;
                    202:        volatile int cnt;
                    203:        int speed;
                    204:
                    205:        pcc->pcc_t1irq = 0;             /* just in case */
                    206:        pcc->pcc_t1pload = 0;
                    207:        pcc->pcc_t1ctl = PCC_TIMERCLEAR;
                    208:        pcc->pcc_t1ctl = PCC_TIMERSTART;
                    209:
                    210:        cnt = 0;
                    211:        for (;;) {
                    212:                tmp = pcc->pcc_t1count;
                    213:                if (tmp > lim)
                    214:                        break;
                    215:                tmp = lim;
                    216:                cnt++;
                    217:        }
                    218:
                    219:        pcc->pcc_t1ctl = PCC_TIMERCLEAR;
                    220:        printf("pccspeed cnt=%d\n", cnt);
                    221:
                    222:        /*
                    223:         * Empirically determined. Unfortunately, because of various
                    224:         * memory board effects and such, it is rather unlikely that
                    225:         * we will find a nice formula.
                    226:         */
                    227:        if (cnt > 230000)
                    228:                speed = 50;
                    229:        else if (cnt > 210000)
                    230:                speed = 33;
                    231:        else if (cnt > 190000)
                    232:                speed = 25;
                    233:        else if (cnt > 170000)  /* 171163, 170335 */
                    234:                speed = 20;
                    235:        else
                    236:                speed = 16;
                    237:        return (speed);
                    238: }

CVSweb