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