1 1.474 jakllsch /* $NetBSD: wd.c,v 1.474 2025/04/13 14:00:59 jakllsch Exp $ */ 2 1.181 bouyer 3 1.181 bouyer /* 4 1.218 bouyer * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. 5 1.181 bouyer * 6 1.181 bouyer * Redistribution and use in source and binary forms, with or without 7 1.181 bouyer * modification, are permitted provided that the following conditions 8 1.181 bouyer * are met: 9 1.181 bouyer * 1. Redistributions of source code must retain the above copyright 10 1.181 bouyer * notice, this list of conditions and the following disclaimer. 11 1.181 bouyer * 2. Redistributions in binary form must reproduce the above copyright 12 1.181 bouyer * notice, this list of conditions and the following disclaimer in the 13 1.181 bouyer * documentation and/or other materials provided with the distribution. 14 1.181 bouyer * 15 1.181 bouyer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 1.181 bouyer * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 1.181 bouyer * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 1.259 dsl * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 1.181 bouyer * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 1.181 bouyer * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 1.181 bouyer * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 1.181 bouyer * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 1.181 bouyer * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 1.181 bouyer * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 1.181 bouyer */ 26 1.100 cgd 27 1.178 mycroft /*- 28 1.280 mycroft * Copyright (c) 1998, 2003, 2004 The NetBSD Foundation, Inc. 29 1.178 mycroft * All rights reserved. 30 1.119 mycroft * 31 1.178 mycroft * This code is derived from software contributed to The NetBSD Foundation 32 1.178 mycroft * by Charles M. Hannum and by Onno van der Linden. 33 1.168 cgd * 34 1.113 mycroft * Redistribution and use in source and binary forms, with or without 35 1.113 mycroft * modification, are permitted provided that the following conditions 36 1.113 mycroft * are met: 37 1.113 mycroft * 1. Redistributions of source code must retain the above copyright 38 1.113 mycroft * notice, this list of conditions and the following disclaimer. 39 1.113 mycroft * 2. Redistributions in binary form must reproduce the above copyright 40 1.113 mycroft * notice, this list of conditions and the following disclaimer in the 41 1.113 mycroft * documentation and/or other materials provided with the distribution. 42 1.113 mycroft * 43 1.178 mycroft * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 44 1.178 mycroft * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 45 1.178 mycroft * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 46 1.178 mycroft * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 47 1.178 mycroft * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 48 1.178 mycroft * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 49 1.178 mycroft * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 50 1.178 mycroft * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 51 1.178 mycroft * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 52 1.178 mycroft * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 53 1.178 mycroft * POSSIBILITY OF SUCH DAMAGE. 54 1.1 cgd */ 55 1.215 lukem 56 1.215 lukem #include <sys/cdefs.h> 57 1.474 jakllsch __KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.474 2025/04/13 14:00:59 jakllsch Exp $"); 58 1.1 cgd 59 1.338 dyoung #include "opt_ata.h" 60 1.430 jdolecek #include "opt_wd.h" 61 1.181 bouyer 62 1.29 mycroft #include <sys/param.h> 63 1.29 mycroft #include <sys/systm.h> 64 1.43 mycroft #include <sys/kernel.h> 65 1.29 mycroft #include <sys/conf.h> 66 1.29 mycroft #include <sys/file.h> 67 1.29 mycroft #include <sys/stat.h> 68 1.29 mycroft #include <sys/ioctl.h> 69 1.29 mycroft #include <sys/buf.h> 70 1.296 yamt #include <sys/bufq.h> 71 1.29 mycroft #include <sys/uio.h> 72 1.64 mycroft #include <sys/device.h> 73 1.94 mycroft #include <sys/disklabel.h> 74 1.94 mycroft #include <sys/disk.h> 75 1.29 mycroft #include <sys/syslog.h> 76 1.149 christos #include <sys/proc.h> 77 1.354 joerg #include <sys/reboot.h> 78 1.196 enami #include <sys/vnode.h> 79 1.419 riastrad #include <sys/rndsource.h> 80 1.29 mycroft 81 1.347 ad #include <sys/intr.h> 82 1.347 ad #include <sys/bus.h> 83 1.237 thorpej 84 1.181 bouyer #include <dev/ata/atareg.h> 85 1.181 bouyer #include <dev/ata/atavar.h> 86 1.181 bouyer #include <dev/ata/wdvar.h> 87 1.181 bouyer #include <dev/ic/wdcreg.h> 88 1.186 kenh #include <sys/ataio.h> 89 1.163 bouyer #include "locators.h" 90 1.1 cgd 91 1.330 thorpej #include <prop/proplib.h> 92 1.330 thorpej 93 1.430 jdolecek #define WDIORETRIES_SINGLE 4 /* number of retries for single-sector */ 94 1.181 bouyer #define WDIORETRIES 5 /* number of retries before giving up */ 95 1.181 bouyer #define RECOVERYTIME hz/2 /* time to wait before retrying a cmd */ 96 1.23 deraadt 97 1.181 bouyer #define WDUNIT(dev) DISKUNIT(dev) 98 1.181 bouyer #define WDPART(dev) DISKPART(dev) 99 1.196 enami #define WDMINOR(unit, part) DISKMINOR(unit, part) 100 1.92 cgd #define MAKEWDDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part) 101 1.92 cgd 102 1.92 cgd #define WDLABELDEV(dev) (MAKEWDDEV(major(dev), WDUNIT(dev), RAW_PART)) 103 1.1 cgd 104 1.181 bouyer #define DEBUG_FUNCS 0x08 105 1.181 bouyer #define DEBUG_PROBE 0x10 106 1.433 jdolecek #define DEBUG_DETACH 0x20 107 1.470 uwe #define DEBUG_XFERS 0x40 108 1.289 thorpej #ifdef ATADEBUG 109 1.434 mlelstv #ifndef ATADEBUG_WD_MASK 110 1.434 mlelstv #define ATADEBUG_WD_MASK 0x0 111 1.434 mlelstv #endif 112 1.434 mlelstv int wdcdebug_wd_mask = ATADEBUG_WD_MASK; 113 1.289 thorpej #define ATADEBUG_PRINT(args, level) \ 114 1.181 bouyer if (wdcdebug_wd_mask & (level)) \ 115 1.181 bouyer printf args 116 1.163 bouyer #else 117 1.289 thorpej #define ATADEBUG_PRINT(args, level) 118 1.163 bouyer #endif 119 1.181 bouyer 120 1.434 mlelstv static int wdprobe(device_t, cfdata_t, void *); 121 1.434 mlelstv static void wdattach(device_t, device_t, void *); 122 1.434 mlelstv static int wddetach(device_t, int); 123 1.434 mlelstv static void wdperror(const struct wd_softc *, struct ata_xfer *); 124 1.102 mycroft 125 1.388 jakllsch static void wdminphys(struct buf *); 126 1.388 jakllsch 127 1.434 mlelstv static int wd_firstopen(device_t, dev_t, int, int); 128 1.434 mlelstv static int wd_lastclose(device_t); 129 1.384 dyoung static bool wd_suspend(device_t, const pmf_qual_t *); 130 1.353 jmcneill static int wd_standby(struct wd_softc *, int); 131 1.351 jmcneill 132 1.371 dyoung CFATTACH_DECL3_NEW(wd, sizeof(struct wd_softc), 133 1.375 dyoung wdprobe, wdattach, wddetach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN); 134 1.147 thorpej 135 1.167 thorpej extern struct cfdriver wd_cd; 136 1.108 mycroft 137 1.434 mlelstv static dev_type_open(wdopen); 138 1.434 mlelstv static dev_type_close(wdclose); 139 1.434 mlelstv static dev_type_read(wdread); 140 1.434 mlelstv static dev_type_write(wdwrite); 141 1.434 mlelstv static dev_type_ioctl(wdioctl); 142 1.434 mlelstv static dev_type_strategy(wdstrategy); 143 1.434 mlelstv static dev_type_dump(wddump); 144 1.434 mlelstv static dev_type_size(wdsize); 145 1.410 dholland static dev_type_discard(wddiscard); 146 1.225 gehenna 147 1.225 gehenna const struct bdevsw wd_bdevsw = { 148 1.407 dholland .d_open = wdopen, 149 1.407 dholland .d_close = wdclose, 150 1.407 dholland .d_strategy = wdstrategy, 151 1.407 dholland .d_ioctl = wdioctl, 152 1.407 dholland .d_dump = wddump, 153 1.407 dholland .d_psize = wdsize, 154 1.410 dholland .d_discard = wddiscard, 155 1.467 riastrad .d_cfdriver = &wd_cd, 156 1.467 riastrad .d_devtounit = disklabel_dev_unit, 157 1.407 dholland .d_flag = D_DISK 158 1.225 gehenna }; 159 1.225 gehenna 160 1.225 gehenna const struct cdevsw wd_cdevsw = { 161 1.407 dholland .d_open = wdopen, 162 1.407 dholland .d_close = wdclose, 163 1.407 dholland .d_read = wdread, 164 1.407 dholland .d_write = wdwrite, 165 1.407 dholland .d_ioctl = wdioctl, 166 1.407 dholland .d_stop = nostop, 167 1.407 dholland .d_tty = notty, 168 1.407 dholland .d_poll = nopoll, 169 1.407 dholland .d_mmap = nommap, 170 1.407 dholland .d_kqfilter = nokqfilter, 171 1.410 dholland .d_discard = wddiscard, 172 1.467 riastrad .d_cfdriver = &wd_cd, 173 1.467 riastrad .d_devtounit = disklabel_dev_unit, 174 1.407 dholland .d_flag = D_DISK 175 1.225 gehenna }; 176 1.225 gehenna 177 1.430 jdolecek /* #define WD_DUMP_NOT_TRUSTED if you just want to watch */ 178 1.430 jdolecek static int wddoingadump = 0; 179 1.430 jdolecek static int wddumprecalibrated = 0; 180 1.430 jdolecek 181 1.185 kenh /* 182 1.185 kenh * Glue necessary to hook WDCIOCCOMMAND into physio 183 1.185 kenh */ 184 1.185 kenh 185 1.185 kenh struct wd_ioctl { 186 1.185 kenh LIST_ENTRY(wd_ioctl) wi_list; 187 1.185 kenh struct buf wi_bp; 188 1.185 kenh struct uio wi_uio; 189 1.185 kenh struct iovec wi_iov; 190 1.186 kenh atareq_t wi_atareq; 191 1.185 kenh struct wd_softc *wi_softc; 192 1.185 kenh }; 193 1.185 kenh 194 1.434 mlelstv static struct wd_ioctl *wi_find(struct buf *); 195 1.434 mlelstv static void wi_free(struct wd_ioctl *); 196 1.434 mlelstv static struct wd_ioctl *wi_get(struct wd_softc *); 197 1.434 mlelstv static void wdioctlstrategy(struct buf *); 198 1.434 mlelstv 199 1.442 jdolecek static void wdrestart(void *); 200 1.435 mlelstv static void wdstart1(struct wd_softc *, struct buf *, struct ata_xfer *); 201 1.434 mlelstv static int wd_diskstart(device_t, struct buf *); 202 1.434 mlelstv static int wd_dumpblocks(device_t, void *, daddr_t, int); 203 1.434 mlelstv static void wd_iosize(device_t, int *); 204 1.434 mlelstv static int wd_discard(device_t, off_t, off_t); 205 1.442 jdolecek static void wdbioretry(void *); 206 1.442 jdolecek static void wdbiorequeue(void *); 207 1.434 mlelstv static void wddone(device_t, struct ata_xfer *); 208 1.462 jdolecek static int wd_get_params(struct wd_softc *, struct ataparams *); 209 1.434 mlelstv static void wd_set_geometry(struct wd_softc *); 210 1.464 christos static int wd_flushcache(struct wd_softc *, int); 211 1.434 mlelstv static int wd_trim(struct wd_softc *, daddr_t, long); 212 1.434 mlelstv static bool wd_shutdown(device_t, int); 213 1.108 mycroft 214 1.434 mlelstv static int wd_getcache(struct wd_softc *, int *); 215 1.434 mlelstv static int wd_setcache(struct wd_softc *, int); 216 1.248 bouyer 217 1.430 jdolecek static void wd_sysctl_attach(struct wd_softc *); 218 1.430 jdolecek static void wd_sysctl_detach(struct wd_softc *); 219 1.430 jdolecek 220 1.461 maxv static const struct dkdriver wddkdriver = { 221 1.434 mlelstv .d_open = wdopen, 222 1.434 mlelstv .d_close = wdclose, 223 1.420 mlelstv .d_strategy = wdstrategy, 224 1.434 mlelstv .d_minphys = wdminphys, 225 1.434 mlelstv .d_diskstart = wd_diskstart, 226 1.434 mlelstv .d_dumpblocks = wd_dumpblocks, 227 1.434 mlelstv .d_iosize = wd_iosize, 228 1.434 mlelstv .d_firstopen = wd_firstopen, 229 1.434 mlelstv .d_lastclose = wd_lastclose, 230 1.434 mlelstv .d_discard = wd_discard 231 1.420 mlelstv }; 232 1.65 mycroft 233 1.170 leo #ifdef HAS_BAD144_HANDLING 234 1.259 dsl static void bad144intern(struct wd_softc *); 235 1.170 leo #endif 236 1.1 cgd 237 1.239 thorpej #define WD_QUIRK_SPLIT_MOD15_WRITE 0x0001 /* must split certain writes */ 238 1.239 thorpej 239 1.457 simonb #define WD_QUIRK_FMT "\20\1SPLIT_MOD15_WRITE" 240 1.327 lukem 241 1.239 thorpej /* 242 1.239 thorpej * Quirk table for IDE drives. Put more-specific matches first, since 243 1.389 jakllsch * a simple globing routine is used for matching. 244 1.239 thorpej */ 245 1.239 thorpej static const struct wd_quirk { 246 1.239 thorpej const char *wdq_match; /* inquiry pattern to match */ 247 1.239 thorpej int wdq_quirks; /* drive quirks */ 248 1.239 thorpej } wd_quirk_table[] = { 249 1.239 thorpej /* 250 1.239 thorpej * Some Seagate S-ATA drives have a PHY which can get confused 251 1.239 thorpej * with the way data is packetized by some S-ATA controllers. 252 1.239 thorpej * 253 1.246 mason * The work-around is to split in two any write transfer whose 254 1.239 thorpej * sector count % 15 == 1 (assuming 512 byte sectors). 255 1.239 thorpej * 256 1.239 thorpej * XXX This is an incomplete list. There are at least a couple 257 1.239 thorpej * XXX more model numbers. If you have trouble with such transfers 258 1.239 thorpej * XXX (8K is the most common) on Seagate S-ATA drives, please 259 1.269 keihan * XXX notify thorpej (at) NetBSD.org. 260 1.389 jakllsch * 261 1.389 jakllsch * The ST360015AS has not yet been confirmed to have this 262 1.389 jakllsch * issue, however, it is the only other drive in the 263 1.389 jakllsch * Seagate Barracuda Serial ATA V family. 264 1.389 jakllsch * 265 1.239 thorpej */ 266 1.457 simonb { "ST3120023AS", WD_QUIRK_SPLIT_MOD15_WRITE }, 267 1.457 simonb { "ST380023AS", WD_QUIRK_SPLIT_MOD15_WRITE }, 268 1.457 simonb { "ST360015AS", WD_QUIRK_SPLIT_MOD15_WRITE }, 269 1.456 simonb { NULL, 270 1.456 simonb 0 } 271 1.239 thorpej }; 272 1.239 thorpej 273 1.239 thorpej static const struct wd_quirk * 274 1.239 thorpej wd_lookup_quirks(const char *name) 275 1.239 thorpej { 276 1.239 thorpej const struct wd_quirk *wdq; 277 1.239 thorpej const char *estr; 278 1.239 thorpej 279 1.239 thorpej for (wdq = wd_quirk_table; wdq->wdq_match != NULL; wdq++) { 280 1.239 thorpej /* 281 1.239 thorpej * We only want exact matches (which include matches 282 1.239 thorpej * against globbing characters). 283 1.239 thorpej */ 284 1.239 thorpej if (pmatch(name, wdq->wdq_match, &estr) == 2) 285 1.239 thorpej return (wdq); 286 1.239 thorpej } 287 1.239 thorpej return (NULL); 288 1.239 thorpej } 289 1.239 thorpej 290 1.434 mlelstv static int 291 1.373 cegger wdprobe(device_t parent, cfdata_t match, void *aux) 292 1.1 cgd { 293 1.216 bouyer struct ata_device *adev = aux; 294 1.167 thorpej 295 1.216 bouyer if (adev == NULL) 296 1.181 bouyer return 0; 297 1.216 bouyer if (adev->adev_bustype->bustype_type != SCSIPI_BUSTYPE_ATA) 298 1.64 mycroft return 0; 299 1.181 bouyer 300 1.263 bouyer if (match->cf_loc[ATA_HLCF_DRIVE] != ATA_HLCF_DRIVE_DEFAULT && 301 1.263 bouyer match->cf_loc[ATA_HLCF_DRIVE] != adev->adev_drv_data->drive) 302 1.74 mycroft return 0; 303 1.74 mycroft return 1; 304 1.74 mycroft } 305 1.64 mycroft 306 1.434 mlelstv static void 307 1.373 cegger wdattach(device_t parent, device_t self, void *aux) 308 1.74 mycroft { 309 1.360 cube struct wd_softc *wd = device_private(self); 310 1.434 mlelstv struct dk_softc *dksc = &wd->sc_dksc; 311 1.216 bouyer struct ata_device *adev= aux; 312 1.74 mycroft int i, blank; 313 1.474 jakllsch uint32_t firstaligned = 0, alignment = 1; 314 1.445 mlelstv char tbuf[41],pbuf[9], c, *p, *q; 315 1.239 thorpej const struct wd_quirk *wdq; 316 1.434 mlelstv int dtype = DKTYPE_UNKNOWN; 317 1.350 itohy 318 1.434 mlelstv dksc->sc_dev = self; 319 1.360 cube 320 1.289 thorpej ATADEBUG_PRINT(("wdattach\n"), DEBUG_FUNCS | DEBUG_PROBE); 321 1.430 jdolecek mutex_init(&wd->sc_lock, MUTEX_DEFAULT, IPL_BIO); 322 1.292 drochner #ifdef WD_SOFTBADSECT 323 1.241 darrenr SLIST_INIT(&wd->sc_bslist); 324 1.466 riastrad cv_init(&wd->sc_bslist_cv, "wdbadsect"); 325 1.292 drochner #endif 326 1.217 bouyer wd->atabus = adev->adev_bustype; 327 1.446 mlelstv wd->inflight = 0; 328 1.235 simonb wd->drvp = adev->adev_drv_data; 329 1.270 thorpej 330 1.430 jdolecek wd->drvp->drv_openings = 1; 331 1.270 thorpej wd->drvp->drv_done = wddone; 332 1.434 mlelstv wd->drvp->drv_softc = dksc->sc_dev; /* done in atabusconfig_thread() 333 1.400 bouyer but too late */ 334 1.181 bouyer 335 1.442 jdolecek SLIST_INIT(&wd->sc_retry_list); 336 1.442 jdolecek SLIST_INIT(&wd->sc_requeue_list); 337 1.442 jdolecek callout_init(&wd->sc_retry_callout, 0); /* XXX MPSAFE */ 338 1.442 jdolecek callout_init(&wd->sc_requeue_callout, 0); /* XXX MPSAFE */ 339 1.442 jdolecek callout_init(&wd->sc_restart_diskqueue, 0); /* XXX MPSAFE */ 340 1.442 jdolecek 341 1.253 thorpej aprint_naive("\n"); 342 1.386 enami aprint_normal("\n"); 343 1.253 thorpej 344 1.181 bouyer /* read our drive info */ 345 1.462 jdolecek if (wd_get_params(wd, &wd->sc_params) != 0) { 346 1.386 enami aprint_error_dev(self, "IDENTIFY failed\n"); 347 1.400 bouyer goto out; 348 1.181 bouyer } 349 1.163 bouyer 350 1.301 christos for (blank = 0, p = wd->sc_params.atap_model, q = tbuf, i = 0; 351 1.181 bouyer i < sizeof(wd->sc_params.atap_model); i++) { 352 1.135 mycroft c = *p++; 353 1.135 mycroft if (c == '\0') 354 1.135 mycroft break; 355 1.135 mycroft if (c != ' ') { 356 1.135 mycroft if (blank) { 357 1.135 mycroft *q++ = ' '; 358 1.135 mycroft blank = 0; 359 1.135 mycroft } 360 1.135 mycroft *q++ = c; 361 1.135 mycroft } else 362 1.135 mycroft blank = 1; 363 1.195 enami } 364 1.135 mycroft *q++ = '\0'; 365 1.135 mycroft 366 1.445 mlelstv wd->sc_typename = kmem_asprintf("%s", tbuf); 367 1.445 mlelstv aprint_normal_dev(self, "<%s>\n", wd->sc_typename); 368 1.113 mycroft 369 1.301 christos wdq = wd_lookup_quirks(tbuf); 370 1.239 thorpej if (wdq != NULL) 371 1.239 thorpej wd->sc_quirks = wdq->wdq_quirks; 372 1.239 thorpej 373 1.327 lukem if (wd->sc_quirks != 0) { 374 1.327 lukem char sbuf[sizeof(WD_QUIRK_FMT) + 64]; 375 1.366 christos snprintb(sbuf, sizeof(sbuf), WD_QUIRK_FMT, wd->sc_quirks); 376 1.360 cube aprint_normal_dev(self, "quirks %s\n", sbuf); 377 1.429 jdolecek 378 1.429 jdolecek if (wd->sc_quirks & WD_QUIRK_SPLIT_MOD15_WRITE) { 379 1.429 jdolecek aprint_error_dev(self, "drive corrupts write transfers with certain controllers, consider replacing\n"); 380 1.429 jdolecek } 381 1.327 lukem } 382 1.327 lukem 383 1.181 bouyer if ((wd->sc_params.atap_multi & 0xff) > 1) { 384 1.430 jdolecek wd->drvp->multi = wd->sc_params.atap_multi & 0xff; 385 1.113 mycroft } else { 386 1.430 jdolecek wd->drvp->multi = 1; 387 1.113 mycroft } 388 1.113 mycroft 389 1.360 cube aprint_verbose_dev(self, "drive supports %d-sector PIO transfers,", 390 1.430 jdolecek wd->drvp->multi); 391 1.172 mycroft 392 1.220 christos /* 48-bit LBA addressing */ 393 1.268 yamt if ((wd->sc_params.atap_cmd2_en & ATA_CMD2_LBA48) != 0) 394 1.220 christos wd->sc_flags |= WDF_LBA48; 395 1.220 christos 396 1.172 mycroft /* Prior to ATA-4, LBA was optional. */ 397 1.181 bouyer if ((wd->sc_params.atap_capabilities1 & WDC_CAP_LBA) != 0) 398 1.181 bouyer wd->sc_flags |= WDF_LBA; 399 1.174 mycroft #if 0 400 1.172 mycroft /* ATA-4 requires LBA. */ 401 1.181 bouyer if (wd->sc_params.atap_ataversion != 0xffff && 402 1.181 bouyer wd->sc_params.atap_ataversion >= WDC_VER_ATA4) 403 1.181 bouyer wd->sc_flags |= WDF_LBA; 404 1.174 mycroft #endif 405 1.172 mycroft 406 1.220 christos if ((wd->sc_flags & WDF_LBA48) != 0) { 407 1.336 ad aprint_verbose(" LBA48 addressing\n"); 408 1.220 christos wd->sc_capacity = 409 1.413 matt ((uint64_t) wd->sc_params.atap_max_lba[3] << 48) | 410 1.413 matt ((uint64_t) wd->sc_params.atap_max_lba[2] << 32) | 411 1.413 matt ((uint64_t) wd->sc_params.atap_max_lba[1] << 16) | 412 1.413 matt ((uint64_t) wd->sc_params.atap_max_lba[0] << 0); 413 1.380 bouyer wd->sc_capacity28 = 414 1.380 bouyer (wd->sc_params.atap_capacity[1] << 16) | 415 1.380 bouyer wd->sc_params.atap_capacity[0]; 416 1.468 mlelstv /* 417 1.468 mlelstv * Force LBA48 addressing for invalid numbers. 418 1.468 mlelstv */ 419 1.468 mlelstv if (wd->sc_capacity28 > 0xfffffff) 420 1.468 mlelstv wd->sc_capacity28 = 0xfffffff; 421 1.220 christos } else if ((wd->sc_flags & WDF_LBA) != 0) { 422 1.336 ad aprint_verbose(" LBA addressing\n"); 423 1.468 mlelstv wd->sc_capacity28 = 424 1.380 bouyer (wd->sc_params.atap_capacity[1] << 16) | 425 1.181 bouyer wd->sc_params.atap_capacity[0]; 426 1.468 mlelstv /* 427 1.468 mlelstv * Limit capacity to LBA28 numbers to avoid overflow. 428 1.468 mlelstv */ 429 1.468 mlelstv if (wd->sc_capacity28 > 0xfffffff) 430 1.468 mlelstv wd->sc_capacity28 = 0xfffffff; 431 1.468 mlelstv wd->sc_capacity = wd->sc_capacity28; 432 1.172 mycroft } else { 433 1.336 ad aprint_verbose(" chs addressing\n"); 434 1.468 mlelstv wd->sc_capacity = 435 1.181 bouyer wd->sc_params.atap_cylinders * 436 1.181 bouyer wd->sc_params.atap_heads * 437 1.181 bouyer wd->sc_params.atap_sectors; 438 1.468 mlelstv /* 439 1.468 mlelstv * LBA28 size is ignored for CHS addressing. Use a reasonable 440 1.469 andvar * value for debugging. The CHS values may be artificial and 441 1.468 mlelstv * are mostly ignored. 442 1.468 mlelstv */ 443 1.468 mlelstv if (wd->sc_capacity < 0xfffffff) 444 1.468 mlelstv wd->sc_capacity28 = wd->sc_capacity; 445 1.468 mlelstv else 446 1.468 mlelstv wd->sc_capacity28 = 0xfffffff; 447 1.172 mycroft } 448 1.424 jakllsch if ((wd->sc_params.atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID 449 1.424 jakllsch && ((wd->sc_params.atap_secsz & ATA_SECSZ_LLS) != 0)) { 450 1.424 jakllsch wd->sc_blksize = 2ULL * 451 1.426 christos ((uint32_t)((wd->sc_params.atap_lls_secsz[1] << 16) | 452 1.426 christos wd->sc_params.atap_lls_secsz[0])); 453 1.424 jakllsch } else { 454 1.424 jakllsch wd->sc_blksize = 512; 455 1.424 jakllsch } 456 1.459 riastrad if ((wd->sc_params.atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID 457 1.459 riastrad && ((wd->sc_params.atap_secsz & ATA_SECSZ_LPS) != 0)) { 458 1.474 jakllsch alignment = 1 << 459 1.459 riastrad (wd->sc_params.atap_secsz & ATA_SECSZ_LPS_SZMSK); 460 1.459 riastrad if ((wd->sc_params.atap_logical_align & ATA_LA_VALID_MASK) == 461 1.459 riastrad ATA_LA_VALID) { 462 1.474 jakllsch firstaligned = 463 1.472 jakllsch wd->sc_params.atap_logical_align & ATA_LA_MASK; 464 1.459 riastrad } 465 1.459 riastrad } 466 1.424 jakllsch wd->sc_capacity512 = (wd->sc_capacity * wd->sc_blksize) / DEV_BSIZE; 467 1.424 jakllsch format_bytes(pbuf, sizeof(pbuf), wd->sc_capacity * wd->sc_blksize); 468 1.360 cube aprint_normal_dev(self, "%s, %d cyl, %d head, %d sec, " 469 1.459 riastrad "%d bytes/sect x %llu sectors", 470 1.360 cube pbuf, 471 1.260 bouyer (wd->sc_flags & WDF_LBA) ? (int)(wd->sc_capacity / 472 1.260 bouyer (wd->sc_params.atap_heads * wd->sc_params.atap_sectors)) : 473 1.260 bouyer wd->sc_params.atap_cylinders, 474 1.201 enami wd->sc_params.atap_heads, wd->sc_params.atap_sectors, 475 1.424 jakllsch wd->sc_blksize, (unsigned long long)wd->sc_capacity); 476 1.474 jakllsch if (alignment != 1) { 477 1.459 riastrad aprint_normal(" (%d bytes/physsect", 478 1.474 jakllsch alignment * wd->sc_blksize); 479 1.474 jakllsch if (firstaligned != 0) { 480 1.459 riastrad aprint_normal("; first aligned sector: %jd", 481 1.474 jakllsch (intmax_t)firstaligned); 482 1.459 riastrad } 483 1.459 riastrad aprint_normal(")"); 484 1.459 riastrad } 485 1.459 riastrad aprint_normal("\n"); 486 1.201 enami 487 1.289 thorpej ATADEBUG_PRINT(("%s: atap_dmatiming_mimi=%d, atap_dmatiming_recom=%d\n", 488 1.360 cube device_xname(self), wd->sc_params.atap_dmatiming_mimi, 489 1.181 bouyer wd->sc_params.atap_dmatiming_recom), DEBUG_PROBE); 490 1.424 jakllsch 491 1.424 jakllsch if (wd->sc_blksize <= 0 || !powerof2(wd->sc_blksize) || 492 1.424 jakllsch wd->sc_blksize < DEV_BSIZE || wd->sc_blksize > MAXPHYS) { 493 1.424 jakllsch aprint_normal_dev(self, "WARNING: block size %u " 494 1.424 jakllsch "might not actually work\n", wd->sc_blksize); 495 1.424 jakllsch } 496 1.430 jdolecek 497 1.434 mlelstv if (strcmp(wd->sc_params.atap_model, "ST506") == 0) 498 1.434 mlelstv dtype = DKTYPE_ST506; 499 1.434 mlelstv else 500 1.434 mlelstv dtype = DKTYPE_ESDI; 501 1.434 mlelstv 502 1.400 bouyer out: 503 1.181 bouyer /* 504 1.181 bouyer * Initialize and attach the disk structure. 505 1.181 bouyer */ 506 1.434 mlelstv dk_init(dksc, self, dtype); 507 1.434 mlelstv disk_init(&dksc->sc_dkdev, dksc->sc_xname, &wddkdriver); 508 1.434 mlelstv 509 1.434 mlelstv /* Attach dk and disk subsystems */ 510 1.434 mlelstv dk_attach(dksc); 511 1.434 mlelstv disk_attach(&dksc->sc_dkdev); 512 1.434 mlelstv wd_set_geometry(wd); 513 1.434 mlelstv 514 1.434 mlelstv bufq_alloc(&dksc->sc_bufq, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK); 515 1.434 mlelstv 516 1.434 mlelstv /* reference to label structure, used by ata code */ 517 1.434 mlelstv wd->drvp->lp = dksc->sc_dkdev.dk_label; 518 1.294 thorpej 519 1.294 thorpej /* Discover wedges on this disk. */ 520 1.434 mlelstv dkwedge_discover(&dksc->sc_dkdev); 521 1.351 jmcneill 522 1.357 drochner if (!pmf_device_register1(self, wd_suspend, NULL, wd_shutdown)) 523 1.351 jmcneill aprint_error_dev(self, "couldn't establish power handler\n"); 524 1.430 jdolecek 525 1.430 jdolecek wd_sysctl_attach(wd); 526 1.351 jmcneill } 527 1.351 jmcneill 528 1.351 jmcneill static bool 529 1.384 dyoung wd_suspend(device_t dv, const pmf_qual_t *qual) 530 1.351 jmcneill { 531 1.351 jmcneill struct wd_softc *sc = device_private(dv); 532 1.351 jmcneill 533 1.406 drochner /* the adapter needs to be enabled */ 534 1.406 drochner if (sc->atabus->ata_addref(sc->drvp)) 535 1.406 drochner return true; /* no need to complain */ 536 1.406 drochner 537 1.464 christos wd_flushcache(sc, AT_WAIT); 538 1.356 drochner wd_standby(sc, AT_WAIT); 539 1.406 drochner 540 1.406 drochner sc->atabus->ata_delref(sc->drvp); 541 1.351 jmcneill return true; 542 1.196 enami } 543 1.196 enami 544 1.434 mlelstv static int 545 1.373 cegger wddetach(device_t self, int flags) 546 1.196 enami { 547 1.434 mlelstv struct wd_softc *wd = device_private(self); 548 1.434 mlelstv struct dk_softc *dksc = &wd->sc_dksc; 549 1.430 jdolecek int bmaj, cmaj, i, mn, rc; 550 1.374 dyoung 551 1.434 mlelstv if ((rc = disk_begindetach(&dksc->sc_dkdev, wd_lastclose, self, flags)) != 0) 552 1.374 dyoung return rc; 553 1.196 enami 554 1.196 enami /* locate the major number */ 555 1.225 gehenna bmaj = bdevsw_lookup_major(&wd_bdevsw); 556 1.225 gehenna cmaj = cdevsw_lookup_major(&wd_cdevsw); 557 1.196 enami 558 1.286 mycroft /* Nuke the vnodes for any open instances. */ 559 1.286 mycroft for (i = 0; i < MAXPARTITIONS; i++) { 560 1.321 thorpej mn = WDMINOR(device_unit(self), i); 561 1.286 mycroft vdevgone(bmaj, mn, mn, VBLK); 562 1.286 mycroft vdevgone(cmaj, mn, mn, VCHR); 563 1.286 mycroft } 564 1.286 mycroft 565 1.434 mlelstv dk_drain(dksc); 566 1.294 thorpej 567 1.434 mlelstv /* Kill off any pending commands. */ 568 1.434 mlelstv mutex_enter(&wd->sc_lock); 569 1.434 mlelstv wd->atabus->ata_killpending(wd->drvp); 570 1.442 jdolecek 571 1.442 jdolecek callout_halt(&wd->sc_retry_callout, &wd->sc_lock); 572 1.442 jdolecek callout_destroy(&wd->sc_retry_callout); 573 1.442 jdolecek callout_halt(&wd->sc_requeue_callout, &wd->sc_lock); 574 1.442 jdolecek callout_destroy(&wd->sc_requeue_callout); 575 1.442 jdolecek callout_halt(&wd->sc_restart_diskqueue, &wd->sc_lock); 576 1.442 jdolecek callout_destroy(&wd->sc_restart_diskqueue); 577 1.442 jdolecek 578 1.434 mlelstv mutex_exit(&wd->sc_lock); 579 1.196 enami 580 1.434 mlelstv bufq_free(dksc->sc_bufq); 581 1.224 hannken 582 1.444 mlelstv /* Delete all of our wedges. */ 583 1.444 mlelstv dkwedge_delall(&dksc->sc_dkdev); 584 1.444 mlelstv 585 1.434 mlelstv if (flags & DETACH_POWEROFF) 586 1.434 mlelstv wd_standby(wd, AT_POLL); 587 1.430 jdolecek 588 1.434 mlelstv /* Detach from the disk list. */ 589 1.434 mlelstv disk_detach(&dksc->sc_dkdev); 590 1.434 mlelstv disk_destroy(&dksc->sc_dkdev); 591 1.196 enami 592 1.434 mlelstv dk_detach(dksc); 593 1.196 enami 594 1.292 drochner #ifdef WD_SOFTBADSECT 595 1.282 bouyer /* Clean out the bad sector list */ 596 1.437 pgoyette while (!SLIST_EMPTY(&wd->sc_bslist)) { 597 1.442 jdolecek struct disk_badsectors *dbs = SLIST_FIRST(&wd->sc_bslist); 598 1.437 pgoyette SLIST_REMOVE_HEAD(&wd->sc_bslist, dbs_next); 599 1.442 jdolecek kmem_free(dbs, sizeof(*dbs)); 600 1.282 bouyer } 601 1.437 pgoyette wd->sc_bscount = 0; 602 1.292 drochner #endif 603 1.445 mlelstv if (wd->sc_typename != NULL) { 604 1.445 mlelstv kmem_free(wd->sc_typename, strlen(wd->sc_typename) + 1); 605 1.445 mlelstv wd->sc_typename = NULL; 606 1.445 mlelstv } 607 1.282 bouyer 608 1.351 jmcneill pmf_device_deregister(self); 609 1.196 enami 610 1.434 mlelstv wd_sysctl_detach(wd); 611 1.430 jdolecek 612 1.466 riastrad #ifdef WD_SOFTBADSECT 613 1.466 riastrad KASSERT(SLIST_EMPTY(&wd->sc_bslist)); 614 1.466 riastrad cv_destroy(&wd->sc_bslist_cv); 615 1.466 riastrad #endif 616 1.466 riastrad 617 1.434 mlelstv mutex_destroy(&wd->sc_lock); 618 1.196 enami 619 1.434 mlelstv wd->drvp->drive_type = ATA_DRIVET_NONE; /* no drive any more here */ 620 1.434 mlelstv wd->drvp->drive_flags = 0; 621 1.283 bouyer 622 1.196 enami return (0); 623 1.1 cgd } 624 1.1 cgd 625 1.64 mycroft /* 626 1.135 mycroft * Read/write routine for a buffer. Validates the arguments and schedules the 627 1.135 mycroft * transfer. Does not wait for the transfer to complete. 628 1.1 cgd */ 629 1.434 mlelstv static void 630 1.259 dsl wdstrategy(struct buf *bp) 631 1.1 cgd { 632 1.360 cube struct wd_softc *wd = 633 1.363 tsutsui device_lookup_private(&wd_cd, WDUNIT(bp->b_dev)); 634 1.434 mlelstv struct dk_softc *dksc = &wd->sc_dksc; 635 1.202 thorpej 636 1.434 mlelstv ATADEBUG_PRINT(("wdstrategy (%s)\n", dksc->sc_xname), 637 1.182 bouyer DEBUG_XFERS); 638 1.259 dsl 639 1.375 dyoung /* If device invalidated (e.g. media change, door open, 640 1.385 dyoung * device detachment), then error. 641 1.375 dyoung */ 642 1.385 dyoung if ((wd->sc_flags & WDF_LOADED) == 0 || 643 1.434 mlelstv !device_is_enabled(dksc->sc_dev)) 644 1.434 mlelstv goto err; 645 1.202 thorpej 646 1.292 drochner #ifdef WD_SOFTBADSECT 647 1.241 darrenr /* 648 1.241 darrenr * If the transfer about to be attempted contains only a block that 649 1.241 darrenr * is known to be bad then return an error for the transfer without 650 1.241 darrenr * even attempting to start a transfer up under the premis that we 651 1.241 darrenr * will just end up doing more retries for a transfer that will end 652 1.241 darrenr * up failing again. 653 1.241 darrenr */ 654 1.241 darrenr if (__predict_false(!SLIST_EMPTY(&wd->sc_bslist))) { 655 1.438 mlelstv struct disklabel *lp = dksc->sc_dkdev.dk_label; 656 1.241 darrenr struct disk_badsectors *dbs; 657 1.438 mlelstv daddr_t blkno, maxblk; 658 1.438 mlelstv 659 1.438 mlelstv /* convert the block number to absolute */ 660 1.438 mlelstv if (lp->d_secsize >= DEV_BSIZE) 661 1.438 mlelstv blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE); 662 1.438 mlelstv else 663 1.438 mlelstv blkno = bp->b_blkno * (DEV_BSIZE / lp->d_secsize); 664 1.438 mlelstv if (WDPART(bp->b_dev) != RAW_PART) 665 1.438 mlelstv blkno += lp->d_partitions[WDPART(bp->b_dev)].p_offset; 666 1.438 mlelstv maxblk = blkno + (bp->b_bcount / wd->sc_blksize) - 1; 667 1.241 darrenr 668 1.430 jdolecek mutex_enter(&wd->sc_lock); 669 1.241 darrenr SLIST_FOREACH(dbs, &wd->sc_bslist, dbs_next) 670 1.437 pgoyette if ((dbs->dbs_min <= bp->b_rawblkno && 671 1.437 pgoyette bp->b_rawblkno <= dbs->dbs_max) || 672 1.245 darrenr (dbs->dbs_min <= maxblk && maxblk <= dbs->dbs_max)){ 673 1.430 jdolecek mutex_exit(&wd->sc_lock); 674 1.434 mlelstv goto err; 675 1.245 darrenr } 676 1.430 jdolecek mutex_exit(&wd->sc_lock); 677 1.241 darrenr } 678 1.292 drochner #endif 679 1.241 darrenr 680 1.434 mlelstv dk_strategy(dksc, bp); 681 1.434 mlelstv return; 682 1.430 jdolecek 683 1.434 mlelstv err: 684 1.434 mlelstv bp->b_error = EIO; 685 1.135 mycroft bp->b_resid = bp->b_bcount; 686 1.1 cgd biodone(bp); 687 1.1 cgd } 688 1.1 cgd 689 1.435 mlelstv static void 690 1.435 mlelstv wdstart1(struct wd_softc *wd, struct buf *bp, struct ata_xfer *xfer) 691 1.1 cgd { 692 1.434 mlelstv struct dk_softc *dksc = &wd->sc_dksc; 693 1.463 jdolecek const uint32_t secsize = dksc->sc_dkdev.dk_geom.dg_secsize; 694 1.430 jdolecek 695 1.430 jdolecek KASSERT(bp == xfer->c_bio.bp || xfer->c_bio.bp == NULL); 696 1.430 jdolecek KASSERT((xfer->c_flags & (C_WAITACT|C_FREE)) == 0); 697 1.460 jdolecek KASSERT(mutex_owned(&wd->sc_lock)); 698 1.430 jdolecek 699 1.430 jdolecek /* Reset state, so that retries don't use stale info */ 700 1.430 jdolecek if (__predict_false(xfer->c_retries > 0)) { 701 1.430 jdolecek xfer->c_flags = 0; 702 1.430 jdolecek memset(&xfer->c_bio, 0, sizeof(xfer->c_bio)); 703 1.430 jdolecek } 704 1.430 jdolecek 705 1.430 jdolecek xfer->c_bio.blkno = bp->b_rawblkno; 706 1.430 jdolecek xfer->c_bio.bcount = bp->b_bcount; 707 1.430 jdolecek xfer->c_bio.databuf = bp->b_data; 708 1.430 jdolecek xfer->c_bio.blkdone = 0; 709 1.430 jdolecek xfer->c_bio.bp = bp; 710 1.430 jdolecek 711 1.463 jdolecek /* Adjust blkno and bcount if xfer has been already partially done */ 712 1.463 jdolecek if (__predict_false(xfer->c_skip > 0)) { 713 1.463 jdolecek KASSERT(xfer->c_skip < xfer->c_bio.bcount); 714 1.463 jdolecek KASSERT((xfer->c_skip % secsize) == 0); 715 1.463 jdolecek xfer->c_bio.bcount -= xfer->c_skip; 716 1.463 jdolecek xfer->c_bio.blkno += xfer->c_skip / secsize; 717 1.463 jdolecek } 718 1.463 jdolecek 719 1.430 jdolecek #ifdef WD_CHAOS_MONKEY 720 1.430 jdolecek /* 721 1.430 jdolecek * Override blkno to be over device capacity to trigger error, 722 1.430 jdolecek * but only if it's read, to avoid trashing disk contents should 723 1.430 jdolecek * the command be clipped, or otherwise misinterpreted, by the 724 1.430 jdolecek * driver or controller. 725 1.430 jdolecek */ 726 1.430 jdolecek if (BUF_ISREAD(bp) && xfer->c_retries == 0 && wd->drv_chaos_freq > 0 && 727 1.430 jdolecek (++wd->drv_chaos_cnt % wd->drv_chaos_freq) == 0) { 728 1.442 jdolecek device_printf(dksc->sc_dev, "%s: chaos xfer %"PRIxPTR"\n", 729 1.442 jdolecek __func__, (intptr_t)xfer & PAGE_MASK); 730 1.430 jdolecek xfer->c_bio.blkno = 7777777 + wd->sc_capacity; 731 1.430 jdolecek xfer->c_flags |= C_CHAOS; 732 1.430 jdolecek } 733 1.430 jdolecek #endif 734 1.202 thorpej 735 1.181 bouyer /* 736 1.181 bouyer * If we're retrying, retry in single-sector mode. This will give us 737 1.181 bouyer * the sector number of the problem, and will eventually allow the 738 1.430 jdolecek * transfer to succeed. If FUA is requested, we can't actually 739 1.430 jdolecek * do this, as ATA_SINGLE is usually executed as PIO transfer by drivers 740 1.430 jdolecek * which support it, and that isn't compatible with NCQ/FUA. 741 1.181 bouyer */ 742 1.430 jdolecek if (xfer->c_retries >= WDIORETRIES_SINGLE && 743 1.430 jdolecek (bp->b_flags & B_MEDIA_FUA) == 0) 744 1.430 jdolecek xfer->c_bio.flags = ATA_SINGLE; 745 1.181 bouyer else 746 1.430 jdolecek xfer->c_bio.flags = 0; 747 1.434 mlelstv 748 1.434 mlelstv /* 749 1.434 mlelstv * request LBA48 transfers when supported by the controller 750 1.434 mlelstv * and needed by transfer offset or size. 751 1.434 mlelstv */ 752 1.295 bouyer if (wd->sc_flags & WDF_LBA48 && 753 1.463 jdolecek (((xfer->c_bio.blkno + xfer->c_bio.bcount / secsize) > 754 1.430 jdolecek wd->sc_capacity28) || 755 1.463 jdolecek ((xfer->c_bio.bcount / secsize) > 128))) 756 1.430 jdolecek xfer->c_bio.flags |= ATA_LBA48; 757 1.430 jdolecek 758 1.430 jdolecek /* 759 1.430 jdolecek * If NCQ was negotiated, always use it for the first several attempts. 760 1.430 jdolecek * Since device cancels all outstanding requests on error, downgrade 761 1.430 jdolecek * to non-NCQ on retry, so that the retried transfer would not cause 762 1.430 jdolecek * cascade failure for the other transfers if it fails again. 763 1.430 jdolecek * If FUA was requested, we can't downgrade, as that would violate 764 1.430 jdolecek * the semantics - FUA would not be honored. In that case, continue 765 1.430 jdolecek * retrying with NCQ. 766 1.430 jdolecek */ 767 1.430 jdolecek if (WD_USE_NCQ(wd) && (xfer->c_retries < WDIORETRIES_SINGLE || 768 1.430 jdolecek (bp->b_flags & B_MEDIA_FUA) != 0)) { 769 1.430 jdolecek xfer->c_bio.flags |= ATA_LBA48; 770 1.430 jdolecek xfer->c_flags |= C_NCQ; 771 1.430 jdolecek 772 1.430 jdolecek if (WD_USE_NCQ_PRIO(wd) && 773 1.430 jdolecek BIO_GETPRIO(bp) == BPRIO_TIMECRITICAL) 774 1.430 jdolecek xfer->c_bio.flags |= ATA_PRIO_HIGH; 775 1.430 jdolecek } 776 1.430 jdolecek 777 1.181 bouyer if (wd->sc_flags & WDF_LBA) 778 1.430 jdolecek xfer->c_bio.flags |= ATA_LBA; 779 1.449 bouyer if (bp->b_flags & B_READ) { 780 1.430 jdolecek xfer->c_bio.flags |= ATA_READ; 781 1.449 bouyer } else { 782 1.449 bouyer /* it's a write */ 783 1.449 bouyer wd->sc_flags |= WDF_DIRTY; 784 1.449 bouyer } 785 1.430 jdolecek if (bp->b_flags & B_MEDIA_FUA) { 786 1.430 jdolecek /* If not using NCQ, the command WRITE DMA FUA EXT is LBA48 */ 787 1.430 jdolecek KASSERT((wd->sc_flags & WDF_LBA48) != 0); 788 1.430 jdolecek if ((xfer->c_flags & C_NCQ) == 0) 789 1.430 jdolecek xfer->c_bio.flags |= ATA_LBA48; 790 1.430 jdolecek 791 1.430 jdolecek xfer->c_bio.flags |= ATA_FUA; 792 1.430 jdolecek } 793 1.430 jdolecek 794 1.451 mlelstv if (xfer->c_retries == 0) 795 1.451 mlelstv wd->inflight++; 796 1.460 jdolecek mutex_exit(&wd->sc_lock); 797 1.460 jdolecek 798 1.462 jdolecek /* Queue the xfer */ 799 1.462 jdolecek wd->atabus->ata_bio(wd->drvp, xfer); 800 1.460 jdolecek 801 1.460 jdolecek mutex_enter(&wd->sc_lock); 802 1.435 mlelstv } 803 1.435 mlelstv 804 1.435 mlelstv static int 805 1.435 mlelstv wd_diskstart(device_t dev, struct buf *bp) 806 1.435 mlelstv { 807 1.435 mlelstv struct wd_softc *wd = device_private(dev); 808 1.435 mlelstv #ifdef ATADEBUG 809 1.435 mlelstv struct dk_softc *dksc = &wd->sc_dksc; 810 1.435 mlelstv #endif 811 1.435 mlelstv struct ata_xfer *xfer; 812 1.446 mlelstv struct ata_channel *chp; 813 1.446 mlelstv unsigned openings; 814 1.450 mlelstv int ticks; 815 1.435 mlelstv 816 1.435 mlelstv mutex_enter(&wd->sc_lock); 817 1.435 mlelstv 818 1.446 mlelstv chp = wd->drvp->chnl_softc; 819 1.446 mlelstv 820 1.446 mlelstv ata_channel_lock(chp); 821 1.446 mlelstv openings = ata_queue_openings(chp); 822 1.446 mlelstv ata_channel_unlock(chp); 823 1.446 mlelstv 824 1.446 mlelstv openings = uimin(openings, wd->drvp->drv_openings); 825 1.446 mlelstv 826 1.446 mlelstv if (wd->inflight >= openings) { 827 1.450 mlelstv /* 828 1.450 mlelstv * pretend we run out of memory when the queue is full, 829 1.450 mlelstv * so that the operation is retried after a minimal 830 1.450 mlelstv * delay. 831 1.450 mlelstv */ 832 1.450 mlelstv xfer = NULL; 833 1.450 mlelstv ticks = 1; 834 1.450 mlelstv } else { 835 1.450 mlelstv /* 836 1.450 mlelstv * If there is no available memory, retry later. This 837 1.450 mlelstv * happens very rarely and only under memory pressure, 838 1.450 mlelstv * so wait relatively long before retry. 839 1.450 mlelstv */ 840 1.450 mlelstv xfer = ata_get_xfer(chp, false); 841 1.450 mlelstv ticks = hz/2; 842 1.446 mlelstv } 843 1.446 mlelstv 844 1.435 mlelstv if (xfer == NULL) { 845 1.435 mlelstv ATADEBUG_PRINT(("wd_diskstart %s no xfer\n", 846 1.435 mlelstv dksc->sc_xname), DEBUG_XFERS); 847 1.442 jdolecek 848 1.442 jdolecek /* 849 1.450 mlelstv * The disk queue is pushed automatically when an I/O 850 1.450 mlelstv * operation finishes or another one is queued. We 851 1.450 mlelstv * need this extra timeout because an ATA channel 852 1.450 mlelstv * might be shared by more than one disk queue and 853 1.450 mlelstv * all queues need to be restarted when another slot 854 1.450 mlelstv * becomes available. 855 1.442 jdolecek */ 856 1.442 jdolecek if (!callout_pending(&wd->sc_restart_diskqueue)) { 857 1.450 mlelstv callout_reset(&wd->sc_restart_diskqueue, ticks, 858 1.442 jdolecek wdrestart, dev); 859 1.442 jdolecek } 860 1.442 jdolecek 861 1.435 mlelstv mutex_exit(&wd->sc_lock); 862 1.435 mlelstv return EAGAIN; 863 1.435 mlelstv } 864 1.435 mlelstv 865 1.435 mlelstv wdstart1(wd, bp, xfer); 866 1.434 mlelstv 867 1.434 mlelstv mutex_exit(&wd->sc_lock); 868 1.434 mlelstv 869 1.434 mlelstv return 0; 870 1.181 bouyer } 871 1.181 bouyer 872 1.434 mlelstv /* 873 1.434 mlelstv * Queue a drive for I/O. 874 1.434 mlelstv */ 875 1.434 mlelstv static void 876 1.442 jdolecek wdrestart(void *x) 877 1.434 mlelstv { 878 1.442 jdolecek device_t self = x; 879 1.434 mlelstv struct wd_softc *wd = device_private(self); 880 1.434 mlelstv struct dk_softc *dksc = &wd->sc_dksc; 881 1.434 mlelstv 882 1.434 mlelstv ATADEBUG_PRINT(("wdstart %s\n", dksc->sc_xname), 883 1.434 mlelstv DEBUG_XFERS); 884 1.434 mlelstv 885 1.434 mlelstv if (!device_is_active(dksc->sc_dev)) 886 1.434 mlelstv return; 887 1.434 mlelstv 888 1.434 mlelstv dk_start(dksc, NULL); 889 1.434 mlelstv } 890 1.434 mlelstv 891 1.434 mlelstv static void 892 1.430 jdolecek wddone(device_t self, struct ata_xfer *xfer) 893 1.181 bouyer { 894 1.430 jdolecek struct wd_softc *wd = device_private(self); 895 1.434 mlelstv struct dk_softc *dksc = &wd->sc_dksc; 896 1.221 yamt const char *errmsg; 897 1.221 yamt int do_perror = 0; 898 1.430 jdolecek struct buf *bp; 899 1.349 itohy 900 1.434 mlelstv ATADEBUG_PRINT(("wddone %s\n", dksc->sc_xname), 901 1.182 bouyer DEBUG_XFERS); 902 1.430 jdolecek 903 1.430 jdolecek if (__predict_false(wddoingadump)) { 904 1.430 jdolecek /* just drop it to the floor */ 905 1.430 jdolecek ata_free_xfer(wd->drvp->chnl_softc, xfer); 906 1.214 bjh21 return; 907 1.430 jdolecek } 908 1.430 jdolecek 909 1.430 jdolecek bp = xfer->c_bio.bp; 910 1.430 jdolecek KASSERT(bp != NULL); 911 1.430 jdolecek 912 1.430 jdolecek bp->b_resid = xfer->c_bio.bcount; 913 1.430 jdolecek switch (xfer->c_bio.error) { 914 1.181 bouyer case ERR_DMA: 915 1.221 yamt errmsg = "DMA error"; 916 1.181 bouyer goto retry; 917 1.181 bouyer case ERR_DF: 918 1.221 yamt errmsg = "device fault"; 919 1.181 bouyer goto retry; 920 1.181 bouyer case TIMEOUT: 921 1.221 yamt errmsg = "device timeout"; 922 1.181 bouyer goto retry; 923 1.430 jdolecek case REQUEUE: 924 1.430 jdolecek errmsg = "requeue"; 925 1.430 jdolecek goto retry2; 926 1.281 bouyer case ERR_RESET: 927 1.281 bouyer errmsg = "channel reset"; 928 1.281 bouyer goto retry2; 929 1.181 bouyer case ERROR: 930 1.181 bouyer /* Don't care about media change bits */ 931 1.430 jdolecek if (xfer->c_bio.r_error != 0 && 932 1.430 jdolecek (xfer->c_bio.r_error & ~(WDCE_MC | WDCE_MCR)) == 0) 933 1.181 bouyer goto noerror; 934 1.221 yamt errmsg = "error"; 935 1.221 yamt do_perror = 1; 936 1.181 bouyer retry: /* Just reset and retry. Can we do more ? */ 937 1.431 jdolecek if ((xfer->c_flags & C_RECOVERED) == 0) { 938 1.431 jdolecek int wflags = (xfer->c_flags & C_POLL) ? AT_POLL : 0; 939 1.442 jdolecek ata_channel_lock(wd->drvp->chnl_softc); 940 1.442 jdolecek ata_thread_run(wd->drvp->chnl_softc, wflags, 941 1.442 jdolecek ATACH_TH_DRIVE_RESET, wd->drvp->drive); 942 1.442 jdolecek ata_channel_unlock(wd->drvp->chnl_softc); 943 1.431 jdolecek } 944 1.281 bouyer retry2: 945 1.430 jdolecek mutex_enter(&wd->sc_lock); 946 1.430 jdolecek 947 1.221 yamt diskerr(bp, "wd", errmsg, LOG_PRINTF, 948 1.434 mlelstv xfer->c_bio.blkdone, dksc->sc_dkdev.dk_label); 949 1.430 jdolecek if (xfer->c_retries < WDIORETRIES) 950 1.442 jdolecek printf(", xfer %"PRIxPTR", retry %d", 951 1.442 jdolecek (intptr_t)xfer & PAGE_MASK, 952 1.442 jdolecek xfer->c_retries); 953 1.345 bouyer printf("\n"); 954 1.221 yamt if (do_perror) 955 1.430 jdolecek wdperror(wd, xfer); 956 1.430 jdolecek 957 1.430 jdolecek if (xfer->c_retries < WDIORETRIES) { 958 1.430 jdolecek xfer->c_retries++; 959 1.430 jdolecek 960 1.430 jdolecek /* Rerun ASAP if just requeued */ 961 1.442 jdolecek if (xfer->c_bio.error == REQUEUE) { 962 1.442 jdolecek SLIST_INSERT_HEAD(&wd->sc_requeue_list, xfer, 963 1.442 jdolecek c_retrychain); 964 1.442 jdolecek callout_reset(&wd->sc_requeue_callout, 965 1.442 jdolecek 1, wdbiorequeue, wd); 966 1.442 jdolecek } else { 967 1.442 jdolecek SLIST_INSERT_HEAD(&wd->sc_retry_list, xfer, 968 1.442 jdolecek c_retrychain); 969 1.442 jdolecek callout_reset(&wd->sc_retry_callout, 970 1.442 jdolecek RECOVERYTIME, wdbioretry, wd); 971 1.442 jdolecek } 972 1.430 jdolecek 973 1.430 jdolecek mutex_exit(&wd->sc_lock); 974 1.181 bouyer return; 975 1.181 bouyer } 976 1.241 darrenr 977 1.430 jdolecek mutex_exit(&wd->sc_lock); 978 1.430 jdolecek 979 1.292 drochner #ifdef WD_SOFTBADSECT 980 1.241 darrenr /* 981 1.241 darrenr * Not all errors indicate a failed block but those that do, 982 1.241 darrenr * put the block on the bad-block list for the device. Only 983 1.241 darrenr * do this for reads because the drive should do it for writes, 984 1.241 darrenr * itself, according to Manuel. 985 1.241 darrenr */ 986 1.242 dogcow if ((bp->b_flags & B_READ) && 987 1.430 jdolecek ((wd->drvp->ata_vers >= 4 && xfer->c_bio.r_error & 64) || 988 1.430 jdolecek (wd->drvp->ata_vers < 4 && xfer->c_bio.r_error & 192))) { 989 1.241 darrenr struct disk_badsectors *dbs; 990 1.241 darrenr 991 1.442 jdolecek dbs = kmem_zalloc(sizeof *dbs, KM_NOSLEEP); 992 1.430 jdolecek if (dbs == NULL) { 993 1.471 jakllsch device_printf(dksc->sc_dev, 994 1.430 jdolecek "failed to add bad block to list\n"); 995 1.430 jdolecek goto out; 996 1.430 jdolecek } 997 1.430 jdolecek 998 1.241 darrenr dbs->dbs_min = bp->b_rawblkno; 999 1.424 jakllsch dbs->dbs_max = dbs->dbs_min + 1000 1.424 jakllsch (bp->b_bcount /wd->sc_blksize) - 1; 1001 1.241 darrenr microtime(&dbs->dbs_failedat); 1002 1.430 jdolecek 1003 1.430 jdolecek mutex_enter(&wd->sc_lock); 1004 1.241 darrenr SLIST_INSERT_HEAD(&wd->sc_bslist, dbs, dbs_next); 1005 1.243 darrenr wd->sc_bscount++; 1006 1.430 jdolecek mutex_exit(&wd->sc_lock); 1007 1.241 darrenr } 1008 1.430 jdolecek out: 1009 1.292 drochner #endif 1010 1.181 bouyer bp->b_error = EIO; 1011 1.181 bouyer break; 1012 1.181 bouyer case NOERROR: 1013 1.430 jdolecek #ifdef WD_CHAOS_MONKEY 1014 1.442 jdolecek /* 1015 1.442 jdolecek * For example Parallels AHCI emulation doesn't actually 1016 1.442 jdolecek * return error for the invalid I/O, so just re-run 1017 1.442 jdolecek * the request and do not panic. 1018 1.442 jdolecek */ 1019 1.442 jdolecek if (__predict_false(xfer->c_flags & C_CHAOS)) { 1020 1.442 jdolecek xfer->c_bio.error = REQUEUE; 1021 1.442 jdolecek errmsg = "chaos noerror"; 1022 1.442 jdolecek goto retry2; 1023 1.442 jdolecek } 1024 1.430 jdolecek #endif 1025 1.442 jdolecek 1026 1.442 jdolecek noerror: if ((xfer->c_bio.flags & ATA_CORR) || xfer->c_retries > 0) 1027 1.442 jdolecek device_printf(dksc->sc_dev, 1028 1.442 jdolecek "soft error (corrected) xfer %"PRIxPTR"\n", 1029 1.442 jdolecek (intptr_t)xfer & PAGE_MASK); 1030 1.197 enami break; 1031 1.197 enami case ERR_NODEV: 1032 1.197 enami bp->b_error = EIO; 1033 1.197 enami break; 1034 1.64 mycroft } 1035 1.393 bouyer if (__predict_false(bp->b_error != 0) && bp->b_resid == 0) { 1036 1.393 bouyer /* 1037 1.393 bouyer * the disk or controller sometimes report a complete 1038 1.393 bouyer * xfer, when there has been an error. This is wrong, 1039 1.453 msaitoh * assume nothing got transferred in this case 1040 1.393 bouyer */ 1041 1.393 bouyer bp->b_resid = bp->b_bcount; 1042 1.393 bouyer } 1043 1.434 mlelstv 1044 1.430 jdolecek ata_free_xfer(wd->drvp->chnl_softc, xfer); 1045 1.434 mlelstv 1046 1.451 mlelstv mutex_enter(&wd->sc_lock); 1047 1.446 mlelstv wd->inflight--; 1048 1.451 mlelstv mutex_exit(&wd->sc_lock); 1049 1.434 mlelstv dk_done(dksc, bp); 1050 1.446 mlelstv dk_start(dksc, NULL); 1051 1.181 bouyer } 1052 1.181 bouyer 1053 1.430 jdolecek static void 1054 1.442 jdolecek wdbioretry(void *v) 1055 1.442 jdolecek { 1056 1.442 jdolecek struct wd_softc *wd = v; 1057 1.442 jdolecek struct ata_xfer *xfer; 1058 1.442 jdolecek 1059 1.442 jdolecek ATADEBUG_PRINT(("%s %s\n", __func__, wd->sc_dksc.sc_xname), 1060 1.442 jdolecek DEBUG_XFERS); 1061 1.442 jdolecek 1062 1.442 jdolecek mutex_enter(&wd->sc_lock); 1063 1.442 jdolecek while ((xfer = SLIST_FIRST(&wd->sc_retry_list))) { 1064 1.442 jdolecek SLIST_REMOVE_HEAD(&wd->sc_retry_list, c_retrychain); 1065 1.442 jdolecek wdstart1(wd, xfer->c_bio.bp, xfer); 1066 1.442 jdolecek } 1067 1.442 jdolecek mutex_exit(&wd->sc_lock); 1068 1.442 jdolecek } 1069 1.442 jdolecek 1070 1.442 jdolecek static void 1071 1.442 jdolecek wdbiorequeue(void *v) 1072 1.181 bouyer { 1073 1.442 jdolecek struct wd_softc *wd = v; 1074 1.442 jdolecek struct ata_xfer *xfer; 1075 1.350 itohy 1076 1.442 jdolecek ATADEBUG_PRINT(("%s %s\n", __func__, wd->sc_dksc.sc_xname), 1077 1.182 bouyer DEBUG_XFERS); 1078 1.430 jdolecek 1079 1.435 mlelstv mutex_enter(&wd->sc_lock); 1080 1.442 jdolecek while ((xfer = SLIST_FIRST(&wd->sc_requeue_list))) { 1081 1.442 jdolecek SLIST_REMOVE_HEAD(&wd->sc_requeue_list, c_retrychain); 1082 1.442 jdolecek wdstart1(wd, xfer->c_bio.bp, xfer); 1083 1.442 jdolecek } 1084 1.435 mlelstv mutex_exit(&wd->sc_lock); 1085 1.141 mycroft } 1086 1.141 mycroft 1087 1.388 jakllsch static void 1088 1.388 jakllsch wdminphys(struct buf *bp) 1089 1.388 jakllsch { 1090 1.424 jakllsch const struct wd_softc * const wd = 1091 1.424 jakllsch device_lookup_private(&wd_cd, WDUNIT(bp->b_dev)); 1092 1.434 mlelstv int maxsectors; 1093 1.430 jdolecek 1094 1.430 jdolecek /* 1095 1.430 jdolecek * The limit is actually 65536 for LBA48 and 256 for non-LBA48, 1096 1.430 jdolecek * but that requires to set the count for the ATA command 1097 1.430 jdolecek * to 0, which is somewhat error prone, so better stay safe. 1098 1.430 jdolecek */ 1099 1.430 jdolecek if (wd->sc_flags & WDF_LBA48) 1100 1.430 jdolecek maxsectors = 65535; 1101 1.430 jdolecek else 1102 1.430 jdolecek maxsectors = 128; 1103 1.430 jdolecek 1104 1.430 jdolecek if (bp->b_bcount > (wd->sc_blksize * maxsectors)) 1105 1.430 jdolecek bp->b_bcount = (wd->sc_blksize * maxsectors); 1106 1.388 jakllsch 1107 1.388 jakllsch minphys(bp); 1108 1.388 jakllsch } 1109 1.388 jakllsch 1110 1.434 mlelstv static void 1111 1.434 mlelstv wd_iosize(device_t dev, int *count) 1112 1.434 mlelstv { 1113 1.434 mlelstv struct buf B; 1114 1.434 mlelstv int bmaj; 1115 1.434 mlelstv 1116 1.434 mlelstv bmaj = bdevsw_lookup_major(&wd_bdevsw); 1117 1.434 mlelstv B.b_dev = MAKEWDDEV(bmaj,device_unit(dev),RAW_PART); 1118 1.434 mlelstv B.b_bcount = *count; 1119 1.434 mlelstv 1120 1.434 mlelstv wdminphys(&B); 1121 1.434 mlelstv 1122 1.434 mlelstv *count = B.b_bcount; 1123 1.434 mlelstv } 1124 1.434 mlelstv 1125 1.434 mlelstv static int 1126 1.335 christos wdread(dev_t dev, struct uio *uio, int flags) 1127 1.141 mycroft { 1128 1.141 mycroft 1129 1.289 thorpej ATADEBUG_PRINT(("wdread\n"), DEBUG_XFERS); 1130 1.388 jakllsch return (physio(wdstrategy, NULL, dev, B_READ, wdminphys, uio)); 1131 1.141 mycroft } 1132 1.141 mycroft 1133 1.434 mlelstv static int 1134 1.335 christos wdwrite(dev_t dev, struct uio *uio, int flags) 1135 1.141 mycroft { 1136 1.141 mycroft 1137 1.289 thorpej ATADEBUG_PRINT(("wdwrite\n"), DEBUG_XFERS); 1138 1.388 jakllsch return (physio(wdstrategy, NULL, dev, B_WRITE, wdminphys, uio)); 1139 1.64 mycroft } 1140 1.64 mycroft 1141 1.434 mlelstv static int 1142 1.335 christos wdopen(dev_t dev, int flag, int fmt, struct lwp *l) 1143 1.1 cgd { 1144 1.135 mycroft struct wd_softc *wd; 1145 1.434 mlelstv struct dk_softc *dksc; 1146 1.434 mlelstv int unit, part, error; 1147 1.163 bouyer 1148 1.289 thorpej ATADEBUG_PRINT(("wdopen\n"), DEBUG_FUNCS); 1149 1.434 mlelstv unit = WDUNIT(dev); 1150 1.434 mlelstv wd = device_lookup_private(&wd_cd, unit); 1151 1.158 pk if (wd == NULL) 1152 1.208 thorpej return (ENXIO); 1153 1.434 mlelstv dksc = &wd->sc_dksc; 1154 1.187 thorpej 1155 1.434 mlelstv if (! device_is_active(dksc->sc_dev)) 1156 1.283 bouyer return (ENODEV); 1157 1.283 bouyer 1158 1.434 mlelstv part = WDPART(dev); 1159 1.434 mlelstv 1160 1.400 bouyer if (wd->sc_capacity == 0) 1161 1.400 bouyer return (ENODEV); 1162 1.400 bouyer 1163 1.294 thorpej /* 1164 1.434 mlelstv * If any partition is open, but the disk has been invalidated, 1165 1.434 mlelstv * disallow further opens. 1166 1.294 thorpej */ 1167 1.435 mlelstv if ((wd->sc_flags & (WDF_OPEN | WDF_LOADED)) == WDF_OPEN) { 1168 1.434 mlelstv if (part != RAW_PART || fmt != S_IFCHR) 1169 1.434 mlelstv return EIO; 1170 1.294 thorpej } 1171 1.294 thorpej 1172 1.434 mlelstv error = dk_open(dksc, dev, flag, fmt, l); 1173 1.434 mlelstv 1174 1.434 mlelstv return error; 1175 1.434 mlelstv } 1176 1.3 deraadt 1177 1.434 mlelstv /* 1178 1.434 mlelstv * Serialized by caller 1179 1.434 mlelstv */ 1180 1.434 mlelstv static int 1181 1.434 mlelstv wd_firstopen(device_t self, dev_t dev, int flag, int fmt) 1182 1.434 mlelstv { 1183 1.434 mlelstv struct wd_softc *wd = device_private(self); 1184 1.434 mlelstv struct dk_softc *dksc = &wd->sc_dksc; 1185 1.434 mlelstv int error; 1186 1.108 mycroft 1187 1.434 mlelstv error = wd->atabus->ata_addref(wd->drvp); 1188 1.434 mlelstv if (error) 1189 1.434 mlelstv return error; 1190 1.108 mycroft 1191 1.434 mlelstv if ((wd->sc_flags & WDF_LOADED) == 0) { 1192 1.434 mlelstv int param_error; 1193 1.259 dsl 1194 1.434 mlelstv /* Load the physical device parameters. */ 1195 1.462 jdolecek param_error = wd_get_params(wd, &wd->sc_params); 1196 1.434 mlelstv if (param_error != 0) { 1197 1.434 mlelstv aprint_error_dev(dksc->sc_dev, "IDENTIFY failed\n"); 1198 1.434 mlelstv error = EIO; 1199 1.434 mlelstv goto bad; 1200 1.434 mlelstv } 1201 1.434 mlelstv wd_set_geometry(wd); 1202 1.434 mlelstv wd->sc_flags |= WDF_LOADED; 1203 1.3 deraadt } 1204 1.60 mycroft 1205 1.435 mlelstv wd->sc_flags |= WDF_OPEN; 1206 1.37 mycroft return 0; 1207 1.93 mycroft 1208 1.434 mlelstv bad: 1209 1.434 mlelstv wd->atabus->ata_delref(wd->drvp); 1210 1.93 mycroft return error; 1211 1.1 cgd } 1212 1.1 cgd 1213 1.425 jakllsch /* 1214 1.374 dyoung * Caller must hold wd->sc_dk.dk_openlock. 1215 1.374 dyoung */ 1216 1.376 dyoung static int 1217 1.434 mlelstv wd_lastclose(device_t self) 1218 1.374 dyoung { 1219 1.376 dyoung struct wd_softc *wd = device_private(self); 1220 1.376 dyoung 1221 1.441 jdolecek KASSERTMSG(bufq_peek(wd->sc_dksc.sc_bufq) == NULL, "bufq not empty"); 1222 1.441 jdolecek 1223 1.449 bouyer if (wd->sc_flags & WDF_DIRTY) 1224 1.464 christos wd_flushcache(wd, AT_WAIT); 1225 1.374 dyoung 1226 1.374 dyoung wd->atabus->ata_delref(wd->drvp); 1227 1.435 mlelstv wd->sc_flags &= ~WDF_OPEN; 1228 1.376 dyoung 1229 1.376 dyoung return 0; 1230 1.374 dyoung } 1231 1.374 dyoung 1232 1.434 mlelstv static int 1233 1.335 christos wdclose(dev_t dev, int flag, int fmt, struct lwp *l) 1234 1.135 mycroft { 1235 1.434 mlelstv struct wd_softc *wd; 1236 1.434 mlelstv struct dk_softc *dksc; 1237 1.434 mlelstv int unit; 1238 1.259 dsl 1239 1.434 mlelstv unit = WDUNIT(dev); 1240 1.434 mlelstv wd = device_lookup_private(&wd_cd, unit); 1241 1.434 mlelstv dksc = &wd->sc_dksc; 1242 1.294 thorpej 1243 1.434 mlelstv return dk_close(dksc, dev, flag, fmt, l); 1244 1.108 mycroft } 1245 1.108 mycroft 1246 1.217 bouyer void 1247 1.430 jdolecek wdperror(const struct wd_softc *wd, struct ata_xfer *xfer) 1248 1.217 bouyer { 1249 1.221 yamt static const char *const errstr0_3[] = {"address mark not found", 1250 1.217 bouyer "track 0 not found", "aborted command", "media change requested", 1251 1.217 bouyer "id not found", "media changed", "uncorrectable data error", 1252 1.217 bouyer "bad block detected"}; 1253 1.221 yamt static const char *const errstr4_5[] = { 1254 1.221 yamt "obsolete (address mark not found)", 1255 1.217 bouyer "no media/write protected", "aborted command", 1256 1.217 bouyer "media change requested", "id not found", "media changed", 1257 1.217 bouyer "uncorrectable data error", "interface CRC error"}; 1258 1.259 dsl const char *const *errstr; 1259 1.217 bouyer int i; 1260 1.301 christos const char *sep = ""; 1261 1.217 bouyer 1262 1.434 mlelstv const struct dk_softc *dksc = &wd->sc_dksc; 1263 1.434 mlelstv const char *devname = dksc->sc_xname; 1264 1.221 yamt struct ata_drive_datas *drvp = wd->drvp; 1265 1.430 jdolecek int errno = xfer->c_bio.r_error; 1266 1.221 yamt 1267 1.217 bouyer if (drvp->ata_vers >= 4) 1268 1.217 bouyer errstr = errstr4_5; 1269 1.217 bouyer else 1270 1.217 bouyer errstr = errstr0_3; 1271 1.217 bouyer 1272 1.221 yamt printf("%s: (", devname); 1273 1.221 yamt 1274 1.217 bouyer if (errno == 0) 1275 1.221 yamt printf("error not notified"); 1276 1.217 bouyer 1277 1.217 bouyer for (i = 0; i < 8; i++) { 1278 1.217 bouyer if (errno & (1 << i)) { 1279 1.221 yamt printf("%s%s", sep, errstr[i]); 1280 1.217 bouyer sep = ", "; 1281 1.217 bouyer } 1282 1.217 bouyer } 1283 1.221 yamt printf(")\n"); 1284 1.217 bouyer } 1285 1.217 bouyer 1286 1.1 cgd int 1287 1.434 mlelstv wdioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) 1288 1.1 cgd { 1289 1.360 cube struct wd_softc *wd = 1290 1.363 tsutsui device_lookup_private(&wd_cd, WDUNIT(dev)); 1291 1.434 mlelstv struct dk_softc *dksc = &wd->sc_dksc; 1292 1.163 bouyer 1293 1.289 thorpej ATADEBUG_PRINT(("wdioctl\n"), DEBUG_FUNCS); 1294 1.163 bouyer 1295 1.181 bouyer if ((wd->sc_flags & WDF_LOADED) == 0) 1296 1.108 mycroft return EIO; 1297 1.108 mycroft 1298 1.434 mlelstv switch (cmd) { 1299 1.170 leo #ifdef HAS_BAD144_HANDLING 1300 1.1 cgd case DIOCSBAD: 1301 1.3 deraadt if ((flag & FWRITE) == 0) 1302 1.54 mycroft return EBADF; 1303 1.434 mlelstv dksc->sc_dkdev.dk_cpulabel->bad = *(struct dkbad *)addr; 1304 1.434 mlelstv dksc->sc_dkdev.dk_label->d_flags |= D_BADSECT; 1305 1.64 mycroft bad144intern(wd); 1306 1.54 mycroft return 0; 1307 1.170 leo #endif 1308 1.292 drochner #ifdef WD_SOFTBADSECT 1309 1.466 riastrad case DIOCBSLIST: { 1310 1.413 matt uint32_t count, missing, skip; 1311 1.243 darrenr struct disk_badsecinfo dbsi; 1312 1.466 riastrad struct disk_badsectors *dbs, dbsbuf; 1313 1.241 darrenr size_t available; 1314 1.344 jnemeth uint8_t *laddr; 1315 1.466 riastrad int error; 1316 1.241 darrenr 1317 1.243 darrenr dbsi = *(struct disk_badsecinfo *)addr; 1318 1.243 darrenr missing = wd->sc_bscount; 1319 1.241 darrenr count = 0; 1320 1.243 darrenr available = dbsi.dbsi_bufsize; 1321 1.243 darrenr skip = dbsi.dbsi_skip; 1322 1.344 jnemeth laddr = (uint8_t *)dbsi.dbsi_buffer; 1323 1.243 darrenr 1324 1.243 darrenr /* 1325 1.243 darrenr * We start this loop with the expectation that all of the 1326 1.243 darrenr * entries will be missed and decrement this counter each 1327 1.243 darrenr * time we either skip over one (already copied out) or 1328 1.243 darrenr * we actually copy it back to user space. The structs 1329 1.243 darrenr * holding the bad sector information are copied directly 1330 1.243 darrenr * back to user space whilst the summary is returned via 1331 1.243 darrenr * the struct passed in via the ioctl. 1332 1.243 darrenr */ 1333 1.466 riastrad error = 0; 1334 1.442 jdolecek mutex_enter(&wd->sc_lock); 1335 1.466 riastrad wd->sc_bslist_inuse++; 1336 1.241 darrenr SLIST_FOREACH(dbs, &wd->sc_bslist, dbs_next) { 1337 1.243 darrenr if (skip > 0) { 1338 1.243 darrenr missing--; 1339 1.243 darrenr skip--; 1340 1.243 darrenr continue; 1341 1.243 darrenr } 1342 1.243 darrenr if (available < sizeof(*dbs)) 1343 1.241 darrenr break; 1344 1.243 darrenr available -= sizeof(*dbs); 1345 1.466 riastrad memset(&dbsbuf, 0, sizeof(dbsbuf)); 1346 1.466 riastrad dbsbuf.dbs_min = dbs->dbs_min; 1347 1.466 riastrad dbsbuf.dbs_max = dbs->dbs_max; 1348 1.466 riastrad dbsbuf.dbs_failedat = dbs->dbs_failedat; 1349 1.466 riastrad mutex_exit(&wd->sc_lock); 1350 1.466 riastrad error = copyout(&dbsbuf, laddr, sizeof(dbsbuf)); 1351 1.466 riastrad mutex_enter(&wd->sc_lock); 1352 1.466 riastrad if (error) 1353 1.466 riastrad break; 1354 1.241 darrenr laddr += sizeof(*dbs); 1355 1.243 darrenr missing--; 1356 1.241 darrenr count++; 1357 1.241 darrenr } 1358 1.466 riastrad if (--wd->sc_bslist_inuse == 0) 1359 1.466 riastrad cv_broadcast(&wd->sc_bslist_cv); 1360 1.442 jdolecek mutex_exit(&wd->sc_lock); 1361 1.243 darrenr dbsi.dbsi_left = missing; 1362 1.243 darrenr dbsi.dbsi_copied = count; 1363 1.243 darrenr *(struct disk_badsecinfo *)addr = dbsi; 1364 1.466 riastrad 1365 1.466 riastrad /* 1366 1.466 riastrad * If we copied anything out, ignore error and return 1367 1.466 riastrad * success -- can't back it out. 1368 1.466 riastrad */ 1369 1.466 riastrad return count ? 0 : error; 1370 1.241 darrenr } 1371 1.241 darrenr 1372 1.466 riastrad case DIOCBSFLUSH: { 1373 1.466 riastrad int error; 1374 1.466 riastrad 1375 1.241 darrenr /* Clean out the bad sector list */ 1376 1.442 jdolecek mutex_enter(&wd->sc_lock); 1377 1.466 riastrad while (wd->sc_bslist_inuse) { 1378 1.466 riastrad error = cv_wait_sig(&wd->sc_bslist_cv, &wd->sc_lock); 1379 1.466 riastrad if (error) { 1380 1.466 riastrad mutex_exit(&wd->sc_lock); 1381 1.466 riastrad return error; 1382 1.466 riastrad } 1383 1.466 riastrad } 1384 1.241 darrenr while (!SLIST_EMPTY(&wd->sc_bslist)) { 1385 1.442 jdolecek struct disk_badsectors *dbs = 1386 1.442 jdolecek SLIST_FIRST(&wd->sc_bslist); 1387 1.241 darrenr SLIST_REMOVE_HEAD(&wd->sc_bslist, dbs_next); 1388 1.466 riastrad mutex_exit(&wd->sc_lock); 1389 1.442 jdolecek kmem_free(dbs, sizeof(*dbs)); 1390 1.466 riastrad mutex_enter(&wd->sc_lock); 1391 1.241 darrenr } 1392 1.442 jdolecek mutex_exit(&wd->sc_lock); 1393 1.243 darrenr wd->sc_bscount = 0; 1394 1.241 darrenr return 0; 1395 1.466 riastrad } 1396 1.292 drochner #endif 1397 1.259 dsl 1398 1.1 cgd #ifdef notyet 1399 1.1 cgd case DIOCWFORMAT: 1400 1.1 cgd if ((flag & FWRITE) == 0) 1401 1.54 mycroft return EBADF; 1402 1.181 bouyer { 1403 1.54 mycroft register struct format_op *fop; 1404 1.54 mycroft struct iovec aiov; 1405 1.54 mycroft struct uio auio; 1406 1.434 mlelstv int error1; 1407 1.259 dsl 1408 1.54 mycroft fop = (struct format_op *)addr; 1409 1.54 mycroft aiov.iov_base = fop->df_buf; 1410 1.54 mycroft aiov.iov_len = fop->df_count; 1411 1.54 mycroft auio.uio_iov = &aiov; 1412 1.54 mycroft auio.uio_iovcnt = 1; 1413 1.54 mycroft auio.uio_resid = fop->df_count; 1414 1.54 mycroft auio.uio_offset = 1415 1.181 bouyer fop->df_startblk * wd->sc_dk.dk_label->d_secsize; 1416 1.320 yamt auio.uio_vmspace = l->l_proc->p_vmspace; 1417 1.434 mlelstv error1 = physio(wdformat, NULL, dev, B_WRITE, wdminphys, 1418 1.64 mycroft &auio); 1419 1.54 mycroft fop->df_count -= auio.uio_resid; 1420 1.64 mycroft fop->df_reg[0] = wdc->sc_status; 1421 1.64 mycroft fop->df_reg[1] = wdc->sc_error; 1422 1.434 mlelstv return error1; 1423 1.181 bouyer } 1424 1.1 cgd #endif 1425 1.248 bouyer case DIOCGCACHE: 1426 1.248 bouyer return wd_getcache(wd, (int *)addr); 1427 1.248 bouyer 1428 1.248 bouyer case DIOCSCACHE: 1429 1.248 bouyer return wd_setcache(wd, *(int *)addr); 1430 1.185 kenh 1431 1.276 bouyer case DIOCCACHESYNC: 1432 1.464 christos return wd_flushcache(wd, AT_WAIT); 1433 1.276 bouyer 1434 1.186 kenh case ATAIOCCOMMAND: 1435 1.185 kenh /* 1436 1.185 kenh * Make sure this command is (relatively) safe first 1437 1.185 kenh */ 1438 1.186 kenh if ((((atareq_t *) addr)->flags & ATACMD_READ) == 0 && 1439 1.185 kenh (flag & FWRITE) == 0) 1440 1.185 kenh return (EBADF); 1441 1.185 kenh { 1442 1.185 kenh struct wd_ioctl *wi; 1443 1.186 kenh atareq_t *atareq = (atareq_t *) addr; 1444 1.301 christos int error1; 1445 1.185 kenh 1446 1.430 jdolecek wi = wi_get(wd); 1447 1.186 kenh wi->wi_atareq = *atareq; 1448 1.185 kenh 1449 1.186 kenh if (atareq->datalen && atareq->flags & 1450 1.186 kenh (ATACMD_READ | ATACMD_WRITE)) { 1451 1.339 dsl void *tbuf; 1452 1.339 dsl if (atareq->datalen < DEV_BSIZE 1453 1.339 dsl && atareq->command == WDCC_IDENTIFY) { 1454 1.442 jdolecek tbuf = kmem_zalloc(DEV_BSIZE, KM_SLEEP); 1455 1.339 dsl wi->wi_iov.iov_base = tbuf; 1456 1.339 dsl wi->wi_iov.iov_len = DEV_BSIZE; 1457 1.339 dsl UIO_SETUP_SYSSPACE(&wi->wi_uio); 1458 1.339 dsl } else { 1459 1.339 dsl tbuf = NULL; 1460 1.339 dsl wi->wi_iov.iov_base = atareq->databuf; 1461 1.339 dsl wi->wi_iov.iov_len = atareq->datalen; 1462 1.339 dsl wi->wi_uio.uio_vmspace = l->l_proc->p_vmspace; 1463 1.339 dsl } 1464 1.185 kenh wi->wi_uio.uio_iov = &wi->wi_iov; 1465 1.185 kenh wi->wi_uio.uio_iovcnt = 1; 1466 1.186 kenh wi->wi_uio.uio_resid = atareq->datalen; 1467 1.185 kenh wi->wi_uio.uio_offset = 0; 1468 1.185 kenh wi->wi_uio.uio_rw = 1469 1.186 kenh (atareq->flags & ATACMD_READ) ? B_READ : B_WRITE; 1470 1.301 christos error1 = physio(wdioctlstrategy, &wi->wi_bp, dev, 1471 1.186 kenh (atareq->flags & ATACMD_READ) ? B_READ : B_WRITE, 1472 1.388 jakllsch wdminphys, &wi->wi_uio); 1473 1.339 dsl if (tbuf != NULL && error1 == 0) { 1474 1.339 dsl error1 = copyout(tbuf, atareq->databuf, 1475 1.339 dsl atareq->datalen); 1476 1.442 jdolecek kmem_free(tbuf, DEV_BSIZE); 1477 1.339 dsl } 1478 1.185 kenh } else { 1479 1.185 kenh /* No need to call physio if we don't have any 1480 1.185 kenh user data */ 1481 1.185 kenh wi->wi_bp.b_flags = 0; 1482 1.185 kenh wi->wi_bp.b_data = 0; 1483 1.185 kenh wi->wi_bp.b_bcount = 0; 1484 1.430 jdolecek wi->wi_bp.b_dev = dev; 1485 1.314 christos wi->wi_bp.b_proc = l->l_proc; 1486 1.185 kenh wdioctlstrategy(&wi->wi_bp); 1487 1.301 christos error1 = wi->wi_bp.b_error; 1488 1.185 kenh } 1489 1.186 kenh *atareq = wi->wi_atareq; 1490 1.185 kenh wi_free(wi); 1491 1.301 christos return(error1); 1492 1.185 kenh } 1493 1.185 kenh 1494 1.1 cgd default: 1495 1.434 mlelstv return dk_ioctl(dksc, dev, cmd, addr, flag, l); 1496 1.1 cgd } 1497 1.54 mycroft 1498 1.54 mycroft #ifdef DIAGNOSTIC 1499 1.54 mycroft panic("wdioctl: impossible"); 1500 1.54 mycroft #endif 1501 1.1 cgd } 1502 1.1 cgd 1503 1.410 dholland static int 1504 1.434 mlelstv wd_discard(device_t dev, off_t pos, off_t len) 1505 1.410 dholland { 1506 1.434 mlelstv struct wd_softc *wd = device_private(dev); 1507 1.410 dholland daddr_t bno; 1508 1.410 dholland long size, done; 1509 1.410 dholland long maxatonce, amount; 1510 1.410 dholland int result; 1511 1.410 dholland 1512 1.410 dholland if (!(wd->sc_params.atap_ata_major & WDC_VER_ATA7) 1513 1.410 dholland || !(wd->sc_params.support_dsm & ATA_SUPPORT_DSM_TRIM)) { 1514 1.410 dholland /* not supported; ignore request */ 1515 1.410 dholland ATADEBUG_PRINT(("wddiscard (unsupported)\n"), DEBUG_FUNCS); 1516 1.410 dholland return 0; 1517 1.410 dholland } 1518 1.410 dholland maxatonce = 0xffff; /*wd->sc_params.max_dsm_blocks*/ 1519 1.410 dholland 1520 1.410 dholland ATADEBUG_PRINT(("wddiscard\n"), DEBUG_FUNCS); 1521 1.410 dholland 1522 1.410 dholland if ((wd->sc_flags & WDF_LOADED) == 0) 1523 1.410 dholland return EIO; 1524 1.410 dholland 1525 1.410 dholland /* round the start up and the end down */ 1526 1.424 jakllsch bno = (pos + wd->sc_blksize - 1) / wd->sc_blksize; 1527 1.424 jakllsch size = ((pos + len) / wd->sc_blksize) - bno; 1528 1.410 dholland 1529 1.410 dholland done = 0; 1530 1.410 dholland while (done < size) { 1531 1.410 dholland amount = size - done; 1532 1.410 dholland if (amount > maxatonce) { 1533 1.410 dholland amount = maxatonce; 1534 1.410 dholland } 1535 1.434 mlelstv result = wd_trim(wd, bno + done, amount); 1536 1.410 dholland if (result) { 1537 1.410 dholland return result; 1538 1.410 dholland } 1539 1.410 dholland done += amount; 1540 1.410 dholland } 1541 1.410 dholland return 0; 1542 1.410 dholland } 1543 1.410 dholland 1544 1.434 mlelstv static int 1545 1.434 mlelstv wddiscard(dev_t dev, off_t pos, off_t len) 1546 1.434 mlelstv { 1547 1.434 mlelstv struct wd_softc *wd; 1548 1.434 mlelstv struct dk_softc *dksc; 1549 1.434 mlelstv int unit; 1550 1.434 mlelstv 1551 1.434 mlelstv unit = WDUNIT(dev); 1552 1.434 mlelstv wd = device_lookup_private(&wd_cd, unit); 1553 1.434 mlelstv dksc = &wd->sc_dksc; 1554 1.434 mlelstv 1555 1.434 mlelstv return dk_discard(dksc, dev, pos, len); 1556 1.434 mlelstv } 1557 1.434 mlelstv 1558 1.44 mycroft #ifdef B_FORMAT 1559 1.1 cgd int 1560 1.1 cgd wdformat(struct buf *bp) 1561 1.1 cgd { 1562 1.44 mycroft 1563 1.1 cgd bp->b_flags |= B_FORMAT; 1564 1.37 mycroft return wdstrategy(bp); 1565 1.1 cgd } 1566 1.1 cgd #endif 1567 1.1 cgd 1568 1.1 cgd int 1569 1.259 dsl wdsize(dev_t dev) 1570 1.1 cgd { 1571 1.64 mycroft struct wd_softc *wd; 1572 1.434 mlelstv struct dk_softc *dksc; 1573 1.434 mlelstv int unit; 1574 1.163 bouyer 1575 1.289 thorpej ATADEBUG_PRINT(("wdsize\n"), DEBUG_FUNCS); 1576 1.163 bouyer 1577 1.434 mlelstv unit = WDUNIT(dev); 1578 1.434 mlelstv wd = device_lookup_private(&wd_cd, unit); 1579 1.158 pk if (wd == NULL) 1580 1.158 pk return (-1); 1581 1.434 mlelstv dksc = &wd->sc_dksc; 1582 1.158 pk 1583 1.434 mlelstv if (!device_is_active(dksc->sc_dev)) 1584 1.434 mlelstv return (-1); 1585 1.158 pk 1586 1.434 mlelstv return dk_size(dksc, dev); 1587 1.1 cgd } 1588 1.1 cgd 1589 1.64 mycroft /* 1590 1.64 mycroft * Dump core after a system crash. 1591 1.64 mycroft */ 1592 1.434 mlelstv static int 1593 1.337 christos wddump(dev_t dev, daddr_t blkno, void *va, size_t size) 1594 1.140 cgd { 1595 1.434 mlelstv struct wd_softc *wd; 1596 1.434 mlelstv struct dk_softc *dksc; 1597 1.434 mlelstv int unit; 1598 1.140 cgd 1599 1.140 cgd /* Check if recursive dump; if so, punt. */ 1600 1.116 mycroft if (wddoingadump) 1601 1.116 mycroft return EFAULT; 1602 1.142 mycroft wddoingadump = 1; 1603 1.140 cgd 1604 1.434 mlelstv unit = WDUNIT(dev); 1605 1.434 mlelstv wd = device_lookup_private(&wd_cd, unit); 1606 1.208 thorpej if (wd == NULL) 1607 1.208 thorpej return (ENXIO); 1608 1.434 mlelstv dksc = &wd->sc_dksc; 1609 1.60 mycroft 1610 1.458 riastrad return dk_dump(dksc, dev, blkno, va, size, 0); 1611 1.434 mlelstv } 1612 1.140 cgd 1613 1.434 mlelstv static int 1614 1.434 mlelstv wd_dumpblocks(device_t dev, void *va, daddr_t blkno, int nblk) 1615 1.434 mlelstv { 1616 1.434 mlelstv struct wd_softc *wd = device_private(dev); 1617 1.434 mlelstv struct dk_softc *dksc = &wd->sc_dksc; 1618 1.434 mlelstv struct disk_geom *dg = &dksc->sc_dkdev.dk_geom; 1619 1.442 jdolecek struct ata_xfer *xfer = &wd->dump_xfer; 1620 1.434 mlelstv int err; 1621 1.60 mycroft 1622 1.140 cgd /* Recalibrate, if first dump transfer. */ 1623 1.140 cgd if (wddumprecalibrated == 0) { 1624 1.140 cgd wddumprecalibrated = 1; 1625 1.442 jdolecek ata_channel_lock(wd->drvp->chnl_softc); 1626 1.442 jdolecek /* This will directly execute the reset due to AT_POLL */ 1627 1.442 jdolecek ata_thread_run(wd->drvp->chnl_softc, AT_POLL, 1628 1.442 jdolecek ATACH_TH_DRIVE_RESET, wd->drvp->drive); 1629 1.442 jdolecek 1630 1.205 bouyer wd->drvp->state = RESET; 1631 1.442 jdolecek ata_channel_unlock(wd->drvp->chnl_softc); 1632 1.63 mycroft } 1633 1.259 dsl 1634 1.442 jdolecek memset(xfer, 0, sizeof(*xfer)); 1635 1.442 jdolecek xfer->c_flags |= C_PRIVATE_ALLOC | C_SKIP_QUEUE; 1636 1.430 jdolecek 1637 1.430 jdolecek xfer->c_bio.blkno = blkno; 1638 1.430 jdolecek xfer->c_bio.flags = ATA_POLL; 1639 1.308 bouyer if (wd->sc_flags & WDF_LBA48 && 1640 1.434 mlelstv (xfer->c_bio.blkno + nblk) > wd->sc_capacity28) 1641 1.430 jdolecek xfer->c_bio.flags |= ATA_LBA48; 1642 1.308 bouyer if (wd->sc_flags & WDF_LBA) 1643 1.430 jdolecek xfer->c_bio.flags |= ATA_LBA; 1644 1.434 mlelstv xfer->c_bio.bcount = nblk * dg->dg_secsize; 1645 1.430 jdolecek xfer->c_bio.databuf = va; 1646 1.181 bouyer #ifndef WD_DUMP_NOT_TRUSTED 1647 1.462 jdolecek /* This will poll until the bio is complete */ 1648 1.462 jdolecek wd->atabus->ata_bio(wd->drvp, xfer); 1649 1.462 jdolecek 1650 1.430 jdolecek switch(err = xfer->c_bio.error) { 1651 1.308 bouyer case TIMEOUT: 1652 1.308 bouyer printf("wddump: device timed out"); 1653 1.308 bouyer err = EIO; 1654 1.308 bouyer break; 1655 1.308 bouyer case ERR_DF: 1656 1.308 bouyer printf("wddump: drive fault"); 1657 1.308 bouyer err = EIO; 1658 1.308 bouyer break; 1659 1.308 bouyer case ERR_DMA: 1660 1.308 bouyer printf("wddump: DMA error"); 1661 1.308 bouyer err = EIO; 1662 1.308 bouyer break; 1663 1.308 bouyer case ERROR: 1664 1.308 bouyer printf("wddump: "); 1665 1.430 jdolecek wdperror(wd, xfer); 1666 1.308 bouyer err = EIO; 1667 1.308 bouyer break; 1668 1.308 bouyer case NOERROR: 1669 1.308 bouyer err = 0; 1670 1.308 bouyer break; 1671 1.308 bouyer default: 1672 1.442 jdolecek panic("wddump: unknown error type %x", err); 1673 1.308 bouyer } 1674 1.430 jdolecek 1675 1.308 bouyer if (err != 0) { 1676 1.308 bouyer printf("\n"); 1677 1.308 bouyer return err; 1678 1.308 bouyer } 1679 1.140 cgd #else /* WD_DUMP_NOT_TRUSTED */ 1680 1.308 bouyer /* Let's just talk about this first... */ 1681 1.308 bouyer printf("wd%d: dump addr 0x%x, cylin %d, head %d, sector %d\n", 1682 1.308 bouyer unit, va, cylin, head, sector); 1683 1.308 bouyer delay(500 * 1000); /* half a second */ 1684 1.140 cgd #endif 1685 1.1 cgd 1686 1.140 cgd wddoingadump = 0; 1687 1.140 cgd return 0; 1688 1.140 cgd } 1689 1.3 deraadt 1690 1.170 leo #ifdef HAS_BAD144_HANDLING 1691 1.3 deraadt /* 1692 1.3 deraadt * Internalize the bad sector table. 1693 1.3 deraadt */ 1694 1.3 deraadt void 1695 1.259 dsl bad144intern(struct wd_softc *wd) 1696 1.3 deraadt { 1697 1.434 mlelstv struct dk_softc *dksc = &wd->sc_dksc; 1698 1.434 mlelstv struct dkbad *bt = &dksc->sc_dkdev.dk_cpulabel->bad; 1699 1.434 mlelstv struct disklabel *lp = dksc->sc_dkdev.dk_label; 1700 1.98 mycroft int i = 0; 1701 1.55 mycroft 1702 1.289 thorpej ATADEBUG_PRINT(("bad144intern\n"), DEBUG_XFERS); 1703 1.163 bouyer 1704 1.170 leo for (; i < NBT_BAD; i++) { 1705 1.98 mycroft if (bt->bt_bad[i].bt_cyl == 0xffff) 1706 1.55 mycroft break; 1707 1.430 jdolecek wd->drvp->badsect[i] = 1708 1.98 mycroft bt->bt_bad[i].bt_cyl * lp->d_secpercyl + 1709 1.98 mycroft (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors + 1710 1.98 mycroft (bt->bt_bad[i].bt_trksec & 0xff); 1711 1.3 deraadt } 1712 1.170 leo for (; i < NBT_BAD+1; i++) 1713 1.430 jdolecek wd->drvp->badsect[i] = -1; 1714 1.64 mycroft } 1715 1.170 leo #endif 1716 1.64 mycroft 1717 1.330 thorpej static void 1718 1.434 mlelstv wd_set_geometry(struct wd_softc *wd) 1719 1.330 thorpej { 1720 1.434 mlelstv struct dk_softc *dksc = &wd->sc_dksc; 1721 1.434 mlelstv struct disk_geom *dg = &dksc->sc_dkdev.dk_geom; 1722 1.330 thorpej 1723 1.403 christos memset(dg, 0, sizeof(*dg)); 1724 1.330 thorpej 1725 1.403 christos dg->dg_secperunit = wd->sc_capacity; 1726 1.424 jakllsch dg->dg_secsize = wd->sc_blksize; 1727 1.403 christos dg->dg_nsectors = wd->sc_params.atap_sectors; 1728 1.403 christos dg->dg_ntracks = wd->sc_params.atap_heads; 1729 1.403 christos if ((wd->sc_flags & WDF_LBA) == 0) 1730 1.403 christos dg->dg_ncylinders = wd->sc_params.atap_cylinders; 1731 1.474 jakllsch if ((wd->sc_params.atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID 1732 1.474 jakllsch && ((wd->sc_params.atap_secsz & ATA_SECSZ_LPS) != 0)) { 1733 1.474 jakllsch dg->dg_physsecsize = wd->sc_blksize << (wd->sc_params.atap_secsz & 1734 1.474 jakllsch ATA_SECSZ_LPS_SZMSK); 1735 1.474 jakllsch if ((wd->sc_params.atap_logical_align & ATA_LA_VALID_MASK) == 1736 1.474 jakllsch ATA_LA_VALID) { 1737 1.474 jakllsch dg->dg_alignedsec = (wd->sc_params.atap_logical_align & 1738 1.474 jakllsch ATA_LA_MASK) & ((1u << (wd->sc_params.atap_secsz & 1739 1.474 jakllsch ATA_SECSZ_LPS_SZMSK)) - 1); 1740 1.474 jakllsch } 1741 1.474 jakllsch } 1742 1.403 christos 1743 1.445 mlelstv disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, wd->sc_typename); 1744 1.330 thorpej } 1745 1.330 thorpej 1746 1.181 bouyer int 1747 1.462 jdolecek wd_get_params(struct wd_softc *wd, struct ataparams *params) 1748 1.63 mycroft { 1749 1.447 bouyer int retry = 0; 1750 1.452 mlelstv struct ata_channel *chp = wd->drvp->chnl_softc; 1751 1.462 jdolecek const int flags = AT_WAIT; 1752 1.350 itohy 1753 1.447 bouyer again: 1754 1.217 bouyer switch (wd->atabus->ata_get_params(wd->drvp, flags, params)) { 1755 1.181 bouyer case CMD_AGAIN: 1756 1.181 bouyer return 1; 1757 1.181 bouyer case CMD_ERR: 1758 1.447 bouyer if (retry == 0) { 1759 1.447 bouyer retry++; 1760 1.452 mlelstv ata_channel_lock(chp); 1761 1.448 bouyer (*wd->atabus->ata_reset_drive)(wd->drvp, flags, NULL); 1762 1.452 mlelstv ata_channel_unlock(chp); 1763 1.447 bouyer goto again; 1764 1.447 bouyer } 1765 1.447 bouyer 1766 1.400 bouyer if (wd->drvp->drive_type != ATA_DRIVET_OLD) 1767 1.400 bouyer return 1; 1768 1.181 bouyer /* 1769 1.181 bouyer * We `know' there's a drive here; just assume it's old. 1770 1.181 bouyer * This geometry is only used to read the MBR and print a 1771 1.181 bouyer * (false) attach message. 1772 1.181 bouyer */ 1773 1.181 bouyer strncpy(params->atap_model, "ST506", 1774 1.181 bouyer sizeof params->atap_model); 1775 1.181 bouyer params->atap_config = ATA_CFG_FIXED; 1776 1.181 bouyer params->atap_cylinders = 1024; 1777 1.181 bouyer params->atap_heads = 8; 1778 1.181 bouyer params->atap_sectors = 17; 1779 1.181 bouyer params->atap_multi = 1; 1780 1.181 bouyer params->atap_capabilities1 = params->atap_capabilities2 = 0; 1781 1.190 bouyer wd->drvp->ata_vers = -1; /* Mark it as pre-ATA */ 1782 1.330 thorpej /* FALLTHROUGH */ 1783 1.181 bouyer case CMD_OK: 1784 1.181 bouyer return 0; 1785 1.181 bouyer default: 1786 1.181 bouyer panic("wd_get_params: bad return code from ata_get_params"); 1787 1.181 bouyer /* NOTREACHED */ 1788 1.181 bouyer } 1789 1.248 bouyer } 1790 1.248 bouyer 1791 1.248 bouyer int 1792 1.259 dsl wd_getcache(struct wd_softc *wd, int *bitsp) 1793 1.248 bouyer { 1794 1.248 bouyer struct ataparams params; 1795 1.248 bouyer 1796 1.462 jdolecek if (wd_get_params(wd, ¶ms) != 0) 1797 1.248 bouyer return EIO; 1798 1.248 bouyer if (params.atap_cmd_set1 == 0x0000 || 1799 1.248 bouyer params.atap_cmd_set1 == 0xffff || 1800 1.248 bouyer (params.atap_cmd_set1 & WDC_CMD1_CACHE) == 0) { 1801 1.248 bouyer *bitsp = 0; 1802 1.248 bouyer return 0; 1803 1.248 bouyer } 1804 1.248 bouyer *bitsp = DKCACHE_WCHANGE | DKCACHE_READ; 1805 1.248 bouyer if (params.atap_cmd1_en & WDC_CMD1_CACHE) 1806 1.248 bouyer *bitsp |= DKCACHE_WRITE; 1807 1.248 bouyer 1808 1.430 jdolecek if (WD_USE_NCQ(wd) || (wd->drvp->drive_flags & ATA_DRIVE_WFUA)) 1809 1.430 jdolecek *bitsp |= DKCACHE_FUA; 1810 1.430 jdolecek 1811 1.248 bouyer return 0; 1812 1.248 bouyer } 1813 1.248 bouyer 1814 1.464 christos 1815 1.464 christos static int 1816 1.464 christos wd_check_error(const struct dk_softc *dksc, const struct ata_xfer *xfer, 1817 1.464 christos const char *func) 1818 1.464 christos { 1819 1.464 christos static const char at_errbits[] = "\20\10ERROR\11TIMEOU\12DF"; 1820 1.464 christos 1821 1.464 christos int flags = xfer->c_ata_c.flags; 1822 1.464 christos 1823 1.464 christos if ((flags & AT_ERROR) != 0 && xfer->c_ata_c.r_error == WDCE_ABRT) { 1824 1.464 christos /* command not supported */ 1825 1.464 christos aprint_debug_dev(dksc->sc_dev, "%s: not supported\n", func); 1826 1.464 christos return ENODEV; 1827 1.464 christos } 1828 1.464 christos if (flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { 1829 1.464 christos char sbuf[sizeof(at_errbits) + 64]; 1830 1.464 christos snprintb(sbuf, sizeof(sbuf), at_errbits, flags); 1831 1.471 jakllsch device_printf(dksc->sc_dev, "%s: status=%s\n", func, sbuf); 1832 1.464 christos return EIO; 1833 1.464 christos } 1834 1.464 christos return 0; 1835 1.464 christos } 1836 1.286 mycroft 1837 1.248 bouyer int 1838 1.259 dsl wd_setcache(struct wd_softc *wd, int bits) 1839 1.248 bouyer { 1840 1.434 mlelstv struct dk_softc *dksc = &wd->sc_dksc; 1841 1.248 bouyer struct ataparams params; 1842 1.430 jdolecek struct ata_xfer *xfer; 1843 1.430 jdolecek int error; 1844 1.248 bouyer 1845 1.462 jdolecek if (wd_get_params(wd, ¶ms) != 0) 1846 1.248 bouyer return EIO; 1847 1.248 bouyer 1848 1.248 bouyer if (params.atap_cmd_set1 == 0x0000 || 1849 1.250 bouyer params.atap_cmd_set1 == 0xffff || 1850 1.248 bouyer (params.atap_cmd_set1 & WDC_CMD1_CACHE) == 0) 1851 1.248 bouyer return EOPNOTSUPP; 1852 1.248 bouyer 1853 1.249 bouyer if ((bits & DKCACHE_READ) == 0 || 1854 1.249 bouyer (bits & DKCACHE_SAVE) != 0) 1855 1.248 bouyer return EOPNOTSUPP; 1856 1.248 bouyer 1857 1.442 jdolecek xfer = ata_get_xfer(wd->drvp->chnl_softc, true); 1858 1.430 jdolecek 1859 1.430 jdolecek xfer->c_ata_c.r_command = SET_FEATURES; 1860 1.430 jdolecek xfer->c_ata_c.r_st_bmask = 0; 1861 1.430 jdolecek xfer->c_ata_c.r_st_pmask = 0; 1862 1.430 jdolecek xfer->c_ata_c.timeout = 30000; /* 30s timeout */ 1863 1.430 jdolecek xfer->c_ata_c.flags = AT_WAIT; 1864 1.248 bouyer if (bits & DKCACHE_WRITE) 1865 1.430 jdolecek xfer->c_ata_c.r_features = WDSF_WRITE_CACHE_EN; 1866 1.248 bouyer else 1867 1.430 jdolecek xfer->c_ata_c.r_features = WDSF_WRITE_CACHE_DS; 1868 1.462 jdolecek 1869 1.462 jdolecek wd->atabus->ata_exec_command(wd->drvp, xfer); 1870 1.462 jdolecek ata_wait_cmd(wd->drvp->chnl_softc, xfer); 1871 1.430 jdolecek 1872 1.464 christos error = wd_check_error(dksc, xfer, __func__); 1873 1.430 jdolecek ata_free_xfer(wd->drvp->chnl_softc, xfer); 1874 1.430 jdolecek return error; 1875 1.286 mycroft } 1876 1.286 mycroft 1877 1.351 jmcneill static int 1878 1.286 mycroft wd_standby(struct wd_softc *wd, int flags) 1879 1.286 mycroft { 1880 1.434 mlelstv struct dk_softc *dksc = &wd->sc_dksc; 1881 1.430 jdolecek struct ata_xfer *xfer; 1882 1.430 jdolecek int error; 1883 1.286 mycroft 1884 1.444 mlelstv aprint_debug_dev(dksc->sc_dev, "standby immediate\n"); 1885 1.442 jdolecek xfer = ata_get_xfer(wd->drvp->chnl_softc, true); 1886 1.430 jdolecek 1887 1.430 jdolecek xfer->c_ata_c.r_command = WDCC_STANDBY_IMMED; 1888 1.430 jdolecek xfer->c_ata_c.r_st_bmask = WDCS_DRDY; 1889 1.430 jdolecek xfer->c_ata_c.r_st_pmask = WDCS_DRDY; 1890 1.430 jdolecek xfer->c_ata_c.flags = flags; 1891 1.430 jdolecek xfer->c_ata_c.timeout = 30000; /* 30s timeout */ 1892 1.462 jdolecek 1893 1.462 jdolecek wd->atabus->ata_exec_command(wd->drvp, xfer); 1894 1.462 jdolecek ata_wait_cmd(wd->drvp->chnl_softc, xfer); 1895 1.462 jdolecek 1896 1.464 christos error = wd_check_error(dksc, xfer, __func__); 1897 1.430 jdolecek ata_free_xfer(wd->drvp->chnl_softc, xfer); 1898 1.430 jdolecek return error; 1899 1.190 bouyer } 1900 1.190 bouyer 1901 1.276 bouyer int 1902 1.464 christos wd_flushcache(struct wd_softc *wd, int flags) 1903 1.190 bouyer { 1904 1.434 mlelstv struct dk_softc *dksc = &wd->sc_dksc; 1905 1.430 jdolecek struct ata_xfer *xfer; 1906 1.430 jdolecek int error; 1907 1.190 bouyer 1908 1.297 bouyer /* 1909 1.297 bouyer * WDCC_FLUSHCACHE is here since ATA-4, but some drives report 1910 1.297 bouyer * only ATA-2 and still support it. 1911 1.297 bouyer */ 1912 1.297 bouyer if (wd->drvp->ata_vers < 4 && 1913 1.297 bouyer ((wd->sc_params.atap_cmd_set2 & WDC_CMD2_FC) == 0 || 1914 1.297 bouyer wd->sc_params.atap_cmd_set2 == 0xffff)) 1915 1.276 bouyer return ENODEV; 1916 1.430 jdolecek 1917 1.442 jdolecek xfer = ata_get_xfer(wd->drvp->chnl_softc, true); 1918 1.430 jdolecek 1919 1.275 bouyer if ((wd->sc_params.atap_cmd2_en & ATA_CMD2_LBA48) != 0 && 1920 1.397 jakllsch (wd->sc_params.atap_cmd2_en & ATA_CMD2_FCE) != 0) { 1921 1.430 jdolecek xfer->c_ata_c.r_command = WDCC_FLUSHCACHE_EXT; 1922 1.397 jakllsch flags |= AT_LBA48; 1923 1.397 jakllsch } else 1924 1.430 jdolecek xfer->c_ata_c.r_command = WDCC_FLUSHCACHE; 1925 1.430 jdolecek xfer->c_ata_c.r_st_bmask = WDCS_DRDY; 1926 1.430 jdolecek xfer->c_ata_c.r_st_pmask = WDCS_DRDY; 1927 1.430 jdolecek xfer->c_ata_c.flags = flags | AT_READREG; 1928 1.430 jdolecek xfer->c_ata_c.timeout = 300000; /* 5m timeout */ 1929 1.462 jdolecek 1930 1.462 jdolecek wd->atabus->ata_exec_command(wd->drvp, xfer); 1931 1.462 jdolecek ata_wait_cmd(wd->drvp->chnl_softc, xfer); 1932 1.462 jdolecek 1933 1.464 christos error = wd_check_error(dksc, xfer, __func__); 1934 1.449 bouyer wd->sc_flags &= ~WDF_DIRTY; 1935 1.430 jdolecek ata_free_xfer(wd->drvp->chnl_softc, xfer); 1936 1.430 jdolecek return error; 1937 1.190 bouyer } 1938 1.190 bouyer 1939 1.443 jdolecek /* 1940 1.443 jdolecek * Execute TRIM command, assumes sleep context. 1941 1.443 jdolecek */ 1942 1.434 mlelstv static int 1943 1.434 mlelstv wd_trim(struct wd_softc *wd, daddr_t bno, long size) 1944 1.401 drochner { 1945 1.434 mlelstv struct dk_softc *dksc = &wd->sc_dksc; 1946 1.430 jdolecek struct ata_xfer *xfer; 1947 1.430 jdolecek int error; 1948 1.401 drochner unsigned char *req; 1949 1.401 drochner 1950 1.442 jdolecek xfer = ata_get_xfer(wd->drvp->chnl_softc, true); 1951 1.430 jdolecek 1952 1.401 drochner req = kmem_zalloc(512, KM_SLEEP); 1953 1.401 drochner req[0] = bno & 0xff; 1954 1.401 drochner req[1] = (bno >> 8) & 0xff; 1955 1.401 drochner req[2] = (bno >> 16) & 0xff; 1956 1.401 drochner req[3] = (bno >> 24) & 0xff; 1957 1.401 drochner req[4] = (bno >> 32) & 0xff; 1958 1.401 drochner req[5] = (bno >> 40) & 0xff; 1959 1.410 dholland req[6] = size & 0xff; 1960 1.410 dholland req[7] = (size >> 8) & 0xff; 1961 1.401 drochner 1962 1.443 jdolecek /* 1963 1.443 jdolecek * XXX We could possibly use NCQ TRIM, which supports executing 1964 1.443 jdolecek * this command concurrently. It would need some investigation, some 1965 1.443 jdolecek * early or not so early disk firmware caused data loss with NCQ TRIM. 1966 1.443 jdolecek * atastart() et.al would need to be adjusted to allow and support 1967 1.443 jdolecek * running several non-I/O ATA commands in parallel. 1968 1.443 jdolecek */ 1969 1.443 jdolecek 1970 1.430 jdolecek xfer->c_ata_c.r_command = ATA_DATA_SET_MANAGEMENT; 1971 1.430 jdolecek xfer->c_ata_c.r_count = 1; 1972 1.430 jdolecek xfer->c_ata_c.r_features = ATA_SUPPORT_DSM_TRIM; 1973 1.430 jdolecek xfer->c_ata_c.r_st_bmask = WDCS_DRDY; 1974 1.430 jdolecek xfer->c_ata_c.r_st_pmask = WDCS_DRDY; 1975 1.430 jdolecek xfer->c_ata_c.timeout = 30000; /* 30s timeout */ 1976 1.430 jdolecek xfer->c_ata_c.data = req; 1977 1.430 jdolecek xfer->c_ata_c.bcount = 512; 1978 1.430 jdolecek xfer->c_ata_c.flags |= AT_WRITE | AT_WAIT; 1979 1.462 jdolecek 1980 1.462 jdolecek wd->atabus->ata_exec_command(wd->drvp, xfer); 1981 1.462 jdolecek ata_wait_cmd(wd->drvp->chnl_softc, xfer); 1982 1.462 jdolecek 1983 1.401 drochner kmem_free(req, 512); 1984 1.464 christos error = wd_check_error(dksc, xfer, __func__); 1985 1.430 jdolecek ata_free_xfer(wd->drvp->chnl_softc, xfer); 1986 1.430 jdolecek return error; 1987 1.401 drochner } 1988 1.401 drochner 1989 1.357 drochner bool 1990 1.357 drochner wd_shutdown(device_t dev, int how) 1991 1.356 drochner { 1992 1.368 drochner struct wd_softc *wd = device_private(dev); 1993 1.368 drochner 1994 1.368 drochner /* the adapter needs to be enabled */ 1995 1.368 drochner if (wd->atabus->ata_addref(wd->drvp)) 1996 1.368 drochner return true; /* no need to complain */ 1997 1.356 drochner 1998 1.464 christos wd_flushcache(wd, AT_POLL); 1999 1.357 drochner if ((how & RB_POWERDOWN) == RB_POWERDOWN) 2000 1.356 drochner wd_standby(wd, AT_POLL); 2001 1.357 drochner return true; 2002 1.356 drochner } 2003 1.356 drochner 2004 1.185 kenh /* 2005 1.185 kenh * Allocate space for a ioctl queue structure. Mostly taken from 2006 1.185 kenh * scsipi_ioctl.c 2007 1.185 kenh */ 2008 1.185 kenh struct wd_ioctl * 2009 1.430 jdolecek wi_get(struct wd_softc *wd) 2010 1.185 kenh { 2011 1.185 kenh struct wd_ioctl *wi; 2012 1.185 kenh 2013 1.442 jdolecek wi = kmem_zalloc(sizeof(struct wd_ioctl), KM_SLEEP); 2014 1.430 jdolecek wi->wi_softc = wd; 2015 1.355 ad buf_init(&wi->wi_bp); 2016 1.430 jdolecek 2017 1.185 kenh return (wi); 2018 1.185 kenh } 2019 1.185 kenh 2020 1.185 kenh /* 2021 1.185 kenh * Free an ioctl structure and remove it from our list 2022 1.185 kenh */ 2023 1.185 kenh 2024 1.185 kenh void 2025 1.259 dsl wi_free(struct wd_ioctl *wi) 2026 1.185 kenh { 2027 1.355 ad buf_destroy(&wi->wi_bp); 2028 1.442 jdolecek kmem_free(wi, sizeof(*wi)); 2029 1.185 kenh } 2030 1.185 kenh 2031 1.185 kenh /* 2032 1.185 kenh * Find a wd_ioctl structure based on the struct buf. 2033 1.185 kenh */ 2034 1.185 kenh 2035 1.185 kenh struct wd_ioctl * 2036 1.259 dsl wi_find(struct buf *bp) 2037 1.185 kenh { 2038 1.430 jdolecek return container_of(bp, struct wd_ioctl, wi_bp); 2039 1.185 kenh } 2040 1.185 kenh 2041 1.424 jakllsch static uint 2042 1.424 jakllsch wi_sector_size(const struct wd_ioctl * const wi) 2043 1.424 jakllsch { 2044 1.424 jakllsch switch (wi->wi_atareq.command) { 2045 1.424 jakllsch case WDCC_READ: 2046 1.424 jakllsch case WDCC_WRITE: 2047 1.424 jakllsch case WDCC_READMULTI: 2048 1.424 jakllsch case WDCC_WRITEMULTI: 2049 1.424 jakllsch case WDCC_READDMA: 2050 1.424 jakllsch case WDCC_WRITEDMA: 2051 1.424 jakllsch case WDCC_READ_EXT: 2052 1.424 jakllsch case WDCC_WRITE_EXT: 2053 1.424 jakllsch case WDCC_READMULTI_EXT: 2054 1.424 jakllsch case WDCC_WRITEMULTI_EXT: 2055 1.424 jakllsch case WDCC_READDMA_EXT: 2056 1.424 jakllsch case WDCC_WRITEDMA_EXT: 2057 1.424 jakllsch case WDCC_READ_FPDMA_QUEUED: 2058 1.424 jakllsch case WDCC_WRITE_FPDMA_QUEUED: 2059 1.424 jakllsch return wi->wi_softc->sc_blksize; 2060 1.424 jakllsch default: 2061 1.424 jakllsch return 512; 2062 1.424 jakllsch } 2063 1.424 jakllsch } 2064 1.424 jakllsch 2065 1.185 kenh /* 2066 1.185 kenh * Ioctl pseudo strategy routine 2067 1.185 kenh * 2068 1.185 kenh * This is mostly stolen from scsipi_ioctl.c:scsistrategy(). What 2069 1.185 kenh * happens here is: 2070 1.185 kenh * 2071 1.185 kenh * - wdioctl() queues a wd_ioctl structure. 2072 1.185 kenh * 2073 1.185 kenh * - wdioctl() calls physio/wdioctlstrategy based on whether or not 2074 1.185 kenh * user space I/O is required. If physio() is called, physio() eventually 2075 1.185 kenh * calls wdioctlstrategy(). 2076 1.185 kenh * 2077 1.217 bouyer * - In either case, wdioctlstrategy() calls wd->atabus->ata_exec_command() 2078 1.185 kenh * to perform the actual command 2079 1.185 kenh * 2080 1.185 kenh * The reason for the use of the pseudo strategy routine is because 2081 1.185 kenh * when doing I/O to/from user space, physio _really_ wants to be in 2082 1.185 kenh * the loop. We could put the entire buffer into the ioctl request 2083 1.185 kenh * structure, but that won't scale if we want to do things like download 2084 1.185 kenh * microcode. 2085 1.185 kenh */ 2086 1.185 kenh 2087 1.185 kenh void 2088 1.259 dsl wdioctlstrategy(struct buf *bp) 2089 1.185 kenh { 2090 1.185 kenh struct wd_ioctl *wi; 2091 1.430 jdolecek struct ata_xfer *xfer; 2092 1.185 kenh int error = 0; 2093 1.185 kenh 2094 1.185 kenh wi = wi_find(bp); 2095 1.185 kenh if (wi == NULL) { 2096 1.313 martin printf("wdioctlstrategy: " 2097 1.313 martin "No matching ioctl request found in queue\n"); 2098 1.185 kenh error = EINVAL; 2099 1.430 jdolecek goto out2; 2100 1.185 kenh } 2101 1.185 kenh 2102 1.442 jdolecek xfer = ata_get_xfer(wi->wi_softc->drvp->chnl_softc, true); 2103 1.185 kenh 2104 1.185 kenh /* 2105 1.185 kenh * Abort if physio broke up the transfer 2106 1.185 kenh */ 2107 1.185 kenh 2108 1.186 kenh if (bp->b_bcount != wi->wi_atareq.datalen) { 2109 1.185 kenh printf("physio split wd ioctl request... cannot proceed\n"); 2110 1.185 kenh error = EIO; 2111 1.430 jdolecek goto out; 2112 1.185 kenh } 2113 1.185 kenh 2114 1.185 kenh /* 2115 1.185 kenh * Abort if we didn't get a buffer size that was a multiple of 2116 1.424 jakllsch * our sector size (or overflows CHS/LBA28 sector count) 2117 1.185 kenh */ 2118 1.185 kenh 2119 1.424 jakllsch if ((bp->b_bcount % wi_sector_size(wi)) != 0 || 2120 1.424 jakllsch (bp->b_bcount / wi_sector_size(wi)) >= 2121 1.185 kenh (1 << NBBY)) { 2122 1.185 kenh error = EINVAL; 2123 1.430 jdolecek goto out; 2124 1.185 kenh } 2125 1.185 kenh 2126 1.185 kenh /* 2127 1.185 kenh * Make sure a timeout was supplied in the ioctl request 2128 1.185 kenh */ 2129 1.185 kenh 2130 1.186 kenh if (wi->wi_atareq.timeout == 0) { 2131 1.185 kenh error = EINVAL; 2132 1.430 jdolecek goto out; 2133 1.185 kenh } 2134 1.185 kenh 2135 1.186 kenh if (wi->wi_atareq.flags & ATACMD_READ) 2136 1.430 jdolecek xfer->c_ata_c.flags |= AT_READ; 2137 1.186 kenh else if (wi->wi_atareq.flags & ATACMD_WRITE) 2138 1.430 jdolecek xfer->c_ata_c.flags |= AT_WRITE; 2139 1.185 kenh 2140 1.188 kenh if (wi->wi_atareq.flags & ATACMD_READREG) 2141 1.430 jdolecek xfer->c_ata_c.flags |= AT_READREG; 2142 1.188 kenh 2143 1.391 jakllsch if ((wi->wi_atareq.flags & ATACMD_LBA) != 0) 2144 1.430 jdolecek xfer->c_ata_c.flags |= AT_LBA; 2145 1.391 jakllsch 2146 1.430 jdolecek xfer->c_ata_c.flags |= AT_WAIT; 2147 1.185 kenh 2148 1.430 jdolecek xfer->c_ata_c.timeout = wi->wi_atareq.timeout; 2149 1.430 jdolecek xfer->c_ata_c.r_command = wi->wi_atareq.command; 2150 1.430 jdolecek xfer->c_ata_c.r_lba = ((wi->wi_atareq.head & 0x0f) << 24) | 2151 1.391 jakllsch (wi->wi_atareq.cylinder << 8) | 2152 1.391 jakllsch wi->wi_atareq.sec_num; 2153 1.430 jdolecek xfer->c_ata_c.r_count = wi->wi_atareq.sec_count; 2154 1.430 jdolecek xfer->c_ata_c.r_features = wi->wi_atareq.features; 2155 1.430 jdolecek xfer->c_ata_c.r_st_bmask = WDCS_DRDY; 2156 1.430 jdolecek xfer->c_ata_c.r_st_pmask = WDCS_DRDY; 2157 1.430 jdolecek xfer->c_ata_c.data = wi->wi_bp.b_data; 2158 1.430 jdolecek xfer->c_ata_c.bcount = wi->wi_bp.b_bcount; 2159 1.185 kenh 2160 1.462 jdolecek wi->wi_softc->atabus->ata_exec_command(wi->wi_softc->drvp, xfer); 2161 1.462 jdolecek ata_wait_cmd(wi->wi_softc->drvp->chnl_softc, xfer); 2162 1.185 kenh 2163 1.430 jdolecek if (xfer->c_ata_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) { 2164 1.430 jdolecek if (xfer->c_ata_c.flags & AT_ERROR) { 2165 1.186 kenh wi->wi_atareq.retsts = ATACMD_ERROR; 2166 1.430 jdolecek wi->wi_atareq.error = xfer->c_ata_c.r_error; 2167 1.430 jdolecek } else if (xfer->c_ata_c.flags & AT_DF) 2168 1.186 kenh wi->wi_atareq.retsts = ATACMD_DF; 2169 1.185 kenh else 2170 1.186 kenh wi->wi_atareq.retsts = ATACMD_TIMEOUT; 2171 1.188 kenh } else { 2172 1.186 kenh wi->wi_atareq.retsts = ATACMD_OK; 2173 1.188 kenh if (wi->wi_atareq.flags & ATACMD_READREG) { 2174 1.430 jdolecek wi->wi_atareq.command = xfer->c_ata_c.r_status; 2175 1.430 jdolecek wi->wi_atareq.features = xfer->c_ata_c.r_error; 2176 1.430 jdolecek wi->wi_atareq.sec_count = xfer->c_ata_c.r_count; 2177 1.430 jdolecek wi->wi_atareq.sec_num = xfer->c_ata_c.r_lba & 0xff; 2178 1.430 jdolecek wi->wi_atareq.head = (xfer->c_ata_c.r_device & 0xf0) | 2179 1.430 jdolecek ((xfer->c_ata_c.r_lba >> 24) & 0x0f); 2180 1.430 jdolecek wi->wi_atareq.cylinder = 2181 1.430 jdolecek (xfer->c_ata_c.r_lba >> 8) & 0xffff; 2182 1.430 jdolecek wi->wi_atareq.error = xfer->c_ata_c.r_error; 2183 1.188 kenh } 2184 1.188 kenh } 2185 1.185 kenh 2186 1.430 jdolecek out: 2187 1.430 jdolecek ata_free_xfer(wi->wi_softc->drvp->chnl_softc, xfer); 2188 1.430 jdolecek out2: 2189 1.185 kenh bp->b_error = error; 2190 1.430 jdolecek if (error) 2191 1.430 jdolecek bp->b_resid = bp->b_bcount; 2192 1.185 kenh biodone(bp); 2193 1.21 deraadt } 2194 1.430 jdolecek 2195 1.430 jdolecek static void 2196 1.430 jdolecek wd_sysctl_attach(struct wd_softc *wd) 2197 1.430 jdolecek { 2198 1.434 mlelstv struct dk_softc *dksc = &wd->sc_dksc; 2199 1.430 jdolecek const struct sysctlnode *node; 2200 1.430 jdolecek int error; 2201 1.430 jdolecek 2202 1.430 jdolecek /* sysctl set-up */ 2203 1.430 jdolecek if (sysctl_createv(&wd->nodelog, 0, NULL, &node, 2204 1.434 mlelstv 0, CTLTYPE_NODE, dksc->sc_xname, 2205 1.430 jdolecek SYSCTL_DESCR("wd driver settings"), 2206 1.430 jdolecek NULL, 0, NULL, 0, 2207 1.430 jdolecek CTL_HW, CTL_CREATE, CTL_EOL) != 0) { 2208 1.434 mlelstv aprint_error_dev(dksc->sc_dev, 2209 1.430 jdolecek "could not create %s.%s sysctl node\n", 2210 1.434 mlelstv "hw", dksc->sc_xname); 2211 1.430 jdolecek return; 2212 1.430 jdolecek } 2213 1.430 jdolecek 2214 1.456 simonb wd->drv_ncq = true; 2215 1.430 jdolecek if ((error = sysctl_createv(&wd->nodelog, 0, NULL, NULL, 2216 1.430 jdolecek CTLFLAG_READWRITE, CTLTYPE_BOOL, "use_ncq", 2217 1.430 jdolecek SYSCTL_DESCR("use NCQ if supported"), 2218 1.430 jdolecek NULL, 0, &wd->drv_ncq, 0, 2219 1.430 jdolecek CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL)) 2220 1.430 jdolecek != 0) { 2221 1.434 mlelstv aprint_error_dev(dksc->sc_dev, 2222 1.430 jdolecek "could not create %s.%s.use_ncq sysctl - error %d\n", 2223 1.434 mlelstv "hw", dksc->sc_xname, error); 2224 1.430 jdolecek return; 2225 1.430 jdolecek } 2226 1.430 jdolecek 2227 1.432 jdolecek wd->drv_ncq_prio = false; 2228 1.430 jdolecek if ((error = sysctl_createv(&wd->nodelog, 0, NULL, NULL, 2229 1.430 jdolecek CTLFLAG_READWRITE, CTLTYPE_BOOL, "use_ncq_prio", 2230 1.430 jdolecek SYSCTL_DESCR("use NCQ PRIORITY if supported"), 2231 1.430 jdolecek NULL, 0, &wd->drv_ncq_prio, 0, 2232 1.430 jdolecek CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL)) 2233 1.430 jdolecek != 0) { 2234 1.434 mlelstv aprint_error_dev(dksc->sc_dev, 2235 1.430 jdolecek "could not create %s.%s.use_ncq_prio sysctl - error %d\n", 2236 1.434 mlelstv "hw", dksc->sc_xname, error); 2237 1.430 jdolecek return; 2238 1.430 jdolecek } 2239 1.430 jdolecek 2240 1.430 jdolecek #ifdef WD_CHAOS_MONKEY 2241 1.430 jdolecek wd->drv_chaos_freq = 0; 2242 1.430 jdolecek if ((error = sysctl_createv(&wd->nodelog, 0, NULL, NULL, 2243 1.430 jdolecek CTLFLAG_READWRITE, CTLTYPE_INT, "chaos_freq", 2244 1.430 jdolecek SYSCTL_DESCR("simulated bio read error rate"), 2245 1.430 jdolecek NULL, 0, &wd->drv_chaos_freq, 0, 2246 1.430 jdolecek CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL)) 2247 1.430 jdolecek != 0) { 2248 1.434 mlelstv aprint_error_dev(dksc->sc_dev, 2249 1.430 jdolecek "could not create %s.%s.chaos_freq sysctl - error %d\n", 2250 1.434 mlelstv "hw", dksc->sc_xname, error); 2251 1.430 jdolecek return; 2252 1.430 jdolecek } 2253 1.430 jdolecek 2254 1.430 jdolecek wd->drv_chaos_cnt = 0; 2255 1.430 jdolecek if ((error = sysctl_createv(&wd->nodelog, 0, NULL, NULL, 2256 1.430 jdolecek CTLFLAG_READONLY, CTLTYPE_INT, "chaos_cnt", 2257 1.430 jdolecek SYSCTL_DESCR("number of processed bio reads"), 2258 1.430 jdolecek NULL, 0, &wd->drv_chaos_cnt, 0, 2259 1.430 jdolecek CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL)) 2260 1.430 jdolecek != 0) { 2261 1.434 mlelstv aprint_error_dev(dksc->sc_dev, 2262 1.430 jdolecek "could not create %s.%s.chaos_cnt sysctl - error %d\n", 2263 1.434 mlelstv "hw", dksc->sc_xname, error); 2264 1.430 jdolecek return; 2265 1.430 jdolecek } 2266 1.430 jdolecek #endif 2267 1.430 jdolecek 2268 1.430 jdolecek } 2269 1.430 jdolecek 2270 1.430 jdolecek static void 2271 1.430 jdolecek wd_sysctl_detach(struct wd_softc *wd) 2272 1.430 jdolecek { 2273 1.430 jdolecek sysctl_teardown(&wd->nodelog); 2274 1.430 jdolecek } 2275 1.430 jdolecek 2276 1.440 jdolecek #ifdef ATADEBUG 2277 1.440 jdolecek int wddebug(void); 2278 1.440 jdolecek 2279 1.440 jdolecek int 2280 1.440 jdolecek wddebug(void) 2281 1.440 jdolecek { 2282 1.440 jdolecek struct wd_softc *wd; 2283 1.440 jdolecek struct dk_softc *dksc; 2284 1.440 jdolecek int unit; 2285 1.440 jdolecek 2286 1.440 jdolecek for (unit = 0; unit <= 3; unit++) { 2287 1.440 jdolecek wd = device_lookup_private(&wd_cd, unit); 2288 1.440 jdolecek if (wd == NULL) 2289 1.440 jdolecek continue; 2290 1.440 jdolecek dksc = &wd->sc_dksc; 2291 1.440 jdolecek printf("%s fl %x bufq %p:\n", 2292 1.440 jdolecek dksc->sc_xname, wd->sc_flags, bufq_peek(dksc->sc_bufq)); 2293 1.440 jdolecek 2294 1.440 jdolecek atachannel_debug(wd->drvp->chnl_softc); 2295 1.440 jdolecek } 2296 1.440 jdolecek return 0; 2297 1.440 jdolecek } 2298 1.440 jdolecek #endif /* ATADEBUG */ 2299