File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / d / ioex / xylog.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Sun Jul 28 12:24:19 2019 UTC (7 years ago) by root
Branches: bsd, MAIN
CVS tags: v12b, v121, HEAD
Power 6/32 Unix version 1.2b

#include "xylog.h"
#include "pte.h"


/*	This table contains drive type for each
	drive attached to Xylogic controller.
	e.g Drive 0 is EAGLE type. This info. is
	configuration dependent.
*/

#define DUMMY	EAGLE
struct DTYPE dtype[MAXXYDRIVES] = {
	EAGLE,DUMMY,DUMMY,DUMMY
};

struct TYPEPAR typepar[2] = {
	20,46,842,"Eagle",
	0,0,0,""
};

extern long unused, IOinit;
struct Xreg *Xyreg;
struct IOPB xiopb;
long Xdone=0;
long ForMat = 1;

xylog()
{	register long r12;
	long oldvec;

	writes("\n	** Xylogics test **\n");
	m_xy();			/* Map register I/O address */

	/* Set handler for Xylogics interrupt */
	asm("movab xyhdlr,r12");
	set_handler(XYVEC,&oldvec,r12);

	if (xy_reset()) {		/* Reset controller */
		writes("\nXylogic controller is at ");
		writeh(XBASE+XOFFS);
		}
	   else {
		writes("\nXylogic not found...\n");
		return(0); }
	xy_ex();		/* Exercise controller */
	return(1);
}

xy_ex()
{	register long ix, stat;
	register struct TYPEPAR *tp;
	char Buff[NBPG];

	for(ix=0;ix<MAXXYDRIVES;ix++) setdr(dtype[ix].type);
	if (ForMat) Form(0);
	tp = &typepar[0];
	for (ix=0;ix<NBPG;ix++) Buff[ix] = 0xab;
	/* Write last sector */
	stat = xyop(0,XYWRITE,1,tp->nocyls-1,tp->noheads-1,tp->nosecs-1,Buff);
	if (stat) { writes("\nWrite error ... \n");
		return; }
	for (ix=0;ix<NBPG;ix++) Buff[ix] = 0;
	/* Read last sector */
	stat = xyop(0,XYREAD,1,tp->nocyls-1,tp->noheads-1,tp->nosecs-1,Buff);
	if (stat) { writes("\nRead error ... \n");
		return; }
	for (ix=0;ix<512;ix++) {
		if (Buff[ix] != 0xab) {
			writes("\ncompare error, expect "); writeh(0xab);
			writes(" ,actual "); writeh(Buff[ix]&0xff);
			writes(" ,address "); writeh(&Buff[ix]);
			}
		}
}

Form(devno)
long devno;
{	register long  cyl, trak;
	struct TYPEPAR *tp;

	tp = &typepar[devno];
	writes("\nFormating drive "); writeh(devno); writes(" ...\n");
	for (cyl=0; cyl < tp->nocyls-1; cyl++) {
		if (format(devno,cyl)) {
			writes("\nformat error ...\n");
			return;
			}
		writed(cyl);
		}
	writes("\nFormat completed ...\n");
}


setdr(type)
long  type;
{	struct IOPB *iop;

	iop = &xiopb;
	iop->comm = SETDRIVE | IEN | AUD;
	iop->imode = IEI;
	iop->stat1 = iop->stat2 = iop->throt = (char)0;
	iop->devno = (type&0x3) << 7;	
	iop->headr = typepar[type].noheads -1;
	iop->secadr = typepar[type].nosecs -1;
	iop->calow = (char)((typepar[type].nocyls -1) & 0xff);
	iop->cahig = (char)(((typepar[type].nocyls-1) >> 8) & 0x3);
	iop->hoffs = (char)0;
	if (xygo(iop)) 
		writes("\nset drive error..\n");
	   else writes("\nset drive completed.\n");
}

format(devno,cyl)
long devno, cyl;
{	struct IOPB *iop;
	register long nosecs;

	iop = &xiopb;
	iop->comm = XFORMAT | IEN | AUD;
	iop->imode = IEI;
	iop->stat1 = iop->stat2 = iop->throt = (char)0;
	iop->devno = devno | ((dtype[devno].type & 3) << 7);
	iop->headr = 0;
	iop->secadr = 0;
	iop->calow = (char)(cyl & 0xff);
	iop->cahig = (char)((cyl & 0x300) >> 8);
	nosecs = typepar[devno].nosecs * typepar[devno].noheads;
	iop->sclow = (char)(nosecs & 0xff);
	iop->schig = (char)((nosecs >> 8) & 0xff);
	return(xygo(iop)); 
}

