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