mike@BRL (12/30/82)
From: Michael Muuss <mike@BRL>
Date: 29 Dec 82 4:41:58-EST (Wed)
#
/*
* B U S M A P . C
* Version 2.7 -- 12/23/81
* Routines-
* mapalloc Allocate a portion of the UNIBUS map
* mapfree Deallocate as above
* ubminit Unibus map initialization (called by main)
*
*
* UNIBUS MAPPING
* The UNIBUS map provides a translation of addresses on the UNIBUS
* of a PDP-11/70 to memory-bus 22 bit addresses. As the UNIBUS address
* is 18 bits, only a fraction of the memory-bus may be directly accessed
* by the UNIBUS. Fortunately, the each register can map 4k words,
* which requires AT MOST 8 mapping registers per transfer, and more typically
* only one register. This allows many multiple tranfers simultaneously.
*
* The 5 high-order bits of the unibus 18-bit address are used to select
* which mapping register to use. Although there are 32 mapping registers,
* which can be read and written, the 32nd cannot be used for mapping
* because it would be used by unibus addresses 17760000-17777777 which
* are not recognized as valid addresses by the hardware. Therefore only
* 31 mapping registers are used. In the current implementation, the first
* 8 registers are reserved for kernel data space, for normal I/O.
*
* The benefits of allowing simultaneous "raw" I/O are numerous.
* For example, it permits swapping and user I/O to proceed without
* competition for the UNIBUS map. Also, it is essential when buffers,
* clists, etc. are moved out of kernel data space.
*
* Converted to generalized per-transfer mapping by Peter Gross, NCAR.
*
* R E V I S I O N H I S T O R Y
*
* 12/10/80 PAG Converted to use of malloc() on ubmap for generalized
* multi-transfer capability
*
* 02/02/81 PAG Cleaned up code and comments
*
* 06/24/81 PAG Fixed bug in wtoub() macro
*
* 10/24/81 PAG Added spl6() before mfree() call in mapfree();
* converted to use b_ubsiz and b_ubadr.
*
* 04/14/82 MJM Converted to memalloc/memfree, UBUF (BRL 6.155)
* Also fixed b_addr computation (03 -> 07)
*
* 10/06/82 MJM Converted to use UBMapflag, as set by the machine
* assist (BRL 6.171)
*/
#include "../h/types.h"
#include "param.h"
#include "../h/const.h"
#include "../h/buf.h"
#include "../h/seg.h"
#include "../h/systm.h"
#include "../h/res.h"
#include "../h/pqueue.h"
#include "../h/brlnet.h"
/*
* macro to convert words to ub map segments (4kw)
* handles boundary conditions
*/
#define wtoub(x) ( (((x)>>12) & 017) + ( ((x) & 07777)?1:0 ) )
int mapwanted;
/*
* M A P A L L O C
*/
mapalloc(bp)
register struct buf *bp;
{
register int *ub_reg;
register int i;
int base[2];
if( !UBMapflag )
return;
/*
* Compute # of 4kw segments (unibus map 'clicks') necessary for
* the transfer
*/
bp->b_ubsiz = wtoub( -bp->b_wcount);
spl6();
/*
* Grab enough (consecutive) mapping registers to for this transfer
*/
while( (bp->b_ubadr = memalloc( &ubmmap, bp->b_ubsiz )) == NULL ) {
mapwanted++;
psleep( &ubmapq, PSWP, WUBM );
}
spl0();
r.r_ubmuse++;
/* compute base addr of mem WORD in which DMA originates */
base[0] = bp->b_xmem;
base[1] = bp->b_addr & ~1; /* UBM addr must be even */
/*
* Here the buffer address is adjusted so that when the
* unibus address is accessed it will choose the appropriate
* mapping register (bits 17-13 of the UB addr)
*/
bp->b_addr &= 01;
bp->b_addr |= (bp->b_ubadr&07)<<13;
bp->b_xmem = (bp->b_ubadr&030)>>3;
bp->b_flags |= B_MAP;
ub_reg = &UBMAP->r[bp->b_ubadr*2];
for( i=0; i < bp->b_ubsiz; i++ ) {
*ub_reg++ = base[1];
*ub_reg++ = base[0];
base->longp += 020000; /* 4Kw memory pages */
}
}
/*
* M A P F R E E
*/
mapfree(bp)
register struct buf *bp;
{
register int s;
bp->b_flags &= ~B_MAP;
/* High spl is required because of interupt level invocations
* by iodone().
*/
s = PS->integ;
spl6();
memfree( &ubmmap, bp->b_ubsiz, bp->b_ubadr );
PS->integ = s;
bp->b_ubsiz = bp->b_ubadr = 0;
#ifdef UBUF
/* Repair damage done by mapalloc() to the b_addr & b_xmem fields */
bp->b_addr = NETBA(bp->b_paddr << 6);
bp->b_xmem = bp->b_paddr >> (16-6);
/* The B_PHYS flag should still be OK */
#endif UBUF
if(mapwanted) {
mapwanted = 0;
pwakeup( &ubmapq );
}
}
/*
* U B M I N I T
*/
ubminit()
{
register int i;
if( UBMapflag ) {
/*
* Initialize the kernel data space mapping registers (0-7)
*/
for( i=0; i<62; i += 2 ) {
UBMAP->r[i] = i<<12;
UBMAP->r[i+1] = 0;
}
/*
* intialize the ubmap with the remaining free regs
*/
memfree( &ubmmap, (31-8), 8 );
}
}