1 /* $OpenBSD: octcf.c,v 1.35 2022/10/23 19:33:39 krw 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 const 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_version = 1; 519 520 lp->d_magic = DISKMAGIC; 521 lp->d_magic2 = DISKMAGIC; 522 lp->d_checksum = dkcksum(lp); 523 } 524 525 /* 526 * Fabricate a default disk label, and try to read the correct one. 527 */ 528 int 529 octcfgetdisklabel(dev_t dev, struct octcf_softc *wd, struct disklabel *lp, 530 int spoofonly) 531 { 532 int error; 533 534 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS); 535 536 octcfgetdefaultlabel(wd, lp); 537 error = readdisklabel(DISKLABELDEV(dev), octcfstrategy, lp, 538 spoofonly); 539 return (error); 540 } 541 542 int 543 octcfioctl(dev_t dev, u_long xfer, caddr_t addr, int flag, struct proc *p) 544 { 545 struct octcf_softc *wd; 546 struct disklabel *lp; 547 int error = 0; 548 549 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS); 550 551 wd = octcflookup(DISKUNIT(dev)); 552 if (wd == NULL) 553 return ENXIO; 554 555 if ((wd->sc_flags & OCTCFF_LOADED) == 0) { 556 error = EIO; 557 goto exit; 558 } 559 560 switch (xfer) { 561 case DIOCRLDINFO: 562 lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK); 563 octcfgetdisklabel(dev, wd, lp, 0); 564 bcopy(lp, wd->sc_dk.dk_label, sizeof(*lp)); 565 free(lp, M_TEMP, sizeof(*lp)); 566 goto exit; 567 568 case DIOCGPDINFO: 569 octcfgetdisklabel(dev, wd, (struct disklabel *)addr, 1); 570 goto exit; 571 572 case DIOCGDINFO: 573 *(struct disklabel *)addr = *(wd->sc_dk.dk_label); 574 goto exit; 575 576 case DIOCGPART: 577 ((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label; 578 ((struct partinfo *)addr)->part = 579 &wd->sc_dk.dk_label->d_partitions[DISKPART(dev)]; 580 goto exit; 581 582 case DIOCWDINFO: 583 case DIOCSDINFO: 584 if ((flag & FWRITE) == 0) { 585 error = EBADF; 586 goto exit; 587 } 588 589 if ((error = disk_lock(&wd->sc_dk)) != 0) 590 goto exit; 591 592 error = setdisklabel(wd->sc_dk.dk_label, 593 (struct disklabel *)addr, wd->sc_dk.dk_openmask); 594 if (error == 0) { 595 if (xfer == DIOCWDINFO) 596 error = writedisklabel(DISKLABELDEV(dev), 597 octcfstrategy, wd->sc_dk.dk_label); 598 } 599 600 disk_unlock(&wd->sc_dk); 601 goto exit; 602 603 default: 604 error = ENOTTY; 605 goto exit; 606 } 607 608 #ifdef DIAGNOSTIC 609 panic("octcfioctl: impossible"); 610 #endif 611 612 exit: 613 device_unref(&wd->sc_dev); 614 return (error); 615 } 616 617 #ifdef B_FORMAT 618 int 619 wdformat(struct buf *bp) 620 { 621 bp->b_flags |= B_FORMAT; 622 return octcfstrategy(bp); 623 } 624 #endif 625 626 daddr_t 627 octcfsize(dev_t dev) 628 { 629 struct octcf_softc *wd; 630 struct disklabel *lp; 631 int part, omask; 632 daddr_t size; 633 634 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS); 635 636 wd = octcflookup(DISKUNIT(dev)); 637 if (wd == NULL) 638 return (-1); 639 640 part = DISKPART(dev); 641 omask = wd->sc_dk.dk_openmask & (1 << part); 642 643 if (omask == 0 && octcfopen(dev, 0, S_IFBLK, NULL) != 0) { 644 size = -1; 645 goto exit; 646 } 647 648 lp = wd->sc_dk.dk_label; 649 size = DL_SECTOBLK(lp, DL_GETPSIZE(&lp->d_partitions[part])); 650 if (omask == 0 && octcfclose(dev, 0, S_IFBLK, NULL) != 0) 651 size = -1; 652 653 exit: 654 device_unref(&wd->sc_dev); 655 return (size); 656 } 657 658 /* 659 * Dump core after a system crash. 660 */ 661 int 662 octcfdump(dev_t dev, daddr_t blkno, caddr_t va, size_t size) 663 { 664 return ENXIO; 665 } 666 667 int 668 octcf_read_sectors(struct octcf_softc *wd, uint32_t nr_sectors, 669 uint32_t start_sector, void *buf) 670 { 671 uint32_t count; 672 uint16_t *ptr = (uint16_t*)buf; 673 int error; 674 uint8_t status; 675 676 while (nr_sectors--) { 677 while ((status = (OCTCF_REG_READ(wd, wdr_status)>>8)) & WDCS_BSY) 678 DELAY(OCTCFDELAY); 679 octcf_command(wd, start_sector++, WDCC_READ); 680 error = octcf_wait_busy(wd); 681 if (error != 0) 682 return (error); 683 684 volatile uint16_t dummy; 685 for (count = 0; count < SECTOR_SIZE; count+=2) { 686 uint16_t temp; 687 temp = OCTCF_REG_READ(wd, 0x0); 688 *ptr++ = swap16(temp); 689 if ((count & 0xf) == 0) 690 dummy = OCTCF_REG_READ(wd, wdr_status); 691 } 692 } 693 return (0); 694 } 695 696 int 697 octcf_write_sectors(struct octcf_softc *wd, uint32_t nr_sectors, 698 uint32_t start_sector, void *buf) 699 { 700 uint32_t count; 701 uint16_t *ptr = (uint16_t*)buf; 702 int error; 703 uint8_t status; 704 705 while (nr_sectors--) { 706 while ((status = (OCTCF_REG_READ(wd, wdr_status)>>8)) & WDCS_BSY) 707 DELAY(OCTCFDELAY); 708 octcf_command(wd, start_sector++, WDCC_WRITE); 709 if((error = octcf_wait_busy(wd))) 710 return (error); 711 712 volatile uint16_t dummy; 713 for (count = 0; count < SECTOR_SIZE; count+=2) { 714 uint16_t temp = *ptr++; 715 OCTCF_REG_WRITE(wd, 0x0, swap16(temp)); 716 if ((count & 0xf) == 0) 717 dummy = OCTCF_REG_READ(wd, wdr_status); 718 } 719 } 720 return (0); 721 } 722 723 void 724 octcf_command(struct octcf_softc *wd, uint32_t lba, uint8_t cmd) 725 { 726 OCTCF_REG_WRITE(wd, wdr_seccnt, 1 | ((lba & 0xff) << 8)); 727 OCTCF_REG_WRITE(wd, wdr_cyl_lo, 728 ((lba >> 8) & 0xff) | (((lba >> 16) & 0xff) << 8)); 729 OCTCF_REG_WRITE(wd, wdr_sdh, 730 (((lba >> 24) & 0xff) | 0xe0) | (cmd << 8)); 731 } 732 733 int 734 octcf_wait_busy(struct octcf_softc *wd) 735 { 736 uint8_t status; 737 738 status = OCTCF_REG_READ(wd, wdr_status)>>8; 739 while ((status & WDCS_BSY) == WDCS_BSY) { 740 if ((status & WDCS_DWF) != 0) 741 return (EIO); 742 DELAY(OCTCFDELAY); 743 status = (uint8_t)(OCTCF_REG_READ(wd, wdr_status)>>8); 744 } 745 746 if ((status & WDCS_DRQ) == 0) 747 return (ENXIO); 748 749 return (0); 750 } 751 752 /* Get the disk's parameters */ 753 int 754 octcf_get_params(struct octcf_softc *wd, struct ataparams *params) 755 { 756 char *tb; 757 int i; 758 u_int16_t *p; 759 int count; 760 uint8_t status; 761 int error; 762 763 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS); 764 765 tb = malloc(ATAPARAMS_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO); 766 if (tb == NULL) 767 return CMD_AGAIN; 768 769 while ((status = (OCTCF_REG_READ(wd, wdr_status)>>8)) & WDCS_BSY) 770 DELAY(OCTCFDELAY); 771 772 OCTCF_REG_WRITE(wd, wdr_seccnt, 0); 773 OCTCF_REG_WRITE(wd, wdr_cyl_lo, 0); 774 OCTCF_REG_WRITE(wd, wdr_sdh, 0 | (WDCC_IDENTIFY<<8)); 775 776 error = octcf_wait_busy(wd); 777 if (error == 0) { 778 for (count = 0; count < SECTOR_SIZE; count+=2) { 779 uint16_t temp; 780 temp = OCTCF_REG_READ(wd, 0x0); 781 782 /* endianness will be swapped below */ 783 tb[count] = (temp & 0xff); 784 tb[count+1] = (temp & 0xff00)>>8; 785 } 786 } 787 788 if (error != 0) { 789 printf("%s: identify failed: %d\n", __func__, error); 790 free(tb, M_DEVBUF, ATAPARAMS_SIZE); 791 return CMD_ERR; 792 } else { 793 /* 794 * All the fields in the params structure are 16-bit 795 * integers except for the ID strings which are char 796 * strings. The 16-bit integers are currently in 797 * memory in little-endian, regardless of architecture. 798 * So, they need to be swapped on big-endian architectures 799 * before they are accessed through the ataparams structure. 800 * 801 * The swaps below avoid touching the char strings. 802 */ 803 swap16_multi((u_int16_t *)tb, 10); 804 swap16_multi((u_int16_t *)tb + 20, 3); 805 swap16_multi((u_int16_t *)tb + 47, ATAPARAMS_SIZE / 2 - 47); 806 807 /* Read in parameter block. */ 808 bcopy(tb, params, sizeof(struct ataparams)); 809 810 /* 811 * Shuffle string byte order. 812 * ATAPI Mitsumi and NEC drives don't need this. 813 */ 814 if ((params->atap_config & WDC_CFG_ATAPI_MASK) == 815 WDC_CFG_ATAPI && 816 ((params->atap_model[0] == 'N' && 817 params->atap_model[1] == 'E') || 818 (params->atap_model[0] == 'F' && 819 params->atap_model[1] == 'X'))) { 820 free(tb, M_DEVBUF, ATAPARAMS_SIZE); 821 return CMD_OK; 822 } 823 for (i = 0; i < sizeof(params->atap_model); i += 2) { 824 p = (u_short *)(params->atap_model + i); 825 *p = swap16(*p); 826 } 827 for (i = 0; i < sizeof(params->atap_serial); i += 2) { 828 p = (u_short *)(params->atap_serial + i); 829 *p = swap16(*p); 830 } 831 for (i = 0; i < sizeof(params->atap_revision); i += 2) { 832 p = (u_short *)(params->atap_revision + i); 833 *p = swap16(*p); 834 } 835 836 free(tb, M_DEVBUF, ATAPARAMS_SIZE); 837 return CMD_OK; 838 } 839 } 840