FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/wd.c
1 /*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * William Jolitz.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * from: @(#)wd.c 7.2 (Berkeley) 5/9/91
37 * $FreeBSD: src/sys/i386/isa/wd.c,v 1.119.2.14 1999/09/05 08:13:41 peter Exp $
38 */
39
40 /* TODO:
41 * o Bump error count after timeout.
42 * o Satisfy ATA timing in all cases.
43 * o Finish merging berry/sos timeout code (bump error count...).
44 * o Merge/fix TIH/NetBSD bad144 code.
45 * o Don't use polling except for initialization. Need to
46 * reorganize the state machine. Then "extra" interrupts
47 * shouldn't happen (except maybe one for initialization).
48 * o Fix disklabel, boot and driver inconsistencies with
49 * bad144 in standard versions.
50 * o Support extended DOS partitions.
51 * o Support swapping to DOS partitions.
52 * o Handle bad sectors, clustering, disklabelling, DOS
53 * partitions and swapping driver-independently. Use
54 * i386/dkbad.c for bad sectors. Swapping will need new
55 * driver entries for polled reinit and polled write).
56 */
57
58 #include "wd.h"
59 #ifdef NWDC
60 #undef NWDC
61 #endif
62
63 #include "wdc.h"
64 #include "opt_wd.h"
65 #include "opt_atapi.h"
66
67 #if NWDC > 0
68
69 #include <sys/param.h>
70 #include <sys/dkbad.h>
71 #include <sys/systm.h>
72 #include <sys/kernel.h>
73 #include <sys/conf.h>
74 #include <sys/disklabel.h>
75 #include <sys/diskslice.h>
76 #include <sys/buf.h>
77 #include <sys/malloc.h>
78 #ifdef DEVFS
79 #include <sys/devfsext.h>
80 #endif /*DEVFS*/
81 #include <machine/bootinfo.h>
82 #include <machine/clock.h>
83 #include <machine/cons.h>
84 #include <machine/md_var.h>
85 #include <i386/isa/isa.h>
86 #include <i386/isa/isa_device.h>
87 #include <i386/isa/wdreg.h>
88 #include <sys/syslog.h>
89 #include <sys/dkstat.h>
90 #include <vm/vm.h>
91 #include <vm/vm_prot.h>
92 #include <vm/pmap.h>
93
94
95 #ifdef ATAPI
96 #include <i386/isa/atapi.h>
97 #endif
98
99 #ifdef CMD640
100 #include <i386/isa/wdc_p.h>
101 #endif /*CMD640*/
102
103 extern void wdstart(int ctrlr);
104
105 #define TIMEOUT 10000
106 #define RETRIES 5 /* number of retries before giving up */
107 #define RECOVERYTIME 500000 /* usec for controller to recover after err */
108 #define MAXTRANSFER 255 /* max size of transfer in sectors */
109 /* correct max is 256 but some controllers */
110 /* can't handle that in all cases */
111 #define WDOPT_32BIT 0x8000
112 #define WDOPT_SLEEPHACK 0x4000
113 #define WDOPT_FORCEHD(x) (((x)&0x0f00)>>8)
114 #define WDOPT_MULTIMASK 0x00ff
115
116 /*
117 * This biotab field doubles as a field for the physical unit number on
118 * the controller.
119 */
120 #define id_physid id_scsiid
121
122 /*
123 * Drive states. Used to initialize drive.
124 */
125
126 #define CLOSED 0 /* disk is closed. */
127 #define WANTOPEN 1 /* open requested, not started */
128 #define RECAL 2 /* doing restore */
129 #define OPEN 3 /* done with open */
130
131 #define PRIMARY 0
132
133 /*
134 * Disk geometry. A small part of struct disklabel.
135 * XXX disklabel.5 contains an old clone of disklabel.h.
136 */
137 struct diskgeom {
138 u_long d_secsize; /* # of bytes per sector */
139 u_long d_nsectors; /* # of data sectors per track */
140 u_long d_ntracks; /* # of tracks per cylinder */
141 u_long d_ncylinders; /* # of data cylinders per unit */
142 u_long d_secpercyl; /* # of data sectors per cylinder */
143 u_long d_secperunit; /* # of data sectors per unit */
144 u_long d_precompcyl; /* XXX always 0 */
145 };
146
147 /*
148 * The structure of a disk drive.
149 */
150 struct disk {
151 long dk_bc; /* byte count left */
152 short dk_skip; /* blocks already transferred */
153 int dk_ctrlr; /* physical controller number */
154 #ifdef CMD640
155 int dk_ctrlr_cmd640;/* controller number for CMD640 quirk */
156 #endif
157 int dk_unit; /* physical unit number */
158 int dk_lunit; /* logical unit number */
159 char dk_state; /* control state */
160 u_char dk_status; /* copy of status reg. */
161 u_char dk_error; /* copy of error reg. */
162 u_char dk_timeout; /* countdown to next timeout */
163 int dk_port; /* i/o port base */
164 #ifdef DEVFS
165 void *dk_bdev; /* devfs token for whole disk */
166 void *dk_cdev; /* devfs token for raw whole disk */
167 #endif
168 u_long cfg_flags; /* configured characteristics */
169 short dk_flags; /* drive characteristics found */
170 #define DKFL_SINGLE 0x00004 /* sector at a time mode */
171 #define DKFL_ERROR 0x00008 /* processing a disk error */
172 #define DKFL_LABELLING 0x00080 /* readdisklabel() in progress */
173 #define DKFL_32BIT 0x00100 /* use 32-bit i/o mode */
174 #define DKFL_MULTI 0x00200 /* use multi-i/o mode */
175 #define DKFL_BADSCAN 0x00400 /* report all errors */
176 struct wdparams dk_params; /* ESDI/IDE drive/controller parameters */
177 int dk_dkunit; /* disk stats unit number */
178 int dk_multi; /* multi transfers */
179 int dk_currentiosize; /* current io size */
180 struct diskgeom dk_dd; /* device configuration data */
181 struct diskslices *dk_slices; /* virtual drives */
182 };
183
184 #define WD_COUNT_RETRIES
185 static int wdtest = 0;
186
187 static struct disk *wddrives[NWD]; /* table of units */
188 static struct buf_queue_head drive_queue[NWD]; /* head of queue per drive */
189 static struct {
190 int b_errcnt;
191 int b_active;
192 } wdutab[NWD];
193 /*
194 static struct buf wdtab[NWDC];
195 */
196 static struct {
197 struct buf_queue_head controller_queue;
198 int b_errcnt;
199 int b_active;
200 } wdtab[NWDC];
201
202 struct wddma wddma;
203
204 #ifdef notyet
205 static struct buf rwdbuf[NWD]; /* buffers for raw IO */
206 #endif
207
208 static int wdprobe(struct isa_device *dvp);
209 static int wdattach(struct isa_device *dvp);
210 static void wdustart(struct disk *du);
211 static int wdcontrol(struct buf *bp);
212 static int wdcommand(struct disk *du, u_int cylinder, u_int head,
213 u_int sector, u_int count, u_int command);
214 static int wdsetctlr(struct disk *du);
215 #if 0
216 static int wdwsetctlr(struct disk *du);
217 #endif
218 static int wdgetctlr(struct disk *du);
219 static void wderror(struct buf *bp, struct disk *du, char *mesg);
220 static void wdflushirq(struct disk *du, int old_ipl);
221 static int wdreset(struct disk *du);
222 static void wdsleep(int ctrlr, char *wmesg);
223 static void wdstrategy1(struct buf *bp);
224 static timeout_t wdtimeout;
225 static int wdunwedge(struct disk *du);
226 static int wdwait(struct disk *du, u_char bits_wanted, int timeout);
227
228 struct isa_driver wdcdriver = {
229 wdprobe, wdattach, "wdc",
230 };
231
232 static d_open_t wdopen;
233 static d_close_t wdclose;
234 static d_strategy_t wdstrategy;
235 static d_ioctl_t wdioctl;
236 static d_dump_t wddump;
237 static d_psize_t wdsize;
238
239 #define CDEV_MAJOR 3
240 #define BDEV_MAJOR 0
241 static struct cdevsw wd_cdevsw;
242 static struct bdevsw wd_bdevsw =
243 { wdopen, wdclose, wdstrategy, wdioctl, /**/
244 wddump, wdsize, 0, "wd", &wd_cdevsw, -1 };
245
246 #ifdef CMD640
247 static int atapictrlr;
248 static int eide_quirks;
249 #endif
250
251
252 /*
253 * Here we use the pci-subsystem to find out, whether there is
254 * a cmd640b-chip attached on this pci-bus. This public routine
255 * will be called by wdc_p.c .
256 */
257
258 #ifdef CMD640
259 void
260 wdc_pci(int quirks)
261 {
262 eide_quirks = quirks;
263 }
264 #endif
265
266 /*
267 * Probe for controller.
268 */
269 static int
270 wdprobe(struct isa_device *dvp)
271 {
272 int unit = dvp->id_unit;
273 struct disk *du;
274
275 if (unit >= NWDC)
276 return (0);
277
278 du = malloc(sizeof *du, M_TEMP, M_NOWAIT);
279 if (du == NULL)
280 return (0);
281 bzero(du, sizeof *du);
282 du->dk_ctrlr = dvp->id_unit;
283 du->dk_port = dvp->id_iobase;
284
285
286 /* check if we have registers that work */
287 outb(du->dk_port + wd_sdh, WDSD_IBM); /* set unit 0 */
288 outb(du->dk_port + wd_cyl_lo, 0xa5); /* wd_cyl_lo is read/write */
289 if (inb(du->dk_port + wd_cyl_lo) == 0xff) { /* XXX too weak */
290 #ifdef ATAPI
291 /* There is no master, try the ATAPI slave. */
292 outb(du->dk_port + wd_sdh, WDSD_IBM | 0x10);
293 outb(du->dk_port + wd_cyl_lo, 0xa5);
294 if (inb(du->dk_port + wd_cyl_lo) == 0xff)
295 #endif
296 goto nodevice;
297 }
298
299 if (wdreset(du) == 0)
300 goto reset_ok;
301 #ifdef ATAPI
302 /* test for ATAPI signature */
303 outb(du->dk_port + wd_sdh, WDSD_IBM); /* master */
304 if (inb(du->dk_port + wd_cyl_lo) == 0x14 &&
305 inb(du->dk_port + wd_cyl_hi) == 0xeb)
306 goto reset_ok;
307 du->dk_unit = 1;
308 outb(du->dk_port + wd_sdh, WDSD_IBM | 0x10); /* slave */
309 if (inb(du->dk_port + wd_cyl_lo) == 0x14 &&
310 inb(du->dk_port + wd_cyl_hi) == 0xeb)
311 goto reset_ok;
312 #endif
313 DELAY(RECOVERYTIME);
314 if (wdreset(du) != 0)
315 goto nodevice;
316 reset_ok:
317
318 /* execute a controller only command */
319 if (wdcommand(du, 0, 0, 0, 0, WDCC_DIAGNOSE) != 0
320 || wdwait(du, 0, TIMEOUT) < 0)
321 goto nodevice;
322
323 /*
324 * drive(s) did not time out during diagnostic :
325 * Get error status and check that both drives are OK.
326 * Table 9-2 of ATA specs suggests that we must check for
327 * a value of 0x01
328 *
329 * Strangely, some controllers will return a status of
330 * 0x81 (drive 0 OK, drive 1 failure), and then when
331 * the DRV bit is set, return status of 0x01 (OK) for
332 * drive 2. (This seems to contradict the ATA spec.)
333 */
334 du->dk_error = inb(du->dk_port + wd_error);
335 /* printf("Error : %x\n", du->dk_error); */
336 if(du->dk_error != 0x01 && du->dk_error != 0) {
337 if(du->dk_error & 0x80) { /* drive 1 failure */
338
339 /* first set the DRV bit */
340 u_int sdh;
341 sdh = inb(du->dk_port+ wd_sdh);
342 sdh = sdh | 0x10;
343 outb(du->dk_port+ wd_sdh, sdh);
344
345 /* Wait, to make sure drv 1 has completed diags */
346 if ( wdwait(du, 0, TIMEOUT) < 0)
347 goto nodevice;
348
349 /* Get status for drive 1 */
350 du->dk_error = inb(du->dk_port + wd_error);
351 /* printf("Error (drv 1) : %x\n", du->dk_error); */
352 /*
353 * Sometimes (apparently mostly with ATAPI
354 * drives involved) 0x81 really means 0x81
355 * (drive 0 OK, drive 1 failed).
356 */
357 if(du->dk_error != 0x01 && du->dk_error != 0x81)
358 goto nodevice;
359 } else /* drive 0 fail */
360 goto nodevice;
361 }
362
363
364 free(du, M_TEMP);
365 return (IO_WDCSIZE);
366
367 nodevice:
368 free(du, M_TEMP);
369 return (0);
370 }
371
372 /*
373 * Attach each drive if possible.
374 */
375 static int
376 wdattach(struct isa_device *dvp)
377 {
378 #ifdef DEVFS
379 int mynor;
380 #endif
381 int unit, lunit;
382 struct isa_device *wdup;
383 struct disk *du;
384
385 if (dvp->id_unit >= NWDC)
386 return (0);
387
388 #ifdef CMD640
389 if (eide_quirks & Q_CMD640B) {
390 if (dvp->id_unit == PRIMARY) {
391 printf("wdc0: CMD640B workaround enabled\n");
392 bufq_init(&wdtab[PRIMARY].controller_queue);
393 }
394 } else
395 bufq_init(&wdtab[dvp->id_unit].controller_queue);
396
397 #else
398 bufq_init(&wdtab[dvp->id_unit].controller_queue);
399 #endif
400
401 for (wdup = isa_biotab_wdc; wdup->id_driver != 0; wdup++) {
402 if (wdup->id_iobase != dvp->id_iobase)
403 continue;
404 lunit = wdup->id_unit;
405 if (lunit >= NWD)
406 continue;
407
408 unit = wdup->id_physid;
409
410 du = malloc(sizeof *du, M_TEMP, M_NOWAIT);
411 if (du == NULL)
412 continue;
413 if (wddrives[lunit] != NULL)
414 panic("drive attached twice");
415 wddrives[lunit] = du;
416 bufq_init(&drive_queue[lunit]);
417 bzero(du, sizeof *du);
418 du->dk_ctrlr = dvp->id_unit;
419 #ifdef CMD640
420 if (eide_quirks & Q_CMD640B) {
421 du->dk_ctrlr_cmd640 = PRIMARY;
422 } else {
423 du->dk_ctrlr_cmd640 = du->dk_ctrlr;
424 }
425 #endif
426 du->dk_unit = unit;
427 du->dk_lunit = lunit;
428 du->dk_port = dvp->id_iobase;
429
430 /*
431 * Use the individual device flags or the controller
432 * flags.
433 */
434 du->cfg_flags = wdup->id_flags |
435 ((dvp->id_flags) >> (16 * unit));
436
437 if (wdgetctlr(du) == 0) {
438 /*
439 * Print out description of drive.
440 * wdp_model may not be null terminated.
441 */
442 printf("wdc%d: unit %d (wd%d): <%.*s>",
443 dvp->id_unit, unit, lunit,
444 sizeof du->dk_params.wdp_model,
445 du->dk_params.wdp_model);
446 if (du->dk_flags & DKFL_32BIT)
447 printf(", 32-bit");
448 if (du->dk_multi > 1)
449 printf(", multi-block-%d", du->dk_multi);
450 if (du->cfg_flags & WDOPT_SLEEPHACK)
451 printf(", sleep-hack");
452 printf("\n");
453 if (du->dk_params.wdp_heads == 0)
454 printf("wd%d: size unknown, using %s values\n",
455 lunit, du->dk_dd.d_secperunit > 17
456 ? "BIOS" : "fake");
457 printf(
458 "wd%d: %luMB (%lu sectors), %lu cyls, %lu heads, %lu S/T, %lu B/S\n",
459 lunit,
460 du->dk_dd.d_secperunit
461 / ((1024L * 1024L) / du->dk_dd.d_secsize),
462 du->dk_dd.d_secperunit,
463 du->dk_dd.d_ncylinders,
464 du->dk_dd.d_ntracks,
465 du->dk_dd.d_nsectors,
466 du->dk_dd.d_secsize);
467
468 /*
469 * Start timeout routine for this drive.
470 * XXX timeout should be per controller.
471 */
472 wdtimeout(du);
473
474 #ifdef DEVFS
475 mynor = dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART);
476 du->dk_bdev = devfs_add_devswf(&wd_bdevsw, mynor,
477 DV_BLK, UID_ROOT,
478 GID_OPERATOR, 0640,
479 "wd%d", unit);
480 du->dk_cdev = devfs_add_devswf(&wd_cdevsw, mynor,
481 DV_CHR, UID_ROOT,
482 GID_OPERATOR, 0640,
483 "rwd%d", unit);
484 #endif
485
486 if (dk_ndrive < DK_NDRIVE) {
487 sprintf(dk_names[dk_ndrive], "wd%d", lunit);
488 /*
489 * XXX we don't know the transfer rate of the
490 * drive. Guess the maximum ISA rate of
491 * 4MB/sec. `wpms' is words per _second_
492 * according to iostat.
493 */
494 dk_wpms[dk_ndrive] = 4 * 1024 * 1024 / 2;
495 du->dk_dkunit = dk_ndrive++;
496 } else {
497 du->dk_dkunit = -1;
498 }
499 } else {
500 free(du, M_TEMP);
501 wddrives[lunit] = NULL;
502 }
503 }
504 #ifdef ATAPI
505 /*
506 * Probe all free IDE units, searching for ATAPI drives.
507 */
508 for (unit=0; unit<2; ++unit) {
509 for (lunit=0; lunit<NWD; ++lunit)
510 if (wddrives[lunit] &&
511 wddrives[lunit]->dk_ctrlr == dvp->id_unit &&
512 wddrives[lunit]->dk_unit == unit)
513 goto next;
514 #ifdef CMD640
515 if (atapi_attach (dvp->id_unit, unit, dvp->id_iobase))
516 atapictrlr = dvp->id_unit;
517 #else
518 atapi_attach (dvp->id_unit, unit, dvp->id_iobase);
519 #endif
520 next: ;
521 }
522 #endif
523 /*
524 * Discard any interrupts generated by wdgetctlr(). wdflushirq()
525 * doesn't work now because the ambient ipl is too high.
526 */
527 #ifdef CMD640
528 if (eide_quirks & Q_CMD640B) {
529 wdtab[PRIMARY].b_active = 2;
530 } else {
531 wdtab[dvp->id_unit].b_active = 2;
532 }
533 #else
534 wdtab[dvp->id_unit].b_active = 2;
535 #endif
536
537 return (1);
538 }
539
540 /* Read/write routine for a buffer. Finds the proper unit, range checks
541 * arguments, and schedules the transfer. Does not wait for the transfer
542 * to complete. Multi-page transfers are supported. All I/O requests must
543 * be a multiple of a sector in length.
544 */
545 void
546 wdstrategy(register struct buf *bp)
547 {
548 struct disk *du;
549 int lunit = dkunit(bp->b_dev);
550 int s;
551
552 /* valid unit, controller, and request? */
553 if (lunit >= NWD || bp->b_blkno < 0 || (du = wddrives[lunit]) == NULL
554 || bp->b_bcount % DEV_BSIZE != 0) {
555
556 bp->b_error = EINVAL;
557 bp->b_flags |= B_ERROR;
558 goto done;
559 }
560
561 /*
562 * Do bounds checking, adjust transfer, and set b_pblkno.
563 */
564 if (dscheck(bp, du->dk_slices) <= 0)
565 goto done;
566
567 /*
568 * Check for *any* block on this transfer being on the bad block list
569 * if it is, then flag the block as a transfer that requires
570 * bad block handling. Also, used as a hint for low level disksort
571 * clustering code to keep from coalescing a bad transfer into
572 * a normal transfer. Single block transfers for a large number of
573 * blocks associated with a cluster I/O are undesirable.
574 *
575 * XXX the old disksort() doesn't look at B_BAD. Coalescing _is_
576 * desirable. We should split the results at bad blocks just
577 * like we should split them at MAXTRANSFER boundaries.
578 */
579 if (dsgetbad(bp->b_dev, du->dk_slices) != NULL) {
580 long *badsect = dsgetbad(bp->b_dev, du->dk_slices)->bi_bad;
581 int i;
582 int nsecs = howmany(bp->b_bcount, DEV_BSIZE);
583 /* XXX pblkno is too physical. */
584 daddr_t nspblkno = bp->b_pblkno
585 - du->dk_slices->dss_slices[dkslice(bp->b_dev)].ds_offset;
586 int blkend = nspblkno + nsecs;
587
588 for (i = 0; badsect[i] != -1 && badsect[i] < blkend; i++) {
589 if (badsect[i] >= nspblkno) {
590 bp->b_flags |= B_BAD;
591 break;
592 }
593 }
594 }
595
596 /* queue transfer on drive, activate drive and controller if idle */
597 s = splbio();
598
599 bufqdisksort(&drive_queue[lunit], bp);
600
601 if (wdutab[lunit].b_active == 0)
602 wdustart(du); /* start drive */
603
604 /* Pick up changes made by readdisklabel(). */
605 if (du->dk_flags & DKFL_LABELLING && du->dk_state > RECAL) {
606 wdsleep(du->dk_ctrlr, "wdlab");
607 du->dk_state = WANTOPEN;
608 }
609
610 #ifdef CMD640
611 if (wdtab[du->dk_ctrlr_cmd640].b_active == 0)
612 #else
613 if (wdtab[du->dk_ctrlr].b_active == 0)
614 #endif
615 wdstart(du->dk_ctrlr); /* start controller */
616
617 if (du->dk_dkunit >= 0) {
618 /*
619 * XXX perhaps we should only count successful transfers.
620 */
621 dk_xfer[du->dk_dkunit]++;
622 /*
623 * XXX we can't count seeks correctly but we can do better
624 * than this. E.g., assume that the geometry is correct
625 * and count 1 seek if the starting cylinder of this i/o
626 * differs from the starting cylinder of the previous i/o,
627 * or count 1 seek if the starting bn of this i/o doesn't
628 * immediately follow the ending bn of the previos i/o.
629 */
630 dk_seek[du->dk_dkunit]++;
631 }
632
633 splx(s);
634 return;
635
636 done:
637 s = splbio();
638 /* toss transfer, we're done early */
639 biodone(bp);
640 splx(s);
641 }
642
643 static void
644 wdstrategy1(struct buf *bp)
645 {
646 /*
647 * XXX - do something to make wdstrategy() but not this block while
648 * we're doing dsinit() and dsioctl().
649 */
650 wdstrategy(bp);
651 }
652
653 /*
654 * Routine to queue a command to the controller. The unit's
655 * request is linked into the active list for the controller.
656 * If the controller is idle, the transfer is started.
657 */
658 static void
659 wdustart(register struct disk *du)
660 {
661 register struct buf *bp;
662 #ifdef CMD640
663 int ctrlr = du->dk_ctrlr_cmd640;
664 #else
665 int ctrlr = du->dk_ctrlr;
666 #endif
667
668 /* unit already active? */
669 if (wdutab[du->dk_lunit].b_active)
670 return;
671
672
673 bp = bufq_first(&drive_queue[du->dk_lunit]);
674 if (bp == NULL) { /* yes, an assign */
675 return;
676 }
677 bufq_remove(&drive_queue[du->dk_lunit], bp);
678
679 /* link onto controller queue */
680 bufq_insert_tail(&wdtab[ctrlr].controller_queue, bp);
681
682 /* mark the drive unit as busy */
683 wdutab[du->dk_lunit].b_active = 1;
684 }
685
686 /*
687 * Controller startup routine. This does the calculation, and starts
688 * a single-sector read or write operation. Called to start a transfer,
689 * or from the interrupt routine to continue a multi-sector transfer.
690 * RESTRICTIONS:
691 * 1. The transfer length must be an exact multiple of the sector size.
692 */
693
694 void
695 wdstart(int ctrlr)
696 {
697 register struct disk *du;
698 register struct buf *bp;
699 struct diskgeom *lp; /* XXX sic */
700 long blknum;
701 long secpertrk, secpercyl;
702 int lunit;
703 int count;
704 #ifdef CMD640
705 int ctrlr_atapi;
706
707 if (eide_quirks & Q_CMD640B) {
708 ctrlr = PRIMARY;
709 ctrlr_atapi = atapictrlr;
710 } else {
711 ctrlr_atapi = ctrlr;
712 }
713 #endif
714
715 #ifdef ATAPI
716 if (wdtab[ctrlr].b_active == 2)
717 wdtab[ctrlr].b_active = 0;
718 if (wdtab[ctrlr].b_active)
719 return;
720 #endif
721 /* is there a drive for the controller to do a transfer with? */
722 bp = bufq_first(&wdtab[ctrlr].controller_queue);
723 if (bp == NULL) {
724 #ifdef ATAPI
725 #ifdef CMD640
726 if (atapi_start && atapi_start (ctrlr_atapi))
727 wdtab[ctrlr].b_active = 3;
728 #else
729 if (atapi_start && atapi_start (ctrlr))
730 /* mark controller active in ATAPI mode */
731 wdtab[ctrlr].b_active = 3;
732 #endif
733 #endif
734 return;
735 }
736
737 /* obtain controller and drive information */
738 lunit = dkunit(bp->b_dev);
739 du = wddrives[lunit];
740
741 /* if not really a transfer, do control operations specially */
742 if (du->dk_state < OPEN) {
743 if (du->dk_state != WANTOPEN)
744 printf("wd%d: wdstart: weird dk_state %d\n",
745 du->dk_lunit, du->dk_state);
746 if (wdcontrol(bp) != 0)
747 printf("wd%d: wdstart: wdcontrol returned nonzero, state = %d\n",
748 du->dk_lunit, du->dk_state);
749 return;
750 }
751
752 /* calculate transfer details */
753 blknum = bp->b_pblkno + du->dk_skip;
754 #ifdef WDDEBUG
755 if (du->dk_skip == 0)
756 printf("wd%d: wdstart: %s %d@%d; map ", lunit,
757 (bp->b_flags & B_READ) ? "read" : "write",
758 bp->b_bcount, blknum);
759 else
760 printf(" %d)%x", du->dk_skip, inb(du->dk_port + wd_altsts));
761 #endif
762
763 lp = &du->dk_dd;
764 secpertrk = lp->d_nsectors;
765 secpercyl = lp->d_secpercyl;
766
767 if (du->dk_skip == 0) {
768 du->dk_bc = bp->b_bcount;
769
770 if (bp->b_flags & B_BAD
771 /*
772 * XXX handle large transfers inefficiently instead
773 * of crashing on them.
774 */
775 || howmany(du->dk_bc, DEV_BSIZE) > MAXTRANSFER)
776 du->dk_flags |= DKFL_SINGLE;
777 }
778
779 if (du->dk_flags & DKFL_SINGLE
780 && dsgetbad(bp->b_dev, du->dk_slices) != NULL) {
781 /* XXX */
782 u_long ds_offset =
783 du->dk_slices->dss_slices[dkslice(bp->b_dev)].ds_offset;
784
785 blknum = transbad144(dsgetbad(bp->b_dev, du->dk_slices),
786 blknum - ds_offset) + ds_offset;
787 }
788
789 wdtab[ctrlr].b_active = 1; /* mark controller active */
790
791 /* if starting a multisector transfer, or doing single transfers */
792 if (du->dk_skip == 0 || (du->dk_flags & DKFL_SINGLE)) {
793 u_int command;
794 u_int count1;
795 long cylin, head, sector;
796
797 cylin = blknum / secpercyl;
798 head = (blknum % secpercyl) / secpertrk;
799 sector = blknum % secpertrk;
800
801 if (wdtab[ctrlr].b_errcnt && (bp->b_flags & B_READ) == 0)
802 du->dk_bc += DEV_BSIZE;
803 count1 = howmany( du->dk_bc, DEV_BSIZE);
804
805 du->dk_flags &= ~DKFL_MULTI;
806
807 #ifdef B_FORMAT
808 if (bp->b_flags & B_FORMAT) {
809 command = WDCC_FORMAT;
810 count1 = lp->d_nsectors;
811 sector = lp->d_gap3 - 1; /* + 1 later */
812 } else
813 #endif
814
815 {
816 if (du->dk_flags & DKFL_SINGLE) {
817 command = (bp->b_flags & B_READ)
818 ? WDCC_READ : WDCC_WRITE;
819 count1 = 1;
820 du->dk_currentiosize = 1;
821 } else {
822 if( (count1 > 1) && (du->dk_multi > 1)) {
823 du->dk_flags |= DKFL_MULTI;
824 if( bp->b_flags & B_READ) {
825 command = WDCC_READ_MULTI;
826 } else {
827 command = WDCC_WRITE_MULTI;
828 }
829 du->dk_currentiosize = du->dk_multi;
830 if( du->dk_currentiosize > count1)
831 du->dk_currentiosize = count1;
832 } else {
833 if( bp->b_flags & B_READ) {
834 command = WDCC_READ;
835 } else {
836 command = WDCC_WRITE;
837 }
838 du->dk_currentiosize = 1;
839 }
840 }
841 }
842
843 /*
844 * XXX this loop may never terminate. The code to handle
845 * counting down of retries and eventually failing the i/o
846 * is in wdintr() and we can't get there from here.
847 */
848 if (wdtest != 0) {
849 if (--wdtest == 0) {
850 wdtest = 100;
851 printf("dummy wdunwedge\n");
852 wdunwedge(du);
853 }
854 }
855 if(du->dk_dkunit >= 0) {
856 dk_busy |= 1 << du->dk_dkunit;
857 }
858 while (wdcommand(du, cylin, head, sector, count1, command)
859 != 0) {
860 wderror(bp, du,
861 "wdstart: timeout waiting to give command");
862 wdunwedge(du);
863 }
864 #ifdef WDDEBUG
865 printf("cylin %ld head %ld sector %ld addr %x sts %x\n",
866 cylin, head, sector,
867 (int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE,
868 inb(du->dk_port + wd_altsts));
869 #endif
870 }
871
872 /*
873 * Schedule wdtimeout() to wake up after a few seconds. Retrying
874 * unmarked bad blocks can take 3 seconds! Then it is not good that
875 * we retry 5 times.
876 *
877 * XXX wdtimeout() doesn't increment the error count so we may loop
878 * forever. More seriously, the loop isn't forever but causes a
879 * crash.
880 *
881 * TODO fix b_resid bug elsewhere (fd.c....). Fix short but positive
882 * counts being discarded after there is an error (in physio I
883 * think). Discarding them would be OK if the (special) file offset
884 * was not advanced.
885 */
886 du->dk_timeout = 1 + 3;
887
888 /* If this is a read operation, just go away until it's done. */
889 if (bp->b_flags & B_READ)
890 return;
891
892 /* Ready to send data? */
893 if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ, TIMEOUT) < 0) {
894 wderror(bp, du, "wdstart: timeout waiting for DRQ");
895 /*
896 * XXX what do we do now? If we've just issued the command,
897 * then we can treat this failure the same as a command
898 * failure. But if we are continuing a multi-sector write,
899 * the command was issued ages ago, so we can't simply
900 * restart it.
901 *
902 * XXX we waste a lot of time unnecessarily translating block
903 * numbers to cylin/head/sector for continued i/o's.
904 */
905 }
906
907 count = 1;
908 if( du->dk_flags & DKFL_MULTI) {
909 count = howmany(du->dk_bc, DEV_BSIZE);
910 if( count > du->dk_multi)
911 count = du->dk_multi;
912 if( du->dk_currentiosize > count)
913 du->dk_currentiosize = count;
914 }
915
916 if (du->dk_flags & DKFL_32BIT)
917 outsl(du->dk_port + wd_data,
918 (void *)((int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE),
919 (count * DEV_BSIZE) / sizeof(long));
920 else
921 outsw(du->dk_port + wd_data,
922 (void *)((int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE),
923 (count * DEV_BSIZE) / sizeof(short));
924 du->dk_bc -= DEV_BSIZE * count;
925 if (du->dk_dkunit >= 0) {
926 /*
927 * `wd's are blocks of 32 16-bit `word's according to
928 * iostat. dk_wds[] is the one disk i/o statistic that
929 * we can record correctly.
930 * XXX perhaps we shouldn't record words for failed
931 * transfers.
932 */
933 dk_wds[du->dk_dkunit] += (count * DEV_BSIZE) >> 6;
934 }
935 }
936
937 /* Interrupt routine for the controller. Acknowledge the interrupt, check for
938 * errors on the current operation, mark it done if necessary, and start
939 * the next request. Also check for a partially done transfer, and
940 * continue with the next chunk if so.
941 */
942 void
943 wdintr(int unit)
944 {
945 register struct disk *du;
946 register struct buf *bp;
947
948 #ifdef CMD640
949 int ctrlr_atapi;
950
951 if (eide_quirks & Q_CMD640B) {
952 unit = PRIMARY;
953 ctrlr_atapi = atapictrlr;
954 } else {
955 ctrlr_atapi = unit;
956 }
957 #endif
958
959 if (wdtab[unit].b_active == 2)
960 return; /* intr in wdflushirq() */
961 if (!wdtab[unit].b_active) {
962 #ifdef WDDEBUG
963 /*
964 * These happen mostly because the power-mgt part of the
965 * bios shuts us down, and we just manage to see the
966 * interrupt from the "SLEEP" command.
967 */
968 printf("wdc%d: extra interrupt\n", unit);
969 #endif
970 return;
971 }
972 #ifdef ATAPI
973 if (wdtab[unit].b_active == 3) {
974 /* process an ATAPI interrupt */
975 #ifdef CMD640
976 if (atapi_intr && atapi_intr (ctrlr_atapi))
977 #else
978 if (atapi_intr && atapi_intr (unit))
979 #endif
980 /* ATAPI op continues */
981 return;
982 /* controller is free, start new op */
983 wdtab[unit].b_active = 0;
984 wdstart (unit);
985 return;
986 }
987 #endif
988 bp = bufq_first(&wdtab[unit].controller_queue);
989 du = wddrives[dkunit(bp->b_dev)];
990 du->dk_timeout = 0;
991
992 if (wdwait(du, 0, TIMEOUT) < 0) {
993 wderror(bp, du, "wdintr: timeout waiting for status");
994 du->dk_status |= WDCS_ERR; /* XXX */
995 }
996
997 /* is it not a transfer, but a control operation? */
998 if (du->dk_state < OPEN) {
999 wdtab[unit].b_active = 0;
1000 switch (wdcontrol(bp)) {
1001 case 0:
1002 return;
1003 case 1:
1004 wdstart(unit);
1005 return;
1006 case 2:
1007 goto done;
1008 }
1009 }
1010
1011 /* have we an error? */
1012 if (du->dk_status & (WDCS_ERR | WDCS_ECCCOR)) {
1013 oops:
1014 /*
1015 * XXX bogus inb() here, register 0 is assumed and intr status
1016 * is reset.
1017 */
1018 if( (du->dk_flags & DKFL_MULTI) && (inb(du->dk_port) & WDERR_ABORT)) {
1019 wderror(bp, du, "reverting to non-multi sector mode");
1020 du->dk_multi = 1;
1021 }
1022 #ifdef WDDEBUG
1023 wderror(bp, du, "wdintr");
1024 #endif
1025 if ((du->dk_flags & DKFL_SINGLE) == 0) {
1026 du->dk_flags |= DKFL_ERROR;
1027 goto outt;
1028 }
1029 #ifdef B_FORMAT
1030 if (bp->b_flags & B_FORMAT) {
1031 bp->b_error = EIO;
1032 bp->b_flags |= B_ERROR;
1033 goto done;
1034 }
1035 #endif
1036
1037 if (du->dk_flags & DKFL_BADSCAN) {
1038 bp->b_error = EIO;
1039 bp->b_flags |= B_ERROR;
1040 } else if (du->dk_status & WDCS_ERR) {
1041 if (++wdtab[unit].b_errcnt < RETRIES) {
1042 wdtab[unit].b_active = 0;
1043 } else {
1044 wderror(bp, du, "hard error");
1045 bp->b_error = EIO;
1046 bp->b_flags |= B_ERROR; /* flag the error */
1047 }
1048 } else
1049 wderror(bp, du, "soft ecc");
1050 }
1051
1052 /*
1053 * If this was a successful read operation, fetch the data.
1054 */
1055 if (((bp->b_flags & (B_READ | B_ERROR)) == B_READ)
1056 && wdtab[unit].b_active) {
1057 int chk, dummy, multisize;
1058 multisize = chk = du->dk_currentiosize * DEV_BSIZE;
1059 if( du->dk_bc < chk) {
1060 chk = du->dk_bc;
1061 if( ((chk + DEV_BSIZE - 1) / DEV_BSIZE) < du->dk_currentiosize) {
1062 du->dk_currentiosize = (chk + DEV_BSIZE - 1) / DEV_BSIZE;
1063 multisize = du->dk_currentiosize * DEV_BSIZE;
1064 }
1065 }
1066
1067 /* ready to receive data? */
1068 if ((du->dk_status & (WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ))
1069 != (WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ))
1070 wderror(bp, du, "wdintr: read intr arrived early");
1071 if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ, TIMEOUT) != 0) {
1072 wderror(bp, du, "wdintr: read error detected late");
1073 goto oops;
1074 }
1075
1076 /* suck in data */
1077 if( du->dk_flags & DKFL_32BIT)
1078 insl(du->dk_port + wd_data,
1079 (void *)((int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE),
1080 chk / sizeof(long));
1081 else
1082 insw(du->dk_port + wd_data,
1083 (void *)((int)bp->b_un.b_addr + du->dk_skip * DEV_BSIZE),
1084 chk / sizeof(short));
1085 du->dk_bc -= chk;
1086
1087 /* XXX for obsolete fractional sector reads. */
1088 while (chk < multisize) {
1089 insw(du->dk_port + wd_data, &dummy, 1);
1090 chk += sizeof(short);
1091 }
1092
1093 if (du->dk_dkunit >= 0)
1094 dk_wds[du->dk_dkunit] += chk >> 6;
1095 }
1096
1097 outt:
1098 if (wdtab[unit].b_active) {
1099 if ((bp->b_flags & B_ERROR) == 0) {
1100 du->dk_skip += du->dk_currentiosize;/* add to successful sectors */
1101 if (wdtab[unit].b_errcnt)
1102 wderror(bp, du, "soft error");
1103 wdtab[unit].b_errcnt = 0;
1104
1105 /* see if more to transfer */
1106 if (du->dk_bc > 0 && (du->dk_flags & DKFL_ERROR) == 0) {
1107 if( (du->dk_flags & DKFL_SINGLE) ||
1108 ((bp->b_flags & B_READ) == 0)) {
1109 wdtab[unit].b_active = 0;
1110 wdstart(unit);
1111 } else {
1112 du->dk_timeout = 1 + 3;
1113 }
1114 return; /* next chunk is started */
1115 } else if ((du->dk_flags & (DKFL_SINGLE | DKFL_ERROR))
1116 == DKFL_ERROR) {
1117 du->dk_skip = 0;
1118 du->dk_flags &= ~DKFL_ERROR;
1119 du->dk_flags |= DKFL_SINGLE;
1120 wdtab[unit].b_active = 0;
1121 wdstart(unit);
1122 return; /* redo xfer sector by sector */
1123 }
1124 }
1125
1126 done: ;
1127 /* done with this transfer, with or without error */
1128 du->dk_flags &= ~DKFL_SINGLE;
1129 bufq_remove(&wdtab[unit].controller_queue, bp);
1130 wdtab[unit].b_errcnt = 0;
1131 bp->b_resid = bp->b_bcount - du->dk_skip * DEV_BSIZE;
1132 wdutab[du->dk_lunit].b_active = 0;
1133 wdutab[du->dk_lunit].b_errcnt = 0;
1134 du->dk_skip = 0;
1135 biodone(bp);
1136 }
1137
1138 if(du->dk_dkunit >= 0) {
1139 dk_busy &= ~(1 << du->dk_dkunit);
1140 }
1141
1142 /* controller idle */
1143 wdtab[unit].b_active = 0;
1144
1145 /* anything more on drive queue? */
1146 wdustart(du);
1147 /* anything more for controller to do? */
1148 #ifndef ATAPI
1149 /* This is not valid in ATAPI mode. */
1150 if (bufq_first(&wdtab[unit].controller_queue) != NULL)
1151 #endif
1152 wdstart(unit);
1153 }
1154
1155 /*
1156 * Initialize a drive.
1157 */
1158 int
1159 wdopen(dev_t dev, int flags, int fmt, struct proc *p)
1160 {
1161 register unsigned int lunit;
1162 register struct disk *du;
1163 int error;
1164
1165 lunit = dkunit(dev);
1166 if (lunit >= NWD || dktype(dev) != 0)
1167 return (ENXIO);
1168 du = wddrives[lunit];
1169 if (du == NULL)
1170 return (ENXIO);
1171
1172 /* Finish flushing IRQs left over from wdattach(). */
1173 #ifdef CMD640
1174 if (wdtab[du->dk_ctrlr_cmd640].b_active == 2)
1175 wdtab[du->dk_ctrlr_cmd640].b_active = 0;
1176 #else
1177 if (wdtab[du->dk_ctrlr].b_active == 2)
1178 wdtab[du->dk_ctrlr].b_active = 0;
1179 #endif
1180
1181 du->dk_flags &= ~DKFL_BADSCAN;
1182
1183 while (du->dk_flags & DKFL_LABELLING)
1184 tsleep((caddr_t)&du->dk_flags, PZERO - 1, "wdopen", 1);
1185 #if 1
1186 wdsleep(du->dk_ctrlr, "wdopn1");
1187 du->dk_flags |= DKFL_LABELLING;
1188 du->dk_state = WANTOPEN;
1189 {
1190 struct disklabel label;
1191
1192 bzero(&label, sizeof label);
1193 label.d_secsize = du->dk_dd.d_secsize;
1194 label.d_nsectors = du->dk_dd.d_nsectors;
1195 label.d_ntracks = du->dk_dd.d_ntracks;
1196 label.d_ncylinders = du->dk_dd.d_ncylinders;
1197 label.d_secpercyl = du->dk_dd.d_secpercyl;
1198 label.d_secperunit = du->dk_dd.d_secperunit;
1199 error = dsopen("wd", dev, fmt, &du->dk_slices, &label, wdstrategy1,
1200 (ds_setgeom_t *)NULL, &wd_bdevsw, &wd_cdevsw);
1201 }
1202 du->dk_flags &= ~DKFL_LABELLING;
1203 wdsleep(du->dk_ctrlr, "wdopn2");
1204 return (error);
1205 #else
1206 if ((du->dk_flags & DKFL_BSDLABEL) == 0) {
1207 /*
1208 * wdtab[ctrlr].b_active != 0 implies XXX applicable now ??
1209 * drive_queue[lunit].b_act == NULL (?) XXX applicable now ??
1210 * so the following guards most things (until the next i/o).
1211 * It doesn't guard against a new i/o starting and being
1212 * affected by the label being changed. Sigh.
1213 */
1214 wdsleep(du->dk_ctrlr, "wdopn1");
1215
1216 du->dk_flags |= DKFL_LABELLING;
1217 du->dk_state = WANTOPEN;
1218
1219 error = dsinit(dkmodpart(dev, RAW_PART), wdstrategy,
1220 &du->dk_dd, &du->dk_slices);
1221 if (error != 0) {
1222 du->dk_flags &= ~DKFL_LABELLING;
1223 return (error);
1224 }
1225 /* XXX check value returned by wdwsetctlr(). */
1226 wdwsetctlr(du);
1227 if (dkslice(dev) == WHOLE_DISK_SLICE) {
1228 dsopen(dev, fmt, du->dk_slices);
1229 return (0);
1230 }
1231
1232 /*
1233 * Read label using RAW_PART partition.
1234 *
1235 * If the drive has an MBR, then the current geometry (from
1236 * wdgetctlr()) is used to read it; then the BIOS/DOS
1237 * geometry is inferred and used to read the label off the
1238 * 'c' partition. Otherwise the label is read using the
1239 * current geometry. The label gives the final geometry.
1240 * If bad sector handling is enabled, then this geometry
1241 * is used to read the bad sector table. The geometry
1242 * changes occur inside readdisklabel() and are propagated
1243 * to the driver by resetting the state machine.
1244 *
1245 * XXX can now handle changes directly since dsinit() doesn't
1246 * do too much.
1247 */
1248 msg = correct_readdisklabel(dkmodpart(dev, RAW_PART), wdstrategy,
1249 &du->dk_dd);
1250 /* XXX check value returned by wdwsetctlr(). */
1251 wdwsetctlr(du);
1252 if (msg == NULL && du->dk_dd.d_flags & D_BADSECT)
1253 msg = readbad144(dkmodpart(dev, RAW_PART), wdstrategy,
1254 &du->dk_dd, &du->dk_bad);
1255 du->dk_flags &= ~DKFL_LABELLING;
1256 if (msg != NULL) {
1257 log(LOG_WARNING, "wd%d: cannot find label (%s)\n",
1258 lunit, msg);
1259 if (part != RAW_PART)
1260 return (EINVAL); /* XXX needs translation */
1261 /*
1262 * Soon return. This is how slices without labels
1263 * are allowed. They only work on the raw partition.
1264 */
1265 } else {
1266 unsigned long newsize, offset, size;
1267 #if 0
1268 /*
1269 * Force RAW_PART partition to be the whole disk.
1270 */
1271 offset = du->dk_dd.d_partitions[RAW_PART].p_offset;
1272 if (offset != 0) {
1273 printf(
1274 "wd%d: changing offset of '%c' partition from %lu to 0\n",
1275 du->dk_lunit, 'a' + RAW_PART, offset);
1276 du->dk_dd.d_partitions[RAW_PART].p_offset = 0;
1277 }
1278 size = du->dk_dd.d_partitions[RAW_PART].p_size;
1279 newsize = du->dk_dd.d_secperunit; /* XXX */
1280 if (size != newsize) {
1281 printf(
1282 "wd%d: changing size of '%c' partition from %lu to %lu\n",
1283 du->dk_lunit, 'a' + RAW_PART, size,
1284 newsize);
1285 du->dk_dd.d_partitions[RAW_PART].p_size
1286 = newsize;
1287 }
1288 #endif
1289 }
1290
1291 /* Pick up changes made by readdisklabel(). */
1292 wdsleep(du->dk_ctrlr, "wdopn2");
1293 du->dk_state = WANTOPEN;
1294 }
1295
1296 /*
1297 * Warn if a partion is opened that overlaps another partition which
1298 * is open unless one is the "raw" partition (whole disk).
1299 */
1300 if ((du->dk_openpart & mask) == 0 && part != RAW_PART) {
1301 int start, end;
1302
1303 pp = &du->dk_dd.d_partitions[part];
1304 start = pp->p_offset;
1305 end = pp->p_offset + pp->p_size;
1306 for (pp = du->dk_dd.d_partitions;
1307 pp < &du->dk_dd.d_partitions[du->dk_dd.d_npartitions];
1308 pp++) {
1309 if (pp->p_offset + pp->p_size <= start ||
1310 pp->p_offset >= end)
1311 continue;
1312 if (pp - du->dk_dd.d_partitions == RAW_PART)
1313 continue;
1314 if (du->dk_openpart
1315 & (1 << (pp - du->dk_dd.d_partitions)))
1316 log(LOG_WARNING,
1317 "wd%d%c: overlaps open partition (%c)\n",
1318 lunit, part + 'a',
1319 pp - du->dk_dd.d_partitions + 'a');
1320 }
1321 }
1322 if (part >= du->dk_dd.d_npartitions && part != RAW_PART)
1323 return (ENXIO);
1324
1325 dsopen(dev, fmt, du->dk_slices);
1326
1327 return (0);
1328 #endif
1329 }
1330
1331 /*
1332 * Implement operations other than read/write.
1333 * Called from wdstart or wdintr during opens and formats.
1334 * Uses finite-state-machine to track progress of operation in progress.
1335 * Returns 0 if operation still in progress, 1 if completed, 2 if error.
1336 */
1337 static int
1338 wdcontrol(register struct buf *bp)
1339 {
1340 register struct disk *du;
1341 int ctrlr;
1342
1343 du = wddrives[dkunit(bp->b_dev)];
1344 #ifdef CMD640
1345 ctrlr = du->dk_ctrlr_cmd640;
1346 #else
1347 ctrlr = du->dk_ctrlr;
1348 #endif
1349
1350 switch (du->dk_state) {
1351 case WANTOPEN:
1352 tryagainrecal:
1353 wdtab[ctrlr].b_active = 1;
1354 if (wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) != 0) {
1355 wderror(bp, du, "wdcontrol: wdcommand failed");
1356 goto maybe_retry;
1357 }
1358 du->dk_state = RECAL;
1359 return (0);
1360 case RECAL:
1361 if (du->dk_status & WDCS_ERR || wdsetctlr(du) != 0) {
1362 wderror(bp, du, "wdcontrol: recal failed");
1363 maybe_retry:
1364 if (du->dk_status & WDCS_ERR)
1365 wdunwedge(du);
1366 du->dk_state = WANTOPEN;
1367 if (++wdtab[ctrlr].b_errcnt < RETRIES)
1368 goto tryagainrecal;
1369 bp->b_error = ENXIO; /* XXX needs translation */
1370 bp->b_flags |= B_ERROR;
1371 return (2);
1372 }
1373 wdtab[ctrlr].b_errcnt = 0;
1374 du->dk_state = OPEN;
1375 /*
1376 * The rest of the initialization can be done by normal
1377 * means.
1378 */
1379 return (1);
1380 }
1381 panic("wdcontrol");
1382 return (2);
1383 }
1384
1385 /*
1386 * Wait uninterruptibly until controller is not busy, then send it a command.
1387 * The wait usually terminates immediately because we waited for the previous
1388 * command to terminate.
1389 */
1390 static int
1391 wdcommand(struct disk *du, u_int cylinder, u_int head, u_int sector,
1392 u_int count, u_int command)
1393 {
1394 u_int wdc;
1395
1396 wdc = du->dk_port;
1397 if (du->cfg_flags & WDOPT_SLEEPHACK) {
1398 /* OK, so the APM bios has put the disk into SLEEP mode,
1399 * how can we tell ? Uhm, we can't. There is no
1400 * standardized way of finding out, and the only way to
1401 * wake it up is to reset it. Bummer.
1402 *
1403 * All the many and varied versions of the IDE/ATA standard
1404 * explicitly tells us not to look at these registers if
1405 * the disk is in SLEEP mode. Well, too bad really, we
1406 * have to find out if it's in sleep mode before we can
1407 * avoid reading the registers.
1408 *
1409 * I have reason to belive that most disks will return
1410 * either 0xff or 0x00 in all but the status register
1411 * when in SLEEP mode, but I have yet to see one return
1412 * 0x00, so we don't check for that yet.
1413 *
1414 * The check for WDCS_BUSY is for the case where the
1415 * bios spins up the disk for us, but doesn't initialize
1416 * it correctly /phk
1417 */
1418 if(inb(wdc + wd_precomp) + inb(wdc + wd_cyl_lo) +
1419 inb(wdc + wd_cyl_hi) + inb(wdc + wd_sdh) +
1420 inb(wdc + wd_sector) + inb(wdc + wd_seccnt) == 6 * 0xff) {
1421 if (bootverbose)
1422 printf("wd(%d,%d): disk aSLEEP\n",
1423 du->dk_ctrlr, du->dk_unit);
1424 wdunwedge(du);
1425 } else if(inb(wdc + wd_status) == WDCS_BUSY) {
1426 if (bootverbose)
1427 printf("wd(%d,%d): disk is BUSY\n",
1428 du->dk_ctrlr, du->dk_unit);
1429 wdunwedge(du);
1430 }
1431 }
1432
1433 if (wdwait(du, 0, TIMEOUT) < 0)
1434 return (1);
1435 if( command == WDCC_FEATURES) {
1436 outb(wdc + wd_features, count);
1437 } else {
1438 outb(wdc + wd_precomp, du->dk_dd.d_precompcyl / 4);
1439 outb(wdc + wd_cyl_lo, cylinder);
1440 outb(wdc + wd_cyl_hi, cylinder >> 8);
1441 outb(wdc + wd_sdh, WDSD_IBM | (du->dk_unit << 4) | head);
1442 outb(wdc + wd_sector, sector + 1);
1443 outb(wdc + wd_seccnt, count);
1444 }
1445 if (wdwait(du, command == WDCC_DIAGNOSE || command == WDCC_IDC
1446 ? 0 : WDCS_READY, TIMEOUT) < 0)
1447 return (1);
1448 outb(wdc + wd_command, command);
1449 return (0);
1450 }
1451
1452 static void
1453 wdsetmulti(struct disk *du)
1454 {
1455 /*
1456 * The config option flags low 8 bits define the maximum multi-block
1457 * transfer size. If the user wants the maximum that the drive
1458 * is capable of, just set the low bits of the config option to
1459 * 0x00ff.
1460 */
1461 if ((du->cfg_flags & WDOPT_MULTIMASK) != 0 && (du->dk_multi > 1)) {
1462 int configval = du->cfg_flags & WDOPT_MULTIMASK;
1463 du->dk_multi = min(du->dk_multi, configval);
1464 if (wdcommand(du, 0, 0, 0, du->dk_multi, WDCC_SET_MULTI)) {
1465 du->dk_multi = 1;
1466 } else {
1467 if (wdwait(du, WDCS_READY, TIMEOUT) < 0) {
1468 du->dk_multi = 1;
1469 }
1470 }
1471 } else {
1472 du->dk_multi = 1;
1473 }
1474 }
1475
1476 /*
1477 * issue IDC to drive to tell it just what geometry it is to be.
1478 */
1479 static int
1480 wdsetctlr(struct disk *du)
1481 {
1482 int error = 0;
1483 #ifdef WDDEBUG
1484 printf("wd(%d,%d): wdsetctlr: C %lu H %lu S %lu\n",
1485 du->dk_ctrlr, du->dk_unit,
1486 du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks,
1487 du->dk_dd.d_nsectors);
1488 #endif
1489 if (du->dk_dd.d_ntracks == 0 || du->dk_dd.d_ntracks > 16) {
1490 struct wdparams *wp;
1491
1492 printf("wd%d: can't handle %lu heads from partition table ",
1493 du->dk_lunit, du->dk_dd.d_ntracks);
1494 /* obtain parameters */
1495 wp = &du->dk_params;
1496 if (wp->wdp_heads > 0 && wp->wdp_heads <= 16) {
1497 printf("(controller value %u restored)\n",
1498 wp->wdp_heads);
1499 du->dk_dd.d_ntracks = wp->wdp_heads;
1500 }
1501 else {
1502 printf("(truncating to 16)\n");
1503 du->dk_dd.d_ntracks = 16;
1504 }
1505 }
1506
1507 if (du->dk_dd.d_nsectors == 0 || du->dk_dd.d_nsectors > 255) {
1508 printf("wd%d: cannot handle %lu sectors (max 255)\n",
1509 du->dk_lunit, du->dk_dd.d_nsectors);
1510 error = 1;
1511 }
1512 if (error) {
1513 #ifdef CMD640
1514 wdtab[du->dk_ctrlr_cmd640].b_errcnt += RETRIES;
1515 #else
1516 wdtab[du->dk_ctrlr].b_errcnt += RETRIES;
1517 #endif
1518 return (1);
1519 }
1520 if (wdcommand(du, du->dk_dd.d_ncylinders, du->dk_dd.d_ntracks - 1, 0,
1521 du->dk_dd.d_nsectors, WDCC_IDC) != 0
1522 || wdwait(du, WDCS_READY, TIMEOUT) < 0) {
1523 wderror((struct buf *)NULL, du, "wdsetctlr failed");
1524 return (1);
1525 }
1526
1527 wdsetmulti(du);
1528
1529 #ifdef NOTYET
1530 /* set read caching and write caching */
1531 wdcommand(du, 0, 0, 0, WDFEA_RCACHE, WDCC_FEATURES);
1532 wdwait(du, WDCS_READY, TIMEOUT);
1533
1534 wdcommand(du, 0, 0, 0, WDFEA_WCACHE, WDCC_FEATURES);
1535 wdwait(du, WDCS_READY, TIMEOUT);
1536 #endif
1537
1538 return (0);
1539 }
1540
1541 #if 0
1542 /*
1543 * Wait until driver is inactive, then set up controller.
1544 */
1545 static int
1546 wdwsetctlr(struct disk *du)
1547 {
1548 int stat;
1549 int x;
1550
1551 wdsleep(du->dk_ctrlr, "wdwset");
1552 x = splbio();
1553 stat = wdsetctlr(du);
1554 wdflushirq(du, x);
1555 splx(x);
1556 return (stat);
1557 }
1558 #endif
1559
1560 /*
1561 * issue READP to drive to ask it what it is.
1562 */
1563 static int
1564 wdgetctlr(struct disk *du)
1565 {
1566 int i;
1567 char tb[DEV_BSIZE], tb2[DEV_BSIZE];
1568 struct wdparams *wp = NULL;
1569 u_long flags = du->cfg_flags;
1570 again:
1571 if (wdcommand(du, 0, 0, 0, 0, WDCC_READP) != 0
1572 || wdwait(du, WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ, TIMEOUT) != 0) {
1573
1574 /*
1575 * if we failed on the second try, assume non-32bit
1576 */
1577 if( du->dk_flags & DKFL_32BIT)
1578 goto failed;
1579
1580 /* XXX need to check error status after final transfer. */
1581 /*
1582 * Old drives don't support WDCC_READP. Try a seek to 0.
1583 * Some IDE controllers return trash if there is no drive
1584 * attached, so first test that the drive can be selected.
1585 * This also avoids long waits for nonexistent drives.
1586 */
1587 if (wdwait(du, 0, TIMEOUT) < 0)
1588 return (1);
1589 outb(du->dk_port + wd_sdh, WDSD_IBM | (du->dk_unit << 4));
1590 DELAY(5000); /* usually unnecessary; drive select is fast */
1591 /*
1592 * Do this twice: may get a false WDCS_READY the first time.
1593 */
1594 inb(du->dk_port + wd_status);
1595 if ((inb(du->dk_port + wd_status) & (WDCS_BUSY | WDCS_READY))
1596 != WDCS_READY
1597 || wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) != 0
1598 || wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0)
1599 return (1);
1600
1601 if (du->dk_unit == bootinfo.bi_n_bios_used) {
1602 du->dk_dd.d_secsize = DEV_BSIZE;
1603 du->dk_dd.d_nsectors =
1604 bootinfo.bi_bios_geom[du->dk_unit] & 0xff;
1605 du->dk_dd.d_ntracks =
1606 ((bootinfo.bi_bios_geom[du->dk_unit] >> 8) & 0xff)
1607 + 1;
1608 /* XXX Why 2 ? */
1609 du->dk_dd.d_ncylinders =
1610 (bootinfo.bi_bios_geom[du->dk_unit] >> 16) + 2;
1611 du->dk_dd.d_secpercyl =
1612 du->dk_dd.d_ntracks * du->dk_dd.d_nsectors;
1613 du->dk_dd.d_secperunit =
1614 du->dk_dd.d_secpercyl * du->dk_dd.d_ncylinders;
1615 #if 0
1616 du->dk_dd.d_partitions[WDRAW].p_size =
1617 du->dk_dd.d_secperunit;
1618 du->dk_dd.d_type = DTYPE_ST506;
1619 du->dk_dd.d_subtype |= DSTYPE_GEOMETRY;
1620 strncpy(du->dk_dd.d_typename, "Bios geometry",
1621 sizeof du->dk_dd.d_typename);
1622 strncpy(du->dk_params.wdp_model, "ST506",
1623 sizeof du->dk_params.wdp_model);
1624 #endif
1625 bootinfo.bi_n_bios_used ++;
1626 return 0;
1627 }
1628 /*
1629 * Fake minimal drive geometry for reading the MBR.
1630 * readdisklabel() may enlarge it to read the label and the
1631 * bad sector table.
1632 */
1633 du->dk_dd.d_secsize = DEV_BSIZE;
1634 du->dk_dd.d_nsectors = 17;
1635 du->dk_dd.d_ntracks = 1;
1636 du->dk_dd.d_ncylinders = 1;
1637 du->dk_dd.d_secpercyl = 17;
1638 du->dk_dd.d_secperunit = 17;
1639
1640 #if 0
1641 /*
1642 * Fake maximal drive size for writing the label.
1643 */
1644 du->dk_dd.d_partitions[RAW_PART].p_size = 64 * 16 * 1024;
1645
1646 /*
1647 * Fake some more of the label for printing by disklabel(1)
1648 * in case there is no real label.
1649 */
1650 du->dk_dd.d_type = DTYPE_ST506;
1651 du->dk_dd.d_subtype |= DSTYPE_GEOMETRY;
1652 strncpy(du->dk_dd.d_typename, "Fake geometry",
1653 sizeof du->dk_dd.d_typename);
1654 #endif
1655
1656 /* Fake the model name for printing by wdattach(). */
1657 strncpy(du->dk_params.wdp_model, "unknown",
1658 sizeof du->dk_params.wdp_model);
1659
1660 return (0);
1661 }
1662
1663 /* obtain parameters */
1664 wp = &du->dk_params;
1665 if (du->dk_flags & DKFL_32BIT)
1666 insl(du->dk_port + wd_data, tb, sizeof(tb) / sizeof(long));
1667 else
1668 insw(du->dk_port + wd_data, tb, sizeof(tb) / sizeof(short));
1669
1670 /* try 32-bit data path (VLB IDE controller) */
1671 if (flags & WDOPT_32BIT) {
1672 if (! (du->dk_flags & DKFL_32BIT)) {
1673 bcopy(tb, tb2, sizeof(struct wdparams));
1674 du->dk_flags |= DKFL_32BIT;
1675 goto again;
1676 }
1677
1678 /* check that we really have 32-bit controller */
1679 if (bcmp (tb, tb2, sizeof(struct wdparams)) != 0) {
1680 failed:
1681 /* test failed, use 16-bit i/o mode */
1682 bcopy(tb2, tb, sizeof(struct wdparams));
1683 du->dk_flags &= ~DKFL_32BIT;
1684 }
1685 }
1686
1687 bcopy(tb, wp, sizeof(struct wdparams));
1688
1689 /* shuffle string byte order */
1690 for (i = 0; i < sizeof(wp->wdp_model); i += 2) {
1691 u_short *p;
1692
1693 p = (u_short *) (wp->wdp_model + i);
1694 *p = ntohs(*p);
1695 }
1696 /*
1697 * Clean up the wdp_model by converting nulls to spaces, and
1698 * then removing the trailing spaces.
1699 */
1700 for (i=0; i < sizeof(wp->wdp_model); i++) {
1701 if (wp->wdp_model[i] == '\0') {
1702 wp->wdp_model[i] = ' ';
1703 }
1704 }
1705 for (i=sizeof(wp->wdp_model)-1; i>=0 && wp->wdp_model[i]==' '; i--) {
1706 wp->wdp_model[i] = '\0';
1707 }
1708
1709 /*
1710 * find out the drives maximum multi-block transfer capability
1711 */
1712 du->dk_multi = wp->wdp_nsecperint & 0xff;
1713 wdsetmulti(du);
1714
1715 #ifdef WDDEBUG
1716 printf(
1717 "\nwd(%d,%d): wdgetctlr: gc %x cyl %d trk %d sec %d type %d sz %d model %s\n",
1718 du->dk_ctrlr, du->dk_unit, wp->wdp_config, wp->wdp_cylinders,
1719 wp->wdp_heads, wp->wdp_sectors, wp->wdp_buffertype,
1720 wp->wdp_buffersize, wp->wdp_model);
1721 #endif
1722
1723 /* update disklabel given drive information */
1724 du->dk_dd.d_secsize = DEV_BSIZE;
1725 du->dk_dd.d_ncylinders = wp->wdp_cylinders; /* +- 1 */
1726 du->dk_dd.d_ntracks = wp->wdp_heads;
1727 du->dk_dd.d_nsectors = wp->wdp_sectors;
1728 du->dk_dd.d_secpercyl = du->dk_dd.d_ntracks * du->dk_dd.d_nsectors;
1729 du->dk_dd.d_secperunit = du->dk_dd.d_secpercyl * du->dk_dd.d_ncylinders;
1730 if (wp->wdp_cylinders == 16383 &&
1731 du->dk_dd.d_secperunit < wp->wdp_lbasize) {
1732 du->dk_dd.d_secperunit = wp->wdp_lbasize;
1733 du->dk_dd.d_ncylinders =
1734 du->dk_dd.d_secperunit / du->dk_dd.d_secpercyl;
1735 }
1736
1737 if (WDOPT_FORCEHD(du->cfg_flags)) {
1738 du->dk_dd.d_ntracks = WDOPT_FORCEHD(du->cfg_flags);
1739 du->dk_dd.d_secpercyl =
1740 du->dk_dd.d_ntracks * du->dk_dd.d_nsectors;
1741 du->dk_dd.d_ncylinders =
1742 du->dk_dd.d_secperunit / du->dk_dd.d_secpercyl;
1743 }
1744 #if 0
1745 du->dk_dd.d_partitions[RAW_PART].p_size = du->dk_dd.d_secperunit;
1746 /* dubious ... */
1747 bcopy("ESDI/IDE", du->dk_dd.d_typename, 9);
1748 bcopy(wp->wdp_model + 20, du->dk_dd.d_packname, 14 - 1);
1749 /* better ... */
1750 du->dk_dd.d_type = DTYPE_ESDI;
1751 du->dk_dd.d_subtype |= DSTYPE_GEOMETRY;
1752 #endif
1753
1754 return (0);
1755 }
1756
1757 int
1758 wdclose(dev_t dev, int flags, int fmt, struct proc *p)
1759 {
1760 dsclose(dev, fmt, wddrives[dkunit(dev)]->dk_slices);
1761 return (0);
1762 }
1763
1764 int
1765 wdioctl(dev_t dev, int cmd, caddr_t addr, int flags, struct proc *p)
1766 {
1767 int lunit = dkunit(dev);
1768 register struct disk *du;
1769 int error;
1770 #ifdef notyet
1771 struct uio auio;
1772 struct iovec aiov;
1773 struct format_op *fop;
1774 #endif
1775
1776 du = wddrives[lunit];
1777 wdsleep(du->dk_ctrlr, "wdioct");
1778 error = dsioctl("wd", dev, cmd, addr, flags, &du->dk_slices,
1779 wdstrategy1, (ds_setgeom_t *)NULL);
1780 if (error != -1)
1781 return (error);
1782
1783 switch (cmd) {
1784 case DIOCSBADSCAN:
1785 if (*(int *)addr)
1786 du->dk_flags |= DKFL_BADSCAN;
1787 else
1788 du->dk_flags &= ~DKFL_BADSCAN;
1789 return (0);
1790 #ifdef notyet
1791 case DIOCWFORMAT:
1792 if (!(flag & FWRITE))
1793 return (EBADF);
1794 fop = (struct format_op *)addr;
1795 aiov.iov_base = fop->df_buf;
1796 aiov.iov_len = fop->df_count;
1797 auio.uio_iov = &aiov;
1798 auio.uio_iovcnt = 1;
1799 auio.uio_resid = fop->df_count;
1800 auio.uio_segflg = 0;
1801 auio.uio_offset = fop->df_startblk * du->dk_dd.d_secsize;
1802 #error /* XXX the 386BSD interface is different */
1803 error = physio(wdformat, &rwdbuf[lunit], 0, dev, B_WRITE,
1804 minphys, &auio);
1805 fop->df_count -= auio.uio_resid;
1806 fop->df_reg[0] = du->dk_status;
1807 fop->df_reg[1] = du->dk_error;
1808 return (error);
1809 #endif
1810
1811 default:
1812 return (ENOTTY);
1813 }
1814 }
1815
1816 #ifdef B_FORMAT
1817 int
1818 wdformat(struct buf *bp)
1819 {
1820
1821 bp->b_flags |= B_FORMAT;
1822 wdstrategy(bp);
1823 /*
1824 * phk put this here, better that return(wdstrategy(bp));
1825 * XXX
1826 */
1827 return -1;
1828 }
1829 #endif
1830
1831 int
1832 wdsize(dev_t dev)
1833 {
1834 struct disk *du;
1835 int lunit;
1836
1837 lunit = dkunit(dev);
1838 if (lunit >= NWD || dktype(dev) != 0)
1839 return (-1);
1840 du = wddrives[lunit];
1841 if (du == NULL)
1842 return (-1);
1843 return (dssize(dev, &du->dk_slices, wdopen, wdclose));
1844 }
1845
1846 /*
1847 * Dump core after a system crash.
1848 */
1849 int
1850 wddump(dev_t dev)
1851 {
1852 register struct disk *du;
1853 struct disklabel *lp;
1854 long num; /* number of sectors to write */
1855 int lunit, part;
1856 long blkoff, blknum;
1857 long blkchk, blkcnt, blknext;
1858 long cylin, head, sector;
1859 long secpertrk, secpercyl, nblocks;
1860 u_long ds_offset;
1861 char *addr;
1862 static int wddoingadump = 0;
1863
1864 /* Toss any characters present prior to dump. */
1865 while (cncheckc() != -1)
1866 ;
1867
1868 /* Check for acceptable device. */
1869 /* XXX should reset to maybe allow du->dk_state < OPEN. */
1870 lunit = dkunit(dev); /* eventually support floppies? */
1871 part = dkpart(dev);
1872 if (lunit >= NWD || (du = wddrives[lunit]) == NULL
1873 || du->dk_state < OPEN
1874 || (lp = dsgetlabel(dev, du->dk_slices)) == NULL)
1875 return (ENXIO);
1876
1877 /* Size of memory to dump, in disk sectors. */
1878 num = (u_long)Maxmem * PAGE_SIZE / du->dk_dd.d_secsize;
1879
1880 secpertrk = du->dk_dd.d_nsectors;
1881 secpercyl = du->dk_dd.d_secpercyl;
1882 nblocks = lp->d_partitions[part].p_size;
1883 blkoff = lp->d_partitions[part].p_offset;
1884 /* XXX */
1885 ds_offset = du->dk_slices->dss_slices[dkslice(dev)].ds_offset;
1886 blkoff += ds_offset;
1887
1888 #if 0
1889 pg("part %x, nblocks %d, dumplo %d num %d\n",
1890 part, nblocks, dumplo, num);
1891 #endif
1892
1893 /* Check transfer bounds against partition size. */
1894 if (dumplo < 0 || dumplo + num > nblocks)
1895 return (EINVAL);
1896
1897 /* Check if we are being called recursively. */
1898 if (wddoingadump)
1899 return (EFAULT);
1900
1901 #if 0
1902 /* Mark controller active for if we panic during the dump. */
1903 wdtab[du->dk_ctrlr].b_active = 1;
1904 #endif
1905 wddoingadump = 1;
1906
1907 /* Recalibrate the drive. */
1908 DELAY(5); /* ATA spec XXX NOT */
1909 if (wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) != 0
1910 || wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0
1911 || wdsetctlr(du) != 0) {
1912 wderror((struct buf *)NULL, du, "wddump: recalibrate failed");
1913 return (EIO);
1914 }
1915
1916 du->dk_flags |= DKFL_SINGLE;
1917 addr = (char *) 0;
1918 blknum = dumplo + blkoff;
1919 while (num > 0) {
1920 blkcnt = num;
1921 if (blkcnt > MAXTRANSFER)
1922 blkcnt = MAXTRANSFER;
1923 /* Keep transfer within current cylinder. */
1924 if ((blknum + blkcnt - 1) / secpercyl != blknum / secpercyl)
1925 blkcnt = secpercyl - (blknum % secpercyl);
1926 blknext = blknum + blkcnt;
1927
1928 /*
1929 * See if one of the sectors is in the bad sector list
1930 * (if we have one). If the first sector is bad, then
1931 * reduce the transfer to this one bad sector; if another
1932 * sector is bad, then reduce reduce the transfer to
1933 * avoid any bad sectors.
1934 */
1935 if (du->dk_flags & DKFL_SINGLE
1936 && dsgetbad(dev, du->dk_slices) != NULL) {
1937 for (blkchk = blknum; blkchk < blknum + blkcnt; blkchk++) {
1938 daddr_t blknew;
1939 blknew = transbad144(dsgetbad(dev, du->dk_slices),
1940 blkchk - ds_offset) + ds_offset;
1941 if (blknew != blkchk) {
1942 /* Found bad block. */
1943 blkcnt = blkchk - blknum;
1944 if (blkcnt > 0) {
1945 blknext = blknum + blkcnt;
1946 goto out;
1947 }
1948 blkcnt = 1;
1949 blknext = blknum + blkcnt;
1950 #if 1 || defined(WDDEBUG)
1951 printf("bad block %lu -> %lu\n",
1952 blknum, blknew);
1953 #endif
1954 break;
1955 }
1956 }
1957 }
1958 out:
1959
1960 /* Compute disk address. */
1961 cylin = blknum / secpercyl;
1962 head = (blknum % secpercyl) / secpertrk;
1963 sector = blknum % secpertrk;
1964
1965 #if 0
1966 /* Let's just talk about this first... */
1967 pg("cylin l%d head %ld sector %ld addr 0x%x count %ld",
1968 cylin, head, sector, addr, blkcnt);
1969 #endif
1970
1971 /* Do the write. */
1972 if (wdcommand(du, cylin, head, sector, blkcnt, WDCC_WRITE)
1973 != 0) {
1974 wderror((struct buf *)NULL, du,
1975 "wddump: timeout waiting to to give command");
1976 return (EIO);
1977 }
1978 while (blkcnt != 0) {
1979 if (is_physical_memory((vm_offset_t)addr))
1980 pmap_enter(kernel_pmap, (vm_offset_t)CADDR1,
1981 trunc_page(addr), VM_PROT_READ, TRUE);
1982 else
1983 pmap_enter(kernel_pmap, (vm_offset_t)CADDR1,
1984 trunc_page(0), VM_PROT_READ, TRUE);
1985
1986 /* Ready to send data? */
1987 DELAY(5); /* ATA spec */
1988 if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ, TIMEOUT)
1989 < 0) {
1990 wderror((struct buf *)NULL, du,
1991 "wddump: timeout waiting for DRQ");
1992 return (EIO);
1993 }
1994 if (du->dk_flags & DKFL_32BIT)
1995 outsl(du->dk_port + wd_data,
1996 CADDR1 + ((int)addr & PAGE_MASK),
1997 DEV_BSIZE / sizeof(long));
1998 else
1999 outsw(du->dk_port + wd_data,
2000 CADDR1 + ((int)addr & PAGE_MASK),
2001 DEV_BSIZE / sizeof(short));
2002 addr += DEV_BSIZE;
2003 /*
2004 * If we are dumping core, it may take a while.
2005 * So reassure the user and hold off any watchdogs.
2006 */
2007 if ((unsigned)addr % (1024 * 1024) == 0) {
2008 #ifdef HW_WDOG
2009 if (wdog_tickler)
2010 (*wdog_tickler)();
2011 #endif /* HW_WDOG */
2012 printf("%ld ", num / (1024 * 1024 / DEV_BSIZE));
2013 }
2014 num--;
2015 blkcnt--;
2016 }
2017
2018 /* Wait for completion. */
2019 DELAY(5); /* ATA spec XXX NOT */
2020 if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) < 0) {
2021 wderror((struct buf *)NULL, du,
2022 "wddump: timeout waiting for status");
2023 return (EIO);
2024 }
2025
2026 /* Check final status. */
2027 if (du->dk_status
2028 & (WDCS_READY | WDCS_SEEKCMPLT | WDCS_DRQ | WDCS_ERR)
2029 != (WDCS_READY | WDCS_SEEKCMPLT)) {
2030 wderror((struct buf *)NULL, du,
2031 "wddump: extra DRQ, or error");
2032 return (EIO);
2033 }
2034
2035 /* Update block count. */
2036 blknum = blknext;
2037
2038 /* Operator aborting dump? */
2039 if (cncheckc() != -1)
2040 return (EINTR);
2041 }
2042 return (0);
2043 }
2044
2045 static void
2046 wderror(struct buf *bp, struct disk *du, char *mesg)
2047 {
2048 if (bp == NULL)
2049 printf("wd%d: %s:\n", du->dk_lunit, mesg);
2050 else
2051 diskerr(bp, "wd", mesg, LOG_PRINTF, du->dk_skip,
2052 dsgetlabel(bp->b_dev, du->dk_slices));
2053 printf("wd%d: status %b error %b\n", du->dk_lunit,
2054 du->dk_status, WDCS_BITS, du->dk_error, WDERR_BITS);
2055 }
2056
2057 /*
2058 * Discard any interrupts that were latched by the interrupt system while
2059 * we were doing polled i/o.
2060 */
2061 static void
2062 wdflushirq(struct disk *du, int old_ipl)
2063 {
2064 #ifdef CMD640
2065 wdtab[du->dk_ctrlr_cmd640].b_active = 2;
2066 splx(old_ipl);
2067 (void)splbio();
2068 wdtab[du->dk_ctrlr_cmd640].b_active = 0;
2069 #else
2070 wdtab[du->dk_ctrlr].b_active = 2;
2071 splx(old_ipl);
2072 (void)splbio();
2073 wdtab[du->dk_ctrlr].b_active = 0;
2074 #endif
2075 }
2076
2077 /*
2078 * Reset the controller.
2079 */
2080 static int
2081 wdreset(struct disk *du)
2082 {
2083 int wdc, err = 0;
2084
2085 wdc = du->dk_port;
2086 (void)wdwait(du, 0, TIMEOUT);
2087 outb(wdc + wd_ctlr, WDCTL_IDS | WDCTL_RST);
2088 DELAY(10 * 1000);
2089 outb(wdc + wd_ctlr, WDCTL_IDS);
2090 #ifdef ATAPI
2091 if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0)
2092 err = 1; /* no IDE drive found */
2093 du->dk_error = inb(wdc + wd_error);
2094 if (du->dk_error != 0x01)
2095 err = 1; /* the drive is incompatible */
2096 #else
2097 if (wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) != 0
2098 || (du->dk_error = inb(wdc + wd_error)) != 0x01)
2099 return (1);
2100 #endif
2101 outb(wdc + wd_ctlr, WDCTL_4BIT);
2102 return (err);
2103 }
2104
2105 /*
2106 * Sleep until driver is inactive.
2107 * This is used only for avoiding rare race conditions, so it is unimportant
2108 * that the sleep may be far too short or too long.
2109 */
2110 static void
2111 wdsleep(int ctrlr, char *wmesg)
2112 {
2113 int s = splbio();
2114 #ifdef CMD640
2115 if (eide_quirks & Q_CMD640B)
2116 ctrlr = PRIMARY;
2117 #endif
2118 while (wdtab[ctrlr].b_active)
2119 tsleep((caddr_t)&wdtab[ctrlr].b_active, PZERO - 1, wmesg, 1);
2120 splx(s);
2121 }
2122
2123 static void
2124 wdtimeout(void *cdu)
2125 {
2126 struct disk *du;
2127 int x;
2128 static int timeouts;
2129
2130 du = (struct disk *)cdu;
2131 x = splbio();
2132 if (du->dk_timeout != 0 && --du->dk_timeout == 0) {
2133 if(timeouts++ == 5)
2134 wderror((struct buf *)NULL, du,
2135 "Last time I say: interrupt timeout. Probably a portable PC.");
2136 else if(timeouts++ < 5)
2137 wderror((struct buf *)NULL, du, "interrupt timeout");
2138 wdunwedge(du);
2139 wdflushirq(du, x);
2140 du->dk_skip = 0;
2141 du->dk_flags |= DKFL_SINGLE;
2142 wdstart(du->dk_ctrlr);
2143 }
2144 timeout(wdtimeout, cdu, hz);
2145 splx(x);
2146 }
2147
2148 /*
2149 * Reset the controller after it has become wedged. This is different from
2150 * wdreset() so that wdreset() can be used in the probe and so that this
2151 * can restore the geometry .
2152 */
2153 static int
2154 wdunwedge(struct disk *du)
2155 {
2156 struct disk *du1;
2157 int lunit;
2158
2159 /* Schedule other drives for recalibration. */
2160 for (lunit = 0; lunit < NWD; lunit++)
2161 if ((du1 = wddrives[lunit]) != NULL && du1 != du
2162 && du1->dk_ctrlr == du->dk_ctrlr
2163 && du1->dk_state > WANTOPEN)
2164 du1->dk_state = WANTOPEN;
2165
2166 DELAY(RECOVERYTIME);
2167 if (wdreset(du) == 0) {
2168 /*
2169 * XXX - recalibrate current drive now because some callers
2170 * aren't prepared to have its state change.
2171 */
2172 if (wdcommand(du, 0, 0, 0, 0, WDCC_RESTORE | WD_STEP) == 0
2173 && wdwait(du, WDCS_READY | WDCS_SEEKCMPLT, TIMEOUT) == 0
2174 && wdsetctlr(du) == 0)
2175 return (0);
2176 }
2177 wderror((struct buf *)NULL, du, "wdunwedge failed");
2178 return (1);
2179 }
2180
2181 /*
2182 * Wait uninterruptibly until controller is not busy and either certain
2183 * status bits are set or an error has occurred.
2184 * The wait is usually short unless it is for the controller to process
2185 * an entire critical command.
2186 * Return 1 for (possibly stale) controller errors, -1 for timeout errors,
2187 * or 0 for no errors.
2188 * Return controller status in du->dk_status and, if there was a controller
2189 * error, return the error code in du->dk_error.
2190 */
2191 #ifdef WD_COUNT_RETRIES
2192 static int min_retries[NWDC];
2193 #endif
2194
2195 static int
2196 wdwait(struct disk *du, u_char bits_wanted, int timeout)
2197 {
2198 int wdc;
2199 u_char status;
2200
2201 #define POLLING 1000
2202
2203 wdc = du->dk_port;
2204 timeout += POLLING;
2205
2206 /*
2207 * This delay is really too long, but does not impact the performance
2208 * as much when using the multi-sector option. Shorter delays have
2209 * caused I/O errors on some drives and system configs. This should
2210 * probably be fixed if we develop a better short term delay mechanism.
2211 */
2212 DELAY(1);
2213
2214 do {
2215 #ifdef WD_COUNT_RETRIES
2216 if (min_retries[du->dk_ctrlr] > timeout
2217 || min_retries[du->dk_ctrlr] == 0)
2218 min_retries[du->dk_ctrlr] = timeout;
2219 #endif
2220 du->dk_status = status = inb(wdc + wd_status);
2221 #ifdef ATAPI
2222 /*
2223 * Atapi drives have a very interesting feature, when attached
2224 * as a slave on the IDE bus, and there is no master.
2225 * They release the bus after getting the command.
2226 * We should reselect the drive here to get the status.
2227 */
2228 if (status == 0xff) {
2229 outb(wdc + wd_sdh, WDSD_IBM | du->dk_unit << 4);
2230 du->dk_status = status = inb(wdc + wd_status);
2231 }
2232 #endif
2233 if (!(status & WDCS_BUSY)) {
2234 if (status & WDCS_ERR) {
2235 du->dk_error = inb(wdc + wd_error);
2236 /*
2237 * We once returned here. This is wrong
2238 * because the error bit is apparently only
2239 * valid after the controller has interrupted
2240 * (e.g., the error bit is stale when we wait
2241 * for DRQ for writes). So we can't depend
2242 * on the error bit at all when polling for
2243 * command completion.
2244 */
2245 }
2246 if ((status & bits_wanted) == bits_wanted)
2247 return (status & WDCS_ERR);
2248 }
2249 if (timeout < TIMEOUT)
2250 /*
2251 * Switch to a polling rate of about 1 KHz so that
2252 * the timeout is almost machine-independent. The
2253 * controller is taking a long time to respond, so
2254 * an extra msec won't matter.
2255 */
2256 DELAY(1000);
2257 else
2258 DELAY(1);
2259 } while (--timeout != 0);
2260 return (-1);
2261 }
2262
2263 static wd_devsw_installed = 0;
2264
2265 static void wd_drvinit(void *unused)
2266 {
2267
2268 if( ! wd_devsw_installed ) {
2269 bdevsw_add_generic(BDEV_MAJOR,CDEV_MAJOR, &wd_bdevsw);
2270 wd_devsw_installed = 1;
2271 }
2272 }
2273
2274 SYSINIT(wddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,wd_drvinit,NULL)
2275
2276
2277 #endif /* NWDC > 0 */
Cache object: df686b0e3949fd1621dc446d86fd76ec
|