Exemplo n.º 1
0
Arquivo: ehci.c Projeto: MWDD/osdev
// ------------------------------------------------------------------------------------------------
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);
    }
}
Exemplo n.º 2
0
/* 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);
}