/*	mba.c	2.1	1/5/80	*/

#include "../h/param.h"
#include "../h/buf.h"
#include "../h/conf.h"
#include "../h/systm.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/proc.h"
#include "../h/seg.h"
#include "../h/pte.h"
#include "../h/map.h"
#include "../h/mba.h"
#include "../h/mtpr.h"
#include "../h/vm.h"

/*
 * startup routine for MBA controllers.
 */
#define	MBAWCOM	0x30
#define	MBARCOM	0x38
#define	GO	01

int mbaboff;

mbastart(bp, adcr)
register struct buf *bp;
int *adcr;
{
	register int i;
	int npf;
	unsigned v;
	register struct pte *pte, *io;
	int o;
	int vaddr;
	register struct mba_regs *mbap;
	struct proc *rp;
	extern int mbanum[], *mbaloc[];
	extern char buffers[][];

	mbap = (struct mba_regs *)mbaloc[mbanum[major(bp->b_dev)]];
	if ((bp->b_flags & B_PHYS) == 0)
		vaddr = (bp->b_un.b_addr - (char *)buffers) + mbaboff;
	else {
		io = (struct pte *)mbap;
		io += (MBA_MAP + 128*4)/4;
		v = btop(bp->b_un.b_addr);
		o = (int)bp->b_un.b_addr & PGOFSET;
		npf = btoc(bp->b_bcount + o);
		rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc;
		vaddr = (128 << 9) | o;
		if (bp->b_flags & B_UAREA) {
			for (i = 0; i < UPAGES; i++) {
				if (rp->p_addr[i] == 0)
					panic("mba: zero upage");
				*(int *)io++ = rp->p_addr[i] | PG_V;
			}
		} else if ((bp->b_flags & B_PHYS) == 0) {
			v &= 0x1fffff;		/* drop to physical addr */
			while (--npf >= 0)
				*(int *)io++ = v++ | PG_V;
		} else {
			if (bp->b_flags & B_PAGET)
				pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];
			else
				pte = vtopte(rp, v);
			while (--npf >= 0) {
				if (pte->pg_pfnum == 0)
					panic("mba, zero entry");
				*(int *)io++ = pte++->pg_pfnum | PG_V;
			}
		}
	}
	mbap->mba_sr = -1;	/* clear status (error) bits */
	mbap->mba_bcr = -bp->b_bcount;
	mbap->mba_var = vaddr;
	if (bp->b_flags & B_READ)
		*adcr = MBARCOM | GO;
	else
		*adcr = MBAWCOM | GO;
}

mbainit()
{
	register int *io0, *io1, *b, t, j;
	extern int *mbaloc[];
	extern char buffers[][];

	io0 = mbaloc[0] + (MBA_MAP/4);
	io1 = mbaloc[1] + (MBA_MAP/4);
	b = (int *)Sysmap + ((((int) buffers)>>9)&PG_PFNUM);
	j = NBUF * CLSIZE + ((int)buffers & 0x1ff ? 1 : 0);
	do {
		t = PG_V | (*b++ & PG_PFNUM);
		*io0++ = t;
		*io1++ = t;
	} while (--j>0);
	*io0 = 0;		/* invalidate next entry */
	*io1 = 0;
	mbaboff = (int)buffers & 0x1ff;
}
