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