|
|
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.