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