/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1999-2000 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* 1394 Services Layer CSR and Config ROM Routines
* Contains all of the CSR callback routines for various required
* CSR registers. Also contains routines for their initialization
* and destruction, as well as routines to handle the processing
* of Config ROM update requests.
*/
#include <sys/tnf_probe.h>
/*
* s1394_setup_CSR_space()
* setups up the local host's CSR registers and callback routines.
*/
int
{
int result;
"");
/*
* Although they are not freed up in this routine, if
* one of the s1394_claim_addr_blk() routines fails,
* all of the previously successful claims will be
* freed up in s1394_destroy_addr_space() upon returning
* DDI_FAILURE from this routine.
*/
/*
* STATE_CLEAR
* see IEEE 1394-1995, Section 8.3.2.2.1 or
* IEEE 1212-1994, Section 7.4.1
*/
if (result != DDI_SUCCESS) {
"STATE_CLEAR: CSR setup failed");
S1394_TNF_SL_CSR_STACK, "");
return (DDI_FAILURE);
}
/*
* STATE_SET
* see IEEE 1394-1995, Section 8.3.2.2.2 or
* IEEE 1212-1994, Section 7.4.2
*/
if (result != DDI_SUCCESS) {
"STATE_SET: CSR setup failed");
S1394_TNF_SL_CSR_STACK, "");
return (DDI_FAILURE);
}
/*
* NODE_IDS
* see IEEE 1394-1995, Section 8.3.2.2.3 or
* IEEE 1212-1994, Section 7.4.3
*/
if (result != DDI_SUCCESS) {
"NODE_IDS: CSR setup failed");
S1394_TNF_SL_CSR_STACK, "");
return (DDI_FAILURE);
}
/*
* RESET_START
* see IEEE 1394-1995, Section 8.3.2.2.4 or
* IEEE 1212-1994, Section 7.4.4
*/
if (result != DDI_SUCCESS) {
"RESET_START: CSR setup failed");
S1394_TNF_SL_CSR_STACK, "");
return (DDI_FAILURE);
}
/*
* SPLIT_TIMEOUT
* see IEEE 1394-1995, Section 8.3.2.2.6 or
* IEEE 1212-1994, Section 7.4.7
*/
if (result != DDI_SUCCESS) {
"SPLIT_TIMEOUT: CSR setup failed");
S1394_TNF_SL_CSR_STACK, "");
return (DDI_FAILURE);
}
/*
* ARGUMENT_HI and ARGUMENT_LO
* see IEEE 1394-1995, Section 8.3.2.2.7 or
* IEEE 1212-1994, Section 7.4.8
*/
if (result != DDI_SUCCESS) {
"ARGUMENT registers: CSR setup failed");
S1394_TNF_SL_CSR_STACK, "");
return (DDI_FAILURE);
}
/*
* TEST_START and TEST_STATUS
* see IEEE 1394-1995, Section 8.3.2.2.7 or
* IEEE 1212-1994, Section 7.4.9 - 7.4.10
*/
if (result != DDI_SUCCESS) {
"TEST registers: CSR setup failed");
S1394_TNF_SL_CSR_STACK, "");
return (DDI_FAILURE);
}
/*
* INTERRUPT_TARGET and INTERRUPT_MASK
* see IEEE 1394-1995, Section 8.3.2.2.9 or
* IEEE 1212-1994, Section 7.4.15 - 7.4.16
*/
if (result != DDI_SUCCESS) {
"INTERRUPT registers: CSR setup failed");
S1394_TNF_SL_CSR_STACK, "");
return (DDI_FAILURE);
}
/*
* CLOCK_VALUE, CLOCK_TICK_PERIOD, CLOCK_INFO, etc.
* see IEEE 1394-1995, Section 8.3.2.2.10 or
* IEEE 1212-1994, Section 7.4.17 - 7.4.20
*/
if (result != DDI_SUCCESS) {
"CLOCK registers: CSR setup failed");
S1394_TNF_SL_CSR_STACK, "");
return (DDI_FAILURE);
}
/*
* MESSAGE_REQUEST and MESSAGE_RESPONSE
* see IEEE 1394-1995, Section 8.3.2.2.11 or
* IEEE 1212-1994, Section 7.4.21
*/
if (result != DDI_SUCCESS) {
"MESSAGE registers: CSR setup failed");
S1394_TNF_SL_CSR_STACK, "");
return (DDI_FAILURE);
}
/*
* CYCLE_TIME
* see IEEE 1394-1995, Section 8.3.2.3.1
*/
if (result != DDI_SUCCESS) {
"CYCLE_TIME: CSR setup failed");
S1394_TNF_SL_CSR_STACK, "");
return (DDI_FAILURE);
}
/*
* BUS_TIME
* see IEEE 1394-1995, Section 8.3.2.3.2
*/
if (result != DDI_SUCCESS) {
"BUS_TIME: CSR setup failed");
S1394_TNF_SL_CSR_STACK, "");
return (DDI_FAILURE);
}
/*
* BUSY_TIMEOUT
* see IEEE 1394-1995, Section 8.3.2.3.5
*/
if (result != DDI_SUCCESS) {
"BUSY_TIMEOUT: CSR setup failed");
S1394_TNF_SL_CSR_STACK, "");
return (DDI_FAILURE);
}
/*
* BUS_MANAGER_ID
* BANDWIDTH_AVAILABLE
* CHANNELS_AVAILABLE
* see IEEE 1394-1995, Section 8.3.2.3.6 - 8.3.2.3.8
*/
if (result != DDI_SUCCESS) {
"IRM registers: CSR setup failed");
S1394_TNF_SL_CSR_STACK, "");
return (DDI_FAILURE);
}
/*
* Reserved for Configuration ROM
* see IEEE 1394-1995, Section 8.3.2.5.3
*/
if (result != DDI_SUCCESS) {
"Unable to reserve Config ROM");
S1394_TNF_SL_CSR_STACK, "");
return (DDI_FAILURE);
}
/*
* TOPOLOGY_MAP
* see IEEE 1394-1995, Section 8.3.2.4.1
*/
KM_SLEEP);
if (result != DDI_SUCCESS) {
"TOPOLOGY_MAP: CSR setup failed");
S1394_TNF_SL_CSR_STACK, "");
return (DDI_FAILURE);
}
/* Set up the block so that we free kmem_bufp at detach */
/*
* Reserve the SPEED_MAP
* see IEEE 1394-1995, Section 8.3.2.4.1
* (obsoleted in P1394A)
*/
if (result != DDI_SUCCESS) {
"SPEED_MAP: CSR setup failed");
S1394_TNF_SL_CSR_STACK, "");
return (DDI_FAILURE);
}
/*
* Reserved - Boundary between reserved Serial Bus
* dependent registers and other CSR register space.
* See IEEE 1394-1995, Table 8-4 for this address.
*
* This quadlet is reserved as a way of preventing
* the inadvertant allocation of a part of CSR space
* that will likely be used by future specifications
*/
if (result != DDI_SUCCESS) {
"Unable to reserve boundary quadlet");
"stacktrace 1394 s1394", "");
return (DDI_FAILURE);
}
"");
return (DDI_SUCCESS);
}
/*
* s1394_CSR_state_clear()
* handles all requests to the STATE_CLEAR CSR register. It enforces
* that certain bits that can be twiddled only by a given node (IRM or
* Bus Manager).
*/
static void
{
int result;
"");
/* Register offset */
/* Verify that request is quadlet aligned */
if ((offset & 0x3) != 0) {
S1394_TNF_SL_CSR_STACK, "");
return;
}
/* Only writes from IRM or Bus Mgr allowed (in some cases) */
else
case CMD1394_ASYNCH_RD_QUAD:
/*
* The csr_read() call can return DDI_FAILURE if the HAL
* is shutdown or if the register at "offset" is
* unimplemented. But although the STATE_CLEAR register
* is required to be implemented and readable, we will
* return IEEE1394_RESP_ADDRESS_ERROR in the response if
* we ever see this error.
*/
if (result == DDI_SUCCESS) {
} else {
}
break;
case CMD1394_ASYNCH_WR_QUAD:
if (is_from != should_be_from) {
}
/* DREQ bit - disabling DREQ can come from anyone */
if (data & IEEE1394_CSR_STATE_DREQ) {
hal->disable_requests_bit = 0;
}
/* ABDICATE bit */
if (data & IEEE1394_CSR_STATE_ABDICATE) {
hal->abdicate_bus_mgr_bit = 0;
}
/*
* The csr_write() call can return DDI_FAILURE if the HAL
* is shutdown or if the register at "offset" is
* unimplemented. But although the STATE_CLEAR register
* is required to be implemented and writeable, we will
* return IEEE1394_RESP_ADDRESS_ERROR in the response if
* we ever see this error.
*/
if (result == DDI_SUCCESS) {
} else {
}
break;
default:
}
"");
}
/*
* s1394_CSR_state_set()
* handles all requests to the STATE_SET CSR register. It enforces that
* certain bits that can be twiddled only by a given node (IRM or Bus
* Manager).
*/
static void
{
int result;
"");
/* Register offset */
/* Verify that request is quadlet aligned */
if ((offset & 0x3) != 0) {
S1394_TNF_SL_CSR_STACK, "");
return;
}
/* Only writes from IRM or Bus Mgr allowed (in some cases) */
else
case CMD1394_ASYNCH_WR_QUAD:
/* & must be root to have bit set */
if ((is_from != should_be_from) ||
}
if (is_from != should_be_from) {
} else if (data & IEEE1394_CSR_STATE_DREQ) {
}
/* ABDICATE bit */
if (data & IEEE1394_CSR_STATE_ABDICATE) {
}
/*
* The csr_write() call can return DDI_FAILURE if the HAL
* is shutdown or if the register at "offset" is
* unimplemented. But although the STATE_SET register
* is required to be implemented and writeable, we will
* return IEEE1394_RESP_ADDRESS_ERROR in the response if
* we ever see this error.
*/
if (result == DDI_SUCCESS) {
} else {
}
break;
default:
}
"");
}
/*
* s1394_CSR_node_ids()
* handles all requests to the NODE_IDS CSR register. It passes all
* requests to the common routine - s1394_common_CSR_routine().
*/
static void
{
}
/*
* s1394_CSR_reset_start()
* handles all requests to the RESET_START CSR register. Only write
* requests are legal, everything else gets a type_error response.
*/
static void
{
"");
/* RESET_START register offset */
/* Verify that request is quadlet aligned */
if ((offset & 0x3) != 0) {
S1394_TNF_SL_CSR_STACK, "");
return;
}
case CMD1394_ASYNCH_WR_QUAD:
/*
* The csr_write() call can return DDI_FAILURE if the HAL
* is shutdown or if the register at "offset" is
* unimplemented. Because we don't do any thing with
* the RESET_START register we will ignore failures and
* return IEEE1394_RESP_COMPLETE regardless.
*/
break;
default:
}
"");
}
/*
* s1394_CSR_split_timeout()
* handles all requests to the SPLIT_TIMEOUT CSR register. It passes all
* requests to the common routine - s1394_common_CSR_routine().
*/
static void
{
S1394_TNF_SL_CSR_STACK, "");
S1394_TNF_SL_CSR_STACK, "");
}
/*
* s1394_CSR_argument_regs()
* handles all requests to the ARGUMENT CSR registers. It passes all
* requests to the common routine - s1394_common_CSR_routine().
*/
static void
{
S1394_TNF_SL_CSR_STACK, "");
S1394_TNF_SL_CSR_STACK, "");
}
/*
* s1394_CSR_test_regs()
* handles all requests to the TEST CSR registers. It passes all requests
* to the common routine - s1394_common_CSR_routine().
*/
static void
{
S1394_TNF_SL_CSR_STACK, "");
/* TEST register offset */
/* TEST_STATUS is Read-Only */
} else {
}
S1394_TNF_SL_CSR_STACK, "");
}
/*
* s1394_CSR_interrupt_regs()
* handles all requests to the INTERRUPT CSR registers. It passes all
* requests to the common routine - s1394_common_CSR_routine().
*/
static void
{
S1394_TNF_SL_CSR_STACK, "");
S1394_TNF_SL_CSR_STACK, "");
}
/*
* s1394_CSR_clock_regs()
* handles all requests to the CLOCK CSR registers. It passes all
* requests to the common routine - s1394_common_CSR_routine().
*/
static void
{
S1394_TNF_SL_CSR_STACK, "");
S1394_TNF_SL_CSR_STACK, "");
}
/*
* s1394_CSR_message_regs()
* handles all requests to the MESSAGE CSR registers. It passes all
* requests to the common routine - s1394_common_CSR_routine().
*/
static void
{
S1394_TNF_SL_CSR_STACK, "");
S1394_TNF_SL_CSR_STACK, "");
}
/*
* s1394_CSR_cycle_time()
* handles all requests to the CYCLE_TIME CSR register.
*/
static void
{
int result;
S1394_TNF_SL_CSR_STACK, "");
/* CYCLE_TIME register offset */
/* Verify that request is quadlet aligned */
if ((offset & 0x3) != 0) {
S1394_TNF_SL_CSR_STACK, "");
return;
}
case CMD1394_ASYNCH_RD_QUAD:
/*
* The csr_read() call can return DDI_FAILURE if the HAL
* is shutdown or if the register at "offset" is
* unimplemented. But although the CYCLE_TIME register
* is required to be implemented on devices capable of
* providing isochronous services (like us), we will
* return IEEE1394_RESP_ADDRESS_ERROR in the response
* if we ever see this error.
*/
if (result == DDI_SUCCESS) {
} else {
}
break;
case CMD1394_ASYNCH_WR_QUAD:
/*
* The csr_write() call can return DDI_FAILURE if the HAL
* is shutdown or if the register at "offset" is
* unimplemented. But although the CYCLE_TIME register
* is required to be implemented on devices capable of
* providing isochronous services (like us), the effects
* of a write are "node-dependent" so we will return
* IEEE1394_RESP_ADDRESS_ERROR in the response if we
* ever see this error.
*/
if (result == DDI_SUCCESS) {
} else {
}
break;
default:
}
S1394_TNF_SL_CSR_STACK, "");
}
/*
* s1394_CSR_bus_time()
* handles all requests to the BUS_TIME CSR register. It enforces that
* only a broadcast write request from the IRM or Bus Manager can change
* its value.
*/
static void
{
int result;
/* BUS_TIME register offset */
/* Verify that request is quadlet aligned */
if ((offset & 0x3) != 0) {
S1394_TNF_SL_CSR_STACK, "");
return;
}
case CMD1394_ASYNCH_RD_QUAD:
/*
* The csr_read() call can return DDI_FAILURE if the HAL
* is shutdown or if the register at "offset" is
* unimplemented. But although the BUS_TIME register
* is required to be implemented by devices capable of
* being cycle master (like us), we will return
* IEEE1394_RESP_ADDRESS_ERROR in the response if we
* ever see this error.
*/
if (result == DDI_SUCCESS) {
} else {
}
break;
case CMD1394_ASYNCH_WR_QUAD:
/* Only broadcast writes from IRM or Bus Mgr allowed */
else
break;
}
/*
* The csr_write() call can return DDI_FAILURE if the HAL
* is shutdown or if the register at "offset" is
* unimplemented. But although the BUS_TIME register
* is required to be implemented on devices capable of
* being cycle master (like us), we will return
* IEEE1394_RESP_ADDRESS_ERROR in the response if we
* ever see this error.
*/
if (result == DDI_SUCCESS) {
} else {
}
break;
default:
}
}
/*
* s1394_CSR_busy_timeout()
* handles all requests to the BUSY_TIMEOUT CSR register. It passes all
* requests to the common routine - s1394_common_CSR_routine().
*/
static void
{
S1394_TNF_SL_CSR_STACK, "");
S1394_TNF_SL_CSR_STACK, "");
}
/*
* s1394_CSR_IRM_regs()
* handles all requests to the IRM registers, including BANDWIDTH_AVAILABLE,
* CHANNELS_AVAILABLE, and the BUS_MANAGER_ID. Only quadlet read and lock
* requests are allowed.
*/
static void
{
int result;
/* IRM register offset */
/* Verify that request is quadlet aligned */
if ((offset & 0x3) != 0) {
S1394_TNF_SL_CSR_STACK, "");
return;
}
case CMD1394_ASYNCH_RD_QUAD:
/*
* The csr_read() call can return DDI_FAILURE if the HAL
* is shutdown or if the register at "offset" is
* unimplemented. In many cases these registers will
* have been implemented in HW. We are not likely to ever
* receive this callback. If we do, though, we will
* return IEEE1394_RESP_ADDRESS_ERROR when we get an error
* and IEEE1394_RESP_COMPLETE for success.
*/
if (result == DDI_SUCCESS) {
} else {
}
break;
case CMD1394_ASYNCH_LOCK_32:
/*
* The csr_cswap32() call can return DDI_FAILURE if
* the HAL is shutdown, if the register at "offset"
* is unimplemented, or if the generation has changed.
* In the last case, it shouldn't matter because the
* call to s1394_send_response will fail on a bad
* generation and the command will be freed.
*/
if (result == DDI_SUCCESS) {
} else {
}
break;
} else {
}
break;
default:
}
}
/*
* s1394_CSR_topology_map()
* handles all request for the TOPOLOGY_MAP[]. Since it is implemented
* with backing store, there isn't much to do besides return success or
* failure.
*/
static void
{
S1394_TNF_SL_CSR_STACK, "");
/* Make sure it's a quadlet read request */
else
S1394_TNF_SL_CSR_STACK, "");
}
/*
* s1394_CSR_topology_map_update()
* is used to update the local host's TOPOLOGY_MAP[] buffer. It copies in
* the SelfID packets, updates the generation and other fields, and
* computes the necessary CRC values before returning.
* Callers must be holding the topology_tree_mutex.
*/
void
{
int i, j, c;
c = 0;
for (i = 0; i < hal->number_of_nodes; i++) {
j = -1;
do {
j++;
}
while (IEEE1394_SELFID_ISMORE(&selfid_packet[j]));
}
/* Update Topology Map Generation */
/* Update Node_Count and Self_Id_Count */
node_count = (i & IEEE1394_TOP_MAP_LEN_MASK);
self_id_count = (c & IEEE1394_TOP_MAP_LEN_MASK);
/* Calculate CRC-16 */
}
/*
* s1394_CSR_topology_map_disable()
* is used to disable the local host's TOPOLOGY_MAP[] buffer (during bus
* reset processing). It sets the topology map's length to zero to
* indicate that it is invalid.
*/
void
{
/* Set length = 0 */
}
/*
* s1394_common_CSR_routine()
* is used to handle most of the CSR register requests. They are passed
* to the appropriate HAL entry point for further processing. Then they
* are filled in with an appropriate response code, and the response is sent.
*/
static void
{
int result;
S1394_TNF_SL_CSR_STACK, "");
/* Register offset */
/* Verify that request is quadlet aligned */
if ((offset & 0x3) != 0) {
}
case CMD1394_ASYNCH_RD_QUAD:
/*
* The csr_read() call can return DDI_FAILURE if the HAL
* is shutdown or if the register at "offset" is
* unimplemented. We will return IEEE1394_RESP_ADDRESS_ERROR
* in the response if we see this error.
*/
if (result == DDI_SUCCESS) {
} else {
}
break;
case CMD1394_ASYNCH_WR_QUAD:
/*
* The csr_read() call can return DDI_FAILURE if the HAL
* is shutdown or if the register at "offset" is
* unimplemented. We will return IEEE1394_RESP_ADDRESS_ERROR
* in the response if we see this error.
*/
if (result == DDI_SUCCESS) {
} else {
}
break;
default:
}
S1394_TNF_SL_CSR_STACK, "");
}
/*
* s1394_init_local_config_rom()
* is called in the HAL attach routine - h1394_attach() - to setup the
* initial Config ROM entries on the local host, including the
* bus_info_block and the root and unit directories.
*/
int
{
void *n_handle;
/* Setup Config ROM mutex */
/* Allocate 1K for the Config ROM buffer */
KM_SLEEP);
/* Allocate 1K for the temporary buffer */
/* Lock the Config ROM buffer */
/* Build the config ROM structures */
if (ret != DDI_SUCCESS) {
/* Unlock the Config ROM buffer */
"Failed in s1394_init_config_rom_structures()");
return (DDI_FAILURE);
}
/* Build the Bus_Info_Block - see IEEE 1394-1995, Section 8.3.2.5.4 */
/*
* If we are Isoch Resource Manager capable then we are
* Bus Manager capable too.
*/
if (irmc)
/*
* Set generation to P1394a valid (but changeable)
* Even if we have a 1995 PHY, we will still provide
* certain P1394A functionality (especially with respect
* to Config ROM updates). So we must publish this
* information.
*/
g = 2 << IEEE1394_BIB_GEN_SHIFT;
bus_capabilities = bus_capabilities | g;
/* Get the GUID */
/* The CRC covers only our Bus_Info_Block */
/* Do byte-swapping if necessary (x86) */
for (i = 0; i < IEEE1394_BIB_QUAD_SZ; i++)
/* Build the Root_Directory - see IEEE 1394-1995, Section 8.3.2.5.5 */
/* MODULE_VENDOR_ID - see IEEE 1394-1995, Section 8.3.2.5.5.1 */
/* NODE_CAPABILITIES - see IEEE 1394-1995, Section 8.3.2.5.5.2 */
root_dir_len = 2;
/* Do byte-swapping if necessary (x86) */
for (i = IEEE1394_BIB_QUAD_SZ; i < 8; i++)
/* Build the Root Text leaf - see IEEE 1394-1995, Section 8.3.2.5.7 */
/* Do byte-swapping if necessary (x86) */
for (i = 0; i < 9; i++)
if (ret != DDI_SUCCESS) {
/* Destroy the config_rom structures */
(void) s1394_destroy_config_rom_structures(hal);
/* Unlock the Config ROM buffer */
"Failure in kmem_zalloc");
return (DDI_FAILURE);
}
/* Build the Node_Unique_Id leaf - IEEE 1394-1995, Sect. 8.3.2.5.7.1 */
KM_SLEEP);
/* Do byte-swapping if necessary (x86) */
for (i = 0; i < S1394_NODE_UNIQUE_ID_QUAD_SZ; i++)
&status);
if (ret != DDI_SUCCESS) {
kmem_free((void *)node_unique_id_leaf,
/* Destroy the config_rom structures */
(void) s1394_destroy_config_rom_structures(hal);
/* Unlock the Config ROM buffer */
"Failure in kmem_zalloc");
return (DDI_FAILURE);
}
/* Build the Unit_Directory for 1394 Framework */
/* Do byte-swapping if necessary (x86) */
for (i = 0; i < 4; i++)
/* Build the Unit Directory text leaf */
/* Do byte-swapping if necessary (x86) */
for (i = 4; i < S1394_UNIT_DIR_QUAD_SZ; i++)
if (ret != DDI_SUCCESS) {
/* Destroy the config_rom structures */
(void) s1394_destroy_config_rom_structures(hal);
/* Unlock the Config ROM buffer */
/* Free the 1K for the Config ROM buffer */
"Failure in kmem_zalloc");
return (DDI_FAILURE);
}
hal->free_space);
/* Unlock the Config ROM buffer */
/*
* The update_config_rom() call can return DDI_FAILURE if the
* HAL is shutdown.
*/
return (DDI_SUCCESS);
}
/*
* s1394_destroy_local_config_rom()
* is necessary for h1394_detach(). It undoes all the work that
* s1394_init_local_config_rom() had setup and more. By pulling
* everything out of the conig rom structures and freeing them and their
* associated mutexes, the Config ROM is completely cleaned up.
*/
void
{
/* Lock the Config ROM buffer */
/* Destroy the config_rom structures */
(void) s1394_destroy_config_rom_structures(hal);
/* Unlock the Config ROM buffer */
/* Free the 1K for the temporary buffer */
/* Free the 1K for the Config ROM buffer */
/* Setup Config ROM mutex */
}
/*
* s1394_init_config_rom_structures()
* initializes the structures that are used to maintain the local Config ROM.
* Callers must be holding the local_config_rom_mutex.
*/
static int
{
sizeof (s1394_config_rom_t), KM_SLEEP);
sizeof (s1394_config_rom_t), KM_SLEEP);
return (DDI_SUCCESS);
}
/*
* s1394_destroy_config_rom_structures()
* is used to destroy the structures that maintain the local Config ROM.
* Callers must be holding the local_config_rom_mutex.
*/
static int
{
}
return (DDI_SUCCESS);
}
/*
* s1394_add_config_rom_entry()
* is used to add a new entry to the local host's config ROM. By
* specifying a key and a buffer, it is possible to update the Root
* Directory to point to the new entry (in buffer). Additionally, all
* of the relevant CRCs, lengths, and generations are updated as well.
* By returning a Config ROM "handle", we can allow targets to remove
* the corresponding entry.
* Callers must be holding the local_config_rom_mutex.
*/
int
{
int i;
"stacktrace 1394 s1394", "");
/* Out of space */
return (DDI_FAILURE);
}
/* Copy the Bus_Info_Block */
/* Copy and add to the Root_Directory */
tmp_offset) + 1;
/* Swap... add one... then unswap */
temp++;
} else {
hal->free_space--;
break;
}
}
/* Get the pointer to the "free" space */
/* Is it an exact fit? */
} else { /* Must break this piece */
sizeof (s1394_config_rom_t), KM_SLEEP);
return (DDI_FAILURE);
}
}
/* Copy in the new entry */
/* Update root directory */
/* Do byte-swapping if necessary (x86) */
i++)
/* Redo byte-swapping if necessary (x86) */
/* Copy it back to config_rom buffer */
/* Return a handle to this block */
*status = T1394_NOERROR;
return (DDI_SUCCESS);
}
/*
* s1394_remove_config_rom_entry()
* is used to remove an entry from the local host's config ROM. By
* specifying the Config ROM "handle" that was given in the allocation,
* it is possible to remove the entry. Subsequently, the Config ROM is
* updated again.
* Callers must be holding the local_config_rom_mutex.
*/
int
{
int i;
/* Copy the Bus_Info_Block */
/* Update Root_Directory entries before the deleted one */
for (i = root_offset; i < del_offset; i++) {
/* If entry is an offset address - update it */
if (entry & 0x80000000)
else
}
/* Move all Unit_Directories prior to the deleted one */
tmp_size << 2);
}
/* Move all Unit_Directories after the deleted one */
(del_offset + 1);
(del_offset + 1);
}
/* Remove del_blk from the list */
/* Update and zero out the "free" block */
(del_offset + 1);
} else {
sizeof (s1394_config_rom_t), KM_SLEEP);
return (DDI_FAILURE);
}
(del_offset + 1);
}
/* Update root directory */
/* Do byte-swapping if necessary (x86) */
i++)
/* Do byte-swapping if necessary (x86) */
i++)
/* Copy it back to config_rom buffer */
/* Return a handle to this block */
*status = T1394_NOERROR;
return (DDI_SUCCESS);
}
/*
* s1394_update_config_rom_callback()
* is the callback used by t1394_add_cfgrom_entry() and
* t1394_rem_cfgrom_entry(). After a target updates the Config ROM, a
* timer is set with this as its callback function. This is to reduce
* the number of bus resets that would be necessary if many targets
* wished to update the Config ROM simultaneously.
*/
void
{
uint32_t g;
int i, ret;
/* Lock the Config ROM buffer */
/* Update Generation and CRC for Bus_Info_Block */
/* Do byte-swapping if necessary (x86) */
for (i = 0; i < IEEE1394_BIB_QUAD_SZ; i++)
g = ((bus_capabilities & IEEE1394_BIB_GEN_MASK) >>
IEEE1394_BIB_GEN_SHIFT) + 1;
if (g > 15)
g = 2;
g = g << IEEE1394_BIB_GEN_SHIFT;
/* Do byte-swapping if necessary (x86) */
for (i = 0; i < IEEE1394_BIB_QUAD_SZ; i++)
/* Make sure we update only what is necessary */
hal->free_space);
/* Clear the timer flag */
/* Unlock the Config ROM buffer */
/*
* The update_config_rom() call can return DDI_FAILURE if the
* HAL is shutdown.
*/
/* Initiate a bus reset */
if (ret != DDI_SUCCESS) {
"Error initiating bus reset");
}
}