bscbus.c revision 7656:2621e50fdf4a
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 2008 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
118typedef 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
138typedef 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
148uint32_t	bscbus_cmd_log_size = 1024;
149
150uint32_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 */
234enum 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
245struct 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
299struct 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 */
350struct bscbus_child_info {
351	lombus_regspec_t *rsp;
352	int nregs;
353};
354
355#ifdef BSCBUS_LOGSTATUS
356void 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
367static void *bscbus_statep;
368
369static major_t bscbus_major = NOMAJOR;
370
371static 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
383static void
384bscbus_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
410static struct bscbus_state *
411bscbus_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
457static void
458bscbus_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
466static uint8_t
467bscbus_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
480static void
481bscbus_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
487static boolean_t
488bscbus_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 */
498static void
499bscbus_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
610static void
611bscbus_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
644static void
645bscbus_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
674static void
675bscbus_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
694static boolean_t
695bscbus_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 */
788static void
789bscbus_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
856static uint_t
857bscbus_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
894void
895bscbus_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 */
925static uint8_t
926bscbus_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	clock_t tick;
931	uint8_t status;
932
933	/*
934	 * First of all, wait for the interface to be available.
935	 *
936	 * NOTE: we blow through all the mutex/cv/state checking and
937	 * preempt any command in progress if the system is panicking!
938	 */
939	csp = HANDLE_PRIVATE(hdlp);
940	mutex_enter(csp->lo_mutex);
941	while (csp->cmdstate != BSCBUS_CMDSTATE_IDLE && !ddi_in_panic())
942		cv_wait(csp->lo_cv, csp->lo_mutex);
943
944	csp->cmdstate = BSCBUS_CMDSTATE_BUSY;
945	csp->sequence = (csp->sequence + BSCBUS_SEQ_LSB) & BSCBUS_SEQ;
946
947	/*
948	 * We have exclusive ownership, so assemble the command (backwards):
949	 *
950	 * [byte 0]	Command:	modified by XADDR and/or WMSB bits
951	 * [Optional] Parameter: 	Value to write (low 7 bits)
952	 * [Optional] Parameter: 	Register number (high 7 bits)
953	 * [Optional] Parameter: 	Register number (low 7 bits)
954	 */
955	csp->cmdp = &csp->cmdbuf[0];
956	*csp->cmdp++ = BSCBUS_CMD | csp->sequence | cmd;
957	switch (cmd) {
958	case BSCBUS_CMD_WRITE:
959		*csp->cmdp++ = val & 0x7f;
960		if (val >= 0x80)
961			csp->cmdbuf[0] |= BSCBUS_CMD_WMSB;
962		/*FALLTHRU*/
963	case BSCBUS_CMD_READ:
964		if (BSCBUS_VREG_HI(vreg) != 0) {
965			*csp->cmdp++ = BSCBUS_VREG_HI(vreg);
966			csp->cmdbuf[0] |= BSCBUS_CMD_XADDR;
967		}
968		*csp->cmdp++ = BSCBUS_VREG_LO(vreg);
969		/*FALLTHRU*/
970	case BSCBUS_CMD_NOP:
971		break;
972	}
973
974	/*
975	 * Check and update the H8 h/w fault status before accessing
976	 * the chip registers.  If there's a (new or previous) fault,
977	 * we'll run through the protocol but won't really touch the
978	 * hardware and all commands will timeout.  If a previously
979	 * discovered fault has now gone away (!), then we can (try to)
980	 * proceed with the new command (probably a probe).
981	 */
982	bscbus_check_fault_status(csp);
983
984	/*
985	 * Prepare for the command (to be processed by the interrupt
986	 * handler and/or polling loop below), and wait for a response
987	 * or timeout.
988	 */
989	start = ddi_get_lbolt();
990	csp->deadline = start + drv_usectohz(LOMBUS_CMD_TIMEOUT/1000);
991	csp->error = 0;
992	csp->index = 0;
993	csp->result = DUMMY_VALUE;
994
995	status = bscbus_get_reg(csp, H8_STR);
996	if (status & H8_STR_BUSY) {
997		bscbus_cmd_log(csp, BSC_CMD_BUSY, status, 0xfd);
998		/*
999		 * Must ensure that the busy state has cleared before
1000		 * sending the command
1001		 */
1002		csp->cmdstate = BSCBUS_CMDSTATE_CLEARING;
1003		bscbus_trace(csp, 'P', "bscbus_cmd",
1004		    "h8 reporting status (%x) busy - clearing", status);
1005	} else {
1006		/* It is clear to send the command immediately */
1007		csp->cmdstate = BSCBUS_CMDSTATE_SENDING;
1008		bscbus_trace(csp, 'P', "bscbus_cmd",
1009		    "sending first byte of command, status %x", status);
1010		bscbus_poll(csp);
1011	}
1012
1013	csp->poll_hz = drv_usectohz(
1014	    (csp->interrupt_failed ?
1015	    BSCBUS_CMD_POLLNOINTS : BSCBUS_CMD_POLL) / 1000);
1016
1017	while ((csp->cmdstate != BSCBUS_CMDSTATE_READY) &&
1018	    (csp->cmdstate != BSCBUS_CMDSTATE_ERROR)) {
1019		ASSERT(csp->cmdstate != BSCBUS_CMDSTATE_IDLE);
1020
1021		tick = ddi_get_lbolt() + csp->poll_hz;
1022		if ((cv_timedwait(csp->lo_cv, csp->lo_mutex, tick) == -1) &&
1023		    csp->cmdstate != BSCBUS_CMDSTATE_READY &&
1024		    csp->cmdstate != BSCBUS_CMDSTATE_ERROR) {
1025			if (!csp->interrupt_failed) {
1026				bscbus_trace(csp, 'I', "bscbus_cmd:",
1027				    "interrupt_failed channel %d", csp->chno);
1028				csp->interrupt_failed = B_TRUE;
1029				csp->poll_hz = drv_usectohz(
1030				    BSCBUS_CMD_POLLNOINTS / 1000);
1031			}
1032			bscbus_poll(csp);
1033		}
1034	}
1035
1036	/*
1037	 * The return value may not be meaningful but retrieve it anyway
1038	 */
1039	val = csp->result;
1040	if (bscbus_faulty(csp)) {
1041		val = DUMMY_VALUE;
1042		HANDLE_FAULT(hdlp) = LOMBUS_ERR_SIOHW;
1043	} else if (csp->cmdstate != BSCBUS_CMDSTATE_READY) {
1044		/*
1045		 * Some problem here ... transfer the error code from
1046		 * the per-instance state to the per-handle fault flag.
1047		 * The error code shouldn't be zero!
1048		 */
1049		if (csp->error != 0)
1050			HANDLE_FAULT(hdlp) = csp->error;
1051		else
1052			HANDLE_FAULT(hdlp) = LOMBUS_ERR_BADERRCODE;
1053	}
1054
1055	/*
1056	 * All done now!
1057	 */
1058	csp->index = 0;
1059	csp->cmdstate = BSCBUS_CMDSTATE_IDLE;
1060	cv_broadcast(csp->lo_cv);
1061	mutex_exit(csp->lo_mutex);
1062
1063	return (val);
1064}
1065
1066/*
1067 * Space 0 - LOM virtual register access
1068 * Only 8-bit accesses are supported.
1069 */
1070static uint8_t
1071bscbus_vreg_get8(HANDLE_TYPE *hdlp, uint8_t *addr)
1072{
1073	ptrdiff_t offset;
1074
1075	/*
1076	 * Check the offset that the caller has added to the base address
1077	 * against the length of the mapping originally requested.
1078	 */
1079	offset = ADDR_TO_OFFSET(addr, hdlp);
1080	if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1081		/*
1082		 * Invalid access - flag a fault and return a dummy value
1083		 */
1084		HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1085		return (DUMMY_VALUE);
1086	}
1087
1088	/*
1089	 * Derive the virtual register number and run the command
1090	 */
1091	return (bscbus_cmd(hdlp, ADDR_TO_VREG(addr), 0, BSCBUS_CMD_READ));
1092}
1093
1094static void
1095bscbus_vreg_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
1096{
1097	ptrdiff_t offset;
1098
1099	/*
1100	 * Check the offset that the caller has added to the base address
1101	 * against the length of the mapping originally requested.
1102	 */
1103	offset = ADDR_TO_OFFSET(addr, hdlp);
1104	if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1105		/*
1106		 * Invalid access - flag a fault and return
1107		 */
1108		HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1109		return;
1110	}
1111
1112	/*
1113	 * Derive the virtual register number and run the command
1114	 */
1115	(void) bscbus_cmd(hdlp, ADDR_TO_VREG(addr), val, BSCBUS_CMD_WRITE);
1116}
1117
1118static void
1119bscbus_vreg_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1120	uint8_t *dev_addr, size_t repcount, uint_t flags)
1121{
1122	size_t inc;
1123
1124	inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1125	for (; repcount--; dev_addr += inc)
1126		*host_addr++ = bscbus_vreg_get8(hdlp, dev_addr);
1127}
1128
1129static void
1130bscbus_vreg_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1131	uint8_t *dev_addr, size_t repcount, uint_t flags)
1132{
1133	size_t inc;
1134
1135	inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1136	for (; repcount--; dev_addr += inc)
1137		bscbus_vreg_put8(hdlp, dev_addr, *host_addr++);
1138}
1139
1140
1141/*
1142 * Space 1 - LOM watchdog pat register access
1143 * Only 8-bit accesses are supported.
1144 *
1145 * Reads have no effect and return 0.
1146 *
1147 * Multi-byte reads (using ddi_rep_get8(9F)) are a fairly inefficient
1148 * way of zeroing the destination area ;-) and still won't pat the dog.
1149 *
1150 * Multi-byte writes (using ddi_rep_put8(9F)) will almost certainly
1151 * only count as a single pat, no matter how many bytes the caller
1152 * says to write, as the inter-pat time is VERY long compared with
1153 * the time it will take to read the memory source area.
1154 */
1155
1156static uint8_t
1157bscbus_pat_get8(HANDLE_TYPE *hdlp, uint8_t *addr)
1158{
1159	ptrdiff_t offset;
1160
1161	/*
1162	 * Check the offset that the caller has added to the base address
1163	 * against the length of the mapping originally requested.
1164	 */
1165	offset = ADDR_TO_OFFSET(addr, hdlp);
1166	if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1167		/*
1168		 * Invalid access - flag a fault and return a dummy value
1169		 */
1170		HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1171		return (DUMMY_VALUE);
1172	}
1173
1174	return (0);
1175}
1176
1177static void
1178bscbus_pat_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
1179{
1180	struct bscbus_channel_state *csp;
1181	ptrdiff_t offset;
1182
1183	/*
1184	 * Check the offset that the caller has added to the base address
1185	 * against the length of the mapping originally requested.
1186	 */
1187	offset = ADDR_TO_OFFSET(addr, hdlp);
1188	if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1189		/*
1190		 * Invalid access - flag a fault and return
1191		 */
1192		HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1193		return;
1194	}
1195
1196	csp = HANDLE_PRIVATE(hdlp);
1197	mutex_enter(csp->dog_mutex);
1198	bscbus_pat_dog(csp, val);
1199	mutex_exit(csp->dog_mutex);
1200}
1201
1202static void
1203bscbus_pat_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1204	uint8_t *dev_addr, size_t repcount, uint_t flags)
1205{
1206	size_t inc;
1207
1208	inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1209	for (; repcount--; dev_addr += inc)
1210		*host_addr++ = bscbus_pat_get8(hdlp, dev_addr);
1211}
1212
1213static void
1214bscbus_pat_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1215	uint8_t *dev_addr, size_t repcount, uint_t flags)
1216{
1217	size_t inc;
1218
1219	inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1220	for (; repcount--; dev_addr += inc)
1221		bscbus_pat_put8(hdlp, dev_addr, *host_addr++);
1222}
1223
1224
1225/*
1226 * Space 2 - LOM async event flag register access
1227 * Only 16-bit accesses are supported.
1228 */
1229static uint16_t
1230bscbus_event_get16(HANDLE_TYPE *hdlp, uint16_t *addr)
1231{
1232	struct bscbus_channel_state *csp;
1233	ptrdiff_t offset;
1234
1235	/*
1236	 * Check the offset that the caller has added to the base address
1237	 * against the length of the mapping orignally requested.
1238	 */
1239	offset = ADDR_TO_OFFSET(addr, hdlp);
1240	if (offset < 0 || (offset%2) != 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1241		/*
1242		 * Invalid access - flag a fault and return a dummy value
1243		 */
1244		HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1245		return (DUMMY_VALUE);
1246	}
1247
1248	/*
1249	 * Return the value of the asynchronous-event-pending flag
1250	 * as passed back by the LOM at the end of the last command.
1251	 */
1252	csp = HANDLE_PRIVATE(hdlp);
1253	return (csp->async);
1254}
1255
1256static void
1257bscbus_event_put16(HANDLE_TYPE *hdlp, uint16_t *addr, uint16_t val)
1258{
1259	ptrdiff_t offset;
1260
1261	_NOTE(ARGUNUSED(val))
1262
1263	/*
1264	 * Check the offset that the caller has added to the base address
1265	 * against the length of the mapping originally requested.
1266	 */
1267	offset = ADDR_TO_OFFSET(addr, hdlp);
1268	if (offset < 0 || (offset%2) != 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1269		/*
1270		 * Invalid access - flag a fault and return
1271		 */
1272		HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1273		return;
1274	}
1275
1276	/*
1277	 * The user can't overwrite the asynchronous-event-pending flag!
1278	 */
1279	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_RO;
1280}
1281
1282static void
1283bscbus_event_rep_get16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
1284	uint16_t *dev_addr, size_t repcount, uint_t flags)
1285{
1286	size_t inc;
1287
1288	inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1289	for (; repcount--; dev_addr += inc)
1290		*host_addr++ = bscbus_event_get16(hdlp, dev_addr);
1291}
1292
1293static void
1294bscbus_event_rep_put16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
1295	uint16_t *dev_addr, size_t repcount, uint_t flags)
1296{
1297	size_t inc;
1298
1299	inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1300	for (; repcount--; dev_addr += inc)
1301		bscbus_event_put16(hdlp, dev_addr, *host_addr++);
1302}
1303
1304
1305/*
1306 * All spaces - access handle fault information
1307 * Only 32-bit accesses are supported.
1308 */
1309static uint32_t
1310bscbus_meta_get32(HANDLE_TYPE *hdlp, uint32_t *addr)
1311{
1312	struct bscbus_channel_state *csp;
1313	ptrdiff_t offset;
1314
1315	/*
1316	 * Derive the offset that the caller has added to the base
1317	 * address originally returned, and use it to determine
1318	 * which meta-register is to be accessed ...
1319	 */
1320	offset = ADDR_TO_OFFSET(addr, hdlp);
1321	switch (offset) {
1322	case LOMBUS_FAULT_REG:
1323		/*
1324		 * This meta-register provides a code for the most
1325		 * recent virtual register access fault, if any.
1326		 */
1327		return (HANDLE_FAULT(hdlp));
1328
1329	case LOMBUS_PROBE_REG:
1330		/*
1331		 * Reading this meta-register clears any existing fault
1332		 * (at the virtual, not the hardware access layer), then
1333		 * runs a NOP command and returns the fault code from that.
1334		 */
1335		HANDLE_FAULT(hdlp) = 0;
1336		(void) bscbus_cmd(hdlp, 0, 0, BSCBUS_CMD_NOP);
1337		return (HANDLE_FAULT(hdlp));
1338
1339	case LOMBUS_ASYNC_REG:
1340		/*
1341		 * Obsolescent - but still supported for backwards
1342		 * compatibility.  This is an alias for the newer
1343		 * LOMBUS_EVENT_REG, but doesn't require a separate
1344		 * "reg" entry and ddi_regs_map_setup() call.
1345		 *
1346		 * It returns the value of the asynchronous-event-pending
1347		 * flag as passed back by the BSC at the end of the last
1348		 * completed command.
1349		 */
1350		csp = HANDLE_PRIVATE(hdlp);
1351		return (csp->async);
1352
1353	default:
1354		/*
1355		 * Invalid access - flag a fault and return a dummy value
1356		 */
1357		HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1358		return (DUMMY_VALUE);
1359	}
1360}
1361
1362static void
1363bscbus_meta_put32(HANDLE_TYPE *hdlp, uint32_t *addr, uint32_t val)
1364{
1365	ptrdiff_t offset;
1366
1367	/*
1368	 * Derive the offset that the caller has added to the base
1369	 * address originally returned, and use it to determine
1370	 * which meta-register is to be accessed ...
1371	 */
1372	offset = ADDR_TO_OFFSET(addr, hdlp);
1373	switch (offset) {
1374	case LOMBUS_FAULT_REG:
1375		/*
1376		 * This meta-register contains a code for the most
1377		 * recent virtual register access fault, if any.
1378		 * It can be cleared simply by writing 0 to it.
1379		 */
1380		HANDLE_FAULT(hdlp) = val;
1381		return;
1382
1383	case LOMBUS_PROBE_REG:
1384		/*
1385		 * Writing this meta-register clears any existing fault
1386		 * (at the virtual, not the hardware acess layer), then
1387		 * runs a NOP command.  The caller can check the fault
1388		 * code later if required.
1389		 */
1390		HANDLE_FAULT(hdlp) = 0;
1391		(void) bscbus_cmd(hdlp, 0, 0, BSCBUS_CMD_NOP);
1392		return;
1393
1394	default:
1395		/*
1396		 * Invalid access - flag a fault
1397		 */
1398		HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1399		return;
1400	}
1401}
1402
1403static void
1404bscbus_meta_rep_get32(HANDLE_TYPE *hdlp, uint32_t *host_addr,
1405	uint32_t *dev_addr, size_t repcount, uint_t flags)
1406{
1407	size_t inc;
1408
1409	inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1410	for (; repcount--; dev_addr += inc)
1411		*host_addr++ = bscbus_meta_get32(hdlp, dev_addr);
1412}
1413
1414static void
1415bscbus_meta_rep_put32(HANDLE_TYPE *hdlp, uint32_t *host_addr,
1416	uint32_t *dev_addr, size_t repcount, uint_t flags)
1417{
1418	size_t inc;
1419
1420	inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1421	for (; repcount--; dev_addr += inc)
1422		bscbus_meta_put32(hdlp, dev_addr, *host_addr++);
1423}
1424
1425
1426/*
1427 * Finally, some dummy functions for all unsupported access
1428 * space/size/mode combinations ...
1429 */
1430static uint8_t
1431bscbus_no_get8(HANDLE_TYPE *hdlp, uint8_t *addr)
1432{
1433	_NOTE(ARGUNUSED(addr))
1434
1435	/*
1436	 * Invalid access - flag a fault and return a dummy value
1437	 */
1438	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1439	return (DUMMY_VALUE);
1440}
1441
1442static void
1443bscbus_no_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
1444{
1445	_NOTE(ARGUNUSED(addr, val))
1446
1447	/*
1448	 * Invalid access - flag a fault
1449	 */
1450	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1451}
1452
1453static void
1454bscbus_no_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1455		uint8_t *dev_addr, size_t repcount, uint_t flags)
1456{
1457	_NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1458
1459	/*
1460	 * Invalid access - flag a fault
1461	 */
1462	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1463}
1464
1465static void
1466bscbus_no_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1467	uint8_t *dev_addr, size_t repcount, uint_t flags)
1468{
1469	_NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1470
1471	/*
1472	 * Invalid access - flag a fault
1473	 */
1474	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1475}
1476
1477static uint16_t
1478bscbus_no_get16(HANDLE_TYPE *hdlp, uint16_t *addr)
1479{
1480	_NOTE(ARGUNUSED(addr))
1481
1482	/*
1483	 * Invalid access - flag a fault and return a dummy value
1484	 */
1485	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1486	return (DUMMY_VALUE);
1487}
1488
1489static void
1490bscbus_no_put16(HANDLE_TYPE *hdlp, uint16_t *addr, uint16_t val)
1491{
1492	_NOTE(ARGUNUSED(addr, val))
1493
1494	/*
1495	 * Invalid access - flag a fault
1496	 */
1497	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1498}
1499
1500static void
1501bscbus_no_rep_get16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
1502		uint16_t *dev_addr, size_t repcount, uint_t flags)
1503{
1504	_NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1505
1506	/*
1507	 * Invalid access - flag a fault
1508	 */
1509	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1510}
1511
1512static void
1513bscbus_no_rep_put16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
1514	uint16_t *dev_addr, size_t repcount, uint_t flags)
1515{
1516	_NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1517
1518	/*
1519	 * Invalid access - flag a fault
1520	 */
1521	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1522}
1523
1524static uint64_t
1525bscbus_no_get64(HANDLE_TYPE *hdlp, uint64_t *addr)
1526{
1527	_NOTE(ARGUNUSED(addr))
1528
1529	/*
1530	 * Invalid access - flag a fault and return a dummy value
1531	 */
1532	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1533	return (DUMMY_VALUE);
1534}
1535
1536static void
1537bscbus_no_put64(HANDLE_TYPE *hdlp, uint64_t *addr, uint64_t val)
1538{
1539	_NOTE(ARGUNUSED(addr, val))
1540
1541	/*
1542	 * Invalid access - flag a fault
1543	 */
1544	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1545}
1546
1547static void
1548bscbus_no_rep_get64(HANDLE_TYPE *hdlp, uint64_t *host_addr,
1549	uint64_t *dev_addr, size_t repcount, uint_t flags)
1550{
1551	_NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1552
1553	/*
1554	 * Invalid access - flag a fault
1555	 */
1556	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1557}
1558
1559static void
1560bscbus_no_rep_put64(HANDLE_TYPE *hdlp, uint64_t *host_addr,
1561	uint64_t *dev_addr, size_t repcount, uint_t flags)
1562{
1563	_NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1564
1565	/*
1566	 * Invalid access - flag a fault
1567	 */
1568	HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1569}
1570
1571static int
1572bscbus_acc_fault_check(HANDLE_TYPE *hdlp)
1573{
1574	return (HANDLE_FAULT(hdlp) != 0);
1575}
1576
1577/*
1578 * Hardware setup - ensure that there are no pending transactions and
1579 * hence no pending interrupts. We do this be ensuring that the BSC is
1580 * not reporting a busy condition and that it does not have any data
1581 * pending in its output buffer.
1582 * This is important because if we have pending interrupts at attach
1583 * time Solaris will hang due to bugs in ddi_get_iblock_cookie.
1584 */
1585static void
1586bscbus_hw_reset(struct bscbus_channel_state *csp)
1587{
1588	int64_t timeout;
1589	uint8_t status;
1590
1591	if (csp->map_count == 0) {
1592		/* No-one using this instance - no need to reset hardware */
1593		return;
1594	}
1595
1596	bscbus_trace(csp, 'R', "bscbus_hw_reset",
1597	    "resetting channel %d", csp->chno);
1598
1599	status = bscbus_get_reg(csp, H8_STR);
1600	if (status & H8_STR_BUSY) {
1601		/*
1602		 * Give the h8 time to complete a reply.
1603		 * In practice we should never worry about this
1604		 * because whenever we get here it will have been
1605		 * long enough for the h8 to complete a reply
1606		 */
1607		bscbus_cmd_log(csp, BSC_CMD_BUSY, status, 0);
1608		bscbus_trace(csp, 'R', "bscbus_hw_reset",
1609		    "h8 reporting status (%x) busy - waiting", status);
1610		if (ddi_in_panic()) {
1611			drv_usecwait(BSCBUS_HWRESET_POLL/1000);
1612		} else {
1613			delay(drv_usectohz(BSCBUS_HWRESET_POLL/1000));
1614		}
1615	}
1616	/* Reply should be completed by now. Try to clear busy status */
1617	status = bscbus_get_reg(csp, H8_STR);
1618	if (status & (H8_STR_BUSY | H8_STR_OBF)) {
1619		bscbus_trace(csp, 'R', "bscbus_hw_reset",
1620		    "clearing busy status for channel %d", csp->chno);
1621
1622		for (timeout = BSCBUS_HWRESET_TIMEOUT;
1623		    (timeout > 0);
1624		    timeout -= BSCBUS_HWRESET_POLL) {
1625			if (status & H8_STR_OBF) {
1626				(void) bscbus_get_reg(csp, H8_ODR);
1627				if (!(status & H8_STR_BUSY)) {
1628					/* We are done */
1629					break;
1630				}
1631			}
1632			if (ddi_in_panic()) {
1633				drv_usecwait(BSCBUS_HWRESET_POLL/1000);
1634			} else {
1635				delay(drv_usectohz(BSCBUS_HWRESET_POLL/1000));
1636			}
1637			status = bscbus_get_reg(csp, H8_STR);
1638		}
1639		if (timeout <= 0) {
1640			cmn_err(CE_WARN, "bscbus_hw_reset: timed out "
1641			    "clearing busy status");
1642		}
1643	}
1644	/*
1645	 * We read ODR just in case there is a pending interrupt with
1646	 * no data. This is potentially dangerous because we could get
1647	 * out of sync due to race conditions BUT at this point the
1648	 * channel should be idle so it is safe.
1649	 */
1650	(void) bscbus_get_reg(csp, H8_ODR);
1651}
1652
1653/*
1654 * Higher-level setup & teardown
1655 */
1656
1657static void
1658bscbus_offline(struct bscbus_state *ssp)
1659{
1660	if (ssp->h8_handle != NULL)
1661		ddi_regs_map_free(&ssp->h8_handle);
1662	ssp->h8_handle = NULL;
1663	ssp->h8_regs = NULL;
1664}
1665
1666static int
1667bscbus_online(struct bscbus_state *ssp)
1668{
1669	ddi_acc_handle_t h;
1670	caddr_t p;
1671	int nregs;
1672	int err;
1673
1674	ssp->h8_handle = NULL;
1675	ssp->h8_regs = (void *)NULL;
1676	ssp->per_channel_regs = B_FALSE;
1677
1678	if (ddi_dev_nregs(ssp->dip, &nregs) != DDI_SUCCESS)
1679		nregs = 0;
1680
1681	switch (nregs) {
1682	case 1:
1683		/*
1684		 *  regset 0 represents the H8 interface registers
1685		 */
1686		err = ddi_regs_map_setup(ssp->dip, 0, &p, 0, 0,
1687		    bscbus_dev_acc_attr, &h);
1688		if (err != DDI_SUCCESS)
1689			return (EIO);
1690
1691		ssp->h8_handle = h;
1692		ssp->h8_regs = (void *)p;
1693		break;
1694
1695	case 0:
1696		/*
1697		 *  If no registers are defined, succeed vacuously;
1698		 *  commands will be accepted, but we fake the accesses.
1699		 */
1700		break;
1701
1702	default:
1703		/*
1704		 * Remember that we are using the new register scheme.
1705		 * reg set 0 is chan 0
1706		 * reg set 1 is chan 1 ...
1707		 * Interrupts are specified in that order but later
1708		 * channels may not have interrupts.
1709		 * We map the regs later on a per channel basis.
1710		 */
1711		ssp->per_channel_regs = B_TRUE;
1712		break;
1713	}
1714	return (0);
1715}
1716
1717static int
1718bscbus_claim_channel(struct bscbus_channel_state *csp, boolean_t map_dog)
1719{
1720	int err;
1721
1722	mutex_enter(csp->ssp->ch_mutex);
1723	csp->map_count++;
1724	bscbus_trace(csp, 'C', "bscbus_claim_channel",
1725	    "claim channel for channel %d, count %d",
1726	    csp->chno, csp->map_count);
1727
1728	if (csp->map_count == 1) {
1729		/* No-one is using this channel - initialise it */
1730		bscbus_trace(csp, 'C', "bscbus_claim_channel",
1731		    "initialise channel %d, count %d",
1732		    csp->chno, csp->map_count);
1733
1734		mutex_init(csp->dog_mutex, NULL, MUTEX_DRIVER,
1735		    (void *)(uintptr_t)__ipltospl(SPL7 - 1));
1736		csp->map_dog = map_dog;
1737		csp->interrupt_failed = B_FALSE;
1738		csp->cmdstate = BSCBUS_CMDSTATE_IDLE;
1739		csp->pat_retry_count = 0;
1740		csp->pat_fail_count = 0;
1741
1742		/* Map appropriate register set for this channel */
1743		if (csp->ssp->per_channel_regs == B_TRUE) {
1744			ddi_acc_handle_t h;
1745			caddr_t p;
1746
1747			err = ddi_regs_map_setup(csp->ssp->dip, csp->chno,
1748			    &p, 0, 0, bscbus_dev_acc_attr, &h);
1749
1750			if (err != DDI_SUCCESS) {
1751				goto failed1;
1752			}
1753
1754			csp->ch_handle = h;
1755			csp->ch_regs = (void *)p;
1756
1757			bscbus_trace(csp, 'C', "bscbus_claim_channel",
1758			    "mapped chno=%d ch_handle=%d ch_regs=%p",
1759			    csp->chno, h, p);
1760		} else {
1761			/*
1762			 * if using the old reg property scheme use the
1763			 * common mapping.
1764			 */
1765			csp->ch_handle = csp->ssp->h8_handle;
1766			csp->ch_regs =
1767			    csp->ssp->h8_regs +
1768			    BSCBUS_CHANNEL_TO_OFFSET(csp->chno);
1769		}
1770
1771		/* Ensure no interrupts pending prior to getting iblk cookie */
1772		bscbus_hw_reset(csp);
1773
1774		if (csp->map_dog == 1) {
1775			/*
1776			 * we don't want lo_mutex to be initialised
1777			 * with an iblock cookie if we are the wdog,
1778			 * because we don't use interrupts.
1779			 */
1780			mutex_init(csp->lo_mutex, NULL,
1781			    MUTEX_DRIVER, NULL);
1782			cv_init(csp->lo_cv, NULL,
1783			    CV_DRIVER, NULL);
1784			csp->unclaimed_count = 0;
1785		} else {
1786			int ninterrupts;
1787
1788			/*
1789			 * check that there is an interrupt for this
1790			 * this channel. If we fail to setup interrupts we
1791			 * must unmap the registers and fail.
1792			 */
1793			err = ddi_dev_nintrs(csp->ssp->dip, &ninterrupts);
1794
1795			if (err != DDI_SUCCESS) {
1796				ninterrupts = 0;
1797			}
1798
1799			if (ninterrupts <= csp->chno) {
1800				cmn_err(CE_WARN,
1801				    "no interrupt available for "
1802				    "bscbus channel %d", csp->chno);
1803				goto failed2;
1804			}
1805
1806			if (ddi_intr_hilevel(csp->ssp->dip, csp->chno) != 0) {
1807				cmn_err(CE_WARN,
1808				    "bscbus interrupts are high "
1809				    "level - channel not usable.");
1810				goto failed2;
1811			} else {
1812				err = ddi_get_iblock_cookie(csp->ssp->dip,
1813				    csp->chno, &csp->lo_iblk);
1814				if (err != DDI_SUCCESS) {
1815					goto failed2;
1816				}
1817
1818				mutex_init(csp->lo_mutex, NULL,
1819				    MUTEX_DRIVER, csp->lo_iblk);
1820				cv_init(csp->lo_cv, NULL,
1821				    CV_DRIVER, NULL);
1822				csp->unclaimed_count = 0;
1823
1824				err = ddi_add_intr(csp->ssp->dip, csp->chno,
1825				    &csp->lo_iblk, NULL,
1826				    bscbus_hwintr, (caddr_t)csp);
1827				if (err != DDI_SUCCESS) {
1828					cv_destroy(csp->lo_cv);
1829					mutex_destroy(csp->lo_mutex);
1830					goto failed2;
1831				}
1832			}
1833		}
1834		/*
1835		 * The channel is now live and may
1836		 * receive interrupts
1837		 */
1838	} else if (csp->map_dog != map_dog) {
1839		bscbus_trace(csp, 'C', "bscbus_claim_channel",
1840		    "request conflicts with previous mapping. old %x, new %x.",
1841		    csp->map_dog, map_dog);
1842		goto failed1;
1843	}
1844	mutex_exit(csp->ssp->ch_mutex);
1845	return (1);
1846
1847failed2:
1848	/* unmap regs for failed channel */
1849	if (csp->ssp->per_channel_regs == B_TRUE) {
1850		ddi_regs_map_free(&csp->ch_handle);
1851	}
1852	csp->ch_handle = NULL;
1853	csp->ch_regs = (void *)NULL;
1854failed1:
1855	csp->map_count--;
1856	mutex_exit(csp->ssp->ch_mutex);
1857	return (0);
1858}
1859
1860static void
1861bscbus_release_channel(struct bscbus_channel_state *csp)
1862{
1863	mutex_enter(csp->ssp->ch_mutex);
1864	if (csp->map_count == 1) {
1865		/* No-one is now using this channel - shutdown channel */
1866		bscbus_trace(csp, 'C', "bscbus_release_channel",
1867		    "shutdown channel %d, count %d",
1868		    csp->chno, csp->map_count);
1869
1870		if (csp->map_dog == 0) {
1871			ASSERT(!ddi_intr_hilevel(csp->ssp->dip, csp->chno));
1872			ddi_remove_intr(csp->ssp->dip, csp->chno, csp->lo_iblk);
1873		}
1874		cv_destroy(csp->lo_cv);
1875		mutex_destroy(csp->lo_mutex);
1876		mutex_destroy(csp->dog_mutex);
1877		bscbus_hw_reset(csp);
1878
1879		/* unmap registers if using the new register scheme */
1880		if (csp->ssp->per_channel_regs == B_TRUE) {
1881			ddi_regs_map_free(&csp->ch_handle);
1882		}
1883		csp->ch_handle = NULL;
1884		csp->ch_regs = (void *)NULL;
1885	}
1886	csp->map_count--;
1887	bscbus_trace(csp, 'C', "bscbus_release_channel",
1888	    "release channel %d, count %d",
1889	    csp->chno, csp->map_count);
1890	mutex_exit(csp->ssp->ch_mutex);
1891}
1892
1893
1894/*
1895 *  Nexus routines
1896 */
1897
1898#if	defined(NDI_ACC_HDL_V2)
1899
1900static const ndi_acc_fns_t bscbus_vreg_acc_fns = {
1901	NDI_ACC_FNS_CURRENT,
1902	NDI_ACC_FNS_V1,
1903
1904	bscbus_vreg_get8,
1905	bscbus_vreg_put8,
1906	bscbus_vreg_rep_get8,
1907	bscbus_vreg_rep_put8,
1908
1909	bscbus_no_get16,
1910	bscbus_no_put16,
1911	bscbus_no_rep_get16,
1912	bscbus_no_rep_put16,
1913
1914	bscbus_meta_get32,
1915	bscbus_meta_put32,
1916	bscbus_meta_rep_get32,
1917	bscbus_meta_rep_put32,
1918
1919	bscbus_no_get64,
1920	bscbus_no_put64,
1921	bscbus_no_rep_get64,
1922	bscbus_no_rep_put64,
1923
1924	bscbus_acc_fault_check
1925};
1926
1927static const ndi_acc_fns_t bscbus_pat_acc_fns = {
1928	NDI_ACC_FNS_CURRENT,
1929	NDI_ACC_FNS_V1,
1930
1931	bscbus_pat_get8,
1932	bscbus_pat_put8,
1933	bscbus_pat_rep_get8,
1934	bscbus_pat_rep_put8,
1935
1936	bscbus_no_get16,
1937	bscbus_no_put16,
1938	bscbus_no_rep_get16,
1939	bscbus_no_rep_put16,
1940
1941	bscbus_meta_get32,
1942	bscbus_meta_put32,
1943	bscbus_meta_rep_get32,
1944	bscbus_meta_rep_put32,
1945
1946	bscbus_no_get64,
1947	bscbus_no_put64,
1948	bscbus_no_rep_get64,
1949	bscbus_no_rep_put64,
1950
1951	bscbus_acc_fault_check
1952};
1953
1954static const ndi_acc_fns_t bscbus_event_acc_fns = {
1955	NDI_ACC_FNS_CURRENT,
1956	NDI_ACC_FNS_V1,
1957
1958	bscbus_no_get8,
1959	bscbus_no_put8,
1960	bscbus_no_rep_get8,
1961	bscbus_no_rep_put8,
1962
1963	bscbus_event_get16,
1964	bscbus_event_put16,
1965	bscbus_event_rep_get16,
1966	bscbus_event_rep_put16,
1967
1968	bscbus_meta_get32,
1969	bscbus_meta_put32,
1970	bscbus_meta_rep_get32,
1971	bscbus_meta_rep_put32,
1972
1973	bscbus_no_get64,
1974	bscbus_no_put64,
1975	bscbus_no_rep_get64,
1976	bscbus_no_rep_put64,
1977
1978	bscbus_acc_fault_check
1979};
1980
1981static int
1982bscbus_map_handle(struct bscbus_channel_state *csp, ddi_map_op_t op,
1983	int space, caddr_t vaddr, off_t len,
1984	ndi_acc_handle_t *hdlp, caddr_t *addrp)
1985{
1986	switch (op) {
1987	default:
1988		return (DDI_ME_UNIMPLEMENTED);
1989
1990	case DDI_MO_MAP_LOCKED:
1991		if (bscbus_claim_channel(csp,
1992		    (space == LOMBUS_PAT_SPACE)) == 0) {
1993			return (DDI_ME_GENERIC);
1994		}
1995
1996		switch (space) {
1997		default:
1998			return (DDI_ME_REGSPEC_RANGE);
1999
2000		case LOMBUS_VREG_SPACE:
2001			ndi_set_acc_fns(hdlp, &bscbus_vreg_acc_fns);
2002			break;
2003
2004		case LOMBUS_PAT_SPACE:
2005			ndi_set_acc_fns(hdlp, &bscbus_pat_acc_fns);
2006			break;
2007
2008		case LOMBUS_EVENT_SPACE:
2009			ndi_set_acc_fns(hdlp, &bscbus_event_acc_fns);
2010			break;
2011		}
2012		hdlp->ah_addr = *addrp = vaddr;
2013		hdlp->ah_len = len;
2014		hdlp->ah_bus_private = csp;
2015		return (DDI_SUCCESS);
2016
2017	case DDI_MO_UNMAP:
2018		*addrp = NULL;
2019		hdlp->ah_bus_private = NULL;
2020		bscbus_release_channel(csp);
2021		return (DDI_SUCCESS);
2022	}
2023}
2024
2025#else
2026
2027static int
2028bscbus_map_handle(struct bscbus_channel_state *csp, ddi_map_op_t op,
2029	int space, caddr_t vaddr, off_t len,
2030	ddi_acc_hdl_t *hdlp, caddr_t *addrp)
2031{
2032	ddi_acc_impl_t *aip = hdlp->ah_platform_private;
2033
2034	switch (op) {
2035	default:
2036		return (DDI_ME_UNIMPLEMENTED);
2037
2038	case DDI_MO_MAP_LOCKED:
2039		if (bscbus_claim_channel(csp,
2040		    (space == LOMBUS_PAT_SPACE)) == 0) {
2041			return (DDI_ME_GENERIC);
2042		}
2043
2044		switch (space) {
2045		default:
2046			return (DDI_ME_REGSPEC_RANGE);
2047
2048		case LOMBUS_VREG_SPACE:
2049			aip->ahi_get8 = bscbus_vreg_get8;
2050			aip->ahi_put8 = bscbus_vreg_put8;
2051			aip->ahi_rep_get8 = bscbus_vreg_rep_get8;
2052			aip->ahi_rep_put8 = bscbus_vreg_rep_put8;
2053
2054			aip->ahi_get16 = bscbus_no_get16;
2055			aip->ahi_put16 = bscbus_no_put16;
2056			aip->ahi_rep_get16 = bscbus_no_rep_get16;
2057			aip->ahi_rep_put16 = bscbus_no_rep_put16;
2058
2059			aip->ahi_get32 = bscbus_meta_get32;
2060			aip->ahi_put32 = bscbus_meta_put32;
2061			aip->ahi_rep_get32 = bscbus_meta_rep_get32;
2062			aip->ahi_rep_put32 = bscbus_meta_rep_put32;
2063
2064			aip->ahi_get64 = bscbus_no_get64;
2065			aip->ahi_put64 = bscbus_no_put64;
2066			aip->ahi_rep_get64 = bscbus_no_rep_get64;
2067			aip->ahi_rep_put64 = bscbus_no_rep_put64;
2068
2069			aip->ahi_fault_check = bscbus_acc_fault_check;
2070			break;
2071
2072		case LOMBUS_PAT_SPACE:
2073			aip->ahi_get8 = bscbus_pat_get8;
2074			aip->ahi_put8 = bscbus_pat_put8;
2075			aip->ahi_rep_get8 = bscbus_pat_rep_get8;
2076			aip->ahi_rep_put8 = bscbus_pat_rep_put8;
2077
2078			aip->ahi_get16 = bscbus_no_get16;
2079			aip->ahi_put16 = bscbus_no_put16;
2080			aip->ahi_rep_get16 = bscbus_no_rep_get16;
2081			aip->ahi_rep_put16 = bscbus_no_rep_put16;
2082
2083			aip->ahi_get32 = bscbus_meta_get32;
2084			aip->ahi_put32 = bscbus_meta_put32;
2085			aip->ahi_rep_get32 = bscbus_meta_rep_get32;
2086			aip->ahi_rep_put32 = bscbus_meta_rep_put32;
2087
2088			aip->ahi_get64 = bscbus_no_get64;
2089			aip->ahi_put64 = bscbus_no_put64;
2090			aip->ahi_rep_get64 = bscbus_no_rep_get64;
2091			aip->ahi_rep_put64 = bscbus_no_rep_put64;
2092
2093			aip->ahi_fault_check = bscbus_acc_fault_check;
2094			break;
2095
2096		case LOMBUS_EVENT_SPACE:
2097			aip->ahi_get8 = bscbus_no_get8;
2098			aip->ahi_put8 = bscbus_no_put8;
2099			aip->ahi_rep_get8 = bscbus_no_rep_get8;
2100			aip->ahi_rep_put8 = bscbus_no_rep_put8;
2101
2102			aip->ahi_get16 = bscbus_event_get16;
2103			aip->ahi_put16 = bscbus_event_put16;
2104			aip->ahi_rep_get16 = bscbus_event_rep_get16;
2105			aip->ahi_rep_put16 = bscbus_event_rep_put16;
2106
2107			aip->ahi_get32 = bscbus_meta_get32;
2108			aip->ahi_put32 = bscbus_meta_put32;
2109			aip->ahi_rep_get32 = bscbus_meta_rep_get32;
2110			aip->ahi_rep_put32 = bscbus_meta_rep_put32;
2111
2112			aip->ahi_get64 = bscbus_no_get64;
2113			aip->ahi_put64 = bscbus_no_put64;
2114			aip->ahi_rep_get64 = bscbus_no_rep_get64;
2115			aip->ahi_rep_put64 = bscbus_no_rep_put64;
2116
2117			aip->ahi_fault_check = bscbus_acc_fault_check;
2118			break;
2119		}
2120		hdlp->ah_addr = *addrp = vaddr;
2121		hdlp->ah_len = len;
2122		hdlp->ah_bus_private = csp;
2123		return (DDI_SUCCESS);
2124
2125	case DDI_MO_UNMAP:
2126		*addrp = NULL;
2127		hdlp->ah_bus_private = NULL;
2128		bscbus_release_channel(csp);
2129		return (DDI_SUCCESS);
2130	}
2131}
2132
2133#endif	/* NDI_ACC_HDL_V2 */
2134
2135static int
2136bscbus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
2137	off_t off, off_t len, caddr_t *addrp)
2138{
2139	struct bscbus_child_info *lcip;
2140	struct bscbus_state *ssp;
2141	lombus_regspec_t *rsp;
2142
2143	if ((ssp = bscbus_getstate(dip, -1, "bscbus_map")) == NULL)
2144		return (DDI_FAILURE);	/* this "can't happen" */
2145
2146	/*
2147	 * Validate mapping request ...
2148	 */
2149
2150	if (mp->map_flags != DDI_MF_KERNEL_MAPPING)
2151		return (DDI_ME_UNSUPPORTED);
2152	if (mp->map_handlep == NULL)
2153		return (DDI_ME_UNSUPPORTED);
2154	if (mp->map_type != DDI_MT_RNUMBER)
2155		return (DDI_ME_UNIMPLEMENTED);
2156	if ((lcip = ddi_get_parent_data(rdip)) == NULL)
2157		return (DDI_ME_INVAL);
2158	if ((rsp = lcip->rsp) == NULL)
2159		return (DDI_ME_INVAL);
2160	if (mp->map_obj.rnumber >= lcip->nregs)
2161		return (DDI_ME_RNUMBER_RANGE);
2162	rsp += mp->map_obj.rnumber;
2163	if (off < 0 || off >= rsp->lombus_size)
2164		return (DDI_ME_INVAL);
2165	if (len == 0)
2166		len = rsp->lombus_size-off;
2167	if (len < 0)
2168		return (DDI_ME_INVAL);
2169	if (off+len < 0 || off+len > rsp->lombus_size)
2170		return (DDI_ME_INVAL);
2171
2172	return (bscbus_map_handle(
2173	    &ssp->channel[LOMBUS_SPACE_TO_CHANNEL(rsp->lombus_space)],
2174	    mp->map_op, LOMBUS_SPACE_TO_REGSET(rsp->lombus_space),
2175	    VREG_TO_ADDR(rsp->lombus_base+off), len, mp->map_handlep, addrp));
2176}
2177
2178
2179static int
2180bscbus_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op,
2181	void *arg, void *result)
2182{
2183	struct bscbus_child_info *lcip;
2184	lombus_regspec_t *rsp;
2185	dev_info_t *cdip;
2186	char addr[32];
2187	uint_t nregs;
2188	uint_t rnum;
2189	int *regs;
2190	int limit;
2191	int err;
2192	int i;
2193
2194	if (bscbus_getstate(dip, -1, "bscbus_ctlops") == NULL)
2195		return (DDI_FAILURE);	/* this "can't happen" */
2196
2197	switch (op) {
2198	default:
2199		break;
2200
2201	case DDI_CTLOPS_INITCHILD:
2202		/*
2203		 * First, look up and validate the "reg" property.
2204		 *
2205		 * It must be a non-empty integer array containing a set
2206		 * of triples.  Once we've verified that, we can treat it
2207		 * as an array of type lombus_regspec_t[], which defines
2208		 * the meaning of the elements of each triple:
2209		 * +  the first element of each triple must be a valid space
2210		 * +  the second and third elements (base, size) of each
2211		 *	triple must define a valid subrange of that space
2212		 * If it passes all the tests, we save it away for future
2213		 * reference in the child's parent-private-data field.
2214		 */
2215		cdip = arg;
2216		err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
2217		    DDI_PROP_DONTPASS, "reg", &regs, &nregs);
2218		if (err != DDI_PROP_SUCCESS)
2219			return (DDI_FAILURE);
2220
2221		err = (nregs <= 0 || (nregs % LOMBUS_REGSPEC_SIZE) != 0);
2222		nregs /= LOMBUS_REGSPEC_SIZE;
2223		rsp = (lombus_regspec_t *)regs;
2224		for (i = 0; i < nregs && !err; ++i) {
2225			switch (LOMBUS_SPACE_TO_REGSET(rsp[i].lombus_space)) {
2226			default:
2227				limit = 0;
2228				err = 1;
2229				cmn_err(CE_WARN,
2230				    "child(%p): unknown reg space %d",
2231				    (void *)cdip, rsp[i].lombus_space);
2232				break;
2233
2234			case LOMBUS_VREG_SPACE:
2235				limit = LOMBUS_MAX_REG+1;
2236				break;
2237
2238			case LOMBUS_PAT_SPACE:
2239				limit = LOMBUS_PAT_REG+1;
2240				break;
2241
2242			case LOMBUS_EVENT_SPACE:
2243				limit = LOMBUS_EVENT_REG+1;
2244				break;
2245			}
2246
2247			err |= (rsp[i].lombus_base < 0);
2248			err |= (rsp[i].lombus_base >= limit);
2249
2250			if (rsp[i].lombus_size == 0)
2251				rsp[i].lombus_size = limit-rsp[i].lombus_base;
2252
2253			err |= (rsp[i].lombus_size < 0);
2254			err |= (rsp[i].lombus_base+rsp[i].lombus_size < 0);
2255			err |= (rsp[i].lombus_base+rsp[i].lombus_size > limit);
2256
2257			err |= (rsp[i].lombus_base+rsp[i].lombus_size > limit);
2258
2259		}
2260
2261		if (err) {
2262			ddi_prop_free(regs);
2263			return (DDI_FAILURE);
2264		}
2265
2266		lcip = kmem_zalloc(sizeof (*lcip), KM_SLEEP);
2267		lcip->nregs = nregs;
2268		lcip->rsp = rsp;
2269		ddi_set_parent_data(cdip, lcip);
2270
2271		(void) snprintf(addr, sizeof (addr),
2272		    "%x,%x", rsp[0].lombus_space, rsp[0].lombus_base);
2273		ddi_set_name_addr(cdip, addr);
2274
2275		return (DDI_SUCCESS);
2276
2277	case DDI_CTLOPS_UNINITCHILD:
2278		cdip = arg;
2279		ddi_set_name_addr(cdip, NULL);
2280		lcip = ddi_get_parent_data(cdip);
2281		ddi_set_parent_data(cdip, NULL);
2282		ddi_prop_free(lcip->rsp);
2283		kmem_free(lcip, sizeof (*lcip));
2284		return (DDI_SUCCESS);
2285
2286	case DDI_CTLOPS_REPORTDEV:
2287		if (rdip == NULL)
2288			return (DDI_FAILURE);
2289
2290		cmn_err(CE_CONT, "?BSC device: %s@%s, %s#%d\n",
2291		    ddi_node_name(rdip), ddi_get_name_addr(rdip),
2292		    ddi_driver_name(dip), ddi_get_instance(dip));
2293
2294		return (DDI_SUCCESS);
2295
2296	case DDI_CTLOPS_REGSIZE:
2297		if ((lcip = ddi_get_parent_data(rdip)) == NULL)
2298			return (DDI_FAILURE);
2299		if ((rnum = *(uint_t *)arg) >= lcip->nregs)
2300			return (DDI_FAILURE);
2301		*(off_t *)result = lcip->rsp[rnum].lombus_size;
2302		return (DDI_SUCCESS);
2303
2304	case DDI_CTLOPS_NREGS:
2305		if ((lcip = ddi_get_parent_data(rdip)) == NULL)
2306			return (DDI_FAILURE);
2307		*(int *)result = lcip->nregs;
2308		return (DDI_SUCCESS);
2309	}
2310
2311	return (ddi_ctlops(dip, rdip, op, arg, result));
2312}
2313
2314
2315/*
2316 * This nexus does not support passing interrupts to leaf drivers, so
2317 * all the intrspec-related operations just fail as cleanly as possible.
2318 */
2319
2320/*ARGSUSED*/
2321static int
2322bscbus_intr_op(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op,
2323    ddi_intr_handle_impl_t *hdlp, void *result)
2324{
2325#if defined(__sparc)
2326	return (i_ddi_intr_ops(dip, rdip, op, hdlp, result));
2327#else
2328	_NOTE(ARGUNUSED(dip, rdip, op, hdlp, result))
2329	return (DDI_FAILURE);
2330#endif
2331}
2332
2333/*
2334 *  Clean up on detach or failure of attach
2335 */
2336static int
2337bscbus_unattach(struct bscbus_state *ssp, int instance)
2338{
2339	int chno;
2340
2341	if (ssp != NULL) {
2342		for (chno = 0; chno < BSCBUS_MAX_CHANNELS; chno++) {
2343			ASSERT(ssp->channel[chno].map_count == 0);
2344		}
2345		bscbus_offline(ssp);
2346		ddi_set_driver_private(ssp->dip, NULL);
2347		mutex_destroy(ssp->ch_mutex);
2348	}
2349#ifdef BSCBUS_LOGSTATUS
2350	if (ssp->cmd_log_size != 0) {
2351		kmem_free(ssp->cmd_log,
2352		    ssp->cmd_log_size * sizeof (bsc_cmd_log_t));
2353	}
2354#endif /* BSCBUS_LOGSTATUS */
2355
2356
2357	ddi_soft_state_free(bscbus_statep, instance);
2358	return (DDI_FAILURE);
2359}
2360
2361/*
2362 *  Autoconfiguration routines
2363 */
2364
2365static int
2366bscbus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2367{
2368	struct bscbus_state *ssp = NULL;
2369	int chno;
2370	int instance;
2371	int err;
2372
2373	switch (cmd) {
2374	default:
2375		return (DDI_FAILURE);
2376
2377	case DDI_ATTACH:
2378		break;
2379	}
2380
2381	/*
2382	 *  Allocate the soft-state structure
2383	 */
2384	instance = ddi_get_instance(dip);
2385	if (ddi_soft_state_zalloc(bscbus_statep, instance) != DDI_SUCCESS)
2386		return (DDI_FAILURE);
2387	if ((ssp = bscbus_getstate(dip, instance, "bscbus_attach")) == NULL)
2388		return (bscbus_unattach(ssp, instance));
2389	ddi_set_driver_private(dip, ssp);
2390
2391	/*
2392	 *  Initialise devinfo-related fields
2393	 */
2394	ssp->dip = dip;
2395	ssp->majornum = ddi_driver_major(dip);
2396	ssp->instance = instance;
2397
2398	/*
2399	 *  Set various options from .conf properties
2400	 */
2401	ssp->debug = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2402	    DDI_PROP_DONTPASS, "debug", 0);
2403
2404	mutex_init(ssp->ch_mutex, NULL, MUTEX_DRIVER, NULL);
2405
2406#ifdef BSCBUS_LOGSTATUS
2407	ssp->cmd_log_size = bscbus_cmd_log_size;
2408	if (ssp->cmd_log_size != 0) {
2409		ssp->cmd_log_idx = 0;
2410		ssp->cmd_log = kmem_zalloc(ssp->cmd_log_size *
2411		    sizeof (bsc_cmd_log_t), KM_SLEEP);
2412	}
2413#endif /* BSCBUS_LOGSTATUS */
2414
2415	/*
2416	 *  Online the hardware ...
2417	 */
2418	err = bscbus_online(ssp);
2419	if (err != 0)
2420		return (bscbus_unattach(ssp, instance));
2421
2422	for (chno = 0; chno < BSCBUS_MAX_CHANNELS; chno++) {
2423		struct bscbus_channel_state *csp = &ssp->channel[chno];
2424
2425		/*
2426		 * Initialise state
2427		 * The hardware/interrupts are setup at map time to
2428		 * avoid claiming hardware that OBP is using
2429		 */
2430		csp->ssp = ssp;
2431		csp->chno = chno;
2432		csp->map_count = 0;
2433		csp->map_dog = B_FALSE;
2434	}
2435
2436	/*
2437	 *  All done, report success
2438	 */
2439	ddi_report_dev(dip);
2440	return (DDI_SUCCESS);
2441}
2442
2443static int
2444bscbus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2445{
2446	struct bscbus_state *ssp;
2447	int instance;
2448
2449	switch (cmd) {
2450	default:
2451		return (DDI_FAILURE);
2452
2453	case DDI_DETACH:
2454		break;
2455	}
2456
2457	instance = ddi_get_instance(dip);
2458	if ((ssp = bscbus_getstate(dip, instance, "bscbus_detach")) == NULL)
2459		return (DDI_FAILURE);	/* this "can't happen" */
2460
2461	(void) bscbus_unattach(ssp, instance);
2462	return (DDI_SUCCESS);
2463}
2464
2465static int
2466bscbus_reset(dev_info_t *dip, ddi_reset_cmd_t cmd)
2467{
2468	struct bscbus_state *ssp;
2469	int chno;
2470
2471	_NOTE(ARGUNUSED(cmd))
2472
2473	if ((ssp = bscbus_getstate(dip, -1, "bscbus_reset")) == NULL)
2474		return (DDI_FAILURE);
2475
2476	for (chno = 0; chno < BSCBUS_MAX_CHANNELS; chno++) {
2477		bscbus_hw_reset(&ssp->channel[chno]);
2478	}
2479	return (DDI_SUCCESS);
2480}
2481
2482
2483/*
2484 * System interface structures
2485 */
2486
2487static struct cb_ops bscbus_cb_ops =
2488{
2489	nodev,			/* b/c open	*/
2490	nodev,			/* b/c close	*/
2491	nodev,			/* b   strategy	*/
2492	nodev,			/* b   print	*/
2493	nodev,			/* b   dump 	*/
2494	nodev,			/* c   read	*/
2495	nodev,			/* c   write	*/
2496	nodev,			/* c   ioctl	*/
2497	nodev,			/* c   devmap	*/
2498	nodev,			/* c   mmap	*/
2499	nodev,			/* c   segmap	*/
2500	nochpoll,		/* c   poll	*/
2501	ddi_prop_op,		/* b/c prop_op	*/
2502	NULL,			/* c   streamtab */
2503	D_MP | D_NEW		/* b/c flags	*/
2504};
2505
2506static struct bus_ops bscbus_bus_ops =
2507{
2508	BUSO_REV,			/* revision		*/
2509	bscbus_map,			/* bus_map		*/
2510	0,				/* get_intrspec		*/
2511	0,				/* add_intrspec		*/
2512	0,				/* remove_intrspec	*/
2513	i_ddi_map_fault,		/* map_fault		*/
2514	ddi_no_dma_map,			/* dma_map		*/
2515	ddi_no_dma_allochdl,		/* allocate DMA handle	*/
2516	ddi_no_dma_freehdl,		/* free DMA handle	*/
2517	ddi_no_dma_bindhdl,		/* bind DMA handle	*/
2518	ddi_no_dma_unbindhdl,		/* unbind DMA handle	*/
2519	ddi_no_dma_flush,		/* flush DMA		*/
2520	ddi_no_dma_win,			/* move DMA window	*/
2521	ddi_no_dma_mctl,		/* generic DMA control	*/
2522	bscbus_ctlops,			/* generic control	*/
2523	ddi_bus_prop_op,		/* prop_op		*/
2524	ndi_busop_get_eventcookie,	/* get_eventcookie	*/
2525	ndi_busop_add_eventcall,	/* add_eventcall	*/
2526	ndi_busop_remove_eventcall,	/* remove_eventcall	*/
2527	ndi_post_event,			/* post_event		*/
2528	0,				/* interrupt control	*/
2529	0,				/* bus_config		*/
2530	0,				/* bus_unconfig		*/
2531	0,				/* bus_fm_init		*/
2532	0,				/* bus_fm_fini		*/
2533	0,				/* bus_fm_access_enter	*/
2534	0,				/* bus_fm_access_exit	*/
2535	0,				/* bus_power		*/
2536	bscbus_intr_op			/* bus_intr_op		*/
2537};
2538
2539static struct dev_ops bscbus_dev_ops =
2540{
2541	DEVO_REV,
2542	0,				/* refcount		*/
2543	ddi_no_info,			/* getinfo		*/
2544	nulldev,			/* identify		*/
2545	nulldev,			/* probe		*/
2546	bscbus_attach,			/* attach		*/
2547	bscbus_detach,			/* detach		*/
2548	bscbus_reset,			/* reset		*/
2549	&bscbus_cb_ops,			/* driver operations	*/
2550	&bscbus_bus_ops,		/* bus operations	*/
2551	NULL,				/* power		*/
2552	ddi_quiesce_not_needed,			/* quiesce		*/
2553};
2554
2555static struct modldrv modldrv =
2556{
2557	&mod_driverops,
2558	"bscbus driver",
2559	&bscbus_dev_ops
2560};
2561
2562static struct modlinkage modlinkage =
2563{
2564	MODREV_1,
2565	{
2566		&modldrv,
2567		NULL
2568	}
2569};
2570
2571
2572/*
2573 *  Dynamic loader interface code
2574 */
2575
2576int
2577_init(void)
2578{
2579	int err;
2580
2581	err = ddi_soft_state_init(&bscbus_statep,
2582	    sizeof (struct bscbus_state), 0);
2583	if (err == DDI_SUCCESS)
2584		if ((err = mod_install(&modlinkage)) != DDI_SUCCESS) {
2585			ddi_soft_state_fini(&bscbus_statep);
2586		}
2587
2588	return (err);
2589}
2590
2591int
2592_info(struct modinfo *mip)
2593{
2594	return (mod_info(&modlinkage, mip));
2595}
2596
2597int
2598_fini(void)
2599{
2600	int err;
2601
2602	if ((err = mod_remove(&modlinkage)) == DDI_SUCCESS) {
2603		ddi_soft_state_fini(&bscbus_statep);
2604		bscbus_major = NOMAJOR;
2605	}
2606
2607	return (err);
2608}
2609
2610#ifdef BSCBUS_LOGSTATUS
2611void bscbus_cmd_log(struct bscbus_channel_state *csp, bsc_cmd_stamp_t cat,
2612    uint8_t status, uint8_t data)
2613{
2614	int idx;
2615	bsc_cmd_log_t *logp;
2616	struct bscbus_state *ssp;
2617
2618	if ((csp) == NULL)
2619		return;
2620	if ((ssp = (csp)->ssp) == NULL)
2621		return;
2622	if (ssp->cmd_log_size == 0)
2623		return;
2624	if ((bscbus_cmd_log_flags & (1 << cat)) == 0)
2625		return;
2626	idx = atomic_add_32_nv(&ssp->cmd_log_idx, 1);
2627	logp = &ssp->cmd_log[idx % ssp->cmd_log_size];
2628	logp->bcl_seq = idx;
2629	logp->bcl_cat = cat;
2630	logp->bcl_now = gethrtime();
2631	logp->bcl_chno = csp->chno;
2632	logp->bcl_cmdstate = csp->cmdstate;
2633	logp->bcl_status = status;
2634	logp->bcl_data = data;
2635}
2636#endif /* BSCBUS_LOGSTATUS */
2637