This source file includes following definitions.
- wdprobe
- wdattach
- wdactivate
- wddetach
- wdstrategy
- wdstart
- __wdstart
- wddone
- wdrestart
- wdread
- wdwrite
- wdopen
- wdclose
- wdgetdefaultlabel
- wdgetdisklabel
- wdioctl
- wdformat
- wdsize
- wddump
- wd_get_params
- wd_flushcache
- wd_shutdown
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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 #include <sys/vnode.h>
89
90 #include <uvm/uvm_extern.h>
91
92 #include <machine/intr.h>
93 #include <machine/bus.h>
94
95 #include <dev/ata/atareg.h>
96 #include <dev/ata/atavar.h>
97 #include <dev/ata/wdvar.h>
98 #include <dev/ic/wdcreg.h>
99 #include <dev/ic/wdcvar.h>
100 #if 0
101 #include "locators.h"
102 #endif
103
104 #define LBA48_THRESHOLD (0xfffffff)
105
106 #define WDIORETRIES_SINGLE 4
107 #define WDIORETRIES 5
108 #define RECOVERYTIME hz/2
109
110 #define DEBUG_INTR 0x01
111 #define DEBUG_XFERS 0x02
112 #define DEBUG_STATUS 0x04
113 #define DEBUG_FUNCS 0x08
114 #define DEBUG_PROBE 0x10
115 #ifdef WDCDEBUG
116 extern int wdcdebug_wd_mask;
117 #define WDCDEBUG_PRINT(args, level) do { \
118 if ((wdcdebug_wd_mask & (level)) != 0) \
119 printf args; \
120 } while (0)
121 #else
122 #define WDCDEBUG_PRINT(args, level)
123 #endif
124
125 struct wd_softc {
126
127 struct device sc_dev;
128 struct disk sc_dk;
129 struct buf sc_q;
130
131 struct ata_bio sc_wdc_bio;
132 struct buf *sc_bp;
133 struct ata_drive_datas *drvp;
134 int openings;
135 struct ataparams sc_params;
136 int sc_flags;
137 #define WDF_LOCKED 0x01
138 #define WDF_WANTED 0x02
139 #define WDF_WLABEL 0x04
140 #define WDF_LABELLING 0x08
141
142
143
144
145 #define WDF_LOADED 0x10
146 #define WDF_WAIT 0x20
147 #define WDF_LBA 0x40
148 #define WDF_LBA48 0x80
149
150 u_int64_t sc_capacity;
151 int cyl;
152 int heads;
153 int sectors;
154 int retries;
155 struct timeout sc_restart_timeout;
156 void *sc_sdhook;
157 };
158
159 #define sc_drive sc_wdc_bio.drive
160 #define sc_mode sc_wdc_bio.mode
161 #define sc_multi sc_wdc_bio.multi
162
163 int wdprobe(struct device *, void *, void *);
164 void wdattach(struct device *, struct device *, void *);
165 int wddetach(struct device *, int);
166 int wdactivate(struct device *, enum devact);
167 int wdprint(void *, char *);
168
169 struct cfattach wd_ca = {
170 sizeof(struct wd_softc), wdprobe, wdattach,
171 wddetach, wdactivate
172 };
173
174 struct cfdriver wd_cd = {
175 NULL, "wd", DV_DISK
176 };
177
178 void wdgetdefaultlabel(struct wd_softc *, struct disklabel *);
179 void wdgetdisklabel(dev_t dev, struct wd_softc *, struct disklabel *, int);
180 void wdstrategy(struct buf *);
181 void wdstart(void *);
182 void __wdstart(struct wd_softc*, struct buf *);
183 void wdrestart(void *);
184 int wd_get_params(struct wd_softc *, u_int8_t, struct ataparams *);
185 void wd_flushcache(struct wd_softc *, int);
186 void wd_shutdown(void *);
187
188 struct dkdriver wddkdriver = { wdstrategy };
189
190
191 cdev_decl(wd);
192 bdev_decl(wd);
193
194 #define wdlock(wd) disk_lock(&(wd)->sc_dk)
195 #define wdunlock(wd) disk_unlock(&(wd)->sc_dk)
196 #define wdlookup(unit) (struct wd_softc *)device_lookup(&wd_cd, (unit))
197
198
199 int
200 wdprobe(struct device *parent, void *match_, void *aux)
201 {
202 struct ata_atapi_attach *aa_link = aux;
203 struct cfdata *match = match_;
204
205 if (aa_link == NULL)
206 return 0;
207 if (aa_link->aa_type != T_ATA)
208 return 0;
209
210 if (match->cf_loc[0] != -1 &&
211 match->cf_loc[0] != aa_link->aa_channel)
212 return 0;
213
214 if (match->cf_loc[1] != -1 &&
215 match->cf_loc[1] != aa_link->aa_drv_data->drive)
216 return 0;
217
218 return 1;
219 }
220
221 void
222 wdattach(struct device *parent, struct device *self, void *aux)
223 {
224 struct wd_softc *wd = (void *)self;
225 struct ata_atapi_attach *aa_link= aux;
226 struct wdc_command wdc_c;
227 int i, blank;
228 char buf[41], c, *p, *q;
229 WDCDEBUG_PRINT(("wdattach\n"), DEBUG_FUNCS | DEBUG_PROBE);
230
231 wd->openings = aa_link->aa_openings;
232 wd->drvp = aa_link->aa_drv_data;
233
234 strlcpy(wd->drvp->drive_name, wd->sc_dev.dv_xname,
235 sizeof(wd->drvp->drive_name));
236 wd->drvp->cf_flags = wd->sc_dev.dv_cfdata->cf_flags;
237
238 if ((NERRS_MAX - 2) > 0)
239 wd->drvp->n_dmaerrs = NERRS_MAX - 2;
240 else
241 wd->drvp->n_dmaerrs = 0;
242
243
244 if (wd_get_params(wd, at_poll, &wd->sc_params) != 0) {
245 printf("%s: IDENTIFY failed\n", wd->sc_dev.dv_xname);
246 return;
247 }
248
249 for (blank = 0, p = wd->sc_params.atap_model, q = buf, i = 0;
250 i < sizeof(wd->sc_params.atap_model); i++) {
251 c = *p++;
252 if (c == '\0')
253 break;
254 if (c != ' ') {
255 if (blank) {
256 *q++ = ' ';
257 blank = 0;
258 }
259 *q++ = c;
260 } else
261 blank = 1;
262 }
263 *q++ = '\0';
264
265 printf(": <%s>\n", buf);
266
267 wdc_probe_caps(wd->drvp, &wd->sc_params);
268 wdc_print_caps(wd->drvp);
269
270 if ((wd->sc_params.atap_multi & 0xff) > 1) {
271 wd->sc_multi = wd->sc_params.atap_multi & 0xff;
272 } else {
273 wd->sc_multi = 1;
274 }
275
276 printf("%s: %d-sector PIO,", wd->sc_dev.dv_xname, wd->sc_multi);
277
278
279
280 if ((wd->sc_params.atap_cmd2_en & ATAPI_CMD2_48AD) != 0)
281 wd->sc_flags |= WDF_LBA48;
282
283
284 if ((wd->sc_params.atap_capabilities1 & WDC_CAP_LBA) != 0)
285 wd->sc_flags |= WDF_LBA;
286 #if 0
287
288 if (wd->sc_params.atap_ataversion != 0xffff &&
289 wd->sc_params.atap_ataversion >= WDC_VER_ATA4)
290 wd->sc_flags |= WDF_LBA;
291 #endif
292
293 if ((wd->sc_flags & WDF_LBA48) != 0) {
294 wd->sc_capacity =
295 (((u_int64_t)wd->sc_params.atap_max_lba[3] << 48) |
296 ((u_int64_t)wd->sc_params.atap_max_lba[2] << 32) |
297 ((u_int64_t)wd->sc_params.atap_max_lba[1] << 16) |
298 (u_int64_t)wd->sc_params.atap_max_lba[0]);
299 printf(" LBA48, %lluMB, %llu sectors\n",
300 wd->sc_capacity / (1048576 / DEV_BSIZE),
301 wd->sc_capacity);
302 } else if ((wd->sc_flags & WDF_LBA) != 0) {
303 wd->sc_capacity =
304 (wd->sc_params.atap_capacity[1] << 16) |
305 wd->sc_params.atap_capacity[0];
306 printf(" LBA, %lluMB, %llu sectors\n",
307 wd->sc_capacity / (1048576 / DEV_BSIZE),
308 wd->sc_capacity);
309 } else {
310 wd->sc_capacity =
311 wd->sc_params.atap_cylinders *
312 wd->sc_params.atap_heads *
313 wd->sc_params.atap_sectors;
314 printf(" CHS, %lluMB, %d cyl, %d head, %d sec, %llu sectors\n",
315 wd->sc_capacity / (1048576 / DEV_BSIZE),
316 wd->sc_params.atap_cylinders,
317 wd->sc_params.atap_heads,
318 wd->sc_params.atap_sectors,
319 wd->sc_capacity);
320 }
321 WDCDEBUG_PRINT(("%s: atap_dmatiming_mimi=%d, atap_dmatiming_recom=%d\n",
322 self->dv_xname, wd->sc_params.atap_dmatiming_mimi,
323 wd->sc_params.atap_dmatiming_recom), DEBUG_PROBE);
324
325
326
327
328
329
330
331
332 bzero(&wdc_c, sizeof(struct wdc_command));
333
334 wdc_c.r_command = WDCC_SEC_FREEZE_LOCK;
335 wdc_c.timeout = 1000;
336 wdc_c.flags = at_poll;
337 if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) {
338 printf("%s: freeze lock command didn't complete\n",
339 wd->sc_dev.dv_xname);
340 }
341
342
343
344
345 wd->sc_dk.dk_driver = &wddkdriver;
346 wd->sc_dk.dk_name = wd->sc_dev.dv_xname;
347 disk_attach(&wd->sc_dk);
348 wd->sc_wdc_bio.lp = wd->sc_dk.dk_label;
349 wd->sc_sdhook = shutdownhook_establish(wd_shutdown, wd);
350 if (wd->sc_sdhook == NULL)
351 printf("%s: WARNING: unable to establish shutdown hook\n",
352 wd->sc_dev.dv_xname);
353 timeout_set(&wd->sc_restart_timeout, wdrestart, wd);
354 }
355
356 int
357 wdactivate(struct device *self, enum devact act)
358 {
359 int rv = 0;
360
361 switch (act) {
362 case DVACT_ACTIVATE:
363 break;
364
365 case DVACT_DEACTIVATE:
366
367
368
369 break;
370 }
371 return (rv);
372 }
373
374 int
375 wddetach(struct device *self, int flags)
376 {
377 struct wd_softc *sc = (struct wd_softc *)self;
378 struct buf *dp, *bp;
379 int s, bmaj, cmaj, mn;
380
381
382 s = splbio();
383 for (dp = &sc->sc_q; (bp = dp->b_actf) != NULL; ) {
384 dp->b_actf = bp->b_actf;
385 bp->b_error = ENXIO;
386 bp->b_flags |= B_ERROR;
387 biodone(bp);
388 }
389 splx(s);
390
391
392 mn = DISKMINOR(self->dv_unit, 0);
393
394 for (bmaj = 0; bmaj < nblkdev; bmaj++)
395 if (bdevsw[bmaj].d_open == wdopen)
396 vdevgone(bmaj, mn, mn + MAXPARTITIONS - 1, VBLK);
397 for (cmaj = 0; cmaj < nchrdev; cmaj++)
398 if (cdevsw[cmaj].d_open == wdopen)
399 vdevgone(cmaj, mn, mn + MAXPARTITIONS - 1, VCHR);
400
401
402 if (sc->sc_sdhook != NULL)
403 shutdownhook_disestablish(sc->sc_sdhook);
404
405
406 disk_detach(&sc->sc_dk);
407
408 return (0);
409 }
410
411
412
413
414
415 void
416 wdstrategy(struct buf *bp)
417 {
418 struct wd_softc *wd;
419 int s;
420
421 wd = wdlookup(DISKUNIT(bp->b_dev));
422 if (wd == NULL) {
423 bp->b_error = ENXIO;
424 goto bad;
425 }
426
427 WDCDEBUG_PRINT(("wdstrategy (%s)\n", wd->sc_dev.dv_xname),
428 DEBUG_XFERS);
429
430
431 if (bp->b_blkno < 0 ||
432 (bp->b_bcount % wd->sc_dk.dk_label->d_secsize) != 0 ||
433 (bp->b_bcount / wd->sc_dk.dk_label->d_secsize) >= (1 << NBBY)) {
434 bp->b_error = EINVAL;
435 goto bad;
436 }
437
438
439 if ((wd->sc_flags & WDF_LOADED) == 0) {
440 bp->b_error = EIO;
441 goto bad;
442 }
443
444
445 if (bp->b_bcount == 0)
446 goto done;
447
448
449
450
451
452 if (DISKPART(bp->b_dev) != RAW_PART &&
453 bounds_check_with_label(bp, wd->sc_dk.dk_label,
454 (wd->sc_flags & (WDF_WLABEL|WDF_LABELLING)) != 0) <= 0)
455 goto done;
456
457 s = splbio();
458 disksort(&wd->sc_q, bp);
459 wdstart(wd);
460 splx(s);
461 device_unref(&wd->sc_dev);
462 return;
463 bad:
464 bp->b_flags |= B_ERROR;
465 done:
466
467 bp->b_resid = bp->b_bcount;
468 s = splbio();
469 biodone(bp);
470 splx(s);
471 if (wd != NULL)
472 device_unref(&wd->sc_dev);
473 }
474
475
476
477
478 void
479 wdstart(void *arg)
480 {
481 struct wd_softc *wd = arg;
482 struct buf *dp, *bp = NULL;
483
484 WDCDEBUG_PRINT(("wdstart %s\n", wd->sc_dev.dv_xname),
485 DEBUG_XFERS);
486 while (wd->openings > 0) {
487
488
489 dp = &wd->sc_q;
490 if ((bp = dp->b_actf) == NULL)
491 return;
492 dp->b_actf = bp->b_actf;
493
494
495
496
497 wd->openings--;
498
499 wd->retries = 0;
500 __wdstart(wd, bp);
501 }
502 }
503
504 void
505 __wdstart(struct wd_softc *wd, struct buf *bp)
506 {
507 daddr64_t nblks;
508
509 wd->sc_wdc_bio.blkno = bp->b_blkno +
510 DL_GETPOFFSET(&wd->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)]);
511 wd->sc_wdc_bio.blkno /= (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
512 wd->sc_wdc_bio.blkdone =0;
513 wd->sc_bp = bp;
514
515
516
517
518
519 if (wd->sc_multi == 1 || wd->retries >= WDIORETRIES_SINGLE)
520 wd->sc_wdc_bio.flags = ATA_SINGLE;
521 else
522 wd->sc_wdc_bio.flags = 0;
523 nblks = bp->b_bcount / wd->sc_dk.dk_label->d_secsize;
524 if ((wd->sc_flags & WDF_LBA48) &&
525
526 ((wd->sc_wdc_bio.blkno + nblks - 1 > LBA48_THRESHOLD) ||
527 (nblks > 0xff)))
528 wd->sc_wdc_bio.flags |= ATA_LBA48;
529 if (wd->sc_flags & WDF_LBA)
530 wd->sc_wdc_bio.flags |= ATA_LBA;
531 if (bp->b_flags & B_READ)
532 wd->sc_wdc_bio.flags |= ATA_READ;
533 wd->sc_wdc_bio.bcount = bp->b_bcount;
534 wd->sc_wdc_bio.databuf = bp->b_data;
535 wd->sc_wdc_bio.wd = wd;
536
537 disk_busy(&wd->sc_dk);
538 switch (wdc_ata_bio(wd->drvp, &wd->sc_wdc_bio)) {
539 case WDC_TRY_AGAIN:
540 timeout_add(&wd->sc_restart_timeout, hz);
541 break;
542 case WDC_QUEUED:
543 break;
544 case WDC_COMPLETE:
545
546
547
548
549 #if 0
550 if (wd->sc_wdc_bio.flags & ATA_POLL)
551 wddone(wd);
552 #endif
553 break;
554 default:
555 panic("__wdstart: bad return code from wdc_ata_bio()");
556 }
557 }
558
559 void
560 wddone(void *v)
561 {
562 struct wd_softc *wd = v;
563 struct buf *bp = wd->sc_bp;
564 char buf[256], *errbuf = buf;
565 WDCDEBUG_PRINT(("wddone %s\n", wd->sc_dev.dv_xname),
566 DEBUG_XFERS);
567
568 bp->b_resid = wd->sc_wdc_bio.bcount;
569 errbuf[0] = '\0';
570 switch (wd->sc_wdc_bio.error) {
571 case ERR_NODEV:
572 bp->b_flags |= B_ERROR;
573 bp->b_error = ENXIO;
574 break;
575 case ERR_DMA:
576 errbuf = "DMA error";
577 goto retry;
578 case ERR_DF:
579 errbuf = "device fault";
580 goto retry;
581 case TIMEOUT:
582 errbuf = "device timeout";
583 goto retry;
584 case ERROR:
585
586 if (wd->sc_wdc_bio.r_error != 0 &&
587 (wd->sc_wdc_bio.r_error & ~(WDCE_MC | WDCE_MCR)) == 0)
588 goto noerror;
589 ata_perror(wd->drvp, wd->sc_wdc_bio.r_error, errbuf,
590 sizeof buf);
591 retry:
592
593 wdc_reset_channel(wd->drvp);
594 diskerr(bp, "wd", errbuf, LOG_PRINTF,
595 wd->sc_wdc_bio.blkdone, wd->sc_dk.dk_label);
596 if (wd->retries++ < WDIORETRIES) {
597 printf(", retrying\n");
598 timeout_add(&wd->sc_restart_timeout, RECOVERYTIME);
599 return;
600 }
601 printf("\n");
602 bp->b_flags |= B_ERROR;
603 bp->b_error = EIO;
604 break;
605 case NOERROR:
606 noerror: if ((wd->sc_wdc_bio.flags & ATA_CORR) || wd->retries > 0)
607 printf("%s: soft error (corrected)\n",
608 wd->sc_dev.dv_xname);
609 }
610 disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid),
611 (bp->b_flags & B_READ));
612 biodone(bp);
613 wd->openings++;
614 wdstart(wd);
615 }
616
617 void
618 wdrestart(void *v)
619 {
620 struct wd_softc *wd = v;
621 struct buf *bp = wd->sc_bp;
622 int s;
623 WDCDEBUG_PRINT(("wdrestart %s\n", wd->sc_dev.dv_xname),
624 DEBUG_XFERS);
625
626 s = splbio();
627 disk_unbusy(&wd->sc_dk, 0, (bp->b_flags & B_READ));
628 __wdstart(v, bp);
629 splx(s);
630 }
631
632 int
633 wdread(dev_t dev, struct uio *uio, int flags)
634 {
635
636 WDCDEBUG_PRINT(("wdread\n"), DEBUG_XFERS);
637 return (physio(wdstrategy, NULL, dev, B_READ, minphys, uio));
638 }
639
640 int
641 wdwrite(dev_t dev, struct uio *uio, int flags)
642 {
643
644 WDCDEBUG_PRINT(("wdwrite\n"), DEBUG_XFERS);
645 return (physio(wdstrategy, NULL, dev, B_WRITE, minphys, uio));
646 }
647
648 int
649 wdopen(dev_t dev, int flag, int fmt, struct proc *p)
650 {
651 struct wd_softc *wd;
652 int unit, part;
653 int error;
654
655 WDCDEBUG_PRINT(("wdopen\n"), DEBUG_FUNCS);
656
657 unit = DISKUNIT(dev);
658 wd = wdlookup(unit);
659 if (wd == NULL)
660 return ENXIO;
661
662
663
664
665
666 if ((error = wdlock(wd)) != 0)
667 goto bad4;
668
669 if (wd->sc_dk.dk_openmask != 0) {
670
671
672
673
674 if ((wd->sc_flags & WDF_LOADED) == 0) {
675 error = EIO;
676 goto bad3;
677 }
678 } else {
679 if ((wd->sc_flags & WDF_LOADED) == 0) {
680 wd->sc_flags |= WDF_LOADED;
681
682
683 wd_get_params(wd, AT_WAIT, &wd->sc_params);
684
685
686 wdgetdisklabel(dev, wd, wd->sc_dk.dk_label, 0);
687 }
688 }
689
690 part = DISKPART(dev);
691
692
693 if (part != RAW_PART &&
694 (part >= wd->sc_dk.dk_label->d_npartitions ||
695 wd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
696 error = ENXIO;
697 goto bad;
698 }
699
700
701 switch (fmt) {
702 case S_IFCHR:
703 wd->sc_dk.dk_copenmask |= (1 << part);
704 break;
705 case S_IFBLK:
706 wd->sc_dk.dk_bopenmask |= (1 << part);
707 break;
708 }
709 wd->sc_dk.dk_openmask =
710 wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
711
712 wdunlock(wd);
713 device_unref(&wd->sc_dev);
714 return 0;
715
716 bad:
717 if (wd->sc_dk.dk_openmask == 0) {
718 }
719
720 bad3:
721 wdunlock(wd);
722 bad4:
723 device_unref(&wd->sc_dev);
724 return error;
725 }
726
727 int
728 wdclose(dev_t dev, int flag, int fmt, struct proc *p)
729 {
730 struct wd_softc *wd;
731 int part = DISKPART(dev);
732 int error = 0;
733
734 wd = wdlookup(DISKUNIT(dev));
735 if (wd == NULL)
736 return ENXIO;
737
738 WDCDEBUG_PRINT(("wdclose\n"), DEBUG_FUNCS);
739 if ((error = wdlock(wd)) != 0)
740 goto exit;
741
742 switch (fmt) {
743 case S_IFCHR:
744 wd->sc_dk.dk_copenmask &= ~(1 << part);
745 break;
746 case S_IFBLK:
747 wd->sc_dk.dk_bopenmask &= ~(1 << part);
748 break;
749 }
750 wd->sc_dk.dk_openmask =
751 wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
752
753 if (wd->sc_dk.dk_openmask == 0) {
754 wd_flushcache(wd, 0);
755
756 }
757
758 wdunlock(wd);
759
760 exit:
761 device_unref(&wd->sc_dev);
762 return (error);
763 }
764
765 void
766 wdgetdefaultlabel(struct wd_softc *wd, struct disklabel *lp)
767 {
768 WDCDEBUG_PRINT(("wdgetdefaultlabel\n"), DEBUG_FUNCS);
769 bzero(lp, sizeof(struct disklabel));
770
771 lp->d_secsize = DEV_BSIZE;
772 DL_SETDSIZE(lp, wd->sc_capacity);
773 lp->d_ntracks = wd->sc_params.atap_heads;
774 lp->d_nsectors = wd->sc_params.atap_sectors;
775 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
776 lp->d_ncylinders = DL_GETDSIZE(lp) / lp->d_secpercyl;
777 if (wd->drvp->ata_vers == -1) {
778 lp->d_type = DTYPE_ST506;
779 strncpy(lp->d_typename, "ST506/MFM/RLL", sizeof lp->d_typename);
780 } else {
781 lp->d_type = DTYPE_ESDI;
782 strncpy(lp->d_typename, "ESDI/IDE disk", sizeof lp->d_typename);
783 }
784
785 strncpy(lp->d_packname, wd->sc_params.atap_model, sizeof lp->d_packname);
786 lp->d_rpm = 3600;
787 lp->d_interleave = 1;
788 lp->d_flags = 0;
789 lp->d_version = 1;
790
791 lp->d_magic = DISKMAGIC;
792 lp->d_magic2 = DISKMAGIC;
793 lp->d_checksum = dkcksum(lp);
794 }
795
796
797
798
799 void
800 wdgetdisklabel(dev_t dev, struct wd_softc *wd, struct disklabel *lp,
801 int spoofonly)
802 {
803 char *errstring;
804
805 WDCDEBUG_PRINT(("wdgetdisklabel\n"), DEBUG_FUNCS);
806
807 wdgetdefaultlabel(wd, lp);
808
809 if (wd->drvp->state > RECAL)
810 wd->drvp->drive_flags |= DRIVE_RESET;
811 errstring = readdisklabel(DISKLABELDEV(dev), wdstrategy, lp,
812 spoofonly);
813 if (wd->drvp->state > RECAL)
814 wd->drvp->drive_flags |= DRIVE_RESET;
815 if (errstring) {
816
817 }
818 }
819
820 int
821 wdioctl(dev_t dev, u_long xfer, caddr_t addr, int flag, struct proc *p)
822 {
823 struct wd_softc *wd;
824 struct disklabel *lp;
825 int error = 0;
826
827 WDCDEBUG_PRINT(("wdioctl\n"), DEBUG_FUNCS);
828
829 wd = wdlookup(DISKUNIT(dev));
830 if (wd == NULL)
831 return ENXIO;
832
833 if ((wd->sc_flags & WDF_LOADED) == 0) {
834 error = EIO;
835 goto exit;
836 }
837
838 switch (xfer) {
839 case DIOCRLDINFO:
840 lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK);
841 wdgetdisklabel(dev, wd, lp, 0);
842 bcopy(lp, wd->sc_dk.dk_label, sizeof(*lp));
843 free(lp, M_TEMP);
844 goto exit;
845
846 case DIOCGPDINFO:
847 wdgetdisklabel(dev, wd, (struct disklabel *)addr, 1);
848 goto exit;
849
850 case DIOCGDINFO:
851 *(struct disklabel *)addr = *(wd->sc_dk.dk_label);
852 goto exit;
853
854 case DIOCGPART:
855 ((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label;
856 ((struct partinfo *)addr)->part =
857 &wd->sc_dk.dk_label->d_partitions[DISKPART(dev)];
858 goto exit;
859
860 case DIOCWDINFO:
861 case DIOCSDINFO:
862 if ((flag & FWRITE) == 0) {
863 error = EBADF;
864 goto exit;
865 }
866
867 if ((error = wdlock(wd)) != 0)
868 goto exit;
869 wd->sc_flags |= WDF_LABELLING;
870
871 error = setdisklabel(wd->sc_dk.dk_label,
872 (struct disklabel *)addr, 0);
873 if (error == 0) {
874 if (wd->drvp->state > RECAL)
875 wd->drvp->drive_flags |= DRIVE_RESET;
876 if (xfer == DIOCWDINFO)
877 error = writedisklabel(DISKLABELDEV(dev),
878 wdstrategy, wd->sc_dk.dk_label);
879 }
880
881 wd->sc_flags &= ~WDF_LABELLING;
882 wdunlock(wd);
883 goto exit;
884
885 case DIOCWLABEL:
886 if ((flag & FWRITE) == 0) {
887 error = EBADF;
888 goto exit;
889 }
890
891 if (*(int *)addr)
892 wd->sc_flags |= WDF_WLABEL;
893 else
894 wd->sc_flags &= ~WDF_WLABEL;
895 goto exit;
896
897 #ifdef notyet
898 case DIOCWFORMAT:
899 if ((flag & FWRITE) == 0)
900 return EBADF;
901 {
902 struct format_op *fop;
903 struct iovec aiov;
904 struct uio auio;
905
906 fop = (struct format_op *)addr;
907 aiov.iov_base = fop->df_buf;
908 aiov.iov_len = fop->df_count;
909 auio.uio_iov = &aiov;
910 auio.uio_iovcnt = 1;
911 auio.uio_resid = fop->df_count;
912 auio.uio_segflg = 0;
913 auio.uio_offset =
914 fop->df_startblk * wd->sc_dk.dk_label->d_secsize;
915 auio.uio_procp = p;
916 error = physio(wdformat, NULL, dev, B_WRITE, minphys,
917 &auio);
918 fop->df_count -= auio.uio_resid;
919 fop->df_reg[0] = wdc->sc_status;
920 fop->df_reg[1] = wdc->sc_error;
921 goto exit;
922 }
923 #endif
924
925 default:
926 error = wdc_ioctl(wd->drvp, xfer, addr, flag, p);
927 goto exit;
928 }
929
930 #ifdef DIAGNOSTIC
931 panic("wdioctl: impossible");
932 #endif
933
934 exit:
935 device_unref(&wd->sc_dev);
936 return (error);
937 }
938
939 #ifdef B_FORMAT
940 int
941 wdformat(struct buf *bp)
942 {
943
944 bp->b_flags |= B_FORMAT;
945 return wdstrategy(bp);
946 }
947 #endif
948
949 daddr64_t
950 wdsize(dev_t dev)
951 {
952 struct wd_softc *wd;
953 int part, omask;
954 int64_t size;
955
956 WDCDEBUG_PRINT(("wdsize\n"), DEBUG_FUNCS);
957
958 wd = wdlookup(DISKUNIT(dev));
959 if (wd == NULL)
960 return (-1);
961
962 part = DISKPART(dev);
963 omask = wd->sc_dk.dk_openmask & (1 << part);
964
965 if (omask == 0 && wdopen(dev, 0, S_IFBLK, NULL) != 0) {
966 size = -1;
967 goto exit;
968 }
969
970 size = DL_GETPSIZE(&wd->sc_dk.dk_label->d_partitions[part]) *
971 (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
972 if (omask == 0 && wdclose(dev, 0, S_IFBLK, NULL) != 0)
973 size = -1;
974
975 exit:
976 device_unref(&wd->sc_dev);
977 return (size);
978 }
979
980
981 static int wddoingadump = 0;
982 static int wddumprecalibrated = 0;
983 static int wddumpmulti = 1;
984
985
986
987
988 int
989 wddump(dev_t dev, daddr64_t blkno, caddr_t va, size_t size)
990 {
991 struct wd_softc *wd;
992 struct disklabel *lp;
993 int unit, part;
994 int nblks;
995 int err;
996 char errbuf[256];
997
998
999 if (wddoingadump)
1000 return EFAULT;
1001 wddoingadump = 1;
1002
1003 unit = DISKUNIT(dev);
1004 wd = wdlookup(unit);
1005 if (wd == NULL)
1006 return ENXIO;
1007
1008 part = DISKPART(dev);
1009
1010
1011 if (wd->drvp->state < READY)
1012 return ENXIO;
1013
1014
1015 lp = wd->sc_dk.dk_label;
1016 if ((size % lp->d_secsize) != 0)
1017 return EFAULT;
1018 nblks = size / lp->d_secsize;
1019 blkno = blkno / (lp->d_secsize / DEV_BSIZE);
1020
1021
1022 if ((blkno < 0) || ((blkno + nblks) > DL_GETPSIZE(&lp->d_partitions[part])))
1023 return EINVAL;
1024
1025
1026 blkno += DL_GETPOFFSET(&lp->d_partitions[part]);
1027
1028
1029 if (wddumprecalibrated == 0) {
1030 wddumpmulti = wd->sc_multi;
1031 wddumprecalibrated = 1;
1032 wd->drvp->state = RECAL;
1033 }
1034
1035 while (nblks > 0) {
1036 again:
1037 wd->sc_wdc_bio.blkno = blkno;
1038 wd->sc_wdc_bio.flags = ATA_POLL;
1039 if (wddumpmulti == 1)
1040 wd->sc_wdc_bio.flags |= ATA_SINGLE;
1041 if (wd->sc_flags & WDF_LBA48)
1042 wd->sc_wdc_bio.flags |= ATA_LBA48;
1043 if (wd->sc_flags & WDF_LBA)
1044 wd->sc_wdc_bio.flags |= ATA_LBA;
1045 wd->sc_wdc_bio.bcount =
1046 min(nblks, wddumpmulti) * lp->d_secsize;
1047 wd->sc_wdc_bio.databuf = va;
1048 wd->sc_wdc_bio.wd = wd;
1049 #ifndef WD_DUMP_NOT_TRUSTED
1050 switch (wdc_ata_bio(wd->drvp, &wd->sc_wdc_bio)) {
1051 case WDC_TRY_AGAIN:
1052 panic("wddump: try again");
1053 break;
1054 case WDC_QUEUED:
1055 panic("wddump: polled command has been queued");
1056 break;
1057 case WDC_COMPLETE:
1058 break;
1059 }
1060 switch(wd->sc_wdc_bio.error) {
1061 case TIMEOUT:
1062 printf("wddump: device timed out");
1063 err = EIO;
1064 break;
1065 case ERR_DF:
1066 printf("wddump: drive fault");
1067 err = EIO;
1068 break;
1069 case ERR_DMA:
1070 printf("wddump: DMA error");
1071 err = EIO;
1072 break;
1073 case ERROR:
1074 errbuf[0] = '\0';
1075 ata_perror(wd->drvp, wd->sc_wdc_bio.r_error, errbuf,
1076 sizeof errbuf);
1077 printf("wddump: %s", errbuf);
1078 err = EIO;
1079 break;
1080 case NOERROR:
1081 err = 0;
1082 break;
1083 default:
1084 panic("wddump: unknown error type");
1085 }
1086 if (err != 0) {
1087 if (wddumpmulti != 1) {
1088 wddumpmulti = 1;
1089 printf(", retrying\n");
1090 goto again;
1091 }
1092 printf("\n");
1093 return err;
1094 }
1095 #else
1096
1097 printf("wd%d: dump addr 0x%x, cylin %d, head %d, sector %d\n",
1098 unit, va, cylin, head, sector);
1099 delay(500 * 1000);
1100 #endif
1101
1102
1103 nblks -= min(nblks, wddumpmulti);
1104 blkno += min(nblks, wddumpmulti);
1105 va += min(nblks, wddumpmulti) * lp->d_secsize;
1106 }
1107
1108 wddoingadump = 0;
1109 return 0;
1110 }
1111
1112 int
1113 wd_get_params(struct wd_softc *wd, u_int8_t flags, struct ataparams *params)
1114 {
1115 switch (ata_get_params(wd->drvp, flags, params)) {
1116 case CMD_AGAIN:
1117 return 1;
1118 case CMD_ERR:
1119
1120 if (wd->sc_params.atap_cylinders != 0) {
1121 if (params != &wd->sc_params)
1122 bcopy(&wd->sc_params, params,
1123 sizeof(struct ataparams));
1124 return 0;
1125 }
1126
1127
1128
1129
1130
1131 bzero(params, sizeof(struct ataparams));
1132 strncpy(params->atap_model, "ST506",
1133 sizeof params->atap_model);
1134 params->atap_config = ATA_CFG_FIXED;
1135 params->atap_cylinders = 1024;
1136 params->atap_heads = 8;
1137 params->atap_sectors = 17;
1138 params->atap_multi = 1;
1139 params->atap_capabilities1 = params->atap_capabilities2 = 0;
1140 wd->drvp->ata_vers = -1;
1141 return 0;
1142 case CMD_OK:
1143 return 0;
1144 default:
1145 panic("wd_get_params: bad return code from ata_get_params");
1146
1147 }
1148 }
1149
1150 void
1151 wd_flushcache(struct wd_softc *wd, int flags)
1152 {
1153 struct wdc_command wdc_c;
1154
1155 if (wd->drvp->ata_vers < 4)
1156 return;
1157 bzero(&wdc_c, sizeof(struct wdc_command));
1158 wdc_c.r_command = (wd->sc_flags & WDF_LBA48 ? WDCC_FLUSHCACHE_EXT :
1159 WDCC_FLUSHCACHE);
1160 wdc_c.r_st_bmask = WDCS_DRDY;
1161 wdc_c.r_st_pmask = WDCS_DRDY;
1162 if (flags != 0) {
1163 wdc_c.flags = AT_POLL;
1164 } else {
1165 wdc_c.flags = AT_WAIT;
1166 }
1167 wdc_c.timeout = 30000;
1168 if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) {
1169 printf("%s: flush cache command didn't complete\n",
1170 wd->sc_dev.dv_xname);
1171 }
1172 if (wdc_c.flags & AT_TIMEOU) {
1173 printf("%s: flush cache command timeout\n",
1174 wd->sc_dev.dv_xname);
1175 }
1176 if (wdc_c.flags & AT_DF) {
1177 printf("%s: flush cache command: drive fault\n",
1178 wd->sc_dev.dv_xname);
1179 }
1180
1181
1182
1183
1184
1185 }
1186
1187 void
1188 wd_shutdown(void *arg)
1189 {
1190 struct wd_softc *wd = arg;
1191 wd_flushcache(wd, AT_POLL);
1192 }