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