xyop(devno,op,len,cyl,head,sec,buf)
long devno, cyl, len, head, sec;
char op, *buf;
{	struct IOPB *iop;
	register long nosecs;

	iop = &xiopb;
	iop->comm = op | IEN | AUD;
	iop->imode = IEI;
	iop->stat1 = iop->stat2 = iop->throt = (char)0;
	iop->devno = devno | ((dtype[devno].type & 3) << 7);
	iop->headr = head;
	iop->secadr = sec;
	iop->calow = (char)(cyl & 0xff);
	iop->cahig = (char)((cyl & 0x300) >> 8);
	iop->sclow = (char)(len & 0xff);
	iop->schig = (char)((len >> 8) & 0xff);
	iop->dalow = (char)((long)buf & 0xff);
	iop->dahig = (char)(((long)buf >> 8) & 0xff);
	iop->drlow = (char)(((long)buf >> 16)&0xff);
	iop->drhig = 0;
	return(xygo(iop)); 
}

/*	Map register I/O address of Xylogics controller
*/
m_xy()
{	register long r12;
	long phys_pg, pte, old_pte, which1;

	/* physical page of Xylogics' registers in IO space */
	phys_pg = ((XBASE+IOBASE) >> PGSHIFT) & 0x3fffff;
	/* Virtual address of Xylogics IO registers */
	Xyreg = (struct Xreg *)((unused << PGSHIFT) + XOFFS);
	pte = phys_pg | PG_KW | PG_V | PG_NC;
	fix_pte(SBR,unused,&old_pte,pte);
	unused++;
	pte = (phys_pg+1) | PG_KW | PG_V | PG_NC;
	fix_pte(SBR,unused,&old_pte,pte);
	asm("mfpr $SLR,r12");
	r12 += 2;
	asm("mtpr r12,$SLR");
	unused++;
}


xy_reset()
{	char c, movib();
	register long cnt;

	movib(&Xyreg->crr);	/* Reset controller by reading this register */
	cnt = 0xff0;
	while (!((movib(&Xyreg->csr)) & DRDY)) {
		DELAY(0xff00);
		if (--cnt <= 0) { writes("\nReset time out..\n");
			return(0); }
		}
	return(1);
}


/*	All ready to go,issue command to Xylogic
*/
xygo(iopb)
struct IOPB *iopb;
{	register long r12;

	r12 = (long)iopb;
	if (!xyrdy()) return(1);
	movob(&Xyreg->adlow,(char)(r12 & 0xff));
	movob(&Xyreg->adhig,(char)((r12&0xff00)>>8));
	movob(&Xyreg->relow,(char)((r12&0xff0000)>>16));
	movob(&Xyreg->rehig,(char)0);
	movob(&Xyreg->csr,(char)(GBSY|ADRM));
	return(waitxy());	/* Return 0 if cmd O.K else error status */
}

xyrdy()
{	register cnt;
	char movib();
	cnt = 0xfff0;
	while ((movib(&Xyreg->csr))&0x80) {
		if (--cnt == 0) { 
			writes("\nXY not ready time out !\n");
			return(0);
		}
	}
	return(1);
}

waitxy()
{	register long cnt;
	Xdone = 0;
	cnt = 0xff00;
	while (!Xdone) {
		DELAY(0xff00);
		if (--cnt == 0) {
			writes("\ntime out on Xylogic..\n");
			return(1);
			}
		}
	if (Xdone==2) return(Xdone);
		else return(0);
}


movob(addr,byte)
char *addr, byte;
{	register long r12;

	r12 = (long)addr;
	asm("movob 11(fp),(r12)");
	DELAY(80);
}

char movib(addr)
char *addr;
{	register long r12, r11;

	r12 = (long)addr;
	asm("movob (r12),r11");
	DELAY(80);
	return((char)r11);
}

mk32(adr,rel)
long adr, rel;
{	register long a32;

	a32 = (adr&0xffff) | ((rel&0xffff)<<16);
	return(a32&0xffffff);
}

/*	Xylogics interrupt handler 
*/
xyintr()
{	char err, movib();
	register long r12;

	err = movib(&Xyreg->csr);	/* Get error code from CSR */
	r12 = (long)&xiopb;		/* Uncache 1st longword in IOPB */
	uncache(r12); uncache(r12+4);
	if ((err & (ERR|DERR)) || (((long)xiopb.stat1) & XS_ERR)) {
		movob(&Xyreg->csr,IPND|ERR);	/* Clear interrupt,error */
		writes("\nXy hard error, csr "); writeh(((long)err)&0xff);
		writes("\niopb_stat2 "); writeh(((long)xiopb.stat2)&0xff);
		return(0);
		}
	movob(&Xyreg->csr,IPND);	/* Clear interrupt */
	return(1);
}


Xyhdr()
{
asm(".align 2");
asm("xyhdlr:");
	asm("svpctx");
	if (xyintr()) Xdone = 1;
		else Xdone = 2;		/* Command error */
	asm("ldpctx");
	asm("rei");
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.