1 /* vd.c 1.6 86/01/20 */ 2 3 #include "fsd.h" 4 #if NVD > 0 5 /* 6 * VDDC - Versabus SMD/ESMD driver. 7 */ 8 #ifdef VDDCPERF 9 #define DOSCOPE 10 #endif 11 12 #include "../tahoe/mtpr.h" 13 #include "../tahoe/pte.h" 14 15 #include "param.h" 16 #include "buf.h" 17 #include "cmap.h" 18 #include "conf.h" 19 #include "dir.h" 20 #include "dk.h" 21 #include "map.h" 22 #include "systm.h" 23 #include "user.h" 24 #include "vmmac.h" 25 #include "proc.h" 26 #include "uio.h" 27 28 #include "../tahoevba/vbavar.h" 29 #define VDGENDATA 30 #include "../tahoevba/vddcreg.h" 31 #undef VDGENDATA 32 #include "../tahoevba/scope.h" 33 34 #define VDMAXIO (MAXBPTE*NBPG) 35 #define DUMPSIZE 64 /* controller limit */ 36 37 #define VDUNIT(x) (minor(x) >> 3) 38 #define FILSYS(x) (minor(x) & 0x07) 39 #define PHYS(x) (vtoph((struct proc *)0, (unsigned)(x))) 40 #define TRUE 1 41 #define FALSE 0 42 43 #define CTLR_ERROR 1 44 #define DRIVE_ERROR 2 45 #define HARD_DATA_ERROR 3 46 #define SOFT_DATA_ERROR 4 47 48 #define b_cylin b_resid 49 #define b_daddr b_error 50 51 struct vba_ctlr *vdminfo[NVD]; 52 struct vba_device *vddinfo[NFSD]; 53 int vdprobe(), vdslave(), vdattach(), vddgo(); 54 struct vba_driver vddriver = 55 { vdprobe, vdslave, vdattach, vddgo, vddcaddr, "smd/fsd", 56 vddinfo, "vd", vdminfo }; 57 58 /* 59 * Per-drive state. 60 */ 61 typedef struct { 62 struct buf raw_q_element; 63 short sec_per_blk; 64 short sec_per_cyl; 65 char status; 66 struct buf xfer_queue; 67 int drive_type; 68 fs_tab info; 69 } unit_tab; 70 71 /* 72 * Per-controller state. 73 */ 74 typedef struct { 75 char ctlr_type; /* controller type */ 76 struct pte *map; /* i/o page map */ 77 caddr_t utl; /* mapped i/o space */ 78 u_int cur_slave:8; /* last active unit number */ 79 u_int int_expected:1; /* expect an interupt */ 80 u_int ctlr_started:1; /* start command was issued */ 81 u_int overlap_seeks:1;/* should overlap seeks */ 82 u_int initdone:1; /* controller initialization completed */ 83 u_int off_cylinder:16;/* off cylinder bit map */ 84 u_int unit_type[16]; /* slave types */ 85 u_int cur_cyl[16]; /* cylinder last selected */ 86 long cur_trk[16]; /* track last selected */ 87 fmt_mdcb ctlr_mdcb; /* controller mdcb */ 88 fmt_dcb ctlr_dcb; /* r/w dcb */ 89 fmt_dcb seek_dcb[4]; /* dcbs for overlapped seeks */ 90 /* buffer for raw/swap i/o */ 91 char rawbuf[VDMAXIO]; 92 } ctlr_tab; 93 94 ctlr_tab vdctlr_info[NVD]; 95 unit_tab vdunit_info[NFSD]; 96 97 /* 98 * See if the controller is really there; if so, initialize it. 99 */ 100 vdprobe(reg, vm) 101 caddr_t reg; 102 struct vba_ctlr *vm; 103 { 104 register br, cvec; /* must be r12, r11 */ 105 register cdr *addr = (cdr *)reg; 106 register ctlr_tab *ci; 107 int i; 108 109 if (badaddr((caddr_t)reg, 2)) 110 return (0); 111 ci = &vdctlr_info[vm->um_ctlr]; 112 addr->cdr_reset = 0xffffffff; 113 DELAY(1000000); 114 if (addr->cdr_reset != (unsigned)0xffffffff) { 115 ci->ctlr_type = SMDCTLR; 116 ci->overlap_seeks = 0; 117 DELAY(1000000); 118 } else { 119 ci->overlap_seeks = 1; 120 ci->ctlr_type = SMD_ECTLR; 121 addr->cdr_reserved = 0x0; 122 DELAY(3000000); 123 addr->cdr_csr = 0; 124 addr->mdcb_tcf = AM_ENPDA; 125 addr->dcb_tcf = AM_ENPDA; 126 addr->trail_tcf = AM_ENPDA; 127 addr->data_tcf = AM_ENPDA; 128 addr->cdr_ccf = CCF_STS | XMD_32BIT | BSZ_16WRD | 129 CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE | CCF_ERR; 130 } 131 /* 132 * Allocate page tables. 133 */ 134 vbmapalloc(btoc(VDMAXIO)+1, &ci->map, &ci->utl); 135 /* 136 * Initialize all the drives to be of an unknown type. 137 */ 138 for (i = 0; i < 15; i++) 139 ci->unit_type[i] = UNKNOWN; 140 br = 0x17, cvec = 0xe0 + vm->um_ctlr; /* XXX */ 141 return (sizeof (*addr)); 142 } 143 144 /* 145 * See if a drive is really there 146 * Try to reset/configure the drive, then test its status. 147 */ 148 vdslave(vi, addr) 149 register struct vba_device *vi; 150 register cdr *addr; 151 { 152 register ctlr_tab *ci = &vdctlr_info[vi->ui_ctlr]; 153 register unit_tab *ui = &vdunit_info[vi->ui_unit]; 154 register fmt_mdcb *mdcb = &ci->ctlr_mdcb; 155 register fmt_dcb *dcb = &ci->ctlr_dcb; 156 register int type; 157 158 if (!ci->initdone) { 159 printf("vd%d: %s controller\n", vi->ui_ctlr, 160 ci->ctlr_type == SMDCTLR ? "smd" : "xsmd"); 161 if (vdnotrailer(addr, vi->ui_ctlr, vi->ui_slave, INIT, 10) & 162 HRDERR) { 163 printf("vd%d: init error\n", vi->ui_ctlr); 164 return (0); 165 } 166 if (vdnotrailer(addr, vi->ui_ctlr, vi->ui_slave, DIAG, 10) & 167 HRDERR) { 168 printf("vd%d: diagnostic error\n", vi->ui_ctlr); 169 return (0); 170 } 171 ci->initdone = 1; 172 } 173 /* 174 * Seek on all drive types starting from the largest one. 175 * a successful seek to the last sector/cylinder/track verifies 176 * the drive type connected to this port. 177 */ 178 for (type = 0; type < nvddrv; type++) { 179 /* XXX */ 180 if (ci->ctlr_type == SMDCTLR && vdst[type].nsec != 32) 181 continue; 182 /* XXX */ 183 if (!vdconfigure_drive(addr, vi->ui_ctlr, vi->ui_slave, type,0)) 184 return (0); 185 dcb->opcode = (short)RD; 186 dcb->intflg = NOINT; 187 dcb->nxtdcb = (fmt_dcb *)0; /* end of chain */ 188 dcb->operrsta = 0; 189 dcb->devselect = (char)(vi->ui_slave); 190 dcb->trailcnt = (char)(sizeof (trrw) / sizeof (long)); 191 dcb->trail.rwtrail.memadr = (char *)PHYS(ci->rawbuf); 192 dcb->trail.rwtrail.wcount = vdst[type].secsize/sizeof(short); 193 dcb->trail.rwtrail.disk.cylinder = vdst[type].ncyl - 2; 194 dcb->trail.rwtrail.disk.track = vdst[type].ntrak - 1; 195 dcb->trail.rwtrail.disk.sector = vdst[type].nsec - 1; 196 mdcb->firstdcb = (fmt_dcb *)(PHYS(dcb)); 197 mdcb->vddcstat = 0; 198 VDDC_ATTENTION(addr, (fmt_mdcb *)(PHYS(mdcb)), ci->ctlr_type); 199 if (!vdpoll(ci, addr, 60)) 200 printf(" during probe\n"); 201 if ((dcb->operrsta&HRDERR) == 0) 202 break; 203 } 204 if (type >= nvddrv) { 205 /* 206 * If reached here, a drive which is not defined in the 207 * 'vdst' tables is connected. Cannot set it's type. 208 */ 209 printf("vd%d: unknown drive type\n", vi->ui_unit); 210 return (0); 211 } 212 ui->drive_type = type; 213 ui->info = vdst[type]; 214 ui->sec_per_blk = DEV_BSIZE / ui->info.secsize; 215 vi->ui_type = type; 216 vi->ui_dk = 1; 217 vddriver.ud_dname = ui->info.type_name; 218 return (1); 219 } 220 221 vdconfigure_drive(addr, ctlr, slave, type, pass) 222 register cdr *addr; 223 int ctlr, slave, type, pass; 224 { 225 register ctlr_tab *ci = &vdctlr_info[ctlr]; 226 227 ci->ctlr_dcb.opcode = RSTCFG; /* command */ 228 ci->ctlr_dcb.intflg = NOINT; 229 ci->ctlr_dcb.nxtdcb = (fmt_dcb *)0; /* end of chain */ 230 ci->ctlr_dcb.operrsta = 0; 231 ci->ctlr_dcb.devselect = (char)slave; 232 ci->ctlr_dcb.trail.rstrail.ncyl = vdst[type].ncyl; 233 ci->ctlr_dcb.trail.rstrail.nsurfaces = vdst[type].ntrak; 234 if (ci->ctlr_type == SMD_ECTLR) { 235 ci->ctlr_dcb.trailcnt = (char)4; 236 ci->ctlr_dcb.trail.rstrail.nsectors = vdst[type].nsec; 237 ci->ctlr_dcb.trail.rstrail.slip_sec = vdst[type].nslip; 238 } else 239 ci->ctlr_dcb.trailcnt = (char)2; 240 ci->ctlr_mdcb.firstdcb = (fmt_dcb *)(PHYS(&ci->ctlr_dcb)); 241 ci->ctlr_mdcb.vddcstat = 0; 242 VDDC_ATTENTION(addr, (fmt_mdcb *)(PHYS(&ci->ctlr_mdcb)), ci->ctlr_type); 243 if (!vdpoll(ci, addr, 5)) { 244 printf(" during config\n"); 245 return (0); 246 } 247 if (ci->ctlr_dcb.operrsta & HRDERR) { 248 if ((ci->ctlr_dcb.operrsta & (NOTCYLERR|DRVNRDY)) == 0) 249 printf("vd%d: drive %d: config error\n", ctlr, slave); 250 else if (pass == 0) { 251 vdstart_drive(addr, ctlr, slave); 252 return (vdconfigure_drive(addr, ctlr, slave, type, 1)); 253 } else if (pass == 2) 254 return (vdconfigure_drive(addr, ctlr, slave, type, 3)); 255 return (0); 256 } 257 return (1); 258 } 259 260 vdstart_drive(addr, ctlr, slave) 261 cdr *addr; 262 register int ctlr, slave; 263 { 264 int error = 0; 265 266 printf("vd%d: starting drive %d, wait...", ctlr, slave); 267 if (vdctlr_info[ctlr].ctlr_started) { 268 printf("DELAY(5500000)..."); 269 DELAY(5500000); 270 goto done; 271 } 272 vdctlr_info[ctlr].ctlr_started = 1; 273 error = vdnotrailer(addr, ctlr, 0, VDSTART, (slave*6)+62) & HRDERR; 274 if (!error) { 275 printf("DELAY(%d)...", (slave * 5500000) + 62000000); 276 DELAY((slave * 5500000) + 62000000); 277 } 278 done: 279 printf("\n"); 280 return (error == 0); 281 } 282 283 vdnotrailer(addr, ctlr, unit, function, time) 284 register cdr *addr; 285 int ctlr, unit, function, time; 286 { 287 register ctlr_tab *ci = &vdctlr_info[ctlr]; 288 fmt_mdcb *mdcb = &ci->ctlr_mdcb; 289 fmt_dcb *dcb = &ci->ctlr_dcb; 290 291 dcb->opcode = function; /* command */ 292 dcb->intflg = NOINT; 293 dcb->nxtdcb = (fmt_dcb *)0; /* end of chain */ 294 dcb->operrsta = 0; 295 dcb->devselect = (char)unit; 296 dcb->trailcnt = (char)0; 297 mdcb->firstdcb = (fmt_dcb *)(PHYS(dcb)); 298 mdcb->vddcstat = 0; 299 VDDC_ATTENTION(addr, (fmt_mdcb *)(PHYS(mdcb)), ci->ctlr_type); 300 if (!vdpoll(ci, addr, time)) { 301 printf(" during init\n"); 302 return (DCBCMP|ANYERR|HRDERR|OPABRT); 303 } 304 return (dcb->operrsta); 305 } 306 307 vdattach(vi) 308 register struct vba_device *vi; 309 { 310 register unit_tab *ui = &vdunit_info[vi->ui_unit]; 311 register ctlr_tab *ci = &vdctlr_info[vi->ui_ctlr]; 312 register struct buf *cq = &vi->ui_mi->um_tab; 313 register struct buf *uq = cq->b_forw; 314 register struct buf *start_queue = uq; 315 register fs_tab *fs = &ui->info; 316 317 ui->info = vdst[vi->ui_type]; 318 ui->sec_per_blk = DEV_BSIZE / ui->info.secsize; 319 ui->sec_per_cyl = ui->info.nsec * ui->info.ntrak; 320 ui->xfer_queue.b_dev = vi->ui_slave; 321 ci->unit_type[vi->ui_slave] = vi->ui_type; 322 /* load unit into controller's active unit list */ 323 if (uq == NULL) { 324 cq->b_forw = &ui->xfer_queue; 325 ui->xfer_queue.b_forw = &ui->xfer_queue; 326 ui->xfer_queue.b_back = &ui->xfer_queue; 327 } else { 328 while (uq->b_forw != start_queue) 329 uq = uq->b_forw; 330 ui->xfer_queue.b_forw = start_queue; 331 ui->xfer_queue.b_back = uq; 332 uq->b_forw = &ui->xfer_queue; 333 start_queue->b_back = &ui->xfer_queue; 334 } 335 /* 336 * (60 / rpm) / (number of sectors per track * (bytes per sector / 2)) 337 */ 338 dk_mspw[vi->ui_unit] = 120.0 / (fs->rpm * fs->nsec * fs->secsize); 339 } 340 341 /*ARGSUSED*/ 342 vddgo(um) 343 struct vba_ctlr *um; 344 { 345 346 } 347 348 vdstrategy(bp) 349 register struct buf *bp; 350 { 351 register int unit = VDUNIT(bp->b_dev); 352 register struct vba_device *vi = vddinfo[unit]; 353 register par_tab *par; 354 register unit_tab *ui; 355 register fs_tab *fs; 356 register int blks, bn, s; 357 358 if (bp->b_bcount == 0 || vi == 0 || vi->ui_alive == 0) 359 goto bad; 360 ui = &vdunit_info[unit]; 361 fs = &ui->info; 362 par = &fs->partition[FILSYS(bp->b_dev)]; 363 blks = (bp->b_bcount + DEV_BSIZE-1) >> DEV_BSHIFT; 364 if (bp->b_blkno + blks >= par->par_len) { 365 blks = par->par_len - bp->b_blkno; 366 if (blks <= 0) 367 goto bad; 368 bp->b_bcount = blks * DEV_BSIZE; 369 } 370 bn = bp->b_blkno + par->par_start; 371 bn *= ui->sec_per_blk; 372 bp->b_daddr = (bn / fs->nsec) % fs->ntrak; 373 bp->b_cylin = bn / ui->sec_per_cyl; 374 vbasetup(bp, ui->info.secsize); 375 s = spl7(); 376 if (ui->xfer_queue.av_forw == NULL) { 377 register ctlr_tab *ci = &vdctlr_info[vi->ui_ctlr]; 378 int slave = vi->ui_slave; 379 380 if (bp->b_cylin != ci->cur_cyl[slave] || 381 bp->b_daddr != ci->cur_trk[slave]) 382 ci->off_cylinder |= 1 << slave; 383 } 384 bp->b_daddr |= (bn % fs->nsec) << 8; 385 disksort(&ui->xfer_queue, bp); 386 if (!vddinfo[unit]->ui_mi->um_tab.b_active++) { 387 splx(s); 388 vdstart(vddinfo[unit]->ui_mi); 389 } else 390 splx(s); 391 return; 392 bad: 393 bp->b_flags |= B_ERROR, bp->b_error = ENXIO; 394 bp->b_resid = bp->b_bcount; 395 iodone(bp); 396 } 397 398 /* 399 * Start up a transfer on a drive. 400 */ 401 vdstart(ci) 402 register struct vba_ctlr *ci; 403 { 404 register struct buf *cq = &ci->um_tab; 405 register struct buf *uq = cq->b_forw; 406 407 /* search for next ready unit */ 408 cq->b_forw = cq->b_forw->b_forw; 409 uq = cq->b_forw; 410 do { 411 if (uq->av_forw != NULL) { 412 cq->b_forw = uq; 413 vdexecute(ci, uq); 414 return; 415 } 416 uq = uq->b_forw; 417 } while (uq != cq->b_forw); 418 } 419 420 /* 421 * Initiate seeks for all drives off-cylinder. 422 */ 423 vdload_seeks(ci, uq) 424 register ctlr_tab *ci; 425 register struct buf *uq; 426 { 427 register int unit, slave, nseeks; 428 register fmt_dcb *dcb; 429 register struct buf *bp; 430 register struct buf *start_queue = uq; 431 432 nseeks = 0; 433 do { 434 bp = uq->av_forw; 435 if (bp != NULL) { 436 unit = VDUNIT(bp->b_dev); 437 slave = vddinfo[unit]->ui_slave; 438 if (ci->off_cylinder & (1 << slave)) { 439 ci->off_cylinder &= ~(1 << slave); 440 if (ci->cur_cyl[slave] != bp->b_cylin) { 441 ci->cur_cyl[slave] = bp->b_cylin; 442 dk_seek[unit]++; 443 } 444 ci->cur_trk[slave] = bp->b_daddr&0xff; 445 dcb = &ci->seek_dcb[nseeks++]; 446 dcb->opcode = SEEK; 447 dcb->intflg = NOINT | INT_PBA; 448 dcb->operrsta = 0; 449 dcb->devselect = (char)slave; 450 dcb->trailcnt = (char)1; 451 dcb->trail.sktrail.skaddr.cylinder = 452 bp->b_cylin; 453 dcb->trail.sktrail.skaddr.track = 454 bp->b_daddr & 0xff; 455 dcb->trail.sktrail.skaddr.sector = 0; 456 } 457 } 458 uq = uq->b_forw; 459 } while (uq != start_queue && nseeks < 4); 460 return (nseeks); 461 } 462 463 extern vd_int_timeout(); 464 /* 465 * Execute the next command on the unit queue uq. 466 */ 467 vdexecute(controller_info, uq) 468 register struct vba_ctlr *controller_info; 469 register struct buf *uq; 470 { 471 register struct buf *bp = uq->av_forw; 472 register int ctlr = controller_info->um_ctlr; 473 register ctlr_tab *ci = &vdctlr_info[ctlr]; 474 register int unit = VDUNIT(bp->b_dev); 475 register int slave = vddinfo[unit]->ui_slave; 476 register fmt_mdcb *mdcb = &ci->ctlr_mdcb; 477 register fmt_dcb *dcb = &ci->ctlr_dcb; 478 479 /* 480 * If there are overlapped seeks to perform, shuffle 481 * them to the front of the queue and get them started 482 * before any data transfers (to get some parallelism). 483 */ 484 if ((ci->off_cylinder & ~(1<<slave)) && ci->overlap_seeks) { 485 register int i, nseeks; 486 487 /* setup seek requests in seek-q */ 488 nseeks = vdload_seeks(ci, uq); 489 /* place at the front of the master q */ 490 mdcb->firstdcb = (fmt_dcb *)PHYS(&ci->seek_dcb[0]); 491 /* shuffle any remaining seeks up in the seek-q */ 492 for (i = 1; i < nseeks; i++) 493 ci->seek_dcb[i-1].nxtdcb = 494 (fmt_dcb *)PHYS(&ci->seek_dcb[i]); 495 ci->seek_dcb[nseeks-1].nxtdcb = (fmt_dcb *)PHYS(dcb); 496 } else { 497 if (bp->b_cylin != ci->cur_cyl[slave]) { 498 ci->cur_cyl[slave] = bp->b_cylin; 499 dk_seek[unit]++; 500 } 501 ci->cur_trk[slave] = bp->b_daddr & 0xff; 502 ci->off_cylinder = 0; 503 mdcb->firstdcb = (fmt_dcb *)(PHYS(dcb)); 504 } 505 dcb->opcode = (bp->b_flags & B_READ) ? RD : WD; 506 dcb->intflg = INTDONE; 507 dcb->nxtdcb = (fmt_dcb *)0; /* end of chain */ 508 dcb->operrsta = 0; 509 dcb->devselect = (char)slave; 510 dcb->trailcnt = (char)(sizeof (trrw) / sizeof (long)); 511 dcb->trail.rwtrail.memadr = (char *) 512 vbastart(bp, ci->rawbuf, (long *)ci->map, ci->utl); 513 dcb->trail.rwtrail.wcount = (short)((bp->b_bcount+1) / sizeof (short)); 514 dcb->trail.rwtrail.disk.cylinder = bp->b_cylin; 515 dcb->trail.rwtrail.disk.track = bp->b_daddr & 0xff; 516 dcb->trail.rwtrail.disk.sector = bp->b_daddr >> 8; 517 mdcb->vddcstat = 0; 518 dk_wds[unit] += bp->b_bcount / 32; 519 ci->int_expected = 1; 520 timeout(vd_int_timeout, (caddr_t)ctlr, 20*60); 521 dk_busy |= 1 << unit; 522 scope_out(1); 523 VDDC_ATTENTION((cdr *)(vdminfo[ctlr]->um_addr), 524 (fmt_mdcb *)(PHYS(mdcb)), ci->ctlr_type); 525 } 526 527 /* 528 * Watch for lost interrupts. 529 */ 530 vd_int_timeout(ctlr) 531 register int ctlr; 532 { 533 register ctlr_tab *ci = &vdctlr_info[ctlr]; 534 register fmt_dcb *dcb = &ci->ctlr_dcb; 535 536 uncache(&dcb->operrsta); 537 printf("vd%d: lost interupt, status %x", ctlr, dcb->operrsta); 538 if (ci->ctlr_type == SMD_ECTLR) { 539 uncache(&dcb->err_code); 540 printf(", error code %x", dcb->err_code); 541 } 542 printf("\n"); 543 if ((dcb->operrsta&DCBCMP) == 0) { 544 VDDC_ABORT((cdr *)(vdminfo[ctlr]->um_addr), ci->ctlr_type); 545 dcb->operrsta |= DCBUSC | DCBABT | ANYERR | HRDERR | CTLRERR; 546 } 547 vdintr(ctlr); 548 } 549 550 /* 551 * Handle a disk interrupt. 552 */ 553 vdintr(ctlr) 554 register int ctlr; 555 { 556 register ctlr_tab *ci; 557 register struct buf *cq, *uq, *bp; 558 register int slave, unit; 559 register fmt_mdcb *mdcb; 560 register fmt_dcb *dcb; 561 int code, s; 562 563 untimeout(vd_int_timeout, (caddr_t)ctlr); 564 scope_out(2); 565 ci = &vdctlr_info[ctlr]; 566 if (!ci->int_expected) { 567 printf("vd%d: stray interrupt\n", ctlr); 568 return; 569 } 570 /* 571 * Take first request off controller's queue. 572 */ 573 cq = &vdminfo[ctlr]->um_tab; 574 uq = cq->b_forw; 575 bp = uq->av_forw; 576 unit = VDUNIT(bp->b_dev); 577 dk_busy &= ~(1 << unit); 578 dk_xfer[unit]++; 579 ci->int_expected = 0; 580 /* find associated control blocks */ 581 mdcb = &ci->ctlr_mdcb, uncache(&mdcb->intdcb); 582 dcb = &ci->ctlr_dcb, uncache(&dcb->operrsta); 583 if (ci->ctlr_type == SMD_ECTLR) 584 uncache(&dcb->err_code); 585 slave = uq->b_dev; 586 switch (code = vddecode_error(dcb)) { 587 588 case CTLR_ERROR: 589 case DRIVE_ERROR: 590 if (cq->b_errcnt >= 2) 591 vdhard_error(ci, bp, dcb); 592 if (code == CTLR_ERROR) 593 vdreset_ctlr((cdr *)vdminfo[ctlr]->um_addr, ctlr); 594 else 595 reset_drive((cdr *)vdminfo[ctlr]->um_addr, ctlr, 596 slave, 2); 597 if (cq->b_errcnt++ < 2) { /* retry error */ 598 cq->b_forw = uq->b_back; 599 vdstart(vdminfo[ctlr]); 600 return; 601 } 602 bp->b_resid = bp->b_bcount; 603 break; 604 605 case HARD_DATA_ERROR: 606 vdhard_error(ci, bp, dcb); 607 bp->b_resid = 0; 608 break; 609 610 case SOFT_DATA_ERROR: 611 vdsoft_error(ci, bp, dcb); 612 /* fall thru... */ 613 614 default: /* operation completed */ 615 bp->b_error = 0; 616 bp->b_resid = 0; 617 break; 618 } 619 vbadone(bp, ci->rawbuf, (long *)ci->map, ci->utl); 620 /* 621 * Take next request on this unit q, or, if none, 622 * the next request on the next active unit q. 623 */ 624 s = spl7(); 625 uq->av_forw = bp->av_forw; 626 if (uq->av_back != bp) { 627 register struct buf *next; 628 629 unit = VDUNIT(uq->av_forw->b_dev); 630 slave = vddinfo[unit]->ui_slave; 631 next = uq->av_forw; 632 if (next->b_cylin != ci->cur_cyl[slave] || 633 (next->b_daddr & 0xff) != ci->cur_trk[slave]) 634 ci->off_cylinder |= 1 << slave; 635 } else 636 uq->av_back = NULL; 637 splx(s); 638 /* reset controller state */ 639 cq->b_errcnt = 0; 640 cq->b_active--; 641 scope_out(3); 642 if (bp->b_flags & B_ERROR) 643 bp->b_error = EIO; 644 iodone(bp); 645 vdstart(vdminfo[ctlr]); 646 } 647 648 /* 649 * Convert controller status to internal operation/error code. 650 */ 651 vddecode_error(dcb) 652 register fmt_dcb *dcb; 653 { 654 655 if (dcb->operrsta & HRDERR) { 656 if (dcb->operrsta & (HCRCERR | HCMPERR | UCDATERR | WPTERR | 657 DSEEKERR | NOTCYLERR |DRVNRDY | INVDADR)) 658 return (DRIVE_ERROR); 659 if (dcb->operrsta & (CTLRERR | OPABRT | INVCMD | DNEMEM)) 660 return (CTLR_ERROR); 661 return (HARD_DATA_ERROR); 662 } 663 if (dcb->operrsta & SFTERR) 664 return (SOFT_DATA_ERROR); 665 return (0); 666 } 667 668 /* 669 * Report a hard error. 670 */ 671 vdhard_error(ci, bp, dcb) 672 ctlr_tab *ci; 673 register struct buf *bp; 674 register fmt_dcb *dcb; 675 { 676 unit_tab *ui = &vdunit_info[VDUNIT(bp->b_dev)]; 677 678 bp->b_flags |= B_ERROR; 679 harderr(bp, ui->info.type_name); 680 printf("status %x", dcb->operrsta); 681 if (ci->ctlr_type == SMD_ECTLR) 682 printf(" ecode %x", dcb->err_code); 683 printf("\n"); 684 } 685 686 /* 687 * Report a soft error. 688 */ 689 vdsoft_error(ci, bp, dcb) 690 ctlr_tab *ci; 691 register struct buf *bp; 692 register fmt_dcb *dcb; 693 { 694 unit_tab *ui = &vdunit_info[VDUNIT(bp->b_dev)]; 695 696 printf("%s%d%c: soft error sn%d status %x", ui->info.type_name, 697 minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev)&07), bp->b_blkno, 698 dcb->operrsta); 699 if (ci->ctlr_type == SMD_ECTLR) 700 printf(" ecode %x", dcb->err_code); 701 printf("\n"); 702 } 703 704 /*ARGSUSED*/ 705 vdopen(dev, flag) 706 dev_t dev; 707 int flag; 708 { 709 register unit = VDUNIT(dev); 710 register struct vba_device *vi = vddinfo[unit]; 711 712 if (vi == 0 || vi->ui_alive == 0 || vi->ui_type >= nvddrv) 713 return (ENXIO); 714 if (vdunit_info[unit].info.partition[FILSYS(dev)].par_len == 0) 715 return (ENXIO); 716 return (0); 717 } 718 719 vdread(dev, uio) 720 dev_t dev; 721 struct uio *uio; 722 { 723 register int unit = VDUNIT(dev); 724 register unit_tab *ui = &vdunit_info[unit]; 725 726 if (unit >= NFSD) 727 return (ENXIO); 728 return (physio(vdstrategy, &ui->raw_q_element, dev, B_READ, 729 minphys, uio)); 730 } 731 732 vdwrite(dev, uio) 733 dev_t dev; 734 struct uio *uio; 735 { 736 register int unit = VDUNIT(dev); 737 register unit_tab *ui = &vdunit_info[unit]; 738 739 if (unit >= NFSD) 740 return (ENXIO); 741 return (physio(vdstrategy, &ui->raw_q_element, dev, B_WRITE, 742 minphys, uio)); 743 } 744 745 /* 746 * Crash dump. 747 */ 748 vddump(dev) 749 dev_t dev; 750 { 751 register int unit = VDUNIT(dev); 752 register unit_tab *ui = &vdunit_info[unit]; 753 register fs_tab *fs = &ui->info; 754 register int ctlr = vddinfo[unit]->ui_ctlr; 755 register struct vba_ctlr *vba_vdctlr_info = vdminfo[ctlr]; 756 register int filsys = FILSYS(dev); 757 register cdr *addr = (cdr *)(vba_vdctlr_info->um_addr); 758 register int cur_blk, blkcount, blocks; 759 caddr_t memaddr; 760 761 vdreset_ctlr(addr, ctlr); 762 blkcount = maxfree - 2; /* In 1k byte pages */ 763 if (dumplo + blkcount > fs->partition[filsys].par_len) { 764 blkcount = fs->partition[filsys].par_len - dumplo; 765 printf("vd%d: Dump truncated to %dMB\n", unit, blkcount/1024); 766 } 767 cur_blk = fs->partition[filsys].par_start + dumplo; 768 memaddr = 0; 769 while (blkcount > 0) { 770 blocks = MIN(blkcount, DUMPSIZE); 771 if (!vdwrite_block(addr, ctlr, unit, memaddr, cur_blk, blocks)) 772 return (EIO); 773 blkcount -= blocks; 774 memaddr += blocks * NBPG; 775 cur_blk += blocks; 776 } 777 return (0); 778 } 779 780 /* 781 * Write a block to disk during a crash dump. 782 */ 783 vdwrite_block(caddr, ctlr, unit, addr, block, blocks) 784 register cdr *caddr; 785 register int ctlr, unit; 786 register caddr_t addr; 787 register int block, blocks; 788 { 789 register ctlr_tab *ci = &vdctlr_info[ctlr]; 790 register fmt_mdcb *mdcb = &ci->ctlr_mdcb; 791 register fmt_dcb *dcb = &ci->ctlr_dcb; 792 register unit_tab *ui = &vdunit_info[unit]; 793 register fs_tab *fs = &ui->info; 794 795 block *= (int)ui->sec_per_blk; 796 blocks *= (int)ui->sec_per_blk; 797 mdcb->firstdcb = (fmt_dcb *)(PHYS(dcb)); 798 dcb->intflg = NOINT; 799 dcb->opcode = WD; 800 dcb->operrsta = 0; 801 dcb->devselect = (char)(vddinfo[unit])->ui_slave; 802 dcb->trailcnt = (char)(sizeof (trrw) / sizeof (long)); 803 dcb->trail.rwtrail.memadr = addr; 804 dcb->trail.rwtrail.wcount = (short) 805 ((blocks * fs->secsize)/ sizeof (short)); 806 dcb->trail.rwtrail.disk.cylinder = (short)(block / ui->sec_per_cyl); 807 dcb->trail.rwtrail.disk.track = (char)((block / fs->nsec) % fs->ntrak); 808 dcb->trail.rwtrail.disk.sector = (char)(block % fs->nsec); 809 VDDC_ATTENTION(caddr, (fmt_mdcb *)(PHYS(mdcb)), ci->ctlr_type); 810 if (!vdpoll(ci, caddr, 5)) { 811 printf(" during dump\n"); 812 return (0); 813 } 814 if (dcb->operrsta & HRDERR) { 815 printf("vd%d: hard error, status %x\n", unit, dcb->operrsta); 816 return (0); 817 } 818 return (1); 819 } 820 821 vdsize(dev) 822 dev_t dev; 823 { 824 struct vba_device *vi = vddinfo[VDUNIT(dev)]; 825 826 if (vi == 0 || vi->ui_alive == 0 || vi->ui_type >= nvddrv) 827 return (-1); 828 return (vdunit_info[VDUNIT(dev)].info.partition[FILSYS(dev)].par_len); 829 } 830 831 /* 832 * Perform a controller reset. 833 */ 834 vdreset_ctlr(addr, ctlr) 835 register cdr *addr; 836 register int ctlr; 837 { 838 register struct buf *cq = &vdminfo[ctlr]->um_tab; 839 register struct buf *uq = cq->b_forw; 840 register ctlr_tab *ci = &vdctlr_info[ctlr]; 841 842 VDDC_RESET(addr, ci->ctlr_type); 843 ci->ctlr_started = 0; 844 if (ci->ctlr_type == SMD_ECTLR) { 845 addr->cdr_csr = 0; 846 addr->mdcb_tcf = AM_ENPDA; 847 addr->dcb_tcf = AM_ENPDA; 848 addr->trail_tcf = AM_ENPDA; 849 addr->data_tcf = AM_ENPDA; 850 addr->cdr_ccf = CCF_STS | XMD_32BIT | BSZ_16WRD | 851 CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE | CCF_ERR; 852 } 853 if (vdnotrailer(addr, ctlr, 0, INIT, 10) & HRDERR) { 854 printf("failed to init\n"); 855 return (0); 856 } 857 if (vdnotrailer(addr, ctlr, 0, DIAG, 10) & HRDERR) { 858 printf("diagnostic error\n"); 859 return (0); 860 } 861 /* reset all units attached to controller */ 862 uq = cq->b_forw; 863 do { 864 reset_drive(addr, ctlr, uq->b_dev, 0); 865 uq = uq->b_forw; 866 } while (uq != cq->b_forw); 867 return (1); 868 } 869 870 /* 871 * Perform a reset on a drive. 872 */ 873 reset_drive(addr, ctlr, slave, start) 874 register cdr *addr; 875 register int ctlr, slave, start; 876 { 877 register int type = vdctlr_info[ctlr].unit_type[slave]; 878 879 if (type == UNKNOWN) 880 return; 881 if (!vdconfigure_drive(addr, ctlr, slave, type, start)) 882 printf("vd%d: drive %d: couldn't reset\n", ctlr, slave); 883 } 884 885 /* 886 * Poll controller until operation completes 887 * or timeout expires. 888 */ 889 vdpoll(ci, addr, t) 890 register ctlr_tab *ci; 891 register cdr *addr; 892 register int t; 893 { 894 register fmt_dcb *dcb = &ci->ctlr_dcb; 895 896 t *= 1000; 897 uncache(&dcb->operrsta); 898 while ((dcb->operrsta&(DCBCMP|DCBABT)) == 0) { 899 DELAY(1000); 900 uncache(&dcb->operrsta); 901 if (--t <= 0) { 902 printf("vd%d: controller timeout", ci-vdctlr_info); 903 VDDC_ABORT(addr, ci->ctlr_type); 904 DELAY(30000); 905 uncache(&dcb->operrsta); 906 return (0); 907 } 908 } 909 if (ci->ctlr_type == SMD_ECTLR) { 910 uncache(&addr->cdr_csr); 911 while (addr->cdr_csr&CS_GO) { 912 DELAY(50); 913 uncache(&addr->cdr_csr); 914 } 915 DELAY(300); 916 } 917 DELAY(200); 918 uncache(&dcb->operrsta); 919 return (1); 920 } 921 922 #ifdef notdef 923 /* 924 * Dump the mdcb and DCB for diagnostic purposes. 925 */ 926 vdprintdcb(lp) 927 register long *lp; 928 { 929 register int i, dcb, tc; 930 931 for (dcb = 0; lp; lp = (long *)(*lp), dcb++) { 932 lp = (long *)((long)lp | 0xc0000000); 933 printf("\nDump of dcb%d@%x:", dcb, lp); 934 for (i = 0, tc = lp[3] & 0xff; i < tc+7; i++) 935 printf(" %lx", lp[i]); 936 printf("\n"); 937 } 938 DELAY(1750000); 939 } 940 #endif 941 #endif 942