1 #ifndef lint 2 static char sccsid[] = "@(#)io.c 1.2 (Berkeley/CCI) 11/04/86"; 3 #endif 4 5 #include "vdfmt.h" 6 #include "cmd.h" 7 8 9 /* 10 ** 11 */ 12 13 static cmd_text_element nul_table[] = { 14 { 0, "", "" } 15 }; 16 17 int wait_for_char; 18 char *clean_up = "Cleaning up... Please wait.\n"; 19 20 21 /* 22 ** 23 */ 24 25 poll(wait) 26 int wait; 27 { 28 int tokens[10]; 29 int didmsg = 0; 30 31 wait_for_char = 0; 32 vdtimeout = wait*1000*1000; 33 uncache(&(dcb.operrsta)); 34 while (!((dcb.operrsta) & (DCBCMP | DCBABT))) { 35 if (input()) { 36 get_text_cmd(nul_table, tokens); 37 if (didmsg == 0 && kill_processes == true) { 38 didmsg = 1; 39 indent(); 40 print(clean_up); 41 exdent(1); 42 } 43 } 44 vdtimeout--; 45 uncache(&(dcb.operrsta)); 46 if (vdtimeout <= 0) { 47 if(C_INFO.type == SMDCTLR) 48 printf("\nVDDC"); 49 else 50 printf("\nSMD-E"); 51 printf(": Controller timeout"); 52 VDDC_ABORT(C_INFO.addr, C_INFO.type); 53 DELAY(30000); 54 break; 55 } 56 } 57 if((vdtimeout > 0)) { 58 if(C_INFO.type == SMD_ECTLR) { 59 uncache(&(C_INFO.addr->cdr_csr)); 60 while(C_INFO.addr->cdr_csr & CS_GO) { 61 DELAY(50); 62 uncache(&(C_INFO.addr->cdr_csr)); 63 } 64 } 65 DELAY(500); 66 } 67 if((dcb.opcode == RD) || (dcb.opcode == RD_RAW)) 68 mtpr(PADC, 0); 69 uncache(&(dcb.operrsta)); 70 uncache(&(dcb.err_code)); 71 wait_for_char = 1; 72 } 73 74 75 /* 76 ** Access_with_no_trailer is used to perform controller functions which 77 ** require no data movement. 78 */ 79 80 access_with_no_trailer(function, wait_time) 81 int function, wait_time; 82 { 83 dcb.opcode = function; /* command */ 84 dcb.intflg = NOINT; 85 dcb.nxtdcb = (fmt_dcb *)0; /* end of chain */ 86 dcb.operrsta = 0; 87 dcb.devselect = (function == VDSTART) ? 0 : (char)cur.drive; 88 dcb.trailcnt = (char)0; 89 mdcb.firstdcb = &dcb; 90 mdcb.vddcstat = 0; 91 VDDC_ATTENTION(C_INFO.addr, &mdcb, C_INFO.type); 92 poll(wait_time); 93 if(vdtimeout <= 0) { 94 printf(" during startup operation.\n"); 95 _longjmp(abort_environ, 1); 96 } 97 return dcb.operrsta; 98 } 99 100 101 /* 102 ** access_dsk is used by other routines to do reads and writes to the disk. 103 ** The status of the read / write is returned to the caller for processing. 104 */ 105 106 access_dsk(buf, dskaddr, func, count, wait) 107 char *buf; 108 dskadr *dskaddr; 109 int func, count, wait; 110 { 111 cur.daddr.cylinder = dskaddr->cylinder; 112 cur.daddr.track = dskaddr->track; 113 wait_for_char = 0; 114 dcb.opcode = func; /* format sector command */ 115 dcb.intflg = NOINT; 116 dcb.nxtdcb = (fmt_dcb *)0; /* end of chain */ 117 dcb.operrsta = 0; 118 dcb.devselect = (char)cur.drive; 119 if(func == SEEK) { 120 dcb.trailcnt = (char)(sizeof(trseek) / sizeof(long)); 121 dcb.trail.sktrail.skaddr.cylinder = dskaddr->cylinder; 122 dcb.trail.sktrail.skaddr.track = dskaddr->track; 123 dcb.trail.sktrail.skaddr.sector = dskaddr->sector; 124 } 125 else { 126 dcb.trailcnt = (char)(sizeof(trrw) / sizeof(long)); 127 dcb.trail.rwtrail.memadr = buf; 128 dcb.trail.rwtrail.wcount=count*(SECSIZ/sizeof(short)); 129 dcb.trail.rwtrail.disk.cylinder = dskaddr->cylinder; 130 dcb.trail.rwtrail.disk.track = dskaddr->track; 131 dcb.trail.rwtrail.disk.sector = dskaddr->sector; 132 } 133 mdcb.firstdcb = &dcb; 134 mdcb.vddcstat = 0; 135 VDDC_ATTENTION(C_INFO.addr, &mdcb, C_INFO.type); 136 if(wait) { 137 poll(2*60); 138 if(vdtimeout <= 0) { 139 printf(" in access_dsk.\n"); 140 _longjmp(abort_environ, 1); 141 } 142 } 143 wait_for_char = 1; 144 return dcb.operrsta; 145 } 146 147 148 /* 149 ** Spin_up_drive starts the drives on a controller and waits around for 150 ** the drive to spin up if it is not already spinning. 151 */ 152 153 spin_up_drive() 154 { 155 VDDC_RESET(C_INFO.addr, C_INFO.type); 156 if(C_INFO.type == SMD_ECTLR) { 157 C_INFO.addr->cdr_csr = 0; 158 C_INFO.addr->mdcb_tcf = AM_ENPDA; 159 C_INFO.addr->dcb_tcf = AM_ENPDA; 160 C_INFO.addr->trail_tcf = AM_ENPDA; 161 C_INFO.addr->data_tcf = AM_ENPDA; 162 C_INFO.addr->cdr_ccf = CCF_SEN | 0x8 | CCF_STS | 163 XMD_32BIT | BSZ_16WRD | CCF_ERR | 164 CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE; 165 } 166 access_with_no_trailer(INIT, 10); 167 access_with_no_trailer(DIAG, 20); 168 configure_drive(0); 169 } 170 171 /* 172 ** Configure_drive tells the controller what kind of drive is attached 173 ** on a particular line. 174 */ 175 176 configure_drive(pass) 177 int pass; 178 { 179 dcb.opcode = RSTCFG; /* command */ 180 dcb.intflg = NOINT; 181 dcb.nxtdcb = (fmt_dcb *)0; /* end of chain */ 182 dcb.operrsta = 0; 183 dcb.devselect = (char)cur.drive; 184 dcb.trail.rstrail.ncyl = CURRENT->vc_ncyl; 185 dcb.trail.rstrail.nsurfaces = CURRENT->vc_ntrak; 186 if(C_INFO.type == SMDCTLR) 187 dcb.trailcnt = (char)2; 188 else { 189 dcb.trailcnt = (char)4; 190 dcb.trail.rstrail.nsectors = CURRENT->vc_nsec; 191 dcb.trail.rstrail.slip_sec = CURRENT->vc_nslip; 192 dcb.trail.rstrail.recovery = 0x00; 193 C_INFO.addr->cyl_skew = (*C_INFO.cylinder_skew)(); 194 C_INFO.addr->trk_skew = (*C_INFO.track_skew)(); 195 } 196 mdcb.firstdcb = &dcb; 197 mdcb.vddcstat = 0; 198 VDDC_ATTENTION(C_INFO.addr, &mdcb, C_INFO.type); 199 poll(5); 200 if(vdtimeout <= 0) { 201 printf(" during drive configuration.\n"); 202 _longjmp(abort_environ, 1); 203 } 204 if(dcb.operrsta & (NOTCYLERR | DRVNRDY)) { 205 if(pass) { 206 printf("\nDrive failed to start!\n\n"); 207 _longjmp(abort_environ, -1); 208 } 209 printf("\ndrive not ready, attempting to spin up..."); 210 access_with_no_trailer(VDSTART, (cur.drive * 6) + 62); 211 DELAY((cur.drive * 5500000) + 62000000); 212 printf(" retrying drive configuration\n"); 213 configure_drive(1); 214 } 215 } 216 217 218 /* 219 ** data_ok checks an error status word for bit patterns 220 ** associated with error conditions from the VDDC controller. If a hardware 221 ** error is present then the problem is reported on the console and the program 222 ** is halted. If a data error is present the a zero is returned. 223 ** If everything is OK then a 1 is returned. 224 */ 225 226 data_ok() 227 { 228 register int status = dcb.operrsta; 229 230 if(status & HARD_ERROR){ 231 if(status & DRVNRDY) 232 printf("\nDrive is not ready!"); 233 else if(status & INVDADR) 234 printf("\nInvalid disk address issued!"); 235 else if(status & DNEMEM) 236 printf("\nNon-existent memory error!"); 237 else if(status & PARERR) 238 printf("\nMain memory parity error!"); 239 else if(status & OPABRT) 240 printf("\nCPU aborted operation!"); 241 else if(status & WPTERR) 242 printf("\nDrive is write protected!"); 243 else if(status & DSEEKERR) 244 printf("\nDisk seek error!"); 245 else if(status & CTLRERR) 246 printf("\nController hardware error!"); 247 else 248 printf("\nNot on cylinder error!"); 249 printf(" Status = 0x%lx", status); 250 if(C_INFO.type == SMD_ECTLR) 251 printf(" Error code = 0x%x", dcb.err_code & 0xff); 252 printf("\n"); 253 printf("cylinder = %d, track = %d,", dcb.err_cyl, dcb.err_trk); 254 printf(" sector = %d, op = 0x%x\n", dcb.err_sec, dcb.opcode); 255 reset_controller(); 256 dcb.operrsta &= HEADER_ERROR; 257 } 258 return (int)(!(status & (DATA_ERROR | HEADER_ERROR))); 259 } 260 261 262 /* 263 ** 264 */ 265 266 reset_controller() 267 { 268 printf("Resetting controller. Please wait...\n"); 269 spin_up_drive(); 270 printf("Controller was reset successfully.\n"); 271 } 272 273 /* 274 ** 275 */ 276 277 static int indent_count; 278 279 280 /* 281 ** 282 */ 283 284 indent() 285 { 286 indent_count += 2; 287 } 288 289 290 /* 291 ** 292 */ 293 294 exdent(count) 295 int count; 296 { 297 if(count == -1) 298 indent_count = 0; 299 else 300 indent_count -= count * 2; 301 if(indent_count < 0) 302 indent_count = 0; 303 } 304 305 306 /* 307 ** 308 */ 309 /*VARARGS1*/ 310 print(par0, par1, par2, par3, par4, par5, par6) 311 char *par0, *par1, *par2, *par3, *par4, *par5, *par6; 312 { 313 register int count = indent_count; 314 315 while(count--) 316 printf(" "); 317 printf(par0, par1, par2, par3, par4, par5, par6); 318 DELAY((strlen(par0) + 20) * 9000); 319 } 320