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