xref: /netbsd-src/sys/dev/ata/wd.c (revision 037708cbd4616ccd0d7d0381ebd3964d6696c188)
1 /*	$NetBSD: wd.c,v 1.156 1997/01/17 20:45:29 perry Exp $	*/
2 
3 /*
4  * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
5  *
6  * DMA and multi-sector PIO handling are derived from code contributed by
7  * Onno van der Linden.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *	This product includes software developed by Charles M. Hannum.
20  * 4. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/conf.h>
39 #include <sys/file.h>
40 #include <sys/stat.h>
41 #include <sys/ioctl.h>
42 #include <sys/buf.h>
43 #include <sys/uio.h>
44 #include <sys/malloc.h>
45 #include <sys/device.h>
46 #include <sys/disklabel.h>
47 #include <sys/disk.h>
48 #include <sys/syslog.h>
49 #include <sys/proc.h>
50 
51 #include <vm/vm.h>
52 
53 #include <machine/cpu.h>
54 #include <machine/intr.h>
55 #include <machine/pio.h>
56 
57 #include <dev/isa/isavar.h>
58 #include <dev/isa/isadmavar.h>
59 #include <dev/isa/wdreg.h>
60 
61 #define	WAITTIME	(4 * hz)	/* time to wait for a completion */
62 #define	RECOVERYTIME	(hz / 2)	/* time to recover from an error */
63 
64 #define WDCDELAY	100
65 #define WDCNDELAY	100000		/* delay = 100us; so 10s for a controller state change */
66 #if 0
67 /* If you enable this, it will report any delays more than 100us * N long. */
68 #define WDCNDELAY_DEBUG	10
69 #endif
70 
71 #define	WDIORETRIES	5		/* number of retries before giving up */
72 
73 #define	WDUNIT(dev)			DISKUNIT(dev)
74 #define	WDPART(dev)			DISKPART(dev)
75 #define	MAKEWDDEV(maj, unit, part)	MAKEDISKDEV(maj, unit, part)
76 
77 #define	WDLABELDEV(dev)	(MAKEWDDEV(major(dev), WDUNIT(dev), RAW_PART))
78 
79 struct wd_softc {
80 	struct device sc_dev;
81 	struct disk sc_dk;
82 
83 	/* Information about the current transfer: */
84 	daddr_t sc_blkno;	/* starting block number */
85 	int sc_bcount;		/* byte count left */
86 	int sc_skip;		/* bytes already transferred */
87 	int sc_nblks;		/* number of blocks currently transferring */
88 	int sc_nbytes;		/* number of bytes currently transferring */
89 
90 	/* Long-term state: */
91 	int sc_drive;			/* physical unit number */
92 	int sc_state;			/* control state */
93 #define	RECAL		0		/* recalibrate */
94 #define	RECAL_WAIT	1		/* done recalibrating */
95 #define	GEOMETRY	2		/* upload geometry */
96 #define	GEOMETRY_WAIT	3		/* done uploading geometry */
97 #define	MULTIMODE	4		/* set multiple mode */
98 #define	MULTIMODE_WAIT	5		/* done setting multiple mode */
99 #define	READY		6		/* ready for use */
100 	int sc_mode;			/* transfer mode */
101 #define	WDM_PIOSINGLE	0		/* single-sector PIO */
102 #define	WDM_PIOMULTI	1		/* multi-sector PIO */
103 #define	WDM_DMA		2		/* DMA */
104 	int sc_multiple;		/* multiple for WDM_PIOMULTI */
105 	int sc_flags;			/* drive characteistics found */
106 #define	WDF_LOCKED	0x01
107 #define	WDF_WANTED	0x02
108 #define	WDF_WLABEL	0x04		/* label is writable */
109 #define	WDF_LABELLING	0x08		/* writing label */
110 /* XXX Nothing resets this yet, but disk change sensing will when ATAPI is
111    implemented. */
112 #define	WDF_LOADED	0x10		/* parameters loaded */
113 #define	WDF_32BIT	0x20		/* can do 32-bit transfer */
114 
115 	struct wdparams sc_params;	/* ESDI/ATA drive parameters */
116 	daddr_t	sc_badsect[127];	/* 126 plus trailing -1 marker */
117 
118 	TAILQ_ENTRY(wd_softc) sc_drivechain;
119 	struct buf sc_q;
120 };
121 
122 struct wdc_softc {
123 	struct device sc_dev;
124 	void *sc_ih;
125 
126 	int sc_iobase;			/* I/O port base */
127 	int sc_drq;			/* DMA channel */
128 
129 	TAILQ_HEAD(drivehead, wd_softc) sc_drives;
130 	int sc_flags;
131 #define	WDCF_ACTIVE	0x01		/* controller is active */
132 #define	WDCF_SINGLE	0x02		/* sector at a time mode */
133 #define	WDCF_ERROR	0x04		/* processing a disk error */
134 #define	WDCF_WANTED	0x08		/* XXX locking for wd_get_parms() */
135 	int sc_errors;			/* errors during current transfer */
136 	u_char sc_status;		/* copy of status register */
137 	u_char sc_error;		/* copy of error register */
138 };
139 
140 int	wdcprobe 	__P((struct device *, void *, void *));
141 void	wdcattach 	__P((struct device *, struct device *, void *));
142 int	wdcintr		__P((void *));
143 
144 struct cfattach wdc_ca = {
145 	sizeof(struct wdc_softc), wdcprobe, wdcattach
146 };
147 
148 struct cfdriver wdc_cd = {
149 	NULL, "wdc", DV_DULL
150 };
151 
152 int wdprobe __P((struct device *, void *, void *));
153 void wdattach __P((struct device *, struct device *, void *));
154 int wdprint __P((void *, const char *));
155 
156 struct cfattach wd_ca = {
157 	sizeof(struct wd_softc), wdprobe, wdattach
158 };
159 
160 struct cfdriver wd_cd = {
161 	NULL, "wd", DV_DISK
162 };
163 
164 void	wdgetdisklabel	__P((struct wd_softc *));
165 int	wd_get_parms	__P((struct wd_softc *));
166 void	wdstrategy	__P((struct buf *));
167 void	wdstart		__P((struct wd_softc *));
168 
169 struct dkdriver wddkdriver = { wdstrategy };
170 
171 /* XXX: these should go elsewhere */
172 cdev_decl(wd);
173 bdev_decl(wd);
174 
175 void	wdfinish	__P((struct wd_softc *, struct buf *));
176 int 	dcintr		__P((void *));
177 void	wdcstart	__P((struct wdc_softc *));
178 int	wdcommand	__P((struct wd_softc *, int, int, int, int, int));
179 int	wdcommandshort	__P((struct wdc_softc *, int, int));
180 int	wdcontrol	__P((struct wd_softc *));
181 int	wdsetctlr	__P((struct wd_softc *));
182 static void bad144intern __P((struct wd_softc *));
183 int	wdcreset	__P((struct wdc_softc *));
184 void	wdcrestart	__P((void *arg));
185 void	wdcunwedge	__P((struct wdc_softc *));
186 void	wdctimeout	__P((void *arg));
187 void	wderror		__P((void *, struct buf *, char *));
188 int	wdcwait		__P((struct wdc_softc *, int));
189 int	wdlock		__P((struct wd_softc *));
190 void	wdunlock	__P((struct wd_softc *));
191 
192 /* ST506 spec says that if READY or SEEKCMPLT go off, then the read or write
193    command is aborted. */
194 #define	wait_for_drq(d)		wdcwait(d, WDCS_DRDY | WDCS_DSC | WDCS_DRQ)
195 #define	wait_for_ready(d)	wdcwait(d, WDCS_DRDY | WDCS_DSC)
196 #define	wait_for_unbusy(d)	wdcwait(d, 0)
197 
198 int
199 wdcprobe(parent, match, aux)
200 	struct device *parent;
201 	void *match, *aux;
202 {
203 	struct wdc_softc *wdc = match;
204 	struct isa_attach_args *ia = aux;
205 	int iobase;
206 
207 	wdc->sc_iobase = iobase = ia->ia_iobase;
208 
209 	/* Check if we have registers that work. */
210 	outb(iobase+wd_error, 0x5a);	/* Error register not writable, */
211 	outb(iobase+wd_cyl_lo, 0xa5);	/* but all of cyllo are. */
212 	if (inb(iobase+wd_error) == 0x5a || inb(iobase+wd_cyl_lo) != 0xa5)
213 		return 0;
214 
215 	if (wdcreset(wdc) != 0) {
216 		delay(500000);
217 		if (wdcreset(wdc) != 0)
218 			return 0;
219 	}
220 
221 	/* Select drive 0. */
222 	outb(iobase+wd_sdh, WDSD_IBM | 0);
223 
224 	/* Wait for controller to become ready. */
225 	if (wait_for_unbusy(wdc) < 0)
226 		return 0;
227 
228 	/* Start drive diagnostics. */
229 	outb(iobase+wd_command, WDCC_DIAGNOSE);
230 
231 	/* Wait for command to complete. */
232 	if (wait_for_unbusy(wdc) < 0)
233 		return 0;
234 
235 	ia->ia_iosize = 8;
236 	ia->ia_msize = 0;
237 	return 1;
238 }
239 
240 struct wdc_attach_args {
241 	int wa_drive;
242 };
243 
244 int
245 wdprint(aux, wdc)
246 	void *aux;
247 	const char *wdc;
248 {
249 	struct wdc_attach_args *wa = aux;
250 
251 	if (!wdc)
252 		printf(" drive %d", wa->wa_drive);
253 	return QUIET;
254 }
255 
256 void
257 wdcattach(parent, self, aux)
258 	struct device *parent, *self;
259 	void *aux;
260 {
261 	struct wdc_softc *wdc = (void *)self;
262 	struct isa_attach_args *ia = aux;
263 	struct wdc_attach_args wa;
264 
265 	TAILQ_INIT(&wdc->sc_drives);
266 	wdc->sc_drq = ia->ia_drq;
267 
268 	printf("\n");
269 
270 	wdc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
271 	    IPL_BIO, wdcintr, wdc);
272 
273 	for (wa.wa_drive = 0; wa.wa_drive < 2; wa.wa_drive++)
274 		(void)config_found(self, (void *)&wa, wdprint);
275 }
276 
277 int
278 wdprobe(parent, match, aux)
279 	struct device *parent;
280 	void *match, *aux;
281 {
282 	struct wdc_softc *wdc = (void *)parent;
283 	struct cfdata *cf = match;
284 	struct wdc_attach_args *wa = aux;
285 	int drive = wa->wa_drive;
286 
287 	if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != drive)
288 		return 0;
289 
290 	if (wdcommandshort(wdc, drive, WDCC_RECAL) != 0 ||
291 	    wait_for_ready(wdc) != 0)
292 		return 0;
293 
294 	return 1;
295 }
296 
297 void
298 wdattach(parent, self, aux)
299 	struct device *parent, *self;
300 	void *aux;
301 {
302 	struct wd_softc *wd = (void *)self;
303 	struct wdc_softc *wdc = (void *)parent;
304 	struct wdc_attach_args *wa = aux;
305 	int i, blank;
306 	char buf[41], c, *p, *q;
307 
308 	wd->sc_drive = wa->wa_drive;
309 
310 	/*
311 	 * Initialize and attach the disk structure.
312 	 */
313 	wd->sc_dk.dk_driver = &wddkdriver;
314 	wd->sc_dk.dk_name = wd->sc_dev.dv_xname;
315 	disk_attach(&wd->sc_dk);
316 
317 	wd_get_parms(wd);
318 	for (blank = 0, p = wd->sc_params.wdp_model, q = buf, i = 0;
319 	     i < sizeof(wd->sc_params.wdp_model); i++) {
320 		c = *p++;
321 		if (c == '\0')
322 			break;
323 		if (c != ' ') {
324 			if (blank) {
325 				*q++ = ' ';
326 				blank = 0;
327 			}
328 			*q++ = c;
329 		} else
330 			blank = 1;
331 	}
332 	*q++ = '\0';
333 
334 	printf(": <%s>\n%s: %dMB, %d cyl, %d head, %d sec, %d bytes/sec\n",
335 	    buf, wd->sc_dev.dv_xname,
336 	    wd->sc_params.wdp_cylinders *
337 	      (wd->sc_params.wdp_heads * wd->sc_params.wdp_sectors) /
338 	      (1048576 / DEV_BSIZE),
339 	    wd->sc_params.wdp_cylinders,
340 	    wd->sc_params.wdp_heads,
341 	    wd->sc_params.wdp_sectors,
342 	    DEV_BSIZE);
343 
344 	if ((wd->sc_params.wdp_capabilities & WD_CAP_DMA) != 0 &&
345 	    wdc->sc_drq != DRQUNK) {
346 		wd->sc_mode = WDM_DMA;
347 	} else if (wd->sc_params.wdp_maxmulti > 1) {
348 		wd->sc_mode = WDM_PIOMULTI;
349 		wd->sc_multiple = min(wd->sc_params.wdp_maxmulti, 16);
350 	} else {
351 		wd->sc_mode = WDM_PIOSINGLE;
352 		wd->sc_multiple = 1;
353 	}
354 
355 	printf("%s: using", wd->sc_dev.dv_xname);
356 	if (wd->sc_mode == WDM_DMA)
357 		printf(" dma transfers,");
358 	else
359 		printf(" %d-sector %d-bit pio transfers,",
360 		    wd->sc_multiple, (wd->sc_flags & WDF_32BIT) == 0 ? 16 : 32);
361 	if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0)
362 		printf(" lba addressing\n");
363 	else
364 		printf(" chs addressing\n");
365 }
366 
367 /*
368  * Read/write routine for a buffer.  Validates the arguments and schedules the
369  * transfer.  Does not wait for the transfer to complete.
370  */
371 void
372 wdstrategy(bp)
373 	struct buf *bp;
374 {
375 	struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(bp->b_dev)];
376 	int s;
377 
378 	/* Valid request?  */
379 	if (bp->b_blkno < 0 ||
380 	    (bp->b_bcount % wd->sc_dk.dk_label->d_secsize) != 0 ||
381 	    (bp->b_bcount / wd->sc_dk.dk_label->d_secsize) >= (1 << NBBY)) {
382 		bp->b_error = EINVAL;
383 		goto bad;
384 	}
385 
386 	/* If device invalidated (e.g. media change, door open), error. */
387 	if ((wd->sc_flags & WDF_LOADED) == 0) {
388 		bp->b_error = EIO;
389 		goto bad;
390 	}
391 
392 	/* If it's a null transfer, return immediately. */
393 	if (bp->b_bcount == 0)
394 		goto done;
395 
396 	/*
397 	 * Do bounds checking, adjust transfer. if error, process.
398 	 * If end of partition, just return.
399 	 */
400 	if (WDPART(bp->b_dev) != RAW_PART &&
401 	    bounds_check_with_label(bp, wd->sc_dk.dk_label,
402 	    (wd->sc_flags & (WDF_WLABEL|WDF_LABELLING)) != 0) <= 0)
403 		goto done;
404 
405 	/* Queue transfer on drive, activate drive and controller if idle. */
406 	s = splbio();
407 	disksort(&wd->sc_q, bp);
408 	if (!wd->sc_q.b_active)
409 		wdstart(wd);
410 #if 0
411 	else {
412 		struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
413 		if ((wdc->sc_flags & (WDCF_ACTIVE|WDCF_ERROR)) == 0) {
414 			printf("wdstrategy: controller inactive\n");
415 			wdcstart(wdc);
416 		}
417 	}
418 #endif
419 	splx(s);
420 	return;
421 
422 bad:
423 	bp->b_flags |= B_ERROR;
424 done:
425 	/* Toss transfer; we're done early. */
426 	bp->b_resid = bp->b_bcount;
427 	biodone(bp);
428 }
429 
430 /*
431  * Queue a drive for I/O.
432  */
433 void
434 wdstart(wd)
435 	struct wd_softc *wd;
436 {
437 	struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
438 	int active = wdc->sc_drives.tqh_first != 0;
439 
440 	/* Link onto controller queue. */
441 	wd->sc_q.b_active = 1;
442 	TAILQ_INSERT_TAIL(&wdc->sc_drives, wd, sc_drivechain);
443 
444 	disk_busy(&wd->sc_dk);
445 
446 	/* If controller not already active, start it. */
447 	if (!active)
448 		wdcstart(wdc);
449 }
450 
451 /*
452  * Finish an I/O operation.  Clean up the drive and controller state, set the
453  * residual count, and inform the upper layers that the operation is complete.
454  */
455 void
456 wdfinish(wd, bp)
457 	struct wd_softc *wd;
458 	struct buf *bp;
459 {
460 	struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
461 
462 	wdc->sc_flags &= ~(WDCF_SINGLE | WDCF_ERROR);
463 	wdc->sc_errors = 0;
464 	/*
465 	 * Move this drive to the end of the queue to give others a `fair'
466 	 * chance.
467 	 */
468 	if (wd->sc_drivechain.tqe_next) {
469 		TAILQ_REMOVE(&wdc->sc_drives, wd, sc_drivechain);
470 		if (bp->b_actf) {
471 			TAILQ_INSERT_TAIL(&wdc->sc_drives, wd, sc_drivechain);
472 		} else
473 			wd->sc_q.b_active = 0;
474 	}
475 	bp->b_resid = wd->sc_bcount;
476 	wd->sc_skip = 0;
477 	wd->sc_q.b_actf = bp->b_actf;
478 
479 	disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid));
480 
481 	if (!wd->sc_q.b_actf) {
482 		TAILQ_REMOVE(&wdc->sc_drives, wd, sc_drivechain);
483 		wd->sc_q.b_active = 0;
484 	} else
485 		disk_busy(&wd->sc_dk);
486 
487 	biodone(bp);
488 }
489 
490 int
491 wdread(dev, uio, flags)
492 	dev_t dev;
493 	struct uio *uio;
494 	int flags;
495 {
496 
497 	return (physio(wdstrategy, NULL, dev, B_READ, minphys, uio));
498 }
499 
500 int
501 wdwrite(dev, uio, flags)
502 	dev_t dev;
503 	struct uio *uio;
504 	int flags;
505 {
506 
507 	return (physio(wdstrategy, NULL, dev, B_WRITE, minphys, uio));
508 }
509 
510 /*
511  * Start I/O on a controller.  This does the calculation, and starts a read or
512  * write operation.  Called to from wdstart() to start a transfer, from
513  * wdcintr() to continue a multi-sector transfer or start the next transfer, or
514  * wdcrestart() after recovering from an error.
515  */
516 void
517 wdcstart(wdc)
518 	struct wdc_softc *wdc;
519 {
520 	struct wd_softc *wd;
521 	struct buf *bp;
522 	struct disklabel *lp;
523 	int nblks;
524 
525 #ifdef DIAGNOSTIC
526 	if ((wdc->sc_flags & WDCF_ACTIVE) != 0)
527 		panic("wdcstart: controller still active");
528 #endif
529 
530 	/*
531 	 * XXX
532 	 * This is a kluge.  See comments in wd_get_parms().
533 	 */
534 	if ((wdc->sc_flags & WDCF_WANTED) != 0) {
535 		wdc->sc_flags &= ~WDCF_WANTED;
536 		wakeup(wdc);
537 		return;
538 	}
539 
540 loop:
541 	/* Is there a drive for the controller to do a transfer with? */
542 	wd = wdc->sc_drives.tqh_first;
543 	if (wd == NULL)
544 		return;
545 
546 	/* Is there a transfer to this drive?  If not, deactivate drive. */
547 	bp = wd->sc_q.b_actf;
548 
549 	if (wdc->sc_errors >= WDIORETRIES) {
550 		wderror(wd, bp, "wdcstart hard error");
551 		bp->b_error = EIO;
552 		bp->b_flags |= B_ERROR;
553 		wdfinish(wd, bp);
554 		goto loop;
555 	}
556 
557 	/* Do control operations specially. */
558 	if (wd->sc_state < READY) {
559 		/*
560 		 * Actually, we want to be careful not to mess with the control
561 		 * state if the device is currently busy, but we can assume
562 		 * that we never get to this point if that's the case.
563 		 */
564 		if (wdcontrol(wd) == 0) {
565 			/* The drive is busy.  Wait. */
566 			return;
567 		}
568 	}
569 
570 	/*
571 	 * WDCF_ERROR is set by wdcunwedge() and wdcintr() when an error is
572 	 * encountered.  If we are in multi-sector mode, then we switch to
573 	 * single-sector mode and retry the operation from the start.
574 	 */
575 	if (wdc->sc_flags & WDCF_ERROR) {
576 		wdc->sc_flags &= ~WDCF_ERROR;
577 		if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
578 			wdc->sc_flags |= WDCF_SINGLE;
579 			wd->sc_skip = 0;
580 		}
581 	}
582 
583 	lp = wd->sc_dk.dk_label;
584 
585 	/* When starting a transfer... */
586 	if (wd->sc_skip == 0) {
587 		int part = WDPART(bp->b_dev);
588 		daddr_t blkno;
589 
590 #ifdef WDDEBUG
591 		printf("\n%s: wdcstart %s %ld@%d; map ", wd->sc_dev.dv_xname,
592 		    (bp->b_flags & B_READ) ? "read" : "write", bp->b_bcount,
593 		    bp->b_blkno);
594 #endif
595 		wd->sc_bcount = bp->b_bcount;
596 		blkno = bp->b_blkno;
597 		if (part != RAW_PART)
598 			blkno += lp->d_partitions[part].p_offset;
599 		wd->sc_blkno = blkno / (lp->d_secsize / DEV_BSIZE);
600 	} else {
601 #ifdef WDDEBUG
602 		printf(" %d)%x", wd->sc_skip, inb(wdc->sc_iobase+wd_altsts));
603 #endif
604 	}
605 
606 	/* When starting a multi-sector transfer, or doing single-sector
607 	    transfers... */
608 	if (wd->sc_skip == 0 || (wdc->sc_flags & WDCF_SINGLE) != 0 ||
609 	    wd->sc_mode == WDM_DMA) {
610 		daddr_t blkno = wd->sc_blkno;
611 		long cylin, head, sector;
612 		int command;
613 
614 		if ((wdc->sc_flags & WDCF_SINGLE) != 0)
615 			nblks = 1;
616 		else if (wd->sc_mode != WDM_DMA)
617 			nblks = wd->sc_bcount / lp->d_secsize;
618 		else
619 			nblks = min(wd->sc_bcount / lp->d_secsize, 8);
620 
621 		/* Check for bad sectors and adjust transfer, if necessary. */
622 		if ((lp->d_flags & D_BADSECT) != 0
623 #ifdef B_FORMAT
624 		    && (bp->b_flags & B_FORMAT) == 0
625 #endif
626 		    ) {
627 			long blkdiff;
628 			int i;
629 
630 			for (i = 0; (blkdiff = wd->sc_badsect[i]) != -1; i++) {
631 				blkdiff -= blkno;
632 				if (blkdiff < 0)
633 					continue;
634 				if (blkdiff == 0) {
635 					/* Replace current block of transfer. */
636 					blkno =
637 					    lp->d_secperunit - lp->d_nsectors - i - 1;
638 				}
639 				if (blkdiff < nblks) {
640 					/* Bad block inside transfer. */
641 					wdc->sc_flags |= WDCF_SINGLE;
642 					nblks = 1;
643 				}
644 				break;
645 			}
646 			/* Tranfer is okay now. */
647 		}
648 
649 		if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) {
650 			sector = (blkno >> 0) & 0xff;
651 			cylin = (blkno >> 8) & 0xffff;
652 			head = (blkno >> 24) & 0xf;
653 			head |= WDSD_LBA;
654 		} else {
655 			sector = blkno % lp->d_nsectors;
656 			sector++;	/* Sectors begin with 1, not 0. */
657 			blkno /= lp->d_nsectors;
658 			head = blkno % lp->d_ntracks;
659 			blkno /= lp->d_ntracks;
660 			cylin = blkno;
661 			head |= WDSD_CHS;
662 		}
663 
664 		if (wd->sc_mode == WDM_PIOSINGLE ||
665 		    (wdc->sc_flags & WDCF_SINGLE) != 0)
666 			wd->sc_nblks = 1;
667 		else if (wd->sc_mode == WDM_PIOMULTI)
668 			wd->sc_nblks = min(nblks, wd->sc_multiple);
669 		else
670 			wd->sc_nblks = nblks;
671 		wd->sc_nbytes = wd->sc_nblks * lp->d_secsize;
672 
673 #ifdef B_FORMAT
674 		if (bp->b_flags & B_FORMAT) {
675 			sector = lp->d_gap3;
676 			nblks = lp->d_nsectors;
677 			command = WDCC_FORMAT;
678 		} else
679 #endif
680 		switch (wd->sc_mode) {
681 		case WDM_DMA:
682 			command = (bp->b_flags & B_READ) ?
683 			    WDCC_READDMA : WDCC_WRITEDMA;
684 			/* Start the DMA channel and bounce the buffer if
685 			   necessary. */
686 			isa_dmastart(
687 			    bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE,
688 			    bp->b_data + wd->sc_skip,
689 			    wd->sc_nbytes, wdc->sc_drq);
690 			break;
691 		case WDM_PIOMULTI:
692 			command = (bp->b_flags & B_READ) ?
693 			    WDCC_READMULTI : WDCC_WRITEMULTI;
694 			break;
695 		case WDM_PIOSINGLE:
696 			command = (bp->b_flags & B_READ) ?
697 			    WDCC_READ : WDCC_WRITE;
698 			break;
699 		default:
700 #ifdef DIAGNOSTIC
701 			panic("bad wd mode");
702 #endif
703 			return;
704 		}
705 
706 		/* Initiate command! */
707 		if (wdcommand(wd, command, cylin, head, sector, nblks) != 0) {
708 			wderror(wd, NULL,
709 			    "wdcstart: timeout waiting for unbusy");
710 			wdcunwedge(wdc);
711 			return;
712 		}
713 
714 #ifdef WDDEBUG
715 		printf("sector %ld cylin %ld head %ld addr %p sts %x\n",
716 		    sector, cylin, head, bp->b_data,
717 		    inb(wdc->sc_iobase+wd_altsts));
718 #endif
719 	} else if (wd->sc_nblks > 1) {
720 		/* The number of blocks in the last stretch may be smaller. */
721 		nblks = wd->sc_bcount / lp->d_secsize;
722 		if (wd->sc_nblks > nblks) {
723 			wd->sc_nblks = nblks;
724 			wd->sc_nbytes = wd->sc_bcount;
725 		}
726 	}
727 
728 	/* If this was a write and not using DMA, push the data. */
729 	if (wd->sc_mode != WDM_DMA &&
730 	    (bp->b_flags & (B_READ|B_WRITE)) == B_WRITE) {
731 		if (wait_for_drq(wdc) < 0) {
732 			wderror(wd, NULL, "wdcstart: timeout waiting for drq");
733 			wdcunwedge(wdc);
734 			return;
735 		}
736 
737 		/* Push out data. */
738 		if ((wd->sc_flags & WDF_32BIT) == 0)
739 			outsw(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
740 			    wd->sc_nbytes >> 1);
741 		else
742 			outsl(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
743 			    wd->sc_nbytes >> 2);
744 	}
745 
746 	wdc->sc_flags |= WDCF_ACTIVE;
747 	timeout(wdctimeout, wdc, WAITTIME);
748 }
749 
750 /*
751  * Interrupt routine for the controller.  Acknowledge the interrupt, check for
752  * errors on the current operation, mark it done if necessary, and start the
753  * next request.  Also check for a partially done transfer, and continue with
754  * the next chunk if so.
755  */
756 int
757 wdcintr(arg)
758 	void *arg;
759 {
760 	struct wdc_softc *wdc = arg;
761 	struct wd_softc *wd;
762 	struct buf *bp;
763 
764 	if ((wdc->sc_flags & WDCF_ACTIVE) == 0) {
765 		/* Clear the pending interrupt and abort. */
766 		(void) inb(wdc->sc_iobase+wd_status);
767 		return 0;
768 	}
769 
770 	wdc->sc_flags &= ~WDCF_ACTIVE;
771 	untimeout(wdctimeout, wdc);
772 
773 	wd = wdc->sc_drives.tqh_first;
774 	bp = wd->sc_q.b_actf;
775 
776 #ifdef WDDEBUG
777 	printf("I%d ", wdc->sc_dev.dv_unit);
778 #endif
779 
780 	if (wait_for_unbusy(wdc) < 0) {
781 		wderror(wd, NULL, "wdcintr: timeout waiting for unbusy");
782 		wdc->sc_status |= WDCS_ERR;	/* XXX */
783 	}
784 
785 	/* Is it not a transfer, but a control operation? */
786 	if (wd->sc_state < READY) {
787 		if (wdcontrol(wd) == 0) {
788 			/* The drive is busy.  Wait. */
789 			return 1;
790 		}
791 		wdcstart(wdc);
792 		return 1;
793 	}
794 
795 	/* Turn off the DMA channel and unbounce the buffer. */
796 	if (wd->sc_mode == WDM_DMA)
797 		isa_dmadone(bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE,
798 		    bp->b_data + wd->sc_skip, wd->sc_nbytes, wdc->sc_drq);
799 
800 	/* Have we an error? */
801 	if (wdc->sc_status & WDCS_ERR) {
802 #ifdef WDDEBUG
803 		wderror(wd, NULL, "wdcintr");
804 #endif
805 		if ((wdc->sc_flags & WDCF_SINGLE) == 0) {
806 			wdc->sc_flags |= WDCF_ERROR;
807 			goto restart;
808 		}
809 
810 #ifdef B_FORMAT
811 		if (bp->b_flags & B_FORMAT)
812 			goto bad;
813 #endif
814 
815 		if (++wdc->sc_errors < WDIORETRIES) {
816 			if (wdc->sc_errors == (WDIORETRIES + 1) / 2) {
817 #if 0
818 				wderror(wd, NULL, "wedgie");
819 #endif
820 				wdcunwedge(wdc);
821 				return 1;
822 			}
823 			goto restart;
824 		}
825 		wderror(wd, bp, "wdcintr hard error");
826 #ifdef B_FORMAT
827 	bad:
828 #endif
829 		bp->b_error = EIO;
830 		bp->b_flags |= B_ERROR;
831 		goto done;
832 	}
833 
834 	/* If this was a read and not using DMA, fetch the data. */
835 	if (wd->sc_mode != WDM_DMA &&
836 	    (bp->b_flags & (B_READ|B_WRITE)) == B_READ) {
837 		if ((wdc->sc_status & (WDCS_DRDY | WDCS_DSC | WDCS_DRQ))
838 		    != (WDCS_DRDY | WDCS_DSC | WDCS_DRQ)) {
839 			wderror(wd, NULL, "wdcintr: read intr before drq");
840 			wdcunwedge(wdc);
841 			return 1;
842 		}
843 
844 		/* Pull in data. */
845 		if ((wd->sc_flags & WDF_32BIT) == 0)
846 			insw(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
847 			    wd->sc_nbytes >> 1);
848 		else
849 			insl(wdc->sc_iobase+wd_data, bp->b_data + wd->sc_skip,
850 			    wd->sc_nbytes >> 2);
851 	}
852 
853 	/* If we encountered any abnormalities, flag it as a soft error. */
854 	if (wdc->sc_errors > 0 ||
855 	    (wdc->sc_status & WDCS_CORR) != 0) {
856 		wderror(wd, bp, "soft error (corrected)");
857 		wdc->sc_errors = 0;
858 	}
859 
860 	/* Adjust pointers for the next block, if any. */
861 	wd->sc_blkno += wd->sc_nblks;
862 	wd->sc_skip += wd->sc_nbytes;
863 	wd->sc_bcount -= wd->sc_nbytes;
864 
865 	/* See if this transfer is complete. */
866 	if (wd->sc_bcount > 0)
867 		goto restart;
868 
869 done:
870 	/* Done with this transfer, with or without error. */
871 	wdfinish(wd, bp);
872 
873 restart:
874 	/* Start the next operation, if any. */
875 	wdcstart(wdc);
876 
877 	return 1;
878 }
879 
880 /*
881  * Wait interruptibly for an exclusive lock.
882  *
883  * XXX
884  * Several drivers do this; it should be abstracted and made MP-safe.
885  */
886 int
887 wdlock(wd)
888 	struct wd_softc *wd;
889 {
890 	int error;
891 
892 	while ((wd->sc_flags & WDF_LOCKED) != 0) {
893 		wd->sc_flags |= WDF_WANTED;
894 		if ((error = tsleep(wd, PRIBIO | PCATCH, "wdlck", 0)) != 0)
895 			return error;
896 	}
897 	wd->sc_flags |= WDF_LOCKED;
898 	return 0;
899 }
900 
901 /*
902  * Unlock and wake up any waiters.
903  */
904 void
905 wdunlock(wd)
906 	struct wd_softc *wd;
907 {
908 
909 	wd->sc_flags &= ~WDF_LOCKED;
910 	if ((wd->sc_flags & WDF_WANTED) != 0) {
911 		wd->sc_flags &= ~WDF_WANTED;
912 		wakeup(wd);
913 	}
914 }
915 
916 int
917 wdopen(dev, flag, fmt, p)
918 	dev_t dev;
919 	int flag, fmt;
920 	struct proc *p;
921 {
922 	struct wd_softc *wd;
923 	int unit, part;
924 	int error;
925 
926 	unit = WDUNIT(dev);
927 	if (unit >= wd_cd.cd_ndevs)
928 		return ENXIO;
929 	wd = wd_cd.cd_devs[unit];
930 	if (wd == 0)
931 		return ENXIO;
932 
933 	if ((error = wdlock(wd)) != 0)
934 		return error;
935 
936 	if (wd->sc_dk.dk_openmask != 0) {
937 		/*
938 		 * If any partition is open, but the disk has been invalidated,
939 		 * disallow further opens.
940 		 */
941 		if ((wd->sc_flags & WDF_LOADED) == 0) {
942 			error = EIO;
943 			goto bad3;
944 		}
945 	} else {
946 		if ((wd->sc_flags & WDF_LOADED) == 0) {
947 			wd->sc_flags |= WDF_LOADED;
948 
949 			/* Load the physical device parameters. */
950 			if (wd_get_parms(wd) != 0) {
951 				error = ENXIO;
952 				goto bad2;
953 			}
954 
955 			/* Load the partition info if not already loaded. */
956 			wdgetdisklabel(wd);
957 		}
958 	}
959 
960 	part = WDPART(dev);
961 
962 	/* Check that the partition exists. */
963 	if (part != RAW_PART &&
964 	    (part >= wd->sc_dk.dk_label->d_npartitions ||
965 	     wd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
966 		error = ENXIO;
967 		goto bad;
968 	}
969 
970 	/* Insure only one open at a time. */
971 	switch (fmt) {
972 	case S_IFCHR:
973 		wd->sc_dk.dk_copenmask |= (1 << part);
974 		break;
975 	case S_IFBLK:
976 		wd->sc_dk.dk_bopenmask |= (1 << part);
977 		break;
978 	}
979 	wd->sc_dk.dk_openmask = wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
980 
981 	wdunlock(wd);
982 	return 0;
983 
984 bad2:
985 	wd->sc_flags &= ~WDF_LOADED;
986 
987 bad:
988 	if (wd->sc_dk.dk_openmask == 0) {
989 	}
990 
991 bad3:
992 	wdunlock(wd);
993 	return error;
994 }
995 
996 int
997 wdclose(dev, flag, fmt, p)
998 	dev_t dev;
999 	int flag, fmt;
1000 	struct proc *p;
1001 {
1002 	struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)];
1003 	int part = WDPART(dev);
1004 	int error;
1005 
1006 	if ((error = wdlock(wd)) != 0)
1007 		return error;
1008 
1009 	switch (fmt) {
1010 	case S_IFCHR:
1011 		wd->sc_dk.dk_copenmask &= ~(1 << part);
1012 		break;
1013 	case S_IFBLK:
1014 		wd->sc_dk.dk_bopenmask &= ~(1 << part);
1015 		break;
1016 	}
1017 	wd->sc_dk.dk_openmask = wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
1018 
1019 	if (wd->sc_dk.dk_openmask == 0) {
1020 		/* XXXX Must wait for I/O to complete! */
1021 	}
1022 
1023 	wdunlock(wd);
1024 	return 0;
1025 }
1026 
1027 /*
1028  * Fabricate a default disk label, and try to read the correct one.
1029  */
1030 void
1031 wdgetdisklabel(wd)
1032 	struct wd_softc *wd;
1033 {
1034 	struct disklabel *lp = wd->sc_dk.dk_label;
1035 	char *errstring;
1036 
1037 	bzero(lp, sizeof(struct disklabel));
1038 	bzero(wd->sc_dk.dk_cpulabel, sizeof(struct cpu_disklabel));
1039 
1040 	lp->d_secsize = DEV_BSIZE;
1041 	lp->d_ntracks = wd->sc_params.wdp_heads;
1042 	lp->d_nsectors = wd->sc_params.wdp_sectors;
1043 	lp->d_ncylinders = wd->sc_params.wdp_cylinders;
1044 	lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
1045 
1046 #if 0
1047 	strncpy(lp->d_typename, "ST506 disk", 16);
1048 	lp->d_type = DTYPE_ST506;
1049 #endif
1050 	strncpy(lp->d_packname, wd->sc_params.wdp_model, 16);
1051 	lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
1052 	lp->d_rpm = 3600;
1053 	lp->d_interleave = 1;
1054 	lp->d_flags = 0;
1055 
1056 	lp->d_partitions[RAW_PART].p_offset = 0;
1057 	lp->d_partitions[RAW_PART].p_size =
1058 	    lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
1059 	lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
1060 	lp->d_npartitions = RAW_PART + 1;
1061 
1062 	lp->d_magic = DISKMAGIC;
1063 	lp->d_magic2 = DISKMAGIC;
1064 	lp->d_checksum = dkcksum(lp);
1065 
1066 	wd->sc_badsect[0] = -1;
1067 
1068 	if (wd->sc_state > RECAL)
1069 		wd->sc_state = RECAL;
1070 	errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, RAW_PART),
1071 	    wdstrategy, lp, wd->sc_dk.dk_cpulabel);
1072 	if (errstring) {
1073 		/*
1074 		 * This probably happened because the drive's default
1075 		 * geometry doesn't match the DOS geometry.  We
1076 		 * assume the DOS geometry is now in the label and try
1077 		 * again.  XXX This is a kluge.
1078 		 */
1079 		if (wd->sc_state > GEOMETRY)
1080 			wd->sc_state = GEOMETRY;
1081 		errstring = readdisklabel(MAKEWDDEV(0, wd->sc_dev.dv_unit, RAW_PART),
1082 		    wdstrategy, lp, wd->sc_dk.dk_cpulabel);
1083 	}
1084 	if (errstring) {
1085 		printf("%s: %s\n", wd->sc_dev.dv_xname, errstring);
1086 		return;
1087 	}
1088 
1089 	if (wd->sc_state > GEOMETRY)
1090 		wd->sc_state = GEOMETRY;
1091 	if ((lp->d_flags & D_BADSECT) != 0)
1092 		bad144intern(wd);
1093 }
1094 
1095 /*
1096  * Implement operations needed before read/write.
1097  * Returns 0 if operation still in progress, 1 if completed.
1098  */
1099 int
1100 wdcontrol(wd)
1101 	struct wd_softc *wd;
1102 {
1103 	struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
1104 
1105 	switch (wd->sc_state) {
1106 	case RECAL:			/* Set SDH, step rate, do recal. */
1107 		if (wdcommandshort(wdc, wd->sc_drive, WDCC_RECAL) != 0) {
1108 			wderror(wd, NULL, "wdcontrol: recal failed (1)");
1109 			goto bad;
1110 		}
1111 		wd->sc_state = RECAL_WAIT;
1112 		break;
1113 
1114 	case RECAL_WAIT:
1115 		if (wdc->sc_status & WDCS_ERR) {
1116 			wderror(wd, NULL, "wdcontrol: recal failed (2)");
1117 			goto bad;
1118 		}
1119 		/* fall through */
1120 	case GEOMETRY:
1121 		if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0)
1122 			goto multimode;
1123 		if (wdsetctlr(wd) != 0) {
1124 			/* Already printed a message. */
1125 			goto bad;
1126 		}
1127 		wd->sc_state = GEOMETRY_WAIT;
1128 		break;
1129 
1130 	case GEOMETRY_WAIT:
1131 		if (wdc->sc_status & WDCS_ERR) {
1132 			wderror(wd, NULL, "wdcontrol: geometry failed");
1133 			goto bad;
1134 		}
1135 		/* fall through */
1136 	case MULTIMODE:
1137 	multimode:
1138 		if (wd->sc_mode != WDM_PIOMULTI)
1139 			goto ready;
1140 		outb(wdc->sc_iobase+wd_seccnt, wd->sc_multiple);
1141 		if (wdcommandshort(wdc, wd->sc_drive, WDCC_SETMULTI) != 0) {
1142 			wderror(wd, NULL, "wdcontrol: setmulti failed (1)");
1143 			goto bad;
1144 		}
1145 		wd->sc_state = MULTIMODE_WAIT;
1146 		break;
1147 
1148 	case MULTIMODE_WAIT:
1149 		if (wdc->sc_status & WDCS_ERR) {
1150 			wderror(wd, NULL, "wdcontrol: setmulti failed (2)");
1151 			goto bad;
1152 		}
1153 		/* fall through */
1154 	case READY:
1155 	ready:
1156 		wdc->sc_errors = 0;
1157 		wd->sc_state = READY;
1158 		/*
1159 		 * The rest of the initialization can be done by normal means.
1160 		 */
1161 		return 1;
1162 
1163 	bad:
1164 		wdcunwedge(wdc);
1165 		return 0;
1166 	}
1167 
1168 	wdc->sc_flags |= WDCF_ACTIVE;
1169 	timeout(wdctimeout, wdc, WAITTIME);
1170 	return 0;
1171 }
1172 
1173 /*
1174  * Wait for the drive to become ready and send a command.
1175  * Return -1 if busy for too long or 0 otherwise.
1176  * Assumes interrupts are blocked.
1177  */
1178 int
1179 wdcommand(wd, command, cylin, head, sector, count)
1180 	struct wd_softc *wd;
1181 	int command;
1182 	int cylin, head, sector, count;
1183 {
1184 	struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
1185 	int iobase = wdc->sc_iobase;
1186 	int stat;
1187 
1188 	/* Select drive, head, and addressing mode. */
1189 	outb(iobase+wd_sdh, WDSD_IBM | (wd->sc_drive << 4) | head);
1190 
1191 	/* Wait for it to become ready to accept a command. */
1192 	if (command == WDCC_IDP)
1193 		stat = wait_for_unbusy(wdc);
1194 	else
1195 		stat = wdcwait(wdc, WDCS_DRDY);
1196 	if (stat < 0)
1197 		return -1;
1198 
1199 	/* Load parameters. */
1200 	if (wd->sc_dk.dk_label->d_type == DTYPE_ST506)
1201 		outb(iobase+wd_precomp, wd->sc_dk.dk_label->d_precompcyl / 4);
1202 	else
1203 		outb(iobase+wd_features, 0);
1204 	outb(iobase+wd_cyl_lo, cylin);
1205 	outb(iobase+wd_cyl_hi, cylin >> 8);
1206 	outb(iobase+wd_sector, sector);
1207 	outb(iobase+wd_seccnt, count);
1208 
1209 	/* Send command. */
1210 	outb(iobase+wd_command, command);
1211 
1212 	return 0;
1213 }
1214 
1215 /*
1216  * Simplified version of wdcommand().
1217  */
1218 int
1219 wdcommandshort(wdc, drive, command)
1220 	struct wdc_softc *wdc;
1221 	int drive;
1222 	int command;
1223 {
1224 	int iobase = wdc->sc_iobase;
1225 
1226 	/* Select drive. */
1227 	outb(iobase+wd_sdh, WDSD_IBM | (drive << 4));
1228 
1229 	if (wdcwait(wdc, WDCS_DRDY) < 0)
1230 		return -1;
1231 
1232 	outb(iobase+wd_command, command);
1233 
1234 	return 0;
1235 }
1236 
1237 /*
1238  * Tell the drive what geometry to use.
1239  */
1240 int
1241 wdsetctlr(wd)
1242 	struct wd_softc *wd;
1243 {
1244 
1245 #ifdef WDDEBUG
1246 	printf("wd(%d,%d) C%dH%dS%d\n", wd->sc_dev.dv_unit, wd->sc_drive,
1247 	    wd->sc_dk.dk_label->d_ncylinders, wd->sc_dk.dk_label->d_ntracks,
1248 	    wd->sc_dk.dk_label->d_nsectors);
1249 #endif
1250 
1251 	if (wdcommand(wd, WDCC_IDP, wd->sc_dk.dk_label->d_ncylinders,
1252 	    wd->sc_dk.dk_label->d_ntracks - 1, 0,
1253 	    wd->sc_dk.dk_label->d_nsectors) != 0) {
1254 		wderror(wd, NULL, "wdsetctlr: geometry upload failed");
1255 		return -1;
1256 	}
1257 
1258 	return 0;
1259 }
1260 
1261 /*
1262  * Get the drive parameters, if ESDI or ATA, or create fake ones for ST506.
1263  */
1264 int
1265 wd_get_parms(wd)
1266 	struct wd_softc *wd;
1267 {
1268 	struct wdc_softc *wdc = (void *)wd->sc_dev.dv_parent;
1269 	int i;
1270 	char tb[DEV_BSIZE];
1271 	int s, error;
1272 
1273 	/*
1274 	 * XXX
1275 	 * The locking done here, and the length of time this may keep the rest
1276 	 * of the system suspended, is a kluge.  This should be rewritten to
1277 	 * set up a transfer and queue it through wdstart(), but it's called
1278 	 * infrequently enough that this isn't a pressing matter.
1279 	 */
1280 
1281 	s = splbio();
1282 
1283 	while ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
1284 		wdc->sc_flags |= WDCF_WANTED;
1285 		if ((error = tsleep(wdc, PRIBIO | PCATCH, "wdprm", 0)) != 0) {
1286 			splx(s);
1287 			return error;
1288 		}
1289 	}
1290 
1291 	if (wdcommandshort(wdc, wd->sc_drive, WDCC_IDENTIFY) != 0 ||
1292 	    wait_for_drq(wdc) != 0) {
1293 		/*
1294 		 * We `know' there's a drive here; just assume it's old.
1295 		 * This geometry is only used to read the MBR and print a
1296 		 * (false) attach message.
1297 		 */
1298 		strncpy(wd->sc_dk.dk_label->d_typename, "ST506",
1299 		    sizeof wd->sc_dk.dk_label->d_typename);
1300 		wd->sc_dk.dk_label->d_type = DTYPE_ST506;
1301 
1302 		strncpy(wd->sc_params.wdp_model, "unknown",
1303 		    sizeof wd->sc_params.wdp_model);
1304 		wd->sc_params.wdp_config = WD_CFG_FIXED;
1305 		wd->sc_params.wdp_cylinders = 1024;
1306 		wd->sc_params.wdp_heads = 8;
1307 		wd->sc_params.wdp_sectors = 17;
1308 		wd->sc_params.wdp_maxmulti = 0;
1309 		wd->sc_params.wdp_usedmovsd = 0;
1310 		wd->sc_params.wdp_capabilities = 0;
1311 	} else {
1312 		strncpy(wd->sc_dk.dk_label->d_typename, "ESDI/IDE",
1313 		    sizeof wd->sc_dk.dk_label->d_typename);
1314 		wd->sc_dk.dk_label->d_type = DTYPE_ESDI;
1315 
1316 		/* Read in parameter block. */
1317 		insw(wdc->sc_iobase+wd_data, tb, sizeof(tb) / sizeof(short));
1318 		bcopy(tb, &wd->sc_params, sizeof(struct wdparams));
1319 
1320 		/* Shuffle string byte order. */
1321 		for (i = 0; i < sizeof(wd->sc_params.wdp_model); i += 2) {
1322 			u_short *p;
1323 			p = (u_short *)(wd->sc_params.wdp_model + i);
1324 			*p = ntohs(*p);
1325 		}
1326 	}
1327 
1328 	/* Clear any leftover interrupt. */
1329 	(void) inb(wdc->sc_iobase+wd_status);
1330 
1331 	/* Restart the queue. */
1332 	wdcstart(wdc);
1333 
1334 	splx(s);
1335 	return 0;
1336 }
1337 
1338 int
1339 wdioctl(dev, cmd, addr, flag, p)
1340 	dev_t dev;
1341 	u_long cmd;
1342 	caddr_t addr;
1343 	int flag;
1344 	struct proc *p;
1345 {
1346 	struct wd_softc *wd = wd_cd.cd_devs[WDUNIT(dev)];
1347 	int error;
1348 
1349 	if ((wd->sc_flags & WDF_LOADED) == 0)
1350 		return EIO;
1351 
1352 	switch (cmd) {
1353 	case DIOCSBAD:
1354 		if ((flag & FWRITE) == 0)
1355 			return EBADF;
1356 		wd->sc_dk.dk_cpulabel->bad = *(struct dkbad *)addr;
1357 		wd->sc_dk.dk_label->d_flags |= D_BADSECT;
1358 		bad144intern(wd);
1359 		return 0;
1360 
1361 	case DIOCGDINFO:
1362 		*(struct disklabel *)addr = *(wd->sc_dk.dk_label);
1363 		return 0;
1364 
1365 	case DIOCGPART:
1366 		((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label;
1367 		((struct partinfo *)addr)->part =
1368 		    &wd->sc_dk.dk_label->d_partitions[WDPART(dev)];
1369 		return 0;
1370 
1371 	case DIOCWDINFO:
1372 	case DIOCSDINFO:
1373 		if ((flag & FWRITE) == 0)
1374 			return EBADF;
1375 
1376 		if ((error = wdlock(wd)) != 0)
1377 			return error;
1378 		wd->sc_flags |= WDF_LABELLING;
1379 
1380 		error = setdisklabel(wd->sc_dk.dk_label,
1381 		    (struct disklabel *)addr, /*wd->sc_dk.dk_openmask : */0,
1382 		    wd->sc_dk.dk_cpulabel);
1383 		if (error == 0) {
1384 			if (wd->sc_state > GEOMETRY)
1385 				wd->sc_state = GEOMETRY;
1386 			if (cmd == DIOCWDINFO)
1387 				error = writedisklabel(WDLABELDEV(dev),
1388 				    wdstrategy, wd->sc_dk.dk_label,
1389 				    wd->sc_dk.dk_cpulabel);
1390 		}
1391 
1392 		wd->sc_flags &= ~WDF_LABELLING;
1393 		wdunlock(wd);
1394 		return error;
1395 
1396 	case DIOCWLABEL:
1397 		if ((flag & FWRITE) == 0)
1398 			return EBADF;
1399 		if (*(int *)addr)
1400 			wd->sc_flags |= WDF_WLABEL;
1401 		else
1402 			wd->sc_flags &= ~WDF_WLABEL;
1403 		return 0;
1404 
1405 #ifdef notyet
1406 	case DIOCWFORMAT:
1407 		if ((flag & FWRITE) == 0)
1408 			return EBADF;
1409 	{
1410 		register struct format_op *fop;
1411 		struct iovec aiov;
1412 		struct uio auio;
1413 
1414 		fop = (struct format_op *)addr;
1415 		aiov.iov_base = fop->df_buf;
1416 		aiov.iov_len = fop->df_count;
1417 		auio.uio_iov = &aiov;
1418 		auio.uio_iovcnt = 1;
1419 		auio.uio_resid = fop->df_count;
1420 		auio.uio_segflg = 0;
1421 		auio.uio_offset =
1422 		    fop->df_startblk * wd->sc_dk.dk_label->d_secsize;
1423 		auio.uio_procp = p;
1424 		error = physio(wdformat, NULL, dev, B_WRITE, minphys,
1425 		    &auio);
1426 		fop->df_count -= auio.uio_resid;
1427 		fop->df_reg[0] = wdc->sc_status;
1428 		fop->df_reg[1] = wdc->sc_error;
1429 		return error;
1430 	}
1431 #endif
1432 
1433 	default:
1434 		return ENOTTY;
1435 	}
1436 
1437 #ifdef DIAGNOSTIC
1438 	panic("wdioctl: impossible");
1439 #endif
1440 }
1441 
1442 #ifdef B_FORMAT
1443 int
1444 wdformat(struct buf *bp)
1445 {
1446 
1447 	bp->b_flags |= B_FORMAT;
1448 	return wdstrategy(bp);
1449 }
1450 #endif
1451 
1452 int
1453 wdsize(dev)
1454 	dev_t dev;
1455 {
1456 	struct wd_softc *wd;
1457 	int part;
1458 	int size;
1459 
1460 	if (wdopen(dev, 0, S_IFBLK, NULL) != 0)
1461 		return -1;
1462 	wd = wd_cd.cd_devs[WDUNIT(dev)];
1463 	part = WDPART(dev);
1464 	if (wd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
1465 		size = -1;
1466 	else
1467 		size = wd->sc_dk.dk_label->d_partitions[part].p_size;
1468 	if (wdclose(dev, 0, S_IFBLK, NULL) != 0)
1469 		return -1;
1470 	return size;
1471 }
1472 
1473 
1474 #ifndef __BDEVSW_DUMP_OLD_TYPE
1475 /* #define WD_DUMP_NOT_TRUSTED if you just want to watch */
1476 static int wddoingadump;
1477 static int wddumprecalibrated;
1478 
1479 /*
1480  * Dump core after a system crash.
1481  */
1482 int
1483 wddump(dev, blkno, va, size)
1484         dev_t dev;
1485         daddr_t blkno;
1486         caddr_t va;
1487         size_t size;
1488 {
1489 	struct wd_softc *wd;	/* disk unit to do the I/O */
1490 	struct wdc_softc *wdc;	/* disk controller to do the I/O */
1491 	struct disklabel *lp;	/* disk's disklabel */
1492 	int	unit, part;
1493 	int	nblks;		/* total number of sectors left to write */
1494 
1495 	/* Check if recursive dump; if so, punt. */
1496 	if (wddoingadump)
1497 		return EFAULT;
1498 	wddoingadump = 1;
1499 
1500 	unit = WDUNIT(dev);
1501 	if (unit >= wd_cd.cd_ndevs)
1502 		return ENXIO;
1503 	wd = wd_cd.cd_devs[unit];
1504 	if (wd == 0)
1505 		return ENXIO;
1506 
1507 	part = WDPART(dev);
1508 
1509 	/* Make sure it was initialized. */
1510 	if (wd->sc_state < READY)
1511 		return ENXIO;
1512 
1513 	wdc = (void *)wd->sc_dev.dv_parent;
1514 
1515         /* Convert to disk sectors.  Request must be a multiple of size. */
1516 	lp = wd->sc_dk.dk_label;
1517 	if ((size % lp->d_secsize) != 0)
1518 		return EFAULT;
1519 	nblks = size / lp->d_secsize;
1520 	blkno = blkno / (lp->d_secsize / DEV_BSIZE);
1521 
1522 	/* Check transfer bounds against partition size. */
1523 	if ((blkno < 0) || ((blkno + nblks) > lp->d_partitions[part].p_size))
1524 		return EINVAL;
1525 
1526 	/* Offset block number to start of partition. */
1527 	blkno += lp->d_partitions[part].p_offset;
1528 
1529 	/* Recalibrate, if first dump transfer. */
1530 	if (wddumprecalibrated == 0) {
1531 		wddumprecalibrated = 1;
1532 		if (wdcommandshort(wdc, wd->sc_drive, WDCC_RECAL) != 0 ||
1533 		    wait_for_ready(wdc) != 0 || wdsetctlr(wd) != 0 ||
1534 		    wait_for_ready(wdc) != 0) {
1535 			wderror(wd, NULL, "wddump: recal failed");
1536 			return EIO;
1537 		}
1538 	}
1539 
1540 	while (nblks > 0) {
1541 		daddr_t xlt_blkno = blkno;
1542 		long cylin, head, sector;
1543 
1544 		if ((lp->d_flags & D_BADSECT) != 0) {
1545 			long blkdiff;
1546 			int i;
1547 
1548 			for (i = 0; (blkdiff = wd->sc_badsect[i]) != -1; i++) {
1549 				blkdiff -= xlt_blkno;
1550 				if (blkdiff < 0)
1551 					continue;
1552 				if (blkdiff == 0) {
1553 					/* Replace current block of transfer. */
1554 					xlt_blkno = lp->d_secperunit -
1555 					    lp->d_nsectors - i - 1;
1556 				}
1557 				break;
1558 			}
1559 			/* Tranfer is okay now. */
1560 		}
1561 
1562 		if ((wd->sc_params.wdp_capabilities & WD_CAP_LBA) != 0) {
1563 			sector = (xlt_blkno >> 0) & 0xff;
1564 			cylin = (xlt_blkno >> 8) & 0xffff;
1565 			head = (xlt_blkno >> 24) & 0xf;
1566 			head |= WDSD_LBA;
1567 		} else {
1568 			sector = xlt_blkno % lp->d_nsectors;
1569 			sector++;	/* Sectors begin with 1, not 0. */
1570 			xlt_blkno /= lp->d_nsectors;
1571 			head = xlt_blkno % lp->d_ntracks;
1572 			xlt_blkno /= lp->d_ntracks;
1573 			cylin = xlt_blkno;
1574 			head |= WDSD_CHS;
1575 		}
1576 
1577 #ifndef WD_DUMP_NOT_TRUSTED
1578 		if (wdcommand(wd, WDCC_WRITE, cylin, head, sector, 1) != 0 ||
1579 		    wait_for_drq(wdc) != 0) {
1580 			wderror(wd, NULL, "wddump: write failed");
1581 			return EIO;
1582 		}
1583 
1584 		outsw(wdc->sc_iobase+wd_data, va, lp->d_secsize >> 1);
1585 
1586 		/* Check data request (should be done). */
1587 		if (wait_for_ready(wdc) != 0) {
1588 			wderror(wd, NULL, "wddump: timeout waiting for ready");
1589 			return EIO;
1590 		}
1591 #else	/* WD_DUMP_NOT_TRUSTED */
1592 		/* Let's just talk about this first... */
1593 		printf("wd%d: dump addr 0x%x, cylin %d, head %d, sector %d\n",
1594 		    unit, va, cylin, head, sector);
1595 		delay(500 * 1000);	/* half a second */
1596 #endif
1597 
1598 		/* update block count */
1599 		nblks -= 1;
1600 		blkno += 1;
1601 		va += lp->d_secsize;
1602 	}
1603 
1604 	wddoingadump = 0;
1605 	return 0;
1606 }
1607 #else /* __BDEVSW_DUMP_NEW_TYPE */
1608 int
1609 wddump(dev, blkno, va, size)
1610         dev_t dev;
1611         daddr_t blkno;
1612         caddr_t va;
1613         size_t size;
1614 {
1615 
1616 	/* Not implemented. */
1617 	return ENXIO;
1618 }
1619 #endif /* __BDEVSW_DUMP_NEW_TYPE */
1620 
1621 /*
1622  * Internalize the bad sector table.
1623  */
1624 void
1625 bad144intern(wd)
1626 	struct wd_softc *wd;
1627 {
1628 	struct dkbad *bt = &wd->sc_dk.dk_cpulabel->bad;
1629 	struct disklabel *lp = wd->sc_dk.dk_label;
1630 	int i = 0;
1631 
1632 	for (; i < 126; i++) {
1633 		if (bt->bt_bad[i].bt_cyl == 0xffff)
1634 			break;
1635 		wd->sc_badsect[i] =
1636 		    bt->bt_bad[i].bt_cyl * lp->d_secpercyl +
1637 		    (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors +
1638 		    (bt->bt_bad[i].bt_trksec & 0xff);
1639 	}
1640 	for (; i < 127; i++)
1641 		wd->sc_badsect[i] = -1;
1642 }
1643 
1644 int
1645 wdcreset(wdc)
1646 	struct wdc_softc *wdc;
1647 {
1648 	int iobase = wdc->sc_iobase;
1649 
1650 	/* Reset the device. */
1651 	outb(iobase+wd_ctlr, WDCTL_RST | WDCTL_IDS);
1652 	delay(1000);
1653 	outb(iobase+wd_ctlr, WDCTL_IDS);
1654 	delay(1000);
1655 	(void) inb(iobase+wd_error);
1656 	outb(iobase+wd_ctlr, WDCTL_4BIT);
1657 
1658 	if (wait_for_unbusy(wdc) < 0) {
1659 		printf("%s: reset failed\n", wdc->sc_dev.dv_xname);
1660 		return 1;
1661 	}
1662 
1663 	return 0;
1664 }
1665 
1666 void
1667 wdcrestart(arg)
1668 	void *arg;
1669 {
1670 	struct wdc_softc *wdc = arg;
1671 	int s;
1672 
1673 	s = splbio();
1674 	wdcstart(wdc);
1675 	splx(s);
1676 }
1677 
1678 /*
1679  * Unwedge the controller after an unexpected error.  We do this by resetting
1680  * it, marking all drives for recalibration, and stalling the queue for a short
1681  * period to give the reset time to finish.
1682  * NOTE: We use a timeout here, so this routine must not be called during
1683  * autoconfig or dump.
1684  */
1685 void
1686 wdcunwedge(wdc)
1687 	struct wdc_softc *wdc;
1688 {
1689 	int unit;
1690 
1691 	untimeout(wdctimeout, wdc);
1692 	(void) wdcreset(wdc);
1693 
1694 	/* Schedule recalibrate for all drives on this controller. */
1695 	for (unit = 0; unit < wd_cd.cd_ndevs; unit++) {
1696 		struct wd_softc *wd = wd_cd.cd_devs[unit];
1697 		if (!wd || (void *)wd->sc_dev.dv_parent != wdc)
1698 			continue;
1699 		if (wd->sc_state > RECAL)
1700 			wd->sc_state = RECAL;
1701 	}
1702 
1703 	wdc->sc_flags |= WDCF_ERROR;
1704 	++wdc->sc_errors;
1705 
1706 	/* Wake up in a little bit and restart the operation. */
1707 	timeout(wdcrestart, wdc, RECOVERYTIME);
1708 }
1709 
1710 int
1711 wdcwait(wdc, mask)
1712 	struct wdc_softc *wdc;
1713 	int mask;
1714 {
1715 	int iobase = wdc->sc_iobase;
1716 	int timeout = 0;
1717 	u_char status;
1718 #ifdef WDCNDELAY_DEBUG
1719 	extern int cold;
1720 #endif
1721 
1722 	for (;;) {
1723 		wdc->sc_status = status = inb(iobase+wd_status);
1724 		if ((status & WDCS_BSY) == 0 && (status & mask) == mask)
1725 			break;
1726 		if (++timeout > WDCNDELAY)
1727 			return -1;
1728 		delay(WDCDELAY);
1729 	}
1730 	if (status & WDCS_ERR) {
1731 		wdc->sc_error = inb(iobase+wd_error);
1732 		return WDCS_ERR;
1733 	}
1734 #ifdef WDCNDELAY_DEBUG
1735 	/* After autoconfig, there should be no long delays. */
1736 	if (!cold && timeout > WDCNDELAY_DEBUG)
1737 		printf("%s: warning: busy-wait took %dus\n",
1738 		    wdc->sc_dev.dv_xname, WDCDELAY * timeout);
1739 #endif
1740 	return 0;
1741 }
1742 
1743 void
1744 wdctimeout(arg)
1745 	void *arg;
1746 {
1747 	struct wdc_softc *wdc = (struct wdc_softc *)arg;
1748 	int s;
1749 
1750 	s = splbio();
1751 	if ((wdc->sc_flags & WDCF_ACTIVE) != 0) {
1752 		struct wd_softc *wd = wdc->sc_drives.tqh_first;
1753 		struct buf *bp = wd->sc_q.b_actf;
1754 
1755 		wdc->sc_flags &= ~WDCF_ACTIVE;
1756 		wderror(wdc, NULL, "lost interrupt");
1757 		printf("%s: lost interrupt: %sing %d@%s:%d\n",
1758 		    wdc->sc_dev.dv_xname,
1759 		    (bp->b_flags & B_READ) ? "read" : "writ",
1760 		    wd->sc_nblks, wd->sc_dev.dv_xname, wd->sc_blkno);
1761 		wdcunwedge(wdc);
1762 	} else
1763 		wderror(wdc, NULL, "missing untimeout");
1764 	splx(s);
1765 }
1766 
1767 void
1768 wderror(dev, bp, msg)
1769 	void *dev;
1770 	struct buf *bp;
1771 	char *msg;
1772 {
1773 	struct wd_softc *wd = dev;
1774 	struct wdc_softc *wdc = dev;
1775 
1776 	if (bp) {
1777 		diskerr(bp, "wd", msg, LOG_PRINTF, wd->sc_skip / DEV_BSIZE,
1778 		    wd->sc_dk.dk_label);
1779 		printf("\n");
1780 	} else
1781 		printf("%s: %s: status %b error %b\n", wdc->sc_dev.dv_xname,
1782 		    msg, wdc->sc_status, WDCS_BITS, wdc->sc_error, WDERR_BITS);
1783 }
1784