1 /* 2 * Copyright (c) 1992 OMRON Corporation. 3 * Copyright (c) 1992, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * OMRON Corporation. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)sd.c 8.1 (Berkeley) 06/10/93 12 */ 13 14 /* 15 * sd.c -- SCSI Disk Device Driver 16 * remaked by A.Fujita, MAR-22-1992 17 */ 18 19 /* 20 * SCSI CCS (Command Command Set) disk driver. 21 */ 22 #include "sd.h" 23 #if NSD > 0 24 25 #include <sys/param.h> 26 #include <sys/systm.h> 27 #include <sys/buf.h> 28 #include <sys/dkstat.h> 29 #include <sys/proc.h> 30 #include <sys/disklabel.h> 31 32 #include <luna68k/dev/device.h> 33 #include <luna68k/dev/scsireg.h> 34 #include <luna68k/dev/scsivar.h> 35 36 int sdinit(), sdstrategy(), sdstart(), sdintr(); 37 38 struct driver sddriver = { 39 sdinit, "sd", sdstart, (int (*)()) 0, sdintr, (int (*)()) 0 40 }; 41 42 struct disklabel sdlabel[NSD]; 43 44 struct sd_softc { 45 struct hp_device *sc_hd; 46 struct scsi_queue sc_dq; 47 short sc_flags; 48 short sc_type; /* drive type */ 49 short sc_punit; /* physical unit (scsi lun) */ 50 u_int sc_blks; /* number of blocks on device */ 51 int sc_blksize; /* device block size in bytes */ 52 u_int sc_wpms; /* average xfer rate in 16 bit wds/sec. */ 53 } sd_softc[NSD]; 54 55 /* sc_flags values */ 56 #define SDF_ALIVE 0x1 57 58 struct buf sdtab[NSD]; 59 struct scsi_fmt_sense sdsense[NSD]; 60 61 static struct scsi_fmt_cdb sd_read_cmd = { 10, CMD_READ_EXT }; 62 static struct scsi_fmt_cdb sd_write_cmd = { 10, CMD_WRITE_EXT }; 63 64 #define sdunit(x) ((minor(x) >> 3) & 0x7) 65 #define sdpart(x) (minor(x) & 0x7) 66 #define sdpunit(x) ((x) & 7) 67 #define sdminor(unit, part) (((unit) << 3) | (part)) 68 69 #define b_lba b_resid 70 71 #define SDRETRY 3 /* IO retry count */ 72 73 struct sd_iostat { 74 int imax; 75 int imin; 76 int omax; 77 int omin; 78 }; 79 80 struct sd_iostat sd_iostat[NSD] = { 81 { 14000, -1, 100, -1 }, 82 }; 83 84 /* 85 * Initialize 86 */ 87 88 int 89 sdinit(hd) 90 register struct hp_device *hd; 91 { 92 register struct sd_softc *sc = &sd_softc[hd->hp_unit]; 93 register struct disklabel *lp; 94 char *msg, *sdreadlabel(); 95 96 sc->sc_hd = hd; 97 sc->sc_punit = sdpunit(hd->hp_flags); 98 sc->sc_type = sdident(sc, hd); 99 if (sc->sc_type < 0) 100 return(0); 101 sc->sc_dq.dq_ctlr = hd->hp_ctlr; 102 sc->sc_dq.dq_unit = hd->hp_unit; 103 sc->sc_dq.dq_slave = hd->hp_slave; 104 sc->sc_dq.dq_driver = &sddriver; 105 106 /* 107 * Use the default sizes until we've read the label, 108 * or longer if there isn't one there. 109 */ 110 lp = &sdlabel[hd->hp_unit]; 111 112 if (lp->d_secpercyl == 0) { 113 lp->d_secsize = DEV_BSIZE; 114 lp->d_nsectors = 32; 115 lp->d_ntracks = 20; 116 lp->d_secpercyl = 32*20; 117 lp->d_npartitions = 1; 118 lp->d_partitions[0].p_offset = 0; 119 lp->d_partitions[0].p_size = LABELSECTOR + 1; 120 } 121 122 /* 123 * read disklabel 124 */ 125 if (msg = sdreadlabel(makedev(4, (hd->hp_unit<<3)), sdstrategy, lp)) { 126 if (msg != NULL) { 127 printf("sd%d: %s\n", hd->hp_unit, msg); 128 return(0); 129 } 130 } 131 132 sc->sc_flags = SDF_ALIVE; 133 return(1); 134 } 135 136 static struct scsi_inquiry inqbuf; 137 static struct scsi_fmt_cdb inq = { 138 6, 139 CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0 140 }; 141 142 static u_long capbuf[2]; 143 struct scsi_fmt_cdb cap = { 144 10, 145 CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 146 }; 147 148 int 149 sdident(sc, hd) 150 struct sd_softc *sc; 151 struct hp_device *hd; 152 { 153 char idstr[32]; 154 int unit; 155 register int ctlr, slave; 156 register int i; 157 register int tries = 10; 158 159 ctlr = hd->hp_ctlr; 160 slave = hd->hp_slave; 161 unit = sc->sc_punit; 162 163 /* 164 * See if unit exists and is a disk then read block size & nblocks. 165 */ 166 while ((i = scsi_test_unit_rdy(ctlr, slave, unit)) != 0) { 167 if (i < 0 || --tries < 0) 168 return (-1); 169 if (i == STS_CHECKCOND) { 170 u_char sensebuf[8]; 171 struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf; 172 173 scsi_request_sense(ctlr, slave, unit, sensebuf, 8); 174 if (sp->class == 7 && sp->key == 6) 175 /* drive doing an RTZ -- give it a while */ 176 DELAY(1000000); 177 } 178 DELAY(1000); 179 } 180 if (scsi_immed_command(ctlr, slave, unit, &inq, (u_char *)&inqbuf, 181 sizeof(inqbuf)) || 182 scsi_immed_command(ctlr, slave, unit, &cap, (u_char *)&capbuf, 183 sizeof(capbuf))) 184 /* doesn't exist or not a CCS device */ 185 return (-1); 186 187 switch (inqbuf.type) { 188 case 0: /* disk */ 189 case 4: /* WORM */ 190 case 5: /* CD-ROM */ 191 case 7: /* Magneto-optical */ 192 break; 193 default: /* not a disk */ 194 return (-1); 195 } 196 sc->sc_blks = capbuf[0]; 197 sc->sc_blksize = capbuf[1]; 198 199 bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28); 200 for (i = 27; i > 23; --i) 201 if (idstr[i] != ' ') 202 break; 203 idstr[i+1] = 0; 204 for (i = 23; i > 7; --i) 205 if (idstr[i] != ' ') 206 break; 207 idstr[i+1] = 0; 208 for (i = 7; i >= 0; --i) 209 if (idstr[i] != ' ') 210 break; 211 idstr[i+1] = 0; 212 printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8], 213 &idstr[24]); 214 215 printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize); 216 if (sc->sc_blksize != DEV_BSIZE) { 217 printf("sd%d: need %d byte blocks - drive ignored\n", unit, DEV_BSIZE); 218 return(1); 219 } 220 221 sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2); /* XXX */ 222 return(inqbuf.type); 223 } 224 225 226 /* 227 * Open 228 */ 229 230 int 231 sdopen(dev, flags, mode, p) 232 dev_t dev; 233 int flags, mode; 234 struct proc *p; 235 { 236 register int unit = sdunit(dev); 237 register struct sd_softc *sc = &sd_softc[unit]; 238 239 if (unit >= NSD) 240 return(ENXIO); 241 if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(p->p_ucred, &p->p_acflag)) 242 return(ENXIO); 243 244 if (sc->sc_hd->hp_dk >= 0) 245 dk_wpms[sc->sc_hd->hp_dk] = sc->sc_wpms; 246 return(0); 247 } 248 249 250 /* 251 * Close 252 */ 253 254 int 255 sdclose(dev, flag, mode, p) 256 dev_t dev; 257 int flag, mode; 258 struct proc *p; 259 { 260 } 261 262 /* 263 * Strategy 264 */ 265 266 int 267 sdstrategy(bp) 268 register struct buf *bp; 269 { 270 register int unit = sdunit(bp->b_dev); 271 register int part = sdpart(bp->b_dev); 272 register struct sd_softc *sc = &sd_softc[unit]; 273 register struct disklabel *lp = &sdlabel[unit]; 274 register struct partition *pp = &(lp->d_partitions[part]); 275 register struct buf *dp = &sdtab[unit]; 276 register daddr_t bn; 277 register int sz, s; 278 279 bn = bp->b_blkno; 280 sz = howmany(bp->b_bcount, DEV_BSIZE); 281 282 /* check that tracsfer is within a drive's partition */ 283 284 if (bn < 0 || (bn + sz) > pp->p_size) { 285 sz = pp->p_size - bn; 286 if (sz == 0) { 287 bp->b_resid = bp->b_bcount; 288 goto done; 289 } 290 if (sz < 0) { 291 bp->b_error = EINVAL; 292 bp->b_flags |= B_ERROR; 293 goto done; 294 } 295 bp->b_bcount = dbtob(sz); 296 } 297 298 /* calculate LBA for transfer */ 299 300 bp->b_lba = bn + pp->p_offset; 301 302 /* raise priority to block sdintr */ 303 304 s = splbio(); 305 306 /* call disksort to sort request into drive queue */ 307 308 disksort(dp, bp); 309 310 if (dp->b_active == 0) { /* */ 311 dp->b_active = 1; 312 sdustart(unit); 313 } 314 315 /* lower priority */ 316 317 splx(s); 318 319 return; 320 321 done: 322 biodone(bp); 323 } 324 325 int 326 sdustart(unit) 327 register int unit; 328 { 329 register struct sd_softc *sc = &sd_softc[unit]; 330 register struct hp_device *hp = sc->sc_hd; 331 register struct scsi_queue *dq = &sc->sc_dq; 332 register struct buf *bp = sdtab[unit].b_actf; 333 register struct scsi_fmt_cdb *cmd; 334 335 cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd; 336 *(int *)(&cmd->cdb[2]) = bp->b_lba; 337 *(u_short *)(&cmd->cdb[7]) = howmany(bp->b_bcount, DEV_BSIZE); 338 339 dq->dq_cdb = cmd; 340 dq->dq_bp = bp; 341 dq->dq_flags = DQ_DISCONNECT; /* SCSI Disconnect */ 342 343 if (screq(dq)) 344 sdstart(unit); 345 } 346 347 int 348 sdstart(unit) 349 register int unit; 350 { 351 register struct sd_softc *sc = &sd_softc[unit]; 352 register struct hp_device *hp = sc->sc_hd; 353 354 if (hp->hp_dk >= 0) { 355 dk_busy |= 1 << hp->hp_dk; 356 } 357 358 scstart(hp->hp_ctlr); 359 } 360 361 362 /* 363 * Return: 364 * 0 if not really an error 365 * <0 if we should do a retry 366 * >0 if a fatal error 367 */ 368 static int 369 sderror(unit, sc, hp, stat) 370 int unit, stat; 371 register struct sd_softc *sc; 372 register struct hp_device *hp; 373 { 374 int cond = 1; 375 376 sdsense[unit].status = stat; 377 if (stat & STS_CHECKCOND) { 378 struct scsi_xsense *sp; 379 380 scsi_request_sense(hp->hp_ctlr, hp->hp_slave, 381 sc->sc_punit, sdsense[unit].sense, 382 sizeof(sdsense[unit].sense)); 383 sp = (struct scsi_xsense *)sdsense[unit].sense; 384 printf("sd%d: scsi sense class %d, code %d", unit, 385 sp->class, sp->code); 386 if (sp->class == 7) { 387 printf(", key %d", sp->key); 388 if (sp->valid) 389 printf(", blk %d", *(int *)&sp->info1); 390 switch (sp->key) { 391 /* no sense, try again */ 392 case 0: 393 cond = -1; 394 break; 395 /* recovered error, not a problem */ 396 case 1: 397 cond = 0; 398 break; 399 } 400 } 401 printf("\n"); 402 } 403 return(cond); 404 } 405 406 /* 407 * Interrupt 408 */ 409 410 int 411 sdintr(unit, stat) 412 register int unit; 413 int stat; 414 { 415 register struct sd_softc *sc = &sd_softc[unit]; 416 register struct hp_device *hp = sc->sc_hd; 417 register struct scsi_queue *dq = &sc->sc_dq; 418 register struct buf *bp = dq->dq_bp; 419 int cond; 420 421 if (stat == SC_IO_TIMEOUT) { 422 printf("sdintr: sd%d timeout error\n", unit, stat); 423 } 424 425 if (hp->hp_dk >= 0) { 426 dk_busy &=~ (1 << hp->hp_dk); 427 if (stat == 0) { 428 ++dk_seek[hp->hp_dk]; 429 ++dk_xfer[hp->hp_dk]; 430 dk_wds[hp->hp_dk] += bp->b_bcount >> 6; 431 } 432 } 433 434 if (bp->b_flags & B_READ) { 435 sd_iostat[unit].imin = min(dq->dq_imin, sd_iostat[unit].imin); 436 if (dq->dq_imax > sd_iostat[unit].imax) { 437 sd_iostat[unit].imax = dq->dq_imax; 438 #ifdef SD_IOSTAT 439 printf("sdintr: sd%d INPUT MAX = %d, MIN = %d\n", 440 unit, sd_iostat[unit].imax, sd_iostat[unit].imin); 441 #endif 442 } 443 } else { 444 sd_iostat[unit].omin = min(dq->dq_omin, sd_iostat[unit].omin); 445 if (dq->dq_omax > sd_iostat[unit].omax) { 446 sd_iostat[unit].omax = dq->dq_omax; 447 #ifdef SD_IOSTAT 448 printf("sdintr: sd%d OUTPUT MAX = %d, MIN = %d\n", 449 unit, sd_iostat[unit].omax, sd_iostat[unit].omin); 450 #endif 451 } 452 } 453 454 if (stat != 0) { 455 if (stat > 0) { 456 #ifdef DEBUGPRINT 457 dbgprintall(); 458 printf("\n"); 459 #endif 460 cond = sderror(unit, sc, hp, stat); 461 if (cond) { 462 if (cond < 0 && sdtab[unit].b_errcnt++ < SDRETRY) { 463 sdstart(unit); 464 return; 465 } 466 } 467 } else { 468 if (sdtab[unit].b_errcnt++ < SDRETRY) { 469 printf("sdintr: sd%d restart IO request\n", unit); 470 sdstart(unit); 471 return; 472 } 473 } 474 bp->b_flags |= B_ERROR; 475 bp->b_error = EIO; 476 } 477 478 sdtab[unit].b_errcnt = 0; 479 sdtab[unit].b_actf = bp->b_actf; 480 481 bp->b_resid = 0; 482 483 biodone(bp); 484 485 scfree(dq); 486 487 if (sdtab[unit].b_actf) { 488 sdustart(unit); 489 } else { 490 sdtab[unit].b_active = 0; 491 } 492 } 493 494 495 /* 496 * RAW Device Routines 497 */ 498 499 int 500 sdread(dev, uio, flags) 501 dev_t dev; 502 struct uio *uio; 503 int flags; 504 { 505 register int unit = sdunit(dev); 506 507 return (physio(sdstrategy, NULL, dev, B_READ, minphys, uio)); 508 } 509 510 int 511 sdwrite(dev, uio, flags) 512 dev_t dev; 513 struct uio *uio; 514 int flags; 515 { 516 register int unit = sdunit(dev); 517 518 return (physio(sdstrategy, NULL, dev, B_WRITE, minphys, uio)); 519 } 520 521 int 522 sdioctl(dev, cmd, data, flag, p) 523 dev_t dev; 524 int cmd; 525 caddr_t data; 526 int flag; 527 struct proc *p; 528 { 529 int unit = sdunit(dev); 530 register struct sd_softc *sc = &sd_softc[unit]; 531 register struct disklabel *lp = &sdlabel[unit]; 532 int error = 0; 533 534 switch (cmd) { 535 536 case DIOCGDINFO: 537 *(struct disklabel *)data = *lp; 538 break; 539 540 case DIOCGPART: 541 ((struct partinfo *)data)->disklab = lp; 542 ((struct partinfo *)data)->part = 543 &lp->d_partitions[sdpart(dev)]; 544 break; 545 546 case DIOCWLABEL: 547 case DIOCSDINFO: 548 case DIOCWDINFO: 549 break; 550 551 default: 552 error = ENOTTY; 553 break; 554 } 555 return (error); 556 } 557 558 559 /* 560 * Size 561 */ 562 563 int 564 sdsize(dev) 565 dev_t dev; 566 { 567 register int unit = sdunit(dev); 568 register struct sd_softc *sc = &sd_softc[unit]; 569 570 if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0) 571 return(-1); 572 573 return(sdlabel[unit].d_partitions[sdpart(dev)].p_size); 574 } 575 576 577 /* 578 * Dump 579 */ 580 581 int 582 sddump(dev) 583 dev_t dev; 584 { 585 } 586 587 /* 588 * Disk Subs 589 */ 590 591 /* 592 * Attempt to read a disk label from a device 593 * using the indicated stategy routine. 594 * The label must be partly set up before this: 595 * secpercyl and anything required in the strategy routine 596 * (e.g., sector size) must be filled in before calling us. 597 * Returns null on success and an error string on failure. 598 */ 599 char * 600 sdreadlabel(dev, strat, lp) 601 dev_t dev; 602 int (*strat)(); 603 register struct disklabel *lp; 604 { 605 register struct buf *bp; 606 struct disklabel *dlp; 607 char *msg = NULL; 608 609 if (lp->d_secperunit == 0) 610 lp->d_secperunit = 0x1fffffff; 611 lp->d_npartitions = 1; 612 if (lp->d_partitions[0].p_size == 0) 613 lp->d_partitions[0].p_size = 0x1fffffff; 614 lp->d_partitions[0].p_offset = 0; 615 616 bp = geteblk((int)lp->d_secsize); 617 bp->b_dev = dev; 618 bp->b_blkno = LABELSECTOR; 619 bp->b_bcount = lp->d_secsize; 620 bp->b_flags = B_BUSY | B_READ; 621 (*strat)(bp); 622 if (biowait(bp)) { 623 msg = "I/O error"; 624 } else { 625 for (dlp = (struct disklabel *)bp->b_un.b_addr; 626 dlp <= (struct disklabel *)(bp->b_un.b_addr+DEV_BSIZE-sizeof(*dlp)); 627 dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { 628 if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { 629 if (msg == NULL) 630 msg = "no disk label"; 631 } else if (dlp->d_npartitions > MAXPARTITIONS || 632 dkcksum(dlp) != 0) 633 msg = "disk label corrupted"; 634 else { 635 *lp = *dlp; 636 msg = NULL; 637 break; 638 } 639 } 640 } 641 bp->b_flags = B_INVAL | B_AGE; 642 brelse(bp); 643 return (msg); 644 } 645 646 #ifdef notyet 647 648 /* 649 * Checksum routine for OMRON native disklabel 650 */ 651 652 #define OMRON_LBLSIZE 512 653 654 u_short 655 omcksum(omp) 656 register char *omp; 657 { 658 register u_short *start, *end; 659 register u_short sum = 0; 660 661 start = (u_short *) omp; 662 end = (u_short *) &start[(OMRON_LBLSIZE/sizeof(u_short) - 1)]; 663 while (start < end) 664 sum ^= *start++; 665 666 printf("omcksum: saved ... 0x%s\n", hexstr(*end, 4)); 667 printf("omcksum: calced ... 0x%s\n", hexstr(sum, 4)); 668 669 return (sum); 670 } 671 672 /* 673 * Write disk label back to device after modification. 674 */ 675 sdwritelabel(dev, strat, lp) 676 dev_t dev; 677 int (*strat)(); 678 register struct disklabel *lp; 679 { 680 struct buf *bp; 681 struct disklabel *dlp; 682 int labelpart; 683 int error = 0; 684 685 labelpart = sdpart(dev); 686 if (lp->d_partitions[labelpart].p_offset != 0) { 687 if (lp->d_partitions[0].p_offset != 0) 688 return (EXDEV); /* not quite right */ 689 labelpart = 0; 690 } 691 692 bp = geteblk((int)lp->d_secsize); 693 bp->b_dev = makedev(major(dev), sdminor(sdunit(dev), labelpart)); 694 bp->b_blkno = LABELSECTOR; 695 bp->b_bcount = lp->d_secsize; 696 bp->b_flags = B_READ; 697 (*strat)(bp); 698 if (error = biowait(bp)) 699 goto done; 700 701 for (dlp = (struct disklabel *)bp->b_un.b_addr; 702 dlp <= (struct disklabel *) 703 (bp->b_un.b_addr + lp->d_secsize - sizeof(*dlp)); 704 dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { 705 if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC && 706 dkcksum(dlp) == 0) { 707 omcksum(bp->b_un.b_addr); 708 /* 709 *dlp = *lp; 710 bp->b_flags = B_WRITE; 711 (*strat)(bp); 712 error = biowait(bp); 713 goto done; 714 */ 715 } 716 } 717 error = ESRCH; 718 done: 719 brelse(bp); 720 return (error); 721 } 722 #endif 723 724 #endif 725