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