Ultrix-3.1/sys/sys/ubmap.c

Compare this file to the similar file:
Show the results in this format:


/**********************************************************************
 *   Copyright (c) Digital Equipment Corporation 1984, 1985, 1986.    *
 *   All Rights Reserved. 					      *
 *   Reference "/usr/src/COPYRIGHT" for applicable restrictions.      *
 **********************************************************************/

/*
 * SCCSID: @(#)ubmap.c	3.0	4/21/86
 */
/*
 *  File name:
 *
 *	ubmap.c
 *
 *  Source file description:
 *
 *	This module contains the kernel routines needed to: initialize,
 *	allocate, and free the unibus map resource. These routines were
 *	moved from main.c and machdep.c to ubmap.c so that they can be
 *	optionally included in the kernel at sysgen time. This saves
 *	kernel space if the processor does not have a unibus map.
 *
 *  Functions:
 *
 *	mapinit		Initialize the unibus mapping registers.
 *	mapalloc	Allocates the unibus map for an I/O transfer.
 *	mapfree		Frees the map after the I/O transfer completes.
 *
 *  Usage:
 *
 *	Called by the kernel and device drivers.
 *
 *  Compile:
 *
 *	cd /usr/sys/sys; make -k
 *	cd /usr/sys/ovsys; make -k
 *	(cc -c -O ubmap.c)
 *
 *  Modification history:
 *
 *	June 1985
 *		Modified to use malloc/mfree for keeping track
 *		of the mapping registers.  This also has changes
 *		for mapping out the clists.  -Dave Borman
 *	30 December 1984
 *		File Created -- Fred Canter
 *
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/seg.h>
#include <sys/buf.h>
#include <sys/uba.h>
#include <sys/map.h>

memaddr	bpaddr;		/* physical address of buffers (in 64 byte clicks) */

struct map ub_map[12] = { MAPDATA(12) };
/*
 * Initialize the ub_map, and some of the mapping registers.
 * The first register maps the stuff between &ub_start and &ub_end.
 * This includes things like uda, hp_bads, hk_bads, and
 * TS (cmdpkt, chrbuf, mesbuf).  If the clists aren't mapped out,
 * cfree is also included in this.  If the clists are mapped out,
 * then the second unibus register maps them.  We then allocate
 * enough registers to map the buffers, and free up the rest.
 */

mapinit()
{
	register int i, lastbuf_reg;
	long paddr = (long)bpaddr << 6;
	extern int nclist;

	if(!ubmaps)
		return;
	setubregno(0, (long)&cfree);
#ifdef	UCB_CLIST
	setubregno(CLIST_UBADDR/UBPAGE, clstaddr);
#endif	UCB_CLIST

	lastbuf_reg = nubreg(nbuf, BSIZE) + BUF_UBADDR/UBPAGE;
	for (i = BUF_UBADDR/UBPAGE; i < lastbuf_reg; i++) {
		setubregno(i, paddr);
		paddr += (long)UBPAGE;
	}
	mfree(ub_map, 31 - lastbuf_reg, lastbuf_reg);
}

/*
 * Unibus map allocation routine
 *
 * Unibus Map Registers are allocated as follows:
 *
 *  UMBR 31 is not used.
 *
 * Map register 0 maps the fisrt 8K bytes of BSS space, this covers
 * 	NPR access to: UDA comm. area, hp_bads & hk_bads.
 * Map register 1 maps to the clist area.
 * Map registers 2 thru ? map the I/O buffer cache.
 * The rest of the registers are available for mapping raw I/O transfers.
 */

int	maplock;

mapalloc(bp)
register struct buf *bp;
{
	long			paddr, ubaddr;
	int			s, ub_nregs;
	register int		ub_first;
	register struct ubmap	*ubp;

	if(!ubmaps)
		return;

	paddr = (((long) ((unsigned) bp->b_xmem)) << 16 )
		| ((long) ((unsigned) bp->b_un.b_addr));
	if ((bp->b_flags & B_PHYS) == 0) {
		/*
		 * Transfer in the buffer cache.
		 * Change the buffers's physical address
		 * into a UNIBUS address for the driver.
		 */
		ubaddr = paddr - (((ubadr_t) bpaddr) << 6) + BUF_UBADDR;
		bp->b_un.b_addr = loint(ubaddr);
		bp->b_xmem = hiint(ubaddr);
		bp->b_flags |= B_MAP;
	} else {
		ub_nregs = (int)btoub(bp->b_bcount);

		s = spl6();
		while ((ub_first = malloc(ub_map, ub_nregs)) == NULL) {
			maplock = 1;
			sleep((caddr_t)&ub_map, PSWP+1);
		}
		splx(s);

		ubp = &UBMAP[ub_first];
		bp->b_xmem = ub_first >> 3;
		bp->b_un.b_addr = (ub_first & 07) << 13;
		bp->b_flags |= B_MAP;

		while (ub_nregs--) {
			ubp->ub_lo = loint(paddr);
			ubp->ub_hi = hiint(paddr);
			ubp++;
			paddr += (long)UBPAGE;
		}
	}
}

/*
 * ub_alloc(paddr, count)
 * Given a physical address and a byte count, ub_alloc
 * maps the given memory onto the unibus and returns
 * this unibus address in clicks.
 */

ub_alloc(paddr, count)
long	paddr;
int	count;
{
	register int ub_first, ub_nregs;
	register struct ubmap	*ubp;
	int s;

	ub_nregs = (int)btoub(count);

	s = spl6();
	while ((ub_first = malloc(ub_map, ub_nregs)) == NULL) {
		maplock = 1;
		sleep((caddr_t)&ub_map, PSWP+1);
	}
	splx(s);

	for (ubp = &UBMAP[ub_first]; ub_nregs--; ubp++) {
		ubp->ub_lo = loint(paddr);
		ubp->ub_hi = hiint(paddr);
		paddr += (long)UBPAGE;
	}
	return(ub_first<<7);
}

#ifdef	notused
/*
 * ub_free(ubaddr, count)
 * Given a unibus address (in clicks) and a byte count, ub_free()
 * releases that segment of the unibus map and wakes up anyone
 * waiting for the unibus map.
 */

ub_free(ubaddr, count)
unsigned	ubaddr;
unsigned	count;
{
	register int s = spl6();

	mfree(ub_map, (int) btoub(count),
		ubaddr>>7);
	splx(s);
	if (maplock) {
		wakeup((caddr_t)ub_map);
		maplock = 0;
	}
}
#endif	notused

mapfree(bp)
register struct buf *bp;
{
	register int s;

	if (bp->b_flags & B_PHYS) {
		s = spl6();
		mfree(ub_map, (int) btoub(bp->b_bcount),
			(bp->b_xmem << 3) | (((int)bp->b_un.b_addr >> 13) & 07));
		splx(s);
		bp->b_flags &= ~B_MAP;
		if (maplock) {
			wakeup((caddr_t)ub_map);
			maplock = 0;
		}
	} else {
		long ubaddr, paddr;
		/*
		 * Translate the UNIBUS virtual address of this buffer
		 * back to a physical memory address.
		 */
		ubaddr = (((long) ((unsigned) bp->b_xmem)) << 16)
			| ((long) ((unsigned) bp->b_un.b_addr));
		paddr = ubaddr - (long) BUF_UBADDR + (((long) bpaddr) << 6);
		bp->b_un.b_addr = loint(paddr);
		bp->b_xmem = hiint(paddr);
		bp->b_flags &= ~B_MAP;
	}
}