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