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