// ------------------------------------------------------------------------------------------------ static void ehci_qh_process(EHCI_Controller* hc, EHCI_QH* qh) { USB_Transfer* t = qh->transfer; if (qh->token & TD_TOK_HALTED) { t->success = false; t->complete = true; } else if (qh->next_link & PTR_TERMINATE) { if (~qh->token & TD_TOK_ACTIVE) { if (qh->token & TD_TOK_DATABUFFER) { console_print(" Data Buffer Error\n"); } if (qh->token & TD_TOK_BABBLE) { console_print(" Babble Detected\n"); } if (qh->token & TD_TOK_XACT) { console_print(" Transaction Error\n"); } if (qh->token & TD_TOK_MMF) { console_print(" Missed Micro-Frame\n"); } t->success = true; t->complete = true; } } if (t->complete) { // Clear transfer from queue qh->transfer = 0; // Update endpoint toggle state if (t->success && t->endp) { t->endp->toggle ^= 1; } // Remove queue from schedule ehci_remove_qh(qh); // Free transfer descriptors EHCI_TD* td = (EHCI_TD*)(uintptr_t)qh->td_head; while (td) { EHCI_TD* next = (EHCI_TD*)(uintptr_t)td->td_next; ehci_free_td(td); td = next; } // Free queue head ehci_free_qh(qh); } }
/* ARGSUSED */ int ehci_hcdi_pipe_close( usba_pipe_handle_data_t *ph, usb_flags_t flags) { ehci_state_t *ehcip = ehci_obtain_state( ph->p_usba_device->usb_root_hub_dip); ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; usb_ep_descr_t *eptd = &ph->p_ep; int error = USB_SUCCESS; USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, "ehci_hcdi_pipe_close: addr = 0x%x, ep%d", ph->p_usba_device->usb_addr, eptd->bEndpointAddress & USB_EP_NUM_MASK); /* Check and handle root hub pipe close */ if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { mutex_enter(&ehcip->ehci_int_mutex); error = ehci_handle_root_hub_pipe_close(ph); mutex_exit(&ehcip->ehci_int_mutex); return (error); } ASSERT(ph->p_hcd_private != NULL); mutex_enter(&ehcip->ehci_int_mutex); /* Set pipe state to pipe close */ pp->pp_state = EHCI_PIPE_STATE_CLOSE; ehci_pipe_cleanup(ehcip, ph); /* * Remove the endpoint descriptor from Host * Controller's appropriate endpoint list. */ ehci_remove_qh(ehcip, pp, B_TRUE); /* Deallocate bandwidth */ if (EHCI_PERIODIC_ENDPOINT(eptd)) { mutex_enter(&ph->p_mutex); ehci_deallocate_bandwidth(ehcip, ph, pp->pp_pnode, pp->pp_smask, pp->pp_cmask); mutex_exit(&ph->p_mutex); } mutex_enter(&ph->p_mutex); /* Destroy the xfer completion condition variable */ cv_destroy(&pp->pp_xfer_cmpl_cv); /* Destory halt completion condition variable */ cv_destroy(&pp->pp_halt_cmpl_cv); /* * Deallocate the hcd private portion * of the pipe handle. */ kmem_free(ph->p_hcd_private, sizeof (ehci_pipe_private_t)); ph->p_hcd_private = NULL; mutex_exit(&ph->p_mutex); USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, "ehci_hcdi_pipe_close: ph = 0x%p", (void *)ph); ehcip->ehci_open_pipe_count--; mutex_exit(&ehcip->ehci_int_mutex); return (error); }