1 /* $NetBSD: sd.c,v 1.50 1994/12/16 04:38:36 mycroft Exp $ */ 2 3 /* 4 * Copyright (c) 1994 Charles Hannum. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Charles Hannum. 17 * 4. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Originally written by Julian Elischer (julian@dialix.oz.au) 34 * for TRW Financial Systems for use under the MACH(2.5) operating system. 35 * 36 * TRW Financial Systems, in accordance with their agreement with Carnegie 37 * Mellon University, makes this software available to CMU to distribute 38 * or use in any manner that they see fit as long as this message is kept with 39 * the software. For this reason TFS also grants any other persons or 40 * organisations permission to use or modify this software. 41 * 42 * TFS supplies this software to be publicly redistributed 43 * on the understanding that TFS is not responsible for the correct 44 * functioning of this software in any circumstances. 45 * 46 * Ported to run under 386BSD by Julian Elischer (julian@dialix.oz.au) Sept 1992 47 */ 48 49 #include <sys/types.h> 50 #include <sys/param.h> 51 #include <sys/systm.h> 52 #include <sys/conf.h> 53 #include <sys/file.h> 54 #include <sys/stat.h> 55 #include <sys/ioctl.h> 56 #include <sys/buf.h> 57 #include <sys/uio.h> 58 #include <sys/malloc.h> 59 #include <sys/errno.h> 60 #include <sys/device.h> 61 #include <sys/disklabel.h> 62 #include <sys/disk.h> 63 64 #include <scsi/scsi_all.h> 65 #include <scsi/scsi_disk.h> 66 #include <scsi/scsiconf.h> 67 68 #ifdef DDB 69 int Debugger(); 70 #else /* DDB */ 71 #define Debugger() 72 #endif /* DDB */ 73 74 #define SDOUTSTANDING 2 75 #define SDRETRIES 4 76 77 #define SDUNIT(dev) DISKUNIT(dev) 78 #define SDPART(dev) DISKPART(dev) 79 #define MAKESDDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part) 80 81 #define SDLABELDEV(dev) (MAKESDDEV(major(dev), SDUNIT(dev), RAW_PART)) 82 83 struct sd_data { 84 struct device sc_dev; 85 struct dkdevice sc_dk; 86 87 int flags; 88 #define SDF_LOCKED 0x01 89 #define SDF_WANTED 0x02 90 #define SDF_BSDLABEL 0x04 91 #define SDF_WLABEL 0x08 /* label is writable */ 92 struct scsi_link *sc_link; /* contains our targ, lun etc. */ 93 u_int32 ad_info; /* info about the adapter */ 94 u_int32 cmdscount; /* cmds allowed outstanding by board */ 95 struct disk_parms { 96 u_char heads; /* Number of heads */ 97 u_int16 cyls; /* Number of cylinders */ 98 u_char sectors; /* Number of sectors/track */ 99 u_int32 blksize; /* Number of bytes/sector */ 100 u_long disksize; /* total number sectors */ 101 } params; 102 u_int32 xfer_block_wait; 103 struct buf buf_queue; 104 }; 105 106 void sdattach __P((struct device *, struct device *, void *)); 107 108 struct cfdriver sdcd = { 109 NULL, "sd", scsi_targmatch, sdattach, DV_DISK, sizeof(struct sd_data) 110 }; 111 112 void sdgetdisklabel __P((struct sd_data *)); 113 int sd_get_parms __P((struct sd_data *, int)); 114 void sdstrategy __P((struct buf *)); 115 void sdstart __P((struct sd_data *)); 116 117 struct dkdriver sddkdriver = { sdstrategy }; 118 119 struct scsi_device sd_switch = { 120 NULL, /* Use default error handler */ 121 sdstart, /* have a queue, served by this */ 122 NULL, /* have no async handler */ 123 NULL, /* Use default 'done' routine */ 124 "sd", 125 0 126 }; 127 128 /* 129 * The routine called by the low level scsi routine when it discovers 130 * a device suitable for this driver. 131 */ 132 void 133 sdattach(parent, self, aux) 134 struct device *parent, *self; 135 void *aux; 136 { 137 struct sd_data *sd = (void *)self; 138 struct disk_parms *dp = &sd->params; 139 struct scsi_link *sc_link = aux; 140 141 SC_DEBUG(sc_link, SDEV_DB2, ("sdattach: ")); 142 143 /* 144 * Store information needed to contact our base driver 145 */ 146 sd->sc_link = sc_link; 147 sc_link->device = &sd_switch; 148 sc_link->device_softc = sd; 149 150 sd->sc_dk.dk_driver = &sddkdriver; 151 #if !defined(i386) || defined(NEWCONFIG) 152 dk_establish(&sd->sc_dk, &sd->sc_dev); 153 #endif 154 155 if (sd->sc_link->adapter->adapter_info) { 156 sd->ad_info = ((*(sd->sc_link->adapter->adapter_info)) (sc_link->adapter_softc)); 157 sd->cmdscount = sd->ad_info & AD_INF_MAX_CMDS; 158 if (sd->cmdscount > SDOUTSTANDING) 159 sd->cmdscount = SDOUTSTANDING; 160 } else { 161 sd->ad_info = 1; 162 sd->cmdscount = 1; 163 } 164 sc_link->opennings = sd->cmdscount; 165 166 /* 167 * Use the subdriver to request information regarding 168 * the drive. We cannot use interrupts yet, so the 169 * request must specify this. 170 */ 171 sd_get_parms(sd, SCSI_NOSLEEP | SCSI_NOMASK); 172 printf(": %dMB, %d cyl, %d head, %d sec, %d bytes/sec\n", 173 dp->disksize / (1048576 / dp->blksize), dp->cyls, 174 dp->heads, dp->sectors, dp->blksize); 175 } 176 177 /* 178 * open the device. Make sure the partition info is a up-to-date as can be. 179 */ 180 int 181 sdopen(dev, flag, fmt) 182 dev_t dev; 183 int flag, fmt; 184 { 185 int error; 186 int unit, part; 187 struct sd_data *sd; 188 struct scsi_link *sc_link; 189 190 unit = SDUNIT(dev); 191 if (unit >= sdcd.cd_ndevs) 192 return ENXIO; 193 sd = sdcd.cd_devs[unit]; 194 if (!sd) 195 return ENXIO; 196 197 part = SDPART(dev); 198 sc_link = sd->sc_link; 199 200 SC_DEBUG(sc_link, SDEV_DB1, 201 ("sdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit, 202 sdcd.cd_ndevs, part)); 203 204 while ((sd->flags & SDF_LOCKED) != 0) { 205 sd->flags |= SDF_WANTED; 206 if ((error = tsleep(sd, PRIBIO | PCATCH, "sdopn", 0)) != 0) 207 return error; 208 } 209 210 if (sd->sc_dk.dk_openmask != 0) { 211 /* 212 * If any partition is open, but the disk has been invalidated, 213 * disallow further opens. 214 */ 215 if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) 216 return ENXIO; 217 } else { 218 sd->flags |= SDF_LOCKED; 219 220 /* 221 * "unit attention" errors should occur here if the 222 * drive has been restarted or the pack changed. 223 * just ingnore the result, it's a decoy instruction 224 * The error code will act on the error though 225 * and invalidate any media information we had. 226 */ 227 scsi_test_unit_ready(sc_link, SCSI_SILENT); 228 229 /* 230 * In case it is a funny one, tell it to start 231 * not needed for most hard drives (ignore failure) 232 */ 233 scsi_start(sc_link, SSS_START, SCSI_ERR_OK | SCSI_SILENT); 234 235 sc_link->flags |= SDEV_OPEN; /* unit attn becomes an err now */ 236 237 /* 238 * Check that it is still responding and ok. 239 */ 240 if (scsi_test_unit_ready(sc_link, 0)) { 241 SC_DEBUG(sc_link, SDEV_DB3, ("device not responding\n")); 242 error = ENXIO; 243 goto bad; 244 } 245 SC_DEBUG(sc_link, SDEV_DB3, ("device ok\n")); 246 247 /* Lock the pack in. */ 248 scsi_prevent(sc_link, PR_PREVENT, SCSI_ERR_OK | SCSI_SILENT); 249 250 if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) { 251 sd->flags &= ~SDF_BSDLABEL; 252 sc_link->flags |= SDEV_MEDIA_LOADED; 253 254 /* Load the physical device parameters. */ 255 if (sd_get_parms(sd, 0) != 0) { 256 error = ENXIO; 257 goto bad2; 258 } 259 SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded ")); 260 261 /* Load the partition info if not already loaded. */ 262 sdgetdisklabel(sd); 263 SC_DEBUG(sc_link, SDEV_DB3, ("Disklabel loaded ")); 264 } 265 266 sd->flags &= ~SDF_LOCKED; 267 if ((sd->flags & SDF_WANTED) != 0) { 268 sd->flags &= ~SDF_WANTED; 269 wakeup(sd); 270 } 271 } 272 273 /* Check that the partition exists. */ 274 if (part != RAW_PART && 275 (part >= sd->sc_dk.dk_label.d_npartitions || 276 sd->sc_dk.dk_label.d_partitions[part].p_fstype == FS_UNUSED)) { 277 error = ENXIO; 278 goto bad; 279 } 280 281 /* Insure only one open at a time. */ 282 switch (fmt) { 283 case S_IFCHR: 284 sd->sc_dk.dk_copenmask |= (1 << part); 285 break; 286 case S_IFBLK: 287 sd->sc_dk.dk_bopenmask |= (1 << part); 288 break; 289 } 290 sd->sc_dk.dk_openmask = sd->sc_dk.dk_copenmask | sd->sc_dk.dk_bopenmask; 291 292 SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n")); 293 return 0; 294 295 bad2: 296 sc_link->flags &= ~SDEV_MEDIA_LOADED; 297 298 bad: 299 if (sd->sc_dk.dk_openmask == 0) { 300 scsi_prevent(sc_link, PR_ALLOW, SCSI_ERR_OK | SCSI_SILENT); 301 sc_link->flags &= ~SDEV_OPEN; 302 303 sd->flags &= ~SDF_LOCKED; 304 if ((sd->flags & SDF_WANTED) != 0) { 305 sd->flags &= ~SDF_WANTED; 306 wakeup(sd); 307 } 308 } 309 310 return error; 311 } 312 313 /* 314 * close the device.. only called if we are the LAST occurence of an open 315 * device. Convenient now but usually a pain. 316 */ 317 int 318 sdclose(dev, flag, fmt) 319 dev_t dev; 320 int flag, fmt; 321 { 322 struct sd_data *sd = sdcd.cd_devs[SDUNIT(dev)]; 323 int part = SDPART(dev); 324 int s; 325 326 switch (fmt) { 327 case S_IFCHR: 328 sd->sc_dk.dk_copenmask &= ~(1 << part); 329 break; 330 case S_IFBLK: 331 sd->sc_dk.dk_bopenmask &= ~(1 << part); 332 break; 333 } 334 sd->sc_dk.dk_openmask = sd->sc_dk.dk_copenmask | sd->sc_dk.dk_bopenmask; 335 336 if (sd->sc_dk.dk_openmask == 0) { 337 sd->flags |= SDF_LOCKED; 338 339 #if 0 340 s = splbio(); 341 while (...) { 342 sd->flags |= SDF_WAITING; 343 if ((error = tsleep(sd, PRIBIO | PCATCH, "sdcls", 0)) != 0) 344 return error; 345 } 346 splx(s); 347 #endif 348 349 scsi_prevent(sd->sc_link, PR_ALLOW, SCSI_ERR_OK | SCSI_SILENT); 350 sd->sc_link->flags &= ~SDEV_OPEN; 351 352 sd->flags &= ~SDF_LOCKED; 353 if ((sd->flags & SDF_WANTED) != 0) { 354 sd->flags &= ~SDF_WANTED; 355 wakeup(sd); 356 } 357 } 358 359 return 0; 360 } 361 362 /* 363 * trim the size of the transfer if needed, called by physio 364 * basically the smaller of our max and the scsi driver's 365 * minphys (note we have no max) 366 * 367 * Trim buffer length if buffer-size is bigger than page size 368 */ 369 void 370 sdminphys(bp) 371 struct buf *bp; 372 { 373 register struct sd_data *sd = sdcd.cd_devs[SDUNIT(bp->b_dev)]; 374 375 (sd->sc_link->adapter->scsi_minphys) (bp); 376 } 377 378 /* 379 * Actually translate the requested transfer into one the physical driver 380 * can understand. The transfer is described by a buf and will include 381 * only one physical transfer. 382 */ 383 void 384 sdstrategy(bp) 385 struct buf *bp; 386 { 387 struct sd_data *sd = sdcd.cd_devs[SDUNIT(bp->b_dev)]; 388 int opri; 389 390 SC_DEBUG(sd->sc_link, SDEV_DB2, ("sdstrategy ")); 391 SC_DEBUG(sd->sc_link, SDEV_DB1, 392 ("%d bytes @ blk %d\n", bp->b_bcount, bp->b_blkno)); 393 sdminphys(bp); 394 /* 395 * If the device has been made invalid, error out 396 */ 397 if (!(sd->sc_link->flags & SDEV_MEDIA_LOADED)) { 398 bp->b_error = EIO; 399 goto bad; 400 } 401 #if 0 402 /* 403 * "soft" write protect check 404 */ 405 if ((sd->flags & SDF_WRITEPROT) && (bp->b_flags & B_READ) == 0) { 406 bp->b_error = EROFS; 407 goto bad; 408 } 409 #endif 410 /* 411 * If it's a null transfer, return immediatly 412 */ 413 if (bp->b_bcount == 0) 414 goto done; 415 /* 416 * Decide which unit and partition we are talking about 417 * only raw is ok if no label 418 */ 419 if (SDPART(bp->b_dev) != RAW_PART) { 420 if ((sd->flags & SDF_BSDLABEL) == 0) { 421 bp->b_error = EIO; 422 goto bad; 423 } 424 /* 425 * do bounds checking, adjust transfer. if error, process. 426 * if end of partition, just return 427 */ 428 if (bounds_check_with_label(bp, &sd->sc_dk.dk_label, 429 (sd->flags & SDF_WLABEL) != 0) <= 0) 430 goto done; 431 /* otherwise, process transfer request */ 432 } 433 434 opri = splbio(); 435 436 /* 437 * Place it in the queue of disk activities for this disk 438 */ 439 disksort(&sd->buf_queue, bp); 440 441 /* 442 * Tell the device to get going on the transfer if it's 443 * not doing anything, otherwise just wait for completion 444 */ 445 sdstart(sd); 446 447 splx(opri); 448 return; 449 450 bad: 451 bp->b_flags |= B_ERROR; 452 done: 453 /* 454 * Correctly set the buf to indicate a completed xfer 455 */ 456 bp->b_resid = bp->b_bcount; 457 biodone(bp); 458 } 459 460 /* 461 * sdstart looks to see if there is a buf waiting for the device 462 * and that the device is not already busy. If both are true, 463 * It dequeues the buf and creates a scsi command to perform the 464 * transfer in the buf. The transfer request will call scsi_done 465 * on completion, which will in turn call this routine again 466 * so that the next queued transfer is performed. 467 * The bufs are queued by the strategy routine (sdstrategy) 468 * 469 * This routine is also called after other non-queued requests 470 * have been made of the scsi driver, to ensure that the queue 471 * continues to be drained. 472 * 473 * must be called at the correct (highish) spl level 474 * sdstart() is called at splbio from sdstrategy and scsi_done 475 */ 476 void 477 sdstart(sd) 478 register struct sd_data *sd; 479 { 480 register struct scsi_link *sc_link = sd->sc_link; 481 struct buf *bp = 0; 482 struct buf *dp; 483 struct scsi_rw_big cmd; 484 int blkno, nblks; 485 struct partition *p; 486 487 SC_DEBUG(sc_link, SDEV_DB2, ("sdstart ")); 488 /* 489 * Check if the device has room for another command 490 */ 491 while (sc_link->opennings) { 492 /* 493 * there is excess capacity, but a special waits 494 * It'll need the adapter as soon as we clear out of the 495 * way and let it run (user level wait). 496 */ 497 if (sc_link->flags & SDEV_WAITING) { 498 sc_link->flags &= ~SDEV_WAITING; 499 wakeup((caddr_t)sc_link); 500 return; 501 } 502 503 /* 504 * See if there is a buf with work for us to do.. 505 */ 506 dp = &sd->buf_queue; 507 if ((bp = dp->b_actf) == NULL) /* yes, an assign */ 508 return; 509 dp->b_actf = bp->b_actf; 510 511 /* 512 * If the device has become invalid, abort all the 513 * reads and writes until all files have been closed and 514 * re-openned 515 */ 516 if (!(sc_link->flags & SDEV_MEDIA_LOADED)) { 517 bp->b_error = EIO; 518 bp->b_flags |= B_ERROR; 519 biodone(bp); 520 continue; 521 } 522 523 /* 524 * We have a buf, now we know we are going to go through 525 * With this thing.. 526 * 527 * First, translate the block to absolute 528 */ 529 blkno = 530 bp->b_blkno / (sd->sc_dk.dk_label.d_secsize / DEV_BSIZE); 531 if (SDPART(bp->b_dev) != RAW_PART) { 532 p = &sd->sc_dk.dk_label.d_partitions[SDPART(bp->b_dev)]; 533 blkno += p->p_offset; 534 } 535 nblks = howmany(bp->b_bcount, sd->sc_dk.dk_label.d_secsize); 536 537 /* 538 * Fill out the scsi command 539 */ 540 bzero(&cmd, sizeof(cmd)); 541 cmd.op_code = (bp->b_flags & B_READ) ? READ_BIG : WRITE_BIG; 542 cmd.addr_3 = (blkno & 0xff000000) >> 24; 543 cmd.addr_2 = (blkno & 0xff0000) >> 16; 544 cmd.addr_1 = (blkno & 0xff00) >> 8; 545 cmd.addr_0 = blkno & 0xff; 546 cmd.length2 = (nblks & 0xff00) >> 8; 547 cmd.length1 = (nblks & 0xff); 548 549 /* 550 * Call the routine that chats with the adapter. 551 * Note: we cannot sleep as we may be an interrupt 552 */ 553 if (scsi_scsi_cmd(sc_link, (struct scsi_generic *)&cmd, 554 sizeof(cmd), (u_char *)bp->b_data, bp->b_bcount, 555 SDRETRIES, 10000, bp, SCSI_NOSLEEP | 556 ((bp->b_flags & B_READ) ? SCSI_DATA_IN : SCSI_DATA_OUT)) 557 != SUCCESSFULLY_QUEUED) 558 printf("%s: not queued", sd->sc_dev.dv_xname); 559 } 560 } 561 562 /* 563 * Perform special action on behalf of the user 564 * Knows about the internals of this device 565 */ 566 int 567 sdioctl(dev, cmd, addr, flag) 568 dev_t dev; 569 u_long cmd; 570 caddr_t addr; 571 int flag; 572 { 573 struct sd_data *sd = sdcd.cd_devs[SDUNIT(dev)]; 574 int error; 575 576 /* 577 * If the device is not valid.. abandon ship 578 */ 579 if (!(sd->sc_link->flags & SDEV_MEDIA_LOADED)) 580 return EIO; 581 582 switch (cmd) { 583 case DIOCGDINFO: 584 *(struct disklabel *)addr = sd->sc_dk.dk_label; 585 return 0; 586 587 case DIOCGPART: 588 ((struct partinfo *)addr)->disklab = &sd->sc_dk.dk_label; 589 ((struct partinfo *)addr)->part = 590 &sd->sc_dk.dk_label.d_partitions[SDPART(dev)]; 591 return 0; 592 593 case DIOCSDINFO: 594 if ((flag & FWRITE) == 0) 595 return EBADF; 596 error = setdisklabel(&sd->sc_dk.dk_label, 597 (struct disklabel *)addr, 598 /*(sd->flags & SDF_BSDLABEL) ? sd->sc_dk.dk_openmask : */0, 599 &sd->sc_dk.dk_cpulabel); 600 if (error == 0) 601 sd->flags |= SDF_BSDLABEL; 602 return error; 603 604 case DIOCWLABEL: 605 if ((flag & FWRITE) == 0) 606 return EBADF; 607 if (*(int *)addr) 608 sd->flags |= SDF_WLABEL; 609 else 610 sd->flags &= ~SDF_WLABEL; 611 return 0; 612 613 case DIOCWDINFO: 614 if ((flag & FWRITE) == 0) 615 return EBADF; 616 error = setdisklabel(&sd->sc_dk.dk_label, 617 (struct disklabel *)addr, 618 /*(sd->flags & SDF_BSDLABEL) ? sd->sc_dk.dk_openmask : */0, 619 &sd->sc_dk.dk_cpulabel); 620 if (error == 0) { 621 sd->flags |= SDF_BSDLABEL; 622 623 /* Simulate opening partition 0 so write succeeds. */ 624 sd->sc_dk.dk_openmask |= (1 << 0); /* XXX */ 625 error = writedisklabel(SDLABELDEV(dev), sdstrategy, 626 &sd->sc_dk.dk_label, &sd->sc_dk.dk_cpulabel); 627 sd->sc_dk.dk_openmask = 628 sd->sc_dk.dk_copenmask | sd->sc_dk.dk_bopenmask; 629 } 630 return error; 631 632 default: 633 if (SDPART(dev) != RAW_PART) 634 return ENOTTY; 635 return scsi_do_ioctl(sd->sc_link, dev, cmd, addr, flag); 636 } 637 638 #ifdef DIAGNOSTIC 639 panic("sdioctl: impossible"); 640 #endif 641 } 642 643 /* 644 * Load the label information on the named device 645 */ 646 void 647 sdgetdisklabel(sd) 648 struct sd_data *sd; 649 { 650 char *errstring; 651 652 if ((sd->flags & SDF_BSDLABEL) != 0) 653 return; 654 655 bzero(&sd->sc_dk.dk_label, sizeof(struct disklabel)); 656 bzero(&sd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel)); 657 658 sd->sc_dk.dk_label.d_secsize = sd->params.blksize; 659 sd->sc_dk.dk_label.d_ntracks = sd->params.heads; 660 sd->sc_dk.dk_label.d_nsectors = sd->params.sectors; 661 sd->sc_dk.dk_label.d_ncylinders = sd->params.cyls; 662 sd->sc_dk.dk_label.d_secpercyl = 663 sd->sc_dk.dk_label.d_ntracks * sd->sc_dk.dk_label.d_nsectors; 664 if (sd->sc_dk.dk_label.d_secpercyl == 0) { 665 sd->sc_dk.dk_label.d_secpercyl = 100; 666 /* as long as it's not 0 - readdisklabel divides by it (?) */ 667 } 668 669 strncpy(sd->sc_dk.dk_label.d_typename, "SCSI disk", 16); 670 sd->sc_dk.dk_label.d_type = DTYPE_SCSI; 671 strncpy(sd->sc_dk.dk_label.d_packname, "ficticious", 16); 672 sd->sc_dk.dk_label.d_secperunit = sd->params.disksize; 673 sd->sc_dk.dk_label.d_rpm = 3600; 674 sd->sc_dk.dk_label.d_interleave = 1; 675 sd->sc_dk.dk_label.d_flags = 0; 676 677 sd->sc_dk.dk_label.d_partitions[RAW_PART].p_offset = 0; 678 sd->sc_dk.dk_label.d_partitions[RAW_PART].p_size = 679 sd->sc_dk.dk_label.d_secperunit * 680 (sd->sc_dk.dk_label.d_secsize / DEV_BSIZE); 681 sd->sc_dk.dk_label.d_partitions[RAW_PART].p_fstype = FS_UNUSED; 682 sd->sc_dk.dk_label.d_npartitions = RAW_PART + 1; 683 684 sd->sc_dk.dk_label.d_magic = DISKMAGIC; 685 sd->sc_dk.dk_label.d_magic2 = DISKMAGIC; 686 sd->sc_dk.dk_label.d_checksum = dkcksum(&sd->sc_dk.dk_label); 687 688 /* 689 * Call the generic disklabel extraction routine 690 */ 691 if (errstring = readdisklabel(MAKESDDEV(0, sd->sc_dev.dv_unit, 692 RAW_PART), sdstrategy, &sd->sc_dk.dk_label, 693 &sd->sc_dk.dk_cpulabel)) { 694 printf("%s: %s\n", sd->sc_dev.dv_xname, errstring); 695 return; 696 } 697 698 sd->flags |= SDF_BSDLABEL; 699 } 700 701 /* 702 * Find out from the device what it's capacity is 703 */ 704 u_int32 705 sd_size(sd, flags) 706 struct sd_data *sd; 707 int flags; 708 { 709 struct scsi_read_cap_data rdcap; 710 struct scsi_read_capacity scsi_cmd; 711 u_int32 size; 712 713 /* 714 * make up a scsi command and ask the scsi driver to do 715 * it for you. 716 */ 717 bzero(&scsi_cmd, sizeof(scsi_cmd)); 718 scsi_cmd.op_code = READ_CAPACITY; 719 720 /* 721 * If the command works, interpret the result as a 4 byte 722 * number of blocks 723 */ 724 if (scsi_scsi_cmd(sd->sc_link, (struct scsi_generic *)&scsi_cmd, 725 sizeof(scsi_cmd), (u_char *)&rdcap, sizeof(rdcap), SDRETRIES, 726 2000, NULL, flags | SCSI_DATA_IN) != 0) { 727 printf("%s: could not get size\n", sd->sc_dev.dv_xname); 728 return 0; 729 } 730 731 size = (rdcap.addr_3 << 24) + (rdcap.addr_2 << 16) + 732 (rdcap.addr_1 << 8) + rdcap.addr_0 + 1; 733 734 return size; 735 } 736 737 /* 738 * Tell the device to map out a defective block 739 */ 740 int 741 sd_reassign_blocks(sd, block) 742 struct sd_data *sd; 743 int block; 744 { 745 struct scsi_reassign_blocks scsi_cmd; 746 struct scsi_reassign_blocks_data rbdata; 747 748 bzero(&scsi_cmd, sizeof(scsi_cmd)); 749 bzero(&rbdata, sizeof(rbdata)); 750 scsi_cmd.op_code = REASSIGN_BLOCKS; 751 752 rbdata.length_msb = 0; 753 rbdata.length_lsb = sizeof(rbdata.defect_descriptor[0]); 754 rbdata.defect_descriptor[0].dlbaddr_3 = ((block >> 24) & 0xff); 755 rbdata.defect_descriptor[0].dlbaddr_2 = ((block >> 16) & 0xff); 756 rbdata.defect_descriptor[0].dlbaddr_1 = ((block >> 8) & 0xff); 757 rbdata.defect_descriptor[0].dlbaddr_0 = ((block) & 0xff); 758 759 return scsi_scsi_cmd(sd->sc_link, (struct scsi_generic *)&scsi_cmd, 760 sizeof(scsi_cmd), (u_char *)&rbdata, sizeof(rbdata), SDRETRIES, 761 5000, NULL, SCSI_DATA_OUT); 762 } 763 764 #define b2tol(a) (((unsigned)(a##_1) << 8) + (unsigned)a##_0 ) 765 766 /* 767 * Get the scsi driver to send a full inquiry to the * device and use the 768 * results to fill out the disk parameter structure. 769 */ 770 int 771 sd_get_parms(sd, flags) 772 struct sd_data *sd; 773 int flags; 774 { 775 struct disk_parms *dp = &sd->params; 776 struct scsi_mode_sense scsi_cmd; 777 struct scsi_mode_sense_data { 778 struct scsi_mode_header header; 779 struct blk_desc blk_desc; 780 union disk_pages pages; 781 } scsi_sense; 782 u_int32 sectors; 783 784 /* 785 * do a "mode sense page 4" 786 */ 787 bzero(&scsi_cmd, sizeof(scsi_cmd)); 788 scsi_cmd.op_code = MODE_SENSE; 789 scsi_cmd.page = 4; 790 scsi_cmd.length = 0x20; 791 /* 792 * If the command worked, use the results to fill out 793 * the parameter structure 794 */ 795 if (scsi_scsi_cmd(sd->sc_link, (struct scsi_generic *)&scsi_cmd, 796 sizeof(scsi_cmd), (u_char *)&scsi_sense, sizeof(scsi_sense), 797 SDRETRIES, 6000, NULL, flags | SCSI_DATA_IN) != 0) { 798 printf("%s: could not mode sense (4)", sd->sc_dev.dv_xname); 799 fake_it: 800 printf("; using ficticious geometry\n"); 801 /* 802 * use adaptec standard ficticious geometry 803 * this depends on which controller (e.g. 1542C is 804 * different. but we have to put SOMETHING here..) 805 */ 806 sectors = sd_size(sd, flags); 807 dp->heads = 64; 808 dp->sectors = 32; 809 dp->cyls = sectors / (64 * 32); 810 dp->blksize = 512; 811 dp->disksize = sectors; 812 } else { 813 SC_DEBUG(sd->sc_link, SDEV_DB3, 814 ("%d cyls, %d heads, %d precomp, %d red_write, %d land_zone\n", 815 _3btol(&scsi_sense.pages.rigid_geometry.ncyl_2), 816 scsi_sense.pages.rigid_geometry.nheads, 817 b2tol(scsi_sense.pages.rigid_geometry.st_cyl_wp), 818 b2tol(scsi_sense.pages.rigid_geometry.st_cyl_rwc), 819 b2tol(scsi_sense.pages.rigid_geometry.land_zone))); 820 821 /* 822 * KLUDGE!! (for zone recorded disks) 823 * give a number of sectors so that sec * trks * cyls 824 * is <= disk_size 825 * can lead to wasted space! THINK ABOUT THIS ! 826 */ 827 dp->heads = scsi_sense.pages.rigid_geometry.nheads; 828 dp->cyls = 829 _3btol(&scsi_sense.pages.rigid_geometry.ncyl_2); 830 dp->blksize = _3btol(scsi_sense.blk_desc.blklen); 831 832 if (!dp->heads || !dp->cyls || 833 !dp->blksize) { 834 printf("%s: mode sense (4) returned nonsense", 835 sd->sc_dev.dv_xname); 836 goto fake_it; 837 } 838 839 sectors = sd_size(sd, flags); 840 dp->disksize = sectors; 841 sectors /= (dp->heads * dp->cyls); 842 dp->sectors = sectors; /* XXX dubious on SCSI */ 843 } 844 845 return 0; 846 } 847 848 int 849 sdsize(dev) 850 dev_t dev; 851 { 852 struct sd_data *sd; 853 int part; 854 int size; 855 856 if (sdopen(dev, 0, S_IFBLK) != 0) 857 return -1; 858 sd = sdcd.cd_devs[SDUNIT(dev)]; 859 part = SDPART(dev); 860 if ((sd->flags & SDF_BSDLABEL) == 0 || 861 sd->sc_dk.dk_label.d_partitions[part].p_fstype != FS_SWAP) 862 size = -1; 863 else 864 size = sd->sc_dk.dk_label.d_partitions[part].p_size; 865 if (sdclose(dev, 0, S_IFBLK) != 0) 866 return -1; 867 return size; 868 } 869 870 871 #define SCSIDUMP 1 872 #undef SCSIDUMP 873 #define NOT_TRUSTED 1 874 875 #ifdef SCSIDUMP 876 #include <vm/vm.h> 877 878 static struct scsi_xfer sx; 879 #define MAXTRANSFER 8 /* 1 page at a time */ 880 881 /* 882 * dump all of physical memory into the partition specified, starting 883 * at offset 'dumplo' into the partition. 884 */ 885 int 886 sddump(dev_t dev) 887 { /* dump core after a system crash */ 888 register struct sd_data *sd; /* disk unit to do the IO */ 889 int32 num; /* number of sectors to write */ 890 u_int32 unit, part; 891 int32 blkoff, blknum, blkcnt = MAXTRANSFER; 892 int32 nblocks; 893 char *addr; 894 struct scsi_rw_big cmd; 895 extern int Maxmem; 896 static int sddoingadump = 0; 897 #define MAPTO CADDR1 898 extern caddr_t MAPTO; /* map the page we are about to write, here */ 899 struct scsi_xfer *xs = &sx; 900 int retval; 901 int c; 902 903 addr = (char *) 0; /* starting address */ 904 905 /* toss any characters present prior to dump */ 906 while ((c = sgetc(1)) && (c != 0x100)); /*syscons and pccons differ */ 907 908 /* size of memory to dump */ 909 num = Maxmem; 910 unit = SDUNIT(dev); /* eventually support floppies? */ 911 part = SDPART(dev); /* file system */ 912 /* check for acceptable drive number */ 913 if (unit >= sdcd.cd_ndevs) 914 return ENXIO; 915 916 sd = sd_data[unit]; 917 if (!sd) 918 return ENXIO; 919 if (sd->sc_link->flags & SDEV_MEDIA_LOADED != SDEV_MEDIA_LOADED) 920 return ENXIO; 921 922 /* Convert to disk sectors */ 923 num = (u_int32)num * NBPG / sd->sc_dk.dk_label.d_secsize; 924 925 /* check if controller active */ 926 if (sddoingadump) 927 return EFAULT; 928 929 nblocks = sd->sc_dk.dk_label.d_partitions[part].p_size; 930 blkoff = sd->sc_dk.dk_label.d_partitions[part].p_offset; 931 932 /* check transfer bounds against partition size */ 933 if ((dumplo < 0) || ((dumplo + num) > nblocks)) 934 return EINVAL; 935 936 sddoingadump = 1; 937 938 blknum = dumplo + blkoff; 939 while (num > 0) { 940 pmap_enter(kernel_pmap, 941 MAPTO, 942 trunc_page(addr), 943 VM_PROT_READ, 944 TRUE); 945 #ifndef NOT_TRUSTED 946 /* 947 * Fill out the scsi command 948 */ 949 bzero(&cmd, sizeof(cmd)); 950 cmd.op_code = WRITE_BIG; 951 cmd.addr_3 = (blknum & 0xff000000) >> 24; 952 cmd.addr_2 = (blknum & 0xff0000) >> 16; 953 cmd.addr_1 = (blknum & 0xff00) >> 8; 954 cmd.addr_0 = blknum & 0xff; 955 cmd.length2 = (blkcnt & 0xff00) >> 8; 956 cmd.length1 = (blkcnt & 0xff); 957 /* 958 * Fill out the scsi_xfer structure 959 * Note: we cannot sleep as we may be an interrupt 960 * don't use scsi_scsi_cmd() as it may want 961 * to wait for an xs. 962 */ 963 bzero(xs, sizeof(sx)); 964 xs->flags |= SCSI_NOMASK | SCSI_NOSLEEP | INUSE; 965 xs->sc_link = sd->sc_link; 966 xs->retries = SDRETRIES; 967 xs->timeout = 10000; /* 10000 millisecs for a disk ! */ 968 xs->cmd = (struct scsi_generic *)&cmd; 969 xs->cmdlen = sizeof(cmd); 970 xs->resid = blkcnt * 512; 971 xs->error = XS_NOERROR; 972 xs->bp = 0; 973 xs->data = (u_char *) MAPTO; 974 xs->datalen = blkcnt * 512; 975 976 /* 977 * Pass all this info to the scsi driver. 978 */ 979 retval = (*(sd->sc_link->adapter->scsi_cmd)) (xs); 980 switch (retval) { 981 case SUCCESSFULLY_QUEUED: 982 case HAD_ERROR: 983 return ENXIO; /* we said not to sleep! */ 984 case COMPLETE: 985 break; 986 default: 987 return ENXIO; /* we said not to sleep! */ 988 } 989 #else /* NOT_TRUSTED */ 990 /* lets just talk about this first... */ 991 printf("sd%d: dump addr 0x%x, blk %d\n", unit, addr, blknum); 992 #endif /* NOT_TRUSTED */ 993 994 if ((unsigned)addr % (1024 * 1024) == 0) 995 printf("%d ", num / 2048); 996 /* update block count */ 997 num -= blkcnt; 998 blknum += blkcnt; 999 (int)addr += 512 * blkcnt; 1000 1001 /* operator aborting dump? */ 1002 if ((c = sgetc(1)) && (c != 0x100)) 1003 return EINTR; 1004 } 1005 return 0; 1006 } 1007 #else /* SCSIDUMP */ 1008 int 1009 sddump() 1010 { 1011 printf("\nsddump() -- not implemented\n"); 1012 delay(6000000); /* 6 seconds */ 1013 return -1; 1014 } 1015 #endif /* SCSIDUMP */ 1016