[net.unix-wizards] UNIBUS MAP Allocation

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 );
	}
}