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