1 /* $NetBSD: ka820.c,v 1.35 2002/10/10 11:45:14 jdolecek Exp $ */ 2 /* 3 * Copyright (c) 1988 Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * Chris Torek. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)ka820.c 7.4 (Berkeley) 12/16/90 38 */ 39 40 /* 41 * KA820 specific CPU code. (Note that the VAX8200 uses a KA820, not 42 * a KA8200. Sigh.) 43 */ 44 45 #include "opt_multiprocessor.h" 46 47 #include <sys/param.h> 48 #include <sys/time.h> 49 #include <sys/kernel.h> 50 #include <sys/device.h> 51 #include <sys/systm.h> 52 #include <sys/conf.h> 53 #include <sys/proc.h> 54 #include <sys/user.h> 55 56 #include <uvm/uvm_extern.h> 57 58 #include <machine/ka820.h> 59 #include <machine/cpu.h> 60 #include <machine/mtpr.h> 61 #include <machine/nexus.h> 62 #include <machine/clock.h> 63 #include <machine/scb.h> 64 #include <machine/bus.h> 65 66 #include <dev/clock_subr.h> 67 #include <dev/cons.h> 68 69 #include <dev/bi/bireg.h> 70 #include <dev/bi/bivar.h> 71 72 #include <vax/vax/crx.h> 73 74 #include "ioconf.h" 75 #include "locators.h" 76 77 struct ka820port *ka820port_ptr; 78 struct rx50device *rx50device_ptr; 79 static volatile struct ka820clock *ka820_clkpage; 80 static int mastercpu; 81 82 static int ka820_match(struct device *, struct cfdata *, void *); 83 static void ka820_attach(struct device *, struct device *, void*); 84 static void ka820_memerr(void); 85 static void ka820_conf(void); 86 static int ka820_mchk(caddr_t); 87 static int ka820_clkread(time_t base); 88 static void ka820_clkwrite(void); 89 static void rxcdintr(void *); 90 static void vaxbierr(void *); 91 #if defined(MULTIPROCESSOR) 92 static void ka820_startslave(struct device *, struct cpu_info *); 93 static void ka820_send_ipi(struct device *); 94 static void ka820_txrx(int, char *, int); 95 static void ka820_sendstr(int, char *); 96 static void ka820_sergeant(int); 97 static int rxchar(void); 98 static void ka820_putc(int); 99 static void ka820_cnintr(void); 100 static void ka820_ipintr(void *); 101 cons_decl(gen); 102 #endif 103 104 struct cpu_dep ka820_calls = { 105 0, 106 ka820_mchk, 107 ka820_memerr, 108 ka820_conf, 109 ka820_clkread, 110 ka820_clkwrite, 111 3, /* ~VUPS */ 112 5, /* SCB pages */ 113 0, 114 0, 115 0, 116 0, 117 0, 118 }; 119 120 #if defined(MULTIPROCESSOR) 121 struct cpu_mp_dep ka820_mp_dep = { 122 ka820_startslave, 123 ka820_send_ipi, 124 ka820_cnintr, 125 }; 126 #endif 127 128 struct ka820_softc { 129 struct device sc_dev; 130 struct cpu_info sc_ci; 131 int sc_binid; /* CPU node ID */ 132 }; 133 134 CFATTACH_DECL(cpu_bi, sizeof(struct ka820_softc), 135 ka820_match, ka820_attach, NULL, NULL); 136 137 #ifdef notyet 138 extern struct pte BRAMmap[]; 139 extern struct pte EEPROMmap[]; 140 char bootram[KA820_BRPAGES * VAX_NBPG]; 141 char eeprom[KA820_EEPAGES * VAX_NBPG]; 142 #endif 143 144 static int 145 ka820_match(struct device *parent, struct cfdata *cf, void *aux) 146 { 147 struct bi_attach_args *ba = aux; 148 149 if (bus_space_read_2(ba->ba_iot, ba->ba_ioh, BIREG_DTYPE) != BIDT_KA820) 150 return 0; 151 152 if (cf->cf_loc[BICF_NODE] != BICF_NODE_DEFAULT && 153 cf->cf_loc[BICF_NODE] != ba->ba_nodenr) 154 return 0; 155 156 return 1; 157 } 158 159 static void 160 ka820_attach(struct device *parent, struct device *self, void *aux) 161 { 162 struct ka820_softc *sc = (void *)self; 163 struct bi_attach_args *ba = aux; 164 register int csr; 165 u_short rev; 166 167 rev = bus_space_read_4(ba->ba_iot, ba->ba_ioh, BIREG_DTYPE) >> 16; 168 mastercpu = mfpr(PR_BINID); 169 strcpy(cpu_model, "VAX 8200"); 170 cpu_model[6] = rev & 0x8000 ? '5' : '0'; 171 printf(": ka82%c (%s) cpu rev %d, u patch rev %d, sec patch %d\n", 172 cpu_model[6], mastercpu == ba->ba_nodenr ? "master" : "slave", 173 ((rev >> 11) & 15), ((rev >> 1) &1023), rev & 1); 174 sc->sc_binid = ba->ba_nodenr; 175 176 /* Allow for IPINTR */ 177 bus_space_write_4(ba->ba_iot, ba->ba_ioh, 178 BIREG_IPINTRMSK, BIIPINTR_MASK); 179 180 #if defined(MULTIPROCESSOR) 181 if (ba->ba_nodenr != mastercpu) { 182 v_putc = ka820_putc; /* Need special console handling */ 183 return cpu_slavesetup(self); 184 } 185 #endif 186 187 #if defined(MULTIPROCESSOR) 188 /* 189 * Catch interprocessor interrupts. 190 */ 191 scb_vecalloc(KA820_INT_IPINTR, ka820_ipintr, sc, SCB_ISTACK, NULL); 192 #endif 193 /* 194 * Copy cpu_info into new position. 195 */ 196 bcopy(curcpu(), &sc->sc_ci, sizeof(struct cpu_info)); 197 mtpr(&sc->sc_ci, PR_SSP); 198 proc0.p_addr->u_pcb.SSP = mfpr(PR_SSP); 199 proc0.p_cpu = curcpu(); 200 curcpu()->ci_dev = self; 201 202 /* reset the console and enable the RX50 */ 203 ka820port_ptr = (void *)vax_map_physmem(KA820_PORTADDR, 1); 204 csr = ka820port_ptr->csr; 205 csr &= ~KA820PORT_RSTHALT; /* ??? */ 206 csr |= KA820PORT_CONSCLR | KA820PORT_CRDCLR | KA820PORT_CONSEN | 207 KA820PORT_RXIE; 208 ka820port_ptr->csr = csr; 209 bus_space_write_4(ba->ba_iot, ba->ba_ioh, 210 BIREG_INTRDES, ba->ba_intcpu); 211 bus_space_write_4(ba->ba_iot, ba->ba_ioh, BIREG_VAXBICSR, 212 bus_space_read_4(ba->ba_iot, ba->ba_ioh, BIREG_VAXBICSR) | 213 BICSR_SEIE | BICSR_HEIE); 214 } 215 216 void 217 ka820_conf() 218 { 219 /* 220 * Setup parameters necessary to read time from clock chip. 221 */ 222 ka820_clkpage = (void *)vax_map_physmem(KA820_CLOCKADDR, 1); 223 224 /* Enable cache */ 225 mtpr(0, PR_CADR); 226 227 /* Steal the interrupt vectors that are unique for us */ 228 scb_vecalloc(KA820_INT_RXCD, rxcdintr, NULL, SCB_ISTACK, NULL); 229 scb_vecalloc(0x50, vaxbierr, NULL, SCB_ISTACK, NULL); 230 231 /* XXX - should be done somewhere else */ 232 scb_vecalloc(SCB_RX50, crxintr, NULL, SCB_ISTACK, NULL); 233 rx50device_ptr = (void *)vax_map_physmem(KA820_RX50ADDR, 1); 234 #if defined(MULTIPROCESSOR) 235 mp_dep_call = &ka820_mp_dep; 236 #endif 237 } 238 239 void 240 vaxbierr(void *arg) 241 { 242 if (cold == 0) 243 panic("vaxbierr"); 244 } 245 246 #ifdef notdef 247 /* 248 * MS820 support. 249 */ 250 struct ms820regs { 251 struct biiregs biic; /* BI interface chip */ 252 u_long ms_gpr[4]; /* the four gprs (unused) */ 253 int ms_csr1; /* control/status register 1 */ 254 int ms_csr2; /* control/status register 2 */ 255 }; 256 #endif 257 258 #define MEMRD(reg) bus_space_read_4(sc->sc_iot, sc->sc_ioh, (reg)) 259 #define MEMWR(reg, val) bus_space_write_4(sc->sc_iot, sc->sc_ioh, (reg), (val)) 260 261 #define MSREG_CSR1 0x100 262 #define MSREG_CSR2 0x104 263 /* 264 * Bits in CSR1. 265 */ 266 #define MS1_ERRSUM 0x80000000 /* error summary (ro) */ 267 #define MS1_ECCDIAG 0x40000000 /* ecc diagnostic (rw) */ 268 #define MS1_ECCDISABLE 0x20000000 /* ecc disable (rw) */ 269 #define MS1_MSIZEMASK 0x1ffc0000 /* mask for memory size (ro) */ 270 #define MS1_RAMTYMASK 0x00030000 /* mask for ram type (ro) */ 271 #define MS1_RAMTY64K 0x00000000 /* 64K chips */ 272 #define MS1_RAMTY256K 0x00010000 /* 256K chips */ 273 #define MS1_RAMTY1MB 0x00020000 /* 1MB chips */ 274 /* type 3 reserved */ 275 #define MS1_CRDINH 0x00008000 /* inhibit crd interrupts (rw) */ 276 #define MS1_MEMVALID 0x00004000 /* memory has been written (ro) */ 277 #define MS1_INTLK 0x00002000 /* interlock flag (ro) */ 278 #define MS1_BROKE 0x00001000 /* broken (rw) */ 279 #define MS1_MBZ 0x00000880 /* zero */ 280 #define MS1_MWRITEERR 0x00000400 /* rds during masked write (rw) */ 281 #define MS1_CNTLERR 0x00000200 /* internal timing busted (rw) */ 282 #define MS1_INTLV 0x00000100 /* internally interleaved (ro) */ 283 #define MS1_DIAGC 0x0000007f /* ecc diagnostic bits (rw) */ 284 285 /* 286 * Bits in CSR2. 287 */ 288 #define MS2_RDSERR 0x80000000 /* rds error (rw) */ 289 #define MS2_HIERR 0x40000000 /* high error rate (rw) */ 290 #define MS2_CRDERR 0x20000000 /* crd error (rw) */ 291 #define MS2_ADRSERR 0x10000000 /* rds due to addr par err (rw) */ 292 #define MS2_MBZ 0x0f000080 /* zero */ 293 #define MS2_ADDR 0x00fffe00 /* address in error (relative) (ro) */ 294 #define MS2_INTLVADDR 0x00000100 /* error was in bank 1 (ro) */ 295 #define MS2_SYN 0x0000007f /* error syndrome (ro, rw diag) */ 296 297 static int ms820_match(struct device *, struct cfdata *, void *); 298 static void ms820_attach(struct device *, struct device *, void*); 299 300 struct mem_bi_softc { 301 struct device sc_dev; 302 bus_space_tag_t sc_iot; 303 bus_space_handle_t sc_ioh; 304 }; 305 306 CFATTACH_DECL(mem_bi, sizeof(struct mem_bi_softc), 307 ms820_match, ms820_attach, NULL, NULL); 308 309 static int 310 ms820_match(struct device *parent, struct cfdata *cf, void *aux) 311 { 312 struct bi_attach_args *ba = aux; 313 314 if (bus_space_read_2(ba->ba_iot, ba->ba_ioh, BIREG_DTYPE) != BIDT_MS820) 315 return 0; 316 317 if (cf->cf_loc[BICF_NODE] != BICF_NODE_DEFAULT && 318 cf->cf_loc[BICF_NODE] != ba->ba_nodenr) 319 return 0; 320 321 return 1; 322 } 323 324 static void 325 ms820_attach(struct device *parent, struct device *self, void *aux) 326 { 327 struct mem_bi_softc *sc = (void *)self; 328 struct bi_attach_args *ba = aux; 329 330 sc->sc_iot = ba->ba_iot; 331 sc->sc_ioh = ba->ba_ioh; 332 333 if ((MEMRD(BIREG_VAXBICSR) & BICSR_STS) == 0) 334 printf(": failed self test\n"); 335 else 336 printf(": size %dMB, %s chips\n", ((MEMRD(MSREG_CSR1) & 337 MS1_MSIZEMASK) >> 20), (MEMRD(MSREG_CSR1) & MS1_RAMTYMASK 338 ? MEMRD(MSREG_CSR1) & MS1_RAMTY256K ? "256K":"1M":"64K")); 339 340 MEMWR(BIREG_INTRDES, ba->ba_intcpu); 341 MEMWR(BIREG_VAXBICSR, MEMRD(BIREG_VAXBICSR) | BICSR_SEIE | BICSR_HEIE); 342 343 MEMWR(MSREG_CSR1, MS1_MWRITEERR | MS1_CNTLERR); 344 MEMWR(MSREG_CSR2, MS2_RDSERR | MS2_HIERR | MS2_CRDERR | MS2_ADRSERR); 345 } 346 347 static void 348 ka820_memerr() 349 { 350 struct mem_bi_softc *sc; 351 int m, hard, csr1, csr2; 352 char *type; 353 354 static char b1[] = "\20\40ERRSUM\37ECCDIAG\36ECCDISABLE\20CRDINH\17VALID\ 355 \16INTLK\15BROKE\13MWRITEERR\12CNTLERR\11INTLV"; 356 static char b2[] = "\20\40RDS\37HIERR\36CRD\35ADRS"; 357 358 char sbuf[sizeof(b1) + 64], sbuf2[sizeof(b2) + 64]; 359 360 for (m = 0; m < mem_cd.cd_ndevs; m++) { 361 sc = mem_cd.cd_devs[m]; 362 if (sc == NULL) 363 continue; 364 csr1 = MEMRD(MSREG_CSR1); 365 csr2 = MEMRD(MSREG_CSR2); 366 bitmask_snprintf(csr1, b1, sbuf, sizeof(sbuf)); 367 bitmask_snprintf(csr2, b2, sbuf2, sizeof(sbuf2)); 368 printf("%s: csr1=%s csr2=%s\n", sc->sc_dev.dv_xname, 369 sbuf, sbuf2); 370 if ((csr1 & MS1_ERRSUM) == 0) 371 continue; 372 hard = 1; 373 if (csr1 & MS1_BROKE) 374 type = "broke"; 375 else if (csr1 & MS1_CNTLERR) 376 type = "cntl err"; 377 else if (csr2 & MS2_ADRSERR) 378 type = "address parity err"; 379 else if (csr2 & MS2_RDSERR) 380 type = "rds err"; 381 else if (csr2 & MS2_CRDERR) { 382 hard = 0; 383 type = ""; 384 } else 385 type = "mysterious error"; 386 printf("%s: %s%s%s addr %x bank %x syn %x\n", 387 sc->sc_dev.dv_xname, hard ? "hard error: " : "soft ecc", 388 type, csr2 & MS2_HIERR ? " (+ other rds or crd err)" : "", 389 ((csr2 & MS2_ADDR) + MEMRD(BIREG_SADR)) >> 9, 390 (csr2 & MS2_INTLVADDR) != 0, csr2 & MS2_SYN); 391 MEMWR(MSREG_CSR1, csr1 | MS1_CRDINH); 392 MEMWR(MSREG_CSR2, csr2); 393 } 394 } 395 396 /* these are bits 0 to 6 in the summary field */ 397 char *mc8200[] = { 398 "cpu bad ipl", "ucode lost err", 399 "ucode par err", "DAL par err", 400 "BI bus err", "BTB tag par", 401 "cache tag par", 402 }; 403 #define MC8200_BADIPL 0x01 404 #define MC8200_UERR 0x02 405 #define MC8200_UPAR 0x04 406 #define MC8200_DPAR 0x08 407 #define MC8200_BIERR 0x10 408 #define MC8200_BTAGPAR 0x20 409 #define MC8200_CTAGPAR 0x40 410 411 struct mc8200frame { 412 int mc82_bcnt; /* byte count == 0x20 */ 413 int mc82_summary; /* summary parameter */ 414 int mc82_param1; /* parameter 1 */ 415 int mc82_va; /* va register */ 416 int mc82_vap; /* va prime register */ 417 int mc82_ma; /* memory address */ 418 int mc82_status; /* status word */ 419 int mc82_epc; /* error pc */ 420 int mc82_upc; /* micro pc */ 421 int mc82_pc; /* current pc */ 422 int mc82_psl; /* current psl */ 423 }; 424 425 static int 426 ka820_mchk(caddr_t cmcf) 427 { 428 register struct mc8200frame *mcf = (struct mc8200frame *)cmcf; 429 register int i, type = mcf->mc82_summary; 430 431 /* ignore BI bus errors during configuration */ 432 if (cold && type == MC8200_BIERR) { 433 mtpr(PR_MCESR, 0xf); 434 return (MCHK_RECOVERED); 435 } 436 437 /* 438 * SOME ERRORS ARE RECOVERABLE 439 * do it later 440 */ 441 printf("machine check %x: ", type); 442 for (i = 0; i < sizeof (mc8200) / sizeof (mc8200[0]); i++) 443 if (type & (1 << i)) 444 printf(" %s,", mc8200[i]); 445 printf(" param1 %x\n", mcf->mc82_param1); 446 printf( 447 "\tva %x va' %x ma %x pc %x psl %x\n\tstatus %x errpc %x upc %x\n", 448 mcf->mc82_va, mcf->mc82_vap, mcf->mc82_ma, 449 mcf->mc82_pc, mcf->mc82_psl, 450 mcf->mc82_status, mcf->mc82_epc, mcf->mc82_upc); 451 return (MCHK_PANIC); 452 } 453 454 #if defined(MULTIPROCESSOR) 455 #define RXBUF 80 456 static char rxbuf[RXBUF]; 457 static int got = 0, taken = 0; 458 static int expect = 0; 459 #endif 460 /* 461 * Receive a character from logical console. 462 */ 463 static void 464 rxcdintr(void *arg) 465 { 466 int c = mfpr(PR_RXCD); 467 468 if (c == 0) 469 return; 470 471 #if defined(MULTIPROCESSOR) 472 if (expect == ((c >> 8) & 0xf)) 473 rxbuf[got++] = c & 0xff; 474 475 if (got == RXBUF) 476 got = 0; 477 #endif 478 } 479 480 #if defined(MULTIPROCESSOR) 481 int 482 rxchar() 483 { 484 int ret; 485 486 if (got == taken) 487 return 0; 488 489 ret = rxbuf[taken++]; 490 if (taken == RXBUF) 491 taken = 0; 492 return ret; 493 } 494 #endif 495 496 int 497 ka820_clkread(time_t base) 498 { 499 struct clock_ymdhms c; 500 int s; 501 502 while (ka820_clkpage->csr0 & KA820CLK_0_BUSY) 503 ; 504 s = splhigh(); 505 c.dt_sec = ka820_clkpage->sec; 506 c.dt_min = ka820_clkpage->min; 507 c.dt_hour = ka820_clkpage->hr; 508 c.dt_wday = ka820_clkpage->dayofwk; 509 c.dt_day = ka820_clkpage->day; 510 c.dt_mon = ka820_clkpage->mon; 511 c.dt_year = ka820_clkpage->yr; 512 splx(s); 513 514 /* strange conversion */ 515 c.dt_sec = ((c.dt_sec << 7) | (c.dt_sec >> 1)) & 0377; 516 c.dt_min = ((c.dt_min << 7) | (c.dt_min >> 1)) & 0377; 517 c.dt_hour = ((c.dt_hour << 7) | (c.dt_hour >> 1)) & 0377; 518 c.dt_wday = ((c.dt_wday << 7) | (c.dt_wday >> 1)) & 0377; 519 c.dt_day = ((c.dt_day << 7) | (c.dt_day >> 1)) & 0377; 520 c.dt_mon = ((c.dt_mon << 7) | (c.dt_mon >> 1)) & 0377; 521 c.dt_year = ((c.dt_year << 7) | (c.dt_year >> 1)) & 0377; 522 523 time.tv_sec = clock_ymdhms_to_secs(&c); 524 return CLKREAD_OK; 525 } 526 527 void 528 ka820_clkwrite(void) 529 { 530 struct clock_ymdhms c; 531 532 clock_secs_to_ymdhms(time.tv_sec, &c); 533 534 ka820_clkpage->csr1 = KA820CLK_1_SET; 535 ka820_clkpage->sec = ((c.dt_sec << 1) | (c.dt_sec >> 7)) & 0377; 536 ka820_clkpage->min = ((c.dt_min << 1) | (c.dt_min >> 7)) & 0377; 537 ka820_clkpage->hr = ((c.dt_hour << 1) | (c.dt_hour >> 7)) & 0377; 538 ka820_clkpage->dayofwk = ((c.dt_wday << 1) | (c.dt_wday >> 7)) & 0377; 539 ka820_clkpage->day = ((c.dt_day << 1) | (c.dt_day >> 7)) & 0377; 540 ka820_clkpage->mon = ((c.dt_mon << 1) | (c.dt_mon >> 7)) & 0377; 541 ka820_clkpage->yr = ((c.dt_year << 1) | (c.dt_year >> 7)) & 0377; 542 543 ka820_clkpage->csr1 = KA820CLK_1_GO; 544 } 545 546 #if defined(MULTIPROCESSOR) 547 static void 548 ka820_startslave(struct device *dev, struct cpu_info *ci) 549 { 550 struct ka820_softc *sc = (void *)dev; 551 int id = sc->sc_binid; 552 int i; 553 554 expect = sc->sc_binid; 555 /* First empty queue */ 556 for (i = 0; i < 10000; i++) 557 if (rxchar()) 558 i = 0; 559 ka820_txrx(id, "\020", 0); /* Send ^P to get attention */ 560 ka820_txrx(id, "I\r", 0); /* Init other end */ 561 ka820_txrx(id, "D/I 4 %x\r", ci->ci_istack); /* Interrupt stack */ 562 ka820_txrx(id, "D/I C %x\r", mfpr(PR_SBR)); /* SBR */ 563 ka820_txrx(id, "D/I D %x\r", mfpr(PR_SLR)); /* SLR */ 564 ka820_txrx(id, "D/I 10 %x\r", (int)ci->ci_pcb); /* PCB for idle proc */ 565 ka820_txrx(id, "D/I 11 %x\r", mfpr(PR_SCBB)); /* SCB */ 566 ka820_txrx(id, "D/I 38 %x\r", mfpr(PR_MAPEN)); /* Enable MM */ 567 ka820_txrx(id, "S %x\r", (int)&tramp); /* Start! */ 568 expect = 0; 569 for (i = 0; i < 10000; i++) 570 if ((volatile int)ci->ci_flags & CI_RUNNING) 571 break; 572 if (i == 10000) 573 printf("%s: (ID %d) failed starting??!!??\n", 574 dev->dv_xname, sc->sc_binid); 575 } 576 577 void 578 ka820_txrx(int id, char *fmt, int arg) 579 { 580 char buf[20]; 581 582 sprintf(buf, fmt, arg); 583 ka820_sendstr(id, buf); 584 ka820_sergeant(id); 585 } 586 587 static void 588 ka820_sendchr(int chr) 589 { 590 /* 591 * It seems like mtpr to TXCD sets the V flag if it fails. 592 * Cannot check that flag in C... 593 */ 594 asm __volatile("1:;mtpr %0,$92;bvs 1b" :: "g"(chr)); 595 } 596 597 void 598 ka820_sendstr(int id, char *buf) 599 { 600 u_int utchr; 601 int ch, i; 602 603 while (*buf) { 604 utchr = *buf | id << 8; 605 606 ka820_sendchr(utchr); 607 buf++; 608 i = 30000; 609 while ((ch = rxchar()) == 0 && --i) 610 ; 611 if (ch == 0) 612 continue; /* failed */ 613 } 614 } 615 616 void 617 ka820_sergeant(int id) 618 { 619 int i, ch, nserg; 620 621 nserg = 0; 622 for (i = 0; i < 30000; i++) { 623 if ((ch = rxchar()) == 0) 624 continue; 625 if (ch == '>') 626 nserg++; 627 else 628 nserg = 0; 629 i = 0; 630 if (nserg == 3) 631 break; 632 } 633 /* What to do now??? */ 634 } 635 636 /* 637 * Write to master console. 638 */ 639 static volatile int ch = 0; 640 641 void 642 ka820_putc(int c) 643 { 644 if (curcpu()->ci_flags & CI_MASTERCPU) { 645 gencnputc(0, c); 646 return; 647 } 648 ch = c; 649 650 cpu_send_ipi(IPI_DEST_MASTER, IPI_SEND_CNCHAR); 651 while (ch != 0) 652 ; /* Wait for master to handle */ 653 } 654 655 /* 656 * Got character IPI. 657 */ 658 void 659 ka820_cnintr() 660 { 661 if (ch != 0) 662 gencnputc(0, ch); 663 ch = 0; /* Release slavecpu */ 664 } 665 666 void 667 ka820_send_ipi(struct device *dev) 668 { 669 struct ka820_softc *sc = (void *)dev; 670 671 mtpr(1 << sc->sc_binid, PR_IPIR); 672 } 673 674 void 675 ka820_ipintr(void *arg) 676 { 677 cpu_handle_ipi(); 678 } 679 #endif 680