1 /* 2 * Copyright (c) 1982, 1986, 1988 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)ut.c 7.6 (Berkeley) 04/04/90 7 */ 8 9 /* 10 * SI Model 9700 -- emulates TU45 on the UNIBUS 11 */ 12 13 #include "param.h" 14 15 #include "../vax/pte.h" 16 17 #include "../vaxuba/ubareg.h" 18 #include "../vaxuba/utreg.h" 19 20 #include "saio.h" 21 #include "savax.h" 22 23 #define MASKREG(reg) ((reg)&0xffff) 24 25 #define MAXCTLR 1 /* all addresses must be specified */ 26 u_short utstd[MAXCTLR] = { 0172440 }; /* non-standard */ 27 28 utopen(io) 29 register struct iob *io; 30 { 31 register int skip; 32 33 if ((u_int)io->i_adapt >= nuba) 34 return (EADAPT); 35 if ((u_int)io->i_ctlr >= MAXCTLR) 36 return (ECTLR); 37 if (badaddr((char *)ubamem(io->i_unit, utstd[io->i_ctlr]), sizeof(short))) 38 return (ENXIO); 39 utstrategy(io, UT_REW); 40 for (skip = io->i_part; skip--;) 41 utstrategy(io, UT_SFORWF); 42 return (0); 43 } 44 45 utclose(io) 46 register struct iob *io; 47 { 48 utstrategy(io, UT_REW); 49 } 50 51 #define UTWAIT(addr) { \ 52 do \ 53 word = addr->utcs1; \ 54 while((word&UT_RDY) == 0); \ 55 } 56 57 utstrategy(io, func) 58 register struct iob *io; 59 { 60 register struct utdevice *addr; 61 register u_short word; 62 register int errcnt; 63 int info, resid; 64 u_short dens; 65 66 addr = (struct utdevice *)ubamem(io->i_unit, utstd[io->i_ctlr]); 67 dens = io->i_unit | PDP11FMT | UT_PE; 68 errcnt = 0; 69 retry: 70 utquiet(addr); 71 addr->uttc = dens; 72 info = ubasetup(io, 1); 73 addr->utwc = -((io->i_cc+1) >> 1); 74 addr->utfc = -io->i_cc; 75 if (func == READ) { 76 addr->utba = info; 77 addr->utcs1 = UT_RCOM | ((info>>8) & 0x30) | UT_GO; 78 } else if (func == WRITE) { 79 addr->utba = info; 80 addr->utcs1 = UT_WCOM | ((info>>8) & 0x30) | UT_GO; 81 } else if (func == UT_SREV) { 82 addr->utcs1 = UT_SREV | UT_GO; 83 return (0); 84 } else 85 addr->utcs1 = func | UT_GO; 86 UTWAIT(addr); 87 ubafree(io, info); 88 word = addr->utds; 89 if (word&(UTDS_EOT|UTDS_TM)) { 90 addr->utcs1 = UT_CLEAR | UT_GO; 91 goto done; 92 } 93 if ((word&UTDS_ERR) || (addr->utcs1&UT_TRE)) { 94 printf("ut error: cs1=%b er=%b cs2=%b ds=%b", 95 addr->utcs1, UT_BITS, addr->uter, UTER_BITS, 96 addr->utcs2, UTCS2_BITS, word, UTDS_BITS); 97 if (errcnt++ == 10) { 98 printf("ut: unrecovered error\n"); 99 return (-1); 100 } 101 if (addr->utcs1&UT_TRE) 102 addr->utcs2 |= UTCS2_CLR; 103 addr->utcs1 = UT_CLEAR | UT_GO; 104 utstrategy(io, UT_SREV); 105 utquiet(addr); 106 if (func == WRITE) { 107 addr->utcs1 = UT_ERASE | UT_GO; 108 UTWAIT(addr); 109 } 110 goto retry; 111 } 112 if (errcnt) 113 printf("ut: recovered by retry\n"); 114 done: 115 if (func == READ) { 116 resid = 0; 117 if (io->i_cc > MASKREG(addr->utfc)) 118 resid = io->i_cc - MASKREG(addr->utfc); 119 } else 120 resid = MASKREG(-addr->utfc); 121 return (io->i_cc - resid); 122 } 123 124 static 125 utquiet(addr) 126 register struct utdevice *addr; 127 { 128 register u_short word; 129 130 UTWAIT(addr); 131 do 132 word = addr->utds; 133 while ((word&UTDS_DRY) == 0 && (word&UTDS_PIP)); 134 } 135