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