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