|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)tm.c 1.1 86/02/03 Copyr 1985 Sun Micro"; ! 3: #endif ! 4: ! 5: /* ! 6: * Copyright (c) 1985 by Sun Microsystems, Inc. ! 7: */ ! 8: ! 9: /* ! 10: * Standalone driver for Ciprico TapeMaster Multibus tape controller ! 11: */ ! 12: ! 13: #include "saio.h" ! 14: #include "../sundev/tmreg.h" ! 15: #include "../mon/cpu.map.h" ! 16: #include "../mon/cpu.addrs.h" ! 17: ! 18: /* ! 19: * Standard addresses for this board ! 20: */ ! 21: #define NTMADDR 2 ! 22: unsigned long tmstd[] = { 0xA0, 0xA2 }; ! 23: ! 24: /* ! 25: * Structure of our dma space ! 26: */ ! 27: #define MAXTMREC (20*1024) /* max size tape rec allowed */ ! 28: struct tmdma { ! 29: struct tm_mbinfo tm_mbinfo; /* Multibus IOPB crap */ ! 30: char tmbuf[MAXTMREC];/* Block of data */ ! 31: }; ! 32: ! 33: #define MB_DMA_ADDR_MASK 0x000FFFFF /* Low meg */ ! 34: ! 35: /* ! 36: * Driver definition ! 37: */ ! 38: struct devinfo tminfo = { ! 39: sizeof(struct tmdevice), /* Size of device registers */ ! 40: sizeof(struct tmdma), /* DMA space required */ ! 41: 0, /* Local variable space */ ! 42: NTMADDR, /* # of standard addresses */ ! 43: tmstd, /* Standard addr vector */ ! 44: MAP_MBIO, /* Map type of device regs */ ! 45: MAXTMREC, /* transfer size */ ! 46: }; ! 47: ! 48: /* ! 49: * What facilities we export to the world ! 50: */ ! 51: int tmstrategy(), tmopen(), tmclose(); ! 52: extern int ttboot(); ! 53: extern int nullsys(); ! 54: ! 55: struct boottab mtdriver = { ! 56: "mt", nullsys, ttboot, tmopen, tmclose, tmstrategy, ! 57: "mt: TapeMaster 9-track tape", &tminfo, ! 58: }; ! 59: ! 60: ! 61: /* ! 62: * Open a tape drive ! 63: */ ! 64: tmopen(sip) ! 65: register struct saioreq *sip; ! 66: { ! 67: register skip; ! 68: ! 69: if (tminit(sip) == -1) ! 70: return (-1); ! 71: tmcmd(sip, TM_REWINDX); ! 72: skip = sip->si_boff; ! 73: while (skip--) { ! 74: sip->si_cc = 0; ! 75: tmcmd(sip, TM_SEARCH); ! 76: } ! 77: return (0); ! 78: } ! 79: ! 80: tmclose(sip) ! 81: struct saioreq *sip; ! 82: { ! 83: ! 84: tmcmd(sip, TM_REWINDX); ! 85: } ! 86: ! 87: tmstrategy(sip, rw) ! 88: register struct saioreq *sip; ! 89: int rw; ! 90: { ! 91: int func = (rw == WRITE) ? TM_WRITE : TM_READ; ! 92: ! 93: return tmcmd(sip, func); ! 94: } ! 95: ! 96: #define NOTZERO 1 /* don't care value-but not zero (clr inst botch) */ ! 97: #define ATTN(c) (((struct tmdevice *)c)->tmdev_attn=NOTZERO) ! 98: #define RESET(c) (((struct tmdevice *)c)->tmdev_reset=NOTZERO) ! 99: #define clrtpb(tp) bzero((caddr_t)(tp), sizeof *(tp)); ! 100: ! 101: tmcmd(sip, func) ! 102: register struct saioreq *sip; ! 103: { ! 104: # define tmdmap ((struct tmdma *)sip->si_dmaaddr) ! 105: # define tmb (&tmdmap->tm_mbinfo) ! 106: register struct tmdevice *tmaddr = ! 107: (struct tmdevice *)sip->si_devaddr; ! 108: register struct tpb *tpb = &tmb->tmb_tpb; ! 109: int count = 1; ! 110: int size = 0; ! 111: struct tmstat tms; ! 112: int err; ! 113: ! 114: switch (func) { ! 115: ! 116: case TM_READ: ! 117: size = sip->si_cc; ! 118: break; ! 119: ! 120: case TM_WRITE: ! 121: size = sip->si_cc; ! 122: swab((char *)sip->si_ma, tmdmap->tmbuf, size); ! 123: break; ! 124: } ! 125: ! 126: clrtpb(tpb); ! 127: tpb->tm_cmd = func &~ TM_DIRBIT; ! 128: tpb->tm_ctl.tmc_rev = func & TM_DIRBIT; ! 129: tpb->tm_ctl.tmc_width = 1; ! 130: tpb->tm_ctl.tmc_speed = sip->si_unit & 08; ! 131: tpb->tm_ctl.tmc_tape = sip->si_unit & 03; ! 132: tpb->tm_rcount = count; ! 133: tpb->tm_bsize = size; ! 134: c68t86((long)tmdmap->tmbuf, &tpb->tm_baddr); ! 135: tmb->tmb_ccb.tmccb_gate = TMG_CLOSED; ! 136: ! 137: /* Start the command and wait for completion */ ! 138: ATTN(tmaddr); ! 139: while (tmb->tmb_ccb.tmccb_gate == TMG_CLOSED) ! 140: ; ! 141: ! 142: tms = tpb->tm_stat; ! 143: err = tms.tms_error; ! 144: ! 145: /* ! 146: * An operation completed... record status ! 147: */ ! 148: if (err == E_EOT && tms.tms_load) ! 149: err = E_NOERROR; ! 150: /* ! 151: * Check for errors. ! 152: */ ! 153: if (err != E_NOERROR && err != E_SHORTREC) { ! 154: if (err == E_EOF || err == E_EOT) ! 155: return (0); ! 156: /* Note: TapeMaster does retries for us */ ! 157: printf("tm hard err %x\n", err); ! 158: return (-1); ! 159: } ! 160: if (func == TM_READ) ! 161: swab(tmdmap->tmbuf, sip->si_ma, tpb->tm_count); ! 162: return (tpb->tm_count); ! 163: # undef tmdma ! 164: # undef tmb ! 165: } ! 166: ! 167: #define SPININIT 1000000 ! 168: /* ! 169: * Initialize a controller ! 170: * Reset it, set up SCP, SCB, and CCB, ! 171: * and give it an attention. ! 172: * Make sure its there by waiting for the gate to open ! 173: * Once initialization is done, issue CONFIG just to be safe. ! 174: */ ! 175: tminit(sip) ! 176: register struct saioreq *sip; ! 177: { ! 178: register struct tm_mbinfo *tmb = ! 179: &((struct tmdma *)(sip->si_dmaaddr))->tm_mbinfo; ! 180: register struct tmdevice *tmaddr = ! 181: (struct tmdevice *)sip->si_devaddr; ! 182: register struct tpb *tpb = &tmb->tmb_tpb; ! 183: ! 184: bzero((caddr_t)tmb, sizeof (struct tm_mbinfo)); ! 185: RESET(tmaddr); ! 186: ! 187: /* setup System Configuration Block */ ! 188: tmb->tmb_scb.tmscb_03 = tmb->tmb_scb.tmscb_03x = TMSCB_CONS; ! 189: c68t86((long)&tmb->tmb_ccb, &tmb->tmb_scb.tmccb_ptr); ! 190: ! 191: /* setup Channel Control Block */ ! 192: tmb->tmb_ccb.tmccb_gate = TMG_CLOSED; ! 193: ! 194: { ! 195: register struct tmscp *tmscp; ! 196: char *temp; ! 197: register int spin; ! 198: int virtstart; ! 199: ! 200: /* Snatch the dma space that this screwy Intel device needs */ ! 201: /* get the virtual address */ ! 202: tmscp = (struct tmscp *)(DVMA_BASE + TM_SCPADDR); ! 203: virtstart = getpgmap((char *)tmscp); ! 204: /* get random page */ ! 205: temp = resalloc(RES_MAINMEM, sizeof (struct tmscp)); ! 206: /* point virt at new page */ ! 207: setpgmap((char *)tmscp, getpgmap(temp)); ! 208: ! 209: /* setup System Configuration Pointer */ ! 210: tmscp->tmscb_bus = tmscp->tmscb_busx = TMSCB_BUS16; ! 211: c68t86((long)&tmb->tmb_scb, &tmscp->tmscb_ptr); ! 212: ! 213: /* Start the TapeMaster and wait til it says "done" */ ! 214: ATTN(tmaddr); ! 215: for (spin = SPININIT; tmb->tmb_ccb.tmccb_gate != TMG_OPEN; ) ! 216: if (--spin <= 0) ! 217: break; ! 218: ! 219: /* Give back the dma space this screwy Intel device needs */ ! 220: setpgmap((char *)tmscp, virtstart); ! 221: ! 222: if (spin <= 0) { ! 223: printf("tm: no response from ctlr %x\n", sip->si_ctlr); ! 224: return (-1); ! 225: } ! 226: } ! 227: ! 228: /* Finish CCB, point it at TPB */ ! 229: tmb->tmb_ccb.tmccb_ccw = TMC_NORMAL; ! 230: c68t86((long)tpb, &tmb->tmb_ccb.tmtpb_ptr); ! 231: ! 232: /* Issue CONFIG command */ ! 233: clrtpb(tpb); ! 234: tpb->tm_cmd = TM_CONFIG; ! 235: tpb->tm_cmd2 = 0; ! 236: tpb->tm_ctl.tmc_width = 1; ! 237: ! 238: /* Get the gate */ ! 239: while (tmb->tmb_ccb.tmccb_gate != TMG_OPEN) ! 240: ; ! 241: tmb->tmb_ccb.tmccb_gate = TMG_CLOSED; ! 242: ! 243: /* Start the command and wait for completion */ ! 244: ATTN(tmaddr); ! 245: while (tmb->tmb_ccb.tmccb_gate == TMG_CLOSED) ! 246: ; ! 247: ! 248: /* Check and report errors */ ! 249: if (tpb->tm_stat.tms_error) { ! 250: printf("tm: error %d during config of ctlr %x\n", ! 251: tpb->tm_stat.tms_error, sip->si_ctlr); ! 252: tpb->tm_stat.tms_error = 0; ! 253: return (-1); ! 254: } ! 255: return (0); ! 256: } ! 257: ! 258: /* ! 259: * Convert a 68000 address into a 8086 address ! 260: * This involves translating a virtual address into a ! 261: * physical multibus address and converting the 20 bit result ! 262: * into a two word base and offset. ! 263: */ ! 264: static c68t86(a68, a86) ! 265: long a68; ! 266: ptr86_t *a86; ! 267: { ! 268: ! 269: a68 &= MB_DMA_ADDR_MASK; ! 270: a86->a_offset = a68 & 0xFFFF; ! 271: a86->a_base = (a68 & 0xF0000) >> 4; ! 272: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.