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