Home | History | Annotate | Line # | Download | only in i2o
ld_iop.c revision 1.3.2.2
      1  1.3.2.2  bouyer /*	$NetBSD: ld_iop.c,v 1.3.2.2 2000/12/08 09:12:19 bouyer Exp $	*/
      2  1.3.2.2  bouyer 
      3  1.3.2.2  bouyer /*-
      4  1.3.2.2  bouyer  * Copyright (c) 2000 The NetBSD Foundation, Inc.
      5  1.3.2.2  bouyer  * All rights reserved.
      6  1.3.2.2  bouyer  *
      7  1.3.2.2  bouyer  * This code is derived from software contributed to The NetBSD Foundation
      8  1.3.2.2  bouyer  * by Andrew Doran.
      9  1.3.2.2  bouyer  *
     10  1.3.2.2  bouyer  * Redistribution and use in source and binary forms, with or without
     11  1.3.2.2  bouyer  * modification, are permitted provided that the following conditions
     12  1.3.2.2  bouyer  * are met:
     13  1.3.2.2  bouyer  * 1. Redistributions of source code must retain the above copyright
     14  1.3.2.2  bouyer  *    notice, this list of conditions and the following disclaimer.
     15  1.3.2.2  bouyer  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.3.2.2  bouyer  *    notice, this list of conditions and the following disclaimer in the
     17  1.3.2.2  bouyer  *    documentation and/or other materials provided with the distribution.
     18  1.3.2.2  bouyer  * 3. All advertising materials mentioning features or use of this software
     19  1.3.2.2  bouyer  *    must display the following acknowledgement:
     20  1.3.2.2  bouyer  *        This product includes software developed by the NetBSD
     21  1.3.2.2  bouyer  *        Foundation, Inc. and its contributors.
     22  1.3.2.2  bouyer  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  1.3.2.2  bouyer  *    contributors may be used to endorse or promote products derived
     24  1.3.2.2  bouyer  *    from this software without specific prior written permission.
     25  1.3.2.2  bouyer  *
     26  1.3.2.2  bouyer  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  1.3.2.2  bouyer  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  1.3.2.2  bouyer  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  1.3.2.2  bouyer  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  1.3.2.2  bouyer  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  1.3.2.2  bouyer  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  1.3.2.2  bouyer  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  1.3.2.2  bouyer  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  1.3.2.2  bouyer  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  1.3.2.2  bouyer  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  1.3.2.2  bouyer  * POSSIBILITY OF SUCH DAMAGE.
     37  1.3.2.2  bouyer  */
     38  1.3.2.2  bouyer 
     39  1.3.2.2  bouyer /*
     40  1.3.2.2  bouyer  * I2O front-end for ld(4) driver, supporting random block storage class
     41  1.3.2.2  bouyer  * devices.  Currently, this doesn't handle anything more complex than
     42  1.3.2.2  bouyer  * fixed direct-access devices.
     43  1.3.2.2  bouyer  */
     44  1.3.2.2  bouyer 
     45  1.3.2.2  bouyer #include "opt_i2o.h"
     46  1.3.2.2  bouyer #include "rnd.h"
     47  1.3.2.2  bouyer 
     48  1.3.2.2  bouyer #include <sys/param.h>
     49  1.3.2.2  bouyer #include <sys/systm.h>
     50  1.3.2.2  bouyer #include <sys/kernel.h>
     51  1.3.2.2  bouyer #include <sys/device.h>
     52  1.3.2.2  bouyer #include <sys/buf.h>
     53  1.3.2.2  bouyer #include <sys/endian.h>
     54  1.3.2.2  bouyer #include <sys/dkio.h>
     55  1.3.2.2  bouyer #include <sys/disk.h>
     56  1.3.2.2  bouyer #include <sys/proc.h>
     57  1.3.2.2  bouyer #if NRND > 0
     58  1.3.2.2  bouyer #include <sys/rnd.h>
     59  1.3.2.2  bouyer #endif
     60  1.3.2.2  bouyer 
     61  1.3.2.2  bouyer #include <machine/bus.h>
     62  1.3.2.2  bouyer 
     63  1.3.2.2  bouyer #include <dev/ldvar.h>
     64  1.3.2.2  bouyer 
     65  1.3.2.2  bouyer #include <dev/i2o/i2o.h>
     66  1.3.2.2  bouyer #include <dev/i2o/iopvar.h>
     67  1.3.2.2  bouyer 
     68  1.3.2.2  bouyer #define	LD_IOP_MAXQUEUECNT	64		/* XXX */
     69  1.3.2.2  bouyer #define	LD_IOP_TIMEOUT		10*1000*1000
     70  1.3.2.2  bouyer 
     71  1.3.2.2  bouyer struct ld_iop_softc {
     72  1.3.2.2  bouyer 	struct	ld_softc sc_ld;
     73  1.3.2.2  bouyer 	struct	iop_initiator sc_ii;
     74  1.3.2.2  bouyer 	struct	iop_initiator sc_eventii;
     75  1.3.2.2  bouyer 	int	sc_claimed;
     76  1.3.2.2  bouyer 	u_int	sc_tid;
     77  1.3.2.2  bouyer };
     78  1.3.2.2  bouyer 
     79  1.3.2.2  bouyer static void	ld_iop_attach(struct device *, struct device *, void *);
     80  1.3.2.2  bouyer static int	ld_iop_detach(struct device *, int);
     81  1.3.2.2  bouyer static int	ld_iop_dump(struct ld_softc *, void *, int, int);
     82  1.3.2.2  bouyer static int	ld_iop_flush(struct ld_softc *);
     83  1.3.2.2  bouyer static void	ld_iop_intr(struct device *, struct iop_msg *, void *);
     84  1.3.2.2  bouyer static void	ld_iop_intr_event(struct device *, struct iop_msg *, void *);
     85  1.3.2.2  bouyer static int	ld_iop_start(struct ld_softc *, struct buf *);
     86  1.3.2.2  bouyer static int	ld_iop_match(struct device *, struct cfdata *, void *);
     87  1.3.2.2  bouyer 
     88  1.3.2.2  bouyer struct cfattach ld_iop_ca = {
     89  1.3.2.2  bouyer 	sizeof(struct ld_iop_softc),
     90  1.3.2.2  bouyer 	ld_iop_match,
     91  1.3.2.2  bouyer 	ld_iop_attach,
     92  1.3.2.2  bouyer 	ld_iop_detach
     93  1.3.2.2  bouyer };
     94  1.3.2.2  bouyer 
     95  1.3.2.2  bouyer #ifdef I2OVERBOSE
     96  1.3.2.2  bouyer static const char *ld_iop_errors[] = {
     97  1.3.2.2  bouyer 	"success",
     98  1.3.2.2  bouyer 	"media error",
     99  1.3.2.2  bouyer 	"failure communicating with device",
    100  1.3.2.2  bouyer 	"device failure",
    101  1.3.2.2  bouyer 	"device is not ready",
    102  1.3.2.2  bouyer 	"media not present",
    103  1.3.2.2  bouyer 	"media locked by another user",
    104  1.3.2.2  bouyer 	"media failure",
    105  1.3.2.2  bouyer 	"failure communicating to device",
    106  1.3.2.2  bouyer 	"device bus failure",
    107  1.3.2.2  bouyer 	"device locked by another user",
    108  1.3.2.2  bouyer 	"device write protected",
    109  1.3.2.2  bouyer 	"device reset",
    110  1.3.2.2  bouyer 	"volume has changed, waiting for acknowledgement",
    111  1.3.2.2  bouyer };
    112  1.3.2.2  bouyer #endif
    113  1.3.2.2  bouyer 
    114  1.3.2.2  bouyer static int
    115  1.3.2.2  bouyer ld_iop_match(struct device *parent, struct cfdata *match, void *aux)
    116  1.3.2.2  bouyer {
    117  1.3.2.2  bouyer 	struct iop_attach_args *ia;
    118  1.3.2.2  bouyer 
    119  1.3.2.2  bouyer 	ia = aux;
    120  1.3.2.2  bouyer 
    121  1.3.2.2  bouyer 	return (ia->ia_class == I2O_CLASS_RANDOM_BLOCK_STORAGE);
    122  1.3.2.2  bouyer }
    123  1.3.2.2  bouyer 
    124  1.3.2.2  bouyer static void
    125  1.3.2.2  bouyer ld_iop_attach(struct device *parent, struct device *self, void *aux)
    126  1.3.2.2  bouyer {
    127  1.3.2.2  bouyer 	struct iop_attach_args *ia;
    128  1.3.2.2  bouyer 	struct ld_softc *ld;
    129  1.3.2.2  bouyer 	struct ld_iop_softc *sc;
    130  1.3.2.2  bouyer 	struct iop_softc *iop;
    131  1.3.2.2  bouyer 	int rv, evreg, enable;
    132  1.3.2.2  bouyer 	char ident[64 + 1], *typestr, *fixedstr;
    133  1.3.2.2  bouyer 	u_int cachesz;
    134  1.3.2.2  bouyer 	struct {
    135  1.3.2.2  bouyer 		struct	i2o_param_op_results pr;
    136  1.3.2.2  bouyer 		struct	i2o_param_read_results prr;
    137  1.3.2.2  bouyer 		union {
    138  1.3.2.2  bouyer 			struct	i2o_param_rbs_cache_control cc;
    139  1.3.2.2  bouyer 			struct	i2o_param_rbs_device_info bdi;
    140  1.3.2.2  bouyer 			struct	i2o_param_device_identity di;
    141  1.3.2.2  bouyer 			struct	i2o_param_rbs_operation op;
    142  1.3.2.2  bouyer 		} p;
    143  1.3.2.2  bouyer 	} param;
    144  1.3.2.2  bouyer 
    145  1.3.2.2  bouyer 	sc = (struct ld_iop_softc *)self;
    146  1.3.2.2  bouyer 	ld = &sc->sc_ld;
    147  1.3.2.2  bouyer 	iop = (struct iop_softc *)parent;
    148  1.3.2.2  bouyer 	ia = (struct iop_attach_args *)aux;
    149  1.3.2.2  bouyer 	sc->sc_tid = ia->ia_tid;
    150  1.3.2.2  bouyer 	evreg = 0;
    151  1.3.2.2  bouyer 
    152  1.3.2.2  bouyer 	/* Register us as an initiator. */
    153  1.3.2.2  bouyer 	sc->sc_ii.ii_dv = self;
    154  1.3.2.2  bouyer 	sc->sc_ii.ii_intr = ld_iop_intr;
    155  1.3.2.2  bouyer 	sc->sc_ii.ii_flags = 0;
    156  1.3.2.2  bouyer 	sc->sc_ii.ii_tid = ia->ia_tid;
    157  1.3.2.2  bouyer 	if (iop_initiator_register(iop, &sc->sc_ii) != 0) {
    158  1.3.2.2  bouyer 		printf("%s: unable to register initiator\n", self->dv_xname);
    159  1.3.2.2  bouyer 		return;
    160  1.3.2.2  bouyer 	}
    161  1.3.2.2  bouyer 
    162  1.3.2.2  bouyer 	/* Register another initiator to handle events from the device. */
    163  1.3.2.2  bouyer 	sc->sc_eventii.ii_dv = self;
    164  1.3.2.2  bouyer 	sc->sc_eventii.ii_intr = ld_iop_intr_event;
    165  1.3.2.2  bouyer 	sc->sc_eventii.ii_flags = II_DISCARD | II_UTILITY;
    166  1.3.2.2  bouyer 	sc->sc_eventii.ii_tid = ia->ia_tid;
    167  1.3.2.2  bouyer 	if (iop_initiator_register(iop, &sc->sc_eventii) != 0) {
    168  1.3.2.2  bouyer 		printf("%s: unable to register initiator", self->dv_xname);
    169  1.3.2.2  bouyer 		goto bad;
    170  1.3.2.2  bouyer 	}
    171  1.3.2.2  bouyer 	if (iop_util_eventreg(iop, &sc->sc_eventii, 0xffffffff)) {
    172  1.3.2.2  bouyer 		printf("%s: unable to register for events", self->dv_xname);
    173  1.3.2.2  bouyer 		goto bad;
    174  1.3.2.2  bouyer 	}
    175  1.3.2.2  bouyer 	evreg = 1;
    176  1.3.2.2  bouyer 
    177  1.3.2.2  bouyer 	ld->sc_maxxfer = IOP_MAX_XFER;
    178  1.3.2.2  bouyer 	ld->sc_maxqueuecnt = LD_IOP_MAXQUEUECNT;
    179  1.3.2.2  bouyer 	ld->sc_dump = ld_iop_dump;
    180  1.3.2.2  bouyer 	ld->sc_flush = ld_iop_flush;
    181  1.3.2.2  bouyer 	ld->sc_start = ld_iop_start;
    182  1.3.2.2  bouyer 
    183  1.3.2.2  bouyer 	/* Say what the device is. */
    184  1.3.2.2  bouyer 	printf(": ");
    185  1.3.2.2  bouyer 	if (iop_param_op(iop, ia->ia_tid, 0, I2O_PARAM_DEVICE_IDENTITY, &param,
    186  1.3.2.2  bouyer 	    sizeof(param)) == 0) {
    187  1.3.2.2  bouyer 		iop_strvis(iop, param.p.di.vendorinfo,
    188  1.3.2.2  bouyer 		    sizeof(param.p.di.vendorinfo), ident, sizeof(ident));
    189  1.3.2.2  bouyer 		printf("<%s, ", ident);
    190  1.3.2.2  bouyer 		iop_strvis(iop, param.p.di.productinfo,
    191  1.3.2.2  bouyer 		    sizeof(param.p.di.productinfo), ident, sizeof(ident));
    192  1.3.2.2  bouyer 		printf("%s, ", ident);
    193  1.3.2.2  bouyer 		iop_strvis(iop, param.p.di.revlevel,
    194  1.3.2.2  bouyer 		    sizeof(param.p.di.revlevel), ident, sizeof(ident));
    195  1.3.2.2  bouyer 		printf("%s> ", ident);
    196  1.3.2.2  bouyer 	}
    197  1.3.2.2  bouyer 
    198  1.3.2.2  bouyer 	/*
    199  1.3.2.2  bouyer 	 * Claim the device so that we don't get any nasty surprises.  Allow
    200  1.3.2.2  bouyer 	 * failure.
    201  1.3.2.2  bouyer 	 */
    202  1.3.2.2  bouyer 	sc->sc_claimed = !iop_util_claim(iop, &sc->sc_ii, 0,
    203  1.3.2.2  bouyer 	    I2O_UTIL_CLAIM_CAPACITY_SENSITIVE |
    204  1.3.2.2  bouyer 	    I2O_UTIL_CLAIM_NO_PEER_SERVICE |
    205  1.3.2.2  bouyer 	    I2O_UTIL_CLAIM_NO_MANAGEMENT_SERVICE |
    206  1.3.2.2  bouyer 	    I2O_UTIL_CLAIM_PRIMARY_USER);
    207  1.3.2.2  bouyer 
    208  1.3.2.2  bouyer 	rv = iop_param_op(iop, ia->ia_tid, 0, I2O_PARAM_RBS_DEVICE_INFO,
    209  1.3.2.2  bouyer 	    &param, sizeof(param));
    210  1.3.2.2  bouyer 	if (rv != 0) {
    211  1.3.2.2  bouyer 		printf("%s: unable to get parameters (0x%04x; %d)\n",
    212  1.3.2.2  bouyer 		   ld->sc_dv.dv_xname, I2O_PARAM_RBS_DEVICE_INFO, rv);
    213  1.3.2.2  bouyer 		goto bad;
    214  1.3.2.2  bouyer 	}
    215  1.3.2.2  bouyer 
    216  1.3.2.2  bouyer 	ld->sc_secsize = le32toh(param.p.bdi.blocksize);
    217  1.3.2.2  bouyer 	ld->sc_secperunit = (int)
    218  1.3.2.2  bouyer 	    (le64toh(param.p.bdi.capacity) / ld->sc_secsize);
    219  1.3.2.2  bouyer 
    220  1.3.2.2  bouyer 	/* Build synthetic geometry. */
    221  1.3.2.2  bouyer 	if (ld->sc_secperunit <= 528 * 2048)		/* 528MB */
    222  1.3.2.2  bouyer 		ld->sc_nheads = 16;
    223  1.3.2.2  bouyer 	else if (ld->sc_secperunit <= 1024 * 2048)	/* 1GB */
    224  1.3.2.2  bouyer 		ld->sc_nheads = 32;
    225  1.3.2.2  bouyer 	else if (ld->sc_secperunit <= 21504 * 2048)	/* 21GB */
    226  1.3.2.2  bouyer 		ld->sc_nheads = 64;
    227  1.3.2.2  bouyer 	else if (ld->sc_secperunit <= 43008 * 2048)	/* 42GB */
    228  1.3.2.2  bouyer 		ld->sc_nheads = 128;
    229  1.3.2.2  bouyer 	else
    230  1.3.2.2  bouyer 		ld->sc_nheads = 255;
    231  1.3.2.2  bouyer 
    232  1.3.2.2  bouyer 	ld->sc_nsectors = 63;
    233  1.3.2.2  bouyer 	ld->sc_ncylinders = ld->sc_secperunit /
    234  1.3.2.2  bouyer 	    (ld->sc_nheads * ld->sc_nsectors);
    235  1.3.2.2  bouyer 
    236  1.3.2.2  bouyer 	switch (param.p.bdi.type) {
    237  1.3.2.2  bouyer 	case I2O_RBS_TYPE_DIRECT:
    238  1.3.2.2  bouyer 		typestr = "direct access";
    239  1.3.2.2  bouyer 		enable = 1;
    240  1.3.2.2  bouyer 		break;
    241  1.3.2.2  bouyer 	case I2O_RBS_TYPE_WORM:
    242  1.3.2.2  bouyer 		typestr = "WORM";
    243  1.3.2.2  bouyer 		enable = 0;
    244  1.3.2.2  bouyer 		break;
    245  1.3.2.2  bouyer 	case I2O_RBS_TYPE_CDROM:
    246  1.3.2.2  bouyer 		typestr = "cdrom";
    247  1.3.2.2  bouyer 		enable = 0;
    248  1.3.2.2  bouyer 		break;
    249  1.3.2.2  bouyer 	case I2O_RBS_TYPE_OPTICAL:
    250  1.3.2.2  bouyer 		typestr = "optical";
    251  1.3.2.2  bouyer 		enable = 0;
    252  1.3.2.2  bouyer 		break;
    253  1.3.2.2  bouyer 	default:
    254  1.3.2.2  bouyer 		typestr = "unknown";
    255  1.3.2.2  bouyer 		enable = 0;
    256  1.3.2.2  bouyer 		break;
    257  1.3.2.2  bouyer 	}
    258  1.3.2.2  bouyer 
    259  1.3.2.2  bouyer 	if ((le32toh(param.p.bdi.capabilities) & I2O_RBS_CAP_REMOVEABLE_MEDIA)
    260  1.3.2.2  bouyer 	    != 0) {
    261  1.3.2.2  bouyer 		/* ld->sc_flags = LDF_REMOVEABLE; */
    262  1.3.2.2  bouyer 		fixedstr = "removeable";
    263  1.3.2.2  bouyer 		enable = 0;
    264  1.3.2.2  bouyer 	} else
    265  1.3.2.2  bouyer 		fixedstr = "fixed";
    266  1.3.2.2  bouyer 
    267  1.3.2.2  bouyer 	printf("%s, %s", typestr, fixedstr);
    268  1.3.2.2  bouyer 
    269  1.3.2.2  bouyer 	/*
    270  1.3.2.2  bouyer 	 * Determine if the device has an private cache.  If so, print the
    271  1.3.2.2  bouyer 	 * cache size.  Even if the device doesn't appear to have a cache,
    272  1.3.2.2  bouyer 	 * we perform a flush at shutdown, as it is still valid to do so.
    273  1.3.2.2  bouyer 	 */
    274  1.3.2.2  bouyer 	rv = iop_param_op(iop, ia->ia_tid, 0, I2O_PARAM_RBS_CACHE_CONTROL,
    275  1.3.2.2  bouyer 	    &param, sizeof(param));
    276  1.3.2.2  bouyer 	if (rv != 0) {
    277  1.3.2.2  bouyer 		printf("%s: unable to get parameters (0x%04x; %d)\n",
    278  1.3.2.2  bouyer 		   ld->sc_dv.dv_xname, I2O_PARAM_RBS_CACHE_CONTROL, rv);
    279  1.3.2.2  bouyer 		goto bad;
    280  1.3.2.2  bouyer 	}
    281  1.3.2.2  bouyer 
    282  1.3.2.2  bouyer 	if ((cachesz = le32toh(param.p.cc.totalcachesize)) != 0)
    283  1.3.2.2  bouyer 		printf(", %dkB cache", cachesz >> 10);
    284  1.3.2.2  bouyer 
    285  1.3.2.2  bouyer 	printf("\n");
    286  1.3.2.2  bouyer 
    287  1.3.2.2  bouyer 	/*
    288  1.3.2.2  bouyer 	 * Configure the DDM's timeout functions to time out all commands
    289  1.3.2.2  bouyer 	 * after 10 seconds.
    290  1.3.2.2  bouyer 	 */
    291  1.3.2.2  bouyer 	rv = iop_param_op(iop, ia->ia_tid, 0, I2O_PARAM_RBS_OPERATION,
    292  1.3.2.2  bouyer 	    &param, sizeof(param));
    293  1.3.2.2  bouyer 	if (rv != 0) {
    294  1.3.2.2  bouyer 		printf("%s: unable to get parameters (0x%04x; %d)\n",
    295  1.3.2.2  bouyer 		   ld->sc_dv.dv_xname, I2O_PARAM_RBS_OPERATION, rv);
    296  1.3.2.2  bouyer 		goto bad;
    297  1.3.2.2  bouyer 	}
    298  1.3.2.2  bouyer 
    299  1.3.2.2  bouyer 	param.p.op.timeoutbase = htole32(LD_IOP_TIMEOUT);
    300  1.3.2.2  bouyer 	param.p.op.rwvtimeoutbase = htole32(LD_IOP_TIMEOUT);
    301  1.3.2.2  bouyer 	param.p.op.rwvtimeout = 0;
    302  1.3.2.2  bouyer 
    303  1.3.2.2  bouyer 	rv = iop_param_op(iop, ia->ia_tid, 1, I2O_PARAM_RBS_OPERATION,
    304  1.3.2.2  bouyer 	    &param, sizeof(param));
    305  1.3.2.2  bouyer 	if (rv != 0) {
    306  1.3.2.2  bouyer 		printf("%s: unable to set parameters (0x%04x; %d)\n",
    307  1.3.2.2  bouyer 		   ld->sc_dv.dv_xname, I2O_PARAM_RBS_OPERATION, rv);
    308  1.3.2.2  bouyer 		goto bad;
    309  1.3.2.2  bouyer 	}
    310  1.3.2.2  bouyer 
    311  1.3.2.2  bouyer 	if (enable)
    312  1.3.2.2  bouyer 		ld->sc_flags |= LDF_ENABLED;
    313  1.3.2.2  bouyer 	else
    314  1.3.2.2  bouyer 		printf("%s: device not yet supported\n", self->dv_xname);
    315  1.3.2.2  bouyer 
    316  1.3.2.2  bouyer 	ldattach(ld);
    317  1.3.2.2  bouyer 	return;
    318  1.3.2.2  bouyer 
    319  1.3.2.2  bouyer bad:
    320  1.3.2.2  bouyer 	if (sc->sc_claimed)
    321  1.3.2.2  bouyer 		iop_util_claim(iop, &sc->sc_ii, 1,
    322  1.3.2.2  bouyer 		    I2O_UTIL_CLAIM_PRIMARY_USER);
    323  1.3.2.2  bouyer 	if (evreg)
    324  1.3.2.2  bouyer 		iop_util_eventreg(iop, &sc->sc_eventii, 0);
    325  1.3.2.2  bouyer 	if (sc->sc_eventii.ii_intr != NULL)
    326  1.3.2.2  bouyer 		iop_initiator_unregister(iop, &sc->sc_eventii);
    327  1.3.2.2  bouyer 	iop_initiator_unregister(iop, &sc->sc_ii);
    328  1.3.2.2  bouyer }
    329  1.3.2.2  bouyer 
    330  1.3.2.2  bouyer static int
    331  1.3.2.2  bouyer ld_iop_detach(struct device *self, int flags)
    332  1.3.2.2  bouyer {
    333  1.3.2.2  bouyer 	struct ld_iop_softc *sc;
    334  1.3.2.2  bouyer 	struct iop_softc *iop;
    335  1.3.2.2  bouyer 	int s, rv;
    336  1.3.2.2  bouyer 
    337  1.3.2.2  bouyer 	sc = (struct ld_iop_softc *)self;
    338  1.3.2.2  bouyer 
    339  1.3.2.2  bouyer 	/* XXX */
    340  1.3.2.2  bouyer 	if ((flags & DETACH_FORCE) == 0 && sc->sc_ld.sc_dk.dk_openmask != 0)
    341  1.3.2.2  bouyer 		return (EBUSY);
    342  1.3.2.2  bouyer 	s = splbio();
    343  1.3.2.2  bouyer 	sc->sc_ld.sc_flags |= LDF_DRAIN;
    344  1.3.2.2  bouyer 	splx(s);
    345  1.3.2.2  bouyer 
    346  1.3.2.2  bouyer 	iop = (struct iop_softc *)self->dv_parent;
    347  1.3.2.2  bouyer 
    348  1.3.2.2  bouyer 	/*
    349  1.3.2.2  bouyer 	 * Abort any requests queued with the IOP, but allow requests that
    350  1.3.2.2  bouyer 	 * are already in progress to complete.
    351  1.3.2.2  bouyer 	 */
    352  1.3.2.2  bouyer 	if ((sc->sc_ld.sc_flags & LDF_ENABLED) != 0)
    353  1.3.2.2  bouyer 		iop_util_abort(iop, &sc->sc_ii, 0, 0,
    354  1.3.2.2  bouyer 		    I2O_UTIL_ABORT_WILD | I2O_UTIL_ABORT_CLEAN);
    355  1.3.2.2  bouyer 
    356  1.3.2.2  bouyer 	lddetach(&sc->sc_ld);
    357  1.3.2.2  bouyer 
    358  1.3.2.2  bouyer 	/* Un-claim the target, and un-register us as an initiator. */
    359  1.3.2.2  bouyer 	if ((sc->sc_ld.sc_flags & LDF_ENABLED) != 0) {
    360  1.3.2.2  bouyer 		if (sc->sc_claimed) {
    361  1.3.2.2  bouyer 			rv = iop_util_claim(iop, &sc->sc_ii, 1,
    362  1.3.2.2  bouyer 			    I2O_UTIL_CLAIM_PRIMARY_USER);
    363  1.3.2.2  bouyer 			if (rv != 0)
    364  1.3.2.2  bouyer 				return (rv);
    365  1.3.2.2  bouyer 		}
    366  1.3.2.2  bouyer 		iop_util_eventreg(iop, &sc->sc_eventii, 0);
    367  1.3.2.2  bouyer 		iop_initiator_unregister(iop, &sc->sc_eventii);
    368  1.3.2.2  bouyer 		iop_initiator_unregister(iop, &sc->sc_ii);
    369  1.3.2.2  bouyer 	}
    370  1.3.2.2  bouyer 
    371  1.3.2.2  bouyer 	return (0);
    372  1.3.2.2  bouyer }
    373  1.3.2.2  bouyer 
    374  1.3.2.2  bouyer static int
    375  1.3.2.2  bouyer ld_iop_start(struct ld_softc *ld, struct buf *bp)
    376  1.3.2.2  bouyer {
    377  1.3.2.2  bouyer 	struct iop_msg *im;
    378  1.3.2.2  bouyer 	struct iop_softc *iop;
    379  1.3.2.2  bouyer 	struct ld_iop_softc *sc;
    380  1.3.2.2  bouyer 	struct i2o_rbs_block_read *mb;
    381  1.3.2.2  bouyer 	int rv, flags, write;
    382  1.3.2.2  bouyer 	u_int64_t ba;
    383  1.3.2.2  bouyer 
    384  1.3.2.2  bouyer 	sc = (struct ld_iop_softc *)ld;
    385  1.3.2.2  bouyer 	iop = (struct iop_softc *)ld->sc_dv.dv_parent;
    386  1.3.2.2  bouyer 
    387  1.3.2.2  bouyer 	im = NULL;
    388  1.3.2.2  bouyer 	if ((rv = iop_msg_alloc(iop, &sc->sc_ii, &im, IM_NOWAIT)) != 0)
    389  1.3.2.2  bouyer 		goto bad;
    390  1.3.2.2  bouyer 	im->im_dvcontext = bp;
    391  1.3.2.2  bouyer 
    392  1.3.2.2  bouyer 	write = ((bp->b_flags & B_READ) == 0);
    393  1.3.2.2  bouyer 	ba = (u_int64_t)bp->b_rawblkno * ld->sc_secsize;
    394  1.3.2.2  bouyer 
    395  1.3.2.2  bouyer 	/*
    396  1.3.2.2  bouyer 	 * Write through the cache when performing synchronous writes.  When
    397  1.3.2.2  bouyer 	 * performing a read, we don't request that the DDM cache the data,
    398  1.3.2.2  bouyer 	 * as there's little advantage to it.
    399  1.3.2.2  bouyer 	 */
    400  1.3.2.2  bouyer 	if (write) {
    401  1.3.2.2  bouyer 		if ((bp->b_flags & B_ASYNC) == 0)
    402  1.3.2.2  bouyer 			flags = I2O_RBS_BLOCK_WRITE_CACHE_WT;
    403  1.3.2.2  bouyer 		else
    404  1.3.2.2  bouyer 			flags = I2O_RBS_BLOCK_WRITE_CACHE_WB;
    405  1.3.2.2  bouyer 	} else
    406  1.3.2.2  bouyer 		flags = 0;
    407  1.3.2.2  bouyer 
    408  1.3.2.2  bouyer 	/*
    409  1.3.2.2  bouyer 	 * Fill the message frame.  We can use the block_read structure for
    410  1.3.2.2  bouyer 	 * both reads and writes, as it's almost identical to the
    411  1.3.2.2  bouyer 	 * block_write structure.
    412  1.3.2.2  bouyer 	 */
    413  1.3.2.2  bouyer 	mb = (struct i2o_rbs_block_read *)im->im_msg;
    414  1.3.2.2  bouyer 	mb->msgflags = I2O_MSGFLAGS(i2o_rbs_block_read);
    415  1.3.2.2  bouyer 	mb->msgfunc = I2O_MSGFUNC(sc->sc_tid,
    416  1.3.2.2  bouyer 	    write ? I2O_RBS_BLOCK_WRITE : I2O_RBS_BLOCK_READ);
    417  1.3.2.2  bouyer 	mb->msgictx = sc->sc_ii.ii_ictx;
    418  1.3.2.2  bouyer 	mb->msgtctx = im->im_tctx;
    419  1.3.2.2  bouyer 	mb->flags = flags | (1 << 16);		/* flags & time multiplier */
    420  1.3.2.2  bouyer 	mb->datasize = bp->b_bcount;
    421  1.3.2.2  bouyer 	mb->lowoffset = (u_int32_t)ba;
    422  1.3.2.2  bouyer 	mb->highoffset = (u_int32_t)(ba >> 32);
    423  1.3.2.2  bouyer 
    424  1.3.2.2  bouyer 	/* Map the data transfer. */
    425  1.3.2.2  bouyer 	if ((rv = iop_msg_map(iop, im, bp->b_data, bp->b_bcount, write)) != 0)
    426  1.3.2.2  bouyer 		goto bad;
    427  1.3.2.2  bouyer 
    428  1.3.2.2  bouyer 	/* Enqueue the command. */
    429  1.3.2.2  bouyer 	iop_msg_enqueue(iop, im, 0);
    430  1.3.2.2  bouyer 	return (0);
    431  1.3.2.2  bouyer 
    432  1.3.2.2  bouyer bad:
    433  1.3.2.2  bouyer 	if (im != NULL)
    434  1.3.2.2  bouyer 		iop_msg_free(iop, &sc->sc_ii, im);
    435  1.3.2.2  bouyer 	return (rv);
    436  1.3.2.2  bouyer }
    437  1.3.2.2  bouyer 
    438  1.3.2.2  bouyer static int
    439  1.3.2.2  bouyer ld_iop_dump(struct ld_softc *ld, void *data, int blkno, int blkcnt)
    440  1.3.2.2  bouyer {
    441  1.3.2.2  bouyer 	struct iop_msg *im;
    442  1.3.2.2  bouyer 	struct iop_softc *iop;
    443  1.3.2.2  bouyer 	struct ld_iop_softc *sc;
    444  1.3.2.2  bouyer 	struct i2o_rbs_block_write *mb;
    445  1.3.2.2  bouyer 	int rv, bcount;
    446  1.3.2.2  bouyer 	u_int64_t ba;
    447  1.3.2.2  bouyer 
    448  1.3.2.2  bouyer 	sc = (struct ld_iop_softc *)ld;
    449  1.3.2.2  bouyer 	iop = (struct iop_softc *)ld->sc_dv.dv_parent;
    450  1.3.2.2  bouyer 	bcount = blkcnt * ld->sc_secsize;
    451  1.3.2.2  bouyer 	ba = (u_int64_t)blkno * ld->sc_secsize;
    452  1.3.2.2  bouyer 
    453  1.3.2.2  bouyer 	rv = iop_msg_alloc(iop, &sc->sc_ii, &im, IM_NOWAIT | IM_NOINTR);
    454  1.3.2.2  bouyer 	if (rv != 0)
    455  1.3.2.2  bouyer 		return (rv);
    456  1.3.2.2  bouyer 
    457  1.3.2.2  bouyer 	mb = (struct i2o_rbs_block_write *)im->im_msg;
    458  1.3.2.2  bouyer 	mb->msgflags = I2O_MSGFLAGS(i2o_rbs_block_write);
    459  1.3.2.2  bouyer 	mb->msgfunc = I2O_MSGFUNC(sc->sc_tid, I2O_RBS_BLOCK_WRITE);
    460  1.3.2.2  bouyer 	mb->msgictx = sc->sc_ii.ii_ictx;
    461  1.3.2.2  bouyer 	mb->msgtctx = im->im_tctx;
    462  1.3.2.2  bouyer 	mb->flags = I2O_RBS_BLOCK_WRITE_CACHE_WT | (1 << 16);
    463  1.3.2.2  bouyer 	mb->datasize = bcount;
    464  1.3.2.2  bouyer 	mb->lowoffset = (u_int32_t)ba;
    465  1.3.2.2  bouyer 	mb->highoffset = (u_int32_t)(ba >> 32);
    466  1.3.2.2  bouyer 
    467  1.3.2.2  bouyer 	if ((rv = iop_msg_map(iop, im, data, bcount, 1)) != 0) {
    468  1.3.2.2  bouyer 		iop_msg_free(iop, &sc->sc_ii, im);
    469  1.3.2.2  bouyer 		return (rv);
    470  1.3.2.2  bouyer 	}
    471  1.3.2.2  bouyer 
    472  1.3.2.2  bouyer 	rv = (iop_msg_send(iop, im, 5000) != 0 ? EIO : 0);
    473  1.3.2.2  bouyer 	iop_msg_unmap(iop, im);
    474  1.3.2.2  bouyer 	iop_msg_free(iop, &sc->sc_ii, im);
    475  1.3.2.2  bouyer  	return (rv);
    476  1.3.2.2  bouyer }
    477  1.3.2.2  bouyer 
    478  1.3.2.2  bouyer static int
    479  1.3.2.2  bouyer ld_iop_flush(struct ld_softc *ld)
    480  1.3.2.2  bouyer {
    481  1.3.2.2  bouyer 	struct iop_msg *im;
    482  1.3.2.2  bouyer 	struct iop_softc *iop;
    483  1.3.2.2  bouyer 	struct ld_iop_softc *sc;
    484  1.3.2.2  bouyer 	struct i2o_rbs_cache_flush *mb;
    485  1.3.2.2  bouyer 	int rv;
    486  1.3.2.2  bouyer 
    487  1.3.2.2  bouyer 	sc = (struct ld_iop_softc *)ld;
    488  1.3.2.2  bouyer 	iop = (struct iop_softc *)ld->sc_dv.dv_parent;
    489  1.3.2.2  bouyer 
    490  1.3.2.2  bouyer 	rv = iop_msg_alloc(iop, &sc->sc_ii, &im, IM_NOWAIT | IM_NOINTR);
    491  1.3.2.2  bouyer 	if (rv != 0)
    492  1.3.2.2  bouyer 		return (rv);
    493  1.3.2.2  bouyer 
    494  1.3.2.2  bouyer 	mb = (struct i2o_rbs_cache_flush *)im->im_msg;
    495  1.3.2.2  bouyer 	mb->msgflags = I2O_MSGFLAGS(i2o_rbs_cache_flush);
    496  1.3.2.2  bouyer 	mb->msgfunc = I2O_MSGFUNC(sc->sc_tid, I2O_RBS_CACHE_FLUSH);
    497  1.3.2.2  bouyer 	mb->msgictx = sc->sc_ii.ii_ictx;
    498  1.3.2.2  bouyer 	mb->msgtctx = im->im_tctx;
    499  1.3.2.2  bouyer 	mb->flags = 1 << 16;			/* time multiplier */
    500  1.3.2.2  bouyer 
    501  1.3.2.2  bouyer  	rv = iop_msg_send(iop, im, 10000);
    502  1.3.2.2  bouyer 	iop_msg_free(iop, &sc->sc_ii, im);
    503  1.3.2.2  bouyer 	return (rv);
    504  1.3.2.2  bouyer }
    505  1.3.2.2  bouyer 
    506  1.3.2.2  bouyer void
    507  1.3.2.2  bouyer ld_iop_intr(struct device *dv, struct iop_msg *im, void *reply)
    508  1.3.2.2  bouyer {
    509  1.3.2.2  bouyer 	struct i2o_rbs_reply *rb;
    510  1.3.2.2  bouyer 	struct buf *bp;
    511  1.3.2.2  bouyer 	struct ld_iop_softc *sc;
    512  1.3.2.2  bouyer 	struct iop_softc *iop;
    513  1.3.2.2  bouyer #ifdef I2OVERBOSE
    514  1.3.2.2  bouyer 	int detail;
    515  1.3.2.2  bouyer 	const char *errstr;
    516  1.3.2.2  bouyer #endif
    517  1.3.2.2  bouyer 
    518  1.3.2.2  bouyer 	rb = reply;
    519  1.3.2.2  bouyer 	bp = im->im_dvcontext;
    520  1.3.2.2  bouyer 	sc = (struct ld_iop_softc *)dv;
    521  1.3.2.2  bouyer 	iop = (struct iop_softc *)dv->dv_parent;
    522  1.3.2.2  bouyer 
    523  1.3.2.2  bouyer #ifdef I2OVERBOSE
    524  1.3.2.2  bouyer 	if (rb->reqstatus != I2O_STATUS_SUCCESS) {
    525  1.3.2.2  bouyer 		detail = le16toh(rb->detail);
    526  1.3.2.2  bouyer 		if (detail > sizeof(ld_iop_errors) / sizeof(ld_iop_errors[0]))
    527  1.3.2.2  bouyer 			errstr = "unknown error";
    528  1.3.2.2  bouyer 		else
    529  1.3.2.2  bouyer 			errstr = ld_iop_errors[detail];
    530  1.3.2.2  bouyer 		printf("%s: %s\n", dv->dv_xname, errstr);
    531  1.3.2.2  bouyer #else
    532  1.3.2.2  bouyer 	if (rb->reqstatus != I2O_STATUS_SUCCESS) {
    533  1.3.2.2  bouyer #endif
    534  1.3.2.2  bouyer 		bp->b_flags |= B_ERROR;
    535  1.3.2.2  bouyer 		bp->b_error = EIO;
    536  1.3.2.2  bouyer #ifndef notyet
    537  1.3.2.2  bouyer 		bp->b_resid = bp->b_bcount;
    538  1.3.2.2  bouyer 	} else
    539  1.3.2.2  bouyer 		bp->b_resid = 0;
    540  1.3.2.2  bouyer #else
    541  1.3.2.2  bouyer 	}
    542  1.3.2.2  bouyer 	bp->b_resid = bp->b_bcount - le32toh(rb->transfercount);
    543  1.3.2.2  bouyer #endif
    544  1.3.2.2  bouyer 
    545  1.3.2.2  bouyer 	iop_msg_unmap(iop, im);
    546  1.3.2.2  bouyer 	iop_msg_free(iop, &sc->sc_ii, im);
    547  1.3.2.2  bouyer 	lddone(&sc->sc_ld, bp);
    548  1.3.2.2  bouyer }
    549  1.3.2.2  bouyer 
    550  1.3.2.2  bouyer static void
    551  1.3.2.2  bouyer ld_iop_intr_event(struct device *dv, struct iop_msg *im, void *reply)
    552  1.3.2.2  bouyer {
    553  1.3.2.2  bouyer 	struct i2o_util_event_register_reply *rb;
    554  1.3.2.2  bouyer 	u_int event;
    555  1.3.2.2  bouyer 
    556  1.3.2.2  bouyer 	rb = reply;
    557  1.3.2.2  bouyer 	event = le32toh(rb->event);
    558  1.3.2.2  bouyer 
    559  1.3.2.2  bouyer #ifndef I2ODEBUG
    560  1.3.2.2  bouyer 	if (event == I2O_EVENT_GEN_EVENT_MASK_MODIFIED)
    561  1.3.2.2  bouyer 		return;
    562  1.3.2.2  bouyer #endif
    563  1.3.2.2  bouyer 
    564  1.3.2.2  bouyer 	printf("%s: event 0x%08x received\n", dv->dv_xname, event);
    565  1.3.2.2  bouyer }
    566