xref: /illumos-gate/usr/src/uts/common/io/1394/h1394.c (revision 2570281cf351044b6936651ce26dbe1f801dcbd8)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * h1394.c
29  *    1394 Services Layer HAL Interface
30  *    Contains all of the routines that define the HAL to Services Layer
31  *    interface
32  */
33 
34 #include <sys/conf.h>
35 #include <sys/ddi.h>
36 #include <sys/sunddi.h>
37 #include <sys/modctl.h>
38 #include <sys/sunndi.h>
39 #include <sys/cmn_err.h>
40 #include <sys/types.h>
41 #include <sys/kmem.h>
42 #include <sys/thread.h>
43 #include <sys/proc.h>
44 #include <sys/disp.h>
45 #include <sys/time.h>
46 #include <sys/devctl.h>
47 #include <sys/1394/t1394.h>
48 #include <sys/1394/s1394.h>
49 #include <sys/1394/h1394.h>
50 #include <sys/1394/ieee1394.h>
51 
52 
53 extern struct bus_ops nx1394_busops;
54 extern int nx1394_define_events(s1394_hal_t *hal);
55 extern void nx1394_undefine_events(s1394_hal_t *hal);
56 extern int s1394_ignore_invalid_gap_cnt;
57 
58 /*
59  * Function:    h1394_init()
60  * Input(s):    modlp			The structure containing all of the
61  *					    HAL's relevant information
62  *
63  * Output(s):
64  *
65  * Description:	h1394_init() is called by the HAL's _init function and is
66  *		used to set up the nexus bus ops.
67  */
68 int
h1394_init(struct modlinkage * modlp)69 h1394_init(struct modlinkage *modlp)
70 {
71 	struct dev_ops	*devops;
72 
73 	devops = ((struct modldrv *)(modlp->ml_linkage[0]))->drv_dev_ops;
74 	devops->devo_bus_ops = &nx1394_busops;
75 
76 	return (0);
77 }
78 
79 /*
80  * Function:    h1394_fini()
81  * Input(s):    modlp			The structure containing all of the
82  *					    HAL's relevant information
83  *
84  * Output(s):
85  *
86  * Description:	h1394_fini() is called by the HAL's _fini function and is
87  *		used to NULL out the nexus bus ops.
88  */
89 void
h1394_fini(struct modlinkage * modlp)90 h1394_fini(struct modlinkage *modlp)
91 {
92 	struct dev_ops	*devops;
93 
94 	devops = ((struct modldrv *)(modlp->ml_linkage[0]))->drv_dev_ops;
95 	devops->devo_bus_ops = NULL;
96 }
97 
98 /*
99  * Function:    h1394_attach()
100  * Input(s):    halinfo			The structure containing all of the
101  *					    HAL's relevant information
102  *		cmd			The ddi_attach_cmd_t that tells us
103  *					    if this is a RESUME or a regular
104  *					    attach() call
105  *
106  * Output(s):	sl_private		The HAL "handle" to be used for
107  *					    all subsequent calls into the
108  *					    1394 Software Framework
109  *
110  * Description:	h1394_attach() registers the HAL with the 1394 Software
111  *		Framework.  It returns a HAL "handle" to be used for
112  *		all subsequent calls into the 1394 Software Framework.
113  */
114 int
h1394_attach(h1394_halinfo_t * halinfo,ddi_attach_cmd_t cmd,void ** sl_private)115 h1394_attach(h1394_halinfo_t *halinfo, ddi_attach_cmd_t cmd, void **sl_private)
116 {
117 	s1394_hal_t	*hal;
118 	int		ret;
119 	char		buf[32];
120 	uint_t		cmd_size;
121 
122 	ASSERT(sl_private != NULL);
123 
124 	/* If this is a DDI_RESUME, return success */
125 	if (cmd == DDI_RESUME) {
126 		hal = (s1394_hal_t *)(*sl_private);
127 		/* If we have a 1394A PHY, then reset the "contender bit" */
128 		if (hal->halinfo.phy == H1394_PHY_1394A)
129 			(void) HAL_CALL(hal).set_contender_bit(
130 			    hal->halinfo.hal_private);
131 		return (DDI_SUCCESS);
132 	} else if (cmd != DDI_ATTACH) {
133 		return (DDI_FAILURE);
134 	}
135 
136 	/* Allocate space for s1394_hal_t */
137 	hal = kmem_zalloc(sizeof (s1394_hal_t), KM_SLEEP);
138 
139 	/* Setup HAL state */
140 	hal->hal_state = S1394_HAL_INIT;
141 
142 	/* Copy in the halinfo struct */
143 	hal->halinfo = *halinfo;
144 
145 	/* Create the topology tree mutex */
146 	mutex_init(&hal->topology_tree_mutex, NULL, MUTEX_DRIVER,
147 	    hal->halinfo.hw_interrupt);
148 
149 	/* Create the Cycle Mater timer mutex */
150 	mutex_init(&hal->cm_timer_mutex, NULL, MUTEX_DRIVER,
151 	    hal->halinfo.hw_interrupt);
152 
153 	/* Initialize the Isoch CEC list */
154 	hal->isoch_cec_list_head = NULL;
155 	hal->isoch_cec_list_tail = NULL;
156 	mutex_init(&hal->isoch_cec_list_mutex, NULL, MUTEX_DRIVER,
157 	    hal->halinfo.hw_interrupt);
158 
159 	/* Initialize the Bus Manager node ID mutex and cv */
160 	mutex_init(&hal->bus_mgr_node_mutex, NULL, MUTEX_DRIVER,
161 	    hal->halinfo.hw_interrupt);
162 	cv_init(&hal->bus_mgr_node_cv, NULL, CV_DRIVER,
163 	    hal->halinfo.hw_interrupt);
164 
165 	/* Initialize the Bus Manager node ID - "-1" means undetermined */
166 	hal->bus_mgr_node	= -1;
167 	hal->incumbent_bus_mgr	= B_FALSE;
168 
169 	/* Initialize the Target list */
170 	hal->target_head = NULL;
171 	hal->target_tail = NULL;
172 	rw_init(&hal->target_list_rwlock, NULL, RW_DRIVER,
173 	    hal->halinfo.hw_interrupt);
174 
175 	/* Setup Request Q's */
176 	hal->outstanding_q_head	= NULL;
177 	hal->outstanding_q_tail	= NULL;
178 	mutex_init(&hal->outstanding_q_mutex, NULL, MUTEX_DRIVER,
179 	    hal->halinfo.hw_interrupt);
180 	hal->pending_q_head	= NULL;
181 	hal->pending_q_tail	= NULL;
182 	mutex_init(&hal->pending_q_mutex, NULL, MUTEX_DRIVER,
183 	    hal->halinfo.hw_interrupt);
184 
185 	/* Create the kmem_cache for command allocations */
186 	(void) sprintf(buf, "hal%d_cache", ddi_get_instance(hal->halinfo.dip));
187 	cmd_size = sizeof (cmd1394_cmd_t) + sizeof (s1394_cmd_priv_t) +
188 	    hal->halinfo.hal_overhead;
189 
190 	hal->hal_kmem_cachep = kmem_cache_create(buf, cmd_size, 8, NULL, NULL,
191 	    NULL, NULL, NULL, 0);
192 
193 	/* Setup the event stuff */
194 	ret = nx1394_define_events(hal);
195 	if (ret != DDI_SUCCESS) {
196 		/* Clean up before leaving */
197 		s1394_cleanup_for_detach(hal, H1394_CLEANUP_LEVEL0);
198 
199 		return (DDI_FAILURE);
200 	}
201 
202 	/* Initialize the mutexes and cv's used by the bus reset thread */
203 	mutex_init(&hal->br_thread_mutex, NULL, MUTEX_DRIVER,
204 	    hal->halinfo.hw_interrupt);
205 	cv_init(&hal->br_thread_cv, NULL, CV_DRIVER, hal->halinfo.hw_interrupt);
206 	mutex_init(&hal->br_cmplq_mutex, NULL, MUTEX_DRIVER,
207 	    hal->halinfo.hw_interrupt);
208 	cv_init(&hal->br_cmplq_cv, NULL, CV_DRIVER, hal->halinfo.hw_interrupt);
209 
210 	/*
211 	 * Create a bus reset thread to handle the device discovery.
212 	 *    It should take the default stack sizes, it should run
213 	 *    the s1394_br_thread() routine at the start, passing the
214 	 *    HAL pointer as its argument.  The thread should be put
215 	 *    on processor p0, its state should be set to runnable,
216 	 *    but not yet on a processor, and its scheduling priority
217 	 *    should be the minimum level of any system class.
218 	 */
219 	hal->br_thread = thread_create((caddr_t)NULL, 0, s1394_br_thread,
220 	    hal, 0, &p0, TS_RUN, minclsyspri);
221 
222 	/* Until we see a bus reset this HAL has no nodes */
223 	hal->number_of_nodes = 0;
224 	hal->num_bus_reset_till_fail = NUM_BR_FAIL;
225 
226 	/* Initialize the SelfID Info */
227 	hal->current_buffer = 0;
228 	hal->selfid_buf0 = kmem_zalloc(S1394_SELFID_BUF_SIZE, KM_SLEEP);
229 	hal->selfid_buf1 = kmem_zalloc(S1394_SELFID_BUF_SIZE, KM_SLEEP);
230 
231 	/* Initialize kstat structures */
232 	ret = s1394_kstat_init(hal);
233 	if (ret != DDI_SUCCESS) {
234 		/* Clean up before leaving */
235 		s1394_cleanup_for_detach(hal, H1394_CLEANUP_LEVEL3);
236 
237 		return (DDI_FAILURE);
238 	}
239 	hal->hal_kstats->guid = hal->halinfo.guid;
240 
241 	/* Setup the node tree pointers */
242 	hal->old_tree	   = &hal->last_valid_tree[0];
243 	hal->topology_tree = &hal->current_tree[0];
244 
245 	/* Initialize the local Config ROM entry */
246 	ret = s1394_init_local_config_rom(hal);
247 	if (ret != DDI_SUCCESS) {
248 		/* Clean up before leaving */
249 		s1394_cleanup_for_detach(hal, H1394_CLEANUP_LEVEL4);
250 
251 		return (DDI_FAILURE);
252 	}
253 
254 	/* Initialize 1394 Address Space */
255 	ret = s1394_init_addr_space(hal);
256 	if (ret != DDI_SUCCESS) {
257 		/* Clean up before leaving */
258 		s1394_cleanup_for_detach(hal, H1394_CLEANUP_LEVEL5);
259 
260 		return (DDI_FAILURE);
261 	}
262 
263 	/* Initialize FCP subsystem */
264 	ret = s1394_fcp_hal_init(hal);
265 	if (ret != DDI_SUCCESS) {
266 		/* Clean up before leaving */
267 		s1394_cleanup_for_detach(hal, H1394_CLEANUP_LEVEL6);
268 
269 		return (DDI_FAILURE);
270 	}
271 
272 	/* Initialize the IRM node ID - "-1" means invalid, undetermined */
273 	hal->IRM_node = -1;
274 
275 	/* If we have a 1394A PHY, then set the "contender bit" */
276 	if (hal->halinfo.phy == H1394_PHY_1394A)
277 		(void) HAL_CALL(hal).set_contender_bit(
278 		    hal->halinfo.hal_private);
279 
280 	/* Add into linked list */
281 	mutex_enter(&s1394_statep->hal_list_mutex);
282 	if ((s1394_statep->hal_head == NULL) &&
283 	    (s1394_statep->hal_tail == NULL)) {
284 		s1394_statep->hal_head = hal;
285 		s1394_statep->hal_tail = hal;
286 	} else {
287 		s1394_statep->hal_tail->hal_next = hal;
288 		hal->hal_prev = s1394_statep->hal_tail;
289 		s1394_statep->hal_tail = hal;
290 	}
291 	mutex_exit(&s1394_statep->hal_list_mutex);
292 
293 	/* Fill in services layer private info */
294 	*sl_private = (void *)hal;
295 
296 	return (DDI_SUCCESS);
297 }
298 
299 /*
300  * Function:    h1394_detach()
301  * Input(s):    sl_private		The HAL "handle" returned by
302  *					    h1394_attach()
303  *		cmd			The ddi_detach_cmd_t that tells us
304  *					    if this is a SUSPEND or a regular
305  *					    detach() call
306  *
307  * Output(s):	DDI_SUCCESS		HAL successfully detached
308  *		DDI_FAILURE		HAL failed to detach
309  *
310  * Description:	h1394_detach() unregisters the HAL from the 1394 Software
311  *		Framework.  It can be called during a SUSPEND operation or
312  *		for a real detach() event.
313  */
314 int
h1394_detach(void ** sl_private,ddi_detach_cmd_t cmd)315 h1394_detach(void **sl_private, ddi_detach_cmd_t cmd)
316 {
317 	s1394_hal_t	*hal;
318 
319 	hal = (s1394_hal_t *)(*sl_private);
320 
321 	switch (cmd) {
322 	case DDI_DETACH:
323 		/* Clean up before leaving */
324 		s1394_cleanup_for_detach(hal, H1394_CLEANUP_LEVEL7);
325 		/* NULL out the HAL "handle" */
326 		*sl_private = NULL;
327 		break;
328 
329 	case DDI_SUSPEND:
330 		/* Turn off any timers that might be set */
331 		s1394_destroy_timers(hal);
332 		/* Set the hal_was_suspended bit */
333 		hal->hal_was_suspended = B_TRUE;
334 		break;
335 
336 	default:
337 		return (DDI_FAILURE);
338 	}
339 
340 	return (DDI_SUCCESS);
341 }
342 
343 /*
344  * Function:    h1394_alloc_cmd()
345  * Input(s):    sl_private		The HAL "handle" returned by
346  *					    h1394_attach()
347  *		flags			The flags parameter is described below
348  *
349  * Output(s):	cmdp			Pointer to the newly allocated command
350  *		hal_priv_ptr		Offset into the command, points to
351  *					    the HAL's private area
352  *
353  * Description:	h1394_alloc_cmd() allocates a command for use with the
354  *		h1394_read_request(), h1394_write_request(), or
355  *		h1394_lock_request() interfaces of the 1394 Software Framework.
356  *		By default, h1394_alloc_cmd() may sleep while allocating
357  *		memory for the command structure.  If this is undesirable,
358  *		the HAL may set the H1394_ALLOC_CMD_NOSLEEP bit in the flags
359  *		parameter.
360  */
361 int
h1394_alloc_cmd(void * sl_private,uint_t flags,cmd1394_cmd_t ** cmdp,h1394_cmd_priv_t ** hal_priv_ptr)362 h1394_alloc_cmd(void *sl_private, uint_t flags, cmd1394_cmd_t **cmdp,
363     h1394_cmd_priv_t **hal_priv_ptr)
364 {
365 	s1394_hal_t	 *hal;
366 	s1394_cmd_priv_t *s_priv;
367 
368 	hal = (s1394_hal_t *)sl_private;
369 
370 	if (s1394_alloc_cmd(hal, flags, cmdp) != DDI_SUCCESS) {
371 		return (DDI_FAILURE);
372 	}
373 
374 	/* Get the Services Layer private area */
375 	s_priv = S1394_GET_CMD_PRIV(*cmdp);
376 
377 	*hal_priv_ptr = &s_priv->hal_cmd_private;
378 
379 	return (DDI_SUCCESS);
380 }
381 
382 /*
383  * Function:    h1394_free_cmd()
384  * Input(s):    sl_private		The HAL "handle" returned by
385  *					    h1394_attach()
386  *		cmdp			Pointer to the command to be freed
387  *
388  * Output(s):	DDI_SUCCESS		HAL successfully freed command
389  *		DDI_FAILURE		HAL failed to free command
390  *
391  * Description:	h1394_free_cmd() attempts to free a command that has previously
392  *		been allocated by the HAL.  It is possible for h1394_free_cmd()
393  *		to fail because the command is currently in-use by the 1394
394  *		Software Framework.
395  */
396 int
h1394_free_cmd(void * sl_private,cmd1394_cmd_t ** cmdp)397 h1394_free_cmd(void *sl_private, cmd1394_cmd_t **cmdp)
398 {
399 	s1394_hal_t	 *hal;
400 	s1394_cmd_priv_t *s_priv;
401 
402 	hal = (s1394_hal_t *)sl_private;
403 
404 	/* Get the Services Layer private area */
405 	s_priv = S1394_GET_CMD_PRIV(*cmdp);
406 
407 	/* Check that command isn't in use */
408 	if (s_priv->cmd_in_use == B_TRUE) {
409 		ASSERT(s_priv->cmd_in_use == B_FALSE);
410 		return (DDI_FAILURE);
411 	}
412 
413 	kmem_cache_free(hal->hal_kmem_cachep, *cmdp);
414 
415 	/* Command pointer is set to NULL before returning */
416 	*cmdp = NULL;
417 
418 	/* kstats - number of cmds freed */
419 	hal->hal_kstats->cmd_free++;
420 
421 	return (DDI_SUCCESS);
422 }
423 
424 /*
425  * Function:    h1394_cmd_is_complete()
426  * Input(s):    sl_private		The HAL "handle" returned by
427  *					    h1394_attach()
428  *		command_id		Pointer to the command that has
429  *					    just completed
430  *		cmd_type		AT_RESP => AT response or ATREQ =
431  *					    AT request
432  *		status			Command's completion status
433  *
434  * Output(s):	None
435  *
436  * Description:	h1394_cmd_is_complete() is called by the HAL whenever an
437  *		outstanding command has completed (successfully or otherwise).
438  *		After determining whether it was an AT request or and AT
439  *		response that we are handling, the command is dispatched to
440  *		the appropriate handler in the 1394 Software Framework.
441  */
442 void
h1394_cmd_is_complete(void * sl_private,cmd1394_cmd_t * command_id,uint32_t cmd_type,int status)443 h1394_cmd_is_complete(void *sl_private, cmd1394_cmd_t *command_id,
444     uint32_t cmd_type, int status)
445 {
446 	s1394_hal_t	*hal;
447 	dev_info_t	*dip;
448 
449 	hal = (s1394_hal_t *)sl_private;
450 
451 	/* Is it AT_RESP or AT_REQ? */
452 	switch (cmd_type) {
453 	case H1394_AT_REQ:
454 		s1394_atreq_cmd_complete(hal, command_id, status);
455 		break;
456 
457 	case H1394_AT_RESP:
458 		s1394_atresp_cmd_complete(hal, command_id, status);
459 		break;
460 
461 	default:
462 		dip = hal->halinfo.dip;
463 
464 		/* An unexpected error in the HAL */
465 		cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
466 		    ddi_node_name(dip), ddi_get_instance(dip));
467 
468 		/* Disable the HAL */
469 		s1394_hal_shutdown(hal, B_TRUE);
470 
471 		break;
472 	}
473 }
474 
475 /*
476  * Function:    h1394_bus_reset()
477  * Input(s):    sl_private		The HAL "handle" returned by
478  *					    h1394_attach()
479  *
480  * Output(s):	selfid_buf_addr		The pointer to a buffer into which
481  *					    any Self ID packets should be put
482  *
483  * Description:	h1394_bus_reset() is called whenever a 1394 bus reset event
484  *		is detected by the HAL.  This routine simply prepares for
485  *		the subsequent Self ID packets.
486  */
487 void
h1394_bus_reset(void * sl_private,void ** selfid_buf_addr)488 h1394_bus_reset(void *sl_private, void **selfid_buf_addr)
489 {
490 	s1394_hal_t	*hal;
491 
492 	hal = (s1394_hal_t *)sl_private;
493 
494 	mutex_enter(&hal->topology_tree_mutex);
495 
496 	/* Update the HAL's state */
497 	if (hal->hal_state != S1394_HAL_SHUTDOWN) {
498 		hal->hal_state = S1394_HAL_RESET;
499 	} else {
500 		mutex_exit(&hal->topology_tree_mutex);
501 		return;
502 	}
503 
504 	if (hal->initiated_bus_reset == B_TRUE) {
505 		hal->initiated_bus_reset = B_FALSE;
506 		if (hal->num_bus_reset_till_fail > 0) {
507 			hal->num_bus_reset_till_fail--;
508 		}
509 	} else {
510 		hal->num_bus_reset_till_fail = NUM_BR_FAIL;
511 	}
512 
513 	/* Reset the IRM node ID */
514 	hal->IRM_node = -1;
515 
516 	/* Slowest node defaults to IEEE1394_S400 */
517 	hal->slowest_node_speed = IEEE1394_S400;
518 
519 	/* Pick a SelfID buffer to give */
520 	if (hal->current_buffer == 0) {
521 		*selfid_buf_addr = (void *)hal->selfid_buf1;
522 		hal->current_buffer = 1;
523 	} else {
524 		*selfid_buf_addr = (void *)hal->selfid_buf0;
525 		hal->current_buffer = 0;
526 	}
527 
528 	/* Disable the CSR topology_map (temporarily) */
529 	s1394_CSR_topology_map_disable(hal);
530 
531 	mutex_exit(&hal->topology_tree_mutex);
532 
533 	/* Reset the Bus Manager node ID */
534 	mutex_enter(&hal->bus_mgr_node_mutex);
535 	hal->bus_mgr_node = -1;
536 	mutex_exit(&hal->bus_mgr_node_mutex);
537 }
538 
539 /*
540  * Function:    h1394_self_ids()
541  * Input(s):    sl_private		The HAL "handle" returned by
542  *					    h1394_attach()
543  *		selfid_buf_addr		Pointer to the Self ID buffer
544  *		selfid_size		The size of the filled part of the
545  *					    Self ID buffer
546  *		node_id			The local (host) node ID for the
547  *					    current generation
548  *		generation_count	The current generation number
549  *
550  * Output(s):	None
551  *
552  * Description:	h1394_self_ids() does alot of the work at bus reset.  It
553  *		takes the Self ID packets and parses them, builds a topology
554  *		tree representation of them, calculates gap count, IRM, speed
555  *		map, does any node matching that's possible, and then wakes
556  *		up the br_thread.
557  */
558 void
h1394_self_ids(void * sl_private,void * selfid_buf_addr,uint32_t selfid_size,uint32_t node_id,uint32_t generation_count)559 h1394_self_ids(void *sl_private, void *selfid_buf_addr, uint32_t selfid_size,
560     uint32_t node_id, uint32_t generation_count)
561 {
562 	s1394_hal_t	*hal;
563 	int		diameter;
564 	uint_t		gen_diff, gen_rollover;
565 	boolean_t	tree_copied = B_FALSE;
566 	ushort_t	saved_number_of_nodes;
567 
568 	/*
569 	 * NOTE: current topology tree is referred to as topology_tree
570 	 * and the old topology tree is referred to as old_tree.
571 	 * tree_valid indicates selfID buffer checked out OK and we were
572 	 * able to build the topology tree.
573 	 * tree_processed indicates we read the config ROMs as needed.
574 	 */
575 	hal = (s1394_hal_t *)sl_private;
576 
577 	/* Lock the topology tree */
578 	mutex_enter(&hal->topology_tree_mutex);
579 	if (hal->hal_state == S1394_HAL_SHUTDOWN) {
580 		mutex_exit(&hal->topology_tree_mutex);
581 		return;
582 	}
583 
584 	/* kstats - number of selfid completes */
585 	hal->hal_kstats->selfid_complete++;
586 
587 	if (generation_count > hal->generation_count) {
588 		gen_diff = generation_count - hal->generation_count;
589 		hal->hal_kstats->bus_reset += gen_diff;
590 	} else {
591 		gen_diff = hal->generation_count - generation_count;
592 		/* Use max_generation to determine how many bus resets */
593 		hal->hal_kstats->bus_reset +=
594 		    (hal->halinfo.max_generation - gen_diff);
595 	}
596 
597 	/*
598 	 * If the current tree has a valid topology tree (selfids
599 	 * checked out OK etc) and config roms read as needed,
600 	 * then make it the old tree before building a new one.
601 	 */
602 	if ((hal->topology_tree_valid == B_TRUE) &&
603 	    (hal->topology_tree_processed == B_TRUE)) {
604 		/* Trees are switched after the copy completes */
605 		s1394_copy_old_tree(hal);
606 		tree_copied = B_TRUE;
607 	}
608 
609 	/* Set the new generation and node id */
610 	hal->node_id = node_id;
611 	hal->generation_count = generation_count;
612 
613 	/* Invalidate the current topology tree */
614 	hal->topology_tree_valid = B_FALSE;
615 	hal->topology_tree_processed = B_FALSE;
616 	hal->cfgroms_being_read = 0;
617 
618 	/*
619 	 * Save the number of nodes prior to parsing the self id buffer.
620 	 * We need this saved value while initializing the topology tree
621 	 * (for non-copy case).
622 	 */
623 	saved_number_of_nodes = hal->number_of_nodes;
624 
625 	/* Parse the SelfID buffer */
626 	if (s1394_parse_selfid_buffer(hal, selfid_buf_addr, selfid_size) !=
627 	    DDI_SUCCESS) {
628 		/* Unlock the topology tree */
629 		mutex_exit(&hal->topology_tree_mutex);
630 
631 		/* kstats - SelfID buffer error */
632 		hal->hal_kstats->selfid_buffer_error++;
633 		return;		/* Error parsing SelfIDs */
634 	}
635 
636 	/* Sort the SelfID packets by node number (if it's a 1995 PHY) */
637 	if (hal->halinfo.phy == H1394_PHY_1995) {
638 		s1394_sort_selfids(hal);
639 	}
640 
641 	/*
642 	 * Update the cycle master timer - if the timer is set and
643 	 * we were the root but we are not anymore, then disable it.
644 	 */
645 	mutex_enter(&hal->cm_timer_mutex);
646 	if ((hal->cm_timer_set == B_TRUE) &&
647 	    ((hal->old_number_of_nodes - 1) ==
648 		IEEE1394_NODE_NUM(hal->old_node_id)) &&
649 	    ((hal->number_of_nodes - 1) !=
650 		IEEE1394_NODE_NUM(hal->node_id))) {
651 		mutex_exit(&hal->cm_timer_mutex);
652 		(void) untimeout(hal->cm_timer);
653 	} else {
654 		mutex_exit(&hal->cm_timer_mutex);
655 	}
656 
657 	s1394_init_topology_tree(hal, tree_copied, saved_number_of_nodes);
658 
659 	/* Determine the 1394 bus gap count */
660 	hal->gap_count = s1394_get_current_gap_count(hal);
661 	/* If gap counts are inconsistent, reset */
662 	if (hal->gap_count == -1) {
663 		/* Unlock the topology tree */
664 		mutex_exit(&hal->topology_tree_mutex);
665 
666 		/* kstats - SelfID buffer error (invalid gap counts) */
667 		hal->hal_kstats->selfid_buffer_error++;
668 
669 		if (s1394_ignore_invalid_gap_cnt == 1) {
670 			/* Lock the topology tree again */
671 			mutex_enter(&hal->topology_tree_mutex);
672 			hal->gap_count = 0x3F;
673 		} else {
674 			return;	/* Invalid gap counts in SelfID buffer */
675 		}
676 	}
677 
678 	/* Determine the Isoch Resource Manager */
679 	hal->IRM_node = s1394_get_isoch_rsrc_mgr(hal);
680 
681 	/* Build the topology tree */
682 	if (s1394_topology_tree_build(hal) != DDI_SUCCESS) {
683 		/* Unlock the topology tree */
684 		mutex_exit(&hal->topology_tree_mutex);
685 
686 		/* kstats - SelfID buffer error (Invalid topology tree) */
687 		hal->hal_kstats->selfid_buffer_error++;
688 		return;		/* Error building topology tree from SelfIDs */
689 	}
690 
691 	/* Update the CSR topology_map */
692 	s1394_CSR_topology_map_update(hal);
693 
694 	/* Calculate the diameter */
695 	diameter = s1394_topology_tree_calculate_diameter(hal);
696 
697 	/* Determine the optimum gap count */
698 	hal->optimum_gap_count = s1394_gap_count_optimize(diameter);
699 
700 	/* Fill in the speed map */
701 	s1394_speed_map_fill(hal);
702 
703 	/* Initialize the two trees (for tree walking) */
704 	s1394_topology_tree_mark_all_unvisited(hal);
705 	s1394_old_tree_mark_all_unvisited(hal);
706 	s1394_old_tree_mark_all_unmatched(hal);
707 
708 	/* Are both trees (old and new) valid? */
709 	if ((hal->old_tree_valid == B_TRUE) &&
710 	    (hal->topology_tree_valid == B_TRUE)) {
711 		/* If HAL was in a suspended state, then do no matching */
712 		if (hal->hal_was_suspended == B_TRUE) {
713 		    hal->hal_was_suspended = B_FALSE;
714 		} else {
715 			gen_rollover = hal->halinfo.max_generation + 1;
716 			/* If only one bus reset occurred, match the trees */
717 			if (((hal->old_generation_count + 1) % gen_rollover) ==
718 			    generation_count) {
719 				s1394_match_tree_nodes(hal);
720 			}
721 		}
722 	}
723 
724 	/* Unlock the topology tree */
725 	mutex_exit(&hal->topology_tree_mutex);
726 
727 	/* Wake up the bus reset processing thread */
728 	s1394_tickle_bus_reset_thread(hal);
729 }
730 
731 /*
732  * Function:    h1394_read_request()
733  * Input(s):    sl_private		The HAL "handle" returned by
734  *					    h1394_attach()
735  *		req			The incoming AR request
736  *
737  * Output(s):	None
738  *
739  * Description:	h1394_read_request() receives incoming AR requests.  These
740  *		asynchronous read requests are dispatched to the appropriate
741  *		target (if one has registered) or are handled by the 1394
742  *		Software Framework, which will send out an appropriate
743  *		response.
744  */
745 void
h1394_read_request(void * sl_private,cmd1394_cmd_t * req)746 h1394_read_request(void *sl_private, cmd1394_cmd_t *req)
747 {
748 	s1394_hal_t		*hal;
749 	s1394_cmd_priv_t	*s_priv;
750 	s1394_addr_space_blk_t  *addr_blk;
751 	dev_info_t		*dip;
752 	uint64_t		end_of_request;
753 	uint32_t		offset;
754 	size_t			cmd_length;
755 	uchar_t			*bufp_addr;
756 	uchar_t			*begin_ptr;
757 	uchar_t			*end_ptr;
758 	uchar_t			*tmp_ptr;
759 	void (*recv_read_req)(cmd1394_cmd_t *);
760 
761 	hal = (s1394_hal_t *)sl_private;
762 
763 	/* Get the Services Layer private area */
764 	s_priv = S1394_GET_CMD_PRIV(req);
765 
766 	s_priv->cmd_priv_xfer_type = S1394_CMD_READ;
767 
768 	switch (req->cmd_type) {
769 	case CMD1394_ASYNCH_RD_QUAD:
770 		cmd_length = IEEE1394_QUADLET;
771 		hal->hal_kstats->arreq_quad_rd++;
772 		break;
773 
774 	case CMD1394_ASYNCH_RD_BLOCK:
775 		cmd_length = req->cmd_u.b.blk_length;
776 		hal->hal_kstats->arreq_blk_rd++;
777 		break;
778 
779 	default:
780 		dip = hal->halinfo.dip;
781 
782 		/* An unexpected error in the HAL */
783 		cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
784 		    ddi_node_name(dip), ddi_get_instance(dip));
785 
786 		/* Disable the HAL */
787 		s1394_hal_shutdown(hal, B_TRUE);
788 
789 		return;
790 	}
791 
792 	/* Lock the "used" tree */
793 	mutex_enter(&hal->addr_space_used_mutex);
794 
795 	/* Has the 1394 address been allocated? */
796 	addr_blk = s1394_used_tree_search(hal, req->cmd_addr);
797 
798 	/* If it wasn't found, it isn't owned... */
799 	if (addr_blk == NULL) {
800 		/* Unlock the "used" tree */
801 		mutex_exit(&hal->addr_space_used_mutex);
802 		req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
803 		(void) s1394_send_response(hal, req);
804 		return;
805 	}
806 
807 	/* Does the WHOLE request fit in the allocated block? */
808 	end_of_request = (req->cmd_addr + cmd_length) - 1;
809 	if (end_of_request > addr_blk->addr_hi) {
810 		/* Unlock the "used" tree */
811 		mutex_exit(&hal->addr_space_used_mutex);
812 		req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
813 		(void) s1394_send_response(hal, req);
814 		return;
815 	}
816 
817 	/* Is a read request valid for this address space? */
818 	if (!(addr_blk->addr_enable & T1394_ADDR_RDENBL)) {
819 		/* Unlock the "used" tree */
820 		mutex_exit(&hal->addr_space_used_mutex);
821 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
822 		(void) s1394_send_response(hal, req);
823 		return;
824 	}
825 
826 	/* Make sure quadlet requests are quadlet-aligned */
827 	offset = req->cmd_addr - addr_blk->addr_lo;
828 	if ((req->cmd_type == CMD1394_ASYNCH_RD_QUAD) &&
829 	    ((offset & 0x3) != 0)) {
830 		/* Unlock the "used" tree */
831 		mutex_exit(&hal->addr_space_used_mutex);
832 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
833 		(void) s1394_send_response(hal, req);
834 		return;
835 	}
836 
837 	/* Fill in the backing store if necessary */
838 	if (addr_blk->kmem_bufp != NULL) {
839 		offset = req->cmd_addr - addr_blk->addr_lo;
840 		bufp_addr = (uchar_t *)addr_blk->kmem_bufp + offset;
841 
842 		switch (req->cmd_type) {
843 		case CMD1394_ASYNCH_RD_QUAD:
844 			bcopy((void *)bufp_addr,
845 			    (void *)&(req->cmd_u.q.quadlet_data), cmd_length);
846 			break;
847 
848 		case CMD1394_ASYNCH_RD_BLOCK:
849 			begin_ptr = req->cmd_u.b.data_block->b_wptr;
850 			end_ptr	  = begin_ptr + cmd_length;
851 			tmp_ptr	  = req->cmd_u.b.data_block->b_datap->db_lim;
852 			if (end_ptr <= tmp_ptr) {
853 				bcopy((void *)bufp_addr, (void *)begin_ptr,
854 				    cmd_length);
855 				/* Update b_wptr to refelect the new data */
856 				req->cmd_u.b.data_block->b_wptr = end_ptr;
857 			} else {
858 				dip = hal->halinfo.dip;
859 
860 				/* An unexpected error in the HAL */
861 				cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
862 				    ddi_node_name(dip), ddi_get_instance(dip));
863 
864 				/* Unlock the "used" tree */
865 				mutex_exit(&hal->addr_space_used_mutex);
866 
867 				/* Disable the HAL */
868 				s1394_hal_shutdown(hal, B_TRUE);
869 
870 				return;
871 			}
872 			break;
873 
874 		default:
875 			dip = hal->halinfo.dip;
876 
877 			/* An unexpected error in the HAL */
878 			cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
879 			    ddi_node_name(dip), ddi_get_instance(dip));
880 
881 			/* Unlock the "used" tree */
882 			mutex_exit(&hal->addr_space_used_mutex);
883 
884 			/* Disable the HAL */
885 			s1394_hal_shutdown(hal, B_TRUE);
886 
887 			return;
888 		}
889 	}
890 
891 	/* Fill in the rest of the info in the request */
892 	s_priv->arreq_valid_addr = B_TRUE;
893 	req->cmd_callback_arg	 = addr_blk->addr_arg;
894 	recv_read_req		 = addr_blk->addr_events.recv_read_request;
895 
896 	/* Unlock the "used" tree */
897 	mutex_exit(&hal->addr_space_used_mutex);
898 
899 	/*
900 	 * Add no code that modifies the command after the target
901 	 * callback is called or after the response is sent to the
902 	 * HAL.
903 	 */
904 	if (recv_read_req != NULL) {
905 		recv_read_req(req);
906 	} else {
907 		req->cmd_result = IEEE1394_RESP_COMPLETE;
908 		(void) s1394_send_response(hal, req);
909 		return;
910 	}
911 }
912 
913 /*
914  * Function:    h1394_write_request()
915  * Input(s):    sl_private		The HAL "handle" returned by
916  *					    h1394_attach()
917  *		req			The incoming AR request
918  *
919  * Output(s):	None
920  *
921  * Description:	h1394_write_request() receives incoming AR requests.  These
922  *		asynchronous write requests are dispatched to the appropriate
923  *		target (if one has registered) or are handled by the 1394
924  *		Software Framework, which will send out an appropriate
925  *		response.
926  */
927 void
h1394_write_request(void * sl_private,cmd1394_cmd_t * req)928 h1394_write_request(void *sl_private, cmd1394_cmd_t *req)
929 {
930 	s1394_hal_t		*hal;
931 	s1394_cmd_priv_t	*s_priv;
932 	h1394_cmd_priv_t	*h_priv;
933 	s1394_addr_space_blk_t	*addr_blk;
934 	dev_info_t		*dip;
935 	uint32_t		offset;
936 	size_t			cmd_length;
937 	uchar_t			*bufp_addr;
938 	uchar_t			*begin_ptr;
939 	uchar_t			*end_ptr;
940 	uchar_t			*tmp_ptr;
941 	uint64_t		end_of_request;
942 	boolean_t		posted_write = B_FALSE;
943 	boolean_t		write_error = B_FALSE;
944 	void (*recv_write_req)(cmd1394_cmd_t *);
945 
946 	hal = (s1394_hal_t *)sl_private;
947 
948 	/* Get the Services Layer private area */
949 	s_priv = S1394_GET_CMD_PRIV(req);
950 
951 	s_priv->cmd_priv_xfer_type = S1394_CMD_WRITE;
952 
953 	switch (req->cmd_type) {
954 	case CMD1394_ASYNCH_WR_QUAD:
955 		cmd_length = IEEE1394_QUADLET;
956 		hal->hal_kstats->arreq_quad_wr++;
957 		break;
958 
959 	case CMD1394_ASYNCH_WR_BLOCK:
960 		cmd_length = req->cmd_u.b.blk_length;
961 		hal->hal_kstats->arreq_blk_wr++;
962 		hal->hal_kstats->arreq_blk_wr_size += cmd_length;
963 		break;
964 
965 	default:
966 		dip = hal->halinfo.dip;
967 
968 		/* An unexpected error in the HAL */
969 		cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
970 		    ddi_node_name(dip), ddi_get_instance(dip));
971 
972 		/* Disable the HAL */
973 		s1394_hal_shutdown(hal, B_TRUE);
974 
975 		return;
976 	}
977 
978 	/* Lock the "used" tree */
979 	mutex_enter(&hal->addr_space_used_mutex);
980 
981 	/* Has the 1394 address been allocated? */
982 	addr_blk = s1394_used_tree_search(hal, req->cmd_addr);
983 
984 	/* Is this a posted write request? */
985 	posted_write = s1394_is_posted_write(hal, req->cmd_addr);
986 
987 	/* If it wasn't found, it isn't owned... */
988 	if (addr_blk == NULL) {
989 		req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
990 		write_error	= B_TRUE;
991 		goto write_error_check;
992 	}
993 
994 	/* Does the WHOLE request fit in the allocated block? */
995 	end_of_request = (req->cmd_addr + cmd_length) - 1;
996 	if (end_of_request > addr_blk->addr_hi) {
997 		req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
998 		write_error	= B_TRUE;
999 		goto write_error_check;
1000 	}
1001 
1002 	/* Is a write request valid for this address space? */
1003 	if (!(addr_blk->addr_enable & T1394_ADDR_WRENBL)) {
1004 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
1005 		write_error	= B_TRUE;
1006 		goto write_error_check;
1007 	}
1008 
1009 	/* Make sure quadlet request is quadlet aligned */
1010 	offset = req->cmd_addr - addr_blk->addr_lo;
1011 	if ((req->cmd_type == CMD1394_ASYNCH_WR_QUAD) &&
1012 	    ((offset & 0x3) != 0)) {
1013 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
1014 		write_error	= B_TRUE;
1015 		goto write_error_check;
1016 	}
1017 
1018 write_error_check:
1019 	/* Check if posted-write when sending error responses */
1020 	if (write_error == B_TRUE) {
1021 		/* Unlock the "used" tree */
1022 		mutex_exit(&hal->addr_space_used_mutex);
1023 
1024 		if (posted_write == B_TRUE) {
1025 			/* Get a pointer to the HAL private struct */
1026 			h_priv = (h1394_cmd_priv_t *)&s_priv->hal_cmd_private;
1027 			hal->hal_kstats->arreq_posted_write_error++;
1028 			/* Free the command - Pass it back to the HAL */
1029 			HAL_CALL(hal).response_complete(
1030 			    hal->halinfo.hal_private, req, h_priv);
1031 			return;
1032 		} else {
1033 			(void) s1394_send_response(hal, req);
1034 			return;
1035 		}
1036 	}
1037 
1038 	/* Fill in the backing store if necessary */
1039 	if (addr_blk->kmem_bufp != NULL) {
1040 		offset = req->cmd_addr - addr_blk->addr_lo;
1041 		bufp_addr = (uchar_t *)addr_blk->kmem_bufp + offset;
1042 		switch (req->cmd_type) {
1043 		case CMD1394_ASYNCH_WR_QUAD:
1044 			bcopy((void *)&(req->cmd_u.q.quadlet_data),
1045 			    (void *)bufp_addr, cmd_length);
1046 			break;
1047 
1048 		case CMD1394_ASYNCH_WR_BLOCK:
1049 			begin_ptr = req->cmd_u.b.data_block->b_rptr;
1050 			end_ptr = begin_ptr + cmd_length;
1051 			tmp_ptr = req->cmd_u.b.data_block->b_wptr;
1052 			if (end_ptr <= tmp_ptr) {
1053 				bcopy((void *)begin_ptr, (void *)bufp_addr,
1054 				    cmd_length);
1055 			} else {
1056 				dip = hal->halinfo.dip;
1057 
1058 				/* An unexpected error in the HAL */
1059 				cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
1060 				    ddi_node_name(dip), ddi_get_instance(dip));
1061 
1062 				/* Unlock the "used" tree */
1063 				mutex_exit(&hal->addr_space_used_mutex);
1064 
1065 				/* Disable the HAL */
1066 				s1394_hal_shutdown(hal, B_TRUE);
1067 
1068 				return;
1069 			}
1070 			break;
1071 
1072 		default:
1073 			dip = hal->halinfo.dip;
1074 
1075 			/* An unexpected error in the HAL */
1076 			cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
1077 			    ddi_node_name(dip), ddi_get_instance(dip));
1078 
1079 			/* Unlock the "used" tree */
1080 			mutex_exit(&hal->addr_space_used_mutex);
1081 
1082 			/* Disable the HAL */
1083 			s1394_hal_shutdown(hal, B_TRUE);
1084 
1085 			return;
1086 		}
1087 	}
1088 
1089 	/* Fill in the rest of the info in the request */
1090 	if (addr_blk->addr_type == T1394_ADDR_POSTED_WRITE)
1091 		s_priv->posted_write = B_TRUE;
1092 
1093 	s_priv->arreq_valid_addr = B_TRUE;
1094 	req->cmd_callback_arg	 = addr_blk->addr_arg;
1095 	recv_write_req		 = addr_blk->addr_events.recv_write_request;
1096 
1097 	/* Unlock the "used" tree */
1098 	mutex_exit(&hal->addr_space_used_mutex);
1099 
1100 	/*
1101 	 * Add no code that modifies the command after the target
1102 	 * callback is called or after the response is sent to the
1103 	 * HAL.
1104 	 */
1105 	if (recv_write_req != NULL) {
1106 		recv_write_req(req);
1107 	} else {
1108 		req->cmd_result = IEEE1394_RESP_COMPLETE;
1109 		(void) s1394_send_response(hal, req);
1110 		return;
1111 	}
1112 }
1113 
1114 /*
1115  * Function:    h1394_lock_request()
1116  * Input(s):    sl_private		The HAL "handle" returned by
1117  *					    h1394_attach()
1118  *		req			The incoming AR request
1119  *
1120  * Output(s):	None
1121  *
1122  * Description:	h1394_lock_request() receives incoming AR requests.  These
1123  *		asynchronous lock requests are dispatched to the appropriate
1124  *		target (if one has registered) or are handled by the 1394
1125  *		Software Framework, which will send out an appropriate
1126  *		response.
1127  */
1128 void
h1394_lock_request(void * sl_private,cmd1394_cmd_t * req)1129 h1394_lock_request(void *sl_private, cmd1394_cmd_t *req)
1130 {
1131 	s1394_hal_t		*hal;
1132 	s1394_cmd_priv_t	*s_priv;
1133 	s1394_addr_space_blk_t	*addr_blk;
1134 	dev_info_t		*dip;
1135 	uint64_t		end_of_request;
1136 	uint32_t		offset;
1137 	uchar_t			*bufp_addr;
1138 	cmd1394_lock_type_t	lock_type;
1139 	void (*recv_lock_req)(cmd1394_cmd_t *);
1140 
1141 	hal = (s1394_hal_t *)sl_private;
1142 
1143 	/* Get the Services Layer private area */
1144 	s_priv = S1394_GET_CMD_PRIV(req);
1145 
1146 	s_priv->cmd_priv_xfer_type = S1394_CMD_LOCK;
1147 
1148 	/* Lock the "used" tree */
1149 	mutex_enter(&hal->addr_space_used_mutex);
1150 
1151 	/* Has the 1394 address been allocated? */
1152 	addr_blk = s1394_used_tree_search(hal, req->cmd_addr);
1153 
1154 	/* If it wasn't found, it isn't owned... */
1155 	if (addr_blk == NULL) {
1156 		/* Unlock the "used" tree */
1157 		mutex_exit(&hal->addr_space_used_mutex);
1158 		req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
1159 		(void) s1394_send_response(hal, req);
1160 		return;
1161 	}
1162 
1163 	/* Does the WHOLE request fit in the allocated block? */
1164 	switch (req->cmd_type) {
1165 	case CMD1394_ASYNCH_LOCK_32:
1166 		end_of_request = (req->cmd_addr + IEEE1394_QUADLET) - 1;
1167 		/* kstats - 32-bit lock request */
1168 		hal->hal_kstats->arreq_lock32++;
1169 		break;
1170 
1171 	case CMD1394_ASYNCH_LOCK_64:
1172 		end_of_request = (req->cmd_addr + IEEE1394_OCTLET) - 1;
1173 		/* kstats - 64-bit lock request */
1174 		hal->hal_kstats->arreq_lock64++;
1175 		break;
1176 
1177 	default:
1178 		/* Unlock the "used" tree */
1179 		mutex_exit(&hal->addr_space_used_mutex);
1180 
1181 		dip = hal->halinfo.dip;
1182 
1183 		/* An unexpected error in the HAL */
1184 		cmn_err(CE_WARN, HALT_ERROR_MESSAGE,
1185 		    ddi_node_name(dip), ddi_get_instance(dip));
1186 
1187 		/* Disable the HAL */
1188 		s1394_hal_shutdown(hal, B_TRUE);
1189 
1190 		return;
1191 	}
1192 
1193 	if (end_of_request > addr_blk->addr_hi) {
1194 		/* Unlock the "used" tree */
1195 		mutex_exit(&hal->addr_space_used_mutex);
1196 		req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
1197 		(void) s1394_send_response(hal, req);
1198 		return;
1199 	}
1200 
1201 	/* Is a lock request valid for this address space? */
1202 	if (!(addr_blk->addr_enable & T1394_ADDR_LKENBL)) {
1203 		/* Unlock the "used" tree */
1204 		mutex_exit(&hal->addr_space_used_mutex);
1205 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
1206 		(void) s1394_send_response(hal, req);
1207 		return;
1208 	}
1209 
1210 	/* Fill in the backing store if necessary */
1211 	if (addr_blk->kmem_bufp != NULL) {
1212 		offset = req->cmd_addr - addr_blk->addr_lo;
1213 		bufp_addr = (uchar_t *)addr_blk->kmem_bufp + offset;
1214 
1215 		if (req->cmd_type == CMD1394_ASYNCH_LOCK_32) {
1216 			uint32_t	old_value;
1217 			uint32_t	arg_value;
1218 			uint32_t	data_value;
1219 			uint32_t	new_value;
1220 
1221 			arg_value	= req->cmd_u.l32.arg_value;
1222 			data_value	= req->cmd_u.l32.data_value;
1223 			lock_type	= req->cmd_u.l32.lock_type;
1224 			bcopy((void *)bufp_addr, (void *)&old_value,
1225 			    IEEE1394_QUADLET);
1226 
1227 			switch (lock_type) {
1228 			case CMD1394_LOCK_MASK_SWAP:
1229 				/* Mask-Swap (see P1394A - Table 1.7) */
1230 				new_value = (data_value & arg_value) |
1231 				    (old_value & ~arg_value);
1232 				/* Copy new_value into backing store */
1233 				bcopy((void *)&new_value, (void *)bufp_addr,
1234 				    IEEE1394_QUADLET);
1235 				req->cmd_u.l32.old_value = old_value;
1236 				break;
1237 
1238 			case CMD1394_LOCK_COMPARE_SWAP:
1239 				/* Compare-Swap */
1240 				if (old_value == arg_value) {
1241 					new_value = data_value;
1242 					/* Copy new_value into backing store */
1243 					bcopy((void *)&new_value,
1244 					    (void *)bufp_addr,
1245 					    IEEE1394_QUADLET);
1246 				}
1247 				req->cmd_u.l32.old_value = old_value;
1248 				break;
1249 
1250 			case CMD1394_LOCK_FETCH_ADD:
1251 				/* Fetch-Add (see P1394A - Table 1.7) */
1252 				old_value = T1394_DATA32(old_value);
1253 				new_value = old_value + data_value;
1254 				new_value = T1394_DATA32(new_value);
1255 				/* Copy new_value into backing store */
1256 				bcopy((void *)&new_value, (void *)bufp_addr,
1257 				    IEEE1394_QUADLET);
1258 				req->cmd_u.l32.old_value = old_value;
1259 				break;
1260 
1261 			case CMD1394_LOCK_LITTLE_ADD:
1262 				/* Little-Add (see P1394A - Table 1.7) */
1263 				old_value = T1394_DATA32(old_value);
1264 				new_value = old_value + data_value;
1265 				new_value = T1394_DATA32(new_value);
1266 				/* Copy new_value into backing store */
1267 				bcopy((void *)&new_value, (void *)bufp_addr,
1268 				    IEEE1394_QUADLET);
1269 				req->cmd_u.l32.old_value = old_value;
1270 				break;
1271 
1272 			case CMD1394_LOCK_BOUNDED_ADD:
1273 				/* Bounded-Add (see P1394A - Table 1.7) */
1274 				old_value = T1394_DATA32(old_value);
1275 				if (old_value != arg_value) {
1276 					new_value = old_value + data_value;
1277 					new_value = T1394_DATA32(new_value);
1278 					/* Copy new_value into backing store */
1279 					bcopy((void *)&new_value,
1280 					    (void *)bufp_addr,
1281 					    IEEE1394_QUADLET);
1282 				}
1283 				req->cmd_u.l32.old_value = old_value;
1284 				break;
1285 
1286 			case CMD1394_LOCK_WRAP_ADD:
1287 				/* Wrap-Add (see P1394A - Table 1.7) */
1288 				old_value = T1394_DATA32(old_value);
1289 				if (old_value != arg_value) {
1290 					new_value = old_value + data_value;
1291 				} else {
1292 					new_value = data_value;
1293 				}
1294 				new_value = T1394_DATA32(new_value);
1295 				/* Copy new_value into backing store */
1296 				bcopy((void *)&new_value, (void *)bufp_addr,
1297 				    IEEE1394_QUADLET);
1298 				req->cmd_u.l32.old_value = old_value;
1299 				break;
1300 
1301 			default:
1302 				/* Unlock the "used" tree */
1303 				mutex_exit(&hal->addr_space_used_mutex);
1304 				req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
1305 				(void) s1394_send_response(hal, req);
1306 				return;
1307 			}
1308 		} else {
1309 			/* Handling for the 8-byte (64-bit) lock requests */
1310 			uint64_t	old_value;
1311 			uint64_t	arg_value;
1312 			uint64_t	data_value;
1313 			uint64_t	new_value;
1314 
1315 			arg_value	= req->cmd_u.l64.arg_value;
1316 			data_value	= req->cmd_u.l64.data_value;
1317 			lock_type	= req->cmd_u.l64.lock_type;
1318 			bcopy((void *)bufp_addr, (void *)&old_value,
1319 			    IEEE1394_OCTLET);
1320 
1321 			switch (lock_type) {
1322 			case CMD1394_LOCK_MASK_SWAP:
1323 				/* Mask-Swap (see P1394A - Table 1.7) */
1324 				new_value = (data_value & arg_value) |
1325 				    (old_value & ~arg_value);
1326 				/* Copy new_value into backing store */
1327 				bcopy((void *)&new_value, (void *)bufp_addr,
1328 				    IEEE1394_OCTLET);
1329 				req->cmd_u.l64.old_value = old_value;
1330 				break;
1331 
1332 			case CMD1394_LOCK_COMPARE_SWAP:
1333 				/* Compare-Swap */
1334 				if (old_value == arg_value) {
1335 					new_value = data_value;
1336 					/* Copy new_value into backing store */
1337 					bcopy((void *)&new_value,
1338 					    (void *)bufp_addr,
1339 					    IEEE1394_OCTLET);
1340 				}
1341 				req->cmd_u.l64.old_value = old_value;
1342 				break;
1343 
1344 			case CMD1394_LOCK_FETCH_ADD:
1345 				/* Fetch-Add (see P1394A - Table 1.7) */
1346 				old_value = T1394_DATA64(old_value);
1347 				new_value = old_value + data_value;
1348 				new_value = T1394_DATA64(new_value);
1349 				/* Copy new_value into backing store */
1350 				bcopy((void *)&new_value, (void *)bufp_addr,
1351 				    IEEE1394_OCTLET);
1352 				req->cmd_u.l64.old_value = old_value;
1353 				break;
1354 
1355 			case CMD1394_LOCK_LITTLE_ADD:
1356 				/* Little-Add (see P1394A - Table 1.7) */
1357 				old_value = T1394_DATA64(old_value);
1358 				new_value = old_value + data_value;
1359 				new_value = T1394_DATA64(new_value);
1360 				/* Copy new_value into backing store */
1361 				bcopy((void *)&new_value, (void *)bufp_addr,
1362 				    IEEE1394_OCTLET);
1363 				req->cmd_u.l64.old_value = old_value;
1364 				break;
1365 
1366 			case CMD1394_LOCK_BOUNDED_ADD:
1367 				/* Bounded-Add (see P1394A - Table 1.7) */
1368 				old_value = T1394_DATA64(old_value);
1369 				if (old_value != arg_value) {
1370 					new_value = old_value + data_value;
1371 					new_value = T1394_DATA64(new_value);
1372 					/* Copy new_value into backing store */
1373 					bcopy((void *)&new_value,
1374 					    (void *)bufp_addr,
1375 					    IEEE1394_OCTLET);
1376 				}
1377 				req->cmd_u.l64.old_value = old_value;
1378 				break;
1379 
1380 			case CMD1394_LOCK_WRAP_ADD:
1381 				/* Wrap-Add (see P1394A - Table 1.7) */
1382 				old_value = T1394_DATA64(old_value);
1383 				if (old_value != arg_value) {
1384 					new_value = old_value + data_value;
1385 				} else {
1386 					new_value = data_value;
1387 				}
1388 				new_value = T1394_DATA64(new_value);
1389 				/* Copy new_value into backing store */
1390 				bcopy((void *)&new_value, (void *)bufp_addr,
1391 				    IEEE1394_OCTLET);
1392 				req->cmd_u.l64.old_value = old_value;
1393 				break;
1394 
1395 			default:
1396 				/* Unlock the "used" tree */
1397 				mutex_exit(&hal->addr_space_used_mutex);
1398 				req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
1399 				(void) s1394_send_response(hal, req);
1400 				return;
1401 			}
1402 		}
1403 	}
1404 
1405 	/* Fill in the rest of the info in the request */
1406 	s_priv->arreq_valid_addr = B_TRUE;
1407 	req->cmd_callback_arg	 = addr_blk->addr_arg;
1408 	recv_lock_req		 = addr_blk->addr_events.recv_lock_request;
1409 
1410 	/* Unlock the "used" tree */
1411 	mutex_exit(&hal->addr_space_used_mutex);
1412 
1413 	/*
1414 	 * Add no code that modifies the command after the target
1415 	 * callback is called or after the response is sent to the
1416 	 * HAL.
1417 	 */
1418 	if (recv_lock_req != NULL) {
1419 		recv_lock_req(req);
1420 	} else {
1421 		req->cmd_result = IEEE1394_RESP_COMPLETE;
1422 		(void) s1394_send_response(hal, req);
1423 		return;
1424 	}
1425 }
1426 
1427 /*
1428  * Function:    h1394_ioctl()
1429  * Input(s):    sl_private		The HAL "handle" returned by
1430  *					    h1394_attach()
1431  *		cmd			ioctl cmd
1432  *		arg			argument for the ioctl cmd
1433  *		mode			mode bits (see ioctl(9e))
1434  *		cred_p			cred structure pointer
1435  *		rval_p			pointer to return value (see ioctl(9e))
1436  *
1437  * Output(s):	EINVAL if not a DEVCTL ioctl, else return value from s1394_ioctl
1438  *
1439  * Description:	h1394_ioctl() implements non-HAL specific ioctls. Currently,
1440  *		DEVCTL ioctls are the only generic ioctls supported.
1441  */
1442 int
h1394_ioctl(void * sl_private,int cmd,intptr_t arg,int mode,cred_t * cred_p,int * rval_p)1443 h1394_ioctl(void *sl_private, int cmd, intptr_t arg, int mode, cred_t *cred_p,
1444     int *rval_p)
1445 {
1446 	int	status;
1447 
1448 	if ((cmd & DEVCTL_IOC) != DEVCTL_IOC)
1449 		return (EINVAL);
1450 
1451 	status = s1394_ioctl((s1394_hal_t *)sl_private, cmd, arg, mode,
1452 	    cred_p, rval_p);
1453 
1454 	return (status);
1455 }
1456 
1457 /*
1458  * Function:    h1394_phy_packet()
1459  * Input(s):    sl_private		The HAL "handle" returned by
1460  *					    h1394_attach()
1461  *		packet_data		Pointer to a buffer of packet data
1462  *		quadlet_count		Length of the buffer
1463  *		timestamp		Timestamp indicating time of arrival
1464  *
1465  * Output(s):	None
1466  *
1467  * Description:	h1394_phy_packet() is not implemented currently, but would
1468  *		be used to process the responses to PHY ping packets in P1394A
1469  *		When one is sent out, a timestamp is given indicating its time
1470  *		of departure. Comparing that old timestamp with this new
1471  *		timestamp, we can determine the time of flight and can use
1472  *		those times to optimize the gap count.
1473  */
1474 /* ARGSUSED */
1475 void
h1394_phy_packet(void * sl_private,uint32_t * packet_data,uint_t quadlet_count,uint_t timestamp)1476 h1394_phy_packet(void *sl_private, uint32_t *packet_data, uint_t quadlet_count,
1477 	uint_t timestamp)
1478 {
1479 	/* This interface is not yet implemented */
1480 }
1481 
1482 /*
1483  * Function:    h1394_error_detected()
1484  * Input(s):    sl_private		The HAL "handle" returned by
1485  *					    h1394_attach()
1486  *		type			The type of error the HAL detected
1487  *		arg			Pointer to any extra information
1488  *
1489  * Output(s):	None
1490  *
1491  * Description:	h1394_error_detected() is used by the HAL to report errors
1492  *		to the 1394 Software Framework.
1493  */
1494 void
h1394_error_detected(void * sl_private,h1394_error_t type,void * arg)1495 h1394_error_detected(void *sl_private, h1394_error_t type, void *arg)
1496 {
1497 	s1394_hal_t	*hal;
1498 	uint_t		hal_node_num;
1499 	uint_t		IRM_node_num;
1500 
1501 	hal = (s1394_hal_t *)sl_private;
1502 
1503 	switch (type) {
1504 	case H1394_LOCK_RESP_ERR:
1505 		/* If we are the IRM, then initiate a bus reset */
1506 		mutex_enter(&hal->topology_tree_mutex);
1507 		hal_node_num = IEEE1394_NODE_NUM(hal->node_id);
1508 		IRM_node_num = hal->IRM_node;
1509 		mutex_exit(&hal->topology_tree_mutex);
1510 		if (IRM_node_num == hal_node_num)
1511 			s1394_initiate_hal_reset(hal, NON_CRITICAL);
1512 		break;
1513 
1514 	case H1394_POSTED_WR_ERR:
1515 		break;
1516 
1517 	case H1394_SELF_INITIATED_SHUTDOWN:
1518 		s1394_hal_shutdown(hal, B_FALSE);
1519 		break;
1520 
1521 	case H1394_CYCLE_TOO_LONG:
1522 		/* Set a timer to become cycle master after 1 second */
1523 		mutex_enter(&hal->cm_timer_mutex);
1524 		hal->cm_timer_set = B_TRUE;
1525 		mutex_exit(&hal->cm_timer_mutex);
1526 		hal->cm_timer = timeout(s1394_cycle_too_long_callback, hal,
1527 		    drv_usectohz(CYCLE_MASTER_TIMER * 1000));
1528 
1529 		break;
1530 
1531 	default:
1532 		break;
1533 	}
1534 }
1535