1 /* $OpenBSD: octcf.c,v 1.18 2014/07/12 21:47:04 pirofti 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 <machine/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 bufq sc_bufq; 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 break; 203 } 204 } 205 206 /* Check if CF is inserted */ 207 i = 0; 208 while ( (status = (OCTCF_REG_READ(wd, wdr_status)>>8)) & WDCS_BSY) { 209 if ((i++) == NR_TRIES ) { 210 printf(": card not present\n"); 211 return; 212 } 213 DELAY(OCTCFDELAY); 214 } 215 216 /* read our drive info */ 217 if (octcf_get_params(wd, &wd->sc_params) != 0) { 218 printf(": IDENTIFY failed\n"); 219 return; 220 } 221 222 for (blank = 0, p = wd->sc_params.atap_model, q = buf, i = 0; 223 i < sizeof(wd->sc_params.atap_model); i++) { 224 c = *p++; 225 if (c == '\0') 226 break; 227 if (c != ' ') { 228 if (blank) { 229 *q++ = ' '; 230 blank = 0; 231 } 232 *q++ = c; 233 } else 234 blank = 1; 235 } 236 *q++ = '\0'; 237 238 printf(": <%s>\n", buf); 239 printf("%s: %d-sector PIO,", 240 wd->sc_dev.dv_xname, wd->sc_params.atap_multi & 0xff); 241 242 wd->sc_capacity = 243 wd->sc_params.atap_cylinders * 244 wd->sc_params.atap_heads * 245 wd->sc_params.atap_sectors; 246 printf(" CHS, %lluMB, %d cyl, %d head, %d sec, %llu sectors\n", 247 wd->sc_capacity / (1048576 / DEV_BSIZE), 248 wd->sc_params.atap_cylinders, 249 wd->sc_params.atap_heads, 250 wd->sc_params.atap_sectors, 251 wd->sc_capacity); 252 253 OCTCFDEBUG_PRINT( 254 ("%s: atap_dmatiming_mimi=%d, atap_dmatiming_recom=%d\n", 255 self->dv_xname, wd->sc_params.atap_dmatiming_mimi, 256 wd->sc_params.atap_dmatiming_recom), DEBUG_PROBE); 257 258 /* 259 * Initialize disk structures. 260 */ 261 wd->sc_dk.dk_name = wd->sc_dev.dv_xname; 262 bufq_init(&wd->sc_bufq, BUFQ_DEFAULT); 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 the I/O */ 330 bufq_queue(&wd->sc_bufq, bp); 331 332 /* Queue transfer on drive, activate drive and controller if idle. */ 333 s = splbio(); 334 octcfstart(wd); 335 splx(s); 336 device_unref(&wd->sc_dev); 337 return; 338 339 bad: 340 bp->b_flags |= B_ERROR; 341 bp->b_resid = bp->b_bcount; 342 done: 343 s = splbio(); 344 biodone(bp); 345 splx(s); 346 if (wd != NULL) 347 device_unref(&wd->sc_dev); 348 } 349 350 /* 351 * Queue a drive for I/O. 352 */ 353 void 354 octcfstart(void *arg) 355 { 356 struct octcf_softc *wd = arg; 357 struct buf *bp; 358 359 OCTCFDEBUG_PRINT(("%s %s\n", __func__, wd->sc_dev.dv_xname), 360 DEBUG_XFERS); 361 while ((bp = bufq_dequeue(&wd->sc_bufq)) != NULL) { 362 /* Transfer this buffer now. */ 363 _octcfstart(wd, bp); 364 } 365 } 366 367 void 368 _octcfstart(struct octcf_softc *wd, struct buf *bp) 369 { 370 struct disklabel *lp; 371 u_int64_t secno; 372 u_int64_t nsecs; 373 374 lp = wd->sc_dk.dk_label; 375 secno = DL_BLKTOSEC(lp, bp->b_blkno) + 376 DL_GETPOFFSET(&lp->d_partitions[DISKPART(bp->b_dev)]); 377 nsecs = howmany(bp->b_bcount, lp->d_secsize); 378 379 wd->sc_bp = bp; 380 381 /* Instrumentation. */ 382 disk_busy(&wd->sc_dk); 383 384 if (bp->b_flags & B_READ) 385 bp->b_error = octcf_read_sectors(wd, nsecs, secno, bp->b_data); 386 else 387 bp->b_error = octcf_write_sectors(wd, nsecs, secno, bp->b_data); 388 389 octcfdone(wd); 390 } 391 392 void 393 octcfdone(void *arg) 394 { 395 struct octcf_softc *wd = arg; 396 struct buf *bp = wd->sc_bp; 397 398 if (bp->b_error == 0) 399 bp->b_resid = 0; 400 else 401 bp->b_flags |= B_ERROR; 402 403 disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid), 404 (bp->b_flags & B_READ)); 405 biodone(bp); 406 } 407 408 int 409 octcfread(dev_t dev, struct uio *uio, int flags) 410 { 411 412 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_XFERS); 413 return (physio(octcfstrategy, dev, B_READ, minphys, uio)); 414 } 415 416 int 417 octcfwrite(dev_t dev, struct uio *uio, int flags) 418 { 419 420 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_XFERS); 421 return (physio(octcfstrategy, dev, B_WRITE, minphys, uio)); 422 } 423 424 int 425 octcfopen(dev_t dev, int flag, int fmt, struct proc *p) 426 { 427 struct octcf_softc *wd; 428 int unit, part; 429 int error; 430 431 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS); 432 433 unit = DISKUNIT(dev); 434 wd = octcflookup(unit); 435 if (wd == NULL) 436 return ENXIO; 437 438 /* 439 * If this is the first open of this device, add a reference 440 * to the adapter. 441 */ 442 if ((error = disk_lock(&wd->sc_dk)) != 0) 443 goto bad4; 444 445 if (wd->sc_dk.dk_openmask != 0) { 446 /* 447 * If any partition is open, but the disk has been invalidated, 448 * disallow further opens. 449 */ 450 if ((wd->sc_flags & OCTCFF_LOADED) == 0) { 451 error = EIO; 452 goto bad3; 453 } 454 } else { 455 if ((wd->sc_flags & OCTCFF_LOADED) == 0) { 456 wd->sc_flags |= OCTCFF_LOADED; 457 458 /* Load the physical device parameters. */ 459 octcf_get_params(wd, &wd->sc_params); 460 461 /* Load the partition info if not already loaded. */ 462 if (octcfgetdisklabel(dev, wd, 463 wd->sc_dk.dk_label, 0) == EIO) { 464 error = EIO; 465 goto bad; 466 } 467 } 468 } 469 470 part = DISKPART(dev); 471 472 /* Check that the partition exists. */ 473 if (part != RAW_PART && 474 (part >= wd->sc_dk.dk_label->d_npartitions || 475 wd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) { 476 error = ENXIO; 477 goto bad; 478 } 479 480 /* Insure only one open at a time. */ 481 switch (fmt) { 482 case S_IFCHR: 483 wd->sc_dk.dk_copenmask |= (1 << part); 484 break; 485 case S_IFBLK: 486 wd->sc_dk.dk_bopenmask |= (1 << part); 487 break; 488 } 489 wd->sc_dk.dk_openmask = 490 wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask; 491 492 disk_unlock(&wd->sc_dk); 493 device_unref(&wd->sc_dev); 494 return 0; 495 496 bad: 497 if (wd->sc_dk.dk_openmask == 0) { 498 } 499 500 bad3: 501 disk_unlock(&wd->sc_dk); 502 bad4: 503 device_unref(&wd->sc_dev); 504 return error; 505 } 506 507 int 508 octcfclose(dev_t dev, int flag, int fmt, struct proc *p) 509 { 510 struct octcf_softc *wd; 511 int part = DISKPART(dev); 512 513 wd = octcflookup(DISKUNIT(dev)); 514 if (wd == NULL) 515 return ENXIO; 516 517 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS); 518 519 disk_lock_nointr(&wd->sc_dk); 520 521 switch (fmt) { 522 case S_IFCHR: 523 wd->sc_dk.dk_copenmask &= ~(1 << part); 524 break; 525 case S_IFBLK: 526 wd->sc_dk.dk_bopenmask &= ~(1 << part); 527 break; 528 } 529 wd->sc_dk.dk_openmask = 530 wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask; 531 532 disk_unlock(&wd->sc_dk); 533 534 device_unref(&wd->sc_dev); 535 return (0); 536 } 537 538 void 539 octcfgetdefaultlabel(struct octcf_softc *wd, struct disklabel *lp) 540 { 541 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS); 542 bzero(lp, sizeof(struct disklabel)); 543 544 lp->d_secsize = DEV_BSIZE; 545 DL_SETDSIZE(lp, wd->sc_capacity); 546 lp->d_ntracks = wd->sc_params.atap_heads; 547 lp->d_nsectors = wd->sc_params.atap_sectors; 548 lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; 549 lp->d_ncylinders = DL_GETDSIZE(lp) / lp->d_secpercyl; 550 lp->d_type = DTYPE_ESDI; 551 strncpy(lp->d_typename, "ESDI/IDE disk", sizeof lp->d_typename); 552 553 /* XXX - user viscopy() like sd.c */ 554 strncpy(lp->d_packname, wd->sc_params.atap_model, sizeof lp->d_packname); 555 lp->d_flags = 0; 556 lp->d_version = 1; 557 558 lp->d_magic = DISKMAGIC; 559 lp->d_magic2 = DISKMAGIC; 560 lp->d_checksum = dkcksum(lp); 561 } 562 563 /* 564 * Fabricate a default disk label, and try to read the correct one. 565 */ 566 int 567 octcfgetdisklabel(dev_t dev, struct octcf_softc *wd, struct disklabel *lp, 568 int spoofonly) 569 { 570 int error; 571 572 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS); 573 574 octcfgetdefaultlabel(wd, lp); 575 error = readdisklabel(DISKLABELDEV(dev), octcfstrategy, lp, 576 spoofonly); 577 return (error); 578 } 579 580 int 581 octcfioctl(dev_t dev, u_long xfer, caddr_t addr, int flag, struct proc *p) 582 { 583 struct octcf_softc *wd; 584 struct disklabel *lp; 585 int error = 0; 586 587 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS); 588 589 wd = octcflookup(DISKUNIT(dev)); 590 if (wd == NULL) 591 return ENXIO; 592 593 if ((wd->sc_flags & OCTCFF_LOADED) == 0) { 594 error = EIO; 595 goto exit; 596 } 597 598 switch (xfer) { 599 case DIOCRLDINFO: 600 lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK); 601 octcfgetdisklabel(dev, wd, lp, 0); 602 bcopy(lp, wd->sc_dk.dk_label, sizeof(*lp)); 603 free(lp, M_TEMP, 0); 604 goto exit; 605 606 case DIOCGPDINFO: 607 octcfgetdisklabel(dev, wd, (struct disklabel *)addr, 1); 608 goto exit; 609 610 case DIOCGDINFO: 611 *(struct disklabel *)addr = *(wd->sc_dk.dk_label); 612 goto exit; 613 614 case DIOCGPART: 615 ((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label; 616 ((struct partinfo *)addr)->part = 617 &wd->sc_dk.dk_label->d_partitions[DISKPART(dev)]; 618 goto exit; 619 620 case DIOCWDINFO: 621 case DIOCSDINFO: 622 if ((flag & FWRITE) == 0) { 623 error = EBADF; 624 goto exit; 625 } 626 627 if ((error = disk_lock(&wd->sc_dk)) != 0) 628 goto exit; 629 630 error = setdisklabel(wd->sc_dk.dk_label, 631 (struct disklabel *)addr, /*wd->sc_dk.dk_openmask : */0); 632 if (error == 0) { 633 if (xfer == DIOCWDINFO) 634 error = writedisklabel(DISKLABELDEV(dev), 635 octcfstrategy, wd->sc_dk.dk_label); 636 } 637 638 disk_unlock(&wd->sc_dk); 639 goto exit; 640 641 #ifdef notyet 642 case DIOCWFORMAT: 643 if ((flag & FWRITE) == 0) 644 return EBADF; 645 { 646 struct format_op *fop; 647 struct iovec aiov; 648 struct uio auio; 649 650 fop = (struct format_op *)addr; 651 aiov.iov_base = fop->df_buf; 652 aiov.iov_len = fop->df_count; 653 auio.uio_iov = &aiov; 654 auio.uio_iovcnt = 1; 655 auio.uio_resid = fop->df_count; 656 auio.uio_segflg = 0; 657 auio.uio_offset = 658 fop->df_startblk * wd->sc_dk.dk_label->d_secsize; 659 auio.uio_procp = p; 660 error = physio(wdformat, dev, B_WRITE, minphys, &auio); 661 fop->df_count -= auio.uio_resid; 662 fop->df_reg[0] = wdc->sc_status; 663 fop->df_reg[1] = wdc->sc_error; 664 goto exit; 665 } 666 #endif 667 668 default: 669 error = ENOTTY; 670 goto exit; 671 } 672 673 #ifdef DIAGNOSTIC 674 panic("octcfioctl: impossible"); 675 #endif 676 677 exit: 678 device_unref(&wd->sc_dev); 679 return (error); 680 } 681 682 #ifdef B_FORMAT 683 int 684 wdformat(struct buf *bp) 685 { 686 687 bp->b_flags |= B_FORMAT; 688 return octcfstrategy(bp); 689 } 690 #endif 691 692 daddr_t 693 octcfsize(dev_t dev) 694 { 695 struct octcf_softc *wd; 696 int part, omask; 697 int64_t size; 698 699 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS); 700 701 wd = octcflookup(DISKUNIT(dev)); 702 if (wd == NULL) 703 return (-1); 704 705 part = DISKPART(dev); 706 omask = wd->sc_dk.dk_openmask & (1 << part); 707 708 if (omask == 0 && octcfopen(dev, 0, S_IFBLK, NULL) != 0) { 709 size = -1; 710 goto exit; 711 } 712 713 size = DL_GETPSIZE(&wd->sc_dk.dk_label->d_partitions[part]) * 714 (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE); 715 if (omask == 0 && octcfclose(dev, 0, S_IFBLK, NULL) != 0) 716 size = -1; 717 718 exit: 719 device_unref(&wd->sc_dev); 720 return (size); 721 } 722 723 /* 724 * Dump core after a system crash. 725 */ 726 int 727 octcfdump(dev_t dev, daddr_t blkno, caddr_t va, size_t size) 728 { 729 return ENXIO; 730 } 731 732 int 733 octcf_read_sectors(struct octcf_softc *wd, uint32_t nr_sectors, 734 uint32_t start_sector, void *buf) 735 { 736 uint32_t count; 737 uint16_t *ptr = (uint16_t*)buf; 738 int error; 739 uint8_t status; 740 741 while (nr_sectors--) { 742 while ((status = (OCTCF_REG_READ(wd, wdr_status)>>8)) & WDCS_BSY) 743 DELAY(OCTCFDELAY); 744 octcf_command(wd, start_sector++, WDCC_READ); 745 error = octcf_wait_busy(wd); 746 if (error != 0) 747 return (error); 748 749 volatile uint16_t dummy; 750 for (count = 0; count < SECTOR_SIZE; count+=2) { 751 uint16_t temp; 752 temp = OCTCF_REG_READ(wd, 0x0); 753 *ptr++ = swap16(temp); 754 if ((count & 0xf) == 0) 755 dummy = OCTCF_REG_READ(wd, wdr_status); 756 } 757 } 758 return (0); 759 } 760 761 int 762 octcf_write_sectors(struct octcf_softc *wd, uint32_t nr_sectors, 763 uint32_t start_sector, void *buf) 764 { 765 uint32_t count; 766 uint16_t *ptr = (uint16_t*)buf; 767 int error; 768 uint8_t status; 769 770 while (nr_sectors--) { 771 while ((status = (OCTCF_REG_READ(wd, wdr_status)>>8)) & WDCS_BSY) 772 DELAY(OCTCFDELAY); 773 octcf_command(wd, start_sector++, WDCC_WRITE); 774 if((error = octcf_wait_busy(wd))) 775 return (error); 776 777 volatile uint16_t dummy; 778 for (count = 0; count < SECTOR_SIZE; count+=2) { 779 uint16_t temp = *ptr++; 780 OCTCF_REG_WRITE(wd, 0x0, swap16(temp)); 781 if ((count & 0xf) == 0) 782 dummy = OCTCF_REG_READ(wd, wdr_status); 783 } 784 } 785 return (0); 786 } 787 788 void 789 octcf_command(struct octcf_softc *wd, uint32_t lba, uint8_t cmd) 790 { 791 OCTCF_REG_WRITE(wd, wdr_seccnt, 1 | ((lba & 0xff) << 8)); 792 OCTCF_REG_WRITE(wd, wdr_cyl_lo, 793 ((lba >> 8) & 0xff) | (((lba >> 16) & 0xff) << 8)); 794 OCTCF_REG_WRITE(wd, wdr_sdh, 795 (((lba >> 24) & 0xff) | 0xe0) | (cmd << 8)); 796 } 797 798 int 799 octcf_wait_busy(struct octcf_softc *wd) 800 { 801 uint8_t status; 802 803 status = OCTCF_REG_READ(wd, wdr_status)>>8; 804 while ((status & WDCS_BSY) == WDCS_BSY) { 805 if ((status & WDCS_DWF) != 0) 806 return (EIO); 807 DELAY(OCTCFDELAY); 808 status = (uint8_t)(OCTCF_REG_READ(wd, wdr_status)>>8); 809 } 810 811 if ((status & WDCS_DRQ) == 0) 812 return (ENXIO); 813 814 return (0); 815 } 816 817 /* Get the disk's parameters */ 818 int 819 octcf_get_params(struct octcf_softc *wd, struct ataparams *prms) 820 { 821 char *tb; 822 int i; 823 u_int16_t *p; 824 int count; 825 uint8_t status; 826 int error; 827 828 OCTCFDEBUG_PRINT(("%s\n", __func__), DEBUG_FUNCS); 829 830 tb = malloc(ATAPARAMS_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO); 831 if (tb == NULL) 832 return CMD_AGAIN; 833 834 while ((status = (OCTCF_REG_READ(wd, wdr_status)>>8)) & WDCS_BSY) 835 DELAY(OCTCFDELAY); 836 837 OCTCF_REG_WRITE(wd, wdr_seccnt, 0); 838 OCTCF_REG_WRITE(wd, wdr_cyl_lo, 0); 839 OCTCF_REG_WRITE(wd, wdr_sdh, 0 | (WDCC_IDENTIFY<<8)); 840 841 error = octcf_wait_busy(wd); 842 if (error == 0) { 843 for (count = 0; count < SECTOR_SIZE; count+=2) { 844 uint16_t temp; 845 temp = OCTCF_REG_READ(wd, 0x0); 846 847 /* endianess will be swapped below */ 848 tb[count] = (temp & 0xff); 849 tb[count+1] = (temp & 0xff00)>>8; 850 } 851 } 852 853 if (error != 0) { 854 printf("%s: identify failed: %d\n", __func__, error); 855 free(tb, M_DEVBUF, 0); 856 return CMD_ERR; 857 } else { 858 #if BYTE_ORDER == BIG_ENDIAN 859 /* All the fields in the params structure are 16-bit 860 integers except for the ID strings which are char 861 strings. The 16-bit integers are currently in 862 memory in little-endian, regardless of architecture. 863 So, they need to be swapped on big-endian architectures 864 before they are accessed through the ataparams structure. 865 866 The swaps below avoid touching the char strings. 867 */ 868 869 swap16_multi((u_int16_t *)tb, 10); 870 swap16_multi((u_int16_t *)tb + 20, 3); 871 swap16_multi((u_int16_t *)tb + 47, ATAPARAMS_SIZE / 2 - 47); 872 #endif 873 /* Read in parameter block. */ 874 bcopy(tb, prms, sizeof(struct ataparams)); 875 876 /* 877 * Shuffle string byte order. 878 * ATAPI Mitsumi and NEC drives don't need this. 879 */ 880 if ((prms->atap_config & WDC_CFG_ATAPI_MASK) == 881 WDC_CFG_ATAPI && 882 ((prms->atap_model[0] == 'N' && 883 prms->atap_model[1] == 'E') || 884 (prms->atap_model[0] == 'F' && 885 prms->atap_model[1] == 'X'))) { 886 free(tb, M_DEVBUF, 0); 887 return CMD_OK; 888 } 889 for (i = 0; i < sizeof(prms->atap_model); i += 2) { 890 p = (u_short *)(prms->atap_model + i); 891 *p = swap16(*p); 892 } 893 for (i = 0; i < sizeof(prms->atap_serial); i += 2) { 894 p = (u_short *)(prms->atap_serial + i); 895 *p = swap16(*p); 896 } 897 for (i = 0; i < sizeof(prms->atap_revision); i += 2) { 898 p = (u_short *)(prms->atap_revision + i); 899 *p = swap16(*p); 900 } 901 902 free(tb, M_DEVBUF, 0); 903 return CMD_OK; 904 } 905 } 906