#include <sys/usb/hcd/xhci/xhci.h>
boolean_t
xhci_ddi_intr_disable(xhci_t *xhcip)
{
int ret;
if (xhcip->xhci_intr_caps & DDI_INTR_FLAG_BLOCK) {
if ((ret = ddi_intr_block_disable(&xhcip->xhci_intr_hdl,
xhcip->xhci_intr_num)) != DDI_SUCCESS) {
xhci_error(xhcip, "failed to block-disable interrupts: "
"%d", ret);
return (B_FALSE);
}
} else {
if ((ret = ddi_intr_disable(xhcip->xhci_intr_hdl)) !=
DDI_SUCCESS) {
xhci_error(xhcip, "failed to disable interrupt: %d",
ret);
return (B_FALSE);
}
}
return (B_TRUE);
}
boolean_t
xhci_ddi_intr_enable(xhci_t *xhcip)
{
int ret;
if (xhcip->xhci_intr_caps & DDI_INTR_FLAG_BLOCK) {
if ((ret = ddi_intr_block_enable(&xhcip->xhci_intr_hdl,
xhcip->xhci_intr_num)) != DDI_SUCCESS) {
xhci_error(xhcip, "failed to block-enable interrupts: "
"%d", ret);
return (B_FALSE);
}
} else {
if ((ret = ddi_intr_enable(xhcip->xhci_intr_hdl)) !=
DDI_SUCCESS) {
xhci_error(xhcip, "failed to enable interrupt: %d",
ret);
return (B_FALSE);
}
}
return (B_TRUE);
}
int
xhci_intr_conf(xhci_t *xhcip)
{
uint32_t reg;
reg = xhci_get32(xhcip, XHCI_R_RUN, XHCI_IMAN(0));
reg |= XHCI_IMAN_INTR_ENA;
xhci_put32(xhcip, XHCI_R_RUN, XHCI_IMAN(0), reg);
xhci_put32(xhcip, XHCI_R_RUN, XHCI_IMOD(0), XHCI_IMOD_DEFAULT);
reg = xhci_get32(xhcip, XHCI_R_OPER, XHCI_USBCMD);
reg |= XHCI_CMD_INTE;
xhci_put32(xhcip, XHCI_R_OPER, XHCI_USBCMD, reg);
if (xhci_check_regs_acc(xhcip) != DDI_FM_OK) {
ddi_fm_service_impact(xhcip->xhci_dip, DDI_SERVICE_LOST);
return (EIO);
}
return (0);
}
uint_t
xhci_intr(caddr_t arg1, caddr_t arg2)
{
uint32_t iman, status;
xhci_t *xhcip = (xhci_t *)(void *)arg1;
uintptr_t vector = (uintptr_t)arg2;
ASSERT0(vector);
status = xhci_get32(xhcip, XHCI_R_OPER, XHCI_USBSTS);
if (xhci_check_regs_acc(xhcip) != DDI_FM_OK) {
xhci_error(xhcip, "failed to read USB status register: "
"encountered fatal FM error, resetting device");
xhci_fm_runtime_reset(xhcip);
return (DDI_INTR_CLAIMED);
}
if ((status & (XHCI_STS_HSE | XHCI_STS_SRE | XHCI_STS_HCE)) != 0) {
xhci_error(xhcip, "found fatal error bit in status register, "
"value: 0x%x: resetting device", status);
xhci_fm_runtime_reset(xhcip);
return (DDI_INTR_CLAIMED);
}
iman = xhci_get32(xhcip, XHCI_R_RUN, XHCI_IMAN(0));
if (xhci_check_regs_acc(xhcip) != DDI_FM_OK) {
xhci_error(xhcip, "failed to read interrupt register 0: "
"encountered fatal FM error, resetting device");
xhci_fm_runtime_reset(xhcip);
return (DDI_INTR_CLAIMED);
}
if (xhcip->xhci_intr_type == DDI_INTR_TYPE_FIXED &&
(iman & XHCI_IMAN_INTR_PEND) == 0) {
return (DDI_INTR_UNCLAIMED);
}
if (xhci_event_process(xhcip) == B_FALSE) {
return (DDI_INTR_CLAIMED);
}
xhci_put32(xhcip, XHCI_R_RUN, XHCI_IMAN(0), iman);
if (xhci_check_regs_acc(xhcip) != DDI_FM_OK) {
xhci_error(xhcip, "failed to write USB status register: "
"encountered fatal FM error, resetting device");
xhci_fm_runtime_reset(xhcip);
}
return (DDI_INTR_CLAIMED);
}