|
|
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 tm_bsiz = 0;
extern long unused, Multi, Berr;
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(cy_setup()); /* Set up structures and initailize 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(0x5000);
if (--cntr == 0) {
writes("sent_tm no interrupt respond\n");
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("Received interrupt but gate closed.\n");
}
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("Cannot clear interrupt\n");
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 & 0xc0) != 0xc0)
{ writes("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("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);
if (!Berr) { writes("\nTape controller is at "); writeh(TBASE); }
}
/* 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 : initilization Cypher */
cntr = RETRY;
while (ccblk.gate == GATE_CLOSED) {
DELAY(0x400); /* wait for completion */
if (--cntr == 0) {
writes("Init : Cypher time out\n");
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("g_open time out\n");
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] = (0|(intr << 5)); /* Bank=0,Drive=0,interrupt */
tpblk->count = 0; /* Return count = 0 */
cptr = (char *)&tpblk->size; /* Set buffer size */
*cptr++ = (char)(bufsiz & 0xff);
*cptr = (char)((bufsiz & 0xff00)>>8);
tpblk->rec_over = 0;
/* Set system buffer address */
set_pointer((long)(bufadr),(char *)tpblk->pt_data);
tpblk->status[0] = tpblk->status[1] = 0;
}
/* *************************************
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;
switch (cmd) {
case READ_TA : { writec('.'); break; }
case WRIT_TA : { writec(','); break; }
case REWD_TA : { writec('*'); break; }
}
set_g3(&tpb,cmd,buf_siz,buf_adr,1); /* Set up command block */
while (g_open()==0) { /* Gate closed !! */
tm_init(); /* Init controller */
writes("\ntape_op : Can not open gate !!\n");
return(0);
}
return(sent_tm());
}
/* Rewind tapemaster
*/
tm_rew()
{ char tstat;
if (tape_op(REWD_TA,0,0) == -1) return(0);
tstat = tpb.status[0];
if ( (tstat & 0x20) != 0x20) 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 : initilization Cypher */
cntr = RETRY;
while (ccblk.gate == GATE_CLOSED) {
DELAY(2000); /* wait for completion */
if (--cntr == 0) {
writes("Init : Cypher time out\n");
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.