Commit 556c74dd authored by Jialin Li's avatar Jialin Li
Browse files

Tx completion + MSI interrupt done

parent 8ea6c5de
...@@ -14,14 +14,15 @@ extern "C" { ...@@ -14,14 +14,15 @@ extern "C" {
} }
static void issue_dma_op(corundum::DMAOp *op); static void issue_dma_op(corundum::DMAOp *op);
static void msi_issue(uint8_t vec);
static void eth_send(void *data, size_t len); static void eth_send(void *data, size_t len);
namespace corundum { namespace corundum {
DescRing::DescRing() DescRing::DescRing()
: _dmaAddr(0), _sizeLog(0), _size(0), _sizeMask(0), : _dmaAddr(0), _sizeLog(0), _size(0), _sizeMask(0),
_index(0), _headPtr(0), _tailPtr(0), _currTail(0), _index(0), _headPtr(0), _tailPtr(0),
active(false) _currHead(0), _currTail(0), active(false)
{ {
} }
...@@ -119,7 +120,116 @@ DescRing::empty() ...@@ -119,7 +120,116 @@ DescRing::empty()
return (this->_headPtr == this->_tailPtr); return (this->_headPtr == this->_tailPtr);
} }
TxRing::TxRing() bool
DescRing::full()
{
return (this->_headPtr - this->_tailPtr >= this->_size);
}
EventRing::EventRing()
{
}
EventRing::~EventRing()
{
}
void
EventRing::dmaDone(DMAOp *op)
{
assert(op->write);
switch (op->type) {
case DMA_TYPE_EVENT:
// TODO: assume in order transmission
assert(this->_headPtr == op->tag);
this->_headPtr++;
msi_issue(0);
delete op;
break;
default:
fprintf(stderr, "Unknown DMA type %u\n", op->type);
abort();
}
}
void
EventRing::issueEvent(unsigned type, unsigned source)
{
assert(type == EVENT_TYPE_TX_CPL || type == EVENT_TYPE_RX_CPL);
if (full()) {
fprintf(stderr, "Event ring is rull\n");
abort();
}
addr_t dma_addr = this->_dmaAddr + (this->_currHead & this->_sizeMask) * EVENT_SIZE;
/* Issue DMA write */
DMAOp *op = new DMAOp;
op->type = DMA_TYPE_EVENT;
op->dma_addr = dma_addr;
op->len = EVENT_SIZE;
op->ring = this;
op->tag = this->_currHead;
op->write = true;
Event *event = (Event *)op->data;
memset(event, 0, sizeof(Event));
event->type = type;
event->source = source;
issue_dma_op(op);
this->_currHead++;
}
CplRing::CplRing(EventRing *eventRing)
: eventRing(eventRing)
{
}
CplRing::~CplRing()
{
}
void
CplRing::dmaDone(DMAOp *op)
{
assert(op->write);
switch (op->type) {
case DMA_TYPE_CPL:
// TODO: assume in order transmission
assert(this->_headPtr == op->tag);
this->_headPtr++;
this->eventRing->issueEvent(EVENT_TYPE_TX_CPL, 0);
delete op;
break;
default:
fprintf(stderr, "Unknown DMA type %u\n", op->type);
abort();
}
}
void
CplRing::complete(unsigned index, size_t len)
{
if (full()) {
fprintf(stderr, "Completion ring is full\n");
abort();
}
addr_t dma_addr = this->_dmaAddr + (this->_currHead & this->_sizeMask) * CPL_SIZE;
/* Issue DMA write */
DMAOp *op = new DMAOp;
op->type = DMA_TYPE_CPL;
op->dma_addr = dma_addr;
op->len = CPL_SIZE;
op->ring = this;
op->tag = this->_currHead;
op->write = true;
Cpl *cpl = (Cpl *)op->data;
memset(cpl, 0, sizeof(Cpl));
cpl->index = index;
cpl->len = len;
issue_dma_op(op);
this->_currHead++;
}
TxRing::TxRing(CplRing *cplRing)
: txCplRing(cplRing)
{ {
} }
...@@ -166,6 +276,7 @@ TxRing::dmaDone(DMAOp *op) ...@@ -166,6 +276,7 @@ TxRing::dmaDone(DMAOp *op)
// TODO: assume in order transmission // TODO: assume in order transmission
assert(this->_tailPtr == op->tag); assert(this->_tailPtr == op->tag);
this->_tailPtr++; this->_tailPtr++;
this->txCplRing->complete(op->tag, op->len);
delete op; delete op;
break; break;
default: default:
...@@ -312,6 +423,8 @@ Port::queueDisable() ...@@ -312,6 +423,8 @@ Port::queueDisable()
} }
Corundum::Corundum() Corundum::Corundum()
: txCplRing(&this->eventRing), rxCplRing(&this->eventRing),
txRing(&this->txCplRing)
{ {
this->port.setId(0); this->port.setId(0);
this->port.setFeatures(0x711); this->port.setFeatures(0x711);
...@@ -385,7 +498,7 @@ Corundum::readReg(addr_t addr) ...@@ -385,7 +498,7 @@ Corundum::readReg(addr_t addr)
case IF_REG_PORT_STRIDE: case IF_REG_PORT_STRIDE:
return 0x200000; return 0x200000;
case EVENT_QUEUE_HEAD_PTR_REG: case EVENT_QUEUE_HEAD_PTR_REG:
return this->eqRing.headPtr(); return this->eventRing.headPtr();
case TX_QUEUE_ACTIVE_LOG_SIZE_REG: case TX_QUEUE_ACTIVE_LOG_SIZE_REG:
return this->txRing.sizeLog(); return this->txRing.sizeLog();
case TX_QUEUE_TAIL_PTR_REG: case TX_QUEUE_TAIL_PTR_REG:
...@@ -433,22 +546,22 @@ Corundum::writeReg(addr_t addr, reg_t val) ...@@ -433,22 +546,22 @@ Corundum::writeReg(addr_t addr, reg_t val)
case PHC_REG_PTP_SET_SEC_H: case PHC_REG_PTP_SET_SEC_H:
break; break;
case EVENT_QUEUE_BASE_ADDR_REG: case EVENT_QUEUE_BASE_ADDR_REG:
this->eqRing.setDMALower(val); this->eventRing.setDMALower(val);
break; break;
case EVENT_QUEUE_BASE_ADDR_REG + 4: case EVENT_QUEUE_BASE_ADDR_REG + 4:
this->eqRing.setDMAUpper(val); this->eventRing.setDMAUpper(val);
break; break;
case EVENT_QUEUE_ACTIVE_LOG_SIZE_REG: case EVENT_QUEUE_ACTIVE_LOG_SIZE_REG:
this->eqRing.setSizeLog(val); this->eventRing.setSizeLog(val);
break; break;
case EVENT_QUEUE_INTERRUPT_INDEX_REG: case EVENT_QUEUE_INTERRUPT_INDEX_REG:
this->eqRing.setIndex(val); this->eventRing.setIndex(val);
break; break;
case EVENT_QUEUE_HEAD_PTR_REG: case EVENT_QUEUE_HEAD_PTR_REG:
this->eqRing.setHeadPtr(val); this->eventRing.setHeadPtr(val);
break; break;
case EVENT_QUEUE_TAIL_PTR_REG: case EVENT_QUEUE_TAIL_PTR_REG:
this->eqRing.setTailPtr(val); this->eventRing.setTailPtr(val);
break; break;
case TX_QUEUE_BASE_ADDR_REG: case TX_QUEUE_BASE_ADDR_REG:
this->txRing.setDMALower(val); this->txRing.setDMALower(val);
...@@ -605,6 +718,20 @@ issue_dma_op(DMAOp *op) ...@@ -605,6 +718,20 @@ issue_dma_op(DMAOp *op)
} }
} }
static void
msi_issue(uint8_t vec)
{
volatile union cosim_pcie_proto_d2h *msg = d2h_alloc();
printf("issue MSI interrupt vec %u\n", vec);
volatile struct cosim_pcie_proto_d2h_interrupt *intr = &msg->interrupt;
intr->vector = vec;
intr->inttype = COSIM_PCIE_PROTO_INT_MSI;
// WMB();
intr->own_type = COSIM_PCIE_PROTO_D2H_MSG_INTERRUPT |
COSIM_PCIE_PROTO_D2H_OWN_HOST;
}
static void static void
h2d_read(Corundum &nic, volatile struct cosim_pcie_proto_h2d_read *read) h2d_read(Corundum &nic, volatile struct cosim_pcie_proto_h2d_read *read)
{ {
......
...@@ -94,6 +94,8 @@ typedef uint16_t ptr_t; ...@@ -94,6 +94,8 @@ typedef uint16_t ptr_t;
namespace corundum { namespace corundum {
#define DESC_SIZE 16 #define DESC_SIZE 16
#define CPL_SIZE 32
#define EVENT_SIZE 32
#define MAX_DMA_LEN 2048 #define MAX_DMA_LEN 2048
class DescRing; class DescRing;
...@@ -105,9 +107,35 @@ struct Desc { ...@@ -105,9 +107,35 @@ struct Desc {
uint64_t addr; uint64_t addr;
} __attribute__((packed)) ; } __attribute__((packed)) ;
struct Cpl {
uint16_t queue;
uint16_t index;
uint16_t len;
uint16_t rsvd0;
uint32_t ts_ns;
uint16_t ts_s;
uint16_t rx_csum;
uint32_t rx_hash;
uint8_t rx_hash_type;
uint8_t rsvd1;
uint8_t rsvd2;
uint8_t rsvd3;
uint32_t rsvd4;
uint32_t rsvd5;
} __attribute__((packed)) ;
#define EVENT_TYPE_TX_CPL 0x0000
#define EVENT_TYPE_RX_CPL 0x0001
struct Event {
uint16_t type;
uint16_t source;
} __attribute__((packed)) ;
#define DMA_TYPE_DESC 0 #define DMA_TYPE_DESC 0
#define DMA_TYPE_MEM 1 #define DMA_TYPE_MEM 1
#define DMA_TYPE_CPL 2
#define DMA_TYPE_EVENT 3
struct DMAOp { struct DMAOp {
uint8_t type; uint8_t type;
...@@ -141,6 +169,7 @@ public: ...@@ -141,6 +169,7 @@ public:
protected: protected:
bool empty(); bool empty();
bool full();
addr_t _dmaAddr; addr_t _dmaAddr;
size_t _sizeLog; size_t _sizeLog;
...@@ -149,17 +178,42 @@ protected: ...@@ -149,17 +178,42 @@ protected:
unsigned _index; unsigned _index;
ptr_t _headPtr; ptr_t _headPtr;
ptr_t _tailPtr; ptr_t _tailPtr;
ptr_t _currHead;
ptr_t _currTail; ptr_t _currTail;
bool active; bool active;
}; };
class EventRing : public DescRing {
public:
EventRing();
~EventRing();
virtual void dmaDone(DMAOp *op) override;
void issueEvent(unsigned type, unsigned source);
};
class CplRing : public DescRing {
public:
CplRing(EventRing *eventRing);
~CplRing();
virtual void dmaDone(DMAOp *op) override;
void complete(unsigned index, size_t len);
private:
EventRing *eventRing;
};
class TxRing : public DescRing { class TxRing : public DescRing {
public: public:
TxRing(); TxRing(CplRing *cplRing);
~TxRing(); ~TxRing();
virtual void setHeadPtr(ptr_t ptr) override; virtual void setHeadPtr(ptr_t ptr) override;
virtual void dmaDone(DMAOp *op) override; virtual void dmaDone(DMAOp *op) override;
private:
CplRing *txCplRing;
}; };
class Port { class Port {
...@@ -211,11 +265,11 @@ public: ...@@ -211,11 +265,11 @@ public:
void writeReg(addr_t addr, reg_t val); void writeReg(addr_t addr, reg_t val);
private: private:
DescRing eqRing; EventRing eventRing;
TxRing txRing; TxRing txRing;
DescRing txCplRing; CplRing txCplRing;
DescRing rxRing; DescRing rxRing;
DescRing rxCplRing; CplRing rxCplRing;
Port port; Port port;
}; };
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment