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