📄 xmiinit.c
字号:
#ifndef lintstatic char *sccsid = "@(#)xmiinit.c 4.7 ULTRIX 12/6/90";#endif lint/************************************************************************ * * * Copyright (c) 1988,1990 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 * * 03-Dec-90 Joe Szczypek * Added return() to get_xmi() to silence LINT. * * 29-Aug-90 stuarth (Stuart Hollander) * Fixed bug in xmisst when determining which xmi a node is on. * Added comments explaining xmiconf structure. * * 17-Aug-90 rafiey (Ali Rafieymehr) * Made the following changes for Stuart Hollander. * Split xmiconf() into xmiconf_reset() and xmiconf_conf(). * Allows, per xmi bus, to reset all nodes, then wait as they * all perform self-test in parallel, instead of resetting and * waiting for each device, one-by-one. * Also, handles multiple xmi s. * * 03-Aug-90 rafiey (Ali Rafieymehr) * Changed xmi_io_space for VAX9000. Defined numxmi for multiple * XMI support. * * 02-May-90 Joe Szczypek * Modified error routines for xbi+ support. * * 13-Mar-90 rafiey (Ali Rafieymehr) * Removed unnecessary check for invalid slot of xmi node from xmi_io_space(). * * 11-Dec-89 Paul Grist * Modified xmierrors to call panic using status returned from * xbi_check_errs(). Added new routine log_xmi_bierrors() to * to log pending VAXBI errors and log_xmierrors to just log pending * xbi errors. They will be used by exception handlers looking for * more error information. * * 08-Dec-89 Pete Keilty * Modified nxaccess() in xmiconf() routine to use XMINODE_SIZE * as node space size define in xmireg.h for VAX. * * 08-Dec-89 jaw * make printf use decimal for printing node and bus numbers. * * 13-Nov-89 burns * Made xmi_io_space consistent over vax/mips platforms. Trickery * now performed in nxaccess(). * * 09-Nov-89 jaw * fix bug where hooking xna to wrong bus. * * 20-Jul-89 rafiey (Ali Rafieymehr) * Added support for XMI devices. * * 24-May-89 darrell * Changed the #include for cpuconf.h to find it in it's new home -- * sys/machine/common/cpuconf.h * * 24-May-89 darrell * Removed the v_ prefix from all cpusw fields, removed cpup from any * arguments being passed in function args. cpup is now defined * globally -- as part of the new cpusw. * *************************************************************************/#include "../machine/pte.h"#include "../h/param.h"#include "../h/systm.h"#include "../h/map.h"#include "../h/buf.h"#include "../h/time.h"#include "../h/kernel.h"#include "../h/errlog.h"#include "../../machine/common/cpuconf.h"#include "../h/dk.h"#include "../h/config.h"#include "../h/kmalloc.h"#include "../h/vmmac.h"#include "../machine/cpu.h"#ifdef vax#include "../machine/mtpr.h"#endif vax#include "../machine/nexus.h"#include "../machine/scb.h"#include "../io/xmi/xmireg.h"#include "../io/uba/ubavar.h"#ifdef vax#define XMI_START_PHYS 0x21800000#endif vax#ifdef mips#define XMI_START_PHYS 0x11800000#endif mipsextern int dkn; /* number of iostat dk numbers assigned so far */extern int nNUBA;#ifdef vaxextern int catcher[256];#endif vax#ifdef mipsextern int stray();#endif mipsextern int nNXMI;extern int vecbi;extern int cpu; /* Ultrix internal System type */extern struct bus_dispatch xmierr_dispatch[];extern struct cpusw *cpup; /* pointer to cpusw entry */extern struct config_adpt *ni_port_adpt;extern struct bidata bidata[];int numxmi;xmisetvec(xminumber)int xminumber;{ int i; struct xmidata *xmidata; xmidata = get_xmi(xminumber); for(i=0; xmierr_dispatch[i].bus_num != xminumber ; i++) { if (xmierr_dispatch[i].bus_num == -1) panic("no vector"); } *(xmidata->xmivec_page+(XMIEINT_XMIVEC/4))= scbentry(xmierr_dispatch[i].bus_vec,SCB_ISTACK);}struct xmidata *get_xmi(xminumber) int xminumber;{ register struct xmidata *xmidata; xmidata = head_xmidata; while(xmidata) { if(xmidata->xminum == xminumber) return(xmidata); xmidata = xmidata->next; } panic("no bus data"); /*NOTREACHED*/}extern struct xmi_reg xmi_start[]; /* Instead of being simply one large function, xmiconf is structured as three subfunctions so that one could easily write a function to initialize multiple xmis in parallel by calling xmiconf_reset for each xmi, then calling xmiconf_wait for each, and then calling xmiconf_conf for each. We keep xmiconf as a function that initializes only one xmi so that existing code can remain unchanged. */xmiconf(xminumber)int xminumber;{ int s; s = spl5(); xmiconf_reset(xminumber); /* Reset all nodes on the xmi */ xmiconf_wait(xminumber); /* Wait for all initializations to complete */ splx(s); xmiconf_conf(xminumber); /* Configure each node */}xmiconf_reset(xminumber)int xminumber;{ struct xmi_reg *nxv; /* virtual pointer to XMI node */ struct xmi_reg *nxp; /* physical pointer to XMI node */ register int xminode; register struct xmisw *pxmisw; register struct xmidata *xmidata; register struct xmi_reg *cpunode=0; register int i; xmidata = get_xmi(xminumber); /* set xmi alive in adpter struct */ config_set_alive("xmi",xminumber); nxp = xmidata->xmiphys; /* see if we need to allocate pte's */ /* * Set up initial virtual address for xmi node space. * This is a bit of a misnomer. On Vaxes XMI node space is mapped * and thus accesses via real virtual addresses. On mips XMI node * is accessible vis KSEG0 and KSEG1, so we use a KSEG1 "virtual" * address which really is a direct translation of the physical. */#ifdef vax nxv = xmi_start; nxv += (xminumber * 16);#endif vax#ifdef mips nxv = (struct xmi_reg *)PHYS_TO_K1(XMI_START_PHYS);#endif mips xmidata->xmivirt = nxv; printf("xmi %d at address 0x%x\n",xminumber,nxp); xmidata->xminodes_alive =0; /* figure out cpu node from xmi interrupt dst. reg */ xmidata->cpu_xmi_addr = nxv + (ffs(xmidata->xmiintr_dst) -1); /* If on first page of scb, do not change the first 64 * vectors, as these are the standard arch defined vectors. * On other pages, initialize all vectors. */ if (xmidata->xmivec_page == &scb.scb_stray) i=64; else i=0; /* initialize SCB to catcher */ for ( ; i < 128; i++) *(SCB_XMI_ADDR(xmidata) + i) =#ifdef vax scbentry(&catcher[i*2], SCB_ISTACK);#endif vax#ifdef mips scbentry(stray, 0);#endif mips /* set error interrupt vector */ xmisetvec(xminumber); for(xminode = 0; xminode < MAX_XMI_NODE; xminode++,nxv++) { /* get physical address to map */ nxp = (struct xmi_reg *) cpup->nexaddr(xminumber,xminode);#ifdef vax /* map xmi node space */ nxaccess(nxp,&Sysmap[btop((int)(nxv) & ~VA_SYS)],XMINODE_SIZE);#endif vax#ifdef mips /* * XMI node space is not mapped on mips. */#endif mips /* xmi node alive ??? */ if (BADADDR((caddr_t) nxv,sizeof(long))) continue; for (pxmisw = xmisw ; pxmisw->xmi_type ; pxmisw++) { if (pxmisw->xmi_type == (short)(nxv->xmi_dtype)) { xmidata->xmierr[xminode].pxmisw= pxmisw; xmidata->xminodes_alive |= (1 << xminode); if (pxmisw->xmi_flags&XMIF_SST) { nxv->xmi_xbe = (nxv->xmi_xbe & ~XMI_XBAD) | XMI_NRST; } break; } } if (pxmisw->xmi_type ==0) printf ("xmi %d node %d, unsupported device type 0x%x\n", xminumber,xminode, (unsigned short) nxv->xmi_dtype); } DELAY(10000); /* need to give time for XMI bad line to be set */} /* Wait for reset of xmi nodes to take effect. */xmiconf_wait(xminumber)int xminumber;{ struct xmi_reg *nxv; /* virtual pointer to XMI node */ struct xmi_reg *nxp; /* physical pointer to XMI node */ register int xminode; register struct xmisw *pxmisw; register struct xmidata *xmidata; register struct xmi_reg *cpunode=0; register int i; int broke; int alive; int totaldelay; /* Wait cumulative up to 20 seconds. For extra safety, this is double the spec value. */ totaldelay = 2000; xmidata = get_xmi(xminumber); nxv = xmidata->xmivirt; for(xminode = 0; xminode < MAX_XMI_NODE; xminode++,nxv++) { if( !(xmidata->xminodes_alive & (1 << xminode))) continue; pxmisw = xmidata->xmierr[xminode].pxmisw; /* wait here for up to remaining count time or until device is reset. */ if (pxmisw->xmi_flags&XMIF_SST) { cpunode = xmidata->cpu_xmi_addr; while((cpunode->xmi_xbe & XMI_XBAD) && (totaldelay-- > 0)) DELAY(10000); while((nxv->xmi_xbe&(XMI_ETF|XMI_STF)) && (totaldelay-- > 0)) DELAY(10000); nxv->xmi_xbe = nxv->xmi_xbe & ~(XMI_XBAD | XMI_NRST); } }} /* Do config of nodes. */xmiconf_conf(xminumber)int xminumber;{ struct xmi_reg *nxv; /* virtual pointer to XMI node */ struct xmi_reg *nxp; /* physical pointer to XMI node */ register int xminode; register struct xmisw *pxmisw; register struct xmidata *xmidata; register struct xmi_reg *cpunode=0; register int i; int broke; int alive; int totaldelay; xmidata = get_xmi(xminumber); /* do config of devices, adapters, controllers, etc. */ nxv = xmidata->xmivirt; for(xminode = 0; xminode < MAX_XMI_NODE; xminode++,nxv++) { if( !(xmidata->xminodes_alive & (1 << xminode))) continue; pxmisw = xmidata->xmierr[xminode].pxmisw; nxp = (struct xmi_reg *) cpup->nexaddr(xminumber,xminode); broke = (nxv->xmi_xbe & XMI_ETF) || (nxv->xmi_xbe & XMI_STF); alive = 0; if (pxmisw->xmi_flags&XMIF_DEVICE) alive |= xmi_config_dev(nxv,nxp,xminumber,xminode,xmidata); if (pxmisw->xmi_flags&XMIF_CONTROLLER); alive |= xmi_config_con(nxv,nxp,xminumber,xminode,xmidata); if (pxmisw->xmi_flags&XMIF_ADAPTER){ (**pxmisw->probes)(nxv,nxp,xminumber,xminode,xmidata); alive = 1; } if (pxmisw->xmi_flags&XMIF_NOCONF) { printf ("%s at xmi%d node %d", pxmisw->xmi_name,xminumber,xminode); if (broke == 0) printf("\n"); else printf(" is broken, continuing!\n"); (**pxmisw->probes)(nxv,nxp,xminumber,xminode,xmidata); alive=1; } if (alive==0) xminotconf(nxv,nxp,xminumber,xminode,xmidata); } /* The following loop cleans up any errors that might have gotten set when we probed the XMI */ nxv = xmidata->xmivirt; for(xminode = 0; xminode < MAX_XMI_NODE; xminode++,nxv++) { if (xmidata->xminodes_alive & (1<<xminode)) { nxv->xmi_xbe = nxv->xmi_xbe & ~XMI_XBAD; } }}struct uba_ctlr *xmifindum();xmi_config_con(nxv,nxp,xminumber,xminode,xmidata)struct xmi_reg *nxv;char *nxp;register int xminumber;register int xminode;register struct xmidata *xmidata;{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -