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