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