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.6 (Berkeley) 03/17/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 #ifdef DEBUG 280 printf("sdstrategy: bp->b_blkno = %d, bp->bcount = %d\n", 281 bp->b_blkno, bp->b_bcount); 282 #endif 283 bn = bp->b_blkno; 284 sz = howmany(bp->b_bcount, DEV_BSIZE); 285 286 /* check that tracsfer is within a drive's partition */ 287 288 if (bn < 0 || (bn + sz) > pp->p_size) { 289 sz = pp->p_size - bn; 290 if (sz == 0) { 291 bp->b_resid = bp->b_bcount; 292 goto done; 293 } 294 if (sz < 0) { 295 bp->b_error = EINVAL; 296 bp->b_flags |= B_ERROR; 297 goto done; 298 } 299 bp->b_bcount = dbtob(sz); 300 } 301 302 /* calculate LBA for transfer */ 303 304 bp->b_lba = bn + pp->p_offset; 305 306 /* raise priority to block sdintr */ 307 308 s = splbio(); 309 310 /* call disksort to sort request into drive queue */ 311 312 disksort(dp, bp); 313 314 #ifdef DEBUG 315 printf("sdstrategy: dp->b_active = %d\n", dp->b_active); 316 #endif 317 if (dp->b_active == 0) { /* */ 318 dp->b_active = 1; 319 sdustart(unit); 320 } 321 322 /* lower priority */ 323 324 splx(s); 325 326 return; 327 328 done: 329 biodone(bp); 330 } 331 332 int 333 sdustart(unit) 334 register int unit; 335 { 336 register struct sd_softc *sc = &sd_softc[unit]; 337 register struct hp_device *hp = sc->sc_hd; 338 register struct scsi_queue *dq = &sc->sc_dq; 339 register struct buf *bp = sdtab[unit].b_actf; 340 register struct scsi_fmt_cdb *cmd; 341 342 cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd; 343 *(int *)(&cmd->cdb[2]) = bp->b_lba; 344 *(u_short *)(&cmd->cdb[7]) = howmany(bp->b_bcount, DEV_BSIZE); 345 346 dq->dq_cdb = cmd; 347 dq->dq_bp = bp; 348 dq->dq_flags = DQ_DISCONNECT; /* SCSI Disconnect */ 349 350 if (screq(dq)) 351 sdstart(unit); 352 } 353 354 int 355 sdstart(unit) 356 register int unit; 357 { 358 register struct sd_softc *sc = &sd_softc[unit]; 359 register struct hp_device *hp = sc->sc_hd; 360 361 if (hp->hp_dk >= 0) { 362 dk_busy |= 1 << hp->hp_dk; 363 } 364 365 scstart(hp->hp_ctlr); 366 } 367 368 369 /* 370 * Return: 371 * 0 if not really an error 372 * <0 if we should do a retry 373 * >0 if a fatal error 374 */ 375 static int 376 sderror(unit, sc, hp, stat) 377 int unit, stat; 378 register struct sd_softc *sc; 379 register struct hp_device *hp; 380 { 381 int cond = 1; 382 383 sdsense[unit].status = stat; 384 if (stat & STS_CHECKCOND) { 385 struct scsi_xsense *sp; 386 387 scsi_request_sense(hp->hp_ctlr, hp->hp_slave, 388 sc->sc_punit, sdsense[unit].sense, 389 sizeof(sdsense[unit].sense)); 390 sp = (struct scsi_xsense *)sdsense[unit].sense; 391 printf("sd%d: scsi sense class %d, code %d", unit, 392 sp->class, sp->code); 393 if (sp->class == 7) { 394 printf(", key %d", sp->key); 395 if (sp->valid) 396 printf(", blk %d", *(int *)&sp->info1); 397 switch (sp->key) { 398 /* no sense, try again */ 399 case 0: 400 cond = -1; 401 break; 402 /* recovered error, not a problem */ 403 case 1: 404 cond = 0; 405 break; 406 } 407 } 408 printf("\n"); 409 } 410 return(cond); 411 } 412 413 /* 414 * Interrupt 415 */ 416 417 int 418 sdintr(unit, stat) 419 register int unit; 420 int stat; 421 { 422 register struct sd_softc *sc = &sd_softc[unit]; 423 register struct hp_device *hp = sc->sc_hd; 424 register struct scsi_queue *dq = &sc->sc_dq; 425 register struct buf *bp = dq->dq_bp; 426 int cond; 427 428 #ifdef DEBUG 429 printf("sdintr(unit = %d, stat = %d)\n", unit, stat); 430 #endif 431 432 if (stat == SC_IO_TIMEOUT) { 433 printf("sdintr: sd%d timeout error\n", unit, stat); 434 } 435 436 if (hp->hp_dk >= 0) { 437 dk_busy &=~ (1 << hp->hp_dk); 438 if (stat == 0) { 439 ++dk_seek[hp->hp_dk]; 440 ++dk_xfer[hp->hp_dk]; 441 dk_wds[hp->hp_dk] += bp->b_bcount >> 6; 442 } 443 } 444 445 if (bp->b_flags & B_READ) { 446 sd_iostat[unit].imin = min(dq->dq_imin, sd_iostat[unit].imin); 447 if (dq->dq_imax > sd_iostat[unit].imax) { 448 sd_iostat[unit].imax = dq->dq_imax; 449 #ifdef SD_IOSTAT 450 printf("sdintr: sd%d INPUT MAX = %d, MIN = %d\n", 451 unit, sd_iostat[unit].imax, sd_iostat[unit].imin); 452 #endif 453 } 454 } else { 455 sd_iostat[unit].omin = min(dq->dq_omin, sd_iostat[unit].omin); 456 if (dq->dq_omax > sd_iostat[unit].omax) { 457 sd_iostat[unit].omax = dq->dq_omax; 458 #ifdef SD_IOSTAT 459 printf("sdintr: sd%d OUTPUT MAX = %d, MIN = %d\n", 460 unit, sd_iostat[unit].omax, sd_iostat[unit].omin); 461 #endif 462 } 463 } 464 465 if (stat != 0) { 466 if (stat > 0) { 467 #ifdef DEBUGPRINT 468 dbgprintall(); 469 printf("\n"); 470 #endif 471 cond = sderror(unit, sc, hp, stat); 472 if (cond) { 473 if (cond < 0 && sdtab[unit].b_errcnt++ < SDRETRY) { 474 sdstart(unit); 475 return; 476 } 477 } 478 } else { 479 if (sdtab[unit].b_errcnt++ < SDRETRY) { 480 printf("sdintr: sd%d restart IO request\n", unit); 481 sdstart(unit); 482 return; 483 } 484 } 485 bp->b_flags |= B_ERROR; 486 bp->b_error = EIO; 487 } 488 489 sdtab[unit].b_errcnt = 0; 490 sdtab[unit].b_actf = bp->b_actf; 491 492 bp->b_resid = 0; 493 494 biodone(bp); 495 496 scfree(dq); 497 498 if (sdtab[unit].b_actf) { 499 sdustart(unit); 500 } else { 501 sdtab[unit].b_active = 0; 502 } 503 } 504 505 506 /* 507 * RAW Device Routines 508 */ 509 510 int 511 sdread(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_READ, minphys, uio)); 519 } 520 521 int 522 sdwrite(dev, uio, flags) 523 dev_t dev; 524 struct uio *uio; 525 int flags; 526 { 527 register int unit = sdunit(dev); 528 529 return (physio(sdstrategy, NULL, dev, B_WRITE, minphys, uio)); 530 } 531 532 int 533 sdioctl(dev, cmd, data, flag, p) 534 dev_t dev; 535 int cmd; 536 caddr_t data; 537 int flag; 538 struct proc *p; 539 { 540 int unit = sdunit(dev); 541 register struct sd_softc *sc = &sd_softc[unit]; 542 register struct disklabel *lp = &sdlabel[unit]; 543 int error = 0; 544 545 switch (cmd) { 546 547 case DIOCGDINFO: 548 *(struct disklabel *)data = *lp; 549 break; 550 551 case DIOCGPART: 552 ((struct partinfo *)data)->disklab = lp; 553 ((struct partinfo *)data)->part = 554 &lp->d_partitions[sdpart(dev)]; 555 break; 556 557 case DIOCWLABEL: 558 case DIOCSDINFO: 559 case DIOCWDINFO: 560 break; 561 562 default: 563 error = ENOTTY; 564 break; 565 } 566 return (error); 567 } 568 569 570 /* 571 * Size 572 */ 573 574 int 575 sdsize(dev) 576 dev_t dev; 577 { 578 register int unit = sdunit(dev); 579 register struct sd_softc *sc = &sd_softc[unit]; 580 581 if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0) 582 return(-1); 583 584 return(sdlabel[unit].d_partitions[sdpart(dev)].p_size); 585 } 586 587 588 /* 589 * Dump 590 */ 591 592 int 593 sddump(dev) 594 dev_t dev; 595 { 596 } 597 598 /* 599 * Disk Subs 600 */ 601 602 /* 603 * Attempt to read a disk label from a device 604 * using the indicated stategy routine. 605 * The label must be partly set up before this: 606 * secpercyl and anything required in the strategy routine 607 * (e.g., sector size) must be filled in before calling us. 608 * Returns null on success and an error string on failure. 609 */ 610 char * 611 sdreadlabel(dev, strat, lp) 612 dev_t dev; 613 int (*strat)(); 614 register struct disklabel *lp; 615 { 616 register struct buf *bp; 617 struct disklabel *dlp; 618 char *msg = NULL; 619 620 if (lp->d_secperunit == 0) 621 lp->d_secperunit = 0x1fffffff; 622 lp->d_npartitions = 1; 623 if (lp->d_partitions[0].p_size == 0) 624 lp->d_partitions[0].p_size = 0x1fffffff; 625 lp->d_partitions[0].p_offset = 0; 626 627 bp = geteblk((int)lp->d_secsize); 628 bp->b_dev = dev; 629 bp->b_blkno = LABELSECTOR; 630 bp->b_bcount = lp->d_secsize; 631 bp->b_flags = B_BUSY | B_READ; 632 (*strat)(bp); 633 if (biowait(bp)) { 634 msg = "I/O error"; 635 } else { 636 for (dlp = (struct disklabel *)bp->b_un.b_addr; 637 dlp <= (struct disklabel *)(bp->b_un.b_addr+DEV_BSIZE-sizeof(*dlp)); 638 dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { 639 if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { 640 if (msg == NULL) 641 msg = "no disk label"; 642 } else if (dlp->d_npartitions > MAXPARTITIONS || 643 dkcksum(dlp) != 0) 644 msg = "disk label corrupted"; 645 else { 646 *lp = *dlp; 647 msg = NULL; 648 break; 649 } 650 } 651 } 652 bp->b_flags = B_INVAL | B_AGE; 653 brelse(bp); 654 return (msg); 655 } 656 657 #ifdef notyet 658 659 /* 660 * Checksum routine for OMRON native disklabel 661 */ 662 663 #define OMRON_LBLSIZE 512 664 665 u_short 666 omcksum(omp) 667 register char *omp; 668 { 669 register u_short *start, *end; 670 register u_short sum = 0; 671 672 start = (u_short *) omp; 673 end = (u_short *) &start[(OMRON_LBLSIZE/sizeof(u_short) - 1)]; 674 while (start < end) 675 sum ^= *start++; 676 677 printf("omcksum: saved ... 0x%s\n", hexstr(*end, 4)); 678 printf("omcksum: calced ... 0x%s\n", hexstr(sum, 4)); 679 680 return (sum); 681 } 682 683 /* 684 * Write disk label back to device after modification. 685 */ 686 sdwritelabel(dev, strat, lp) 687 dev_t dev; 688 int (*strat)(); 689 register struct disklabel *lp; 690 { 691 struct buf *bp; 692 struct disklabel *dlp; 693 int labelpart; 694 int error = 0; 695 696 labelpart = sdpart(dev); 697 if (lp->d_partitions[labelpart].p_offset != 0) { 698 if (lp->d_partitions[0].p_offset != 0) 699 return (EXDEV); /* not quite right */ 700 labelpart = 0; 701 } 702 703 bp = geteblk((int)lp->d_secsize); 704 bp->b_dev = makedev(major(dev), sdminor(sdunit(dev), labelpart)); 705 bp->b_blkno = LABELSECTOR; 706 bp->b_bcount = lp->d_secsize; 707 bp->b_flags = B_READ; 708 (*strat)(bp); 709 if (error = biowait(bp)) 710 goto done; 711 712 for (dlp = (struct disklabel *)bp->b_un.b_addr; 713 dlp <= (struct disklabel *) 714 (bp->b_un.b_addr + lp->d_secsize - sizeof(*dlp)); 715 dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { 716 if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC && 717 dkcksum(dlp) == 0) { 718 omcksum(bp->b_un.b_addr); 719 /* 720 *dlp = *lp; 721 bp->b_flags = B_WRITE; 722 (*strat)(bp); 723 error = biowait(bp); 724 goto done; 725 */ 726 } 727 } 728 error = ESRCH; 729 done: 730 brelse(bp); 731 return (error); 732 } 733 #endif 734 735 #endif 736