|
|
1.1 ! root 1: /* cy.c Tahoe version Mar 1983. */ ! 2: ! 3: /* ! 4: * Cypher tape driver. Stand alone version. ! 5: * ! 6: */ ! 7: #include "../h/param.h" ! 8: #include "../h/inode.h" ! 9: #include "../h/fs.h" ! 10: #include "../machine/pte.h" ! 11: #include "../machine/mtpr.h" ! 12: #include "../stand/saio.h" ! 13: #include "../stand/cyvar.h" ! 14: ! 15: long cystd[] = { 0xf4000, 0 }; ! 16: ! 17: struct scp /* SYSTEM CONFIGURATION POINTER */ ! 18: { ! 19: char sysbus ; /* width of system buss 0=8;1=16 */ ! 20: char nu1 ; ! 21: char pt_scb[4] ; /* pointer to ->SYSTEM CONFIGURATION BLOCK */ ! 22: }; ! 23: ! 24: struct scp * SCP; /* absolute address - jumpered on the controller */ ! 25: /* set to 0xC06 for Tahoe */ ! 26: ! 27: struct scb /* SYSTEM CONFIGUREATION BLOCK */ ! 28: { ! 29: char sysblk[1] ; /* 0x03 fixed value code */ ! 30: char nu2[1] ; ! 31: char pt_ccb[4] ; /* pointer to ->CHANNEL CONTROL BLOCK */ ! 32: }scb; ! 33: ! 34: struct ccb /* CHANNEL CONTROL BLOCK */ ! 35: { ! 36: char ccw[1] ; /* 0x11 normal; 0x09 clear non_vect interrupt */ ! 37: char gate[1] ; /* This is "the" GATE */ ! 38: char pt_tpb[4] ; /* pointer to ->TAPE OPERATION BLOCK or MOVE BLOCK */ ! 39: }ccb; ! 40: ! 41: struct tpb /* TAPE OPERATIONS PARAMETER BLOCK */ ! 42: { ! 43: long cmd ; /* COMMAND (input) */ ! 44: char control[2] ; /* CONTROL (input) */ ! 45: short count ; /* RETURN COUNT (output) */ ! 46: short size ; /* BUFFER SIZE (input/output) */ ! 47: short rec_over ; /* RECORDS/OVERRUN (input/output) */ ! 48: char pt_data[4] ; /* pointer to ->SOURCE/DEST (input) */ ! 49: char status[2] ; /* STATUS (output) */ ! 50: char pt_link[4] ; /* pointer to ->INTERRUPT/PARAMETER BLOCK (input) */ ! 51: } tpb; ! 52: ! 53: struct tpb cycool /* tape parameter block to clear interrupts */ ! 54: = { ! 55: 0L, /* command */ ! 56: 0,0, /* control */ ! 57: 0, /* count */ ! 58: 0, /* size */ ! 59: 0, /* rec_over */ ! 60: 0,0,0,0, /* pt_data */ ! 61: 0,0, /* status */ ! 62: 0,0,0,0 /* pt_link */ ! 63: } ; ! 64: int cyblksiz = 1024; /* foreign tape size as found in open routine */ ! 65: long cyblock; /* next block number for i/o */ ! 66: /* ! 67: * Reset the controller. ! 68: */ ! 69: cyopen(io) ! 70: register struct iob *io; ! 71: { ! 72: register ctlradr; ! 73: ! 74: ctlradr = cystd[0] + IOBASE; ! 75: SCP = (struct scp *)0xc06; /* absolute - for setup */ ! 76: TM_RESET(ctlradr,0xff); /* reset the controller */ ! 77: /* ! 78: * Initialize the system configuration pointer ! 79: */ ! 80: SCP->sysbus = 1; /* system width = 16 bits. */ ! 81: /* initialize the pointer to the system configuration block */ ! 82: set_pointer((long)&scb.sysblk[0],(char *)SCP->pt_scb); ! 83: /* ! 84: * Initialize the system configuration block. ! 85: */ ! 86: scb.sysblk[0] = 0x3; /* fixed value */ ! 87: /* initialize the pointer to the channel control block */ ! 88: set_pointer((long)&ccb.ccw[0],(char *)scb.pt_ccb); ! 89: /* ! 90: * Initialize the channel control block. ! 91: */ ! 92: ccb.ccw[0] = 0x11; /* normal interrupts */ ! 93: /* initialize the pointer to the tape parameter block */ ! 94: set_pointer((long)&tpb,(char *)ccb.pt_tpb); ! 95: /* ! 96: * set the command to be NO_OP. ! 97: */ ! 98: tpb.cmd = NO_OP; ! 99: tpb.control[0] = CW_BL; /* TPB not used on first attention */ ! 100: tpb.control[1] = CW_16bits; ! 101: ccb.gate[0] = GATE_CLOSED; ! 102: TM_ATTENTION(ctlradr, 0xff); /* execute! */ ! 103: cywait(10*1000); ! 104: /* ! 105: * set the command to be CONFIGURE. ! 106: */ ! 107: tpb.cmd = CONFIG; ! 108: tpb.control[0] = CW_BL; /* NO interrupt on completion */ ! 109: tpb.control[1] = CW_16bits; ! 110: tpb.status[0] = tpb.status[1] = 0; ! 111: ccb.gate[0] = GATE_CLOSED; ! 112: TM_ATTENTION(ctlradr, 0xff); /* execute! */ ! 113: cywait(10*1000); ! 114: uncache (&tpb.status[1]) ; ! 115: if (tpb.status[1] & CS_ERm) { ! 116: printf("Cypher initialization error!\n"); ! 117: cy_decode_error(tpb.status[1]&CS_ERm); ! 118: _stop(""); ! 119: } ! 120: if(cycmd(io,REWD_TA) == -1) ! 121: _stop("Rewind failed!\n"); ! 122: while(io->i_boff > 0) { ! 123: if(cycmd(io,SPAC_FM) == -1) ! 124: _stop("cy: seek failure!\n"); ! 125: io->i_boff--; ! 126: } ! 127: #ifdef NOBLOCK ! 128: if (io->i_flgs & F_READ) { ! 129: if((cyblksiz = cycmd(io,READ_FO)) == -1) ! 130: _stop("Read foriegn tape failed!\n"); ! 131: if(cycmd(io,REWD_TA) == -1) ! 132: _stop("Rewind after read failed\n"); ! 133: } ! 134: #endif ! 135: } ! 136: ! 137: /* if tape was open for writing write a file mark */ ! 138: cyclose(io) ! 139: register struct iob *io; ! 140: { ! 141: if (io->i_flgs & F_WRITE) cycmd(io,WRITE_FMARK); ! 142: cycmd(io,REWD_TA); ! 143: cyblock = 0; ! 144: } ! 145: ! 146: cystrategy(io,func) ! 147: register struct iob *io; ! 148: register long func; ! 149: { ! 150: ! 151: #ifndef NOBLOCK ! 152: if ((func != SPACE) && (func != REWD_TA) && (io->i_bn != cyblock)) { ! 153: cycmd(io,SPACE); ! 154: tpb.rec_over = 0; ! 155: } ! 156: if(func==READ || func==WRITE) { ! 157: struct iob liob; ! 158: register struct iob *lio = &liob; ! 159: register count; ! 160: ! 161: liob = *io; ! 162: while(lio->i_cc > 0) { ! 163: if((count = cycmd(lio, func)) == 0) ! 164: return(-1); ! 165: lio->i_cc -= count; ! 166: lio->i_ma += count; ! 167: } ! 168: return(io->i_cc); ! 169: } ! 170: #endif ! 171: return(cycmd(io, func)); ! 172: } ! 173: ! 174: cycmd(io,func) ! 175: register struct iob *io; ! 176: long func; ! 177: { ! 178: register ctlradr; ! 179: short j; ! 180: ! 181: ctlradr = cystd[0] + IOBASE; ! 182: cywait(9000); ! 183: if (func == READ) func = READ_TA; ! 184: else if (func == WRITE) func = WRIT_TA; ! 185: else if (func == WRITE_FMARK) func = WRIT_FM; ! 186: tpb.cmd = func; ! 187: uncache(&ccb.gate[0]); ! 188: while(ccb.gate[0] == GATE_CLOSED) ! 189: uncache(&ccb.gate[0]); ! 190: ccb.gate[0] = GATE_CLOSED; ! 191: tpb.control[0] = CW_BL; ! 192: tpb.control[1] = CW_16bits; ! 193: tpb.status[0] = tpb.status[1] = 0; ! 194: tpb.count = 0; ! 195: set_pointer((long)&tpb,(char *)ccb.pt_tpb); ! 196: switch (func) ! 197: { ! 198: case READ_TA: ! 199: if (io->i_cc > cyblksiz) ! 200: tpb.size = TM_SHORT(cyblksiz); ! 201: else tpb.size = TM_SHORT(io->i_cc); ! 202: set_pointer((long)io->i_ma,(char *)tpb.pt_data); ! 203: cyblock += 1; ! 204: break; ! 205: case WRIT_TA: ! 206: tpb.size = TM_SHORT(io->i_cc); ! 207: set_pointer((long)io->i_ma,(char *)tpb.pt_data); ! 208: cyblock += 1; ! 209: break; ! 210: case SPACE: ! 211: if ((j = io->i_bn - cyblock) < 0) { ! 212: j = -j; ! 213: tpb.control[1] |= CW_R; ! 214: cyblock -= j; ! 215: } ! 216: else ! 217: cyblock += j; ! 218: tpb.rec_over = TM_SHORT(j); ! 219: break; ! 220: case REWD_TA: ! 221: cyblock = 0; ! 222: break; ! 223: } ! 224: TM_ATTENTION(ctlradr, 0xff); /* execute! */ ! 225: if (func == REWD_TA || func == SPACE) { ! 226: cywait(60*5*1000); ! 227: } ! 228: else cywait(10*1000); ! 229: /* ! 230: * First we clear the interrupt and close the gate. ! 231: */ ! 232: mtpr (0, PADC); ! 233: ccb.gate[0] = GATE_CLOSED; ! 234: set_pointer((int)&cycool,(char *)ccb.pt_tpb); ! 235: cycool.cmd = NO_OP; /* no operation */ ! 236: cycool.control[0] = CW_BL; /* No INTERRUPTS */ ! 237: cycool.control[1] = 0; ! 238: TM_ATTENTION(ctlradr,0xff); /* cool it ! */ ! 239: cywait(20000); ! 240: uncache (&tpb.status[1] ) ; ! 241: if (tpb.status[1] & CS_ERm) { ! 242: cy_decode_error(tpb.status[1]&CS_ERm); ! 243: return -1; ! 244: } ! 245: uncache (&tpb.count); ! 246: return((long)TM_SHORT(tpb.count)); ! 247: } ! 248: ! 249: ! 250: ! 251: cyprint_error(message) ! 252: register char *message; ! 253: { ! 254: printf("cy0: %s.\n", message); ! 255: } ! 256: ! 257: /* ! 258: */ ! 259: ! 260: cy_decode_error(status) ! 261: register int status; ! 262: { ! 263: switch(status) { ! 264: case ER_TO1: ! 265: case ER_TO2: ! 266: case ER_TO3: ! 267: case ER_TO4: ! 268: case ER_TO5: ! 269: cyprint_error("Drive timed out during transfer"); ! 270: break; ! 271: case ER_TO6: ! 272: cyprint_error("Non-existant system memory reference"); ! 273: break; ! 274: case ER_DIAG: ! 275: case ER_JUMP: ! 276: cyprint_error("Controller micro diagnostics failed"); ! 277: break; ! 278: case ER_HARD: ! 279: cyprint_error("Unrecoverble media error"); ! 280: break; ! 281: case ER_TOF: ! 282: if (tpb.cmd == WRIT_TA) ! 283: cyprint_error("Unsatisfactory media"); ! 284: break; ! 285: case ER_FIFO: ! 286: cyprint_error("Data transfer over run"); ! 287: break; ! 288: case ER_TRN: ! 289: cyprint_error("Drive is not ready"); ! 290: break; ! 291: case ER_PRO: ! 292: cyprint_error("Tape is write protected"); ! 293: break; ! 294: case ER_PSUM: ! 295: cyprint_error("Checksum error in controller proms"); ! 296: break; ! 297: case ER_PARI: ! 298: cyprint_error("Unrecoverable tape parity error"); ! 299: break; ! 300: case ER_BLAN: ! 301: cyprint_error("Blank tape found where data was expected"); ! 302: break; ! 303: case ER_ER: ! 304: cyprint_error("Unrecoverble hardware error"); ! 305: default: ! 306: break; ! 307: } ! 308: } ! 309: ! 310: ! 311: long ! 312: cywait(timeout) ! 313: long timeout; ! 314: { ! 315: long dummy; ! 316: ! 317: uncache (&ccb.gate[0]) ; ! 318: while (ccb.gate[0] != GATE_OPEN) { ! 319: uncache (&ccb.gate[0]) ; ! 320: DELAY(1000); ! 321: if (--timeout == 0) { ! 322: cyprint_error("Transfer timeout"); ! 323: _stop(""); ! 324: } ! 325: } ! 326: } ! 327: ! 328: /* ! 329: * Set a TAPEMASTER pointer (first parameter), into the ! 330: * 4 bytes array pointed by the second parameter. ! 331: */ ! 332: set_pointer(pointer,dest) ! 333: long pointer; ! 334: char * dest; ! 335: { ! 336: *dest++ = pointer & 0xff; /* low byte - offset */ ! 337: *dest++ = (pointer >> 8) & 0xff; /* high byte - offset */ ! 338: *dest++ = 0; ! 339: *dest = (pointer & 0xf0000) >> 12; /* base */ ! 340: } ! 341: ! 342: movow(word, destination) ! 343: long word, destination; ! 344: { ! 345: asm("movow 6(fp),*8(fp);"); ! 346: } ! 347: ! 348: movob(byte, destination) ! 349: long byte, destination; ! 350: { ! 351: asm("movob 7(fp),*8(fp);"); ! 352: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.