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