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