/*
* 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 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* 1394 Services Layer Miscellaneous Routines
* This file contains miscellaneous routines used as "helper" functions
* by various other files in the Services Layer.
*/
#include <sys/tnf_probe.h>
/*
* s1394_cleanup_for_detach()
* is used to do all of the necessary cleanup to handle a detach or a
* failure in h1394_attach(). The cleanup_level specifies how far we
* got in h1394_attach() before failure.
*/
void
{
"");
switch (cleanup_level) {
case H1394_CLEANUP_LEVEL7:
/* remove HAL from the global HAL list */
} else {
}
/*
* No FCP cleanup needed at this time -- the following call
* to s1394_destroy_addr_space() takes care of everything.
*/
/* FALLTHROUGH */
case H1394_CLEANUP_LEVEL6:
/* FALLTHROUGH */
case H1394_CLEANUP_LEVEL5:
/* FALLTHROUGH */
case H1394_CLEANUP_LEVEL4:
/* Undo all the kstat stuff */
(void) s1394_kstat_delete(hal);
/* FALLTHROUGH */
case H1394_CLEANUP_LEVEL3:
/* Free up the memory for selfID buffer #1 */
/* Free up the memory for selfID buffer #0 */
/* Turn off any timers that might be set */
/* Destroy the bus_reset thread */
/* Cleanup the Config ROM buffers in the topology_tree */
/* FALLTHROUGH */
case H1394_CLEANUP_LEVEL2:
/* Destroy the br_cmplq_cv and br_cmplq_mutex */
/* Destroy the br_thread_cv and br_thread_mutex */
/* FALLTHROUGH */
case H1394_CLEANUP_LEVEL1:
/* FALLTHROUGH */
case H1394_CLEANUP_LEVEL0:
/* Destroy pending_q_mutex and outstanding_q_mutex */
/* Destroy target_list_rwlock */
/* Destroy bus_mgr_node_mutex and bus_mgr_node_cv */
/* Destroy isoch_cec_list_mutex */
/* Destroy the Cycle Master timer mutex */
/* Destroy topology_tree_mutex */
/* Free the hal structure */
break;
default:
/* Error */
"Invalid cleanup_level");
break;
}
"");
}
/*
* s1394_hal_shutdown()
* is used to shutdown the HAL. If the HAL indicates that an error
* condition (hardware or software) has occurred, it is shutdown. This
* routine is also called when HAL informs the services layer of a shutdown
* (due an internal shutdown, for eg). disable_hal indicates whether the
* caller intends to inform the hal of the (services layer) shutdown or not.
*/
void
{
if (disable_hal == B_TRUE)
S1394_TNF_SL_STACK, "");
return;
}
/* Disable the HAL */
if (disable_hal == B_TRUE)
/*
* Send a remove event to all interested parties
*/
}
/*
* s1394_initiate_hal_reset()
* sets up the HAL structure to indicate a self-initiated bus reset and
* calls the appropriate HAL entry point. If too many bus resets have
* happened, a message is printed out and the call is ignored.
*/
void
{
int ret;
"");
if (hal->num_bus_reset_till_fail > 0) {
/* Reset the bus */
if (ret != DDI_SUCCESS) {
"Error initiating bus reset");
}
} else {
" devices have recently been added, remove them.");
}
"");
}
/*
* s1394_on_br_thread()
* is used to determine if the current thread of execution is the same
* as the bus reset thread. This is useful during bus reset callbacks
* to determine whether or not a target may block.
*/
{
return (B_TRUE);
else
return (B_FALSE);
}
/*
* s1394_destroy_br_thread()
* is used in h1394_detach() to signal the bus reset thread to go away.
*/
void
{
"");
/* Send the signal to the reset thread to go away */
/* Wakeup the bus_reset thread if waiting for bus_mgr timer */
/* Wait for the br_thread to be done */
"");
}
/*
* s1394_tickle_bus_reset_thread()
* is used to wakeup the bus reset thread after the interrupt routine
* has completed its bus reset processing.
*/
void
{
/* Send the signal to the reset thread */
/* Signal the msgq wait, too (just in case) */
/* Signal the bus_mgr wait, too (just in case) */
}
}
/*
* s1394_block_on_asynch_cmd()
* is used by many of the asynch routines to block (if necessary)
* while waiting for command completion.
*/
void
{
S1394_TNF_SL_ATREQ_STACK, "");
/* Get the Services Layer private area */
/* Is this a blocking command? */
/* Block until command completes */
}
S1394_TNF_SL_ATREQ_STACK, "");
}
/*
* s1394_HAL_asynch_error()
* is used by many of the asynch routines to determine what error
* code is expected in a given situation (based on HAL state).
*/
/* ARGSUSED */
int
{
switch (state) {
case S1394_HAL_RESET:
/* "dreq" bit is set (CSR) */
return (CMD1394_ENO_ATREQ);
else
return (CMD1394_CMDSUCCESS);
case S1394_HAL_DREQ:
/* "dreq" bit is set (CSR) */
return (CMD1394_ENO_ATREQ);
case S1394_HAL_SHUTDOWN:
return (CMD1394_EFATAL_ERROR);
default:
return (CMD1394_CMDSUCCESS);
}
}
/*
* s1394_mblk_too_small()
* is used to determine if the mlbk_t structure(s) given in an asynch
* block request are sufficient to hold the amount of data requested.
*/
{
"");
msgb_len = 0;
} else {
msgb_len +=
}
break;
}
}
"");
return (flag);
}
/*
* s1394_address_rollover()
* is used to determine if the address given will rollover the 48-bit
* address space.
*/
{
S1394_TNF_SL_ATREQ_STACK, "");
case CMD1394_ASYNCH_RD_QUAD:
case CMD1394_ASYNCH_WR_QUAD:
case CMD1394_ASYNCH_LOCK_32:
break;
case CMD1394_ASYNCH_LOCK_64:
break;
case CMD1394_ASYNCH_RD_BLOCK:
case CMD1394_ASYNCH_WR_BLOCK:
break;
}
if (addr_after < addr_before) {
S1394_TNF_SL_ATREQ_STACK, "");
return (B_TRUE);
}
S1394_TNF_SL_ATREQ_STACK, "");
return (B_FALSE);
}
/*
* s1394_stoi()
* beginning at *p. Does no overflow checking.
*/
{
int n;
int c;
if (len == 0)
return (0);
if (c >= '0' && c <= '9')
c = c - '0';
else if (c >= 'a' && c <= 'f')
c = c - 'a' + 10;
else if (c >= 'A' && c <= 'F')
c = c - 'F' + 10;
n = (n * base) + c;
}
return (n);
}
/*
* s1394_CRC16()
*/
{
int shift;
int i;
for (i = 0; i < crc_length; i++) {
data = d[i];
/* Another check should be made with "shift > 0" in */
/* order to support any devices that coded it wrong. */
}
}
return (CRC);
}
/*
* s1394_CRC16_old()
* specification the C code example was incorrect and some devices
* were manufactured using this incorrect CRC. On CRC16 failures
* this CRC is tried in case it is a legacy device.
*/
{
int shift;
int i;
for (i = 0; i < crc_length; i++) {
data = d[i];
}
}
return (CRC);
}
/*
* s1394_ioctl()
* implements generic ioctls (eg. devctl support) and any non-HAL ioctls.
* Only ioctls required for devctl support are implemented at present.
*/
/* ARGSUSED */
int
int *rval_p)
{
int rv = 0;
int ret;
/*
* We can use the generic implementation for these ioctls
*/
switch (cmd) {
case DEVCTL_DEVICE_GETSTATE:
case DEVCTL_DEVICE_ONLINE:
case DEVCTL_DEVICE_OFFLINE:
case DEVCTL_DEVICE_REMOVE:
case DEVCTL_BUS_GETSTATE:
}
/* Read devctl ioctl data */
"");
return (EFAULT);
}
switch (cmd) {
case DEVCTL_DEVICE_RESET:
case DEVCTL_DEVICE_REMOVE:
break;
case DEVCTL_BUS_CONFIGURE:
case DEVCTL_BUS_UNCONFIGURE:
break;
case DEVCTL_BUS_QUIESCE:
case DEVCTL_BUS_UNQUIESCE:
break;
case DEVCTL_BUS_RESET:
case DEVCTL_BUS_RESETALL:
if (ret != DDI_SUCCESS) {
"Error initiating short bus reset");
}
} else {
if (ret != DDI_SUCCESS) {
"Error initiating bus reset");
}
}
break;
default:
}
return (rv);
}
/*
* s1394_kstat_init()
* is used to initialize and the Services Layer's kernel statistics.
*/
int
{
int instance;
KM_SLEEP);
"");
return (DDI_SUCCESS);
} else {
"");
return (DDI_FAILURE);
}
}
/*
* s1394_kstat_delete()
* kernel statistics.
*/
int
{
return (DDI_SUCCESS);
}
/*
* s1394_kstat_update()
* is a callback that is called whenever a request to read the kernel
* statistics is made.
*/
int
{
if (rw == KSTAT_WRITE) {
"");
return (EACCES);
} else {
}
return (0);
}
/*
* s1394_addr_alloc_kstat()
* is used by the kernel statistics to update the count for each type of
* address allocation.
*/
void
{
/* kstats - number of addr allocs */
}
/*
* s1394_print_node_info()
* is used to print speed map and GUID information on the console.
*/
void
{
int i, j;
extern void log_enter(void);
extern void log_exit(void);
if (s1394_print_guids == 0)
return;
log_enter();
for (i = 0; i < hal->number_of_nodes; i++) {
}
for (i = 0; i < hal->number_of_nodes; i++) {
}
for (i = 0; i < hal->number_of_nodes; i++) {
for (j = 0; j < hal->number_of_nodes; j++) {
}
if (i == hal_node_num) {
} else {
}
}
log_exit();
}
/*
* s1394_dip_to_hal()
* is used to lookup a HAL's structure pointer by its dip.
*/
{
/* Search the HAL list for this dip */
while (current_hal != NULL) {
break;
}
}
return (current_hal);
}
/*
* s1394_target_from_dip_locked()
* searches target_list on the HAL for target corresponding to tdip;
* if found, target is returned, else returns NULL. This routine assumes
* target_list_rwlock is locked.
* NOTE: the callers may have the list locked in either write mode or read
* mode. Currently, there is no ddi-compliant way we can assert on the lock
* being held in write mode.
*/
{
S1394_TNF_SL_STACK, "");
return (temp);
}
}
S1394_TNF_SL_STACK, "");
return (NULL);
}
/*
* s1394_target_from_dip()
* searches target_list on the HAL for target corresponding to tdip;
* if found, target is returned locked.
*/
{
return (target);
}
/*
* s1394_destroy_timers()
* turns off any outstanding timers in preparation for detach or suspend.
*/
void
{
/* Destroy both of the Bus Mgr timers */
/* Destroy the Cycle Master timer */
/* Wait for the Config ROM timer (if necessary) */
}
}
/*
* s1394_cleanup_node_cfgrom()
* frees up all of the Config ROM in use by nodes in the topology_tree
*/
static void
{
int i;
for (i = 0; i < IEEE1394_MAX_NODES; i++) {
}
}
/*
* s1394_cycle_too_long_callback()
* turns on the cycle master bit of the root node (current Cycle Master)
*/
void
{
S1394_TNF_SL_STACK, "");
/* Clear the cm_timer_cet bit */
/* Get the root node and host node numbers */
/* If we are the root node, set the cycle master bit */
if (hal_node_num == root_node_num) {
}
S1394_TNF_SL_STACK, "");
}