Annotation of sys/arch/mvme68k/dev/pcc.c, Revision 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