int native_setup_irq_handler(unsigned int irq) { struct irq_data *data = get_irq_data(irq); if(data->handle == NULL) { return -E_NULL_PTR; } else { setup_irq_handler(irq); } /* now we check if we might have to reset some values.. */ if(data->base_handle == NULL || data->base_handle == &do_irq) { data->base_handle = &do_irq; return -E_SUCCESS; } else { /* * A different base handler has to be used. */ writel((void*)data->irq_base+DYNAMIC_IRQ_HANDLER_VALUE, (uint32_t)data-> base_handle); } return 0; }
uint32_t debug_dynamic_irq() { struct irq_data *data = alloc_irq(); setup_irq_handler(data->irq); debug("irq: %x - vector: %x\n", data->irq, data->irq_config->vector); install_irq_vector(data); return data->irq_config->vector; }
/* UDC ISR function */ void INT_UDC(void) { uint32_t txstat, rxstat; /* read what caused UDC irq */ uint32_t intsrc = INT2FLAG & 0x7fffff; if (intsrc & USBRST_INTR) /* usb reset */ { EN_INT = EN_SUSP_INTR | /* Enable Suspend Irq */ EN_RESUME_INTR | /* Enable Resume Irq */ EN_USBRST_INTR | /* Enable USB Reset Irq */ EN_OUT0_INTR | /* Enable OUT Token receive Irq EP0 */ EN_IN0_INTR | /* Enable IN Token transmit Irq EP0 */ EN_SETUP_INTR; /* Enable SETUP Packet Receive Irq */ TX0CON = TXACKINTEN | /* Set as one to enable the EP0 tx irq */ TXNAK; /* Set as one to response NAK handshake */ RX0CON = RXACKINTEN | RXEPEN | /* Endpoint 0 Enable. When cleared the * endpoint does not respond to an SETUP * or OUT token */ RXNAK; /* Set as one to response NAK handshake */ usb_drv_rcv_done = true; } if (intsrc & SETUP_INTR) /* setup interrupt */ { setup_irq_handler(); } if (intsrc & IN0_INTR) /* ep0 in interrupt */ { txstat = TX0STAT; /* read clears flags */ /* TODO handle errors */ if (txstat & TXACK) /* check TxACK flag */ { /* Decrement by max packet size is intentional. * This way if we have final packet short one we will get negative len * after transfer, which in turn indicates we *don't* need to send * zero length packet. If the final packet is max sized packet we will * get zero len after transfer which indicates we need to send * zero length packet to signal host end of the transfer. */ if (ctrlep[DIR_IN].cnt > 0) { /* we still have data to send */ ep0_in_dma_setup(); } else { if (ctrlep[DIR_IN].cnt == 0) { ep0_in_dma_setup(); } /* final ack received */ usb_drv_send_done = true; } } } if (intsrc & OUT0_INTR) /* ep0 out interrupt */ { rxstat = RX0STAT; /* TODO handle errors */ if (rxstat & RXACK) /* RxACK */ { int xfer_size = rxstat & 0x7ff; ctrlep[DIR_OUT].cnt -= xfer_size; if (ctrlep[DIR_OUT].cnt > 0 && xfer_size == 64) { /* advance the buffer */ ctrlep[DIR_OUT].buf += xfer_size; ep0_out_dma_setup(); } else usb_drv_rcv_done = true; } } if (intsrc & RESUME_INTR) /* usb resume */ { TX0CON |= TXCLR; /* TxClr */ TX0CON &= ~TXCLR; RX0CON |= RXCLR; /* RxClr */ RX0CON &= ~RXCLR; } }