* trans/bus_pci.c
* - PCI Bus Driver
*/
-#define DEBUG 1
+#define DEBUG 0
#include <udi.h>
#include <udi_physio.h>
#include <udi_pci.h>
int interrupt_handle;
- udi_pio_handle_t intr_preprocessing;
+ udi_pio_handle_t intr_preprocessing;
udi_intr_event_cb_t *event_cbs[PCI_MAX_EVENT_CBS];
- int event_cb_wr_ofs;
- int event_cb_rd_ofs;
+ udi_index_t event_cb_wr_ofs;
+ udi_index_t event_cb_rd_ofs;
+ int bIntrEnabled;
} pci_child_chan_context_t;
// === PROTOTYPES ===
void pci_intr_ch_event_ind(udi_channel_event_cb_t *cb);
void pci_intr_event_rdy(udi_intr_event_cb_t *cb);
+void pci_intr_event_rdy__irqs_enabled(udi_cb_t *gcb, udi_buf_t *newbuf, udi_status_t status, udi_ubit16_t result);
void pci_intr_handler(int irq, void *void_context);
void pci_intr_handle__trans_done(udi_cb_t *gcb, udi_buf_t *new_buf, udi_status_t status, udi_ubit16_t result);
attr_list ++;
DPT_SET_ATTR32(attr_list, "pci_device_id", dev);
attr_list ++;
+
+ DPT_SET_ATTR32(attr_list, "pci_baseclass", class >> 16);
+ attr_list ++;
+ DPT_SET_ATTR32(attr_list, "pci_base_class", class >> 16); // E20010702.1
+ attr_list ++;
+ DPT_SET_ATTR32(attr_list, "pci_sub_class", (class >> 8) & 0xFF);
+ attr_list ++;
+ DPT_SET_ATTR32(attr_list, "pci_prog_if", (class >> 0) & 0xFF);
+ attr_list ++;
cb->attr_valid_length = attr_list - cb->attr_list;
cb->child_ID = rdata->cur_iter;
context->interrupt_handle = IRQ_AddHandler(
PCI_GetIRQ(context->child_chan_context.child_ID),
- pci_intr_handler, new_channel);
+ pci_intr_handler, context);
udi_intr_attach_ack(cb, UDI_OK);
}
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{%p}]", context->event_cb_rd_ofs, context->event_cb_wr_ofs, cb, cb->event_buf);
if( context->event_cbs[context->event_cb_wr_ofs] )
{
// oops, overrun.
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)
+{
+ // Do 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);
+ ASSERT(cb->gcb.scratch);
if( UDI_HANDLE_IS_NULL(context->intr_preprocessing, udi_pio_handle_t) )
{
+ // TODO: Ensure region is an interrupt region
udi_intr_event_ind(cb, 0);
}
else
{
// Processing
+ *(udi_ubit8_t*)(cb->gcb.scratch) = 0;
// - 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);
+ // V V V
}
}
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);
+ LOG("cb(%p)->event_buf=%p, new_buf=%p",
+ cb, cb->event_buf, new_buf);
+ // TODO: Buffers should not change
+ cb->event_buf = new_buf;
cb->intr_result = result;
- udi_intr_event_ind(cb, UDI_INTR_PREPROCESSED);
+ udi_ubit8_t intr_status = *(udi_ubit8_t*)(gcb->scratch);
+ if( intr_status & UDI_INTR_UNCLAIMED )
+ {
+ // Not claimed, next please.
+ // NOTE: Same as no event in the acess model
+ LOG("Unclaimed");
+ pci_intr_event_rdy(cb);
+ }
+ else if( intr_status & UDI_INTR_NO_EVENT )
+ {
+ // No event should be generated, return cb to pool
+ // EVIL!
+ pci_intr_event_rdy(cb);
+ LOG("No event, return cb to pool");
+ }
+ else
+ {
+ LOG("Inform driver");
+ udi_intr_event_ind(cb, UDI_INTR_PREPROCESSED);
+ }
}
// - physio hooks
udi_status_t pci_pio_do_io(uint32_t child_ID, udi_ubit32_t regset_idx, udi_ubit32_t ofs, udi_ubit8_t len,
void *data, bool isOutput)
{
- LOG("child_ID=%i, regset_idx=%i,ofs=0x%x,len=%i,data=%p,isOutput=%b",
- child_ID, regset_idx, ofs, len, data, isOutput);
+// LOG("child_ID=%i, regset_idx=%i,ofs=0x%x,len=%i,data=%p,isOutput=%b",
+// child_ID, regset_idx, ofs, len, data, isOutput);
tPCIDev pciid = child_ID;
// TODO: Cache child mappings
// TODO:
return UDI_STAT_NOT_SUPPORTED;
case UDI_PCI_BAR_0 ... UDI_PCI_BAR_5: {
- Uint64 bar = PCI_GetBAR(pciid, regset_idx);
+ Uint32 bar = PCI_GetBAR(pciid, regset_idx);
if(bar & 1)
{
// IO BAR
bar &= ~3;
#define _IO(fc, type) do {\
- if( isOutput ) out##fc(bar+ofs, *(type*)data); \
- else *(type*)data = in##fc(bar+ofs); \
+ if( isOutput ) { \
+ /*LOG("out"#fc"(0x%x, 0x%x)",bar+ofs,*(type*)data);*/\
+ out##fc(bar+ofs, *(type*)data); \
+ } \
+ else { \
+ *(type*)data = in##fc(bar+ofs); \
+ /*LOG("in"#fc"(0x%x) = 0x%x",bar+ofs,*(type*)data);*/\
+ }\
} while(0)
switch(len)
{
else
{
// Memory BAR
- bar = PCI_GetValidBAR(pciid, regset_idx, PCI_BARTYPE_MEM);
+ //Uint64 longbar = PCI_GetValidBAR(pciid, regset_idx, PCI_BARTYPE_MEM);
return UDI_STAT_NOT_SUPPORTED;
}
break; }
.mgmt_ops = &pci_mgmt_ops,
.mgmt_op_flags = pci_mgmt_op_flags,
.mgmt_scratch_requirement = 0,
- .enumeration_attr_list_length = 4,
+ .enumeration_attr_list_length = 7,
.rdata_size = sizeof(pci_rdata_t),
.child_data_size = 0,
.per_parent_paths = 0