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