'\"macro stdmacro
.if n .pH ddi_dki.pullupmsg @(#)pullupmsg	40.7 of 11/20/89
.\" Copyright 1989 AT&T
.de IX
.ie '\\n(.z'' .tm .Index: \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9	\\n%
.el \\!.IX \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
..
.nr X
.if \nX=0 .ds x} pullupmsg D3DK "STREAMS" "DDI/DKI" "\&"
.if \nX=1 .ds x} pullupmsg D3DK "STREAMS" "DDI/DKI"
.if \nX=2 .ds x} pullupmsg D3DK "" "\&"
.if \nX=3 .ds x} pullupmsg "" "" "\&"
.TH \*(x}
.IX "\f4pullupmsg\fP(D3DK)"
.SH NAME
\f4pullupmsg\f1 \- concatenate bytes in a message
.SH SYNOPSIS
.nf
.na
\f4#include <sys/stream.h>
.sp 0.5
int pullupmsg(mblk_t *\f2mp, \f4int\f2 len\f4);\f1
.ad
.fi
.SH ARGUMENTS
.RS 0n 10
.IP "\f2*mp\f1" 10n
Pointer to the message whose blocks are to be concatenated.  \f4mblk_t\f1
is an instance of the \f4msgb\f1(D4DK)
structure.
.IP "\f2len\f1" 10n
Number of bytes to concatenate.
.RE
.SH DESCRIPTION
\f4pullupmsg\f1 tries to combine multiple data blocks into a single block.
\f4pullupmsg\f1 concatenates and aligns the first \f2len\f1 data bytes of
the message pointed to by \f2mp\f1.
If \f2len\f1 equals \f4-1\f1, all data is concatenated.  If \f2len\f1 bytes
of the same message type cannot be found, \f4pullupmsg\f1 fails and returns
\f40\f1.
.SH RETURN VALUE
On success, \f41\f1 is returned; on failure, \f40\f1 is returned.
.SH LEVEL
Base or Interrupt
.SH SEE ALSO
\f2BCI Driver Development Guide\f1, Chapter 7, ``STREAMS''
.P
.na
\f4allocb\f1(D3DK)
.ad
.SH EXAMPLE
.IX "\f4msgb\fP(D4DK), example"
.IX "\f4pullupmsg\fP(D3DK), example"
.IX "\f4freemsg\fP(D3DK), example"
.IX "\f4getq\fP(D3DK), example"
.IX "\f4queue\fP(D4DK), example"
.P
This is a driver write \f4srv\f1(D2DK) (service) routine for a
device that does not support scatter/gather \s-1DMA\s0.
For all \f4M_DATA\f1
messages, the data will be transferred to the device with \s-1DMA\s0.
.P
First, try to pull up the message into one message
block with the \f4pullupmsg\f1 function (line 12).
If successful, the transfer can be accomplished in one
.SM DMA
job.  Otherwise, it must be done one message block
at a time (lines 19\-22).
After the data has been transferred to the
device, free the message and continue processing messages on
the queue.
.P
.ne 4
.P
.nf
.ft 4
.ps 7
 1 xxxwsrv(q)
 2      queue_t *q;
 3 {
 4	mblk_t *mp;
 5	mblk_t *tmp;
 6	caddr_t dma_addr;
 7	int dma_len;
 8
 9	while ((mp = getq(q)) != NULL) {
10		switch (mp->b_datap->db_type) {
11		case M_DATA:
12			if (pullupmsg(mp, -1)) {
13				dma_addr = vtop(mp->b_rptr);
14				dma_len = mp->b_wptr - mp->b_rptr;
15				xxx_do_dma(dma_addr, dma_len);
16				freemsg(mp);
17				break;
18			}
19			for (tmp = mp; tmp; tmp = tmp->b_cont) {
20				dma_addr = vtop(tmp->b_rptr);
21				dma_len = tmp->b_wptr - tmp->b_rptr;
22				xxx_do_dma(dma_addr, dma_len);
23			}
24			freemsg(mp);
25			break;
	. . .
26		}
27	}
28  }
.ps
.ft 1
.fi
.P
.FG "pullupmsg \- concatenate messages"
