|
|
BSD 4.3tahoe
/*
* Copyright (c) 1988 Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Chris Torek.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* @(#)ka820.c 7.2 (Berkeley) 7/9/88
*/
#if VAX8200
/*
* KA820 specific CPU code. (Note that the VAX8200 uses a KA820, not
* a KA8200. Sigh.)
*/
#include "param.h"
#include "time.h"
#include "kernel.h"
#include "vmmac.h"
#include "cpu.h"
#include "clock.h"
#include "ka820.h"
#include "mem.h"
#include "mtpr.h"
#include "pte.h"
#include "../vaxbi/bireg.h"
extern struct pte Clockmap[];
extern struct pte RX50map[];
extern struct pte Ka820map[];
struct ka820clock ka820clock;
struct ka820port ka820port;
#ifdef notyet
extern struct pte BRAMmap[];
extern struct pte EEPROMmap[];
char bootram[KA820_BRPAGES * NBPG];
char eeprom[KA820_EEPAGES * NBPG];
#endif
ka820_init()
{
register int csr;
/* map in the various devices */
*(int *)&Ka820map[0] = PG_V|PG_KW|btop(KA820_PORTADDR);
*(int *)&RX50map[0] = PG_V|PG_KW|btop(KA820_RX50ADDR);
*(int *)&Clockmap[0] = PG_V|PG_KW|btop(KA820_CLOCKADDR);
#ifdef notyet
ioaccess(bootram, BRAMmap, KA820_BRPAGES * NBPG);
ioaccess(eeprom, EEPROMmap, KA820_EEPAGES * NBPG);
#else
mtpr(TBIA, 0);
#endif
/* reset the console and enable the RX50 */
csr = ka820port.csr;
csr &= ~KA820PORT_RSTHALT; /* ??? */
csr |= KA820PORT_CONSCLR | KA820PORT_CRDCLR | KA820PORT_CONSEN |
KA820PORT_RXIE;
ka820port.csr = csr;
}
/* Set system time from clock */
/* ARGSUSED */
ka820_clkread(base)
time_t base;
{
register struct ka820clock *clock = &ka820clock;
struct chiptime c;
int s, rv;
rv = CLKREAD_OK;
/* I wish I knew the differences between these */
if ((clock->csr3 & KA820CLK_3_VALID) == 0) {
printf("WARNING: TOY clock not marked valid\n");
rv = CLKREAD_WARN;
}
if ((clock->csr1 & KA820CLK_1_GO) != KA820CLK_1_GO) {
printf("WARNING: TOY clock stopped\n");
rv = CLKREAD_WARN;
}
/* THIS IS NOT RIGHT (clock may change on us) */
s = splhigh();
while (clock->csr0 & KA820CLK_0_BUSY)
/* void */;
c.sec = clock->sec;
c.min = clock->min;
c.hour = clock->hr;
c.day = clock->day;
c.mon = clock->mon;
c.year = clock->yr;
splx(s);
/* the darn thing needs tweaking! */
c.sec >>= 1; /* tweak */
c.min >>= 1; /* tweak */
c.hour >>= 1; /* tweak */
c.day >>= 1; /* tweak */
c.mon >>= 1; /* tweak */
c.year >>= 1; /* tweak */
time.tv_sec = chiptotime(&c);
return (time.tv_sec ? rv : CLKREAD_BAD);
}
/* store time into clock */
ka820_clkwrite()
{
register struct ka820clock *clock = &ka820clock;
struct chiptime c;
int s;
timetochip(&c);
/* play it again, sam (or mike or kirk or ...) */
c.sec <<= 1; /* tweak */
c.min <<= 1; /* tweak */
c.hour <<= 1; /* tweak */
c.day <<= 1; /* tweak */
c.mon <<= 1; /* tweak */
c.year <<= 1; /* tweak */
s = splhigh();
clock->csr1 = KA820CLK_1_SET;
while (clock->csr0 & KA820CLK_0_BUSY)
/* void */;
clock->sec = c.sec;
clock->min = c.min;
clock->hr = c.hour;
clock->day = c.day;
clock->mon = c.mon;
clock->yr = c.year;
/* should we set a `rate'? */
clock->csr1 = KA820CLK_1_GO;
splx(s);
}
/*
* MS820 support.
*/
struct ms820regs {
struct biiregs biic; /* BI interface chip */
u_long ms_gpr[4]; /* the four gprs (unused) */
int ms_csr1; /* control/status register 1 */
int ms_csr2; /* control/status register 2 */
};
/*
* Bits in CSR1.
*/
#define MS1_ERRSUM 0x80000000 /* error summary (ro) */
#define MS1_ECCDIAG 0x40000000 /* ecc diagnostic (rw) */
#define MS1_ECCDISABLE 0x20000000 /* ecc disable (rw) */
#define MS1_MSIZEMASK 0x1ffc0000 /* mask for memory size (ro) */
#define MS1_RAMTYMASK 0x00030000 /* mask for ram type (ro) */
#define MS1_RAMTY64K 0x00000000 /* 64K chips */
#define MS1_RAMTY256K 0x00010000 /* 256K chips */
/* types 2 and 3 reserved */
#define MS1_CRDINH 0x00008000 /* inhibit crd interrupts (rw) */
#define MS1_MEMVALID 0x00004000 /* memory has been written (ro) */
#define MS1_INTLK 0x00002000 /* interlock flag (ro) */
#define MS1_BROKE 0x00001000 /* broken (rw) */
#define MS1_MBZ 0x00000880 /* zero */
#define MS1_MWRITEERR 0x00000400 /* rds during masked write (rw) */
#define MS1_CNTLERR 0x00000200 /* internal timing busted (rw) */
#define MS1_INTLV 0x00000100 /* internally interleaved (ro) */
#define MS1_DIAGC 0x0000007f /* ecc diagnostic bits (rw) */
/*
* Bits in CSR2.
*/
#define MS2_RDSERR 0x80000000 /* rds error (rw) */
#define MS2_HIERR 0x40000000 /* high error rate (rw) */
#define MS2_CRDERR 0x20000000 /* crd error (rw) */
#define MS2_ADRSERR 0x10000000 /* rds due to addr par err (rw) */
#define MS2_MBZ 0x0f000080 /* zero */
#define MS2_ADDR 0x00fffe00 /* address in error (relative) (ro) */
#define MS2_INTLVADDR 0x00000100 /* error was in bank 1 (ro) */
#define MS2_SYN 0x0000007f /* error syndrome (ro, rw diag) */
ka820_memenable()
{
register struct ms820regs *mcr;
register int m;
for (m = 0; m < nmcr; m++) {
mcr = (struct ms820regs *)mcraddr[m];
/*
* This will be noisy. Should we do anything
* about that?
*/
if ((mcr->biic.bi_csr & BICSR_STS) == 0)
printf("mcr%d: failed self test\n", m);
else {
mcr->ms_csr1 = MS1_MWRITEERR | MS1_CNTLERR;
mcr->ms_csr2 = MS2_RDSERR | MS2_HIERR |
MS2_CRDERR | MS2_ADRSERR;
}
}
}
ka820_memerr()
{
register struct ms820regs *mcr;
register int m, hard;
register char *type;
static char b1[] = "\20\40ERRSUM\37ECCDIAG\36ECCDISABLE\20CRDINH\17VALID\
\16INTLK\15BROKE\13MWRITEERR\12CNTLERR\11INTLV";
static char b2[] = "\20\40RDS\37HIERR\36CRD\35ADRS";
for (m = 0; m < nmcr; m++) {
mcr = (struct ms820regs *)mcraddr[m];
printf("mcr%d: csr1=%b csr2=%b\n", m, mcr->ms_csr1, b1, mcr->ms_csr2, b2);
if ((mcr->ms_csr1 & MS1_ERRSUM) == 0)
continue;
hard = 1;
if (mcr->ms_csr1 & MS1_BROKE)
type = "broke";
else if (mcr->ms_csr1 & MS1_CNTLERR)
type = "cntl err";
else if (mcr->ms_csr2 & MS2_ADRSERR)
type = "address parity err";
else if (mcr->ms_csr2 & MS2_RDSERR)
type = "rds err";
else if (mcr->ms_csr2 & MS2_CRDERR) {
hard = 0;
type = "";
} else
type = "mysterious error";
printf("mcr%d: %s%s%s addr %x bank %x syn %x\n", m,
hard ? "hard error: " : "soft ecc",
type, mcr->ms_csr2 & MS2_HIERR ?
" (+ other rds or crd err)" : "",
((mcr->ms_csr2 & MS2_ADDR) + mcr->biic.bi_sadr) >> 9,
(mcr->ms_csr2 & MS2_INTLVADDR) != 0,
mcr->ms_csr2 & MS2_SYN);
mcr->ms_csr1 = mcr->ms_csr1 | MS1_CRDINH;
mcr->ms_csr2 = mcr->ms_csr2;
}
}
/* these are bits 0 to 6 in the summary field */
char *mc8200[] = {
"cpu bad ipl", "ucode lost err",
"ucode par err", "DAL par err",
"BI bus err", "BTB tag par",
"cache tag par",
};
#define MC8200_BADIPL 0x01
#define MC8200_UERR 0x02
#define MC8200_UPAR 0x04
#define MC8200_DPAR 0x08
#define MC8200_BIERR 0x10
#define MC8200_BTAGPAR 0x20
#define MC8200_CTAGPAR 0x40
struct mc8200frame {
int mc82_bcnt; /* byte count == 0x20 */
int mc82_summary; /* summary parameter */
int mc82_param1; /* parameter 1 */
int mc82_va; /* va register */
int mc82_vap; /* va prime register */
int mc82_ma; /* memory address */
int mc82_status; /* status word */
int mc82_epc; /* error pc */
int mc82_upc; /* micro pc */
int mc82_pc; /* current pc */
int mc82_psl; /* current psl */
};
ka820_mchk(cmcf)
caddr_t cmcf;
{
register struct mc8200frame *mcf = (struct mc8200frame *)cmcf;
register int i, type = mcf->mc82_summary;
extern int cold;
/* ignore BI bus errors during configuration */
if (cold && type == MC8200_BIERR) {
mtpr(MCESR, 0xf);
return (MCHK_RECOVERED);
}
/*
* SOME ERRORS ARE RECOVERABLE
* do it later
*/
printf("machine check %x: ", type);
for (i = 0; i < sizeof (mc8200) / sizeof (mc8200[0]); i++)
if (type & (1 << i))
printf(" %s,", mc8200[i]);
printf(" param1 %x\n", mcf->mc82_param1);
printf(
"\tva %x va' %x ma %x pc %x psl %x\n\tstatus %x errpc %x upc %x\n",
mcf->mc82_va, mcf->mc82_vap, mcf->mc82_ma,
mcf->mc82_pc, mcf->mc82_psl,
mcf->mc82_status, mcf->mc82_epc, mcf->mc82_upc);
return (MCHK_PANIC);
}
/*
* Receive a character from logical console.
*/
rxcdintr()
{
register int c = mfpr(RXCD);
/* not sure what (if anything) to do with these */
printf("rxcd node %x c=0x%x\n", (c >> 8) & 0xf, c & 0xff);
}
#endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.