1 /* $NetBSD: ka820.c,v 1.31 2001/06/03 15:07:20 ragge 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 struct cfattach cpu_bi_ca = { 135 sizeof(struct ka820_softc), ka820_match, ka820_attach 136 }; 137 138 #ifdef notyet 139 extern struct pte BRAMmap[]; 140 extern struct pte EEPROMmap[]; 141 char bootram[KA820_BRPAGES * VAX_NBPG]; 142 char eeprom[KA820_EEPAGES * VAX_NBPG]; 143 #endif 144 145 static int 146 ka820_match(struct device *parent, struct cfdata *cf, void *aux) 147 { 148 struct bi_attach_args *ba = aux; 149 150 if (bus_space_read_2(ba->ba_iot, ba->ba_ioh, BIREG_DTYPE) != BIDT_KA820) 151 return 0; 152 153 if (cf->cf_loc[BICF_NODE] != BICF_NODE_DEFAULT && 154 cf->cf_loc[BICF_NODE] != ba->ba_nodenr) 155 return 0; 156 157 return 1; 158 } 159 160 static void 161 ka820_attach(struct device *parent, struct device *self, void *aux) 162 { 163 struct ka820_softc *sc = (void *)self; 164 struct bi_attach_args *ba = aux; 165 register int csr; 166 u_short rev; 167 168 rev = bus_space_read_4(ba->ba_iot, ba->ba_ioh, BIREG_DTYPE) >> 16; 169 mastercpu = mfpr(PR_BINID); 170 strcpy(cpu_model, "VAX 8200"); 171 cpu_model[6] = rev & 0x8000 ? '5' : '0'; 172 printf(": ka82%c (%s) cpu rev %d, u patch rev %d, sec patch %d\n", 173 cpu_model[6], mastercpu == ba->ba_nodenr ? "master" : "slave", 174 ((rev >> 11) & 15), ((rev >> 1) &1023), rev & 1); 175 sc->sc_binid = ba->ba_nodenr; 176 177 /* Allow for IPINTR */ 178 bus_space_write_4(ba->ba_iot, ba->ba_ioh, 179 BIREG_IPINTRMSK, BIIPINTR_MASK); 180 181 #if defined(MULTIPROCESSOR) 182 if (ba->ba_nodenr != mastercpu) { 183 v_putc = ka820_putc; /* Need special console handling */ 184 return cpu_slavesetup(self); 185 } 186 #endif 187 188 #if defined(MULTIPROCESSOR) 189 /* 190 * Catch interprocessor interrupts. 191 */ 192 scb_vecalloc(KA820_INT_IPINTR, ka820_ipintr, sc, SCB_ISTACK, NULL); 193 #endif 194 /* 195 * Copy cpu_info into new position. 196 */ 197 bcopy(curcpu(), &sc->sc_ci, sizeof(struct cpu_info)); 198 mtpr(&sc->sc_ci, PR_SSP); 199 proc0.p_addr->u_pcb.SSP = mfpr(PR_SSP); 200 proc0.p_cpu = curcpu(); 201 curcpu()->ci_dev = self; 202 203 /* reset the console and enable the RX50 */ 204 ka820port_ptr = (void *)vax_map_physmem(KA820_PORTADDR, 1); 205 csr = ka820port_ptr->csr; 206 csr &= ~KA820PORT_RSTHALT; /* ??? */ 207 csr |= KA820PORT_CONSCLR | KA820PORT_CRDCLR | KA820PORT_CONSEN | 208 KA820PORT_RXIE; 209 ka820port_ptr->csr = csr; 210 bus_space_write_4(ba->ba_iot, ba->ba_ioh, 211 BIREG_INTRDES, ba->ba_intcpu); 212 bus_space_write_4(ba->ba_iot, ba->ba_ioh, BIREG_VAXBICSR, 213 bus_space_read_4(ba->ba_iot, ba->ba_ioh, BIREG_VAXBICSR) | 214 BICSR_SEIE | BICSR_HEIE); 215 } 216 217 void 218 ka820_conf() 219 { 220 /* 221 * Setup parameters necessary to read time from clock chip. 222 */ 223 ka820_clkpage = (void *)vax_map_physmem(KA820_CLOCKADDR, 1); 224 225 /* Enable cache */ 226 mtpr(0, PR_CADR); 227 228 /* Steal the interrupt vectors that are unique for us */ 229 scb_vecalloc(KA820_INT_RXCD, rxcdintr, NULL, SCB_ISTACK, NULL); 230 scb_vecalloc(0x50, vaxbierr, NULL, SCB_ISTACK, NULL); 231 232 /* XXX - should be done somewhere else */ 233 scb_vecalloc(SCB_RX50, crxintr, NULL, SCB_ISTACK, NULL); 234 rx50device_ptr = (void *)vax_map_physmem(KA820_RX50ADDR, 1); 235 #if defined(MULTIPROCESSOR) 236 mp_dep_call = &ka820_mp_dep; 237 #endif 238 } 239 240 void 241 vaxbierr(void *arg) 242 { 243 if (cold == 0) 244 panic("vaxbierr"); 245 } 246 247 #ifdef notdef 248 /* 249 * MS820 support. 250 */ 251 struct ms820regs { 252 struct biiregs biic; /* BI interface chip */ 253 u_long ms_gpr[4]; /* the four gprs (unused) */ 254 int ms_csr1; /* control/status register 1 */ 255 int ms_csr2; /* control/status register 2 */ 256 }; 257 #endif 258 259 #define MEMRD(reg) bus_space_read_4(sc->sc_iot, sc->sc_ioh, (reg)) 260 #define MEMWR(reg, val) bus_space_write_4(sc->sc_iot, sc->sc_ioh, (reg), (val)) 261 262 #define MSREG_CSR1 0x100 263 #define MSREG_CSR2 0x104 264 /* 265 * Bits in CSR1. 266 */ 267 #define MS1_ERRSUM 0x80000000 /* error summary (ro) */ 268 #define MS1_ECCDIAG 0x40000000 /* ecc diagnostic (rw) */ 269 #define MS1_ECCDISABLE 0x20000000 /* ecc disable (rw) */ 270 #define MS1_MSIZEMASK 0x1ffc0000 /* mask for memory size (ro) */ 271 #define MS1_RAMTYMASK 0x00030000 /* mask for ram type (ro) */ 272 #define MS1_RAMTY64K 0x00000000 /* 64K chips */ 273 #define MS1_RAMTY256K 0x00010000 /* 256K chips */ 274 #define MS1_RAMTY1MB 0x00020000 /* 1MB chips */ 275 /* type 3 reserved */ 276 #define MS1_CRDINH 0x00008000 /* inhibit crd interrupts (rw) */ 277 #define MS1_MEMVALID 0x00004000 /* memory has been written (ro) */ 278 #define MS1_INTLK 0x00002000 /* interlock flag (ro) */ 279 #define MS1_BROKE 0x00001000 /* broken (rw) */ 280 #define MS1_MBZ 0x00000880 /* zero */ 281 #define MS1_MWRITEERR 0x00000400 /* rds during masked write (rw) */ 282 #define MS1_CNTLERR 0x00000200 /* internal timing busted (rw) */ 283 #define MS1_INTLV 0x00000100 /* internally interleaved (ro) */ 284 #define MS1_DIAGC 0x0000007f /* ecc diagnostic bits (rw) */ 285 286 /* 287 * Bits in CSR2. 288 */ 289 #define MS2_RDSERR 0x80000000 /* rds error (rw) */ 290 #define MS2_HIERR 0x40000000 /* high error rate (rw) */ 291 #define MS2_CRDERR 0x20000000 /* crd error (rw) */ 292 #define MS2_ADRSERR 0x10000000 /* rds due to addr par err (rw) */ 293 #define MS2_MBZ 0x0f000080 /* zero */ 294 #define MS2_ADDR 0x00fffe00 /* address in error (relative) (ro) */ 295 #define MS2_INTLVADDR 0x00000100 /* error was in bank 1 (ro) */ 296 #define MS2_SYN 0x0000007f /* error syndrome (ro, rw diag) */ 297 298 static int ms820_match(struct device *, struct cfdata *, void *); 299 static void ms820_attach(struct device *, struct device *, void*); 300 301 struct mem_bi_softc { 302 struct device sc_dev; 303 bus_space_tag_t sc_iot; 304 bus_space_handle_t sc_ioh; 305 }; 306 307 struct cfattach mem_bi_ca = { 308 sizeof(struct mem_bi_softc), ms820_match, ms820_attach 309 }; 310 311 static int 312 ms820_match(struct device *parent, struct cfdata *cf, void *aux) 313 { 314 struct bi_attach_args *ba = aux; 315 316 if (bus_space_read_2(ba->ba_iot, ba->ba_ioh, BIREG_DTYPE) != BIDT_MS820) 317 return 0; 318 319 if (cf->cf_loc[BICF_NODE] != BICF_NODE_DEFAULT && 320 cf->cf_loc[BICF_NODE] != ba->ba_nodenr) 321 return 0; 322 323 return 1; 324 } 325 326 static void 327 ms820_attach(struct device *parent, struct device *self, void *aux) 328 { 329 struct mem_bi_softc *sc = (void *)self; 330 struct bi_attach_args *ba = aux; 331 332 sc->sc_iot = ba->ba_iot; 333 sc->sc_ioh = ba->ba_ioh; 334 335 if ((MEMRD(BIREG_VAXBICSR) & BICSR_STS) == 0) 336 printf(": failed self test\n"); 337 else 338 printf(": size %dMB, %s chips\n", ((MEMRD(MSREG_CSR1) & 339 MS1_MSIZEMASK) >> 20), (MEMRD(MSREG_CSR1) & MS1_RAMTYMASK 340 ? MEMRD(MSREG_CSR1) & MS1_RAMTY256K ? "256K":"1M":"64K")); 341 342 MEMWR(BIREG_INTRDES, ba->ba_intcpu); 343 MEMWR(BIREG_VAXBICSR, MEMRD(BIREG_VAXBICSR) | BICSR_SEIE | BICSR_HEIE); 344 345 MEMWR(MSREG_CSR1, MS1_MWRITEERR | MS1_CNTLERR); 346 MEMWR(MSREG_CSR2, MS2_RDSERR | MS2_HIERR | MS2_CRDERR | MS2_ADRSERR); 347 } 348 349 static void 350 ka820_memerr() 351 { 352 struct mem_bi_softc *sc; 353 int m, hard, csr1, csr2; 354 char *type; 355 356 static char b1[] = "\20\40ERRSUM\37ECCDIAG\36ECCDISABLE\20CRDINH\17VALID\ 357 \16INTLK\15BROKE\13MWRITEERR\12CNTLERR\11INTLV"; 358 static char b2[] = "\20\40RDS\37HIERR\36CRD\35ADRS"; 359 360 char sbuf[sizeof(b1) + 64], sbuf2[sizeof(b2) + 64]; 361 362 for (m = 0; m < mem_cd.cd_ndevs; m++) { 363 sc = mem_cd.cd_devs[m]; 364 if (sc == NULL) 365 continue; 366 csr1 = MEMRD(MSREG_CSR1); 367 csr2 = MEMRD(MSREG_CSR2); 368 bitmask_snprintf(csr1, b1, sbuf, sizeof(sbuf)); 369 bitmask_snprintf(csr2, b2, sbuf2, sizeof(sbuf2)); 370 printf("%s: csr1=%s csr2=%s\n", sc->sc_dev.dv_xname, 371 sbuf, sbuf2); 372 if ((csr1 & MS1_ERRSUM) == 0) 373 continue; 374 hard = 1; 375 if (csr1 & MS1_BROKE) 376 type = "broke"; 377 else if (csr1 & MS1_CNTLERR) 378 type = "cntl err"; 379 else if (csr2 & MS2_ADRSERR) 380 type = "address parity err"; 381 else if (csr2 & MS2_RDSERR) 382 type = "rds err"; 383 else if (csr2 & MS2_CRDERR) { 384 hard = 0; 385 type = ""; 386 } else 387 type = "mysterious error"; 388 printf("%s: %s%s%s addr %x bank %x syn %x\n", 389 sc->sc_dev.dv_xname, hard ? "hard error: " : "soft ecc", 390 type, csr2 & MS2_HIERR ? " (+ other rds or crd err)" : "", 391 ((csr2 & MS2_ADDR) + MEMRD(BIREG_SADR)) >> 9, 392 (csr2 & MS2_INTLVADDR) != 0, csr2 & MS2_SYN); 393 MEMWR(MSREG_CSR1, csr1 | MS1_CRDINH); 394 MEMWR(MSREG_CSR2, csr2); 395 } 396 } 397 398 /* these are bits 0 to 6 in the summary field */ 399 char *mc8200[] = { 400 "cpu bad ipl", "ucode lost err", 401 "ucode par err", "DAL par err", 402 "BI bus err", "BTB tag par", 403 "cache tag par", 404 }; 405 #define MC8200_BADIPL 0x01 406 #define MC8200_UERR 0x02 407 #define MC8200_UPAR 0x04 408 #define MC8200_DPAR 0x08 409 #define MC8200_BIERR 0x10 410 #define MC8200_BTAGPAR 0x20 411 #define MC8200_CTAGPAR 0x40 412 413 struct mc8200frame { 414 int mc82_bcnt; /* byte count == 0x20 */ 415 int mc82_summary; /* summary parameter */ 416 int mc82_param1; /* parameter 1 */ 417 int mc82_va; /* va register */ 418 int mc82_vap; /* va prime register */ 419 int mc82_ma; /* memory address */ 420 int mc82_status; /* status word */ 421 int mc82_epc; /* error pc */ 422 int mc82_upc; /* micro pc */ 423 int mc82_pc; /* current pc */ 424 int mc82_psl; /* current psl */ 425 }; 426 427 static int 428 ka820_mchk(caddr_t cmcf) 429 { 430 register struct mc8200frame *mcf = (struct mc8200frame *)cmcf; 431 register int i, type = mcf->mc82_summary; 432 433 /* ignore BI bus errors during configuration */ 434 if (cold && type == MC8200_BIERR) { 435 mtpr(PR_MCESR, 0xf); 436 return (MCHK_RECOVERED); 437 } 438 439 /* 440 * SOME ERRORS ARE RECOVERABLE 441 * do it later 442 */ 443 printf("machine check %x: ", type); 444 for (i = 0; i < sizeof (mc8200) / sizeof (mc8200[0]); i++) 445 if (type & (1 << i)) 446 printf(" %s,", mc8200[i]); 447 printf(" param1 %x\n", mcf->mc82_param1); 448 printf( 449 "\tva %x va' %x ma %x pc %x psl %x\n\tstatus %x errpc %x upc %x\n", 450 mcf->mc82_va, mcf->mc82_vap, mcf->mc82_ma, 451 mcf->mc82_pc, mcf->mc82_psl, 452 mcf->mc82_status, mcf->mc82_epc, mcf->mc82_upc); 453 return (MCHK_PANIC); 454 } 455 456 #if defined(MULTIPROCESSOR) 457 #define RXBUF 80 458 static char rxbuf[RXBUF]; 459 static int got = 0, taken = 0; 460 static int expect = 0; 461 #endif 462 /* 463 * Receive a character from logical console. 464 */ 465 static void 466 rxcdintr(void *arg) 467 { 468 int c = mfpr(PR_RXCD); 469 470 if (c == 0) 471 return; 472 473 #if defined(MULTIPROCESSOR) 474 if (expect == ((c >> 8) & 0xf)) 475 rxbuf[got++] = c & 0xff; 476 477 if (got == RXBUF) 478 got = 0; 479 #endif 480 } 481 482 #if defined(MULTIPROCESSOR) 483 int 484 rxchar() 485 { 486 int ret; 487 488 if (got == taken) 489 return 0; 490 491 ret = rxbuf[taken++]; 492 if (taken == RXBUF) 493 taken = 0; 494 return ret; 495 } 496 #endif 497 498 int 499 ka820_clkread(time_t base) 500 { 501 struct clock_ymdhms c; 502 int s; 503 504 while (ka820_clkpage->csr0 & KA820CLK_0_BUSY) 505 ; 506 s = splhigh(); 507 c.dt_sec = ka820_clkpage->sec; 508 c.dt_min = ka820_clkpage->min; 509 c.dt_hour = ka820_clkpage->hr; 510 c.dt_wday = ka820_clkpage->dayofwk; 511 c.dt_day = ka820_clkpage->day; 512 c.dt_mon = ka820_clkpage->mon; 513 c.dt_year = ka820_clkpage->yr; 514 splx(s); 515 516 /* strange conversion */ 517 c.dt_sec = ((c.dt_sec << 7) | (c.dt_sec >> 1)) & 0377; 518 c.dt_min = ((c.dt_min << 7) | (c.dt_min >> 1)) & 0377; 519 c.dt_hour = ((c.dt_hour << 7) | (c.dt_hour >> 1)) & 0377; 520 c.dt_wday = ((c.dt_wday << 7) | (c.dt_wday >> 1)) & 0377; 521 c.dt_day = ((c.dt_day << 7) | (c.dt_day >> 1)) & 0377; 522 c.dt_mon = ((c.dt_mon << 7) | (c.dt_mon >> 1)) & 0377; 523 c.dt_year = ((c.dt_year << 7) | (c.dt_year >> 1)) & 0377; 524 525 time.tv_sec = clock_ymdhms_to_secs(&c); 526 return CLKREAD_OK; 527 } 528 529 void 530 ka820_clkwrite(void) 531 { 532 struct clock_ymdhms c; 533 534 clock_secs_to_ymdhms(time.tv_sec, &c); 535 536 ka820_clkpage->csr1 = KA820CLK_1_SET; 537 ka820_clkpage->sec = ((c.dt_sec << 1) | (c.dt_sec >> 7)) & 0377; 538 ka820_clkpage->min = ((c.dt_min << 1) | (c.dt_min >> 7)) & 0377; 539 ka820_clkpage->hr = ((c.dt_hour << 1) | (c.dt_hour >> 7)) & 0377; 540 ka820_clkpage->dayofwk = ((c.dt_wday << 1) | (c.dt_wday >> 7)) & 0377; 541 ka820_clkpage->day = ((c.dt_day << 1) | (c.dt_day >> 7)) & 0377; 542 ka820_clkpage->mon = ((c.dt_mon << 1) | (c.dt_mon >> 7)) & 0377; 543 ka820_clkpage->yr = ((c.dt_year << 1) | (c.dt_year >> 7)) & 0377; 544 545 ka820_clkpage->csr1 = KA820CLK_1_GO; 546 } 547 548 #if defined(MULTIPROCESSOR) 549 static void 550 ka820_startslave(struct device *dev, struct cpu_info *ci) 551 { 552 struct ka820_softc *sc = (void *)dev; 553 int id = sc->sc_binid; 554 int i; 555 556 expect = sc->sc_binid; 557 /* First empty queue */ 558 for (i = 0; i < 10000; i++) 559 if (rxchar()) 560 i = 0; 561 ka820_txrx(id, "\020", 0); /* Send ^P to get attention */ 562 ka820_txrx(id, "I\r", 0); /* Init other end */ 563 ka820_txrx(id, "D/I 4 %x\r", ci->ci_istack); /* Interrupt stack */ 564 ka820_txrx(id, "D/I C %x\r", mfpr(PR_SBR)); /* SBR */ 565 ka820_txrx(id, "D/I D %x\r", mfpr(PR_SLR)); /* SLR */ 566 ka820_txrx(id, "D/I 10 %x\r", (int)ci->ci_pcb); /* PCB for idle proc */ 567 ka820_txrx(id, "D/I 11 %x\r", mfpr(PR_SCBB)); /* SCB */ 568 ka820_txrx(id, "D/I 38 %x\r", mfpr(PR_MAPEN)); /* Enable MM */ 569 ka820_txrx(id, "S %x\r", (int)&tramp); /* Start! */ 570 expect = 0; 571 for (i = 0; i < 10000; i++) 572 if ((volatile)ci->ci_flags & CI_RUNNING) 573 break; 574 if (i == 10000) 575 printf("%s: (ID %d) failed starting??!!??\n", 576 dev->dv_xname, sc->sc_binid); 577 } 578 579 void 580 ka820_txrx(int id, char *fmt, int arg) 581 { 582 char buf[20]; 583 584 sprintf(buf, fmt, arg); 585 ka820_sendstr(id, buf); 586 ka820_sergeant(id); 587 } 588 589 static void 590 ka820_sendchr(int chr) 591 { 592 /* 593 * It seems like mtpr to TXCD sets the V flag if it fails. 594 * Cannot check that flag in C... 595 */ 596 asm __volatile("1:;mtpr %0,$92;bvs 1b" :: "g"(chr)); 597 } 598 599 void 600 ka820_sendstr(int id, char *buf) 601 { 602 u_int utchr; 603 int ch, i; 604 605 while (*buf) { 606 utchr = *buf | id << 8; 607 608 ka820_sendchr(utchr); 609 buf++; 610 i = 30000; 611 while ((ch = rxchar()) == 0 && --i) 612 ; 613 if (ch == 0) 614 continue; /* failed */ 615 } 616 } 617 618 void 619 ka820_sergeant(int id) 620 { 621 int i, ch, nserg; 622 623 nserg = 0; 624 for (i = 0; i < 30000; i++) { 625 if ((ch = rxchar()) == 0) 626 continue; 627 if (ch == '>') 628 nserg++; 629 else 630 nserg = 0; 631 i = 0; 632 if (nserg == 3) 633 break; 634 } 635 /* What to do now??? */ 636 } 637 638 /* 639 * Write to master console. 640 */ 641 static volatile int ch = 0; 642 643 void 644 ka820_putc(int c) 645 { 646 if (curcpu()->ci_flags & CI_MASTERCPU) { 647 gencnputc(0, c); 648 return; 649 } 650 ch = c; 651 652 cpu_send_ipi(IPI_DEST_MASTER, IPI_SEND_CNCHAR); 653 while (ch != 0) 654 ; /* Wait for master to handle */ 655 } 656 657 /* 658 * Got character IPI. 659 */ 660 void 661 ka820_cnintr() 662 { 663 if (ch != 0) 664 gencnputc(0, ch); 665 ch = 0; /* Release slavecpu */ 666 } 667 668 void 669 ka820_send_ipi(struct device *dev) 670 { 671 struct ka820_softc *sc = (void *)dev; 672 673 mtpr(1 << sc->sc_binid, PR_IPIR); 674 } 675 676 void 677 ka820_ipintr(void *arg) 678 { 679 cpu_handle_ipi(); 680 } 681 #endif 682