|
|
1.1 root 1: #include "fsd.h"
2: #if NVD > 0
3:
4:
5: /*
6: ** VDDC Driver - Versabus to SMD direct interface version.
7: ** Written for TAHOE vmunix, CCI-WDC 9/1/83.
8: */
9:
10: #include "../h/param.h"
11: #include "../h/buf.h"
12: #include "../h/cmap.h"
13: #include "../h/conf.h"
14: #include "../h/dir.h"
15: #include "../h/dk.h"
16: #include "../h/map.h"
17: #include "../machine/mtpr.h"
18: #include "../machine/pte.h"
19: #include "../h/systm.h"
20: #include "../vba/vbavar.h"
21: #include "../h/user.h"
22: #include "../h/vmmac.h"
23: #include "../h/proc.h"
24: #include "../h/uio.h"
25: #define VDGENDATA
26: #include "../vba/vddc.h"
27: #undef VDGENDATA
28:
29:
30: #define MAX_BLOCKSIZE MAXBPTE * NBPG
31: #define DUMPSIZE 64 /* Up to 64k at a time - controller limit */
32:
33: /*
34: ** Layout of minor number assignments for the VDDC devices.
35: **
36: ** 1
37: ** 5 3 2 0
38: ** +---------------------------+-----+
39: ** | Unit number | FLS |
40: ** +---------------------------+-----+
41: ** | |_____ File system # ( 0-7 )
42: ** |__________ Unit # in the system
43: */
44:
45: #define VDUNIT(x) (minor(x) >> 3)
46: #define FILSYS(x) (minor(x) & 0x07)
47: #define PHYS(x) (vtoph(0, (int)(x)))
48: #define TRUE 1
49: #define FALSE 0
50: #define NOERROR 0
51:
52: #define CTLR_ERROR 1
53: #define DRIVE_ERROR 2
54: #define HARD_DATA_ERROR 3
55: #define SOFT_DATA_ERROR 4
56:
57: #define b_cylin b_resid
58: #define b_daddr b_error
59:
60: /*
61: **
62: */
63:
64: struct vba_ctlr *vdminfo[NVD];
65:
66:
67: /*
68: **
69: */
70:
71: struct vba_device *vddinfo[NFSD];
72:
73:
74: /*
75: **
76: */
77:
78: int vdprobe(); /* See if VDDC is really there */
79: int vdslave(); /* See if drive is really there */
80: int vdattach(); /* Enter a drive in internal tables */
81: int vddgo(); /* Old VAX function, not used. */
82:
83:
84:
85: /*
86: **
87: */
88:
89: struct vba_driver vddriver = {
90: vdprobe, vdslave, vdattach, vddgo, vddcaddr,
91: "", vddinfo, "", vdminfo
92: };
93:
94:
95: /*
96: **
97: */
98:
99: typedef struct {
100: struct buf raw_q_element;
101: short sec_per_blk;
102: short sec_per_cyl;
103: char status;
104: struct buf xfer_queue;
105: int drive_type;
106: fs_tab info;
107: } unit_tab;
108:
109: /*
110: **
111: */
112:
113: typedef struct {
114: char ctlr_type; /* */
115: char *map; /* */
116: char *utl; /* */
117: unsigned cur_slave : 8; /* last active unit number */
118: unsigned int_expected : 1; /* expect an interupt */
119: unsigned ctlr_started : 1; /* start command was issued */
120: unsigned overlap_seeks : 1; /* Should overlap seeks */
121: unsigned off_cylinder : 16; /* Off cylinder bit map */
122: unsigned unit_type[16]; /* type of each slave */
123: long cur_cyl[16]; /* cylinder last selected */
124: long cur_trk[16]; /* track last selected */
125: fmt_mdcb ctlr_mdcb; /* controller mdcb */
126: fmt_dcb ctlr_dcb; /* R/W dcb */
127: fmt_dcb seek_dcb[4]; /* dcbs for overlapped seeks */
128: char rawbuf[MAX_BLOCKSIZE]; /* buffer for raw/swap i/o */
129: } ctlr_tab;
130:
131:
132: /*
133: **
134: */
135:
136: extern char vd0utl[];
137: #if NVD > 1
138: extern char vd1utl[];
139: #if NVD > 2
140: extern char vd2utl[];
141: #if NVD > 3
142: extern char vd3utl[];
143: #endif
144: #endif
145: #endif
146:
147:
148: /*
149: **
150: */
151:
152: ctlr_tab vdctlr_info[NVD] = {
153: {UNKNOWN, (char *)VD0map, vd0utl, 0, FALSE, FALSE, TRUE, 0,
154: {UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,
155: UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,
156: UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,
157: UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN}}
158: #if NVD > 1
159: ,{UNKNOWN, (char *)VD1map, vd1utl, 0, FALSE, FALSE, TRUE, 0,
160: {UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,
161: UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,
162: UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,
163: UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN}}
164: #if NVD > 2
165: ,{UNKNOWN, (char *)VD2map, vd2utl, 0, FALSE, FALSE, TRUE, 0,
166: {UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,
167: UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,
168: UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,
169: UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN}}
170: #if NVD > 3
171: ,{UNKNOWN, (char *)VD3map, vd3utl, 0, FALSE, FALSE, TRUE, 0,
172: {UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,
173: UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,
174: UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,
175: UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN}}
176: #endif
177: #endif
178: #endif
179: };
180:
181:
182: /*
183: **
184: */
185:
186: unit_tab vdunit_info[NFSD];
187:
188:
189: /*
190: ** See if the controller is really there.
191: ** if TRUE - initialize the controller.
192: */
193:
194: vdprobe(ctlr_addr)
195: cdr *ctlr_addr;
196: {
197: if(!badaddr(ctlr_addr, 2)) {
198: ctlr_addr->cdr_reset = 0xffffffff;
199: DELAY(1000000);
200: if(ctlr_addr->cdr_reset != 0xffffffff) {
201: vddriver.ud_mname = "VSMD Controller #";
202: DELAY(1000000);
203: }
204: else {
205: vddriver.ud_mname = "SMD/E Controller #";
206: ctlr_addr->cdr_reserved = 0x0;
207: DELAY(3000000);
208: }
209: return TRUE;
210: }
211: return FALSE; /* no controller */
212: }
213:
214:
215: /*
216: ** See if a drive is really there
217: ** Try to Reset/Configure the drive, then test its status.
218: */
219:
220: vdslave(vba_dev_info, ctlr_addr)
221: register struct vba_device *vba_dev_info;
222: register cdr *ctlr_addr;
223: {
224: register int ctlr = vba_dev_info->ui_ctlr;
225: register ctlr_tab *c_info = &vdctlr_info[ctlr];
226: register int unit = vba_dev_info->ui_unit;
227: register unit_tab *u_info = &vdunit_info[unit];
228: register int slave = vba_dev_info->ui_slave;
229: register int type;
230: register fmt_mdcb *mdcb = &c_info->ctlr_mdcb;
231: register fmt_dcb *dcb = &c_info->ctlr_dcb;
232:
233: if(c_info->ctlr_type == UNKNOWN) {
234: ctlr_addr->cdr_reset = 0xffffffff;
235: DELAY(1000000);
236: if(ctlr_addr->cdr_reset != 0xffffffff) {
237: c_info->ctlr_type = SMDCTLR;
238: c_info->overlap_seeks = FALSE;
239: DELAY(1000000);
240: }
241: else {
242: c_info->overlap_seeks = TRUE;
243: c_info->ctlr_type = SMD_ECTLR;
244: ctlr_addr->cdr_reserved = 0x0;
245: DELAY(3000000);
246: ctlr_addr->cdr_csr = 0;
247: ctlr_addr->mdcb_tcf = AM_ENPDA;
248: ctlr_addr->dcb_tcf = AM_ENPDA;
249: ctlr_addr->trail_tcf = AM_ENPDA;
250: ctlr_addr->data_tcf = AM_ENPDA;
251: ctlr_addr->cdr_ccf = CCF_STS | XMD_32BIT | BSZ_16WRD |
252: CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE | CCF_ERR;
253: }
254: if(vdaccess_with_no_trailer(ctlr_addr,ctlr,slave,INIT,10) &
255: HRDERR) {
256: printf("\nVDDC: Controller #%d init error.\n", ctlr);
257: return FALSE;
258: }
259: if(vdaccess_with_no_trailer(ctlr_addr,ctlr,slave,DIAG,10) &
260: HRDERR) {
261: printf("\nVDDC: Controller #%d diagnostic error.\n",ctlr);
262: return FALSE;
263: }
264: }
265: /*
266: * Seek on all drive types starting from the largest one.
267: * a successful seek to the last sector/cylinder/track verifies
268: * the drive type connected to this port.
269: */
270: for (type = 0; type < nvddrv; type++) {
271: if((c_info->ctlr_type == SMDCTLR) && (vdst[type].nsec != 32))
272: continue;
273: if(vdconfigure_drive(ctlr_addr, ctlr, slave, type, 0)) {
274: dcb->opcode = (short)RD;
275: dcb->intflg = NOINT;
276: dcb->nxtdcb = (fmt_dcb *)0; /* end of chain */
277: dcb->operrsta = 0;
278: dcb->devselect = (char)slave;
279: dcb->trailcnt = (char)(sizeof(trrw) / sizeof(long));
280: dcb->trail.rwtrail.memadr=(char *)PHYS(c_info->rawbuf);
281: dcb->trail.rwtrail.wcount =
282: vdst[type].secsize/sizeof(short);
283: dcb->trail.rwtrail.disk.cylinder = vdst[type].ncyl - 2;
284: dcb->trail.rwtrail.disk.track = vdst[type].ntrak - 1;
285: dcb->trail.rwtrail.disk.sector=vdst[type].nsec - 1;
286: mdcb->firstdcb = (fmt_dcb *)(PHYS(dcb));
287: mdcb->vddcstat = 0;
288: VDDC_ATTENTION(ctlr_addr, (fmt_mdcb *)(PHYS(mdcb)),
289: c_info->ctlr_type);
290: POLLTILLDONE(ctlr_addr, dcb, 60, c_info->ctlr_type);
291: if(vdtimeout <= 0) {
292: printf(" during probe operation.\n");
293: }
294: if(!(dcb->operrsta & HRDERR))
295: break;
296: }
297: else
298: return FALSE;
299: }
300: if (type >= nvddrv) {
301: /*
302: * If reached here, a drive which is not defined in the
303: * 'vdst' tables is connected. Cannot set it's type.
304: */
305: printf("VDDC: Counld not identify controller #%d, drive #%d!\n",
306: ctlr, slave);
307: return FALSE;
308: }
309: u_info->drive_type = type;
310: u_info->info = vdst[type];
311: u_info->sec_per_blk = DEV_BSIZE / u_info->info.secsize;
312: vba_dev_info->ui_type = type;
313: vba_dev_info->ui_dk = TRUE;
314: vddriver.ud_dname = u_info->info.type_name;
315: return TRUE;
316: }
317:
318:
319:
320: /*
321: **
322: */
323:
324: vdconfigure_drive(ctlr_addr, ctlr, slave, type, pass)
325: cdr *ctlr_addr;
326: register int ctlr, slave, type, pass;
327: {
328: register ctlr_tab *c_info = &vdctlr_info[ctlr];
329:
330: c_info->ctlr_dcb.opcode = RSTCFG; /* command */
331: c_info->ctlr_dcb.intflg = NOINT;
332: c_info->ctlr_dcb.nxtdcb = (fmt_dcb *)0; /* end of chain */
333: c_info->ctlr_dcb.operrsta = 0;
334: c_info->ctlr_dcb.devselect = (char)slave;
335: c_info->ctlr_dcb.trail.rstrail.ncyl = vdst[type].ncyl;
336: c_info->ctlr_dcb.trail.rstrail.nsurfaces = vdst[type].ntrak;
337: if(c_info->ctlr_type == SMD_ECTLR) {
338: c_info->ctlr_dcb.trailcnt = (char)4;
339: c_info->ctlr_dcb.trail.rstrail.nsectors = vdst[type].nsec;
340: c_info->ctlr_dcb.trail.rstrail.slip_sec = vdst[type].nslip;
341: }
342: else
343: c_info->ctlr_dcb.trailcnt = (char)2;
344: c_info->ctlr_mdcb.firstdcb = (fmt_dcb *)(PHYS(&c_info->ctlr_dcb));
345: c_info->ctlr_mdcb.vddcstat = 0;
346: VDDC_ATTENTION(ctlr_addr, (fmt_mdcb *)(PHYS(&c_info->ctlr_mdcb)),
347: c_info->ctlr_type);
348: POLLTILLDONE(ctlr_addr, &c_info->ctlr_dcb, 5, c_info->ctlr_type);
349: if(vdtimeout <= 0) {
350: printf(" during drive configuration.\n");
351: return FALSE;
352: }
353: if(c_info->ctlr_dcb.operrsta & HRDERR) {
354: if(!(c_info->ctlr_dcb.operrsta & (NOTCYLERR | DRVNRDY)))
355: printf("\nVDDC: Configuration error.\n");
356: else if(pass == 0) {
357: vdstart_drive(ctlr_addr, ctlr, slave);
358: return vdconfigure_drive(ctlr_addr,ctlr,slave,type,1);
359: }
360: else if(pass == 2)
361: return vdconfigure_drive(ctlr_addr,ctlr,slave,type,3);
362: return FALSE;
363: }
364: return TRUE;
365: }
366:
367:
368: /*
369: **
370: */
371:
372: vdstart_drive(ctlr_addr, ctlr, slave)
373: cdr *ctlr_addr;
374: register int ctlr, slave;
375: {
376: printf("\nVDDC: Attempting to start drive #%d. Please wait...", slave);
377: if(vdctlr_info[ctlr].ctlr_started) {
378: DELAY(5500000);
379: printf("\n");
380: return TRUE;
381: }
382: vdctlr_info[ctlr].ctlr_started = TRUE;
383: if(vdaccess_with_no_trailer(ctlr_addr, ctlr, 0, VDSTART, (slave*6)+62)
384: & HRDERR) {
385: printf("\n");
386: return FALSE;
387: }
388: DELAY((slave * 5500000) + 62000000);
389: printf("\n");
390: return TRUE;
391: }
392:
393:
394: /*
395: **
396: */
397:
398: vdaccess_with_no_trailer(ctlr_addr, ctlr, unit, function, time)
399: register cdr *ctlr_addr;
400: register int ctlr, unit, function, time;
401: {
402: fmt_mdcb *mdcb = &vdctlr_info[ctlr].ctlr_mdcb;
403: fmt_dcb *dcb = &vdctlr_info[ctlr].ctlr_dcb;
404:
405: dcb->opcode = function; /* command */
406: dcb->intflg = NOINT;
407: dcb->nxtdcb = (fmt_dcb *)0; /* end of chain */
408: dcb->operrsta = 0;
409: dcb->devselect = (char)unit;
410: dcb->trailcnt = (char)0;
411: mdcb->firstdcb = (fmt_dcb *)(PHYS(dcb));
412: mdcb->vddcstat = 0;
413: VDDC_ATTENTION(ctlr_addr, (fmt_mdcb *)(PHYS(mdcb)),
414: vdctlr_info[ctlr].ctlr_type);
415: POLLTILLDONE(ctlr_addr, dcb, time, vdctlr_info[ctlr].ctlr_type);
416: if(vdtimeout <= 0) {
417: printf(" during initialization operation.\n");
418: return (DCBCMP | ANYERR | HRDERR | OPABRT);
419: }
420: return dcb->operrsta;
421: }
422:
423:
424: /*
425: **
426: */
427:
428: vdattach(vba_dev_info)
429: struct vba_device *vba_dev_info;
430: {
431: register int unit = vba_dev_info->ui_unit;
432: register unit_tab *u_info = &vdunit_info[unit];
433: register ctlr_tab *c_info = &vdctlr_info[vba_dev_info->ui_ctlr];
434: register struct buf *c_queue = &vba_dev_info->ui_mi->um_tab;
435: register struct buf *u_queue = c_queue->b_forw;
436: register struct buf *start_queue = u_queue;
437: register int type = vba_dev_info->ui_type;
438: register fs_tab *fs = &u_info->info;
439:
440: u_info->info = vdst[type];
441: u_info->sec_per_blk = DEV_BSIZE / u_info->info.secsize;
442: u_info->sec_per_cyl = u_info->info.nsec * u_info->info.ntrak;
443: u_info->xfer_queue.b_dev = vba_dev_info->ui_slave;
444: c_info->unit_type[vba_dev_info->ui_slave] = type;
445: /* load unit into controller's active unit list */
446: if(u_queue == NULL) {
447: c_queue->b_forw = &u_info->xfer_queue;
448: u_info->xfer_queue.b_forw = &u_info->xfer_queue;
449: u_info->xfer_queue.b_back = &u_info->xfer_queue;
450: }
451: else {
452: while(u_queue->b_forw != start_queue)
453: u_queue = u_queue->b_forw;
454: u_info->xfer_queue.b_forw = start_queue;
455: u_info->xfer_queue.b_back = u_queue;
456: u_queue->b_forw = &u_info->xfer_queue;
457: start_queue->b_back = &u_info->xfer_queue;
458: }
459: /*
460: ** (60 / rpm) / (number of sectors per track * (bytes per sector / 2))
461: */
462: dk_mspw[unit] = 120.0 / (fs->rpm * fs->nsec * fs->secsize);
463: }
464:
465:
466: /*
467: ** Historic VAX routine.
468: */
469:
470: vddgo(um)
471: struct vba_ctlr *um;
472: {
473: }
474:
475:
476: /*
477: **
478: */
479:
480: vdstrategy(request)
481: register struct buf *request;
482: {
483: register int unit = VDUNIT(request->b_dev);
484: register struct vba_device *vba_dev_info = vddinfo[unit];
485: register int par = FILSYS(request->b_dev);
486: register unit_tab *u_info = &vdunit_info[unit];
487: register ctlr_tab *c_info;
488: register fs_tab *fs = &u_info->info;
489: register int blks, blk, priority, slave;
490:
491: if((request->b_bcount != 0) && (vba_dev_info != NULL) &&
492: (vba_dev_info->ui_alive != 0)&&(fs->partition[par].par_len != 0)) {
493: slave = vba_dev_info->ui_slave;
494: c_info = &vdctlr_info[vba_dev_info->ui_ctlr];
495: blks = (request->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
496: if(fs->partition[par].par_len < (request->b_blkno + blks)) {
497: blks = fs->partition[par].par_len - request->b_blkno;
498: if(blks > 0)
499: request->b_bcount = blks * DEV_BSIZE;
500: else
501: goto error;
502: }
503: blk = request->b_blkno + fs->partition[par].par_start;
504: blk *= u_info->sec_per_blk;
505: request->b_daddr = (blk / fs->nsec) % fs->ntrak;
506: request->b_cylin = blk / u_info->sec_per_cyl;
507: buf_setup (request, u_info->info.secsize);
508: priority = spl7();
509: if(u_info->xfer_queue.av_forw == NULL)
510: if((request->b_cylin != c_info->cur_cyl[slave]) ||
511: (request->b_daddr)!=(c_info->cur_trk[slave]))
512: c_info->off_cylinder |= 1 << slave;
513: request->b_daddr |= (blk % fs->nsec) << 8;
514: disksort(&u_info->xfer_queue, request);
515: if(!vddinfo[unit]->ui_mi->um_tab.b_active++) {
516: splx(priority);
517: vdstart(vddinfo[unit]->ui_mi);
518: }
519: else splx(priority);
520: return;
521: }
522: error:
523: request->b_flags |= B_ERROR;
524: request->b_error = ENXIO;
525: request->b_resid = request->b_bcount;
526: iodone(request);
527: }
528:
529:
530: /*
531: * Start up a transfer on a drive.
532: */
533: vdstart(controller_info)
534: register struct vba_ctlr *controller_info;
535: {
536: register struct buf *c_queue = &controller_info->um_tab;
537: register struct buf *u_queue = c_queue->b_forw;
538:
539: /* Search for next ready unit */
540: c_queue->b_forw = c_queue->b_forw->b_forw;
541: u_queue = c_queue->b_forw;
542: do {
543: if(u_queue->av_forw != NULL) {
544: c_queue->b_forw = u_queue;
545: vdexecute(controller_info, c_queue, u_queue);
546: return;
547: }
548: u_queue = u_queue->b_forw;
549: } while(u_queue != c_queue->b_forw);
550: }
551:
552:
553: vdload_seeks(c_info, u_queue)
554: register ctlr_tab *c_info;
555: register struct buf *u_queue;
556: {
557: register int unit, slave, seek_count = 0;
558: register fmt_dcb *dcb;
559: register struct buf *request;
560: register int new_cyl;
561: register struct buf *start_queue = u_queue;
562:
563: do {
564: if((request = u_queue->av_forw) != NULL) {
565: unit = VDUNIT(request->b_dev);
566: slave = vddinfo[unit]->ui_slave;
567: if(c_info->off_cylinder & (1 << slave)) {
568: c_info->off_cylinder &= ~(1 << slave);
569: if(c_info->cur_cyl[slave] != request->b_cylin) {
570: c_info->cur_cyl[slave]=request->b_cylin;
571: dk_seek[unit]++;
572: }
573: c_info->cur_trk[slave] = request->b_daddr&0xff;
574: dcb = &c_info->seek_dcb[seek_count++];
575: dcb->opcode = SEEK;
576: dcb->intflg = NOINT | INT_PBA;
577: dcb->operrsta = 0;
578: dcb->devselect = (char)slave;
579: dcb->trailcnt = (char)1;
580: dcb->trail.sktrail.skaddr.cylinder =
581: request->b_cylin;
582: dcb->trail.sktrail.skaddr.track =
583: request->b_daddr & 0xff;
584: dcb->trail.sktrail.skaddr.sector = 0;
585: }
586: }
587: u_queue = u_queue->b_forw;
588: } while((u_queue != start_queue) && (seek_count < 4));
589: return seek_count;
590: }
591:
592:
593: /*
594: **
595: */
596:
597: vdexecute(controller_info, c_queue, u_queue)
598: register struct vba_ctlr *controller_info;
599: register struct buf *c_queue, *u_queue;
600: {
601: extern vd_int_timeout();
602: register struct buf *request = u_queue->av_forw;
603: register int ctlr = controller_info->um_ctlr;
604: register ctlr_tab *c_info = &vdctlr_info[ctlr];
605: register int unit = VDUNIT(request->b_dev);
606: register int slave = vddinfo[unit]->ui_slave;
607: register fs_tab *fs = &vdunit_info[unit].info;
608: register fmt_mdcb *mdcb = &c_info->ctlr_mdcb;
609: register fmt_dcb *dcb = &c_info->ctlr_dcb;
610:
611: if((c_info->off_cylinder & ~(1<<slave)) && c_info->overlap_seeks) {
612: register int index;
613: register int seek_count = vdload_seeks(c_info, u_queue);
614:
615: mdcb->firstdcb = (fmt_dcb *)PHYS(&c_info->seek_dcb[0]);
616: for(index = 1; index < seek_count; index++)
617: c_info->seek_dcb[index-1].nxtdcb =
618: (fmt_dcb *)PHYS(&c_info->seek_dcb[index]);
619: c_info->seek_dcb[seek_count-1].nxtdcb = (fmt_dcb *)PHYS(dcb);
620: }
621: else {
622: if(request->b_cylin != c_info->cur_cyl[slave]) {
623: c_info->cur_cyl[slave] = request->b_cylin;
624: dk_seek[unit]++;
625: }
626: c_info->cur_trk[slave] = request->b_daddr & 0xff;
627: c_info->off_cylinder = 0;
628: mdcb->firstdcb = (fmt_dcb *)(PHYS(dcb));
629: }
630: dcb->opcode = (request->b_flags & B_READ) ? RD : WD;
631: dcb->intflg = INTDONE;
632: dcb->nxtdcb = (fmt_dcb *)0; /* end of chain */
633: dcb->operrsta = 0;
634: dcb->devselect = (char)slave;
635: dcb->trailcnt = (char)(sizeof(trrw) / sizeof(long));
636: dcb->trail.rwtrail.memadr = (char *)get_ioadr(request, c_info->rawbuf,
637: c_info->map, c_info->utl);
638: dcb->trail.rwtrail.wcount=(short)((request->b_bcount+1)/sizeof(short));
639: dcb->trail.rwtrail.disk.cylinder = request->b_cylin;
640: dcb->trail.rwtrail.disk.track = request->b_daddr & 0xff;
641: dcb->trail.rwtrail.disk.sector = request->b_daddr >> 8;
642: mdcb->vddcstat = 0;
643: dk_wds[unit] += request->b_bcount / 32;
644: c_info->int_expected = TRUE;
645: timeout(vd_int_timeout, ctlr, 20*60);
646: dk_busy |= 1 << unit;
647: #ifdef VDDCPERF
648: scope_out(1);
649: #endif
650: VDDC_ATTENTION((cdr *)(vdminfo[ctlr]->um_addr),(fmt_mdcb *)(PHYS(mdcb)),
651: c_info->ctlr_type);
652: }
653:
654:
655: /*
656: **
657: */
658:
659: vd_int_timeout(ctlr)
660: register int ctlr;
661: {
662: register ctlr_tab *c_info = &vdctlr_info[ctlr];
663: register fmt_mdcb *mdcb = &c_info->ctlr_mdcb;
664: register fmt_dcb *dcb = &c_info->ctlr_dcb;
665:
666: uncache(&dcb->operrsta);
667: printf("\nVDDC: Controller #%d didn't interupt!", ctlr);
668: printf(" Status = %x", dcb->operrsta);
669: if(c_info->ctlr_type == SMD_ECTLR) {
670: uncache(&dcb->err_code);
671: printf(" Error code = %x", dcb->err_code);
672: }
673: printf("\n");
674: if(!(dcb->operrsta & DCBCMP)) {
675: VDDC_ABORT((cdr *)(vdminfo[ctlr]->um_addr), c_info->ctlr_type);
676: dcb->operrsta |= DCBUSC | DCBABT | ANYERR | HRDERR | CTLRERR;
677: }
678: vdintr(ctlr);
679: }
680:
681:
682: /*
683: * Handle a disk interrupt.
684: */
685: vdintr(ctlr)
686: register int ctlr;
687: {
688: extern vd_int_timeout();
689: register ctlr_tab *c_info = &vdctlr_info[ctlr];
690:
691:
692: untimeout(vd_int_timeout, ctlr);
693: #ifdef VDDCPERF
694: scope_out(2);
695: #endif
696: if(c_info->int_expected) {
697: register struct buf *u_queue=vdminfo[ctlr]->um_tab.b_forw;
698: register struct buf *request = u_queue->av_forw;
699: register int slave = u_queue->b_dev;
700: register int unit = VDUNIT(request->b_dev);
701: register unit_tab *u_info = &vdunit_info[unit];
702: register fmt_mdcb *mdcb = &c_info->ctlr_mdcb;
703: register fmt_dcb *dcb = &c_info->ctlr_dcb;
704: register int priority;
705:
706: dk_busy &= ~(1 << unit);
707: dk_xfer[unit]++;
708: c_info->int_expected = FALSE;
709: uncache(&mdcb->intdcb);
710: uncache(&dcb->operrsta);
711: if(c_info->ctlr_type == SMD_ECTLR)
712: uncache(&dcb->err_code);
713: switch(vddecode_error(request, dcb)) {
714: case CTLR_ERROR :
715: if(vdminfo[ctlr]->um_tab.b_errcnt >= 2)
716: vdhard_error(c_info, request, dcb);
717: vdreset_ctlr(vdminfo[ctlr]->um_addr,ctlr);
718: if(vdminfo[ctlr]->um_tab.b_errcnt++ < 2) {
719: vdminfo[ctlr]->um_tab.b_forw =
720: u_queue->b_back;
721: vdstart(vdminfo[ctlr]);
722: return;
723: }
724: request->b_resid = request->b_bcount;
725: break;
726: case DRIVE_ERROR :
727: if(vdminfo[ctlr]->um_tab.b_errcnt >= 2)
728: vdhard_error(c_info, request, dcb);
729: reset_drive(vdminfo[ctlr]->um_addr,
730: ctlr, slave, 2);
731: if(vdminfo[ctlr]->um_tab.b_errcnt++ < 2) {
732: vdminfo[ctlr]->um_tab.b_forw =
733: u_queue->b_back;
734: vdstart(vdminfo[ctlr]);
735: return;
736: }
737: request->b_resid = request->b_bcount;
738: break;
739: case HARD_DATA_ERROR :
740: vdhard_error(c_info, request, dcb);
741: request->b_resid = 0;
742: break;
743: case SOFT_DATA_ERROR :
744: vdsoft_error(c_info, request, dcb);
745: default :
746: request->b_error = 0;
747: request->b_resid = 0;
748: break;
749: }
750: end_transfer(request, c_info->rawbuf, c_info->map, c_info->utl);
751: priority = spl7();
752: u_queue->av_forw = request->av_forw;
753: if(u_queue->av_back == request)
754: u_queue->av_back = NULL;
755: else {
756: register struct buf *next;
757:
758: unit = VDUNIT(u_queue->av_forw->b_dev);
759: slave = vddinfo[unit]->ui_slave;
760: next = u_queue->av_forw;
761: if((next->b_cylin != c_info->cur_cyl[slave]) ||
762: ((next->b_daddr & 0xff) != c_info->cur_trk[slave]))
763: c_info->off_cylinder |= 1 << slave;
764: }
765: splx(priority);
766: vdminfo[ctlr]->um_tab.b_errcnt = 0;
767: vdminfo[ctlr]->um_tab.b_active--;
768: #ifdef VDDCPERF
769: scope_out(3);
770: #endif
771: if(request->b_flags & B_ERROR)
772: request->b_error = EIO;
773: iodone(request);
774: vdstart(vdminfo[ctlr]);
775: return;
776: }
777: printf("\nVDDC: Unexpected interupt from controller #%d!\n", ctlr);
778: }
779:
780:
781: /*
782: **
783: */
784:
785: vddecode_error(request, dcb)
786: register struct buf *request;
787: register fmt_dcb *dcb;
788: {
789: register int unit = VDUNIT(request->b_dev);
790:
791: if(dcb->operrsta & HRDERR) {
792: if (dcb->operrsta & (HCRCERR | HCMPERR | UCDATERR | WPTERR |
793: DSEEKERR | NOTCYLERR |DRVNRDY | INVDADR))
794: return DRIVE_ERROR;
795: else if(dcb->operrsta & (CTLRERR | OPABRT | INVCMD | DNEMEM))
796: return CTLR_ERROR;
797: return HARD_DATA_ERROR;
798: }
799: if(dcb->operrsta & SFTERR)
800: return SOFT_DATA_ERROR;
801: return NOERROR;
802: }
803:
804:
805: /*
806: **
807: */
808:
809: vdhard_error(c_info, request, dcb)
810: ctlr_tab *c_info;
811: register struct buf *request;
812: register fmt_dcb *dcb;
813: {
814: register int delta;
815: register int unit = VDUNIT(request->b_dev);
816: register unit_tab *u_info = &vdunit_info[unit];
817: register int blk = request->b_blkno * u_info->sec_per_blk;
818:
819: request->b_flags |= B_ERROR;
820: delta = (request->b_bcount+u_info->info.secsize-1)/u_info->info.secsize;
821: harderr(request, u_info->info.type_name);
822: printf("- Hard error between sectors %d and %d.",
823: blk, blk + delta);
824: printf(" Status = 0x%x", dcb->operrsta);
825: if(c_info->ctlr_type == SMD_ECTLR)
826: printf(", Error code = 0x%x", dcb->err_code);
827: printf("\n");
828: }
829:
830:
831: /*
832: **
833: */
834:
835: vdsoft_error(c_info, request, dcb)
836: ctlr_tab *c_info;
837: register struct buf *request;
838: register fmt_dcb *dcb;
839: {
840: register int delta;
841: register int unit = VDUNIT(request->b_dev);
842: register unit_tab *u_info = &vdunit_info[unit];
843: register int blk = request->b_blkno * u_info->sec_per_blk;
844:
845: delta = (request->b_bcount+u_info->info.secsize-1)/u_info->info.secsize;
846: harderr(request, u_info->info.type_name);
847: printf("- Corrected soft error between sectors %d and %d.",
848: blk, blk + delta);
849: printf(" Status = 0x%x", dcb->operrsta);
850: if(c_info->ctlr_type == SMD_ECTLR)
851: printf(", Error code = 0x%x", dcb->err_code);
852: printf("\n");
853: }
854:
855:
856: /*
857: **
858: */
859:
860: vdopen(dev, flag)
861: register dev_t dev;
862: int flag;
863: {
864: register unit = VDUNIT(dev);
865: register struct vba_device *vba_dev_info = vddinfo[unit];
866:
867: if((vba_dev_info == 0) ||
868: (vba_dev_info->ui_alive == 0) ||
869: (vba_dev_info->ui_type >= nvddrv))
870: return ENXIO;
871: if(vdunit_info[unit].info.partition[FILSYS(dev)].par_len == 0)
872: return ENXIO;
873: return NOERROR;
874: }
875:
876:
877: /*
878: **
879: */
880:
881: vdread(dev, uio)
882: dev_t dev;
883: struct uio *uio;
884: {
885: extern vdstrategy();
886: register int unit = VDUNIT(dev);
887: register unit_tab *u_info = &vdunit_info[unit];
888:
889: if (unit >= NFSD)
890: return ENXIO;
891: return physio(vdstrategy, &u_info->raw_q_element, dev, B_READ,
892: minphys, uio);
893: }
894:
895:
896: /*
897: **
898: */
899:
900: vdwrite(dev, uio)
901: dev_t dev;
902: struct uio *uio;
903: {
904: extern vdstrategy();
905: register int unit = VDUNIT(dev);
906: register unit_tab *u_info = &vdunit_info[unit];
907:
908: if (unit >= NFSD)
909: return ENXIO;
910: return physio(vdstrategy, &u_info->raw_q_element, dev, B_WRITE,
911: minphys, uio);
912: }
913:
914:
915: /*
916: **
917: */
918:
919: vddump(dev)
920: dev_t dev;
921: {
922: register int unit = VDUNIT(dev);
923: register unit_tab *u_info = &vdunit_info[unit];
924: register fs_tab *fs = &u_info->info;
925: register int ctlr = vddinfo[unit]->ui_ctlr;
926: register struct vba_ctlr *vba_vdctlr_info = vdminfo[ctlr];
927: register int filsys = FILSYS(dev);
928: register cdr *ctlr_addr = (cdr *)(vba_vdctlr_info->um_addr);
929: register int cur_blk, blkcount, blocks;
930: int dump_short = FALSE;
931: int memaddr = 0x0;
932:
933: vdreset_ctlr(ctlr_addr, ctlr);
934: blkcount = maxfree - 2; /* In 1k byte pages */
935: if ((dumplo + blkcount) > fs->partition[filsys].par_len) {
936: blkcount = fs->partition[filsys].par_len - dumplo;
937: printf("\nVDDC: Only dumping first %dmb of memory!\n",
938: blkcount / 1024);
939: dump_short = TRUE;
940: }
941: cur_blk = fs->partition[filsys].par_start + dumplo;
942: while (blkcount > 0) {
943: blocks = MIN(blkcount, DUMPSIZE);
944: if(!vdwrite_block(ctlr_addr,ctlr,unit,memaddr,cur_blk,blocks))
945: return EIO;
946: blkcount -= blocks;
947: memaddr += blocks * NBPG;
948: cur_blk += blocks;
949: }
950: return dump_short ? ENXIO : NOERROR;
951: }
952:
953:
954: /*
955: **
956: */
957:
958: vdwrite_block(ctlr_addr, ctlr, unit, addr, block, blocks)
959: register cdr *ctlr_addr;
960: register int ctlr, unit;
961: register char *addr;
962: register int block, blocks;
963: {
964: register fmt_mdcb *mdcb = &vdctlr_info[ctlr].ctlr_mdcb;
965: register fmt_dcb *dcb = &vdctlr_info[ctlr].ctlr_dcb;
966: register unit_tab *u_info = &vdunit_info[unit];
967: register fs_tab *fs = &u_info->info;
968:
969: block *= (int)u_info->sec_per_blk;
970: blocks *= (int)u_info->sec_per_blk;
971: mdcb->firstdcb = (fmt_dcb *)(PHYS(dcb));
972: dcb->intflg = NOINT;
973: dcb->opcode = WD;
974: dcb->operrsta = 0;
975: dcb->devselect = (char)(vddinfo[unit])->ui_slave;
976: dcb->trailcnt = (char)(sizeof(trrw) / sizeof(long));
977: dcb->trail.rwtrail.memadr = addr;
978: dcb->trail.rwtrail.wcount = (short)((blocks*fs->secsize)/sizeof(short));
979: dcb->trail.rwtrail.disk.cylinder= (short)(block / u_info->sec_per_cyl);
980: dcb->trail.rwtrail.disk.track = (char)((block / fs->nsec) % fs->ntrak);
981: dcb->trail.rwtrail.disk.sector = (char)(block % fs->nsec);
982: VDDC_ATTENTION(ctlr_addr, (fmt_mdcb *)(PHYS(mdcb)),
983: vdctlr_info[ctlr].ctlr_type);
984: POLLTILLDONE(ctlr_addr, dcb, 5, vdctlr_info[ctlr].ctlr_type);
985: if(vdtimeout <= 0) {
986: printf(" during dump operation!\n");
987: return(FALSE);
988: }
989: if (dcb->operrsta & HRDERR) {
990: printf("\nVDDC: Dump error. Status = %x\n", dcb->operrsta);
991: return(FALSE);
992: }
993: return TRUE;
994: }
995:
996:
997:
998: /*
999: **
1000: */
1001:
1002: vdsize(dev)
1003: register dev_t dev;
1004: {
1005: register unit = VDUNIT(dev);
1006: register struct vba_device *vba_dev_info = vddinfo[unit];
1007:
1008: if((vba_dev_info == 0) ||
1009: (vba_dev_info->ui_alive == 0) ||
1010: (vba_dev_info->ui_type >= nvddrv))
1011: return -1;
1012: return vdunit_info[unit].info.partition[FILSYS(dev)].par_len;
1013: }
1014:
1015:
1016: /*
1017: **
1018: */
1019:
1020: vdreset_ctlr(ctlr_addr, ctlr)
1021: register cdr *ctlr_addr;
1022: register int ctlr;
1023: {
1024: register struct buf *c_queue = &vdminfo[ctlr]->um_tab;
1025: register struct buf *u_queue = c_queue->b_forw;
1026: register ctlr_tab *c_info = &vdctlr_info[ctlr];
1027: register int type, priority;
1028:
1029: printf("\nVDDC: Resetting controller #%d. Please wait...\n", ctlr);
1030: VDDC_RESET(ctlr_addr, type);
1031: c_info->ctlr_started = FALSE;
1032: if(c_info->ctlr_type == SMD_ECTLR) {
1033: ctlr_addr->cdr_csr = 0;
1034: ctlr_addr->mdcb_tcf = AM_ENPDA;
1035: ctlr_addr->dcb_tcf = AM_ENPDA;
1036: ctlr_addr->trail_tcf = AM_ENPDA;
1037: ctlr_addr->data_tcf = AM_ENPDA;
1038: ctlr_addr->cdr_ccf = CCF_STS | XMD_32BIT | BSZ_16WRD |
1039: CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE | CCF_ERR;
1040: }
1041: if(vdaccess_with_no_trailer(ctlr_addr,ctlr,0,INIT,10) & HRDERR) {
1042: printf("\nVDDC: Controller #%d failed to initialize!\n", ctlr);
1043: return FALSE;
1044: }
1045: if(vdaccess_with_no_trailer(ctlr_addr,ctlr,0,DIAG,10) & HRDERR) {
1046: printf("\nVDDC: Controller #%d diagnostic error!\n",ctlr);
1047: return FALSE;
1048: }
1049: /* reset all units attached to controller */
1050: u_queue = c_queue->b_forw;
1051: do {
1052: reset_drive(ctlr_addr, ctlr, u_queue->b_dev, 0);
1053: u_queue = u_queue->b_forw;
1054: } while(u_queue != c_queue->b_forw);
1055: printf("VDDC: Controller #%d was reset successfully.\n", ctlr);
1056: return TRUE;
1057: }
1058:
1059:
1060: /*
1061: **
1062: */
1063:
1064: reset_drive(ctlr_addr, ctlr, slave, start)
1065: register cdr *ctlr_addr;
1066: register int ctlr, slave, start;
1067: {
1068: register int type = vdctlr_info[ctlr].unit_type[slave];
1069:
1070: if(type != UNKNOWN)
1071: if(!vdconfigure_drive(ctlr_addr, ctlr, slave, type, start))
1072: printf("\nVDDC: Couldn't reset unit #%d, controller #%d!\n",
1073: slave, ctlr);
1074: }
1075:
1076: /*
1077: Print_dcb() dumps the mdcb and DCB for diagnostic purposes. This
1078: routine is called whenever a fatal error is encountered.
1079: */
1080:
1081: vdprintdcb(ptr)
1082: register long *ptr;
1083: {
1084: register long i, j=0;
1085: register long trailer_count;
1086:
1087: ptr = (long *)(*ptr | 0xc0000000);
1088: while(ptr != (long *)NULL) {
1089: ptr = (long *)((long)ptr | 0xc0000000);
1090: printf(" Dump of DCB 0x%x,%d:", ptr, j++);
1091: trailer_count = *(ptr+3) & 0xff;
1092: for(i=0; i<7+trailer_count; i++)
1093: printf(" %lx", *(ptr+i));
1094: ptr = (long *)(*ptr);
1095: printf("\n");
1096: }
1097: printf("\n");
1098: for(i=0; i<5000000; i++) ;
1099: }
1100:
1101: #endif NVD > 0
1102:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.