summaryrefslogtreecommitdiff
path: root/sys/arch/sparc64
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2009-12-26 21:21:11 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2009-12-26 21:21:11 +0000
commit3caddfed9eea1c170e8e7bd76768502e2ec99891 (patch)
tree42990dad92da480a8b2634a1617d12b550317bb7 /sys/arch/sparc64
parentc2b4adaf322c7ff83060dd6590694cad4df7c81e (diff)
Add support for fragmented messages.
Diffstat (limited to 'sys/arch/sparc64')
-rw-r--r--sys/arch/sparc64/dev/ldc.c23
-rw-r--r--sys/arch/sparc64/dev/ldcvar.h13
2 files changed, 33 insertions, 3 deletions
diff --git a/sys/arch/sparc64/dev/ldc.c b/sys/arch/sparc64/dev/ldc.c
index 13799d5d818..5b172acdbb8 100644
--- a/sys/arch/sparc64/dev/ldc.c
+++ b/sys/arch/sparc64/dev/ldc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldc.c,v 1.6 2009/05/12 22:31:45 kettenis Exp $ */
+/* $OpenBSD: ldc.c,v 1.7 2009/12/26 21:21:10 kettenis Exp $ */
/*
* Copyright (c) 2009 Mark Kettenis
*
@@ -72,6 +72,7 @@ ldc_rx_ctrl_vers(struct ldc_conn *lc, struct ldc_pkt *lp)
{
switch (lp->stype) {
case LDC_INFO:
+ DPRINTF(("CTRL/INFO/VERS\n"));
if (lp->major == LDC_VERSION_MAJOR &&
lp->minor == LDC_VERSION_MINOR)
ldc_send_ack(lc);
@@ -203,6 +204,8 @@ ldc_rx_ctrl_rdx(struct ldc_conn *lc, struct ldc_pkt *lp)
void
ldc_rx_data(struct ldc_conn *lc, struct ldc_pkt *lp)
{
+ size_t len;
+
if (lp->stype != LDC_INFO) {
DPRINTF(("DATA/0x%02x\n", lp->stype));
ldc_reset(lc);
@@ -216,7 +219,23 @@ ldc_rx_data(struct ldc_conn *lc, struct ldc_pkt *lp)
return;
}
- lc->lc_rx_data(lc, lp);
+ if (lp->env & LDC_FRAG_START) {
+ lc->lc_len = (lp->env & LDC_LEN_MASK) + 8;
+ KASSERT(lc->lc_len <= sizeof(lc->lc_msg));
+ memcpy((uint8_t *)lc->lc_msg, lp, lc->lc_len);
+ } else {
+ len = (lp->env & LDC_LEN_MASK);
+ if (lc->lc_len + len > sizeof(lc->lc_msg)) {
+ DPRINTF(("Buffer overrun\n"));
+ ldc_reset(lc);
+ return;
+ }
+ memcpy(((uint8_t *)lc->lc_msg) + lc->lc_len, &lp->major, len);
+ lc->lc_len += len;
+ }
+
+ if (lp->env & LDC_FRAG_STOP)
+ lc->lc_rx_data(lc, (struct ldc_pkt *)lc->lc_msg);
}
void
diff --git a/sys/arch/sparc64/dev/ldcvar.h b/sys/arch/sparc64/dev/ldcvar.h
index 832823a2375..bf7a9ed7f11 100644
--- a/sys/arch/sparc64/dev/ldcvar.h
+++ b/sys/arch/sparc64/dev/ldcvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldcvar.h,v 1.3 2009/05/12 21:52:30 kettenis Exp $ */
+/* $OpenBSD: ldcvar.h,v 1.4 2009/12/26 21:21:10 kettenis Exp $ */
/*
* Copyright (c) 2009 Mark Kettenis
*
@@ -36,6 +36,8 @@ void ldc_queue_free(bus_dma_tag_t, struct ldc_queue *);
#define LDC_VERSION_MAJOR 1
#define LDC_VERSION_MINOR 0
+#define LDC_PKT_PAYLOAD 56
+
struct ldc_pkt {
uint8_t type;
uint8_t stype;
@@ -74,6 +76,12 @@ struct ldc_pkt {
#define LDC_FRAG_START 0x40
#define LDC_FRAG_STOP 0x80
+/*
+ * XXX Get rid of the +8 once we no longer need to store the header of
+ * the first packet.
+ */
+#define LDC_MSG_MAX (128 + 8)
+
struct ldc_conn {
uint64_t lc_id;
@@ -90,6 +98,9 @@ struct ldc_conn {
#define LDC_SND_RTR 4
#define LDC_SND_RDX 5
+ uint64_t lc_msg[LDC_MSG_MAX / 8];
+ size_t lc_len;
+
void *lc_sc;
void (*lc_reset)(struct ldc_conn *);
void (*lc_start)(struct ldc_conn *);