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