msgscgth -- construct a DMA scatter/gather list for a message block

Synopsis (Not in ODDI)

   #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);


The msgscgth( ) function allocates and passes back a DMA scatter/gather list in *scgthp that can be used for DMA operations to and from the data area of the message block. The message block is an msgb(D4str) structure, and the data area is between b_rptr (inclusive) and b_wptr (exclusive).


Pointer to the message to be DMA'ed.

Physical requirements for the data buffer.

Pointer to the scgth(D4) structure that msgscgth( ) passes back.

Return values

On success, msgscgth( ) returns a pointer to the DMA scatter/gather list.

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.


msgscgth( ) ensures that data blocks for a message satisfy a set of physical requirements using the same algorithms as msgphysreq(D3str).

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.


Base or interrupt.

Synchronization constraints

Hardware applicability


Version applicability

ddi: 8, 8mp


msgphysreq(D3str), scgth(D4), scgth_free(D3)

``Scatter/gather operations'' in HDK Technical Reference


The following example shows a simple STREAMS driver write-side put(D2str) routine that simply outputs all incoming M_DATA(D7str) blocks using an imaginary DMA mechanism.

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 /
    	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");

19 June 2005
© 2005 The SCO Group, Inc. All rights reserved.
OpenServer 6 and UnixWare (SVR5) HDK - June 2005