1 /* $NetBSD: mscp_disk.c,v 1.25 2000/05/27 04:52:35 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 = splimp(); 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 364 lp = ra->ra_disk.dk_label; 365 366 switch (cmd) { 367 368 case DIOCGDINFO: 369 bcopy(lp, data, sizeof (struct disklabel)); 370 break; 371 372 case DIOCGPART: 373 ((struct partinfo *)data)->disklab = lp; 374 ((struct partinfo *)data)->part = 375 &lp->d_partitions[DISKPART(dev)]; 376 break; 377 378 case DIOCWDINFO: 379 case DIOCSDINFO: 380 if ((flag & FWRITE) == 0) 381 error = EBADF; 382 else { 383 error = setdisklabel(lp, (struct disklabel *)data,0,0); 384 if ((error == 0) && (cmd == DIOCWDINFO)) { 385 ra->ra_wlabel = 1; 386 error = writedisklabel(dev, rastrategy, lp,0); 387 ra->ra_wlabel = 0; 388 } 389 } 390 break; 391 392 case DIOCWLABEL: 393 if ((flag & FWRITE) == 0) 394 error = EBADF; 395 else 396 ra->ra_wlabel = 1; 397 break; 398 399 case DIOCGDEFLABEL: 400 tp = (struct disklabel *)data; 401 bzero(data, sizeof(struct disklabel)); 402 tp->d_secsize = lp->d_secsize; 403 tp->d_nsectors = lp->d_nsectors; 404 tp->d_ntracks = lp->d_ntracks; 405 tp->d_ncylinders = lp->d_ncylinders; 406 tp->d_secpercyl = lp->d_secpercyl; 407 tp->d_secperunit = lp->d_secperunit; 408 tp->d_type = DTYPE_MSCP; 409 tp->d_rpm = 3600; 410 rrmakelabel(tp, ra->ra_mediaid); 411 break; 412 413 default: 414 error = ENOTTY; 415 break; 416 } 417 return (error); 418 } 419 420 421 int 422 radump(dev, blkno, va, size) 423 dev_t dev; 424 daddr_t blkno; 425 caddr_t va; 426 size_t size; 427 { 428 return ENXIO; 429 } 430 431 /* 432 * Return the size of a partition, if known, or -1 if not. 433 */ 434 int 435 rasize(dev) 436 dev_t dev; 437 { 438 int unit = DISKUNIT(dev); 439 struct ra_softc *ra; 440 441 if (unit >= ra_cd.cd_ndevs || ra_cd.cd_devs[unit] == 0) 442 return -1; 443 444 ra = ra_cd.cd_devs[unit]; 445 446 if (ra->ra_state == DK_CLOSED) 447 if (ra_putonline(ra) == MSCP_FAILED) 448 return -1; 449 450 return ra->ra_disk.dk_label->d_partitions[DISKPART(dev)].p_size * 451 (ra->ra_disk.dk_label->d_secsize / DEV_BSIZE); 452 } 453 454 #endif /* NRA */ 455 456 #if NRX 457 458 int rxmatch __P((struct device *, struct cfdata *, void *)); 459 int rxopen __P((dev_t, int, int, struct proc *)); 460 int rxclose __P((dev_t, int, int, struct proc *)); 461 void rxstrategy __P((struct buf *)); 462 int rxread __P((dev_t, struct uio *)); 463 int rxwrite __P((dev_t, struct uio *)); 464 int rxioctl __P((dev_t, int, caddr_t, int, struct proc *)); 465 int rxdump __P((dev_t, daddr_t, caddr_t, size_t)); 466 int rxsize __P((dev_t)); 467 468 struct cfattach rx_ca = { 469 sizeof(struct rx_softc), rxmatch, rxattach 470 }; 471 472 /* 473 * More driver definitions, for generic MSCP code. 474 */ 475 476 int 477 rxmatch(parent, cf, aux) 478 struct device *parent; 479 struct cfdata *cf; 480 void *aux; 481 { 482 struct drive_attach_args *da = aux; 483 struct mscp *mp = da->da_mp; 484 485 if ((da->da_typ & MSCPBUS_DISK) == 0) 486 return 0; 487 if (cf->cf_loc[MSCPBUSCF_DRIVE] != MSCPBUSCF_DRIVE_DEFAULT && 488 cf->cf_loc[MSCPBUSCF_DRIVE] != mp->mscp_unit) 489 return 0; 490 /* 491 * Check if this disk is a floppy; then configure it. 492 * Seems to be a safe way to test it per Chris Torek. 493 */ 494 if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@') 495 return 1; 496 return 0; 497 } 498 499 #endif /* NRX */ 500 501 /* 502 * The attach routine only checks and prints drive type. 503 * Bringing the disk online is done when the disk is accessed 504 * the first time. 505 */ 506 void 507 rxattach(parent, self, aux) 508 struct device *parent, *self; 509 void *aux; 510 { 511 struct rx_softc *rx = (void *)self; 512 struct drive_attach_args *da = aux; 513 struct mscp *mp = da->da_mp; 514 struct mscp_softc *mi = (void *)parent; 515 struct disklabel *dl; 516 517 rx->ra_mediaid = mp->mscp_guse.guse_mediaid; 518 rx->ra_state = DK_CLOSED; 519 rx->ra_hwunit = mp->mscp_unit; 520 mi->mi_dp[mp->mscp_unit] = self; 521 522 rx->ra_disk.dk_name = rx->ra_dev.dv_xname; 523 disk_attach((struct disk *)&rx->ra_disk); 524 525 /* Fill in what we know. The actual size is gotten later */ 526 dl = rx->ra_disk.dk_label; 527 528 dl->d_secsize = DEV_BSIZE; 529 dl->d_nsectors = mp->mscp_guse.guse_nspt; 530 dl->d_ntracks = mp->mscp_guse.guse_ngpc * mp->mscp_guse.guse_group; 531 dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks; 532 disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid); 533 #ifdef DEBUG 534 printf("%s: nspt %d group %d ngpc %d rct %d nrpt %d nrct %d\n", 535 self->dv_xname, mp->mscp_guse.guse_nspt, mp->mscp_guse.guse_group, 536 mp->mscp_guse.guse_ngpc, mp->mscp_guse.guse_rctsize, 537 mp->mscp_guse.guse_nrpt, mp->mscp_guse.guse_nrct); 538 #endif 539 } 540 541 /* 542 * (Try to) put the drive online. This is done the first time the 543 * drive is opened, or if it har fallen offline. 544 */ 545 int 546 rx_putonline(rx) 547 struct rx_softc *rx; 548 { 549 struct mscp *mp; 550 struct mscp_softc *mi = (struct mscp_softc *)rx->ra_dev.dv_parent; 551 volatile int i; 552 553 rx->ra_state = DK_CLOSED; 554 mp = mscp_getcp(mi, MSCP_WAIT); 555 mp->mscp_opcode = M_OP_ONLINE; 556 mp->mscp_unit = rx->ra_hwunit; 557 mp->mscp_cmdref = 1; 558 *mp->mscp_addr |= MSCP_OWN | MSCP_INT; 559 560 /* Poll away */ 561 i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0); 562 if (tsleep(&rx->ra_dev.dv_unit, PRIBIO, "rxonline", 100*100)) 563 rx->ra_state = DK_CLOSED; 564 565 if (rx->ra_state == DK_CLOSED) 566 return MSCP_FAILED; 567 568 return MSCP_DONE; 569 } 570 571 #if NRX 572 573 /* 574 * Open a drive. 575 */ 576 /*ARGSUSED*/ 577 int 578 rxopen(dev, flag, fmt, p) 579 dev_t dev; 580 int flag, fmt; 581 struct proc *p; 582 { 583 struct rx_softc *rx; 584 int unit; 585 586 /* 587 * Make sure this is a reasonable open request. 588 */ 589 unit = DISKUNIT(dev); 590 if (unit >= rx_cd.cd_ndevs) 591 return ENXIO; 592 rx = rx_cd.cd_devs[unit]; 593 if (rx == 0) 594 return ENXIO; 595 596 /* 597 * If this is the first open; we must first try to put 598 * the disk online (and read the label). 599 */ 600 if (rx->ra_state == DK_CLOSED) 601 if (rx_putonline(rx) == MSCP_FAILED) 602 return ENXIO; 603 604 return 0; 605 } 606 607 /* ARGSUSED */ 608 int 609 rxclose(dev, flags, fmt, p) 610 dev_t dev; 611 int flags, fmt; 612 struct proc *p; 613 { 614 return (0); 615 } 616 617 /* 618 * Queue a transfer request, and if possible, hand it to the controller. 619 * 620 * This routine is broken into two so that the internal version 621 * udastrat1() can be called by the (nonexistent, as yet) bad block 622 * revectoring routine. 623 */ 624 void 625 rxstrategy(bp) 626 struct buf *bp; 627 { 628 int unit; 629 struct rx_softc *rx; 630 631 /* 632 * Make sure this is a reasonable drive to use. 633 */ 634 unit = DISKUNIT(bp->b_dev); 635 if (unit > rx_cd.cd_ndevs || (rx = rx_cd.cd_devs[unit]) == NULL) { 636 bp->b_error = ENXIO; 637 bp->b_flags |= B_ERROR; 638 goto done; 639 } 640 641 /* If disk is not online, try to put it online */ 642 if (rx->ra_state == DK_CLOSED) 643 if (rx_putonline(rx) == MSCP_FAILED) { 644 bp->b_flags |= B_ERROR; 645 bp->b_error = EIO; 646 goto done; 647 } 648 649 /* 650 * Determine the size of the transfer, and make sure it is 651 * within the boundaries of the partition. 652 */ 653 if (bp->b_blkno >= rx->ra_disk.dk_label->d_secperunit) { 654 bp->b_resid = bp->b_bcount; 655 goto done; 656 } 657 658 /* Make some statistics... /bqt */ 659 rx->ra_disk.dk_xfer++; 660 rx->ra_disk.dk_bytes += bp->b_bcount; 661 mscp_strategy(bp, rx->ra_dev.dv_parent); 662 return; 663 664 done: 665 biodone(bp); 666 } 667 668 int 669 rxread(dev, uio) 670 dev_t dev; 671 struct uio *uio; 672 { 673 674 return (physio(rxstrategy, NULL, dev, B_READ, minphys, uio)); 675 } 676 677 int 678 rxwrite(dev, uio) 679 dev_t dev; 680 struct uio *uio; 681 { 682 683 return (physio(rxstrategy, NULL, dev, B_WRITE, minphys, uio)); 684 } 685 686 /* 687 * I/O controls. 688 */ 689 int 690 rxioctl(dev, cmd, data, flag, p) 691 dev_t dev; 692 int cmd; 693 caddr_t data; 694 int flag; 695 struct proc *p; 696 { 697 int unit = DISKUNIT(dev); 698 struct disklabel *lp; 699 struct rx_softc *rx = rx_cd.cd_devs[unit]; 700 int error = 0; 701 702 lp = rx->ra_disk.dk_label; 703 704 switch (cmd) { 705 706 case DIOCGDINFO: 707 bcopy(lp, data, sizeof (struct disklabel)); 708 break; 709 710 case DIOCGPART: 711 ((struct partinfo *)data)->disklab = lp; 712 ((struct partinfo *)data)->part = 713 &lp->d_partitions[DISKPART(dev)]; 714 break; 715 716 717 case DIOCWDINFO: 718 case DIOCSDINFO: 719 case DIOCWLABEL: 720 break; 721 722 default: 723 error = ENOTTY; 724 break; 725 } 726 return (error); 727 } 728 729 int 730 rxdump(dev, blkno, va, size) 731 dev_t dev; 732 daddr_t blkno; 733 caddr_t va; 734 size_t size; 735 { 736 737 /* Not likely. */ 738 return ENXIO; 739 } 740 741 int 742 rxsize(dev) 743 dev_t dev; 744 { 745 746 return -1; 747 } 748 749 #endif /* NRX */ 750 751 void rrdgram __P((struct device *, struct mscp *, struct mscp_softc *)); 752 void rriodone __P((struct device *, struct buf *)); 753 int rronline __P((struct device *, struct mscp *)); 754 int rrgotstatus __P((struct device *, struct mscp *)); 755 void rrreplace __P((struct device *, struct mscp *)); 756 int rrioerror __P((struct device *, struct mscp *, struct buf *)); 757 void rrfillin __P((struct buf *, struct mscp *)); 758 void rrbb __P((struct device *, struct mscp *, struct buf *)); 759 760 761 struct mscp_device ra_device = { 762 rrdgram, 763 rriodone, 764 rronline, 765 rrgotstatus, 766 rrreplace, 767 rrioerror, 768 rrbb, 769 rrfillin, 770 }; 771 772 /* 773 * Handle an error datagram. 774 * This can come from an unconfigured drive as well. 775 */ 776 void 777 rrdgram(usc, mp, mi) 778 struct device *usc; 779 struct mscp *mp; 780 struct mscp_softc *mi; 781 { 782 if (mscp_decodeerror(usc == NULL?"unconf disk" : usc->dv_xname, mp, mi)) 783 return; 784 /* 785 * SDI status information bytes 10 and 11 are the microprocessor 786 * error code and front panel code respectively. These vary per 787 * drive type and are printed purely for field service information. 788 */ 789 if (mp->mscp_format == M_FM_SDI) 790 printf("\tsdi uproc error code 0x%x, front panel code 0x%x\n", 791 mp->mscp_erd.erd_sdistat[10], 792 mp->mscp_erd.erd_sdistat[11]); 793 } 794 795 void 796 rriodone(usc, bp) 797 struct device *usc; 798 struct buf *bp; 799 { 800 801 biodone(bp); 802 } 803 804 /* 805 * A drive came on line. Check its type and size. Return DONE if 806 * we think the drive is truly on line. In any case, awaken anyone 807 * sleeping on the drive on-line-ness. 808 */ 809 int 810 rronline(usc, mp) 811 struct device *usc; 812 struct mscp *mp; 813 { 814 struct rx_softc *rx = (struct rx_softc *)usc; 815 struct disklabel *dl; 816 817 wakeup((caddr_t)&usc->dv_unit); 818 if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { 819 printf("%s: attempt to bring on line failed: ", usc->dv_xname); 820 mscp_printevent(mp); 821 return (MSCP_FAILED); 822 } 823 824 rx->ra_state = DK_OPEN; 825 826 dl = rx->ra_disk.dk_label; 827 dl->d_secperunit = (daddr_t)mp->mscp_onle.onle_unitsize; 828 829 if (dl->d_secpercyl) { 830 dl->d_ncylinders = dl->d_secperunit/dl->d_secpercyl; 831 dl->d_type = DTYPE_MSCP; 832 dl->d_rpm = 3600; 833 } else { 834 dl->d_type = DTYPE_FLOPPY; 835 dl->d_rpm = 300; 836 } 837 rrmakelabel(dl, rx->ra_mediaid); 838 839 return (MSCP_DONE); 840 } 841 842 void 843 rrmakelabel(dl, type) 844 struct disklabel *dl; 845 long type; 846 { 847 int n, p = 0; 848 849 dl->d_bbsize = BBSIZE; 850 dl->d_sbsize = SBSIZE; 851 852 /* Create the disk name for disklabel. Phew... */ 853 dl->d_typename[p++] = MSCP_MID_CHAR(2, type); 854 dl->d_typename[p++] = MSCP_MID_CHAR(1, type); 855 if (MSCP_MID_ECH(0, type)) 856 dl->d_typename[p++] = MSCP_MID_CHAR(0, type); 857 n = MSCP_MID_NUM(type); 858 if (n > 99) { 859 dl->d_typename[p++] = '1'; 860 n -= 100; 861 } 862 if (n > 9) { 863 dl->d_typename[p++] = (n / 10) + '0'; 864 n %= 10; 865 } 866 dl->d_typename[p++] = n + '0'; 867 dl->d_typename[p] = 0; 868 dl->d_npartitions = MAXPARTITIONS; 869 dl->d_partitions[0].p_size = dl->d_partitions[2].p_size = 870 dl->d_secperunit; 871 dl->d_partitions[0].p_offset = dl->d_partitions[2].p_offset = 0; 872 dl->d_interleave = dl->d_headswitch = 1; 873 dl->d_magic = dl->d_magic2 = DISKMAGIC; 874 dl->d_checksum = dkcksum(dl); 875 } 876 877 /* 878 * We got some (configured) unit's status. Return DONE if it succeeded. 879 */ 880 int 881 rrgotstatus(usc, mp) 882 struct device *usc; 883 struct mscp *mp; 884 { 885 if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { 886 printf("%s: attempt to get status failed: ", usc->dv_xname); 887 mscp_printevent(mp); 888 return (MSCP_FAILED); 889 } 890 /* record for (future) bad block forwarding and whatever else */ 891 #ifdef notyet 892 uda_rasave(ui->ui_unit, mp, 1); 893 #endif 894 return (MSCP_DONE); 895 } 896 897 /* 898 * A replace operation finished. 899 */ 900 /*ARGSUSED*/ 901 void 902 rrreplace(usc, mp) 903 struct device *usc; 904 struct mscp *mp; 905 { 906 907 panic("udareplace"); 908 } 909 910 /* 911 * A transfer failed. We get a chance to fix or restart it. 912 * Need to write the bad block forwaring code first.... 913 */ 914 /*ARGSUSED*/ 915 int 916 rrioerror(usc, mp, bp) 917 struct device *usc; 918 struct mscp *mp; 919 struct buf *bp; 920 { 921 struct ra_softc *ra = (void *)usc; 922 int code = mp->mscp_event; 923 924 switch (code & M_ST_MASK) { 925 /* The unit has fallen offline. Try to figure out why. */ 926 case M_ST_OFFLINE: 927 bp->b_flags |= B_ERROR; 928 bp->b_error = EIO; 929 ra->ra_state = DK_CLOSED; 930 if (code & M_OFFLINE_UNMOUNTED) 931 printf("%s: not mounted/spun down\n", usc->dv_xname); 932 if (code & M_OFFLINE_DUPLICATE) 933 printf("%s: duplicate unit number!!!\n", usc->dv_xname); 934 return MSCP_DONE; 935 936 case M_ST_AVAILABLE: 937 ra->ra_state = DK_CLOSED; /* Force another online */ 938 return MSCP_DONE; 939 940 default: 941 printf("%s:", usc->dv_xname); 942 break; 943 } 944 return (MSCP_FAILED); 945 } 946 947 /* 948 * Fill in disk addresses in a mscp packet waiting for transfer. 949 */ 950 void 951 rrfillin(bp, mp) 952 struct buf *bp; 953 struct mscp *mp; 954 { 955 struct rx_softc *rx = 0; /* Wall */ 956 struct disklabel *lp; 957 int unit = DISKUNIT(bp->b_dev); 958 int part = DISKPART(bp->b_dev); 959 960 #if NRA 961 if (major(bp->b_dev) == RAMAJOR) 962 rx = ra_cd.cd_devs[unit]; 963 #endif 964 #if NRX 965 if (major(bp->b_dev) != RAMAJOR) 966 rx = rx_cd.cd_devs[unit]; 967 #endif 968 lp = rx->ra_disk.dk_label; 969 970 mp->mscp_seq.seq_lbn = lp->d_partitions[part].p_offset + bp->b_blkno; 971 mp->mscp_unit = rx->ra_hwunit; 972 mp->mscp_seq.seq_bytecount = bp->b_bcount; 973 } 974 975 /* 976 * A bad block related operation finished. 977 */ 978 /*ARGSUSED*/ 979 void 980 rrbb(usc, mp, bp) 981 struct device *usc; 982 struct mscp *mp; 983 struct buf *bp; 984 { 985 986 panic("udabb"); 987 } 988