Home | History | Annotate | Line # | Download | only in i2o
ld_iop.c revision 1.3.2.5
      1  1.3.2.5  bouyer /*	$NetBSD: ld_iop.c,v 1.3.2.5 2001/03/27 15:31:52 bouyer Exp $	*/
      2  1.3.2.2  bouyer 
      3  1.3.2.2  bouyer /*-
      4  1.3.2.5  bouyer  * Copyright (c) 2000, 2001 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.5  bouyer #include <dev/i2o/iopio.h>
     67  1.3.2.2  bouyer #include <dev/i2o/iopvar.h>
     68  1.3.2.2  bouyer 
     69  1.3.2.5  bouyer #define	LD_IOP_TIMEOUT		30*1000
     70  1.3.2.5  bouyer 
     71  1.3.2.5  bouyer #define	LD_IOP_CLAIMED		0x01
     72  1.3.2.5  bouyer #define	LD_IOP_NEW_EVTMASK	0x02
     73  1.3.2.2  bouyer 
     74  1.3.2.2  bouyer struct ld_iop_softc {
     75  1.3.2.2  bouyer 	struct	ld_softc sc_ld;
     76  1.3.2.2  bouyer 	struct	iop_initiator sc_ii;
     77  1.3.2.2  bouyer 	struct	iop_initiator sc_eventii;
     78  1.3.2.5  bouyer 	int	sc_flags;
     79  1.3.2.2  bouyer };
     80  1.3.2.2  bouyer 
     81  1.3.2.5  bouyer static void	ld_iop_adjqparam(struct device *, int);
     82  1.3.2.2  bouyer static void	ld_iop_attach(struct device *, struct device *, void *);
     83  1.3.2.2  bouyer static int	ld_iop_detach(struct device *, int);
     84  1.3.2.2  bouyer static int	ld_iop_dump(struct ld_softc *, void *, int, int);
     85  1.3.2.2  bouyer static int	ld_iop_flush(struct ld_softc *);
     86  1.3.2.2  bouyer static void	ld_iop_intr(struct device *, struct iop_msg *, void *);
     87  1.3.2.2  bouyer static void	ld_iop_intr_event(struct device *, struct iop_msg *, void *);
     88  1.3.2.2  bouyer static int	ld_iop_match(struct device *, struct cfdata *, void *);
     89  1.3.2.5  bouyer static int	ld_iop_start(struct ld_softc *, struct buf *);
     90  1.3.2.5  bouyer static void	ld_iop_unconfig(struct ld_iop_softc *, int);
     91  1.3.2.2  bouyer 
     92  1.3.2.2  bouyer struct cfattach ld_iop_ca = {
     93  1.3.2.2  bouyer 	sizeof(struct ld_iop_softc),
     94  1.3.2.2  bouyer 	ld_iop_match,
     95  1.3.2.2  bouyer 	ld_iop_attach,
     96  1.3.2.2  bouyer 	ld_iop_detach
     97  1.3.2.2  bouyer };
     98  1.3.2.2  bouyer 
     99  1.3.2.2  bouyer #ifdef I2OVERBOSE
    100  1.3.2.5  bouyer static const char * const ld_iop_errors[] = {
    101  1.3.2.2  bouyer 	"success",
    102  1.3.2.2  bouyer 	"media error",
    103  1.3.2.5  bouyer 	"access error",
    104  1.3.2.2  bouyer 	"device failure",
    105  1.3.2.5  bouyer 	"device not ready",
    106  1.3.2.2  bouyer 	"media not present",
    107  1.3.2.5  bouyer 	"media locked",
    108  1.3.2.2  bouyer 	"media failure",
    109  1.3.2.5  bouyer 	"protocol failure",
    110  1.3.2.5  bouyer 	"bus failure",
    111  1.3.2.5  bouyer 	"access violation",
    112  1.3.2.5  bouyer 	"media write protected",
    113  1.3.2.2  bouyer 	"device reset",
    114  1.3.2.5  bouyer 	"volume changed, waiting for acknowledgement",
    115  1.3.2.5  bouyer 	"timeout",
    116  1.3.2.2  bouyer };
    117  1.3.2.2  bouyer #endif
    118  1.3.2.2  bouyer 
    119  1.3.2.2  bouyer static int
    120  1.3.2.2  bouyer ld_iop_match(struct device *parent, struct cfdata *match, void *aux)
    121  1.3.2.2  bouyer {
    122  1.3.2.2  bouyer 	struct iop_attach_args *ia;
    123  1.3.2.2  bouyer 
    124  1.3.2.2  bouyer 	ia = aux;
    125  1.3.2.2  bouyer 
    126  1.3.2.2  bouyer 	return (ia->ia_class == I2O_CLASS_RANDOM_BLOCK_STORAGE);
    127  1.3.2.2  bouyer }
    128  1.3.2.2  bouyer 
    129  1.3.2.2  bouyer static void
    130  1.3.2.2  bouyer ld_iop_attach(struct device *parent, struct device *self, void *aux)
    131  1.3.2.2  bouyer {
    132  1.3.2.2  bouyer 	struct iop_attach_args *ia;
    133  1.3.2.2  bouyer 	struct ld_softc *ld;
    134  1.3.2.2  bouyer 	struct ld_iop_softc *sc;
    135  1.3.2.2  bouyer 	struct iop_softc *iop;
    136  1.3.2.2  bouyer 	int rv, evreg, enable;
    137  1.3.2.5  bouyer 	char *typestr, *fixedstr;
    138  1.3.2.2  bouyer 	u_int cachesz;
    139  1.3.2.2  bouyer 	struct {
    140  1.3.2.2  bouyer 		struct	i2o_param_op_results pr;
    141  1.3.2.2  bouyer 		struct	i2o_param_read_results prr;
    142  1.3.2.2  bouyer 		union {
    143  1.3.2.2  bouyer 			struct	i2o_param_rbs_cache_control cc;
    144  1.3.2.2  bouyer 			struct	i2o_param_rbs_device_info bdi;
    145  1.3.2.2  bouyer 			struct	i2o_param_rbs_operation op;
    146  1.3.2.2  bouyer 		} p;
    147  1.3.2.5  bouyer 	} param /* XXX gcc __attribute__ ((__packed__)) */;
    148  1.3.2.2  bouyer 
    149  1.3.2.2  bouyer 	sc = (struct ld_iop_softc *)self;
    150  1.3.2.2  bouyer 	ld = &sc->sc_ld;
    151  1.3.2.2  bouyer 	iop = (struct iop_softc *)parent;
    152  1.3.2.2  bouyer 	ia = (struct iop_attach_args *)aux;
    153  1.3.2.2  bouyer 	evreg = 0;
    154  1.3.2.2  bouyer 
    155  1.3.2.2  bouyer 	/* Register us as an initiator. */
    156  1.3.2.2  bouyer 	sc->sc_ii.ii_dv = self;
    157  1.3.2.2  bouyer 	sc->sc_ii.ii_intr = ld_iop_intr;
    158  1.3.2.5  bouyer 	sc->sc_ii.ii_adjqparam = ld_iop_adjqparam;
    159  1.3.2.2  bouyer 	sc->sc_ii.ii_flags = 0;
    160  1.3.2.2  bouyer 	sc->sc_ii.ii_tid = ia->ia_tid;
    161  1.3.2.5  bouyer 	iop_initiator_register(iop, &sc->sc_ii);
    162  1.3.2.2  bouyer 
    163  1.3.2.2  bouyer 	/* Register another initiator to handle events from the device. */
    164  1.3.2.2  bouyer 	sc->sc_eventii.ii_dv = self;
    165  1.3.2.2  bouyer 	sc->sc_eventii.ii_intr = ld_iop_intr_event;
    166  1.3.2.2  bouyer 	sc->sc_eventii.ii_flags = II_DISCARD | II_UTILITY;
    167  1.3.2.2  bouyer 	sc->sc_eventii.ii_tid = ia->ia_tid;
    168  1.3.2.5  bouyer 	iop_initiator_register(iop, &sc->sc_eventii);
    169  1.3.2.5  bouyer 
    170  1.3.2.5  bouyer 	rv = iop_util_eventreg(iop, &sc->sc_eventii,
    171  1.3.2.5  bouyer 	    I2O_EVENT_GEN_EVENT_MASK_MODIFIED |
    172  1.3.2.5  bouyer 	    I2O_EVENT_GEN_DEVICE_RESET |
    173  1.3.2.5  bouyer 	    I2O_EVENT_GEN_STATE_CHANGE |
    174  1.3.2.5  bouyer 	    I2O_EVENT_GEN_GENERAL_WARNING);
    175  1.3.2.5  bouyer 	if (rv != 0) {
    176  1.3.2.2  bouyer 		printf("%s: unable to register for events", self->dv_xname);
    177  1.3.2.2  bouyer 		goto bad;
    178  1.3.2.2  bouyer 	}
    179  1.3.2.2  bouyer 	evreg = 1;
    180  1.3.2.2  bouyer 
    181  1.3.2.5  bouyer 	/*
    182  1.3.2.5  bouyer 	 * Start out with one queued command.  The `iop' driver will adjust
    183  1.3.2.5  bouyer 	 * the queue parameters once we're up and running.
    184  1.3.2.5  bouyer 	 */
    185  1.3.2.5  bouyer 	ld->sc_maxqueuecnt = 1;
    186  1.3.2.5  bouyer 
    187  1.3.2.2  bouyer 	ld->sc_maxxfer = IOP_MAX_XFER;
    188  1.3.2.2  bouyer 	ld->sc_dump = ld_iop_dump;
    189  1.3.2.2  bouyer 	ld->sc_flush = ld_iop_flush;
    190  1.3.2.2  bouyer 	ld->sc_start = ld_iop_start;
    191  1.3.2.2  bouyer 
    192  1.3.2.2  bouyer 	/* Say what the device is. */
    193  1.3.2.5  bouyer 	printf(":");
    194  1.3.2.5  bouyer 	iop_print_ident(iop, ia->ia_tid);
    195  1.3.2.2  bouyer 
    196  1.3.2.2  bouyer 	/*
    197  1.3.2.2  bouyer 	 * Claim the device so that we don't get any nasty surprises.  Allow
    198  1.3.2.2  bouyer 	 * failure.
    199  1.3.2.2  bouyer 	 */
    200  1.3.2.5  bouyer 	rv = iop_util_claim(iop, &sc->sc_ii, 0,
    201  1.3.2.2  bouyer 	    I2O_UTIL_CLAIM_CAPACITY_SENSITIVE |
    202  1.3.2.2  bouyer 	    I2O_UTIL_CLAIM_NO_PEER_SERVICE |
    203  1.3.2.2  bouyer 	    I2O_UTIL_CLAIM_NO_MANAGEMENT_SERVICE |
    204  1.3.2.2  bouyer 	    I2O_UTIL_CLAIM_PRIMARY_USER);
    205  1.3.2.5  bouyer 	sc->sc_flags = rv ? 0 : LD_IOP_CLAIMED;
    206  1.3.2.2  bouyer 
    207  1.3.2.5  bouyer 	rv = iop_param_op(iop, ia->ia_tid, NULL, 0, I2O_PARAM_RBS_DEVICE_INFO,
    208  1.3.2.2  bouyer 	    &param, sizeof(param));
    209  1.3.2.2  bouyer 	if (rv != 0) {
    210  1.3.2.2  bouyer 		printf("%s: unable to get parameters (0x%04x; %d)\n",
    211  1.3.2.2  bouyer 		   ld->sc_dv.dv_xname, I2O_PARAM_RBS_DEVICE_INFO, rv);
    212  1.3.2.2  bouyer 		goto bad;
    213  1.3.2.2  bouyer 	}
    214  1.3.2.2  bouyer 
    215  1.3.2.2  bouyer 	ld->sc_secsize = le32toh(param.p.bdi.blocksize);
    216  1.3.2.2  bouyer 	ld->sc_secperunit = (int)
    217  1.3.2.2  bouyer 	    (le64toh(param.p.bdi.capacity) / ld->sc_secsize);
    218  1.3.2.2  bouyer 
    219  1.3.2.2  bouyer 	/* Build synthetic geometry. */
    220  1.3.2.2  bouyer 	if (ld->sc_secperunit <= 528 * 2048)		/* 528MB */
    221  1.3.2.2  bouyer 		ld->sc_nheads = 16;
    222  1.3.2.2  bouyer 	else if (ld->sc_secperunit <= 1024 * 2048)	/* 1GB */
    223  1.3.2.2  bouyer 		ld->sc_nheads = 32;
    224  1.3.2.2  bouyer 	else if (ld->sc_secperunit <= 21504 * 2048)	/* 21GB */
    225  1.3.2.2  bouyer 		ld->sc_nheads = 64;
    226  1.3.2.2  bouyer 	else if (ld->sc_secperunit <= 43008 * 2048)	/* 42GB */
    227  1.3.2.2  bouyer 		ld->sc_nheads = 128;
    228  1.3.2.2  bouyer 	else
    229  1.3.2.2  bouyer 		ld->sc_nheads = 255;
    230  1.3.2.2  bouyer 
    231  1.3.2.2  bouyer 	ld->sc_nsectors = 63;
    232  1.3.2.2  bouyer 	ld->sc_ncylinders = ld->sc_secperunit /
    233  1.3.2.2  bouyer 	    (ld->sc_nheads * ld->sc_nsectors);
    234  1.3.2.2  bouyer 
    235  1.3.2.2  bouyer 	switch (param.p.bdi.type) {
    236  1.3.2.2  bouyer 	case I2O_RBS_TYPE_DIRECT:
    237  1.3.2.2  bouyer 		typestr = "direct access";
    238  1.3.2.2  bouyer 		enable = 1;
    239  1.3.2.2  bouyer 		break;
    240  1.3.2.2  bouyer 	case I2O_RBS_TYPE_WORM:
    241  1.3.2.2  bouyer 		typestr = "WORM";
    242  1.3.2.2  bouyer 		enable = 0;
    243  1.3.2.2  bouyer 		break;
    244  1.3.2.2  bouyer 	case I2O_RBS_TYPE_CDROM:
    245  1.3.2.5  bouyer 		typestr = "CD-ROM";
    246  1.3.2.2  bouyer 		enable = 0;
    247  1.3.2.2  bouyer 		break;
    248  1.3.2.2  bouyer 	case I2O_RBS_TYPE_OPTICAL:
    249  1.3.2.2  bouyer 		typestr = "optical";
    250  1.3.2.2  bouyer 		enable = 0;
    251  1.3.2.2  bouyer 		break;
    252  1.3.2.2  bouyer 	default:
    253  1.3.2.2  bouyer 		typestr = "unknown";
    254  1.3.2.2  bouyer 		enable = 0;
    255  1.3.2.2  bouyer 		break;
    256  1.3.2.2  bouyer 	}
    257  1.3.2.2  bouyer 
    258  1.3.2.2  bouyer 	if ((le32toh(param.p.bdi.capabilities) & I2O_RBS_CAP_REMOVEABLE_MEDIA)
    259  1.3.2.2  bouyer 	    != 0) {
    260  1.3.2.2  bouyer 		/* ld->sc_flags = LDF_REMOVEABLE; */
    261  1.3.2.2  bouyer 		fixedstr = "removeable";
    262  1.3.2.2  bouyer 		enable = 0;
    263  1.3.2.2  bouyer 	} else
    264  1.3.2.2  bouyer 		fixedstr = "fixed";
    265  1.3.2.2  bouyer 
    266  1.3.2.5  bouyer 	printf(" %s, %s", typestr, fixedstr);
    267  1.3.2.2  bouyer 
    268  1.3.2.2  bouyer 	/*
    269  1.3.2.2  bouyer 	 * Determine if the device has an private cache.  If so, print the
    270  1.3.2.2  bouyer 	 * cache size.  Even if the device doesn't appear to have a cache,
    271  1.3.2.5  bouyer 	 * we perform a flush at shutdown.
    272  1.3.2.2  bouyer 	 */
    273  1.3.2.5  bouyer 	rv = iop_param_op(iop, ia->ia_tid, NULL, 0,
    274  1.3.2.5  bouyer 	    I2O_PARAM_RBS_CACHE_CONTROL, &param, sizeof(param));
    275  1.3.2.2  bouyer 	if (rv != 0) {
    276  1.3.2.2  bouyer 		printf("%s: unable to get parameters (0x%04x; %d)\n",
    277  1.3.2.2  bouyer 		   ld->sc_dv.dv_xname, I2O_PARAM_RBS_CACHE_CONTROL, rv);
    278  1.3.2.2  bouyer 		goto bad;
    279  1.3.2.2  bouyer 	}
    280  1.3.2.2  bouyer 
    281  1.3.2.2  bouyer 	if ((cachesz = le32toh(param.p.cc.totalcachesize)) != 0)
    282  1.3.2.2  bouyer 		printf(", %dkB cache", cachesz >> 10);
    283  1.3.2.2  bouyer 
    284  1.3.2.2  bouyer 	printf("\n");
    285  1.3.2.2  bouyer 
    286  1.3.2.2  bouyer 	/*
    287  1.3.2.2  bouyer 	 * Configure the DDM's timeout functions to time out all commands
    288  1.3.2.5  bouyer 	 * after 30 seconds.
    289  1.3.2.2  bouyer 	 */
    290  1.3.2.5  bouyer 	rv = iop_param_op(iop, ia->ia_tid, NULL, 0, I2O_PARAM_RBS_OPERATION,
    291  1.3.2.2  bouyer 	    &param, sizeof(param));
    292  1.3.2.2  bouyer 	if (rv != 0) {
    293  1.3.2.2  bouyer 		printf("%s: unable to get parameters (0x%04x; %d)\n",
    294  1.3.2.2  bouyer 		   ld->sc_dv.dv_xname, I2O_PARAM_RBS_OPERATION, rv);
    295  1.3.2.2  bouyer 		goto bad;
    296  1.3.2.2  bouyer 	}
    297  1.3.2.2  bouyer 
    298  1.3.2.5  bouyer 	param.p.op.timeoutbase = htole32(LD_IOP_TIMEOUT * 1000);
    299  1.3.2.5  bouyer 	param.p.op.rwvtimeoutbase = htole32(LD_IOP_TIMEOUT * 1000);
    300  1.3.2.2  bouyer 	param.p.op.rwvtimeout = 0;
    301  1.3.2.2  bouyer 
    302  1.3.2.5  bouyer 	rv = iop_param_op(iop, ia->ia_tid, NULL, 1, I2O_PARAM_RBS_OPERATION,
    303  1.3.2.2  bouyer 	    &param, sizeof(param));
    304  1.3.2.5  bouyer #ifdef notdef
    305  1.3.2.5  bouyer 	/*
    306  1.3.2.5  bouyer 	 * Intel RAID adapters don't like the above, but do post a
    307  1.3.2.5  bouyer 	 * `parameter changed' event.  Perhaps we're doing something
    308  1.3.2.5  bouyer 	 * wrong...
    309  1.3.2.5  bouyer 	 */
    310  1.3.2.2  bouyer 	if (rv != 0) {
    311  1.3.2.2  bouyer 		printf("%s: unable to set parameters (0x%04x; %d)\n",
    312  1.3.2.2  bouyer 		   ld->sc_dv.dv_xname, I2O_PARAM_RBS_OPERATION, rv);
    313  1.3.2.2  bouyer 		goto bad;
    314  1.3.2.2  bouyer 	}
    315  1.3.2.5  bouyer #endif
    316  1.3.2.2  bouyer 
    317  1.3.2.2  bouyer 	if (enable)
    318  1.3.2.2  bouyer 		ld->sc_flags |= LDF_ENABLED;
    319  1.3.2.2  bouyer 	else
    320  1.3.2.2  bouyer 		printf("%s: device not yet supported\n", self->dv_xname);
    321  1.3.2.2  bouyer 
    322  1.3.2.2  bouyer 	ldattach(ld);
    323  1.3.2.2  bouyer 	return;
    324  1.3.2.2  bouyer 
    325  1.3.2.5  bouyer  bad:
    326  1.3.2.5  bouyer 	ld_iop_unconfig(sc, evreg);
    327  1.3.2.5  bouyer }
    328  1.3.2.5  bouyer 
    329  1.3.2.5  bouyer static void
    330  1.3.2.5  bouyer ld_iop_unconfig(struct ld_iop_softc *sc, int evreg)
    331  1.3.2.5  bouyer {
    332  1.3.2.5  bouyer 	struct iop_softc *iop;
    333  1.3.2.5  bouyer 	int s;
    334  1.3.2.5  bouyer 
    335  1.3.2.5  bouyer 	iop = (struct iop_softc *)sc->sc_ld.sc_dv.dv_parent;
    336  1.3.2.5  bouyer 
    337  1.3.2.5  bouyer 	if ((sc->sc_flags & LD_IOP_CLAIMED) != 0)
    338  1.3.2.2  bouyer 		iop_util_claim(iop, &sc->sc_ii, 1,
    339  1.3.2.2  bouyer 		    I2O_UTIL_CLAIM_PRIMARY_USER);
    340  1.3.2.5  bouyer 
    341  1.3.2.5  bouyer 	if (evreg) {
    342  1.3.2.5  bouyer 		/*
    343  1.3.2.5  bouyer 		 * Mask off events, and wait up to 5 seconds for a reply.
    344  1.3.2.5  bouyer 		 * Note that some adapters won't reply to this (XXX We
    345  1.3.2.5  bouyer 		 * should check the event capabilities).
    346  1.3.2.5  bouyer 		 */
    347  1.3.2.5  bouyer 		sc->sc_flags &= ~LD_IOP_NEW_EVTMASK;
    348  1.3.2.5  bouyer 		iop_util_eventreg(iop, &sc->sc_eventii,
    349  1.3.2.5  bouyer 		    I2O_EVENT_GEN_EVENT_MASK_MODIFIED);
    350  1.3.2.5  bouyer 		s = splbio();
    351  1.3.2.5  bouyer 		if ((sc->sc_flags & LD_IOP_NEW_EVTMASK) == 0)
    352  1.3.2.5  bouyer 			tsleep(&sc->sc_eventii, PRIBIO, "ld_iopevt", hz * 5);
    353  1.3.2.5  bouyer 		splx(s);
    354  1.3.2.5  bouyer #ifdef I2ODEBUG
    355  1.3.2.5  bouyer 		if ((sc->sc_flags & LD_IOP_NEW_EVTMASK) == 0)
    356  1.3.2.5  bouyer 			printf("%s: didn't reply to event unregister",
    357  1.3.2.5  bouyer 			    sc->sc_ld.sc_dv.dv_xname);
    358  1.3.2.5  bouyer #endif
    359  1.3.2.5  bouyer 	}
    360  1.3.2.5  bouyer 
    361  1.3.2.5  bouyer 	iop_initiator_unregister(iop, &sc->sc_eventii);
    362  1.3.2.2  bouyer 	iop_initiator_unregister(iop, &sc->sc_ii);
    363  1.3.2.2  bouyer }
    364  1.3.2.2  bouyer 
    365  1.3.2.2  bouyer static int
    366  1.3.2.2  bouyer ld_iop_detach(struct device *self, int flags)
    367  1.3.2.2  bouyer {
    368  1.3.2.2  bouyer 	struct ld_iop_softc *sc;
    369  1.3.2.2  bouyer 	struct iop_softc *iop;
    370  1.3.2.3  bouyer 	int rv;
    371  1.3.2.2  bouyer 
    372  1.3.2.2  bouyer 	sc = (struct ld_iop_softc *)self;
    373  1.3.2.5  bouyer 	iop = (struct iop_softc *)self->dv_parent;
    374  1.3.2.2  bouyer 
    375  1.3.2.4  bouyer 	if ((rv = ldbegindetach(&sc->sc_ld, flags)) != 0)
    376  1.3.2.3  bouyer 		return (rv);
    377  1.3.2.2  bouyer 
    378  1.3.2.2  bouyer 	/*
    379  1.3.2.2  bouyer 	 * Abort any requests queued with the IOP, but allow requests that
    380  1.3.2.2  bouyer 	 * are already in progress to complete.
    381  1.3.2.2  bouyer 	 */
    382  1.3.2.2  bouyer 	if ((sc->sc_ld.sc_flags & LDF_ENABLED) != 0)
    383  1.3.2.2  bouyer 		iop_util_abort(iop, &sc->sc_ii, 0, 0,
    384  1.3.2.2  bouyer 		    I2O_UTIL_ABORT_WILD | I2O_UTIL_ABORT_CLEAN);
    385  1.3.2.2  bouyer 
    386  1.3.2.4  bouyer 	ldenddetach(&sc->sc_ld);
    387  1.3.2.2  bouyer 
    388  1.3.2.5  bouyer 	/* Un-claim the target, and un-register our initiators. */
    389  1.3.2.5  bouyer 	if ((sc->sc_ld.sc_flags & LDF_ENABLED) != 0)
    390  1.3.2.5  bouyer 		ld_iop_unconfig(sc, 1);
    391  1.3.2.2  bouyer 
    392  1.3.2.2  bouyer 	return (0);
    393  1.3.2.2  bouyer }
    394  1.3.2.2  bouyer 
    395  1.3.2.2  bouyer static int
    396  1.3.2.2  bouyer ld_iop_start(struct ld_softc *ld, struct buf *bp)
    397  1.3.2.2  bouyer {
    398  1.3.2.2  bouyer 	struct iop_msg *im;
    399  1.3.2.2  bouyer 	struct iop_softc *iop;
    400  1.3.2.2  bouyer 	struct ld_iop_softc *sc;
    401  1.3.2.5  bouyer 	struct i2o_rbs_block_read *mf;
    402  1.3.2.5  bouyer 	u_int rv, flags, write;
    403  1.3.2.2  bouyer 	u_int64_t ba;
    404  1.3.2.5  bouyer 	u_int32_t mb[IOP_MAX_MSG_SIZE / sizeof(u_int32_t)];
    405  1.3.2.2  bouyer 
    406  1.3.2.2  bouyer 	sc = (struct ld_iop_softc *)ld;
    407  1.3.2.2  bouyer 	iop = (struct iop_softc *)ld->sc_dv.dv_parent;
    408  1.3.2.2  bouyer 
    409  1.3.2.5  bouyer 	im = iop_msg_alloc(iop, &sc->sc_ii, 0);
    410  1.3.2.2  bouyer 	im->im_dvcontext = bp;
    411  1.3.2.2  bouyer 
    412  1.3.2.2  bouyer 	write = ((bp->b_flags & B_READ) == 0);
    413  1.3.2.2  bouyer 	ba = (u_int64_t)bp->b_rawblkno * ld->sc_secsize;
    414  1.3.2.2  bouyer 
    415  1.3.2.2  bouyer 	/*
    416  1.3.2.2  bouyer 	 * Write through the cache when performing synchronous writes.  When
    417  1.3.2.2  bouyer 	 * performing a read, we don't request that the DDM cache the data,
    418  1.3.2.2  bouyer 	 * as there's little advantage to it.
    419  1.3.2.2  bouyer 	 */
    420  1.3.2.2  bouyer 	if (write) {
    421  1.3.2.2  bouyer 		if ((bp->b_flags & B_ASYNC) == 0)
    422  1.3.2.2  bouyer 			flags = I2O_RBS_BLOCK_WRITE_CACHE_WT;
    423  1.3.2.2  bouyer 		else
    424  1.3.2.2  bouyer 			flags = I2O_RBS_BLOCK_WRITE_CACHE_WB;
    425  1.3.2.2  bouyer 	} else
    426  1.3.2.2  bouyer 		flags = 0;
    427  1.3.2.2  bouyer 
    428  1.3.2.2  bouyer 	/*
    429  1.3.2.2  bouyer 	 * Fill the message frame.  We can use the block_read structure for
    430  1.3.2.2  bouyer 	 * both reads and writes, as it's almost identical to the
    431  1.3.2.2  bouyer 	 * block_write structure.
    432  1.3.2.2  bouyer 	 */
    433  1.3.2.5  bouyer 	mf = (struct i2o_rbs_block_read *)mb;
    434  1.3.2.5  bouyer 	mf->msgflags = I2O_MSGFLAGS(i2o_rbs_block_read);
    435  1.3.2.5  bouyer 	mf->msgfunc = I2O_MSGFUNC(sc->sc_ii.ii_tid,
    436  1.3.2.2  bouyer 	    write ? I2O_RBS_BLOCK_WRITE : I2O_RBS_BLOCK_READ);
    437  1.3.2.5  bouyer 	mf->msgictx = sc->sc_ii.ii_ictx;
    438  1.3.2.5  bouyer 	mf->msgtctx = im->im_tctx;
    439  1.3.2.5  bouyer 	mf->flags = flags | (1 << 16);		/* flags & time multiplier */
    440  1.3.2.5  bouyer 	mf->datasize = bp->b_bcount;
    441  1.3.2.5  bouyer 	mf->lowoffset = (u_int32_t)ba;
    442  1.3.2.5  bouyer 	mf->highoffset = (u_int32_t)(ba >> 32);
    443  1.3.2.5  bouyer 
    444  1.3.2.5  bouyer 	/* Map the data transfer and enqueue the command. */
    445  1.3.2.5  bouyer 	rv = iop_msg_map_bio(iop, im, mb, bp->b_data, bp->b_bcount, write);
    446  1.3.2.5  bouyer 	if (rv == 0) {
    447  1.3.2.5  bouyer 		if ((rv = iop_msg_post(iop, im, mb, 0)) != 0) {
    448  1.3.2.5  bouyer 			iop_msg_unmap(iop, im);
    449  1.3.2.5  bouyer 			iop_msg_free(iop, im);
    450  1.3.2.5  bouyer 		}
    451  1.3.2.5  bouyer 	}
    452  1.3.2.2  bouyer 	return (rv);
    453  1.3.2.2  bouyer }
    454  1.3.2.2  bouyer 
    455  1.3.2.2  bouyer static int
    456  1.3.2.2  bouyer ld_iop_dump(struct ld_softc *ld, void *data, int blkno, int blkcnt)
    457  1.3.2.2  bouyer {
    458  1.3.2.2  bouyer 	struct iop_msg *im;
    459  1.3.2.2  bouyer 	struct iop_softc *iop;
    460  1.3.2.2  bouyer 	struct ld_iop_softc *sc;
    461  1.3.2.5  bouyer 	struct i2o_rbs_block_write *mf;
    462  1.3.2.2  bouyer 	int rv, bcount;
    463  1.3.2.2  bouyer 	u_int64_t ba;
    464  1.3.2.5  bouyer 	u_int32_t mb[IOP_MAX_MSG_SIZE / sizeof(u_int32_t)];
    465  1.3.2.2  bouyer 
    466  1.3.2.2  bouyer 	sc = (struct ld_iop_softc *)ld;
    467  1.3.2.2  bouyer 	iop = (struct iop_softc *)ld->sc_dv.dv_parent;
    468  1.3.2.2  bouyer 	bcount = blkcnt * ld->sc_secsize;
    469  1.3.2.2  bouyer 	ba = (u_int64_t)blkno * ld->sc_secsize;
    470  1.3.2.5  bouyer 	im = iop_msg_alloc(iop, &sc->sc_ii, IM_POLL);
    471  1.3.2.2  bouyer 
    472  1.3.2.5  bouyer 	mf = (struct i2o_rbs_block_write *)mb;
    473  1.3.2.5  bouyer 	mf->msgflags = I2O_MSGFLAGS(i2o_rbs_block_write);
    474  1.3.2.5  bouyer 	mf->msgfunc = I2O_MSGFUNC(sc->sc_ii.ii_tid, I2O_RBS_BLOCK_WRITE);
    475  1.3.2.5  bouyer 	mf->msgictx = sc->sc_ii.ii_ictx;
    476  1.3.2.5  bouyer 	mf->msgtctx = im->im_tctx;
    477  1.3.2.5  bouyer 	mf->flags = I2O_RBS_BLOCK_WRITE_CACHE_WT | (1 << 16);
    478  1.3.2.5  bouyer 	mf->datasize = bcount;
    479  1.3.2.5  bouyer 	mf->lowoffset = (u_int32_t)ba;
    480  1.3.2.5  bouyer 	mf->highoffset = (u_int32_t)(ba >> 32);
    481  1.3.2.2  bouyer 
    482  1.3.2.5  bouyer 	if ((rv = iop_msg_map(iop, im, mb, data, bcount, 1)) != 0) {
    483  1.3.2.5  bouyer 		iop_msg_free(iop, im);
    484  1.3.2.2  bouyer 		return (rv);
    485  1.3.2.2  bouyer 	}
    486  1.3.2.2  bouyer 
    487  1.3.2.5  bouyer 	rv = iop_msg_post(iop, im, mb, LD_IOP_TIMEOUT * 2);
    488  1.3.2.2  bouyer 	iop_msg_unmap(iop, im);
    489  1.3.2.5  bouyer 	iop_msg_free(iop, im);
    490  1.3.2.2  bouyer  	return (rv);
    491  1.3.2.2  bouyer }
    492  1.3.2.2  bouyer 
    493  1.3.2.2  bouyer static int
    494  1.3.2.2  bouyer ld_iop_flush(struct ld_softc *ld)
    495  1.3.2.2  bouyer {
    496  1.3.2.2  bouyer 	struct iop_msg *im;
    497  1.3.2.2  bouyer 	struct iop_softc *iop;
    498  1.3.2.2  bouyer 	struct ld_iop_softc *sc;
    499  1.3.2.5  bouyer 	struct i2o_rbs_cache_flush mf;
    500  1.3.2.2  bouyer 	int rv;
    501  1.3.2.2  bouyer 
    502  1.3.2.2  bouyer 	sc = (struct ld_iop_softc *)ld;
    503  1.3.2.2  bouyer 	iop = (struct iop_softc *)ld->sc_dv.dv_parent;
    504  1.3.2.5  bouyer 	im = iop_msg_alloc(iop, &sc->sc_ii, IM_WAIT);
    505  1.3.2.2  bouyer 
    506  1.3.2.5  bouyer 	mf.msgflags = I2O_MSGFLAGS(i2o_rbs_cache_flush);
    507  1.3.2.5  bouyer 	mf.msgfunc = I2O_MSGFUNC(sc->sc_ii.ii_tid, I2O_RBS_CACHE_FLUSH);
    508  1.3.2.5  bouyer 	mf.msgictx = sc->sc_ii.ii_ictx;
    509  1.3.2.5  bouyer 	mf.msgtctx = im->im_tctx;
    510  1.3.2.5  bouyer 	mf.flags = 1 << 16;			/* time multiplier */
    511  1.3.2.2  bouyer 
    512  1.3.2.5  bouyer 	/*
    513  1.3.2.5  bouyer 	 * XXX Aincent disks will return an error here.  Also, we shouldn't
    514  1.3.2.5  bouyer 	 * be polling on completion while the system is running.
    515  1.3.2.5  bouyer 	 */
    516  1.3.2.5  bouyer 	rv = iop_msg_post(iop, im, &mf, LD_IOP_TIMEOUT * 2);
    517  1.3.2.5  bouyer 	iop_msg_free(iop, im);
    518  1.3.2.2  bouyer 	return (rv);
    519  1.3.2.2  bouyer }
    520  1.3.2.2  bouyer 
    521  1.3.2.2  bouyer void
    522  1.3.2.2  bouyer ld_iop_intr(struct device *dv, struct iop_msg *im, void *reply)
    523  1.3.2.2  bouyer {
    524  1.3.2.2  bouyer 	struct i2o_rbs_reply *rb;
    525  1.3.2.2  bouyer 	struct buf *bp;
    526  1.3.2.2  bouyer 	struct ld_iop_softc *sc;
    527  1.3.2.2  bouyer 	struct iop_softc *iop;
    528  1.3.2.5  bouyer 	int err, detail;
    529  1.3.2.2  bouyer #ifdef I2OVERBOSE
    530  1.3.2.2  bouyer 	const char *errstr;
    531  1.3.2.2  bouyer #endif
    532  1.3.2.2  bouyer 
    533  1.3.2.2  bouyer 	rb = reply;
    534  1.3.2.2  bouyer 	bp = im->im_dvcontext;
    535  1.3.2.2  bouyer 	sc = (struct ld_iop_softc *)dv;
    536  1.3.2.2  bouyer 	iop = (struct iop_softc *)dv->dv_parent;
    537  1.3.2.2  bouyer 
    538  1.3.2.5  bouyer 	err = ((rb->msgflags & I2O_MSGFLAGS_FAIL) != 0);
    539  1.3.2.5  bouyer 
    540  1.3.2.5  bouyer 	if (!err && rb->reqstatus != I2O_STATUS_SUCCESS) {
    541  1.3.2.2  bouyer 		detail = le16toh(rb->detail);
    542  1.3.2.5  bouyer #ifdef I2OVERBOSE
    543  1.3.2.2  bouyer 		if (detail > sizeof(ld_iop_errors) / sizeof(ld_iop_errors[0]))
    544  1.3.2.5  bouyer 			errstr = "<unknown>";
    545  1.3.2.2  bouyer 		else
    546  1.3.2.2  bouyer 			errstr = ld_iop_errors[detail];
    547  1.3.2.5  bouyer 		printf("%s: error 0x%04x: %s\n", dv->dv_xname, detail, errstr);
    548  1.3.2.2  bouyer #else
    549  1.3.2.5  bouyer 		printf("%s: error 0x%04x\n", dv->dv_xname, detail);
    550  1.3.2.2  bouyer #endif
    551  1.3.2.5  bouyer 		err = 1;
    552  1.3.2.5  bouyer 	}
    553  1.3.2.5  bouyer 
    554  1.3.2.5  bouyer 	if (err) {
    555  1.3.2.2  bouyer 		bp->b_flags |= B_ERROR;
    556  1.3.2.2  bouyer 		bp->b_error = EIO;
    557  1.3.2.2  bouyer 		bp->b_resid = bp->b_bcount;
    558  1.3.2.2  bouyer 	} else
    559  1.3.2.5  bouyer 		bp->b_resid = bp->b_bcount - le32toh(rb->transfercount);
    560  1.3.2.2  bouyer 
    561  1.3.2.2  bouyer 	iop_msg_unmap(iop, im);
    562  1.3.2.5  bouyer 	iop_msg_free(iop, im);
    563  1.3.2.2  bouyer 	lddone(&sc->sc_ld, bp);
    564  1.3.2.2  bouyer }
    565  1.3.2.2  bouyer 
    566  1.3.2.2  bouyer static void
    567  1.3.2.2  bouyer ld_iop_intr_event(struct device *dv, struct iop_msg *im, void *reply)
    568  1.3.2.2  bouyer {
    569  1.3.2.2  bouyer 	struct i2o_util_event_register_reply *rb;
    570  1.3.2.5  bouyer 	struct ld_iop_softc *sc;
    571  1.3.2.2  bouyer 	u_int event;
    572  1.3.2.2  bouyer 
    573  1.3.2.2  bouyer 	rb = reply;
    574  1.3.2.5  bouyer 
    575  1.3.2.5  bouyer 	if ((rb->msgflags & I2O_MSGFLAGS_FAIL) != 0)
    576  1.3.2.5  bouyer 		return;
    577  1.3.2.5  bouyer 
    578  1.3.2.2  bouyer 	event = le32toh(rb->event);
    579  1.3.2.5  bouyer 	sc = (struct ld_iop_softc *)dv;
    580  1.3.2.2  bouyer 
    581  1.3.2.5  bouyer 	if (event == I2O_EVENT_GEN_EVENT_MASK_MODIFIED) {
    582  1.3.2.5  bouyer 		sc->sc_flags |= LD_IOP_NEW_EVTMASK;
    583  1.3.2.5  bouyer 		wakeup(&sc->sc_eventii);
    584  1.3.2.2  bouyer #ifndef I2ODEBUG
    585  1.3.2.2  bouyer 		return;
    586  1.3.2.2  bouyer #endif
    587  1.3.2.5  bouyer 	}
    588  1.3.2.2  bouyer 
    589  1.3.2.2  bouyer 	printf("%s: event 0x%08x received\n", dv->dv_xname, event);
    590  1.3.2.2  bouyer }
    591  1.3.2.5  bouyer 
    592  1.3.2.5  bouyer static void
    593  1.3.2.5  bouyer ld_iop_adjqparam(struct device *dv, int mpi)
    594  1.3.2.5  bouyer {
    595  1.3.2.5  bouyer 	struct iop_softc *iop;
    596  1.3.2.5  bouyer 
    597  1.3.2.5  bouyer 	/*
    598  1.3.2.5  bouyer 	 * AMI controllers seem to loose the plot if you hand off lots of
    599  1.3.2.5  bouyer 	 * queued commands.
    600  1.3.2.5  bouyer 	 */
    601  1.3.2.5  bouyer 	iop = (struct iop_softc *)dv->dv_parent;
    602  1.3.2.5  bouyer 	if (le16toh(I2O_ORG_AMI) == iop->sc_status.orgid && mpi > 64)
    603  1.3.2.5  bouyer 		mpi = 64;
    604  1.3.2.5  bouyer 
    605  1.3.2.5  bouyer 	ldadjqparam((struct ld_softc *)dv, mpi);
    606  1.3.2.5  bouyer }
    607