|
|
Power 6/32 Unix version 1.2b
/*
*********************
*
* Cypher tape driver
*
*********************/
#include "pte.h"
#include "cy.h"
#include "cyconf.h"
struct scp *SCP; /* Pointer System configuration block */
struct scb scblk; /* System conf. block */
struct ccb ccblk; /* Channel control block */
struct tpb tpb; /* Tape parameter block */
struct tpb tpb1; /* Tape parameter block (spare) */
long cmd_done; /* 1 : cmd completed without error */
/* 2 : cmd error */
long CYattn; /* Virtual address of Cypher I/O attention address */
long ntape;
extern long unused, Multi, Berr;
extern short erase, unit;
chk_tape()
{ register long r12;
long oldvec;
m_cy(); /* Map Tape master space */
/* Set handler for tape master interrupt */
asm("movab cyhdlr,r12");
set_handler(CYVEC,&oldvec,r12);
cy_reset(); /* Reset Tape master */
return(ntape);
}
tape()
{
if (ntape == 0) {
writes("\n\nNo Tape controller installed\n");
return(0); }
return(cy_setup()); /* Set up structures and initialize Tape master */
}
long tm_cnt;
/*
Routine to sent a command to Tape master
return -1 if error
return return count of TPB if sucessful
*/
sent_tm()
{ register long cntr, rtn_cnt;
tm_cnt = 0;
ccblk.gate = (char)GATE_CLOSED; /* Close gate */
cy_attn(); /* Execute command */
cntr = RETRY;
cmd_done = 0;
if (Multi) return;
while (!cmd_done) { /* Wait for completion interrupt */
DELAY(0x100000);
if (--cntr == 0) {
writes("\n...sent_tm no interrupt respond");
return(-1); /* Time out */
}
}
if (cmd_done == 2) return(-1); /* Command has error */
return(tm_cnt);
}
/* Tape master completion interrupt handler
*/
tm_hdlr()
{
if (chk_cstat())
cmd_done = 2; /* completion error */
else cmd_done = 1; /* completion without error */
tm_cnt = gt_bcnt(); /* Get return count from TPB */
clr_tint(); /* Clear tape master interrupt */
}
/*
Routine to ACK on tape master completion interrupt
Sent out a NOOP command without interrupt on completion
*/
clr_tint()
{
while (g_open()==0) /* Gate close */
{ tm_init();
error("\n...Received interrupt but gate closed.");
}
ccblk.gate = GATE_CLOSED;
ccblk.ccw = 0x9; /* Clear tape master interrupt */
set_g3(&tpb,NOOP,0,0,0); /* No Interrupt on completion please */
cy_attn();
DELAY(0x1500); /* wait for completion */
while (g_open()==0) /* Gate close */
{ tm_init();
error("\n...Cannot clear interrupt");
return(0);
}
ccblk.ccw = 0x11;
return(1);
}
/*
Check status of command previously issued
If all are OK return 0
else return Status byte.
*/
chk_cstat()
{
register long *r12, cstat;
r12 = (long *)&tpb.status[1];
uncache(r12);
/* Cmd status without retry bit */
cstat = (long)tpb.status[1];
if (((cstat & 0x87) == 0x87) && (erase))
{ writes("\nCy hard error 87 expected, tape is blank\n");
return(cstat); }
if ((cstat & 0xc0) != 0xc0)
{ writes("\n...Cy hard error ");
writeh(cstat & 0xff); writec('\n');
return(cstat); }
return(0);
}
/*
Check status of drive after received command
completion interrupt. If all are OK return 0
else return Status byte.
*/
chk_dstat()
{ register long *r12, tstat;
r12 = (long *)&tpb.status[0];
uncache(r12);
tstat = tpb.status[0];
if ( (tstat & 0x48) != 0x48)
{ writes("\n...drive error ");
writeh(tstat & 0xff);
return(tstat); }
return(0);
}
/*
Routine to get return_count field of TPB after
receive command completion interrupt
*/
gt_bcnt()
{ register long *r12, tmp1, tmp2;
r12 = (long *)&tpb.count;
uncache(r12);
tmp1 = (long)((tpb.count & (short)0xff)<<8);
tmp2 = (long)((tpb.count & (short)0xff00)>>8);
return(tmp1|tmp2);
}
/*
Routine to issue a GO command to tape master
also known as Channel attention interrupt
*/
cy_attn()
{ register long r12;
r12 = CYattn; /* R12 = Cypher attention address */
asm("movob $0xff,(r12)");
}
/*
Routine to reset Tape master controller
*/
cy_reset()
{ register long r12;
r12 = CYattn + 1; /* R12 = Cypher attention address */
asm("movob $0xff,(r12)");
DELAY(100);
ntape = 0;
writes("\n\nProbing for Tape Master controller...");
if(!Berr) {
writes("\nTape Master controller at address ");
writeh(TBASE);
ntape++; }
writes("\n"); writed(ntape); writes(" Tape controller(s) found");
}
/*
Map channel attention address of Tape master
*/
m_cy()
{ register long r12;
long phys_pg, pte, old_pte, which1;
/* physical page of Tape master in IO space */
phys_pg = ((TBASE+IOBASE) >> PGSHIFT) & 0x3fffff;
pte = phys_pg | PG_KW | PG_V | PG_NC;
fix_pte(SBR,unused,&old_pte,pte);
CYattn = (unused << PGSHIFT); /* Virtual address of CY attn address */
asm("mfpr $SLR,r12");
r12++;
asm("mtpr r12,$SLR");
unused++; /* Next unused PTE in system map */
}
/*
Set up all structures for Tape master
and initialize Tape master
*/
cy_setup()
{
register long cntr;
SCP = (struct scp *)SCP_ADR; /* absolute - for setup */
/* Initialize the system configuration pointer */
SCP->sysbus = 1; /* system width = 16 bits. */
set_pointer(&scblk.sysblk,(char *)SCP->pt_scb);
/* Initialize the system configuration block. */
scblk.sysblk = 0x3; /* fixed value */
scblk.nu2 = 0; /* not used */
set_pointer(&ccblk.ccw,(char *)scblk.pt_ccb);
/* Initialize the channel control block. */
ccblk.ccw = 0x11; /* normal interrupts */
set_pointer(&tpb,(char *)ccblk.pt_tpb);
ccblk.gate = GATE_CLOSED;
cy_attn(); /* 1st attention : initialization Cypher */
cntr = RETRY;
while (ccblk.gate == GATE_CLOSED) {
DELAY(0x400); /* wait for completion */
if (--cntr == 0) {
writes("\n...Init : Cypher time out");
return(0); } /* Time out */
}
return(1);
}
/*
Set a TAPEMASTER 20_bit pointer (first parameter), into
the 4 bytes array pointed by the second parameter.
*/
set_pointer(pointer,dest)
long pointer;
char *dest;
{
*dest++ = pointer & 0xff; /* low byte - offset */
*dest++ = (pointer >> 8) & 0xff; /* high byte - offset */
*dest++ = 0;
*dest = (pointer & 0xf0000) >> 12; /* base */
}
g_open()
{ register long *r12, cntr;
r12 = (long *)&ccblk.gate;
cntr = RETRY;
while (ccblk.gate!=0) {
uncache(r12);
DELAY(0x500); /* wait for completion */
if (--cntr == 0) {
writes("\n...g_open time out");
return(0);
}
}
return(1);
}
error(msg)
char *msg;
{
writes(msg);
}
/*
Set Tape Parameter Block
Input :
cmd = Opcode
bufsiz = Block size
bufadr = System buffer address
int = interrupt on completion or not
*/
set_g3(tpblk,cmd,bufsiz,bufadr,intr)
struct tpb *tpblk;
long cmd, bufsiz, intr;
char *bufadr;
{ char *cptr;
tpblk->cmd = cmd; /* Command */
tpblk->control[1] = 0x80 | CW_100ips; /* 16_bit system bus */
tpblk->control[0] = ((unit << 2)|(intr << 5)); /* Drive,interrupt */
tpblk->count = 0; /* Return count = 0 */
cptr = (char *)&tpblk->size; /* Set buffer size */
*cptr++ = (char)(bufsiz & 0xff);
*cptr = (char)((bufsiz & 0xff00)>>8);
if(cmd == ERASE_F)
tpblk->rec_over = 0x0004; /* Set record count, erase */
else
tpblk->rec_over = 0; /* Set record count */
/* Set system buffer address */
set_pointer((long)(bufadr),(char *)tpblk->pt_data);
tpblk->status[0] = tpblk->status[1] = 0;/* Clear ctlr & drive status */
}
/*
*************************************
Routine to Read/Write Cypher tape
return 0 if cannot complete operation
*************************************
*/
long tape_op(cmd,buf_adr,buf_siz)
long cmd, buf_siz;
char *buf_adr;
{ char *cptr;
register long cnt, stat, tmp1, tmp2;
set_g3(&tpb,cmd,buf_siz,buf_adr,1); /* Set up command block */
while (g_open()==0) { /* Gate closed !! */
tm_init(); /* Init controller */
writes("\n...tape_op : Can not open gate !!");
return(0);
}
return(sent_tm());
}
/*
Rewind tapemaster
*/
tm_rew()
{ char tstat;
writes("\nTape rewinding");
if (tape_op(REWD_TA,0,0) == -1) return(0);
tstat = tpb.status[0];
if ( (tstat & 0x20) != 0x20) return(0);
return(1);
}
/*
Erase 1024 records
*/
tm_erase()
{
writes("\nErasing 1024 records");
if (tape_op(ERASE_F,0,0) == -1) return(0);
return(1);
}
/*
Routine to initialize tape master
*/
tm_init()
{ register long cntr;
cy_reset();
if (!g_open()) return(0);
ccblk.gate = GATE_CLOSED;
cy_attn(); /* 1st attention : initialization Cypher */
cntr = RETRY;
while (ccblk.gate == GATE_CLOSED) {
DELAY(2000); /* wait for completion */
if (--cntr == 0) {
writes("\n...Init : Cypher time out");
return(0); } /* Time out */
}
return(1);
}
cyhandler()
{ long dummy;
asm(".align 2");
asm("cyhdlr:");
asm("svpctx");
tm_hdlr();
asm("ldpctx");
asm("rei");
dummy = 0;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.