129532Ssam #ifndef lint
2*34667Skarels static char sccsid[] = "@(#)io.c 1.7 (Berkeley/CCI) 06/07/88";
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
poll(wait)2629532Ssam poll(wait)
2729532Ssam int wait;
2829532Ssam {
2932662Skarels register struct vddevice *addr = C_INFO->addr;
3029532Ssam int tokens[10];
3129532Ssam
32*34667Skarels if (kill_processes == false)
33*34667Skarels wait_for_char = 0;
3432662Skarels vdtimeout = wait*1000;
3532662Skarels for (;;) {
3632662Skarels uncache(&(dcb.operrsta));
3732662Skarels if (dcb.operrsta & (DCBS_DONE | DCBS_ABORT))
3832662Skarels break;
39*34667Skarels if (kill_processes == false && input()) {
4029532Ssam get_text_cmd(nul_table, tokens);
41*34667Skarels if (kill_processes == true) {
4229532Ssam indent();
4329532Ssam print(clean_up);
4429532Ssam exdent(1);
4529532Ssam }
4629532Ssam }
4732662Skarels if (vdtimeout-- <= 0) {
4832662Skarels if(C_INFO->type == VDTYPE_VDDC)
4929532Ssam printf("\nVDDC");
5029532Ssam else
5129532Ssam printf("\nSMD-E");
5229532Ssam printf(": Controller timeout");
5332662Skarels abort:
5432662Skarels VDABORT(addr, C_INFO->type);
5529532Ssam DELAY(30000);
5629532Ssam break;
5729532Ssam }
5832662Skarels DELAY(1000);
5929532Ssam }
6032662Skarels if ((vdtimeout > 0)) {
6132662Skarels if (C_INFO->type == VDTYPE_SMDE) {
6232662Skarels for (;;) {
6332662Skarels uncache(&(addr->vdcsr));
6432662Skarels if ((addr->vdcsr & CS_GO) == 0)
6532662Skarels break;
6632662Skarels DELAY(1000);
6732662Skarels if (vdtimeout-- <= 0) {
6832662Skarels printf("\nSMD-E timed out clearing GO");
6932662Skarels goto abort;
7032662Skarels }
7129532Ssam }
7232662Skarels DELAY(300);
7329532Ssam }
7429532Ssam DELAY(500);
7529532Ssam }
7632662Skarels DELAY(200);
7731318Ssam if((dcb.opcode == VDOP_RD) || (dcb.opcode == VDOP_RDRAW))
7829981Skarels mtpr(PADC, 0);
7929532Ssam uncache(&(dcb.operrsta));
8029981Skarels uncache(&(dcb.err_code));
8129981Skarels wait_for_char = 1;
8229532Ssam }
8329532Ssam
8429532Ssam
8529532Ssam /*
8629532Ssam ** Access_with_no_trailer is used to perform controller functions which
8729532Ssam ** require no data movement.
8829532Ssam */
8929532Ssam
access_with_no_trailer(function,wait_time)9029532Ssam access_with_no_trailer(function, wait_time)
9129532Ssam int function, wait_time;
9229532Ssam {
9329532Ssam dcb.opcode = function; /* command */
9431318Ssam dcb.intflg = DCBINT_NONE;
9531318Ssam dcb.nxtdcb = (struct dcb *)0; /* end of chain */
9629532Ssam dcb.operrsta = 0;
9732662Skarels dcb.devselect = (function == VDOP_START) ? 0 :
9832662Skarels ((char)cur.drive | lab->d_devflags);
9929532Ssam dcb.trailcnt = (char)0;
10031318Ssam mdcb.mdcb_head = &dcb;
10131318Ssam mdcb.mdcb_status = 0;
10232662Skarels VDGO(C_INFO->addr, (u_long)&mdcb, C_INFO->type);
10329532Ssam poll(wait_time);
10429532Ssam if(vdtimeout <= 0) {
10529532Ssam printf(" during startup operation.\n");
10629532Ssam _longjmp(abort_environ, 1);
10729532Ssam }
10829532Ssam return dcb.operrsta;
10929532Ssam }
11029532Ssam
vread(sn,buf,seccnt)11132662Skarels vread(sn, buf, seccnt)
11232662Skarels int sn, seccnt;
11332662Skarels char *buf;
11432662Skarels {
115*34667Skarels int ret;
116*34667Skarels
117*34667Skarels ret = vrdwr(sn, buf, seccnt, VDOP_RD);
118*34667Skarels if (ret == 0)
119*34667Skarels vd_error("read");
120*34667Skarels return (ret);
12132662Skarels }
12229532Ssam
vwrite(sn,buf,seccnt)12332662Skarels vwrite(sn, buf, seccnt)
12432662Skarels int sn, seccnt;
12532662Skarels char *buf;
12632662Skarels {
127*34667Skarels int ret;
12832662Skarels
129*34667Skarels ret = vrdwr(sn, buf, seccnt, VDOP_WD);
130*34667Skarels if (ret == 0)
131*34667Skarels vd_error("write");
132*34667Skarels return (ret);
133*34667Skarels };
134*34667Skarels
vrdwr(sn,buf,seccnt,op)13532662Skarels vrdwr(sn, buf, seccnt, op)
13632662Skarels int sn, seccnt, op;
13732662Skarels char *buf;
13832662Skarels {
13932662Skarels dskadr dskaddr;
14032662Skarels
14132662Skarels dskaddr.cylinder = sn / lab->d_secpercyl;
14232662Skarels sn %= lab->d_secpercyl;
14332662Skarels dskaddr.track = sn / lab->d_nsectors;
14432662Skarels dskaddr.sector = sn % lab->d_nsectors;
14532662Skarels if (access_dsk(buf, &dskaddr, op, seccnt, 1) & DCBS_HARD)
14632662Skarels return (0);
14732662Skarels return (seccnt);
14832662Skarels }
14932662Skarels
15029532Ssam /*
15129532Ssam ** access_dsk is used by other routines to do reads and writes to the disk.
15229532Ssam ** The status of the read / write is returned to the caller for processing.
15329532Ssam */
15429532Ssam
access_dsk(buf,dskaddr,func,count,wait)15529532Ssam access_dsk(buf, dskaddr, func, count, wait)
15629532Ssam char *buf;
15729532Ssam dskadr *dskaddr;
15829532Ssam int func, count, wait;
15929532Ssam {
16029532Ssam cur.daddr.cylinder = dskaddr->cylinder;
16129532Ssam cur.daddr.track = dskaddr->track;
16229981Skarels wait_for_char = 0;
16329532Ssam dcb.opcode = func; /* format sector command */
16431318Ssam dcb.intflg = DCBINT_NONE;
16531318Ssam dcb.nxtdcb = (struct dcb *)0; /* end of chain */
16629532Ssam dcb.operrsta = 0;
16732662Skarels dcb.devselect = (char)cur.drive | lab->d_devflags;
16831318Ssam if(func == VDOP_SEEK) {
16931318Ssam dcb.trailcnt = (char)(sizeof(struct trseek) / sizeof(long));
17029532Ssam dcb.trail.sktrail.skaddr.cylinder = dskaddr->cylinder;
17129532Ssam dcb.trail.sktrail.skaddr.track = dskaddr->track;
17229532Ssam dcb.trail.sktrail.skaddr.sector = dskaddr->sector;
17332662Skarels } else {
17431318Ssam dcb.trailcnt = (char)(sizeof(struct trrw) / sizeof(long));
17531318Ssam dcb.trail.rwtrail.memadr = (u_long)buf;
17632662Skarels dcb.trail.rwtrail.wcount=count*(lab->d_secsize/sizeof(short));
17729532Ssam dcb.trail.rwtrail.disk.cylinder = dskaddr->cylinder;
17829532Ssam dcb.trail.rwtrail.disk.track = dskaddr->track;
17929532Ssam dcb.trail.rwtrail.disk.sector = dskaddr->sector;
18029532Ssam }
18131318Ssam mdcb.mdcb_head = &dcb;
18231318Ssam mdcb.mdcb_status = 0;
18332662Skarels VDGO(C_INFO->addr, (u_long)&mdcb, C_INFO->type);
18429532Ssam if(wait) {
18532662Skarels poll(10);
18629532Ssam if(vdtimeout <= 0) {
18729532Ssam printf(" in access_dsk.\n");
18829532Ssam _longjmp(abort_environ, 1);
18929532Ssam }
19029532Ssam }
19129981Skarels wait_for_char = 1;
19229532Ssam return dcb.operrsta;
19329532Ssam }
19429532Ssam
19529532Ssam
19629532Ssam /*
19729532Ssam ** Spin_up_drive starts the drives on a controller and waits around for
19829532Ssam ** the drive to spin up if it is not already spinning.
19929532Ssam */
20029532Ssam
spin_up_drive()20129532Ssam spin_up_drive()
20229532Ssam {
20332662Skarels register struct vddevice *addr = C_INFO->addr;
20432662Skarels
20532662Skarels VDRESET(addr, C_INFO->type);
20632662Skarels if(C_INFO->type == VDTYPE_SMDE) {
20732662Skarels addr->vdcsr = 0;
20832662Skarels addr->vdtcf_mdcb = AM_ENPDA;
20932662Skarels addr->vdtcf_dcb = AM_ENPDA;
21032662Skarels addr->vdtcf_trail = AM_ENPDA;
21132662Skarels addr->vdtcf_data = AM_ENPDA;
21232662Skarels addr->vdccf = CCF_SEN | 0x8 | CCF_STS |
21329532Ssam XMD_32BIT | BSZ_16WRD | CCF_ERR |
21429532Ssam CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE;
21529532Ssam }
21631318Ssam access_with_no_trailer(VDOP_INIT, 10);
21731318Ssam access_with_no_trailer(VDOP_DIAG, 20);
21829532Ssam configure_drive(0);
21929532Ssam }
22029532Ssam
22129532Ssam /*
22229532Ssam ** Configure_drive tells the controller what kind of drive is attached
22329532Ssam ** on a particular line.
22429532Ssam */
22529532Ssam
configure_drive(pass)22629532Ssam configure_drive(pass)
22729532Ssam int pass;
22829532Ssam {
22932662Skarels register struct vddevice *addr = C_INFO->addr;
23032662Skarels register i;
23132662Skarels
23232662Skarels top:
23331318Ssam dcb.opcode = VDOP_CONFIG; /* command */
23431318Ssam dcb.intflg = DCBINT_NONE;
23531318Ssam dcb.nxtdcb = (struct dcb *)0; /* end of chain */
23632662Skarels dcb.operrsta = 0;
23732662Skarels dcb.devselect = cur.drive | lab->d_devflags;
23832662Skarels dcb.trail.rstrail.ncyl = lab->d_ncylinders;
23932662Skarels dcb.trail.rstrail.nsurfaces = lab->d_ntracks;
24032662Skarels if(C_INFO->type == VDTYPE_VDDC)
24129532Ssam dcb.trailcnt = (char)2;
24229532Ssam else {
24332662Skarels dcb.trailcnt = sizeof (struct treset)/sizeof (long);
24432662Skarels dcb.trail.rstrail.nsectors = lab->d_nsectors;
24532662Skarels dcb.trail.rstrail.slip_sec = lab->d_sparespertrack;
24632662Skarels dcb.trail.rstrail.recovery = VDRF_NONE;
24732662Skarels addr->vdcylskew = lab->d_cylskew;
24832662Skarels addr->vdtrackskew = lab->d_trackskew;
24932662Skarels addr->vdsecsize = lab->d_secsize/sizeof(short);
25029532Ssam }
25131318Ssam mdcb.mdcb_head = &dcb;
25231318Ssam mdcb.mdcb_status = 0;
25332662Skarels VDGO(addr, (u_long)&mdcb, C_INFO->type);
25429532Ssam poll(5);
25529532Ssam if(vdtimeout <= 0) {
25629532Ssam printf(" during drive configuration.\n");
25732662Skarels goto bad;
25829532Ssam }
25932662Skarels if(dcb.operrsta & VDERR_HARD) {
26032662Skarels if (C_INFO->type == VDTYPE_SMDE) {
26132662Skarels if (lab->d_devflags == 0) {
26232662Skarels lab->d_devflags = VD_ESDI;
26332662Skarels goto top;
26432662Skarels }
26532662Skarels #ifdef notdef
26632662Skarels printf("vdstatus %x\n", addr->vdstatus[cur.drive]);
26732662Skarels if ((addr->vdstatus[cur.drive] & STA_US) == 0) {
26832662Skarels printf("Drive not present\n\n");
26932662Skarels goto bad;
27032662Skarels }
27132662Skarels #endif
27232662Skarels }
27332662Skarels if ((dcb.operrsta & (DCBS_OCYL|DCBS_NRDY)) == 0) {
27432662Skarels printf("drive config error\n");
27532662Skarels goto bad;
27632662Skarels }
27729532Ssam if(pass) {
27829532Ssam printf("\nDrive failed to start!\n\n");
27932662Skarels goto bad;
28029532Ssam }
28129981Skarels printf("\ndrive not ready, attempting to spin up...");
28232662Skarels access_with_no_trailer(VDOP_START, 62);
28332662Skarels for (i = 0; i < 620; i++) {
28432662Skarels if (C_INFO->type == VDTYPE_SMDE &&
28532662Skarels addr->vdstatus[cur.drive] & STA_UR)
28632662Skarels break;
28732662Skarels DELAY(100000);
28832662Skarels }
28929981Skarels printf(" retrying drive configuration\n");
29032662Skarels pass++;
29132662Skarels lab->d_devflags = 0;
29232662Skarels goto top;
29329532Ssam }
29432662Skarels D_INFO->alive = u_true;
29532662Skarels return;
29632662Skarels bad:
29732662Skarels D_INFO->alive = u_false;
29832662Skarels _longjmp(abort_environ, -1);
29929532Ssam }
30029532Ssam
30129532Ssam
30229532Ssam /*
30329532Ssam ** data_ok checks an error status word for bit patterns
30429532Ssam ** associated with error conditions from the VDDC controller. If a hardware
30534557Skarels ** error is present then the problem is reported on the console.
30634557Skarels ** If a data error is present the a zero is returned.
30729532Ssam ** If everything is OK then a 1 is returned.
30829532Ssam */
30929532Ssam
data_ok()31029532Ssam data_ok()
31129532Ssam {
31229532Ssam register int status = dcb.operrsta;
31329532Ssam
31429532Ssam if(status & HARD_ERROR){
31534557Skarels vd_error("data transfer");
31634557Skarels printf(" op = 0x%x\n", dcb.opcode);
31729532Ssam reset_controller();
31829532Ssam dcb.operrsta &= HEADER_ERROR;
31929532Ssam }
32029532Ssam return (int)(!(status & (DATA_ERROR | HEADER_ERROR)));
32129532Ssam }
32229532Ssam
vd_error(s)32334557Skarels vd_error(s)
32434557Skarels char *s;
32534557Skarels {
32634557Skarels register int status = dcb.operrsta;
32729532Ssam
328*34667Skarels print("%s error at sector %d (cyl %d trk %d sect %d),\n",
329*34667Skarels s, to_sector(cur.daddr), dcb.err_cyl & 0xfff, dcb.err_trk,
33034557Skarels dcb.err_sec);
33134557Skarels print(" status=%b", dcb.operrsta, VDERRBITS);
33234557Skarels if (C_INFO->type == VDTYPE_SMDE)
33334557Skarels printf(", ecode=0x%x", dcb.err_code);
334*34667Skarels printf(".\n");
33534557Skarels }
33634557Skarels
33734557Skarels
33829532Ssam /*
33929532Ssam **
34029532Ssam */
34129532Ssam
reset_controller()34229532Ssam reset_controller()
34329532Ssam {
34429532Ssam printf("Resetting controller. Please wait...\n");
34529532Ssam spin_up_drive();
34629532Ssam printf("Controller was reset successfully.\n");
34729532Ssam }
34829532Ssam
34929532Ssam /*
35029532Ssam **
35129532Ssam */
35229532Ssam
35329532Ssam static int indent_count;
35429532Ssam
35529532Ssam
35629532Ssam /*
35729532Ssam **
35829532Ssam */
35929532Ssam
indent()36029532Ssam indent()
36129532Ssam {
36229532Ssam indent_count += 2;
36329532Ssam }
36429532Ssam
36529532Ssam
36629532Ssam /*
36729532Ssam **
36829532Ssam */
36929532Ssam
exdent(count)37029532Ssam exdent(count)
37129532Ssam int count;
37229532Ssam {
37329532Ssam if(count == -1)
37429532Ssam indent_count = 0;
37529532Ssam else
37629532Ssam indent_count -= count * 2;
37729532Ssam if(indent_count < 0)
37829532Ssam indent_count = 0;
37929532Ssam }
38029532Ssam
38129532Ssam
38229532Ssam /*
38329532Ssam **
38429532Ssam */
38529532Ssam /*VARARGS1*/
print(par0,par1,par2,par3,par4,par5,par6)38629532Ssam print(par0, par1, par2, par3, par4, par5, par6)
38729532Ssam char *par0, *par1, *par2, *par3, *par4, *par5, *par6;
38829532Ssam {
38929532Ssam register int count = indent_count;
39029532Ssam
39129532Ssam while(count--)
39229532Ssam printf(" ");
39329532Ssam printf(par0, par1, par2, par3, par4, par5, par6);
39429532Ssam DELAY((strlen(par0) + 20) * 9000);
39529532Ssam }
396