i40e_hmc.cc 3.66 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
#include <stdlib.h>
#include <string.h>
#include <cassert>
#include <iostream>

#include "i40e_bm.h"

#include "i40e_base_wrapper.h"

using namespace i40e;

extern nicbm::Runner *runner;

host_mem_cache::host_mem_cache(i40e_bm &dev_)
    : dev(dev_)
16
17
18
19
20
{
    reset();
}

void host_mem_cache::reset()
Antoine Kaufmann's avatar
Antoine Kaufmann committed
21
22
{
    for (size_t i = 0; i < MAX_SEGMENTS; i++) {
23
        segs[i].addr = 0;
Antoine Kaufmann's avatar
Antoine Kaufmann committed
24
25
26
27
28
29
30
31
        segs[i].pgcount = 0;
        segs[i].valid = false;
        segs[i].direct = false;
    }
}

void host_mem_cache::reg_updated(uint64_t addr)
{
32
33
34
35
36
37
38
39
40
41
    if (addr == I40E_PFHMC_SDCMD) {
        // read/write command for descriptor
        uint32_t cmd = dev.regs.pfhmc_sdcmd;
        uint16_t idx = (cmd & I40E_PFHMC_SDCMD_PMSDIDX_MASK) >>
            I40E_PFHMC_SDCMD_PMSDIDX_SHIFT;

        uint32_t lo = dev.regs.pfhmc_sddatalow;
        uint32_t hi = dev.regs.pfhmc_sddatahigh;
        if ((cmd & I40E_PFHMC_SDCMD_PMSDWR_MASK)) {
            // write
42
#ifdef DEBUG_HMC
43
            std::cerr << "hmc: writing descriptor " << idx << std::endl;
44
#endif
45
46
47
48
49
50
51
52
53

            segs[idx].addr = ((lo & I40E_PFHMC_SDDATALOW_PMSDDATALOW_MASK) >>
                I40E_PFHMC_SDDATALOW_PMSDDATALOW_SHIFT) << 12;
            segs[idx].addr |= ((uint64_t) hi) << 32;
            segs[idx].pgcount = (lo & I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_MASK) >>
                I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT;
            segs[idx].valid = !!(lo & I40E_PFHMC_SDDATALOW_PMSDVALID_MASK);
            segs[idx].direct = !!(lo & I40E_PFHMC_SDDATALOW_PMSDTYPE_MASK);

54
#ifdef DEBUG_HMC
55
56
57
            std::cerr << "    addr=" << segs[idx].addr << " pgcount=" <<
                segs[idx].pgcount << " valid=" << segs[idx].valid <<
                " direct=" << segs[idx].direct << std::endl;
58
#endif
59
60
        } else {
            // read
61
#ifdef DEBUG_HMC
62
            std::cerr << "hmc: reading descriptor " << idx << std::endl;
63
#endif
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

            dev.regs.pfhmc_sddatalow = ((segs[idx].addr >> 12) <<
                    I40E_PFHMC_SDDATALOW_PMSDDATALOW_SHIFT) &
                I40E_PFHMC_SDDATALOW_PMSDDATALOW_MASK;
            dev.regs.pfhmc_sddatalow |= (segs[idx].pgcount <<
                    I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) &
                I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_MASK;
            if (segs[idx].valid)
                dev.regs.pfhmc_sddatalow |= I40E_PFHMC_SDDATALOW_PMSDVALID_MASK;
            if (segs[idx].direct)
                dev.regs.pfhmc_sddatalow |= I40E_PFHMC_SDDATALOW_PMSDTYPE_MASK;
            dev.regs.pfhmc_sddatahigh = segs[idx].addr >> 32;
        }
    }
}

void host_mem_cache::issue_mem_op(mem_op &op)
{
    uint64_t addr = op.dma_addr;
    uint16_t seg_idx = addr >> 21;
    uint16_t seg_idx_last = (addr + op.len - 1) >> 21;
    uint32_t dir_off = addr & ((1 << 21) - 1);
    struct segment *seg = &segs[seg_idx];

    if (seg_idx >= MAX_SEGMENTS) {
        std::cerr << "hmc issue_mem_op: seg index too high " << seg_idx <<
            std::endl;
        abort();
    }

    if (!seg->valid) {
        // TODO: errorinfo and data registers
        std::cerr << "hmc issue_mem_op: segment invalid addr=" << addr <<
            std::endl;
        op.failed = true;
        return;
    }

    if (seg_idx != seg_idx_last) {
        std::cerr << "hmc issue_mem_op: operation crosses segs addr=" <<
            addr << " len=" << op.len << std::endl;
        abort();
    }

    if (!seg->direct) {
        std::cerr << "hmc issue_mem_op: TODO paged ops addr=" << addr <<
            std::endl;
        abort();
    }

    op.failed = false;
    op.dma_addr = seg->addr + dir_off;

117
#ifdef DEBUG_HMC
118
119
    std::cerr << "hmc issue_mem_op: hmc_addr=" << addr << " dma_addr=" <<
        op.dma_addr << " len=" << op.len << std::endl;
120
#endif
121
    runner->issue_dma(op);
Antoine Kaufmann's avatar
Antoine Kaufmann committed
122
}