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