ka88.c revision 1.21
11.21Sriastrad/* $NetBSD: ka88.c,v 1.21 2022/03/03 06:28:26 riastradh Exp $ */ 21.1Sragge 31.1Sragge/* 41.1Sragge * Copyright (c) 2000 Ludd, University of Lule}, Sweden. All rights reserved. 51.1Sragge * 61.1Sragge * Redistribution and use in source and binary forms, with or without 71.1Sragge * modification, are permitted provided that the following conditions 81.1Sragge * are met: 91.1Sragge * 1. Redistributions of source code must retain the above copyright 101.1Sragge * notice, this list of conditions and the following disclaimer. 111.1Sragge * 2. Redistributions in binary form must reproduce the above copyright 121.1Sragge * notice, this list of conditions and the following disclaimer in the 131.1Sragge * documentation and/or other materials provided with the distribution. 141.1Sragge * 151.1Sragge * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 161.1Sragge * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 171.1Sragge * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 181.1Sragge * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 191.1Sragge * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 201.1Sragge * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 211.1Sragge * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 221.1Sragge * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 231.1Sragge * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 241.1Sragge * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 251.1Sragge */ 261.1Sragge 271.1Sragge/* 281.1Sragge * KA88 specific CPU code. 291.1Sragge */ 301.1Sragge/* 311.1Sragge * TODO: 321.1Sragge * - Machine check code 331.1Sragge */ 341.6Slukem 351.6Slukem#include <sys/cdefs.h> 361.21Sriastrad__KERNEL_RCSID(0, "$NetBSD: ka88.c,v 1.21 2022/03/03 06:28:26 riastradh Exp $"); 371.1Sragge 381.1Sragge#include "opt_multiprocessor.h" 391.1Sragge 401.1Sragge#include <sys/param.h> 411.1Sragge#include <sys/systm.h> 421.15Smatt#include <sys/bus.h> 431.13Smatt#include <sys/cpu.h> 441.15Smatt#include <sys/device.h> 451.15Smatt#include <sys/kernel.h> 461.13Smatt#include <sys/malloc.h> 471.13Smatt#include <sys/lwp.h> 481.1Sragge 491.1Sragge#include <machine/nexus.h> 501.1Sragge#include <machine/clock.h> 511.1Sragge#include <machine/scb.h> 521.1Sragge#include <machine/sid.h> 531.1Sragge#include <machine/rpb.h> 541.1Sragge#include <machine/ka88.h> 551.1Sragge 561.13Smatt#include <dev/cons.h> 571.1Sragge#include <vax/vax/gencons.h> 581.1Sragge 591.1Sragge#include "ioconf.h" 601.1Sragge#include "locators.h" 611.1Sragge 621.1Sraggestatic void ka88_memerr(void); 631.1Sraggestatic void ka88_conf(void); 641.11Schristosstatic int ka88_mchk(void *); 651.1Sraggestatic void ka88_steal_pages(void); 661.10Smattstatic int ka88_gettime(volatile struct timeval *); 671.10Smattstatic void ka88_settime(volatile struct timeval *); 681.1Sraggestatic void ka88_badaddr(void); 691.13Smatt 701.13Smattstatic long *ka88_mcl; 711.13Smattstatic int mastercpu; 721.13Smatt 731.13Smattstatic const char * const ka88_devs[] = { "nmi", NULL }; 741.13Smatt 751.13Smattconst struct cpu_dep ka88_calls = { 761.13Smatt .cpu_steal_pages = ka88_steal_pages, 771.13Smatt .cpu_mchk = ka88_mchk, 781.13Smatt .cpu_memerr = ka88_memerr, 791.13Smatt .cpu_conf = ka88_conf, 801.13Smatt .cpu_gettime = ka88_gettime, 811.13Smatt .cpu_settime = ka88_settime, 821.13Smatt .cpu_vups = 6, /* ~VUPS */ 831.13Smatt .cpu_scbsz = 64, /* SCB pages */ 841.13Smatt .cpu_devs = ka88_devs, 851.13Smatt .cpu_badaddr = ka88_badaddr, 861.13Smatt}; 871.13Smatt 881.1Sragge#if defined(MULTIPROCESSOR) 891.13Smattstatic void ka88_startslave(struct cpu_info *); 901.18Schristosstatic void ka88_txrx(int, const char *, ...) __printflike(2, 3); 911.7Shestatic void ka88_sendstr(int, const char *); 921.1Sraggestatic void ka88_sergeant(int); 931.1Sraggestatic int rxchar(void); 941.1Sraggestatic void ka88_putc(int); 951.1Sraggestatic void ka88_cnintr(void); 961.1Sraggecons_decl(gen); 971.1Sragge 981.13Smattconst struct cpu_mp_dep ka88_mp_calls = { 991.13Smatt .cpu_startslave = ka88_startslave, 1001.13Smatt .cpu_cnintr = ka88_cnintr, 1011.13Smatt}; 1021.1Sragge#endif 1031.1Sragge 1041.1Sraggestatic void 1051.1Sraggeka88_conf(void) 1061.1Sragge{ 1071.1Sragge ka88_mcl = (void *)vax_map_physmem(0x3e000000, 1); 1081.1Sragge printf("Serial number %d, rev %d\n", 1091.1Sragge mfpr(PR_SID) & 65535, (mfpr(PR_SID) >> 16) & 127); 1101.13Smatt#ifdef MULTIPROCESSOR 1111.13Smatt mp_dep_call = &ka88_mp_calls; 1121.13Smatt#endif 1131.1Sragge} 1141.1Sragge 1151.1Sraggestatic int 1161.13Smattka88_cpu_match(device_t parent, cfdata_t cf, void *aux) 1171.1Sragge{ 1181.13Smatt struct nmi_attach_args * const na = aux; 1191.1Sragge 1201.1Sragge if (cf->cf_loc[NMICF_SLOT] != NMICF_SLOT_DEFAULT && 1211.13Smatt cf->cf_loc[NMICF_SLOT] != na->na_slot) 1221.1Sragge return 0; 1231.13Smatt if (na->na_slot >= 20) 1241.1Sragge return 1; 1251.1Sragge return 0; 1261.1Sragge} 1271.1Sragge 1281.1Sraggestatic void 1291.13Smattka88_cpu_attach(device_t parent, device_t self, void *aux) 1301.1Sragge{ 1311.13Smatt struct cpu_info *ci; 1321.13Smatt struct nmi_attach_args * const na = aux; 1331.13Smatt const char *ms, *lr; 1341.13Smatt const bool master = (na->na_slot == mastercpu); 1351.1Sragge 1361.13Smatt if (((ka88_confdata & KA88_LEFTPRIM) && master) || 1371.13Smatt ((ka88_confdata & KA88_LEFTPRIM) == 0 && !master)) 1381.1Sragge lr = "left"; 1391.1Sragge else 1401.1Sragge lr = "right"; 1411.13Smatt ms = (master ? "master" : "slave"); 1421.1Sragge 1431.13Smatt aprint_normal(": KA88 %s %s\n", lr, ms); 1441.13Smatt if (!master) { 1451.1Sragge#if defined(MULTIPROCESSOR) 1461.1Sragge v_putc = ka88_putc; /* Need special console handling */ 1471.13Smatt cpu_slavesetup(self, na->na_slot); 1481.1Sragge#endif 1491.1Sragge return; 1501.1Sragge } 1511.13Smatt ci = curcpu(); 1521.21Sriastrad device_set_private(self, ci); 1531.13Smatt ci->ci_dev = self; 1541.13Smatt ci->ci_cpuid = device_unit(self); 1551.13Smatt ci->ci_slotid = na->na_slot; 1561.1Sragge} 1571.1Sragge 1581.13SmattCFATTACH_DECL_NEW(cpu_nmi, 0, 1591.13Smatt ka88_cpu_match, ka88_cpu_attach, NULL, NULL); 1601.1Sragge 1611.1Sraggestruct mem_nmi_softc { 1621.16Smatt device_t sc_dev; 1631.1Sragge bus_space_tag_t sc_iot; 1641.1Sragge bus_space_handle_t sc_ioh; 1651.1Sragge}; 1661.1Sragge 1671.1Sraggestatic int 1681.13Smattms88_match(device_t parent, cfdata_t cf, void *aux) 1691.1Sragge{ 1701.13Smatt struct nmi_attach_args * const na = aux; 1711.1Sragge 1721.1Sragge if (cf->cf_loc[NMICF_SLOT] != NMICF_SLOT_DEFAULT && 1731.13Smatt cf->cf_loc[NMICF_SLOT] != na->na_slot) 1741.1Sragge return 0; 1751.13Smatt if (na->na_slot != 10) 1761.1Sragge return 0; 1771.1Sragge return 1; 1781.1Sragge} 1791.1Sragge 1801.1Sraggestatic void 1811.13Smattms88_attach(device_t parent, device_t self, void *aux) 1821.1Sragge{ 1831.13Smatt struct nmi_attach_args * const na = aux; 1841.13Smatt struct mem_nmi_softc * const sc = device_private(self); 1851.13Smatt 1861.13Smatt aprint_normal("\n"); 1871.13Smatt 1881.13Smatt sc->sc_dev = self; 1891.13Smatt sc->sc_iot = na->na_iot; 1901.1Sragge} 1911.1Sragge 1921.13SmattCFATTACH_DECL_NEW(mem_nmi, sizeof(struct mem_nmi_softc), 1931.5Sthorpej ms88_match, ms88_attach, NULL, NULL); 1941.1Sragge 1951.1Sraggestatic void 1961.1Sraggeka88_badaddr(void) 1971.1Sragge{ 1981.1Sragge volatile int hej; 1991.1Sragge /* 2001.1Sragge * This is some magic to clear the NMI faults, described 2011.1Sragge * in section 7.9 in the VAX 8800 System Maintenance Guide. 2021.1Sragge */ 2031.1Sragge hej = ka88_mcl[5]; 2041.1Sragge hej = ka88_mcl[0]; 2051.1Sragge ka88_mcl[0] = 0x04000000; 2061.1Sragge mtpr(1, 0x88); 2071.1Sragge} 2081.1Sragge 2091.1Sraggestatic void 2101.13Smattka88_memerr(void) 2111.1Sragge{ 2121.1Sragge printf("ka88_memerr\n"); 2131.1Sragge} 2141.1Sragge 2151.1Sraggestruct mc88frame { 2161.1Sragge int mc64_summary; /* summary parameter */ 2171.1Sragge int mc64_va; /* va register */ 2181.1Sragge int mc64_vb; /* memory address */ 2191.1Sragge int mc64_sisr; /* status word */ 2201.1Sragge int mc64_state; /* error pc */ 2211.1Sragge int mc64_sc; /* micro pc */ 2221.1Sragge int mc64_pc; /* current pc */ 2231.1Sragge int mc64_psl; /* current psl */ 2241.1Sragge}; 2251.1Sragge 2261.1Sraggestatic int 2271.11Schristoska88_mchk(void *cmcf) 2281.1Sragge{ 2291.1Sragge return (MCHK_PANIC); 2301.1Sragge} 2311.1Sragge 2321.1Sragge#if defined(MULTIPROCESSOR) 2331.1Sragge#define RXBUF 80 2341.1Sraggestatic char rxbuf[RXBUF]; 2351.1Sraggestatic int got = 0, taken = 0; 2361.1Sraggestatic int expect = 0; 2371.1Sragge#endif 2381.1Sragge#if 0 2391.1Sragge/* 2401.1Sragge * Receive a character from logical console. 2411.1Sragge */ 2421.1Sraggestatic void 2431.1Sraggerxcdintr(void *arg) 2441.1Sragge{ 2451.1Sragge int c = mfpr(PR_RXCD); 2461.1Sragge 2471.1Sragge if (c == 0) 2481.1Sragge return; 2491.1Sragge 2501.1Sragge#if defined(MULTIPROCESSOR) 2511.1Sragge if ((c & 0xff) == 0) { 2521.1Sragge if (curcpu()->ci_flags & CI_MASTERCPU) 2531.1Sragge ka88_cnintr(); 2541.1Sragge return; 2551.1Sragge } 2561.1Sragge 2571.1Sragge if (expect == ((c >> 8) & 0xf)) 2581.1Sragge rxbuf[got++] = c & 0xff; 2591.1Sragge 2601.1Sragge if (got == RXBUF) 2611.1Sragge got = 0; 2621.1Sragge#endif 2631.1Sragge} 2641.1Sragge#endif 2651.1Sragge 2661.1Sraggestatic void 2671.1Sraggetocons(int val) 2681.1Sragge{ 2691.2Sthorpej int s = splhigh(); 2701.1Sragge 2711.1Sragge while ((mfpr(PR_TXCS) & GC_RDY) == 0) /* Wait until xmit ready */ 2721.1Sragge ; 2731.1Sragge mtpr(val, PR_TXDB); /* xmit character */ 2741.1Sragge splx(s); 2751.1Sragge} 2761.1Sragge 2771.1Sraggestatic int 2781.1Sraggefromcons(int func) 2791.1Sragge{ 2801.2Sthorpej int ret, s = splhigh(); 2811.1Sragge 2821.1Sragge while (1) { 2831.1Sragge while ((mfpr(PR_RXCS) & GC_DON) == 0) 2841.1Sragge ; 2851.1Sragge ret = mfpr(PR_RXDB); 2861.1Sragge if ((ret & 0xf00) == func) 2871.1Sragge break; 2881.1Sragge } 2891.1Sragge splx(s); 2901.1Sragge return ret; 2911.1Sragge} 2921.1Sragge 2931.1Sraggestatic int 2941.10Smattka88_gettime(volatile struct timeval *tvp) 2951.1Sragge{ 2961.1Sragge union {u_int ret;u_char r[4];} u; 2971.2Sthorpej int i, s = splhigh(); 2981.1Sragge 2991.1Sragge tocons(KA88_COMM|KA88_TOYREAD); 3001.1Sragge for (i = 0; i < 4; i++) { 3011.1Sragge u.r[i] = fromcons(KA88_TOY) & 255; 3021.1Sragge } 3031.1Sragge splx(s); 3041.10Smatt tvp->tv_sec = u.ret; 3051.10Smatt return 0; 3061.1Sragge} 3071.1Sragge 3081.1Sraggestatic void 3091.10Smattka88_settime(volatile struct timeval *tvp) 3101.1Sragge{ 3111.1Sragge union {u_int ret;u_char r[4];} u; 3121.2Sthorpej int i, s = splhigh(); 3131.1Sragge 3141.10Smatt u.ret = tvp->tv_sec - yeartonum(numtoyear(tvp->tv_sec)); 3151.1Sragge tocons(KA88_COMM|KA88_TOYWRITE); 3161.1Sragge for (i = 0; i < 4; i++) 3171.1Sragge tocons(KA88_TOY|u.r[i]); 3181.1Sragge splx(s); 3191.1Sragge} 3201.1Sragge 3211.1Sraggevoid 3221.1Sraggeka88_steal_pages(void) 3231.1Sragge{ 3241.17Schristos char c = '0', d = '0'; 3251.1Sragge mtpr(1, PR_COR); /* Cache on */ 3261.1Sragge tocons(KA88_COMM|KA88_GETCONF); 3271.1Sragge ka88_confdata = fromcons(KA88_CONFDATA); 3281.1Sragge ka88_confdata = mfpr(PR_RXDB); 3291.1Sragge mastercpu = 20; 3301.1Sragge if (vax_cputype == VAX_TYP_8NN) { 3311.1Sragge if (ka88_confdata & KA88_SMALL) { 3321.17Schristos c = '5'; 3331.1Sragge if (ka88_confdata & KA88_SLOW) { 3341.1Sragge vax_boardtype = VAX_BTYP_8500; 3351.17Schristos d = '3'; 3361.1Sragge } else { 3371.1Sragge vax_boardtype = VAX_BTYP_8550; 3381.17Schristos d = '5'; 3391.1Sragge } 3401.1Sragge } else if (ka88_confdata & KA88_SINGLE) { 3411.1Sragge vax_boardtype = VAX_BTYP_8700; 3421.17Schristos c = '7'; 3431.1Sragge } 3441.1Sragge } 3451.17Schristos cpu_setmodel("VAX 88%c%c", c, d); 3461.1Sragge} 3471.1Sragge 3481.1Sragge 3491.13Smatt#if defined(MULTIPROCESSOR) 3501.1Sraggeint 3511.13Smattrxchar(void) 3521.1Sragge{ 3531.1Sragge int ret; 3541.1Sragge 3551.1Sragge if (got == taken) 3561.1Sragge return 0; 3571.1Sragge 3581.1Sragge ret = rxbuf[taken++]; 3591.1Sragge if (taken == RXBUF) 3601.1Sragge taken = 0; 3611.1Sragge return ret; 3621.1Sragge} 3631.1Sragge 3641.1Sraggestatic void 3651.13Smattka88_startslave(struct cpu_info *ci) 3661.1Sragge{ 3671.20Sad const struct pcb *pcb = lwp_getpcb(ci->ci_onproc); 3681.13Smatt const int id = ci->ci_slotid; 3691.1Sragge int i; 3701.1Sragge 3711.13Smatt expect = id; 3721.1Sragge /* First empty queue */ 3731.1Sragge for (i = 0; i < 10000; i++) 3741.1Sragge if (rxchar()) 3751.1Sragge i = 0; 3761.18Schristos ka88_txrx(id, "\020"); /* Send ^P to get attention */ 3771.18Schristos ka88_txrx(id, "I\r"); /* Init other end */ 3781.1Sragge ka88_txrx(id, "D/I 4 %x\r", ci->ci_istack); /* Interrupt stack */ 3791.1Sragge ka88_txrx(id, "D/I C %x\r", mfpr(PR_SBR)); /* SBR */ 3801.1Sragge ka88_txrx(id, "D/I D %x\r", mfpr(PR_SLR)); /* SLR */ 3811.14Srmind ka88_txrx(id, "D/I 10 %x\r", pcb->pcb_paddr); /* PCB for idle proc */ 3821.1Sragge ka88_txrx(id, "D/I 11 %x\r", mfpr(PR_SCBB)); /* SCB */ 3831.1Sragge ka88_txrx(id, "D/I 38 %x\r", mfpr(PR_MAPEN)); /* Enable MM */ 3841.7She ka88_txrx(id, "S %x\r", (int)&vax_mp_tramp); /* Start! */ 3851.1Sragge expect = 0; 3861.1Sragge for (i = 0; i < 10000; i++) 3871.13Smatt if (ci->ci_flags & CI_RUNNING) 3881.1Sragge break; 3891.1Sragge if (i == 10000) 3901.13Smatt aprint_error_dev(ci->ci_dev, "(ID %d) failed starting!!\n", id); 3911.1Sragge} 3921.1Sragge 3931.18Schristosstatic void 3941.18Schristoska88_txrx(int id, const char *fmt, ...) 3951.1Sragge{ 3961.1Sragge char buf[20]; 3971.18Schristos va_list ap; 3981.1Sragge 3991.18Schristos va_start(ap, fmt); 4001.18Schristos vsnprintf(buf, sizeof(buf), fmt, ap); 4011.18Schristos va_end(ap); 4021.1Sragge ka88_sendstr(id, buf); 4031.1Sragge ka88_sergeant(id); 4041.1Sragge} 4051.1Sragge 4061.1Sraggevoid 4071.7Sheka88_sendstr(int id, const char *buf) 4081.1Sragge{ 4091.13Smatt u_int utchr; /* Ends up in R11 with PCC */ 4101.1Sragge int ch, i; 4111.1Sragge 4121.1Sragge while (*buf) { 4131.1Sragge utchr = *buf | id << 8; 4141.1Sragge 4151.1Sragge /* 4161.1Sragge * It seems like mtpr to TXCD sets the V flag if it fails. 4171.1Sragge * Cannot check that flag in C... 4181.1Sragge */ 4191.1Sragge#ifdef __GNUC__ 4201.9Sperry __asm("1:;mtpr %0,$92;bvs 1b" :: "g"(utchr)); 4211.1Sragge#else 4221.9Sperry __asm("1:;mtpr r11,$92;bvs 1b"); 4231.1Sragge#endif 4241.1Sragge buf++; 4251.1Sragge i = 30000; 4261.1Sragge while ((ch = rxchar()) == 0 && --i) 4271.1Sragge ; 4281.1Sragge if (ch == 0) 4291.1Sragge continue; /* failed */ 4301.1Sragge } 4311.1Sragge} 4321.1Sragge 4331.1Sraggevoid 4341.1Sraggeka88_sergeant(int id) 4351.1Sragge{ 4361.1Sragge int i, ch, nserg; 4371.1Sragge 4381.1Sragge nserg = 0; 4391.1Sragge for (i = 0; i < 30000; i++) { 4401.1Sragge if ((ch = rxchar()) == 0) 4411.1Sragge continue; 4421.1Sragge if (ch == '>') 4431.1Sragge nserg++; 4441.1Sragge else 4451.1Sragge nserg = 0; 4461.1Sragge i = 0; 4471.1Sragge if (nserg == 3) 4481.1Sragge break; 4491.1Sragge } 4501.1Sragge /* What to do now??? */ 4511.1Sragge} 4521.1Sragge 4531.1Sragge/* 4541.1Sragge * Write to master console. 4551.1Sragge * Need no locking here; done in the print functions. 4561.1Sragge */ 4571.1Sraggestatic volatile int ch = 0; 4581.1Sragge 4591.1Sraggevoid 4601.1Sraggeka88_putc(int c) 4611.1Sragge{ 4621.1Sragge if (curcpu()->ci_flags & CI_MASTERCPU) { 4631.1Sragge gencnputc(0, c); 4641.1Sragge return; 4651.1Sragge } 4661.1Sragge ch = c; 4671.1Sragge mtpr(mastercpu << 8, PR_RXCD); /* Send IPI to mastercpu */ 4681.1Sragge while (ch != 0) 4691.1Sragge ; /* Wait for master to handle */ 4701.1Sragge} 4711.1Sragge 4721.1Sragge/* 4731.1Sragge * Got character IPI. 4741.1Sragge */ 4751.1Sraggevoid 4761.13Smattka88_cnintr(void) 4771.1Sragge{ 4781.1Sragge if (ch != 0) 4791.1Sragge gencnputc(0, ch); 4801.1Sragge ch = 0; /* Release slavecpu */ 4811.1Sragge} 4821.1Sragge#endif 483