ka88.c revision 1.4
1/* $NetBSD: ka88.c,v 1.4 2002/10/01 05:19:02 thorpej 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 * KA88 specific CPU code. 35 */ 36/* 37 * TODO: 38 * - Machine check code 39 */ 40 41#include "opt_multiprocessor.h" 42 43#include <sys/param.h> 44#include <sys/time.h> 45#include <sys/kernel.h> 46#include <sys/device.h> 47#include <sys/systm.h> 48#include <sys/conf.h> 49 50#include <machine/cpu.h> 51#include <machine/mtpr.h> 52#include <machine/nexus.h> 53#include <machine/clock.h> 54#include <machine/scb.h> 55#include <machine/bus.h> 56#include <machine/sid.h> 57#include <machine/rpb.h> 58#include <machine/ka88.h> 59 60#include <vax/vax/gencons.h> 61 62#include "ioconf.h" 63#include "locators.h" 64 65static void ka88_memerr(void); 66static void ka88_conf(void); 67static int ka88_mchk(caddr_t); 68static void ka88_steal_pages(void); 69static int ka88_clkread(time_t); 70static void ka88_clkwrite(void); 71static void ka88_badaddr(void); 72#if defined(MULTIPROCESSOR) 73static void ka88_startslave(struct device *, struct cpu_info *); 74static void ka88_txrx(int, char *, int); 75static void ka88_sendstr(int, char *); 76static void ka88_sergeant(int); 77static int rxchar(void); 78static void ka88_putc(int); 79static void ka88_cnintr(void); 80cons_decl(gen); 81#endif 82 83static long *ka88_mcl; 84static int mastercpu; 85 86struct cpu_dep ka88_calls = { 87 ka88_steal_pages, 88 ka88_mchk, 89 ka88_memerr, 90 ka88_conf, 91 ka88_clkread, 92 ka88_clkwrite, 93 6, /* ~VUPS */ 94 64, /* SCB pages */ 95 0, 96 0, 97 0, 98 0, 99 0, 100#if defined(MULTIPROCESSOR) 101 ka88_startslave, 102#endif 103 ka88_badaddr, 104}; 105 106struct ka88_softc { 107 struct device sc_dev; 108 int sc_slot; 109}; 110 111static void 112ka88_conf(void) 113{ 114 ka88_mcl = (void *)vax_map_physmem(0x3e000000, 1); 115 printf("Serial number %d, rev %d\n", 116 mfpr(PR_SID) & 65535, (mfpr(PR_SID) >> 16) & 127); 117} 118 119static int 120ka88_match(struct device *parent, struct cfdata *cf, void *aux) 121{ 122 struct nmi_attach_args *na = aux; 123 124 if (cf->cf_loc[NMICF_SLOT] != NMICF_SLOT_DEFAULT && 125 cf->cf_loc[NMICF_SLOT] != na->slot) 126 return 0; 127 if (na->slot >= 20) 128 return 1; 129 return 0; 130} 131 132static void 133ka88_attach(struct device *parent, struct device *self, void *aux) 134{ 135 struct ka88_softc *sc = (void *)self; 136 struct nmi_attach_args *na = aux; 137 char *ms, *lr; 138 139 if (((ka88_confdata & KA88_LEFTPRIM) && (na->slot == 20)) || 140 ((ka88_confdata & KA88_LEFTPRIM) == 0 && (na->slot != 20))) 141 lr = "left"; 142 else 143 lr = "right"; 144 ms = na->slot == 20 ? "master" : "slave"; 145 146 printf(": ka88 (%s) (%s)\n", lr, ms); 147 sc->sc_slot = na->slot; 148 if (na->slot != mastercpu) { 149#if defined(MULTIPROCESSOR) 150 sc->sc_ci = cpu_slavesetup(self); 151 v_putc = ka88_putc; /* Need special console handling */ 152#endif 153 return; 154 } 155 curcpu()->ci_dev = self; 156} 157 158CFATTACH_DECL(cpu_nmi, sizeof(struct ka88_softc), 159 ka88_match, ka88_attach, NULL, NULL) 160 161struct mem_nmi_softc { 162 struct device sc_dev; 163 bus_space_tag_t sc_iot; 164 bus_space_handle_t sc_ioh; 165}; 166 167static int 168ms88_match(struct device *parent, struct cfdata *cf, void *aux) 169{ 170 struct nmi_attach_args *na = aux; 171 172 if (cf->cf_loc[NMICF_SLOT] != NMICF_SLOT_DEFAULT && 173 cf->cf_loc[NMICF_SLOT] != na->slot) 174 return 0; 175 if (na->slot != 10) 176 return 0; 177 return 1; 178} 179 180static void 181ms88_attach(struct device *parent, struct device *self, void *aux) 182{ 183 printf("\n"); 184} 185 186CFATTACH_DECL(mem_nmi, sizeof(struct mem_nmi_softc), 187 ms88_match, ms88_attach, NULL, NULL) 188 189static void 190ka88_badaddr(void) 191{ 192 volatile int hej; 193 /* 194 * This is some magic to clear the NMI faults, described 195 * in section 7.9 in the VAX 8800 System Maintenance Guide. 196 */ 197 hej = ka88_mcl[5]; 198 hej = ka88_mcl[0]; 199 ka88_mcl[0] = 0x04000000; 200 mtpr(1, 0x88); 201} 202 203static void 204ka88_memerr() 205{ 206 printf("ka88_memerr\n"); 207} 208 209struct mc88frame { 210 int mc64_summary; /* summary parameter */ 211 int mc64_va; /* va register */ 212 int mc64_vb; /* memory address */ 213 int mc64_sisr; /* status word */ 214 int mc64_state; /* error pc */ 215 int mc64_sc; /* micro pc */ 216 int mc64_pc; /* current pc */ 217 int mc64_psl; /* current psl */ 218}; 219 220static int 221ka88_mchk(caddr_t cmcf) 222{ 223 return (MCHK_PANIC); 224} 225 226#if defined(MULTIPROCESSOR) 227#define RXBUF 80 228static char rxbuf[RXBUF]; 229static int got = 0, taken = 0; 230static int expect = 0; 231#endif 232#if 0 233/* 234 * Receive a character from logical console. 235 */ 236static void 237rxcdintr(void *arg) 238{ 239 int c = mfpr(PR_RXCD); 240 241 if (c == 0) 242 return; 243 244#if defined(MULTIPROCESSOR) 245 if ((c & 0xff) == 0) { 246 if (curcpu()->ci_flags & CI_MASTERCPU) 247 ka88_cnintr(); 248 return; 249 } 250 251 if (expect == ((c >> 8) & 0xf)) 252 rxbuf[got++] = c & 0xff; 253 254 if (got == RXBUF) 255 got = 0; 256#endif 257} 258#endif 259 260static void 261tocons(int val) 262{ 263 int s = splhigh(); 264 265 while ((mfpr(PR_TXCS) & GC_RDY) == 0) /* Wait until xmit ready */ 266 ; 267 mtpr(val, PR_TXDB); /* xmit character */ 268 splx(s); 269} 270 271static int 272fromcons(int func) 273{ 274 int ret, s = splhigh(); 275 276 while (1) { 277 while ((mfpr(PR_RXCS) & GC_DON) == 0) 278 ; 279 ret = mfpr(PR_RXDB); 280 if ((ret & 0xf00) == func) 281 break; 282 } 283 splx(s); 284 return ret; 285} 286 287static int 288ka88_clkread(time_t base) 289{ 290 union {u_int ret;u_char r[4];} u; 291 int i, s = splhigh(); 292 293 tocons(KA88_COMM|KA88_TOYREAD); 294 for (i = 0; i < 4; i++) { 295 u.r[i] = fromcons(KA88_TOY) & 255; 296 } 297 splx(s); 298 return u.ret; 299} 300 301static void 302ka88_clkwrite(void) 303{ 304 union {u_int ret;u_char r[4];} u; 305 int i, s = splhigh(); 306 307 u.ret = time.tv_sec - yeartonum(numtoyear(time.tv_sec)); 308 tocons(KA88_COMM|KA88_TOYWRITE); 309 for (i = 0; i < 4; i++) 310 tocons(KA88_TOY|u.r[i]); 311 splx(s); 312} 313 314void 315ka88_steal_pages(void) 316{ 317 mtpr(1, PR_COR); /* Cache on */ 318 strcpy(cpu_model, "VAX 8800"); 319 tocons(KA88_COMM|KA88_GETCONF); 320 ka88_confdata = fromcons(KA88_CONFDATA); 321 ka88_confdata = mfpr(PR_RXDB); 322 mastercpu = 20; 323 if (vax_cputype == VAX_TYP_8NN) { 324 if (ka88_confdata & KA88_SMALL) { 325 cpu_model[5] = '5'; 326 if (ka88_confdata & KA88_SLOW) { 327 vax_boardtype = VAX_BTYP_8500; 328 cpu_model[6] = '3'; 329 } else { 330 vax_boardtype = VAX_BTYP_8550; 331 cpu_model[6] = '5'; 332 } 333 } else if (ka88_confdata & KA88_SINGLE) { 334 vax_boardtype = VAX_BTYP_8700; 335 cpu_model[5] = '7'; 336 } 337 } 338} 339 340 341#if defined(MULTIPROCESSOR) && 0 342int 343rxchar() 344{ 345 int ret; 346 347 if (got == taken) 348 return 0; 349 350 ret = rxbuf[taken++]; 351 if (taken == RXBUF) 352 taken = 0; 353 return ret; 354} 355 356static void 357ka88_startslave(struct device *dev, struct cpu_info *ci) 358{ 359 struct ka88_softc *sc = (void *)dev; 360 int id = sc->sc_binid; 361 int i; 362 363 expect = sc->sc_binid; 364 /* First empty queue */ 365 for (i = 0; i < 10000; i++) 366 if (rxchar()) 367 i = 0; 368 ka88_txrx(id, "\020", 0); /* Send ^P to get attention */ 369 ka88_txrx(id, "I\r", 0); /* Init other end */ 370 ka88_txrx(id, "D/I 4 %x\r", ci->ci_istack); /* Interrupt stack */ 371 ka88_txrx(id, "D/I C %x\r", mfpr(PR_SBR)); /* SBR */ 372 ka88_txrx(id, "D/I D %x\r", mfpr(PR_SLR)); /* SLR */ 373 ka88_txrx(id, "D/I 10 %x\r", (int)ci->ci_pcb); /* PCB for idle proc */ 374 ka88_txrx(id, "D/I 11 %x\r", mfpr(PR_SCBB)); /* SCB */ 375 ka88_txrx(id, "D/I 38 %x\r", mfpr(PR_MAPEN)); /* Enable MM */ 376 ka88_txrx(id, "S %x\r", (int)&tramp); /* Start! */ 377 expect = 0; 378 for (i = 0; i < 10000; i++) 379 if ((volatile)ci->ci_flags & CI_RUNNING) 380 break; 381 if (i == 10000) 382 printf("%s: (ID %d) failed starting??!!??\n", 383 dev->dv_xname, sc->sc_binid); 384} 385 386void 387ka88_txrx(int id, char *fmt, int arg) 388{ 389 char buf[20]; 390 391 sprintf(buf, fmt, arg); 392 ka88_sendstr(id, buf); 393 ka88_sergeant(id); 394} 395 396void 397ka88_sendstr(int id, char *buf) 398{ 399 register u_int utchr; /* Ends up in R11 with PCC */ 400 int ch, i; 401 402 while (*buf) { 403 utchr = *buf | id << 8; 404 405 /* 406 * It seems like mtpr to TXCD sets the V flag if it fails. 407 * Cannot check that flag in C... 408 */ 409#ifdef __GNUC__ 410 asm("1:;mtpr %0,$92;bvs 1b" :: "g"(utchr)); 411#else 412 asm("1:;mtpr r11,$92;bvs 1b"); 413#endif 414 buf++; 415 i = 30000; 416 while ((ch = rxchar()) == 0 && --i) 417 ; 418 if (ch == 0) 419 continue; /* failed */ 420 } 421} 422 423void 424ka88_sergeant(int id) 425{ 426 int i, ch, nserg; 427 428 nserg = 0; 429 for (i = 0; i < 30000; i++) { 430 if ((ch = rxchar()) == 0) 431 continue; 432 if (ch == '>') 433 nserg++; 434 else 435 nserg = 0; 436 i = 0; 437 if (nserg == 3) 438 break; 439 } 440 /* What to do now??? */ 441} 442 443/* 444 * Write to master console. 445 * Need no locking here; done in the print functions. 446 */ 447static volatile int ch = 0; 448 449void 450ka88_putc(int c) 451{ 452 if (curcpu()->ci_flags & CI_MASTERCPU) { 453 gencnputc(0, c); 454 return; 455 } 456 ch = c; 457 mtpr(mastercpu << 8, PR_RXCD); /* Send IPI to mastercpu */ 458 while (ch != 0) 459 ; /* Wait for master to handle */ 460} 461 462/* 463 * Got character IPI. 464 */ 465void 466ka88_cnintr() 467{ 468 if (ch != 0) 469 gencnputc(0, ch); 470 ch = 0; /* Release slavecpu */ 471} 472#endif 473