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