|
|
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");
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.