1 /* scat_vddc.c 1.2 86/01/05 */ 2 3 #include "fsd.h" 4 #if NVD > 0 5 /* 6 ** VDDC Driver - Versabus to SMD direct interface version. 7 ** Written for TAHOE vmunix, CCI-WDC 9/1/83. 8 ** Modified June 1984 to use scatter/gather. 9 */ 10 11 #include "../h/param.h" 12 #include "../h/buf.h" 13 #include "../h/cmap.h" 14 #include "../h/conf.h" 15 #include "../h/dir.h" 16 #include "../h/dk.h" 17 #include "../h/map.h" 18 #include "../tahoe/mtpr.h" 19 #include "../tahoe/pte.h" 20 #include "../h/systm.h" 21 #include "../tahoevba/vbavar.h" 22 #include "../h/user.h" 23 #include "../h/vmmac.h" 24 #include "../h/proc.h" 25 #include "../h/uio.h" 26 #include "../tahoevba/vddc.h" 27 28 int vddebug = 1; /* if = 1, error messages are printed on the console */ 29 int vdintflg = 0; /* if = 1, interrupts are handled by the driver, 30 * otherwise they are just ignored. (during setup) */ 31 32 static struct size FSD[] = { 33 9600, 0, /* minor 0/ 8/16/24 = fsd0a - fsd3a - cyl 0 - 59*/ 34 12000, 9600, /* minor 1/ 9/17/25 = fsd0b - fsd3b - cyl 60 - 134*/ 35 108480, 21600, /* minor 2/10/18/26 = fsd0c - fsd3c - cyl 135 - 812*/ 36 1600, 130080, /* minor 3/11/19/27 = fsd0d - fsd3d - cyl 813 - 822*/ 37 130080, 0, /* minor 4/12/20/28 = fsd0e - fsd3e - cyl 0 - 812*/ 38 131680, 0, /* minor 5/13/21/29 = fsd0f - fsd3f - cyl 0 - 822*/ 39 0, 0, /* Non existent minor device */ 40 0, 0, /* Non existent minor device */ 41 0, 0, /* Non existent minor device */ 42 0, 0, /* Non existent minor device */ 43 0, 0, /* Non existent minor device */ 44 0, 0, /* Non existent minor device */ 45 0, 0, /* Non existent minor device */ 46 0, 0, /* Non existent minor device */ 47 0, 0, /* Non existent minor device */ 48 0, 0, /* Non existent minor device */ 49 }; 50 51 static struct size SMD[]= { 52 20064, 0, /* minor 32/40/48/56 = smd0a - smd3a cyl 0- 65 */ 53 13680, 20064, /* minor 33/41/49/57 = smd0b - smd3b cyl 66- 110 */ 54 214928, 33744, /* minor 34/42/50/58 = smd0c - smd3c cyl 111-817 */ 55 1520, 248672, /* minor 35/43/51/59 = smd0d - smd3d cyl 818-822 */ 56 248672, 0, /* minor 36/44/52/60 = smd0e - smd3e cyl 0-817 */ 57 250192, 0, /* minor 37/45/53/61 = smd0f - smd3f cyl 0-822 */ 58 0, 0, /* minor 38/46/54/62 = smd0g - smd3g */ 59 0, 0, /* minor 39/47/55/63 = smd0h - smd3h */ 60 0, 0, /* Non existent minor device */ 61 0, 0, /* Non existent minor device */ 62 0, 0, /* Non existent minor device */ 63 0, 0, /* Non existent minor device */ 64 0, 0, /* Non existent minor device */ 65 0, 0, /* Non existent minor device */ 66 0, 0, /* Non existent minor device */ 67 0, 0, /* Non existent minor device */ 68 }; 69 70 static struct size XFSD[] = { 71 20352, 0, /* minor 64/72/80/88 = xfsd0a - xfsd3a cyl 0- 52 */ 72 20352, 20352, /* minor 65/73/81/89 = xfsd0b - xfsd3b cyl 53- 105 */ 73 230400, 40704, /* minor 66/74/82/90 = xfsd0c - xfsd3c cyl 106-705 */ 74 1920, 271104, /* minor 67/75/83/91 = xfsd0d - xfsd3d cyl 706-710 */ 75 271104, 0, /* minor 68/76/84/92 = xfsd0e - xfsd3e cyl 0-705 */ 76 273024, 0, /* minor 69/77/85/93 = xfsd0f - xfsd3f cyl 0-710 */ 77 0, 0, /* minor 70/78/86/94 = xfsd0g - xfsd3g */ 78 0, 0, /* minor 71/79/87/95 = xfsd0h - xfsd3h */ 79 0, 0, /* Non existent minor device */ 80 0, 0, /* Non existent minor device */ 81 0, 0, /* Non existent minor device */ 82 0, 0, /* Non existent minor device */ 83 0, 0, /* Non existent minor device */ 84 0, 0, /* Non existent minor device */ 85 0, 0, /* Non existent minor device */ 86 0, 0, /* Non existent minor device */ 87 }; 88 89 /* 90 /* 91 /* Layout of major/minor number assignments for the VDDC devices. 92 /* 93 /* 1 94 /* 5 8 7 4 3 2 0 95 /* +----------------+------+---+-----+ 96 /* | Major device # | TYPE | D | FLS | 97 /* +----------------+------+---+-----+ 98 /* | | |_____ File system # ( 0-7 ) 99 /* | |__________ Drive # (0-3) 100 /* |________________ Drive type ( 0-FSD, 1-SMD ) 101 /* ( 2-XFSD ) (obsolete) 102 /* 103 /********************************************************/ 104 105 #define VDUNIT(x) ((minor(x) & 0x18) >> 3) 106 #define DRVTYPE(x) ((minor(x) & 0xe0) >> 5) (obsolete) 107 #define FLSYS(x) (minor(x) & 0x07) 108 #define PHYS(x) ( vtoph( &proc[2], (int) (x) ) ) 109 110 111 /* Drive types should be in order of drive capacity for auto-configuration */ 112 /* e.g: smallest capacity = drive type 0, highest capacity = type NXPDRV-1 */ 113 114 struct vdst { 115 short nsect; 116 short ntrak; 117 short nspc; 118 short ncyl; 119 struct size *sizes; 120 short dtype; /* type as in byte 5 (drive) of iopb */ 121 char *name; /* drive name for autoconf */ 122 } vdst[] = { 123 124 16, 10, 16*10, 823, FSD, 0, "160 Mb FSD " , 125 16, 19, 16*19, 823, SMD, 1, "300 Mb SMD " , 126 16, 24, 16*24, 711, XFSD, 2, "340 Mb FSD " 127 }; 128 129 130 struct vba_ctlr *vdminfo[NVDDC]; 131 struct vba_device *vddinfo[NUNIT]; 132 133 /* 134 ** Internal Functions 135 */ 136 int vdopen(); 137 int vdclose(); 138 int vdprobe(); /* See if VDDC is really there */ 139 int vd_setup(); /* Called from vdprobe */ 140 int vdslave(); /* See if drive is really there */ 141 int vdattach(); 142 int vddgo(); 143 int vdstrategy(); /* VDDC strategy routine */ 144 int vdstart(); /* Top level interface to device queue */ 145 int vdintr(); /* Top Level ISR */ 146 int vdread(); /* raw i/o read routine */ 147 int vdwrite(); /* raw i/o write routine */ 148 int vddump(); /* dump routine */ 149 int vdsize(); /* sizes for swapconfig */ 150 151 long vdstd[] = { 152 0x0f2000 }; 153 154 struct vba_driver vddriver = 155 { 156 vdprobe, vdslave, vdattach, vddgo, vdstd, 157 "smd/fsd", vddinfo, "VSMD controller ", vdminfo 158 }; 159 160 struct buf vdutab[NUNIT]; 161 struct buf rvdbuf[NUNIT]; 162 char vdbuf[SECTSIZ*2]; 163 extern char vdutl[]; 164 165 /* 166 ** Disk Address 167 */ 168 struct dskadr { 169 char track; /* all 8 bits */ 170 char sector; /* low order 5 bits */ 171 short cylinder; /* low order 12 bits */ 172 }; 173 174 /* 175 ** DCB Trailer Formats 176 **********************************/ 177 178 /* 179 ** Read / Write Trailer 180 */ 181 struct trrw { 182 char *memadr; /* memory address */ 183 long wcount; /* 16 bit word count */ 184 struct dskadr disk; /* disk address */ 185 long scat[MAXBPTE*2+1]; /* gather/scatter trailer */ 186 }; 187 188 /* 189 ** Format Trailer 190 */ 191 struct trfmt { 192 char *addr; /* data buffer to be filled on sector*/ 193 long nsectors; /* # of sectors to be formatted */ 194 struct dskadr disk; 195 struct dskadr hdr; 196 }; 197 198 /* 199 ** Reset / Configure Trailer 200 */ 201 struct treset { 202 long ncyl; /* # cylinders */ 203 long nsurfaces; /* # surfaces */ 204 }; /* # of sectors is defined by VDDC */ 205 /* to be 32/track of 512 data bytes each */ 206 207 /* 208 ** Seek Trailer 209 */ 210 struct trseek { 211 struct dskadr disk; 212 }; 213 214 /* 215 ** DCB Format 216 */ 217 struct fmt_dcb { 218 struct fmt_dcb *nxtdcb; /* next dcb in chain or End of Chain */ 219 short intflg; /* interrupt settings and flags */ 220 short opcode; /* DCB Command code etc... */ 221 long operrsta; /* Error & Status info */ 222 short fill; /* not used */ 223 char devselect; /* Drive selection */ 224 char trailcnt; /* Trailer Word Count */ 225 long err_memadr; /* Error memory address */ 226 short fill2; 227 short err_wcount; /* Error word count */ 228 short err_track; /* Error track/sector */ 229 short err_cyl; /* Error cylinder adr */ 230 union { 231 struct trrw rwtrail; /* read/write trailer */ 232 struct trfmt fmtrail; /* format trailer */ 233 struct treset resetrail; /* reset/configure trailer */ 234 struct trseek seektrail; /* seek trailer */ 235 } trail; 236 }; 237 238 /* 239 ** MDCB Format 240 */ 241 struct fmt_mdcb { 242 struct fmt_dcb *firstdcb; /* first dcb in chain */ 243 struct fmt_dcb *procdcb; /* dcb being processed */ 244 struct fmt_dcb *intdcb; /* dcb causing interrupt */ 245 long vddcstat; /* VDDC status */ 246 }mdcbx; 247 248 /* 249 ** MDCB 250 */ 251 struct fmt_mdcb *mdcb = &mdcbx; 252 253 /* 254 ** DCB 255 */ 256 257 struct fmt_dcb dcbx[NVDDC]; 258 259 int vdtimeout; 260 #define POLLTILLDONE(x) { vdtimeout = 1000*(x); \ 261 uncache((char *)&dcb->operrsta); \ 262 while (! (dcb->operrsta & DCBCMP)) { \ 263 DELAY(1000); \ 264 vdtimeout--; \ 265 uncache((char *)&dcb->operrsta); \ 266 if (vdtimeout <=0) { \ 267 printf("VDDC controller timeout\n"); \ 268 return(0); \ 269 } \ 270 } \ 271 } 272 273 /* 274 ** See if the controller is really there. 275 ** if TRUE - initialize the controller. 276 */ 277 vdprobe(cntrl_vaddr) 278 caddr_t cntrl_vaddr; 279 { 280 if ( badaddr(cntrl_vaddr,2) ) return(0); /* no controller */ 281 else 282 if (vd_setup(cntrl_vaddr)) /* initialize the controller */ 283 return(1); 284 else return(0); /* initialization error */ 285 } 286 287 vd_setup(cntrl_vaddr) 288 caddr_t cntrl_vaddr; 289 { 290 register struct fmt_dcb *dcb = &dcbx[0]; 291 int j; 292 293 VDDC_RESET(cntrl_vaddr); /* Reset the controller */ 294 /* Burn some time ...... needed after accessing reset port */ 295 for (j=0; j<20; j++) 296 DELAY(1000); 297 298 /* setup & issue INIT to initialize VDDC */ 299 300 dcb->opcode = INIT; 301 dcb->nxtdcb = (struct fmt_dcb *)0; 302 dcb->intflg = NOINT; 303 mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb); 304 dcb->operrsta = 0; 305 VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb) ) /* do it */ 306 POLLTILLDONE(1) /* poll till done */ 307 if (dcb->operrsta & HRDERR) { 308 if (vddebug) 309 printf("VDDC INIT error. Status = %x\n",dcb->operrsta); 310 return(0); 311 } 312 /* setup & issue DIAGNOSE */ 313 314 dcb->opcode = DIAG; 315 dcb->nxtdcb = (struct fmt_dcb *)0; 316 dcb->intflg = NOINT; 317 mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb); 318 dcb->operrsta = 0; 319 VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb) ) /* do it */ 320 POLLTILLDONE(1) /* poll till done */ 321 if (dcb->operrsta & HRDERR) { 322 if (vddebug) 323 printf("VDDC DIAGNOSE error. Status = %x\n",dcb->operrsta); 324 return(0); 325 } 326 /* Start drives command */ 327 /* 328 /* dcb->opcode = VDSTART; 329 /* dcb->nxtdcb = (struct fmt_dcb *)0; 330 /* dcb->intflg = NOINT; 331 /* mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb); 332 /* dcb->operrsta = 0; 333 /* VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb) ) /* do it */ 334 /* POLLTILLDONE(20) /* poll till done */ 335 /* if (dcb->operrsta & HRDERR) { 336 /* if (vddebug) 337 /* printf("VDDC START DRIVES error. Status = %x\n",dcb->operrsta); 338 /* return(0); 339 /* } 340 /**/ 341 return(1); 342 } 343 344 /* 345 * See if a drive is really there 346 * Try to Reset/Configure the drive, then test its status. 347 */ 348 vdslave(ui,cntrl_vaddr) 349 register struct vba_device *ui; 350 register caddr_t cntrl_vaddr; 351 { 352 register struct fmt_dcb *dcb = &dcbx[0]; 353 register struct vdst *st; 354 int dsktype; 355 356 /* 357 ** check drive status - see if drive exists. 358 */ 359 dcb->opcode = VDSTATUS; 360 dcb->intflg = NOINT; 361 dcb->operrsta = 0; 362 dcb->devselect = (char)ui->ui_slave; 363 dcb->trailcnt = (char)0; 364 mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb); 365 mdcb->vddcstat = 0; 366 VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb)) /* do it */ 367 POLLTILLDONE(5) 368 /* 369 if (dcb->operrsta & HRDERR) { 370 if (vddebug) 371 printf("VDDC STATUS error. Status = %x, drive %d\n",dcb->operrsta,ui->ui_slave); 372 return(0); 373 } 374 */ 375 uncache((char *)&mdcb->vddcstat); 376 if (mdcb->vddcstat & DRVNRDY) return(0); /* not ready-> non existent */ 377 378 /* 379 * drive is alive, now get its type! 380 * Seek on all drive types starting from the largest one. 381 * a sucessful seek to the last sector/cylinder/track verifies 382 * the drive type connected to this port. 383 */ 384 for (dsktype = NVDDRV-1; dsktype >= 0; dsktype--) { 385 st = &vdst[dsktype]; 386 dcb->opcode = RSTCFG; /* configure drive command */ 387 dcb->intflg = NOINT; 388 dcb->operrsta = 0; 389 dcb->trail.resetrail.ncyl = st->ncyl; 390 dcb->trail.resetrail.nsurfaces = st->ntrak; 391 dcb->devselect = (char)ui->ui_slave; 392 dcb->trailcnt = (char)2; 393 mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb); 394 VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb) ) /* do it */ 395 POLLTILLDONE(3) 396 if (dcb->operrsta & HRDERR) { 397 if (vddebug) 398 printf("VDDC RESET/CONFIGURE error. Status = %x\n",dcb->operrsta); 399 return(0); 400 } 401 mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb); 402 dcb->intflg = NOINT; 403 dcb->opcode = RD; 404 dcb->operrsta = 0; 405 dcb->devselect = (char)ui->ui_slave; 406 dcb->trailcnt = (char)3; 407 dcb->trail.rwtrail.memadr = (char *)PHYS(vdbuf); 408 dcb->trail.rwtrail.wcount = SECTSIZ; 409 dcb->trail.rwtrail.disk.cylinder = st->ncyl -2; 410 dcb->trail.rwtrail.disk.track = st->ntrak -1; 411 dcb->trail.rwtrail.disk.sector = 0; 412 VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb) ) /* do it */ 413 POLLTILLDONE(3) 414 if ( (dcb->operrsta & HRDERR) == 0) 415 /* found the drive type! */ 416 break; 417 } 418 if (dsktype < 0) { 419 /* If reached here, a drive which is not defined in the 420 * 'vdst' tables is connected. Cannot set it's type. 421 */ 422 printf("VDDC error, unrecognized drive type, drive %d\n",ui->ui_slave); 423 return(0); 424 } 425 ui->ui_type = dsktype; 426 vddriver.ud_dname = st->name; 427 return(1); 428 } 429 430 vdattach(ui) 431 struct vba_device *ui; 432 { 433 } 434 435 vddgo(um) 436 struct vba_ctlr *um; 437 { 438 } 439 440 #define b_cylin b_resid 441 442 vdstrategy(bp) 443 register struct buf *bp; 444 { 445 register struct vba_device *ui; 446 register struct vba_ctlr *um; 447 register int unit; 448 register struct buf *dp; 449 register struct size *sizep; 450 int index, blocks, s; 451 452 vdintflg = 1; /* enable interrupts handling by the driver */ 453 blocks = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; 454 if (bp->b_bcount > NBPG*MAXBPTE) { 455 printf ("VDDC I/O length error: %d\n", bp->b_bcount); 456 goto bad1; 457 } 458 unit = VDUNIT(bp->b_dev); 459 ui = vddinfo[unit]; 460 if (ui == 0 || ui->ui_alive == 0) goto bad1; 461 index = FLSYS(bp->b_dev); /* get file system index */ 462 sizep = vdst[ui->ui_type].sizes; 463 if (bp->b_blkno < 0 || 464 (dkblock(bp)+blocks > sizep[index].nblocks)) /* disk overflow */ 465 goto bad1; 466 s = spl8(); 467 dp = &vdutab[ui->ui_unit]; 468 bp->b_resid = bp->b_blkno ; /* block # plays same role as 469 cylinder # for disksort, as long 470 as increasing blocks correspond to 471 increasing cylinders on disk */ 472 473 disksort(dp, bp); 474 if (dp->b_active == 0) { /* unit is on controller queue */ 475 /* put the device on the controller queue */ 476 dp->b_forw = NULL; /* end of queue indicator */ 477 um = ui->ui_mi; /* get controller structure !! */ 478 if (um->um_tab.b_actf == NULL) /* controller queue is empty */ 479 um->um_tab.b_actf = dp; 480 else 481 um->um_tab.b_actl->b_forw = dp; /* add into queue */ 482 um->um_tab.b_actl = dp; /* update queue tail */ 483 dp->b_active ++; 484 } 485 bp = &ui->ui_mi->um_tab; /* controller structure addr */ 486 if (bp->b_actf && /* cntrl queue not empty */ 487 bp->b_active == 0) /* controller not active */ 488 (void) vdstart(ui->ui_mi);/* go start I/O */ 489 splx(s); 490 return; 491 492 bad1: 493 bp->b_flags |= B_ERROR; 494 iodone(bp); 495 return; 496 } 497 498 499 /* 500 * Start up a transfer on a drive. 501 */ 502 vdstart(um) 503 register struct vba_ctlr *um; 504 { 505 register struct buf *bp, *dp; 506 register struct fmt_dcb *dcb = &dcbx[um->um_ctlr]; 507 struct size *sizep; /* Pointer to one of the tables */ 508 register struct vdst *st; 509 register int index ; /* Index in the relevant table */ 510 register int phadr; /* Buffer's physical address */ 511 register caddr_t cntrl_vaddr = um->um_addr; 512 register struct proc *this_proc; 513 register long phaddr, vaddr, length, i; 514 register long *longp; 515 int sblock, unit; 516 517 loop: 518 /* 519 * Pull a request off the controller queue 520 */ 521 if ((dp = um->um_tab.b_actf) == NULL) 522 return ; 523 if ((bp = dp->b_actf) == NULL) { 524 dp->b_active = 0; /* device removed from ctlr queue */ 525 um->um_tab.b_actf = dp->b_forw; 526 goto loop; 527 } 528 /* 529 * Mark controller busy, and 530 * prepare a command packet for the controller. 531 */ 532 um->um_tab.b_active++; 533 unit = VDUNIT(bp->b_dev); 534 st = &vdst[vddinfo[unit]->ui_type]; 535 index = FLSYS(bp->b_dev); 536 sizep = st->sizes; 537 mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb); 538 dcb->intflg = INTDUN; /* interrupt on completion */ 539 540 dcb->operrsta = 0; 541 dcb->devselect = VDUNIT(bp->b_dev); 542 sblock = sizep[index].block0 + bp->b_blkno; 543 dcb->trail.rwtrail.disk.cylinder = (short)(sblock / st->nspc); 544 dcb->trail.rwtrail.disk.track=(char)((sblock % st->nspc) / st->nsect); 545 dcb->trail.rwtrail.disk.sector = (char)(sblock*2 % (st->nsect*2)); 546 if (bp->b_flags & B_DIRTY || bp->b_proc==0) this_proc = &proc[2]; 547 else this_proc = bp->b_proc; 548 phaddr = vtoph(this_proc, bp->b_un.b_addr); /* start addresses */ 549 vaddr = (int)bp->b_un.b_addr; 550 length = (bp->b_bcount+1) & ~1; /* total # of bytes */ 551 printf("\nvaddr=%x length=%x\n", vaddr, length); 552 dcb->trail.rwtrail.memadr = (char *)phaddr; /* default trailer */ 553 printf("%x ", dcb->trail.rwtrail.memadr); 554 i = imin ( NBPG-(phaddr&PGOFSET),length); /* bytes in this page */ 555 dcb->trail.rwtrail.wcount = i/2; 556 if (i != 0x400) printf("/%x ", i/2); 557 dcb->trailcnt = 3; 558 /* 559 * If all required bytes fit into one page frame, that's it. 560 * Otherwise we have to generate a scatter/gather trailer. 561 */ 562 length -= i; 563 vaddr += i; 564 longp = dcb->trail.rwtrail.scat; /* 1'st pair address */ 565 while (length > 0) { 566 i = imin ( NBPG-(phaddr&PGOFSET),length); 567 *longp++ = i/2; 568 *longp++ = vtoph (this_proc, vaddr); 569 vaddr += i; 570 length -= i; 571 dcb->trailcnt += 2; 572 } 573 *longp++ = 0; /* End of list */ 574 *longp = 0; /* End of list */ 575 /*********** 576 dcb->trailcnt +=2 ; 577 ***********/ 578 if (bp->b_flags & B_READ) { /* Read or read&scatter */ 579 if (dcb->trailcnt == 3) dcb->opcode = RD; 580 else dcb->opcode = RAS; 581 } else { /* Write or gather&write */ 582 if (dcb->trailcnt == 3) dcb->opcode = WD; 583 else dcb->opcode = GAW; 584 } 585 while (longp >= (long *)dcb) 586 printf("%x\n", *longp--); 587 588 #ifdef VDDCPERF 589 scope_out(1); 590 #endif 591 592 VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb)) /* do it */ 593 } 594 595 596 /* 597 * Handle a disk interrupt. 598 */ 599 vdintr(vdnum) 600 register vdnum; 601 { 602 register struct buf *bp, *dp; 603 register struct vba_ctlr *um = vdminfo[vdnum]; 604 register struct fmt_dcb *dcb = &dcbx[vdnum]; 605 register int cnt; 606 607 #ifdef VDDCPERF 608 scope_out(2); 609 #endif 610 printf("vddc 1\n"); 611 if (intenable == 0 || vdintflg == 0) /* ignore all interrupts */ 612 return; 613 if (um->um_tab.b_active == NULL) return;/* unexpected interrupt */ 614 uncache((char *)&mdcb->intdcb); 615 uncache((char *)&dcb->operrsta); 616 if ( mdcb->intdcb != (struct fmt_dcb *)PHYS(dcb)) { /* dcb causing interrupt */ 617 printf("VDDC error - dcb causing interrupt (%x) is different from expected dcb (%x) Interrupt ignored\n", mdcb->intdcb,dcb); 618 return; 619 } 620 if (! (dcb->operrsta & DCBCMP)) { /* unexpected interrupt */ 621 printf("VDDC Unexpected interrupt, DCB completed not set. Status = %x\n",dcb->operrsta); 622 return; 623 } 624 dp = um->um_tab.b_actf; /* device queue head in ctlr queue */ 625 bp = dp->b_actf; /* first buffer in device queue */ 626 if (dcb->operrsta & HRDERR) { 627 printf("VDDC hard error - dcb status = %x\n",dcb->operrsta); 628 bp->b_flags |= B_ERROR; 629 } 630 else if (dcb->operrsta & SFTERR) 631 printf("Soft error on VDDC,status = %x, dev=%x, block # %d\n", 632 dcb->operrsta, bp->b_dev, bp->b_blkno); 633 634 /* 635 * If this was a read, we have to purge the data cache for the 636 * rigth virtual pages. It could be nice to just change the 637 * relevant process's data key but this key is in PCB, in _u, 638 * which can be on the disk right now. And besides, what about 639 * reads into the system space? There's no key to change there. 640 */ 641 if (bp->b_flags & B_READ) { 642 printf("vddc 2\n"); 643 if (dcb->opcode == RAS) { /* Multiple pages read */ 644 printf("vddc 3\n"); 645 for (cnt=bp->b_bcount; cnt>=0; cnt -= NBPG) 646 mtpr ((caddr_t)bp->b_un.b_addr+cnt-1, P1DC); 647 if ( ((int)bp->b_un.b_addr & PGOFSET) != 0 ) 648 mtpr ((caddr_t)bp->b_un.b_addr, P1DC); 649 } else { /* Only one page read */ 650 mtpr ((caddr_t)bp->b_un.b_addr, P1DC); 651 printf("vddc 4\n"); 652 } 653 } 654 655 um->um_tab.b_active = 0; 656 um->um_tab.b_errcnt = 0; 657 if (dp->b_forw != NULL) { /* more than 1 unit on queue */ 658 um->um_tab.b_actf = dp->b_forw; /* next device on ctlr queue */ 659 dp->b_forw = um->um_tab.b_actl->b_forw; /* be last in queue */ 660 um->um_tab.b_actl->b_forw = dp; /* last points now to dp */ 661 um->um_tab.b_actl = dp; /* pointer in ctlr structure */ 662 } 663 dp->b_errcnt = 0; 664 dp->b_actf = bp->av_forw; /* remove first from queue */ 665 bp->b_resid = 0; /* All data read here */ 666 667 #ifdef VDDCPERF 668 scope_out(3); 669 #endif 670 671 printf("vddc 5\n"); 672 iodone(bp); 673 printf("vddc 6\n"); 674 vdstart(um); /* start requests for next device on queue */ 675 printf("vddc 7\n"); 676 } 677 678 679 vdread(dev, uio) 680 dev_t dev; 681 struct uio *uio; 682 { 683 register int unit = VDUNIT(dev); 684 register int error; 685 686 if (unit >= NUNIT) return ( ENXIO ); 687 else return 688 (physio(vdstrategy, &rvdbuf[unit], dev, B_READ, minphys, uio)); 689 } 690 691 vdwrite(dev, uio) 692 dev_t dev; 693 struct uio *uio; 694 { 695 register int unit = VDUNIT(dev); 696 register int error; 697 698 if (unit >= NUNIT) return (ENXIO); 699 else return 700 (physio(vdstrategy, &rvdbuf[unit], dev, B_WRITE,minphys, uio)); 701 } 702 703 #define DUMPSIZE 32 /* Up to 32k at a time - controller limit */ 704 705 vddump(dev) 706 dev_t dev; 707 /* 708 * Dump the main memory to the given device. 709 */ 710 { 711 register struct vba_ctlr *um; 712 register struct fmt_dcb *dcb = &dcbx[0]; 713 register struct vdst *st; 714 register int unit; 715 register caddr_t cntrl_vaddr ; 716 register struct size *sizep; /* Pointer to one of the tables */ 717 int index,sblock,blkcount,thiscount; 718 int memaddr; 719 720 unit = VDUNIT(dev); 721 um = (vddinfo[unit])->ui_mi; 722 st = &vdst[(vddinfo[unit])->ui_type]; 723 dcb = &dcbx[um->um_ctlr]; 724 cntrl_vaddr = um->um_addr; 725 memaddr = 0x0; 726 index = FLSYS(dev); 727 sizep = st->sizes; 728 blkcount = maxfree - 2; /* In 1k byte pages */ 729 if (dumplo + blkcount > sizep[index].nblocks) return(EINVAL); 730 sblock = sizep[index].block0 + dumplo; 731 while (blkcount > 0) { 732 thiscount = MIN (blkcount, DUMPSIZE); 733 mdcb->firstdcb = (struct fmt_dcb *)PHYS(dcb); 734 dcb->intflg = NOINT; 735 dcb->opcode = WD; 736 dcb->operrsta = 0; 737 dcb->devselect = unit; 738 dcb->trailcnt = (char)3; 739 dcb->trail.rwtrail.memadr = (char *)memaddr; 740 dcb->trail.rwtrail.wcount = thiscount*512; 741 dcb->trail.rwtrail.disk.cylinder= (short)(sblock/st->nspc); 742 dcb->trail.rwtrail.disk.track = (char)((sblock % st->nspc) 743 / st->nsect); 744 dcb->trail.rwtrail.disk.sector = (char)(sblock*2 % (st->nsect*2)); 745 VDDC_ATTENTION(cntrl_vaddr,PHYS(mdcb) ) /* do it */ 746 POLLTILLDONE(5); 747 if (dcb->operrsta & HRDERR) { 748 if (vddebug) 749 printf("VDDC DUMP error. Status = %x\n", 750 dcb->operrsta); 751 return(EIO); 752 }; 753 blkcount -= thiscount; 754 memaddr += thiscount*NBPG; 755 sblock += thiscount; 756 } 757 return(0); 758 } 759 760 vdopen(dev, flag) 761 register dev_t dev; 762 int flag; 763 { 764 register struct vba_device *ui; 765 register unit = VDUNIT(dev); 766 767 ui = vddinfo[unit]; 768 if (ui == 0 || ui->ui_alive == 0 || ui->ui_type >= NVDDRV) 769 return ENXIO; 770 return 0; 771 } 772 773 vdsize(dev) 774 register dev_t dev; 775 { 776 register struct vba_device *ui; 777 register unit = VDUNIT(dev); 778 779 ui = vddinfo[unit]; 780 if (ui == 0 || ui->ui_alive == 0 || ui->ui_type >= NVDDRV) 781 return -1; 782 return vdst[ui->ui_type].sizes[FLSYS(dev)].nblocks; 783 } 784 #endif 785