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