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