ka88.c revision 1.1
1/* $NetBSD: ka88.c,v 1.1 2000/07/26 11:47:17 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 * 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 158struct cfattach cpu_nmi_ca = { 159 sizeof(struct ka88_softc), ka88_match, ka88_attach 160}; 161 162struct mem_nmi_softc { 163 struct device sc_dev; 164 bus_space_tag_t sc_iot; 165 bus_space_handle_t sc_ioh; 166}; 167 168static int 169ms88_match(struct device *parent, struct cfdata *cf, void *aux) 170{ 171 struct nmi_attach_args *na = aux; 172 173 if (cf->cf_loc[NMICF_SLOT] != NMICF_SLOT_DEFAULT && 174 cf->cf_loc[NMICF_SLOT] != na->slot) 175 return 0; 176 if (na->slot != 10) 177 return 0; 178 return 1; 179} 180 181static void 182ms88_attach(struct device *parent, struct device *self, void *aux) 183{ 184 printf("\n"); 185} 186 187struct cfattach mem_nmi_ca = { 188 sizeof(struct mem_nmi_softc), ms88_match, ms88_attach 189}; 190 191static void 192ka88_badaddr(void) 193{ 194 volatile int hej; 195 /* 196 * This is some magic to clear the NMI faults, described 197 * in section 7.9 in the VAX 8800 System Maintenance Guide. 198 */ 199 hej = ka88_mcl[5]; 200 hej = ka88_mcl[0]; 201 ka88_mcl[0] = 0x04000000; 202 mtpr(1, 0x88); 203} 204 205static void 206ka88_memerr() 207{ 208 printf("ka88_memerr\n"); 209} 210 211struct mc88frame { 212 int mc64_summary; /* summary parameter */ 213 int mc64_va; /* va register */ 214 int mc64_vb; /* memory address */ 215 int mc64_sisr; /* status word */ 216 int mc64_state; /* error pc */ 217 int mc64_sc; /* micro pc */ 218 int mc64_pc; /* current pc */ 219 int mc64_psl; /* current psl */ 220}; 221 222static int 223ka88_mchk(caddr_t cmcf) 224{ 225 return (MCHK_PANIC); 226} 227 228#if defined(MULTIPROCESSOR) 229#define RXBUF 80 230static char rxbuf[RXBUF]; 231static int got = 0, taken = 0; 232static int expect = 0; 233#endif 234#if 0 235/* 236 * Receive a character from logical console. 237 */ 238static void 239rxcdintr(void *arg) 240{ 241 int c = mfpr(PR_RXCD); 242 243 if (c == 0) 244 return; 245 246#if defined(MULTIPROCESSOR) 247 if ((c & 0xff) == 0) { 248 if (curcpu()->ci_flags & CI_MASTERCPU) 249 ka88_cnintr(); 250 return; 251 } 252 253 if (expect == ((c >> 8) & 0xf)) 254 rxbuf[got++] = c & 0xff; 255 256 if (got == RXBUF) 257 got = 0; 258#endif 259} 260#endif 261 262static void 263tocons(int val) 264{ 265 int s = splimp(); 266 267 while ((mfpr(PR_TXCS) & GC_RDY) == 0) /* Wait until xmit ready */ 268 ; 269 mtpr(val, PR_TXDB); /* xmit character */ 270 splx(s); 271} 272 273static int 274fromcons(int func) 275{ 276 int ret, s = splimp(); 277 278 while (1) { 279 while ((mfpr(PR_RXCS) & GC_DON) == 0) 280 ; 281 ret = mfpr(PR_RXDB); 282 if ((ret & 0xf00) == func) 283 break; 284 } 285 splx(s); 286 return ret; 287} 288 289static int 290ka88_clkread(time_t base) 291{ 292 union {u_int ret;u_char r[4];} u; 293 int i, s = splimp(); 294 295 tocons(KA88_COMM|KA88_TOYREAD); 296 for (i = 0; i < 4; i++) { 297 u.r[i] = fromcons(KA88_TOY) & 255; 298 } 299 splx(s); 300 return u.ret; 301} 302 303static void 304ka88_clkwrite(void) 305{ 306 union {u_int ret;u_char r[4];} u; 307 int i, s = splimp(); 308 309 u.ret = time.tv_sec - yeartonum(numtoyear(time.tv_sec)); 310 tocons(KA88_COMM|KA88_TOYWRITE); 311 for (i = 0; i < 4; i++) 312 tocons(KA88_TOY|u.r[i]); 313 splx(s); 314} 315 316void 317ka88_steal_pages(void) 318{ 319 mtpr(1, PR_COR); /* Cache on */ 320 strcpy(cpu_model, "VAX 8800"); 321 tocons(KA88_COMM|KA88_GETCONF); 322 ka88_confdata = fromcons(KA88_CONFDATA); 323 ka88_confdata = mfpr(PR_RXDB); 324 mastercpu = 20; 325 if (vax_cputype == VAX_TYP_8NN) { 326 if (ka88_confdata & KA88_SMALL) { 327 cpu_model[5] = '5'; 328 if (ka88_confdata & KA88_SLOW) { 329 vax_boardtype = VAX_BTYP_8500; 330 cpu_model[6] = '3'; 331 } else { 332 vax_boardtype = VAX_BTYP_8550; 333 cpu_model[6] = '5'; 334 } 335 } else if (ka88_confdata & KA88_SINGLE) { 336 vax_boardtype = VAX_BTYP_8700; 337 cpu_model[5] = '7'; 338 } 339 } 340} 341 342 343#if defined(MULTIPROCESSOR) && 0 344int 345rxchar() 346{ 347 int ret; 348 349 if (got == taken) 350 return 0; 351 352 ret = rxbuf[taken++]; 353 if (taken == RXBUF) 354 taken = 0; 355 return ret; 356} 357 358static void 359ka88_startslave(struct device *dev, struct cpu_info *ci) 360{ 361 struct ka88_softc *sc = (void *)dev; 362 int id = sc->sc_binid; 363 int i; 364 365 expect = sc->sc_binid; 366 /* First empty queue */ 367 for (i = 0; i < 10000; i++) 368 if (rxchar()) 369 i = 0; 370 ka88_txrx(id, "\020", 0); /* Send ^P to get attention */ 371 ka88_txrx(id, "I\r", 0); /* Init other end */ 372 ka88_txrx(id, "D/I 4 %x\r", ci->ci_istack); /* Interrupt stack */ 373 ka88_txrx(id, "D/I C %x\r", mfpr(PR_SBR)); /* SBR */ 374 ka88_txrx(id, "D/I D %x\r", mfpr(PR_SLR)); /* SLR */ 375 ka88_txrx(id, "D/I 10 %x\r", (int)ci->ci_pcb); /* PCB for idle proc */ 376 ka88_txrx(id, "D/I 11 %x\r", mfpr(PR_SCBB)); /* SCB */ 377 ka88_txrx(id, "D/I 38 %x\r", mfpr(PR_MAPEN)); /* Enable MM */ 378 ka88_txrx(id, "S %x\r", (int)&tramp); /* Start! */ 379 expect = 0; 380 for (i = 0; i < 10000; i++) 381 if ((volatile)ci->ci_flags & CI_RUNNING) 382 break; 383 if (i == 10000) 384 printf("%s: (ID %d) failed starting??!!??\n", 385 dev->dv_xname, sc->sc_binid); 386} 387 388void 389ka88_txrx(int id, char *fmt, int arg) 390{ 391 char buf[20]; 392 393 sprintf(buf, fmt, arg); 394 ka88_sendstr(id, buf); 395 ka88_sergeant(id); 396} 397 398void 399ka88_sendstr(int id, char *buf) 400{ 401 register u_int utchr; /* Ends up in R11 with PCC */ 402 int ch, i; 403 404 while (*buf) { 405 utchr = *buf | id << 8; 406 407 /* 408 * It seems like mtpr to TXCD sets the V flag if it fails. 409 * Cannot check that flag in C... 410 */ 411#ifdef __GNUC__ 412 asm("1:;mtpr %0,$92;bvs 1b" :: "g"(utchr)); 413#else 414 asm("1:;mtpr r11,$92;bvs 1b"); 415#endif 416 buf++; 417 i = 30000; 418 while ((ch = rxchar()) == 0 && --i) 419 ; 420 if (ch == 0) 421 continue; /* failed */ 422 } 423} 424 425void 426ka88_sergeant(int id) 427{ 428 int i, ch, nserg; 429 430 nserg = 0; 431 for (i = 0; i < 30000; i++) { 432 if ((ch = rxchar()) == 0) 433 continue; 434 if (ch == '>') 435 nserg++; 436 else 437 nserg = 0; 438 i = 0; 439 if (nserg == 3) 440 break; 441 } 442 /* What to do now??? */ 443} 444 445/* 446 * Write to master console. 447 * Need no locking here; done in the print functions. 448 */ 449static volatile int ch = 0; 450 451void 452ka88_putc(int c) 453{ 454 if (curcpu()->ci_flags & CI_MASTERCPU) { 455 gencnputc(0, c); 456 return; 457 } 458 ch = c; 459 mtpr(mastercpu << 8, PR_RXCD); /* Send IPI to mastercpu */ 460 while (ch != 0) 461 ; /* Wait for master to handle */ 462} 463 464/* 465 * Got character IPI. 466 */ 467void 468ka88_cnintr() 469{ 470 if (ch != 0) 471 gencnputc(0, ch); 472 ch = 0; /* Release slavecpu */ 473} 474#endif 475