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