#
/*
 */

#include "../head/param.h"
#include "../head/buf.h"
#include "../head/bufx.h"
#include "../head/conf.h"
#include "../head/systm.h"
#include "../head/user.h"
#include "../head/userx.h"
#include "../head/proc.h"
#include "../head/procx.h"
#include "../head/seg.h"

/*
 * startup routine for RH controllers.
 */
#define	IENABLE	0100
#define	RHWCOM	060
#define	RHRCOM	070
#define	GO	01

rhstart(bp, devloc, devblk, abae)
struct buf *bp;
int *devloc, *abae;
{
	register int *dp;
	register struct buf *rbp;
	register int com;

	dp = devloc;
	rbp = bp;
	if(cputype == 70)
		*abae = rbp->b_xmem;
	*dp = devblk;			/* block address */
	*--dp = rbp->b_addr;		/* buffer address */
	*--dp = rbp->b_wcount;		/* word count */
	com = IENABLE | GO |
		((rbp->b_xmem & 03) << 8);
	if (rbp->b_flags&B_READ)	/* command + x-mem */
		com =| RHRCOM; else
		com =| RHWCOM;
	*--dp = com;
}

/*
 * 11/70 routine to allocate the
 * UNIBUS map and initialize for
 * a unibus device.
 * The code here and in
 * rhstart assumes that an rh on an 11/70
 * is an rh70 and contains 22 bit addressing.
 */
int	mapwant;

mapalloc(abp)
struct buf *abp;
{
	register i, j;
	register struct buf *bp;
	long dble;
	int regno;

	bp = abp;
	if(cputype != 70 || bp->b_wcount == 0)
		return;
	j = (-bp->b_wcount-1)/4096+1;
	spl6();
	while((regno = malloc(ubmap, j)) == 0) {
		mapwant++;
		sleep(ubmap, PSWP);
	}
	spl0();
	dble.loword = bp->b_addr;
	dble.hiword = bp->b_xmem;
	j = 2*(regno+j);
	for(i = regno*2; i<j ; i =+ 2) {
		UBMAP->r[i] = dble.loword;
		UBMAP->r[i+1] = dble.hiword;
		dble =+ 8192;
	}
	bp->b_xmem = regno>>3;
	bp->b_addr = regno<<13;
	bp->b_flags =| B_MAP;
}

mapfree(abp)
struct buf *abp;
{
	register struct buf *bp;
	register regno;

	bp = abp;
	bp->b_flags =& ~B_MAP;
	regno = bp->b_xmem<<3 | ((bp->b_addr>>13)&07);
	mfree(ubmap, (-bp->b_wcount-1)/4096+1, regno);
	if(mapwant) {
		wakeup(ubmap);
		mapwant = 0;
	}
}
/*
 * For inverted disk areas, negcyl cchecks physical I/O
 * requests to see if they cross cylinder boundaries and
 * breaks the request into two parts if needed
 */
/*
 * NOTE: THE SWAP AREA MAY NOT BE ON AN INVERTED DISK AREA
 */
negcyl(strat,bp,dev,flag,nblks,nsect)
struct buf *bp;
int	(*strat)();
{
	register char *bend,*beg;
	register char *count;
	char	*savcnt;

	count = u.u_count;
	beg = lshift(u.u_offset,-9);
	bend = beg + ((count>>9)&0177) - ((count&0777)?0:1);
	if((bend > beg)&&(ldiv(bend,nsect)!=ldiv(beg,nsect))){
		savcnt = u.u_count = (nsect - lrem(beg,nsect))*512;
		physio(strat,bp,dev,flag,nblks);
		if(u.u_error)
			return;
		if(u.u_count){
			u.u_count =+ count - savcnt;
			return(1);
		}
		dpadd(u.u_offset,savcnt);
		u.u_count = count - savcnt;
		u.u_base =+ savcnt;
	}
	return(0);
}
