coord.h 3.07 KB
Newer Older
Antoine Kaufmann's avatar
Antoine Kaufmann committed
1
2
3
4
5
6
7
8
9
10
#ifndef COORD_H_
#define COORD_H_

#include <deque>
#include <map>
#include <iostream>

#include "debug.h"

class DMAOp;
11
struct MMIOOp;
Antoine Kaufmann's avatar
Antoine Kaufmann committed
12
13
14

void pci_dma_issue(DMAOp *op);
void pci_msi_issue(uint8_t vec);
15
void pci_rwcomp_issue(MMIOOp *op);
Antoine Kaufmann's avatar
Antoine Kaufmann committed
16
17
18
19
20
21

class PCICoordinator {
    protected:
        struct PCIOp {
            union {
                DMAOp *dma_op;
22
                MMIOOp *mmio_op;
Antoine Kaufmann's avatar
Antoine Kaufmann committed
23
24
                uint32_t msi_vec;
            };
25
26
27
28
29
            enum {
                OP_DMA,
                OP_MSI,
                OP_RWCOMP,
            } type;
Antoine Kaufmann's avatar
Antoine Kaufmann committed
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
            bool ready;
        };

        std::deque<PCIOp *> queue;
        std::map<DMAOp *, PCIOp *> dmamap;

        void process()
        {
            PCIOp *op;
            while (!queue.empty()) {
                op = queue.front();
                if (!op->ready)
                    break;

                queue.pop_front();
45
                if (op->type == PCIOp::OP_MSI) {
Antoine Kaufmann's avatar
Antoine Kaufmann committed
46
#ifdef COORD_DEBUG
47
                    std::cout << main_time << " issuing msi " << op->msi_vec << std::endl;
Antoine Kaufmann's avatar
Antoine Kaufmann committed
48
49
#endif
                    pci_msi_issue(op->msi_vec);
50
                } else if (op->type == PCIOp::OP_DMA) {
Antoine Kaufmann's avatar
Antoine Kaufmann committed
51
#ifdef COORD_DEBUG
52
                    std::cout << main_time << " issuing dma " << op->dma_op << std::endl;
Antoine Kaufmann's avatar
Antoine Kaufmann committed
53
54
55
#endif
                    pci_dma_issue(op->dma_op);
                    dmamap.erase(op->dma_op);
56
57
                } else if (op->type == PCIOp::OP_RWCOMP) {
#ifdef COORD_DEBUG
58
                    std::cout << main_time << " issuing mmio " << op->mmio_op << std::endl;
59
60
61
62
#endif
                    pci_rwcomp_issue(op->mmio_op);
                } else {
                    throw "unknown type";
Antoine Kaufmann's avatar
Antoine Kaufmann committed
63
                }
64

Antoine Kaufmann's avatar
Antoine Kaufmann committed
65
66
67
68
69
70
71
72
                delete op;
            }
        }

    public:
        void dma_register(DMAOp *dma_op, bool ready)
        {
#ifdef COORD_DEBUG
73
            std::cout << main_time << " registering dma op " << dma_op << "  " << ready << std::endl;
Antoine Kaufmann's avatar
Antoine Kaufmann committed
74
75
76
#endif
            PCIOp *op = new PCIOp;
            op->dma_op = dma_op;
77
            op->type = PCIOp::OP_DMA;
Antoine Kaufmann's avatar
Antoine Kaufmann committed
78
79
80
81
82
83
84
85
86
87
88
            op->ready = ready;

            queue.push_back(op);
            dmamap[dma_op] = op;

            process();
        }

        void dma_mark_ready(DMAOp *op)
        {
#ifdef COORD_DEBUG
89
            std::cout << main_time << " readying dma op " << op <<  std::endl;
Antoine Kaufmann's avatar
Antoine Kaufmann committed
90
91
92
93
94
95
96
97
98
#endif
            dmamap[op]->ready = true;

            process();
        }

        void msi_enqueue(uint32_t vec)
        {
#ifdef COORD_DEBUG
99
            std::cout << main_time << " enqueuing MSI " << vec <<  std::endl;
Antoine Kaufmann's avatar
Antoine Kaufmann committed
100
101
102
#endif
            PCIOp *op = new PCIOp;
            op->msi_vec = vec;
103
104
105
106
107
108
109
110
111
112
            op->type = PCIOp::OP_MSI;
            op->ready = true;
            queue.push_back(op);

            process();
        }

        void mmio_comp_enqueue(MMIOOp *mmio_op)
        {
#ifdef COORD_DEBUG
113
            std::cout << main_time << " enqueuing MMIO comp " << mmio_op <<  std::endl;
114
115
116
117
#endif
            PCIOp *op = new PCIOp;
            op->mmio_op = mmio_op;
            op->type = PCIOp::OP_RWCOMP;
Antoine Kaufmann's avatar
Antoine Kaufmann committed
118
119
120
121
            op->ready = true;
            queue.push_back(op);

            process();
122

Antoine Kaufmann's avatar
Antoine Kaufmann committed
123
124
125
126
127
128
        }
};



#endif