Home | History | Annotate | Download | only in io
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  *
     25  * The "bscbus" driver provides access to the LOMlite2 virtual registers,
     26  * so that its clients (children) need not be concerned with the details
     27  * of the access mechanism, which in this case is implemented via a
     28  * packet-based protocol over a Xbus (similar to ebus) parallel link to the
     29  * H8 host interface registers.
     30  *
     31  * On the other hand, this driver doesn't generally know what the virtual
     32  * registers signify - only the clients need this information.
     33  */
     34 
     35 
     36 #include <sys/note.h>
     37 #include <sys/types.h>
     38 #include <sys/conf.h>
     39 #include <sys/debug.h>
     40 #include <sys/errno.h>
     41 #include <sys/file.h>
     42 
     43 #if defined(__sparc)
     44 #include <sys/intr.h>
     45 #include <sys/membar.h>
     46 #endif
     47 
     48 #include <sys/kmem.h>
     49 #include <sys/modctl.h>
     50 #include <sys/note.h>
     51 #include <sys/open.h>
     52 #include <sys/poll.h>
     53 #include <sys/spl.h>
     54 #include <sys/stat.h>
     55 #include <sys/strlog.h>
     56 #include <sys/atomic.h>
     57 
     58 #include <sys/ddi.h>
     59 #include <sys/sunddi.h>
     60 #include <sys/sunndi.h>
     61 
     62 #include <sys/bscbus.h>
     63 
     64 #if	defined(NDI_ACC_HDL_V2)
     65 
     66 /*
     67  * Compiling for Solaris 10+ with access handle enhancements
     68  */
     69 #define	HANDLE_TYPE		ndi_acc_handle_t
     70 #define	HANDLE_ADDR(hdlp)	(hdlp->ah_addr)
     71 #define	HANDLE_FAULT(hdlp)	(hdlp->ah_fault)
     72 #define	HANDLE_MAPLEN(hdlp)	(hdlp->ah_len)
     73 #define	HANDLE_PRIVATE(hdlp)	(hdlp->ah_bus_private)
     74 
     75 #else
     76 
     77 /*
     78  * Compatibility definitions for backport to Solaris 8/9
     79  */
     80 #define	HANDLE_TYPE		ddi_acc_impl_t
     81 #define	HANDLE_ADDR(hdlp)	(hdlp->ahi_common.ah_addr)
     82 #define	HANDLE_FAULT(hdlp)	(hdlp->ahi_fault)
     83 #define	HANDLE_MAPLEN(hdlp)	(hdlp->ahi_common.ah_len)
     84 #define	HANDLE_PRIVATE(hdlp)	(hdlp->ahi_common.ah_bus_private)
     85 
     86 #define	ddi_driver_major(dip)	ddi_name_to_major(ddi_binding_name(dip))
     87 
     88 #endif	/* NDI_ACC_HDL_V2 */
     89 
     90 
     91 /*
     92  * Local definitions
     93  */
     94 #define	MYNAME			"bscbus"
     95 #define	NOMAJOR			(~(major_t)0)
     96 #define	DUMMY_VALUE		(~(int8_t)0)
     97 
     98 #define	BSCBUS_INST_TO_MINOR(i)	(i)
     99 #define	BSCBUS_MINOR_TO_INST(m)	(m)
    100 
    101 #define	BSCBUS_MAX_CHANNELS	(4)
    102 
    103 #define	BSCBUS_DUMMY_ADDRESS	((caddr_t)0x0CADD1ED)
    104 #define	ADDR_TO_OFFSET(a, hdlp)	((caddr_t)(a) - HANDLE_ADDR(hdlp))
    105 #define	ADDR_TO_VREG(a)		((caddr_t)(a) - BSCBUS_DUMMY_ADDRESS)
    106 #define	VREG_TO_ADDR(v)		(BSCBUS_DUMMY_ADDRESS + (v))
    107 
    108 #ifdef DEBUG
    109 #define	BSCBUS_LOGSTATUS
    110 #endif /* DEBUG */
    111 
    112 #ifdef BSCBUS_LOGSTATUS
    113 /*
    114  * BSC command logging routines.
    115  * Record the data passing to and from the BSC
    116  */
    117 
    118 typedef enum {
    119 	BSC_CMD_BUSY = 1,		/* bsc reports busy	*/
    120 	BSC_CMD_CLEARING = 2,		/* clearing bsc busy	*/
    121 	BSC_CMD_CLEARED = 3,		/* cleared bsc busy	*/
    122 	BSC_CMD_SENDING = 4,		/* sending next byte	*/
    123 	BSC_CMD_SENT = 5,		/* sending last byte	*/
    124 	BSC_CMD_PENDING = 6,		/* got sent byte ack	*/
    125 	BSC_CMD_REPLY = 7,		/* got reply byte	*/
    126 	BSC_CMD_COMPLETE = 8,		/* command complete	*/
    127 	BSC_CMD_ERROR_SEQ = 9,		/* error status		*/
    128 	BSC_CMD_ERROR_STATUS = 10,	/* error status		*/
    129 	BSC_CMD_ERROR_OFLOW = 11,	/* error status		*/
    130 	BSC_CMD_ERROR_TOUT = 12,	/* error status		*/
    131 
    132 	BSC_CMD_PROCESS = 13,		/* async intr		*/
    133 	BSC_CMD_V1INTR = 14,		/* v1 intr		*/
    134 	BSC_CMD_V1INTRUNCL = 15,	/* v1 intr unclaim	*/
    135 	BSC_CMD_DOGPAT = 17		/* watchdog pat		*/
    136 } bsc_cmd_stamp_t;
    137 
    138 typedef struct {
    139 	hrtime_t	bcl_now;
    140 	int		bcl_seq;
    141 	bsc_cmd_stamp_t	bcl_cat;
    142 	uint8_t		bcl_chno;
    143 	uint8_t		bcl_cmdstate;
    144 	uint8_t		bcl_status;
    145 	uint8_t		bcl_data;
    146 } bsc_cmd_log_t;
    147 
    148 uint32_t	bscbus_cmd_log_size = 1024;
    149 
    150 uint32_t	bscbus_cmd_log_flags = 0xffffffff;
    151 
    152 #endif /* BSCBUS_LOGSTATUS */
    153 
    154 /*
    155  * The following definitions are taken from the Hardware Manual for
    156  * the Hitachi H8S/2148 in conjunction with the hardware specification
    157  * for the Stiletto blade.
    158  *
    159  * Each instance of the host interface has 3 registers on the H8:
    160  * IDRn  - Input Data Register	- write-only for Solaris.
    161  *				  writes to this can be done via two
    162  *				  addresses - control and data.
    163  *				  The H8 can determine which address was
    164  *				  written by examining the C/D bit in
    165  *				  the status register.
    166  * ODRn  - Output Data Register - read-only for Solaris.
    167  *				  A read has the side effect of acknowledging
    168  *				  interrupts.
    169  * STRn  - Status Register	- read-only for Solaris.
    170  *
    171  *
    172  *
    173  * In terms of host access to this the Input and Output data registers are
    174  * mapped at the same address.
    175  */
    176 #define	H8_IDRD	0
    177 #define	H8_IDRC	1
    178 #define	H8_ODR	0
    179 #define	H8_STR	1
    180 
    181 #define	H8_STR_OBF		0x01	/* data available in ODR */
    182 #define	H8_STR_IBF		0x02	/* data for H8 in IDR */
    183 #define	H8_STR_IDRC		0x08	/* last write to IDR was to IDRC */
    184 					/* 0=data, 1=command */
    185 #define	H8_STR_BUSY		0x04	/* H8 busy processing command */
    186 #define	H8_STR_TOKENPROTOCOL	0x80	/* token-passing protocol */
    187 
    188 /*
    189  * Packet format ...
    190  */
    191 #define	BSCBUS_MASK		0xc0	/* Byte-type bits		*/
    192 #define	BSCBUS_PARAM		0x00	/* Parameter byte: 0b0xxxxxxx	*/
    193 #define	BSCBUS_LAST		0x80	/* Last byte of packet		*/
    194 #define	BSCBUS_CMD		0x80	/* Command byte:   0b10###XWV	*/
    195 #define	BSCBUS_STATUS		0xc0	/* Status  byte:   0b11###AEV	*/
    196 
    197 #define	BSCBUS_SEQ		0x38	/* Sequence number bits		*/
    198 #define	BSCBUS_SEQ_LSB		0x08	/* Sequence number LSB		*/
    199 #define	BSCBUS_CMD_XADDR	0x04	/* Extended (2-byte) addressing	*/
    200 #define	BSCBUS_CMD_WRITE	0x02	/* Write command		*/
    201 #define	BSCBUS_CMD_WMSB		0x01	/* Set MSB on Write		*/
    202 #define	BSCBUS_CMD_READ		0x01	/* Read command			*/
    203 #define	BSCBUS_CMD_NOP		0x00	/* NOP command			*/
    204 
    205 #define	BSCBUS_STATUS_ASYNC	0x04	/* Asynchronous event pending	*/
    206 #define	BSCBUS_STATUS_ERR	0x02	/* Error in command processing	*/
    207 #define	BSCBUS_STATUS_MSB	0x01	/* MSB of Value read		*/
    208 
    209 #define	BSCBUS_VREG_LO(x)	((x) & ((1 << 7) - 1))
    210 #define	BSCBUS_VREG_HI(x)	((x) >> 7)
    211 
    212 #define	BSCBUS_BUFSIZE		8
    213 
    214 #define	BSCBUS_CHANNEL_TO_OFFSET(chno)	((chno) * 2)	/* Register offset */
    215 
    216 /*
    217  * Time periods, in nanoseconds
    218  *
    219  * Note that LOMBUS_ONE_SEC and some other time
    220  * periods are defined in <sys/lombus.h>
    221  */
    222 #define	BSCBUS_CMD_POLL			(LOMBUS_ONE_SEC)
    223 #define	BSCBUS_CMD_POLLNOINTS		(LOMBUS_ONE_SEC/20)
    224 #define	BSCBUS_HWRESET_POLL		(LOMBUS_ONE_SEC/20)
    225 #define	BSCBUS_HWRESET_TIMEOUT		(LOMBUS_ONE_SEC*2)
    226 
    227 #define	BSCBUS_DOG_PAT_POLL_LIMIT	(1000)
    228 #define	BSCBUS_DOG_PAT_POLL		(1)
    229 #define	BSCBUS_PAT_RETRY_LIMIT	5
    230 
    231 /*
    232  * Local datatypes
    233  */
    234 enum bscbus_cmdstate {
    235 	BSCBUS_CMDSTATE_IDLE,		/* No transaction in progress */
    236 	BSCBUS_CMDSTATE_BUSY,		/* Setting up command */
    237 	BSCBUS_CMDSTATE_CLEARING,	/* Clearing firmware busy status */
    238 	BSCBUS_CMDSTATE_SENDING,	/* Waiting to send data to f/w */
    239 	BSCBUS_CMDSTATE_PENDING,	/* Waiting for ack from f/w */
    240 	BSCBUS_CMDSTATE_WAITING,	/* Waiting for status from f/w */
    241 	BSCBUS_CMDSTATE_READY,		/* Status received/command done */
    242 	BSCBUS_CMDSTATE_ERROR		/* Command failed with error */
    243 };
    244 
    245 struct bscbus_channel_state {
    246 	/* Changes to these are protected by the instance ch_mutex mutex */
    247 	struct bscbus_state	*ssp;
    248 	uint8_t			*ch_regs;
    249 	ddi_acc_handle_t	ch_handle;  /* per channel access handle */
    250 	unsigned int		chno;
    251 	unsigned int		map_count; /* Number of mappings to channel */
    252 	boolean_t		map_dog;   /* channel is mapped for watchdog */
    253 
    254 	/*
    255 	 * Flag to indicate that we've incurred a hardware fault on
    256 	 * accesses to the H8; once this is set, we fake all further
    257 	 * accesses in order not to provoke additional bus errors.
    258 	 */
    259 	boolean_t		xio_fault;
    260 
    261 	/*
    262 	 * Data protected by the dog_mutex: the watchdog-patting
    263 	 * protocol data (since the dog can be patted from a high-level
    264 	 * cyclic), and the interrupt-enabled flag.
    265 	 */
    266 	kmutex_t		dog_mutex[1];
    267 	unsigned int		pat_retry_count;
    268 	unsigned int		pat_fail_count;
    269 
    270 	/*
    271 	 * Serial protocol state data, protected by lo_mutex
    272 	 * (which is initialised using <lo_iblk>)
    273 	 */
    274 	kmutex_t		lo_mutex[1];
    275 	ddi_iblock_cookie_t	lo_iblk;
    276 	kcondvar_t		lo_cv[1];
    277 	int			unclaimed_count;
    278 
    279 	volatile enum bscbus_cmdstate cmdstate;
    280 	clock_t			deadline;
    281 	clock_t			poll_hz;
    282 	boolean_t		interrupt_failed;
    283 	uint8_t 		cmdbuf[BSCBUS_BUFSIZE];
    284 	uint8_t			*cmdp;	/* Points to last tx'd in cmdbuf */
    285 	uint8_t			reply[BSCBUS_BUFSIZE];
    286 	uint8_t			async;
    287 	uint8_t			index;
    288 	uint8_t			result;
    289 	uint8_t			sequence;
    290 	uint32_t		error;
    291 };
    292 
    293 #define	BSCBUS_TX_PENDING(csp)		((csp)->cmdp > (csp)->cmdbuf)
    294 
    295 /*
    296  * This driver's soft-state structure
    297  */
    298 
    299 struct bscbus_state {
    300 	/*
    301 	 * Configuration data, set during attach
    302 	 */
    303 	dev_info_t		*dip;
    304 	major_t			majornum;
    305 	int			instance;
    306 
    307 	ddi_acc_handle_t	h8_handle;
    308 	uint8_t			*h8_regs;
    309 
    310 	/*
    311 	 * Parameters derived from .conf properties
    312 	 */
    313 	uint32_t		debug;
    314 
    315 	/*
    316 	 * Flag to indicate that we are using per channel
    317 	 * mapping of the register sets and interrupts.
    318 	 * reg set 0 is chan 0
    319 	 * reg set 1 is chan 1 ...
    320 	 *
    321 	 * Interrupts are specified in that order but later
    322 	 * channels may not have interrupts.
    323 	 */
    324 	boolean_t		per_channel_regs;
    325 
    326 	/*
    327 	 * channel state data, protected by ch_mutex
    328 	 * channel claim/release requests are protected by this mutex.
    329 	 */
    330 	kmutex_t		ch_mutex[1];
    331 	struct bscbus_channel_state	channel[BSCBUS_MAX_CHANNELS];
    332 
    333 #ifdef BSCBUS_LOGSTATUS
    334 	/*
    335 	 * Command logging buffer for recording transactions with the
    336 	 * BSC. This is useful for debugging failed transactions and other
    337 	 * such funnies.
    338 	 */
    339 	bsc_cmd_log_t		*cmd_log;
    340 	uint32_t		cmd_log_idx;
    341 	uint32_t		cmd_log_size;
    342 	uint32_t		cmd_log_flags;
    343 #endif /* BSCBUS_LOGSTATUS */
    344 };
    345 
    346 /*
    347  * The auxiliary structure attached to each child
    348  * (the child's parent-private-data points to this).
    349  */
    350 struct bscbus_child_info {
    351 	lombus_regspec_t *rsp;
    352 	int nregs;
    353 };
    354 
    355 #ifdef BSCBUS_LOGSTATUS
    356 void bscbus_cmd_log(struct bscbus_channel_state *, bsc_cmd_stamp_t,
    357     uint8_t, uint8_t);
    358 #else /* BSCBUS_LOGSTATUS */
    359 #define	bscbus_cmd_log(state, stamp, status, data)
    360 #endif /* BSCBUS_LOGSTATUS */
    361 
    362 
    363 /*
    364  * Local data
    365  */
    366 
    367 static void *bscbus_statep;
    368 
    369 static major_t bscbus_major = NOMAJOR;
    370 
    371 static ddi_device_acc_attr_t bscbus_dev_acc_attr[1] = {
    372 	DDI_DEVICE_ATTR_V0,
    373 	DDI_STRUCTURE_LE_ACC,
    374 	DDI_STRICTORDER_ACC
    375 };
    376 
    377 
    378 /*
    379  *  General utility routines ...
    380  */
    381 
    382 #ifdef DEBUG
    383 static void
    384 bscbus_trace(struct bscbus_channel_state *csp, char code, const char *caller,
    385 	const char *fmt, ...)
    386 {
    387 	char buf[256];
    388 	char *p;
    389 	va_list va;
    390 
    391 	if (csp->ssp->debug & (1 << (code-'@'))) {
    392 		p = buf;
    393 		(void) snprintf(p, sizeof (buf) - (p - buf),
    394 		    "%s/%s: ", MYNAME, caller);
    395 		p += strlen(p);
    396 
    397 		va_start(va, fmt);
    398 		(void) vsnprintf(p, sizeof (buf) - (p - buf), fmt, va);
    399 		va_end(va);
    400 
    401 		buf[sizeof (buf) - 1] = '\0';
    402 		(void) strlog(csp->ssp->majornum, csp->ssp->instance,
    403 		    code, SL_TRACE, buf);
    404 	}
    405 }
    406 #else /* DEBUG */
    407 #define	bscbus_trace
    408 #endif /* DEBUG */
    409 
    410 static struct bscbus_state *
    411 bscbus_getstate(dev_info_t *dip, int instance, const char *caller)
    412 {
    413 	struct bscbus_state *ssp = NULL;
    414 	dev_info_t *sdip = NULL;
    415 	major_t dmaj = NOMAJOR;
    416 
    417 	if (dip != NULL) {
    418 		/*
    419 		 * Use the instance number from the <dip>; also,
    420 		 * check that it really corresponds to this driver
    421 		 */
    422 		instance = ddi_get_instance(dip);
    423 		dmaj = ddi_driver_major(dip);
    424 		if (bscbus_major == NOMAJOR && dmaj != NOMAJOR)
    425 			bscbus_major = dmaj;
    426 		else if (dmaj != bscbus_major) {
    427 			cmn_err(CE_WARN,
    428 			    "%s: major number mismatch (%d vs. %d) in %s(),"
    429 			    "probably due to child misconfiguration",
    430 			    MYNAME, bscbus_major, dmaj, caller);
    431 			instance = -1;
    432 		}
    433 	}
    434 
    435 	if (instance >= 0)
    436 		ssp = ddi_get_soft_state(bscbus_statep, instance);
    437 	if (ssp != NULL) {
    438 		sdip = ssp->dip;
    439 		if (dip == NULL && sdip == NULL)
    440 			ssp = NULL;
    441 		else if (dip != NULL && sdip != NULL && sdip != dip) {
    442 			cmn_err(CE_WARN,
    443 			    "%s: devinfo mismatch (%p vs. %p) in %s(), "
    444 			    "probably due to child misconfiguration",
    445 			    MYNAME, (void *)dip, (void *)sdip, caller);
    446 			ssp = NULL;
    447 		}
    448 	}
    449 
    450 	return (ssp);
    451 }
    452 
    453 /*
    454  * Lowest-level I/O register read/write
    455  */
    456 
    457 static void
    458 bscbus_put_reg(struct bscbus_channel_state *csp, uint_t reg, uint8_t val)
    459 {
    460 	if (csp->ch_handle != NULL && !csp->xio_fault) {
    461 		ddi_put8(csp->ch_handle,
    462 		    csp->ch_regs + reg, val);
    463 	}
    464 }
    465 
    466 static uint8_t
    467 bscbus_get_reg(struct bscbus_channel_state *csp, uint_t reg)
    468 {
    469 	uint8_t val;
    470 
    471 	if (csp->ch_handle != NULL && !csp->xio_fault)
    472 		val = ddi_get8(csp->ch_handle,
    473 		    csp->ch_regs + reg);
    474 	else
    475 		val = DUMMY_VALUE;
    476 
    477 	return (val);
    478 }
    479 
    480 static void
    481 bscbus_check_fault_status(struct bscbus_channel_state *csp)
    482 {
    483 	csp->xio_fault =
    484 	    ddi_check_acc_handle(csp->ch_handle) != DDI_SUCCESS;
    485 }
    486 
    487 static boolean_t
    488 bscbus_faulty(struct bscbus_channel_state *csp)
    489 {
    490 	if (!csp->xio_fault)
    491 		bscbus_check_fault_status(csp);
    492 	return (csp->xio_fault);
    493 }
    494 
    495 /*
    496  * Write data into h8 registers
    497  */
    498 static void
    499 bscbus_pat_dog(struct bscbus_channel_state *csp, uint8_t val)
    500 {
    501 	uint8_t status;
    502 	uint32_t doglimit = BSCBUS_DOG_PAT_POLL_LIMIT;
    503 
    504 	bscbus_trace(csp, 'W', "bscbus_pat_dog:", "");
    505 
    506 	bscbus_cmd_log(csp, BSC_CMD_DOGPAT, 0, val);
    507 	status = bscbus_get_reg(csp, H8_STR);
    508 	while (status & H8_STR_IBF) {
    509 		if (csp->pat_retry_count > BSCBUS_PAT_RETRY_LIMIT) {
    510 			/*
    511 			 * Previous attempts to contact BSC have failed.
    512 			 * Do not bother waiting for it to eat previous
    513 			 * data.
    514 			 * Pat anyway just in case the BSC is really alive
    515 			 * and the IBF bit is lying.
    516 			 */
    517 			bscbus_put_reg(csp, H8_IDRC, val);
    518 			bscbus_trace(csp, 'W', "bscbus_pat_dog:",
    519 			    "retry count exceeded");
    520 			return;
    521 		}
    522 		if (--doglimit == 0) {
    523 			/* The BSC is not responding - give up */
    524 			csp->pat_fail_count++;
    525 			csp->pat_retry_count++;
    526 			/* Pat anyway just in case the BSC is really alive */
    527 			bscbus_put_reg(csp, H8_IDRC, val);
    528 			bscbus_trace(csp, 'W', "bscbus_pat_dog:",
    529 			    "poll limit exceeded");
    530 			return;
    531 		}
    532 		drv_usecwait(BSCBUS_DOG_PAT_POLL);
    533 		status = bscbus_get_reg(csp, H8_STR);
    534 	}
    535 	bscbus_put_reg(csp, H8_IDRC, val);
    536 	csp->pat_retry_count = 0;
    537 }
    538 
    539 /*
    540  * State diagrams for how bscbus_process works.
    541  *	BSCBUS_CMDSTATE_IDLE		No transaction in progress
    542  *	BSCBUS_CMDSTATE_BUSY		Setting up command
    543  *	BSCBUS_CMDSTATE_CLEARING	Clearing firmware busy status
    544  *	BSCBUS_CMDSTATE_SENDING		Waiting to send data to f/w
    545  *	BSCBUS_CMDSTATE_PENDING		Waiting for ack from f/w
    546  *	BSCBUS_CMDSTATE_WAITING		Waiting for status from f/w
    547  *	BSCBUS_CMDSTATE_READY		Status received/command done
    548  *	BSCBUS_CMDSTATE_ERROR		Command failed with error
    549  *
    550  *	+----------+
    551  *	|	   |
    552  *	| IDLE/BUSY|
    553  *	|   (0/1)  |  abnormal
    554  *	+----------+  state
    555  *	    |	  \   detected
    556  *	    |	   \------>------+  +----<---+
    557  *	bsc |			 |  |	     |
    558  *	is  |			 V  V	     |
    559  *     ready|		     +----------+    |
    560  *	    |		     |		|    ^
    561  *	    |		     | CLEARING |    |
    562  *	    |		     |	 (2)	|    |
    563  *	    |		     +----------+    |
    564  *	    |		 cleared /  | \	     | more to clear
    565  *	    |			/   |  \-->--+
    566  *	    |  +-------<-------/    V
    567  *	    |  |		    |
    568  *	    V  V		    |timeout
    569  *	+----------+ timeout	    |
    570  *	|	   |------>---------+--------+
    571  *	| SENDING  |			     |
    572  *	|   (3)	   |------<-------+	     |
    573  *	+----------+		  |	     V
    574  *	sent|	 \ send		  ^ack	     |
    575  *	last|	  \ next	  |received  |
    576  *	    |	   \	     +----------+    |
    577  *	    |	    \	     |		|    |
    578  *	    |	     \------>| PENDING	|-->-+
    579  *	    |		     |	 (4)	|    |
    580  *	    |		     +----------+    |timeout
    581  *	    |	 +---<----+		     |
    582  *	    |	 |	  |		     |
    583  *	    V	 V	  |		     |
    584  *	+----------+	  |		     |
    585  *	|	   |	  |		     |
    586  *	| WAITING  |	  ^		     |
    587  *	|   (5)	   |	  |		     |
    588  *	+----------+	  |		     |
    589  *	    |  | |more	  |		     |
    590  *	    |  V |required|		     |
    591  *	done|  | +--->----+		     |
    592  *	    |  +--->--------------+  +---<---+
    593  *	    |	error/timeout	  |  |
    594  *	    V			  V  V
    595  *	+----------+	      +----------+
    596  *	|	   |	      |		 |
    597  *	| READY	   |	      |	 ERROR	 |
    598  *	|   (7)	   |	      |	  (6)	 |
    599  *	+----------+	      +----------+
    600  *	    |			  |
    601  *	    V			  V
    602  *	    |			  |
    603  *	    +------>---+---<------+
    604  *		       |
    605  *		       |
    606  *		     Back to
    607  *		      Idle
    608  */
    609 
    610 static void
    611 bscbus_process_sending(struct bscbus_channel_state *csp, uint8_t status)
    612 {
    613 	/*
    614 	 * When we get here we actually expect H8_STR_IBF to
    615 	 * be clear but we check just in case of problems.
    616 	 */
    617 	ASSERT(BSCBUS_TX_PENDING(csp));
    618 	if (!(status & H8_STR_IBF)) {
    619 		bscbus_put_reg(csp, H8_IDRD, *--csp->cmdp);
    620 		bscbus_trace(csp, 'P', "bscbus_process_sending",
    621 		    "state %d; val $%x",
    622 		    csp->cmdstate, *csp->cmdp);
    623 		if (!BSCBUS_TX_PENDING(csp)) {
    624 			bscbus_cmd_log(csp, BSC_CMD_SENT,
    625 			    status, *csp->cmdp);
    626 			/* No more pending - move to waiting state */
    627 			bscbus_trace(csp, 'P', "bscbus_process_sending",
    628 			    "moving to waiting");
    629 			csp->cmdstate = BSCBUS_CMDSTATE_WAITING;
    630 			/* Extend deadline because time has moved on */
    631 			csp->deadline = ddi_get_lbolt() +
    632 			    drv_usectohz(LOMBUS_CMD_TIMEOUT/1000);
    633 		} else {
    634 			/* Wait for ack of this byte */
    635 			bscbus_cmd_log(csp, BSC_CMD_SENDING,
    636 			    status, *csp->cmdp);
    637 			csp->cmdstate = BSCBUS_CMDSTATE_PENDING;
    638 			bscbus_trace(csp, 'P', "bscbus_process_sending",
    639 			    "moving to pending");
    640 		}
    641 	}
    642 }
    643 
    644 static void
    645 bscbus_process_clearing(struct bscbus_channel_state *csp,
    646     uint8_t status, uint8_t data)
    647 {
    648 	/*
    649 	 * We only enter this state if H8_STR_BUSY was set when
    650 	 * we started the transaction. We just ignore all received
    651 	 * data until we see OBF set AND BUSY cleared.
    652 	 * It is not good enough to see BUSY clear on its own
    653 	 */
    654 	if ((status & H8_STR_OBF) && !(status & H8_STR_BUSY)) {
    655 		bscbus_cmd_log(csp, BSC_CMD_CLEARED, status, data);
    656 		csp->cmdstate = BSCBUS_CMDSTATE_SENDING;
    657 		/* Throw away any data received up until now */
    658 		bscbus_trace(csp, 'P', "bscbus_process_clearing",
    659 		    "busy cleared");
    660 		/*
    661 		 * Send the next byte immediately.
    662 		 * At this stage we should clear the OBF flag because that
    663 		 * data has been used. IBF is still valid so do not clear that.
    664 		 */
    665 		status &= ~(H8_STR_OBF);
    666 		bscbus_process_sending(csp, status);
    667 	} else {
    668 		if (status & H8_STR_OBF) {
    669 			bscbus_cmd_log(csp, BSC_CMD_CLEARING, status, data);
    670 		}
    671 	}
    672 }
    673 
    674 static void
    675 bscbus_process_pending(struct bscbus_channel_state *csp, uint8_t status)
    676 {
    677 	/* We are waiting for an acknowledgement of a byte */
    678 	if (status & H8_STR_OBF) {
    679 		bscbus_cmd_log(csp, BSC_CMD_PENDING,
    680 		    status, *csp->cmdp);
    681 		bscbus_trace(csp, 'P', "bscbus_process_pending",
    682 		    "moving to sending");
    683 		csp->cmdstate = BSCBUS_CMDSTATE_SENDING;
    684 		/*
    685 		 * Send the next byte immediately.
    686 		 * At this stage we should clear the OBF flag because that
    687 		 * data has been used. IBF is still valid so do not clear that.
    688 		 */
    689 		status &= ~(H8_STR_OBF);
    690 		bscbus_process_sending(csp, status);
    691 	}
    692 }
    693 
    694 static boolean_t
    695 bscbus_process_waiting(struct bscbus_channel_state *csp,
    696     uint8_t status, uint8_t data)
    697 {
    698 	uint8_t rcvd = 0;
    699 	boolean_t ready = B_FALSE;
    700 	uint8_t tmp;
    701 
    702 	if (status & H8_STR_OBF) {
    703 		csp->reply[rcvd = csp->index] = data;
    704 		if (++rcvd < BSCBUS_BUFSIZE)
    705 			csp->index = rcvd;
    706 
    707 		bscbus_trace(csp, 'D', "bscbus_process_waiting",
    708 		    "rcvd %d: $%02x $%02x $%02x $%02x $%02x $%02x $%02x $%02x",
    709 		    rcvd,
    710 		    csp->reply[0], csp->reply[1],
    711 		    csp->reply[2], csp->reply[3],
    712 		    csp->reply[4], csp->reply[5],
    713 		    csp->reply[6], csp->reply[7]);
    714 	}
    715 
    716 	if (rcvd == 0) {
    717 		/*
    718 		 * No bytes received this time through (though there
    719 		 * might be a partial packet sitting in the buffer).
    720 		 */
    721 		/* EMPTY */
    722 		;
    723 	} else if (rcvd >= BSCBUS_BUFSIZE) {
    724 		/*
    725 		 * Buffer overflow; discard the data & treat as an error
    726 		 * (even if the last byte read did claim to terminate a
    727 		 * packet, it can't be a valid one 'cos it's too long!)
    728 		 */
    729 		bscbus_cmd_log(csp, BSC_CMD_ERROR_OFLOW, status, data);
    730 		csp->index = 0;
    731 		csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
    732 		csp->error = LOMBUS_ERR_OFLOW;
    733 		ready = B_TRUE;
    734 	} else if ((data & BSCBUS_LAST) == 0) {
    735 		/*
    736 		 * Packet not yet complete; leave the partial packet in
    737 		 * the buffer for later ...
    738 		 */
    739 		bscbus_cmd_log(csp, BSC_CMD_REPLY, status, data);
    740 	} else if ((data & BSCBUS_MASK) != BSCBUS_STATUS) {
    741 		/* Invalid "status" byte - maybe an echo of the command? */
    742 		bscbus_cmd_log(csp, BSC_CMD_ERROR_STATUS, status, data);
    743 
    744 		csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
    745 		csp->error = LOMBUS_ERR_BADSTATUS;
    746 		ready = B_TRUE;
    747 	} else if ((data & BSCBUS_SEQ) != csp->sequence) {
    748 		/* Wrong sequence number!  Flag this as an error */
    749 		bscbus_cmd_log(csp, BSC_CMD_ERROR_SEQ, status, data);
    750 
    751 		csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
    752 		csp->error = LOMBUS_ERR_SEQUENCE;
    753 		ready = B_TRUE;
    754 	} else {
    755 		/*
    756 		 * Finally, we know that's it's a valid reply to our
    757 		 * last command.  Update the ASYNC status, derive the
    758 		 * reply parameter (if any), and check the ERROR bit
    759 		 * to find out what the parameter means.
    760 		 *
    761 		 * Note that not all the values read/assigned here
    762 		 * are meaningful, but it doesn't matter; the waiting
    763 		 * thread will know which one(s) it should check.
    764 		 */
    765 		bscbus_cmd_log(csp, BSC_CMD_COMPLETE, status, data);
    766 		csp->async = (data & BSCBUS_STATUS_ASYNC) ? 1 : 0;
    767 
    768 		tmp = ((data & BSCBUS_STATUS_MSB) ? 0x80 : 0) | csp->reply[0];
    769 		if (data & BSCBUS_STATUS_ERR) {
    770 			csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
    771 			csp->error = tmp;
    772 		} else {
    773 			csp->cmdstate = BSCBUS_CMDSTATE_READY;
    774 			csp->result = tmp;
    775 		}
    776 		ready = B_TRUE;
    777 	}
    778 	return (ready);
    779 }
    780 
    781 /*
    782  * Packet receive handler
    783  *
    784  * This routine should be called from the low-level softint,
    785  * or bscbus_cmd() (for polled operation), with the
    786  * low-level mutex already held.
    787  */
    788 static void
    789 bscbus_process(struct bscbus_channel_state *csp,
    790     uint8_t status, uint8_t data)
    791 {
    792 	boolean_t ready = B_FALSE;
    793 
    794 	ASSERT(mutex_owned(csp->lo_mutex));
    795 
    796 	if ((status & H8_STR_OBF) || (status & H8_STR_IBF)) {
    797 		bscbus_trace(csp, 'D', "bscbus_process",
    798 		    "state %d; error $%x",
    799 		    csp->cmdstate, csp->error);
    800 	}
    801 
    802 	switch (csp->cmdstate) {
    803 	case BSCBUS_CMDSTATE_CLEARING:
    804 		bscbus_process_clearing(csp, status, data);
    805 		break;
    806 	case BSCBUS_CMDSTATE_SENDING:
    807 		bscbus_process_sending(csp, status);
    808 		break;
    809 	case BSCBUS_CMDSTATE_PENDING:
    810 		bscbus_process_pending(csp, status);
    811 		break;
    812 	case BSCBUS_CMDSTATE_WAITING:
    813 		ready = bscbus_process_waiting(csp, status, data);
    814 		break;
    815 	default:
    816 		/* Nothing to do */
    817 		break;
    818 	}
    819 
    820 	/*
    821 	 * Check for timeouts - but only if the command has not yet
    822 	 * completed (ready is true when command completes in this
    823 	 * call to bscbus_process OR cmdstate is READY or ERROR if
    824 	 * this is a spurious call to bscbus_process i.e. a spurious
    825 	 * interrupt)
    826 	 */
    827 	if (!ready &&
    828 	    ((ddi_get_lbolt() - csp->deadline) > 0) &&
    829 	    csp->cmdstate != BSCBUS_CMDSTATE_READY &&
    830 	    csp->cmdstate != BSCBUS_CMDSTATE_ERROR) {
    831 		bscbus_trace(csp, 'P', "bscbus_process",
    832 		    "timeout previous state %d; error $%x",
    833 		    csp->cmdstate, csp->error);
    834 		bscbus_cmd_log(csp, BSC_CMD_ERROR_TOUT, status, data);
    835 		if (csp->cmdstate == BSCBUS_CMDSTATE_CLEARING) {
    836 			/* Move onto sending because busy might be stuck */
    837 			csp->cmdstate = BSCBUS_CMDSTATE_SENDING;
    838 			/* Extend timeout relative to original start time */
    839 			csp->deadline += drv_usectohz(LOMBUS_CMD_TIMEOUT/1000);
    840 		} else if (csp->cmdstate != BSCBUS_CMDSTATE_IDLE) {
    841 			csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
    842 			csp->error = LOMBUS_ERR_TIMEOUT;
    843 		}
    844 		ready = B_TRUE;
    845 	}
    846 
    847 	if ((status & H8_STR_OBF) || (status & H8_STR_IBF) || ready) {
    848 		bscbus_trace(csp, 'D', "bscbus_process",
    849 		    "last $%02x; state %d; error $%x; ready %d",
    850 		    data, csp->cmdstate, csp->error, ready);
    851 	}
    852 	if (ready)
    853 		cv_broadcast(csp->lo_cv);
    854 }
    855 
    856 static uint_t
    857 bscbus_hwintr(caddr_t arg)
    858 {
    859 	struct bscbus_channel_state *csp = (void *)arg;
    860 
    861 	uint8_t status;
    862 	uint8_t data = 0xb0 /* Dummy value */;
    863 
    864 	mutex_enter(csp->lo_mutex);
    865 	/*
    866 	 * Read the registers to ensure that the interrupt is cleared.
    867 	 * Status must be read first because reading data changes the
    868 	 * status.
    869 	 * We always read the data because that clears the interrupt down.
    870 	 * This is horrible hardware semantics but we have to do it!
    871 	 */
    872 	status = bscbus_get_reg(csp, H8_STR);
    873 	data = bscbus_get_reg(csp, H8_ODR);
    874 	if (!(status & H8_STR_OBF)) {
    875 		bscbus_cmd_log(csp, BSC_CMD_V1INTRUNCL, status, data);
    876 		csp->unclaimed_count++;
    877 	} else {
    878 		bscbus_cmd_log(csp, BSC_CMD_V1INTR, status, data);
    879 	}
    880 	if (status & H8_STR_TOKENPROTOCOL) {
    881 		bscbus_process(csp, status, data);
    882 		if (csp->interrupt_failed) {
    883 			bscbus_trace(csp, 'I', "bscbus_hwintr:",
    884 			    "interrupt fault cleared channel %d", csp->chno);
    885 			csp->interrupt_failed = B_FALSE;
    886 			csp->poll_hz = drv_usectohz(BSCBUS_CMD_POLL / 1000);
    887 		}
    888 	}
    889 
    890 	mutex_exit(csp->lo_mutex);
    891 	return (DDI_INTR_CLAIMED);
    892 }
    893 
    894 void
    895 bscbus_poll(struct bscbus_channel_state *csp)
    896 {
    897 	/*
    898 	 * This routine is only called if we timeout in userland
    899 	 * waiting for an interrupt. This generally means that we have
    900 	 * lost interrupt capabilities or that something has gone
    901 	 * wrong.  In this case we are allowed to access the hardware
    902 	 * and read the data register if necessary.
    903 	 * If interrupts return then recovery actions should mend us!
    904 	 */
    905 	uint8_t status;
    906 	uint8_t data = 0xfa; /* Dummy value */
    907 
    908 	ASSERT(mutex_owned(csp->lo_mutex));
    909 
    910 	/* Should look for data to receive */
    911 	status = bscbus_get_reg(csp, H8_STR);
    912 	if (status & H8_STR_OBF) {
    913 		/* There is data available */
    914 		data = bscbus_get_reg(csp, H8_ODR);
    915 		bscbus_cmd_log(csp, BSC_CMD_PROCESS, status, data);
    916 	}
    917 	bscbus_process(csp, status, data);
    918 }
    919 
    920 /*
    921  * Serial protocol
    922  *
    923  * This routine builds a command and sets it in progress.
    924  */
    925 static uint8_t
    926 bscbus_cmd(HANDLE_TYPE *hdlp, ptrdiff_t vreg, uint_t val, uint_t cmd)
    927 {
    928 	struct bscbus_channel_state *csp;
    929 	clock_t start;
    930 	uint8_t status;
    931 
    932 	/*
    933 	 * First of all, wait for the interface to be available.
    934 	 *
    935 	 * NOTE: we blow through all the mutex/cv/state checking and
    936 	 * preempt any command in progress if the system is panicking!
    937 	 */
    938 	csp = HANDLE_PRIVATE(hdlp);
    939 	mutex_enter(csp->lo_mutex);
    940 	while (csp->cmdstate != BSCBUS_CMDSTATE_IDLE && !ddi_in_panic())
    941 		cv_wait(csp->lo_cv, csp->lo_mutex);
    942 
    943 	csp->cmdstate = BSCBUS_CMDSTATE_BUSY;
    944 	csp->sequence = (csp->sequence + BSCBUS_SEQ_LSB) & BSCBUS_SEQ;
    945 
    946 	/*
    947 	 * We have exclusive ownership, so assemble the command (backwards):
    948 	 *
    949 	 * [byte 0]	Command:	modified by XADDR and/or WMSB bits
    950 	 * [Optional] Parameter: 	Value to write (low 7 bits)
    951 	 * [Optional] Parameter: 	Register number (high 7 bits)
    952 	 * [Optional] Parameter: 	Register number (low 7 bits)
    953 	 */
    954 	csp->cmdp = &csp->cmdbuf[0];
    955 	*csp->cmdp++ = BSCBUS_CMD | csp->sequence | cmd;
    956 	switch (cmd) {
    957 	case BSCBUS_CMD_WRITE:
    958 		*csp->cmdp++ = val & 0x7f;
    959 		if (val >= 0x80)
    960 			csp->cmdbuf[0] |= BSCBUS_CMD_WMSB;
    961 		/*FALLTHRU*/
    962 	case BSCBUS_CMD_READ:
    963 		if (BSCBUS_VREG_HI(vreg) != 0) {
    964 			*csp->cmdp++ = BSCBUS_VREG_HI(vreg);
    965 			csp->cmdbuf[0] |= BSCBUS_CMD_XADDR;
    966 		}
    967 		*csp->cmdp++ = BSCBUS_VREG_LO(vreg);
    968 		/*FALLTHRU*/
    969 	case BSCBUS_CMD_NOP:
    970 		break;
    971 	}
    972 
    973 	/*
    974 	 * Check and update the H8 h/w fault status before accessing
    975 	 * the chip registers.  If there's a (new or previous) fault,
    976 	 * we'll run through the protocol but won't really touch the
    977 	 * hardware and all commands will timeout.  If a previously
    978 	 * discovered fault has now gone away (!), then we can (try to)
    979 	 * proceed with the new command (probably a probe).
    980 	 */
    981 	bscbus_check_fault_status(csp);
    982 
    983 	/*
    984 	 * Prepare for the command (to be processed by the interrupt
    985 	 * handler and/or polling loop below), and wait for a response
    986 	 * or timeout.
    987 	 */
    988 	start = ddi_get_lbolt();
    989 	csp->deadline = start + drv_usectohz(LOMBUS_CMD_TIMEOUT/1000);
    990 	csp->error = 0;
    991 	csp->index = 0;
    992 	csp->result = DUMMY_VALUE;
    993 
    994 	status = bscbus_get_reg(csp, H8_STR);
    995 	if (status & H8_STR_BUSY) {
    996 		bscbus_cmd_log(csp, BSC_CMD_BUSY, status, 0xfd);
    997 		/*
    998 		 * Must ensure that the busy state has cleared before
    999 		 * sending the command
   1000 		 */
   1001 		csp->cmdstate = BSCBUS_CMDSTATE_CLEARING;
   1002 		bscbus_trace(csp, 'P', "bscbus_cmd",
   1003 		    "h8 reporting status (%x) busy - clearing", status);
   1004 	} else {
   1005 		/* It is clear to send the command immediately */
   1006 		csp->cmdstate = BSCBUS_CMDSTATE_SENDING;
   1007 		bscbus_trace(csp, 'P', "bscbus_cmd",
   1008 		    "sending first byte of command, status %x", status);
   1009 		bscbus_poll(csp);
   1010 	}
   1011 
   1012 	csp->poll_hz = drv_usectohz(
   1013 	    (csp->interrupt_failed ?
   1014 	    BSCBUS_CMD_POLLNOINTS : BSCBUS_CMD_POLL) / 1000);
   1015 
   1016 	while ((csp->cmdstate != BSCBUS_CMDSTATE_READY) &&
   1017 	    (csp->cmdstate != BSCBUS_CMDSTATE_ERROR)) {
   1018 		ASSERT(csp->cmdstate != BSCBUS_CMDSTATE_IDLE);
   1019 
   1020 		if ((cv_reltimedwait(csp->lo_cv, csp->lo_mutex,
   1021 		    csp->poll_hz, TR_CLOCK_TICK) == -1) &&
   1022 		    csp->cmdstate != BSCBUS_CMDSTATE_READY &&
   1023 		    csp->cmdstate != BSCBUS_CMDSTATE_ERROR) {
   1024 			if (!csp->interrupt_failed) {
   1025 				bscbus_trace(csp, 'I', "bscbus_cmd:",
   1026 				    "interrupt_failed channel %d", csp->chno);
   1027 				csp->interrupt_failed = B_TRUE;
   1028 				csp->poll_hz = drv_usectohz(
   1029 				    BSCBUS_CMD_POLLNOINTS / 1000);
   1030 			}
   1031 			bscbus_poll(csp);
   1032 		}
   1033 	}
   1034 
   1035 	/*
   1036 	 * The return value may not be meaningful but retrieve it anyway
   1037 	 */
   1038 	val = csp->result;
   1039 	if (bscbus_faulty(csp)) {
   1040 		val = DUMMY_VALUE;
   1041 		HANDLE_FAULT(hdlp) = LOMBUS_ERR_SIOHW;
   1042 	} else if (csp->cmdstate != BSCBUS_CMDSTATE_READY) {
   1043 		/*
   1044 		 * Some problem here ... transfer the error code from
   1045 		 * the per-instance state to the per-handle fault flag.
   1046 		 * The error code shouldn't be zero!
   1047 		 */
   1048 		if (csp->error != 0)
   1049 			HANDLE_FAULT(hdlp) = csp->error;
   1050 		else
   1051 			HANDLE_FAULT(hdlp) = LOMBUS_ERR_BADERRCODE;
   1052 	}
   1053 
   1054 	/*
   1055 	 * All done now!
   1056 	 */
   1057 	csp->index = 0;
   1058 	csp->cmdstate = BSCBUS_CMDSTATE_IDLE;
   1059 	cv_broadcast(csp->lo_cv);
   1060 	mutex_exit(csp->lo_mutex);
   1061 
   1062 	return (val);
   1063 }
   1064 
   1065 /*
   1066  * Space 0 - LOM virtual register access
   1067  * Only 8-bit accesses are supported.
   1068  */
   1069 static uint8_t
   1070 bscbus_vreg_get8(HANDLE_TYPE *hdlp, uint8_t *addr)
   1071 {
   1072 	ptrdiff_t offset;
   1073 
   1074 	/*
   1075 	 * Check the offset that the caller has added to the base address
   1076 	 * against the length of the mapping originally requested.
   1077 	 */
   1078 	offset = ADDR_TO_OFFSET(addr, hdlp);
   1079 	if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
   1080 		/*
   1081 		 * Invalid access - flag a fault and return a dummy value
   1082 		 */
   1083 		HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
   1084 		return (DUMMY_VALUE);
   1085 	}
   1086 
   1087 	/*
   1088 	 * Derive the virtual register number and run the command
   1089 	 */
   1090 	return (bscbus_cmd(hdlp, ADDR_TO_VREG(addr), 0, BSCBUS_CMD_READ));
   1091 }
   1092 
   1093 static void
   1094 bscbus_vreg_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
   1095 {
   1096 	ptrdiff_t offset;
   1097 
   1098 	/*
   1099 	 * Check the offset that the caller has added to the base address
   1100 	 * against the length of the mapping originally requested.
   1101 	 */
   1102 	offset = ADDR_TO_OFFSET(addr, hdlp);
   1103 	if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
   1104 		/*
   1105 		 * Invalid access - flag a fault and return
   1106 		 */
   1107 		HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
   1108 		return;
   1109 	}
   1110 
   1111 	/*
   1112 	 * Derive the virtual register number and run the command
   1113 	 */
   1114 	(void) bscbus_cmd(hdlp, ADDR_TO_VREG(addr), val, BSCBUS_CMD_WRITE);
   1115 }
   1116 
   1117 static void
   1118 bscbus_vreg_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
   1119 	uint8_t *dev_addr, size_t repcount, uint_t flags)
   1120 {
   1121 	size_t inc;
   1122 
   1123 	inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
   1124 	for (; repcount--; dev_addr += inc)
   1125 		*host_addr++ = bscbus_vreg_get8(hdlp, dev_addr);
   1126 }
   1127 
   1128 static void
   1129 bscbus_vreg_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
   1130 	uint8_t *dev_addr, size_t repcount, uint_t flags)
   1131 {
   1132 	size_t inc;
   1133 
   1134 	inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
   1135 	for (; repcount--; dev_addr += inc)
   1136 		bscbus_vreg_put8(hdlp, dev_addr, *host_addr++);
   1137 }
   1138 
   1139 
   1140 /*
   1141  * Space 1 - LOM watchdog pat register access
   1142  * Only 8-bit accesses are supported.
   1143  *
   1144  * Reads have no effect and return 0.
   1145  *
   1146  * Multi-byte reads (using ddi_rep_get8(9F)) are a fairly inefficient
   1147  * way of zeroing the destination area ;-) and still won't pat the dog.
   1148  *
   1149  * Multi-byte writes (using ddi_rep_put8(9F)) will almost certainly
   1150  * only count as a single pat, no matter how many bytes the caller
   1151  * says to write, as the inter-pat time is VERY long compared with
   1152  * the time it will take to read the memory source area.
   1153  */
   1154 
   1155 static uint8_t
   1156 bscbus_pat_get8(HANDLE_TYPE *hdlp, uint8_t *addr)
   1157 {
   1158 	ptrdiff_t offset;
   1159 
   1160 	/*
   1161 	 * Check the offset that the caller has added to the base address
   1162 	 * against the length of the mapping originally requested.
   1163 	 */
   1164 	offset = ADDR_TO_OFFSET(addr, hdlp);
   1165 	if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
   1166 		/*
   1167 		 * Invalid access - flag a fault and return a dummy value
   1168 		 */
   1169 		HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
   1170 		return (DUMMY_VALUE);
   1171 	}
   1172 
   1173 	return (0);
   1174 }
   1175 
   1176 static void
   1177 bscbus_pat_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
   1178 {
   1179 	struct bscbus_channel_state *csp;
   1180 	ptrdiff_t offset;
   1181 
   1182 	/*
   1183 	 * Check the offset that the caller has added to the base address
   1184 	 * against the length of the mapping originally requested.
   1185 	 */
   1186 	offset = ADDR_TO_OFFSET(addr, hdlp);
   1187 	if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
   1188 		/*
   1189 		 * Invalid access - flag a fault and return
   1190 		 */
   1191 		HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
   1192 		return;
   1193 	}
   1194 
   1195 	csp = HANDLE_PRIVATE(hdlp);
   1196 	mutex_enter(csp->dog_mutex);
   1197 	bscbus_pat_dog(csp, val);
   1198 	mutex_exit(csp->dog_mutex);
   1199 }
   1200 
   1201 static void
   1202 bscbus_pat_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
   1203 	uint8_t *dev_addr, size_t repcount, uint_t flags)
   1204 {
   1205 	size_t inc;
   1206 
   1207 	inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
   1208 	for (; repcount--; dev_addr += inc)
   1209 		*host_addr++ = bscbus_pat_get8(hdlp, dev_addr);
   1210 }
   1211 
   1212 static void
   1213 bscbus_pat_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
   1214 	uint8_t *dev_addr, size_t repcount, uint_t flags)
   1215 {
   1216 	size_t inc;
   1217 
   1218 	inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
   1219 	for (; repcount--; dev_addr += inc)
   1220 		bscbus_pat_put8(hdlp, dev_addr, *host_addr++);
   1221 }
   1222 
   1223 
   1224 /*
   1225  * Space 2 - LOM async event flag register access
   1226  * Only 16-bit accesses are supported.
   1227  */
   1228 static uint16_t
   1229 bscbus_event_get16(HANDLE_TYPE *hdlp, uint16_t *addr)
   1230 {
   1231 	struct bscbus_channel_state *csp;
   1232 	ptrdiff_t offset;
   1233 
   1234 	/*
   1235 	 * Check the offset that the caller has added to the base address
   1236 	 * against the length of the mapping orignally requested.
   1237 	 */
   1238 	offset = ADDR_TO_OFFSET(addr, hdlp);
   1239 	if (offset < 0 || (offset%2) != 0 || offset >= HANDLE_MAPLEN(hdlp)) {
   1240 		/*
   1241 		 * Invalid access - flag a fault and return a dummy value
   1242 		 */
   1243 		HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
   1244 		return (DUMMY_VALUE);
   1245 	}
   1246 
   1247 	/*
   1248 	 * Return the value of the asynchronous-event-pending flag
   1249 	 * as passed back by the LOM at the end of the last command.
   1250 	 */
   1251 	csp = HANDLE_PRIVATE(hdlp);
   1252 	return (csp->async);
   1253 }
   1254 
   1255 static void
   1256 bscbus_event_put16(HANDLE_TYPE *hdlp, uint16_t *addr, uint16_t val)
   1257 {
   1258 	ptrdiff_t offset;
   1259 
   1260 	_NOTE(ARGUNUSED(val))
   1261 
   1262 	/*
   1263 	 * Check the offset that the caller has added to the base address
   1264 	 * against the length of the mapping originally requested.
   1265 	 */
   1266 	offset = ADDR_TO_OFFSET(addr, hdlp);
   1267 	if (offset < 0 || (offset%2) != 0 || offset >= HANDLE_MAPLEN(hdlp)) {
   1268 		/*
   1269 		 * Invalid access - flag a fault and return
   1270 		 */
   1271 		HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
   1272 		return;
   1273 	}
   1274 
   1275 	/*
   1276 	 * The user can't overwrite the asynchronous-event-pending flag!
   1277 	 */
   1278 	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_RO;
   1279 }
   1280 
   1281 static void
   1282 bscbus_event_rep_get16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
   1283 	uint16_t *dev_addr, size_t repcount, uint_t flags)
   1284 {
   1285 	size_t inc;
   1286 
   1287 	inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
   1288 	for (; repcount--; dev_addr += inc)
   1289 		*host_addr++ = bscbus_event_get16(hdlp, dev_addr);
   1290 }
   1291 
   1292 static void
   1293 bscbus_event_rep_put16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
   1294 	uint16_t *dev_addr, size_t repcount, uint_t flags)
   1295 {
   1296 	size_t inc;
   1297 
   1298 	inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
   1299 	for (; repcount--; dev_addr += inc)
   1300 		bscbus_event_put16(hdlp, dev_addr, *host_addr++);
   1301 }
   1302 
   1303 
   1304 /*
   1305  * All spaces - access handle fault information
   1306  * Only 32-bit accesses are supported.
   1307  */
   1308 static uint32_t
   1309 bscbus_meta_get32(HANDLE_TYPE *hdlp, uint32_t *addr)
   1310 {
   1311 	struct bscbus_channel_state *csp;
   1312 	ptrdiff_t offset;
   1313 
   1314 	/*
   1315 	 * Derive the offset that the caller has added to the base
   1316 	 * address originally returned, and use it to determine
   1317 	 * which meta-register is to be accessed ...
   1318 	 */
   1319 	offset = ADDR_TO_OFFSET(addr, hdlp);
   1320 	switch (offset) {
   1321 	case LOMBUS_FAULT_REG:
   1322 		/*
   1323 		 * This meta-register provides a code for the most
   1324 		 * recent virtual register access fault, if any.
   1325 		 */
   1326 		return (HANDLE_FAULT(hdlp));
   1327 
   1328 	case LOMBUS_PROBE_REG:
   1329 		/*
   1330 		 * Reading this meta-register clears any existing fault
   1331 		 * (at the virtual, not the hardware access layer), then
   1332 		 * runs a NOP command and returns the fault code from that.
   1333 		 */
   1334 		HANDLE_FAULT(hdlp) = 0;
   1335 		(void) bscbus_cmd(hdlp, 0, 0, BSCBUS_CMD_NOP);
   1336 		return (HANDLE_FAULT(hdlp));
   1337 
   1338 	case LOMBUS_ASYNC_REG:
   1339 		/*
   1340 		 * Obsolescent - but still supported for backwards
   1341 		 * compatibility.  This is an alias for the newer
   1342 		 * LOMBUS_EVENT_REG, but doesn't require a separate
   1343 		 * "reg" entry and ddi_regs_map_setup() call.
   1344 		 *
   1345 		 * It returns the value of the asynchronous-event-pending
   1346 		 * flag as passed back by the BSC at the end of the last
   1347 		 * completed command.
   1348 		 */
   1349 		csp = HANDLE_PRIVATE(hdlp);
   1350 		return (csp->async);
   1351 
   1352 	default:
   1353 		/*
   1354 		 * Invalid access - flag a fault and return a dummy value
   1355 		 */
   1356 		HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
   1357 		return (DUMMY_VALUE);
   1358 	}
   1359 }
   1360 
   1361 static void
   1362 bscbus_meta_put32(HANDLE_TYPE *hdlp, uint32_t *addr, uint32_t val)
   1363 {
   1364 	ptrdiff_t offset;
   1365 
   1366 	/*
   1367 	 * Derive the offset that the caller has added to the base
   1368 	 * address originally returned, and use it to determine
   1369 	 * which meta-register is to be accessed ...
   1370 	 */
   1371 	offset = ADDR_TO_OFFSET(addr, hdlp);
   1372 	switch (offset) {
   1373 	case LOMBUS_FAULT_REG:
   1374 		/*
   1375 		 * This meta-register contains a code for the most
   1376 		 * recent virtual register access fault, if any.
   1377 		 * It can be cleared simply by writing 0 to it.
   1378 		 */
   1379 		HANDLE_FAULT(hdlp) = val;
   1380 		return;
   1381 
   1382 	case LOMBUS_PROBE_REG:
   1383 		/*
   1384 		 * Writing this meta-register clears any existing fault
   1385 		 * (at the virtual, not the hardware acess layer), then
   1386 		 * runs a NOP command.  The caller can check the fault
   1387 		 * code later if required.
   1388 		 */
   1389 		HANDLE_FAULT(hdlp) = 0;
   1390 		(void) bscbus_cmd(hdlp, 0, 0, BSCBUS_CMD_NOP);
   1391 		return;
   1392 
   1393 	default:
   1394 		/*
   1395 		 * Invalid access - flag a fault
   1396 		 */
   1397 		HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
   1398 		return;
   1399 	}
   1400 }
   1401 
   1402 static void
   1403 bscbus_meta_rep_get32(HANDLE_TYPE *hdlp, uint32_t *host_addr,
   1404 	uint32_t *dev_addr, size_t repcount, uint_t flags)
   1405 {
   1406 	size_t inc;
   1407 
   1408 	inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
   1409 	for (; repcount--; dev_addr += inc)
   1410 		*host_addr++ = bscbus_meta_get32(hdlp, dev_addr);
   1411 }
   1412 
   1413 static void
   1414 bscbus_meta_rep_put32(HANDLE_TYPE *hdlp, uint32_t *host_addr,
   1415 	uint32_t *dev_addr, size_t repcount, uint_t flags)
   1416 {
   1417 	size_t inc;
   1418 
   1419 	inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
   1420 	for (; repcount--; dev_addr += inc)
   1421 		bscbus_meta_put32(hdlp, dev_addr, *host_addr++);
   1422 }
   1423 
   1424 
   1425 /*
   1426  * Finally, some dummy functions for all unsupported access
   1427  * space/size/mode combinations ...
   1428  */
   1429 static uint8_t
   1430 bscbus_no_get8(HANDLE_TYPE *hdlp, uint8_t *addr)
   1431 {
   1432 	_NOTE(ARGUNUSED(addr))
   1433 
   1434 	/*
   1435 	 * Invalid access - flag a fault and return a dummy value
   1436 	 */
   1437 	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
   1438 	return (DUMMY_VALUE);
   1439 }
   1440 
   1441 static void
   1442 bscbus_no_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
   1443 {
   1444 	_NOTE(ARGUNUSED(addr, val))
   1445 
   1446 	/*
   1447 	 * Invalid access - flag a fault
   1448 	 */
   1449 	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
   1450 }
   1451 
   1452 static void
   1453 bscbus_no_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
   1454 		uint8_t *dev_addr, size_t repcount, uint_t flags)
   1455 {
   1456 	_NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
   1457 
   1458 	/*
   1459 	 * Invalid access - flag a fault
   1460 	 */
   1461 	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
   1462 }
   1463 
   1464 static void
   1465 bscbus_no_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
   1466 	uint8_t *dev_addr, size_t repcount, uint_t flags)
   1467 {
   1468 	_NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
   1469 
   1470 	/*
   1471 	 * Invalid access - flag a fault
   1472 	 */
   1473 	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
   1474 }
   1475 
   1476 static uint16_t
   1477 bscbus_no_get16(HANDLE_TYPE *hdlp, uint16_t *addr)
   1478 {
   1479 	_NOTE(ARGUNUSED(addr))
   1480 
   1481 	/*
   1482 	 * Invalid access - flag a fault and return a dummy value
   1483 	 */
   1484 	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
   1485 	return (DUMMY_VALUE);
   1486 }
   1487 
   1488 static void
   1489 bscbus_no_put16(HANDLE_TYPE *hdlp, uint16_t *addr, uint16_t val)
   1490 {
   1491 	_NOTE(ARGUNUSED(addr, val))
   1492 
   1493 	/*
   1494 	 * Invalid access - flag a fault
   1495 	 */
   1496 	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
   1497 }
   1498 
   1499 static void
   1500 bscbus_no_rep_get16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
   1501 		uint16_t *dev_addr, size_t repcount, uint_t flags)
   1502 {
   1503 	_NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
   1504 
   1505 	/*
   1506 	 * Invalid access - flag a fault
   1507 	 */
   1508 	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
   1509 }
   1510 
   1511 static void
   1512 bscbus_no_rep_put16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
   1513 	uint16_t *dev_addr, size_t repcount, uint_t flags)
   1514 {
   1515 	_NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
   1516 
   1517 	/*
   1518 	 * Invalid access - flag a fault
   1519 	 */
   1520 	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
   1521 }
   1522 
   1523 static uint64_t
   1524 bscbus_no_get64(HANDLE_TYPE *hdlp, uint64_t *addr)
   1525 {
   1526 	_NOTE(ARGUNUSED(addr))
   1527 
   1528 	/*
   1529 	 * Invalid access - flag a fault and return a dummy value
   1530 	 */
   1531 	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
   1532 	return (DUMMY_VALUE);
   1533 }
   1534 
   1535 static void
   1536 bscbus_no_put64(HANDLE_TYPE *hdlp, uint64_t *addr, uint64_t val)
   1537 {
   1538 	_NOTE(ARGUNUSED(addr, val))
   1539 
   1540 	/*
   1541 	 * Invalid access - flag a fault
   1542 	 */
   1543 	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
   1544 }
   1545 
   1546 static void
   1547 bscbus_no_rep_get64(HANDLE_TYPE *hdlp, uint64_t *host_addr,
   1548 	uint64_t *dev_addr, size_t repcount, uint_t flags)
   1549 {
   1550 	_NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
   1551 
   1552 	/*
   1553 	 * Invalid access - flag a fault
   1554 	 */
   1555 	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
   1556 }
   1557 
   1558 static void
   1559 bscbus_no_rep_put64(HANDLE_TYPE *hdlp, uint64_t *host_addr,
   1560 	uint64_t *dev_addr, size_t repcount, uint_t flags)
   1561 {
   1562 	_NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
   1563 
   1564 	/*
   1565 	 * Invalid access - flag a fault
   1566 	 */
   1567 	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
   1568 }
   1569 
   1570 static int
   1571 bscbus_acc_fault_check(HANDLE_TYPE *hdlp)
   1572 {
   1573 	return (HANDLE_FAULT(hdlp) != 0);
   1574 }
   1575 
   1576 /*
   1577  * Hardware setup - ensure that there are no pending transactions and
   1578  * hence no pending interrupts. We do this be ensuring that the BSC is
   1579  * not reporting a busy condition and that it does not have any data
   1580  * pending in its output buffer.
   1581  * This is important because if we have pending interrupts at attach
   1582  * time Solaris will hang due to bugs in ddi_get_iblock_cookie.
   1583  */
   1584 static void
   1585 bscbus_hw_reset(struct bscbus_channel_state *csp)
   1586 {
   1587 	int64_t timeout;
   1588 	uint8_t status;
   1589 
   1590 	if (csp->map_count == 0) {
   1591 		/* No-one using this instance - no need to reset hardware */
   1592 		return;
   1593 	}
   1594 
   1595 	bscbus_trace(csp, 'R', "bscbus_hw_reset",
   1596 	    "resetting channel %d", csp->chno);
   1597 
   1598 	status = bscbus_get_reg(csp, H8_STR);
   1599 	if (status & H8_STR_BUSY) {
   1600 		/*
   1601 		 * Give the h8 time to complete a reply.
   1602 		 * In practice we should never worry about this
   1603 		 * because whenever we get here it will have been
   1604 		 * long enough for the h8 to complete a reply
   1605 		 */
   1606 		bscbus_cmd_log(csp, BSC_CMD_BUSY, status, 0);
   1607 		bscbus_trace(csp, 'R', "bscbus_hw_reset",
   1608 		    "h8 reporting status (%x) busy - waiting", status);
   1609 		if (ddi_in_panic()) {
   1610 			drv_usecwait(BSCBUS_HWRESET_POLL/1000);
   1611 		} else {
   1612 			delay(drv_usectohz(BSCBUS_HWRESET_POLL/1000));
   1613 		}
   1614 	}
   1615 	/* Reply should be completed by now. Try to clear busy status */
   1616 	status = bscbus_get_reg(csp, H8_STR);
   1617 	if (status & (H8_STR_BUSY | H8_STR_OBF)) {
   1618 		bscbus_trace(csp, 'R', "bscbus_hw_reset",
   1619 		    "clearing busy status for channel %d", csp->chno);
   1620 
   1621 		for (timeout = BSCBUS_HWRESET_TIMEOUT;
   1622 		    (timeout > 0);
   1623 		    timeout -= BSCBUS_HWRESET_POLL) {
   1624 			if (status & H8_STR_OBF) {
   1625 				(void) bscbus_get_reg(csp, H8_ODR);
   1626 				if (!(status & H8_STR_BUSY)) {
   1627 					/* We are done */
   1628 					break;
   1629 				}
   1630 			}
   1631 			if (ddi_in_panic()) {
   1632 				drv_usecwait(BSCBUS_HWRESET_POLL/1000);
   1633 			} else {
   1634 				delay(drv_usectohz(BSCBUS_HWRESET_POLL/1000));
   1635 			}
   1636 			status = bscbus_get_reg(csp, H8_STR);
   1637 		}
   1638 		if (timeout <= 0) {
   1639 			cmn_err(CE_WARN, "bscbus_hw_reset: timed out "
   1640 			    "clearing busy status");
   1641 		}
   1642 	}
   1643 	/*
   1644 	 * We read ODR just in case there is a pending interrupt with
   1645 	 * no data. This is potentially dangerous because we could get
   1646 	 * out of sync due to race conditions BUT at this point the
   1647 	 * channel should be idle so it is safe.
   1648 	 */
   1649 	(void) bscbus_get_reg(csp, H8_ODR);
   1650 }
   1651 
   1652 /*
   1653  * Higher-level setup & teardown
   1654  */
   1655 
   1656 static void
   1657 bscbus_offline(struct bscbus_state *ssp)
   1658 {
   1659 	if (ssp->h8_handle != NULL)
   1660 		ddi_regs_map_free(&ssp->h8_handle);
   1661 	ssp->h8_handle = NULL;
   1662 	ssp->h8_regs = NULL;
   1663 }
   1664 
   1665 static int
   1666 bscbus_online(struct bscbus_state *ssp)
   1667 {
   1668 	ddi_acc_handle_t h;
   1669 	caddr_t p;
   1670 	int nregs;
   1671 	int err;
   1672 
   1673 	ssp->h8_handle = NULL;
   1674 	ssp->h8_regs = (void *)NULL;
   1675 	ssp->per_channel_regs = B_FALSE;
   1676 
   1677 	if (ddi_dev_nregs(ssp->dip, &nregs) != DDI_SUCCESS)
   1678 		nregs = 0;
   1679 
   1680 	switch (nregs) {
   1681 	case 1:
   1682 		/*
   1683 		 *  regset 0 represents the H8 interface registers
   1684 		 */
   1685 		err = ddi_regs_map_setup(ssp->dip, 0, &p, 0, 0,
   1686 		    bscbus_dev_acc_attr, &h);
   1687 		if (err != DDI_SUCCESS)
   1688 			return (EIO);
   1689 
   1690 		ssp->h8_handle = h;
   1691 		ssp->h8_regs = (void *)p;
   1692 		break;
   1693 
   1694 	case 0:
   1695 		/*
   1696 		 *  If no registers are defined, succeed vacuously;
   1697 		 *  commands will be accepted, but we fake the accesses.
   1698 		 */
   1699 		break;
   1700 
   1701 	default:
   1702 		/*
   1703 		 * Remember that we are using the new register scheme.
   1704 		 * reg set 0 is chan 0
   1705 		 * reg set 1 is chan 1 ...
   1706 		 * Interrupts are specified in that order but later
   1707 		 * channels may not have interrupts.
   1708 		 * We map the regs later on a per channel basis.
   1709 		 */
   1710 		ssp->per_channel_regs = B_TRUE;
   1711 		break;
   1712 	}
   1713 	return (0);
   1714 }
   1715 
   1716 static int
   1717 bscbus_claim_channel(struct bscbus_channel_state *csp, boolean_t map_dog)
   1718 {
   1719 	int err;
   1720 
   1721 	mutex_enter(csp->ssp->ch_mutex);
   1722 	csp->map_count++;
   1723 	bscbus_trace(csp, 'C', "bscbus_claim_channel",
   1724 	    "claim channel for channel %d, count %d",
   1725 	    csp->chno, csp->map_count);
   1726 
   1727 	if (csp->map_count == 1) {
   1728 		/* No-one is using this channel - initialise it */
   1729 		bscbus_trace(csp, 'C', "bscbus_claim_channel",
   1730 		    "initialise channel %d, count %d",
   1731 		    csp->chno, csp->map_count);
   1732 
   1733 		mutex_init(csp->dog_mutex, NULL, MUTEX_DRIVER,
   1734 		    (void *)(uintptr_t)__ipltospl(SPL7 - 1));
   1735 		csp->map_dog = map_dog;
   1736 		csp->interrupt_failed = B_FALSE;
   1737 		csp->cmdstate = BSCBUS_CMDSTATE_IDLE;
   1738 		csp->pat_retry_count = 0;
   1739 		csp->pat_fail_count = 0;
   1740 
   1741 		/* Map appropriate register set for this channel */
   1742 		if (csp->ssp->per_channel_regs == B_TRUE) {
   1743 			ddi_acc_handle_t h;
   1744 			caddr_t p;
   1745 
   1746 			err = ddi_regs_map_setup(csp->ssp->dip, csp->chno,
   1747 			    &p, 0, 0, bscbus_dev_acc_attr, &h);
   1748 
   1749 			if (err != DDI_SUCCESS) {
   1750 				goto failed1;
   1751 			}
   1752 
   1753 			csp->ch_handle = h;
   1754 			csp->ch_regs = (void *)p;
   1755 
   1756 			bscbus_trace(csp, 'C', "bscbus_claim_channel",
   1757 			    "mapped chno=%d ch_handle=%d ch_regs=%p",
   1758 			    csp->chno, h, p);
   1759 		} else {
   1760 			/*
   1761 			 * if using the old reg property scheme use the
   1762 			 * common mapping.
   1763 			 */
   1764 			csp->ch_handle = csp->ssp->h8_handle;
   1765 			csp->ch_regs =
   1766 			    csp->ssp->h8_regs +
   1767 			    BSCBUS_CHANNEL_TO_OFFSET(csp->chno);
   1768 		}
   1769 
   1770 		/* Ensure no interrupts pending prior to getting iblk cookie */
   1771 		bscbus_hw_reset(csp);
   1772 
   1773 		if (csp->map_dog == 1) {
   1774 			/*
   1775 			 * we don't want lo_mutex to be initialised
   1776 			 * with an iblock cookie if we are the wdog,
   1777 			 * because we don't use interrupts.
   1778 			 */
   1779 			mutex_init(csp->lo_mutex, NULL,
   1780 			    MUTEX_DRIVER, NULL);
   1781 			cv_init(csp->lo_cv, NULL,
   1782 			    CV_DRIVER, NULL);
   1783 			csp->unclaimed_count = 0;
   1784 		} else {
   1785 			int ninterrupts;
   1786 
   1787 			/*
   1788 			 * check that there is an interrupt for this
   1789 			 * this channel. If we fail to setup interrupts we
   1790 			 * must unmap the registers and fail.
   1791 			 */
   1792 			err = ddi_dev_nintrs(csp->ssp->dip, &ninterrupts);
   1793 
   1794 			if (err != DDI_SUCCESS) {
   1795 				ninterrupts = 0;
   1796 			}
   1797 
   1798 			if (ninterrupts <= csp->chno) {
   1799 				cmn_err(CE_WARN,
   1800 				    "no interrupt available for "
   1801 				    "bscbus channel %d", csp->chno);
   1802 				goto failed2;
   1803 			}
   1804 
   1805 			if (ddi_intr_hilevel(csp->ssp->dip, csp->chno) != 0) {
   1806 				cmn_err(CE_WARN,
   1807 				    "bscbus interrupts are high "
   1808 				    "level - channel not usable.");
   1809 				goto failed2;
   1810 			} else {
   1811 				err = ddi_get_iblock_cookie(csp->ssp->dip,
   1812 				    csp->chno, &csp->lo_iblk);
   1813 				if (err != DDI_SUCCESS) {
   1814 					goto failed2;
   1815 				}
   1816 
   1817 				mutex_init(csp->lo_mutex, NULL,
   1818 				    MUTEX_DRIVER, csp->lo_iblk);
   1819 				cv_init(csp->lo_cv, NULL,
   1820 				    CV_DRIVER, NULL);
   1821 				csp->unclaimed_count = 0;
   1822 
   1823 				err = ddi_add_intr(csp->ssp->dip, csp->chno,
   1824 				    &csp->lo_iblk, NULL,
   1825 				    bscbus_hwintr, (caddr_t)csp);
   1826 				if (err != DDI_SUCCESS) {
   1827 					cv_destroy(csp->lo_cv);
   1828 					mutex_destroy(csp->lo_mutex);
   1829 					goto failed2;
   1830 				}
   1831 			}
   1832 		}
   1833 		/*
   1834 		 * The channel is now live and may
   1835 		 * receive interrupts
   1836 		 */
   1837 	} else if (csp->map_dog != map_dog) {
   1838 		bscbus_trace(csp, 'C', "bscbus_claim_channel",
   1839 		    "request conflicts with previous mapping. old %x, new %x.",
   1840 		    csp->map_dog, map_dog);
   1841 		goto failed1;
   1842 	}
   1843 	mutex_exit(csp->ssp->ch_mutex);
   1844 	return (1);
   1845 
   1846 failed2:
   1847 	/* unmap regs for failed channel */
   1848 	if (csp->ssp->per_channel_regs == B_TRUE) {
   1849 		ddi_regs_map_free(&csp->ch_handle);
   1850 	}
   1851 	csp->ch_handle = NULL;
   1852 	csp->ch_regs = (void *)NULL;
   1853 failed1:
   1854 	csp->map_count--;
   1855 	mutex_exit(csp->ssp->ch_mutex);
   1856 	return (0);
   1857 }
   1858 
   1859 static void
   1860 bscbus_release_channel(struct bscbus_channel_state *csp)
   1861 {
   1862 	mutex_enter(csp->ssp->ch_mutex);
   1863 	if (csp->map_count == 1) {
   1864 		/* No-one is now using this channel - shutdown channel */
   1865 		bscbus_trace(csp, 'C', "bscbus_release_channel",
   1866 		    "shutdown channel %d, count %d",
   1867 		    csp->chno, csp->map_count);
   1868 
   1869 		if (csp->map_dog == 0) {
   1870 			ASSERT(!ddi_intr_hilevel(csp->ssp->dip, csp->chno));
   1871 			ddi_remove_intr(csp->ssp->dip, csp->chno, csp->lo_iblk);
   1872 		}
   1873 		cv_destroy(csp->lo_cv);
   1874 		mutex_destroy(csp->lo_mutex);
   1875 		mutex_destroy(csp->dog_mutex);
   1876 		bscbus_hw_reset(csp);
   1877 
   1878 		/* unmap registers if using the new register scheme */
   1879 		if (csp->ssp->per_channel_regs == B_TRUE) {
   1880 			ddi_regs_map_free(&csp->ch_handle);
   1881 		}
   1882 		csp->ch_handle = NULL;
   1883 		csp->ch_regs = (void *)NULL;
   1884 	}
   1885 	csp->map_count--;
   1886 	bscbus_trace(csp, 'C', "bscbus_release_channel",
   1887 	    "release channel %d, count %d",
   1888 	    csp->chno, csp->map_count);
   1889 	mutex_exit(csp->ssp->ch_mutex);
   1890 }
   1891 
   1892 
   1893 /*
   1894  *  Nexus routines
   1895  */
   1896 
   1897 #if	defined(NDI_ACC_HDL_V2)
   1898 
   1899 static const ndi_acc_fns_t bscbus_vreg_acc_fns = {
   1900 	NDI_ACC_FNS_CURRENT,
   1901 	NDI_ACC_FNS_V1,
   1902 
   1903 	bscbus_vreg_get8,
   1904 	bscbus_vreg_put8,
   1905 	bscbus_vreg_rep_get8,
   1906 	bscbus_vreg_rep_put8,
   1907 
   1908 	bscbus_no_get16,
   1909 	bscbus_no_put16,
   1910 	bscbus_no_rep_get16,
   1911 	bscbus_no_rep_put16,
   1912 
   1913 	bscbus_meta_get32,
   1914 	bscbus_meta_put32,
   1915 	bscbus_meta_rep_get32,
   1916 	bscbus_meta_rep_put32,
   1917 
   1918 	bscbus_no_get64,
   1919 	bscbus_no_put64,
   1920 	bscbus_no_rep_get64,
   1921 	bscbus_no_rep_put64,
   1922 
   1923 	bscbus_acc_fault_check
   1924 };
   1925 
   1926 static const ndi_acc_fns_t bscbus_pat_acc_fns = {
   1927 	NDI_ACC_FNS_CURRENT,
   1928 	NDI_ACC_FNS_V1,
   1929 
   1930 	bscbus_pat_get8,
   1931 	bscbus_pat_put8,
   1932 	bscbus_pat_rep_get8,
   1933 	bscbus_pat_rep_put8,
   1934 
   1935 	bscbus_no_get16,
   1936 	bscbus_no_put16,
   1937 	bscbus_no_rep_get16,
   1938 	bscbus_no_rep_put16,
   1939 
   1940 	bscbus_meta_get32,
   1941 	bscbus_meta_put32,
   1942 	bscbus_meta_rep_get32,
   1943 	bscbus_meta_rep_put32,
   1944 
   1945 	bscbus_no_get64,
   1946 	bscbus_no_put64,
   1947 	bscbus_no_rep_get64,
   1948 	bscbus_no_rep_put64,
   1949 
   1950 	bscbus_acc_fault_check
   1951 };
   1952 
   1953 static const ndi_acc_fns_t bscbus_event_acc_fns = {
   1954 	NDI_ACC_FNS_CURRENT,
   1955 	NDI_ACC_FNS_V1,
   1956 
   1957 	bscbus_no_get8,
   1958 	bscbus_no_put8,
   1959 	bscbus_no_rep_get8,
   1960 	bscbus_no_rep_put8,
   1961 
   1962 	bscbus_event_get16,
   1963 	bscbus_event_put16,
   1964 	bscbus_event_rep_get16,
   1965 	bscbus_event_rep_put16,
   1966 
   1967 	bscbus_meta_get32,
   1968 	bscbus_meta_put32,
   1969 	bscbus_meta_rep_get32,
   1970 	bscbus_meta_rep_put32,
   1971 
   1972 	bscbus_no_get64,
   1973 	bscbus_no_put64,
   1974 	bscbus_no_rep_get64,
   1975 	bscbus_no_rep_put64,
   1976 
   1977 	bscbus_acc_fault_check
   1978 };
   1979 
   1980 static int
   1981 bscbus_map_handle(struct bscbus_channel_state *csp, ddi_map_op_t op,
   1982 	int space, caddr_t vaddr, off_t len,
   1983 	ndi_acc_handle_t *hdlp, caddr_t *addrp)
   1984 {
   1985 	switch (op) {
   1986 	default:
   1987 		return (DDI_ME_UNIMPLEMENTED);
   1988 
   1989 	case DDI_MO_MAP_LOCKED:
   1990 		if (bscbus_claim_channel(csp,
   1991 		    (space == LOMBUS_PAT_SPACE)) == 0) {
   1992 			return (DDI_ME_GENERIC);
   1993 		}
   1994 
   1995 		switch (space) {
   1996 		default:
   1997 			return (DDI_ME_REGSPEC_RANGE);
   1998 
   1999 		case LOMBUS_VREG_SPACE:
   2000 			ndi_set_acc_fns(hdlp, &bscbus_vreg_acc_fns);
   2001 			break;
   2002 
   2003 		case LOMBUS_PAT_SPACE:
   2004 			ndi_set_acc_fns(hdlp, &bscbus_pat_acc_fns);
   2005 			break;
   2006 
   2007 		case LOMBUS_EVENT_SPACE:
   2008 			ndi_set_acc_fns(hdlp, &bscbus_event_acc_fns);
   2009 			break;
   2010 		}
   2011 		hdlp->ah_addr = *addrp = vaddr;
   2012 		hdlp->ah_len = len;
   2013 		hdlp->ah_bus_private = csp;
   2014 		return (DDI_SUCCESS);
   2015 
   2016 	case DDI_MO_UNMAP:
   2017 		*addrp = NULL;
   2018 		hdlp->ah_bus_private = NULL;
   2019 		bscbus_release_channel(csp);
   2020 		return (DDI_SUCCESS);
   2021 	}
   2022 }
   2023 
   2024 #else
   2025 
   2026 static int
   2027 bscbus_map_handle(struct bscbus_channel_state *csp, ddi_map_op_t op,
   2028 	int space, caddr_t vaddr, off_t len,
   2029 	ddi_acc_hdl_t *hdlp, caddr_t *addrp)
   2030 {
   2031 	ddi_acc_impl_t *aip = hdlp->ah_platform_private;
   2032 
   2033 	switch (op) {
   2034 	default:
   2035 		return (DDI_ME_UNIMPLEMENTED);
   2036 
   2037 	case DDI_MO_MAP_LOCKED:
   2038 		if (bscbus_claim_channel(csp,
   2039 		    (space == LOMBUS_PAT_SPACE)) == 0) {
   2040 			return (DDI_ME_GENERIC);
   2041 		}
   2042 
   2043 		switch (space) {
   2044 		default:
   2045 			return (DDI_ME_REGSPEC_RANGE);
   2046 
   2047 		case LOMBUS_VREG_SPACE:
   2048 			aip->ahi_get8 = bscbus_vreg_get8;
   2049 			aip->ahi_put8 = bscbus_vreg_put8;
   2050 			aip->ahi_rep_get8 = bscbus_vreg_rep_get8;
   2051 			aip->ahi_rep_put8 = bscbus_vreg_rep_put8;
   2052 
   2053 			aip->ahi_get16 = bscbus_no_get16;
   2054 			aip->ahi_put16 = bscbus_no_put16;
   2055 			aip->ahi_rep_get16 = bscbus_no_rep_get16;
   2056 			aip->ahi_rep_put16 = bscbus_no_rep_put16;
   2057 
   2058 			aip->ahi_get32 = bscbus_meta_get32;
   2059 			aip->ahi_put32 = bscbus_meta_put32;
   2060 			aip->ahi_rep_get32 = bscbus_meta_rep_get32;
   2061 			aip->ahi_rep_put32 = bscbus_meta_rep_put32;
   2062 
   2063 			aip->ahi_get64 = bscbus_no_get64;
   2064 			aip->ahi_put64 = bscbus_no_put64;
   2065 			aip->ahi_rep_get64 = bscbus_no_rep_get64;
   2066 			aip->ahi_rep_put64 = bscbus_no_rep_put64;
   2067 
   2068 			aip->ahi_fault_check = bscbus_acc_fault_check;
   2069 			break;
   2070 
   2071 		case LOMBUS_PAT_SPACE:
   2072 			aip->ahi_get8 = bscbus_pat_get8;
   2073 			aip->ahi_put8 = bscbus_pat_put8;
   2074 			aip->ahi_rep_get8 = bscbus_pat_rep_get8;
   2075 			aip->ahi_rep_put8 = bscbus_pat_rep_put8;
   2076 
   2077 			aip->ahi_get16 = bscbus_no_get16;
   2078 			aip->ahi_put16 = bscbus_no_put16;
   2079 			aip->ahi_rep_get16 = bscbus_no_rep_get16;
   2080 			aip->ahi_rep_put16 = bscbus_no_rep_put16;
   2081 
   2082 			aip->ahi_get32 = bscbus_meta_get32;
   2083 			aip->ahi_put32 = bscbus_meta_put32;
   2084 			aip->ahi_rep_get32 = bscbus_meta_rep_get32;
   2085 			aip->ahi_rep_put32 = bscbus_meta_rep_put32;
   2086 
   2087 			aip->ahi_get64 = bscbus_no_get64;
   2088 			aip->ahi_put64 = bscbus_no_put64;
   2089 			aip->ahi_rep_get64 = bscbus_no_rep_get64;
   2090 			aip->ahi_rep_put64 = bscbus_no_rep_put64;
   2091 
   2092 			aip->ahi_fault_check = bscbus_acc_fault_check;
   2093 			break;
   2094 
   2095 		case LOMBUS_EVENT_SPACE:
   2096 			aip->ahi_get8 = bscbus_no_get8;
   2097 			aip->ahi_put8 = bscbus_no_put8;
   2098 			aip->ahi_rep_get8 = bscbus_no_rep_get8;
   2099 			aip->ahi_rep_put8 = bscbus_no_rep_put8;
   2100 
   2101 			aip->ahi_get16 = bscbus_event_get16;
   2102 			aip->ahi_put16 = bscbus_event_put16;
   2103 			aip->ahi_rep_get16 = bscbus_event_rep_get16;
   2104 			aip->ahi_rep_put16 = bscbus_event_rep_put16;
   2105 
   2106 			aip->ahi_get32 = bscbus_meta_get32;
   2107 			aip->ahi_put32 = bscbus_meta_put32;
   2108 			aip->ahi_rep_get32 = bscbus_meta_rep_get32;
   2109 			aip->ahi_rep_put32 = bscbus_meta_rep_put32;
   2110 
   2111 			aip->ahi_get64 = bscbus_no_get64;
   2112 			aip->ahi_put64 = bscbus_no_put64;
   2113 			aip->ahi_rep_get64 = bscbus_no_rep_get64;
   2114 			aip->ahi_rep_put64 = bscbus_no_rep_put64;
   2115 
   2116 			aip->ahi_fault_check = bscbus_acc_fault_check;
   2117 			break;
   2118 		}
   2119 		hdlp->ah_addr = *addrp = vaddr;
   2120 		hdlp->ah_len = len;
   2121 		hdlp->ah_bus_private = csp;
   2122 		return (DDI_SUCCESS);
   2123 
   2124 	case DDI_MO_UNMAP:
   2125 		*addrp = NULL;
   2126 		hdlp->ah_bus_private = NULL;
   2127 		bscbus_release_channel(csp);
   2128 		return (DDI_SUCCESS);
   2129 	}
   2130 }
   2131 
   2132 #endif	/* NDI_ACC_HDL_V2 */
   2133 
   2134 static int
   2135 bscbus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
   2136 	off_t off, off_t len, caddr_t *addrp)
   2137 {
   2138 	struct bscbus_child_info *lcip;
   2139 	struct bscbus_state *ssp;
   2140 	lombus_regspec_t *rsp;
   2141 
   2142 	if ((ssp = bscbus_getstate(dip, -1, "bscbus_map")) == NULL)
   2143 		return (DDI_FAILURE);	/* this "can't happen" */
   2144 
   2145 	/*
   2146 	 * Validate mapping request ...
   2147 	 */
   2148 
   2149 	if (mp->map_flags != DDI_MF_KERNEL_MAPPING)
   2150 		return (DDI_ME_UNSUPPORTED);
   2151 	if (mp->map_handlep == NULL)
   2152 		return (DDI_ME_UNSUPPORTED);
   2153 	if (mp->map_type != DDI_MT_RNUMBER)
   2154 		return (DDI_ME_UNIMPLEMENTED);
   2155 	if ((lcip = ddi_get_parent_data(rdip)) == NULL)
   2156 		return (DDI_ME_INVAL);
   2157 	if ((rsp = lcip->rsp) == NULL)
   2158 		return (DDI_ME_INVAL);
   2159 	if (mp->map_obj.rnumber >= lcip->nregs)
   2160 		return (DDI_ME_RNUMBER_RANGE);
   2161 	rsp += mp->map_obj.rnumber;
   2162 	if (off < 0 || off >= rsp->lombus_size)
   2163 		return (DDI_ME_INVAL);
   2164 	if (len == 0)
   2165 		len = rsp->lombus_size-off;
   2166 	if (len < 0)
   2167 		return (DDI_ME_INVAL);
   2168 	if (off+len < 0 || off+len > rsp->lombus_size)
   2169 		return (DDI_ME_INVAL);
   2170 
   2171 	return (bscbus_map_handle(
   2172 	    &ssp->channel[LOMBUS_SPACE_TO_CHANNEL(rsp->lombus_space)],
   2173 	    mp->map_op, LOMBUS_SPACE_TO_REGSET(rsp->lombus_space),
   2174 	    VREG_TO_ADDR(rsp->lombus_base+off), len, mp->map_handlep, addrp));
   2175 }
   2176 
   2177 
   2178 static int
   2179 bscbus_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op,
   2180 	void *arg, void *result)
   2181 {
   2182 	struct bscbus_child_info *lcip;
   2183 	lombus_regspec_t *rsp;
   2184 	dev_info_t *cdip;
   2185 	char addr[32];
   2186 	uint_t nregs;
   2187 	uint_t rnum;
   2188 	int *regs;
   2189 	int limit;
   2190 	int err;
   2191 	int i;
   2192 
   2193 	if (bscbus_getstate(dip, -1, "bscbus_ctlops") == NULL)
   2194 		return (DDI_FAILURE);	/* this "can't happen" */
   2195 
   2196 	switch (op) {
   2197 	default:
   2198 		break;
   2199 
   2200 	case DDI_CTLOPS_INITCHILD:
   2201 		/*
   2202 		 * First, look up and validate the "reg" property.
   2203 		 *
   2204 		 * It must be a non-empty integer array containing a set
   2205 		 * of triples.  Once we've verified that, we can treat it
   2206 		 * as an array of type lombus_regspec_t[], which defines
   2207 		 * the meaning of the elements of each triple:
   2208 		 * +  the first element of each triple must be a valid space
   2209 		 * +  the second and third elements (base, size) of each
   2210 		 *	triple must define a valid subrange of that space
   2211 		 * If it passes all the tests, we save it away for future
   2212 		 * reference in the child's parent-private-data field.
   2213 		 */
   2214 		cdip = arg;
   2215 		err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
   2216 		    DDI_PROP_DONTPASS, "reg", &regs, &nregs);
   2217 		if (err != DDI_PROP_SUCCESS)
   2218 			return (DDI_FAILURE);
   2219 
   2220 		err = (nregs <= 0 || (nregs % LOMBUS_REGSPEC_SIZE) != 0);
   2221 		nregs /= LOMBUS_REGSPEC_SIZE;
   2222 		rsp = (lombus_regspec_t *)regs;
   2223 		for (i = 0; i < nregs && !err; ++i) {
   2224 			switch (LOMBUS_SPACE_TO_REGSET(rsp[i].lombus_space)) {
   2225 			default:
   2226 				limit = 0;
   2227 				err = 1;
   2228 				cmn_err(CE_WARN,
   2229 				    "child(%p): unknown reg space %d",
   2230 				    (void *)cdip, rsp[i].lombus_space);
   2231 				break;
   2232 
   2233 			case LOMBUS_VREG_SPACE:
   2234 				limit = LOMBUS_MAX_REG+1;
   2235 				break;
   2236 
   2237 			case LOMBUS_PAT_SPACE:
   2238 				limit = LOMBUS_PAT_REG+1;
   2239 				break;
   2240 
   2241 			case LOMBUS_EVENT_SPACE:
   2242 				limit = LOMBUS_EVENT_REG+1;
   2243 				break;
   2244 			}
   2245 
   2246 			err |= (rsp[i].lombus_base < 0);
   2247 			err |= (rsp[i].lombus_base >= limit);
   2248 
   2249 			if (rsp[i].lombus_size == 0)
   2250 				rsp[i].lombus_size = limit-rsp[i].lombus_base;
   2251 
   2252 			err |= (rsp[i].lombus_size < 0);
   2253 			err |= (rsp[i].lombus_base+rsp[i].lombus_size < 0);
   2254 			err |= (rsp[i].lombus_base+rsp[i].lombus_size > limit);
   2255 
   2256 			err |= (rsp[i].lombus_base+rsp[i].lombus_size > limit);
   2257 
   2258 		}
   2259 
   2260 		if (err) {
   2261 			ddi_prop_free(regs);
   2262 			return (DDI_FAILURE);
   2263 		}
   2264 
   2265 		lcip = kmem_zalloc(sizeof (*lcip), KM_SLEEP);
   2266 		lcip->nregs = nregs;
   2267 		lcip->rsp = rsp;
   2268 		ddi_set_parent_data(cdip, lcip);
   2269 
   2270 		(void) snprintf(addr, sizeof (addr),
   2271 		    "%x,%x", rsp[0].lombus_space, rsp[0].lombus_base);
   2272 		ddi_set_name_addr(cdip, addr);
   2273 
   2274 		return (DDI_SUCCESS);
   2275 
   2276 	case DDI_CTLOPS_UNINITCHILD:
   2277 		cdip = arg;
   2278 		ddi_set_name_addr(cdip, NULL);
   2279 		lcip = ddi_get_parent_data(cdip);
   2280 		ddi_set_parent_data(cdip, NULL);
   2281 		ddi_prop_free(lcip->rsp);
   2282 		kmem_free(lcip, sizeof (*lcip));
   2283 		return (DDI_SUCCESS);
   2284 
   2285 	case DDI_CTLOPS_REPORTDEV:
   2286 		if (rdip == NULL)
   2287 			return (DDI_FAILURE);
   2288 
   2289 		cmn_err(CE_CONT, "?BSC device: %s@%s, %s#%d\n",
   2290 		    ddi_node_name(rdip), ddi_get_name_addr(rdip),
   2291 		    ddi_driver_name(dip), ddi_get_instance(dip));
   2292 
   2293 		return (DDI_SUCCESS);
   2294 
   2295 	case DDI_CTLOPS_REGSIZE:
   2296 		if ((lcip = ddi_get_parent_data(rdip)) == NULL)
   2297 			return (DDI_FAILURE);
   2298 		if ((rnum = *(uint_t *)arg) >= lcip->nregs)
   2299 			return (DDI_FAILURE);
   2300 		*(off_t *)result = lcip->rsp[rnum].lombus_size;
   2301 		return (DDI_SUCCESS);
   2302 
   2303 	case DDI_CTLOPS_NREGS:
   2304 		if ((lcip = ddi_get_parent_data(rdip)) == NULL)
   2305 			return (DDI_FAILURE);
   2306 		*(int *)result = lcip->nregs;
   2307 		return (DDI_SUCCESS);
   2308 	}
   2309 
   2310 	return (ddi_ctlops(dip, rdip, op, arg, result));
   2311 }
   2312 
   2313 
   2314 /*
   2315  * This nexus does not support passing interrupts to leaf drivers, so
   2316  * all the intrspec-related operations just fail as cleanly as possible.
   2317  */
   2318 
   2319 /*ARGSUSED*/
   2320 static int
   2321 bscbus_intr_op(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op,
   2322     ddi_intr_handle_impl_t *hdlp, void *result)
   2323 {
   2324 #if defined(__sparc)
   2325 	return (i_ddi_intr_ops(dip, rdip, op, hdlp, result));
   2326 #else
   2327 	_NOTE(ARGUNUSED(dip, rdip, op, hdlp, result))
   2328 	return (DDI_FAILURE);
   2329 #endif
   2330 }
   2331 
   2332 /*
   2333  *  Clean up on detach or failure of attach
   2334  */
   2335 static int
   2336 bscbus_unattach(struct bscbus_state *ssp, int instance)
   2337 {
   2338 	int chno;
   2339 
   2340 	if (ssp != NULL) {
   2341 		for (chno = 0; chno < BSCBUS_MAX_CHANNELS; chno++) {
   2342 			ASSERT(ssp->channel[chno].map_count == 0);
   2343 		}
   2344 		bscbus_offline(ssp);
   2345 		ddi_set_driver_private(ssp->dip, NULL);
   2346 		mutex_destroy(ssp->ch_mutex);
   2347 	}
   2348 #ifdef BSCBUS_LOGSTATUS
   2349 	if (ssp->cmd_log_size != 0) {
   2350 		kmem_free(ssp->cmd_log,
   2351 		    ssp->cmd_log_size * sizeof (bsc_cmd_log_t));
   2352 	}
   2353 #endif /* BSCBUS_LOGSTATUS */
   2354 
   2355 
   2356 	ddi_soft_state_free(bscbus_statep, instance);
   2357 	return (DDI_FAILURE);
   2358 }
   2359 
   2360 /*
   2361  *  Autoconfiguration routines
   2362  */
   2363 
   2364 static int
   2365 bscbus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
   2366 {
   2367 	struct bscbus_state *ssp = NULL;
   2368 	int chno;
   2369 	int instance;
   2370 	int err;
   2371 
   2372 	switch (cmd) {
   2373 	default:
   2374 		return (DDI_FAILURE);
   2375 
   2376 	case DDI_ATTACH:
   2377 		break;
   2378 	}
   2379 
   2380 	/*
   2381 	 *  Allocate the soft-state structure
   2382 	 */
   2383 	instance = ddi_get_instance(dip);
   2384 	if (ddi_soft_state_zalloc(bscbus_statep, instance) != DDI_SUCCESS)
   2385 		return (DDI_FAILURE);
   2386 	if ((ssp = bscbus_getstate(dip, instance, "bscbus_attach")) == NULL)
   2387 		return (bscbus_unattach(ssp, instance));
   2388 	ddi_set_driver_private(dip, ssp);
   2389 
   2390 	/*
   2391 	 *  Initialise devinfo-related fields
   2392 	 */
   2393 	ssp->dip = dip;
   2394 	ssp->majornum = ddi_driver_major(dip);
   2395 	ssp->instance = instance;
   2396 
   2397 	/*
   2398 	 *  Set various options from .conf properties
   2399 	 */
   2400 	ssp->debug = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
   2401 	    DDI_PROP_DONTPASS, "debug", 0);
   2402 
   2403 	mutex_init(ssp->ch_mutex, NULL, MUTEX_DRIVER, NULL);
   2404 
   2405 #ifdef BSCBUS_LOGSTATUS
   2406 	ssp->cmd_log_size = bscbus_cmd_log_size;
   2407 	if (ssp->cmd_log_size != 0) {
   2408 		ssp->cmd_log_idx = 0;
   2409 		ssp->cmd_log = kmem_zalloc(ssp->cmd_log_size *
   2410 		    sizeof (bsc_cmd_log_t), KM_SLEEP);
   2411 	}
   2412 #endif /* BSCBUS_LOGSTATUS */
   2413 
   2414 	/*
   2415 	 *  Online the hardware ...
   2416 	 */
   2417 	err = bscbus_online(ssp);
   2418 	if (err != 0)
   2419 		return (bscbus_unattach(ssp, instance));
   2420 
   2421 	for (chno = 0; chno < BSCBUS_MAX_CHANNELS; chno++) {
   2422 		struct bscbus_channel_state *csp = &ssp->channel[chno];
   2423 
   2424 		/*
   2425 		 * Initialise state
   2426 		 * The hardware/interrupts are setup at map time to
   2427 		 * avoid claiming hardware that OBP is using
   2428 		 */
   2429 		csp->ssp = ssp;
   2430 		csp->chno = chno;
   2431 		csp->map_count = 0;
   2432 		csp->map_dog = B_FALSE;
   2433 	}
   2434 
   2435 	/*
   2436 	 *  All done, report success
   2437 	 */
   2438 	ddi_report_dev(dip);
   2439 	return (DDI_SUCCESS);
   2440 }
   2441 
   2442 static int
   2443 bscbus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
   2444 {
   2445 	struct bscbus_state *ssp;
   2446 	int instance;
   2447 
   2448 	switch (cmd) {
   2449 	default:
   2450 		return (DDI_FAILURE);
   2451 
   2452 	case DDI_DETACH:
   2453 		break;
   2454 	}
   2455 
   2456 	instance = ddi_get_instance(dip);
   2457 	if ((ssp = bscbus_getstate(dip, instance, "bscbus_detach")) == NULL)
   2458 		return (DDI_FAILURE);	/* this "can't happen" */
   2459 
   2460 	(void) bscbus_unattach(ssp, instance);
   2461 	return (DDI_SUCCESS);
   2462 }
   2463 
   2464 static int
   2465 bscbus_reset(dev_info_t *dip, ddi_reset_cmd_t cmd)
   2466 {
   2467 	struct bscbus_state *ssp;
   2468 	int chno;
   2469 
   2470 	_NOTE(ARGUNUSED(cmd))
   2471 
   2472 	if ((ssp = bscbus_getstate(dip, -1, "bscbus_reset")) == NULL)
   2473 		return (DDI_FAILURE);
   2474 
   2475 	for (chno = 0; chno < BSCBUS_MAX_CHANNELS; chno++) {
   2476 		bscbus_hw_reset(&ssp->channel[chno]);
   2477 	}
   2478 	return (DDI_SUCCESS);
   2479 }
   2480 
   2481 
   2482 /*
   2483  * System interface structures
   2484  */
   2485 
   2486 static struct cb_ops bscbus_cb_ops =
   2487 {
   2488 	nodev,			/* b/c open	*/
   2489 	nodev,			/* b/c close	*/
   2490 	nodev,			/* b   strategy	*/
   2491 	nodev,			/* b   print	*/
   2492 	nodev,			/* b   dump 	*/
   2493 	nodev,			/* c   read	*/
   2494 	nodev,			/* c   write	*/
   2495 	nodev,			/* c   ioctl	*/
   2496 	nodev,			/* c   devmap	*/
   2497 	nodev,			/* c   mmap	*/
   2498 	nodev,			/* c   segmap	*/
   2499 	nochpoll,		/* c   poll	*/
   2500 	ddi_prop_op,		/* b/c prop_op	*/
   2501 	NULL,			/* c   streamtab */
   2502 	D_MP | D_NEW		/* b/c flags	*/
   2503 };
   2504 
   2505 static struct bus_ops bscbus_bus_ops =
   2506 {
   2507 	BUSO_REV,			/* revision		*/
   2508 	bscbus_map,			/* bus_map		*/
   2509 	0,				/* get_intrspec		*/
   2510 	0,				/* add_intrspec		*/
   2511 	0,				/* remove_intrspec	*/
   2512 	i_ddi_map_fault,		/* map_fault		*/
   2513 	ddi_no_dma_map,			/* dma_map		*/
   2514 	ddi_no_dma_allochdl,		/* allocate DMA handle	*/
   2515 	ddi_no_dma_freehdl,		/* free DMA handle	*/
   2516 	ddi_no_dma_bindhdl,		/* bind DMA handle	*/
   2517 	ddi_no_dma_unbindhdl,		/* unbind DMA handle	*/
   2518 	ddi_no_dma_flush,		/* flush DMA		*/
   2519 	ddi_no_dma_win,			/* move DMA window	*/
   2520 	ddi_no_dma_mctl,		/* generic DMA control	*/
   2521 	bscbus_ctlops,			/* generic control	*/
   2522 	ddi_bus_prop_op,		/* prop_op		*/
   2523 	ndi_busop_get_eventcookie,	/* get_eventcookie	*/
   2524 	ndi_busop_add_eventcall,	/* add_eventcall	*/
   2525 	ndi_busop_remove_eventcall,	/* remove_eventcall	*/
   2526 	ndi_post_event,			/* post_event		*/
   2527 	0,				/* interrupt control	*/
   2528 	0,				/* bus_config		*/
   2529 	0,				/* bus_unconfig		*/
   2530 	0,				/* bus_fm_init		*/
   2531 	0,				/* bus_fm_fini		*/
   2532 	0,				/* bus_fm_access_enter	*/
   2533 	0,				/* bus_fm_access_exit	*/
   2534 	0,				/* bus_power		*/
   2535 	bscbus_intr_op			/* bus_intr_op		*/
   2536 };
   2537 
   2538 static struct dev_ops bscbus_dev_ops =
   2539 {
   2540 	DEVO_REV,
   2541 	0,				/* refcount		*/
   2542 	ddi_no_info,			/* getinfo		*/
   2543 	nulldev,			/* identify		*/
   2544 	nulldev,			/* probe		*/
   2545 	bscbus_attach,			/* attach		*/
   2546 	bscbus_detach,			/* detach		*/
   2547 	bscbus_reset,			/* reset		*/
   2548 	&bscbus_cb_ops,			/* driver operations	*/
   2549 	&bscbus_bus_ops,		/* bus operations	*/
   2550 	NULL,				/* power		*/
   2551 	ddi_quiesce_not_needed,			/* quiesce		*/
   2552 };
   2553 
   2554 static struct modldrv modldrv =
   2555 {
   2556 	&mod_driverops,
   2557 	"bscbus driver",
   2558 	&bscbus_dev_ops
   2559 };
   2560 
   2561 static struct modlinkage modlinkage =
   2562 {
   2563 	MODREV_1,
   2564 	{
   2565 		&modldrv,
   2566 		NULL
   2567 	}
   2568 };
   2569 
   2570 
   2571 /*
   2572  *  Dynamic loader interface code
   2573  */
   2574 
   2575 int
   2576 _init(void)
   2577 {
   2578 	int err;
   2579 
   2580 	err = ddi_soft_state_init(&bscbus_statep,
   2581 	    sizeof (struct bscbus_state), 0);
   2582 	if (err == DDI_SUCCESS)
   2583 		if ((err = mod_install(&modlinkage)) != DDI_SUCCESS) {
   2584 			ddi_soft_state_fini(&bscbus_statep);
   2585 		}
   2586 
   2587 	return (err);
   2588 }
   2589 
   2590 int
   2591 _info(struct modinfo *mip)
   2592 {
   2593 	return (mod_info(&modlinkage, mip));
   2594 }
   2595 
   2596 int
   2597 _fini(void)
   2598 {
   2599 	int err;
   2600 
   2601 	if ((err = mod_remove(&modlinkage)) == DDI_SUCCESS) {
   2602 		ddi_soft_state_fini(&bscbus_statep);
   2603 		bscbus_major = NOMAJOR;
   2604 	}
   2605 
   2606 	return (err);
   2607 }
   2608 
   2609 #ifdef BSCBUS_LOGSTATUS
   2610 void bscbus_cmd_log(struct bscbus_channel_state *csp, bsc_cmd_stamp_t cat,
   2611     uint8_t status, uint8_t data)
   2612 {
   2613 	int idx;
   2614 	bsc_cmd_log_t *logp;
   2615 	struct bscbus_state *ssp;
   2616 
   2617 	if ((csp) == NULL)
   2618 		return;
   2619 	if ((ssp = (csp)->ssp) == NULL)
   2620 		return;
   2621 	if (ssp->cmd_log_size == 0)
   2622 		return;
   2623 	if ((bscbus_cmd_log_flags & (1 << cat)) == 0)
   2624 		return;
   2625 	idx = atomic_add_32_nv(&ssp->cmd_log_idx, 1);
   2626 	logp = &ssp->cmd_log[idx % ssp->cmd_log_size];
   2627 	logp->bcl_seq = idx;
   2628 	logp->bcl_cat = cat;
   2629 	logp->bcl_now = gethrtime();
   2630 	logp->bcl_chno = csp->chno;
   2631 	logp->bcl_cmdstate = csp->cmdstate;
   2632 	logp->bcl_status = status;
   2633 	logp->bcl_data = data;
   2634 }
   2635 #endif /* BSCBUS_LOGSTATUS */
   2636