+void pci_intr_ch_event_ind(udi_channel_event_cb_t *cb)
+{
+ UNIMPLEMENTED();
+}
+void pci_intr_event_rdy(udi_intr_event_cb_t *cb)
+{
+ pci_child_chan_context_t *context = UDI_GCB(cb)->context;
+
+ ASSERTC(context->event_cb_rd_ofs, <, PCI_MAX_EVENT_CBS);
+ ASSERTC(context->event_cb_wr_ofs, <, PCI_MAX_EVENT_CBS);
+
+ LOG("Rd %i, Wr %i [WR %p]", context->event_cb_rd_ofs, context->event_cb_wr_ofs, cb);
+ if( context->event_cbs[context->event_cb_wr_ofs] )
+ {
+ // oops, overrun.
+ return ;
+ }
+ context->event_cbs[context->event_cb_wr_ofs++] = cb;
+ if( context->event_cb_wr_ofs == PCI_MAX_EVENT_CBS )
+ context->event_cb_wr_ofs = 0;
+
+ // TODO: Fire once >= min_event_pend CBs are recieved
+ if( !context->bIntrEnabled )
+ {
+ context->bIntrEnabled = 1;
+ udi_pio_trans(pci_intr_event_rdy__irqs_enabled, NULL, context->intr_preprocessing, 0, NULL, NULL);
+ }
+}
+void pci_intr_event_rdy__irqs_enabled(udi_cb_t *gcb, udi_buf_t *newbuf, udi_status_t status, udi_ubit16_t result)
+{
+ // nothing
+}
+
+void pci_intr_handler(int irq, void *void_context)
+{
+ pci_child_chan_context_t *context = void_context;
+
+ LOG("irq=%i, context=%p", irq, context);
+
+ if( context->event_cb_rd_ofs == context->event_cb_wr_ofs ) {
+ // Dropped
+ return ;
+ }
+
+ ASSERTC(context->event_cb_rd_ofs, <, PCI_MAX_EVENT_CBS);
+ ASSERTC(context->event_cb_wr_ofs, <, PCI_MAX_EVENT_CBS);
+
+ udi_intr_event_cb_t *cb = context->event_cbs[context->event_cb_rd_ofs];
+ LOG("Rd %i, Wr %i [RD %p]", context->event_cb_rd_ofs, context->event_cb_wr_ofs, cb);
+ context->event_cbs[context->event_cb_rd_ofs] = NULL;
+ context->event_cb_rd_ofs ++;
+ if( context->event_cb_rd_ofs == PCI_MAX_EVENT_CBS )
+ context->event_cb_rd_ofs = 0;
+ ASSERT(cb);
+
+ if( UDI_HANDLE_IS_NULL(context->intr_preprocessing, udi_pio_handle_t) )
+ {
+ udi_intr_event_ind(cb, 0);
+ }
+ else
+ {
+ // Processing
+ // - no event info, so mem_ptr=NULL
+ udi_pio_trans(pci_intr_handle__trans_done, UDI_GCB(cb),
+ context->intr_preprocessing, 1, cb->event_buf, NULL);
+ }
+}
+
+void pci_intr_handle__trans_done(udi_cb_t *gcb, udi_buf_t *new_buf, udi_status_t status, udi_ubit16_t result)
+{
+ udi_intr_event_cb_t *cb = UDI_MCB(gcb, udi_intr_event_cb_t);
+
+ cb->intr_result = result;
+
+ udi_intr_event_ind(cb, UDI_INTR_PREPROCESSED);
+}
+