* Copyright (c) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved.
*
* UniProton is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* See the Mulan PSL v2 for more details.
* Create: 2023-09-14
* Description: ringbuffer实现
*/
#include <string.h>
#include "prt_typedef.h"
#include "gdbstub_common.h"
#define LINE_BUF_SIZE 128
typedef struct RingBuffer {
unsigned int in;
unsigned int out;
unsigned int len;
unsigned int reserved;
char data[0];
} RBuffer;
typedef struct LineBuffer {
char data[LINE_BUF_SIZE];
int avails;
int idx;
} LBuffer;
static STUB_DATA RBuffer *g_rxRBuffer;
static STUB_DATA RBuffer *g_txRBuffer;
static STUB_DATA LBuffer g_txLBuffer;
static STUB_DATA LBuffer g_rxLBuffer;
#ifdef __x86_64__
#define WMB() __asm__ volatile("sfence" ::: "memory")
#elif __aarch64__
#define DSB(opt) __asm__ volatile("dsb " #opt : : : "memory")
#define WMB() DSB(st)
#else
#error "unsupported arch"
#endif
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
* internal helper to calculate the unused elements in a fifo
*/
static inline unsigned int FifoUnused(struct RingBuffer *fifo)
{
return fifo->len - (fifo->in - fifo->out);
}
static STUB_TEXT void FifoCopyIn(struct RingBuffer *fifo, const void *src, unsigned int len, unsigned int off)
{
unsigned int size = fifo->len;
unsigned int l;
off = off % size;
l = MIN(len, size - off);
memcpy(fifo->data + off, src, l);
memcpy(fifo->data, src + l, len - l);
* make sure that the data in the fifo is up to date before
* incrementing the fifo->in index counter
*/
WMB();
}
STUB_TEXT unsigned int FifoIn(struct RingBuffer *fifo, const void *buf, unsigned int len)
{
unsigned int l;
l = FifoUnused(fifo);
if (len > l)
len = l;
FifoCopyIn(fifo, buf, len, fifo->in);
fifo->in += len;
return len;
}
static STUB_TEXT void FifoCopyOut(struct RingBuffer *fifo, void *dst, unsigned int len, unsigned int off)
{
unsigned int size = fifo->len;
unsigned int l;
off %= size;
l = MIN(len, size - off);
memcpy(dst, fifo->data + off, l);
memcpy(dst + l, fifo->data, len - l);
* make sure that the data is copied before
* incrementing the fifo->out index counter
*/
WMB();
}
static STUB_TEXT unsigned int FifoOutPeek(struct RingBuffer *fifo, void *buf, unsigned int len)
{
unsigned int l;
l = fifo->in - fifo->out;
if (len > l)
len = l;
FifoCopyOut(fifo, buf, len, fifo->out);
return len;
}
static STUB_TEXT unsigned int FifoOut(struct RingBuffer *fifo, void *buf, unsigned int len)
{
len = FifoOutPeek(fifo, buf, len);
fifo->out += len;
return len;
}
STUB_TEXT int RBufferPairInit(uintptr_t rxaddr, uintptr_t txaddr, int len)
{
if (!rxaddr || !txaddr || len <= sizeof(RBuffer)) {
return -1;
}
g_rxRBuffer = (RBuffer *)rxaddr;
g_txRBuffer = (RBuffer *)txaddr;
return 0;
}
static STUB_TEXT int OsRbufferWrite(RBuffer *buffer, char *buf, int len)
{
int cnt = 0;
if (len <= 0) {
return 0;
}
while (cnt < len) {
int o = FifoIn(buffer, &buf[cnt], len - cnt);
cnt += o;
}
return cnt;
}
static STUB_TEXT int RBufferRead(RBuffer *buffer, char *buf, int len)
{
return FifoOut(buffer, buf, len);
}
STUB_TEXT void OsGdbFlush()
{
int len = g_txLBuffer.idx;
int cnt = 0;
while (cnt < len) {
cnt += OsRbufferWrite(g_txRBuffer, &g_txLBuffer.data[cnt], len - cnt);
}
g_txLBuffer.idx = 0;
}
STUB_TEXT void OsGdbPutchar(char ch)
{
int len = sizeof(g_txLBuffer.data);
g_txLBuffer.data[g_txLBuffer.idx++] = ch;
if (g_txLBuffer.idx == len) {
OsGdbFlush();
g_txLBuffer.idx = 0;
}
}
STUB_TEXT char OsGdbGetchar()
{
char ch;
int len = sizeof(g_rxLBuffer.data);
if (g_rxLBuffer.idx >= len || g_rxLBuffer.idx >= g_rxLBuffer.avails) {
g_rxLBuffer.idx = 0;
int cnt = 0;
while ((cnt = RBufferRead(g_rxRBuffer, g_rxLBuffer.data, sizeof(g_rxLBuffer.data))) == 0) {
;
}
g_rxLBuffer.avails = cnt;
}
ch = g_rxLBuffer.data[g_rxLBuffer.idx++];
return ch;
}
extern struct GdbRingBufferCfg *OsGetGdbRingBufferCfg(void);
STUB_TEXT int OsGdbRingBufferInit()
{
struct GdbRingBufferCfg *cfg = OsGetGdbRingBufferCfg();
if (!cfg) {
return -1;
}
RBufferPairInit(cfg->rxaddr, cfg->txaddr, cfg->size);
return 0;
}