xref: /illumos-gate/usr/src/uts/common/io/1394/s1394_fa.c (revision 2570281cf351044b6936651ce26dbe1f801dcbd8)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  * s1394_fa.c
297c478bd9Sstevel@tonic-gate  *    1394 Services Layer Fixed Address Support Routines
307c478bd9Sstevel@tonic-gate  *    Currently used for FCP support.
317c478bd9Sstevel@tonic-gate  */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include <sys/conf.h>
347c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
357c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
367c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
377c478bd9Sstevel@tonic-gate #include <sys/types.h>
387c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #include <sys/1394/t1394.h>
417c478bd9Sstevel@tonic-gate #include <sys/1394/s1394.h>
427c478bd9Sstevel@tonic-gate #include <sys/1394/h1394.h>
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate static void s1394_fa_completion_cb(cmd1394_cmd_t *cmd);
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate /*
477c478bd9Sstevel@tonic-gate  * s1394_fa_claim_addr_blk()
487c478bd9Sstevel@tonic-gate  *    Claim fixed address block.
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate int
s1394_fa_claim_addr(s1394_hal_t * hal,s1394_fa_type_t type,s1394_fa_descr_t * descr)517c478bd9Sstevel@tonic-gate s1394_fa_claim_addr(s1394_hal_t *hal, s1394_fa_type_t type,
527c478bd9Sstevel@tonic-gate     s1394_fa_descr_t *descr)
537c478bd9Sstevel@tonic-gate {
547c478bd9Sstevel@tonic-gate 	t1394_alloc_addr_t	addr;
557c478bd9Sstevel@tonic-gate 	s1394_fa_hal_t		*falp = &hal->hal_fa[type];
567c478bd9Sstevel@tonic-gate 	int			ret;
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate 	/* Might have been claimed already */
597c478bd9Sstevel@tonic-gate 	if (falp->fal_addr_blk != NULL) {
607c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
617c478bd9Sstevel@tonic-gate 	}
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate 	falp->fal_descr = descr;
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate 	bzero(&addr, sizeof (addr));
667c478bd9Sstevel@tonic-gate 	addr.aa_type = T1394_ADDR_FIXED;
677c478bd9Sstevel@tonic-gate 	addr.aa_address = descr->fd_addr;
687c478bd9Sstevel@tonic-gate 	addr.aa_length = descr->fd_size;
697c478bd9Sstevel@tonic-gate 	addr.aa_enable = descr->fd_enable;
707c478bd9Sstevel@tonic-gate 	addr.aa_evts = descr->fd_evts;
717c478bd9Sstevel@tonic-gate 	addr.aa_arg = hal;
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate 	ret = s1394_claim_addr_blk(hal, &addr);
74*2570281cSToomas Soome 	if (ret == DDI_SUCCESS) {
757c478bd9Sstevel@tonic-gate 		falp->fal_addr_blk = (s1394_addr_space_blk_t *)addr.aa_hdl;
767c478bd9Sstevel@tonic-gate 	}
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 	return (ret);
797c478bd9Sstevel@tonic-gate }
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate /*
827c478bd9Sstevel@tonic-gate  * s1394_fa_free_addr_blk()
837c478bd9Sstevel@tonic-gate  *    Free fixed address block.
847c478bd9Sstevel@tonic-gate  */
857c478bd9Sstevel@tonic-gate void
s1394_fa_free_addr(s1394_hal_t * hal,s1394_fa_type_t type)867c478bd9Sstevel@tonic-gate s1394_fa_free_addr(s1394_hal_t *hal, s1394_fa_type_t type)
877c478bd9Sstevel@tonic-gate {
887c478bd9Sstevel@tonic-gate 	s1394_fa_hal_t		*falp = &hal->hal_fa[type];
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 	/* Might have been freed already */
917c478bd9Sstevel@tonic-gate 	if (falp->fal_addr_blk != NULL) {
92*2570281cSToomas Soome 		(void) s1394_free_addr_blk(hal, falp->fal_addr_blk);
937c478bd9Sstevel@tonic-gate 		falp->fal_addr_blk = NULL;
947c478bd9Sstevel@tonic-gate 	}
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate /*
987c478bd9Sstevel@tonic-gate  * s1394_fa_list_add()
997c478bd9Sstevel@tonic-gate  *    Add target to the list of FA clients.
1007c478bd9Sstevel@tonic-gate  *    target_list_rwlock should be writer-held.
1017c478bd9Sstevel@tonic-gate  */
1027c478bd9Sstevel@tonic-gate void
s1394_fa_list_add(s1394_hal_t * hal,s1394_target_t * target,s1394_fa_type_t type)1037c478bd9Sstevel@tonic-gate s1394_fa_list_add(s1394_hal_t *hal, s1394_target_t *target,
1047c478bd9Sstevel@tonic-gate     s1394_fa_type_t type)
1057c478bd9Sstevel@tonic-gate {
1067c478bd9Sstevel@tonic-gate 	s1394_fa_hal_t	*fal = &hal->hal_fa[type];
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	if (fal->fal_head == NULL) {
1097c478bd9Sstevel@tonic-gate 		ASSERT(fal->fal_tail == NULL);
1107c478bd9Sstevel@tonic-gate 		fal->fal_head = fal->fal_tail = target;
1117c478bd9Sstevel@tonic-gate 	} else {
1127c478bd9Sstevel@tonic-gate 		fal->fal_tail->target_fa[type].fat_next = target;
1137c478bd9Sstevel@tonic-gate 		fal->fal_tail = target;
1147c478bd9Sstevel@tonic-gate 	}
1157c478bd9Sstevel@tonic-gate 	fal->fal_gen++;
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate /*
1197c478bd9Sstevel@tonic-gate  * s1394_fa_list_remove()
1207c478bd9Sstevel@tonic-gate  *    Remove target from the list of FA clients.
1217c478bd9Sstevel@tonic-gate  *    target_list_rwlock should be writer-held.
1227c478bd9Sstevel@tonic-gate  */
1237c478bd9Sstevel@tonic-gate int
s1394_fa_list_remove(s1394_hal_t * hal,s1394_target_t * target,s1394_fa_type_t type)1247c478bd9Sstevel@tonic-gate s1394_fa_list_remove(s1394_hal_t *hal, s1394_target_t *target,
1257c478bd9Sstevel@tonic-gate     s1394_fa_type_t type)
1267c478bd9Sstevel@tonic-gate {
1277c478bd9Sstevel@tonic-gate 	s1394_fa_hal_t	*fal = &hal->hal_fa[type];
1287c478bd9Sstevel@tonic-gate 	s1394_target_t	*curp, **nextp, *prevp = NULL;
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	for (nextp = &fal->fal_head; (curp = *nextp) != NULL; ) {
1317c478bd9Sstevel@tonic-gate 		if (curp == target) {
1327c478bd9Sstevel@tonic-gate 			*nextp = target->target_fa[type].fat_next;
1337c478bd9Sstevel@tonic-gate 			if (target == fal->fal_tail) {
1347c478bd9Sstevel@tonic-gate 				fal->fal_tail = prevp;
1357c478bd9Sstevel@tonic-gate 			}
1367c478bd9Sstevel@tonic-gate 			fal->fal_gen++;
1377c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
1387c478bd9Sstevel@tonic-gate 		}
1397c478bd9Sstevel@tonic-gate 		nextp = &curp->target_fa[type].fat_next;
1407c478bd9Sstevel@tonic-gate 		prevp = curp;
1417c478bd9Sstevel@tonic-gate 	}
1427c478bd9Sstevel@tonic-gate 	return (DDI_FAILURE);
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate /*
1467c478bd9Sstevel@tonic-gate  * s1394_fa_list_is_empty()
1477c478bd9Sstevel@tonic-gate  *    Returns B_TRUE if the target list is empty
1487c478bd9Sstevel@tonic-gate  *    target_list_rwlock should be at least reader-held.
1497c478bd9Sstevel@tonic-gate  */
1507c478bd9Sstevel@tonic-gate boolean_t
s1394_fa_list_is_empty(s1394_hal_t * hal,s1394_fa_type_t type)1517c478bd9Sstevel@tonic-gate s1394_fa_list_is_empty(s1394_hal_t *hal, s1394_fa_type_t type)
1527c478bd9Sstevel@tonic-gate {
1537c478bd9Sstevel@tonic-gate 	s1394_fa_hal_t	*fal = &hal->hal_fa[type];
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	return (fal->fal_head == NULL);
1567c478bd9Sstevel@tonic-gate }
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate /*
1597c478bd9Sstevel@tonic-gate  * s1394_fa_list_gen()
1607c478bd9Sstevel@tonic-gate  *    Returns list generation number.
1617c478bd9Sstevel@tonic-gate  *    target_list_rwlock should be at least reader-held.
1627c478bd9Sstevel@tonic-gate  */
1637c478bd9Sstevel@tonic-gate uint_t
s1394_fa_list_gen(s1394_hal_t * hal,s1394_fa_type_t type)1647c478bd9Sstevel@tonic-gate s1394_fa_list_gen(s1394_hal_t *hal, s1394_fa_type_t type)
1657c478bd9Sstevel@tonic-gate {
1667c478bd9Sstevel@tonic-gate 	s1394_fa_hal_t	*fal = &hal->hal_fa[type];
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 	return (fal->fal_gen);
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate /*
1727c478bd9Sstevel@tonic-gate  * s1394_fa_init_cmd()
1737c478bd9Sstevel@tonic-gate  *    initialize the FA specific part of the command
1747c478bd9Sstevel@tonic-gate  */
1757c478bd9Sstevel@tonic-gate void
s1394_fa_init_cmd(s1394_cmd_priv_t * s_priv,s1394_fa_type_t type)1767c478bd9Sstevel@tonic-gate s1394_fa_init_cmd(s1394_cmd_priv_t *s_priv, s1394_fa_type_t type)
1777c478bd9Sstevel@tonic-gate {
1787c478bd9Sstevel@tonic-gate 	s_priv->cmd_ext_type = S1394_CMD_EXT_FA;
1797c478bd9Sstevel@tonic-gate 	s_priv->cmd_ext.fa.type = type;
1807c478bd9Sstevel@tonic-gate }
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate /*
1837c478bd9Sstevel@tonic-gate  * s1394_fa_convert_cmd()
1847c478bd9Sstevel@tonic-gate  *    convert an FA command (with a relative address) to a regular 1394 command
1857c478bd9Sstevel@tonic-gate  */
1867c478bd9Sstevel@tonic-gate void
s1394_fa_convert_cmd(s1394_hal_t * hal,cmd1394_cmd_t * cmd)1877c478bd9Sstevel@tonic-gate s1394_fa_convert_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd)
1887c478bd9Sstevel@tonic-gate {
1897c478bd9Sstevel@tonic-gate 	s1394_fa_cmd_priv_t *fa_priv = S1394_GET_FA_CMD_PRIV(cmd);
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	cmd->cmd_addr += hal->hal_fa[fa_priv->type].fal_descr->fd_conv_base;
1927c478bd9Sstevel@tonic-gate 	fa_priv->completion_callback = cmd->completion_callback;
1937c478bd9Sstevel@tonic-gate 	fa_priv->callback_arg = cmd->cmd_callback_arg;
1947c478bd9Sstevel@tonic-gate 	cmd->completion_callback = s1394_fa_completion_cb;
1957c478bd9Sstevel@tonic-gate 	cmd->cmd_callback_arg = hal;
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate /*
1997c478bd9Sstevel@tonic-gate  * s1394_fa_restore_cmd()
2007c478bd9Sstevel@tonic-gate  *    opposite of s1394_fa_convert_cmd(): regular 1394 command to FA command
2017c478bd9Sstevel@tonic-gate  */
2027c478bd9Sstevel@tonic-gate void
s1394_fa_restore_cmd(s1394_hal_t * hal,cmd1394_cmd_t * cmd)2037c478bd9Sstevel@tonic-gate s1394_fa_restore_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd)
2047c478bd9Sstevel@tonic-gate {
2057c478bd9Sstevel@tonic-gate 	s1394_fa_cmd_priv_t *fa_priv = S1394_GET_FA_CMD_PRIV(cmd);
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	ASSERT(fa_priv->type < S1394_FA_NTYPES);
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	cmd->cmd_addr -= hal->hal_fa[fa_priv->type].fal_descr->fd_conv_base;
2107c478bd9Sstevel@tonic-gate 	cmd->completion_callback = fa_priv->completion_callback;
2117c478bd9Sstevel@tonic-gate 	cmd->cmd_callback_arg = fa_priv->callback_arg;
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate /*
2157c478bd9Sstevel@tonic-gate  * s1394_fa_check_restore_cmd()
2167c478bd9Sstevel@tonic-gate  *    if a command has FA extension, do s1394_fa_restore_cmd()
2177c478bd9Sstevel@tonic-gate  */
2187c478bd9Sstevel@tonic-gate void
s1394_fa_check_restore_cmd(s1394_hal_t * hal,cmd1394_cmd_t * cmd)2197c478bd9Sstevel@tonic-gate s1394_fa_check_restore_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd)
2207c478bd9Sstevel@tonic-gate {
2217c478bd9Sstevel@tonic-gate 	s1394_cmd_priv_t *s_priv = S1394_GET_CMD_PRIV(cmd);
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	if (s_priv->cmd_ext_type == S1394_CMD_EXT_FA) {
2247c478bd9Sstevel@tonic-gate 		s1394_fa_restore_cmd(hal, cmd);
2257c478bd9Sstevel@tonic-gate 	}
2267c478bd9Sstevel@tonic-gate }
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate /*
2297c478bd9Sstevel@tonic-gate  * s1394_fa_completion_cb()
2307c478bd9Sstevel@tonic-gate  *    FA completion callback: restore command and call original callback
2317c478bd9Sstevel@tonic-gate  */
2327c478bd9Sstevel@tonic-gate static void
s1394_fa_completion_cb(cmd1394_cmd_t * cmd)2337c478bd9Sstevel@tonic-gate s1394_fa_completion_cb(cmd1394_cmd_t *cmd)
2347c478bd9Sstevel@tonic-gate {
2357c478bd9Sstevel@tonic-gate 	s1394_hal_t	*hal = cmd->cmd_callback_arg;
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	s1394_fa_restore_cmd(hal, cmd);
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 	if (cmd->completion_callback) {
2407c478bd9Sstevel@tonic-gate 		cmd->completion_callback(cmd);
2417c478bd9Sstevel@tonic-gate 	}
2427c478bd9Sstevel@tonic-gate }
243