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