|
|
1.1 ! root 1: /* cy.c 7.10 90/06/30 */ ! 2: ! 3: /* ! 4: * Cypher tape driver. Stand alone version. ! 5: */ ! 6: #include "machine/pte.h" ! 7: #include "machine/mtpr.h" ! 8: ! 9: #include "sys/param.h" ! 10: #include "sys/time.h" ! 11: ! 12: #include "saio.h" ! 13: ! 14: #define CYERROR ! 15: #include "tahoevba/cyreg.h" ! 16: #include "tahoevba/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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.