|
|
#include <sys/stream.h> #include <sys/kmem.h> #include <sys/scgth.h> #include <sys/ddi.h>mblk_t msgscgth(mblk_t mp, physreq_t preqp, scgth_t scgthp);
b_rptr
(inclusive)
and b_wptr
(exclusive).
On failure,
msgscgth( )
returns NULL.
The original message pointer is still valid
but must not be used;
scgthp remains uninitialized.
msgscgth( )
fails if there are more blocks in the mp message
than specified in the phys_max_scgth
member
of the physreq structure
specified by the preqp argument
or if appropriate memory cannot be allocated
for the buffers into which the data would be copied.
If the memory for the data pointed to by
the b_rptr
up to b_wptr
members of the
msgb(D4str)
message block(s) in mp
satisfy the constraints specified by the
physreq(D4)
structure pointed to by preqp,
this message is simply returned unaltered.
Otherwise, the data are copied into buffers
that do meet the constraints.
If copied, the data is always in the front of the new buffer;
that is, b_rptr
value of the msgb structure
is the same as the db_base
value of the
datab(D4str)
structure.
In this case, some or all of the original message will be freed,
and a new message pointer may be returned.
The scgthp pointer is then allocated and initialized with a number of physical address elements equal to the number of separate blocks in the mp message.
If msgscgth( ) fails (returns NULL), the code should call the msgpullup_physreq(D3str) function to concatenate and align they bytes in the message according to the driver's physical requirements. If the msgpullup_physreq( ) function also fails, the code should call the freemsg(D3str) function to release the buffer.
``Scatter/gather operations'' in HDK Technical Reference
This code fragment assumes that the
preqp structure has already been
allocated and prepared using the
physreq_alloc(D3)
and
physreq_prep(D3)
functions,
with the correct memory alignment, boundary,
DMA size (32 bits or less for this example),
flags, and phys_max_scgth
value.
Typically, the preqp structure would be
initialized in the driver's
open(D2str)
routine.
#include <sys/stream.h> #include <sys/kmem.h> #include <sys/scgth.h> #include <sys/ddi.h>physreq_t *preqp;
...
static void drv_dma_write(u_int32_t paddr, u_int32_t size) { /* * Driver code to write "size" bytes starting at physical * address "paddr" using DMA out to device. */ }
int drvwput(queue_t *q, mblk_t *mp) { scgth_t scgth; scgth_el32_t *el32; int i;
if (mp->b_datap->db_type != M_DATA) { /* * Driver handles non-data messages here. */ return 0; }
if ((mp = msgscgth(mp, preqp, &scgth)) == NULL) { /* * Driver handles failure here. */ return 0; }
/* * Assumes sg.sg_format == SCGTH32, since * preqp->phys_dmasize is <= 32. */ for (el32 = scgth.sg_elem.el32, i = 0; i < scgth.sg_nelem; i++, el32++) { drv_dma_write(el32->sg_base, el32->sg_size); } scgth_free(&scgth);
return 0; }
The following example is from the MDI shrk driver and illustrates how to use msgpullup_physreq( ) to check the message blocks that are allocated with the msgscgth( ) function. The shrk driver compiles for both the SVR5 and SCO OpenServer 5 operating system so also illustrates how to code similar functionality on SCO OpenServer 5. The full shrk driver code is included in the ndsample and O5ndsamp packages which are available on the HDK media and can be downloaded from the HDK web site.
if ((smp = msgscgth(mp, shrk_txphys, &sg)) == NULL) { / more than shrk_max_txbuf_per_msg fragments / DEBUG14(CE_CONT, "shrktx: msgscgth-1 failed\n"); if ((smp = msgpullup_physreq(mp, -1, shrk_phys)) == NULL) { DEBUG14(CE_CONT, "shrktx: msgpullup_physreq failed\n"); freemsg(mp); / prevent memory leak on msgscgth fail / mst->mac_frame_nosr++; return(B_FALSE); } freemsg(mp); mp = smp; / save pointer to free in case msgscgth fails / if ((smp = msgscgth(mp, shrk_txphys, &sg)) == NULL) { DEBUG14(CE_CONT, "shrktx: msgscgth-2 failed\n"); freemsg(mp); return(B_FALSE); } }