Commit | Line | Data |
---|---|---|
025fd248 MK |
1 | /* |
2 | * @(#)ka860.c 7.1 (UofMD/Berkeley) %G% | |
3 | */ | |
4 | ||
5 | #if VAX8600 | |
6 | ||
7 | /* | |
8 | * VAX 8600 specific routines. | |
9 | */ | |
10 | ||
11 | #include "param.h" | |
12 | ||
13 | #include "cpu.h" | |
14 | #include "mtpr.h" | |
15 | ||
16 | /* | |
17 | * 8600 memory register (MERG) bit definitions | |
18 | */ | |
19 | #define M8600_ICRD 0x400 /* inhibit crd interrupts */ | |
20 | #define M8600_TB_ERR 0xf00 /* translation buffer error mask */ | |
21 | ||
22 | /* | |
23 | * MDECC register | |
24 | */ | |
25 | #define M8600_ADDR_PE 0x080000 /* address parity error */ | |
26 | #define M8600_DBL_ERR 0x100000 /* data double bit error */ | |
27 | #define M8600_SNG_ERR 0x200000 /* data single bit error */ | |
28 | #define M8600_BDT_ERR 0x400000 /* bad data error */ | |
29 | ||
30 | /* | |
31 | * ESPA register is used to address scratch pad registers in the Ebox. | |
32 | * To access a register in the scratch pad, write the ESPA with the address | |
33 | * and then read the ESPD register. | |
34 | * | |
35 | * NOTE: In assmebly code, the mfpr instruction that reads the ESPD | |
36 | * register must immedately follow the mtpr instruction that setup | |
37 | * the ESPA register -- per the VENUS processor register spec. | |
38 | * | |
39 | * The scratchpad registers that are supplied for a single bit ECC | |
40 | * error are: | |
41 | */ | |
42 | #define SPAD_MSTAT1 0x25 /* scratch pad mstat1 register */ | |
43 | #define SPAD_MSTAT2 0x26 /* scratch pad mstat2 register */ | |
44 | #define SPAD_MDECC 0x27 /* scratch pad mdecc register */ | |
45 | #define SPAD_MEAR 0x2a /* scratch pad mear register */ | |
46 | ||
47 | #define M8600_MEMERR(mdecc) ((mdecc) & 0x780000) | |
48 | #define M8600_HRDERR(mdecc) ((mdecc) & 0x580000) | |
49 | #define M8600_SYN(mdecc) (((mdecc) >> 9) & 0x3f) | |
50 | #define M8600_ADDR(mear) ((mear) & 0x3ffffffc) | |
51 | #define M8600_ARRAY(mear) (((mear) >> 22) & 0x0f) | |
52 | ||
53 | #define M8600_MDECC_BITS \ | |
54 | "\20\27BAD_DT_ERR\26SNG_BIT_ERR\25DBL_BIT_ERR\24ADDR_PE" | |
55 | ||
56 | #define M8600_MSTAT1_BITS "\20\30CPR_PE_A\27CPR_PE_B\26ABUS_DT_PE\ | |
57 | \25ABUS_CTL_MSK_PE\24ABUS_ADR_PE\23ABUS_C/A_CYCLE\22ABUS_ADP_1\21ABUS_ADP_0\ | |
58 | \20TB_MISS\17BLK_HIT\16C0_TAG_MISS\15CHE_MISS\14TB_VAL_ERR\13TB_PTE_B_PE\ | |
59 | \12TB_PTE_A_PE\11TB_TAG_PE\10WR_DT_PE_B3\7WR_DT_PE_B2\6WR_DT_PE_B1\ | |
60 | \5WR_DT_PE_B0\4CHE_RD_DT_PE\3CHE_SEL\2ANY_REFL\1CP_BW_CHE_DT_PE" | |
61 | ||
62 | #define M8600_MSTAT2_BITS "\20\20CP_BYT_WR\17ABUS_BD_DT_CODE\10MULT_ERR\ | |
63 | \7CHE_TAG_PE\6CHE_TAG_W_PE\5CHE_WRTN_BIT\4NXM\3CP-IO_BUF_ERR\2MBOX_LOCK" | |
64 | ||
65 | /* enable CRD reports */ | |
66 | ka860_memenable() | |
67 | { | |
68 | ||
69 | mtpr(MERG, mfpr(MERG) & ~M8600_ICRD); | |
70 | } | |
71 | ||
72 | /* log CRD errors */ | |
73 | ka860_memerr() | |
74 | { | |
75 | register int reg11; /* known to be r11 below */ | |
76 | int mdecc, mear, mstat1, mstat2, array; | |
77 | ||
78 | /* | |
79 | * Scratchpad registers in the Ebox must be read by | |
80 | * storing their ID number in ESPA and then immediately | |
81 | * reading ESPD's contents with no other intervening | |
82 | * machine instructions! | |
83 | * | |
84 | * The asm's below have a number of constants which | |
85 | * are defined correctly above and in mtpr.h. | |
86 | */ | |
87 | #ifdef lint | |
88 | reg11 = 0; | |
89 | #else | |
90 | asm("mtpr $0x27,$0x4e; mfpr $0x4f,r11"); | |
91 | #endif | |
92 | mdecc = reg11; /* must acknowledge interrupt? */ | |
93 | if (M8600_MEMERR(mdecc)) { | |
94 | asm("mtpr $0x2a,$0x4e; mfpr $0x4f,r11"); | |
95 | mear = reg11; | |
96 | asm("mtpr $0x25,$0x4e; mfpr $0x4f,r11"); | |
97 | mstat1 = reg11; | |
98 | asm("mtpr $0x26,$0x4e; mfpr $0x4f,r11"); | |
99 | mstat2 = reg11; | |
100 | array = M8600_ARRAY(mear); | |
101 | ||
102 | printf("mcr0: ecc error, addr %x (array %d) syn %x\n", | |
103 | M8600_ADDR(mear), array, M8600_SYN(mdecc)); | |
104 | printf("\tMSTAT1 = %b\n\tMSTAT2 = %b\n", | |
105 | mstat1, M8600_MSTAT1_BITS, | |
106 | mstat2, M8600_MSTAT2_BITS); | |
107 | mtpr(EHSR, 0); | |
108 | mtpr(MERG, mfpr(MERG) | M8600_ICRD); | |
109 | } | |
110 | } | |
111 | ||
112 | #define NMC8600 7 | |
113 | char *mc8600[] = { | |
114 | "unkn type", "fbox error", "ebox error", "ibox error", | |
115 | "mbox error", "tbuf error", "mbox 1D error" | |
116 | }; | |
117 | /* codes for above */ | |
118 | #define MC_FBOX 1 | |
119 | #define MC_EBOX 2 | |
120 | #define MC_IBOX 3 | |
121 | #define MC_MBOX 4 | |
122 | #define MC_TBUF 5 | |
123 | #define MC_MBOX1D 6 | |
124 | ||
125 | /* error bits */ | |
126 | #define MBOX_FE 0x8000 /* Mbox fatal error */ | |
127 | #define FBOX_SERV 0x10000000 /* Fbox service error */ | |
128 | #define IBOX_ERR 0x2000 /* Ibox error */ | |
129 | #define EBOX_ERR 0x1e00 /* Ebox error */ | |
130 | #define MBOX_1D 0x81d0000 /* Mbox 1D error */ | |
131 | #define EDP_PE 0x200 | |
132 | ||
133 | struct mc8600frame { | |
134 | int mc86_bcnt; /* byte count == 0x58 */ | |
135 | int mc86_ehmsts; | |
136 | int mc86_evmqsav; | |
137 | int mc86_ebcs; | |
138 | int mc86_edpsr; | |
139 | int mc86_cslint; | |
140 | int mc86_ibesr; | |
141 | int mc86_ebxwd1; | |
142 | int mc86_ebxwd2; | |
143 | int mc86_ivasav; | |
144 | int mc86_vibasav; | |
145 | int mc86_esasav; | |
146 | int mc86_isasav; | |
147 | int mc86_cpc; | |
148 | int mc86_mstat1; | |
149 | int mc86_mstat2; | |
150 | int mc86_mdecc; | |
151 | int mc86_merg; | |
152 | int mc86_cshctl; | |
153 | int mc86_mear; | |
154 | int mc86_medr; | |
155 | int mc86_accs; | |
156 | int mc86_cses; | |
157 | int mc86_pc; /* trapped pc */ | |
158 | int mc86_psl; /* trapped psl */ | |
159 | }; | |
160 | ||
161 | /* machine check */ | |
162 | ka860_mchk(cmcf) | |
163 | caddr_t cmcf; | |
164 | { | |
165 | register struct mc8600frame *mcf = (struct mc8600frame *)cmcf; | |
166 | register int type; | |
167 | ||
168 | if (mcf->mc86_ebcs & MBOX_FE) | |
169 | mcf->mc86_ehmsts |= MC_MBOX; | |
170 | else if (mcf->mc86_ehmsts & FBOX_SERV) | |
171 | mcf->mc86_ehmsts |= MC_FBOX; | |
172 | else if (mcf->mc86_ebcs & EBOX_ERR) { | |
173 | if (mcf->mc86_ebcs & EDP_PE) | |
174 | mcf->mc86_ehmsts |= MC_MBOX; | |
175 | else | |
176 | mcf->mc86_ehmsts |= MC_EBOX; | |
177 | } else if (mcf->mc86_ehmsts & IBOX_ERR) | |
178 | mcf->mc86_ehmsts |= MC_IBOX; | |
179 | else if (mcf->mc86_mstat1 & M8600_TB_ERR) | |
180 | mcf->mc86_ehmsts |= MC_TBUF; | |
181 | else if ((mcf->mc86_cslint & MBOX_1D) == MBOX_1D) | |
182 | mcf->mc86_ehmsts |= MC_MBOX1D; | |
183 | ||
184 | type = mcf->mc86_ehmsts & 0x7; | |
185 | printf("machine check %x: %s\n", type, | |
186 | type < NMC8600 ? mc8600[type] : "???"); | |
187 | printf("\tehm.sts %x evmqsav %x ebcs %x edpsr %x cslint %x\n", | |
188 | mcf->mc86_ehmsts, mcf->mc86_evmqsav, mcf->mc86_ebcs, | |
189 | mcf->mc86_edpsr, mcf->mc86_cslint); | |
190 | printf("\tibesr %x ebxwd %x %x ivasav %x vibasav %x\n", | |
191 | mcf->mc86_ibesr, mcf->mc86_ebxwd1, mcf->mc86_ebxwd2, | |
192 | mcf->mc86_ivasav, mcf->mc86_vibasav); | |
193 | printf("\tesasav %x isasav %x cpc %x mstat %x %x mdecc %x\n", | |
194 | mcf->mc86_esasav, mcf->mc86_isasav, mcf->mc86_cpc, | |
195 | mcf->mc86_mstat1, mcf->mc86_mstat2, mcf->mc86_mdecc); | |
196 | printf("\tmerg %x cshctl %x mear %x medr %x accs %x cses %x\n", | |
197 | mcf->mc86_merg, mcf->mc86_cshctl, mcf->mc86_mear, | |
198 | mcf->mc86_medr, mcf->mc86_accs, mcf->mc86_cses); | |
199 | printf("\tpc %x psl %x\n", mcf->mc86_pc, mcf->mc86_psl); | |
200 | mtpr(EHSR, 0); | |
201 | return (MCHK_PANIC); | |
202 | } | |
203 | #endif |