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