#include <sys/types.h>
#include <sys/kmem.h>
#include <sys/conf.h>
#include <sys/ddi.h>
#include <sys/modctl.h>
#include <sys/stat.h>
#include <sys/sunddi.h>
#include <sys/1394/h1394.h>
#include <sys/1394/adapters/hci1394.h>
#include <sys/1394/adapters/hci1394_extern.h>
int
hci1394_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
hci1394_state_t *soft_state;
soft_state = ddi_get_soft_state(hci1394_statep, ddi_get_instance(dip));
if (soft_state == NULL) {
return (DDI_FAILURE);
}
switch (cmd) {
case DDI_DETACH:
hci1394_ohci_intr_master_disable(soft_state->ohci);
hci1394_ohci_it_intr_disable(soft_state->ohci, 0xFFFFFFFF);
hci1394_ohci_ir_intr_disable(soft_state->ohci, 0xFFFFFFFF);
hci1394_ohci_intr_clear(soft_state->ohci, 0xFFFFFFFF);
hci1394_ohci_it_intr_clear(soft_state->ohci, 0xFFFFFFFF);
hci1394_ohci_ir_intr_clear(soft_state->ohci, 0xFFFFFFFF);
(void) hci1394_ohci_phy_clr(soft_state->ohci, 4, 0xc0);
ddi_put32(soft_state->ohci->ohci_reg_handle,
&soft_state->ohci->ohci_regs->link_ctrl_clr,
0xFFFFFFFF);
hci1394_isr_handler_fini(soft_state);
(void) hci1394_state_set(&soft_state->drvinfo,
HCI1394_SHUTDOWN);
(void) hci1394_ohci_bus_reset_nroot(soft_state->ohci);
(void) hci1394_ohci_soft_reset(soft_state->ohci);
hci1394_async_flush(soft_state->async);
(void) h1394_detach(&soft_state->drvinfo.di_sl_private,
DDI_DETACH);
ddi_remove_minor_node(dip, "devctl");
hci1394_detach_hardware(soft_state);
hci1394_isr_fini(soft_state);
hci1394_soft_state_fini(soft_state);
ddi_soft_state_free(hci1394_statep,
soft_state->drvinfo.di_instance);
return (DDI_SUCCESS);
case DDI_SUSPEND:
hci1394_ohci_intr_master_disable(soft_state->ohci);
hci1394_ohci_it_intr_disable(soft_state->ohci, 0xFFFFFFFF);
hci1394_ohci_ir_intr_disable(soft_state->ohci, 0xFFFFFFFF);
hci1394_ohci_intr_clear(soft_state->ohci, 0xFFFFFFFF);
hci1394_ohci_it_intr_clear(soft_state->ohci, 0xFFFFFFFF);
hci1394_ohci_ir_intr_clear(soft_state->ohci, 0xFFFFFFFF);
(void) hci1394_ohci_phy_clr(soft_state->ohci, 4, 0xc0);
ddi_put32(soft_state->ohci->ohci_reg_handle,
&soft_state->ohci->ohci_regs->link_ctrl_clr,
0xFFFFFFFF);
(void) hci1394_state_set(&soft_state->drvinfo,
HCI1394_SHUTDOWN);
(void) hci1394_ohci_bus_reset_nroot(soft_state->ohci);
(void) hci1394_ohci_soft_reset(soft_state->ohci);
hci1394_async_suspend(soft_state->async);
(void) h1394_detach(&soft_state->drvinfo.di_sl_private,
DDI_SUSPEND);
return (DDI_SUCCESS);
default:
break;
}
return (DDI_FAILURE);
}
int
hci1394_quiesce(dev_info_t *dip)
{
hci1394_state_t *soft_state;
soft_state = ddi_get_soft_state(hci1394_statep, ddi_get_instance(dip));
if (soft_state == NULL) {
return (DDI_FAILURE);
}
hci1394_ohci_intr_master_disable(soft_state->ohci);
hci1394_ohci_it_intr_disable(soft_state->ohci, 0xFFFFFFFF);
hci1394_ohci_ir_intr_disable(soft_state->ohci, 0xFFFFFFFF);
hci1394_ohci_intr_clear(soft_state->ohci, 0xFFFFFFFF);
hci1394_ohci_it_intr_clear(soft_state->ohci, 0xFFFFFFFF);
hci1394_ohci_ir_intr_clear(soft_state->ohci, 0xFFFFFFFF);
(void) hci1394_ohci_phy_clr(soft_state->ohci, 4, 0xc0);
ddi_put32(soft_state->ohci->ohci_reg_handle,
&soft_state->ohci->ohci_regs->link_ctrl_clr, 0xFFFFFFFF);
(void) hci1394_ohci_bus_reset_nroot(soft_state->ohci);
(void) hci1394_ohci_soft_reset(soft_state->ohci);
return (DDI_SUCCESS);
}
void
hci1394_detach_hardware(hci1394_state_t *soft_state)
{
ASSERT(soft_state != NULL);
hci1394_vendor_fini(&soft_state->vendor);
hci1394_isoch_fini(&soft_state->isoch);
hci1394_async_fini(&soft_state->async);
hci1394_csr_fini(&soft_state->csr);
hci1394_ohci_fini(&soft_state->ohci);
hci1394_pci_fini(soft_state);
}
void
hci1394_pci_fini(hci1394_state_t *soft_state)
{
ASSERT(soft_state != NULL);
pci_config_teardown(&soft_state->pci_config);
}
void
hci1394_soft_state_fini(hci1394_state_t *soft_state)
{
ASSERT(soft_state != NULL);
mutex_destroy(&soft_state->drvinfo.di_drvstate.ds_mutex);
}