1 /* $NetBSD: wd.c,v 1.218 2001/12/03 00:20:23 bouyer Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 2001 Manuel Bouyer. 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 Manuel Bouyer. 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 * Copyright (c) 1998 The NetBSD Foundation, Inc. 34 * All rights reserved. 35 * 36 * This code is derived from software contributed to The NetBSD Foundation 37 * by Charles M. Hannum and by Onno van der Linden. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. All advertising materials mentioning features or use of this software 48 * must display the following acknowledgement: 49 * This product includes software developed by the NetBSD 50 * Foundation, Inc. and its contributors. 51 * 4. Neither the name of The NetBSD Foundation nor the names of its 52 * contributors may be used to endorse or promote products derived 53 * from this software without specific prior written permission. 54 * 55 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 56 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 57 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 58 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 59 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 60 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 61 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 62 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 63 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 64 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 65 * POSSIBILITY OF SUCH DAMAGE. 66 */ 67 68 #include <sys/cdefs.h> 69 __KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.218 2001/12/03 00:20:23 bouyer Exp $"); 70 71 #ifndef WDCDEBUG 72 #define WDCDEBUG 73 #endif /* WDCDEBUG */ 74 75 #include "rnd.h" 76 77 #include <sys/param.h> 78 #include <sys/systm.h> 79 #include <sys/kernel.h> 80 #include <sys/conf.h> 81 #include <sys/file.h> 82 #include <sys/stat.h> 83 #include <sys/ioctl.h> 84 #include <sys/buf.h> 85 #include <sys/uio.h> 86 #include <sys/malloc.h> 87 #include <sys/device.h> 88 #include <sys/disklabel.h> 89 #include <sys/disk.h> 90 #include <sys/syslog.h> 91 #include <sys/proc.h> 92 #include <sys/vnode.h> 93 #if NRND > 0 94 #include <sys/rnd.h> 95 #endif 96 97 #include <machine/intr.h> 98 #include <machine/bus.h> 99 100 #include <dev/ata/atareg.h> 101 #include <dev/ata/atavar.h> 102 #include <dev/ata/wdvar.h> 103 #include <dev/ic/wdcreg.h> 104 #include <sys/ataio.h> 105 #include "locators.h" 106 107 #define WAITTIME (4 * hz) /* time to wait for a completion */ 108 #define WDIORETRIES_SINGLE 4 /* number of retries before single-sector */ 109 #define WDIORETRIES 5 /* number of retries before giving up */ 110 #define RECOVERYTIME hz/2 /* time to wait before retrying a cmd */ 111 112 #define WDUNIT(dev) DISKUNIT(dev) 113 #define WDPART(dev) DISKPART(dev) 114 #define WDMINOR(unit, part) DISKMINOR(unit, part) 115 #define MAKEWDDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part) 116 117 #define WDLABELDEV(dev) (MAKEWDDEV(major(dev), WDUNIT(dev), RAW_PART)) 118 119 #define DEBUG_INTR 0x01 120 #define DEBUG_XFERS 0x02 121 #define DEBUG_STATUS 0x04 122 #define DEBUG_FUNCS 0x08 123 #define DEBUG_PROBE 0x10 124 #ifdef WDCDEBUG 125 extern int wdcdebug_wd_mask; /* init'ed in ata_wdc.c */ 126 #define WDCDEBUG_PRINT(args, level) \ 127 if (wdcdebug_wd_mask & (level)) \ 128 printf args 129 #else 130 #define WDCDEBUG_PRINT(args, level) 131 #endif 132 133 struct wd_softc { 134 /* General disk infos */ 135 struct device sc_dev; 136 struct disk sc_dk; 137 struct buf_queue sc_q; 138 struct callout sc_restart_ch; 139 /* IDE disk soft states */ 140 struct ata_bio sc_wdc_bio; /* current transfer */ 141 struct buf *sc_bp; /* buf being transfered */ 142 void *wdc_softc; /* pointer to our parent */ 143 struct ata_drive_datas *drvp; /* Our controller's infos */ 144 const struct ata_bustype *atabus; 145 int openings; 146 struct ataparams sc_params;/* drive characteistics found */ 147 int sc_flags; 148 #define WDF_LOCKED 0x01 149 #define WDF_WANTED 0x02 150 #define WDF_WLABEL 0x04 /* label is writable */ 151 #define WDF_LABELLING 0x08 /* writing label */ 152 /* 153 * XXX Nothing resets this yet, but disk change sensing will when ATA-4 is 154 * more fully implemented. 155 */ 156 #define WDF_LOADED 0x10 /* parameters loaded */ 157 #define WDF_WAIT 0x20 /* waiting for resources */ 158 #define WDF_LBA 0x40 /* using LBA mode */ 159 #define WDF_KLABEL 0x80 /* retain label after 'full' close */ 160 int sc_capacity; 161 int cyl; /* actual drive parameters */ 162 int heads; 163 int sectors; 164 int retries; /* number of xfer retry */ 165 166 void *sc_sdhook; /* our shutdown hook */ 167 168 #if NRND > 0 169 rndsource_element_t rnd_source; 170 #endif 171 }; 172 173 #define sc_drive sc_wdc_bio.drive 174 #define sc_mode sc_wdc_bio.mode 175 #define sc_multi sc_wdc_bio.multi 176 #define sc_badsect sc_wdc_bio.badsect 177 178 int wdprobe __P((struct device *, struct cfdata *, void *)); 179 void wdattach __P((struct device *, struct device *, void *)); 180 int wddetach __P((struct device *, int)); 181 int wdactivate __P((struct device *, enum devact)); 182 int wdprint __P((void *, char *)); 183 void wdperror __P((struct ata_drive_datas *, int, char *)); 184 185 struct cfattach wd_ca = { 186 sizeof(struct wd_softc), wdprobe, wdattach, wddetach, wdactivate 187 }; 188 189 extern struct cfdriver wd_cd; 190 191 /* 192 * Glue necessary to hook WDCIOCCOMMAND into physio 193 */ 194 195 struct wd_ioctl { 196 LIST_ENTRY(wd_ioctl) wi_list; 197 struct buf wi_bp; 198 struct uio wi_uio; 199 struct iovec wi_iov; 200 atareq_t wi_atareq; 201 struct wd_softc *wi_softc; 202 }; 203 204 LIST_HEAD(, wd_ioctl) wi_head; 205 206 struct wd_ioctl *wi_find __P((struct buf *)); 207 void wi_free __P((struct wd_ioctl *)); 208 struct wd_ioctl *wi_get __P((void)); 209 void wdioctlstrategy __P((struct buf *)); 210 211 void wdgetdefaultlabel __P((struct wd_softc *, struct disklabel *)); 212 void wdgetdisklabel __P((struct wd_softc *)); 213 void wdstrategy __P((struct buf *)); 214 void wdstart __P((void *)); 215 void __wdstart __P((struct wd_softc*, struct buf *)); 216 void wdrestart __P((void*)); 217 int wd_get_params __P((struct wd_softc *, u_int8_t, struct ataparams *)); 218 void wd_flushcache __P((struct wd_softc *, int)); 219 void wd_shutdown __P((void*)); 220 221 struct dkdriver wddkdriver = { wdstrategy }; 222 223 /* XXX: these should go elsewhere */ 224 cdev_decl(wd); 225 bdev_decl(wd); 226 227 #ifdef HAS_BAD144_HANDLING 228 static void bad144intern __P((struct wd_softc *)); 229 #endif 230 int wdlock __P((struct wd_softc *)); 231 void wdunlock __P((struct wd_softc *)); 232 233 int 234 wdprobe(parent, match, aux) 235 struct device *parent; 236 struct cfdata *match; 237 238 void *aux; 239 { 240 struct ata_device *adev = aux; 241 242 if (adev == NULL) 243 return 0; 244 if (adev->adev_bustype->bustype_type != SCSIPI_BUSTYPE_ATA) 245 return 0; 246 247 if (match->cf_loc[ATACF_CHANNEL] != ATACF_CHANNEL_DEFAULT && 248 match->cf_loc[ATACF_CHANNEL] != adev->adev_channel) 249 return 0; 250 251 if (match->cf_loc[ATACF_DRIVE] != ATACF_DRIVE_DEFAULT && 252 match->cf_loc[ATACF_DRIVE] != adev->adev_drv_data->drive) 253 return 0; 254 return 1; 255 } 256 257 void 258 wdattach(parent, self, aux) 259 struct device *parent, *self; 260 void *aux; 261 { 262 struct wd_softc *wd = (void *)self; 263 struct ata_device *adev= aux; 264 int i, blank; 265 char buf[41], pbuf[9], c, *p, *q; 266 WDCDEBUG_PRINT(("wdattach\n"), DEBUG_FUNCS | DEBUG_PROBE); 267 268 callout_init(&wd->sc_restart_ch); 269 BUFQ_INIT(&wd->sc_q); 270 271 wd->atabus = adev->adev_bustype; 272 wd->openings = adev->adev_openings; 273 wd->drvp = adev->adev_drv_data;; 274 wd->wdc_softc = parent; 275 /* give back our softc to our caller */ 276 wd->drvp->drv_softc = &wd->sc_dev; 277 278 /* read our drive info */ 279 if (wd_get_params(wd, AT_POLL, &wd->sc_params) != 0) { 280 printf("%s: IDENTIFY failed\n", wd->sc_dev.dv_xname); 281 return; 282 } 283 284 for (blank = 0, p = wd->sc_params.atap_model, q = buf, i = 0; 285 i < sizeof(wd->sc_params.atap_model); i++) { 286 c = *p++; 287 if (c == '\0') 288 break; 289 if (c != ' ') { 290 if (blank) { 291 *q++ = ' '; 292 blank = 0; 293 } 294 *q++ = c; 295 } else 296 blank = 1; 297 } 298 *q++ = '\0'; 299 300 printf(": <%s>\n", buf); 301 302 if ((wd->sc_params.atap_multi & 0xff) > 1) { 303 wd->sc_multi = wd->sc_params.atap_multi & 0xff; 304 } else { 305 wd->sc_multi = 1; 306 } 307 308 printf("%s: drive supports %d-sector PIO transfers,", 309 wd->sc_dev.dv_xname, wd->sc_multi); 310 311 /* Prior to ATA-4, LBA was optional. */ 312 if ((wd->sc_params.atap_capabilities1 & WDC_CAP_LBA) != 0) 313 wd->sc_flags |= WDF_LBA; 314 #if 0 315 /* ATA-4 requires LBA. */ 316 if (wd->sc_params.atap_ataversion != 0xffff && 317 wd->sc_params.atap_ataversion >= WDC_VER_ATA4) 318 wd->sc_flags |= WDF_LBA; 319 #endif 320 321 if ((wd->sc_flags & WDF_LBA) != 0) { 322 printf(" LBA addressing\n"); 323 wd->sc_capacity = 324 (wd->sc_params.atap_capacity[1] << 16) | 325 wd->sc_params.atap_capacity[0]; 326 } else { 327 printf(" chs addressing\n"); 328 wd->sc_capacity = 329 wd->sc_params.atap_cylinders * 330 wd->sc_params.atap_heads * 331 wd->sc_params.atap_sectors; 332 } 333 format_bytes(pbuf, sizeof(pbuf), 334 (u_int64_t)wd->sc_capacity * DEV_BSIZE); 335 printf("%s: %s, %d cyl, %d head, %d sec, " 336 "%d bytes/sect x %d sectors\n", 337 self->dv_xname, pbuf, wd->sc_params.atap_cylinders, 338 wd->sc_params.atap_heads, wd->sc_params.atap_sectors, 339 DEV_BSIZE, wd->sc_capacity); 340 341 WDCDEBUG_PRINT(("%s: atap_dmatiming_mimi=%d, atap_dmatiming_recom=%d\n", 342 self->dv_xname, wd->sc_params.atap_dmatiming_mimi, 343 wd->sc_params.atap_dmatiming_recom), DEBUG_PROBE); 344 /* 345 * Initialize and attach the disk structure. 346 */ 347 wd->sc_dk.dk_driver = &wddkdriver; 348 wd->sc_dk.dk_name = wd->sc_dev.dv_xname; 349 disk_attach(&wd->sc_dk); 350 wd->sc_wdc_bio.lp = wd->sc_dk.dk_label; 351 wd->sc_sdhook = shutdownhook_establish(wd_shutdown, wd); 352 if (wd->sc_sdhook == NULL) 353 printf("%s: WARNING: unable to establish shutdown hook\n", 354 wd->sc_dev.dv_xname); 355 #if NRND > 0 356 rnd_attach_source(&wd->rnd_source, wd->sc_dev.dv_xname, 357 RND_TYPE_DISK, 0); 358 #endif 359 } 360 361 int 362 wdactivate(self, act) 363 struct device *self; 364 enum devact act; 365 { 366 int rv = 0; 367 368 switch (act) { 369 case DVACT_ACTIVATE: 370 rv = EOPNOTSUPP; 371 break; 372 373 case DVACT_DEACTIVATE: 374 /* 375 * Nothing to do; we key off the device's DVF_ACTIVATE. 376 */ 377 break; 378 } 379 return (rv); 380 } 381 382 int 383 wddetach(self, flags) 384 struct device *self; 385 int flags; 386 { 387 struct wd_softc *sc = (struct wd_softc *)self; 388 struct buf *bp; 389 int s, bmaj, cmaj, i, mn; 390 391 /* locate the major number */ 392 for (bmaj = 0; bmaj < nblkdev; bmaj++) 393 if (bdevsw[bmaj].d_open == wdopen) 394 break; 395 for (cmaj = 0; cmaj < nchrdev; cmaj++) 396 if (cdevsw[cmaj].d_open == wdopen) 397 break; 398 399 s = splbio(); 400 401 /* Kill off any queued buffers. */ 402 while ((bp = BUFQ_FIRST(&sc->sc_q)) != NULL) { 403 BUFQ_REMOVE(&sc->sc_q, bp); 404 bp->b_error = EIO; 405 bp->b_flags |= B_ERROR; 406 bp->b_resid = bp->b_bcount; 407 biodone(bp); 408 } 409 410 splx(s); 411 412 /* Nuke the vnodes for any open instances. */ 413 for (i = 0; i < MAXPARTITIONS; i++) { 414 mn = WDMINOR(self->dv_unit, i); 415 vdevgone(bmaj, mn, mn, VBLK); 416 vdevgone(cmaj, mn, mn, VCHR); 417 } 418 419 /* Detach disk. */ 420 disk_detach(&sc->sc_dk); 421 422 /* Get rid of the shutdown hook. */ 423 if (sc->sc_sdhook != NULL) 424 shutdownhook_disestablish(sc->sc_sdhook); 425 426 #if NRND > 0 427 /* Unhook the entropy source. */ 428 rnd_detach_source(&sc->rnd_source); 429 #endif 430 431 return (0); 432 } 433 434 /* 435 * Read/write routine for a buffer. Validates the arguments and schedules the 436 * transfer. Does not wait for the transfer to complete. 437 */ 438 void 439 wdstrategy(bp) 440 struct buf *bp; 441 { 442 struct wd_softc *wd = device_lookup(&wd_cd, WDUNIT(bp->b_dev)); 443 struct disklabel *lp = wd->sc_dk.dk_label; 444 daddr_t blkno; 445 int s; 446 447 WDCDEBUG_PRINT(("wdstrategy (%s)\n", wd->sc_dev.dv_xname), 448 DEBUG_XFERS); 449 450 /* Valid request? */ 451 if (bp->b_blkno < 0 || 452 (bp->b_bcount % lp->d_secsize) != 0 || 453 (bp->b_bcount / lp->d_secsize) >= (1 << NBBY)) { 454 bp->b_error = EINVAL; 455 goto bad; 456 } 457 458 /* If device invalidated (e.g. media change, door open), error. */ 459 if ((wd->sc_flags & WDF_LOADED) == 0) { 460 bp->b_error = EIO; 461 goto bad; 462 } 463 464 /* If it's a null transfer, return immediately. */ 465 if (bp->b_bcount == 0) 466 goto done; 467 468 /* 469 * Do bounds checking, adjust transfer. if error, process. 470 * If end of partition, just return. 471 */ 472 if (WDPART(bp->b_dev) != RAW_PART && 473 bounds_check_with_label(bp, wd->sc_dk.dk_label, 474 (wd->sc_flags & (WDF_WLABEL|WDF_LABELLING)) != 0) <= 0) 475 goto done; 476 477 /* 478 * Now convert the block number to absolute and put it in 479 * terms of the device's logical block size. 480 */ 481 if (lp->d_secsize >= DEV_BSIZE) 482 blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE); 483 else 484 blkno = bp->b_blkno * (DEV_BSIZE / lp->d_secsize); 485 486 if (WDPART(bp->b_dev) != RAW_PART) 487 blkno += lp->d_partitions[WDPART(bp->b_dev)].p_offset; 488 489 bp->b_rawblkno = blkno; 490 491 /* Queue transfer on drive, activate drive and controller if idle. */ 492 s = splbio(); 493 disksort_blkno(&wd->sc_q, bp); 494 wdstart(wd); 495 splx(s); 496 return; 497 bad: 498 bp->b_flags |= B_ERROR; 499 done: 500 /* Toss transfer; we're done early. */ 501 bp->b_resid = bp->b_bcount; 502 biodone(bp); 503 } 504 505 /* 506 * Queue a drive for I/O. 507 */ 508 void 509 wdstart(arg) 510 void *arg; 511 { 512 struct wd_softc *wd = arg; 513 struct buf *bp = NULL; 514 515 WDCDEBUG_PRINT(("wdstart %s\n", wd->sc_dev.dv_xname), 516 DEBUG_XFERS); 517 while (wd->openings > 0) { 518 519 /* Is there a buf for us ? */ 520 if ((bp = BUFQ_FIRST(&wd->sc_q)) == NULL) 521 return; 522 BUFQ_REMOVE(&wd->sc_q, bp); 523 524 /* 525 * Make the command. First lock the device 526 */ 527 wd->openings--; 528 529 wd->retries = 0; 530 __wdstart(wd, bp); 531 } 532 } 533 534 void 535 __wdstart(wd, bp) 536 struct wd_softc *wd; 537 struct buf *bp; 538 { 539 540 wd->sc_wdc_bio.blkno = bp->b_rawblkno; 541 wd->sc_wdc_bio.blkdone =0; 542 wd->sc_bp = bp; 543 /* 544 * If we're retrying, retry in single-sector mode. This will give us 545 * the sector number of the problem, and will eventually allow the 546 * transfer to succeed. 547 */ 548 if (wd->sc_multi == 1 || wd->retries >= WDIORETRIES_SINGLE) 549 wd->sc_wdc_bio.flags = ATA_SINGLE; 550 else 551 wd->sc_wdc_bio.flags = 0; 552 if (wd->sc_flags & WDF_LBA) 553 wd->sc_wdc_bio.flags |= ATA_LBA; 554 if (bp->b_flags & B_READ) 555 wd->sc_wdc_bio.flags |= ATA_READ; 556 wd->sc_wdc_bio.bcount = bp->b_bcount; 557 wd->sc_wdc_bio.databuf = bp->b_data; 558 /* Instrumentation. */ 559 disk_busy(&wd->sc_dk); 560 switch (wd->atabus->ata_bio(wd->drvp, &wd->sc_wdc_bio)) { 561 case WDC_TRY_AGAIN: 562 callout_reset(&wd->sc_restart_ch, hz, wdrestart, wd); 563 break; 564 case WDC_QUEUED: 565 case WDC_COMPLETE: 566 break; 567 default: 568 panic("__wdstart: bad return code from ata_bio()"); 569 } 570 } 571 572 void 573 wddone(v) 574 void *v; 575 { 576 struct wd_softc *wd = v; 577 struct buf *bp = wd->sc_bp; 578 char buf[256], *errbuf = buf; 579 WDCDEBUG_PRINT(("wddone %s\n", wd->sc_dev.dv_xname), 580 DEBUG_XFERS); 581 582 if (bp == NULL) 583 return; 584 bp->b_resid = wd->sc_wdc_bio.bcount; 585 errbuf[0] = '\0'; 586 switch (wd->sc_wdc_bio.error) { 587 case ERR_DMA: 588 errbuf = "DMA error"; 589 goto retry; 590 case ERR_DF: 591 errbuf = "device fault"; 592 goto retry; 593 case TIMEOUT: 594 errbuf = "device timeout"; 595 goto retry; 596 case ERROR: 597 /* Don't care about media change bits */ 598 if (wd->sc_wdc_bio.r_error != 0 && 599 (wd->sc_wdc_bio.r_error & ~(WDCE_MC | WDCE_MCR)) == 0) 600 goto noerror; 601 wdperror(wd->drvp, wd->sc_wdc_bio.r_error, errbuf); 602 retry: /* Just reset and retry. Can we do more ? */ 603 wd->atabus->ata_reset_channel(wd->drvp); 604 diskerr(bp, "wd", errbuf, LOG_PRINTF, 605 wd->sc_wdc_bio.blkdone, wd->sc_dk.dk_label); 606 if (wd->retries++ < WDIORETRIES) { 607 printf(", retrying\n"); 608 callout_reset(&wd->sc_restart_ch, RECOVERYTIME, 609 wdrestart, wd); 610 return; 611 } 612 printf("\n"); 613 bp->b_flags |= B_ERROR; 614 bp->b_error = EIO; 615 break; 616 case NOERROR: 617 noerror: if ((wd->sc_wdc_bio.flags & ATA_CORR) || wd->retries > 0) 618 printf("%s: soft error (corrected)\n", 619 wd->sc_dev.dv_xname); 620 break; 621 case ERR_NODEV: 622 bp->b_flags |= B_ERROR; 623 bp->b_error = EIO; 624 break; 625 } 626 disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid)); 627 #if NRND > 0 628 rnd_add_uint32(&wd->rnd_source, bp->b_blkno); 629 #endif 630 biodone(bp); 631 wd->openings++; 632 wdstart(wd); 633 } 634 635 void 636 wdrestart(v) 637 void *v; 638 { 639 struct wd_softc *wd = v; 640 struct buf *bp = wd->sc_bp; 641 int s; 642 WDCDEBUG_PRINT(("wdrestart %s\n", wd->sc_dev.dv_xname), 643 DEBUG_XFERS); 644 645 s = splbio(); 646 __wdstart(v, bp); 647 splx(s); 648 } 649 650 int 651 wdread(dev, uio, flags) 652 dev_t dev; 653 struct uio *uio; 654 int flags; 655 { 656 657 WDCDEBUG_PRINT(("wdread\n"), DEBUG_XFERS); 658 return (physio(wdstrategy, NULL, dev, B_READ, minphys, uio)); 659 } 660 661 int 662 wdwrite(dev, uio, flags) 663 dev_t dev; 664 struct uio *uio; 665 int flags; 666 { 667 668 WDCDEBUG_PRINT(("wdwrite\n"), DEBUG_XFERS); 669 return (physio(wdstrategy, NULL, dev, B_WRITE, minphys, uio)); 670 } 671 672 /* 673 * Wait interruptibly for an exclusive lock. 674 * 675 * XXX 676 * Several drivers do this; it should be abstracted and made MP-safe. 677 */ 678 int 679 wdlock(wd) 680 struct wd_softc *wd; 681 { 682 int error; 683 int s; 684 685 WDCDEBUG_PRINT(("wdlock\n"), DEBUG_FUNCS); 686 687 s = splbio(); 688 689 while ((wd->sc_flags & WDF_LOCKED) != 0) { 690 wd->sc_flags |= WDF_WANTED; 691 if ((error = tsleep(wd, PRIBIO | PCATCH, 692 "wdlck", 0)) != 0) { 693 splx(s); 694 return error; 695 } 696 } 697 wd->sc_flags |= WDF_LOCKED; 698 splx(s); 699 return 0; 700 } 701 702 /* 703 * Unlock and wake up any waiters. 704 */ 705 void 706 wdunlock(wd) 707 struct wd_softc *wd; 708 { 709 710 WDCDEBUG_PRINT(("wdunlock\n"), DEBUG_FUNCS); 711 712 wd->sc_flags &= ~WDF_LOCKED; 713 if ((wd->sc_flags & WDF_WANTED) != 0) { 714 wd->sc_flags &= ~WDF_WANTED; 715 wakeup(wd); 716 } 717 } 718 719 int 720 wdopen(dev, flag, fmt, p) 721 dev_t dev; 722 int flag, fmt; 723 struct proc *p; 724 { 725 struct wd_softc *wd; 726 int part, error; 727 728 WDCDEBUG_PRINT(("wdopen\n"), DEBUG_FUNCS); 729 wd = device_lookup(&wd_cd, WDUNIT(dev)); 730 if (wd == NULL) 731 return (ENXIO); 732 733 /* 734 * If this is the first open of this device, add a reference 735 * to the adapter. 736 */ 737 if (wd->sc_dk.dk_openmask == 0 && 738 (error = wd->atabus->ata_addref(wd->drvp)) != 0) 739 return (error); 740 741 if ((error = wdlock(wd)) != 0) 742 goto bad4; 743 744 if (wd->sc_dk.dk_openmask != 0) { 745 /* 746 * If any partition is open, but the disk has been invalidated, 747 * disallow further opens. 748 */ 749 if ((wd->sc_flags & WDF_LOADED) == 0) { 750 error = EIO; 751 goto bad3; 752 } 753 } else { 754 if ((wd->sc_flags & WDF_LOADED) == 0) { 755 wd->sc_flags |= WDF_LOADED; 756 757 /* Load the physical device parameters. */ 758 wd_get_params(wd, AT_WAIT, &wd->sc_params); 759 760 /* Load the partition info if not already loaded. */ 761 wdgetdisklabel(wd); 762 } 763 } 764 765 part = WDPART(dev); 766 767 /* Check that the partition exists. */ 768 if (part != RAW_PART && 769 (part >= wd->sc_dk.dk_label->d_npartitions || 770 wd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) { 771 error = ENXIO; 772 goto bad; 773 } 774 775 /* Insure only one open at a time. */ 776 switch (fmt) { 777 case S_IFCHR: 778 wd->sc_dk.dk_copenmask |= (1 << part); 779 break; 780 case S_IFBLK: 781 wd->sc_dk.dk_bopenmask |= (1 << part); 782 break; 783 } 784 wd->sc_dk.dk_openmask = 785 wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask; 786 787 wdunlock(wd); 788 return 0; 789 790 bad: 791 if (wd->sc_dk.dk_openmask == 0) { 792 } 793 794 bad3: 795 wdunlock(wd); 796 bad4: 797 if (wd->sc_dk.dk_openmask == 0) 798 wd->atabus->ata_delref(wd->drvp); 799 return error; 800 } 801 802 int 803 wdclose(dev, flag, fmt, p) 804 dev_t dev; 805 int flag, fmt; 806 struct proc *p; 807 { 808 struct wd_softc *wd = device_lookup(&wd_cd, WDUNIT(dev)); 809 int part = WDPART(dev); 810 int error; 811 812 WDCDEBUG_PRINT(("wdclose\n"), DEBUG_FUNCS); 813 if ((error = wdlock(wd)) != 0) 814 return error; 815 816 switch (fmt) { 817 case S_IFCHR: 818 wd->sc_dk.dk_copenmask &= ~(1 << part); 819 break; 820 case S_IFBLK: 821 wd->sc_dk.dk_bopenmask &= ~(1 << part); 822 break; 823 } 824 wd->sc_dk.dk_openmask = 825 wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask; 826 827 if (wd->sc_dk.dk_openmask == 0) { 828 wd_flushcache(wd, AT_WAIT); 829 /* XXXX Must wait for I/O to complete! */ 830 831 if (! (wd->sc_flags & WDF_KLABEL)) 832 wd->sc_flags &= ~WDF_LOADED; 833 834 wd->atabus->ata_delref(wd->drvp); 835 } 836 837 wdunlock(wd); 838 return 0; 839 } 840 841 void 842 wdgetdefaultlabel(wd, lp) 843 struct wd_softc *wd; 844 struct disklabel *lp; 845 { 846 847 WDCDEBUG_PRINT(("wdgetdefaultlabel\n"), DEBUG_FUNCS); 848 memset(lp, 0, sizeof(struct disklabel)); 849 850 lp->d_secsize = DEV_BSIZE; 851 lp->d_ntracks = wd->sc_params.atap_heads; 852 lp->d_nsectors = wd->sc_params.atap_sectors; 853 lp->d_ncylinders = wd->sc_params.atap_cylinders; 854 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; 855 856 if (strcmp(wd->sc_params.atap_model, "ST506") == 0) 857 lp->d_type = DTYPE_ST506; 858 else 859 lp->d_type = DTYPE_ESDI; 860 861 strncpy(lp->d_typename, wd->sc_params.atap_model, 16); 862 strncpy(lp->d_packname, "fictitious", 16); 863 lp->d_secperunit = wd->sc_capacity; 864 lp->d_rpm = 3600; 865 lp->d_interleave = 1; 866 lp->d_flags = 0; 867 868 lp->d_partitions[RAW_PART].p_offset = 0; 869 lp->d_partitions[RAW_PART].p_size = 870 lp->d_secperunit * (lp->d_secsize / DEV_BSIZE); 871 lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; 872 lp->d_npartitions = RAW_PART + 1; 873 874 lp->d_magic = DISKMAGIC; 875 lp->d_magic2 = DISKMAGIC; 876 lp->d_checksum = dkcksum(lp); 877 } 878 879 /* 880 * Fabricate a default disk label, and try to read the correct one. 881 */ 882 void 883 wdgetdisklabel(wd) 884 struct wd_softc *wd; 885 { 886 struct disklabel *lp = wd->sc_dk.dk_label; 887 char *errstring; 888 889 WDCDEBUG_PRINT(("wdgetdisklabel\n"), DEBUG_FUNCS); 890 891 memset(wd->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel)); 892 893 wdgetdefaultlabel(wd, lp); 894 895 wd->sc_badsect[0] = -1; 896 897 if (wd->drvp->state > RECAL) 898 wd->drvp->drive_flags |= DRIVE_RESET; 899 errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, RAW_PART), 900 wdstrategy, lp, wd->sc_dk.dk_cpulabel); 901 if (errstring) { 902 /* 903 * This probably happened because the drive's default 904 * geometry doesn't match the DOS geometry. We 905 * assume the DOS geometry is now in the label and try 906 * again. XXX This is a kluge. 907 */ 908 if (wd->drvp->state > RECAL) 909 wd->drvp->drive_flags |= DRIVE_RESET; 910 errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, 911 RAW_PART), wdstrategy, lp, wd->sc_dk.dk_cpulabel); 912 } 913 if (errstring) { 914 printf("%s: %s\n", wd->sc_dev.dv_xname, errstring); 915 return; 916 } 917 918 if (wd->drvp->state > RECAL) 919 wd->drvp->drive_flags |= DRIVE_RESET; 920 #ifdef HAS_BAD144_HANDLING 921 if ((lp->d_flags & D_BADSECT) != 0) 922 bad144intern(wd); 923 #endif 924 } 925 926 void 927 wdperror(drvp, errno, buf) 928 struct ata_drive_datas *drvp; 929 int errno; 930 char *buf; 931 { 932 static char *errstr0_3[] = {"address mark not found", 933 "track 0 not found", "aborted command", "media change requested", 934 "id not found", "media changed", "uncorrectable data error", 935 "bad block detected"}; 936 static char *errstr4_5[] = {"obsolete (address mark not found)", 937 "no media/write protected", "aborted command", 938 "media change requested", "id not found", "media changed", 939 "uncorrectable data error", "interface CRC error"}; 940 char **errstr; 941 int i; 942 char *sep = ""; 943 944 if (drvp->ata_vers >= 4) 945 errstr = errstr4_5; 946 else 947 errstr = errstr0_3; 948 949 if (errno == 0) 950 sprintf(buf, "error not notified"); 951 952 for (i = 0; i < 8; i++) { 953 if (errno & (1 << i)) { 954 buf += sprintf(buf, "%s%s", sep, errstr[i]); 955 sep = ", "; 956 } 957 } 958 } 959 960 int 961 wdioctl(dev, xfer, addr, flag, p) 962 dev_t dev; 963 u_long xfer; 964 caddr_t addr; 965 int flag; 966 struct proc *p; 967 { 968 struct wd_softc *wd = device_lookup(&wd_cd, WDUNIT(dev)); 969 int error; 970 #ifdef __HAVE_OLD_DISKLABEL 971 struct disklabel newlabel; 972 #endif 973 974 WDCDEBUG_PRINT(("wdioctl\n"), DEBUG_FUNCS); 975 976 if ((wd->sc_flags & WDF_LOADED) == 0) 977 return EIO; 978 979 switch (xfer) { 980 #ifdef HAS_BAD144_HANDLING 981 case DIOCSBAD: 982 if ((flag & FWRITE) == 0) 983 return EBADF; 984 wd->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr; 985 wd->sc_dk.dk_label->d_flags |= D_BADSECT; 986 bad144intern(wd); 987 return 0; 988 #endif 989 990 case DIOCGDINFO: 991 *(struct disklabel *)addr = *(wd->sc_dk.dk_label); 992 return 0; 993 #ifdef __HAVE_OLD_DISKLABEL 994 case ODIOCGDINFO: 995 newlabel = *(wd->sc_dk.dk_label); 996 if (newlabel.d_npartitions > OLDMAXPARTITIONS) 997 return ENOTTY; 998 memcpy(addr, &newlabel, sizeof (struct olddisklabel)); 999 return 0; 1000 #endif 1001 1002 case DIOCGPART: 1003 ((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label; 1004 ((struct partinfo *)addr)->part = 1005 &wd->sc_dk.dk_label->d_partitions[WDPART(dev)]; 1006 return 0; 1007 1008 case DIOCWDINFO: 1009 case DIOCSDINFO: 1010 #ifdef __HAVE_OLD_DISKLABEL 1011 case ODIOCWDINFO: 1012 case ODIOCSDINFO: 1013 #endif 1014 { 1015 struct disklabel *lp; 1016 1017 #ifdef __HAVE_OLD_DISKLABEL 1018 if (xfer == ODIOCSDINFO || xfer == ODIOCWDINFO) { 1019 memset(&newlabel, 0, sizeof newlabel); 1020 memcpy(&newlabel, addr, sizeof (struct olddisklabel)); 1021 lp = &newlabel; 1022 } else 1023 #endif 1024 lp = (struct disklabel *)addr; 1025 1026 if ((flag & FWRITE) == 0) 1027 return EBADF; 1028 1029 if ((error = wdlock(wd)) != 0) 1030 return error; 1031 wd->sc_flags |= WDF_LABELLING; 1032 1033 error = setdisklabel(wd->sc_dk.dk_label, 1034 lp, /*wd->sc_dk.dk_openmask : */0, 1035 wd->sc_dk.dk_cpulabel); 1036 if (error == 0) { 1037 if (wd->drvp->state > RECAL) 1038 wd->drvp->drive_flags |= DRIVE_RESET; 1039 if (xfer == DIOCWDINFO 1040 #ifdef __HAVE_OLD_DISKLABEL 1041 || xfer == ODIOCWDINFO 1042 #endif 1043 ) 1044 error = writedisklabel(WDLABELDEV(dev), 1045 wdstrategy, wd->sc_dk.dk_label, 1046 wd->sc_dk.dk_cpulabel); 1047 } 1048 1049 wd->sc_flags &= ~WDF_LABELLING; 1050 wdunlock(wd); 1051 return error; 1052 } 1053 1054 case DIOCKLABEL: 1055 if (*(int *)addr) 1056 wd->sc_flags |= WDF_KLABEL; 1057 else 1058 wd->sc_flags &= ~WDF_KLABEL; 1059 return 0; 1060 1061 case DIOCWLABEL: 1062 if ((flag & FWRITE) == 0) 1063 return EBADF; 1064 if (*(int *)addr) 1065 wd->sc_flags |= WDF_WLABEL; 1066 else 1067 wd->sc_flags &= ~WDF_WLABEL; 1068 return 0; 1069 1070 case DIOCGDEFLABEL: 1071 wdgetdefaultlabel(wd, (struct disklabel *)addr); 1072 return 0; 1073 #ifdef __HAVE_OLD_DISKLABEL 1074 case ODIOCGDEFLABEL: 1075 wdgetdefaultlabel(wd, &newlabel); 1076 if (newlabel.d_npartitions > OLDMAXPARTITIONS) 1077 return ENOTTY; 1078 memcpy(addr, &newlabel, sizeof (struct olddisklabel)); 1079 return 0; 1080 #endif 1081 1082 #ifdef notyet 1083 case DIOCWFORMAT: 1084 if ((flag & FWRITE) == 0) 1085 return EBADF; 1086 { 1087 register struct format_op *fop; 1088 struct iovec aiov; 1089 struct uio auio; 1090 1091 fop = (struct format_op *)addr; 1092 aiov.iov_base = fop->df_buf; 1093 aiov.iov_len = fop->df_count; 1094 auio.uio_iov = &aiov; 1095 auio.uio_iovcnt = 1; 1096 auio.uio_resid = fop->df_count; 1097 auio.uio_segflg = 0; 1098 auio.uio_offset = 1099 fop->df_startblk * wd->sc_dk.dk_label->d_secsize; 1100 auio.uio_procp = p; 1101 error = physio(wdformat, NULL, dev, B_WRITE, minphys, 1102 &auio); 1103 fop->df_count -= auio.uio_resid; 1104 fop->df_reg[0] = wdc->sc_status; 1105 fop->df_reg[1] = wdc->sc_error; 1106 return error; 1107 } 1108 #endif 1109 1110 case ATAIOCCOMMAND: 1111 /* 1112 * Make sure this command is (relatively) safe first 1113 */ 1114 if ((((atareq_t *) addr)->flags & ATACMD_READ) == 0 && 1115 (flag & FWRITE) == 0) 1116 return (EBADF); 1117 { 1118 struct wd_ioctl *wi; 1119 atareq_t *atareq = (atareq_t *) addr; 1120 int error; 1121 1122 wi = wi_get(); 1123 wi->wi_softc = wd; 1124 wi->wi_atareq = *atareq; 1125 1126 if (atareq->datalen && atareq->flags & 1127 (ATACMD_READ | ATACMD_WRITE)) { 1128 wi->wi_iov.iov_base = atareq->databuf; 1129 wi->wi_iov.iov_len = atareq->datalen; 1130 wi->wi_uio.uio_iov = &wi->wi_iov; 1131 wi->wi_uio.uio_iovcnt = 1; 1132 wi->wi_uio.uio_resid = atareq->datalen; 1133 wi->wi_uio.uio_offset = 0; 1134 wi->wi_uio.uio_segflg = UIO_USERSPACE; 1135 wi->wi_uio.uio_rw = 1136 (atareq->flags & ATACMD_READ) ? B_READ : B_WRITE; 1137 wi->wi_uio.uio_procp = p; 1138 error = physio(wdioctlstrategy, &wi->wi_bp, dev, 1139 (atareq->flags & ATACMD_READ) ? B_READ : B_WRITE, 1140 minphys, &wi->wi_uio); 1141 } else { 1142 /* No need to call physio if we don't have any 1143 user data */ 1144 wi->wi_bp.b_flags = 0; 1145 wi->wi_bp.b_data = 0; 1146 wi->wi_bp.b_bcount = 0; 1147 wi->wi_bp.b_dev = 0; 1148 wi->wi_bp.b_proc = p; 1149 wdioctlstrategy(&wi->wi_bp); 1150 error = wi->wi_bp.b_error; 1151 } 1152 *atareq = wi->wi_atareq; 1153 wi_free(wi); 1154 return(error); 1155 } 1156 1157 default: 1158 return ENOTTY; 1159 } 1160 1161 #ifdef DIAGNOSTIC 1162 panic("wdioctl: impossible"); 1163 #endif 1164 } 1165 1166 #ifdef B_FORMAT 1167 int 1168 wdformat(struct buf *bp) 1169 { 1170 1171 bp->b_flags |= B_FORMAT; 1172 return wdstrategy(bp); 1173 } 1174 #endif 1175 1176 int 1177 wdsize(dev) 1178 dev_t dev; 1179 { 1180 struct wd_softc *wd; 1181 int part, omask; 1182 int size; 1183 1184 WDCDEBUG_PRINT(("wdsize\n"), DEBUG_FUNCS); 1185 1186 wd = device_lookup(&wd_cd, WDUNIT(dev)); 1187 if (wd == NULL) 1188 return (-1); 1189 1190 part = WDPART(dev); 1191 omask = wd->sc_dk.dk_openmask & (1 << part); 1192 1193 if (omask == 0 && wdopen(dev, 0, S_IFBLK, NULL) != 0) 1194 return (-1); 1195 if (wd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP) 1196 size = -1; 1197 else 1198 size = wd->sc_dk.dk_label->d_partitions[part].p_size * 1199 (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE); 1200 if (omask == 0 && wdclose(dev, 0, S_IFBLK, NULL) != 0) 1201 return (-1); 1202 return (size); 1203 } 1204 1205 /* #define WD_DUMP_NOT_TRUSTED if you just want to watch */ 1206 static int wddoingadump = 0; 1207 static int wddumprecalibrated = 0; 1208 static int wddumpmulti = 1; 1209 1210 /* 1211 * Dump core after a system crash. 1212 */ 1213 int 1214 wddump(dev, blkno, va, size) 1215 dev_t dev; 1216 daddr_t blkno; 1217 caddr_t va; 1218 size_t size; 1219 { 1220 struct wd_softc *wd; /* disk unit to do the I/O */ 1221 struct disklabel *lp; /* disk's disklabel */ 1222 int part, err; 1223 int nblks; /* total number of sectors left to write */ 1224 char errbuf[256]; 1225 1226 /* Check if recursive dump; if so, punt. */ 1227 if (wddoingadump) 1228 return EFAULT; 1229 wddoingadump = 1; 1230 1231 wd = device_lookup(&wd_cd, WDUNIT(dev)); 1232 if (wd == NULL) 1233 return (ENXIO); 1234 1235 part = WDPART(dev); 1236 1237 /* Make sure it was initialized. */ 1238 if (wd->drvp->state < READY) 1239 return ENXIO; 1240 1241 /* Convert to disk sectors. Request must be a multiple of size. */ 1242 lp = wd->sc_dk.dk_label; 1243 if ((size % lp->d_secsize) != 0) 1244 return EFAULT; 1245 nblks = size / lp->d_secsize; 1246 blkno = blkno / (lp->d_secsize / DEV_BSIZE); 1247 1248 /* Check transfer bounds against partition size. */ 1249 if ((blkno < 0) || ((blkno + nblks) > lp->d_partitions[part].p_size)) 1250 return EINVAL; 1251 1252 /* Offset block number to start of partition. */ 1253 blkno += lp->d_partitions[part].p_offset; 1254 1255 /* Recalibrate, if first dump transfer. */ 1256 if (wddumprecalibrated == 0) { 1257 wddumpmulti = wd->sc_multi; 1258 wddumprecalibrated = 1; 1259 wd->drvp->state = RESET; 1260 } 1261 1262 while (nblks > 0) { 1263 again: 1264 wd->sc_bp = NULL; 1265 wd->sc_wdc_bio.blkno = blkno; 1266 wd->sc_wdc_bio.flags = ATA_POLL; 1267 if (wddumpmulti == 1) 1268 wd->sc_wdc_bio.flags |= ATA_SINGLE; 1269 if (wd->sc_flags & WDF_LBA) 1270 wd->sc_wdc_bio.flags |= ATA_LBA; 1271 wd->sc_wdc_bio.bcount = 1272 min(nblks, wddumpmulti) * lp->d_secsize; 1273 wd->sc_wdc_bio.databuf = va; 1274 #ifndef WD_DUMP_NOT_TRUSTED 1275 switch (wd->atabus->ata_bio(wd->drvp, &wd->sc_wdc_bio)) { 1276 case WDC_TRY_AGAIN: 1277 panic("wddump: try again"); 1278 break; 1279 case WDC_QUEUED: 1280 panic("wddump: polled command has been queued"); 1281 break; 1282 case WDC_COMPLETE: 1283 break; 1284 } 1285 switch(wd->sc_wdc_bio.error) { 1286 case TIMEOUT: 1287 printf("wddump: device timed out"); 1288 err = EIO; 1289 break; 1290 case ERR_DF: 1291 printf("wddump: drive fault"); 1292 err = EIO; 1293 break; 1294 case ERR_DMA: 1295 printf("wddump: DMA error"); 1296 err = EIO; 1297 break; 1298 case ERROR: 1299 errbuf[0] = '\0'; 1300 wdperror(wd->drvp, wd->sc_wdc_bio.r_error, errbuf); 1301 printf("wddump: %s", errbuf); 1302 err = EIO; 1303 break; 1304 case NOERROR: 1305 err = 0; 1306 break; 1307 default: 1308 panic("wddump: unknown error type"); 1309 } 1310 if (err != 0) { 1311 if (wddumpmulti != 1) { 1312 wddumpmulti = 1; /* retry in single-sector */ 1313 printf(", retrying\n"); 1314 goto again; 1315 } 1316 printf("\n"); 1317 return err; 1318 } 1319 #else /* WD_DUMP_NOT_TRUSTED */ 1320 /* Let's just talk about this first... */ 1321 printf("wd%d: dump addr 0x%x, cylin %d, head %d, sector %d\n", 1322 unit, va, cylin, head, sector); 1323 delay(500 * 1000); /* half a second */ 1324 #endif 1325 1326 /* update block count */ 1327 nblks -= min(nblks, wddumpmulti); 1328 blkno += min(nblks, wddumpmulti); 1329 va += min(nblks, wddumpmulti) * lp->d_secsize; 1330 } 1331 1332 wddoingadump = 0; 1333 return 0; 1334 } 1335 1336 #ifdef HAS_BAD144_HANDLING 1337 /* 1338 * Internalize the bad sector table. 1339 */ 1340 void 1341 bad144intern(wd) 1342 struct wd_softc *wd; 1343 { 1344 struct dkbad *bt = &wd->sc_dk.dk_cpulabel->bad; 1345 struct disklabel *lp = wd->sc_dk.dk_label; 1346 int i = 0; 1347 1348 WDCDEBUG_PRINT(("bad144intern\n"), DEBUG_XFERS); 1349 1350 for (; i < NBT_BAD; i++) { 1351 if (bt->bt_bad[i].bt_cyl == 0xffff) 1352 break; 1353 wd->sc_badsect[i] = 1354 bt->bt_bad[i].bt_cyl * lp->d_secpercyl + 1355 (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors + 1356 (bt->bt_bad[i].bt_trksec & 0xff); 1357 } 1358 for (; i < NBT_BAD+1; i++) 1359 wd->sc_badsect[i] = -1; 1360 } 1361 #endif 1362 1363 int 1364 wd_get_params(wd, flags, params) 1365 struct wd_softc *wd; 1366 u_int8_t flags; 1367 struct ataparams *params; 1368 { 1369 switch (wd->atabus->ata_get_params(wd->drvp, flags, params)) { 1370 case CMD_AGAIN: 1371 return 1; 1372 case CMD_ERR: 1373 /* 1374 * We `know' there's a drive here; just assume it's old. 1375 * This geometry is only used to read the MBR and print a 1376 * (false) attach message. 1377 */ 1378 strncpy(params->atap_model, "ST506", 1379 sizeof params->atap_model); 1380 params->atap_config = ATA_CFG_FIXED; 1381 params->atap_cylinders = 1024; 1382 params->atap_heads = 8; 1383 params->atap_sectors = 17; 1384 params->atap_multi = 1; 1385 params->atap_capabilities1 = params->atap_capabilities2 = 0; 1386 wd->drvp->ata_vers = -1; /* Mark it as pre-ATA */ 1387 return 0; 1388 case CMD_OK: 1389 return 0; 1390 default: 1391 panic("wd_get_params: bad return code from ata_get_params"); 1392 /* NOTREACHED */ 1393 } 1394 } 1395 1396 void 1397 wd_flushcache(wd, flags) 1398 struct wd_softc *wd; 1399 int flags; 1400 { 1401 struct wdc_command wdc_c; 1402 1403 if (wd->drvp->ata_vers < 4) /* WDCC_FLUSHCACHE is here since ATA-4 */ 1404 return; 1405 memset(&wdc_c, 0, sizeof(struct wdc_command)); 1406 wdc_c.r_command = WDCC_FLUSHCACHE; 1407 wdc_c.r_st_bmask = WDCS_DRDY; 1408 wdc_c.r_st_pmask = WDCS_DRDY; 1409 wdc_c.flags = flags; 1410 wdc_c.timeout = 30000; /* 30s timeout */ 1411 if (wd->atabus->ata_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) { 1412 printf("%s: flush cache command didn't complete\n", 1413 wd->sc_dev.dv_xname); 1414 } 1415 if (wdc_c.flags & AT_TIMEOU) { 1416 printf("%s: flush cache command timeout\n", 1417 wd->sc_dev.dv_xname); 1418 } 1419 if (wdc_c.flags & AT_DF) { 1420 printf("%s: flush cache command: drive fault\n", 1421 wd->sc_dev.dv_xname); 1422 } 1423 /* 1424 * Ignore error register, it shouldn't report anything else 1425 * than COMMAND ABORTED, which means the device doesn't support 1426 * flush cache 1427 */ 1428 } 1429 1430 void 1431 wd_shutdown(arg) 1432 void *arg; 1433 { 1434 struct wd_softc *wd = arg; 1435 wd_flushcache(wd, AT_POLL); 1436 } 1437 1438 /* 1439 * Allocate space for a ioctl queue structure. Mostly taken from 1440 * scsipi_ioctl.c 1441 */ 1442 struct wd_ioctl * 1443 wi_get() 1444 { 1445 struct wd_ioctl *wi; 1446 int s; 1447 1448 wi = malloc(sizeof(struct wd_ioctl), M_TEMP, M_WAITOK); 1449 memset(wi, 0, sizeof (struct wd_ioctl)); 1450 s = splbio(); 1451 LIST_INSERT_HEAD(&wi_head, wi, wi_list); 1452 splx(s); 1453 return (wi); 1454 } 1455 1456 /* 1457 * Free an ioctl structure and remove it from our list 1458 */ 1459 1460 void 1461 wi_free(wi) 1462 struct wd_ioctl *wi; 1463 { 1464 int s; 1465 1466 s = splbio(); 1467 LIST_REMOVE(wi, wi_list); 1468 splx(s); 1469 free(wi, M_TEMP); 1470 } 1471 1472 /* 1473 * Find a wd_ioctl structure based on the struct buf. 1474 */ 1475 1476 struct wd_ioctl * 1477 wi_find(bp) 1478 struct buf *bp; 1479 { 1480 struct wd_ioctl *wi; 1481 int s; 1482 1483 s = splbio(); 1484 for (wi = wi_head.lh_first; wi != 0; wi = wi->wi_list.le_next) 1485 if (bp == &wi->wi_bp) 1486 break; 1487 splx(s); 1488 return (wi); 1489 } 1490 1491 /* 1492 * Ioctl pseudo strategy routine 1493 * 1494 * This is mostly stolen from scsipi_ioctl.c:scsistrategy(). What 1495 * happens here is: 1496 * 1497 * - wdioctl() queues a wd_ioctl structure. 1498 * 1499 * - wdioctl() calls physio/wdioctlstrategy based on whether or not 1500 * user space I/O is required. If physio() is called, physio() eventually 1501 * calls wdioctlstrategy(). 1502 * 1503 * - In either case, wdioctlstrategy() calls wd->atabus->ata_exec_command() 1504 * to perform the actual command 1505 * 1506 * The reason for the use of the pseudo strategy routine is because 1507 * when doing I/O to/from user space, physio _really_ wants to be in 1508 * the loop. We could put the entire buffer into the ioctl request 1509 * structure, but that won't scale if we want to do things like download 1510 * microcode. 1511 */ 1512 1513 void 1514 wdioctlstrategy(bp) 1515 struct buf *bp; 1516 { 1517 struct wd_ioctl *wi; 1518 struct wdc_command wdc_c; 1519 int error = 0; 1520 1521 wi = wi_find(bp); 1522 if (wi == NULL) { 1523 printf("user_strat: No ioctl\n"); 1524 error = EINVAL; 1525 goto bad; 1526 } 1527 1528 memset(&wdc_c, 0, sizeof(wdc_c)); 1529 1530 /* 1531 * Abort if physio broke up the transfer 1532 */ 1533 1534 if (bp->b_bcount != wi->wi_atareq.datalen) { 1535 printf("physio split wd ioctl request... cannot proceed\n"); 1536 error = EIO; 1537 goto bad; 1538 } 1539 1540 /* 1541 * Abort if we didn't get a buffer size that was a multiple of 1542 * our sector size (or was larger than NBBY) 1543 */ 1544 1545 if ((bp->b_bcount % wi->wi_softc->sc_dk.dk_label->d_secsize) != 0 || 1546 (bp->b_bcount / wi->wi_softc->sc_dk.dk_label->d_secsize) >= 1547 (1 << NBBY)) { 1548 error = EINVAL; 1549 goto bad; 1550 } 1551 1552 /* 1553 * Make sure a timeout was supplied in the ioctl request 1554 */ 1555 1556 if (wi->wi_atareq.timeout == 0) { 1557 error = EINVAL; 1558 goto bad; 1559 } 1560 1561 if (wi->wi_atareq.flags & ATACMD_READ) 1562 wdc_c.flags |= AT_READ; 1563 else if (wi->wi_atareq.flags & ATACMD_WRITE) 1564 wdc_c.flags |= AT_WRITE; 1565 1566 if (wi->wi_atareq.flags & ATACMD_READREG) 1567 wdc_c.flags |= AT_READREG; 1568 1569 wdc_c.flags |= AT_WAIT; 1570 1571 wdc_c.timeout = wi->wi_atareq.timeout; 1572 wdc_c.r_command = wi->wi_atareq.command; 1573 wdc_c.r_head = wi->wi_atareq.head & 0x0f; 1574 wdc_c.r_cyl = wi->wi_atareq.cylinder; 1575 wdc_c.r_sector = wi->wi_atareq.sec_num; 1576 wdc_c.r_count = wi->wi_atareq.sec_count; 1577 wdc_c.r_precomp = wi->wi_atareq.features; 1578 wdc_c.r_st_bmask = WDCS_DRDY; 1579 wdc_c.r_st_pmask = WDCS_DRDY; 1580 wdc_c.data = wi->wi_bp.b_data; 1581 wdc_c.bcount = wi->wi_bp.b_bcount; 1582 1583 if (wi->wi_softc->atabus->ata_exec_command(wi->wi_softc->drvp, &wdc_c) 1584 != WDC_COMPLETE) { 1585 wi->wi_atareq.retsts = ATACMD_ERROR; 1586 goto bad; 1587 } 1588 1589 if (wdc_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { 1590 if (wdc_c.flags & AT_ERROR) { 1591 wi->wi_atareq.retsts = ATACMD_ERROR; 1592 wi->wi_atareq.error = wdc_c.r_error; 1593 } else if (wdc_c.flags & AT_DF) 1594 wi->wi_atareq.retsts = ATACMD_DF; 1595 else 1596 wi->wi_atareq.retsts = ATACMD_TIMEOUT; 1597 } else { 1598 wi->wi_atareq.retsts = ATACMD_OK; 1599 if (wi->wi_atareq.flags & ATACMD_READREG) { 1600 wi->wi_atareq.head = wdc_c.r_head ; 1601 wi->wi_atareq.cylinder = wdc_c.r_cyl; 1602 wi->wi_atareq.sec_num = wdc_c.r_sector; 1603 wi->wi_atareq.sec_count = wdc_c.r_count; 1604 wi->wi_atareq.features = wdc_c.r_precomp; 1605 wi->wi_atareq.error = wdc_c.r_error; 1606 } 1607 } 1608 1609 bp->b_error = 0; 1610 biodone(bp); 1611 return; 1612 bad: 1613 bp->b_flags |= B_ERROR; 1614 bp->b_error = error; 1615 biodone(bp); 1616 } 1617