Kernel/UDI - Fix omission of UDI_PCI_VERSION in bus_pci.c
[tpg/acess2.git] / KernelLand / Modules / Interfaces / UDI / trans / bus_pci.c
index ab09aa4..651329d 100644 (file)
@@ -5,6 +5,8 @@
  * trans/bus_pci.c
  * - PCI Bus Driver
  */
+#define DEBUG  0
+#define UDI_PCI_VERSION        0x101
 #include <udi.h>
 #include <udi_physio.h>
 #include <udi_pci.h>
@@ -65,10 +67,11 @@ typedef struct
 
         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 ===
@@ -86,6 +89,7 @@ void  pci_intr_detach_req(udi_intr_detach_cb_t *cb);
 
 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);
 
@@ -153,6 +157,15 @@ void pci_enumerate_req(udi_enumerate_cb_t *cb, udi_ubit8_t enumeration_level)
                        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;
@@ -217,7 +230,7 @@ void pci_intr_attach_req__channel_spawned(udi_cb_t *gcb, udi_channel_t new_chann
        
        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);
 }
@@ -233,6 +246,11 @@ void pci_intr_ch_event_ind(udi_channel_event_cb_t *cb)
 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.
@@ -241,49 +259,96 @@ void pci_intr_event_rdy(udi_intr_event_cb_t *cb)
        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);
        tPCIDev pciid = child_ID;
        // TODO: Cache child mappings   
 
@@ -293,14 +358,20 @@ udi_status_t pci_pio_do_io(uint32_t child_ID, udi_ubit32_t regset_idx, udi_ubit3
                // 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)
                        {
@@ -316,7 +387,7 @@ udi_status_t pci_pio_do_io(uint32_t child_ID, udi_ubit32_t regset_idx, udi_ubit3
                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; }
@@ -350,7 +421,7 @@ udi_primary_init_t  pci_pri_init = {
        .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

UCC git Repository :: git.ucc.asn.au