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