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