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