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