/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Provides access routines to the OpenHCI HW.
*/
/*
* Data swap macros used to swap config rom data that is going to be placed
* in OpenHCI registers. The config rom is treated like a byte stream. When
* the services layer calls into us to update the config rom, they pass us a
* byte stream of data. This works well except for the the fact that the
* hardware uses its internal registers for the first 5 quadlets. We have to
* copy the cfgrom header and bus options into their corresponding OpenHCI
* registers. On an x86 machine, this means we have to byte swap them first.
*/
#ifdef _LITTLE_ENDIAN
#else
#endif
/*
* hci1394_ohci_init()
* Initialize the OpenHCI hardware.
*/
int
{
int status;
#if defined(__x86)
#endif
/* alloc the space for ohci */
/*
* Start with the cycle timer rollover interrupt disabled. When it is
* enabled, we will get an interrupt every 64 seconds, even if we have
* nothing plugged into the bus. This interrupt is used to keep track
* of the bus time. We will enable the interrupt when the bus manager
* writes to the bus_time CSR register (Currently there are not known
* implementations that write to the bus_time register)
*/
ohci->ohci_bustime_count = 0;
ohci->ohci_gap_count = 0;
/* Map OpenHCI Registers */
&ohci->ohci_reg_handle);
if (status != DDI_SUCCESS) {
"");
"");
return (DDI_FAILURE);
}
/*
* make sure PCI Master and PCI Memory Access are enabled on x86
* platforms. This may not be the case if plug and play OS is
* set in the BIOS
*/
#if defined(__x86)
PCI_COMM_ME)) {
}
#endif
/*
* Initialize the openHCI chip. This is broken out because we need to
* do this when resuming too.
*/
if (status != DDI_SUCCESS) {
"");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Init the 1394 PHY */
if (status != DDI_SUCCESS) {
(void) hci1394_ohci_soft_reset(ohci);
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Init 1394a features if present */
if (status != DDI_SUCCESS) {
(void) hci1394_ohci_soft_reset(ohci);
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
}
/* save away guid, phy type, and vendor info */
/* We do not support version < 1.0 */
if (OHCI_VERSION(version) == 0) {
"hci1394(%d): OpenHCI version %x.%x is not supported",
(void) hci1394_ohci_soft_reset(ohci);
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Initialize the selfid buffer */
if (status != DDI_SUCCESS) {
(void) hci1394_ohci_soft_reset(ohci);
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Initialize the config rom buffer */
if (status != DDI_SUCCESS) {
(void) hci1394_ohci_soft_reset(ohci);
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_fini()
* Cleanup after OpenHCI init. This should be called during detach.
*/
void
{
/* reset chip */
(void) hci1394_ohci_soft_reset(ohci);
/* Free config rom space */
/* Free selfid buffer space */
/* Free up the OpenHCI registers */
/* Free the OpenHCI state space */
}
/*
* hci1394_ohci_chip_init()
* Initialize the OpenHCI registers. This contains the bulk of the initial
* register setup.
*/
static int
{
int status;
"");
/* Reset 1394 OHCI HW */
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/*
* Setup Host Control Register. The software reset does not put all
* registers in a known state. The Host Control Register is one of these
* registers. First make sure noByteSwapData and postedWriteEnable and
* are cleared.
*/
/*
* the determination if we should swap data is made during the PCI
* initialization.
*/
/*
* most hba's don't swap data. It will be swapped in the
* global swap for SPARC. Enable Link Power(LPS). Enable
* Posted Writes
*/
} else {
/*
* Swap Data. Enable Link Power(LPS). Enable Posted Writes
*/
}
/*
* Wait for PHY to come up. There does not seem to be standard time for
* how long wait for the PHY to come up. The problem is that the PHY
* provides a clock to the link layer and if that is not stable, we
* (and maybe an OpenHCI register?) This used to be set to 10mS which
* works for just about every adapter we tested on. We got a new TI
* adapter which would crash the system once in a while if nothing
* (1394 device) was pluged into the adapter. Changing this delay to
* 50mS made that problem go away. This value is set via a patchable
* variable located in hci1394_extern.c
*/
/* Clear Isochrounous receive multi-chan mode registers */
/*
* Setup async retry on busy or ack_data_error
* secondlimit = 0 <= bits 31-29
* cycleLimit = 0 <= bits 28-16
* maxPhysRespRetries = 0 <= bits 11-8
* maxARRespRetries = 0 <= bits 7-4
* maxATReqRetries = 2 <= bits 3-0
*/
/*
* Setup Link Control
* Enable cycleMaster, cycleTimerEnable, and rcvPhyPkt.
*/
/*
* Set the Physical address map boundary to 0x0000FFFFFFFF. The
* phys_upper_bound is the upper 32-bits of the 48-bit 1394 address. The
* lower 16 bits are assumed to be 0xFFFF.
*/
/*
* Enable all async requests.
* The asyncReqResourceAll bit (0x80000000) does not get cleared during
* a bus reset. If this code is changed to selectively allow nodes to
* perform ARREQ's, the ARREQ filter bits will need to be updated after
* every bus reset.
*/
/*
* clear isochronous interrupt event and mask registers clearing the
* mask registers disable all isoc tx & rx ints
*/
"");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_soft_reset()
* Reset OpenHCI HW.
*/
int
{
HCI1394_TNF_HAL_STACK, "");
/* Reset 1394 HW - Reset is bit 16 in HCControl */
/* Wait for reset to complete */
/* Verify reset is complete */
if (resetStatus != 0) {
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
HCI1394_TNF_HAL_STACK, "");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_reg_read()
* Read OpenHCI register. This is called from the test ioctl interface
* through devctl.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_reg_write()
* Write OpenHCI register. This is called from the test ioctl interface
* through devctl.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_intr_master_enable()
* Enable interrupts to be passed on from OpenHCI. This is a global mask.
* Individual interrupts still need to be enabled for interrupts to be
* generated.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_intr_master_disable()
* Disable all OpenHCI interrupts from being passed on. This does not affect
* the individual interrupt mask settings. When interrupts are enabled
* again, the same individual interrupts will still be enabled.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_intr_asserted()
* Return which ENABLED interrupts are asserted. If an interrupt is disabled
* via its mask bit, it will not be returned from here.
*
* NOTE: we may want to make this a macro at some point.
*/
{
HCI1394_TNF_HAL_STACK, "");
/*
* Only look at interrupts which are enabled by reading the
* intr_event_clr register.
*/
HCI1394_TNF_HAL_STACK, "");
return (interrupts_asserted);
}
/*
* hci1394_ohci_intr_enable()
* Enable an individual interrupt or set of interrupts. This does not affect
* the global interrupt mask.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_intr_disable()
* Disable an individual interrupt or set of interrupts. This does not affect
* the global interrupt mask.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_intr_clear()
* Clear a set of interrupts so that they are not asserted anymore.
*
* NOTE: we may want to make this a macro at some point.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_it_intr_asserted()
* Return which ENABLED isoch TX interrupts are asserted. If an interrupt is
* disabled via its mask bit, it will not be returned from here.
*
* NOTE: we may want to make this a macro at some point.
*/
{
HCI1394_TNF_HAL_STACK, "");
/* Only look at interrupts which are enabled */
HCI1394_TNF_HAL_STACK, "");
return (interrupts_asserted);
}
/*
* hci1394_ohci_it_intr_enable()
* Enable an individual isoch TX interrupt. This does not affect the general
* isoch interrupt mask in the OpenHCI Mask register. That is enabled/
* disabled via hci1394_ohci_intr_enable/hci1394_ohci_intr_disable.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_it_intr_disable()
* Disable an individual isoch TX interrupt. This does not affect the general
* isoch interrupt mask in the OpenHCI Mask register. That is enabled/
* disabled via hci1394_ohci_intr_enable/hci1394_ohci_intr_disable.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_it_intr_clear()
* Clear an individual isoch TX interrupt so that it is not asserted anymore.
*
* NOTE: we may want to make this a macro at some point.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_it_ctxt_count_get()
* Determine the number of supported isochronous transmit contexts.
*/
int
{
int count;
HCI1394_TNF_HAL_STACK, "");
/*
* hw is required to support contexts 0 to N, where N <= 31
* the interrupt mask bits are wired to ground for unsupported
* contexts. Write 1's to all it mask bits, then read the mask.
* Implemented contexts will read (sequentially) as 1
*/
count = 0;
while (channel_mask != 0) {
count++;
}
HCI1394_TNF_HAL_STACK, "");
return (count);
}
/*
* hci1394_ohci_it_cmd_ptr_set()
* Set the context pointer for a given isoch TX context. This is the IO
* address for the HW to fetch the first descriptor. The context should
* not be running when this routine is called.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
io_addr);
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_ir_intr_asserted()
* Return which ENABLED isoch RX interrupts are asserted. If an interrupt is
* disabled via its mask bit, it will not be returned from here.
*
* NOTE: we may want to make this a macro at some point.
*/
{
HCI1394_TNF_HAL_STACK, "");
/* Only look at interrupts which are enabled */
HCI1394_TNF_HAL_STACK, "");
return (interrupts_asserted);
}
/*
* hci1394_ohci_ir_intr_enable()
* Enable an individual isoch RX interrupt. This does not affect the isoch
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_ir_intr_disable()
* Disable an individual isoch RX interrupt. This does not affect the isoch
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_ir_intr_clear()
* Clear an individual isoch RX interrupt so that it is not asserted anymore.
*
* NOTE: we may want to make this a macro at some point.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_ir_ctxt_count_get()
* Determine the number of supported isochronous receive contexts.
*/
int
{
int count;
HCI1394_TNF_HAL_STACK, "");
/*
* hw is required to support contexts 0 to N, where N <= 31
* the interrupt mask bits are wired to ground for unsupported
* contexts. Write 1's to all ir mask bits, then read the mask.
* Implemented contexts will read (sequentially) as 1
*/
count = 0;
while (channel_mask != 0) {
count++;
}
HCI1394_TNF_HAL_STACK, "");
return (count);
}
/*
* hci1394_ohci_ir_cmd_ptr_set()
* Set the context pointer for a given isoch RX context. This is the IO
* address for the HW to fetch the first descriptor. The context should
* not be running when this routine is called.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
io_addr);
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_link_enable()
* Enable the 1394 link layer. When the link is enabled, the PHY will pass
* up any 1394 bus transactions which would normally come up to the link.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_link_disable()
* Disable the 1394 link layer. When the link is disabled, the PHY will NOT
* pass up any 1394 bus transactions which would normally come up to the
* link. This "logically" disconnects us from the 1394 bus.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_bus_reset()
* Reset the 1394 bus. This performs a "long" bus reset and can be called
* when the adapter has either a 1394-1995 or 1394A PHY.
*/
int
{
int status;
HCI1394_TNF_HAL_STACK, "");
/*
* We want to reset the bus. We also handle the root_holdoff and gap
* count cacheing explained at the top of this file.
*/
reg = OHCI_PHY_IBR;
}
} else {
}
/*
* Reset the bus. We intentionally do NOT do a PHY read here. A PHY
* read could introduce race conditions and would be more likely to fail
* due to a timeout.
*/
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* clear the root holdoff and gap count state bits */
HCI1394_TNF_HAL_STACK, "");
return (DDI_SUCCESS);
}
/*
*
* hci1394_ohci_bus_reset_nroot()
* Reset the 1394 bus. This performs a "long" bus reset with out a root.
*/
int
{
int status;
/*
* We want to reset the bus. We don't care about any holdoff
* we are suspending need no root...
*/
/*
* Reset the bus. We intentionally do NOT do a PHY read here. A PHY
* read could introduce race conditions and would be more likely to fail
* due to a timeout.
*/
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_phy_init()
* Setup the PHY. This should be called during attach and performs any PHY
* initialization required including figuring out what kind of PHY we have.
*/
int
{
int status;
HCI1394_TNF_HAL_STACK, "");
/*
* if the phy has extended set to 7, the phy is a not a 1394-1995 PHY.
* It could be a 1394a phy or beyond. The PHY type can be found in PHY
* register page 1 in the compliance_level register.
*
* Since there are not any current standards beyond 1394A, we are going
* to consider the PHY to be a 1394A phy if the extended bit is set.
*
* phy registers are byte wide registers and are addressed as 0, 1, 2,
* 3, ... Phy register 0 may not be read or written.
*
* Phy register 0x2 (bit 0 MSB, 7 LSB)
* Extended - bits 0 - 2
* Total Ports - bits 4 - 7
*/
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/*
* if the extended bit is not set, we have to be a 1394-1995
* PHY
*/
} else {
/* Treat all other PHY's as a 1394A PHY */
}
HCI1394_TNF_HAL_STACK, "");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_phy_resume()
* re-initialize the PHY. This routine should be called during a resume after
* a successful suspend has been done.
*/
/* ARGSUSED */
static int
{
HCI1394_TNF_HAL_STACK, "");
/* There is currently nothing to re-initialize here */
HCI1394_TNF_HAL_STACK, "");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_phy_set()
* Perform bitset operation on PHY register.
*/
int
{
int status;
HCI1394_TNF_HAL_STACK, "");
/* read the PHY register */
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Set the bits and write the result back */
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
"");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_phy_clr()
* Perform bitclr operation on PHY register.
*/
int
{
int status;
HCI1394_TNF_HAL_STACK, "");
/* read the PHY register */
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Set the bits and write the result back */
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
"");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_phy_read()
* Atomic PHY register read
*/
int
{
int status;
"");
"");
return (status);
}
/*
* hci1394_ohci_phy_write()
* Atomic PHY register write
*/
int
{
int status;
"");
"");
return (status);
}
/*
* hci1394_ohci_phy_read_no_lock()
* This routine actually performs the PHY register read. It is seperated
* out from phy_read so set & clr lock can perform an atomic PHY register
* operation. It assumes the OpenHCI mutex is held.
*/
static int
{
int count;
HCI1394_TNF_HAL_STACK, "");
/* You can't read or write PHY register #0 */
if (address == 0) {
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Verify phy access not in progress */
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Start the PHY register read */
ohci_reg);
/*
* The PHY read usually takes less than 1uS. It is not worth having
* this be interrupt driven. Having this be interrupt driven would also
* make the bus reset and self id processing much more complex for
* 1995 PHY's. We will wait up to hci1394_phy_delay_uS for the read
* to complete (this was initially set to 10). I have yet to see
* count > 1. The delay is a patchable variable.
*/
count = 0;
while (count < hci1394_phy_delay_uS) {
/* See if the read is done yet */
if ((ohci_reg & OHCI_PHYC_RDDONE) != 0) {
/*
* The read is done. clear the phyRegRecv interrupt. We
* do not have this interrupt enabled but this keeps
* things clean in case someone in the future does.
* Break out of the loop, we are done.
*/
break;
}
/*
* the phy read did not yet complete, wait 1uS, increment the
* count and try again.
*/
drv_usecwait(1);
count++;
}
/* Check to see if we timed out */
if (count >= hci1394_phy_delay_uS) {
/* we timed out, return failure */
*data = 0;
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* setup the PHY read data to be returned */
HCI1394_TNF_HAL_STACK, "");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_phy_write_no_lock()
* This routine actually performs the PHY register write. It is separated
* out from phy_write so set & clr lock can perform an atomic PHY register
* operation. It assumes the OpenHCI mutex is held.
*/
static int
{
int count;
HCI1394_TNF_HAL_STACK, "");
/* You can't read or write PHY register #0 */
if (address == 0) {
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Verify phy access not in progress */
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Start the PHY register write */
/*
* The PHY write usually takes less than 1uS. It is not worth having
* this be interrupt driven. Having this be interrupt driven would also
* make the bus reset and self id processing much more complex. We will
* wait up to hci1394_phy_delay_uS for the write to complete (this was
* initially set to 10). I have yet to see count > 0. The delay is a
* patchable variable.
*/
count = 0;
while (count < hci1394_phy_delay_uS) {
/* See if the write is done yet */
if ((ohci_reg & OHCI_PHYC_WRREG) == 0) {
/*
* The write completed. Break out of the loop, we are
* done.
*/
break;
}
/*
* the phy write did not yet complete, wait 1uS, increment the
* count and try again.
*/
drv_usecwait(1);
count++;
}
/* Check to see if we timed out */
if (count >= hci1394_phy_delay_uS) {
/* we timed out, return failure */
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
HCI1394_TNF_HAL_STACK, "");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_phy_info()
* Return selfid word for our PHY. This routine should ONLY be called for
* adapters with a 1394-1995 PHY. These PHY's do not embed their own selfid
* information in the selfid buffer so we need to do it for them in the
* selfid complete interrupt handler. This routine only supports building
* selfid info for a 3 port PHY. Since we will probably not ever see a
* 1394-1995 PHY in any production system, and if we do it will have 3 ports
* or less, this is a pretty safe assumption.
*/
int
{
int status;
int index;
int num_ports;
int count;
HCI1394_TNF_HAL_STACK, "");
/*
* Set Link on. We are using power class 0 since we have no idea what
* our real power class is.
*/
phy_info = 0x80400000;
/* Add in Physical ID */
/* Add in Gap Count */
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Add in speed & ports */
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* PHY reports that it has 0 ports?? */
if (num_ports == 0) {
"1995 phy has zero ports?");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Build up the port information for each port in the PHY */
count = 0;
if (num_ports > 0) {
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* if port is not connected */
if ((reg & 0x04) == 0) {
/* else if port is connected to parent */
} else if ((reg & 0x08) == 0) {
/* else port is connected to child */
} else {
}
num_ports--;
} else {
}
/* add in the port information */
count++;
}
/* Copy the PHY selfid info to the return parameter */
HCI1394_TNF_HAL_STACK, "");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_current_busgen()
* return the current bus generation.
*/
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
return (generation_count);
}
/*
* hci1394_ohci_startup()
* Startup the 1394 nexus driver. This is called after all of the HW has
* been initialized (in both attach and resume) and we are ready to
* participate on the bus.
*/
int
{
int status;
HCI1394_TNF_HAL_STACK, "");
/*
* Turn on 1394 link. This allows us to receive 1394 traffic off the
* bus
*/
/*
* Reset the 1394 Bus.
* Need to do this so that the link layer can collect all of the self-id
* packets. The Interrupt routine will cause further initialization
* after the bus reset has completed
*/
if (status != DDI_SUCCESS) {
"failed to reset bus");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* setup out initial interrupt mask and enable interrupts */
"");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_postwr_addr()
* Read the Posted Write Address registers. This should be read when a
* posted write error is detected to find out what transaction had an error.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
/* read in the errored address */
/*
* Interrupt should be cleared after reading the posted write address.
* See 13.2.8.1 in OpenHCI spec v1.0.
*/
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_guid()
* Return the adapter's GUID
*/
{
return (guid);
}
/*
* hci1394_ohci_csr_read()
* Read one of the HW implemented CSR registers. These include
* bus_manager_id, bandwidth_available, channels_available_hi, and
* channels_available_lo. Offset should be set to
* OHCI_CSR_SEL_BUS_MGR_ID, OHCI_CSR_SEL_BANDWIDTH_AVAIL
* OHCI_CSR_SEL_CHANS_AVAIL_HI, or OHCI_CSR_SEL_CHANS_AVAIL_LO.
*/
int
{
int status;
"");
/*
* read the CSR register by doing a cswap with the same compare and
* swap value.
*/
data);
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
"");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_csr_cswap()
* include bus_manager_id, bandwidth_available, channels_available_hi, and
* channels_available_lo. Offset should be set to
* OHCI_CSR_SEL_BUS_MGR_ID, OHCI_CSR_SEL_BANDWIDTH_AVAIL
* OHCI_CSR_SEL_CHANS_AVAIL_HI, or OHCI_CSR_SEL_CHANS_AVAIL_LO.
*/
int
{
int count;
HCI1394_TNF_HAL_STACK, "");
/*
* Make sure we have not gotten a bus reset since this action was
* started.
*/
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* init csrData and csrCompare */
/* start the compare swap */
/*
* The CSR access should be immediate. There in nothing that officially
* states this so we will wait up to 2uS just in case before we timeout.
* We actually perform a compare swap with both compare and swap set
* to the same value. This will return the old value which is in
* essence, a read.
*/
count = 0;
while (count < 2) {
/* See if the compare swap is done */
if ((ohci_reg & OHCI_CSR_DONE) != 0) {
/* The compare swap is done, break out of the loop */
break;
}
/*
* The compare swap has not completed yet, wait 1uS, increment
* the count and try again
*/
drv_usecwait(1);
count++;
}
/* If we timed out, return an error */
if (count >= 2) {
*old = 0;
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Copy the old data into the return parameter */
/*
* There is a race condition in the OpenHCI design here. After checking
* the generation and before performing the cswap, we could get a bus
* reset and incorrectly set something like the bus manager. This would
* put us into a condition where we would not have a bus manager and
* we would think there was one. If it is possible that this race
* condition occured, we will reset the bus to clean things up. We only
* care about this if the compare swap was successful.
*/
(void) hci1394_ohci_bus_reset(ohci_hdl);
"Invalid Bus Generation");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
}
"");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_contender_enable()
* Set the contender bit in the PHY. This routine should only be called
* if our PHY is 1394A compliant. (i.e. this routine should not be called
* for a 1394-1995 PHY).
*/
int
{
int status;
HCI1394_TNF_HAL_STACK, "");
/*
* Make sure that phy is not a 1394-1995 phy. Those phy's do not have a
* contender bit to set.
*/
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Set the Contender Bit */
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
HCI1394_TNF_HAL_STACK, "");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_root_holdoff_enable()
* Set the root holdoff bit in the PHY. Since there are race conditions when
* writing to PHY register 1 (which can get updated from a PHY packet off the
* bus), we cache this state until a "long" bus reset is issued.
*/
int
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_gap_count_set()
* Set the gap count in the PHY. Since there are race conditions when writing
* to PHY register 1 (which can get updated from a PHY packet off the bus),
* we cache this gap count until a "long" bus reset is issued.
*/
int
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_phy_filter_set()
* Enable a node (or nodes) to perform transactions to our physical
* address space 0x0 - 0xFFFFFFFF. This address goes out to the IO MMU (in
* the case of a SPARC machine). The HAL starts with all nodes unable to
* nodes via setting a physical filter bit for that given node. Since node
* numbers change every bus reset, the services layer has to call down after
* every bus reset to re-enable physical accesses. (NOTE: the hardware
* automatically clears these bits.
*/
int
{
HCI1394_TNF_HAL_STACK, "");
/*
* Make sure we have not gotten a bus reset since this action was
* started.
*/
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/*
* There is a race condition in the OpenHCI design here. After checking
* the generation and before setting the physical filter bits, we could
* get a bus reset and incorrectly set the physical filter bits. If it
* is possible that this race condition occured, we will reset the bus
* to clean things up.
*/
(void) hci1394_ohci_bus_reset(ohci_hdl);
HCI1394_TNF_HAL_STACK, "");
return (DDI_SUCCESS);
}
HCI1394_TNF_HAL_STACK, "");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_phy_filter_clr()
* Disable a node (or nodes) from performing transactions to our physical
* memory. See hci1394_ohci_phy_filter_set() above for more info.
*/
int
{
HCI1394_TNF_HAL_STACK, "");
/*
* Make sure we have not gotten a bus reset since this action was
* started.
*/
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
HCI1394_TNF_HAL_STACK, "");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_bus_reset_short()
* Perform a 1394A short bus reset. This function should only be called
* on an adapter with a 1394A PHY (or later).
*/
int
{
int status;
HCI1394_TNF_HAL_STACK, "");
/*
* Make sure that phy is not a 1394-1995 phy. Those phy's do not have a
* contender bit to set.
*/
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Initiate the short bus reset */
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
HCI1394_TNF_HAL_STACK, "");
return (status);
}
/*
* hci1394_ohci_cfgrom_update()
* Update the config rom with the provided contents. The config rom is
* provided as a byte stream which is multiple of 4 bytes large. The
* size is passed as a quadlet (4 bytes) count. The entire contents
* of the config rom is updated at once. We do not provide a partial
* update interface.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
/* zero out the config ROM header to start */
/* copy Services Layer buffer into config rom buffer */
/*
* setup OHCI bus options and config rom hdr registers. We need to swap
* the config rom header and bus options on an X86 machine since the
* data is provided to us as a byte stream and the OHCI registers expect
* a big endian 32-bit number.
*/
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_nodeid_get()
* Return our current nodeid (bus #/Node #)
*/
void
{
"");
"");
}
/*
* hci1394_ohci_nodeid_set()
* Set our current nodeid (bus #/Node #). This actually sets our bus number.
* Our node number cannot be set by software. This is usually trigered via
* a write to the CSR NODEIDS register.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_nodeid_info()
* Return our current nodeid (bus #/Node #). This also returns whether or
* not our nodeid error bit is set. This is useful in determining if the
* bus reset completed without errors in the selfid complete interrupt
* processing.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
if ((reg & OHCI_NDID_IDVALID) == 0) {
} else {
}
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_cycletime_get()
* Return the current cycle time
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_cycletime_get()
* Set the cycle time
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_bustime_get()
* Return the current bus time.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
/*
* The bus time is composed of a portion of the cycle time and the
* cycle time rollover count (ohci_bustime_count). There is a race
* condition where we read the rollover count and then the cycle
* timer rolls over. This is the reason for the double read of the
* rollover count.
*/
do {
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_bustime_set()
* Set the cycle timer rollover portion of the bus time.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
/*
* we will start with the cycle 64 seconds interrupt disabled. If this
* is the first write to bus time, enable the interrupt.
*/
/* Clear the cycle64Seconds interrupt then enable it */
}
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_atreq_retries_get()
* Get the number of atreq retries we will perform.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_atreq_retries_get()
* Set the number of atreq retries we will perform.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_isr_cycle64seconds()
* Interrupt handler for the cycle64seconds interrupt.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
/*
* cycle64second interrupts when the MSBit in the cycle timer changes
* state. We only care about rollover so we will increment only when
* the MSBit is set to 0.
*/
if ((cycle_time & 0x80000000) == 0) {
}
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_isr_phy()
* Interrupt handler for a PHY event
*/
void
{
int status;
HCI1394_TNF_HAL_STACK, "");
/* clear the interrupt */
/* increment the statistics count */
/*
* If the PHY is a 1995 phy, just return since there are no status bits
* to read.
*/
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return;
}
/* See why we got this interrupt */
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return;
}
if (phy_status & OHCI_PHY_LOOP_ERR) {
}
if (phy_status & OHCI_PHY_PWRFAIL_ERR) {
}
if (phy_status & OHCI_PHY_TIMEOUT_ERR) {
}
if (phy_status & OHCI_PHY_PORTEVT_ERR) {
}
/* clear any set status bits */
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return;
}
/*
* Disable the PHY interrupt. We are getting stuck in this ISR in
* certain PHY implementations so we will disable the interrupt until
* we see a selfid complete.
*/
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_root_check
* Returns status about if we are currently the root node on the 1394 bus.
* returns B_TRUE if we are the root, B_FALSE if we are not the root.
*/
{
int status;
"");
} else {
}
"");
return (status);
}
/*
* hci1394_ohci_cmc_check()
* Returns status about if we are cycle master capable. Returns
* B_TRUE if we are the cycle master capable, B_FALSE if we are not the cycle
* master capable.
*/
{
int status;
"");
if (reg & OHCI_REG_BUSOPTIONS_CMC) {
} else {
}
"");
return (status);
}
/*
* hci1394_ohci_cycle_master_enable()
* Enables us to be cycle master. If we are root, we will start generating
* cycle start packets.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
/* First make sure that cycleTooLong is clear */
/* Enable Cycle Master */
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_cycle_master_disable()
* Disabled us from being cycle master. If we are root, we will stop
* generating cycle start packets.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
/* disable cycle master */
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_resume()
* Re-initialize the openHCI HW during a resume. (after a power suspend)
*/
int
{
int status;
HCI1394_TNF_HAL_STACK, "");
/* Re-initialize the OpenHCI chip */
if (status != DDI_SUCCESS) {
"");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Re-initialize the PHY */
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Re-initialize any 1394A features we are using */
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Tell OpenHCI where the Config ROM buffer is */
/* Tell OpenHCI where the SelfId buffer is */
/* Enable selfid DMA engine */
/*
* re-setup OHCI bus options and config rom hdr registers. We need to
* read from the config rom using ddi_rep_get8 since it is stored as
* a byte stream. We need to swap he config rom header and bus options
* on an X86 machine since the data is a byte stream and the OHCI
* registers expect a big endian 32-bit number.
*/
HCI1394_TNF_HAL_STACK, "");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_selfid_init()
* Initialize the selfid buffer
*/
static int
{
int status;
/*
* Setup for 2K buffer, aligned on a 2Kbyte address boundary. Make sure
* that the buffer is not broken up into multiple cookies. OpenHCI can
* only handle one address for the selfid buffer location.
*/
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Tell OpenHCI where the buffer is */
/* Enable selfid DMA engine */
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_selfid_enable()
* Allow selfid packets to be placed into the selfid buffer. This should be
* called after the selfid buffer address has been setup in the HW.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
/*
* Allow selfid packets to be received. This should be called during
* driver attach after the selfid buffer address has been initialized.
*
* Link Control Register
* rscSelfId = 1 <= bit 9
*/
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_selfid_read()
* Read a word out of the selfid buffer.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_selfid_info()
* Return the current bus generation, the number of bytes currently in the
* selfid buffer, and if we have seen any selfid errors.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
if ((reg & OHCI_SLFC_ERROR) == 0) {
} else {
}
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_selfid_buf_current()
* Test if the selfid buffer is current. Return B_TRUE if it is current and
* B_FALSE if it is not current.
*/
{
int status;
HCI1394_TNF_HAL_STACK, "");
/*
* if the generation stored in the selfid buffer is not equal to the
* generation we have previously stored, the selfid buffer is not
* current. (It maybe older or it maybe newer)
*/
} else {
}
HCI1394_TNF_HAL_STACK, "");
return (status);
}
/*
* hci1394_ohci_selfid_sync()
* Perform a ddi_dma_sync on the selfid buffer
*/
void
{
HCI1394_TNF_HAL_STACK, "");
"");
}
/*
* hci1394_ohci_cfgrom_init()
* Initialize the configuration ROM buffer
*/
static int
{
int status;
HCI1394_TNF_HAL_STACK, "");
/*
* Setup for 1K buffer, aligned at 1K address boundary, and allow no
* less than 4 byte data transfers. Create the Buffer. Make sure that
* the buffer is not broken up into multiple cookies. OpenHCI can only
* handle one address for the config ROM buffer location.
*/
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
/* Tell OpenHCI where the buffer is */
"");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_bus_capabilities()
* Return our current bus capabilities
*/
void
{
HCI1394_TNF_HAL_STACK, "");
/*
* read in the bus options register. Set bits saying that we are isoch
* resource manager capable, Cycle master capable, and Isoch capable
*/
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_at_active()
* Returns status one if either of the AT engines are active. If either AT
* engine is active, we return B_TRUE. If both AT engines are not active, we
* return B_FALSE.
*/
{
HCI1394_TNF_HAL_STACK, "");
/* see if atreq active bit set */
if (reg & OHCI_CC_ACTIVE_MASK) {
/* atreq engine is still active */
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (B_TRUE);
}
/* see if atresp active bit set */
if (reg & OHCI_CC_ACTIVE_MASK) {
/* atresp engine is still active */
HCI1394_TNF_HAL_ERROR, "");
HCI1394_TNF_HAL_STACK, "");
return (B_TRUE);
}
HCI1394_TNF_HAL_STACK, "");
/* both atreq and atresp active bits are cleared */
return (B_FALSE);
}
/*
* hci1394_ohci_atreq_start()
* Start the atreq dma engine. Set the address of the first descriptor
* to read in equal to cmdptr.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_atreq_wake()
* Wake up the atreq dma engine. This should be called when a new descriptor
* is added to the Q and the dma engine has already be started. It it OK to
* call this when the DMA engine is active.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_atreq_stop()
* Stop the atreq dma engine. No further descriptors will be read until
* it dma engine is started again.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_arresp_start()
* Start the arresp dma engine. Set the address of the first descriptor
* to read in equal to cmdptr.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_arresp_wake()
* Wake up the arresp dma engine. This should be called when a new
* descriptor is added to the Q and the dma engine has already be started.
* It is OK to call this when the DMA engine is active.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_atreq_stop()
* Stop the arresp dma engine. No further data will be received after any
* current packets being received have finished.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_arreq_start()
* Start the arreq dma engine. Set the address of the first descriptor
* to read in equal to cmdptr.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_arreq_wake()
* Wake up the arreq dma engine. This should be called when a new descriptor
* is added to the Q and the dma engine has already be started. It is OK to
* call this when the DMA engine is active.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_arreq_stop()
* Stop the arreq dma engine. No further data will be received after any
* current packets being received have finished.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_atresp_start()
* Start the atresp dma engine. Set the address of the first descriptor
* to read in equal to cmdptr.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_atresp_wake()
* Wake up the atresp dma engine. This should be called when a new
* descriptor is added to the Q and the dma engine has already be started.
* It is OK to call this when the DMA engine is active.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_atresp_stop()
* Stop the atresp dma engine. No further descriptors will be read until
* it dma engine is started again.
*/
void
{
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
}
/*
* hci1394_ohci_1394a_init()
* Initialize any 1394a features that we are using.
*/
/* ARGSUSED */
int
{
int status;
"");
if (reg & OHCI_HC_PROG_PHY_ENBL) {
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
}
"");
return (DDI_SUCCESS);
}
/*
* hci1394_ohci_1394a_init()
* Re-initialize any 1394a features that we are using.
*/
/* ARGSUSED */
int
{
int status;
HCI1394_TNF_HAL_STACK, "");
if (reg & OHCI_HC_PROG_PHY_ENBL) {
if (status != DDI_SUCCESS) {
HCI1394_TNF_HAL_STACK, "");
HCI1394_TNF_HAL_STACK, "");
return (DDI_FAILURE);
}
}
HCI1394_TNF_HAL_STACK, "");
return (DDI_SUCCESS);
}