+ udi_cb_t *gcb = UDI_GCB(cb);
+ ne2k_rdata_t *rdata = gcb->context;
+
+ // Set up PIO handles
+ rdata->init.pio_index = -1;
+ ne2k_bus_dev_bind__pio_map(gcb, UDI_NULL_PIO_HANDLE);
+}
+void ne2k_bus_dev_bind__pio_map(udi_cb_t *gcb, udi_pio_handle_t new_pio_handle)
+{
+ ne2k_rdata_t *rdata = gcb->context;
+
+ if( rdata->init.pio_index != (udi_index_t)-1 )
+ {
+ rdata->pio_handles[rdata->init.pio_index] = new_pio_handle;
+ udi_debug_printf("PIO %i = %p\n", rdata->init.pio_index, new_pio_handle);
+ }
+ rdata->init.pio_index ++;
+ if( rdata->init.pio_index < NE2K_NUM_PIO_OPS )
+ {
+ udi_pio_map(ne2k_bus_dev_bind__pio_map, gcb,
+ UDI_PCI_BAR_0, 0, 0x20,
+ ne2k_pio_ops[rdata->init.pio_index].trans_list,
+ ne2k_pio_ops[rdata->init.pio_index].list_length,
+ UDI_PIO_LITTLE_ENDIAN, 0, 0
+ );
+ return ;
+ }
+
+ // Next: Bind interrupt
+ // - spawn_idx = Interrupt number (0)
+ udi_channel_spawn(ne2k_bus_dev_bind__intr_chanel, gcb, gcb->channel,
+ 0, NE2K_OPS_IRQ, rdata);
+ // V V V V
+}
+void ne2k_bus_dev_bind__intr_chanel(udi_cb_t *gcb, udi_channel_t new_channel)
+{
+ ne2k_rdata_t *rdata = gcb->context;
+
+ rdata->interrupt_channel = new_channel;
+
+ udi_cb_alloc(ne2k_bus_dev_bind__intr_attach, gcb, NE2K_CB_INTR, gcb->channel);
+ // V V V V
+}
+void ne2k_bus_dev_bind__intr_attach(udi_cb_t *gcb, udi_cb_t *new_cb)
+{
+ ne2k_rdata_t *rdata = gcb->context;
+ if( !new_cb )
+ {
+ // Oh...
+ udi_channel_event_complete( UDI_MCB(rdata->active_cb, udi_channel_event_cb_t),
+ UDI_STAT_RESOURCE_UNAVAIL );
+ return ;
+ }
+ udi_intr_attach_cb_t *intr_cb = UDI_MCB(new_cb, udi_intr_attach_cb_t);
+ intr_cb->interrupt_idx = 0;
+ intr_cb->min_event_pend = 2;
+ intr_cb->preprocessing_handle = rdata->pio_handles[NE2K_PIO_IRQACK];
+ udi_intr_attach_req(intr_cb);
+ // continued in ne2k_bus_dev_intr_attach_ack