/* * Corvus Disk System * * (C) 1984 UniSoft Corp. of Berkeley CA * * UniPlus Source Code. This program is proprietary * with Unisoft Corporation and is not to be reproduced * or used in any manner except as authorized in * writing by Unisoft. */#include "sys/param.h"#include "sys/mmu.h"#include "sys/types.h"#include "sys/inode.h"#include "sys/ino.h"#include "saio.h"#include "sys/cops.h"#include "sys/pport.h"#include "sys/d_profile.h"#include "sys/cv.h"#define cvqwait(a)	while(((a)->d_irb & ST_BUSY) == 0)cvwait(addr)register struct device_d *addr;{	register i;	for (i=10; i>0; i--);	/* pause for Sunol */	i = 1000000;	while ((addr->d_irb & ST_BUSY) == 0)		if (i-- == 0) {			printf("cvwait:  timeout waiting for controller\n");			return(-1);		}	return(0);}char cviflag[NPPDEVS];		/* has it been opened before? *//* * cvopen - check for existence of controller */cvopen(iobp)register struct iob *iobp;{	register punit = iobp->i_unit;	if (punit) {	/* for expansion slot check slot number */		if (!PPOK(punit)) {			printf("Invalid device 0x%x\n", punit);			return(-1);		}	}	if (cviflag[punit] == 0) {		if (cvinit(punit))			return(-1);		cviflag[punit]++;	}	return 0;}/* * cvinit - initialize drive first time */cvinit(punit)register punit;{	register struct device_d *devp = pro_da[punit];	register char zero = 0;	if (devp == PPADDR) {		devp->d_ddrb &= 0x5C;	/* port B bits: 0,1,5,7 to in, 2,3,4,6 to out */		devp->d_pcr = 0x6B;	/* set controller CA2 pulse mode strobe */		devp->d_ddra = zero;	/* set port A bits to input **/		devp->d_irb |= CMD|DRW;	/* set command = false  set direction = in */		devp->d_ddrb |= 0x7C;		devp->d_irb &= ~DEN;	/* set enable = true */	} else {		devp->d_pcr = 0x6B;	/* set controller CA2 pulse mode strobe */		devp->d_ddra = zero;	/* set port A bits to input **/		devp->d_irb = CMD|DRW;	/* set command = false  set direction = in */		devp->d_ddrb = 0x7C;	}	return 0;}cvstrategy(ip, func)register struct iob *ip;{	register punit = ip->i_unit;	register daddr_t bn;	register resid;	int offset;	caddr_t addr;	if (ip->i_bn < 0) {		printf("cvstrategy: bn < 0\n");		return(-1);	}	resid = ip->i_cc;loop:	if (resid < PBSIZE)		goto out;	offset = ip->i_cc - resid;	addr = ip->i_ma + offset;	bn = ip->i_bn + (offset >> PBSHIFT);	if (cvrw(punit, bn, func&F_READ, addr) != 0)		return(-1);	resid -= PBSIZE;	goto loop;out:	if (resid != 0)		printf("cvstrategy: bn=%d resid=%d\n", ip->i_bn, resid);	return(ip->i_cc - resid);}cvrw(punit, bn, rflag, buff)register punit;daddr_t bn;register rflag;register caddr_t buff;{	register struct device_d *addr;	register char status;	if (cvop(punit, 4, rflag ? N_R512 : N_W512,		cvbtovd(bn), bn & 0xff, bn>>8 & 0xff) < 0)		return(-1);	if (!rflag && cvw(punit, buff) < 0)		return(-1);	addr = pro_da[punit];	addr->d_ddra = 0x00;	/* data direction port A bits to input */	addr->d_irb |= 0x08;	/* bidirectional driver to input */	if (cvwait(addr) < 0)		return(-1);/*	cvqwait(addr);		/* quick wait (macro without timeout) */	if (status = addr->d_ira) {		printf("bad status 0x%x\n", status&0xFF);		return(-1);	}	if (rflag && cvr(punit, buff, PBSIZE) < 0)		return(-1);	return(0);}/* VARARGS3 */cvop(unit, na, a){	register int *ap;	register struct device_d *addr = pro_da[unit];	addr->d_ddra = 0xff;	/* port A to output */	addr->d_irb &= ~0x08;	/* bidirectional driver to output */	ap = &a;	for (; na > 0; na--, ap++) {		if (cvwait(addr) < 0) {			printf("cvop: timeout\n");			return(-1);		}		addr->d_ira = *ap;	}	return 0;}cvw(unit, buff)register char *buff;{	register char *ira;	register struct device_d *addr = pro_da[unit];	register n = 512;	register zero = 0;	register char status;	if (cvwait(addr) < 0) {		printf("leaving cvw before trying any writes\n");		return(-1);	}	ira = &(addr->d_ira);	for ( ; n > 0; n--) {		while (((status = addr->d_irb) & ST_BUSY) == 0);		if ((status & ST_HTOC) == 0)			break;		*ira = *buff++;	}	for (;;) {		if (cvwait(addr) < 0) {			printf("leaving cvw before fill, %d bytes left\n", n);			return(-1);		}		if ((addr->d_irb & ST_HTOC) == 0)			break;		*ira = zero;	}	if (n > 0) {		printf("cvw: %d bytes short\n", n);		return -1;	}	return 0;}cvr(unit, buff, n)register char *buff;register n;{	register char *ira;	register struct device_d *addr = pro_da[unit];	register char status;	if (cvwait(addr) < 0) {		printf("leaving cvr before trying any reads\n");		return(-1);	}	ira = &(addr->d_ira);	for ( ; n > 0; n--) {		while (((status = addr->d_irb) & ST_BUSY) == 0);		if (status & ST_HTOC)			break;		*buff++ = *ira;	}	if (n > 0) {		printf("cvr: %d bytes short\n", n);		return -1;	}	for (;;) {		if (cvwait(addr) < 0) {			printf("leaving cvr after reading all bytes\n");			return(-1);		}		if (addr->d_irb & ST_HTOC)			break;		n = *ira;	}	return 0;}