coord.h 2.11 KB
Newer Older
Antoine Kaufmann's avatar
Antoine Kaufmann committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#ifndef COORD_H_
#define COORD_H_

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

#include "debug.h"

class DMAOp;

void pci_dma_issue(DMAOp *op);
void pci_msi_issue(uint8_t vec);

class PCICoordinator {
    protected:
        struct PCIOp {
            union {
                DMAOp *dma_op;
                uint32_t msi_vec;
            };
            bool isDma;
            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();
                if (!op->isDma) {
#ifdef COORD_DEBUG
                    std::cout << "issuing msi " << op->msi_vec << std::endl;
#endif
                    pci_msi_issue(op->msi_vec);
                } else {
#ifdef COORD_DEBUG
                    std::cout << "issuing dma " << op->dma_op << std::endl;
#endif
                    pci_dma_issue(op->dma_op);
                    dmamap.erase(op->dma_op);
                }
                delete op;
            }
        }

    public:
        void dma_register(DMAOp *dma_op, bool ready)
        {
#ifdef COORD_DEBUG
            std::cout << "registering dma op " << dma_op << "  " << ready << std::endl;
#endif
            PCIOp *op = new PCIOp;
            op->dma_op = dma_op;
            op->isDma = true;
            op->ready = ready;

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

            process();
        }

        void dma_mark_ready(DMAOp *op)
        {
#ifdef COORD_DEBUG
            std::cout << "readying dma op " << op <<  std::endl;
#endif
            dmamap[op]->ready = true;

            process();
        }

        void msi_enqueue(uint32_t vec)
        {
#ifdef COORD_DEBUG
            std::cout << "enqueuing MSI " << vec <<  std::endl;
#endif
            PCIOp *op = new PCIOp;
            op->msi_vec = vec;
            op->isDma = false;
            op->ready = true;
            queue.push_back(op);

            process();
        }
};



#endif