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