wd.c revision 1.228 1 /* $NetBSD: wd.c,v 1.228 2002/09/30 20:42:10 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Manuel Bouyer.
17 * 4. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*-
33 * Copyright (c) 1998 The NetBSD Foundation, Inc.
34 * All rights reserved.
35 *
36 * This code is derived from software contributed to The NetBSD Foundation
37 * by Charles M. Hannum and by Onno van der Linden.
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
41 * are met:
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. All advertising materials mentioning features or use of this software
48 * must display the following acknowledgement:
49 * This product includes software developed by the NetBSD
50 * Foundation, Inc. and its contributors.
51 * 4. Neither the name of The NetBSD Foundation nor the names of its
52 * contributors may be used to endorse or promote products derived
53 * from this software without specific prior written permission.
54 *
55 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
56 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
57 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
58 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
59 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
60 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
61 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
62 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
63 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
64 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
65 * POSSIBILITY OF SUCH DAMAGE.
66 */
67
68 #include <sys/cdefs.h>
69 __KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.228 2002/09/30 20:42:10 thorpej Exp $");
70
71 #ifndef WDCDEBUG
72 #define WDCDEBUG
73 #endif /* WDCDEBUG */
74
75 #include "rnd.h"
76
77 #include <sys/param.h>
78 #include <sys/systm.h>
79 #include <sys/kernel.h>
80 #include <sys/conf.h>
81 #include <sys/file.h>
82 #include <sys/stat.h>
83 #include <sys/ioctl.h>
84 #include <sys/buf.h>
85 #include <sys/uio.h>
86 #include <sys/malloc.h>
87 #include <sys/device.h>
88 #include <sys/disklabel.h>
89 #include <sys/disk.h>
90 #include <sys/syslog.h>
91 #include <sys/proc.h>
92 #include <sys/vnode.h>
93 #if NRND > 0
94 #include <sys/rnd.h>
95 #endif
96
97 #include <machine/intr.h>
98 #include <machine/bus.h>
99
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 <sys/ataio.h>
105 #include "locators.h"
106
107 #define WAITTIME (4 * hz) /* time to wait for a completion */
108 #define WDIORETRIES_SINGLE 4 /* number of retries before single-sector */
109 #define WDIORETRIES 5 /* number of retries before giving up */
110 #define RECOVERYTIME hz/2 /* time to wait before retrying a cmd */
111
112 #define WDUNIT(dev) DISKUNIT(dev)
113 #define WDPART(dev) DISKPART(dev)
114 #define WDMINOR(unit, part) DISKMINOR(unit, part)
115 #define MAKEWDDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part)
116
117 #define WDLABELDEV(dev) (MAKEWDDEV(major(dev), WDUNIT(dev), RAW_PART))
118
119 #define DEBUG_INTR 0x01
120 #define DEBUG_XFERS 0x02
121 #define DEBUG_STATUS 0x04
122 #define DEBUG_FUNCS 0x08
123 #define DEBUG_PROBE 0x10
124 #ifdef WDCDEBUG
125 extern int wdcdebug_wd_mask; /* init'ed in ata_wdc.c */
126 #define WDCDEBUG_PRINT(args, level) \
127 if (wdcdebug_wd_mask & (level)) \
128 printf args
129 #else
130 #define WDCDEBUG_PRINT(args, level)
131 #endif
132
133 struct wd_softc {
134 /* General disk infos */
135 struct device sc_dev;
136 struct disk sc_dk;
137 struct bufq_state sc_q;
138 struct callout sc_restart_ch;
139 /* IDE disk soft states */
140 struct ata_bio sc_wdc_bio; /* current transfer */
141 struct buf *sc_bp; /* buf being transfered */
142 void *wdc_softc; /* pointer to our parent */
143 struct ata_drive_datas *drvp; /* Our controller's infos */
144 const struct ata_bustype *atabus;
145 int openings;
146 struct ataparams sc_params;/* drive characteistics found */
147 int sc_flags;
148 #define WDF_LOCKED 0x001
149 #define WDF_WANTED 0x002
150 #define WDF_WLABEL 0x004 /* label is writable */
151 #define WDF_LABELLING 0x008 /* writing label */
152 /*
153 * XXX Nothing resets this yet, but disk change sensing will when ATA-4 is
154 * more fully implemented.
155 */
156 #define WDF_LOADED 0x010 /* parameters loaded */
157 #define WDF_WAIT 0x020 /* waiting for resources */
158 #define WDF_LBA 0x040 /* using LBA mode */
159 #define WDF_KLABEL 0x080 /* retain label after 'full' close */
160 #define WDF_LBA48 0x100 /* using 48-bit LBA mode */
161 int sc_capacity;
162 int cyl; /* actual drive parameters */
163 int heads;
164 int sectors;
165 int retries; /* number of xfer retry */
166
167 void *sc_sdhook; /* our shutdown hook */
168
169 #if NRND > 0
170 rndsource_element_t rnd_source;
171 #endif
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 int wdprobe __P((struct device *, struct cfdata *, void *));
180 void wdattach __P((struct device *, struct device *, void *));
181 int wddetach __P((struct device *, int));
182 int wdactivate __P((struct device *, enum devact));
183 int wdprint __P((void *, char *));
184 void wdperror __P((const struct wd_softc *));
185
186 CFATTACH_DECL(wd, sizeof(struct wd_softc),
187 wdprobe, wdattach, wddetach, wdactivate)
188
189 extern struct cfdriver wd_cd;
190
191 dev_type_open(wdopen);
192 dev_type_close(wdclose);
193 dev_type_read(wdread);
194 dev_type_write(wdwrite);
195 dev_type_ioctl(wdioctl);
196 dev_type_strategy(wdstrategy);
197 dev_type_dump(wddump);
198 dev_type_size(wdsize);
199
200 const struct bdevsw wd_bdevsw = {
201 wdopen, wdclose, wdstrategy, wdioctl, wddump, wdsize, D_DISK
202 };
203
204 const struct cdevsw wd_cdevsw = {
205 wdopen, wdclose, wdread, wdwrite, wdioctl,
206 nostop, notty, nopoll, nommap, D_DISK
207 };
208
209 /*
210 * Glue necessary to hook WDCIOCCOMMAND into physio
211 */
212
213 struct wd_ioctl {
214 LIST_ENTRY(wd_ioctl) wi_list;
215 struct buf wi_bp;
216 struct uio wi_uio;
217 struct iovec wi_iov;
218 atareq_t wi_atareq;
219 struct wd_softc *wi_softc;
220 };
221
222 LIST_HEAD(, wd_ioctl) wi_head;
223
224 struct wd_ioctl *wi_find __P((struct buf *));
225 void wi_free __P((struct wd_ioctl *));
226 struct wd_ioctl *wi_get __P((void));
227 void wdioctlstrategy __P((struct buf *));
228
229 void wdgetdefaultlabel __P((struct wd_softc *, struct disklabel *));
230 void wdgetdisklabel __P((struct wd_softc *));
231 void wdstart __P((void *));
232 void __wdstart __P((struct wd_softc*, struct buf *));
233 void wdrestart __P((void*));
234 int wd_get_params __P((struct wd_softc *, u_int8_t, struct ataparams *));
235 void wd_flushcache __P((struct wd_softc *, int));
236 void wd_shutdown __P((void*));
237
238 struct dkdriver wddkdriver = { wdstrategy };
239
240 #ifdef HAS_BAD144_HANDLING
241 static void bad144intern __P((struct wd_softc *));
242 #endif
243 int wdlock __P((struct wd_softc *));
244 void wdunlock __P((struct wd_softc *));
245
246 int
247 wdprobe(parent, match, aux)
248 struct device *parent;
249 struct cfdata *match;
250
251 void *aux;
252 {
253 struct ata_device *adev = aux;
254
255 if (adev == NULL)
256 return 0;
257 if (adev->adev_bustype->bustype_type != SCSIPI_BUSTYPE_ATA)
258 return 0;
259
260 if (match->cf_loc[ATACF_CHANNEL] != ATACF_CHANNEL_DEFAULT &&
261 match->cf_loc[ATACF_CHANNEL] != adev->adev_channel)
262 return 0;
263
264 if (match->cf_loc[ATACF_DRIVE] != ATACF_DRIVE_DEFAULT &&
265 match->cf_loc[ATACF_DRIVE] != adev->adev_drv_data->drive)
266 return 0;
267 return 1;
268 }
269
270 void
271 wdattach(parent, self, aux)
272 struct device *parent, *self;
273 void *aux;
274 {
275 struct wd_softc *wd = (void *)self;
276 struct ata_device *adev= aux;
277 int i, blank;
278 char buf[41], pbuf[9], c, *p, *q;
279 WDCDEBUG_PRINT(("wdattach\n"), DEBUG_FUNCS | DEBUG_PROBE);
280
281 callout_init(&wd->sc_restart_ch);
282 bufq_alloc(&wd->sc_q, BUFQ_DISKSORT|BUFQ_SORT_RAWBLOCK);
283
284 wd->atabus = adev->adev_bustype;
285 wd->openings = adev->adev_openings;
286 wd->drvp = adev->adev_drv_data;;
287 wd->wdc_softc = parent;
288 /* give back our softc to our caller */
289 wd->drvp->drv_softc = &wd->sc_dev;
290
291 /* read our drive info */
292 if (wd_get_params(wd, AT_POLL, &wd->sc_params) != 0) {
293 printf("%s: IDENTIFY failed\n", wd->sc_dev.dv_xname);
294 return;
295 }
296
297 for (blank = 0, p = wd->sc_params.atap_model, q = buf, i = 0;
298 i < sizeof(wd->sc_params.atap_model); i++) {
299 c = *p++;
300 if (c == '\0')
301 break;
302 if (c != ' ') {
303 if (blank) {
304 *q++ = ' ';
305 blank = 0;
306 }
307 *q++ = c;
308 } else
309 blank = 1;
310 }
311 *q++ = '\0';
312
313 printf(": <%s>\n", buf);
314
315 if ((wd->sc_params.atap_multi & 0xff) > 1) {
316 wd->sc_multi = wd->sc_params.atap_multi & 0xff;
317 } else {
318 wd->sc_multi = 1;
319 }
320
321 printf("%s: drive supports %d-sector PIO transfers,",
322 wd->sc_dev.dv_xname, wd->sc_multi);
323
324 /* 48-bit LBA addressing */
325 if ((wd->sc_params.atap_cmd2_en & WDC_CAP_LBA48) != 0)
326 wd->sc_flags |= WDF_LBA48;
327
328 /* Prior to ATA-4, LBA was optional. */
329 if ((wd->sc_params.atap_capabilities1 & WDC_CAP_LBA) != 0)
330 wd->sc_flags |= WDF_LBA;
331 #if 0
332 /* ATA-4 requires LBA. */
333 if (wd->sc_params.atap_ataversion != 0xffff &&
334 wd->sc_params.atap_ataversion >= WDC_VER_ATA4)
335 wd->sc_flags |= WDF_LBA;
336 #endif
337
338 if ((wd->sc_flags & WDF_LBA48) != 0) {
339 printf(" LBA48 addressing\n");
340 wd->sc_capacity =
341 ((u_int64_t) wd->sc_params.__reserved6[11] << 48) |
342 ((u_int64_t) wd->sc_params.__reserved6[10] << 32) |
343 ((u_int64_t) wd->sc_params.__reserved6[9] << 16) |
344 ((u_int64_t) wd->sc_params.__reserved6[8] << 0);
345 } else if ((wd->sc_flags & WDF_LBA) != 0) {
346 printf(" LBA addressing\n");
347 wd->sc_capacity =
348 (wd->sc_params.atap_capacity[1] << 16) |
349 wd->sc_params.atap_capacity[0];
350 } else {
351 printf(" chs addressing\n");
352 wd->sc_capacity =
353 wd->sc_params.atap_cylinders *
354 wd->sc_params.atap_heads *
355 wd->sc_params.atap_sectors;
356 }
357 format_bytes(pbuf, sizeof(pbuf),
358 (u_int64_t)wd->sc_capacity * DEV_BSIZE);
359 printf("%s: %s, %d cyl, %d head, %d sec, "
360 "%d bytes/sect x %d sectors\n",
361 self->dv_xname, pbuf, wd->sc_params.atap_cylinders,
362 wd->sc_params.atap_heads, wd->sc_params.atap_sectors,
363 DEV_BSIZE, wd->sc_capacity);
364
365 WDCDEBUG_PRINT(("%s: atap_dmatiming_mimi=%d, atap_dmatiming_recom=%d\n",
366 self->dv_xname, wd->sc_params.atap_dmatiming_mimi,
367 wd->sc_params.atap_dmatiming_recom), DEBUG_PROBE);
368 /*
369 * Initialize and attach the disk structure.
370 */
371 wd->sc_dk.dk_driver = &wddkdriver;
372 wd->sc_dk.dk_name = wd->sc_dev.dv_xname;
373 disk_attach(&wd->sc_dk);
374 wd->sc_wdc_bio.lp = wd->sc_dk.dk_label;
375 wd->sc_sdhook = shutdownhook_establish(wd_shutdown, wd);
376 if (wd->sc_sdhook == NULL)
377 printf("%s: WARNING: unable to establish shutdown hook\n",
378 wd->sc_dev.dv_xname);
379 #if NRND > 0
380 rnd_attach_source(&wd->rnd_source, wd->sc_dev.dv_xname,
381 RND_TYPE_DISK, 0);
382 #endif
383 }
384
385 int
386 wdactivate(self, act)
387 struct device *self;
388 enum devact act;
389 {
390 int rv = 0;
391
392 switch (act) {
393 case DVACT_ACTIVATE:
394 rv = EOPNOTSUPP;
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
407 wddetach(self, flags)
408 struct device *self;
409 int flags;
410 {
411 struct wd_softc *sc = (struct wd_softc *)self;
412 struct buf *bp;
413 int s, bmaj, cmaj, i, mn;
414
415 /* locate the major number */
416 bmaj = bdevsw_lookup_major(&wd_bdevsw);
417 cmaj = cdevsw_lookup_major(&wd_cdevsw);
418
419 s = splbio();
420
421 /* Kill off any queued buffers. */
422 while ((bp = BUFQ_GET(&sc->sc_q)) != NULL) {
423 bp->b_error = EIO;
424 bp->b_flags |= B_ERROR;
425 bp->b_resid = bp->b_bcount;
426 biodone(bp);
427 }
428
429 bufq_free(&sc->sc_q);
430
431 splx(s);
432
433 /* Nuke the vnodes for any open instances. */
434 for (i = 0; i < MAXPARTITIONS; i++) {
435 mn = WDMINOR(self->dv_unit, i);
436 vdevgone(bmaj, mn, mn, VBLK);
437 vdevgone(cmaj, mn, mn, VCHR);
438 }
439
440 /* Detach disk. */
441 disk_detach(&sc->sc_dk);
442
443 /* Get rid of the shutdown hook. */
444 if (sc->sc_sdhook != NULL)
445 shutdownhook_disestablish(sc->sc_sdhook);
446
447 #if NRND > 0
448 /* Unhook the entropy source. */
449 rnd_detach_source(&sc->rnd_source);
450 #endif
451
452 return (0);
453 }
454
455 /*
456 * Read/write routine for a buffer. Validates the arguments and schedules the
457 * transfer. Does not wait for the transfer to complete.
458 */
459 void
460 wdstrategy(bp)
461 struct buf *bp;
462 {
463 struct wd_softc *wd = device_lookup(&wd_cd, WDUNIT(bp->b_dev));
464 struct disklabel *lp = wd->sc_dk.dk_label;
465 daddr_t blkno;
466 int s;
467
468 WDCDEBUG_PRINT(("wdstrategy (%s)\n", wd->sc_dev.dv_xname),
469 DEBUG_XFERS);
470
471 /* Valid request? */
472 if (bp->b_blkno < 0 ||
473 (bp->b_bcount % lp->d_secsize) != 0 ||
474 (bp->b_bcount / lp->d_secsize) >= (1 << NBBY)) {
475 bp->b_error = EINVAL;
476 goto bad;
477 }
478
479 /* If device invalidated (e.g. media change, door open), error. */
480 if ((wd->sc_flags & WDF_LOADED) == 0) {
481 bp->b_error = EIO;
482 goto bad;
483 }
484
485 /* If it's a null transfer, return immediately. */
486 if (bp->b_bcount == 0)
487 goto done;
488
489 /*
490 * Do bounds checking, adjust transfer. if error, process.
491 * If end of partition, just return.
492 */
493 if (WDPART(bp->b_dev) != RAW_PART &&
494 bounds_check_with_label(bp, wd->sc_dk.dk_label,
495 (wd->sc_flags & (WDF_WLABEL|WDF_LABELLING)) != 0) <= 0)
496 goto done;
497
498 /*
499 * Now convert the block number to absolute and put it in
500 * terms of the device's logical block size.
501 */
502 if (lp->d_secsize >= DEV_BSIZE)
503 blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE);
504 else
505 blkno = bp->b_blkno * (DEV_BSIZE / lp->d_secsize);
506
507 if (WDPART(bp->b_dev) != RAW_PART)
508 blkno += lp->d_partitions[WDPART(bp->b_dev)].p_offset;
509
510 bp->b_rawblkno = blkno;
511
512 /* Queue transfer on drive, activate drive and controller if idle. */
513 s = splbio();
514 BUFQ_PUT(&wd->sc_q, bp);
515 wdstart(wd);
516 splx(s);
517 return;
518 bad:
519 bp->b_flags |= B_ERROR;
520 done:
521 /* Toss transfer; we're done early. */
522 bp->b_resid = bp->b_bcount;
523 biodone(bp);
524 }
525
526 /*
527 * Queue a drive for I/O.
528 */
529 void
530 wdstart(arg)
531 void *arg;
532 {
533 struct wd_softc *wd = arg;
534 struct buf *bp = NULL;
535
536 WDCDEBUG_PRINT(("wdstart %s\n", wd->sc_dev.dv_xname),
537 DEBUG_XFERS);
538 while (wd->openings > 0) {
539
540 /* Is there a buf for us ? */
541 if ((bp = BUFQ_GET(&wd->sc_q)) == NULL)
542 return;
543
544 /*
545 * Make the command. First lock the device
546 */
547 wd->openings--;
548
549 wd->retries = 0;
550 __wdstart(wd, bp);
551 }
552 }
553
554 void
555 __wdstart(wd, bp)
556 struct wd_softc *wd;
557 struct buf *bp;
558 {
559
560 wd->sc_wdc_bio.blkno = bp->b_rawblkno;
561 wd->sc_wdc_bio.blkdone =0;
562 wd->sc_bp = bp;
563 /*
564 * If we're retrying, retry in single-sector mode. This will give us
565 * the sector number of the problem, and will eventually allow the
566 * transfer to succeed.
567 */
568 if (wd->sc_multi == 1 || wd->retries >= WDIORETRIES_SINGLE)
569 wd->sc_wdc_bio.flags = ATA_SINGLE;
570 else
571 wd->sc_wdc_bio.flags = 0;
572 if (wd->sc_flags & WDF_LBA48)
573 wd->sc_wdc_bio.flags |= ATA_LBA48;
574 if (wd->sc_flags & WDF_LBA)
575 wd->sc_wdc_bio.flags |= ATA_LBA;
576 if (bp->b_flags & B_READ)
577 wd->sc_wdc_bio.flags |= ATA_READ;
578 wd->sc_wdc_bio.bcount = bp->b_bcount;
579 wd->sc_wdc_bio.databuf = bp->b_data;
580 /* Instrumentation. */
581 disk_busy(&wd->sc_dk);
582 switch (wd->atabus->ata_bio(wd->drvp, &wd->sc_wdc_bio)) {
583 case WDC_TRY_AGAIN:
584 callout_reset(&wd->sc_restart_ch, hz, wdrestart, wd);
585 break;
586 case WDC_QUEUED:
587 case WDC_COMPLETE:
588 break;
589 default:
590 panic("__wdstart: bad return code from 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 const char *errmsg;
601 int do_perror = 0;
602 WDCDEBUG_PRINT(("wddone %s\n", wd->sc_dev.dv_xname),
603 DEBUG_XFERS);
604
605 if (bp == NULL)
606 return;
607 bp->b_resid = wd->sc_wdc_bio.bcount;
608 switch (wd->sc_wdc_bio.error) {
609 case ERR_DMA:
610 errmsg = "DMA error";
611 goto retry;
612 case ERR_DF:
613 errmsg = "device fault";
614 goto retry;
615 case TIMEOUT:
616 errmsg = "device timeout";
617 goto retry;
618 case ERROR:
619 /* Don't care about media change bits */
620 if (wd->sc_wdc_bio.r_error != 0 &&
621 (wd->sc_wdc_bio.r_error & ~(WDCE_MC | WDCE_MCR)) == 0)
622 goto noerror;
623 errmsg = "error";
624 do_perror = 1;
625 retry: /* Just reset and retry. Can we do more ? */
626 wd->atabus->ata_reset_channel(wd->drvp);
627 diskerr(bp, "wd", errmsg, LOG_PRINTF,
628 wd->sc_wdc_bio.blkdone, wd->sc_dk.dk_label);
629 if (wd->retries < WDIORETRIES)
630 printf(", retrying\n");
631 if (do_perror)
632 wdperror(wd);
633 if (wd->retries < WDIORETRIES) {
634 wd->retries++;
635 callout_reset(&wd->sc_restart_ch, RECOVERYTIME,
636 wdrestart, wd);
637 return;
638 }
639 printf("\n");
640 bp->b_flags |= B_ERROR;
641 bp->b_error = EIO;
642 break;
643 case NOERROR:
644 noerror: if ((wd->sc_wdc_bio.flags & ATA_CORR) || wd->retries > 0)
645 printf("%s: soft error (corrected)\n",
646 wd->sc_dev.dv_xname);
647 break;
648 case ERR_NODEV:
649 bp->b_flags |= B_ERROR;
650 bp->b_error = EIO;
651 break;
652 }
653 disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid));
654 #if NRND > 0
655 rnd_add_uint32(&wd->rnd_source, bp->b_blkno);
656 #endif
657 biodone(bp);
658 wd->openings++;
659 wdstart(wd);
660 }
661
662 void
663 wdrestart(v)
664 void *v;
665 {
666 struct wd_softc *wd = v;
667 struct buf *bp = wd->sc_bp;
668 int s;
669 WDCDEBUG_PRINT(("wdrestart %s\n", wd->sc_dev.dv_xname),
670 DEBUG_XFERS);
671
672 s = splbio();
673 __wdstart(v, bp);
674 splx(s);
675 }
676
677 int
678 wdread(dev, uio, flags)
679 dev_t dev;
680 struct uio *uio;
681 int flags;
682 {
683
684 WDCDEBUG_PRINT(("wdread\n"), DEBUG_XFERS);
685 return (physio(wdstrategy, NULL, dev, B_READ, minphys, uio));
686 }
687
688 int
689 wdwrite(dev, uio, flags)
690 dev_t dev;
691 struct uio *uio;
692 int flags;
693 {
694
695 WDCDEBUG_PRINT(("wdwrite\n"), DEBUG_XFERS);
696 return (physio(wdstrategy, NULL, dev, B_WRITE, minphys, uio));
697 }
698
699 /*
700 * Wait interruptibly for an exclusive lock.
701 *
702 * XXX
703 * Several drivers do this; it should be abstracted and made MP-safe.
704 */
705 int
706 wdlock(wd)
707 struct wd_softc *wd;
708 {
709 int error;
710 int s;
711
712 WDCDEBUG_PRINT(("wdlock\n"), DEBUG_FUNCS);
713
714 s = splbio();
715
716 while ((wd->sc_flags & WDF_LOCKED) != 0) {
717 wd->sc_flags |= WDF_WANTED;
718 if ((error = tsleep(wd, PRIBIO | PCATCH,
719 "wdlck", 0)) != 0) {
720 splx(s);
721 return error;
722 }
723 }
724 wd->sc_flags |= WDF_LOCKED;
725 splx(s);
726 return 0;
727 }
728
729 /*
730 * Unlock and wake up any waiters.
731 */
732 void
733 wdunlock(wd)
734 struct wd_softc *wd;
735 {
736
737 WDCDEBUG_PRINT(("wdunlock\n"), DEBUG_FUNCS);
738
739 wd->sc_flags &= ~WDF_LOCKED;
740 if ((wd->sc_flags & WDF_WANTED) != 0) {
741 wd->sc_flags &= ~WDF_WANTED;
742 wakeup(wd);
743 }
744 }
745
746 int
747 wdopen(dev, flag, fmt, p)
748 dev_t dev;
749 int flag, fmt;
750 struct proc *p;
751 {
752 struct wd_softc *wd;
753 int part, error;
754
755 WDCDEBUG_PRINT(("wdopen\n"), DEBUG_FUNCS);
756 wd = device_lookup(&wd_cd, WDUNIT(dev));
757 if (wd == NULL)
758 return (ENXIO);
759
760 /*
761 * If this is the first open of this device, add a reference
762 * to the adapter.
763 */
764 if (wd->sc_dk.dk_openmask == 0 &&
765 (error = wd->atabus->ata_addref(wd->drvp)) != 0)
766 return (error);
767
768 if ((error = wdlock(wd)) != 0)
769 goto bad4;
770
771 if (wd->sc_dk.dk_openmask != 0) {
772 /*
773 * If any partition is open, but the disk has been invalidated,
774 * disallow further opens.
775 */
776 if ((wd->sc_flags & WDF_LOADED) == 0) {
777 error = EIO;
778 goto bad3;
779 }
780 } else {
781 if ((wd->sc_flags & WDF_LOADED) == 0) {
782 wd->sc_flags |= WDF_LOADED;
783
784 /* Load the physical device parameters. */
785 wd_get_params(wd, AT_WAIT, &wd->sc_params);
786
787 /* Load the partition info if not already loaded. */
788 wdgetdisklabel(wd);
789 }
790 }
791
792 part = WDPART(dev);
793
794 /* Check that the partition exists. */
795 if (part != RAW_PART &&
796 (part >= wd->sc_dk.dk_label->d_npartitions ||
797 wd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
798 error = ENXIO;
799 goto bad;
800 }
801
802 /* Insure only one open at a time. */
803 switch (fmt) {
804 case S_IFCHR:
805 wd->sc_dk.dk_copenmask |= (1 << part);
806 break;
807 case S_IFBLK:
808 wd->sc_dk.dk_bopenmask |= (1 << part);
809 break;
810 }
811 wd->sc_dk.dk_openmask =
812 wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
813
814 wdunlock(wd);
815 return 0;
816
817 bad:
818 if (wd->sc_dk.dk_openmask == 0) {
819 }
820
821 bad3:
822 wdunlock(wd);
823 bad4:
824 if (wd->sc_dk.dk_openmask == 0)
825 wd->atabus->ata_delref(wd->drvp);
826 return error;
827 }
828
829 int
830 wdclose(dev, flag, fmt, p)
831 dev_t dev;
832 int flag, fmt;
833 struct proc *p;
834 {
835 struct wd_softc *wd = device_lookup(&wd_cd, WDUNIT(dev));
836 int part = WDPART(dev);
837 int error;
838
839 WDCDEBUG_PRINT(("wdclose\n"), DEBUG_FUNCS);
840 if ((error = wdlock(wd)) != 0)
841 return error;
842
843 switch (fmt) {
844 case S_IFCHR:
845 wd->sc_dk.dk_copenmask &= ~(1 << part);
846 break;
847 case S_IFBLK:
848 wd->sc_dk.dk_bopenmask &= ~(1 << part);
849 break;
850 }
851 wd->sc_dk.dk_openmask =
852 wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
853
854 if (wd->sc_dk.dk_openmask == 0) {
855 wd_flushcache(wd, AT_WAIT);
856 /* XXXX Must wait for I/O to complete! */
857
858 if (! (wd->sc_flags & WDF_KLABEL))
859 wd->sc_flags &= ~WDF_LOADED;
860
861 wd->atabus->ata_delref(wd->drvp);
862 }
863
864 wdunlock(wd);
865 return 0;
866 }
867
868 void
869 wdgetdefaultlabel(wd, lp)
870 struct wd_softc *wd;
871 struct disklabel *lp;
872 {
873
874 WDCDEBUG_PRINT(("wdgetdefaultlabel\n"), DEBUG_FUNCS);
875 memset(lp, 0, sizeof(struct disklabel));
876
877 lp->d_secsize = DEV_BSIZE;
878 lp->d_ntracks = wd->sc_params.atap_heads;
879 lp->d_nsectors = wd->sc_params.atap_sectors;
880 lp->d_ncylinders = wd->sc_params.atap_cylinders;
881 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
882
883 if (strcmp(wd->sc_params.atap_model, "ST506") == 0)
884 lp->d_type = DTYPE_ST506;
885 else
886 lp->d_type = DTYPE_ESDI;
887
888 strncpy(lp->d_typename, wd->sc_params.atap_model, 16);
889 strncpy(lp->d_packname, "fictitious", 16);
890 lp->d_secperunit = wd->sc_capacity;
891 lp->d_rpm = 3600;
892 lp->d_interleave = 1;
893 lp->d_flags = 0;
894
895 lp->d_partitions[RAW_PART].p_offset = 0;
896 lp->d_partitions[RAW_PART].p_size =
897 lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
898 lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
899 lp->d_npartitions = RAW_PART + 1;
900
901 lp->d_magic = DISKMAGIC;
902 lp->d_magic2 = DISKMAGIC;
903 lp->d_checksum = dkcksum(lp);
904 }
905
906 /*
907 * Fabricate a default disk label, and try to read the correct one.
908 */
909 void
910 wdgetdisklabel(wd)
911 struct wd_softc *wd;
912 {
913 struct disklabel *lp = wd->sc_dk.dk_label;
914 char *errstring;
915
916 WDCDEBUG_PRINT(("wdgetdisklabel\n"), DEBUG_FUNCS);
917
918 memset(wd->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel));
919
920 wdgetdefaultlabel(wd, lp);
921
922 wd->sc_badsect[0] = -1;
923
924 if (wd->drvp->state > RECAL)
925 wd->drvp->drive_flags |= DRIVE_RESET;
926 errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, RAW_PART),
927 wdstrategy, lp, wd->sc_dk.dk_cpulabel);
928 if (errstring) {
929 /*
930 * This probably happened because the drive's default
931 * geometry doesn't match the DOS geometry. We
932 * assume the DOS geometry is now in the label and try
933 * again. XXX This is a kluge.
934 */
935 if (wd->drvp->state > RECAL)
936 wd->drvp->drive_flags |= DRIVE_RESET;
937 errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit,
938 RAW_PART), wdstrategy, lp, wd->sc_dk.dk_cpulabel);
939 }
940 if (errstring) {
941 printf("%s: %s\n", wd->sc_dev.dv_xname, errstring);
942 return;
943 }
944
945 if (wd->drvp->state > RECAL)
946 wd->drvp->drive_flags |= DRIVE_RESET;
947 #ifdef HAS_BAD144_HANDLING
948 if ((lp->d_flags & D_BADSECT) != 0)
949 bad144intern(wd);
950 #endif
951 }
952
953 void
954 wdperror(wd)
955 const struct wd_softc *wd;
956 {
957 static const char *const errstr0_3[] = {"address mark not found",
958 "track 0 not found", "aborted command", "media change requested",
959 "id not found", "media changed", "uncorrectable data error",
960 "bad block detected"};
961 static const char *const errstr4_5[] = {
962 "obsolete (address mark not found)",
963 "no media/write protected", "aborted command",
964 "media change requested", "id not found", "media changed",
965 "uncorrectable data error", "interface CRC error"};
966 const char *const *errstr;
967 int i;
968 char *sep = "";
969
970 const char *devname = wd->sc_dev.dv_xname;
971 struct ata_drive_datas *drvp = wd->drvp;
972 int errno = wd->sc_wdc_bio.r_error;
973
974 if (drvp->ata_vers >= 4)
975 errstr = errstr4_5;
976 else
977 errstr = errstr0_3;
978
979 printf("%s: (", devname);
980
981 if (errno == 0)
982 printf("error not notified");
983
984 for (i = 0; i < 8; i++) {
985 if (errno & (1 << i)) {
986 printf("%s%s", sep, errstr[i]);
987 sep = ", ";
988 }
989 }
990 printf(")\n");
991 }
992
993 int
994 wdioctl(dev, xfer, addr, flag, p)
995 dev_t dev;
996 u_long xfer;
997 caddr_t addr;
998 int flag;
999 struct proc *p;
1000 {
1001 struct wd_softc *wd = device_lookup(&wd_cd, WDUNIT(dev));
1002 int error;
1003 #ifdef __HAVE_OLD_DISKLABEL
1004 struct disklabel newlabel;
1005 #endif
1006
1007 WDCDEBUG_PRINT(("wdioctl\n"), DEBUG_FUNCS);
1008
1009 if ((wd->sc_flags & WDF_LOADED) == 0)
1010 return EIO;
1011
1012 switch (xfer) {
1013 #ifdef HAS_BAD144_HANDLING
1014 case DIOCSBAD:
1015 if ((flag & FWRITE) == 0)
1016 return EBADF;
1017 wd->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr;
1018 wd->sc_dk.dk_label->d_flags |= D_BADSECT;
1019 bad144intern(wd);
1020 return 0;
1021 #endif
1022
1023 case DIOCGDINFO:
1024 *(struct disklabel *)addr = *(wd->sc_dk.dk_label);
1025 return 0;
1026 #ifdef __HAVE_OLD_DISKLABEL
1027 case ODIOCGDINFO:
1028 newlabel = *(wd->sc_dk.dk_label);
1029 if (newlabel.d_npartitions > OLDMAXPARTITIONS)
1030 return ENOTTY;
1031 memcpy(addr, &newlabel, sizeof (struct olddisklabel));
1032 return 0;
1033 #endif
1034
1035 case DIOCGPART:
1036 ((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label;
1037 ((struct partinfo *)addr)->part =
1038 &wd->sc_dk.dk_label->d_partitions[WDPART(dev)];
1039 return 0;
1040
1041 case DIOCWDINFO:
1042 case DIOCSDINFO:
1043 #ifdef __HAVE_OLD_DISKLABEL
1044 case ODIOCWDINFO:
1045 case ODIOCSDINFO:
1046 #endif
1047 {
1048 struct disklabel *lp;
1049
1050 #ifdef __HAVE_OLD_DISKLABEL
1051 if (xfer == ODIOCSDINFO || xfer == ODIOCWDINFO) {
1052 memset(&newlabel, 0, sizeof newlabel);
1053 memcpy(&newlabel, addr, sizeof (struct olddisklabel));
1054 lp = &newlabel;
1055 } else
1056 #endif
1057 lp = (struct disklabel *)addr;
1058
1059 if ((flag & FWRITE) == 0)
1060 return EBADF;
1061
1062 if ((error = wdlock(wd)) != 0)
1063 return error;
1064 wd->sc_flags |= WDF_LABELLING;
1065
1066 error = setdisklabel(wd->sc_dk.dk_label,
1067 lp, /*wd->sc_dk.dk_openmask : */0,
1068 wd->sc_dk.dk_cpulabel);
1069 if (error == 0) {
1070 if (wd->drvp->state > RECAL)
1071 wd->drvp->drive_flags |= DRIVE_RESET;
1072 if (xfer == DIOCWDINFO
1073 #ifdef __HAVE_OLD_DISKLABEL
1074 || xfer == ODIOCWDINFO
1075 #endif
1076 )
1077 error = writedisklabel(WDLABELDEV(dev),
1078 wdstrategy, wd->sc_dk.dk_label,
1079 wd->sc_dk.dk_cpulabel);
1080 }
1081
1082 wd->sc_flags &= ~WDF_LABELLING;
1083 wdunlock(wd);
1084 return error;
1085 }
1086
1087 case DIOCKLABEL:
1088 if (*(int *)addr)
1089 wd->sc_flags |= WDF_KLABEL;
1090 else
1091 wd->sc_flags &= ~WDF_KLABEL;
1092 return 0;
1093
1094 case DIOCWLABEL:
1095 if ((flag & FWRITE) == 0)
1096 return EBADF;
1097 if (*(int *)addr)
1098 wd->sc_flags |= WDF_WLABEL;
1099 else
1100 wd->sc_flags &= ~WDF_WLABEL;
1101 return 0;
1102
1103 case DIOCGDEFLABEL:
1104 wdgetdefaultlabel(wd, (struct disklabel *)addr);
1105 return 0;
1106 #ifdef __HAVE_OLD_DISKLABEL
1107 case ODIOCGDEFLABEL:
1108 wdgetdefaultlabel(wd, &newlabel);
1109 if (newlabel.d_npartitions > OLDMAXPARTITIONS)
1110 return ENOTTY;
1111 memcpy(addr, &newlabel, sizeof (struct olddisklabel));
1112 return 0;
1113 #endif
1114
1115 #ifdef notyet
1116 case DIOCWFORMAT:
1117 if ((flag & FWRITE) == 0)
1118 return EBADF;
1119 {
1120 register struct format_op *fop;
1121 struct iovec aiov;
1122 struct uio auio;
1123
1124 fop = (struct format_op *)addr;
1125 aiov.iov_base = fop->df_buf;
1126 aiov.iov_len = fop->df_count;
1127 auio.uio_iov = &aiov;
1128 auio.uio_iovcnt = 1;
1129 auio.uio_resid = fop->df_count;
1130 auio.uio_segflg = 0;
1131 auio.uio_offset =
1132 fop->df_startblk * wd->sc_dk.dk_label->d_secsize;
1133 auio.uio_procp = p;
1134 error = physio(wdformat, NULL, dev, B_WRITE, minphys,
1135 &auio);
1136 fop->df_count -= auio.uio_resid;
1137 fop->df_reg[0] = wdc->sc_status;
1138 fop->df_reg[1] = wdc->sc_error;
1139 return error;
1140 }
1141 #endif
1142
1143 case ATAIOCCOMMAND:
1144 /*
1145 * Make sure this command is (relatively) safe first
1146 */
1147 if ((((atareq_t *) addr)->flags & ATACMD_READ) == 0 &&
1148 (flag & FWRITE) == 0)
1149 return (EBADF);
1150 {
1151 struct wd_ioctl *wi;
1152 atareq_t *atareq = (atareq_t *) addr;
1153 int error;
1154
1155 wi = wi_get();
1156 wi->wi_softc = wd;
1157 wi->wi_atareq = *atareq;
1158
1159 if (atareq->datalen && atareq->flags &
1160 (ATACMD_READ | ATACMD_WRITE)) {
1161 wi->wi_iov.iov_base = atareq->databuf;
1162 wi->wi_iov.iov_len = atareq->datalen;
1163 wi->wi_uio.uio_iov = &wi->wi_iov;
1164 wi->wi_uio.uio_iovcnt = 1;
1165 wi->wi_uio.uio_resid = atareq->datalen;
1166 wi->wi_uio.uio_offset = 0;
1167 wi->wi_uio.uio_segflg = UIO_USERSPACE;
1168 wi->wi_uio.uio_rw =
1169 (atareq->flags & ATACMD_READ) ? B_READ : B_WRITE;
1170 wi->wi_uio.uio_procp = p;
1171 error = physio(wdioctlstrategy, &wi->wi_bp, dev,
1172 (atareq->flags & ATACMD_READ) ? B_READ : B_WRITE,
1173 minphys, &wi->wi_uio);
1174 } else {
1175 /* No need to call physio if we don't have any
1176 user data */
1177 wi->wi_bp.b_flags = 0;
1178 wi->wi_bp.b_data = 0;
1179 wi->wi_bp.b_bcount = 0;
1180 wi->wi_bp.b_dev = 0;
1181 wi->wi_bp.b_proc = p;
1182 wdioctlstrategy(&wi->wi_bp);
1183 error = wi->wi_bp.b_error;
1184 }
1185 *atareq = wi->wi_atareq;
1186 wi_free(wi);
1187 return(error);
1188 }
1189
1190 default:
1191 return ENOTTY;
1192 }
1193
1194 #ifdef DIAGNOSTIC
1195 panic("wdioctl: impossible");
1196 #endif
1197 }
1198
1199 #ifdef B_FORMAT
1200 int
1201 wdformat(struct buf *bp)
1202 {
1203
1204 bp->b_flags |= B_FORMAT;
1205 return wdstrategy(bp);
1206 }
1207 #endif
1208
1209 int
1210 wdsize(dev)
1211 dev_t dev;
1212 {
1213 struct wd_softc *wd;
1214 int part, omask;
1215 int size;
1216
1217 WDCDEBUG_PRINT(("wdsize\n"), DEBUG_FUNCS);
1218
1219 wd = device_lookup(&wd_cd, WDUNIT(dev));
1220 if (wd == NULL)
1221 return (-1);
1222
1223 part = WDPART(dev);
1224 omask = wd->sc_dk.dk_openmask & (1 << part);
1225
1226 if (omask == 0 && wdopen(dev, 0, S_IFBLK, NULL) != 0)
1227 return (-1);
1228 if (wd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
1229 size = -1;
1230 else
1231 size = wd->sc_dk.dk_label->d_partitions[part].p_size *
1232 (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
1233 if (omask == 0 && wdclose(dev, 0, S_IFBLK, NULL) != 0)
1234 return (-1);
1235 return (size);
1236 }
1237
1238 /* #define WD_DUMP_NOT_TRUSTED if you just want to watch */
1239 static int wddoingadump = 0;
1240 static int wddumprecalibrated = 0;
1241 static int wddumpmulti = 1;
1242
1243 /*
1244 * Dump core after a system crash.
1245 */
1246 int
1247 wddump(dev, blkno, va, size)
1248 dev_t dev;
1249 daddr_t blkno;
1250 caddr_t va;
1251 size_t size;
1252 {
1253 struct wd_softc *wd; /* disk unit to do the I/O */
1254 struct disklabel *lp; /* disk's disklabel */
1255 int part, err;
1256 int nblks; /* total number of sectors left to write */
1257
1258 /* Check if recursive dump; if so, punt. */
1259 if (wddoingadump)
1260 return EFAULT;
1261 wddoingadump = 1;
1262
1263 wd = device_lookup(&wd_cd, WDUNIT(dev));
1264 if (wd == NULL)
1265 return (ENXIO);
1266
1267 part = WDPART(dev);
1268
1269 /* Convert to disk sectors. Request must be a multiple of size. */
1270 lp = wd->sc_dk.dk_label;
1271 if ((size % lp->d_secsize) != 0)
1272 return EFAULT;
1273 nblks = size / lp->d_secsize;
1274 blkno = blkno / (lp->d_secsize / DEV_BSIZE);
1275
1276 /* Check transfer bounds against partition size. */
1277 if ((blkno < 0) || ((blkno + nblks) > lp->d_partitions[part].p_size))
1278 return EINVAL;
1279
1280 /* Offset block number to start of partition. */
1281 blkno += lp->d_partitions[part].p_offset;
1282
1283 /* Recalibrate, if first dump transfer. */
1284 if (wddumprecalibrated == 0) {
1285 wddumpmulti = wd->sc_multi;
1286 wddumprecalibrated = 1;
1287 wd->drvp->state = RESET;
1288 }
1289
1290 while (nblks > 0) {
1291 again:
1292 wd->sc_bp = NULL;
1293 wd->sc_wdc_bio.blkno = blkno;
1294 wd->sc_wdc_bio.flags = ATA_POLL;
1295 if (wddumpmulti == 1)
1296 wd->sc_wdc_bio.flags |= ATA_SINGLE;
1297 if (wd->sc_flags & WDF_LBA48)
1298 wd->sc_wdc_bio.flags |= ATA_LBA48;
1299 if (wd->sc_flags & WDF_LBA)
1300 wd->sc_wdc_bio.flags |= ATA_LBA;
1301 wd->sc_wdc_bio.bcount =
1302 min(nblks, wddumpmulti) * lp->d_secsize;
1303 wd->sc_wdc_bio.databuf = va;
1304 #ifndef WD_DUMP_NOT_TRUSTED
1305 switch (wd->atabus->ata_bio(wd->drvp, &wd->sc_wdc_bio)) {
1306 case WDC_TRY_AGAIN:
1307 panic("wddump: try again");
1308 break;
1309 case WDC_QUEUED:
1310 panic("wddump: polled command has been queued");
1311 break;
1312 case WDC_COMPLETE:
1313 break;
1314 }
1315 switch(wd->sc_wdc_bio.error) {
1316 case TIMEOUT:
1317 printf("wddump: device timed out");
1318 err = EIO;
1319 break;
1320 case ERR_DF:
1321 printf("wddump: drive fault");
1322 err = EIO;
1323 break;
1324 case ERR_DMA:
1325 printf("wddump: DMA error");
1326 err = EIO;
1327 break;
1328 case ERROR:
1329 printf("wddump: ");
1330 wdperror(wd);
1331 err = EIO;
1332 break;
1333 case NOERROR:
1334 err = 0;
1335 break;
1336 default:
1337 panic("wddump: unknown error type");
1338 }
1339 if (err != 0) {
1340 if (wddumpmulti != 1) {
1341 wddumpmulti = 1; /* retry in single-sector */
1342 printf(", retrying\n");
1343 goto again;
1344 }
1345 printf("\n");
1346 return err;
1347 }
1348 #else /* WD_DUMP_NOT_TRUSTED */
1349 /* Let's just talk about this first... */
1350 printf("wd%d: dump addr 0x%x, cylin %d, head %d, sector %d\n",
1351 unit, va, cylin, head, sector);
1352 delay(500 * 1000); /* half a second */
1353 #endif
1354
1355 /* update block count */
1356 nblks -= min(nblks, wddumpmulti);
1357 blkno += min(nblks, wddumpmulti);
1358 va += min(nblks, wddumpmulti) * lp->d_secsize;
1359 }
1360
1361 wddoingadump = 0;
1362 return 0;
1363 }
1364
1365 #ifdef HAS_BAD144_HANDLING
1366 /*
1367 * Internalize the bad sector table.
1368 */
1369 void
1370 bad144intern(wd)
1371 struct wd_softc *wd;
1372 {
1373 struct dkbad *bt = &wd->sc_dk.dk_cpulabel->bad;
1374 struct disklabel *lp = wd->sc_dk.dk_label;
1375 int i = 0;
1376
1377 WDCDEBUG_PRINT(("bad144intern\n"), DEBUG_XFERS);
1378
1379 for (; i < NBT_BAD; i++) {
1380 if (bt->bt_bad[i].bt_cyl == 0xffff)
1381 break;
1382 wd->sc_badsect[i] =
1383 bt->bt_bad[i].bt_cyl * lp->d_secpercyl +
1384 (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors +
1385 (bt->bt_bad[i].bt_trksec & 0xff);
1386 }
1387 for (; i < NBT_BAD+1; i++)
1388 wd->sc_badsect[i] = -1;
1389 }
1390 #endif
1391
1392 int
1393 wd_get_params(wd, flags, params)
1394 struct wd_softc *wd;
1395 u_int8_t flags;
1396 struct ataparams *params;
1397 {
1398 switch (wd->atabus->ata_get_params(wd->drvp, flags, params)) {
1399 case CMD_AGAIN:
1400 return 1;
1401 case CMD_ERR:
1402 /*
1403 * We `know' there's a drive here; just assume it's old.
1404 * This geometry is only used to read the MBR and print a
1405 * (false) attach message.
1406 */
1407 strncpy(params->atap_model, "ST506",
1408 sizeof params->atap_model);
1409 params->atap_config = ATA_CFG_FIXED;
1410 params->atap_cylinders = 1024;
1411 params->atap_heads = 8;
1412 params->atap_sectors = 17;
1413 params->atap_multi = 1;
1414 params->atap_capabilities1 = params->atap_capabilities2 = 0;
1415 wd->drvp->ata_vers = -1; /* Mark it as pre-ATA */
1416 return 0;
1417 case CMD_OK:
1418 return 0;
1419 default:
1420 panic("wd_get_params: bad return code from ata_get_params");
1421 /* NOTREACHED */
1422 }
1423 }
1424
1425 void
1426 wd_flushcache(wd, flags)
1427 struct wd_softc *wd;
1428 int flags;
1429 {
1430 struct wdc_command wdc_c;
1431
1432 if (wd->drvp->ata_vers < 4) /* WDCC_FLUSHCACHE is here since ATA-4 */
1433 return;
1434 memset(&wdc_c, 0, sizeof(struct wdc_command));
1435 wdc_c.r_command = WDCC_FLUSHCACHE;
1436 wdc_c.r_st_bmask = WDCS_DRDY;
1437 wdc_c.r_st_pmask = WDCS_DRDY;
1438 wdc_c.flags = flags;
1439 wdc_c.timeout = 30000; /* 30s timeout */
1440 if (wd->atabus->ata_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) {
1441 printf("%s: flush cache command didn't complete\n",
1442 wd->sc_dev.dv_xname);
1443 }
1444 if (wdc_c.flags & AT_TIMEOU) {
1445 printf("%s: flush cache command timeout\n",
1446 wd->sc_dev.dv_xname);
1447 }
1448 if (wdc_c.flags & AT_DF) {
1449 printf("%s: flush cache command: drive fault\n",
1450 wd->sc_dev.dv_xname);
1451 }
1452 /*
1453 * Ignore error register, it shouldn't report anything else
1454 * than COMMAND ABORTED, which means the device doesn't support
1455 * flush cache
1456 */
1457 }
1458
1459 void
1460 wd_shutdown(arg)
1461 void *arg;
1462 {
1463 struct wd_softc *wd = arg;
1464 wd_flushcache(wd, AT_POLL);
1465 }
1466
1467 /*
1468 * Allocate space for a ioctl queue structure. Mostly taken from
1469 * scsipi_ioctl.c
1470 */
1471 struct wd_ioctl *
1472 wi_get()
1473 {
1474 struct wd_ioctl *wi;
1475 int s;
1476
1477 wi = malloc(sizeof(struct wd_ioctl), M_TEMP, M_WAITOK|M_ZERO);
1478 s = splbio();
1479 LIST_INSERT_HEAD(&wi_head, wi, wi_list);
1480 splx(s);
1481 return (wi);
1482 }
1483
1484 /*
1485 * Free an ioctl structure and remove it from our list
1486 */
1487
1488 void
1489 wi_free(wi)
1490 struct wd_ioctl *wi;
1491 {
1492 int s;
1493
1494 s = splbio();
1495 LIST_REMOVE(wi, wi_list);
1496 splx(s);
1497 free(wi, M_TEMP);
1498 }
1499
1500 /*
1501 * Find a wd_ioctl structure based on the struct buf.
1502 */
1503
1504 struct wd_ioctl *
1505 wi_find(bp)
1506 struct buf *bp;
1507 {
1508 struct wd_ioctl *wi;
1509 int s;
1510
1511 s = splbio();
1512 for (wi = wi_head.lh_first; wi != 0; wi = wi->wi_list.le_next)
1513 if (bp == &wi->wi_bp)
1514 break;
1515 splx(s);
1516 return (wi);
1517 }
1518
1519 /*
1520 * Ioctl pseudo strategy routine
1521 *
1522 * This is mostly stolen from scsipi_ioctl.c:scsistrategy(). What
1523 * happens here is:
1524 *
1525 * - wdioctl() queues a wd_ioctl structure.
1526 *
1527 * - wdioctl() calls physio/wdioctlstrategy based on whether or not
1528 * user space I/O is required. If physio() is called, physio() eventually
1529 * calls wdioctlstrategy().
1530 *
1531 * - In either case, wdioctlstrategy() calls wd->atabus->ata_exec_command()
1532 * to perform the actual command
1533 *
1534 * The reason for the use of the pseudo strategy routine is because
1535 * when doing I/O to/from user space, physio _really_ wants to be in
1536 * the loop. We could put the entire buffer into the ioctl request
1537 * structure, but that won't scale if we want to do things like download
1538 * microcode.
1539 */
1540
1541 void
1542 wdioctlstrategy(bp)
1543 struct buf *bp;
1544 {
1545 struct wd_ioctl *wi;
1546 struct wdc_command wdc_c;
1547 int error = 0;
1548
1549 wi = wi_find(bp);
1550 if (wi == NULL) {
1551 printf("user_strat: No ioctl\n");
1552 error = EINVAL;
1553 goto bad;
1554 }
1555
1556 memset(&wdc_c, 0, sizeof(wdc_c));
1557
1558 /*
1559 * Abort if physio broke up the transfer
1560 */
1561
1562 if (bp->b_bcount != wi->wi_atareq.datalen) {
1563 printf("physio split wd ioctl request... cannot proceed\n");
1564 error = EIO;
1565 goto bad;
1566 }
1567
1568 /*
1569 * Abort if we didn't get a buffer size that was a multiple of
1570 * our sector size (or was larger than NBBY)
1571 */
1572
1573 if ((bp->b_bcount % wi->wi_softc->sc_dk.dk_label->d_secsize) != 0 ||
1574 (bp->b_bcount / wi->wi_softc->sc_dk.dk_label->d_secsize) >=
1575 (1 << NBBY)) {
1576 error = EINVAL;
1577 goto bad;
1578 }
1579
1580 /*
1581 * Make sure a timeout was supplied in the ioctl request
1582 */
1583
1584 if (wi->wi_atareq.timeout == 0) {
1585 error = EINVAL;
1586 goto bad;
1587 }
1588
1589 if (wi->wi_atareq.flags & ATACMD_READ)
1590 wdc_c.flags |= AT_READ;
1591 else if (wi->wi_atareq.flags & ATACMD_WRITE)
1592 wdc_c.flags |= AT_WRITE;
1593
1594 if (wi->wi_atareq.flags & ATACMD_READREG)
1595 wdc_c.flags |= AT_READREG;
1596
1597 wdc_c.flags |= AT_WAIT;
1598
1599 wdc_c.timeout = wi->wi_atareq.timeout;
1600 wdc_c.r_command = wi->wi_atareq.command;
1601 wdc_c.r_head = wi->wi_atareq.head & 0x0f;
1602 wdc_c.r_cyl = wi->wi_atareq.cylinder;
1603 wdc_c.r_sector = wi->wi_atareq.sec_num;
1604 wdc_c.r_count = wi->wi_atareq.sec_count;
1605 wdc_c.r_precomp = wi->wi_atareq.features;
1606 wdc_c.r_st_bmask = WDCS_DRDY;
1607 wdc_c.r_st_pmask = WDCS_DRDY;
1608 wdc_c.data = wi->wi_bp.b_data;
1609 wdc_c.bcount = wi->wi_bp.b_bcount;
1610
1611 if (wi->wi_softc->atabus->ata_exec_command(wi->wi_softc->drvp, &wdc_c)
1612 != WDC_COMPLETE) {
1613 wi->wi_atareq.retsts = ATACMD_ERROR;
1614 goto bad;
1615 }
1616
1617 if (wdc_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
1618 if (wdc_c.flags & AT_ERROR) {
1619 wi->wi_atareq.retsts = ATACMD_ERROR;
1620 wi->wi_atareq.error = wdc_c.r_error;
1621 } else if (wdc_c.flags & AT_DF)
1622 wi->wi_atareq.retsts = ATACMD_DF;
1623 else
1624 wi->wi_atareq.retsts = ATACMD_TIMEOUT;
1625 } else {
1626 wi->wi_atareq.retsts = ATACMD_OK;
1627 if (wi->wi_atareq.flags & ATACMD_READREG) {
1628 wi->wi_atareq.head = wdc_c.r_head ;
1629 wi->wi_atareq.cylinder = wdc_c.r_cyl;
1630 wi->wi_atareq.sec_num = wdc_c.r_sector;
1631 wi->wi_atareq.sec_count = wdc_c.r_count;
1632 wi->wi_atareq.features = wdc_c.r_precomp;
1633 wi->wi_atareq.error = wdc_c.r_error;
1634 }
1635 }
1636
1637 bp->b_error = 0;
1638 biodone(bp);
1639 return;
1640 bad:
1641 bp->b_flags |= B_ERROR;
1642 bp->b_error = error;
1643 biodone(bp);
1644 }
1645