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