1 /* $NetBSD: mscp_disk.c,v 1.29 2001/04/12 20:13:26 thorpej Exp $ */ 2 /* 3 * Copyright (c) 1996 Ludd, University of Lule}, Sweden. 4 * Copyright (c) 1988 Regents of the University of California. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Chris Torek. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)uda.c 7.32 (Berkeley) 2/13/91 39 */ 40 41 /* 42 * RA disk device driver 43 * RX MSCP floppy disk device driver 44 */ 45 46 /* 47 * TODO 48 * write bad block forwarding code 49 */ 50 51 #include <sys/param.h> 52 #include <sys/buf.h> 53 #include <sys/device.h> 54 #include <sys/disk.h> 55 #include <sys/disklabel.h> 56 #include <sys/ioctl.h> 57 #include <sys/stat.h> 58 #include <sys/fcntl.h> 59 #include <sys/reboot.h> 60 #include <sys/proc.h> 61 #include <sys/systm.h> 62 63 #include <ufs/ufs/dinode.h> 64 #include <ufs/ffs/fs.h> 65 66 #include <machine/bus.h> 67 #include <machine/cpu.h> 68 69 #include <dev/mscp/mscp.h> 70 #include <dev/mscp/mscpreg.h> 71 #include <dev/mscp/mscpvar.h> 72 73 #include "locators.h" 74 #include "ioconf.h" 75 #include "ra.h" 76 77 #define RAMAJOR 9 /* RA major device number XXX */ 78 79 /* 80 * Drive status, per drive 81 */ 82 struct ra_softc { 83 struct device ra_dev; /* Autoconf struct */ 84 struct disk ra_disk; 85 int ra_state; /* open/closed state */ 86 u_long ra_mediaid; /* media id */ 87 int ra_hwunit; /* Hardware unit number */ 88 int ra_havelabel; /* true if we have a label */ 89 int ra_wlabel; /* label sector is currently writable */ 90 }; 91 92 #define rx_softc ra_softc 93 94 void rxattach __P((struct device *, struct device *, void *)); 95 int rx_putonline __P((struct rx_softc *)); 96 void rrmakelabel __P((struct disklabel *, long)); 97 98 #if NRA 99 100 int ramatch __P((struct device *, struct cfdata *, void *)); 101 void raattach __P((struct device *, struct device *, void *)); 102 int raopen __P((dev_t, int, int, struct proc *)); 103 int raclose __P((dev_t, int, int, struct proc *)); 104 void rastrategy __P((struct buf *)); 105 int raread __P((dev_t, struct uio *)); 106 int rawrite __P((dev_t, struct uio *)); 107 int raioctl __P((dev_t, int, caddr_t, int, struct proc *)); 108 int radump __P((dev_t, daddr_t, caddr_t, size_t)); 109 int rasize __P((dev_t)); 110 int ra_putonline __P((struct ra_softc *)); 111 112 struct cfattach ra_ca = { 113 sizeof(struct ra_softc), ramatch, rxattach 114 }; 115 116 /* 117 * More driver definitions, for generic MSCP code. 118 */ 119 120 int 121 ramatch(parent, cf, aux) 122 struct device *parent; 123 struct cfdata *cf; 124 void *aux; 125 { 126 struct drive_attach_args *da = aux; 127 struct mscp *mp = da->da_mp; 128 129 if ((da->da_typ & MSCPBUS_DISK) == 0) 130 return 0; 131 if (cf->cf_loc[MSCPBUSCF_DRIVE] != MSCPBUSCF_DRIVE_DEFAULT && 132 cf->cf_loc[MSCPBUSCF_DRIVE] != mp->mscp_unit) 133 return 0; 134 /* 135 * Check if this disk is a floppy; then don't configure it. 136 * Seems to be a safe way to test it per Chris Torek. 137 */ 138 if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@') 139 return 0; 140 return 1; 141 } 142 143 /* 144 * (Try to) put the drive online. This is done the first time the 145 * drive is opened, or if it har fallen offline. 146 */ 147 int 148 ra_putonline(ra) 149 struct ra_softc *ra; 150 { 151 struct disklabel *dl; 152 char *msg; 153 154 if (rx_putonline(ra) != MSCP_DONE) 155 return MSCP_FAILED; 156 157 dl = ra->ra_disk.dk_label; 158 159 ra->ra_state = DK_RDLABEL; 160 printf("%s", ra->ra_dev.dv_xname); 161 if ((msg = readdisklabel(MAKEDISKDEV(RAMAJOR, ra->ra_dev.dv_unit, 162 RAW_PART), rastrategy, dl, NULL)) != NULL) 163 printf(": %s", msg); 164 else { 165 ra->ra_havelabel = 1; 166 ra->ra_state = DK_OPEN; 167 } 168 169 printf(": size %d sectors\n", dl->d_secperunit); 170 171 return MSCP_DONE; 172 } 173 174 /* 175 * Open a drive. 176 */ 177 /*ARGSUSED*/ 178 int 179 raopen(dev, flag, fmt, p) 180 dev_t dev; 181 int flag, fmt; 182 struct proc *p; 183 { 184 struct ra_softc *ra; 185 int part, unit, mask; 186 /* 187 * Make sure this is a reasonable open request. 188 */ 189 unit = DISKUNIT(dev); 190 if (unit >= ra_cd.cd_ndevs) 191 return ENXIO; 192 ra = ra_cd.cd_devs[unit]; 193 if (ra == 0) 194 return ENXIO; 195 196 /* 197 * If this is the first open; we must first try to put 198 * the disk online (and read the label). 199 */ 200 if (ra->ra_state == DK_CLOSED) 201 if (ra_putonline(ra) == MSCP_FAILED) 202 return ENXIO; 203 204 /* If the disk has no label; allow writing everywhere */ 205 if (ra->ra_havelabel == 0) 206 ra->ra_wlabel = 1; 207 208 part = DISKPART(dev); 209 if (part >= ra->ra_disk.dk_label->d_npartitions) 210 return ENXIO; 211 212 /* 213 * Wait for the state to settle 214 */ 215 #if notyet 216 while (ra->ra_state != DK_OPEN) 217 if ((error = tsleep((caddr_t)ra, (PZERO + 1) | PCATCH, 218 devopn, 0))) { 219 splx(s); 220 return (error); 221 } 222 #endif 223 224 mask = 1 << part; 225 226 switch (fmt) { 227 case S_IFCHR: 228 ra->ra_disk.dk_copenmask |= mask; 229 break; 230 case S_IFBLK: 231 ra->ra_disk.dk_bopenmask |= mask; 232 break; 233 } 234 ra->ra_disk.dk_openmask |= mask; 235 return 0; 236 } 237 238 /* ARGSUSED */ 239 int 240 raclose(dev, flags, fmt, p) 241 dev_t dev; 242 int flags, fmt; 243 struct proc *p; 244 { 245 int unit = DISKUNIT(dev); 246 struct ra_softc *ra = ra_cd.cd_devs[unit]; 247 int mask = (1 << DISKPART(dev)); 248 249 switch (fmt) { 250 case S_IFCHR: 251 ra->ra_disk.dk_copenmask &= ~mask; 252 break; 253 case S_IFBLK: 254 ra->ra_disk.dk_bopenmask &= ~mask; 255 break; 256 } 257 ra->ra_disk.dk_openmask = 258 ra->ra_disk.dk_copenmask | ra->ra_disk.dk_bopenmask; 259 260 /* 261 * Should wait for I/O to complete on this partition even if 262 * others are open, but wait for work on blkflush(). 263 */ 264 #if notyet 265 if (ra->ra_openpart == 0) { 266 s = spluba(); 267 while (BUFQ_FIRST(&udautab[unit]) != NULL) 268 (void) tsleep(&udautab[unit], PZERO - 1, 269 "raclose", 0); 270 splx(s); 271 ra->ra_state = CLOSED; 272 ra->ra_wlabel = 0; 273 } 274 #endif 275 return (0); 276 } 277 278 /* 279 * Queue a transfer request, and if possible, hand it to the controller. 280 */ 281 void 282 rastrategy(bp) 283 struct buf *bp; 284 { 285 int unit; 286 struct ra_softc *ra; 287 /* 288 * Make sure this is a reasonable drive to use. 289 */ 290 unit = DISKUNIT(bp->b_dev); 291 if (unit > ra_cd.cd_ndevs || (ra = ra_cd.cd_devs[unit]) == NULL) { 292 bp->b_error = ENXIO; 293 bp->b_flags |= B_ERROR; 294 goto done; 295 } 296 /* 297 * If drive is open `raw' or reading label, let it at it. 298 */ 299 if (ra->ra_state == DK_RDLABEL) { 300 mscp_strategy(bp, ra->ra_dev.dv_parent); 301 return; 302 } 303 304 /* If disk is not online, try to put it online */ 305 if (ra->ra_state == DK_CLOSED) 306 if (ra_putonline(ra) == MSCP_FAILED) { 307 bp->b_flags |= B_ERROR; 308 bp->b_error = EIO; 309 goto done; 310 } 311 312 /* 313 * Determine the size of the transfer, and make sure it is 314 * within the boundaries of the partition. 315 */ 316 if (bounds_check_with_label(bp, ra->ra_disk.dk_label, 317 ra->ra_wlabel) <= 0) 318 goto done; 319 320 /* Make some statistics... /bqt */ 321 ra->ra_disk.dk_xfer++; 322 ra->ra_disk.dk_bytes += bp->b_bcount; 323 mscp_strategy(bp, ra->ra_dev.dv_parent); 324 return; 325 326 done: 327 biodone(bp); 328 } 329 330 int 331 raread(dev, uio) 332 dev_t dev; 333 struct uio *uio; 334 { 335 336 return (physio(rastrategy, NULL, dev, B_READ, minphys, uio)); 337 } 338 339 int 340 rawrite(dev, uio) 341 dev_t dev; 342 struct uio *uio; 343 { 344 345 return (physio(rastrategy, NULL, dev, B_WRITE, minphys, uio)); 346 } 347 348 /* 349 * I/O controls. 350 */ 351 int 352 raioctl(dev, cmd, data, flag, p) 353 dev_t dev; 354 int cmd; 355 caddr_t data; 356 int flag; 357 struct proc *p; 358 { 359 int unit = DISKUNIT(dev); 360 struct disklabel *lp, *tp; 361 struct ra_softc *ra = ra_cd.cd_devs[unit]; 362 int error = 0; 363 #ifdef __HAVE_OLD_DISKLABEL 364 struct disklabel newlabel; 365 #endif 366 367 lp = ra->ra_disk.dk_label; 368 369 switch (cmd) { 370 371 case DIOCGDINFO: 372 bcopy(lp, data, sizeof (struct disklabel)); 373 break; 374 #ifdef __HAVE_OLD_DISKLABEL 375 case ODIOCGDINFO: 376 bcopy(lp, &newlabel, sizeof disklabel); 377 if (newlabel.d_npartitions > OLDMAXPARTITIONS) 378 return ENOTTY; 379 bcopy(&newlabel, data, sizeof (struct olddisklabel)); 380 break; 381 #endif 382 383 case DIOCGPART: 384 ((struct partinfo *)data)->disklab = lp; 385 ((struct partinfo *)data)->part = 386 &lp->d_partitions[DISKPART(dev)]; 387 break; 388 389 case DIOCWDINFO: 390 case DIOCSDINFO: 391 #ifdef __HAVE_OLD_DISKLABEL 392 case ODIOCWDINFO: 393 case ODIOCSDINFO: 394 if (cmd == ODIOCSDINFO || xfer == ODIOCWDINFO) { 395 memset(&newlabel, 0, sizeof newlabel); 396 memcpy(&newlabel, data, sizeof (struct olddisklabel)); 397 tp = &newlabel; 398 } else 399 #endif 400 tp = (struct disklabel *)data; 401 402 if ((flag & FWRITE) == 0) 403 error = EBADF; 404 else { 405 error = setdisklabel(lp, tp, 0, 0); 406 if ((error == 0) && (cmd == DIOCWDINFO 407 #ifdef __HAVE_OLD_DISKLABEL 408 || cmd == ODIOCWDINFO 409 #else 410 )) { 411 #endif 412 ra->ra_wlabel = 1; 413 error = writedisklabel(dev, rastrategy, lp,0); 414 ra->ra_wlabel = 0; 415 } 416 } 417 break; 418 419 case DIOCWLABEL: 420 if ((flag & FWRITE) == 0) 421 error = EBADF; 422 else 423 ra->ra_wlabel = 1; 424 break; 425 426 case DIOCGDEFLABEL: 427 #ifdef __HAVE_OLD_DISKLABEL 428 case ODIOCGDEFLABEL: 429 if (cmd == ODIOCGDEFLABEL) 430 tp = &newlabel; 431 else 432 #else 433 tp = (struct disklabel *)data; 434 #endif 435 bzero(tp, sizeof(struct disklabel)); 436 tp->d_secsize = lp->d_secsize; 437 tp->d_nsectors = lp->d_nsectors; 438 tp->d_ntracks = lp->d_ntracks; 439 tp->d_ncylinders = lp->d_ncylinders; 440 tp->d_secpercyl = lp->d_secpercyl; 441 tp->d_secperunit = lp->d_secperunit; 442 tp->d_type = DTYPE_MSCP; 443 tp->d_rpm = 3600; 444 rrmakelabel(tp, ra->ra_mediaid); 445 #ifdef __HAVE_OLD_DISKLABEL 446 if (cmd == ODIOCGDEFLABEL) { 447 if (tp->d_npartitions > OLDMAXPARTITIONS) 448 return ENOTTY; 449 memcpy(data, tp, sizeof (struct olddisklabel)); 450 } 451 #endif 452 break; 453 454 default: 455 error = ENOTTY; 456 break; 457 } 458 return (error); 459 } 460 461 462 int 463 radump(dev, blkno, va, size) 464 dev_t dev; 465 daddr_t blkno; 466 caddr_t va; 467 size_t size; 468 { 469 return ENXIO; 470 } 471 472 /* 473 * Return the size of a partition, if known, or -1 if not. 474 */ 475 int 476 rasize(dev) 477 dev_t dev; 478 { 479 int unit = DISKUNIT(dev); 480 struct ra_softc *ra; 481 482 if (unit >= ra_cd.cd_ndevs || ra_cd.cd_devs[unit] == 0) 483 return -1; 484 485 ra = ra_cd.cd_devs[unit]; 486 487 if (ra->ra_state == DK_CLOSED) 488 if (ra_putonline(ra) == MSCP_FAILED) 489 return -1; 490 491 return ra->ra_disk.dk_label->d_partitions[DISKPART(dev)].p_size * 492 (ra->ra_disk.dk_label->d_secsize / DEV_BSIZE); 493 } 494 495 #endif /* NRA */ 496 497 #if NRX 498 499 int rxmatch __P((struct device *, struct cfdata *, void *)); 500 int rxopen __P((dev_t, int, int, struct proc *)); 501 int rxclose __P((dev_t, int, int, struct proc *)); 502 void rxstrategy __P((struct buf *)); 503 int rxread __P((dev_t, struct uio *)); 504 int rxwrite __P((dev_t, struct uio *)); 505 int rxioctl __P((dev_t, int, caddr_t, int, struct proc *)); 506 int rxdump __P((dev_t, daddr_t, caddr_t, size_t)); 507 int rxsize __P((dev_t)); 508 509 struct cfattach rx_ca = { 510 sizeof(struct rx_softc), rxmatch, rxattach 511 }; 512 513 /* 514 * More driver definitions, for generic MSCP code. 515 */ 516 517 int 518 rxmatch(parent, cf, aux) 519 struct device *parent; 520 struct cfdata *cf; 521 void *aux; 522 { 523 struct drive_attach_args *da = aux; 524 struct mscp *mp = da->da_mp; 525 526 if ((da->da_typ & MSCPBUS_DISK) == 0) 527 return 0; 528 if (cf->cf_loc[MSCPBUSCF_DRIVE] != MSCPBUSCF_DRIVE_DEFAULT && 529 cf->cf_loc[MSCPBUSCF_DRIVE] != mp->mscp_unit) 530 return 0; 531 /* 532 * Check if this disk is a floppy; then configure it. 533 * Seems to be a safe way to test it per Chris Torek. 534 */ 535 if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@') 536 return 1; 537 return 0; 538 } 539 540 #endif /* NRX */ 541 542 /* 543 * The attach routine only checks and prints drive type. 544 * Bringing the disk online is done when the disk is accessed 545 * the first time. 546 */ 547 void 548 rxattach(parent, self, aux) 549 struct device *parent, *self; 550 void *aux; 551 { 552 struct rx_softc *rx = (void *)self; 553 struct drive_attach_args *da = aux; 554 struct mscp *mp = da->da_mp; 555 struct mscp_softc *mi = (void *)parent; 556 struct disklabel *dl; 557 558 rx->ra_mediaid = mp->mscp_guse.guse_mediaid; 559 rx->ra_state = DK_CLOSED; 560 rx->ra_hwunit = mp->mscp_unit; 561 mi->mi_dp[mp->mscp_unit] = self; 562 563 rx->ra_disk.dk_name = rx->ra_dev.dv_xname; 564 disk_attach((struct disk *)&rx->ra_disk); 565 566 /* Fill in what we know. The actual size is gotten later */ 567 dl = rx->ra_disk.dk_label; 568 569 dl->d_secsize = DEV_BSIZE; 570 dl->d_nsectors = mp->mscp_guse.guse_nspt; 571 dl->d_ntracks = mp->mscp_guse.guse_ngpc * mp->mscp_guse.guse_group; 572 dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks; 573 disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid); 574 #ifdef DEBUG 575 printf("%s: nspt %d group %d ngpc %d rct %d nrpt %d nrct %d\n", 576 self->dv_xname, mp->mscp_guse.guse_nspt, mp->mscp_guse.guse_group, 577 mp->mscp_guse.guse_ngpc, mp->mscp_guse.guse_rctsize, 578 mp->mscp_guse.guse_nrpt, mp->mscp_guse.guse_nrct); 579 #endif 580 } 581 582 /* 583 * (Try to) put the drive online. This is done the first time the 584 * drive is opened, or if it har fallen offline. 585 */ 586 int 587 rx_putonline(rx) 588 struct rx_softc *rx; 589 { 590 struct mscp *mp; 591 struct mscp_softc *mi = (struct mscp_softc *)rx->ra_dev.dv_parent; 592 volatile int i; 593 594 rx->ra_state = DK_CLOSED; 595 mp = mscp_getcp(mi, MSCP_WAIT); 596 mp->mscp_opcode = M_OP_ONLINE; 597 mp->mscp_unit = rx->ra_hwunit; 598 mp->mscp_cmdref = 1; 599 *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 600 601 /* Poll away */ 602 i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0); 603 if (tsleep(&rx->ra_dev.dv_unit, PRIBIO, "rxonline", 100*100)) 604 rx->ra_state = DK_CLOSED; 605 606 if (rx->ra_state == DK_CLOSED) 607 return MSCP_FAILED; 608 609 return MSCP_DONE; 610 } 611 612 #if NRX 613 614 /* 615 * Open a drive. 616 */ 617 /*ARGSUSED*/ 618 int 619 rxopen(dev, flag, fmt, p) 620 dev_t dev; 621 int flag, fmt; 622 struct proc *p; 623 { 624 struct rx_softc *rx; 625 int unit; 626 627 /* 628 * Make sure this is a reasonable open request. 629 */ 630 unit = DISKUNIT(dev); 631 if (unit >= rx_cd.cd_ndevs) 632 return ENXIO; 633 rx = rx_cd.cd_devs[unit]; 634 if (rx == 0) 635 return ENXIO; 636 637 /* 638 * If this is the first open; we must first try to put 639 * the disk online (and read the label). 640 */ 641 if (rx->ra_state == DK_CLOSED) 642 if (rx_putonline(rx) == MSCP_FAILED) 643 return ENXIO; 644 645 return 0; 646 } 647 648 /* ARGSUSED */ 649 int 650 rxclose(dev, flags, fmt, p) 651 dev_t dev; 652 int flags, fmt; 653 struct proc *p; 654 { 655 return (0); 656 } 657 658 /* 659 * Queue a transfer request, and if possible, hand it to the controller. 660 * 661 * This routine is broken into two so that the internal version 662 * udastrat1() can be called by the (nonexistent, as yet) bad block 663 * revectoring routine. 664 */ 665 void 666 rxstrategy(bp) 667 struct buf *bp; 668 { 669 int unit; 670 struct rx_softc *rx; 671 672 /* 673 * Make sure this is a reasonable drive to use. 674 */ 675 unit = DISKUNIT(bp->b_dev); 676 if (unit > rx_cd.cd_ndevs || (rx = rx_cd.cd_devs[unit]) == NULL) { 677 bp->b_error = ENXIO; 678 bp->b_flags |= B_ERROR; 679 goto done; 680 } 681 682 /* If disk is not online, try to put it online */ 683 if (rx->ra_state == DK_CLOSED) 684 if (rx_putonline(rx) == MSCP_FAILED) { 685 bp->b_flags |= B_ERROR; 686 bp->b_error = EIO; 687 goto done; 688 } 689 690 /* 691 * Determine the size of the transfer, and make sure it is 692 * within the boundaries of the partition. 693 */ 694 if (bp->b_blkno >= rx->ra_disk.dk_label->d_secperunit) { 695 bp->b_resid = bp->b_bcount; 696 goto done; 697 } 698 699 /* Make some statistics... /bqt */ 700 rx->ra_disk.dk_xfer++; 701 rx->ra_disk.dk_bytes += bp->b_bcount; 702 mscp_strategy(bp, rx->ra_dev.dv_parent); 703 return; 704 705 done: 706 biodone(bp); 707 } 708 709 int 710 rxread(dev, uio) 711 dev_t dev; 712 struct uio *uio; 713 { 714 715 return (physio(rxstrategy, NULL, dev, B_READ, minphys, uio)); 716 } 717 718 int 719 rxwrite(dev, uio) 720 dev_t dev; 721 struct uio *uio; 722 { 723 724 return (physio(rxstrategy, NULL, dev, B_WRITE, minphys, uio)); 725 } 726 727 /* 728 * I/O controls. 729 */ 730 int 731 rxioctl(dev, cmd, data, flag, p) 732 dev_t dev; 733 int cmd; 734 caddr_t data; 735 int flag; 736 struct proc *p; 737 { 738 int unit = DISKUNIT(dev); 739 struct disklabel *lp; 740 struct rx_softc *rx = rx_cd.cd_devs[unit]; 741 int error = 0; 742 743 lp = rx->ra_disk.dk_label; 744 745 switch (cmd) { 746 747 case DIOCGDINFO: 748 bcopy(lp, data, sizeof (struct disklabel)); 749 break; 750 751 case DIOCGPART: 752 ((struct partinfo *)data)->disklab = lp; 753 ((struct partinfo *)data)->part = 754 &lp->d_partitions[DISKPART(dev)]; 755 break; 756 757 758 case DIOCWDINFO: 759 case DIOCSDINFO: 760 case DIOCWLABEL: 761 break; 762 763 default: 764 error = ENOTTY; 765 break; 766 } 767 return (error); 768 } 769 770 int 771 rxdump(dev, blkno, va, size) 772 dev_t dev; 773 daddr_t blkno; 774 caddr_t va; 775 size_t size; 776 { 777 778 /* Not likely. */ 779 return ENXIO; 780 } 781 782 int 783 rxsize(dev) 784 dev_t dev; 785 { 786 787 return -1; 788 } 789 790 #endif /* NRX */ 791 792 void rrdgram __P((struct device *, struct mscp *, struct mscp_softc *)); 793 void rriodone __P((struct device *, struct buf *)); 794 int rronline __P((struct device *, struct mscp *)); 795 int rrgotstatus __P((struct device *, struct mscp *)); 796 void rrreplace __P((struct device *, struct mscp *)); 797 int rrioerror __P((struct device *, struct mscp *, struct buf *)); 798 void rrfillin __P((struct buf *, struct mscp *)); 799 void rrbb __P((struct device *, struct mscp *, struct buf *)); 800 801 802 struct mscp_device ra_device = { 803 rrdgram, 804 rriodone, 805 rronline, 806 rrgotstatus, 807 rrreplace, 808 rrioerror, 809 rrbb, 810 rrfillin, 811 }; 812 813 /* 814 * Handle an error datagram. 815 * This can come from an unconfigured drive as well. 816 */ 817 void 818 rrdgram(usc, mp, mi) 819 struct device *usc; 820 struct mscp *mp; 821 struct mscp_softc *mi; 822 { 823 if (mscp_decodeerror(usc == NULL?"unconf disk" : usc->dv_xname, mp, mi)) 824 return; 825 /* 826 * SDI status information bytes 10 and 11 are the microprocessor 827 * error code and front panel code respectively. These vary per 828 * drive type and are printed purely for field service information. 829 */ 830 if (mp->mscp_format == M_FM_SDI) 831 printf("\tsdi uproc error code 0x%x, front panel code 0x%x\n", 832 mp->mscp_erd.erd_sdistat[10], 833 mp->mscp_erd.erd_sdistat[11]); 834 } 835 836 void 837 rriodone(usc, bp) 838 struct device *usc; 839 struct buf *bp; 840 { 841 842 biodone(bp); 843 } 844 845 /* 846 * A drive came on line. Check its type and size. Return DONE if 847 * we think the drive is truly on line. In any case, awaken anyone 848 * sleeping on the drive on-line-ness. 849 */ 850 int 851 rronline(usc, mp) 852 struct device *usc; 853 struct mscp *mp; 854 { 855 struct rx_softc *rx = (struct rx_softc *)usc; 856 struct disklabel *dl; 857 858 wakeup((caddr_t)&usc->dv_unit); 859 if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { 860 printf("%s: attempt to bring on line failed: ", usc->dv_xname); 861 mscp_printevent(mp); 862 return (MSCP_FAILED); 863 } 864 865 rx->ra_state = DK_OPEN; 866 867 dl = rx->ra_disk.dk_label; 868 dl->d_secperunit = (daddr_t)mp->mscp_onle.onle_unitsize; 869 870 if (dl->d_secpercyl) { 871 dl->d_ncylinders = dl->d_secperunit/dl->d_secpercyl; 872 dl->d_type = DTYPE_MSCP; 873 dl->d_rpm = 3600; 874 } else { 875 dl->d_type = DTYPE_FLOPPY; 876 dl->d_rpm = 300; 877 } 878 rrmakelabel(dl, rx->ra_mediaid); 879 880 return (MSCP_DONE); 881 } 882 883 void 884 rrmakelabel(dl, type) 885 struct disklabel *dl; 886 long type; 887 { 888 int n, p = 0; 889 890 dl->d_bbsize = BBSIZE; 891 dl->d_sbsize = SBSIZE; 892 893 /* Create the disk name for disklabel. Phew... */ 894 dl->d_typename[p++] = MSCP_MID_CHAR(2, type); 895 dl->d_typename[p++] = MSCP_MID_CHAR(1, type); 896 if (MSCP_MID_ECH(0, type)) 897 dl->d_typename[p++] = MSCP_MID_CHAR(0, type); 898 n = MSCP_MID_NUM(type); 899 if (n > 99) { 900 dl->d_typename[p++] = '1'; 901 n -= 100; 902 } 903 if (n > 9) { 904 dl->d_typename[p++] = (n / 10) + '0'; 905 n %= 10; 906 } 907 dl->d_typename[p++] = n + '0'; 908 dl->d_typename[p] = 0; 909 dl->d_npartitions = MAXPARTITIONS; 910 dl->d_partitions[0].p_size = dl->d_partitions[2].p_size = 911 dl->d_secperunit; 912 dl->d_partitions[0].p_offset = dl->d_partitions[2].p_offset = 0; 913 dl->d_interleave = dl->d_headswitch = 1; 914 dl->d_magic = dl->d_magic2 = DISKMAGIC; 915 dl->d_checksum = dkcksum(dl); 916 } 917 918 /* 919 * We got some (configured) unit's status. Return DONE if it succeeded. 920 */ 921 int 922 rrgotstatus(usc, mp) 923 struct device *usc; 924 struct mscp *mp; 925 { 926 if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { 927 printf("%s: attempt to get status failed: ", usc->dv_xname); 928 mscp_printevent(mp); 929 return (MSCP_FAILED); 930 } 931 /* record for (future) bad block forwarding and whatever else */ 932 #ifdef notyet 933 uda_rasave(ui->ui_unit, mp, 1); 934 #endif 935 return (MSCP_DONE); 936 } 937 938 /* 939 * A replace operation finished. 940 */ 941 /*ARGSUSED*/ 942 void 943 rrreplace(usc, mp) 944 struct device *usc; 945 struct mscp *mp; 946 { 947 948 panic("udareplace"); 949 } 950 951 /* 952 * A transfer failed. We get a chance to fix or restart it. 953 * Need to write the bad block forwaring code first.... 954 */ 955 /*ARGSUSED*/ 956 int 957 rrioerror(usc, mp, bp) 958 struct device *usc; 959 struct mscp *mp; 960 struct buf *bp; 961 { 962 struct ra_softc *ra = (void *)usc; 963 int code = mp->mscp_event; 964 965 switch (code & M_ST_MASK) { 966 /* The unit has fallen offline. Try to figure out why. */ 967 case M_ST_OFFLINE: 968 bp->b_flags |= B_ERROR; 969 bp->b_error = EIO; 970 ra->ra_state = DK_CLOSED; 971 if (code & M_OFFLINE_UNMOUNTED) 972 printf("%s: not mounted/spun down\n", usc->dv_xname); 973 if (code & M_OFFLINE_DUPLICATE) 974 printf("%s: duplicate unit number!!!\n", usc->dv_xname); 975 return MSCP_DONE; 976 977 case M_ST_AVAILABLE: 978 ra->ra_state = DK_CLOSED; /* Force another online */ 979 return MSCP_DONE; 980 981 default: 982 printf("%s:", usc->dv_xname); 983 break; 984 } 985 return (MSCP_FAILED); 986 } 987 988 /* 989 * Fill in disk addresses in a mscp packet waiting for transfer. 990 */ 991 void 992 rrfillin(bp, mp) 993 struct buf *bp; 994 struct mscp *mp; 995 { 996 struct rx_softc *rx = 0; /* Wall */ 997 struct disklabel *lp; 998 int unit = DISKUNIT(bp->b_dev); 999 int part = DISKPART(bp->b_dev); 1000 1001 #if NRA 1002 if (major(bp->b_dev) == RAMAJOR) 1003 rx = ra_cd.cd_devs[unit]; 1004 #endif 1005 #if NRX 1006 if (major(bp->b_dev) != RAMAJOR) 1007 rx = rx_cd.cd_devs[unit]; 1008 #endif 1009 lp = rx->ra_disk.dk_label; 1010 1011 mp->mscp_seq.seq_lbn = lp->d_partitions[part].p_offset + bp->b_blkno; 1012 mp->mscp_unit = rx->ra_hwunit; 1013 mp->mscp_seq.seq_bytecount = bp->b_bcount; 1014 } 1015 1016 /* 1017 * A bad block related operation finished. 1018 */ 1019 /*ARGSUSED*/ 1020 void 1021 rrbb(usc, mp, bp) 1022 struct device *usc; 1023 struct mscp *mp; 1024 struct buf *bp; 1025 { 1026 1027 panic("udabb"); 1028 } 1029