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