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