1 /* $OpenBSD: octcf.c,v 1.7 2011/07/06 04:49:35 matthew Exp $ */ 2 /* $NetBSD: wd.c,v 1.193 1999/02/28 17:15:27 explorer Exp $ */ 3 4 /* 5 * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /*- 29 * Copyright (c) 1998 The NetBSD Foundation, Inc. 30 * All rights reserved. 31 * 32 * This code is derived from software contributed to The NetBSD Foundation 33 * by Charles M. Hannum and by Onno van der Linden. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 44 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 45 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 46 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 47 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 48 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 49 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 50 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 51 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 52 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 53 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 54 * POSSIBILITY OF SUCH DAMAGE. 55 */ 56 57 #include <sys/param.h> 58 #include <sys/systm.h> 59 #include <sys/kernel.h> 60 #include <sys/conf.h> 61 #include <sys/file.h> 62 #include <sys/stat.h> 63 #include <sys/ioctl.h> 64 #include <sys/mutex.h> 65 #include <sys/buf.h> 66 #include <sys/uio.h> 67 #include <sys/malloc.h> 68 #include <sys/device.h> 69 #include <sys/disklabel.h> 70 #include <sys/disk.h> 71 #include <sys/syslog.h> 72 #include <sys/proc.h> 73 #include <sys/vnode.h> 74 #include <sys/dkio.h> 75 76 #include <uvm/uvm_extern.h> 77 78 #include <machine/intr.h> 79 #include <machine/bus.h> 80 81 #include <dev/ata/atareg.h> 82 #include <dev/ata/atavar.h> 83 #include <dev/ic/wdcreg.h> 84 #include <dev/ic/wdcvar.h> 85 86 #include <octeon/dev/iobusvar.h> 87 #include <octeon/dev/octeonreg.h> 88 89 #define OCTCF_REG_SIZE 8 90 #define ATAPARAMS_SIZE 512 91 #define SECTOR_SIZE 512 92 #define OCTCFDELAY 100 /* 100 microseconds */ 93 #define NR_TRIES 1000 94 95 #define DEBUG_XFERS 0x02 96 #define DEBUG_FUNCS 0x08 97 #define DEBUG_PROBE 0x10 98 99 #ifdef OCTCFDEBUG 100 int octcfdebug_mask = 0xff; 101 #define OCTCFDEBUG_PRINT(args, level) do { \ 102 if ((octcfdebug_mask & (level)) != 0) \ 103 printf args; \ 104 } while (0) 105 #else 106 #define OCTCFDEBUG_PRINT(args, level) 107 #endif 108 109 struct octcf_softc { 110 /* General disk infos */ 111 struct device sc_dev; 112 struct disk sc_dk; 113 struct buf sc_q; 114 struct buf *sc_bp; 115 struct ataparams sc_params;/* drive characteristics found */ 116 int sc_flags; 117 #define OCTCFF_LOADED 0x10 /* parameters loaded */ 118 u_int64_t sc_capacity; 119 bus_space_tag_t sc_iot; 120 bus_space_handle_t sc_ioh; 121 }; 122 123 int octcfprobe(struct device *, void *, void *); 124 void octcfattach(struct device *, struct device *, void *); 125 int octcfdetach(struct device *, int); 126 int octcfactivate(struct device *, int); 127 int octcfprint(void *, char *); 128 129 struct cfattach octcf_ca = { 130 sizeof(struct octcf_softc), octcfprobe, octcfattach, 131 octcfdetach, octcfactivate 132 }; 133 134 struct cfdriver octcf_cd = { 135 NULL, "octcf", DV_DISK 136 }; 137 138 void octcfgetdefaultlabel(struct octcf_softc *, struct disklabel *); 139 int octcfgetdisklabel(dev_t dev, struct octcf_softc *, struct disklabel *, int); 140 void octcfstrategy(struct buf *); 141 void octcfstart(void *); 142 void _octcfstart(struct octcf_softc*, struct buf *); 143 void octcfdone(void *); 144 145 cdev_decl(octcf); 146 bdev_decl(octcf); 147 148 #define octcflookup(unit) (struct octcf_softc *)disk_lookup(&octcf_cd, (unit)) 149 150 int octcf_write_sectors(struct octcf_softc *, uint32_t, uint32_t, void *); 151 int octcf_read_sectors(struct octcf_softc *, uint32_t, uint32_t, void *); 152 int octcf_wait_busy(struct octcf_softc *); 153 void octcf_command(struct octcf_softc *, uint32_t, uint8_t); 154 int octcf_get_params(struct octcf_softc *, struct ataparams *); 155 156 #define OCTCF_REG_READ(wd, reg) \ 157 bus_space_read_2(wd->sc_iot, wd->sc_ioh, reg & 0x6) 158 #define OCTCF_REG_WRITE(wd, reg, val) \ 159 bus_space_write_2(wd->sc_iot, wd->sc_ioh, reg & 0x6, val) 160 161 int 162 octcfprobe(struct device *parent, void *match_, void *aux) 163 { 164 return 1; 165 } 166 167 void 168 octcfattach(struct device *parent, struct device *self, void *aux) 169 { 170 struct octcf_softc *wd = (void *)self; 171 struct iobus_attach_args *aa = aux; 172 int i, blank; 173 char buf[41], c, *p, *q; 174 OCTCFDEBUG_PRINT(("octcfattach\n"), DEBUG_FUNCS | DEBUG_PROBE); 175 uint8_t status; 176 177 wd->sc_iot = aa->aa_bust; 178 179 if (bus_space_map(wd->sc_iot, aa->aa_unit->addr, 180 OCTCF_REG_SIZE, BUS_SPACE_MAP_KSEG0, &wd->sc_ioh)) { 181 printf(": couldn't map registers\n"); 182 return; 183 } 184 185 for (i = 0; i < 8; i++) { 186 uint64_t cfg = 187 *(uint64_t *)PHYS_TO_XKPHYS( 188 OCTEON_MIO_BOOT_BASE + MIO_BOOT_REG_CFG(i), CCA_NC); 189 190 if ((cfg & BOOT_CFG_BASE_MASK) == 191 (OCTEON_CF_BASE >> BOOT_CFG_BASE_SHIFT)) { 192 if ((cfg & BOOT_CFG_WIDTH_MASK) == 0) 193 printf(": Doesn't support 8bit card\n", 194 wd->sc_dev.dv_xname); 195 break; 196 } 197 } 198 199 /* Check if CF is inserted */ 200 i = 0; 201 while ( (status = (OCTCF_REG_READ(wd, wdr_status)>>8)) & WDCS_BSY) { 202 if ((i++) == NR_TRIES ) { 203 printf(": card not present\n", wd->sc_dev.dv_xname); 204 return; 205 } 206 DELAY(OCTCFDELAY); 207 } 208 209 /* read our drive info */ 210 if (octcf_get_params(wd, &wd->sc_params) != 0) { 211 printf(": IDENTIFY failed\n", wd->sc_dev.dv_xname); 212 return; 213 } 214 215 for (blank = 0, p = wd->sc_params.atap_model, q = buf, i = 0; 216 i < sizeof(wd->sc_params.atap_model); i++) { 217 c = *p++; 218 if (c == '\0') 219 break; 220 if (c != ' ') { 221 if (blank) { 222 *q++ = ' '; 223 blank = 0; 224 } 225 *q++ = c; 226 } else 227 blank = 1; 228 } 229 *q++ = '\0'; 230 231 printf(": <%s>\n", buf); 232 printf("%s: %d-sector PIO,", 233 wd->sc_dev.dv_xname, wd->sc_params.atap_multi & 0xff); 234 235 wd->sc_capacity = 236 wd->sc_params.atap_cylinders * 237 wd->sc_params.atap_heads * 238 wd->sc_params.atap_sectors; 239 printf(" CHS, %lluMB, %d cyl, %d head, %d sec, %llu sectors\n", 240 wd->sc_capacity / (1048576 / DEV_BSIZE), 241 wd->sc_params.atap_cylinders, 242 wd->sc_params.atap_heads, 243 wd->sc_params.atap_sectors, 244 wd->sc_capacity); 245 246 OCTCFDEBUG_PRINT( 247 ("%s: atap_dmatiming_mimi=%d, atap_dmatiming_recom=%d\n", 248 self->dv_xname, wd->sc_params.atap_dmatiming_mimi, 249 wd->sc_params.atap_dmatiming_recom), DEBUG_PROBE); 250 251 /* 252 * Initialize disk structures. 253 */ 254 wd->sc_dk.dk_name = wd->sc_dev.dv_xname; 255 256 /* Attach disk. */ 257 disk_attach(&wd->sc_dev, &wd->sc_dk); 258 } 259 260 int 261 octcfactivate(struct device *self, int act) 262 { 263 return 0; 264 } 265 266 int 267 octcfdetach(struct device *self, int flags) 268 { 269 struct octcf_softc *sc = (struct octcf_softc *)self; 270 int bmaj, cmaj, mn; 271 272 /* Locate the lowest minor number to be detached. */ 273 mn = DISKMINOR(self->dv_unit, 0); 274 275 for (bmaj = 0; bmaj < nblkdev; bmaj++) 276 if (bdevsw[bmaj].d_open == octcfopen) 277 vdevgone(bmaj, mn, mn + MAXPARTITIONS - 1, VBLK); 278 for (cmaj = 0; cmaj < nchrdev; cmaj++) 279 if (cdevsw[cmaj].d_open == octcfopen) 280 vdevgone(cmaj, mn, mn + MAXPARTITIONS - 1, VCHR); 281 282 /* Detach disk. */ 283 disk_detach(&sc->sc_dk); 284 285 return (0); 286 } 287 288 /* 289 * Read/write routine for a buffer. Validates the arguments and schedules the 290 * transfer. Does not wait for the transfer to complete. 291 */ 292 void 293 octcfstrategy(struct buf *bp) 294 { 295 struct octcf_softc *wd; 296 int s; 297 298 wd = octcflookup(DISKUNIT(bp->b_dev)); 299 if (wd == NULL) { 300 bp->b_error = ENXIO; 301 goto bad; 302 } 303 OCTCFDEBUG_PRINT(("octcfstrategy (%s)\n", wd->sc_dev.dv_xname), 304 DEBUG_XFERS); 305 /* If device invalidated (e.g. media change, door open), error. */ 306 if ((wd->sc_flags & OCTCFF_LOADED) == 0) { 307 bp->b_error = EIO; 308 goto bad; 309 } 310 311 /* Validate the request. */ 312 if (bounds_check_with_label(bp, wd->sc_dk.dk_label) == -1) 313 goto done; 314 315 /* Check that the number of sectors can fit in a byte. */ 316 if ((bp->b_bcount / wd->sc_dk.dk_label->d_secsize) >= (1 << NBBY)) { 317 bp->b_error = EINVAL; 318 goto bad; 319 } 320 321 /* Queue transfer on drive, activate drive and controller if idle. */ 322 s = splbio(); 323 disksort(&wd->sc_q, bp); 324 octcfstart(wd); 325 splx(s); 326 device_unref(&wd->sc_dev); 327 return; 328 329 bad: 330 bp->b_flags |= B_ERROR; 331 bp->b_resid = bp->b_bcount; 332 done: 333 s = splbio(); 334 biodone(bp); 335 splx(s); 336 if (wd != NULL) 337 device_unref(&wd->sc_dev); 338 } 339 340 /* 341 * Queue a drive for I/O. 342 */ 343 void 344 octcfstart(void *arg) 345 { 346 struct octcf_softc *wd = arg; 347 struct buf *dp, *bp; 348 349 OCTCFDEBUG_PRINT(("octcfstart %s\n", wd->sc_dev.dv_xname), 350 DEBUG_XFERS); 351 while (1) { 352 /* Remove the next buffer from the queue or stop. */ 353 dp = &wd->sc_q; 354 bp = dp->b_actf; 355 if (bp == NULL) 356 return; 357 dp->b_actf = bp->b_actf; 358 359 /* Transfer this buffer now. */ 360 _octcfstart(wd, bp); 361 } 362 } 363 364 void 365 _octcfstart(struct octcf_softc *wd, struct buf *bp) 366 { 367 uint32_t blkno; 368 uint32_t nblks; 369 370 blkno = bp->b_blkno + 371 DL_GETPOFFSET(&wd->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)]); 372 blkno /= (SECTOR_SIZE / DEV_BSIZE); 373 nblks = bp->b_bcount / SECTOR_SIZE; 374 375 wd->sc_bp = bp; 376 377 /* Instrumentation. */ 378 disk_busy(&wd->sc_dk); 379 380 if (bp->b_flags & B_READ) 381 bp->b_error = octcf_read_sectors(wd, nblks, blkno, bp->b_data); 382 else 383 bp->b_error = octcf_write_sectors(wd, nblks, blkno, bp->b_data); 384 385 octcfdone(wd); 386 } 387 388 void 389 octcfdone(void *arg) 390 { 391 struct octcf_softc *wd = arg; 392 struct buf *bp = wd->sc_bp; 393 394 if (bp->b_error == 0) 395 bp->b_resid = 0; 396 else 397 bp->b_flags |= B_ERROR; 398 399 disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid), 400 (bp->b_flags & B_READ)); 401 biodone(bp); 402 } 403 404 int 405 octcfread(dev_t dev, struct uio *uio, int flags) 406 { 407 408 OCTCFDEBUG_PRINT(("wdread\n"), DEBUG_XFERS); 409 return (physio(octcfstrategy, dev, B_READ, minphys, uio)); 410 } 411 412 int 413 octcfwrite(dev_t dev, struct uio *uio, int flags) 414 { 415 416 OCTCFDEBUG_PRINT(("octcfwrite\n"), DEBUG_XFERS); 417 return (physio(octcfstrategy, dev, B_WRITE, minphys, uio)); 418 } 419 420 int 421 octcfopen(dev_t dev, int flag, int fmt, struct proc *p) 422 { 423 struct octcf_softc *wd; 424 int unit, part; 425 int error; 426 427 OCTCFDEBUG_PRINT(("octcfopen\n"), DEBUG_FUNCS); 428 429 unit = DISKUNIT(dev); 430 wd = octcflookup(unit); 431 if (wd == NULL) 432 return ENXIO; 433 434 /* 435 * If this is the first open of this device, add a reference 436 * to the adapter. 437 */ 438 if ((error = disk_lock(&wd->sc_dk)) != 0) 439 goto bad4; 440 441 if (wd->sc_dk.dk_openmask != 0) { 442 /* 443 * If any partition is open, but the disk has been invalidated, 444 * disallow further opens. 445 */ 446 if ((wd->sc_flags & OCTCFF_LOADED) == 0) { 447 error = EIO; 448 goto bad3; 449 } 450 } else { 451 if ((wd->sc_flags & OCTCFF_LOADED) == 0) { 452 wd->sc_flags |= OCTCFF_LOADED; 453 454 /* Load the physical device parameters. */ 455 octcf_get_params(wd, &wd->sc_params); 456 457 /* Load the partition info if not already loaded. */ 458 if (octcfgetdisklabel(dev, wd, 459 wd->sc_dk.dk_label, 0) == EIO) { 460 error = EIO; 461 goto bad; 462 } 463 } 464 } 465 466 part = DISKPART(dev); 467 468 /* Check that the partition exists. */ 469 if (part != RAW_PART && 470 (part >= wd->sc_dk.dk_label->d_npartitions || 471 wd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) { 472 error = ENXIO; 473 goto bad; 474 } 475 476 /* Insure only one open at a time. */ 477 switch (fmt) { 478 case S_IFCHR: 479 wd->sc_dk.dk_copenmask |= (1 << part); 480 break; 481 case S_IFBLK: 482 wd->sc_dk.dk_bopenmask |= (1 << part); 483 break; 484 } 485 wd->sc_dk.dk_openmask = 486 wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask; 487 488 disk_unlock(&wd->sc_dk); 489 device_unref(&wd->sc_dev); 490 return 0; 491 492 bad: 493 if (wd->sc_dk.dk_openmask == 0) { 494 } 495 496 bad3: 497 disk_unlock(&wd->sc_dk); 498 bad4: 499 device_unref(&wd->sc_dev); 500 return error; 501 } 502 503 int 504 octcfclose(dev_t dev, int flag, int fmt, struct proc *p) 505 { 506 struct octcf_softc *wd; 507 int part = DISKPART(dev); 508 509 wd = octcflookup(DISKUNIT(dev)); 510 if (wd == NULL) 511 return ENXIO; 512 513 OCTCFDEBUG_PRINT(("octcfclose\n"), DEBUG_FUNCS); 514 515 disk_lock_nointr(&wd->sc_dk); 516 517 switch (fmt) { 518 case S_IFCHR: 519 wd->sc_dk.dk_copenmask &= ~(1 << part); 520 break; 521 case S_IFBLK: 522 wd->sc_dk.dk_bopenmask &= ~(1 << part); 523 break; 524 } 525 wd->sc_dk.dk_openmask = 526 wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask; 527 528 disk_unlock(&wd->sc_dk); 529 530 device_unref(&wd->sc_dev); 531 return (0); 532 } 533 534 void 535 octcfgetdefaultlabel(struct octcf_softc *wd, struct disklabel *lp) 536 { 537 OCTCFDEBUG_PRINT(("octcfgetdefaultlabel\n"), DEBUG_FUNCS); 538 bzero(lp, sizeof(struct disklabel)); 539 540 lp->d_secsize = DEV_BSIZE; 541 DL_SETDSIZE(lp, wd->sc_capacity); 542 lp->d_ntracks = wd->sc_params.atap_heads; 543 lp->d_nsectors = wd->sc_params.atap_sectors; 544 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; 545 lp->d_ncylinders = DL_GETDSIZE(lp) / lp->d_secpercyl; 546 lp->d_type = DTYPE_ESDI; 547 strncpy(lp->d_typename, "ESDI/IDE disk", sizeof lp->d_typename); 548 549 /* XXX - user viscopy() like sd.c */ 550 strncpy(lp->d_packname, wd->sc_params.atap_model, sizeof lp->d_packname); 551 lp->d_flags = 0; 552 lp->d_version = 1; 553 554 lp->d_magic = DISKMAGIC; 555 lp->d_magic2 = DISKMAGIC; 556 lp->d_checksum = dkcksum(lp); 557 } 558 559 /* 560 * Fabricate a default disk label, and try to read the correct one. 561 */ 562 int 563 octcfgetdisklabel(dev_t dev, struct octcf_softc *wd, struct disklabel *lp, 564 int spoofonly) 565 { 566 int error; 567 568 OCTCFDEBUG_PRINT(("octcfgetdisklabel\n"), DEBUG_FUNCS); 569 570 octcfgetdefaultlabel(wd, lp); 571 error = readdisklabel(DISKLABELDEV(dev), octcfstrategy, lp, 572 spoofonly); 573 return (error); 574 } 575 576 int 577 octcfioctl(dev_t dev, u_long xfer, caddr_t addr, int flag, struct proc *p) 578 { 579 struct octcf_softc *wd; 580 struct disklabel *lp; 581 int error = 0; 582 583 OCTCFDEBUG_PRINT(("octcfioctl\n"), DEBUG_FUNCS); 584 585 wd = octcflookup(DISKUNIT(dev)); 586 if (wd == NULL) 587 return ENXIO; 588 589 if ((wd->sc_flags & OCTCFF_LOADED) == 0) { 590 error = EIO; 591 goto exit; 592 } 593 594 switch (xfer) { 595 case DIOCRLDINFO: 596 lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK); 597 octcfgetdisklabel(dev, wd, lp, 0); 598 bcopy(lp, wd->sc_dk.dk_label, sizeof(*lp)); 599 free(lp, M_TEMP); 600 goto exit; 601 602 case DIOCGPDINFO: 603 octcfgetdisklabel(dev, wd, (struct disklabel *)addr, 1); 604 goto exit; 605 606 case DIOCGDINFO: 607 *(struct disklabel *)addr = *(wd->sc_dk.dk_label); 608 goto exit; 609 610 case DIOCGPART: 611 ((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label; 612 ((struct partinfo *)addr)->part = 613 &wd->sc_dk.dk_label->d_partitions[DISKPART(dev)]; 614 goto exit; 615 616 case DIOCWDINFO: 617 case DIOCSDINFO: 618 if ((flag & FWRITE) == 0) { 619 error = EBADF; 620 goto exit; 621 } 622 623 if ((error = disk_lock(&wd->sc_dk)) != 0) 624 goto exit; 625 626 error = setdisklabel(wd->sc_dk.dk_label, 627 (struct disklabel *)addr, /*wd->sc_dk.dk_openmask : */0); 628 if (error == 0) { 629 if (xfer == DIOCWDINFO) 630 error = writedisklabel(DISKLABELDEV(dev), 631 octcfstrategy, wd->sc_dk.dk_label); 632 } 633 634 disk_unlock(&wd->sc_dk); 635 goto exit; 636 637 #ifdef notyet 638 case DIOCWFORMAT: 639 if ((flag & FWRITE) == 0) 640 return EBADF; 641 { 642 struct format_op *fop; 643 struct iovec aiov; 644 struct uio auio; 645 646 fop = (struct format_op *)addr; 647 aiov.iov_base = fop->df_buf; 648 aiov.iov_len = fop->df_count; 649 auio.uio_iov = &aiov; 650 auio.uio_iovcnt = 1; 651 auio.uio_resid = fop->df_count; 652 auio.uio_segflg = 0; 653 auio.uio_offset = 654 fop->df_startblk * wd->sc_dk.dk_label->d_secsize; 655 auio.uio_procp = p; 656 error = physio(wdformat, dev, B_WRITE, minphys, &auio); 657 fop->df_count -= auio.uio_resid; 658 fop->df_reg[0] = wdc->sc_status; 659 fop->df_reg[1] = wdc->sc_error; 660 goto exit; 661 } 662 #endif 663 664 default: 665 error = ENOTTY; 666 goto exit; 667 } 668 669 #ifdef DIAGNOSTIC 670 panic("octcfioctl: impossible"); 671 #endif 672 673 exit: 674 device_unref(&wd->sc_dev); 675 return (error); 676 } 677 678 #ifdef B_FORMAT 679 int 680 wdformat(struct buf *bp) 681 { 682 683 bp->b_flags |= B_FORMAT; 684 return octcfstrategy(bp); 685 } 686 #endif 687 688 daddr64_t 689 octcfsize(dev_t dev) 690 { 691 struct octcf_softc *wd; 692 int part, omask; 693 int64_t size; 694 695 OCTCFDEBUG_PRINT(("wdsize\n"), DEBUG_FUNCS); 696 697 wd = octcflookup(DISKUNIT(dev)); 698 if (wd == NULL) 699 return (-1); 700 701 part = DISKPART(dev); 702 omask = wd->sc_dk.dk_openmask & (1 << part); 703 704 if (omask == 0 && octcfopen(dev, 0, S_IFBLK, NULL) != 0) { 705 size = -1; 706 goto exit; 707 } 708 709 size = DL_GETPSIZE(&wd->sc_dk.dk_label->d_partitions[part]) * 710 (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE); 711 if (omask == 0 && octcfclose(dev, 0, S_IFBLK, NULL) != 0) 712 size = -1; 713 714 exit: 715 device_unref(&wd->sc_dev); 716 return (size); 717 } 718 719 /* 720 * Dump core after a system crash. 721 */ 722 int 723 octcfdump(dev_t dev, daddr64_t blkno, caddr_t va, size_t size) 724 { 725 return ENXIO; 726 } 727 728 int 729 octcf_read_sectors(struct octcf_softc *wd, uint32_t nr_sectors, 730 uint32_t start_sector, void *buf) 731 { 732 uint32_t count; 733 uint16_t *ptr = (uint16_t*)buf; 734 int error; 735 uint8_t status; 736 737 while (nr_sectors--) { 738 while ((status = (OCTCF_REG_READ(wd, wdr_status)>>8)) & WDCS_BSY) 739 DELAY(OCTCFDELAY); 740 octcf_command(wd, start_sector++, WDCC_READ); 741 error = octcf_wait_busy(wd); 742 if (error != 0) 743 return (error); 744 745 volatile uint16_t dummy; 746 for (count = 0; count < SECTOR_SIZE; count+=2) { 747 uint16_t temp; 748 temp = OCTCF_REG_READ(wd, 0x0); 749 *ptr++ = swap16(temp); 750 if ((count & 0xf) == 0) 751 dummy = OCTCF_REG_READ(wd, wdr_status); 752 } 753 } 754 return (0); 755 } 756 757 int 758 octcf_write_sectors(struct octcf_softc *wd, uint32_t nr_sectors, 759 uint32_t start_sector, void *buf) 760 { 761 uint32_t count; 762 uint16_t *ptr = (uint16_t*)buf; 763 int error; 764 uint8_t status; 765 766 while (nr_sectors--) { 767 while ((status = (OCTCF_REG_READ(wd, wdr_status)>>8)) & WDCS_BSY) 768 DELAY(OCTCFDELAY); 769 octcf_command(wd, start_sector++, WDCC_WRITE); 770 if((error = octcf_wait_busy(wd))) 771 return (error); 772 773 volatile uint16_t dummy; 774 for (count = 0; count < SECTOR_SIZE; count+=2) { 775 uint16_t temp = *ptr++; 776 OCTCF_REG_WRITE(wd, 0x0, swap16(temp)); 777 if ((count & 0xf) == 0) 778 dummy = OCTCF_REG_READ(wd, wdr_status); 779 } 780 } 781 return (0); 782 } 783 784 void 785 octcf_command(struct octcf_softc *wd, uint32_t lba, uint8_t cmd) 786 { 787 OCTCF_REG_WRITE(wd, wdr_seccnt, 1 | ((lba & 0xff) << 8)); 788 OCTCF_REG_WRITE(wd, wdr_cyl_lo, 789 ((lba >> 8) & 0xff) | (((lba >> 16) & 0xff) << 8)); 790 OCTCF_REG_WRITE(wd, wdr_sdh, 791 (((lba >> 24) & 0xff) | 0xe0) | (cmd << 8)); 792 } 793 794 int 795 octcf_wait_busy(struct octcf_softc *wd) 796 { 797 uint8_t status; 798 799 status = OCTCF_REG_READ(wd, wdr_status)>>8; 800 while ((status & WDCS_BSY) == WDCS_BSY) { 801 if ((status & WDCS_DWF) != 0) 802 return (EIO); 803 DELAY(OCTCFDELAY); 804 status = (uint8_t)(OCTCF_REG_READ(wd, wdr_status)>>8); 805 } 806 807 if ((status & WDCS_DRQ) == 0) 808 return (ENXIO); 809 810 return (0); 811 } 812 813 /* Get the disk's parameters */ 814 int 815 octcf_get_params(struct octcf_softc *wd, struct ataparams *prms) 816 { 817 char *tb; 818 int i; 819 u_int16_t *p; 820 int count; 821 uint8_t status; 822 int error; 823 824 OCTCFDEBUG_PRINT(("octcf_get_parms\n"), DEBUG_FUNCS); 825 826 tb = malloc(ATAPARAMS_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO); 827 if (tb == NULL) 828 return CMD_AGAIN; 829 830 while ((status = (OCTCF_REG_READ(wd, wdr_status)>>8)) & WDCS_BSY) 831 DELAY(OCTCFDELAY); 832 833 OCTCF_REG_WRITE(wd, wdr_seccnt, 0); 834 OCTCF_REG_WRITE(wd, wdr_cyl_lo, 0); 835 OCTCF_REG_WRITE(wd, wdr_sdh, 0 | (WDCC_IDENTIFY<<8)); 836 837 error = octcf_wait_busy(wd); 838 if (error == 0) { 839 for (count = 0; count < SECTOR_SIZE; count+=2) { 840 uint16_t temp; 841 temp = OCTCF_REG_READ(wd, 0x0); 842 843 /* endianess will be swapped below */ 844 tb[count] = (temp & 0xff); 845 tb[count+1] = (temp & 0xff00)>>8; 846 } 847 } 848 849 if (error != 0) { 850 printf("%s: identify failed: %d\n", __func__, error); 851 free(tb, M_DEVBUF); 852 return CMD_ERR; 853 } else { 854 #if BYTE_ORDER == BIG_ENDIAN 855 /* All the fields in the params structure are 16-bit 856 integers except for the ID strings which are char 857 strings. The 16-bit integers are currently in 858 memory in little-endian, regardless of architecture. 859 So, they need to be swapped on big-endian architectures 860 before they are accessed through the ataparams structure. 861 862 The swaps below avoid touching the char strings. 863 */ 864 865 swap16_multi((u_int16_t *)tb, 10); 866 swap16_multi((u_int16_t *)tb + 20, 3); 867 swap16_multi((u_int16_t *)tb + 47, ATAPARAMS_SIZE / 2 - 47); 868 #endif 869 /* Read in parameter block. */ 870 bcopy(tb, prms, sizeof(struct ataparams)); 871 872 /* 873 * Shuffle string byte order. 874 * ATAPI Mitsumi and NEC drives don't need this. 875 */ 876 if ((prms->atap_config & WDC_CFG_ATAPI_MASK) == 877 WDC_CFG_ATAPI && 878 ((prms->atap_model[0] == 'N' && 879 prms->atap_model[1] == 'E') || 880 (prms->atap_model[0] == 'F' && 881 prms->atap_model[1] == 'X'))) { 882 free(tb, M_DEVBUF); 883 return CMD_OK; 884 } 885 for (i = 0; i < sizeof(prms->atap_model); i += 2) { 886 p = (u_short *)(prms->atap_model + i); 887 *p = swap16(*p); 888 } 889 for (i = 0; i < sizeof(prms->atap_serial); i += 2) { 890 p = (u_short *)(prms->atap_serial + i); 891 *p = swap16(*p); 892 } 893 for (i = 0; i < sizeof(prms->atap_revision); i += 2) { 894 p = (u_short *)(prms->atap_revision + i); 895 *p = swap16(*p); 896 } 897 898 free(tb, M_DEVBUF); 899 return CMD_OK; 900 } 901 } 902