📄 kn5800.c
字号:
#ifndef lintstatic char *sccsid = "@(#)kn5800.c 4.3 (ULTRIX) 10/9/90";#endif lint/************************************************************************ * * * Copyright (c) 1989 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//* * Revision History: * * 30-Apr-90 Randall Brown * Added call to spl_init() to intialize spl function pointers and * the intr() function pointer. * * 29-Mar-90 gmm * enable CRDID in secondary_init() * * 06-Mar-90 gmm * Log soft error on cache FIFO overflow. Also do the extra write even * if lock bit set/clear in bbssi/bbcci * * 08-Dec-89 gmm * Soft error logging changes merged from v3.1C. A workaround for the * console bug to find the number of processors with both 3.1 and 4.0 * console ROMs. Bug fix to map the correct IP interrupt address for * all valid slots (was using VAX page size before). * * 14-Nov-89 gmm * Change to start a secondary processor, changes to bbssi() and bbcci() * to flush cache(). This should get fixed in hardware soon. * * 13-Nov-89 burns * Fixed nxaccess to deal properly with I/O address space, made * interrupt vectors reads handle passive releases. * * 09-Nov-89 bp * Optimized Vaxmap to use mips KSEG0 space to minimize tblmiss hits. * * 26-Oct-89 gmm * Moved bbssi() and bbcci() from interlock.c to this file. * * 13-Oct-89 gmm * SMP changes. Error log buffer gets allocated on per cpu basis. Added * routines like kn5800_init_secondary() and modified cca_setup() etc. * * 12-Sep-89 burns * New way of doing a write buffer flush that is much faster. * Removed printfs that were used for debug. * Removed hack code for "erroneous interrupts". * * 11-Sep-89 Pete Keilty * Change alloc_vaxmap() to use a define Maxvax_dbpte which * is defined in scamachmac.h * * 27-Jan-89 Bill Burns * Created the file. This file contains routines specific * to ISIS systems. */#include "../machine/pte.h"#include "../h/param.h"#include "../h/user.h" /* gets time.h and debug.h too */#include "../h/proc.h"#include "../h/conf.h"#include "../h/errno.h"#include "../h/systm.h"#include "../h/types.h"#include "../h/errlog.h"#include "../h/cmap.h"#include "../h/ioctl.h"#include "../h/tty.h"#include "../h/cpudata.h"#include "../h/kmalloc.h"#include "../h/vmmac.h"#include "../io/uba/ubareg.h"#include "../machine/cpu.h"#include "../machine/reg.h"#include "../../machine/common/cpuconf.h"#include "../machine/ssc.h"#include "../machine/cons.h"#include "../machine/cca.h"#include "../machine/clock.h"#include "../machine/hwconf.h"#include "../machine/param.h"#include "../machine/kn5800.h"#include "../io/xmi/xmireg.h"#include "../io/xmi/xmareg.h"#include "../io/scs/scamachmac.h"#define ESRPKT 1#define MEMPKT 2struct xmidata *head_xmidata;extern int (*(scb[]))();extern caddr_t vatophys();extern struct bidata bidata[];extern int cache_state;extern int nNVAXBI;struct kn5800_regs *kn5800_regp;int powerfail;int cache_state; /* in autoconf for vax */int *kn5800_wbflush_addr; /* Holds the address to read to trigger a write buffer flush */int wbflush_dummy; /* target destination for a write buffer flush - its external to prevent compiler from getting too smart and optimizing out a write buffer flush */struct cca *ccabase; /* console communications area */extern char *kn5800_ip_addr[];/* struct ssc_regs cvqssc[1]; /* SSC regs */struct v5800csr *v5800csr = (struct v5800csr *)CSR5800;struct vaxpte *vax_map;extern struct pte eSysmap[];extern struct vaxpte *Vaxmap; /* pointer to the base of Vaxmap */extern int Vaxmap_size; /* size of the entire Vaxmap in pages */int Vax_page_factor; /* Vax pages per mips page */extern int gvp_max_bds; /* Number of data structs that need 128 ptes */#define VAX_PAGE_SIZE 512/* * Interrupt handlers for the 6 hardware interrupts and 2 software * interrupts for ISIS */extern softclock(), softnet(), kn5800_intr0(), kn5800_intr1(), kn5800_intr2(), kn5800_intr3(), kn5800_halt(), fpuintr();int (*kn5800_intr_vec[8])() = { softclock, /* softint 0 */ softnet, /* softint 1 */ kn5800_intr0, /* hardint 0 - XMI level 4/5 and SSC*/ kn5800_intr1, /* hardint 1 - XMI level 6, IP and Cloc */ kn5800_intr2, /* hardint 2 - XMI level 7 */ kn5800_intr3, /* hardint 3 - Hard and soft errors */ kn5800_halt, /* hardint 4 - Halt interrupt */ fpuintr /* hardint 5 - FPU interrupt */};#ifndef SR_HALT#define SR_HALT SR_IBIT7#endif SR_HALTint kn5800_iplmask[8] = { SR_IMASK1|SR_IEC|SR_HALT, /* soft clock */ SR_IMASK2|SR_IEC|SR_HALT, /* soft net */ SR_IMASK3|SR_IEC|SR_HALT, /* XMI 4/5 and SSC */ SR_IMASK4|SR_IEC|SR_HALT, /* XMI 6, IP and clock */ SR_IMASK5|SR_IEC|SR_HALT, /* XMI 7 */ SR_IMASK6|SR_IEC|SR_HALT, /* Hard and soft errors */ SR_IMASK7|SR_IEC, /* Halt */ SR_IMASK8|SR_IEC|SR_HALT /* FPU */};/* * This array conatins the interrupt mask to use for spl calls. Indexed * by the defines in cpu.h (SPLBIO, etc). */int kn5800_splm[SPLMSIZE] = { SR_IEC | SR_IMASK0 | SR_HALT, /* 0 SPLNONE */ SR_IEC | SR_IMASK1 | SR_HALT, /* 1 SPLSOFTC */ SR_IEC | SR_IMASK2 | SR_HALT, /* 2 SPLNET */ 0, /* 3 NOT_USED */ 0, /* 4 NOT_USED */ SR_IEC | SR_IMASK3 | SR_HALT, /* 5 SPLBIO, SPLIMP, SPLTTY */ SR_IEC | SR_IMASK4 | SR_HALT, /* 6 SPLCLOCK */ SR_IEC | SR_IMASK6 | SR_HALT, /* 7 SPLMEM */ SR_IEC | SR_IMASK8 | SR_HALT, /* 8 SPLFPU, EXTREME, HIGH, 7, 6*/};/* * alloc_vaxmap -- allocate space for a "vax" page table. This table consists * of two parts. First a VAX version of the kernel "sysmap". This is required * for the relative queues that are used by the devices that requires vax * virtual support. The queue heads and elements are kmalloc'ed and use * virtual indexes, thus the Vaxmap and sysmap must coincide virtually. * TODO: This first part of Vaxmap may only need to correspond to kmalloc * space. * * The second part of Vaxmap (indcated by Vaxdbpte) is space reserved to * hold Vax pte's that are used for actual data transfer operations. 128 + 8 * ptes per "gvp_max_bds" give us enough room for the 64kb data transfer * for every device that is configured that needs Vax virtual support. */alloc_vaxmap(){ register int base_size, dbpte_size; register int map_size, i, pfn; register struct vaxpte *pte; /* HACK - needs to be fixed for mips page sizes other than 4k */ Vax_page_factor = (NBPG/VAX_PAGE_SIZE); /* End HACK */ /* * Calculate Vaxmap_size which is the size of the Vaxmap in vax pages. */ base_size = ((eSysmap - Sysmap) * Vax_page_factor); /* * Calculate the size map for db */ dbpte_size = (gvp_max_bds * Maxvax_dbpte); /* * VAX pte space required for map. */ map_size = (((base_size + dbpte_size) * sizeof (struct vaxpte)) + VAX_PAGE_SIZE - 1) / VAX_PAGE_SIZE; Vaxmap_size = base_size + map_size + dbpte_size; if ((vax_map = (struct vaxpte *) kseg0_alloc( (Vaxmap_size * sizeof (struct vaxpte))))); else panic("alloc_vaxmap: allocate failed"); Vaxmap = (struct vaxpte *)vax_map; /* * */ Dbptemap = (struct vaxpte *) (Vaxmap + base_size); /* * Map the map itself */ for (pfn = btoc(K0_TO_PHYS(Vaxmap)) << 3, pte = Vaxmap + base_size + dbpte_size, i = 0; i < map_size; i++, pte++, pfn++) * (int *) pte = pfn | VAX_PG_V; /* * Vax virtual sysmap */ VSysmap = (struct vaxpte *)(VAX_SYSVA + (base_size + dbpte_size) * VAX_PGSIZE); /* * Need a VAX virtual address in VSysmap for dbpte. */ Vaxdbpte = (struct pte *) (VSysmap + base_size);}#define SSC_INTR_LEVEL 0x00000000extern int cnrint(), cnxint();extern int cpu_ip_intr(); /* IPI handler *//* * Configuration routine. */kn5800_conf(){ extern int cold; extern unsigned cpu_systype; extern int cpu; /* Ultrix internal System type */ extern struct cpusw *cpup;extern struct pte eSysmap[];extern struct vaxpte *Vaxmap; char *nxv; int nxp; register int i; register int xcp_node; register struct xmidata *xmidata; struct xcp_reg *xcp; char *start; struct pte *pte; int cpu_subtype; struct kn5800_regs *x3p_regs; cold = 1; hwconf_init(); powerfail = 0; /* reset count of powerfail interrupts */ /* Report what system we are on */ switch (cpu) { case DS_5800: printf("KN5800 processor - system rev %d\n", (GETHRDREV(cpu_systype))); break; default: panic("kn5800_conf called, wrong system"); break; } /* * Begin "calypso-ish" initialization */ /* * coproc_find will cause the system's first write buffer flush in * dealing with the floating point unit. So we must set up the * the write_buffer flush address first. The write buffer flush * address is the external (io) address of the boot processor's * gpr register. */ /* allocate up 1 xmi structure */ KM_ALLOC(xmidata,struct xmidata *,sizeof(struct xmidata ),KM_DEVBUF,KM_NOW_CL_CO_CA); head_xmidata = xmidata; xmidata->next = 0; xmidata->xminum = 0; xmidata->xmivirt = (struct xmi_reg *)PHYS_TO_K1(XMI_START_PHYS); xcp_node = v5800csr->csr1 & XMI_NODE_ID; xcp = ((struct xcp_reg *)PHYS_TO_K1(XMI_START_PHYS) + xcp_node); kn5800_wbflush_addr = (int *)&(xcp->xcp_gpr); coproc_find(); /* Deal with FPU */ /* * set up mapping for interrupt vector locations. */ mapin (btop(kn5800_vectors), btop(KN5800_VEC_REG_BASE), (PG_KW|PG_N|PG_V|PG_G)); scb[0xf8/4] = cnrint; scb[0xfc/4] = cnxint; scb[0x80/4] = cpu_ip_intr; /* put the ipi handler */ init_ssc(); /* * allocate Vaxmap - a vax system page table for use by devices that need * vax virutal address: CI, BVP. */ alloc_vaxmap(); KM_ALLOC(x3p_regs, struct kn5800_regs *, (sizeof(struct kn5800_regs) * MAXCPU), KM_DEVBUF, KM_NOW_CL_CO_CA); kn5800_regp = x3p_regs; /* * fill in table of IP interrupt addresses. Addresses * are of the form: * * vax 2101nnnn * mips b101nnnn * where nnnn is the decoded XMI node number * */#define IP_INTR_ADDRESS_BASE 0x11010000 start = (char *) PHYS_TO_K1(IP_INTR_ADDRESS_BASE); for (i=0 ; i< MAX_XMI_NODE ; i++ ) { nxp = IP_INTR_ADDRESS_BASE + (1<<i); if (i < 12) /* for the 4k page size */ nxv = start + (1<<i); else { nxv = start + ((i-11) * NBPG); } kn5800_ip[i] = nxv; } xcp_node = v5800csr->csr1 & XMI_NODE_ID; xmidata->xmiintr_dst = (1 << xcp_node); kn5800_enable_cache() ; #ifdef mips xmidata->xmiphys = (struct xmi_reg *) XMI_START_PHYS; xmidata->xmivec_page = &scb[0];#endif mips spl0(); /* Ready for interrupts */ cpu_avail = cca_setup() ; /* due to a console bug, the processor always shown to be in cosole mode */ /* allocate space for machine specific error packets */ KM_ALLOC(CURRENT_CPUDATA->cpu_machdep,char *,sizeof(struct el_xcpsoft),KM_DEVBUF,KM_NOW_CL_CO_CA); printf("DECsystem 58%d0 server\n",cpu_avail); /* * configure the I/O system */ xmiconf(0,cpup); /* clear warm and cold boot flags */ ccabase->cca_hflag &= ~(CCA_V_BOOTIP|CCA_V_WARMIP); /* * Configure swap area and related system * parameter based on device(s) used. */#ifndef ultrix setconf(); swapconf();#endif not ultrix cold = 0; kn5800_memenable(); return (0);}/* below define is from machine/vax/mem.h - needs to be put somewhere more portable. */#define MEMINTVL (60 * 15) /* 15 minutes */int memintvl = MEMINTVL;kn5800_memenable(){ int xminode; struct xmi_reg *nxv; /* virtual pointer to XMI node */ struct xmidata *xmidata; int i; extern int hz; xmidata = get_xmi(0); /* * Enable XMAs crd interrupts */ nxv = xmidata->xmivirt; for(xminode = 0; xminode < MAX_XMI_NODE; xminode++,nxv++) { if ((xmidata->xminodes_alive & (1<<xminode)) && ((short) (nxv->xmi_dtype) == XMI_XMA)) { /* clear disable CRD flag in memory controller */ ((struct xma_reg *)nxv)->xma_mctl1 &= ~(XMA_CTL1_CRD_DISABLE); } } /* * Enable cache soft error logging */ CURRENT_CPUDATA->cpu_state &= ~(CPU_SOFT_DISABLE); /* * Schedule next call to ourself for the primary cpu. Secondary cpus * should schedule their own */ if (memintvl > 0) timeout (kn5800_memenable, (caddr_t) 0, memintvl * hz); return(0);}/* * Initialization routine for kn5800 processor (ISIS). */kn5800_init(){ extern int c0vec_tblsize; extern int (*c0vec_tbl[])(); extern int iplmask[]; extern int splm[]; extern int hz; extern int tick; extern int tickadj; extern struct cpusw *cpup; register int xcp_node; struct xcp_reg *xcp; /* * Initialize the interrupt dispatch table c0vec_tbl. * Initialize the spl table for the system we are running on. * Initialize the interrupt masks for the system we are running on. * This must be done very early on at boot time and must * be done before any interrupt is allowed. */ bcopy((int *)kn5800_intr_vec, c0vec_tbl, c0vec_tblsize); bcopy(kn5800_iplmask, iplmask, IPLSIZE * sizeof(int)); bcopy(kn5800_splm, splm, (SPLMSIZE) * sizeof(int)); /* Initialize the spl dispatch table and the intr dispatch routine */ spl_init(); clear_bev(); splextreme(); /* * Set up the system specific value for "hz", the number of clock * interrupts per second; and corresponding tick and tickadj values. */ hz = cpup->HZ; tick = 1000000 / hz; tickadj = 240000 / (60 * hz); xcp_node = v5800csr->csr1 & XMI_NODE_ID; xcp = ((struct xcp_reg *)PHYS_TO_K1(XMI_START_PHYS) + xcp_node); kn5800_wbflush_addr = (int *)&(xcp->xcp_gpr); return (0);}/* * kn5800_halt - R3000 interrupt pin 5 * * Halt interrupt * * Since mips doesn't have a halt instruction we just call the console. */int haltflag;kn5800_halt (ep)u_int *ep;{ panic ("kn5800_halt");}/* * intr3 - R3000 interrupt pin 3 - Hard and soft system errors. * Possible causes: * Powerfail * Memory errors * CRD - corrected read data and memory errors * First level invalidate fifo overflow * * No vector * * Since Ultrix doesn't support powerfail restarts we wait to see it * it is a real powerfail or not. If not we just return, if so we... */kn5800_intr3 (ep)u_int *ep;{ int csr1, csr2, xbe; int tmp; struct xcp_reg *xcp_node; register struct xmidata *xmidata; register struct kn5800_regs *reg; register struct el_xcpsoft *sptr; xmidata = get_xmi(0); xcp_node =(struct xcp_reg *)xmidata->xmivirt + (v5800csr->csr1 & XMI_NODE_ID); sptr = (struct el_xcpsoft *)CURRENT_CPUDATA->cpu_machdep; /* * Gather up X3P registers. */ reg = kn5800_regp; reg->kn5800_csr1 = v5800csr->csr1; reg->kn5800_dtype = xcp_node->xcp_dtype; reg->kn5800_xbe = xcp_node->xcp_xbe; reg->kn5800_fadr = xcp_node->xcp_fadr; reg->kn5800_gpr = xcp_node->xcp_gpr; reg->kn5800_csr2 = xcp_node->xcp_csr2; /* * See if it's a powerfail */ if (!(reg->kn5800_csr1 & XMI_ACLO)) { /* Powerfail - duck */ powerfail++; /* Delay one second, if we are still alive, continue */ DELAY(1000000); } if (reg->kn5800_csr1 & IFIFOFL) { if ((CURRENT_CPUDATA->cpu_state & CPU_SOFT_DISABLE) == 0) kn5800_log_soft(reg,sptr); kn5800_flush_cache(); } /* * If we detect any fatal memory errors call kn5800_memerr to * report, crash and burn. */ if (reg->kn5800_xbe & (XBE_FATAL_BITS | XBE_RER | XBE_RIDNAK)) { kn5800_memerr (ep, reg, EL_PRISEVERE); } if (reg->kn5800_csr2 & (CSR2_WDPE)) { kn5800_memerr (ep, reg, EL_PRISEVERE); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -