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
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.
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]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
31 * 1394 Services Layer HAL Interface
32 * Contains all of the routines that define the HAL to Services Layer
38 #include <sys/sunddi.h>
39 #include <sys/modctl.h>
40 #include <sys/sunndi.h>
41 #include <sys/cmn_err.h>
42 #include <sys/types.h>
44 #include <sys/thread.h>
48 #include <sys/devctl.h>
49 #include <sys/tnf_probe.h>
51 #include <sys/1394/t1394.h>
52 #include <sys/1394/s1394.h>
53 #include <sys/1394/h1394.h>
54 #include <sys/1394/ieee1394.h>
57 extern struct bus_ops nx1394_busops
;
58 extern int nx1394_define_events(s1394_hal_t
*hal
);
59 extern void nx1394_undefine_events(s1394_hal_t
*hal
);
60 extern int s1394_ignore_invalid_gap_cnt
;
63 * Function: h1394_init()
64 * Input(s): modlp The structure containing all of the
65 * HAL's relevant information
69 * Description: h1394_init() is called by the HAL's _init function and is
70 * used to set up the nexus bus ops.
73 h1394_init(struct modlinkage
*modlp
)
75 struct dev_ops
*devops
;
77 TNF_PROBE_0_DEBUG(h1394_init_enter
, S1394_TNF_SL_STACK
, "");
79 devops
= ((struct modldrv
*)(modlp
->ml_linkage
[0]))->drv_dev_ops
;
80 devops
->devo_bus_ops
= &nx1394_busops
;
82 TNF_PROBE_0_DEBUG(h1394_init_exit
, S1394_TNF_SL_STACK
, "");
87 * Function: h1394_fini()
88 * Input(s): modlp The structure containing all of the
89 * HAL's relevant information
93 * Description: h1394_fini() is called by the HAL's _fini function and is
94 * used to NULL out the nexus bus ops.
97 h1394_fini(struct modlinkage
*modlp
)
99 struct dev_ops
*devops
;
101 TNF_PROBE_0_DEBUG(h1394_fini_enter
, S1394_TNF_SL_STACK
, "");
103 devops
= ((struct modldrv
*)(modlp
->ml_linkage
[0]))->drv_dev_ops
;
104 devops
->devo_bus_ops
= NULL
;
106 TNF_PROBE_0_DEBUG(h1394_fini_enter
, S1394_TNF_SL_STACK
, "");
110 * Function: h1394_attach()
111 * Input(s): halinfo The structure containing all of the
112 * HAL's relevant information
113 * cmd The ddi_attach_cmd_t that tells us
114 * if this is a RESUME or a regular
117 * Output(s): sl_private The HAL "handle" to be used for
118 * all subsequent calls into the
119 * 1394 Software Framework
121 * Description: h1394_attach() registers the HAL with the 1394 Software
122 * Framework. It returns a HAL "handle" to be used for
123 * all subsequent calls into the 1394 Software Framework.
126 h1394_attach(h1394_halinfo_t
*halinfo
, ddi_attach_cmd_t cmd
, void **sl_private
)
133 TNF_PROBE_0_DEBUG(h1394_attach_enter
, S1394_TNF_SL_STACK
, "");
135 ASSERT(sl_private
!= NULL
);
137 /* If this is a DDI_RESUME, return success */
138 if (cmd
== DDI_RESUME
) {
139 hal
= (s1394_hal_t
*)(*sl_private
);
140 /* If we have a 1394A PHY, then reset the "contender bit" */
141 if (hal
->halinfo
.phy
== H1394_PHY_1394A
)
142 (void) HAL_CALL(hal
).set_contender_bit(
143 hal
->halinfo
.hal_private
);
144 TNF_PROBE_0_DEBUG(h1394_attach_exit
, S1394_TNF_SL_STACK
,
146 return (DDI_SUCCESS
);
147 } else if (cmd
!= DDI_ATTACH
) {
148 TNF_PROBE_2(h1394_attach_error
, S1394_TNF_SL_ERROR
, "",
149 tnf_string
, msg
, "Invalid ddi_attach_cmd received",
150 tnf_uint
, attach_cmd
, (uint_t
)cmd
);
151 TNF_PROBE_0_DEBUG(h1394_attach_exit
, S1394_TNF_SL_STACK
,
153 return (DDI_FAILURE
);
156 /* Allocate space for s1394_hal_t */
157 hal
= kmem_zalloc(sizeof (s1394_hal_t
), KM_SLEEP
);
159 /* Setup HAL state */
160 hal
->hal_state
= S1394_HAL_INIT
;
162 /* Copy in the halinfo struct */
163 hal
->halinfo
= *halinfo
;
165 /* Create the topology tree mutex */
166 mutex_init(&hal
->topology_tree_mutex
, NULL
, MUTEX_DRIVER
,
167 hal
->halinfo
.hw_interrupt
);
169 /* Create the Cycle Mater timer mutex */
170 mutex_init(&hal
->cm_timer_mutex
, NULL
, MUTEX_DRIVER
,
171 hal
->halinfo
.hw_interrupt
);
173 /* Initialize the Isoch CEC list */
174 hal
->isoch_cec_list_head
= NULL
;
175 hal
->isoch_cec_list_tail
= NULL
;
176 mutex_init(&hal
->isoch_cec_list_mutex
, NULL
, MUTEX_DRIVER
,
177 hal
->halinfo
.hw_interrupt
);
179 /* Initialize the Bus Manager node ID mutex and cv */
180 mutex_init(&hal
->bus_mgr_node_mutex
, NULL
, MUTEX_DRIVER
,
181 hal
->halinfo
.hw_interrupt
);
182 cv_init(&hal
->bus_mgr_node_cv
, NULL
, CV_DRIVER
,
183 hal
->halinfo
.hw_interrupt
);
185 /* Initialize the Bus Manager node ID - "-1" means undetermined */
186 hal
->bus_mgr_node
= -1;
187 hal
->incumbent_bus_mgr
= B_FALSE
;
189 /* Initialize the Target list */
190 hal
->target_head
= NULL
;
191 hal
->target_tail
= NULL
;
192 rw_init(&hal
->target_list_rwlock
, NULL
, RW_DRIVER
,
193 hal
->halinfo
.hw_interrupt
);
195 /* Setup Request Q's */
196 hal
->outstanding_q_head
= NULL
;
197 hal
->outstanding_q_tail
= NULL
;
198 mutex_init(&hal
->outstanding_q_mutex
, NULL
, MUTEX_DRIVER
,
199 hal
->halinfo
.hw_interrupt
);
200 hal
->pending_q_head
= NULL
;
201 hal
->pending_q_tail
= NULL
;
202 mutex_init(&hal
->pending_q_mutex
, NULL
, MUTEX_DRIVER
,
203 hal
->halinfo
.hw_interrupt
);
205 /* Create the kmem_cache for command allocations */
206 (void) sprintf(buf
, "hal%d_cache", ddi_get_instance(hal
->halinfo
.dip
));
207 cmd_size
= sizeof (cmd1394_cmd_t
) + sizeof (s1394_cmd_priv_t
) +
208 hal
->halinfo
.hal_overhead
;
210 hal
->hal_kmem_cachep
= kmem_cache_create(buf
, cmd_size
, 8, NULL
, NULL
,
211 NULL
, NULL
, NULL
, 0);
213 /* Setup the event stuff */
214 ret
= nx1394_define_events(hal
);
215 if (ret
!= DDI_SUCCESS
) {
216 /* Clean up before leaving */
217 s1394_cleanup_for_detach(hal
, H1394_CLEANUP_LEVEL0
);
219 TNF_PROBE_1(h1394_attach_error
, S1394_TNF_SL_ERROR
, "",
220 tnf_string
, msg
, "Unable to define attach events");
221 TNF_PROBE_0_DEBUG(h1394_attach_exit
, S1394_TNF_SL_STACK
,
223 return (DDI_FAILURE
);
226 /* Initialize the mutexes and cv's used by the bus reset thread */
227 mutex_init(&hal
->br_thread_mutex
, NULL
, MUTEX_DRIVER
,
228 hal
->halinfo
.hw_interrupt
);
229 cv_init(&hal
->br_thread_cv
, NULL
, CV_DRIVER
, hal
->halinfo
.hw_interrupt
);
230 mutex_init(&hal
->br_cmplq_mutex
, NULL
, MUTEX_DRIVER
,
231 hal
->halinfo
.hw_interrupt
);
232 cv_init(&hal
->br_cmplq_cv
, NULL
, CV_DRIVER
, hal
->halinfo
.hw_interrupt
);
235 * Create a bus reset thread to handle the device discovery.
236 * It should take the default stack sizes, it should run
237 * the s1394_br_thread() routine at the start, passing the
238 * HAL pointer as its argument. The thread should be put
239 * on processor p0, its state should be set to runnable,
240 * but not yet on a processor, and its scheduling priority
241 * should be the minimum level of any system class.
243 hal
->br_thread
= thread_create((caddr_t
)NULL
, 0, s1394_br_thread
,
244 hal
, 0, &p0
, TS_RUN
, minclsyspri
);
246 /* Until we see a bus reset this HAL has no nodes */
247 hal
->number_of_nodes
= 0;
248 hal
->num_bus_reset_till_fail
= NUM_BR_FAIL
;
250 /* Initialize the SelfID Info */
251 hal
->current_buffer
= 0;
252 hal
->selfid_buf0
= kmem_zalloc(S1394_SELFID_BUF_SIZE
, KM_SLEEP
);
253 hal
->selfid_buf1
= kmem_zalloc(S1394_SELFID_BUF_SIZE
, KM_SLEEP
);
255 /* Initialize kstat structures */
256 ret
= s1394_kstat_init(hal
);
257 if (ret
!= DDI_SUCCESS
) {
258 /* Clean up before leaving */
259 s1394_cleanup_for_detach(hal
, H1394_CLEANUP_LEVEL3
);
261 TNF_PROBE_1(h1394_attach_error
, S1394_TNF_SL_ERROR
, "",
262 tnf_string
, msg
, "Failure in s1394_kstat_init");
263 TNF_PROBE_0_DEBUG(h1394_attach_exit
, S1394_TNF_SL_STACK
,
265 return (DDI_FAILURE
);
267 hal
->hal_kstats
->guid
= hal
->halinfo
.guid
;
269 /* Setup the node tree pointers */
270 hal
->old_tree
= &hal
->last_valid_tree
[0];
271 hal
->topology_tree
= &hal
->current_tree
[0];
273 /* Initialize the local Config ROM entry */
274 ret
= s1394_init_local_config_rom(hal
);
275 if (ret
!= DDI_SUCCESS
) {
276 /* Clean up before leaving */
277 s1394_cleanup_for_detach(hal
, H1394_CLEANUP_LEVEL4
);
279 TNF_PROBE_1(h1394_attach_error
, S1394_TNF_SL_ERROR
, "",
280 tnf_string
, msg
, "Failure in s1394_init_local_config_rom");
281 TNF_PROBE_0_DEBUG(h1394_attach_exit
, S1394_TNF_SL_STACK
, "");
282 return (DDI_FAILURE
);
285 /* Initialize 1394 Address Space */
286 ret
= s1394_init_addr_space(hal
);
287 if (ret
!= DDI_SUCCESS
) {
288 /* Clean up before leaving */
289 s1394_cleanup_for_detach(hal
, H1394_CLEANUP_LEVEL5
);
291 TNF_PROBE_1(h1394_attach_error
, S1394_TNF_SL_ERROR
, "",
292 tnf_string
, msg
, "Invalid 1394 address space");
293 TNF_PROBE_0_DEBUG(h1394_attach_exit
, S1394_TNF_SL_STACK
,
295 return (DDI_FAILURE
);
298 /* Initialize FCP subsystem */
299 ret
= s1394_fcp_hal_init(hal
);
300 if (ret
!= DDI_SUCCESS
) {
301 /* Clean up before leaving */
302 s1394_cleanup_for_detach(hal
, H1394_CLEANUP_LEVEL6
);
304 TNF_PROBE_1(h1394_attach_error
, S1394_TNF_SL_ERROR
, "",
305 tnf_string
, msg
, "FCP initialization failure");
306 TNF_PROBE_0_DEBUG(h1394_attach_exit
, S1394_TNF_SL_STACK
,
308 return (DDI_FAILURE
);
311 /* Initialize the IRM node ID - "-1" means invalid, undetermined */
314 /* If we have a 1394A PHY, then set the "contender bit" */
315 if (hal
->halinfo
.phy
== H1394_PHY_1394A
)
316 (void) HAL_CALL(hal
).set_contender_bit(
317 hal
->halinfo
.hal_private
);
319 /* Add into linked list */
320 mutex_enter(&s1394_statep
->hal_list_mutex
);
321 if ((s1394_statep
->hal_head
== NULL
) &&
322 (s1394_statep
->hal_tail
== NULL
)) {
323 s1394_statep
->hal_head
= hal
;
324 s1394_statep
->hal_tail
= hal
;
326 s1394_statep
->hal_tail
->hal_next
= hal
;
327 hal
->hal_prev
= s1394_statep
->hal_tail
;
328 s1394_statep
->hal_tail
= hal
;
330 mutex_exit(&s1394_statep
->hal_list_mutex
);
332 /* Fill in services layer private info */
333 *sl_private
= (void *)hal
;
335 TNF_PROBE_0_DEBUG(h1394_attach_exit
, S1394_TNF_SL_STACK
, "");
336 return (DDI_SUCCESS
);
340 * Function: h1394_detach()
341 * Input(s): sl_private The HAL "handle" returned by
343 * cmd The ddi_detach_cmd_t that tells us
344 * if this is a SUSPEND or a regular
347 * Output(s): DDI_SUCCESS HAL successfully detached
348 * DDI_FAILURE HAL failed to detach
350 * Description: h1394_detach() unregisters the HAL from the 1394 Software
351 * Framework. It can be called during a SUSPEND operation or
352 * for a real detach() event.
355 h1394_detach(void **sl_private
, ddi_detach_cmd_t cmd
)
359 TNF_PROBE_0_DEBUG(h1394_detach_enter
, S1394_TNF_SL_STACK
, "");
361 hal
= (s1394_hal_t
*)(*sl_private
);
365 /* Clean up before leaving */
366 s1394_cleanup_for_detach(hal
, H1394_CLEANUP_LEVEL7
);
367 /* NULL out the HAL "handle" */
372 /* Turn off any timers that might be set */
373 s1394_destroy_timers(hal
);
374 /* Set the hal_was_suspended bit */
375 hal
->hal_was_suspended
= B_TRUE
;
379 TNF_PROBE_2(h1394_attach_error
, S1394_TNF_SL_ERROR
, "",
380 tnf_string
, msg
, "Invalid ddi_detach_cmd_t type specified",
381 tnf_uint
, detach_cmd
, (uint_t
)cmd
);
382 TNF_PROBE_0_DEBUG(h1394_detach_exit
, S1394_TNF_SL_STACK
, "");
383 return (DDI_FAILURE
);
386 TNF_PROBE_0_DEBUG(h1394_detach_exit
, S1394_TNF_SL_STACK
, "");
387 return (DDI_SUCCESS
);
391 * Function: h1394_alloc_cmd()
392 * Input(s): sl_private The HAL "handle" returned by
394 * flags The flags parameter is described below
396 * Output(s): cmdp Pointer to the newly allocated command
397 * hal_priv_ptr Offset into the command, points to
398 * the HAL's private area
400 * Description: h1394_alloc_cmd() allocates a command for use with the
401 * h1394_read_request(), h1394_write_request(), or
402 * h1394_lock_request() interfaces of the 1394 Software Framework.
403 * By default, h1394_alloc_cmd() may sleep while allocating
404 * memory for the command structure. If this is undesirable,
405 * the HAL may set the H1394_ALLOC_CMD_NOSLEEP bit in the flags
409 h1394_alloc_cmd(void *sl_private
, uint_t flags
, cmd1394_cmd_t
**cmdp
,
410 h1394_cmd_priv_t
**hal_priv_ptr
)
413 s1394_cmd_priv_t
*s_priv
;
415 TNF_PROBE_0_DEBUG(h1394_alloc_cmd_enter
, S1394_TNF_SL_ARREQ_STACK
,
418 hal
= (s1394_hal_t
*)sl_private
;
420 if (s1394_alloc_cmd(hal
, flags
, cmdp
) != DDI_SUCCESS
) {
421 TNF_PROBE_1(h1394_alloc_cmd_error
, S1394_TNF_SL_ARREQ_ERROR
, "",
422 tnf_string
, msg
, "Failed to allocate command structure");
423 TNF_PROBE_0_DEBUG(h1394_alloc_cmd_exit
,
424 S1394_TNF_SL_ARREQ_STACK
, "");
425 return (DDI_FAILURE
);
428 /* Get the Services Layer private area */
429 s_priv
= S1394_GET_CMD_PRIV(*cmdp
);
431 *hal_priv_ptr
= &s_priv
->hal_cmd_private
;
433 TNF_PROBE_0_DEBUG(h1394_alloc_cmd_exit
, S1394_TNF_SL_ARREQ_STACK
,
435 return (DDI_SUCCESS
);
439 * Function: h1394_free_cmd()
440 * Input(s): sl_private The HAL "handle" returned by
442 * cmdp Pointer to the command to be freed
444 * Output(s): DDI_SUCCESS HAL successfully freed command
445 * DDI_FAILURE HAL failed to free command
447 * Description: h1394_free_cmd() attempts to free a command that has previously
448 * been allocated by the HAL. It is possible for h1394_free_cmd()
449 * to fail because the command is currently in-use by the 1394
450 * Software Framework.
453 h1394_free_cmd(void *sl_private
, cmd1394_cmd_t
**cmdp
)
456 s1394_cmd_priv_t
*s_priv
;
458 TNF_PROBE_0_DEBUG(h1394_free_cmd_enter
, S1394_TNF_SL_ARREQ_STACK
,
461 hal
= (s1394_hal_t
*)sl_private
;
463 /* Get the Services Layer private area */
464 s_priv
= S1394_GET_CMD_PRIV(*cmdp
);
466 /* Check that command isn't in use */
467 if (s_priv
->cmd_in_use
== B_TRUE
) {
468 TNF_PROBE_1(h1394_free_cmd_error
, S1394_TNF_SL_ARREQ_ERROR
, "",
469 tnf_string
, msg
, "Attempted to free an in-use command");
470 TNF_PROBE_0_DEBUG(h1394_free_cmd_exit
, S1394_TNF_SL_ARREQ_STACK
,
472 ASSERT(s_priv
->cmd_in_use
== B_FALSE
);
473 return (DDI_FAILURE
);
476 kmem_cache_free(hal
->hal_kmem_cachep
, *cmdp
);
478 /* Command pointer is set to NULL before returning */
481 /* kstats - number of cmds freed */
482 hal
->hal_kstats
->cmd_free
++;
484 TNF_PROBE_0_DEBUG(h1394_free_cmd_exit
, S1394_TNF_SL_ARREQ_STACK
,
486 return (DDI_SUCCESS
);
490 * Function: h1394_cmd_is_complete()
491 * Input(s): sl_private The HAL "handle" returned by
493 * command_id Pointer to the command that has
495 * cmd_type AT_RESP => AT response or ATREQ =
497 * status Command's completion status
501 * Description: h1394_cmd_is_complete() is called by the HAL whenever an
502 * outstanding command has completed (successfully or otherwise).
503 * After determining whether it was an AT request or and AT
504 * response that we are handling, the command is dispatched to
505 * the appropriate handler in the 1394 Software Framework.
508 h1394_cmd_is_complete(void *sl_private
, cmd1394_cmd_t
*command_id
,
509 uint32_t cmd_type
, int status
)
514 TNF_PROBE_0_DEBUG(h1394_cmd_is_complete_enter
,
515 S1394_TNF_SL_ATREQ_ATRESP_STACK
, "");
517 hal
= (s1394_hal_t
*)sl_private
;
519 /* Is it AT_RESP or AT_REQ? */
522 s1394_atreq_cmd_complete(hal
, command_id
, status
);
526 s1394_atresp_cmd_complete(hal
, command_id
, status
);
530 dip
= hal
->halinfo
.dip
;
532 /* An unexpected error in the HAL */
533 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
534 ddi_node_name(dip
), ddi_get_instance(dip
));
536 /* Disable the HAL */
537 s1394_hal_shutdown(hal
, B_TRUE
);
539 TNF_PROBE_1(h1394_cmd_is_complete_error
,
540 S1394_TNF_SL_ATREQ_ATRESP_ERROR
, "",
541 tnf_string
, msg
, "Invalid command type specified");
545 TNF_PROBE_0_DEBUG(h1394_cmd_is_complete_exit
,
546 S1394_TNF_SL_ATREQ_ATRESP_STACK
, "");
550 * Function: h1394_bus_reset()
551 * Input(s): sl_private The HAL "handle" returned by
554 * Output(s): selfid_buf_addr The pointer to a buffer into which
555 * any Self ID packets should be put
557 * Description: h1394_bus_reset() is called whenever a 1394 bus reset event
558 * is detected by the HAL. This routine simply prepares for
559 * the subsequent Self ID packets.
562 h1394_bus_reset(void *sl_private
, void **selfid_buf_addr
)
566 TNF_PROBE_0_DEBUG(h1394_bus_reset_enter
, S1394_TNF_SL_BR_STACK
, "");
568 hal
= (s1394_hal_t
*)sl_private
;
570 mutex_enter(&hal
->topology_tree_mutex
);
572 /* Update the HAL's state */
573 if (hal
->hal_state
!= S1394_HAL_SHUTDOWN
) {
574 hal
->hal_state
= S1394_HAL_RESET
;
576 mutex_exit(&hal
->topology_tree_mutex
);
580 if (hal
->initiated_bus_reset
== B_TRUE
) {
581 hal
->initiated_bus_reset
= B_FALSE
;
582 if (hal
->num_bus_reset_till_fail
> 0) {
583 hal
->num_bus_reset_till_fail
--;
585 TNF_PROBE_2(h1394_bus_reset_error
,
586 S1394_TNF_SL_BR_ERROR
, "",
587 tnf_string
, msg
, "Bus reset fail (too many resets)",
588 tnf_uint
, br_type
, hal
->initiated_br_reason
);
591 hal
->num_bus_reset_till_fail
= NUM_BR_FAIL
;
594 /* Reset the IRM node ID */
597 /* Slowest node defaults to IEEE1394_S400 */
598 hal
->slowest_node_speed
= IEEE1394_S400
;
600 /* Pick a SelfID buffer to give */
601 if (hal
->current_buffer
== 0) {
602 *selfid_buf_addr
= (void *)hal
->selfid_buf1
;
603 hal
->current_buffer
= 1;
605 *selfid_buf_addr
= (void *)hal
->selfid_buf0
;
606 hal
->current_buffer
= 0;
609 /* Disable the CSR topology_map (temporarily) */
610 s1394_CSR_topology_map_disable(hal
);
612 mutex_exit(&hal
->topology_tree_mutex
);
614 /* Reset the Bus Manager node ID */
615 mutex_enter(&hal
->bus_mgr_node_mutex
);
616 hal
->bus_mgr_node
= -1;
617 mutex_exit(&hal
->bus_mgr_node_mutex
);
619 TNF_PROBE_0_DEBUG(h1394_bus_reset_exit
, S1394_TNF_SL_BR_STACK
, "");
623 * Function: h1394_self_ids()
624 * Input(s): sl_private The HAL "handle" returned by
626 * selfid_buf_addr Pointer to the Self ID buffer
627 * selfid_size The size of the filled part of the
629 * node_id The local (host) node ID for the
631 * generation_count The current generation number
635 * Description: h1394_self_ids() does alot of the work at bus reset. It
636 * takes the Self ID packets and parses them, builds a topology
637 * tree representation of them, calculates gap count, IRM, speed
638 * map, does any node matching that's possible, and then wakes
642 h1394_self_ids(void *sl_private
, void *selfid_buf_addr
, uint32_t selfid_size
,
643 uint32_t node_id
, uint32_t generation_count
)
647 uint_t gen_diff
, gen_rollover
;
648 boolean_t tree_copied
= B_FALSE
;
649 ushort_t saved_number_of_nodes
;
652 * NOTE: current topology tree is referred to as topology_tree
653 * and the old topology tree is referred to as old_tree.
654 * tree_valid indicates selfID buffer checked out OK and we were
655 * able to build the topology tree.
656 * tree_processed indicates we read the config ROMs as needed.
658 TNF_PROBE_1_DEBUG(h1394_self_ids_enter
, S1394_TNF_SL_BR_STACK
, "",
659 tnf_uint
, hal_generation
, generation_count
);
661 hal
= (s1394_hal_t
*)sl_private
;
663 /* Lock the topology tree */
664 mutex_enter(&hal
->topology_tree_mutex
);
665 if (hal
->hal_state
== S1394_HAL_SHUTDOWN
) {
666 mutex_exit(&hal
->topology_tree_mutex
);
667 TNF_PROBE_0_DEBUG(h1394_self_ids_exit
, S1394_TNF_SL_BR_STACK
,
672 /* kstats - number of selfid completes */
673 hal
->hal_kstats
->selfid_complete
++;
675 if (generation_count
> hal
->generation_count
) {
676 gen_diff
= generation_count
- hal
->generation_count
;
677 hal
->hal_kstats
->bus_reset
+= gen_diff
;
679 gen_diff
= hal
->generation_count
- generation_count
;
680 /* Use max_generation to determine how many bus resets */
681 hal
->hal_kstats
->bus_reset
+=
682 (hal
->halinfo
.max_generation
- gen_diff
);
686 * If the current tree has a valid topology tree (selfids
687 * checked out OK etc) and config roms read as needed,
688 * then make it the old tree before building a new one.
690 if ((hal
->topology_tree_valid
== B_TRUE
) &&
691 (hal
->topology_tree_processed
== B_TRUE
)) {
692 TNF_PROBE_0_DEBUG(h1394_self_ids_tree_copy
,
693 S1394_TNF_SL_BR_STACK
, "");
694 /* Trees are switched after the copy completes */
695 s1394_copy_old_tree(hal
);
696 tree_copied
= B_TRUE
;
699 /* Set the new generation and node id */
700 hal
->node_id
= node_id
;
701 hal
->generation_count
= generation_count
;
703 /* Invalidate the current topology tree */
704 hal
->topology_tree_valid
= B_FALSE
;
705 hal
->topology_tree_processed
= B_FALSE
;
706 hal
->cfgroms_being_read
= 0;
708 TNF_PROBE_0_DEBUG(h1394_self_ids_parse_selfid
, S1394_TNF_SL_BR_STACK
,
712 * Save the number of nodes prior to parsing the self id buffer.
713 * We need this saved value while initializing the topology tree
714 * (for non-copy case).
716 saved_number_of_nodes
= hal
->number_of_nodes
;
718 /* Parse the SelfID buffer */
719 if (s1394_parse_selfid_buffer(hal
, selfid_buf_addr
, selfid_size
) !=
721 /* Unlock the topology tree */
722 mutex_exit(&hal
->topology_tree_mutex
);
723 TNF_PROBE_1(h1394_self_ids_error
, S1394_TNF_SL_BR_ERROR
, "",
724 tnf_string
, msg
, "Unable to parse selfID buffer");
725 TNF_PROBE_0_DEBUG(h1394_self_ids_exit
, S1394_TNF_SL_BR_STACK
,
728 /* kstats - SelfID buffer error */
729 hal
->hal_kstats
->selfid_buffer_error
++;
730 return; /* Error parsing SelfIDs */
733 /* Sort the SelfID packets by node number (if it's a 1995 PHY) */
734 if (hal
->halinfo
.phy
== H1394_PHY_1995
) {
735 TNF_PROBE_0_DEBUG(h1394_self_ids_sort
, S1394_TNF_SL_BR_STACK
,
737 s1394_sort_selfids(hal
);
741 * Update the cycle master timer - if the timer is set and
742 * we were the root but we are not anymore, then disable it.
744 mutex_enter(&hal
->cm_timer_mutex
);
745 if ((hal
->cm_timer_set
== B_TRUE
) &&
746 ((hal
->old_number_of_nodes
- 1) ==
747 IEEE1394_NODE_NUM(hal
->old_node_id
)) &&
748 ((hal
->number_of_nodes
- 1) !=
749 IEEE1394_NODE_NUM(hal
->node_id
))) {
750 mutex_exit(&hal
->cm_timer_mutex
);
751 (void) untimeout(hal
->cm_timer
);
753 mutex_exit(&hal
->cm_timer_mutex
);
756 TNF_PROBE_0_DEBUG(h1394_self_ids_init_topology
, S1394_TNF_SL_BR_STACK
,
758 s1394_init_topology_tree(hal
, tree_copied
, saved_number_of_nodes
);
760 /* Determine the 1394 bus gap count */
761 hal
->gap_count
= s1394_get_current_gap_count(hal
);
762 /* If gap counts are inconsistent, reset */
763 if (hal
->gap_count
== -1) {
764 /* Unlock the topology tree */
765 mutex_exit(&hal
->topology_tree_mutex
);
766 TNF_PROBE_1(h1394_self_ids_error
, S1394_TNF_SL_BR_ERROR
, "",
767 tnf_string
, msg
, "Invalid gap counts in SelfID pkts");
768 TNF_PROBE_0_DEBUG(h1394_self_ids_exit
, S1394_TNF_SL_BR_STACK
,
771 /* kstats - SelfID buffer error (invalid gap counts) */
772 hal
->hal_kstats
->selfid_buffer_error
++;
774 if (s1394_ignore_invalid_gap_cnt
== 1) {
775 /* Lock the topology tree again */
776 mutex_enter(&hal
->topology_tree_mutex
);
777 hal
->gap_count
= 0x3F;
779 return; /* Invalid gap counts in SelfID buffer */
783 TNF_PROBE_1_DEBUG(h1394_self_ids_get_gap_count
, S1394_TNF_SL_BR_STACK
,
784 "", tnf_uint
, gap_count
, hal
->gap_count
);
786 /* Determine the Isoch Resource Manager */
787 hal
->IRM_node
= s1394_get_isoch_rsrc_mgr(hal
);
789 TNF_PROBE_1_DEBUG(h1394_self_ids_IRM_node
, S1394_TNF_SL_BR_STACK
, "",
790 tnf_int
, IRM_node
, hal
->IRM_node
);
792 TNF_PROBE_0_DEBUG(h1394_self_ids_build_topology_tree
,
793 S1394_TNF_SL_BR_STACK
, "");
795 /* Build the topology tree */
796 if (s1394_topology_tree_build(hal
) != DDI_SUCCESS
) {
797 /* Unlock the topology tree */
798 mutex_exit(&hal
->topology_tree_mutex
);
799 TNF_PROBE_1(h1394_self_ids_error
, S1394_TNF_SL_BR_ERROR
, "",
800 tnf_string
, msg
, "Error building the topology tree");
801 TNF_PROBE_0_DEBUG(h1394_self_ids_exit
, S1394_TNF_SL_BR_STACK
,
804 /* kstats - SelfID buffer error (Invalid topology tree) */
805 hal
->hal_kstats
->selfid_buffer_error
++;
806 return; /* Error building topology tree from SelfIDs */
809 TNF_PROBE_0_DEBUG(h1394_self_ids_topology_CSRs
, S1394_TNF_SL_BR_STACK
,
812 /* Update the CSR topology_map */
813 s1394_CSR_topology_map_update(hal
);
815 /* Calculate the diameter */
816 diameter
= s1394_topology_tree_calculate_diameter(hal
);
818 /* Determine the optimum gap count */
819 hal
->optimum_gap_count
= s1394_gap_count_optimize(diameter
);
821 TNF_PROBE_1_DEBUG(h1394_self_ids_diameter_and_gap_count
,
822 S1394_TNF_SL_BR_STACK
, "",
823 tnf_uint
, optimum_gap
, hal
->optimum_gap_count
);
825 TNF_PROBE_0_DEBUG(h1394_self_ids_speed_map
, S1394_TNF_SL_BR_STACK
, "");
827 /* Fill in the speed map */
828 s1394_speed_map_fill(hal
);
830 /* Initialize the two trees (for tree walking) */
831 s1394_topology_tree_mark_all_unvisited(hal
);
832 s1394_old_tree_mark_all_unvisited(hal
);
833 s1394_old_tree_mark_all_unmatched(hal
);
835 /* Are both trees (old and new) valid? */
836 if ((hal
->old_tree_valid
== B_TRUE
) &&
837 (hal
->topology_tree_valid
== B_TRUE
)) {
838 /* If HAL was in a suspended state, then do no matching */
839 if (hal
->hal_was_suspended
== B_TRUE
) {
840 hal
->hal_was_suspended
= B_FALSE
;
842 gen_rollover
= hal
->halinfo
.max_generation
+ 1;
843 /* If only one bus reset occurred, match the trees */
844 if (((hal
->old_generation_count
+ 1) % gen_rollover
) ==
846 TNF_PROBE_0_DEBUG(h1394_self_ids_tree_matching
,
847 S1394_TNF_SL_BR_STACK
, "");
848 s1394_match_tree_nodes(hal
);
853 /* Unlock the topology tree */
854 mutex_exit(&hal
->topology_tree_mutex
);
856 /* Wake up the bus reset processing thread */
857 s1394_tickle_bus_reset_thread(hal
);
859 TNF_PROBE_0_DEBUG(h1394_self_ids_exit
,
860 S1394_TNF_SL_BR_STACK
, "");
864 * Function: h1394_read_request()
865 * Input(s): sl_private The HAL "handle" returned by
867 * req The incoming AR request
871 * Description: h1394_read_request() receives incoming AR requests. These
872 * asynchronous read requests are dispatched to the appropriate
873 * target (if one has registered) or are handled by the 1394
874 * Software Framework, which will send out an appropriate
878 h1394_read_request(void *sl_private
, cmd1394_cmd_t
*req
)
881 s1394_cmd_priv_t
*s_priv
;
882 s1394_addr_space_blk_t
*addr_blk
;
884 uint64_t end_of_request
;
891 void (*recv_read_req
)(cmd1394_cmd_t
*);
893 TNF_PROBE_0_DEBUG(h1394_read_request_enter
, S1394_TNF_SL_ARREQ_STACK
,
896 hal
= (s1394_hal_t
*)sl_private
;
898 /* Get the Services Layer private area */
899 s_priv
= S1394_GET_CMD_PRIV(req
);
901 s_priv
->cmd_priv_xfer_type
= S1394_CMD_READ
;
903 switch (req
->cmd_type
) {
904 case CMD1394_ASYNCH_RD_QUAD
:
905 cmd_length
= IEEE1394_QUADLET
;
906 hal
->hal_kstats
->arreq_quad_rd
++;
909 case CMD1394_ASYNCH_RD_BLOCK
:
910 cmd_length
= req
->cmd_u
.b
.blk_length
;
911 hal
->hal_kstats
->arreq_blk_rd
++;
915 dip
= hal
->halinfo
.dip
;
917 /* An unexpected error in the HAL */
918 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
919 ddi_node_name(dip
), ddi_get_instance(dip
));
921 /* Disable the HAL */
922 s1394_hal_shutdown(hal
, B_TRUE
);
924 TNF_PROBE_1(h1394_read_request_error
,
925 S1394_TNF_SL_ARREQ_ERROR
, "",
926 tnf_string
, msg
, "Invalid command type specified");
927 TNF_PROBE_0_DEBUG(h1394_read_request_exit
,
928 S1394_TNF_SL_ARREQ_STACK
, "");
932 /* Lock the "used" tree */
933 mutex_enter(&hal
->addr_space_used_mutex
);
935 /* Has the 1394 address been allocated? */
936 addr_blk
= s1394_used_tree_search(hal
, req
->cmd_addr
);
938 TNF_PROBE_0_DEBUG(h1394_read_request_addr_search
,
939 S1394_TNF_SL_ARREQ_STACK
, "");
941 /* If it wasn't found, it isn't owned... */
942 if (addr_blk
== NULL
) {
943 /* Unlock the "used" tree */
944 mutex_exit(&hal
->addr_space_used_mutex
);
945 req
->cmd_result
= IEEE1394_RESP_ADDRESS_ERROR
;
946 (void) s1394_send_response(hal
, req
);
947 TNF_PROBE_0_DEBUG(h1394_read_request_exit
,
948 S1394_TNF_SL_ARREQ_STACK
, "");
952 /* Does the WHOLE request fit in the allocated block? */
953 end_of_request
= (req
->cmd_addr
+ cmd_length
) - 1;
954 if (end_of_request
> addr_blk
->addr_hi
) {
955 /* Unlock the "used" tree */
956 mutex_exit(&hal
->addr_space_used_mutex
);
957 req
->cmd_result
= IEEE1394_RESP_ADDRESS_ERROR
;
958 (void) s1394_send_response(hal
, req
);
959 TNF_PROBE_0_DEBUG(h1394_read_request_exit
,
960 S1394_TNF_SL_ARREQ_STACK
, "");
964 /* Is a read request valid for this address space? */
965 if (!(addr_blk
->addr_enable
& T1394_ADDR_RDENBL
)) {
966 /* Unlock the "used" tree */
967 mutex_exit(&hal
->addr_space_used_mutex
);
968 req
->cmd_result
= IEEE1394_RESP_TYPE_ERROR
;
969 (void) s1394_send_response(hal
, req
);
970 TNF_PROBE_0_DEBUG(h1394_read_request_exit
,
971 S1394_TNF_SL_ARREQ_STACK
, "");
975 /* Make sure quadlet requests are quadlet-aligned */
976 offset
= req
->cmd_addr
- addr_blk
->addr_lo
;
977 if ((req
->cmd_type
== CMD1394_ASYNCH_RD_QUAD
) &&
978 ((offset
& 0x3) != 0)) {
979 /* Unlock the "used" tree */
980 mutex_exit(&hal
->addr_space_used_mutex
);
981 req
->cmd_result
= IEEE1394_RESP_TYPE_ERROR
;
982 (void) s1394_send_response(hal
, req
);
983 TNF_PROBE_0_DEBUG(h1394_read_request_exit
,
984 S1394_TNF_SL_ARREQ_STACK
, "");
988 /* Fill in the backing store if necessary */
989 if (addr_blk
->kmem_bufp
!= NULL
) {
990 offset
= req
->cmd_addr
- addr_blk
->addr_lo
;
991 bufp_addr
= (uchar_t
*)addr_blk
->kmem_bufp
+ offset
;
993 switch (req
->cmd_type
) {
994 case CMD1394_ASYNCH_RD_QUAD
:
995 bcopy((void *)bufp_addr
,
996 (void *)&(req
->cmd_u
.q
.quadlet_data
), cmd_length
);
999 case CMD1394_ASYNCH_RD_BLOCK
:
1000 begin_ptr
= req
->cmd_u
.b
.data_block
->b_wptr
;
1001 end_ptr
= begin_ptr
+ cmd_length
;
1002 tmp_ptr
= req
->cmd_u
.b
.data_block
->b_datap
->db_lim
;
1003 if (end_ptr
<= tmp_ptr
) {
1004 bcopy((void *)bufp_addr
, (void *)begin_ptr
,
1006 /* Update b_wptr to refelect the new data */
1007 req
->cmd_u
.b
.data_block
->b_wptr
= end_ptr
;
1009 dip
= hal
->halinfo
.dip
;
1011 /* An unexpected error in the HAL */
1012 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
1013 ddi_node_name(dip
), ddi_get_instance(dip
));
1015 /* Unlock the "used" tree */
1016 mutex_exit(&hal
->addr_space_used_mutex
);
1018 /* Disable the HAL */
1019 s1394_hal_shutdown(hal
, B_TRUE
);
1021 TNF_PROBE_1(h1394_read_request_error
,
1022 S1394_TNF_SL_ARREQ_ERROR
, "", tnf_string
,
1023 msg
, "Error - mblk too small for request");
1024 TNF_PROBE_0_DEBUG(h1394_read_request_exit
,
1025 S1394_TNF_SL_ARREQ_STACK
, "");
1031 dip
= hal
->halinfo
.dip
;
1033 /* An unexpected error in the HAL */
1034 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
1035 ddi_node_name(dip
), ddi_get_instance(dip
));
1037 /* Unlock the "used" tree */
1038 mutex_exit(&hal
->addr_space_used_mutex
);
1040 /* Disable the HAL */
1041 s1394_hal_shutdown(hal
, B_TRUE
);
1043 TNF_PROBE_1(h1394_read_request_error
,
1044 S1394_TNF_SL_ARREQ_ERROR
, "", tnf_string
, msg
,
1045 "Invalid command type specified");
1046 TNF_PROBE_0_DEBUG(h1394_read_request_exit
,
1047 S1394_TNF_SL_ARREQ_STACK
, "");
1052 /* Fill in the rest of the info in the request */
1053 s_priv
->arreq_valid_addr
= B_TRUE
;
1054 req
->cmd_callback_arg
= addr_blk
->addr_arg
;
1055 recv_read_req
= addr_blk
->addr_events
.recv_read_request
;
1057 /* Unlock the "used" tree */
1058 mutex_exit(&hal
->addr_space_used_mutex
);
1061 * Add no code that modifies the command after the target
1062 * callback is called or after the response is sent to the
1065 if (recv_read_req
!= NULL
) {
1066 TNF_PROBE_0_DEBUG(h1394_read_request_do_callback
,
1067 S1394_TNF_SL_ARREQ_STACK
, "");
1070 req
->cmd_result
= IEEE1394_RESP_COMPLETE
;
1071 (void) s1394_send_response(hal
, req
);
1072 TNF_PROBE_0_DEBUG(h1394_read_request_exit
,
1073 S1394_TNF_SL_ARREQ_STACK
, "");
1077 TNF_PROBE_0_DEBUG(h1394_read_request_exit
, S1394_TNF_SL_ARREQ_STACK
,
1082 * Function: h1394_write_request()
1083 * Input(s): sl_private The HAL "handle" returned by
1085 * req The incoming AR request
1089 * Description: h1394_write_request() receives incoming AR requests. These
1090 * asynchronous write requests are dispatched to the appropriate
1091 * target (if one has registered) or are handled by the 1394
1092 * Software Framework, which will send out an appropriate
1096 h1394_write_request(void *sl_private
, cmd1394_cmd_t
*req
)
1099 s1394_cmd_priv_t
*s_priv
;
1100 h1394_cmd_priv_t
*h_priv
;
1101 s1394_addr_space_blk_t
*addr_blk
;
1109 uint64_t end_of_request
;
1110 boolean_t posted_write
= B_FALSE
;
1111 boolean_t write_error
= B_FALSE
;
1112 void (*recv_write_req
)(cmd1394_cmd_t
*);
1114 TNF_PROBE_0_DEBUG(h1394_write_request_enter
, S1394_TNF_SL_ARREQ_STACK
,
1117 hal
= (s1394_hal_t
*)sl_private
;
1119 /* Get the Services Layer private area */
1120 s_priv
= S1394_GET_CMD_PRIV(req
);
1122 s_priv
->cmd_priv_xfer_type
= S1394_CMD_WRITE
;
1124 switch (req
->cmd_type
) {
1125 case CMD1394_ASYNCH_WR_QUAD
:
1126 cmd_length
= IEEE1394_QUADLET
;
1127 hal
->hal_kstats
->arreq_quad_wr
++;
1130 case CMD1394_ASYNCH_WR_BLOCK
:
1131 cmd_length
= req
->cmd_u
.b
.blk_length
;
1132 hal
->hal_kstats
->arreq_blk_wr
++;
1133 hal
->hal_kstats
->arreq_blk_wr_size
+= cmd_length
;
1137 dip
= hal
->halinfo
.dip
;
1139 /* An unexpected error in the HAL */
1140 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
1141 ddi_node_name(dip
), ddi_get_instance(dip
));
1143 /* Disable the HAL */
1144 s1394_hal_shutdown(hal
, B_TRUE
);
1146 TNF_PROBE_1(h1394_write_request_error
,
1147 S1394_TNF_SL_ARREQ_ERROR
, "", tnf_string
, msg
,
1148 "Invalid command type specified");
1149 TNF_PROBE_0_DEBUG(h1394_write_request_exit
,
1150 S1394_TNF_SL_ARREQ_STACK
, "");
1154 /* Lock the "used" tree */
1155 mutex_enter(&hal
->addr_space_used_mutex
);
1157 /* Has the 1394 address been allocated? */
1158 addr_blk
= s1394_used_tree_search(hal
, req
->cmd_addr
);
1160 TNF_PROBE_0_DEBUG(h1394_write_request_addr_search
,
1161 S1394_TNF_SL_ARREQ_STACK
, "");
1163 /* Is this a posted write request? */
1164 posted_write
= s1394_is_posted_write(hal
, req
->cmd_addr
);
1166 /* If it wasn't found, it isn't owned... */
1167 if (addr_blk
== NULL
) {
1168 req
->cmd_result
= IEEE1394_RESP_ADDRESS_ERROR
;
1169 write_error
= B_TRUE
;
1170 goto write_error_check
;
1173 /* Does the WHOLE request fit in the allocated block? */
1174 end_of_request
= (req
->cmd_addr
+ cmd_length
) - 1;
1175 if (end_of_request
> addr_blk
->addr_hi
) {
1176 req
->cmd_result
= IEEE1394_RESP_ADDRESS_ERROR
;
1177 write_error
= B_TRUE
;
1178 goto write_error_check
;
1181 /* Is a write request valid for this address space? */
1182 if (!(addr_blk
->addr_enable
& T1394_ADDR_WRENBL
)) {
1183 req
->cmd_result
= IEEE1394_RESP_TYPE_ERROR
;
1184 write_error
= B_TRUE
;
1185 goto write_error_check
;
1188 /* Make sure quadlet request is quadlet aligned */
1189 offset
= req
->cmd_addr
- addr_blk
->addr_lo
;
1190 if ((req
->cmd_type
== CMD1394_ASYNCH_WR_QUAD
) &&
1191 ((offset
& 0x3) != 0)) {
1192 req
->cmd_result
= IEEE1394_RESP_TYPE_ERROR
;
1193 write_error
= B_TRUE
;
1194 goto write_error_check
;
1198 /* Check if posted-write when sending error responses */
1199 if (write_error
== B_TRUE
) {
1200 /* Unlock the "used" tree */
1201 mutex_exit(&hal
->addr_space_used_mutex
);
1203 if (posted_write
== B_TRUE
) {
1204 /* Get a pointer to the HAL private struct */
1205 h_priv
= (h1394_cmd_priv_t
*)&s_priv
->hal_cmd_private
;
1206 hal
->hal_kstats
->arreq_posted_write_error
++;
1207 /* Free the command - Pass it back to the HAL */
1208 HAL_CALL(hal
).response_complete(
1209 hal
->halinfo
.hal_private
, req
, h_priv
);
1210 TNF_PROBE_0_DEBUG(h1394_write_request_exit
,
1211 S1394_TNF_SL_ARREQ_STACK
, "");
1214 (void) s1394_send_response(hal
, req
);
1215 TNF_PROBE_0_DEBUG(h1394_write_request_exit
,
1216 S1394_TNF_SL_ARREQ_STACK
, "");
1221 /* Fill in the backing store if necessary */
1222 if (addr_blk
->kmem_bufp
!= NULL
) {
1223 offset
= req
->cmd_addr
- addr_blk
->addr_lo
;
1224 bufp_addr
= (uchar_t
*)addr_blk
->kmem_bufp
+ offset
;
1225 switch (req
->cmd_type
) {
1226 case CMD1394_ASYNCH_WR_QUAD
:
1227 bcopy((void *)&(req
->cmd_u
.q
.quadlet_data
),
1228 (void *)bufp_addr
, cmd_length
);
1231 case CMD1394_ASYNCH_WR_BLOCK
:
1232 begin_ptr
= req
->cmd_u
.b
.data_block
->b_rptr
;
1233 end_ptr
= begin_ptr
+ cmd_length
;
1234 tmp_ptr
= req
->cmd_u
.b
.data_block
->b_wptr
;
1235 if (end_ptr
<= tmp_ptr
) {
1236 bcopy((void *)begin_ptr
, (void *)bufp_addr
,
1239 dip
= hal
->halinfo
.dip
;
1241 /* An unexpected error in the HAL */
1242 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
1243 ddi_node_name(dip
), ddi_get_instance(dip
));
1245 /* Unlock the "used" tree */
1246 mutex_exit(&hal
->addr_space_used_mutex
);
1248 /* Disable the HAL */
1249 s1394_hal_shutdown(hal
, B_TRUE
);
1251 TNF_PROBE_1(h1394_write_request_error
,
1252 S1394_TNF_SL_ARREQ_ERROR
, "", tnf_string
,
1253 msg
, "Error - mblk too small for request");
1254 TNF_PROBE_0_DEBUG(h1394_write_request_exit
,
1255 S1394_TNF_SL_ARREQ_STACK
, "");
1261 dip
= hal
->halinfo
.dip
;
1263 /* An unexpected error in the HAL */
1264 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
1265 ddi_node_name(dip
), ddi_get_instance(dip
));
1267 /* Unlock the "used" tree */
1268 mutex_exit(&hal
->addr_space_used_mutex
);
1270 /* Disable the HAL */
1271 s1394_hal_shutdown(hal
, B_TRUE
);
1273 TNF_PROBE_1(h1394_write_request_error
,
1274 S1394_TNF_SL_ARREQ_ERROR
, "", tnf_string
, msg
,
1275 "Invalid command type specified");
1276 TNF_PROBE_0_DEBUG(h1394_write_request_exit
,
1277 S1394_TNF_SL_ARREQ_STACK
, "");
1282 /* Fill in the rest of the info in the request */
1283 if (addr_blk
->addr_type
== T1394_ADDR_POSTED_WRITE
)
1284 s_priv
->posted_write
= B_TRUE
;
1286 s_priv
->arreq_valid_addr
= B_TRUE
;
1287 req
->cmd_callback_arg
= addr_blk
->addr_arg
;
1288 recv_write_req
= addr_blk
->addr_events
.recv_write_request
;
1290 /* Unlock the "used" tree */
1291 mutex_exit(&hal
->addr_space_used_mutex
);
1294 * Add no code that modifies the command after the target
1295 * callback is called or after the response is sent to the
1298 if (recv_write_req
!= NULL
) {
1299 TNF_PROBE_0_DEBUG(h1394_write_request_do_callback
,
1300 S1394_TNF_SL_ARREQ_STACK
, "");
1301 recv_write_req(req
);
1303 req
->cmd_result
= IEEE1394_RESP_COMPLETE
;
1304 (void) s1394_send_response(hal
, req
);
1305 TNF_PROBE_0_DEBUG(h1394_write_request_exit
,
1306 S1394_TNF_SL_ARREQ_STACK
, "");
1310 TNF_PROBE_0_DEBUG(h1394_write_request_exit
,
1311 S1394_TNF_SL_ARREQ_STACK
, "");
1315 * Function: h1394_lock_request()
1316 * Input(s): sl_private The HAL "handle" returned by
1318 * req The incoming AR request
1322 * Description: h1394_lock_request() receives incoming AR requests. These
1323 * asynchronous lock requests are dispatched to the appropriate
1324 * target (if one has registered) or are handled by the 1394
1325 * Software Framework, which will send out an appropriate
1329 h1394_lock_request(void *sl_private
, cmd1394_cmd_t
*req
)
1332 s1394_cmd_priv_t
*s_priv
;
1333 s1394_addr_space_blk_t
*addr_blk
;
1335 uint64_t end_of_request
;
1338 cmd1394_lock_type_t lock_type
;
1339 void (*recv_lock_req
)(cmd1394_cmd_t
*);
1341 TNF_PROBE_0_DEBUG(h1394_lock_request_enter
,
1342 S1394_TNF_SL_ARREQ_STACK
, "");
1344 hal
= (s1394_hal_t
*)sl_private
;
1346 /* Get the Services Layer private area */
1347 s_priv
= S1394_GET_CMD_PRIV(req
);
1349 s_priv
->cmd_priv_xfer_type
= S1394_CMD_LOCK
;
1351 /* Lock the "used" tree */
1352 mutex_enter(&hal
->addr_space_used_mutex
);
1354 /* Has the 1394 address been allocated? */
1355 addr_blk
= s1394_used_tree_search(hal
, req
->cmd_addr
);
1357 /* If it wasn't found, it isn't owned... */
1358 if (addr_blk
== NULL
) {
1359 /* Unlock the "used" tree */
1360 mutex_exit(&hal
->addr_space_used_mutex
);
1361 req
->cmd_result
= IEEE1394_RESP_ADDRESS_ERROR
;
1362 (void) s1394_send_response(hal
, req
);
1363 TNF_PROBE_0_DEBUG(h1394_lock_request_exit
,
1364 S1394_TNF_SL_ARREQ_STACK
, "");
1368 /* Does the WHOLE request fit in the allocated block? */
1369 switch (req
->cmd_type
) {
1370 case CMD1394_ASYNCH_LOCK_32
:
1371 end_of_request
= (req
->cmd_addr
+ IEEE1394_QUADLET
) - 1;
1372 /* kstats - 32-bit lock request */
1373 hal
->hal_kstats
->arreq_lock32
++;
1376 case CMD1394_ASYNCH_LOCK_64
:
1377 end_of_request
= (req
->cmd_addr
+ IEEE1394_OCTLET
) - 1;
1378 /* kstats - 64-bit lock request */
1379 hal
->hal_kstats
->arreq_lock64
++;
1383 /* Unlock the "used" tree */
1384 mutex_exit(&hal
->addr_space_used_mutex
);
1386 dip
= hal
->halinfo
.dip
;
1388 /* An unexpected error in the HAL */
1389 cmn_err(CE_WARN
, HALT_ERROR_MESSAGE
,
1390 ddi_node_name(dip
), ddi_get_instance(dip
));
1392 /* Disable the HAL */
1393 s1394_hal_shutdown(hal
, B_TRUE
);
1395 TNF_PROBE_1(h1394_lock_request_error
,
1396 S1394_TNF_SL_ARREQ_ERROR
, "", tnf_string
, msg
,
1397 "Invalid command type specified");
1398 TNF_PROBE_0_DEBUG(h1394_lock_request_exit
,
1399 S1394_TNF_SL_ARREQ_STACK
, "");
1403 if (end_of_request
> addr_blk
->addr_hi
) {
1404 /* Unlock the "used" tree */
1405 mutex_exit(&hal
->addr_space_used_mutex
);
1406 req
->cmd_result
= IEEE1394_RESP_ADDRESS_ERROR
;
1407 (void) s1394_send_response(hal
, req
);
1408 TNF_PROBE_0_DEBUG(h1394_lock_request_exit
,
1409 S1394_TNF_SL_ARREQ_STACK
, "");
1413 /* Is a lock request valid for this address space? */
1414 if (!(addr_blk
->addr_enable
& T1394_ADDR_LKENBL
)) {
1415 /* Unlock the "used" tree */
1416 mutex_exit(&hal
->addr_space_used_mutex
);
1417 req
->cmd_result
= IEEE1394_RESP_TYPE_ERROR
;
1418 (void) s1394_send_response(hal
, req
);
1419 TNF_PROBE_0_DEBUG(h1394_lock_request_exit
,
1420 S1394_TNF_SL_ARREQ_STACK
, "");
1424 /* Fill in the backing store if necessary */
1425 if (addr_blk
->kmem_bufp
!= NULL
) {
1426 offset
= req
->cmd_addr
- addr_blk
->addr_lo
;
1427 bufp_addr
= (uchar_t
*)addr_blk
->kmem_bufp
+ offset
;
1429 if (req
->cmd_type
== CMD1394_ASYNCH_LOCK_32
) {
1432 uint32_t data_value
;
1435 arg_value
= req
->cmd_u
.l32
.arg_value
;
1436 data_value
= req
->cmd_u
.l32
.data_value
;
1437 lock_type
= req
->cmd_u
.l32
.lock_type
;
1438 bcopy((void *)bufp_addr
, (void *)&old_value
,
1441 switch (lock_type
) {
1442 case CMD1394_LOCK_MASK_SWAP
:
1443 /* Mask-Swap (see P1394A - Table 1.7) */
1444 new_value
= (data_value
& arg_value
) |
1445 (old_value
& ~arg_value
);
1446 /* Copy new_value into backing store */
1447 bcopy((void *)&new_value
, (void *)bufp_addr
,
1449 req
->cmd_u
.l32
.old_value
= old_value
;
1452 case CMD1394_LOCK_COMPARE_SWAP
:
1454 if (old_value
== arg_value
) {
1455 new_value
= data_value
;
1456 /* Copy new_value into backing store */
1457 bcopy((void *)&new_value
,
1461 req
->cmd_u
.l32
.old_value
= old_value
;
1464 case CMD1394_LOCK_FETCH_ADD
:
1465 /* Fetch-Add (see P1394A - Table 1.7) */
1466 old_value
= T1394_DATA32(old_value
);
1467 new_value
= old_value
+ data_value
;
1468 new_value
= T1394_DATA32(new_value
);
1469 /* Copy new_value into backing store */
1470 bcopy((void *)&new_value
, (void *)bufp_addr
,
1472 req
->cmd_u
.l32
.old_value
= old_value
;
1475 case CMD1394_LOCK_LITTLE_ADD
:
1476 /* Little-Add (see P1394A - Table 1.7) */
1477 old_value
= T1394_DATA32(old_value
);
1478 new_value
= old_value
+ data_value
;
1479 new_value
= T1394_DATA32(new_value
);
1480 /* Copy new_value into backing store */
1481 bcopy((void *)&new_value
, (void *)bufp_addr
,
1483 req
->cmd_u
.l32
.old_value
= old_value
;
1486 case CMD1394_LOCK_BOUNDED_ADD
:
1487 /* Bounded-Add (see P1394A - Table 1.7) */
1488 old_value
= T1394_DATA32(old_value
);
1489 if (old_value
!= arg_value
) {
1490 new_value
= old_value
+ data_value
;
1491 new_value
= T1394_DATA32(new_value
);
1492 /* Copy new_value into backing store */
1493 bcopy((void *)&new_value
,
1497 req
->cmd_u
.l32
.old_value
= old_value
;
1500 case CMD1394_LOCK_WRAP_ADD
:
1501 /* Wrap-Add (see P1394A - Table 1.7) */
1502 old_value
= T1394_DATA32(old_value
);
1503 if (old_value
!= arg_value
) {
1504 new_value
= old_value
+ data_value
;
1506 new_value
= data_value
;
1508 new_value
= T1394_DATA32(new_value
);
1509 /* Copy new_value into backing store */
1510 bcopy((void *)&new_value
, (void *)bufp_addr
,
1512 req
->cmd_u
.l32
.old_value
= old_value
;
1516 /* Unlock the "used" tree */
1517 mutex_exit(&hal
->addr_space_used_mutex
);
1518 req
->cmd_result
= IEEE1394_RESP_TYPE_ERROR
;
1519 (void) s1394_send_response(hal
, req
);
1520 TNF_PROBE_1(h1394_lock_request_error
,
1521 S1394_TNF_SL_ARREQ_ERROR
, "", tnf_string
,
1522 msg
, "Invalid lock_type");
1523 TNF_PROBE_0_DEBUG(h1394_lock_request_exit
,
1524 S1394_TNF_SL_ARREQ_STACK
, "");
1528 /* Handling for the 8-byte (64-bit) lock requests */
1531 uint64_t data_value
;
1534 arg_value
= req
->cmd_u
.l64
.arg_value
;
1535 data_value
= req
->cmd_u
.l64
.data_value
;
1536 lock_type
= req
->cmd_u
.l64
.lock_type
;
1537 bcopy((void *)bufp_addr
, (void *)&old_value
,
1540 switch (lock_type
) {
1541 case CMD1394_LOCK_MASK_SWAP
:
1542 /* Mask-Swap (see P1394A - Table 1.7) */
1543 new_value
= (data_value
& arg_value
) |
1544 (old_value
& ~arg_value
);
1545 /* Copy new_value into backing store */
1546 bcopy((void *)&new_value
, (void *)bufp_addr
,
1548 req
->cmd_u
.l64
.old_value
= old_value
;
1551 case CMD1394_LOCK_COMPARE_SWAP
:
1553 if (old_value
== arg_value
) {
1554 new_value
= data_value
;
1555 /* Copy new_value into backing store */
1556 bcopy((void *)&new_value
,
1560 req
->cmd_u
.l64
.old_value
= old_value
;
1563 case CMD1394_LOCK_FETCH_ADD
:
1564 /* Fetch-Add (see P1394A - Table 1.7) */
1565 old_value
= T1394_DATA64(old_value
);
1566 new_value
= old_value
+ data_value
;
1567 new_value
= T1394_DATA64(new_value
);
1568 /* Copy new_value into backing store */
1569 bcopy((void *)&new_value
, (void *)bufp_addr
,
1571 req
->cmd_u
.l64
.old_value
= old_value
;
1574 case CMD1394_LOCK_LITTLE_ADD
:
1575 /* Little-Add (see P1394A - Table 1.7) */
1576 old_value
= T1394_DATA64(old_value
);
1577 new_value
= old_value
+ data_value
;
1578 new_value
= T1394_DATA64(new_value
);
1579 /* Copy new_value into backing store */
1580 bcopy((void *)&new_value
, (void *)bufp_addr
,
1582 req
->cmd_u
.l64
.old_value
= old_value
;
1585 case CMD1394_LOCK_BOUNDED_ADD
:
1586 /* Bounded-Add (see P1394A - Table 1.7) */
1587 old_value
= T1394_DATA64(old_value
);
1588 if (old_value
!= arg_value
) {
1589 new_value
= old_value
+ data_value
;
1590 new_value
= T1394_DATA64(new_value
);
1591 /* Copy new_value into backing store */
1592 bcopy((void *)&new_value
,
1596 req
->cmd_u
.l64
.old_value
= old_value
;
1599 case CMD1394_LOCK_WRAP_ADD
:
1600 /* Wrap-Add (see P1394A - Table 1.7) */
1601 old_value
= T1394_DATA64(old_value
);
1602 if (old_value
!= arg_value
) {
1603 new_value
= old_value
+ data_value
;
1605 new_value
= data_value
;
1607 new_value
= T1394_DATA64(new_value
);
1608 /* Copy new_value into backing store */
1609 bcopy((void *)&new_value
, (void *)bufp_addr
,
1611 req
->cmd_u
.l64
.old_value
= old_value
;
1615 /* Unlock the "used" tree */
1616 mutex_exit(&hal
->addr_space_used_mutex
);
1617 req
->cmd_result
= IEEE1394_RESP_TYPE_ERROR
;
1618 (void) s1394_send_response(hal
, req
);
1619 TNF_PROBE_1(h1394_lock_request_error
,
1620 S1394_TNF_SL_ARREQ_ERROR
, "", tnf_string
,
1621 msg
, "Invalid lock_type");
1622 TNF_PROBE_0_DEBUG(h1394_lock_request_exit
,
1623 S1394_TNF_SL_ARREQ_STACK
, "");
1629 /* Fill in the rest of the info in the request */
1630 s_priv
->arreq_valid_addr
= B_TRUE
;
1631 req
->cmd_callback_arg
= addr_blk
->addr_arg
;
1632 recv_lock_req
= addr_blk
->addr_events
.recv_lock_request
;
1634 /* Unlock the "used" tree */
1635 mutex_exit(&hal
->addr_space_used_mutex
);
1638 * Add no code that modifies the command after the target
1639 * callback is called or after the response is sent to the
1642 if (recv_lock_req
!= NULL
) {
1643 TNF_PROBE_0_DEBUG(h1394_lock_request_do_callback
,
1644 S1394_TNF_SL_ARREQ_STACK
, "");
1647 req
->cmd_result
= IEEE1394_RESP_COMPLETE
;
1648 (void) s1394_send_response(hal
, req
);
1649 TNF_PROBE_0_DEBUG(h1394_lock_request_exit
,
1650 S1394_TNF_SL_ARREQ_STACK
, "");
1654 TNF_PROBE_0_DEBUG(h1394_lock_request_exit
,
1655 S1394_TNF_SL_ARREQ_STACK
, "");
1659 * Function: h1394_ioctl()
1660 * Input(s): sl_private The HAL "handle" returned by
1663 * arg argument for the ioctl cmd
1664 * mode mode bits (see ioctl(9e))
1665 * cred_p cred structure pointer
1666 * rval_p pointer to return value (see ioctl(9e))
1668 * Output(s): EINVAL if not a DEVCTL ioctl, else return value from s1394_ioctl
1670 * Description: h1394_ioctl() implements non-HAL specific ioctls. Currently,
1671 * DEVCTL ioctls are the only generic ioctls supported.
1674 h1394_ioctl(void *sl_private
, int cmd
, intptr_t arg
, int mode
, cred_t
*cred_p
,
1679 TNF_PROBE_0_DEBUG(h1394_ioctl_enter
, S1394_TNF_SL_IOCTL_STACK
, "");
1681 if ((cmd
& DEVCTL_IOC
) != DEVCTL_IOC
)
1684 status
= s1394_ioctl((s1394_hal_t
*)sl_private
, cmd
, arg
, mode
,
1687 TNF_PROBE_1_DEBUG(h1394_ioctl_exit
, S1394_TNF_SL_IOCTL_STACK
, "",
1688 tnf_int
, status
, status
);
1693 * Function: h1394_phy_packet()
1694 * Input(s): sl_private The HAL "handle" returned by
1696 * packet_data Pointer to a buffer of packet data
1697 * quadlet_count Length of the buffer
1698 * timestamp Timestamp indicating time of arrival
1702 * Description: h1394_phy_packet() is not implemented currently, but would
1703 * be used to process the responses to PHY ping packets in P1394A
1704 * When one is sent out, a timestamp is given indicating its time
1705 * of departure. Comparing that old timestamp with this new
1706 * timestamp, we can determine the time of flight and can use
1707 * those times to optimize the gap count.
1711 h1394_phy_packet(void *sl_private
, uint32_t *packet_data
, uint_t quadlet_count
,
1714 TNF_PROBE_0_DEBUG(h1394_phy_packet_enter
, S1394_TNF_SL_STACK
, "");
1716 /* This interface is not yet implemented */
1717 TNF_PROBE_1_DEBUG(h1394_phy_packet
, S1394_TNF_SL_STACK
, "",
1718 tnf_string
, msg
, "h1394_phy_packet: Received");
1720 TNF_PROBE_0_DEBUG(h1394_phy_packet_exit
, S1394_TNF_SL_STACK
, "");
1724 * Function: h1394_error_detected()
1725 * Input(s): sl_private The HAL "handle" returned by
1727 * type The type of error the HAL detected
1728 * arg Pointer to any extra information
1732 * Description: h1394_error_detected() is used by the HAL to report errors
1733 * to the 1394 Software Framework.
1736 h1394_error_detected(void *sl_private
, h1394_error_t type
, void *arg
)
1739 uint_t hal_node_num
;
1740 uint_t IRM_node_num
;
1742 TNF_PROBE_0_DEBUG(h1394_error_detected_enter
, S1394_TNF_SL_STACK
, "");
1744 hal
= (s1394_hal_t
*)sl_private
;
1747 case H1394_LOCK_RESP_ERR
:
1748 TNF_PROBE_1(h1394_error_detected
, S1394_TNF_SL_ERROR
, "",
1749 tnf_string
, msg
, "Lock response error");
1750 /* If we are the IRM, then initiate a bus reset */
1751 mutex_enter(&hal
->topology_tree_mutex
);
1752 hal_node_num
= IEEE1394_NODE_NUM(hal
->node_id
);
1753 IRM_node_num
= hal
->IRM_node
;
1754 mutex_exit(&hal
->topology_tree_mutex
);
1755 if (IRM_node_num
== hal_node_num
)
1756 s1394_initiate_hal_reset(hal
, NON_CRITICAL
);
1759 case H1394_POSTED_WR_ERR
:
1760 TNF_PROBE_2(h1394_error_detected
, S1394_TNF_SL_ERROR
, "",
1761 tnf_string
, msg
, "Posted write error detected",
1762 tnf_opaque
, addr
, ((h1394_posted_wr_err_t
*)arg
)->addr
);
1765 case H1394_SELF_INITIATED_SHUTDOWN
:
1766 TNF_PROBE_1(h1394_error_detected
, S1394_TNF_SL_ERROR
, "",
1767 tnf_string
, msg
, "HAL self-initiated shutdown");
1768 s1394_hal_shutdown(hal
, B_FALSE
);
1771 case H1394_CYCLE_TOO_LONG
:
1772 /* Set a timer to become cycle master after 1 second */
1773 mutex_enter(&hal
->cm_timer_mutex
);
1774 hal
->cm_timer_set
= B_TRUE
;
1775 mutex_exit(&hal
->cm_timer_mutex
);
1776 hal
->cm_timer
= timeout(s1394_cycle_too_long_callback
, hal
,
1777 drv_usectohz(CYCLE_MASTER_TIMER
* 1000));
1779 TNF_PROBE_1(h1394_error_detected
, S1394_TNF_SL_ERROR
, "",
1780 tnf_string
, msg
, "Isochronous cycle too long error");
1784 TNF_PROBE_2(h1394_error_detected
, S1394_TNF_SL_ERROR
, "",
1785 tnf_string
, msg
, "Unknown error type received",
1786 tnf_uint
, type
, type
);
1790 TNF_PROBE_0_DEBUG(h1394_error_detected_exit
, S1394_TNF_SL_STACK
, "");