Annotation of sys/arch/vax/vax/ka820.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ka820.c,v 1.12 2003/11/10 21:05:06 miod Exp $ */
2: /* $NetBSD: ka820.c,v 1.22 2000/06/04 02:19:27 matt Exp $ */
3: /*
4: * Copyright (c) 1988 Regents of the University of California.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to Berkeley by
8: * Chris Torek.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. Neither the name of the University nor the names of its contributors
19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: *
34: * @(#)ka820.c 7.4 (Berkeley) 12/16/90
35: */
36:
37: /*
38: * KA820 specific CPU code. (Note that the VAX8200 uses a KA820, not
39: * a KA8200. Sigh.)
40: */
41:
42: #include <sys/param.h>
43: #include <sys/time.h>
44: #include <sys/kernel.h>
45: #include <sys/device.h>
46: #include <sys/systm.h>
47:
48: #include <uvm/uvm_extern.h>
49:
50: #include <machine/ka820.h>
51: #include <machine/cpu.h>
52: #include <machine/mtpr.h>
53: #include <machine/nexus.h>
54: #include <machine/clock.h>
55: #include <machine/scb.h>
56: #include <machine/bus.h>
57:
58: #include <vax/bi/bireg.h>
59: #include <vax/bi/bivar.h>
60:
61: #include <vax/vax/crx.h>
62:
63: struct ka820port *ka820port_ptr;
64: struct rx50device *rx50device_ptr;
65: static volatile struct ka820clock *ka820_clkpage;
66:
67: static int ka820_match(struct device *, struct cfdata *, void *);
68: static void ka820_attach(struct device *, struct device *, void *);
69: static void ka820_memerr(void);
70: static void ka820_conf(void);
71: static int ka820_mchk(caddr_t);
72: static int ka820_clkread(time_t base);
73: static void ka820_clkwrite(void);
74: static void rxcdintr(void *);
75: static void vaxbierr(void *);
76:
77: struct cpu_dep ka820_calls = {
78: 0,
79: ka820_mchk,
80: ka820_memerr,
81: ka820_conf,
82: ka820_clkread,
83: ka820_clkwrite,
84: 3, /* ~VUPS */
85: 5, /* SCB pages */
86: };
87:
88: struct cfattach cpu_bi_ca = {
89: sizeof(struct device), ka820_match, ka820_attach
90: };
91:
92: #ifdef notyet
93: extern pt_entry_t BRAMmap[];
94: extern pt_entry_t EEPROMmap[];
95: char bootram[KA820_BRPAGES * VAX_NBPG];
96: char eeprom[KA820_EEPAGES * VAX_NBPG];
97: #endif
98:
99: int
100: ka820_match(parent, cf, aux)
101: struct device *parent;
102: struct cfdata *cf;
103: void *aux;
104: {
105: struct bi_attach_args *ba = aux;
106:
107: if (bus_space_read_2(ba->ba_iot, ba->ba_ioh, BIREG_DTYPE) != BIDT_KA820)
108: return 0;
109:
110: if (ba->ba_nodenr != mastercpu)
111: return 0;
112:
113: if (cf->cf_loc[BICF_NODE] != BICF_NODE_DEFAULT &&
114: cf->cf_loc[BICF_NODE] != ba->ba_nodenr)
115: return 0;
116:
117: return 1;
118: }
119:
120: void
121: ka820_attach(parent, self, aux)
122: struct device *parent, *self;
123: void *aux;
124: {
125: struct bi_attach_args *ba = aux;
126: register int csr;
127: u_short rev;
128:
129: rev = bus_space_read_4(ba->ba_iot, ba->ba_ioh, BIREG_DTYPE) >> 16;
130: strlcpy(cpu_model, "VAX 8200", sizeof cpu_model);
131: cpu_model[6] = rev & 0x8000 ? '5' : '0';
132: printf(": ka82%c (%s) cpu rev %d, u patch rev %d, sec patch %d\n",
133: cpu_model[6], mastercpu == ba->ba_nodenr ? "master" : "slave",
134: ((rev >> 11) & 15), ((rev >> 1) &1023), rev & 1);
135:
136: /* reset the console and enable the RX50 */
137: ka820port_ptr = (void *)vax_map_physmem(KA820_PORTADDR, 1);
138: csr = ka820port_ptr->csr;
139: csr &= ~KA820PORT_RSTHALT; /* ??? */
140: csr |= KA820PORT_CONSCLR | KA820PORT_CRDCLR | KA820PORT_CONSEN |
141: KA820PORT_RXIE;
142: ka820port_ptr->csr = csr;
143: bus_space_write_4(ba->ba_iot, ba->ba_ioh,
144: BIREG_INTRDES, ba->ba_intcpu);
145: bus_space_write_4(ba->ba_iot, ba->ba_ioh, BIREG_VAXBICSR,
146: bus_space_read_4(ba->ba_iot, ba->ba_ioh, BIREG_VAXBICSR) |
147: BICSR_SEIE | BICSR_HEIE);
148:
149: }
150:
151: void
152: ka820_conf()
153: {
154: /*
155: * Setup parameters necessary to read time from clock chip.
156: */
157: ka820_clkpage = (void *)vax_map_physmem(KA820_CLOCKADDR, 1);
158:
159: /* Steal the interrupt vectors that are unique for us */
160: scb_vecalloc(KA820_INT_RXCD, rxcdintr, NULL, SCB_ISTACK, NULL);
161: scb_vecalloc(0x50, vaxbierr, NULL, SCB_ISTACK, NULL);
162:
163: /* XXX - should be done somewhere else */
164: scb_vecalloc(SCB_RX50, crxintr, NULL, SCB_ISTACK, NULL);
165: rx50device_ptr = (void *)vax_map_physmem(KA820_RX50ADDR, 1);
166: }
167:
168: void
169: vaxbierr(void *arg)
170: {
171: if (cold == 0)
172: panic("vaxbierr");
173: }
174:
175: #ifdef notdef
176: /*
177: * MS820 support.
178: */
179: struct ms820regs {
180: struct biiregs biic; /* BI interface chip */
181: u_long ms_gpr[4]; /* the four gprs (unused) */
182: int ms_csr1; /* control/status register 1 */
183: int ms_csr2; /* control/status register 2 */
184: };
185: #endif
186:
187: #define MEMRD(reg) bus_space_read_4(sc->sc_iot, sc->sc_ioh, (reg))
188: #define MEMWR(reg, val) bus_space_write_4(sc->sc_iot, sc->sc_ioh, (reg), (val))
189:
190: #define MSREG_CSR1 0x100
191: #define MSREG_CSR2 0x104
192: /*
193: * Bits in CSR1.
194: */
195: #define MS1_ERRSUM 0x80000000 /* error summary (ro) */
196: #define MS1_ECCDIAG 0x40000000 /* ecc diagnostic (rw) */
197: #define MS1_ECCDISABLE 0x20000000 /* ecc disable (rw) */
198: #define MS1_MSIZEMASK 0x1ffc0000 /* mask for memory size (ro) */
199: #define MS1_RAMTYMASK 0x00030000 /* mask for ram type (ro) */
200: #define MS1_RAMTY64K 0x00000000 /* 64K chips */
201: #define MS1_RAMTY256K 0x00010000 /* 256K chips */
202: #define MS1_RAMTY1MB 0x00020000 /* 1MB chips */
203: /* type 3 reserved */
204: #define MS1_CRDINH 0x00008000 /* inhibit crd interrupts (rw) */
205: #define MS1_MEMVALID 0x00004000 /* memory has been written (ro) */
206: #define MS1_INTLK 0x00002000 /* interlock flag (ro) */
207: #define MS1_BROKE 0x00001000 /* broken (rw) */
208: #define MS1_MBZ 0x00000880 /* zero */
209: #define MS1_MWRITEERR 0x00000400 /* rds during masked write (rw) */
210: #define MS1_CNTLERR 0x00000200 /* internal timing busted (rw) */
211: #define MS1_INTLV 0x00000100 /* internally interleaved (ro) */
212: #define MS1_DIAGC 0x0000007f /* ecc diagnostic bits (rw) */
213:
214: /*
215: * Bits in CSR2.
216: */
217: #define MS2_RDSERR 0x80000000 /* rds error (rw) */
218: #define MS2_HIERR 0x40000000 /* high error rate (rw) */
219: #define MS2_CRDERR 0x20000000 /* crd error (rw) */
220: #define MS2_ADRSERR 0x10000000 /* rds due to addr par err (rw) */
221: #define MS2_MBZ 0x0f000080 /* zero */
222: #define MS2_ADDR 0x00fffe00 /* address in error (relative) (ro) */
223: #define MS2_INTLVADDR 0x00000100 /* error was in bank 1 (ro) */
224: #define MS2_SYN 0x0000007f /* error syndrome (ro, rw diag) */
225:
226: static int ms820_match(struct device *, struct cfdata *, void *);
227: static void ms820_attach(struct device *, struct device *, void *);
228:
229: struct mem_bi_softc {
230: struct device sc_dev;
231: bus_space_tag_t sc_iot;
232: bus_space_handle_t sc_ioh;
233: };
234:
235: struct cfattach mem_bi_ca = {
236: sizeof(struct mem_bi_softc), ms820_match, ms820_attach
237: };
238:
239: static int
240: ms820_match(parent, cf, aux)
241: struct device *parent;
242: struct cfdata *cf;
243: void *aux;
244: {
245: struct bi_attach_args *ba = aux;
246:
247: if (bus_space_read_2(ba->ba_iot, ba->ba_ioh, BIREG_DTYPE) != BIDT_MS820)
248: return 0;
249:
250: if (cf->cf_loc[BICF_NODE] != BICF_NODE_DEFAULT &&
251: cf->cf_loc[BICF_NODE] != ba->ba_nodenr)
252: return 0;
253:
254: return 1;
255: }
256:
257: static void
258: ms820_attach(parent, self, aux)
259: struct device *parent, *self;
260: void *aux;
261: {
262: struct mem_bi_softc *sc = (void *)self;
263: struct bi_attach_args *ba = aux;
264:
265: sc->sc_iot = ba->ba_iot;
266: sc->sc_ioh = ba->ba_ioh;
267:
268: if ((MEMRD(BIREG_VAXBICSR) & BICSR_STS) == 0)
269: printf(": failed self test\n");
270: else
271: printf(": size %dMB, %s chips\n", ((MEMRD(MSREG_CSR1) &
272: MS1_MSIZEMASK) >> 20), (MEMRD(MSREG_CSR1) & MS1_RAMTYMASK
273: ? MEMRD(MSREG_CSR1) & MS1_RAMTY256K ? "256K":"1M":"64K"));
274:
275: MEMWR(BIREG_INTRDES, ba->ba_intcpu);
276: MEMWR(BIREG_VAXBICSR, MEMRD(BIREG_VAXBICSR) | BICSR_SEIE | BICSR_HEIE);
277:
278: MEMWR(MSREG_CSR1, MS1_MWRITEERR | MS1_CNTLERR);
279: MEMWR(MSREG_CSR2, MS2_RDSERR | MS2_HIERR | MS2_CRDERR | MS2_ADRSERR);
280: }
281:
282: void
283: ka820_memerr()
284: {
285: struct mem_bi_softc *sc;
286: int m, hard, csr1, csr2;
287: char *type;
288: static char b1[] = "\20\40ERRSUM\37ECCDIAG\36ECCDISABLE\20CRDINH\17VALID\
289: \16INTLK\15BROKE\13MWRITEERR\12CNTLERR\11INTLV";
290: static char b2[] = "\20\40RDS\37HIERR\36CRD\35ADRS";
291:
292: for (m = 0; m < mem_cd.cd_ndevs; m++) {
293: sc = mem_cd.cd_devs[m];
294: if (sc == NULL)
295: continue;
296: csr1 = MEMRD(MSREG_CSR1);
297: csr2 = MEMRD(MSREG_CSR2);
298: printf("%s: csr1=%b csr2=%b\n", sc->sc_dev.dv_xname,
299: csr1, b1, csr2, b2);
300: if ((csr1 & MS1_ERRSUM) == 0)
301: continue;
302: hard = 1;
303: if (csr1 & MS1_BROKE)
304: type = "broke";
305: else if (csr1 & MS1_CNTLERR)
306: type = "cntl err";
307: else if (csr2 & MS2_ADRSERR)
308: type = "address parity err";
309: else if (csr2 & MS2_RDSERR)
310: type = "rds err";
311: else if (csr2 & MS2_CRDERR) {
312: hard = 0;
313: type = "";
314: } else
315: type = "mysterious error";
316: printf("%s: %s%s%s addr %x bank %x syn %x\n",
317: sc->sc_dev.dv_xname, hard ? "hard error: " : "soft ecc",
318: type, csr2 & MS2_HIERR ? " (+ other rds or crd err)" : "",
319: ((csr2 & MS2_ADDR) + MEMRD(BIREG_SADR)) >> 9,
320: (csr2 & MS2_INTLVADDR) != 0, csr2 & MS2_SYN);
321: MEMWR(MSREG_CSR1, csr1 | MS1_CRDINH);
322: MEMWR(MSREG_CSR2, csr2);
323: }
324: }
325:
326: /* these are bits 0 to 6 in the summary field */
327: char *mc8200[] = {
328: "cpu bad ipl", "ucode lost err",
329: "ucode par err", "DAL par err",
330: "BI bus err", "BTB tag par",
331: "cache tag par",
332: };
333: #define MC8200_BADIPL 0x01
334: #define MC8200_UERR 0x02
335: #define MC8200_UPAR 0x04
336: #define MC8200_DPAR 0x08
337: #define MC8200_BIERR 0x10
338: #define MC8200_BTAGPAR 0x20
339: #define MC8200_CTAGPAR 0x40
340:
341: struct mc8200frame {
342: int mc82_bcnt; /* byte count == 0x20 */
343: int mc82_summary; /* summary parameter */
344: int mc82_param1; /* parameter 1 */
345: int mc82_va; /* va register */
346: int mc82_vap; /* va prime register */
347: int mc82_ma; /* memory address */
348: int mc82_status; /* status word */
349: int mc82_epc; /* error pc */
350: int mc82_upc; /* micro pc */
351: int mc82_pc; /* current pc */
352: int mc82_psl; /* current psl */
353: };
354:
355: int
356: ka820_mchk(cmcf)
357: caddr_t cmcf;
358: {
359: register struct mc8200frame *mcf = (struct mc8200frame *)cmcf;
360: register int i, type = mcf->mc82_summary;
361:
362: /* ignore BI bus errors during configuration */
363: if (cold && type == MC8200_BIERR) {
364: mtpr(PR_MCESR, 0xf);
365: return (MCHK_RECOVERED);
366: }
367:
368: /*
369: * SOME ERRORS ARE RECOVERABLE
370: * do it later
371: */
372: printf("machine check %x: ", type);
373: for (i = 0; i < sizeof (mc8200) / sizeof (mc8200[0]); i++)
374: if (type & (1 << i))
375: printf(" %s,", mc8200[i]);
376: printf(" param1 %x\n", mcf->mc82_param1);
377: printf(
378: "\tva %x va' %x ma %x pc %x psl %x\n\tstatus %x errpc %x upc %x\n",
379: mcf->mc82_va, mcf->mc82_vap, mcf->mc82_ma,
380: mcf->mc82_pc, mcf->mc82_psl,
381: mcf->mc82_status, mcf->mc82_epc, mcf->mc82_upc);
382: return (MCHK_PANIC);
383: }
384:
385: /*
386: * Receive a character from logical console.
387: */
388: void
389: rxcdintr(arg)
390: void *arg;
391: {
392: register int c = mfpr(PR_RXCD);
393:
394: /* not sure what (if anything) to do with these */
395: printf("rxcd node %x c=0x%x\n", (c >> 8) & 0xf, c & 0xff);
396: }
397:
398: int
399: ka820_clkread(time_t base)
400: {
401: struct clock_ymdhms c;
402: int s;
403:
404: while (ka820_clkpage->csr0 & KA820CLK_0_BUSY)
405: ;
406: s = splhigh();
407: c.dt_sec = ka820_clkpage->sec;
408: c.dt_min = ka820_clkpage->min;
409: c.dt_hour = ka820_clkpage->hr;
410: c.dt_wday = ka820_clkpage->dayofwk;
411: c.dt_day = ka820_clkpage->day;
412: c.dt_mon = ka820_clkpage->mon;
413: c.dt_year = ka820_clkpage->yr;
414: splx(s);
415:
416: /* strange conversion */
417: c.dt_sec = ((c.dt_sec << 7) | (c.dt_sec >> 1)) & 0377;
418: c.dt_min = ((c.dt_min << 7) | (c.dt_min >> 1)) & 0377;
419: c.dt_hour = ((c.dt_hour << 7) | (c.dt_hour >> 1)) & 0377;
420: c.dt_wday = ((c.dt_wday << 7) | (c.dt_wday >> 1)) & 0377;
421: c.dt_day = ((c.dt_day << 7) | (c.dt_day >> 1)) & 0377;
422: c.dt_mon = ((c.dt_mon << 7) | (c.dt_mon >> 1)) & 0377;
423: c.dt_year = ((c.dt_year << 7) | (c.dt_year >> 1)) & 0377;
424:
425: time.tv_sec = clock_ymdhms_to_secs(&c);
426: return CLKREAD_OK;
427: }
428:
429: void
430: ka820_clkwrite(void)
431: {
432: struct clock_ymdhms c;
433:
434: clock_secs_to_ymdhms(time.tv_sec, &c);
435:
436: ka820_clkpage->csr1 = KA820CLK_1_SET;
437: ka820_clkpage->sec = ((c.dt_sec << 1) | (c.dt_sec >> 7)) & 0377;
438: ka820_clkpage->min = ((c.dt_min << 1) | (c.dt_min >> 7)) & 0377;
439: ka820_clkpage->hr = ((c.dt_hour << 1) | (c.dt_hour >> 7)) & 0377;
440: ka820_clkpage->dayofwk = ((c.dt_wday << 1) | (c.dt_wday >> 7)) & 0377;
441: ka820_clkpage->day = ((c.dt_day << 1) | (c.dt_day >> 7)) & 0377;
442: ka820_clkpage->mon = ((c.dt_mon << 1) | (c.dt_mon >> 7)) & 0377;
443: ka820_clkpage->yr = ((c.dt_year << 1) | (c.dt_year >> 7)) & 0377;
444:
445: ka820_clkpage->csr1 = KA820CLK_1_GO;
446: }
CVSweb