| 1 | /* vax780_mem.c: VAX 11/780 memory controllers\r |
| 2 | \r |
| 3 | Copyright (c) 2004-2005, Robert M Supnik\r |
| 4 | \r |
| 5 | Permission is hereby granted, free of charge, to any person obtaining a\r |
| 6 | copy of this software and associated documentation files (the "Software"),\r |
| 7 | to deal in the Software without restriction, including without limitation\r |
| 8 | the rights to use, copy, modify, merge, publish, distribute, sublicense,\r |
| 9 | and/or sell copies of the Software, and to permit persons to whom the\r |
| 10 | Software is furnished to do so, subject to the following conditions:\r |
| 11 | \r |
| 12 | The above copyright notice and this permission notice shall be included in\r |
| 13 | all copies or substantial portions of the Software.\r |
| 14 | \r |
| 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r |
| 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r |
| 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r |
| 18 | ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r |
| 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r |
| 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r |
| 21 | \r |
| 22 | Except as contained in this notice, the name of Robert M Supnik shall not be\r |
| 23 | used in advertising or otherwise to promote the sale, use or other dealings\r |
| 24 | in this Software without prior written authorization from Robert M Supnik.\r |
| 25 | \r |
| 26 | This module contains the VAX 11/780 system-specific registers and devices.\r |
| 27 | \r |
| 28 | mctl0, mctl1 MS780C/E memory controllers\r |
| 29 | */\r |
| 30 | \r |
| 31 | #include "vax_defs.h"\r |
| 32 | \r |
| 33 | /* Memory controller register A */\r |
| 34 | \r |
| 35 | #define MCRA_OF 0x0\r |
| 36 | #define MCRA_SUMM 0x00100000 /* err summ (MS780E) */\r |
| 37 | #define MCRA_C_SIZE 0x00007E00 /* array size - fixed */\r |
| 38 | #define MCRA_V_SIZE 9\r |
| 39 | #define MCRA_ILVE 0x00000100 /* interleave wr enab */\r |
| 40 | #define MCRA_TYPE 0x000000F8 /* type */\r |
| 41 | #define MCRA_C_TYPE 0x00000010 /* 16k uninterleaved */\r |
| 42 | #define MCRA_E_TYPE 0x0000006A /* 256k upper + lower */\r |
| 43 | #define MCRA_ILV 0x00000007 /* interleave */\r |
| 44 | #define MCRA_RD (0x00107FFF|SBI_FAULTS)\r |
| 45 | #define MCRA_WR 0x00000100\r |
| 46 | \r |
| 47 | /* Memory controller register B */\r |
| 48 | \r |
| 49 | #define MCRB_OF 0x1\r |
| 50 | #define MCRB_FP 0xF0000000 /* file pointers */\r |
| 51 | #define MCRB_V_SA 15 /* start addr */\r |
| 52 | #define MCRB_M_SA 0x1FFF\r |
| 53 | #define MCRB_SA (MCRB_M_SA << MCRB_V_SA)\r |
| 54 | #define MCRB_SAE 0x00004000 /* start addr wr enab */\r |
| 55 | #define MCRB_INIT 0x00003000 /* init state */\r |
| 56 | #define MCRB_REF 0x00000400 /* refresh */\r |
| 57 | #define MCRB_ECC 0x000003FF /* ECC for diags */\r |
| 58 | #define MCRB_RD 0xFFFFF7FF\r |
| 59 | #define MCRB_WR 0x000043FF\r |
| 60 | \r |
| 61 | /* Memory controller register C,D */\r |
| 62 | \r |
| 63 | #define MCRC_OF 0x2\r |
| 64 | #define MCRD_OF 0x3\r |
| 65 | #define MCRC_DCRD 0x40000000 /* disable CRD */\r |
| 66 | #define MCRC_HER 0x20000000 /* high error rate */\r |
| 67 | #define MCRC_ERL 0x10000000 /* log error */\r |
| 68 | #define MCRC_C_ER 0x0FFFFFFF /* MS780C error */\r |
| 69 | #define MCRC_E_PE1 0x00080000 /* MS780E par ctl 1 */\r |
| 70 | #define MCRC_E_PE0 0x00040000 /* MS780E par ctl 0 */\r |
| 71 | #define MCRC_E_CRD 0x00000200 /* MS780E CRD */\r |
| 72 | #define MCRC_E_PEW 0x00000100 /* MS780E par err wr */\r |
| 73 | #define MCRC_E_USEQ 0x00000080 /* MS780E seq err */\r |
| 74 | #define MCRC_C_RD 0x7FFFFFFF\r |
| 75 | #define MCRC_E_RD 0x700C0380\r |
| 76 | #define MCRC_WR 0x40000000\r |
| 77 | #define MCRC_C_W1C 0x30000000\r |
| 78 | #define MCRC_E_W1C 0x300C0380\r |
| 79 | \r |
| 80 | #define MCRROM_OF 0x400\r |
| 81 | \r |
| 82 | uint32 mcr_a[MCTL_NUM];\r |
| 83 | uint32 mcr_b[MCTL_NUM];\r |
| 84 | uint32 mcr_c[MCTL_NUM];\r |
| 85 | uint32 mcr_d[MCTL_NUM];\r |
| 86 | uint32 rom_lw[MCTL_NUM][ROMSIZE >> 2];\r |
| 87 | \r |
| 88 | extern UNIT cpu_unit;\r |
| 89 | \r |
| 90 | t_stat mctl_reset (DEVICE *dptr);\r |
| 91 | t_stat mctl_rdreg (int32 *val, int32 pa, int32 mode);\r |
| 92 | t_stat mctl_wrreg (int32 val, int32 pa, int32 mode);\r |
| 93 | \r |
| 94 | /* MCTLx data structures\r |
| 95 | \r |
| 96 | mctlx_dev MCTLx device descriptor\r |
| 97 | mctlx_unit MCTLx unit\r |
| 98 | mctlx_reg MCTLx register list\r |
| 99 | */\r |
| 100 | \r |
| 101 | DIB mctl0_dib[] = { TR_MCTL0, 0, &mctl_rdreg, &mctl_wrreg, 0 };\r |
| 102 | \r |
| 103 | UNIT mctl0_unit = { UDATA (NULL, 0, 0) };\r |
| 104 | \r |
| 105 | REG mctl0_reg[] = {\r |
| 106 | { HRDATA (CRA, mcr_a[0], 32) },\r |
| 107 | { HRDATA (CRB, mcr_b[0], 32) },\r |
| 108 | { HRDATA (CRC, mcr_c[0], 32) },\r |
| 109 | { HRDATA (CRD, mcr_d[0], 32) },\r |
| 110 | { BRDATA (ROM, rom_lw[0], 16, 32, ROMSIZE >> 2) },\r |
| 111 | { NULL }\r |
| 112 | };\r |
| 113 | \r |
| 114 | MTAB mctl0_mod[] = {\r |
| 115 | { MTAB_XTD|MTAB_VDV, TR_MCTL0, "NEXUS", NULL,\r |
| 116 | NULL, &show_nexus },\r |
| 117 | { 0 }\r |
| 118 | };\r |
| 119 | \r |
| 120 | DIB mctl1_dib[] = { TR_MCTL1, 0, &mctl_rdreg, &mctl_wrreg, 0 };\r |
| 121 | \r |
| 122 | UNIT mctl1_unit = { UDATA (NULL, 0, 0) };\r |
| 123 | \r |
| 124 | MTAB mctl1_mod[] = {\r |
| 125 | { MTAB_XTD|MTAB_VDV, TR_MCTL1, "NEXUS", NULL,\r |
| 126 | NULL, &show_nexus },\r |
| 127 | { 0 } };\r |
| 128 | \r |
| 129 | REG mctl1_reg[] = {\r |
| 130 | { HRDATA (CRA, mcr_a[1], 32) },\r |
| 131 | { HRDATA (CRB, mcr_b[1], 32) },\r |
| 132 | { HRDATA (CRC, mcr_c[1], 32) },\r |
| 133 | { HRDATA (CRD, mcr_d[1], 32) },\r |
| 134 | { BRDATA (ROM, rom_lw[1], 16, 32, ROMSIZE >> 2) },\r |
| 135 | { NULL }\r |
| 136 | };\r |
| 137 | \r |
| 138 | DEVICE mctl_dev[] = {\r |
| 139 | {\r |
| 140 | "MCTL0", &mctl0_unit, mctl0_reg, mctl0_mod,\r |
| 141 | 1, 16, 16, 1, 16, 8,\r |
| 142 | NULL, NULL, &mctl_reset,\r |
| 143 | NULL, NULL, NULL,\r |
| 144 | &mctl0_dib, DEV_NEXUS\r |
| 145 | },\r |
| 146 | {\r |
| 147 | "MCTL1", &mctl1_unit, mctl1_reg, mctl1_mod,\r |
| 148 | 1, 16, 16, 1, 16, 8,\r |
| 149 | NULL, NULL, &mctl_reset,\r |
| 150 | NULL, NULL, NULL,\r |
| 151 | &mctl1_dib, DEV_NEXUS\r |
| 152 | }\r |
| 153 | };\r |
| 154 | \r |
| 155 | /* Memory controller register read */\r |
| 156 | \r |
| 157 | t_stat mctl_rdreg (int32 *val, int32 pa, int32 lnt)\r |
| 158 | {\r |
| 159 | int32 mctl, ofs;\r |
| 160 | t_bool extmem = MEMSIZE > MAXMEMSIZE;\r |
| 161 | \r |
| 162 | if ((pa & 3) || (lnt != L_LONG)) { /* unaligned or not lw? */\r |
| 163 | printf (">>MCTL: invalid adapter read mask, pa = %X, lnt = %d\r\n", pa, lnt);\r |
| 164 | sbi_set_errcnf (); /* err confirmation */\r |
| 165 | return SCPE_OK;\r |
| 166 | }\r |
| 167 | mctl = NEXUS_GETNEX (pa) - TR_MCTL0; /* get mctl num */\r |
| 168 | ofs = NEXUS_GETOFS (pa); /* get offset */\r |
| 169 | if (ofs >= MCRROM_OF) { /* ROM? */\r |
| 170 | *val = rom_lw[mctl][ofs - MCRROM_OF]; /* get lw */\r |
| 171 | return SCPE_OK;\r |
| 172 | } \r |
| 173 | switch (ofs) {\r |
| 174 | \r |
| 175 | case MCRA_OF: /* CR A */\r |
| 176 | *val = mcr_a[mctl] & MCRA_RD;\r |
| 177 | break;\r |
| 178 | \r |
| 179 | case MCRB_OF: /* CR B */\r |
| 180 | *val = (mcr_b[mctl] & MCRB_RD) | MCRB_INIT;\r |
| 181 | break;\r |
| 182 | \r |
| 183 | case MCRC_OF: /* CR C */\r |
| 184 | *val = mcr_c[mctl] & (extmem? MCRC_E_RD: MCRC_C_RD);\r |
| 185 | break;\r |
| 186 | \r |
| 187 | case MCRD_OF: /* CR D */\r |
| 188 | if (!extmem) return SCPE_NXM; /* MS780E only */\r |
| 189 | *val = mcr_d[mctl] & MCRC_E_RD;\r |
| 190 | break;\r |
| 191 | \r |
| 192 | default:\r |
| 193 | return SCPE_NXM;\r |
| 194 | }\r |
| 195 | \r |
| 196 | return SCPE_OK;\r |
| 197 | }\r |
| 198 | \r |
| 199 | /* Memory controller register write */\r |
| 200 | \r |
| 201 | t_stat mctl_wrreg (int32 val, int32 pa, int32 lnt)\r |
| 202 | {\r |
| 203 | int32 mctl, ofs, mask;\r |
| 204 | t_bool extmem = MEMSIZE > MAXMEMSIZE;\r |
| 205 | \r |
| 206 | if ((pa & 3) || (lnt != L_LONG)) { /* unaligned or not lw? */\r |
| 207 | printf (">>MCTL: invalid adapter write mask, pa = %X, lnt = %d\r\n", pa, lnt);\r |
| 208 | sbi_set_errcnf (); /* err confirmation */\r |
| 209 | return SCPE_OK;\r |
| 210 | }\r |
| 211 | mctl = NEXUS_GETNEX (pa) - TR_MCTL0; /* get mctl num */\r |
| 212 | ofs = NEXUS_GETOFS (pa); /* get offset */\r |
| 213 | switch (ofs) {\r |
| 214 | \r |
| 215 | case MCRA_OF: /* CR A */\r |
| 216 | mask = MCRA_WR | ((val & MCRA_ILVE)? MCRA_ILV: 0);\r |
| 217 | mcr_a[mctl] = (mcr_a[mctl] & ~mask) | (val & mask);\r |
| 218 | break;\r |
| 219 | \r |
| 220 | case MCRB_OF: /* CR B */\r |
| 221 | mask = MCRB_WR | ((val & MCRB_SAE)? MCRB_SA: 0);\r |
| 222 | mcr_b[mctl] = (mcr_b[mctl] & ~mask) | (val & mask);\r |
| 223 | break;\r |
| 224 | \r |
| 225 | case MCRC_OF: /* CR C */\r |
| 226 | mcr_c[mctl] = ((mcr_c[mctl] & ~MCRC_WR) | (val & MCRC_WR)) &\r |
| 227 | ~(val & (extmem? MCRC_E_W1C: MCRC_C_W1C));\r |
| 228 | break;\r |
| 229 | \r |
| 230 | case MCRD_OF: /* CR D */\r |
| 231 | if (!extmem) return SCPE_NXM; /* MS780E only */\r |
| 232 | mcr_d[mctl] = ((mcr_d[mctl] & ~MCRC_WR) | (val & MCRC_WR)) &\r |
| 233 | ~(val & MCRC_E_W1C);\r |
| 234 | break;\r |
| 235 | \r |
| 236 | default:\r |
| 237 | return SCPE_NXM;\r |
| 238 | }\r |
| 239 | \r |
| 240 | return SCPE_OK;\r |
| 241 | }\r |
| 242 | \r |
| 243 | /* Used by CPU and loader */\r |
| 244 | \r |
| 245 | void rom_wr_B (int32 pa, int32 val)\r |
| 246 | {\r |
| 247 | uint32 mctl = NEXUS_GETNEX (pa) - TR_MCTL0; /* get mctl num */\r |
| 248 | uint32 ofs = NEXUS_GETOFS (pa) - MCRROM_OF; /* get offset */\r |
| 249 | int32 sc = (pa & 3) << 3;\r |
| 250 | \r |
| 251 | rom_lw[mctl][ofs] = ((val & 0xFF) << sc) | (rom_lw[mctl][ofs] & ~(0xFF << sc));\r |
| 252 | return;\r |
| 253 | }\r |
| 254 | \r |
| 255 | /* MEMCTL reset */\r |
| 256 | \r |
| 257 | t_stat mctl_reset (DEVICE *dptr)\r |
| 258 | {\r |
| 259 | int32 i, amb;\r |
| 260 | t_bool extmem = MEMSIZE > MAXMEMSIZE;\r |
| 261 | \r |
| 262 | amb = (int32) (MEMSIZE / 2) >> 20; /* array size MB */\r |
| 263 | for (i = 0; i < MCTL_NUM; i++) { /* init for MS780C */\r |
| 264 | if (extmem) { /* extended memory? */\r |
| 265 | mcr_a[i] = ((amb - 1) << MCRA_V_SIZE) | MCRA_E_TYPE;\r |
| 266 | mcr_b[i] = MCRB_INIT | ((i * amb) << (MCRB_V_SA + 4));\r |
| 267 | }\r |
| 268 | else {\r |
| 269 | mcr_a[i] = MCRA_C_SIZE | MCRA_C_TYPE;\r |
| 270 | mcr_b[i] = MCRB_INIT | (i << 21);\r |
| 271 | }\r |
| 272 | mcr_c[i] = 0;\r |
| 273 | mcr_d[i] = 0;\r |
| 274 | }\r |
| 275 | return SCPE_OK;\r |
| 276 | }\r |