|
|
1.1 ! root 1: ! 2: /* ! 3: ********************* ! 4: * ! 5: * Cypher tape driver ! 6: * ! 7: *********************/ ! 8: ! 9: #include "pte.h" ! 10: #include "cy.h" ! 11: #include "cyconf.h" ! 12: ! 13: struct scp *SCP; /* Pointer System configuration block */ ! 14: struct scb scblk; /* System conf. block */ ! 15: struct ccb ccblk; /* Channel control block */ ! 16: struct tpb tpb; /* Tape parameter block */ ! 17: struct tpb tpb1; /* Tape parameter block (spare) */ ! 18: long cmd_done; /* 1 : cmd completed without error */ ! 19: /* 2 : cmd error */ ! 20: long CYattn; /* Virtual address of Cypher I/O attention address */ ! 21: long ntape; ! 22: extern long unused, Multi, Berr; ! 23: extern short erase, unit; ! 24: ! 25: chk_tape() ! 26: { register long r12; ! 27: long oldvec; ! 28: ! 29: m_cy(); /* Map Tape master space */ ! 30: ! 31: /* Set handler for tape master interrupt */ ! 32: asm("movab cyhdlr,r12"); ! 33: set_handler(CYVEC,&oldvec,r12); ! 34: ! 35: cy_reset(); /* Reset Tape master */ ! 36: return(ntape); ! 37: } ! 38: tape() ! 39: { ! 40: if (ntape == 0) { ! 41: writes("\n\nNo Tape controller installed\n"); ! 42: return(0); } ! 43: return(cy_setup()); /* Set up structures and initialize Tape master */ ! 44: } ! 45: long tm_cnt; ! 46: /* ! 47: Routine to sent a command to Tape master ! 48: return -1 if error ! 49: return return count of TPB if sucessful ! 50: */ ! 51: sent_tm() ! 52: { register long cntr, rtn_cnt; ! 53: ! 54: tm_cnt = 0; ! 55: ccblk.gate = (char)GATE_CLOSED; /* Close gate */ ! 56: cy_attn(); /* Execute command */ ! 57: cntr = RETRY; ! 58: cmd_done = 0; ! 59: if (Multi) return; ! 60: while (!cmd_done) { /* Wait for completion interrupt */ ! 61: DELAY(0x100000); ! 62: if (--cntr == 0) { ! 63: writes("\n...sent_tm no interrupt respond"); ! 64: return(-1); /* Time out */ ! 65: } ! 66: } ! 67: if (cmd_done == 2) return(-1); /* Command has error */ ! 68: return(tm_cnt); ! 69: } ! 70: ! 71: /* Tape master completion interrupt handler ! 72: */ ! 73: tm_hdlr() ! 74: { ! 75: if (chk_cstat()) ! 76: cmd_done = 2; /* completion error */ ! 77: else cmd_done = 1; /* completion without error */ ! 78: tm_cnt = gt_bcnt(); /* Get return count from TPB */ ! 79: clr_tint(); /* Clear tape master interrupt */ ! 80: } ! 81: /* ! 82: Routine to ACK on tape master completion interrupt ! 83: Sent out a NOOP command without interrupt on completion ! 84: */ ! 85: clr_tint() ! 86: { ! 87: while (g_open()==0) /* Gate close */ ! 88: { tm_init(); ! 89: error("\n...Received interrupt but gate closed."); ! 90: } ! 91: ccblk.gate = GATE_CLOSED; ! 92: ccblk.ccw = 0x9; /* Clear tape master interrupt */ ! 93: set_g3(&tpb,NOOP,0,0,0); /* No Interrupt on completion please */ ! 94: cy_attn(); ! 95: DELAY(0x1500); /* wait for completion */ ! 96: while (g_open()==0) /* Gate close */ ! 97: { tm_init(); ! 98: error("\n...Cannot clear interrupt"); ! 99: return(0); ! 100: } ! 101: ccblk.ccw = 0x11; ! 102: return(1); ! 103: } ! 104: /* ! 105: Check status of command previously issued ! 106: If all are OK return 0 ! 107: else return Status byte. ! 108: */ ! 109: chk_cstat() ! 110: { ! 111: register long *r12, cstat; ! 112: r12 = (long *)&tpb.status[1]; ! 113: uncache(r12); ! 114: /* Cmd status without retry bit */ ! 115: cstat = (long)tpb.status[1]; ! 116: if (((cstat & 0x87) == 0x87) && (erase)) ! 117: { writes("\nCy hard error 87 expected, tape is blank\n"); ! 118: return(cstat); } ! 119: if ((cstat & 0xc0) != 0xc0) ! 120: { writes("\n...Cy hard error "); ! 121: writeh(cstat & 0xff); writec('\n'); ! 122: return(cstat); } ! 123: return(0); ! 124: } ! 125: /* ! 126: Check status of drive after received command ! 127: completion interrupt. If all are OK return 0 ! 128: else return Status byte. ! 129: */ ! 130: chk_dstat() ! 131: { register long *r12, tstat; ! 132: ! 133: r12 = (long *)&tpb.status[0]; ! 134: uncache(r12); ! 135: tstat = tpb.status[0]; ! 136: if ( (tstat & 0x48) != 0x48) ! 137: { writes("\n...drive error "); ! 138: writeh(tstat & 0xff); ! 139: return(tstat); } ! 140: return(0); ! 141: } ! 142: /* ! 143: Routine to get return_count field of TPB after ! 144: receive command completion interrupt ! 145: */ ! 146: gt_bcnt() ! 147: { register long *r12, tmp1, tmp2; ! 148: ! 149: r12 = (long *)&tpb.count; ! 150: uncache(r12); ! 151: tmp1 = (long)((tpb.count & (short)0xff)<<8); ! 152: tmp2 = (long)((tpb.count & (short)0xff00)>>8); ! 153: return(tmp1|tmp2); ! 154: } ! 155: /* ! 156: Routine to issue a GO command to tape master ! 157: also known as Channel attention interrupt ! 158: */ ! 159: cy_attn() ! 160: { register long r12; ! 161: ! 162: r12 = CYattn; /* R12 = Cypher attention address */ ! 163: asm("movob $0xff,(r12)"); ! 164: } ! 165: /* ! 166: Routine to reset Tape master controller ! 167: */ ! 168: cy_reset() ! 169: { register long r12; ! 170: ! 171: r12 = CYattn + 1; /* R12 = Cypher attention address */ ! 172: asm("movob $0xff,(r12)"); ! 173: DELAY(100); ! 174: ntape = 0; ! 175: writes("\n\nProbing for Tape Master controller..."); ! 176: if(!Berr) { ! 177: writes("\nTape Master controller at address "); ! 178: writeh(TBASE); ! 179: ntape++; } ! 180: writes("\n"); writed(ntape); writes(" Tape controller(s) found"); ! 181: } ! 182: /* ! 183: Map channel attention address of Tape master ! 184: */ ! 185: m_cy() ! 186: { register long r12; ! 187: long phys_pg, pte, old_pte, which1; ! 188: ! 189: /* physical page of Tape master in IO space */ ! 190: phys_pg = ((TBASE+IOBASE) >> PGSHIFT) & 0x3fffff; ! 191: pte = phys_pg | PG_KW | PG_V | PG_NC; ! 192: fix_pte(SBR,unused,&old_pte,pte); ! 193: CYattn = (unused << PGSHIFT); /* Virtual address of CY attn address */ ! 194: asm("mfpr $SLR,r12"); ! 195: r12++; ! 196: asm("mtpr r12,$SLR"); ! 197: unused++; /* Next unused PTE in system map */ ! 198: } ! 199: /* ! 200: Set up all structures for Tape master ! 201: and initialize Tape master ! 202: */ ! 203: cy_setup() ! 204: { ! 205: register long cntr; ! 206: ! 207: SCP = (struct scp *)SCP_ADR; /* absolute - for setup */ ! 208: ! 209: /* Initialize the system configuration pointer */ ! 210: SCP->sysbus = 1; /* system width = 16 bits. */ ! 211: set_pointer(&scblk.sysblk,(char *)SCP->pt_scb); ! 212: ! 213: /* Initialize the system configuration block. */ ! 214: scblk.sysblk = 0x3; /* fixed value */ ! 215: scblk.nu2 = 0; /* not used */ ! 216: set_pointer(&ccblk.ccw,(char *)scblk.pt_ccb); ! 217: ! 218: /* Initialize the channel control block. */ ! 219: ccblk.ccw = 0x11; /* normal interrupts */ ! 220: set_pointer(&tpb,(char *)ccblk.pt_tpb); ! 221: ! 222: ccblk.gate = GATE_CLOSED; ! 223: cy_attn(); /* 1st attention : initialization Cypher */ ! 224: cntr = RETRY; ! 225: while (ccblk.gate == GATE_CLOSED) { ! 226: DELAY(0x400); /* wait for completion */ ! 227: if (--cntr == 0) { ! 228: writes("\n...Init : Cypher time out"); ! 229: return(0); } /* Time out */ ! 230: } ! 231: return(1); ! 232: } ! 233: /* ! 234: Set a TAPEMASTER 20_bit pointer (first parameter), into ! 235: the 4 bytes array pointed by the second parameter. ! 236: */ ! 237: set_pointer(pointer,dest) ! 238: long pointer; ! 239: char *dest; ! 240: { ! 241: *dest++ = pointer & 0xff; /* low byte - offset */ ! 242: *dest++ = (pointer >> 8) & 0xff; /* high byte - offset */ ! 243: *dest++ = 0; ! 244: *dest = (pointer & 0xf0000) >> 12; /* base */ ! 245: } ! 246: g_open() ! 247: { register long *r12, cntr; ! 248: ! 249: r12 = (long *)&ccblk.gate; ! 250: cntr = RETRY; ! 251: while (ccblk.gate!=0) { ! 252: uncache(r12); ! 253: DELAY(0x500); /* wait for completion */ ! 254: if (--cntr == 0) { ! 255: writes("\n...g_open time out"); ! 256: return(0); ! 257: } ! 258: } ! 259: return(1); ! 260: } ! 261: error(msg) ! 262: char *msg; ! 263: { ! 264: writes(msg); ! 265: } ! 266: /* ! 267: Set Tape Parameter Block ! 268: Input : ! 269: cmd = Opcode ! 270: bufsiz = Block size ! 271: bufadr = System buffer address ! 272: int = interrupt on completion or not ! 273: */ ! 274: set_g3(tpblk,cmd,bufsiz,bufadr,intr) ! 275: struct tpb *tpblk; ! 276: long cmd, bufsiz, intr; ! 277: char *bufadr; ! 278: { char *cptr; ! 279: ! 280: tpblk->cmd = cmd; /* Command */ ! 281: tpblk->control[1] = 0x80 | CW_100ips; /* 16_bit system bus */ ! 282: tpblk->control[0] = ((unit << 2)|(intr << 5)); /* Drive,interrupt */ ! 283: tpblk->count = 0; /* Return count = 0 */ ! 284: cptr = (char *)&tpblk->size; /* Set buffer size */ ! 285: *cptr++ = (char)(bufsiz & 0xff); ! 286: *cptr = (char)((bufsiz & 0xff00)>>8); ! 287: if(cmd == ERASE_F) ! 288: tpblk->rec_over = 0x0004; /* Set record count, erase */ ! 289: else ! 290: tpblk->rec_over = 0; /* Set record count */ ! 291: /* Set system buffer address */ ! 292: set_pointer((long)(bufadr),(char *)tpblk->pt_data); ! 293: tpblk->status[0] = tpblk->status[1] = 0;/* Clear ctlr & drive status */ ! 294: } ! 295: /* ! 296: ************************************* ! 297: Routine to Read/Write Cypher tape ! 298: return 0 if cannot complete operation ! 299: ************************************* ! 300: */ ! 301: long tape_op(cmd,buf_adr,buf_siz) ! 302: long cmd, buf_siz; ! 303: char *buf_adr; ! 304: { char *cptr; ! 305: register long cnt, stat, tmp1, tmp2; ! 306: ! 307: set_g3(&tpb,cmd,buf_siz,buf_adr,1); /* Set up command block */ ! 308: while (g_open()==0) { /* Gate closed !! */ ! 309: tm_init(); /* Init controller */ ! 310: writes("\n...tape_op : Can not open gate !!"); ! 311: return(0); ! 312: } ! 313: return(sent_tm()); ! 314: } ! 315: ! 316: /* ! 317: Rewind tapemaster ! 318: */ ! 319: tm_rew() ! 320: { char tstat; ! 321: writes("\nTape rewinding"); ! 322: if (tape_op(REWD_TA,0,0) == -1) return(0); ! 323: tstat = tpb.status[0]; ! 324: if ( (tstat & 0x20) != 0x20) return(0); ! 325: return(1); ! 326: } ! 327: /* ! 328: Erase 1024 records ! 329: */ ! 330: tm_erase() ! 331: { ! 332: writes("\nErasing 1024 records"); ! 333: if (tape_op(ERASE_F,0,0) == -1) return(0); ! 334: return(1); ! 335: } ! 336: /* ! 337: Routine to initialize tape master ! 338: */ ! 339: tm_init() ! 340: { register long cntr; ! 341: ! 342: cy_reset(); ! 343: if (!g_open()) return(0); ! 344: ccblk.gate = GATE_CLOSED; ! 345: cy_attn(); /* 1st attention : initialization Cypher */ ! 346: cntr = RETRY; ! 347: while (ccblk.gate == GATE_CLOSED) { ! 348: DELAY(2000); /* wait for completion */ ! 349: if (--cntr == 0) { ! 350: writes("\n...Init : Cypher time out"); ! 351: return(0); } /* Time out */ ! 352: } ! 353: return(1); ! 354: } ! 355: cyhandler() ! 356: { long dummy; ! 357: ! 358: asm(".align 2"); ! 359: asm("cyhdlr:"); ! 360: asm("svpctx"); ! 361: tm_hdlr(); ! 362: asm("ldpctx"); ! 363: asm("rei"); ! 364: dummy = 0; ! 365: } ! 366:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.