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