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