|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)io.c 1.7 (Berkeley/CCI) 6/7/88"; ! 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: int vdtimeout; ! 19: char *clean_up = "Cleaning up... Please wait.\n"; ! 20: ! 21: ! 22: /* ! 23: ** ! 24: */ ! 25: ! 26: poll(wait) ! 27: int wait; ! 28: { ! 29: register struct vddevice *addr = C_INFO->addr; ! 30: int tokens[10]; ! 31: ! 32: if (kill_processes == false) ! 33: wait_for_char = 0; ! 34: vdtimeout = wait*1000; ! 35: for (;;) { ! 36: uncache(&(dcb.operrsta)); ! 37: if (dcb.operrsta & (DCBS_DONE | DCBS_ABORT)) ! 38: break; ! 39: if (kill_processes == false && input()) { ! 40: get_text_cmd(nul_table, tokens); ! 41: if (kill_processes == true) { ! 42: indent(); ! 43: print(clean_up); ! 44: exdent(1); ! 45: } ! 46: } ! 47: if (vdtimeout-- <= 0) { ! 48: if(C_INFO->type == VDTYPE_VDDC) ! 49: printf("\nVDDC"); ! 50: else ! 51: printf("\nSMD-E"); ! 52: printf(": Controller timeout"); ! 53: abort: ! 54: VDABORT(addr, C_INFO->type); ! 55: DELAY(30000); ! 56: break; ! 57: } ! 58: DELAY(1000); ! 59: } ! 60: if ((vdtimeout > 0)) { ! 61: if (C_INFO->type == VDTYPE_SMDE) { ! 62: for (;;) { ! 63: uncache(&(addr->vdcsr)); ! 64: if ((addr->vdcsr & CS_GO) == 0) ! 65: break; ! 66: DELAY(1000); ! 67: if (vdtimeout-- <= 0) { ! 68: printf("\nSMD-E timed out clearing GO"); ! 69: goto abort; ! 70: } ! 71: } ! 72: DELAY(300); ! 73: } ! 74: DELAY(500); ! 75: } ! 76: DELAY(200); ! 77: if((dcb.opcode == VDOP_RD) || (dcb.opcode == VDOP_RDRAW)) ! 78: mtpr(PADC, 0); ! 79: uncache(&(dcb.operrsta)); ! 80: uncache(&(dcb.err_code)); ! 81: wait_for_char = 1; ! 82: } ! 83: ! 84: ! 85: /* ! 86: ** Access_with_no_trailer is used to perform controller functions which ! 87: ** require no data movement. ! 88: */ ! 89: ! 90: access_with_no_trailer(function, wait_time) ! 91: int function, wait_time; ! 92: { ! 93: dcb.opcode = function; /* command */ ! 94: dcb.intflg = DCBINT_NONE; ! 95: dcb.nxtdcb = (struct dcb *)0; /* end of chain */ ! 96: dcb.operrsta = 0; ! 97: dcb.devselect = (function == VDOP_START) ? 0 : ! 98: ((char)cur.drive | lab->d_devflags); ! 99: dcb.trailcnt = (char)0; ! 100: mdcb.mdcb_head = &dcb; ! 101: mdcb.mdcb_status = 0; ! 102: VDGO(C_INFO->addr, (u_long)&mdcb, C_INFO->type); ! 103: poll(wait_time); ! 104: if(vdtimeout <= 0) { ! 105: printf(" during startup operation.\n"); ! 106: _longjmp(abort_environ, 1); ! 107: } ! 108: return dcb.operrsta; ! 109: } ! 110: ! 111: vread(sn, buf, seccnt) ! 112: int sn, seccnt; ! 113: char *buf; ! 114: { ! 115: int ret; ! 116: ! 117: ret = vrdwr(sn, buf, seccnt, VDOP_RD); ! 118: if (ret == 0) ! 119: vd_error("read"); ! 120: return (ret); ! 121: } ! 122: ! 123: vwrite(sn, buf, seccnt) ! 124: int sn, seccnt; ! 125: char *buf; ! 126: { ! 127: int ret; ! 128: ! 129: ret = vrdwr(sn, buf, seccnt, VDOP_WD); ! 130: if (ret == 0) ! 131: vd_error("write"); ! 132: return (ret); ! 133: }; ! 134: ! 135: vrdwr(sn, buf, seccnt, op) ! 136: int sn, seccnt, op; ! 137: char *buf; ! 138: { ! 139: dskadr dskaddr; ! 140: ! 141: dskaddr.cylinder = sn / lab->d_secpercyl; ! 142: sn %= lab->d_secpercyl; ! 143: dskaddr.track = sn / lab->d_nsectors; ! 144: dskaddr.sector = sn % lab->d_nsectors; ! 145: if (access_dsk(buf, &dskaddr, op, seccnt, 1) & DCBS_HARD) ! 146: return (0); ! 147: return (seccnt); ! 148: } ! 149: ! 150: /* ! 151: ** access_dsk is used by other routines to do reads and writes to the disk. ! 152: ** The status of the read / write is returned to the caller for processing. ! 153: */ ! 154: ! 155: access_dsk(buf, dskaddr, func, count, wait) ! 156: char *buf; ! 157: dskadr *dskaddr; ! 158: int func, count, wait; ! 159: { ! 160: cur.daddr.cylinder = dskaddr->cylinder; ! 161: cur.daddr.track = dskaddr->track; ! 162: wait_for_char = 0; ! 163: dcb.opcode = func; /* format sector command */ ! 164: dcb.intflg = DCBINT_NONE; ! 165: dcb.nxtdcb = (struct dcb *)0; /* end of chain */ ! 166: dcb.operrsta = 0; ! 167: dcb.devselect = (char)cur.drive | lab->d_devflags; ! 168: if(func == VDOP_SEEK) { ! 169: dcb.trailcnt = (char)(sizeof(struct trseek) / sizeof(long)); ! 170: dcb.trail.sktrail.skaddr.cylinder = dskaddr->cylinder; ! 171: dcb.trail.sktrail.skaddr.track = dskaddr->track; ! 172: dcb.trail.sktrail.skaddr.sector = dskaddr->sector; ! 173: } else { ! 174: dcb.trailcnt = (char)(sizeof(struct trrw) / sizeof(long)); ! 175: dcb.trail.rwtrail.memadr = (u_long)buf; ! 176: dcb.trail.rwtrail.wcount=count*(lab->d_secsize/sizeof(short)); ! 177: dcb.trail.rwtrail.disk.cylinder = dskaddr->cylinder; ! 178: dcb.trail.rwtrail.disk.track = dskaddr->track; ! 179: dcb.trail.rwtrail.disk.sector = dskaddr->sector; ! 180: } ! 181: mdcb.mdcb_head = &dcb; ! 182: mdcb.mdcb_status = 0; ! 183: VDGO(C_INFO->addr, (u_long)&mdcb, C_INFO->type); ! 184: if(wait) { ! 185: poll(10); ! 186: if(vdtimeout <= 0) { ! 187: printf(" in access_dsk.\n"); ! 188: _longjmp(abort_environ, 1); ! 189: } ! 190: } ! 191: wait_for_char = 1; ! 192: return dcb.operrsta; ! 193: } ! 194: ! 195: ! 196: /* ! 197: ** Spin_up_drive starts the drives on a controller and waits around for ! 198: ** the drive to spin up if it is not already spinning. ! 199: */ ! 200: ! 201: spin_up_drive() ! 202: { ! 203: register struct vddevice *addr = C_INFO->addr; ! 204: ! 205: VDRESET(addr, C_INFO->type); ! 206: if(C_INFO->type == VDTYPE_SMDE) { ! 207: addr->vdcsr = 0; ! 208: addr->vdtcf_mdcb = AM_ENPDA; ! 209: addr->vdtcf_dcb = AM_ENPDA; ! 210: addr->vdtcf_trail = AM_ENPDA; ! 211: addr->vdtcf_data = AM_ENPDA; ! 212: addr->vdccf = CCF_SEN | 0x8 | CCF_STS | ! 213: XMD_32BIT | BSZ_16WRD | CCF_ERR | ! 214: CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE; ! 215: } ! 216: access_with_no_trailer(VDOP_INIT, 10); ! 217: access_with_no_trailer(VDOP_DIAG, 20); ! 218: configure_drive(0); ! 219: } ! 220: ! 221: /* ! 222: ** Configure_drive tells the controller what kind of drive is attached ! 223: ** on a particular line. ! 224: */ ! 225: ! 226: configure_drive(pass) ! 227: int pass; ! 228: { ! 229: register struct vddevice *addr = C_INFO->addr; ! 230: register i; ! 231: ! 232: top: ! 233: dcb.opcode = VDOP_CONFIG; /* command */ ! 234: dcb.intflg = DCBINT_NONE; ! 235: dcb.nxtdcb = (struct dcb *)0; /* end of chain */ ! 236: dcb.operrsta = 0; ! 237: dcb.devselect = cur.drive | lab->d_devflags; ! 238: dcb.trail.rstrail.ncyl = lab->d_ncylinders; ! 239: dcb.trail.rstrail.nsurfaces = lab->d_ntracks; ! 240: if(C_INFO->type == VDTYPE_VDDC) ! 241: dcb.trailcnt = (char)2; ! 242: else { ! 243: dcb.trailcnt = sizeof (struct treset)/sizeof (long); ! 244: dcb.trail.rstrail.nsectors = lab->d_nsectors; ! 245: dcb.trail.rstrail.slip_sec = lab->d_sparespertrack; ! 246: dcb.trail.rstrail.recovery = VDRF_NONE; ! 247: addr->vdcylskew = lab->d_cylskew; ! 248: addr->vdtrackskew = lab->d_trackskew; ! 249: addr->vdsecsize = lab->d_secsize/sizeof(short); ! 250: } ! 251: mdcb.mdcb_head = &dcb; ! 252: mdcb.mdcb_status = 0; ! 253: VDGO(addr, (u_long)&mdcb, C_INFO->type); ! 254: poll(5); ! 255: if(vdtimeout <= 0) { ! 256: printf(" during drive configuration.\n"); ! 257: goto bad; ! 258: } ! 259: if(dcb.operrsta & VDERR_HARD) { ! 260: if (C_INFO->type == VDTYPE_SMDE) { ! 261: if (lab->d_devflags == 0) { ! 262: lab->d_devflags = VD_ESDI; ! 263: goto top; ! 264: } ! 265: #ifdef notdef ! 266: printf("vdstatus %x\n", addr->vdstatus[cur.drive]); ! 267: if ((addr->vdstatus[cur.drive] & STA_US) == 0) { ! 268: printf("Drive not present\n\n"); ! 269: goto bad; ! 270: } ! 271: #endif ! 272: } ! 273: if ((dcb.operrsta & (DCBS_OCYL|DCBS_NRDY)) == 0) { ! 274: printf("drive config error\n"); ! 275: goto bad; ! 276: } ! 277: if(pass) { ! 278: printf("\nDrive failed to start!\n\n"); ! 279: goto bad; ! 280: } ! 281: printf("\ndrive not ready, attempting to spin up..."); ! 282: access_with_no_trailer(VDOP_START, 62); ! 283: for (i = 0; i < 620; i++) { ! 284: if (C_INFO->type == VDTYPE_SMDE && ! 285: addr->vdstatus[cur.drive] & STA_UR) ! 286: break; ! 287: DELAY(100000); ! 288: } ! 289: printf(" retrying drive configuration\n"); ! 290: pass++; ! 291: lab->d_devflags = 0; ! 292: goto top; ! 293: } ! 294: D_INFO->alive = u_true; ! 295: return; ! 296: bad: ! 297: D_INFO->alive = u_false; ! 298: _longjmp(abort_environ, -1); ! 299: } ! 300: ! 301: ! 302: /* ! 303: ** data_ok checks an error status word for bit patterns ! 304: ** associated with error conditions from the VDDC controller. If a hardware ! 305: ** error is present then the problem is reported on the console. ! 306: ** If a data error is present the a zero is returned. ! 307: ** If everything is OK then a 1 is returned. ! 308: */ ! 309: ! 310: data_ok() ! 311: { ! 312: register int status = dcb.operrsta; ! 313: ! 314: if(status & HARD_ERROR){ ! 315: vd_error("data transfer"); ! 316: printf(" op = 0x%x\n", dcb.opcode); ! 317: reset_controller(); ! 318: dcb.operrsta &= HEADER_ERROR; ! 319: } ! 320: return (int)(!(status & (DATA_ERROR | HEADER_ERROR))); ! 321: } ! 322: ! 323: vd_error(s) ! 324: char *s; ! 325: { ! 326: register int status = dcb.operrsta; ! 327: ! 328: print("%s error at sector %d (cyl %d trk %d sect %d),\n", ! 329: s, to_sector(cur.daddr), dcb.err_cyl & 0xfff, dcb.err_trk, ! 330: dcb.err_sec); ! 331: print(" status=%b", dcb.operrsta, VDERRBITS); ! 332: if (C_INFO->type == VDTYPE_SMDE) ! 333: printf(", ecode=0x%x", dcb.err_code); ! 334: printf(".\n"); ! 335: } ! 336: ! 337: ! 338: /* ! 339: ** ! 340: */ ! 341: ! 342: reset_controller() ! 343: { ! 344: printf("Resetting controller. Please wait...\n"); ! 345: spin_up_drive(); ! 346: printf("Controller was reset successfully.\n"); ! 347: } ! 348: ! 349: /* ! 350: ** ! 351: */ ! 352: ! 353: static int indent_count; ! 354: ! 355: ! 356: /* ! 357: ** ! 358: */ ! 359: ! 360: indent() ! 361: { ! 362: indent_count += 2; ! 363: } ! 364: ! 365: ! 366: /* ! 367: ** ! 368: */ ! 369: ! 370: exdent(count) ! 371: int count; ! 372: { ! 373: if(count == -1) ! 374: indent_count = 0; ! 375: else ! 376: indent_count -= count * 2; ! 377: if(indent_count < 0) ! 378: indent_count = 0; ! 379: } ! 380: ! 381: ! 382: /* ! 383: ** ! 384: */ ! 385: /*VARARGS1*/ ! 386: print(par0, par1, par2, par3, par4, par5, par6) ! 387: char *par0, *par1, *par2, *par3, *par4, *par5, *par6; ! 388: { ! 389: register int count = indent_count; ! 390: ! 391: while(count--) ! 392: printf(" "); ! 393: printf(par0, par1, par2, par3, par4, par5, par6); ! 394: DELAY((strlen(par0) + 20) * 9000); ! 395: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.