1 /* $NetBSD: ka6400.c,v 1.1 2000/07/06 17:40:00 ragge Exp $ */ 2 3 /* 4 * Copyright (c) 2000 Ludd, University of Lule}, Sweden. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed at Ludd, University of 17 * Lule}, Sweden and its contributors. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * KA6400 specific CPU code. 35 */ 36 /* 37 * TODO: 38 * - Machine check code 39 * - Vector processor code 40 */ 41 42 #include "opt_multiprocessor.h" 43 44 #include <sys/param.h> 45 #include <sys/time.h> 46 #include <sys/kernel.h> 47 #include <sys/device.h> 48 #include <sys/systm.h> 49 #include <sys/conf.h> 50 51 #include <machine/ka670.h> 52 #include <machine/cpu.h> 53 #include <machine/mtpr.h> 54 #include <machine/nexus.h> 55 #include <machine/clock.h> 56 #include <machine/scb.h> 57 #include <machine/bus.h> 58 #include <machine/sid.h> 59 #include <machine/cca.h> 60 #include <machine/rpb.h> 61 62 #include <dev/xmi/xmireg.h> 63 #include <dev/xmi/xmivar.h> 64 65 #include "ioconf.h" 66 #include "locators.h" 67 68 static int *rssc; 69 struct cca *cca; 70 71 static int ka6400_match(struct device *, struct cfdata *, void *); 72 static void ka6400_attach(struct device *, struct device *, void*); 73 static void ka6400_memerr(void); 74 static void ka6400_conf(void); 75 static int ka6400_mchk(caddr_t); 76 static void ka6400_steal_pages(void); 77 #if defined(MULTIPROCESSOR) 78 static void ka6400_startslave(struct device *, struct cpu_info *); 79 static void ka6400_txrx(int, char *, int); 80 static void ka6400_sendstr(int, char *); 81 static void ka6400_sergeant(int); 82 static int rxchar(void); 83 static void ka6400_putc(int); 84 static void ka6400_cnintr(void); 85 cons_decl(gen); 86 #endif 87 88 struct cpu_dep ka6400_calls = { 89 ka6400_steal_pages, 90 ka6400_mchk, 91 ka6400_memerr, 92 ka6400_conf, 93 generic_clkread, 94 generic_clkwrite, 95 6, /* ~VUPS */ 96 16, /* SCB pages */ 97 0, 98 0, 99 0, 100 0, 101 0, 102 #if defined(MULTIPROCESSOR) 103 ka6400_startslave, 104 #endif 105 }; 106 107 struct ka6400_softc { 108 struct device sc_dev; 109 struct cpu_info *sc_ci; 110 int sc_nodeid; /* CPU node ID */ 111 }; 112 113 struct cfattach cpu_xmi_ca = { 114 sizeof(struct ka6400_softc), ka6400_match, ka6400_attach 115 }; 116 117 static int 118 ka6400_match(struct device *parent, struct cfdata *cf, void *aux) 119 { 120 struct xmi_attach_args *xa = aux; 121 122 if (bus_space_read_2(xa->xa_iot, xa->xa_ioh, XMI_TYPE) != XMIDT_KA64) 123 return 0; 124 125 if (cf->cf_loc[XMICF_NODE] != XMICF_NODE_DEFAULT && 126 cf->cf_loc[XMICF_NODE] != xa->xa_nodenr) 127 return 0; 128 129 return 1; 130 } 131 132 static void 133 ka6400_attach(struct device *parent, struct device *self, void *aux) 134 { 135 struct ka6400_softc *sc = (void *)self; 136 struct xmi_attach_args *xa = aux; 137 int vp; 138 139 vp = (cca->cca_vecenab & (1 << xa->xa_nodenr)); 140 printf("\n%s: ka6400 (%s) rev %d%s\n", self->dv_xname, 141 mastercpu == xa->xa_nodenr ? "master" : "slave", 142 bus_space_read_4(xa->xa_iot, xa->xa_ioh, XMI_TYPE) >> 16, 143 (vp ? ", vector processor present" : "")); 144 145 sc->sc_nodeid = xa->xa_nodenr; 146 147 if (xa->xa_nodenr != mastercpu) { 148 #if defined(MULTIPROCESSOR) 149 sc->sc_ci = cpu_slavesetup(self); 150 v_putc = ka6400_putc; /* Need special console handling */ 151 #endif 152 return; 153 } 154 155 mtpr(0, PR_VPSR); /* Can't use vector processor */ 156 curcpu()->ci_dev = self; 157 } 158 159 void 160 ka6400_conf() 161 { 162 int mapaddr; 163 164 rssc = (void *)vax_map_physmem(RSSC_ADDR, 1); 165 mastercpu = rssc[RSSC_IPORT/4] & 15; 166 mapaddr = (cca ? (int)cca : rpb.cca_addr); 167 cca = (void *)vax_map_physmem(mapaddr, vax_btoc(sizeof(struct cca))); 168 } 169 170 /* 171 * MS62 support. 172 * This code should: 173 * 1: Be completed. 174 * 2: (eventually) move to dev/xmi/; it is used by Mips also. 175 */ 176 #define MEMRD(reg) bus_space_read_4(sc->sc_iot, sc->sc_ioh, (reg)) 177 #define MEMWR(reg, val) bus_space_write_4(sc->sc_iot, sc->sc_ioh, (reg), (val)) 178 179 #define MS62_TYPE 0 180 #define MS62_XBE 4 181 #define MS62_SEADR 16 182 #define MS62_CTL1 20 183 #define MS62_ECCERR 24 184 #define MS62_ECCEA 28 185 #define MS62_ILK0 32 186 #define MS62_ILK1 36 187 #define MS62_ILK2 40 188 #define MS62_ILK3 44 189 #define MS62_CTL2 48 190 191 static int ms6400_match(struct device *, struct cfdata *, void *); 192 static void ms6400_attach(struct device *, struct device *, void*); 193 194 struct mem_xmi_softc { 195 struct device sc_dev; 196 bus_space_tag_t sc_iot; 197 bus_space_handle_t sc_ioh; 198 }; 199 200 struct cfattach mem_xmi_ca = { 201 sizeof(struct mem_xmi_softc), ms6400_match, ms6400_attach 202 }; 203 204 static int 205 ms6400_match(struct device *parent, struct cfdata *cf, void *aux) 206 { 207 struct xmi_attach_args *xa = aux; 208 209 if (bus_space_read_2(xa->xa_iot, xa->xa_ioh, XMI_TYPE) != XMIDT_MS62) 210 return 0; 211 212 if (cf->cf_loc[XMICF_NODE] != XMICF_NODE_DEFAULT && 213 cf->cf_loc[XMICF_NODE] != xa->xa_nodenr) 214 return 0; 215 216 return 1; 217 } 218 219 static void 220 ms6400_attach(struct device *parent, struct device *self, void *aux) 221 { 222 struct mem_xmi_softc *sc = (void *)self; 223 struct xmi_attach_args *xa = aux; 224 225 sc->sc_iot = xa->xa_iot; 226 sc->sc_ioh = xa->xa_ioh; 227 printf("\n%s: MS62, rev %d, size 32MB\n", self->dv_xname, 228 MEMRD(MS62_TYPE) >> 16); 229 } 230 231 static void 232 ka6400_memerr() 233 { 234 printf("ka6400_memerr\n"); 235 } 236 237 struct mc6400frame { 238 int mc64_summary; /* summary parameter */ 239 int mc64_va; /* va register */ 240 int mc64_vb; /* memory address */ 241 int mc64_sisr; /* status word */ 242 int mc64_state; /* error pc */ 243 int mc64_sc; /* micro pc */ 244 int mc64_pc; /* current pc */ 245 int mc64_psl; /* current psl */ 246 }; 247 248 static int 249 ka6400_mchk(caddr_t cmcf) 250 { 251 return (MCHK_PANIC); 252 } 253 254 #if defined(MULTIPROCESSOR) 255 #define RXBUF 80 256 static char rxbuf[RXBUF]; 257 static int got = 0, taken = 0; 258 static int expect = 0; 259 #endif 260 #if 0 261 /* 262 * Receive a character from logical console. 263 */ 264 static void 265 rxcdintr(void *arg) 266 { 267 int c = mfpr(PR_RXCD); 268 269 if (c == 0) 270 return; 271 272 #if defined(MULTIPROCESSOR) 273 if ((c & 0xff) == 0) { 274 if (curcpu()->ci_flags & CI_MASTERCPU) 275 ka6400_cnintr(); 276 return; 277 } 278 279 if (expect == ((c >> 8) & 0xf)) 280 rxbuf[got++] = c & 0xff; 281 282 if (got == RXBUF) 283 got = 0; 284 #endif 285 } 286 #endif 287 288 /* 289 * From ka670, which has the same cache structure. 290 */ 291 static void 292 ka6400_enable_cache(void) 293 { 294 mtpr(KA670_PCS_REFRESH, PR_PCSTS); /* disable primary cache */ 295 mtpr(mfpr(PR_PCSTS), PR_PCSTS); /* clear error flags */ 296 mtpr(8, PR_BCCTL); /* disable backup cache */ 297 mtpr(0, PR_BCFBTS); /* flush backup cache tag store */ 298 mtpr(0, PR_BCFPTS); /* flush primary cache tag store */ 299 mtpr(0x0e, PR_BCCTL); /* enable backup cache */ 300 mtpr(KA670_PCS_FLUSH | KA670_PCS_REFRESH, PR_PCSTS); /* flush primary cache */ 301 mtpr(KA670_PCS_ENABLE | KA670_PCS_REFRESH, PR_PCSTS); /* flush primary cache */ 302 } 303 304 void 305 ka6400_steal_pages(void) 306 { 307 int i, ncpu; 308 309 ka6400_enable_cache(); /* Turn on cache early */ 310 if (cca == 0) 311 cca = (void *)rpb.cca_addr; 312 /* Is there any way to get number of CPUs easier??? */ 313 for (i = ncpu = 0; i < cca->cca_maxcpu; i++) 314 if (cca->cca_console & (1 << i)) 315 ncpu++; 316 sprintf(cpu_model, "VAX 6000/4%x0", ncpu + 1); 317 } 318 319 320 #if defined(MULTIPROCESSOR) && 0 321 int 322 rxchar() 323 { 324 int ret; 325 326 if (got == taken) 327 return 0; 328 329 ret = rxbuf[taken++]; 330 if (taken == RXBUF) 331 taken = 0; 332 return ret; 333 } 334 335 static void 336 ka6400_startslave(struct device *dev, struct cpu_info *ci) 337 { 338 struct ka6400_softc *sc = (void *)dev; 339 int id = sc->sc_binid; 340 int i; 341 342 expect = sc->sc_binid; 343 /* First empty queue */ 344 for (i = 0; i < 10000; i++) 345 if (rxchar()) 346 i = 0; 347 ka6400_txrx(id, "\020", 0); /* Send ^P to get attention */ 348 ka6400_txrx(id, "I\r", 0); /* Init other end */ 349 ka6400_txrx(id, "D/I 4 %x\r", ci->ci_istack); /* Interrupt stack */ 350 ka6400_txrx(id, "D/I C %x\r", mfpr(PR_SBR)); /* SBR */ 351 ka6400_txrx(id, "D/I D %x\r", mfpr(PR_SLR)); /* SLR */ 352 ka6400_txrx(id, "D/I 10 %x\r", (int)ci->ci_pcb); /* PCB for idle proc */ 353 ka6400_txrx(id, "D/I 11 %x\r", mfpr(PR_SCBB)); /* SCB */ 354 ka6400_txrx(id, "D/I 38 %x\r", mfpr(PR_MAPEN)); /* Enable MM */ 355 ka6400_txrx(id, "S %x\r", (int)&tramp); /* Start! */ 356 expect = 0; 357 for (i = 0; i < 10000; i++) 358 if ((volatile)ci->ci_flags & CI_RUNNING) 359 break; 360 if (i == 10000) 361 printf("%s: (ID %d) failed starting??!!??\n", 362 dev->dv_xname, sc->sc_binid); 363 } 364 365 void 366 ka6400_txrx(int id, char *fmt, int arg) 367 { 368 char buf[20]; 369 370 sprintf(buf, fmt, arg); 371 ka6400_sendstr(id, buf); 372 ka6400_sergeant(id); 373 } 374 375 void 376 ka6400_sendstr(int id, char *buf) 377 { 378 register u_int utchr; /* Ends up in R11 with PCC */ 379 int ch, i; 380 381 while (*buf) { 382 utchr = *buf | id << 8; 383 384 /* 385 * It seems like mtpr to TXCD sets the V flag if it fails. 386 * Cannot check that flag in C... 387 */ 388 #ifdef __GNUC__ 389 asm("1:;mtpr %0,$92;bvs 1b" :: "g"(utchr)); 390 #else 391 asm("1:;mtpr r11,$92;bvs 1b"); 392 #endif 393 buf++; 394 i = 30000; 395 while ((ch = rxchar()) == 0 && --i) 396 ; 397 if (ch == 0) 398 continue; /* failed */ 399 } 400 } 401 402 void 403 ka6400_sergeant(int id) 404 { 405 int i, ch, nserg; 406 407 nserg = 0; 408 for (i = 0; i < 30000; i++) { 409 if ((ch = rxchar()) == 0) 410 continue; 411 if (ch == '>') 412 nserg++; 413 else 414 nserg = 0; 415 i = 0; 416 if (nserg == 3) 417 break; 418 } 419 /* What to do now??? */ 420 } 421 422 /* 423 * Write to master console. 424 * Need no locking here; done in the print functions. 425 */ 426 static volatile int ch = 0; 427 428 void 429 ka6400_putc(int c) 430 { 431 if (curcpu()->ci_flags & CI_MASTERCPU) { 432 gencnputc(0, c); 433 return; 434 } 435 ch = c; 436 mtpr(mastercpu << 8, PR_RXCD); /* Send IPI to mastercpu */ 437 while (ch != 0) 438 ; /* Wait for master to handle */ 439 } 440 441 /* 442 * Got character IPI. 443 */ 444 void 445 ka6400_cnintr() 446 { 447 if (ch != 0) 448 gencnputc(0, ch); 449 ch = 0; /* Release slavecpu */ 450 } 451 #endif 452