129532Ssam #ifndef lint 2*32662Skarels static char sccsid[] = "@(#)io.c 1.5 (Berkeley/CCI) 11/23/87"; 329532Ssam #endif 429532Ssam 529532Ssam #include "vdfmt.h" 629532Ssam #include "cmd.h" 729532Ssam 829532Ssam 929532Ssam /* 1029532Ssam ** 1129532Ssam */ 1229532Ssam 1329532Ssam static cmd_text_element nul_table[] = { 1429532Ssam { 0, "", "" } 1529532Ssam }; 1629532Ssam 1729981Skarels int wait_for_char; 1830324Skarels int vdtimeout; 1929532Ssam char *clean_up = "Cleaning up... Please wait.\n"; 2029532Ssam 2129532Ssam 2229532Ssam /* 2329532Ssam ** 2429532Ssam */ 2529532Ssam 2629532Ssam poll(wait) 2729532Ssam int wait; 2829532Ssam { 29*32662Skarels register struct vddevice *addr = C_INFO->addr; 3029532Ssam int tokens[10]; 3129981Skarels int didmsg = 0; 3229532Ssam 3329981Skarels wait_for_char = 0; 34*32662Skarels vdtimeout = wait*1000; 35*32662Skarels for (;;) { 36*32662Skarels uncache(&(dcb.operrsta)); 37*32662Skarels if (dcb.operrsta & (DCBS_DONE | DCBS_ABORT)) 38*32662Skarels break; 3929981Skarels if (input()) { 4029532Ssam get_text_cmd(nul_table, tokens); 4129981Skarels if (didmsg == 0 && kill_processes == true) { 4229981Skarels didmsg = 1; 4329532Ssam indent(); 4429532Ssam print(clean_up); 4529532Ssam exdent(1); 4629532Ssam } 4729532Ssam } 48*32662Skarels if (vdtimeout-- <= 0) { 49*32662Skarels if(C_INFO->type == VDTYPE_VDDC) 5029532Ssam printf("\nVDDC"); 5129532Ssam else 5229532Ssam printf("\nSMD-E"); 5329532Ssam printf(": Controller timeout"); 54*32662Skarels abort: 55*32662Skarels VDABORT(addr, C_INFO->type); 5629532Ssam DELAY(30000); 5729532Ssam break; 5829532Ssam } 59*32662Skarels DELAY(1000); 6029532Ssam } 61*32662Skarels if ((vdtimeout > 0)) { 62*32662Skarels if (C_INFO->type == VDTYPE_SMDE) { 63*32662Skarels for (;;) { 64*32662Skarels uncache(&(addr->vdcsr)); 65*32662Skarels if ((addr->vdcsr & CS_GO) == 0) 66*32662Skarels break; 67*32662Skarels DELAY(1000); 68*32662Skarels if (vdtimeout-- <= 0) { 69*32662Skarels printf("\nSMD-E timed out clearing GO"); 70*32662Skarels goto abort; 71*32662Skarels } 7229532Ssam } 73*32662Skarels DELAY(300); 7429532Ssam } 7529532Ssam DELAY(500); 7629532Ssam } 77*32662Skarels DELAY(200); 7831318Ssam if((dcb.opcode == VDOP_RD) || (dcb.opcode == VDOP_RDRAW)) 7929981Skarels mtpr(PADC, 0); 8029532Ssam uncache(&(dcb.operrsta)); 8129981Skarels uncache(&(dcb.err_code)); 8229981Skarels wait_for_char = 1; 8329532Ssam } 8429532Ssam 8529532Ssam 8629532Ssam /* 8729532Ssam ** Access_with_no_trailer is used to perform controller functions which 8829532Ssam ** require no data movement. 8929532Ssam */ 9029532Ssam 9129532Ssam access_with_no_trailer(function, wait_time) 9229532Ssam int function, wait_time; 9329532Ssam { 9429532Ssam dcb.opcode = function; /* command */ 9531318Ssam dcb.intflg = DCBINT_NONE; 9631318Ssam dcb.nxtdcb = (struct dcb *)0; /* end of chain */ 9729532Ssam dcb.operrsta = 0; 98*32662Skarels dcb.devselect = (function == VDOP_START) ? 0 : 99*32662Skarels ((char)cur.drive | lab->d_devflags); 10029532Ssam dcb.trailcnt = (char)0; 10131318Ssam mdcb.mdcb_head = &dcb; 10231318Ssam mdcb.mdcb_status = 0; 103*32662Skarels VDGO(C_INFO->addr, (u_long)&mdcb, C_INFO->type); 10429532Ssam poll(wait_time); 10529532Ssam if(vdtimeout <= 0) { 10629532Ssam printf(" during startup operation.\n"); 10729532Ssam _longjmp(abort_environ, 1); 10829532Ssam } 10929532Ssam return dcb.operrsta; 11029532Ssam } 11129532Ssam 112*32662Skarels vread(sn, buf, seccnt) 113*32662Skarels int sn, seccnt; 114*32662Skarels char *buf; 115*32662Skarels { 116*32662Skarels return (vrdwr(sn, buf, seccnt, VDOP_RD)); 117*32662Skarels } 11829532Ssam 119*32662Skarels vwrite(sn, buf, seccnt) 120*32662Skarels int sn, seccnt; 121*32662Skarels char *buf; 122*32662Skarels { 123*32662Skarels return (vrdwr(sn, buf, seccnt, VDOP_WD)); 124*32662Skarels } 125*32662Skarels 126*32662Skarels vrdwr(sn, buf, seccnt, op) 127*32662Skarels int sn, seccnt, op; 128*32662Skarels char *buf; 129*32662Skarels { 130*32662Skarels dskadr dskaddr; 131*32662Skarels 132*32662Skarels dskaddr.cylinder = sn / lab->d_secpercyl; 133*32662Skarels sn %= lab->d_secpercyl; 134*32662Skarels dskaddr.track = sn / lab->d_nsectors; 135*32662Skarels dskaddr.sector = sn % lab->d_nsectors; 136*32662Skarels if (access_dsk(buf, &dskaddr, op, seccnt, 1) & DCBS_HARD) 137*32662Skarels return (0); 138*32662Skarels return (seccnt); 139*32662Skarels } 140*32662Skarels 14129532Ssam /* 14229532Ssam ** access_dsk is used by other routines to do reads and writes to the disk. 14329532Ssam ** The status of the read / write is returned to the caller for processing. 14429532Ssam */ 14529532Ssam 14629532Ssam access_dsk(buf, dskaddr, func, count, wait) 14729532Ssam char *buf; 14829532Ssam dskadr *dskaddr; 14929532Ssam int func, count, wait; 15029532Ssam { 15129532Ssam cur.daddr.cylinder = dskaddr->cylinder; 15229532Ssam cur.daddr.track = dskaddr->track; 15329981Skarels wait_for_char = 0; 15429532Ssam dcb.opcode = func; /* format sector command */ 15531318Ssam dcb.intflg = DCBINT_NONE; 15631318Ssam dcb.nxtdcb = (struct dcb *)0; /* end of chain */ 15729532Ssam dcb.operrsta = 0; 158*32662Skarels dcb.devselect = (char)cur.drive | lab->d_devflags; 15931318Ssam if(func == VDOP_SEEK) { 16031318Ssam dcb.trailcnt = (char)(sizeof(struct trseek) / sizeof(long)); 16129532Ssam dcb.trail.sktrail.skaddr.cylinder = dskaddr->cylinder; 16229532Ssam dcb.trail.sktrail.skaddr.track = dskaddr->track; 16329532Ssam dcb.trail.sktrail.skaddr.sector = dskaddr->sector; 164*32662Skarels } else { 16531318Ssam dcb.trailcnt = (char)(sizeof(struct trrw) / sizeof(long)); 16631318Ssam dcb.trail.rwtrail.memadr = (u_long)buf; 167*32662Skarels dcb.trail.rwtrail.wcount=count*(lab->d_secsize/sizeof(short)); 16829532Ssam dcb.trail.rwtrail.disk.cylinder = dskaddr->cylinder; 16929532Ssam dcb.trail.rwtrail.disk.track = dskaddr->track; 17029532Ssam dcb.trail.rwtrail.disk.sector = dskaddr->sector; 17129532Ssam } 17231318Ssam mdcb.mdcb_head = &dcb; 17331318Ssam mdcb.mdcb_status = 0; 174*32662Skarels VDGO(C_INFO->addr, (u_long)&mdcb, C_INFO->type); 17529532Ssam if(wait) { 176*32662Skarels poll(10); 17729532Ssam if(vdtimeout <= 0) { 17829532Ssam printf(" in access_dsk.\n"); 17929532Ssam _longjmp(abort_environ, 1); 18029532Ssam } 18129532Ssam } 18229981Skarels wait_for_char = 1; 18329532Ssam return dcb.operrsta; 18429532Ssam } 18529532Ssam 18629532Ssam 18729532Ssam /* 18829532Ssam ** Spin_up_drive starts the drives on a controller and waits around for 18929532Ssam ** the drive to spin up if it is not already spinning. 19029532Ssam */ 19129532Ssam 19229532Ssam spin_up_drive() 19329532Ssam { 194*32662Skarels register struct vddevice *addr = C_INFO->addr; 195*32662Skarels 196*32662Skarels VDRESET(addr, C_INFO->type); 197*32662Skarels if(C_INFO->type == VDTYPE_SMDE) { 198*32662Skarels addr->vdcsr = 0; 199*32662Skarels addr->vdtcf_mdcb = AM_ENPDA; 200*32662Skarels addr->vdtcf_dcb = AM_ENPDA; 201*32662Skarels addr->vdtcf_trail = AM_ENPDA; 202*32662Skarels addr->vdtcf_data = AM_ENPDA; 203*32662Skarels addr->vdccf = CCF_SEN | 0x8 | CCF_STS | 20429532Ssam XMD_32BIT | BSZ_16WRD | CCF_ERR | 20529532Ssam CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE; 20629532Ssam } 20731318Ssam access_with_no_trailer(VDOP_INIT, 10); 20831318Ssam access_with_no_trailer(VDOP_DIAG, 20); 20929532Ssam configure_drive(0); 21029532Ssam } 21129532Ssam 21229532Ssam /* 21329532Ssam ** Configure_drive tells the controller what kind of drive is attached 21429532Ssam ** on a particular line. 21529532Ssam */ 21629532Ssam 21729532Ssam configure_drive(pass) 21829532Ssam int pass; 21929532Ssam { 220*32662Skarels register struct vddevice *addr = C_INFO->addr; 221*32662Skarels register i; 222*32662Skarels 223*32662Skarels top: 22431318Ssam dcb.opcode = VDOP_CONFIG; /* command */ 22531318Ssam dcb.intflg = DCBINT_NONE; 22631318Ssam dcb.nxtdcb = (struct dcb *)0; /* end of chain */ 227*32662Skarels dcb.operrsta = 0; 228*32662Skarels dcb.devselect = cur.drive | lab->d_devflags; 229*32662Skarels dcb.trail.rstrail.ncyl = lab->d_ncylinders; 230*32662Skarels dcb.trail.rstrail.nsurfaces = lab->d_ntracks; 231*32662Skarels if(C_INFO->type == VDTYPE_VDDC) 23229532Ssam dcb.trailcnt = (char)2; 23329532Ssam else { 234*32662Skarels dcb.trailcnt = sizeof (struct treset)/sizeof (long); 235*32662Skarels dcb.trail.rstrail.nsectors = lab->d_nsectors; 236*32662Skarels dcb.trail.rstrail.slip_sec = lab->d_sparespertrack; 237*32662Skarels dcb.trail.rstrail.recovery = VDRF_NONE; 238*32662Skarels addr->vdcylskew = lab->d_cylskew; 239*32662Skarels addr->vdtrackskew = lab->d_trackskew; 240*32662Skarels /* 241*32662Skarels addr->vdsecsize = lab->d_secsize/sizeof(short); 242*32662Skarels */ 24329532Ssam } 244*32662Skarels printf("devsel %x, ncyl %d, ntrk %d, nsec %d, slip %d, cylskew %d, trackskew %d, secsize %d\n", dcb.devselect, dcb.trail.rstrail.ncyl, dcb.trail.rstrail.nsurfaces, dcb.trail.rstrail.nsectors, dcb.trail.rstrail.slip_sec, lab->d_cylskew, lab->d_trackskew, lab->d_secsize); 24531318Ssam mdcb.mdcb_head = &dcb; 24631318Ssam mdcb.mdcb_status = 0; 247*32662Skarels VDGO(addr, (u_long)&mdcb, C_INFO->type); 24829532Ssam poll(5); 24929532Ssam if(vdtimeout <= 0) { 25029532Ssam printf(" during drive configuration.\n"); 251*32662Skarels goto bad; 25229532Ssam } 253*32662Skarels if(dcb.operrsta & VDERR_HARD) { 254*32662Skarels if (C_INFO->type == VDTYPE_SMDE) { 255*32662Skarels if (lab->d_devflags == 0) { 256*32662Skarels lab->d_devflags = VD_ESDI; 257*32662Skarels goto top; 258*32662Skarels } 259*32662Skarels #ifdef notdef 260*32662Skarels printf("vdstatus %x\n", addr->vdstatus[cur.drive]); 261*32662Skarels if ((addr->vdstatus[cur.drive] & STA_US) == 0) { 262*32662Skarels printf("Drive not present\n\n"); 263*32662Skarels goto bad; 264*32662Skarels } 265*32662Skarels #endif 266*32662Skarels } 267*32662Skarels if ((dcb.operrsta & (DCBS_OCYL|DCBS_NRDY)) == 0) { 268*32662Skarels printf("drive config error\n"); 269*32662Skarels goto bad; 270*32662Skarels } 27129532Ssam if(pass) { 27229532Ssam printf("\nDrive failed to start!\n\n"); 273*32662Skarels goto bad; 27429532Ssam } 27529981Skarels printf("\ndrive not ready, attempting to spin up..."); 276*32662Skarels access_with_no_trailer(VDOP_START, 62); 277*32662Skarels for (i = 0; i < 620; i++) { 278*32662Skarels if (C_INFO->type == VDTYPE_SMDE && 279*32662Skarels addr->vdstatus[cur.drive] & STA_UR) 280*32662Skarels break; 281*32662Skarels DELAY(100000); 282*32662Skarels } 28329981Skarels printf(" retrying drive configuration\n"); 284*32662Skarels pass++; 285*32662Skarels lab->d_devflags = 0; 286*32662Skarels goto top; 28729532Ssam } 288*32662Skarels D_INFO->alive = u_true; 289*32662Skarels return; 290*32662Skarels bad: 291*32662Skarels D_INFO->alive = u_false; 292*32662Skarels _longjmp(abort_environ, -1); 29329532Ssam } 29429532Ssam 29529532Ssam 29629532Ssam /* 29729532Ssam ** data_ok checks an error status word for bit patterns 29829532Ssam ** associated with error conditions from the VDDC controller. If a hardware 29929532Ssam ** error is present then the problem is reported on the console and the program 30029532Ssam ** is halted. If a data error is present the a zero is returned. 30129532Ssam ** If everything is OK then a 1 is returned. 30229532Ssam */ 30329532Ssam 30429532Ssam data_ok() 30529532Ssam { 30629532Ssam register int status = dcb.operrsta; 30729532Ssam 30829532Ssam if(status & HARD_ERROR){ 30931318Ssam if(status & DCBS_NRDY) 31029532Ssam printf("\nDrive is not ready!"); 31131318Ssam else if(status & DCBS_IVA) 31229532Ssam printf("\nInvalid disk address issued!"); 31331318Ssam else if(status & DCBS_NEM) 31429532Ssam printf("\nNon-existent memory error!"); 31531318Ssam else if(status & DCBS_DPE) 31629532Ssam printf("\nMain memory parity error!"); 31731318Ssam else if(status & DCBS_OAB) 31829532Ssam printf("\nCPU aborted operation!"); 31931318Ssam else if(status & DCBS_WPT) 32029532Ssam printf("\nDrive is write protected!"); 32131318Ssam else if(status & DCBS_SKI) 32229532Ssam printf("\nDisk seek error!"); 32331318Ssam else if(status & DCBS_CHE) 32429532Ssam printf("\nController hardware error!"); 32529532Ssam else 32629532Ssam printf("\nNot on cylinder error!"); 32729532Ssam printf(" Status = 0x%lx", status); 328*32662Skarels if(C_INFO->type == VDTYPE_SMDE) 32929532Ssam printf(" Error code = 0x%x", dcb.err_code & 0xff); 33029532Ssam printf("\n"); 33129532Ssam printf("cylinder = %d, track = %d,", dcb.err_cyl, dcb.err_trk); 33229532Ssam printf(" sector = %d, op = 0x%x\n", dcb.err_sec, dcb.opcode); 33329532Ssam reset_controller(); 33429532Ssam dcb.operrsta &= HEADER_ERROR; 33529532Ssam } 33629532Ssam return (int)(!(status & (DATA_ERROR | HEADER_ERROR))); 33729532Ssam } 33829532Ssam 33929532Ssam 34029532Ssam /* 34129532Ssam ** 34229532Ssam */ 34329532Ssam 34429532Ssam reset_controller() 34529532Ssam { 34629532Ssam printf("Resetting controller. Please wait...\n"); 34729532Ssam spin_up_drive(); 34829532Ssam printf("Controller was reset successfully.\n"); 34929532Ssam } 35029532Ssam 35129532Ssam /* 35229532Ssam ** 35329532Ssam */ 35429532Ssam 35529532Ssam static int indent_count; 35629532Ssam 35729532Ssam 35829532Ssam /* 35929532Ssam ** 36029532Ssam */ 36129532Ssam 36229532Ssam indent() 36329532Ssam { 36429532Ssam indent_count += 2; 36529532Ssam } 36629532Ssam 36729532Ssam 36829532Ssam /* 36929532Ssam ** 37029532Ssam */ 37129532Ssam 37229532Ssam exdent(count) 37329532Ssam int count; 37429532Ssam { 37529532Ssam if(count == -1) 37629532Ssam indent_count = 0; 37729532Ssam else 37829532Ssam indent_count -= count * 2; 37929532Ssam if(indent_count < 0) 38029532Ssam indent_count = 0; 38129532Ssam } 38229532Ssam 38329532Ssam 38429532Ssam /* 38529532Ssam ** 38629532Ssam */ 38729532Ssam /*VARARGS1*/ 38829532Ssam print(par0, par1, par2, par3, par4, par5, par6) 38929532Ssam char *par0, *par1, *par2, *par3, *par4, *par5, *par6; 39029532Ssam { 39129532Ssam register int count = indent_count; 39229532Ssam 39329532Ssam while(count--) 39429532Ssam printf(" "); 39529532Ssam printf(par0, par1, par2, par3, par4, par5, par6); 39629532Ssam DELAY((strlen(par0) + 20) * 9000); 39729532Ssam } 398