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