📄 uba.c
字号:
#ifndef lintstatic char *sccsid = "@(#)uba.c 4.2 (ULTRIX) 11/9/90";#endif lint/************************************************************************ * * * Copyright (c) 1985,86,87 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. * * * ************************************************************************ * Modification History: * * 23-Feb-90 -- sekhar * Merged Joe Martin's fix for 3.1 cld. When copying user PTEs, * check for page crossing and reevaluate vtopte. * * 15-Oct-89 Robin Lewis * patched the qbus map register assignment to set the High bit on vax's * * 20-Jul-89 Mark Parenti * Add code for reset of KDM70. * * 15-Apr-89 Kong * Fixed bug in qbasetup so that the magic cookie returned is * in the format defined in the routine block comment. * * 05-Nov-88 Robin Lewis * Changed the Q22-Bus map register allocation to return registers * in clicks of 8. This is necessary because there are insuficient * bits in the int to pass back the offset in the page, the starting * map register and the number of map registers allocated. Nine * bit are needed to have a 512 offset value and that can not change. * The remainint bits return the starting map register with a max * of 8K and the number of registers which can also be 8K ..? * Passing back clicks of 8 registers allows this to work but * does waste registers (but only until they are released.) * * 12-11-87 Robin L. and Larry C. * Added portclass support to the system. * * 15-Sep-87 -- darrell * Removed unnecessary consistency checks in vs_bufctl. * * 19-May-87 -- darrell * Fixed a hole in vs_bufctl that was causing a panic during the * installation on VAXstation/MicroVAX 2000. * * 12-May-87 -- darrell * Added a temporary variable to vs_bufctl to keep track of a * pointer to the vsdev structure for the driver that is active. * This fixes several panics. * * 23-Apr-87 -- darrell * vs_bufctl has been changed to accpet a pointer to structure * that contains the the ID of the device calling it, the action * to be performed, and a pointer to the routine to call back * into to driver. (stc.c or sdc.c) * * 29-Sep-86 -- darrell * Space for vsbuf is now allocated here instead of in * ../data/sdc_data.c. * * 26-Sep-86 -- darrell * Fixed a bug in vs_bufctl that caused the vaxstar tape/disk * buffer to be allocated incorrectly. * * 05-Sep-86 -- darrell * Added a panic. vs_bufctl will now panic if called by the * owner of the buffer. * * 30-Aug-86 -- darrell (Darrell Dunnuck) * Fix bugs in VAXstar data buffer interlock code, which * allows TZK50 and disk to share a common DMA data buffer. * * 5-Aug-86 -- gmm (George Mathew) and darrell (Darrell Dunnuck) * Added routines to allow sharing the common disk data buffer * between the VAXstar disk and TZK50 drivers. * * 13-Jun-86 -- jaw fix to uba reset and drivers. * * 14-May-86 -- bjg * Move uba# field in subid when logging uba errors * * 16-Apr-86 -- afd * Changed UMEMmap to QMEMmap and umem to qmem for QBUS reset. * * 19-feb-86 -- bjg add uba error logging * * 04-feb-86 -- jaw get rid of biic.h. * * 15-jul-85 -- jaw * VAX8800 support * * 11 Nov 85 depp * Removed System V conditional compiles. * * 08-Aug-85 darrell * Zero vectors are now timed. If we get too many, a message is * printed into the message buffer reporting the rate at which they * are accuring. The routine "ubatimer" was added. * * 11-jul-85 -- jaw * fix bua/bda map registers. * * 19-Jun-85 -- jaw * VAX8200 name change. * * 06 Jun 85 -- jaw * add in the BDA support. * * 7 May 85 -- rjl * Turned on Q-bus map as part of bus init. * * 22 Mar 85 -- depp * Added Sys V Shared memory support * * 13-MAR-85 -jaw * Changes for support of the VAX8200 were merged in. * * 27-Feb-85 -tresvik * Changes for support of the VAX8600 were merged in. * * 12 Nov 84 -- rjl * Added support for MicroVAX-II notion of a q-bus adapter. */#include "../machine/pte.h"#include "../h/param.h"#include "../h/systm.h"#include "../h/map.h"#include "../h/vmmac.h"#include "../h/buf.h"#include "../h/vm.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/proc.h"#include "../h/conf.h"#include "../h/dk.h"#include "../h/kernel.h"#include "../h/clist.h"#include "../h/ipc.h"#include "../h/shm.h"#include "../h/errlog.h"#include "../machine/cpu.h"#ifdef vax#include "../machine/mtpr.h"#endif vax#ifdef mips#include "../machine/ssc.h"#endif mips#include "../machine/nexus.h"#include "../io/uba/ubareg.h"#include "../io/uba/ubavar.h"#include "../io/bi/buareg.h"#define QIPCR 0x1f40 /* Q-bus Inter-processor csr */#define LMEA 0x20 /* Local memory access enable */#define QMCIA 0x4000 /* Invalidate all cached map regs*/#ifdef mips#define WBFLUSH wbflush() /* Flush write buffer on mips */#else#define WBFLUSH ; /* NOP for vax */#endif mips/* * For zero vector timer -- should really be in a data.c file, but * but there isn't one for uba.c */int ubatimer();int zvintvl = ZVINTVL; /* zero vector timer interval in seconds */int zvthresh = ZVTHRESH; /* zero vector timer threhsold for reporting */char ubasr_bits[] = UBASR_BITS;/* * Do transfer on device argument. The controller * and uba involved are implied by the device. * We queue for resource wait in the uba code if necessary. * We return 1 if the transfer was started, 0 if it was not. * If you call this routine with the head of the queue for a * UBA, it will automatically remove the device from the UBA * queue before it returns. If some other device is given * as argument, it will be added to the request queue if the * request cannot be started immediately. This means that * passing a device which is on the queue but not at the head * of the request queue is likely to be a disaster. */ubago(ui) register struct uba_device *ui;{ register struct uba_ctlr *um = ui->ui_mi; register struct uba_hd *uh; register int s, unit; uh = &uba_hd[um->um_ubanum]; s = spl6(); if (um->um_driver->ud_xclu && uh->uh_users > 0 || uh->uh_xclu) goto rwait; um->um_ubinfo = ubasetup(um->um_ubanum, um->um_tab.b_actf->b_actf, UBA_NEEDBDP|UBA_CANTWAIT); if (um->um_ubinfo == 0) goto rwait; uh->uh_users++; if (um->um_driver->ud_xclu) uh->uh_xclu = 1; splx(s); if (ui->ui_dk >= 0) { unit = ui->ui_dk; dk_busy |= 1<<unit; dk_xfer[unit]++; dk_wds[unit] += um->um_tab.b_actf->b_actf->b_bcount>>6; } if (uh->uh_actf == ui) uh->uh_actf = ui->ui_forw; (*um->um_driver->ud_dgo)(um); return (1);rwait: if (uh->uh_actf != ui) { ui->ui_forw = NULL; if (uh->uh_actf == NULL) uh->uh_actf = ui; else uh->uh_actl->ui_forw = ui; uh->uh_actl = ui; } splx(s); return (0);}ubadone(um) register struct uba_ctlr *um;{ register struct uba_hd *uh = &uba_hd[um->um_ubanum]; if (um->um_driver->ud_xclu) uh->uh_xclu = 0; uh->uh_users--; /* already released map registers if it's a MicroVAX I */ if( (uh->uba_type & UBAUVI) ==0) ubarelse(um->um_ubanum, &um->um_ubinfo);}/* * Allocate and setup UBA map registers, and bdp's * Flags says whether bdp is needed, whether the caller can't * wait (e.g. if the caller is at interrupt level). * * Return value: * Bits 0-8 Byte offset * Bits 9-17 Start map reg. no. * Bits 18-27 No. mapping reg's * Bits 28-31 BDP no. */ubasetup(uban, bp, flags) struct buf *bp;{ register struct uba_hd *uh = &uba_hd[uban]; register int temp; int npf, reg, bdp; unsigned v; register struct pte *pte, *io; struct proc *rp; int a, o, ubinfo, vax_pfn; int user_addr = 0;#ifdef mips int mips_of; /* offset within a mips page */ int mips_pfn; /* PFN of a mips pte */#endif mips if (uh->uba_type & (UBA730|UBAUVI|UBAUVII)) flags &= ~UBA_NEEDBDP; v = btop(bp->b_un.b_addr); o = (int)bp->b_un.b_addr & 0x1ff; /* offset within a VAX page, even for mips based systesm where PGOFFSET is different - DO NOT replace 0x1ff with PGOFFSET */#ifdef mips /* offset within a mips page */ mips_of = (int)bp->b_un.b_addr & PGOFSET;#endif /* * Number of VAX pages spanned by the buffer + 1(hence number of * map registers needed since we need one guard page) */ npf = (((unsigned)(bp->b_bcount + o)+0x1ff) >> 9) + 1; a = spl6(); while ((reg = rmalloc(uh->uh_map, (long)npf)) == 0) { if (flags & UBA_CANTWAIT) { splx(a); return (0); } uh->uh_mrwant++; sleep((caddr_t)&uh->uh_mrwant, PSWP); } bdp = 0; if (flags & UBA_NEEDBDP) { while ((bdp = ffs(uh->uh_bdpfree)) == 0) { if (flags & UBA_CANTWAIT) { rmfree(uh->uh_map, (long)npf, (long)reg); splx(a); return (0); } uh->uh_bdpwant++; sleep((caddr_t)&uh->uh_bdpwant, PSWP); } uh->uh_bdpfree &= ~(1 << (bdp-1)); } else if (flags & UBA_HAVEBDP) bdp = (flags >> 28) & 0xf; splx(a); reg--; ubinfo = (bdp << 28) | (npf << 18) | (reg << 9) | o; temp = (bdp << 21) | UBAMR_MRV; if (bdp && (o & 01)) temp |= UBAMR_BO; rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc; pte = 0; if ((bp->b_flags & B_PHYS) == 0) {#ifdef vax pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)];#else /* mips KSEG Addressing */ if(IS_KSEG0(bp->b_un.b_addr)){ /* unmapped KSEG areas */ mips_pfn = btop(K0_TO_PHYS(bp->b_un.b_addr)); } else if(IS_KSEG1(bp->b_un.b_addr)){ /* unmapped KSEG areas */ mips_pfn = btop(K1_TO_PHYS(bp->b_un.b_addr)); } else if(IS_KSEG2(bp->b_un.b_addr)){ /* mapped KSEG areas */ pte = &Sysmap[btop(bp->b_un.b_addr - K2BASE)]; }#endif vax } else if (bp->b_flags & B_UAREA) pte = &rp->p_addr[v]; else if (bp->b_flags & B_PAGET) pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)]; else if ((bp->b_flags & B_SMEM) && /* SHMEM */ ((bp->b_flags & B_DIRTY) == 0)) pte = ((struct smem *)rp)->sm_ptaddr + v; else { pte = vtopte(rp, v); user_addr++; } if ((uh->uba_type & UBAUVI) ==0 || (flags&UBA_MAPANYWAY)) { /* get address of starting UNIBUS map register */ io = &uh->uh_uba->uba_map[reg]; /* Loop to load all the map registers with pte information. * For a mips we need to simulate vax pte structures. * * On a VAX, we have npf map registers to fill, each * map register is to be filled by a VAX pte. * * On a mips, we have npf map registers to fill, but * each mips page is 4KB, so we have fewer mips ptes * to use. * * The following loop iterates for each map register. */ while (--npf != 0) {#ifdef mips if(pte != 0) { /* pte points to the mips pte */ if (pte->pg_pfnum == 0) panic("uba zero uentry"); vax_pfn = (pte->pg_pfnum << 3) + (mips_of / 0x200); } else { /* There are no pte's, use pfn's */ vax_pfn = (mips_pfn << 3) + (mips_of / 0x200); } *(int *)io++ = vax_pfn | UBAMR_MRV; mips_of += 0x200; /* next vax page */ if (mips_of >= 0x1000) { /* Crossing mips page boundary */ /* Go on to next mips page */ mips_of -= 0x1000;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -