5255 uts shouldn't open-code ISP2
[illumos-gate.git] / usr / src / uts / common / io / 1394 / h1394.c
blob09b888ee45000ef9227118e8887d8405dfce7087
1 /*
2 * CDDL HEADER START
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.
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]
20 * CDDL HEADER END
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * h1394.c
31 * 1394 Services Layer HAL Interface
32 * Contains all of the routines that define the HAL to Services Layer
33 * interface
36 #include <sys/conf.h>
37 #include <sys/ddi.h>
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>
43 #include <sys/kmem.h>
44 #include <sys/thread.h>
45 #include <sys/proc.h>
46 #include <sys/disp.h>
47 #include <sys/time.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
67 * Output(s):
69 * Description: h1394_init() is called by the HAL's _init function and is
70 * used to set up the nexus bus ops.
72 int
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, "");
83 return (0);
87 * Function: h1394_fini()
88 * Input(s): modlp The structure containing all of the
89 * HAL's relevant information
91 * Output(s):
93 * Description: h1394_fini() is called by the HAL's _fini function and is
94 * used to NULL out the nexus bus ops.
96 void
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
115 * attach() call
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)
128 s1394_hal_t *hal;
129 int ret;
130 char buf[32];
131 uint_t cmd_size;
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,
145 "");
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,
152 "");
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,
222 "");
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,
264 "");
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,
294 "");
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,
307 "");
308 return (DDI_FAILURE);
311 /* Initialize the IRM node ID - "-1" means invalid, undetermined */
312 hal->IRM_node = -1;
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;
325 } else {
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
342 * h1394_attach()
343 * cmd The ddi_detach_cmd_t that tells us
344 * if this is a SUSPEND or a regular
345 * detach() call
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)
357 s1394_hal_t *hal;
359 TNF_PROBE_0_DEBUG(h1394_detach_enter, S1394_TNF_SL_STACK, "");
361 hal = (s1394_hal_t *)(*sl_private);
363 switch (cmd) {
364 case DDI_DETACH:
365 /* Clean up before leaving */
366 s1394_cleanup_for_detach(hal, H1394_CLEANUP_LEVEL7);
367 /* NULL out the HAL "handle" */
368 *sl_private = NULL;
369 break;
371 case DDI_SUSPEND:
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;
376 break;
378 default:
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
393 * h1394_attach()
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
406 * parameter.
409 h1394_alloc_cmd(void *sl_private, uint_t flags, cmd1394_cmd_t **cmdp,
410 h1394_cmd_priv_t **hal_priv_ptr)
412 s1394_hal_t *hal;
413 s1394_cmd_priv_t *s_priv;
415 TNF_PROBE_0_DEBUG(h1394_alloc_cmd_enter, S1394_TNF_SL_ARREQ_STACK,
416 "");
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,
434 "");
435 return (DDI_SUCCESS);
439 * Function: h1394_free_cmd()
440 * Input(s): sl_private The HAL "handle" returned by
441 * h1394_attach()
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)
455 s1394_hal_t *hal;
456 s1394_cmd_priv_t *s_priv;
458 TNF_PROBE_0_DEBUG(h1394_free_cmd_enter, S1394_TNF_SL_ARREQ_STACK,
459 "");
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,
471 "");
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 */
479 *cmdp = NULL;
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,
485 "");
486 return (DDI_SUCCESS);
490 * Function: h1394_cmd_is_complete()
491 * Input(s): sl_private The HAL "handle" returned by
492 * h1394_attach()
493 * command_id Pointer to the command that has
494 * just completed
495 * cmd_type AT_RESP => AT response or ATREQ =
496 * AT request
497 * status Command's completion status
499 * Output(s): None
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.
507 void
508 h1394_cmd_is_complete(void *sl_private, cmd1394_cmd_t *command_id,
509 uint32_t cmd_type, int status)
511 s1394_hal_t *hal;
512 dev_info_t *dip;
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? */
520 switch (cmd_type) {
521 case H1394_AT_REQ:
522 s1394_atreq_cmd_complete(hal, command_id, status);
523 break;
525 case H1394_AT_RESP:
526 s1394_atresp_cmd_complete(hal, command_id, status);
527 break;
529 default:
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");
542 break;
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
552 * h1394_attach()
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.
561 void
562 h1394_bus_reset(void *sl_private, void **selfid_buf_addr)
564 s1394_hal_t *hal;
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;
575 } else {
576 mutex_exit(&hal->topology_tree_mutex);
577 return;
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--;
584 } else {
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);
590 } else {
591 hal->num_bus_reset_till_fail = NUM_BR_FAIL;
594 /* Reset the IRM node ID */
595 hal->IRM_node = -1;
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;
604 } else {
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
625 * h1394_attach()
626 * selfid_buf_addr Pointer to the Self ID buffer
627 * selfid_size The size of the filled part of the
628 * Self ID buffer
629 * node_id The local (host) node ID for the
630 * current generation
631 * generation_count The current generation number
633 * Output(s): None
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
639 * up the br_thread.
641 void
642 h1394_self_ids(void *sl_private, void *selfid_buf_addr, uint32_t selfid_size,
643 uint32_t node_id, uint32_t generation_count)
645 s1394_hal_t *hal;
646 int diameter;
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,
668 "");
669 return;
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;
678 } else {
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,
709 "");
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) !=
720 DDI_SUCCESS) {
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,
726 "");
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,
736 "");
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);
752 } else {
753 mutex_exit(&hal->cm_timer_mutex);
756 TNF_PROBE_0_DEBUG(h1394_self_ids_init_topology, S1394_TNF_SL_BR_STACK,
757 "");
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,
769 "");
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;
778 } else {
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,
802 "");
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,
810 "");
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;
841 } else {
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) ==
845 generation_count) {
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
866 * h1394_attach()
867 * req The incoming AR request
869 * Output(s): None
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
875 * response.
877 void
878 h1394_read_request(void *sl_private, cmd1394_cmd_t *req)
880 s1394_hal_t *hal;
881 s1394_cmd_priv_t *s_priv;
882 s1394_addr_space_blk_t *addr_blk;
883 dev_info_t *dip;
884 uint64_t end_of_request;
885 uint32_t offset;
886 size_t cmd_length;
887 uchar_t *bufp_addr;
888 uchar_t *begin_ptr;
889 uchar_t *end_ptr;
890 uchar_t *tmp_ptr;
891 void (*recv_read_req)(cmd1394_cmd_t *);
893 TNF_PROBE_0_DEBUG(h1394_read_request_enter, S1394_TNF_SL_ARREQ_STACK,
894 "");
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++;
907 break;
909 case CMD1394_ASYNCH_RD_BLOCK:
910 cmd_length = req->cmd_u.b.blk_length;
911 hal->hal_kstats->arreq_blk_rd++;
912 break;
914 default:
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, "");
929 return;
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, "");
949 return;
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, "");
961 return;
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, "");
972 return;
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, "");
985 return;
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);
997 break;
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,
1005 cmd_length);
1006 /* Update b_wptr to refelect the new data */
1007 req->cmd_u.b.data_block->b_wptr = end_ptr;
1008 } else {
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, "");
1026 return;
1028 break;
1030 default:
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, "");
1048 return;
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
1063 * HAL.
1065 if (recv_read_req != NULL) {
1066 TNF_PROBE_0_DEBUG(h1394_read_request_do_callback,
1067 S1394_TNF_SL_ARREQ_STACK, "");
1068 recv_read_req(req);
1069 } else {
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, "");
1074 return;
1077 TNF_PROBE_0_DEBUG(h1394_read_request_exit, S1394_TNF_SL_ARREQ_STACK,
1078 "");
1082 * Function: h1394_write_request()
1083 * Input(s): sl_private The HAL "handle" returned by
1084 * h1394_attach()
1085 * req The incoming AR request
1087 * Output(s): None
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
1093 * response.
1095 void
1096 h1394_write_request(void *sl_private, cmd1394_cmd_t *req)
1098 s1394_hal_t *hal;
1099 s1394_cmd_priv_t *s_priv;
1100 h1394_cmd_priv_t *h_priv;
1101 s1394_addr_space_blk_t *addr_blk;
1102 dev_info_t *dip;
1103 uint32_t offset;
1104 size_t cmd_length;
1105 uchar_t *bufp_addr;
1106 uchar_t *begin_ptr;
1107 uchar_t *end_ptr;
1108 uchar_t *tmp_ptr;
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,
1115 "");
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++;
1128 break;
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;
1134 break;
1136 default:
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, "");
1151 return;
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;
1197 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, "");
1212 return;
1213 } else {
1214 (void) s1394_send_response(hal, req);
1215 TNF_PROBE_0_DEBUG(h1394_write_request_exit,
1216 S1394_TNF_SL_ARREQ_STACK, "");
1217 return;
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);
1229 break;
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,
1237 cmd_length);
1238 } else {
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, "");
1256 return;
1258 break;
1260 default:
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, "");
1278 return;
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
1296 * HAL.
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);
1302 } else {
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, "");
1307 return;
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
1317 * h1394_attach()
1318 * req The incoming AR request
1320 * Output(s): None
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
1326 * response.
1328 void
1329 h1394_lock_request(void *sl_private, cmd1394_cmd_t *req)
1331 s1394_hal_t *hal;
1332 s1394_cmd_priv_t *s_priv;
1333 s1394_addr_space_blk_t *addr_blk;
1334 dev_info_t *dip;
1335 uint64_t end_of_request;
1336 uint32_t offset;
1337 uchar_t *bufp_addr;
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, "");
1365 return;
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++;
1374 break;
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++;
1380 break;
1382 default:
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, "");
1400 return;
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, "");
1410 return;
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, "");
1421 return;
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) {
1430 uint32_t old_value;
1431 uint32_t arg_value;
1432 uint32_t data_value;
1433 uint32_t new_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,
1439 IEEE1394_QUADLET);
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,
1448 IEEE1394_QUADLET);
1449 req->cmd_u.l32.old_value = old_value;
1450 break;
1452 case CMD1394_LOCK_COMPARE_SWAP:
1453 /* 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,
1458 (void *)bufp_addr,
1459 IEEE1394_QUADLET);
1461 req->cmd_u.l32.old_value = old_value;
1462 break;
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,
1471 IEEE1394_QUADLET);
1472 req->cmd_u.l32.old_value = old_value;
1473 break;
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,
1482 IEEE1394_QUADLET);
1483 req->cmd_u.l32.old_value = old_value;
1484 break;
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,
1494 (void *)bufp_addr,
1495 IEEE1394_QUADLET);
1497 req->cmd_u.l32.old_value = old_value;
1498 break;
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;
1505 } else {
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,
1511 IEEE1394_QUADLET);
1512 req->cmd_u.l32.old_value = old_value;
1513 break;
1515 default:
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, "");
1525 return;
1527 } else {
1528 /* Handling for the 8-byte (64-bit) lock requests */
1529 uint64_t old_value;
1530 uint64_t arg_value;
1531 uint64_t data_value;
1532 uint64_t new_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,
1538 IEEE1394_OCTLET);
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,
1547 IEEE1394_OCTLET);
1548 req->cmd_u.l64.old_value = old_value;
1549 break;
1551 case CMD1394_LOCK_COMPARE_SWAP:
1552 /* 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,
1557 (void *)bufp_addr,
1558 IEEE1394_OCTLET);
1560 req->cmd_u.l64.old_value = old_value;
1561 break;
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,
1570 IEEE1394_OCTLET);
1571 req->cmd_u.l64.old_value = old_value;
1572 break;
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,
1581 IEEE1394_OCTLET);
1582 req->cmd_u.l64.old_value = old_value;
1583 break;
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,
1593 (void *)bufp_addr,
1594 IEEE1394_OCTLET);
1596 req->cmd_u.l64.old_value = old_value;
1597 break;
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;
1604 } else {
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,
1610 IEEE1394_OCTLET);
1611 req->cmd_u.l64.old_value = old_value;
1612 break;
1614 default:
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, "");
1624 return;
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
1640 * HAL.
1642 if (recv_lock_req != NULL) {
1643 TNF_PROBE_0_DEBUG(h1394_lock_request_do_callback,
1644 S1394_TNF_SL_ARREQ_STACK, "");
1645 recv_lock_req(req);
1646 } else {
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, "");
1651 return;
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
1661 * h1394_attach()
1662 * cmd ioctl cmd
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,
1675 int *rval_p)
1677 int status;
1679 TNF_PROBE_0_DEBUG(h1394_ioctl_enter, S1394_TNF_SL_IOCTL_STACK, "");
1681 if ((cmd & DEVCTL_IOC) != DEVCTL_IOC)
1682 return (EINVAL);
1684 status = s1394_ioctl((s1394_hal_t *)sl_private, cmd, arg, mode,
1685 cred_p, rval_p);
1687 TNF_PROBE_1_DEBUG(h1394_ioctl_exit, S1394_TNF_SL_IOCTL_STACK, "",
1688 tnf_int, status, status);
1689 return (status);
1693 * Function: h1394_phy_packet()
1694 * Input(s): sl_private The HAL "handle" returned by
1695 * h1394_attach()
1696 * packet_data Pointer to a buffer of packet data
1697 * quadlet_count Length of the buffer
1698 * timestamp Timestamp indicating time of arrival
1700 * Output(s): None
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.
1709 /* ARGSUSED */
1710 void
1711 h1394_phy_packet(void *sl_private, uint32_t *packet_data, uint_t quadlet_count,
1712 uint_t timestamp)
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
1726 * h1394_attach()
1727 * type The type of error the HAL detected
1728 * arg Pointer to any extra information
1730 * Output(s): None
1732 * Description: h1394_error_detected() is used by the HAL to report errors
1733 * to the 1394 Software Framework.
1735 void
1736 h1394_error_detected(void *sl_private, h1394_error_t type, void *arg)
1738 s1394_hal_t *hal;
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;
1746 switch (type) {
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);
1757 break;
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);
1763 break;
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);
1769 break;
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");
1781 break;
1783 default:
1784 TNF_PROBE_2(h1394_error_detected, S1394_TNF_SL_ERROR, "",
1785 tnf_string, msg, "Unknown error type received",
1786 tnf_uint, type, type);
1787 break;
1790 TNF_PROBE_0_DEBUG(h1394_error_detected_exit, S1394_TNF_SL_STACK, "");