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