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