1 2 /* @(#)tmscp.c 7.5 (Berkeley) 04/04/90 */ 3 4 /**************************************************************** 5 * * 6 * Licensed from Digital Equipment Corporation * 7 * Copyright (c) * 8 * Digital Equipment Corporation * 9 * Maynard, Massachusetts * 10 * 1985, 1986 * 11 * All rights reserved. * 12 * * 13 * The Information in this software is subject to change * 14 * without notice and should not be construed as a commitment * 15 * by Digital Equipment Corporation. Digital makes no * 16 * representations about the suitability of this software for * 17 * any purpose. It is supplied "As Is" without expressed or * 18 * implied warranty. * 19 * * 20 * If the Regents of the University of California or its * 21 * licensees modify the software in a manner creating * 22 * diriviative copyright rights, appropriate copyright * 23 * legends may be placed on the drivative work in addition * 24 * to that set forth above. * 25 ***************************************************************/ 26 /* 27 * tmscp.c - TMSCP (TK50/TU81) standalone driver 28 */ 29 30 # ifndef lint 31 static char *sccsid = "@(#)tmscp.c 1.5 (ULTRIX) 4/18/86"; 32 # endif not lint 33 34 /* ------------------------------------------------------------------------ 35 * Modification History: /sys/stand/tmscp.c 36 * 37 * 3-15-85 afd 38 * Don't ask for an interrupt when commands are issued and 39 * check ownership bit in the response descriptor to detect when a 40 * command is complete. Necessary due to the TU81's failure to set 41 * the response interrupt field in the communications area. 42 * 43 * ------------------------------------------------------------------------ 44 */ 45 46 #include "param.h" 47 48 #include "../vax/pte.h" 49 50 #include "savax.h" 51 #include "saio.h" 52 53 /* 54 * Parameters for the communications area 55 * (Only 1 cmd & 1 rsp packet) 56 */ 57 #define NRSPL2 0 58 #define NCMDL2 0 59 #define NRSP (1<<NRSPL2) 60 #define NCMD (1<<NCMDL2) 61 62 #include "../vaxuba/tmscpreg.h" 63 #include "../vaxuba/ubareg.h" 64 #include "../vax/tmscp.h" 65 66 #define MAXCTLR 1 /* all addresses must be specified */ 67 u_short tmscpstd[MAXCTLR] = { 0174500 }; 68 69 struct iob ctmscpbuf; 70 71 struct tmscpdevice *tmscpaddr = 0; 72 73 struct tmscp { 74 struct tmscpca tmscp_ca; 75 struct mscp tmscp_rsp; 76 struct mscp tmscp_cmd; 77 } tmscp; 78 79 struct tmscp *tmscp_ubaddr; /* Unibus address of tmscp structure */ 80 81 struct mscp *tmscpcmd(); 82 83 int tmscp_offline = 1; /* Flag to prevent multiple STCON */ 84 int tms_offline[4] = {1,1,1,1}; /* Flag to prevent multiple ONLIN */ 85 86 /* 87 * Open a tmscp device. Initialize the controller and set the unit online. 88 */ 89 tmscpopen(io) 90 register struct iob *io; 91 { 92 register struct mscp *mp; 93 int i; 94 95 if ((u_int)io->i_ctlr >= MAXCTLR) 96 return (ECTLR); 97 /* 98 * Have the tmscp controller characteristics already been set up 99 * (STCON)? 100 */ 101 if (tmscp_offline) { 102 if (tmscpaddr == 0) 103 tmscpaddr = (struct tmscpdevice *)ubamem(io->i_adapt, tmscpstd[0]); 104 if (tmscp_ubaddr == 0) { 105 ctmscpbuf = *io; 106 ctmscpbuf.i_ma = (caddr_t)&tmscp; 107 ctmscpbuf.i_cc = sizeof(tmscp); 108 tmscp_ubaddr = (struct tmscp *)ubasetup(&ctmscpbuf, 2); 109 } 110 /* 111 * Initialize the tmscp device and wait for the 4 steps 112 * to complete. 113 */ 114 tmscpaddr->tmscpip = 0; 115 while ((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0); 116 tmscpaddr->tmscpsa =TMSCP_ERR|(NCMDL2<<11)|(NRSPL2<<8); 117 118 while ((tmscpaddr->tmscpsa & TMSCP_STEP2) == 0); 119 # define STEP1MASK 0174377 120 # define STEP1GOOD (TMSCP_STEP2|TMSCP_IE|(NCMDL2<<3)|NRSPL2) 121 if ((tmscpaddr->tmscpsa&STEP1MASK) != STEP1GOOD) 122 printf("tmscpopen: step 1 not successful sa=%o\n",tmscpaddr->tmscpsa&0xffff); 123 tmscpaddr->tmscpsa = (short)&tmscp_ubaddr->tmscp_ca.ca_ringbase; 124 125 while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0); 126 # define STEP2MASK 0174377 127 # define STEP2GOOD (TMSCP_STEP3) 128 if ((tmscpaddr->tmscpsa&STEP2MASK) != STEP2GOOD) 129 printf("tmscpopen: step 2 not successful sa=%o\n",tmscpaddr->tmscpsa&0xffff); 130 tmscpaddr->tmscpsa = (short)(((int)&tmscp_ubaddr->tmscp_ca.ca_ringbase) >> 16); 131 132 while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0); 133 # define STEP3MASK 0174000 134 # define STEP3GOOD TMSCP_STEP4 135 if ((tmscpaddr->tmscpsa&STEP3MASK) != STEP3GOOD) 136 printf("tmscpopen: step 3 not successful sa=%o\n",tmscpaddr->tmscpsa&0xffff); 137 tmscpaddr->tmscpsa = TMSCP_GO; 138 139 /* 140 * Init cmd & rsp area 141 */ 142 tmscp.tmscp_ca.ca_cmddsc[0] = (long)&tmscp_ubaddr->tmscp_cmd.mscp_cmdref; 143 tmscp.tmscp_cmd.mscp_dscptr = tmscp.tmscp_ca.ca_cmddsc; 144 tmscp.tmscp_cmd.mscp_header.tmscp_vcid = 1; /* for tape */ 145 146 tmscp.tmscp_ca.ca_rspdsc[0] = (long)&tmscp_ubaddr->tmscp_rsp.mscp_cmdref; 147 tmscp.tmscp_rsp.mscp_dscptr = tmscp.tmscp_ca.ca_rspdsc; 148 tmscp.tmscp_cmd.mscp_cntflgs = 0; 149 if (tmscpcmd(M_OP_STCON, 0) == 0) { 150 printf("tms: open error, STCON\n"); 151 return (EIO); 152 } 153 tmscp_offline = 0; 154 } 155 tmscp.tmscp_cmd.mscp_unit = io->i_unit&03; 156 /* 157 * Has this unit been issued an ONLIN? 158 */ 159 if (tms_offline[tmscp.tmscp_cmd.mscp_unit]) { 160 if ((mp = tmscpcmd(M_OP_ONLIN, 0)) == 0) { 161 _stop("tms: open error, ONLIN\n"); 162 return (EIO); 163 } 164 tms_offline[tmscp.tmscp_cmd.mscp_unit] = 0; 165 } 166 /* 167 * This makes no sense, but I could be wrong... KB 168 * 169 * if ((u_int)io->i_part > 3) 170 * return (EPART); 171 */ 172 if (io->i_part) { 173 /* 174 * Skip forward the appropriate number of files on the tape. 175 */ 176 tmscp.tmscp_cmd.mscp_tmkcnt = io->i_part; 177 (void)tmscpcmd(M_OP_REPOS, 0); 178 tmscp.tmscp_cmd.mscp_tmkcnt = 0; 179 } 180 return (0); 181 } 182 183 /* 184 * Close the device (rewind it to BOT) 185 */ 186 tmscpclose(io) 187 register struct iob *io; 188 { 189 (void)tmscpcmd(M_OP_REPOS, M_MD_REWND); 190 } 191 192 /* 193 * Set up tmscp command packet. Cause the controller to poll to pick up 194 * the command. 195 */ 196 struct mscp * 197 tmscpcmd(op,mod) 198 int op, mod; /* opcode and modifier (usu 0) */ 199 { 200 struct mscp *mp; /* ptr to cmd packet */ 201 int i; /* read into to init polling */ 202 203 tmscp.tmscp_cmd.mscp_opcode = op; 204 tmscp.tmscp_cmd.mscp_modifier = mod; 205 tmscp.tmscp_cmd.mscp_header.tmscp_msglen = mscp_msglen; 206 tmscp.tmscp_ca.ca_cmddsc[0] |= TMSCP_OWN; /* | TMSCP_INT */ 207 tmscp.tmscp_rsp.mscp_header.tmscp_msglen = mscp_msglen; 208 tmscp.tmscp_ca.ca_rspdsc[0] |= TMSCP_OWN; /* | TMSCP_INT */ 209 210 i = tmscpaddr->tmscpip; 211 for (;;) { 212 if (tmscpaddr->tmscpsa & TMSCP_ERR) { 213 printf("tmscpcmd: Fatal error sa=%o\n", tmscpaddr->tmscpsa & 0xffff); 214 return(0); 215 } 216 217 if (tmscp.tmscp_ca.ca_cmdint) 218 tmscp.tmscp_ca.ca_cmdint = 0; 219 /* 220 * This is to handle the case of devices not setting the 221 * interrupt field in the communications area. Some 222 * devices (early TU81's) only clear the ownership field 223 * in the Response Descriptor. 224 * 225 * 226 * if (tmscp.tmscp_ca.ca_rspint) 227 * break; 228 */ 229 if (!(tmscp.tmscp_ca.ca_rspdsc[0] & (TMSCP_OWN))) 230 break; 231 } 232 tmscp.tmscp_ca.ca_rspint = 0; 233 mp = &tmscp.tmscp_rsp; 234 if (mp->mscp_opcode != (op|M_OP_END) || 235 (mp->mscp_status&M_ST_MASK) != M_ST_SUCC) { 236 /* 237 * Detect hitting tape mark. This signifies the end of the 238 * tape mini-root file. We don't want to return an error 239 * condition to the strategy routine. 240 */ 241 if ((mp->mscp_status & M_ST_MASK) != M_ST_TAPEM) 242 return(0); 243 } 244 return(mp); 245 } 246 247 /* 248 * Set up to do reads and writes; call tmscpcmd to issue the cmd. 249 */ 250 tmscpstrategy(io, func) 251 register struct iob *io; 252 int func; 253 { 254 register struct mscp *mp; 255 int ubinfo; 256 257 ubinfo = ubasetup(io, 1); 258 mp = &tmscp.tmscp_cmd; 259 mp->mscp_lbn = io->i_bn; 260 mp->mscp_unit = io->i_unit&03; 261 mp->mscp_bytecnt = io->i_cc; 262 mp->mscp_buffer = (ubinfo & 0x3fffff) | (((ubinfo>>28)&0xf)<<24); 263 if ((mp = tmscpcmd(func == READ ? M_OP_READ : M_OP_WRITE, 0)) == 0) { 264 ubafree(io, ubinfo); 265 printf("tms: I/O error\n"); 266 return(-1); 267 } 268 ubafree(io, ubinfo); 269 /* 270 * Detect hitting tape mark so we do it gracefully and return a 271 * character count of 0 to signify end of copy. Rewind the tape 272 * before returning. 273 */ 274 if ((mp->mscp_status & M_ST_MASK) == M_ST_TAPEM) 275 return(0); 276 return(io->i_cc); 277 } 278