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