Home | History | Annotate | Line # | Download | only in eisa
mlx_eisa.c revision 1.3.2.4
      1  1.3.2.4  nathanw /*	$NetBSD: mlx_eisa.c,v 1.3.2.4 2002/01/08 00:29:27 nathanw Exp $	*/
      2  1.3.2.2  nathanw 
      3  1.3.2.2  nathanw /*-
      4  1.3.2.2  nathanw  * Copyright (c) 2001 The NetBSD Foundation, Inc.
      5  1.3.2.2  nathanw  * All rights reserved.
      6  1.3.2.2  nathanw  *
      7  1.3.2.2  nathanw  * This code is derived from software contributed to The NetBSD Foundation
      8  1.3.2.2  nathanw  * by Andrew Doran.
      9  1.3.2.2  nathanw  *
     10  1.3.2.2  nathanw  * Redistribution and use in source and binary forms, with or without
     11  1.3.2.2  nathanw  * modification, are permitted provided that the following conditions
     12  1.3.2.2  nathanw  * are met:
     13  1.3.2.2  nathanw  * 1. Redistributions of source code must retain the above copyright
     14  1.3.2.2  nathanw  *    notice, this list of conditions and the following disclaimer.
     15  1.3.2.2  nathanw  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.3.2.2  nathanw  *    notice, this list of conditions and the following disclaimer in the
     17  1.3.2.2  nathanw  *    documentation and/or other materials provided with the distribution.
     18  1.3.2.2  nathanw  * 3. All advertising materials mentioning features or use of this software
     19  1.3.2.2  nathanw  *    must display the following acknowledgement:
     20  1.3.2.2  nathanw  *        This product includes software developed by the NetBSD
     21  1.3.2.2  nathanw  *        Foundation, Inc. and its contributors.
     22  1.3.2.2  nathanw  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  1.3.2.2  nathanw  *    contributors may be used to endorse or promote products derived
     24  1.3.2.2  nathanw  *    from this software without specific prior written permission.
     25  1.3.2.2  nathanw  *
     26  1.3.2.2  nathanw  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  1.3.2.2  nathanw  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  1.3.2.2  nathanw  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  1.3.2.2  nathanw  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  1.3.2.2  nathanw  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  1.3.2.2  nathanw  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  1.3.2.2  nathanw  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  1.3.2.2  nathanw  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  1.3.2.2  nathanw  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  1.3.2.2  nathanw  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  1.3.2.2  nathanw  * POSSIBILITY OF SUCH DAMAGE.
     37  1.3.2.2  nathanw  */
     38  1.3.2.2  nathanw 
     39  1.3.2.2  nathanw /*
     40  1.3.2.2  nathanw  * EISA front-end for mlx(4) driver.
     41  1.3.2.2  nathanw  */
     42  1.3.2.2  nathanw 
     43  1.3.2.3  nathanw #include <sys/cdefs.h>
     44  1.3.2.4  nathanw __KERNEL_RCSID(0, "$NetBSD: mlx_eisa.c,v 1.3.2.4 2002/01/08 00:29:27 nathanw Exp $");
     45  1.3.2.3  nathanw 
     46  1.3.2.2  nathanw #include <sys/param.h>
     47  1.3.2.2  nathanw #include <sys/systm.h>
     48  1.3.2.2  nathanw #include <sys/device.h>
     49  1.3.2.2  nathanw 
     50  1.3.2.2  nathanw #include <machine/bus.h>
     51  1.3.2.2  nathanw #include <machine/intr.h>
     52  1.3.2.2  nathanw 
     53  1.3.2.2  nathanw #include <dev/eisa/eisavar.h>
     54  1.3.2.2  nathanw #include <dev/eisa/eisadevs.h>
     55  1.3.2.2  nathanw 
     56  1.3.2.2  nathanw #include <dev/ic/mlxreg.h>
     57  1.3.2.2  nathanw #include <dev/ic/mlxio.h>
     58  1.3.2.2  nathanw #include <dev/ic/mlxvar.h>
     59  1.3.2.2  nathanw 
     60  1.3.2.4  nathanw #define MLX_EISA_SLOT_OFFSET		0x0c80
     61  1.3.2.2  nathanw #define MLX_EISA_IOSIZE			(0x0ce0 - MLX_EISA_SLOT_OFFSET)
     62  1.3.2.2  nathanw #define MLX_EISA_IOCONF1		(0x0cc1 - MLX_EISA_SLOT_OFFSET)
     63  1.3.2.2  nathanw #define MLX_EISA_IOCONF2		(0x0cc3 - MLX_EISA_SLOT_OFFSET)
     64  1.3.2.2  nathanw 
     65  1.3.2.2  nathanw static void	mlx_eisa_attach(struct device *, struct device *, void *);
     66  1.3.2.2  nathanw static int	mlx_eisa_match(struct device *, struct cfdata *, void *);
     67  1.3.2.2  nathanw 
     68  1.3.2.2  nathanw static int	mlx_v1_submit(struct mlx_softc *, struct mlx_ccb *);
     69  1.3.2.2  nathanw static int	mlx_v1_findcomplete(struct mlx_softc *, u_int *, u_int *);
     70  1.3.2.2  nathanw static void	mlx_v1_intaction(struct mlx_softc *, int);
     71  1.3.2.2  nathanw static int	mlx_v1_fw_handshake(struct mlx_softc *, int *, int *, int *);
     72  1.3.2.2  nathanw #ifdef MLX_RESET
     73  1.3.2.2  nathanw static int	mlx_v1_reset(struct mlx_softc *);
     74  1.3.2.2  nathanw #endif
     75  1.3.2.2  nathanw 
     76  1.3.2.2  nathanw struct cfattach mlx_eisa_ca = {
     77  1.3.2.2  nathanw 	sizeof(struct mlx_softc), mlx_eisa_match, mlx_eisa_attach
     78  1.3.2.2  nathanw };
     79  1.3.2.2  nathanw 
     80  1.3.2.2  nathanw static const char * const mlx_eisa_prod[] = {
     81  1.3.2.2  nathanw 	"MLX0070",
     82  1.3.2.2  nathanw 	"MLX0071",
     83  1.3.2.2  nathanw 	"MLX0072",
     84  1.3.2.2  nathanw 	"MLX0073",
     85  1.3.2.2  nathanw 	"MLX0074",
     86  1.3.2.2  nathanw 	"MLX0075",
     87  1.3.2.2  nathanw 	"MLX0076",
     88  1.3.2.2  nathanw 	"MLX0077",
     89  1.3.2.2  nathanw };
     90  1.3.2.2  nathanw 
     91  1.3.2.2  nathanw static int
     92  1.3.2.2  nathanw mlx_eisa_match(struct device *parent, struct cfdata *match, void *aux)
     93  1.3.2.2  nathanw {
     94  1.3.2.2  nathanw 	struct eisa_attach_args *ea;
     95  1.3.2.2  nathanw 	int i;
     96  1.3.2.2  nathanw 
     97  1.3.2.2  nathanw 	ea = aux;
     98  1.3.2.2  nathanw 
     99  1.3.2.2  nathanw 	for (i = 0; i < sizeof(mlx_eisa_prod) / sizeof(mlx_eisa_prod[0]); i++)
    100  1.3.2.2  nathanw 		if (strcmp(ea->ea_idstring, mlx_eisa_prod[i]) == 0)
    101  1.3.2.2  nathanw 			return (1);
    102  1.3.2.2  nathanw 
    103  1.3.2.2  nathanw 	return (0);
    104  1.3.2.2  nathanw }
    105  1.3.2.2  nathanw 
    106  1.3.2.2  nathanw static void
    107  1.3.2.2  nathanw mlx_eisa_attach(struct device *parent, struct device *self, void *aux)
    108  1.3.2.2  nathanw {
    109  1.3.2.2  nathanw 	struct eisa_attach_args *ea;
    110  1.3.2.2  nathanw 	bus_space_handle_t ioh;
    111  1.3.2.2  nathanw 	eisa_chipset_tag_t ec;
    112  1.3.2.2  nathanw 	eisa_intr_handle_t ih;
    113  1.3.2.2  nathanw 	struct mlx_softc *mlx;
    114  1.3.2.2  nathanw 	bus_space_tag_t iot;
    115  1.3.2.2  nathanw 	const char *intrstr;
    116  1.3.2.2  nathanw 	int irq, le;
    117  1.3.2.2  nathanw 
    118  1.3.2.2  nathanw 	ea = aux;
    119  1.3.2.2  nathanw 	mlx = (struct mlx_softc *)self;
    120  1.3.2.2  nathanw 	iot = ea->ea_iot;
    121  1.3.2.2  nathanw 	ec = ea->ea_ec;
    122  1.3.2.2  nathanw 
    123  1.3.2.2  nathanw 	if (bus_space_map(iot, EISA_SLOT_ADDR(ea->ea_slot) +
    124  1.3.2.2  nathanw 	    MLX_EISA_SLOT_OFFSET, MLX_EISA_IOSIZE, 0, &ioh)) {
    125  1.3.2.2  nathanw 		printf("can't map i/o space\n");
    126  1.3.2.2  nathanw 		return;
    127  1.3.2.2  nathanw 	}
    128  1.3.2.2  nathanw 
    129  1.3.2.2  nathanw 	mlx->mlx_iot = iot;
    130  1.3.2.2  nathanw 	mlx->mlx_ioh = ioh;
    131  1.3.2.2  nathanw 	mlx->mlx_dmat = ea->ea_dmat;
    132  1.3.2.2  nathanw 
    133  1.3.2.2  nathanw 	/*
    134  1.3.2.2  nathanw 	 * Map and establish the interrupt.
    135  1.3.2.2  nathanw 	 */
    136  1.3.2.2  nathanw 	switch (bus_space_read_1(iot, ioh, MLX_EISA_IOCONF1) & 0xf0) {
    137  1.3.2.2  nathanw 	case 0xa0:
    138  1.3.2.2  nathanw 		irq = 11;
    139  1.3.2.2  nathanw 		break;
    140  1.3.2.2  nathanw 	case 0xc0:
    141  1.3.2.2  nathanw 		irq = 12;
    142  1.3.2.2  nathanw 		break;
    143  1.3.2.2  nathanw 	case 0xe0:
    144  1.3.2.2  nathanw 		irq = 14;
    145  1.3.2.2  nathanw 		break;
    146  1.3.2.2  nathanw 	case 0x80:
    147  1.3.2.2  nathanw 		irq = 15;
    148  1.3.2.2  nathanw 		break;
    149  1.3.2.2  nathanw 	default:
    150  1.3.2.2  nathanw 		printf("controller on invalid IRQ\n");
    151  1.3.2.2  nathanw 		return;
    152  1.3.2.2  nathanw 	}
    153  1.3.2.2  nathanw 
    154  1.3.2.2  nathanw 	if (eisa_intr_map(ec, irq, &ih)) {
    155  1.3.2.2  nathanw 		printf("can't map interrupt (%d)\n", irq);
    156  1.3.2.2  nathanw 		return;
    157  1.3.2.2  nathanw 	}
    158  1.3.2.2  nathanw 
    159  1.3.2.2  nathanw 	if ((bus_space_read_1(iot, ioh, MLX_EISA_IOCONF1) & 0x08) != 0)
    160  1.3.2.2  nathanw 		le = IST_LEVEL;
    161  1.3.2.2  nathanw 	else
    162  1.3.2.2  nathanw 		le = IST_EDGE;
    163  1.3.2.2  nathanw 
    164  1.3.2.2  nathanw 	intrstr = eisa_intr_string(ec, ih);
    165  1.3.2.2  nathanw 	mlx->mlx_ih = eisa_intr_establish(ec, ih, le, IPL_BIO, mlx_intr, mlx);
    166  1.3.2.2  nathanw 	if (mlx->mlx_ih == NULL) {
    167  1.3.2.2  nathanw 		printf("can't establish interrupt");
    168  1.3.2.2  nathanw 		if (intrstr != NULL)
    169  1.3.2.2  nathanw 			printf(" at %s", intrstr);
    170  1.3.2.2  nathanw 		printf("\n");
    171  1.3.2.2  nathanw 		return;
    172  1.3.2.2  nathanw 	}
    173  1.3.2.2  nathanw 
    174  1.3.2.2  nathanw 	mlx->mlx_flags = MLXF_EISA;
    175  1.3.2.2  nathanw 
    176  1.3.2.2  nathanw 	mlx->mlx_submit = mlx_v1_submit;
    177  1.3.2.2  nathanw 	mlx->mlx_findcomplete = mlx_v1_findcomplete;
    178  1.3.2.2  nathanw 	mlx->mlx_intaction = mlx_v1_intaction;
    179  1.3.2.2  nathanw 	mlx->mlx_fw_handshake = mlx_v1_fw_handshake;
    180  1.3.2.2  nathanw #ifdef MLX_RESET
    181  1.3.2.2  nathanw 	mlx->mlx_reset = mlx_v1_reset;
    182  1.3.2.2  nathanw #endif
    183  1.3.2.2  nathanw 
    184  1.3.2.2  nathanw 	printf(": Mylex RAID\n");
    185  1.3.2.2  nathanw 	mlx_init(mlx, intrstr);
    186  1.3.2.2  nathanw }
    187  1.3.2.2  nathanw 
    188  1.3.2.2  nathanw /*
    189  1.3.2.2  nathanw  * ================= V1 interface linkage =================
    190  1.3.2.2  nathanw  */
    191  1.3.2.2  nathanw 
    192  1.3.2.2  nathanw /*
    193  1.3.2.2  nathanw  * Try to give (mc) to the controller.  Returns 1 if successful, 0 on
    194  1.3.2.2  nathanw  * failure (the controller is not ready to take a command).
    195  1.3.2.2  nathanw  *
    196  1.3.2.2  nathanw  * Must be called at splbio or in a fashion that prevents reentry.
    197  1.3.2.2  nathanw  */
    198  1.3.2.2  nathanw static int
    199  1.3.2.2  nathanw mlx_v1_submit(struct mlx_softc *mlx, struct mlx_ccb *mc)
    200  1.3.2.2  nathanw {
    201  1.3.2.2  nathanw 
    202  1.3.2.2  nathanw 	/* Ready for our command? */
    203  1.3.2.2  nathanw 	if ((mlx_inb(mlx, MLX_V1REG_IDB) & MLX_V1_IDB_FULL) == 0) {
    204  1.3.2.2  nathanw 		/* Copy mailbox data to window. */
    205  1.3.2.2  nathanw 		bus_space_write_region_1(mlx->mlx_iot, mlx->mlx_ioh,
    206  1.3.2.2  nathanw 		    MLX_V1REG_MAILBOX, mc->mc_mbox, MLX_V1_MAILBOX_LEN);
    207  1.3.2.2  nathanw 		bus_space_barrier(mlx->mlx_iot, mlx->mlx_ioh,
    208  1.3.2.2  nathanw 		    MLX_V1REG_MAILBOX, MLX_V1_MAILBOX_LEN,
    209  1.3.2.2  nathanw 		    BUS_SPACE_BARRIER_WRITE);
    210  1.3.2.2  nathanw 
    211  1.3.2.2  nathanw 		/* Post command. */
    212  1.3.2.2  nathanw 		mlx_outb(mlx, MLX_V1REG_IDB, MLX_V3_IDB_FULL);
    213  1.3.2.2  nathanw 		return (1);
    214  1.3.2.2  nathanw 	}
    215  1.3.2.2  nathanw 
    216  1.3.2.2  nathanw 	return (0);
    217  1.3.2.2  nathanw }
    218  1.3.2.2  nathanw 
    219  1.3.2.2  nathanw /*
    220  1.3.2.2  nathanw  * See if a command has been completed, if so acknowledge its completion and
    221  1.3.2.2  nathanw  * recover the slot number and status code.
    222  1.3.2.2  nathanw  *
    223  1.3.2.2  nathanw  * Must be called at splbio or in a fashion that prevents reentry.
    224  1.3.2.2  nathanw  */
    225  1.3.2.2  nathanw static int
    226  1.3.2.2  nathanw mlx_v1_findcomplete(struct mlx_softc *mlx, u_int *slot, u_int *status)
    227  1.3.2.2  nathanw {
    228  1.3.2.2  nathanw 
    229  1.3.2.2  nathanw 	/* Status available? */
    230  1.3.2.2  nathanw 	if ((mlx_inb(mlx, MLX_V3REG_ODB) & MLX_V3_ODB_SAVAIL) != 0) {
    231  1.3.2.2  nathanw 		*slot = mlx_inb(mlx, MLX_V1REG_MAILBOX + 0x0d);
    232  1.3.2.2  nathanw 		*status = mlx_inw(mlx, MLX_V1REG_MAILBOX + 0x0e);
    233  1.3.2.2  nathanw 
    234  1.3.2.2  nathanw 		/* Acknowledge completion. */
    235  1.3.2.2  nathanw 		mlx_outb(mlx, MLX_V1REG_ODB, MLX_V1_ODB_SAVAIL);
    236  1.3.2.2  nathanw 		mlx_outb(mlx, MLX_V1REG_IDB, MLX_V1_IDB_SACK);
    237  1.3.2.2  nathanw 		return (1);
    238  1.3.2.2  nathanw 	}
    239  1.3.2.2  nathanw 
    240  1.3.2.2  nathanw 	return (0);
    241  1.3.2.2  nathanw }
    242  1.3.2.2  nathanw 
    243  1.3.2.2  nathanw /*
    244  1.3.2.2  nathanw  * Enable/disable interrupts as requested. (No acknowledge required)
    245  1.3.2.2  nathanw  *
    246  1.3.2.2  nathanw  * Must be called at splbio or in a fashion that prevents reentry.
    247  1.3.2.2  nathanw  */
    248  1.3.2.2  nathanw static void
    249  1.3.2.2  nathanw mlx_v1_intaction(struct mlx_softc *mlx, int action)
    250  1.3.2.2  nathanw {
    251  1.3.2.2  nathanw 
    252  1.3.2.2  nathanw 	mlx_outb(mlx, MLX_V1REG_IE, action ? 1 : 0);
    253  1.3.2.2  nathanw }
    254  1.3.2.2  nathanw 
    255  1.3.2.2  nathanw /*
    256  1.3.2.2  nathanw  * Poll for firmware error codes during controller initialisation.
    257  1.3.2.2  nathanw  *
    258  1.3.2.2  nathanw  * Returns 0 if initialisation is complete, 1 if still in progress but no
    259  1.3.2.2  nathanw  * error has been fetched, 2 if an error has been retrieved.
    260  1.3.2.2  nathanw  */
    261  1.3.2.2  nathanw static int
    262  1.3.2.2  nathanw mlx_v1_fw_handshake(struct mlx_softc *mlx, int *error, int *param1, int *param2)
    263  1.3.2.2  nathanw {
    264  1.3.2.2  nathanw 	u_int8_t fwerror;
    265  1.3.2.2  nathanw 
    266  1.3.2.2  nathanw 	/*
    267  1.3.2.2  nathanw 	 * First time around, enable the IDB interrupt and clear any
    268  1.3.2.2  nathanw 	 * hardware completion status.
    269  1.3.2.2  nathanw 	 */
    270  1.3.2.2  nathanw 	if ((mlx->mlx_flags & MLXF_FW_INITTED) == 0) {
    271  1.3.2.2  nathanw 		mlx_outb(mlx, MLX_V1REG_ODB_EN, 1);
    272  1.3.2.2  nathanw 		DELAY(1000);
    273  1.3.2.4  nathanw 		mlx_outb(mlx, MLX_V1REG_ODB, 1);
    274  1.3.2.4  nathanw 		DELAY(1000);
    275  1.3.2.2  nathanw 		mlx_outb(mlx, MLX_V1REG_IDB, MLX_V1_IDB_SACK);
    276  1.3.2.2  nathanw 		DELAY(1000);
    277  1.3.2.2  nathanw 		mlx->mlx_flags |= MLXF_FW_INITTED;
    278  1.3.2.2  nathanw 	}
    279  1.3.2.2  nathanw 
    280  1.3.2.2  nathanw 	/* Init in progress? */
    281  1.3.2.2  nathanw 	if ((mlx_inb(mlx, MLX_V1REG_IDB) & MLX_V1_IDB_INIT_BUSY) == 0)
    282  1.3.2.2  nathanw 		return (0);
    283  1.3.2.2  nathanw 
    284  1.3.2.2  nathanw 	/* Test error value. */
    285  1.3.2.2  nathanw 	fwerror = mlx_inb(mlx, MLX_V1REG_ODB);
    286  1.3.2.2  nathanw 
    287  1.3.2.2  nathanw 	if ((fwerror & MLX_V1_FWERROR_PEND) == 0)
    288  1.3.2.2  nathanw 		return (1);
    289  1.3.2.2  nathanw 
    290  1.3.2.2  nathanw 	/* XXX Fetch status. */
    291  1.3.2.2  nathanw 	*error = fwerror & 0xf0;
    292  1.3.2.2  nathanw 	*param1 = -1;
    293  1.3.2.2  nathanw 	*param2 = -1;
    294  1.3.2.2  nathanw 
    295  1.3.2.2  nathanw 	/* Acknowledge. */
    296  1.3.2.2  nathanw 	mlx_outb(mlx, MLX_V1REG_ODB, fwerror);
    297  1.3.2.2  nathanw 
    298  1.3.2.2  nathanw 	return (2);
    299  1.3.2.2  nathanw }
    300  1.3.2.2  nathanw 
    301  1.3.2.2  nathanw #ifdef MLX_RESET
    302  1.3.2.2  nathanw /*
    303  1.3.2.2  nathanw  * Reset the controller.  Return non-zero on failure.
    304  1.3.2.2  nathanw  */
    305  1.3.2.2  nathanw static int
    306  1.3.2.2  nathanw mlx_v1_reset(struct mlx_softc *mlx)
    307  1.3.2.2  nathanw {
    308  1.3.2.2  nathanw 	int i;
    309  1.3.2.2  nathanw 
    310  1.3.2.2  nathanw 	mlx_outb(mlx, MLX_V1REG_IDB, MLX_V1_IDB_SACK);
    311  1.3.2.2  nathanw 	delay(1000000);
    312  1.3.2.2  nathanw 
    313  1.3.2.2  nathanw 	/* Wait up to 2 minutes for the bit to clear. */
    314  1.3.2.2  nathanw 	for (i = 120; i != 0; i--) {
    315  1.3.2.2  nathanw 		delay(1000000);
    316  1.3.2.2  nathanw 		if ((mlx_inb(mlx, MLX_V1REG_IDB) & MLX_V1_IDB_SACK) == 0)
    317  1.3.2.2  nathanw 			break;
    318  1.3.2.2  nathanw 	}
    319  1.3.2.2  nathanw 	if (i == 0)
    320  1.3.2.2  nathanw 		return (-1);
    321  1.3.2.2  nathanw 
    322  1.3.2.2  nathanw 	mlx_outb(mlx, MLX_V1REG_ODB, MLX_V1_ODB_RESET);
    323  1.3.2.2  nathanw 	mlx_outb(mlx, MLX_V1REG_IDB, MLX_V1_IDB_RESET);
    324  1.3.2.2  nathanw 
    325  1.3.2.2  nathanw 	/* Wait up to 5 seconds for the bit to clear... */
    326  1.3.2.2  nathanw 	for (i = 5; i != 0; i--) {
    327  1.3.2.2  nathanw 		delay(1000000);
    328  1.3.2.2  nathanw 		if ((mlx_inb(mlx, MLX_V1REG_IDB) & MLX_V1_IDB_RESET) == 0)
    329  1.3.2.2  nathanw 			break;
    330  1.3.2.2  nathanw 	}
    331  1.3.2.2  nathanw 	if (i == 0)
    332  1.3.2.2  nathanw 		return (-1);
    333  1.3.2.2  nathanw 
    334  1.3.2.2  nathanw 	/* Wait up to 3 seconds for the other bit to clear... */
    335  1.3.2.2  nathanw 	for (i = 5; i != 0; i--) {
    336  1.3.2.2  nathanw 		delay(1000000);
    337  1.3.2.2  nathanw 		if ((mlx_inb(mlx, MLX_V1REG_ODB) & MLX_V1_ODB_RESET) == 0)
    338  1.3.2.2  nathanw 			break;
    339  1.3.2.2  nathanw 	}
    340  1.3.2.2  nathanw 	if (i == 0)
    341  1.3.2.2  nathanw 		return (-1);
    342  1.3.2.2  nathanw 
    343  1.3.2.2  nathanw 	return (0);
    344  1.3.2.2  nathanw }
    345  1.3.2.2  nathanw #endif	/* MLX_RESET */
    346