#include <sys/conf.h>
#include <sys/ddi.h>
#include <sys/modctl.h>
#include <sys/stat.h>
#include <sys/sunddi.h>
#include <sys/cmn_err.h>
#include <sys/1394/h1394.h>
#include <sys/1394/ixl1394.h>
#include <sys/1394/adapters/hci1394.h>
static void hci1394_s1394if_shutdown(void *hal_private);
static int hci1394_s1394if_phy(void *hal_private, cmd1394_cmd_t *cmd_id,
h1394_cmd_priv_t *cmd_private, int *result);
static int hci1394_s1394if_write(void *hal_private, cmd1394_cmd_t *cmd_id,
h1394_cmd_priv_t *cmd_private, int *result);
static int hci1394_s1394if_read(void *hal_private, cmd1394_cmd_t *cmd_id,
h1394_cmd_priv_t *cmd_private, int *result);
static int hci1394_s1394if_lock(void *hal_private, cmd1394_cmd_t *cmd_id,
h1394_cmd_priv_t *cmd_private, int *result);
static int hci1394_s1394if_write_response(void *hal_private,
cmd1394_cmd_t *cmd_id, h1394_cmd_priv_t *cmd_private, int *result);
static int hci1394_s1394if_read_response(void *hal_private,
cmd1394_cmd_t *cmd_id, h1394_cmd_priv_t *cmd_private, int *result);
static int hci1394_s1394if_lock_response(void *hal_private,
cmd1394_cmd_t *cmd_id, h1394_cmd_priv_t *cmd_private, int *result);
static void hci1394_s1394if_response_complete(void *hal_private,
cmd1394_cmd_t *cmd_id, h1394_cmd_priv_t *cmd_private);
static int hci1394_s1394if_reset_bus(void *hal_private);
static int hci1394_s1394if_set_contender_bit(void *hal_private);
static int hci1394_s1394if_set_root_holdoff_bit(void *hal_private);
static int hci1394_s1394if_set_gap_count(void *hal_private, uint_t gap_count);
static int hci1394_s1394if_update_config_rom(void *hal_private,
void *local_buf, uint_t quadlet_count);
static int hci1394_s1394if_phy_filter_set(void *hal_private,
uint64_t mask, uint_t generation);
static int hci1394_s1394if_phy_filter_clr(void *hal_private,
uint64_t mask, uint_t generation);
static int hci1394_s1394if_short_bus_reset(void *hal_private);
static int hci1394_s1394if_csr_read(void *hal_private,
uint_t offset, uint32_t *data);
static int hci1394_s1394if_csr_write(void *hal_private,
uint_t offset, uint32_t data);
static int hci1394_s1394if_csr_cswap32(void *hal_private, uint_t generation,
uint_t offset, uint32_t compare, uint32_t swap, uint32_t *old);
static void hci1394_s1394if_power_state_change(void *hal_private,
h1394_node_pwr_flags_t nodeflags);
h1394_evts_t hci1394_evts = {
H1394_EVTS_V1,
0,
hci1394_s1394if_shutdown,
hci1394_s1394if_phy,
hci1394_s1394if_read,
hci1394_s1394if_read_response,
hci1394_s1394if_write,
hci1394_s1394if_write_response,
hci1394_s1394if_response_complete,
hci1394_s1394if_lock,
hci1394_s1394if_lock_response,
hci1394_alloc_isoch_dma,
hci1394_free_isoch_dma,
hci1394_start_isoch_dma,
hci1394_stop_isoch_dma,
hci1394_update_isoch_dma,
hci1394_s1394if_update_config_rom,
hci1394_s1394if_reset_bus,
hci1394_s1394if_short_bus_reset,
hci1394_s1394if_set_contender_bit,
hci1394_s1394if_set_root_holdoff_bit,
hci1394_s1394if_set_gap_count,
hci1394_s1394if_csr_read,
hci1394_s1394if_csr_write,
hci1394_s1394if_csr_cswap32,
hci1394_s1394if_phy_filter_set,
hci1394_s1394if_phy_filter_clr,
hci1394_s1394if_power_state_change
};
static void
hci1394_s1394if_shutdown(void *hal_private)
{
hci1394_state_t *soft_state;
ASSERT(hal_private != NULL);
soft_state = (hci1394_state_t *)hal_private;
hci1394_shutdown(soft_state->drvinfo.di_dip);
}
static int
hci1394_s1394if_phy(void *hal_private, cmd1394_cmd_t *cmd_id,
h1394_cmd_priv_t *cmd_private, int *result)
{
hci1394_state_t *soft_state;
int status;
ASSERT(hal_private != NULL);
soft_state = (hci1394_state_t *)hal_private;
if (hci1394_state(&soft_state->drvinfo) != HCI1394_NORMAL) {
if (hci1394_state(&soft_state->drvinfo) == HCI1394_BUS_RESET) {
*result = H1394_STATUS_INVALID_BUSGEN;
} else {
*result = H1394_STATUS_INTERNAL_ERROR;
}
return (DDI_FAILURE);
}
status = hci1394_async_phy(soft_state->async, cmd_id, cmd_private,
result);
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static int
hci1394_s1394if_write(void *hal_private, cmd1394_cmd_t *cmd_id,
h1394_cmd_priv_t *cmd_private, int *result)
{
hci1394_state_t *soft_state;
int status;
ASSERT(hal_private != NULL);
soft_state = (hci1394_state_t *)hal_private;
if (hci1394_state(&soft_state->drvinfo) != HCI1394_NORMAL) {
if (hci1394_state(&soft_state->drvinfo) == HCI1394_BUS_RESET) {
*result = H1394_STATUS_INVALID_BUSGEN;
} else {
*result = H1394_STATUS_INTERNAL_ERROR;
}
return (DDI_FAILURE);
}
status = hci1394_async_write(soft_state->async, cmd_id, cmd_private,
result);
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static int
hci1394_s1394if_read(void *hal_private, cmd1394_cmd_t *cmd_id,
h1394_cmd_priv_t *cmd_private, int *result)
{
hci1394_state_t *soft_state;
int status;
ASSERT(hal_private != NULL);
soft_state = (hci1394_state_t *)hal_private;
if (hci1394_state(&soft_state->drvinfo) != HCI1394_NORMAL) {
if (hci1394_state(&soft_state->drvinfo) == HCI1394_BUS_RESET) {
*result = H1394_STATUS_INVALID_BUSGEN;
} else {
*result = H1394_STATUS_INTERNAL_ERROR;
}
return (DDI_FAILURE);
}
status = hci1394_async_read(soft_state->async, cmd_id, cmd_private,
result);
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static int
hci1394_s1394if_lock(void *hal_private, cmd1394_cmd_t *cmd_id,
h1394_cmd_priv_t *cmd_private, int *result)
{
hci1394_state_t *soft_state;
int status;
ASSERT(hal_private != NULL);
soft_state = (hci1394_state_t *)hal_private;
if (hci1394_state(&soft_state->drvinfo) != HCI1394_NORMAL) {
if (hci1394_state(&soft_state->drvinfo) == HCI1394_BUS_RESET) {
*result = H1394_STATUS_INVALID_BUSGEN;
} else {
*result = H1394_STATUS_INTERNAL_ERROR;
}
return (DDI_FAILURE);
}
status = hci1394_async_lock(soft_state->async, cmd_id, cmd_private,
result);
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static int
hci1394_s1394if_write_response(void *hal_private, cmd1394_cmd_t *cmd_id,
h1394_cmd_priv_t *cmd_private, int *result)
{
hci1394_state_t *soft_state;
int status;
ASSERT(hal_private != NULL);
soft_state = (hci1394_state_t *)hal_private;
if (hci1394_state(&soft_state->drvinfo) != HCI1394_NORMAL) {
if (hci1394_state(&soft_state->drvinfo) == HCI1394_BUS_RESET) {
*result = H1394_STATUS_INVALID_BUSGEN;
} else {
*result = H1394_STATUS_INTERNAL_ERROR;
}
return (DDI_FAILURE);
}
status = hci1394_async_write_response(soft_state->async, cmd_id,
cmd_private, result);
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static int
hci1394_s1394if_read_response(void *hal_private, cmd1394_cmd_t *cmd_id,
h1394_cmd_priv_t *cmd_private, int *result)
{
hci1394_state_t *soft_state;
int status;
ASSERT(hal_private != NULL);
soft_state = (hci1394_state_t *)hal_private;
if (hci1394_state(&soft_state->drvinfo) != HCI1394_NORMAL) {
if (hci1394_state(&soft_state->drvinfo) == HCI1394_BUS_RESET) {
*result = H1394_STATUS_INVALID_BUSGEN;
} else {
*result = H1394_STATUS_INTERNAL_ERROR;
}
return (DDI_FAILURE);
}
status = hci1394_async_read_response(soft_state->async, cmd_id,
cmd_private, result);
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static int
hci1394_s1394if_lock_response(void *hal_private, cmd1394_cmd_t *cmd_id,
h1394_cmd_priv_t *cmd_private, int *result)
{
hci1394_state_t *soft_state;
int status;
ASSERT(hal_private != NULL);
soft_state = (hci1394_state_t *)hal_private;
if (hci1394_state(&soft_state->drvinfo) != HCI1394_NORMAL) {
if (hci1394_state(&soft_state->drvinfo) == HCI1394_BUS_RESET) {
*result = H1394_STATUS_INVALID_BUSGEN;
} else {
*result = H1394_STATUS_INTERNAL_ERROR;
}
return (DDI_FAILURE);
}
status = hci1394_async_lock_response(soft_state->async, cmd_id,
cmd_private, result);
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static void
hci1394_s1394if_response_complete(void *hal_private, cmd1394_cmd_t *cmd_id,
h1394_cmd_priv_t *cmd_private)
{
hci1394_state_t *soft_state;
ASSERT(hal_private != NULL);
soft_state = (hci1394_state_t *)hal_private;
hci1394_async_response_complete(soft_state->async, cmd_id, cmd_private);
}
static int
hci1394_s1394if_reset_bus(void *hal_private)
{
hci1394_state_t *soft_state;
int status;
ASSERT(hal_private != NULL);
soft_state = (hci1394_state_t *)hal_private;
if (hci1394_state(&soft_state->drvinfo) == HCI1394_SHUTDOWN) {
return (DDI_FAILURE);
}
status = hci1394_ohci_bus_reset(soft_state->ohci);
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static int
hci1394_s1394if_set_contender_bit(void *hal_private)
{
hci1394_state_t *soft_state;
int status;
ASSERT(hal_private != NULL);
soft_state = (hci1394_state_t *)hal_private;
if (hci1394_state(&soft_state->drvinfo) == HCI1394_SHUTDOWN) {
return (DDI_FAILURE);
}
if (soft_state->halinfo.phy == H1394_PHY_1995) {
return (DDI_FAILURE);
}
status = hci1394_ohci_contender_enable(soft_state->ohci);
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static int
hci1394_s1394if_set_root_holdoff_bit(void *hal_private)
{
hci1394_state_t *soft_state;
int status;
ASSERT(hal_private != NULL);
soft_state = (hci1394_state_t *)hal_private;
if (hci1394_state(&soft_state->drvinfo) == HCI1394_SHUTDOWN) {
return (DDI_FAILURE);
}
status = hci1394_ohci_root_holdoff_enable(soft_state->ohci);
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static int
hci1394_s1394if_set_gap_count(void *hal_private, uint_t gap_count)
{
hci1394_state_t *soft_state;
int status;
ASSERT(hal_private != NULL);
soft_state = (hci1394_state_t *)hal_private;
if (hci1394_state(&soft_state->drvinfo) == HCI1394_SHUTDOWN) {
return (DDI_FAILURE);
}
status = hci1394_ohci_gap_count_set(soft_state->ohci, gap_count);
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static int
hci1394_s1394if_phy_filter_set(void *hal_private,
uint64_t mask, uint_t generation)
{
hci1394_state_t *soft_state;
int status;
ASSERT(hal_private != NULL);
soft_state = (hci1394_state_t *)hal_private;
if (hci1394_state(&soft_state->drvinfo) == HCI1394_SHUTDOWN) {
return (DDI_FAILURE);
}
status = hci1394_ohci_phy_filter_set(soft_state->ohci, mask,
generation);
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static int
hci1394_s1394if_phy_filter_clr(void *hal_private,
uint64_t mask, uint_t generation)
{
hci1394_state_t *soft_state;
int status;
ASSERT(hal_private != NULL);
soft_state = (hci1394_state_t *)hal_private;
if (hci1394_state(&soft_state->drvinfo) == HCI1394_SHUTDOWN) {
return (DDI_FAILURE);
}
status = hci1394_ohci_phy_filter_clr(soft_state->ohci, mask,
generation);
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static int
hci1394_s1394if_short_bus_reset(void *hal_private)
{
hci1394_state_t *soft_state;
int status;
ASSERT(hal_private != NULL);
soft_state = (hci1394_state_t *)hal_private;
if (hci1394_state(&soft_state->drvinfo) == HCI1394_SHUTDOWN) {
return (DDI_FAILURE);
}
if (soft_state->halinfo.phy == H1394_PHY_1995) {
return (DDI_FAILURE);
}
status = hci1394_ohci_bus_reset_short(soft_state->ohci);
if (status != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static int
hci1394_s1394if_update_config_rom(void *hal_private,
void *local_buf, uint_t quadlet_count)
{
hci1394_state_t *soft_state;
ASSERT(hal_private != NULL);
ASSERT(local_buf != NULL);
soft_state = (hci1394_state_t *)hal_private;
if (hci1394_state(&soft_state->drvinfo) == HCI1394_SHUTDOWN) {
return (DDI_FAILURE);
}
hci1394_ohci_cfgrom_update(soft_state->ohci, local_buf, quadlet_count);
return (DDI_SUCCESS);
}
static int
hci1394_s1394if_csr_read(void *hal_private, uint_t offset, uint32_t *data)
{
hci1394_state_t *soft_state;
int status;
ASSERT(hal_private != NULL);
ASSERT(data != NULL);
soft_state = (hci1394_state_t *)hal_private;
if (hci1394_state(&soft_state->drvinfo) == HCI1394_SHUTDOWN) {
return (DDI_FAILURE);
}
switch (offset) {
case CSR_STATE_CLEAR:
hci1394_csr_state_get(soft_state->csr, data);
status = DDI_SUCCESS;
break;
case CSR_STATE_SET:
status = DDI_FAILURE;
break;
case CSR_NODE_IDS:
hci1394_ohci_nodeid_get(soft_state->ohci, data);
status = DDI_SUCCESS;
break;
case CSR_RESET_START:
status = DDI_FAILURE;
break;
case CSR_SPLIT_TIMEOUT_HI:
hci1394_csr_split_timeout_hi_get(soft_state->csr, data);
status = DDI_SUCCESS;
break;
case CSR_SPLIT_TIMEOUT_LO:
hci1394_csr_split_timeout_lo_get(soft_state->csr, data);
status = DDI_SUCCESS;
break;
case CSR_CYCLE_TIME:
hci1394_ohci_cycletime_get(soft_state->ohci, data);
status = DDI_SUCCESS;
break;
case CSR_BUS_TIME:
hci1394_ohci_bustime_get(soft_state->ohci, data);
status = DDI_SUCCESS;
break;
case CSR_BUSY_TIMEOUT:
hci1394_ohci_atreq_retries_get(soft_state->ohci, data);
status = DDI_SUCCESS;
break;
case CSR_BUS_MANAGER_ID:
status = hci1394_ohci_csr_read(soft_state->ohci, 0, data);
break;
case CSR_BANDWIDTH_AVAILABLE:
status = hci1394_ohci_csr_read(soft_state->ohci, 1, data);
break;
case CSR_CHANNELS_AVAILABLE_HI:
status = hci1394_ohci_csr_read(soft_state->ohci, 2, data);
break;
case CSR_CHANNELS_AVAILABLE_LO:
status = hci1394_ohci_csr_read(soft_state->ohci, 3, data);
break;
default:
status = DDI_FAILURE;
break;
}
return (status);
}
static int
hci1394_s1394if_csr_write(void *hal_private, uint_t offset, uint32_t data)
{
hci1394_state_t *soft_state;
int status;
ASSERT(hal_private != NULL);
soft_state = (hci1394_state_t *)hal_private;
if (hci1394_state(&soft_state->drvinfo) == HCI1394_SHUTDOWN) {
return (DDI_FAILURE);
}
switch (offset) {
case CSR_STATE_CLEAR:
hci1394_csr_state_bclr(soft_state->csr, data);
status = DDI_SUCCESS;
break;
case CSR_STATE_SET:
hci1394_csr_state_bset(soft_state->csr, data);
status = DDI_SUCCESS;
break;
case CSR_NODE_IDS:
hci1394_ohci_nodeid_set(soft_state->ohci, data);
status = DDI_SUCCESS;
break;
case CSR_RESET_START:
status = DDI_FAILURE;
break;
case CSR_SPLIT_TIMEOUT_HI:
hci1394_csr_split_timeout_hi_set(soft_state->csr, data);
hci1394_async_pending_timeout_update(soft_state->async,
OHCI_BUS_CYCLE_TO_nS(hci1394_csr_split_timeout_get(
soft_state->csr)));
status = DDI_SUCCESS;
break;
case CSR_SPLIT_TIMEOUT_LO:
hci1394_csr_split_timeout_lo_set(soft_state->csr, data);
hci1394_async_pending_timeout_update(soft_state->async,
OHCI_BUS_CYCLE_TO_nS(hci1394_csr_split_timeout_get(
soft_state->csr)));
status = DDI_SUCCESS;
break;
case CSR_CYCLE_TIME:
hci1394_ohci_cycletime_set(soft_state->ohci, data);
status = DDI_SUCCESS;
break;
case CSR_BUS_TIME:
hci1394_ohci_bustime_set(soft_state->ohci, data);
status = DDI_SUCCESS;
break;
case CSR_BUSY_TIMEOUT:
hci1394_ohci_atreq_retries_set(soft_state->ohci, data);
status = DDI_SUCCESS;
break;
case CSR_BUS_MANAGER_ID:
status = DDI_FAILURE;
break;
case CSR_BANDWIDTH_AVAILABLE:
status = DDI_FAILURE;
break;
case CSR_CHANNELS_AVAILABLE_HI:
status = DDI_FAILURE;
break;
case CSR_CHANNELS_AVAILABLE_LO:
status = DDI_FAILURE;
break;
default:
status = DDI_FAILURE;
break;
}
return (status);
}
static int
hci1394_s1394if_csr_cswap32(void *hal_private, uint_t generation, uint_t offset,
uint32_t compare, uint32_t swap, uint32_t *old)
{
hci1394_state_t *soft_state;
int status;
ASSERT(hal_private != NULL);
ASSERT(old != NULL);
soft_state = (hci1394_state_t *)hal_private;
if (hci1394_state(&soft_state->drvinfo) == HCI1394_SHUTDOWN) {
return (DDI_FAILURE);
}
switch (offset) {
case CSR_STATE_CLEAR:
status = DDI_FAILURE;
break;
case CSR_STATE_SET:
status = DDI_FAILURE;
break;
case CSR_NODE_IDS:
status = DDI_FAILURE;
break;
case CSR_RESET_START:
status = DDI_FAILURE;
break;
case CSR_SPLIT_TIMEOUT_HI:
status = DDI_FAILURE;
break;
case CSR_SPLIT_TIMEOUT_LO:
status = DDI_FAILURE;
break;
case CSR_CYCLE_TIME:
status = DDI_FAILURE;
break;
case CSR_BUS_TIME:
status = DDI_FAILURE;
break;
case CSR_BUSY_TIMEOUT:
status = DDI_FAILURE;
break;
case CSR_BUS_MANAGER_ID:
status = hci1394_ohci_csr_cswap(soft_state->ohci, generation,
OHCI_CSR_SEL_BUS_MGR_ID, compare, swap, old);
break;
case CSR_BANDWIDTH_AVAILABLE:
status = hci1394_ohci_csr_cswap(soft_state->ohci, generation,
OHCI_CSR_SEL_BANDWIDTH_AVAIL, compare, swap, old);
break;
case CSR_CHANNELS_AVAILABLE_HI:
status = hci1394_ohci_csr_cswap(soft_state->ohci, generation,
OHCI_CSR_SEL_CHANS_AVAIL_HI, compare, swap, old);
break;
case CSR_CHANNELS_AVAILABLE_LO:
status = hci1394_ohci_csr_cswap(soft_state->ohci, generation,
OHCI_CSR_SEL_CHANS_AVAIL_LO, compare, swap, old);
break;
default:
status = DDI_FAILURE;
break;
}
return (status);
}
static void
hci1394_s1394if_power_state_change(void *hal_private,
h1394_node_pwr_flags_t nodeflags)
{
}