ka88.c revision 1.9
11.9Sperry/* $NetBSD: ka88.c,v 1.9 2005/12/24 22:45:40 perry 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 * 3. All advertising materials mentioning features or use of this software 151.1Sragge * must display the following acknowledgement: 161.1Sragge * This product includes software developed at Ludd, University of 171.1Sragge * Lule}, Sweden and its contributors. 181.1Sragge * 4. The name of the author may not be used to endorse or promote products 191.1Sragge * derived from this software without specific prior written permission 201.1Sragge * 211.1Sragge * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 221.1Sragge * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 231.1Sragge * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 241.1Sragge * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 251.1Sragge * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 261.1Sragge * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 271.1Sragge * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 281.1Sragge * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 291.1Sragge * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 301.1Sragge * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 311.1Sragge */ 321.1Sragge 331.1Sragge/* 341.1Sragge * KA88 specific CPU code. 351.1Sragge */ 361.1Sragge/* 371.1Sragge * TODO: 381.1Sragge * - Machine check code 391.1Sragge */ 401.6Slukem 411.6Slukem#include <sys/cdefs.h> 421.9Sperry__KERNEL_RCSID(0, "$NetBSD: ka88.c,v 1.9 2005/12/24 22:45:40 perry Exp $"); 431.1Sragge 441.1Sragge#include "opt_multiprocessor.h" 451.1Sragge 461.1Sragge#include <sys/param.h> 471.1Sragge#include <sys/time.h> 481.1Sragge#include <sys/kernel.h> 491.1Sragge#include <sys/device.h> 501.1Sragge#include <sys/systm.h> 511.1Sragge#include <sys/conf.h> 521.1Sragge 531.1Sragge#include <machine/cpu.h> 541.1Sragge#include <machine/mtpr.h> 551.1Sragge#include <machine/nexus.h> 561.1Sragge#include <machine/clock.h> 571.1Sragge#include <machine/scb.h> 581.1Sragge#include <machine/bus.h> 591.1Sragge#include <machine/sid.h> 601.1Sragge#include <machine/rpb.h> 611.1Sragge#include <machine/ka88.h> 621.1Sragge 631.1Sragge#include <vax/vax/gencons.h> 641.1Sragge 651.1Sragge#include "ioconf.h" 661.1Sragge#include "locators.h" 671.1Sragge 681.1Sraggestatic void ka88_memerr(void); 691.1Sraggestatic void ka88_conf(void); 701.1Sraggestatic int ka88_mchk(caddr_t); 711.1Sraggestatic void ka88_steal_pages(void); 721.1Sraggestatic int ka88_clkread(time_t); 731.1Sraggestatic void ka88_clkwrite(void); 741.1Sraggestatic void ka88_badaddr(void); 751.1Sragge#if defined(MULTIPROCESSOR) 761.1Sraggestatic void ka88_startslave(struct device *, struct cpu_info *); 771.7Shestatic void ka88_txrx(int, const char *, int); 781.7Shestatic void ka88_sendstr(int, const char *); 791.1Sraggestatic void ka88_sergeant(int); 801.1Sraggestatic int rxchar(void); 811.1Sraggestatic void ka88_putc(int); 821.1Sraggestatic void ka88_cnintr(void); 831.1Sraggecons_decl(gen); 841.1Sragge#endif 851.1Sragge 861.1Sraggestatic long *ka88_mcl; 871.1Sraggestatic int mastercpu; 881.1Sragge 891.1Sraggestruct cpu_dep ka88_calls = { 901.1Sragge ka88_steal_pages, 911.1Sragge ka88_mchk, 921.1Sragge ka88_memerr, 931.1Sragge ka88_conf, 941.1Sragge ka88_clkread, 951.1Sragge ka88_clkwrite, 961.1Sragge 6, /* ~VUPS */ 971.1Sragge 64, /* SCB pages */ 981.1Sragge 0, 991.1Sragge 0, 1001.1Sragge 0, 1011.1Sragge 0, 1021.1Sragge 0, 1031.1Sragge#if defined(MULTIPROCESSOR) 1041.1Sragge ka88_startslave, 1051.1Sragge#endif 1061.1Sragge ka88_badaddr, 1071.1Sragge}; 1081.1Sragge 1091.1Sraggestruct ka88_softc { 1101.1Sragge struct device sc_dev; 1111.1Sragge int sc_slot; 1121.1Sragge}; 1131.1Sragge 1141.1Sraggestatic void 1151.1Sraggeka88_conf(void) 1161.1Sragge{ 1171.1Sragge ka88_mcl = (void *)vax_map_physmem(0x3e000000, 1); 1181.1Sragge printf("Serial number %d, rev %d\n", 1191.1Sragge mfpr(PR_SID) & 65535, (mfpr(PR_SID) >> 16) & 127); 1201.1Sragge} 1211.1Sragge 1221.1Sraggestatic int 1231.1Sraggeka88_match(struct device *parent, struct cfdata *cf, void *aux) 1241.1Sragge{ 1251.1Sragge struct nmi_attach_args *na = aux; 1261.1Sragge 1271.1Sragge if (cf->cf_loc[NMICF_SLOT] != NMICF_SLOT_DEFAULT && 1281.1Sragge cf->cf_loc[NMICF_SLOT] != na->slot) 1291.1Sragge return 0; 1301.1Sragge if (na->slot >= 20) 1311.1Sragge return 1; 1321.1Sragge return 0; 1331.1Sragge} 1341.1Sragge 1351.1Sraggestatic void 1361.1Sraggeka88_attach(struct device *parent, struct device *self, void *aux) 1371.1Sragge{ 1381.1Sragge struct ka88_softc *sc = (void *)self; 1391.1Sragge struct nmi_attach_args *na = aux; 1401.1Sragge char *ms, *lr; 1411.1Sragge 1421.1Sragge if (((ka88_confdata & KA88_LEFTPRIM) && (na->slot == 20)) || 1431.1Sragge ((ka88_confdata & KA88_LEFTPRIM) == 0 && (na->slot != 20))) 1441.1Sragge lr = "left"; 1451.1Sragge else 1461.1Sragge lr = "right"; 1471.1Sragge ms = na->slot == 20 ? "master" : "slave"; 1481.1Sragge 1491.1Sragge printf(": ka88 (%s) (%s)\n", lr, ms); 1501.1Sragge sc->sc_slot = na->slot; 1511.1Sragge if (na->slot != mastercpu) { 1521.1Sragge#if defined(MULTIPROCESSOR) 1531.1Sragge sc->sc_ci = cpu_slavesetup(self); 1541.1Sragge v_putc = ka88_putc; /* Need special console handling */ 1551.1Sragge#endif 1561.1Sragge return; 1571.1Sragge } 1581.1Sragge curcpu()->ci_dev = self; 1591.1Sragge} 1601.1Sragge 1611.4SthorpejCFATTACH_DECL(cpu_nmi, sizeof(struct ka88_softc), 1621.5Sthorpej ka88_match, ka88_attach, NULL, NULL); 1631.1Sragge 1641.1Sraggestruct mem_nmi_softc { 1651.1Sragge struct device sc_dev; 1661.1Sragge bus_space_tag_t sc_iot; 1671.1Sragge bus_space_handle_t sc_ioh; 1681.1Sragge}; 1691.1Sragge 1701.1Sraggestatic int 1711.1Sraggems88_match(struct device *parent, struct cfdata *cf, void *aux) 1721.1Sragge{ 1731.1Sragge struct nmi_attach_args *na = aux; 1741.1Sragge 1751.1Sragge if (cf->cf_loc[NMICF_SLOT] != NMICF_SLOT_DEFAULT && 1761.1Sragge cf->cf_loc[NMICF_SLOT] != na->slot) 1771.1Sragge return 0; 1781.1Sragge if (na->slot != 10) 1791.1Sragge return 0; 1801.1Sragge return 1; 1811.1Sragge} 1821.1Sragge 1831.1Sraggestatic void 1841.1Sraggems88_attach(struct device *parent, struct device *self, void *aux) 1851.1Sragge{ 1861.1Sragge printf("\n"); 1871.1Sragge} 1881.1Sragge 1891.4SthorpejCFATTACH_DECL(mem_nmi, sizeof(struct mem_nmi_softc), 1901.5Sthorpej ms88_match, ms88_attach, NULL, NULL); 1911.1Sragge 1921.1Sraggestatic void 1931.1Sraggeka88_badaddr(void) 1941.1Sragge{ 1951.1Sragge volatile int hej; 1961.1Sragge /* 1971.1Sragge * This is some magic to clear the NMI faults, described 1981.1Sragge * in section 7.9 in the VAX 8800 System Maintenance Guide. 1991.1Sragge */ 2001.1Sragge hej = ka88_mcl[5]; 2011.1Sragge hej = ka88_mcl[0]; 2021.1Sragge ka88_mcl[0] = 0x04000000; 2031.1Sragge mtpr(1, 0x88); 2041.1Sragge} 2051.1Sragge 2061.1Sraggestatic void 2071.1Sraggeka88_memerr() 2081.1Sragge{ 2091.1Sragge printf("ka88_memerr\n"); 2101.1Sragge} 2111.1Sragge 2121.1Sraggestruct mc88frame { 2131.1Sragge int mc64_summary; /* summary parameter */ 2141.1Sragge int mc64_va; /* va register */ 2151.1Sragge int mc64_vb; /* memory address */ 2161.1Sragge int mc64_sisr; /* status word */ 2171.1Sragge int mc64_state; /* error pc */ 2181.1Sragge int mc64_sc; /* micro pc */ 2191.1Sragge int mc64_pc; /* current pc */ 2201.1Sragge int mc64_psl; /* current psl */ 2211.1Sragge}; 2221.1Sragge 2231.1Sraggestatic int 2241.1Sraggeka88_mchk(caddr_t cmcf) 2251.1Sragge{ 2261.1Sragge return (MCHK_PANIC); 2271.1Sragge} 2281.1Sragge 2291.1Sragge#if defined(MULTIPROCESSOR) 2301.1Sragge#define RXBUF 80 2311.1Sraggestatic char rxbuf[RXBUF]; 2321.1Sraggestatic int got = 0, taken = 0; 2331.1Sraggestatic int expect = 0; 2341.1Sragge#endif 2351.1Sragge#if 0 2361.1Sragge/* 2371.1Sragge * Receive a character from logical console. 2381.1Sragge */ 2391.1Sraggestatic void 2401.1Sraggerxcdintr(void *arg) 2411.1Sragge{ 2421.1Sragge int c = mfpr(PR_RXCD); 2431.1Sragge 2441.1Sragge if (c == 0) 2451.1Sragge return; 2461.1Sragge 2471.1Sragge#if defined(MULTIPROCESSOR) 2481.1Sragge if ((c & 0xff) == 0) { 2491.1Sragge if (curcpu()->ci_flags & CI_MASTERCPU) 2501.1Sragge ka88_cnintr(); 2511.1Sragge return; 2521.1Sragge } 2531.1Sragge 2541.1Sragge if (expect == ((c >> 8) & 0xf)) 2551.1Sragge rxbuf[got++] = c & 0xff; 2561.1Sragge 2571.1Sragge if (got == RXBUF) 2581.1Sragge got = 0; 2591.1Sragge#endif 2601.1Sragge} 2611.1Sragge#endif 2621.1Sragge 2631.1Sraggestatic void 2641.1Sraggetocons(int val) 2651.1Sragge{ 2661.2Sthorpej int s = splhigh(); 2671.1Sragge 2681.1Sragge while ((mfpr(PR_TXCS) & GC_RDY) == 0) /* Wait until xmit ready */ 2691.1Sragge ; 2701.1Sragge mtpr(val, PR_TXDB); /* xmit character */ 2711.1Sragge splx(s); 2721.1Sragge} 2731.1Sragge 2741.1Sraggestatic int 2751.1Sraggefromcons(int func) 2761.1Sragge{ 2771.2Sthorpej int ret, s = splhigh(); 2781.1Sragge 2791.1Sragge while (1) { 2801.1Sragge while ((mfpr(PR_RXCS) & GC_DON) == 0) 2811.1Sragge ; 2821.1Sragge ret = mfpr(PR_RXDB); 2831.1Sragge if ((ret & 0xf00) == func) 2841.1Sragge break; 2851.1Sragge } 2861.1Sragge splx(s); 2871.1Sragge return ret; 2881.1Sragge} 2891.1Sragge 2901.1Sraggestatic int 2911.1Sraggeka88_clkread(time_t base) 2921.1Sragge{ 2931.1Sragge union {u_int ret;u_char r[4];} u; 2941.2Sthorpej int i, s = splhigh(); 2951.1Sragge 2961.1Sragge tocons(KA88_COMM|KA88_TOYREAD); 2971.1Sragge for (i = 0; i < 4; i++) { 2981.1Sragge u.r[i] = fromcons(KA88_TOY) & 255; 2991.1Sragge } 3001.1Sragge splx(s); 3011.1Sragge return u.ret; 3021.1Sragge} 3031.1Sragge 3041.1Sraggestatic void 3051.1Sraggeka88_clkwrite(void) 3061.1Sragge{ 3071.1Sragge union {u_int ret;u_char r[4];} u; 3081.2Sthorpej int i, s = splhigh(); 3091.1Sragge 3101.1Sragge u.ret = time.tv_sec - yeartonum(numtoyear(time.tv_sec)); 3111.1Sragge tocons(KA88_COMM|KA88_TOYWRITE); 3121.1Sragge for (i = 0; i < 4; i++) 3131.1Sragge tocons(KA88_TOY|u.r[i]); 3141.1Sragge splx(s); 3151.1Sragge} 3161.1Sragge 3171.1Sraggevoid 3181.1Sraggeka88_steal_pages(void) 3191.1Sragge{ 3201.1Sragge mtpr(1, PR_COR); /* Cache on */ 3211.1Sragge strcpy(cpu_model, "VAX 8800"); 3221.1Sragge tocons(KA88_COMM|KA88_GETCONF); 3231.1Sragge ka88_confdata = fromcons(KA88_CONFDATA); 3241.1Sragge ka88_confdata = mfpr(PR_RXDB); 3251.1Sragge mastercpu = 20; 3261.1Sragge if (vax_cputype == VAX_TYP_8NN) { 3271.1Sragge if (ka88_confdata & KA88_SMALL) { 3281.1Sragge cpu_model[5] = '5'; 3291.1Sragge if (ka88_confdata & KA88_SLOW) { 3301.1Sragge vax_boardtype = VAX_BTYP_8500; 3311.1Sragge cpu_model[6] = '3'; 3321.1Sragge } else { 3331.1Sragge vax_boardtype = VAX_BTYP_8550; 3341.1Sragge cpu_model[6] = '5'; 3351.1Sragge } 3361.1Sragge } else if (ka88_confdata & KA88_SINGLE) { 3371.1Sragge vax_boardtype = VAX_BTYP_8700; 3381.1Sragge cpu_model[5] = '7'; 3391.1Sragge } 3401.1Sragge } 3411.1Sragge} 3421.1Sragge 3431.1Sragge 3441.1Sragge#if defined(MULTIPROCESSOR) && 0 3451.1Sraggeint 3461.1Sraggerxchar() 3471.1Sragge{ 3481.1Sragge int ret; 3491.1Sragge 3501.1Sragge if (got == taken) 3511.1Sragge return 0; 3521.1Sragge 3531.1Sragge ret = rxbuf[taken++]; 3541.1Sragge if (taken == RXBUF) 3551.1Sragge taken = 0; 3561.1Sragge return ret; 3571.1Sragge} 3581.1Sragge 3591.1Sraggestatic void 3601.1Sraggeka88_startslave(struct device *dev, struct cpu_info *ci) 3611.1Sragge{ 3621.1Sragge struct ka88_softc *sc = (void *)dev; 3631.1Sragge int id = sc->sc_binid; 3641.1Sragge int i; 3651.1Sragge 3661.1Sragge expect = sc->sc_binid; 3671.1Sragge /* First empty queue */ 3681.1Sragge for (i = 0; i < 10000; i++) 3691.1Sragge if (rxchar()) 3701.1Sragge i = 0; 3711.1Sragge ka88_txrx(id, "\020", 0); /* Send ^P to get attention */ 3721.1Sragge ka88_txrx(id, "I\r", 0); /* Init other end */ 3731.1Sragge ka88_txrx(id, "D/I 4 %x\r", ci->ci_istack); /* Interrupt stack */ 3741.1Sragge ka88_txrx(id, "D/I C %x\r", mfpr(PR_SBR)); /* SBR */ 3751.1Sragge ka88_txrx(id, "D/I D %x\r", mfpr(PR_SLR)); /* SLR */ 3761.1Sragge ka88_txrx(id, "D/I 10 %x\r", (int)ci->ci_pcb); /* PCB for idle proc */ 3771.1Sragge ka88_txrx(id, "D/I 11 %x\r", mfpr(PR_SCBB)); /* SCB */ 3781.1Sragge ka88_txrx(id, "D/I 38 %x\r", mfpr(PR_MAPEN)); /* Enable MM */ 3791.7She ka88_txrx(id, "S %x\r", (int)&vax_mp_tramp); /* Start! */ 3801.1Sragge expect = 0; 3811.1Sragge for (i = 0; i < 10000; i++) 3821.1Sragge if ((volatile)ci->ci_flags & CI_RUNNING) 3831.1Sragge break; 3841.1Sragge if (i == 10000) 3851.1Sragge printf("%s: (ID %d) failed starting??!!??\n", 3861.1Sragge dev->dv_xname, sc->sc_binid); 3871.1Sragge} 3881.1Sragge 3891.1Sraggevoid 3901.7Sheka88_txrx(int id, const char *fmt, int arg) 3911.1Sragge{ 3921.1Sragge char buf[20]; 3931.1Sragge 3941.1Sragge sprintf(buf, fmt, arg); 3951.1Sragge ka88_sendstr(id, buf); 3961.1Sragge ka88_sergeant(id); 3971.1Sragge} 3981.1Sragge 3991.1Sraggevoid 4001.7Sheka88_sendstr(int id, const char *buf) 4011.1Sragge{ 4021.1Sragge register u_int utchr; /* Ends up in R11 with PCC */ 4031.1Sragge int ch, i; 4041.1Sragge 4051.1Sragge while (*buf) { 4061.1Sragge utchr = *buf | id << 8; 4071.1Sragge 4081.1Sragge /* 4091.1Sragge * It seems like mtpr to TXCD sets the V flag if it fails. 4101.1Sragge * Cannot check that flag in C... 4111.1Sragge */ 4121.1Sragge#ifdef __GNUC__ 4131.9Sperry __asm("1:;mtpr %0,$92;bvs 1b" :: "g"(utchr)); 4141.1Sragge#else 4151.9Sperry __asm("1:;mtpr r11,$92;bvs 1b"); 4161.1Sragge#endif 4171.1Sragge buf++; 4181.1Sragge i = 30000; 4191.1Sragge while ((ch = rxchar()) == 0 && --i) 4201.1Sragge ; 4211.1Sragge if (ch == 0) 4221.1Sragge continue; /* failed */ 4231.1Sragge } 4241.1Sragge} 4251.1Sragge 4261.1Sraggevoid 4271.1Sraggeka88_sergeant(int id) 4281.1Sragge{ 4291.1Sragge int i, ch, nserg; 4301.1Sragge 4311.1Sragge nserg = 0; 4321.1Sragge for (i = 0; i < 30000; i++) { 4331.1Sragge if ((ch = rxchar()) == 0) 4341.1Sragge continue; 4351.1Sragge if (ch == '>') 4361.1Sragge nserg++; 4371.1Sragge else 4381.1Sragge nserg = 0; 4391.1Sragge i = 0; 4401.1Sragge if (nserg == 3) 4411.1Sragge break; 4421.1Sragge } 4431.1Sragge /* What to do now??? */ 4441.1Sragge} 4451.1Sragge 4461.1Sragge/* 4471.1Sragge * Write to master console. 4481.1Sragge * Need no locking here; done in the print functions. 4491.1Sragge */ 4501.1Sraggestatic volatile int ch = 0; 4511.1Sragge 4521.1Sraggevoid 4531.1Sraggeka88_putc(int c) 4541.1Sragge{ 4551.1Sragge if (curcpu()->ci_flags & CI_MASTERCPU) { 4561.1Sragge gencnputc(0, c); 4571.1Sragge return; 4581.1Sragge } 4591.1Sragge ch = c; 4601.1Sragge mtpr(mastercpu << 8, PR_RXCD); /* Send IPI to mastercpu */ 4611.1Sragge while (ch != 0) 4621.1Sragge ; /* Wait for master to handle */ 4631.1Sragge} 4641.1Sragge 4651.1Sragge/* 4661.1Sragge * Got character IPI. 4671.1Sragge */ 4681.1Sraggevoid 4691.1Sraggeka88_cnintr() 4701.1Sragge{ 4711.1Sragge if (ch != 0) 4721.1Sragge gencnputc(0, ch); 4731.1Sragge ch = 0; /* Release slavecpu */ 4741.1Sragge} 4751.1Sragge#endif 476