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