1 /* cy.c 7.11 90/12/16 */ 2 3 /* 4 * Cypher tape driver. Stand alone version. 5 */ 6 #include "../include/pte.h" 7 #include "../include/mtpr.h" 8 9 #include "sys/param.h" 10 #include "sys/time.h" 11 12 #include "stand/saio.h" 13 14 #define CYERROR 15 #include "../vba/cyreg.h" 16 #include "../vba/vbaparam.h" 17 18 /* 19 * NB: this driver assumes unit 0 throughout. 20 */ 21 long cystd[] = { 0xf4000, 0 }; 22 #define CYADDR(i) (cystd[i] + (int)VBIOBASE) 23 24 struct cyscp *cyscp[] = { (struct cyscp *)0xc06, (struct cyscp *)0 }; 25 #define CYSCP(i) (cyscp[i]) 26 27 struct cyscp *SCP; 28 struct cyscb scb; 29 struct cyccb ccb; 30 struct cytpb tpb; 31 struct cytpb cycool; /* tape parameter block to clear interrupts */ 32 #ifdef notdef 33 int cyblocksize = 1024; /* foreign tape size as found in open routine */ 34 #endif 35 int cybufsize; /* controller buffer size */ 36 long cyblock; /* next block number for i/o */ 37 38 /* 39 * Reset the controller. 40 */ 41 cyopen(io) 42 register struct iob *io; 43 { 44 register ctlradr = CYADDR(0); 45 register int skip; 46 47 if ((u_int)io->i_adapt) 48 return (EADAPT); 49 if ((u_int)io->i_ctlr) 50 return (ECTLR); 51 SCP = CYSCP(0); /* absolute - for setup */ 52 CY_RESET(ctlradr); /* reset the controller */ 53 /* 54 * Initialize the system configuration pointer 55 */ 56 SCP->csp_buswidth = 1; /* system width = 16 bits. */ 57 SCP->csp_unused = 0; 58 /* initialize the pointer to the system configuration block */ 59 cyldmba(SCP->csp_scb, (caddr_t)&scb); 60 /* 61 * Initialize the system configuration block. 62 */ 63 scb.csb_fixed = CSB_FIXED; /* fixed value */ 64 /* initialize the pointer to the channel control block */ 65 cyldmba(scb.csb_ccb, (caddr_t)&ccb); 66 /* 67 * Initialize the channel control block. 68 */ 69 ccb.cbcw = CBCW_IE; /* normal interrupts */ 70 /* initialize the pointer to the tape parameter block */ 71 cyldmba(ccb.cbtpb, (caddr_t)&tpb); 72 /* 73 * set the command to be CY_NOP. 74 */ 75 tpb.tpcmd = CY_NOP; 76 /* 77 * TPB not used on first attention 78 */ 79 tpb.tpcontrol = CYCW_LOCK | CYCW_16BITS; 80 ccb.cbgate = GATE_CLOSED; 81 CY_GO(ctlradr); /* execute! */ 82 cywait(10*1000); 83 /* 84 * set the command to be CY_CONFIGURE. 85 * NO interrupt on completion. 86 */ 87 tpb.tpcmd = CY_CONFIG; 88 tpb.tpcontrol = CYCW_LOCK | CYCW_16BITS; 89 tpb.tpstatus = 0; 90 ccb.cbgate = GATE_CLOSED; 91 CY_GO(ctlradr); /* execute! */ 92 cywait(10*1000); 93 uncache(&tpb.tpstatus); 94 if (tpb.tpstatus & CYS_ERR) { 95 printf("Cypher initialization error!\n"); 96 cy_print_error(tpb.tpcmd, tpb.tpstatus); 97 return (ENXIO); 98 } 99 uncache(&tpb.tpcount); 100 cybufsize = tpb.tpcount; 101 if (cycmd(io, CY_REW) == -1) { 102 printf("cy%d: Rewind failed!\n", io->i_unit); 103 return (ENXIO); 104 } 105 for (skip = io->i_part; skip--;) 106 if (cycmd(io, CY_FSF) == -1) { 107 printf("cy%d: seek failure!\n", io->i_unit); 108 return (ENXIO); 109 } 110 #ifdef notdef 111 #ifdef NOBLOCK 112 if (io->i_flgs & F_READ) { 113 cyblocksize = cycmd(io, CY_READFORN); 114 if (cyblocksize == -1) 115 _stop("Read foreign tape failed\n"); 116 cyblock++; /* XXX force backspace record */ 117 if (cycmd(io, CY_SFORW) == -1) 118 _stop("Backspace after read foreign failed\n"); 119 } 120 #endif 121 #endif 122 return (0); 123 } 124 125 cyclose(io) 126 register struct iob *io; 127 { 128 129 if (io->i_flgs & F_WRITE) { /* if writing, write file marks */ 130 cycmd(io, CY_WEOF); 131 cycmd(io, CY_WEOF); 132 } 133 cycmd(io, CY_REW); 134 } 135 136 cystrategy(io, func) 137 register struct iob *io; 138 register func; 139 { 140 register count; 141 142 #ifndef NOBLOCK 143 if (func != CY_SFORW && func != CY_REW && io->i_bn != cyblock) { 144 cycmd(io, CY_SFORW); 145 tpb.tprec = 0; 146 } 147 if (func == READ || func == WRITE) { 148 struct iob liob; 149 register struct iob *lio = &liob; 150 151 liob = *io; 152 while (lio->i_cc > 0) { 153 if ((count = cycmd(lio, func)) == 0) { 154 printf("cy%d: I/O error bn %d\n", 155 io->i_unit, io->i_bn); 156 return (-1); 157 } 158 lio->i_cc -= count; 159 lio->i_ma += count; 160 } 161 return (io->i_cc); 162 } 163 #endif 164 count = cycmd(io, func); 165 if (count == -1) 166 printf("cy%d: I/O error bn %d\n", io->i_unit, io->i_bn); 167 return (count); 168 } 169 170 cycmd(io, func) 171 register struct iob *io; 172 long func; 173 { 174 register ctlradr = CYADDR(0); 175 int timeout = 0; 176 int err; 177 short j; 178 179 cywait(9000); /* shouldn't be needed */ 180 #define PACKUNIT(unit) (((unit&1)<<11)|((unit&2)<<9)|((unit&4)>>2)) 181 tpb.tpcontrol = CYCW_LOCK | CYCW_16BITS | PACKUNIT(io->i_unit); 182 tpb.tpstatus = 0; 183 tpb.tpcount = 0; 184 cyldmba(ccb.cbtpb, (caddr_t)&tpb); 185 tpb.tpcmd = func; 186 switch (func) { 187 case READ: 188 #ifdef notdef 189 if (io->i_cc > cyblocksize) 190 tpb.tpsize = htoms(cyblocksize); 191 else 192 #endif 193 tpb.tpsize = htoms(io->i_cc); 194 cyldmba(tpb.tpdata, io->i_ma); 195 tpb.tpcmd = CY_RCOM; 196 cyblock++; 197 break; 198 case WRITE: 199 tpb.tpcmd = CY_WCOM; 200 tpb.tpsize = htoms(io->i_cc); 201 cyldmba(tpb.tpdata, io->i_ma); 202 cyblock++; 203 break; 204 case CY_SFORW: 205 if ((j = io->i_bn - cyblock) < 0) { 206 j = -j; 207 tpb.tpcontrol |= CYCW_REV; 208 cyblock -= j; 209 } else 210 cyblock += j; 211 tpb.tprec = htoms(j); 212 timeout = 60*5; 213 break; 214 case CY_FSF: 215 tpb.tprec = htoms(1); 216 /* fall thru... */ 217 case CY_REW: 218 cyblock = 0; 219 timeout = 60*5; 220 break; 221 } 222 ccb.cbgate = GATE_CLOSED; 223 CY_GO(ctlradr); /* execute! */ 224 if (timeout == 0) 225 timeout = 10; 226 cywait(timeout*1000); 227 /* 228 * First we clear the interrupt and close the gate. 229 */ 230 mtpr(PADC, 0); 231 ccb.cbgate = GATE_CLOSED; 232 cyldmba(ccb.cbtpb, (caddr_t)&cycool); 233 cycool.tpcontrol = CYCW_LOCK; /* No INTERRUPTS */ 234 CY_GO(ctlradr); 235 cywait(20000); 236 uncache(&tpb.tpstatus); 237 if ((err = (tpb.tpstatus & CYS_ERR)) && 238 err != CYER_FM && (err != CYER_STROBE || tpb.tpcmd != CY_RCOM)) { 239 cy_print_error(tpb.tpcmd, tpb.tpstatus); 240 io->i_error = EIO; 241 return (-1); 242 } 243 uncache(&tpb.tpcount); 244 return ((int)htoms(tpb.tpcount)); 245 } 246 247 cy_print_error(op, status) 248 int op, status; 249 { 250 register char *message; 251 252 if ((status & CYS_ERR) < NCYERROR) 253 message = cyerror[status & CYS_ERR]; 254 else 255 message = "unknown error"; 256 printf("cy0: cmd %x %s, status=%b.\n", op, message, status, CYS_BITS); 257 } 258 259 cywait(timeout) 260 register timeout; 261 { 262 do { 263 DELAY(1000); 264 uncache(&ccb.cbgate); 265 } while (ccb.cbgate != GATE_OPEN && --timeout > 0); 266 if (timeout <= 0) 267 _stop("cy: Transfer timeout"); 268 } 269 270 /* 271 * Load a 20 bit pointer into a Tapemaster pointer. 272 */ 273 cyldmba(reg, value) 274 register caddr_t reg; 275 caddr_t value; 276 { 277 register int v = (int)value; 278 279 *reg++ = v; 280 *reg++ = v >> 8; 281 *reg++ = 0; 282 *reg = (v&0xf0000) >> 12; 283 } 284