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