Example #1
0
void INT_USB_FUNC(void)
{
    /* some bits in GINTSTS can be set even though we didn't enable the interrupt source
     * so AND it with the actual mask */
    unsigned long sts = GINTSTS & GINTMSK;
    logf("usb-drv: INT 0x%lx", sts);

    if(sts & GINTMSK_usbreset)
    {
        DCFG &= ~bitm(DCFG, devadr); /* Address 0 */
        reset_endpoints();
        usb_core_bus_reset();
    }

    if(sts & GINTMSK_enumdone)  /* enumeration done, we now know the speed */
    {
        /* Set up the maximum packet sizes accordingly */
        uint32_t maxpacket = (usb_drv_port_speed() ? 512 : 64) << DEPCTL_mps_bitp;
        for (int dir = 0; dir < 2; dir++)
        {
            bool out = dir == DIR_OUT;
            for (unsigned i = 1; i < num_eps(out); i++)
            {
                int ep = (out ? out_ep_list : in_ep_list)[i];
                DEPCTL(ep, out) &= ~(DEPCTL_mps_bits << DEPCTL_mps_bitp);
                DEPCTL(ep, out) |= maxpacket;
            }
        }
    }

    if(sts & (GINTMSK_outepintr | GINTMSK_inepintr))
    {
        unsigned long daint = DAINT;

        for (int i = 0; i < USB_NUM_ENDPOINTS; i++)
        {
            if (daint & DAINT_IN_EP(i))
                handle_ep_int(i, false);
            if (daint & DAINT_OUT_EP(i))
                handle_ep_int(i, true);
        }

        DAINT = daint;
    }

    if(sts & GINTMSK_disconnect)
        cancel_all_transfers(true);

    GINTSTS = sts;
}
Example #2
0
/* IRQ handler */
void INT_USB_FUNC(void)
{
    int i;
    uint32_t ints = GINTSTS;
    uint32_t epints;
    if (ints & 0x1000)  /* bus reset */
    {
        DCFG = 4;  /* Address 0 */
        reset_endpoints(1);
        usb_core_bus_reset();
    }

    if (ints & 0x2000)  /* enumeration done, we now know the speed */
    {
        /* Set up the maximum packet sizes accordingly */
        uint32_t maxpacket = usb_drv_port_speed() ? 512 : 64;
        DIEPCTL1 = (DIEPCTL1 & ~0x000003FF) | maxpacket;
        DOEPCTL2 = (DOEPCTL2 & ~0x000003FF) | maxpacket;
        DIEPCTL3 = (DIEPCTL3 & ~0x000003FF) | maxpacket;
        DOEPCTL4 = (DOEPCTL4 & ~0x000003FF) | maxpacket;
    }

    if (ints & 0x40000)  /* IN EP event */
        for (i = 0; i < 4; i += i + 1)  // 0, 1, 3
            if ((epints = DIEPINT(i)))
            {
                if (epints & 1)  /* Transfer completed */
                {
                    invalidate_dcache();
                    int bytes = endpoints[i].size - (DIEPTSIZ(i) & 0x3FFFF);
                    if (endpoints[i].busy)
                    {
                        endpoints[i].busy = false;
                        endpoints[i].rc = 0;
                        endpoints[i].done = true;
                        usb_core_transfer_complete(i, USB_DIR_IN, 0, bytes);
                        semaphore_release(&endpoints[i].complete);
                    }
                }
                if (epints & 4)  /* AHB error */
                    panicf("USB: AHB error on IN EP%d", i);
                if (epints & 8)  /* Timeout */
                {
                    if (endpoints[i].busy)
                    {
                        endpoints[i].busy = false;
                        endpoints[i].rc = 1;
                        endpoints[i].done = true;
                        semaphore_release(&endpoints[i].complete);
                    }
                }
                DIEPINT(i) = epints;
            }

    if (ints & 0x80000)  /* OUT EP event */
        for (i = 0; i < USB_NUM_ENDPOINTS; i += 2)
            if ((epints = DOEPINT(i)))
            {
                if (epints & 1)  /* Transfer completed */
                {
                    invalidate_dcache();
                    int bytes = endpoints[i].size - (DOEPTSIZ(i) & 0x3FFFF);
                    if (endpoints[i].busy)
                    {
                        endpoints[i].busy = false;
                        endpoints[i].rc = 0;
                        endpoints[i].done = true;
                        usb_core_transfer_complete(i, USB_DIR_OUT, 0, bytes);
                        semaphore_release(&endpoints[i].complete);
                    }
                }
                if (epints & 4)  /* AHB error */
                    panicf("USB: AHB error on OUT EP%d", i);
                if (epints & 8)  /* SETUP phase done */
                {
                    invalidate_dcache();
                    if (i == 0)
                    {
                        if (ctrlreq.bRequest == 5)
                        {
                            /* Already set the new address here,
                               before passing the packet to the core.
                               See below (usb_drv_set_address) for details. */
                            DCFG = (DCFG & ~0x7F0) | (ctrlreq.wValue << 4);
                        }
                        usb_core_control_request(&ctrlreq);
                    }
                    else panicf("USB: SETUP done on OUT EP%d!?", i);
                }
                /* Make sure EP0 OUT is set up to accept the next request */
                if (!i)
                {
                    DOEPTSIZ0 = 0x20080040;
                    DOEPDMA0 = &ctrlreq;
                    DOEPCTL0 |= 0x84000000;
                }
                DOEPINT(i) = epints;
            }

    GINTSTS = ints;
}