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