Add a bit-level transfer queue

Interface drivers regularly need to keep track of where each part of a long
read buffer should be copied, once that data arrives. Both source and
destination are often at an arbitrary bit offset.

This queued bit-level copy can help with that, by allowing the driver to
perform postponed reads from the receive buffer already when building the
transmit buffer, and have those reads executed at a later time when data is
available.

For simplicity, it uses the linked list implementation list.h imported from
the Linux kernel.

Change-Id: I06862a0a6f057cbbcacfb021f17a795195faded2
Signed-off-by: Andreas Fritiofson <andreas.fritiofson@gmail.com>
Reviewed-on: http://openocd.zylin.com/450
Tested-by: jenkins
Reviewed-by: Xiaofan <xiaofanc@gmail.com>
Reviewed-by: Freddie Chopin <freddie.chopin@gmail.com>
Reviewed-by: Peter Stuge <peter@stuge.se>
This commit is contained in:
Andreas Fritiofson
2012-02-12 22:29:50 +01:00
committed by Peter Stuge
parent edf0c3376d
commit 6d639b09f0
4 changed files with 809 additions and 1 deletions

View File

@@ -327,3 +327,46 @@ int str_to_buf(const char *str, unsigned str_len,
return i;
}
void bit_copy_queue_init(struct bit_copy_queue *q)
{
INIT_LIST_HEAD(&q->list);
}
int bit_copy_queued(struct bit_copy_queue *q, uint8_t *dst, unsigned dst_offset, const uint8_t *src,
unsigned src_offset, unsigned bit_count)
{
struct bit_copy_queue_entry *qe = malloc(sizeof(*qe));
if (!qe)
return ERROR_FAIL;
qe->dst = dst;
qe->dst_offset = dst_offset;
qe->src = src;
qe->src_offset = src_offset;
qe->bit_count = bit_count;
list_add_tail(&qe->list, &q->list);
return ERROR_OK;
}
void bit_copy_execute(struct bit_copy_queue *q)
{
struct bit_copy_queue_entry *qe;
struct bit_copy_queue_entry *tmp;
list_for_each_entry_safe(qe, tmp, &q->list, list) {
bit_copy(qe->dst, qe->dst_offset, qe->src, qe->src_offset, qe->bit_count);
list_del(&qe->list);
free(qe);
}
}
void bit_copy_discard(struct bit_copy_queue *q)
{
struct bit_copy_queue_entry *qe;
struct bit_copy_queue_entry *tmp;
list_for_each_entry_safe(qe, tmp, &q->list, list) {
list_del(&qe->list);
free(qe);
}
}