1 /* $OpenBSD: wd.c,v 1.108 2011/07/06 04:49:36 matthew Exp $ */ 2 /* $NetBSD: wd.c,v 1.193 1999/02/28 17:15:27 explorer Exp $ */ 3 4 /* 5 * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /*- 29 * Copyright (c) 1998 The NetBSD Foundation, Inc. 30 * All rights reserved. 31 * 32 * This code is derived from software contributed to The NetBSD Foundation 33 * by Charles M. Hannum and by Onno van der Linden. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 44 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 45 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 46 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 47 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 48 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 49 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 50 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 51 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 52 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 53 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 54 * POSSIBILITY OF SUCH DAMAGE. 55 */ 56 57 #if 0 58 #include "rnd.h" 59 #endif 60 61 #include <sys/param.h> 62 #include <sys/systm.h> 63 #include <sys/kernel.h> 64 #include <sys/conf.h> 65 #include <sys/file.h> 66 #include <sys/stat.h> 67 #include <sys/ioctl.h> 68 #include <sys/mutex.h> 69 #include <sys/buf.h> 70 #include <sys/uio.h> 71 #include <sys/malloc.h> 72 #include <sys/device.h> 73 #include <sys/disklabel.h> 74 #include <sys/disk.h> 75 #include <sys/syslog.h> 76 #include <sys/proc.h> 77 #include <sys/vnode.h> 78 #include <sys/dkio.h> 79 #include <sys/reboot.h> 80 81 #include <uvm/uvm_extern.h> 82 83 #include <machine/intr.h> 84 #include <machine/bus.h> 85 86 #include <dev/ata/atareg.h> 87 #include <dev/ata/atavar.h> 88 #include <dev/ata/wdvar.h> 89 #include <dev/ic/wdcreg.h> 90 #include <dev/ic/wdcvar.h> 91 #if 0 92 #include "locators.h" 93 #endif 94 95 #define LBA48_THRESHOLD (0xfffffff) /* 128GB / DEV_BSIZE */ 96 97 #define WDIORETRIES_SINGLE 4 /* number of retries before single-sector */ 98 #define WDIORETRIES 5 /* number of retries before giving up */ 99 #define RECOVERYTIME hz/2 /* time to wait before retrying a cmd */ 100 101 #define DEBUG_INTR 0x01 102 #define DEBUG_XFERS 0x02 103 #define DEBUG_STATUS 0x04 104 #define DEBUG_FUNCS 0x08 105 #define DEBUG_PROBE 0x10 106 #ifdef WDCDEBUG 107 extern int wdcdebug_wd_mask; /* init'ed in ata_wdc.c */ 108 #define WDCDEBUG_PRINT(args, level) do { \ 109 if ((wdcdebug_wd_mask & (level)) != 0) \ 110 printf args; \ 111 } while (0) 112 #else 113 #define WDCDEBUG_PRINT(args, level) 114 #endif 115 116 117 #define sc_drive sc_wdc_bio.drive 118 #define sc_mode sc_wdc_bio.mode 119 #define sc_multi sc_wdc_bio.multi 120 121 int wdprobe(struct device *, void *, void *); 122 void wdattach(struct device *, struct device *, void *); 123 int wddetach(struct device *, int); 124 int wdactivate(struct device *, int); 125 int wdprint(void *, char *); 126 127 struct cfattach wd_ca = { 128 sizeof(struct wd_softc), wdprobe, wdattach, 129 wddetach, wdactivate 130 }; 131 132 struct cfdriver wd_cd = { 133 NULL, "wd", DV_DISK 134 }; 135 136 void wdgetdefaultlabel(struct wd_softc *, struct disklabel *); 137 int wdgetdisklabel(dev_t dev, struct wd_softc *, struct disklabel *, int); 138 void wdstrategy(struct buf *); 139 void wdstart(void *); 140 void __wdstart(struct wd_softc*, struct buf *); 141 void wdrestart(void *); 142 int wd_get_params(struct wd_softc *, u_int8_t, struct ataparams *); 143 void wd_flushcache(struct wd_softc *, int); 144 void wd_standby(struct wd_softc *, int); 145 void wd_shutdown(void *); 146 147 /* XXX: these should go elsewhere */ 148 cdev_decl(wd); 149 bdev_decl(wd); 150 151 #define wdlookup(unit) (struct wd_softc *)disk_lookup(&wd_cd, (unit)) 152 153 154 int 155 wdprobe(struct device *parent, void *match_, void *aux) 156 { 157 struct ata_atapi_attach *aa_link = aux; 158 struct cfdata *match = match_; 159 160 if (aa_link == NULL) 161 return 0; 162 if (aa_link->aa_type != T_ATA) 163 return 0; 164 165 if (match->cf_loc[0] != -1 && 166 match->cf_loc[0] != aa_link->aa_channel) 167 return 0; 168 169 if (match->cf_loc[1] != -1 && 170 match->cf_loc[1] != aa_link->aa_drv_data->drive) 171 return 0; 172 173 return 1; 174 } 175 176 void 177 wdattach(struct device *parent, struct device *self, void *aux) 178 { 179 struct wd_softc *wd = (void *)self; 180 struct ata_atapi_attach *aa_link= aux; 181 struct wdc_command wdc_c; 182 int i, blank; 183 char buf[41], c, *p, *q; 184 WDCDEBUG_PRINT(("wdattach\n"), DEBUG_FUNCS | DEBUG_PROBE); 185 186 wd->openings = aa_link->aa_openings; 187 wd->drvp = aa_link->aa_drv_data; 188 189 strlcpy(wd->drvp->drive_name, wd->sc_dev.dv_xname, 190 sizeof(wd->drvp->drive_name)); 191 wd->drvp->cf_flags = wd->sc_dev.dv_cfdata->cf_flags; 192 193 if ((NERRS_MAX - 2) > 0) 194 wd->drvp->n_dmaerrs = NERRS_MAX - 2; 195 else 196 wd->drvp->n_dmaerrs = 0; 197 198 /* read our drive info */ 199 if (wd_get_params(wd, at_poll, &wd->sc_params) != 0) { 200 printf("%s: IDENTIFY failed\n", wd->sc_dev.dv_xname); 201 return; 202 } 203 204 for (blank = 0, p = wd->sc_params.atap_model, q = buf, i = 0; 205 i < sizeof(wd->sc_params.atap_model); i++) { 206 c = *p++; 207 if (c == '\0') 208 break; 209 if (c != ' ') { 210 if (blank) { 211 *q++ = ' '; 212 blank = 0; 213 } 214 *q++ = c; 215 } else 216 blank = 1; 217 } 218 *q++ = '\0'; 219 220 printf(": <%s>\n", buf); 221 222 wdc_probe_caps(wd->drvp, &wd->sc_params); 223 wdc_print_caps(wd->drvp); 224 225 if ((wd->sc_params.atap_multi & 0xff) > 1) { 226 wd->sc_multi = wd->sc_params.atap_multi & 0xff; 227 } else { 228 wd->sc_multi = 1; 229 } 230 231 printf("%s: %d-sector PIO,", wd->sc_dev.dv_xname, wd->sc_multi); 232 233 /* use 48-bit LBA if enabled */ 234 /* XXX: shall we use it if drive capacity < 137Gb? */ 235 if ((wd->sc_params.atap_cmd2_en & ATAPI_CMD2_48AD) != 0) 236 wd->sc_flags |= WDF_LBA48; 237 238 /* Prior to ATA-4, LBA was optional. */ 239 if ((wd->sc_params.atap_capabilities1 & WDC_CAP_LBA) != 0) 240 wd->sc_flags |= WDF_LBA; 241 #if 0 242 /* ATA-4 requires LBA. */ 243 if (wd->sc_params.atap_ataversion != 0xffff && 244 wd->sc_params.atap_ataversion >= WDC_VER_ATA4) 245 wd->sc_flags |= WDF_LBA; 246 #endif 247 248 if ((wd->sc_flags & WDF_LBA48) != 0) { 249 wd->sc_capacity = 250 (((u_int64_t)wd->sc_params.atap_max_lba[3] << 48) | 251 ((u_int64_t)wd->sc_params.atap_max_lba[2] << 32) | 252 ((u_int64_t)wd->sc_params.atap_max_lba[1] << 16) | 253 (u_int64_t)wd->sc_params.atap_max_lba[0]); 254 printf(" LBA48, %lluMB, %llu sectors\n", 255 wd->sc_capacity / (1048576 / DEV_BSIZE), 256 wd->sc_capacity); 257 } else if ((wd->sc_flags & WDF_LBA) != 0) { 258 wd->sc_capacity = 259 (wd->sc_params.atap_capacity[1] << 16) | 260 wd->sc_params.atap_capacity[0]; 261 printf(" LBA, %lluMB, %llu sectors\n", 262 wd->sc_capacity / (1048576 / DEV_BSIZE), 263 wd->sc_capacity); 264 } else { 265 wd->sc_capacity = 266 wd->sc_params.atap_cylinders * 267 wd->sc_params.atap_heads * 268 wd->sc_params.atap_sectors; 269 printf(" CHS, %lluMB, %d cyl, %d head, %d sec, %llu sectors\n", 270 wd->sc_capacity / (1048576 / DEV_BSIZE), 271 wd->sc_params.atap_cylinders, 272 wd->sc_params.atap_heads, 273 wd->sc_params.atap_sectors, 274 wd->sc_capacity); 275 } 276 WDCDEBUG_PRINT(("%s: atap_dmatiming_mimi=%d, atap_dmatiming_recom=%d\n", 277 self->dv_xname, wd->sc_params.atap_dmatiming_mimi, 278 wd->sc_params.atap_dmatiming_recom), DEBUG_PROBE); 279 280 /* use read look ahead if supported */ 281 if (wd->sc_params.atap_cmd_set1 & WDC_CMD1_AHEAD) { 282 bzero(&wdc_c, sizeof(struct wdc_command)); 283 wdc_c.r_command = SET_FEATURES; 284 wdc_c.r_precomp = WDSF_READAHEAD_EN; 285 wdc_c.timeout = 1000; 286 wdc_c.flags = at_poll; 287 288 if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) { 289 printf("%s: enable look ahead command didn't " 290 "complete\n", wd->sc_dev.dv_xname); 291 } 292 } 293 294 /* use write cache if supported */ 295 if (wd->sc_params.atap_cmd_set1 & WDC_CMD1_CACHE) { 296 bzero(&wdc_c, sizeof(struct wdc_command)); 297 wdc_c.r_command = SET_FEATURES; 298 wdc_c.r_precomp = WDSF_EN_WR_CACHE; 299 wdc_c.timeout = 1000; 300 wdc_c.flags = at_poll; 301 302 if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) { 303 printf("%s: enable write cache command didn't " 304 "complete\n", wd->sc_dev.dv_xname); 305 } 306 } 307 308 /* 309 * FREEZE LOCK the drive so malicous users can't lock it on us. 310 * As there is no harm in issuing this to drives that don't 311 * support the security feature set we just send it, and don't 312 * bother checking if the drive sends a command abort to tell us it 313 * doesn't support it. 314 */ 315 bzero(&wdc_c, sizeof(struct wdc_command)); 316 317 wdc_c.r_command = WDCC_SEC_FREEZE_LOCK; 318 wdc_c.timeout = 1000; 319 wdc_c.flags = at_poll; 320 if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) { 321 printf("%s: freeze lock command didn't complete\n", 322 wd->sc_dev.dv_xname); 323 } 324 325 /* 326 * Initialize disk structures. 327 */ 328 wd->sc_dk.dk_name = wd->sc_dev.dv_xname; 329 bufq_init(&wd->sc_bufq, BUFQ_DEFAULT); 330 wd->sc_sdhook = shutdownhook_establish(wd_shutdown, wd); 331 if (wd->sc_sdhook == NULL) 332 printf("%s: WARNING: unable to establish shutdown hook\n", 333 wd->sc_dev.dv_xname); 334 timeout_set(&wd->sc_restart_timeout, wdrestart, wd); 335 336 /* Attach disk. */ 337 disk_attach(&wd->sc_dev, &wd->sc_dk); 338 wd->sc_wdc_bio.lp = wd->sc_dk.dk_label; 339 } 340 341 int 342 wdactivate(struct device *self, int act) 343 { 344 struct wd_softc *wd = (void *)self; 345 int rv = 0; 346 347 switch (act) { 348 case DVACT_SUSPEND: 349 wd_flushcache(wd, AT_POLL); 350 wd_standby(wd, AT_POLL); 351 break; 352 case DVACT_RESUME: 353 /* 354 * Do two resets separated by a small delay. The 355 * first wakes the controller, the second resets 356 * the channel. 357 */ 358 wdc_disable_intr(wd->drvp->chnl_softc); 359 wdc_reset_channel(wd->drvp, 1); 360 delay(10000); 361 wdc_reset_channel(wd->drvp, 0); 362 wdc_enable_intr(wd->drvp->chnl_softc); 363 wd_get_params(wd, at_poll, &wd->sc_params); 364 break; 365 } 366 return (rv); 367 } 368 369 int 370 wddetach(struct device *self, int flags) 371 { 372 struct wd_softc *sc = (struct wd_softc *)self; 373 374 timeout_del(&sc->sc_restart_timeout); 375 376 bufq_drain(&sc->sc_bufq); 377 378 disk_gone(wdopen, self->dv_unit); 379 380 /* Get rid of the shutdown hook. */ 381 if (sc->sc_sdhook != NULL) 382 shutdownhook_disestablish(sc->sc_sdhook); 383 384 /* Detach disk. */ 385 bufq_destroy(&sc->sc_bufq); 386 disk_detach(&sc->sc_dk); 387 388 return (0); 389 } 390 391 /* 392 * Read/write routine for a buffer. Validates the arguments and schedules the 393 * transfer. Does not wait for the transfer to complete. 394 */ 395 void 396 wdstrategy(struct buf *bp) 397 { 398 struct wd_softc *wd; 399 int s; 400 401 wd = wdlookup(DISKUNIT(bp->b_dev)); 402 if (wd == NULL) { 403 bp->b_error = ENXIO; 404 goto bad; 405 } 406 407 WDCDEBUG_PRINT(("wdstrategy (%s)\n", wd->sc_dev.dv_xname), 408 DEBUG_XFERS); 409 410 /* If device invalidated (e.g. media change, door open), error. */ 411 if ((wd->sc_flags & WDF_LOADED) == 0) { 412 bp->b_error = EIO; 413 goto bad; 414 } 415 416 /* Validate the request. */ 417 if (bounds_check_with_label(bp, wd->sc_dk.dk_label) == -1) 418 goto done; 419 420 /* Check that the number of sectors can fit in a byte. */ 421 if ((bp->b_bcount / wd->sc_dk.dk_label->d_secsize) >= (1 << NBBY)) { 422 bp->b_error = EINVAL; 423 goto bad; 424 } 425 426 /* Queue transfer on drive, activate drive and controller if idle. */ 427 bufq_queue(&wd->sc_bufq, bp); 428 s = splbio(); 429 wdstart(wd); 430 splx(s); 431 device_unref(&wd->sc_dev); 432 return; 433 434 bad: 435 bp->b_flags |= B_ERROR; 436 bp->b_resid = bp->b_bcount; 437 done: 438 s = splbio(); 439 biodone(bp); 440 splx(s); 441 if (wd != NULL) 442 device_unref(&wd->sc_dev); 443 } 444 445 /* 446 * Queue a drive for I/O. 447 */ 448 void 449 wdstart(void *arg) 450 { 451 struct wd_softc *wd = arg; 452 struct buf *bp = NULL; 453 454 WDCDEBUG_PRINT(("wdstart %s\n", wd->sc_dev.dv_xname), 455 DEBUG_XFERS); 456 while (wd->openings > 0) { 457 458 /* Is there a buf for us ? */ 459 if ((bp = bufq_dequeue(&wd->sc_bufq)) == NULL) 460 return; 461 /* 462 * Make the command. First lock the device 463 */ 464 wd->openings--; 465 466 wd->retries = 0; 467 __wdstart(wd, bp); 468 } 469 } 470 471 void 472 __wdstart(struct wd_softc *wd, struct buf *bp) 473 { 474 daddr64_t nblks; 475 476 wd->sc_wdc_bio.blkno = bp->b_blkno + 477 DL_GETPOFFSET(&wd->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)]); 478 wd->sc_wdc_bio.blkno /= (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE); 479 wd->sc_wdc_bio.blkdone =0; 480 wd->sc_bp = bp; 481 /* 482 * If we're retrying, retry in single-sector mode. This will give us 483 * the sector number of the problem, and will eventually allow the 484 * transfer to succeed. 485 */ 486 if (wd->retries >= WDIORETRIES_SINGLE) 487 wd->sc_wdc_bio.flags = ATA_SINGLE; 488 else 489 wd->sc_wdc_bio.flags = 0; 490 nblks = bp->b_bcount / wd->sc_dk.dk_label->d_secsize; 491 if ((wd->sc_flags & WDF_LBA48) && 492 /* use LBA48 only if really need */ 493 ((wd->sc_wdc_bio.blkno + nblks - 1 >= LBA48_THRESHOLD) || 494 (nblks > 0xff))) 495 wd->sc_wdc_bio.flags |= ATA_LBA48; 496 if (wd->sc_flags & WDF_LBA) 497 wd->sc_wdc_bio.flags |= ATA_LBA; 498 if (bp->b_flags & B_READ) 499 wd->sc_wdc_bio.flags |= ATA_READ; 500 wd->sc_wdc_bio.bcount = bp->b_bcount; 501 wd->sc_wdc_bio.databuf = bp->b_data; 502 wd->sc_wdc_bio.wd = wd; 503 /* Instrumentation. */ 504 disk_busy(&wd->sc_dk); 505 switch (wdc_ata_bio(wd->drvp, &wd->sc_wdc_bio)) { 506 case WDC_TRY_AGAIN: 507 timeout_add_sec(&wd->sc_restart_timeout, 1); 508 break; 509 case WDC_QUEUED: 510 break; 511 case WDC_COMPLETE: 512 /* 513 * This code is never executed because we never set 514 * the ATA_POLL flag above 515 */ 516 #if 0 517 if (wd->sc_wdc_bio.flags & ATA_POLL) 518 wddone(wd); 519 #endif 520 break; 521 default: 522 panic("__wdstart: bad return code from wdc_ata_bio()"); 523 } 524 } 525 526 void 527 wddone(void *v) 528 { 529 struct wd_softc *wd = v; 530 struct buf *bp = wd->sc_bp; 531 char buf[256], *errbuf = buf; 532 WDCDEBUG_PRINT(("wddone %s\n", wd->sc_dev.dv_xname), 533 DEBUG_XFERS); 534 535 bp->b_resid = wd->sc_wdc_bio.bcount; 536 errbuf[0] = '\0'; 537 switch (wd->sc_wdc_bio.error) { 538 case ERR_NODEV: 539 bp->b_flags |= B_ERROR; 540 bp->b_error = ENXIO; 541 break; 542 case ERR_DMA: 543 errbuf = "DMA error"; 544 goto retry; 545 case ERR_DF: 546 errbuf = "device fault"; 547 goto retry; 548 case TIMEOUT: 549 errbuf = "device timeout"; 550 goto retry; 551 case ERROR: 552 /* Don't care about media change bits */ 553 if (wd->sc_wdc_bio.r_error != 0 && 554 (wd->sc_wdc_bio.r_error & ~(WDCE_MC | WDCE_MCR)) == 0) 555 goto noerror; 556 ata_perror(wd->drvp, wd->sc_wdc_bio.r_error, errbuf, 557 sizeof buf); 558 retry: 559 /* Just reset and retry. Can we do more ? */ 560 wdc_reset_channel(wd->drvp, 0); 561 diskerr(bp, "wd", errbuf, LOG_PRINTF, 562 wd->sc_wdc_bio.blkdone, wd->sc_dk.dk_label); 563 if (wd->retries++ < WDIORETRIES) { 564 printf(", retrying\n"); 565 timeout_add(&wd->sc_restart_timeout, RECOVERYTIME); 566 return; 567 } 568 printf("\n"); 569 bp->b_flags |= B_ERROR; 570 bp->b_error = EIO; 571 break; 572 case NOERROR: 573 noerror: if ((wd->sc_wdc_bio.flags & ATA_CORR) || wd->retries > 0) 574 printf("%s: soft error (corrected)\n", 575 wd->sc_dev.dv_xname); 576 } 577 disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid), 578 (bp->b_flags & B_READ)); 579 biodone(bp); 580 wd->openings++; 581 wdstart(wd); 582 } 583 584 void 585 wdrestart(void *v) 586 { 587 struct wd_softc *wd = v; 588 struct buf *bp = wd->sc_bp; 589 struct channel_softc *chnl; 590 int s; 591 WDCDEBUG_PRINT(("wdrestart %s\n", wd->sc_dev.dv_xname), 592 DEBUG_XFERS); 593 594 chnl = (struct channel_softc *)(wd->drvp->chnl_softc); 595 if (chnl->dying) 596 return; 597 598 s = splbio(); 599 disk_unbusy(&wd->sc_dk, 0, (bp->b_flags & B_READ)); 600 __wdstart(v, bp); 601 splx(s); 602 } 603 604 int 605 wdread(dev_t dev, struct uio *uio, int flags) 606 { 607 608 WDCDEBUG_PRINT(("wdread\n"), DEBUG_XFERS); 609 return (physio(wdstrategy, dev, B_READ, minphys, uio)); 610 } 611 612 int 613 wdwrite(dev_t dev, struct uio *uio, int flags) 614 { 615 616 WDCDEBUG_PRINT(("wdwrite\n"), DEBUG_XFERS); 617 return (physio(wdstrategy, dev, B_WRITE, minphys, uio)); 618 } 619 620 int 621 wdopen(dev_t dev, int flag, int fmt, struct proc *p) 622 { 623 struct wd_softc *wd; 624 struct channel_softc *chnl; 625 int unit, part; 626 int error; 627 628 WDCDEBUG_PRINT(("wdopen\n"), DEBUG_FUNCS); 629 630 unit = DISKUNIT(dev); 631 wd = wdlookup(unit); 632 if (wd == NULL) 633 return ENXIO; 634 chnl = (struct channel_softc *)(wd->drvp->chnl_softc); 635 if (chnl->dying) 636 return (ENXIO); 637 638 /* 639 * If this is the first open of this device, add a reference 640 * to the adapter. 641 */ 642 if ((error = disk_lock(&wd->sc_dk)) != 0) 643 goto bad4; 644 645 if (wd->sc_dk.dk_openmask != 0) { 646 /* 647 * If any partition is open, but the disk has been invalidated, 648 * disallow further opens. 649 */ 650 if ((wd->sc_flags & WDF_LOADED) == 0) { 651 error = EIO; 652 goto bad3; 653 } 654 } else { 655 if ((wd->sc_flags & WDF_LOADED) == 0) { 656 wd->sc_flags |= WDF_LOADED; 657 658 /* Load the physical device parameters. */ 659 wd_get_params(wd, AT_WAIT, &wd->sc_params); 660 661 /* Load the partition info if not already loaded. */ 662 if (wdgetdisklabel(dev, wd, 663 wd->sc_dk.dk_label, 0) == EIO) { 664 error = EIO; 665 goto bad; 666 } 667 } 668 } 669 670 part = DISKPART(dev); 671 672 if ((error = disk_openpart(&wd->sc_dk, part, fmt, 1)) != 0) 673 goto bad; 674 675 disk_unlock(&wd->sc_dk); 676 device_unref(&wd->sc_dev); 677 return 0; 678 679 bad: 680 if (wd->sc_dk.dk_openmask == 0) { 681 } 682 683 bad3: 684 disk_unlock(&wd->sc_dk); 685 bad4: 686 device_unref(&wd->sc_dev); 687 return error; 688 } 689 690 int 691 wdclose(dev_t dev, int flag, int fmt, struct proc *p) 692 { 693 struct wd_softc *wd; 694 int part = DISKPART(dev); 695 696 wd = wdlookup(DISKUNIT(dev)); 697 if (wd == NULL) 698 return ENXIO; 699 700 WDCDEBUG_PRINT(("wdclose\n"), DEBUG_FUNCS); 701 702 disk_lock_nointr(&wd->sc_dk); 703 704 disk_closepart(&wd->sc_dk, part, fmt); 705 706 if (wd->sc_dk.dk_openmask == 0) { 707 wd_flushcache(wd, 0); 708 /* XXXX Must wait for I/O to complete! */ 709 } 710 711 disk_unlock(&wd->sc_dk); 712 713 device_unref(&wd->sc_dev); 714 return (0); 715 } 716 717 void 718 wdgetdefaultlabel(struct wd_softc *wd, struct disklabel *lp) 719 { 720 WDCDEBUG_PRINT(("wdgetdefaultlabel\n"), DEBUG_FUNCS); 721 bzero(lp, sizeof(struct disklabel)); 722 723 lp->d_secsize = DEV_BSIZE; 724 DL_SETDSIZE(lp, wd->sc_capacity); 725 lp->d_ntracks = wd->sc_params.atap_heads; 726 lp->d_nsectors = wd->sc_params.atap_sectors; 727 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; 728 lp->d_ncylinders = DL_GETDSIZE(lp) / lp->d_secpercyl; 729 if (wd->drvp->ata_vers == -1) { 730 lp->d_type = DTYPE_ST506; 731 strncpy(lp->d_typename, "ST506/MFM/RLL", sizeof lp->d_typename); 732 } else { 733 lp->d_type = DTYPE_ESDI; 734 strncpy(lp->d_typename, "ESDI/IDE disk", sizeof lp->d_typename); 735 } 736 /* XXX - user viscopy() like sd.c */ 737 strncpy(lp->d_packname, wd->sc_params.atap_model, sizeof lp->d_packname); 738 lp->d_flags = 0; 739 lp->d_version = 1; 740 741 lp->d_magic = DISKMAGIC; 742 lp->d_magic2 = DISKMAGIC; 743 lp->d_checksum = dkcksum(lp); 744 } 745 746 /* 747 * Fabricate a default disk label, and try to read the correct one. 748 */ 749 int 750 wdgetdisklabel(dev_t dev, struct wd_softc *wd, struct disklabel *lp, 751 int spoofonly) 752 { 753 int error; 754 755 WDCDEBUG_PRINT(("wdgetdisklabel\n"), DEBUG_FUNCS); 756 757 wdgetdefaultlabel(wd, lp); 758 759 if (wd->drvp->state > RECAL) 760 wd->drvp->drive_flags |= DRIVE_RESET; 761 error = readdisklabel(DISKLABELDEV(dev), wdstrategy, lp, 762 spoofonly); 763 if (wd->drvp->state > RECAL) 764 wd->drvp->drive_flags |= DRIVE_RESET; 765 return (error); 766 } 767 768 int 769 wdioctl(dev_t dev, u_long xfer, caddr_t addr, int flag, struct proc *p) 770 { 771 struct wd_softc *wd; 772 struct disklabel *lp; 773 int error = 0; 774 775 WDCDEBUG_PRINT(("wdioctl\n"), DEBUG_FUNCS); 776 777 wd = wdlookup(DISKUNIT(dev)); 778 if (wd == NULL) 779 return ENXIO; 780 781 if ((wd->sc_flags & WDF_LOADED) == 0) { 782 error = EIO; 783 goto exit; 784 } 785 786 switch (xfer) { 787 case DIOCRLDINFO: 788 lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK); 789 wdgetdisklabel(dev, wd, lp, 0); 790 bcopy(lp, wd->sc_dk.dk_label, sizeof(*lp)); 791 free(lp, M_TEMP); 792 goto exit; 793 794 case DIOCGPDINFO: 795 wdgetdisklabel(dev, wd, (struct disklabel *)addr, 1); 796 goto exit; 797 798 case DIOCGDINFO: 799 *(struct disklabel *)addr = *(wd->sc_dk.dk_label); 800 goto exit; 801 802 case DIOCGPART: 803 ((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label; 804 ((struct partinfo *)addr)->part = 805 &wd->sc_dk.dk_label->d_partitions[DISKPART(dev)]; 806 goto exit; 807 808 case DIOCWDINFO: 809 case DIOCSDINFO: 810 if ((flag & FWRITE) == 0) { 811 error = EBADF; 812 goto exit; 813 } 814 815 if ((error = disk_lock(&wd->sc_dk)) != 0) 816 goto exit; 817 818 error = setdisklabel(wd->sc_dk.dk_label, 819 (struct disklabel *)addr, wd->sc_dk.dk_openmask); 820 if (error == 0) { 821 if (wd->drvp->state > RECAL) 822 wd->drvp->drive_flags |= DRIVE_RESET; 823 if (xfer == DIOCWDINFO) 824 error = writedisklabel(DISKLABELDEV(dev), 825 wdstrategy, wd->sc_dk.dk_label); 826 } 827 828 disk_unlock(&wd->sc_dk); 829 goto exit; 830 831 #ifdef notyet 832 case DIOCWFORMAT: 833 if ((flag & FWRITE) == 0) 834 return EBADF; 835 { 836 struct format_op *fop; 837 struct iovec aiov; 838 struct uio auio; 839 840 fop = (struct format_op *)addr; 841 aiov.iov_base = fop->df_buf; 842 aiov.iov_len = fop->df_count; 843 auio.uio_iov = &aiov; 844 auio.uio_iovcnt = 1; 845 auio.uio_resid = fop->df_count; 846 auio.uio_segflg = 0; 847 auio.uio_offset = 848 fop->df_startblk * wd->sc_dk.dk_label->d_secsize; 849 auio.uio_procp = p; 850 error = physio(wdformat, dev, B_WRITE, minphys, &auio); 851 fop->df_count -= auio.uio_resid; 852 fop->df_reg[0] = wdc->sc_status; 853 fop->df_reg[1] = wdc->sc_error; 854 goto exit; 855 } 856 #endif 857 858 default: 859 error = wdc_ioctl(wd->drvp, xfer, addr, flag, p); 860 goto exit; 861 } 862 863 #ifdef DIAGNOSTIC 864 panic("wdioctl: impossible"); 865 #endif 866 867 exit: 868 device_unref(&wd->sc_dev); 869 return (error); 870 } 871 872 #ifdef B_FORMAT 873 int 874 wdformat(struct buf *bp) 875 { 876 877 bp->b_flags |= B_FORMAT; 878 return wdstrategy(bp); 879 } 880 #endif 881 882 daddr64_t 883 wdsize(dev_t dev) 884 { 885 struct wd_softc *wd; 886 int part, omask; 887 int64_t size; 888 889 WDCDEBUG_PRINT(("wdsize\n"), DEBUG_FUNCS); 890 891 wd = wdlookup(DISKUNIT(dev)); 892 if (wd == NULL) 893 return (-1); 894 895 part = DISKPART(dev); 896 omask = wd->sc_dk.dk_openmask & (1 << part); 897 898 if (omask == 0 && wdopen(dev, 0, S_IFBLK, NULL) != 0) { 899 size = -1; 900 goto exit; 901 } 902 903 size = DL_GETPSIZE(&wd->sc_dk.dk_label->d_partitions[part]) * 904 (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE); 905 if (omask == 0 && wdclose(dev, 0, S_IFBLK, NULL) != 0) 906 size = -1; 907 908 exit: 909 device_unref(&wd->sc_dev); 910 return (size); 911 } 912 913 /* #define WD_DUMP_NOT_TRUSTED if you just want to watch */ 914 static int wddoingadump = 0; 915 static int wddumprecalibrated = 0; 916 static int wddumpmulti = 1; 917 918 /* 919 * Dump core after a system crash. 920 */ 921 int 922 wddump(dev_t dev, daddr64_t blkno, caddr_t va, size_t size) 923 { 924 struct wd_softc *wd; /* disk unit to do the I/O */ 925 struct disklabel *lp; /* disk's disklabel */ 926 int unit, part; 927 int nblks; /* total number of sectors left to write */ 928 int err; 929 char errbuf[256]; 930 931 /* Check if recursive dump; if so, punt. */ 932 if (wddoingadump) 933 return EFAULT; 934 wddoingadump = 1; 935 936 unit = DISKUNIT(dev); 937 wd = wdlookup(unit); 938 if (wd == NULL) 939 return ENXIO; 940 941 part = DISKPART(dev); 942 943 /* Make sure it was initialized. */ 944 if (wd->drvp->state < READY) 945 return ENXIO; 946 947 /* Convert to disk sectors. Request must be a multiple of size. */ 948 lp = wd->sc_dk.dk_label; 949 if ((size % lp->d_secsize) != 0) 950 return EFAULT; 951 nblks = size / lp->d_secsize; 952 blkno = blkno / (lp->d_secsize / DEV_BSIZE); 953 954 /* Check transfer bounds against partition size. */ 955 if ((blkno < 0) || ((blkno + nblks) > DL_GETPSIZE(&lp->d_partitions[part]))) 956 return EINVAL; 957 958 /* Offset block number to start of partition. */ 959 blkno += DL_GETPOFFSET(&lp->d_partitions[part]); 960 961 /* Recalibrate, if first dump transfer. */ 962 if (wddumprecalibrated == 0) { 963 wddumpmulti = wd->sc_multi; 964 wddumprecalibrated = 1; 965 wd->drvp->state = RECAL; 966 } 967 968 while (nblks > 0) { 969 wd->sc_wdc_bio.blkno = blkno; 970 wd->sc_wdc_bio.flags = ATA_POLL; 971 if (wd->sc_flags & WDF_LBA48) 972 wd->sc_wdc_bio.flags |= ATA_LBA48; 973 if (wd->sc_flags & WDF_LBA) 974 wd->sc_wdc_bio.flags |= ATA_LBA; 975 wd->sc_wdc_bio.bcount = 976 min(nblks, wddumpmulti) * lp->d_secsize; 977 wd->sc_wdc_bio.databuf = va; 978 wd->sc_wdc_bio.wd = wd; 979 #ifndef WD_DUMP_NOT_TRUSTED 980 switch (wdc_ata_bio(wd->drvp, &wd->sc_wdc_bio)) { 981 case WDC_TRY_AGAIN: 982 panic("wddump: try again"); 983 break; 984 case WDC_QUEUED: 985 panic("wddump: polled command has been queued"); 986 break; 987 case WDC_COMPLETE: 988 break; 989 } 990 switch(wd->sc_wdc_bio.error) { 991 case TIMEOUT: 992 printf("wddump: device timed out"); 993 err = EIO; 994 break; 995 case ERR_DF: 996 printf("wddump: drive fault"); 997 err = EIO; 998 break; 999 case ERR_DMA: 1000 printf("wddump: DMA error"); 1001 err = EIO; 1002 break; 1003 case ERROR: 1004 errbuf[0] = '\0'; 1005 ata_perror(wd->drvp, wd->sc_wdc_bio.r_error, errbuf, 1006 sizeof errbuf); 1007 printf("wddump: %s", errbuf); 1008 err = EIO; 1009 break; 1010 case NOERROR: 1011 err = 0; 1012 break; 1013 default: 1014 panic("wddump: unknown error type"); 1015 } 1016 if (err != 0) { 1017 printf("\n"); 1018 return err; 1019 } 1020 #else /* WD_DUMP_NOT_TRUSTED */ 1021 /* Let's just talk about this first... */ 1022 printf("wd%d: dump addr 0x%x, cylin %d, head %d, sector %d\n", 1023 unit, va, cylin, head, sector); 1024 delay(500 * 1000); /* half a second */ 1025 #endif 1026 1027 /* update block count */ 1028 nblks -= min(nblks, wddumpmulti); 1029 blkno += min(nblks, wddumpmulti); 1030 va += min(nblks, wddumpmulti) * lp->d_secsize; 1031 } 1032 1033 wddoingadump = 0; 1034 return 0; 1035 } 1036 1037 int 1038 wd_get_params(struct wd_softc *wd, u_int8_t flags, struct ataparams *params) 1039 { 1040 switch (ata_get_params(wd->drvp, flags, params)) { 1041 case CMD_AGAIN: 1042 return 1; 1043 case CMD_ERR: 1044 /* If we already have drive parameters, reuse them. */ 1045 if (wd->sc_params.atap_cylinders != 0) { 1046 if (params != &wd->sc_params) 1047 bcopy(&wd->sc_params, params, 1048 sizeof(struct ataparams)); 1049 return 0; 1050 } 1051 /* 1052 * We `know' there's a drive here; just assume it's old. 1053 * This geometry is only used to read the MBR and print a 1054 * (false) attach message. 1055 */ 1056 bzero(params, sizeof(struct ataparams)); 1057 strncpy(params->atap_model, "ST506", 1058 sizeof params->atap_model); 1059 params->atap_config = ATA_CFG_FIXED; 1060 params->atap_cylinders = 1024; 1061 params->atap_heads = 8; 1062 params->atap_sectors = 17; 1063 params->atap_multi = 1; 1064 params->atap_capabilities1 = params->atap_capabilities2 = 0; 1065 wd->drvp->ata_vers = -1; /* Mark it as pre-ATA */ 1066 return 0; 1067 case CMD_OK: 1068 return 0; 1069 default: 1070 panic("wd_get_params: bad return code from ata_get_params"); 1071 /* NOTREACHED */ 1072 } 1073 } 1074 1075 void 1076 wd_flushcache(struct wd_softc *wd, int flags) 1077 { 1078 struct wdc_command wdc_c; 1079 1080 if (wd->drvp->ata_vers < 4) /* WDCC_FLUSHCACHE is here since ATA-4 */ 1081 return; 1082 bzero(&wdc_c, sizeof(struct wdc_command)); 1083 wdc_c.r_command = (wd->sc_flags & WDF_LBA48 ? WDCC_FLUSHCACHE_EXT : 1084 WDCC_FLUSHCACHE); 1085 wdc_c.r_st_bmask = WDCS_DRDY; 1086 wdc_c.r_st_pmask = WDCS_DRDY; 1087 if (flags != 0) { 1088 wdc_c.flags = AT_POLL; 1089 } else { 1090 wdc_c.flags = AT_WAIT; 1091 } 1092 wdc_c.timeout = 30000; /* 30s timeout */ 1093 if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) { 1094 printf("%s: flush cache command didn't complete\n", 1095 wd->sc_dev.dv_xname); 1096 } 1097 if (wdc_c.flags & AT_TIMEOU) { 1098 printf("%s: flush cache command timeout\n", 1099 wd->sc_dev.dv_xname); 1100 } 1101 if (wdc_c.flags & AT_DF) { 1102 printf("%s: flush cache command: drive fault\n", 1103 wd->sc_dev.dv_xname); 1104 } 1105 /* 1106 * Ignore error register, it shouldn't report anything else 1107 * than COMMAND ABORTED, which means the device doesn't support 1108 * flush cache 1109 */ 1110 } 1111 1112 void 1113 wd_standby(struct wd_softc *wd, int flags) 1114 { 1115 struct wdc_command wdc_c; 1116 1117 bzero(&wdc_c, sizeof(struct wdc_command)); 1118 wdc_c.r_command = WDCC_STANDBY_IMMED; 1119 wdc_c.r_st_bmask = WDCS_DRDY; 1120 wdc_c.r_st_pmask = WDCS_DRDY; 1121 if (flags != 0) { 1122 wdc_c.flags = AT_POLL; 1123 } else { 1124 wdc_c.flags = AT_WAIT; 1125 } 1126 wdc_c.timeout = 30000; /* 30s timeout */ 1127 if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) { 1128 printf("%s: standby command didn't complete\n", 1129 wd->sc_dev.dv_xname); 1130 } 1131 if (wdc_c.flags & AT_TIMEOU) { 1132 printf("%s: standby command timeout\n", 1133 wd->sc_dev.dv_xname); 1134 } 1135 if (wdc_c.flags & AT_DF) { 1136 printf("%s: standby command: drive fault\n", 1137 wd->sc_dev.dv_xname); 1138 } 1139 /* 1140 * Ignore error register, it shouldn't report anything else 1141 * than COMMAND ABORTED, which means the device doesn't support 1142 * standby 1143 */ 1144 } 1145 1146 void 1147 wd_shutdown(void *arg) 1148 { 1149 struct wd_softc *wd = arg; 1150 1151 wd_flushcache(wd, AT_POLL); 1152 if (boothowto & RB_POWERDOWN) 1153 wd_standby(wd, AT_POLL); 1154 } 1155