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