NAME | SYNOPSIS | INTERFACE LEVEL | PARAMETERS | DESCRIPTION | RETURN VALUES | CONTEXT | EXAMPLES | SEE ALSO | WARNINGS
#include <sys/stream.h>mblk_t *mkiocb(uint_t command);
Solaris DDI specific (Solaris DDI).
STREAMS modules or drivers might need to issue an ioctl to a lower module or driver.The mkiocb() function tries to allocate (using allocb(9F)) a STREAMS M_IOCTL message block ( iocblk(9S)). Buffer allocation fails only when the system is out of memory. If no buffer is available, the qbufcall(9F) function can help a module recover from an allocation failure.
The mkiocb function returns a mblk_t structure which is large enough to hold any of the ioctl messages ( iocblk(9S), copyreq(9S) or copyresp(9S)), and has the following special properties:
Set to b_rptr + sizeof(struct iocblk) .
Set to NULL.
Set to M_IOCTL.
The fields in the iocblk structure are initialized as follows:
Set to the command value passed in.
Set to a unique identifier.
Set to point to a credential structure encoding the maximum system privilege and which does not need to be freed in any fashion.
Set to 0.
Set to 0.
Set to 0.
Set to IOC_NATIVE to reflect that this is native to the running kernel.
Upon success, the mkiocb() function returns a pointer to the allocated mblk_t of type M_IOCTL .
On failure, it returns a null pointer.
The mkiocb() function can be called from user or interrupt context.
The first example shows an M_IOCTL allocation with the ioctl command TEST_CMD. If the iocblk(9S) cannot be allocated, NULL is returned, indicating an allocation failure (line 5). In line 11, the putnext(9F) function is used to send the message downstream.
1 test_function(queue_t *q, test_info_t *testinfo) 2 { 3 mblk_t *mp; 4 5 if ((mp = mkiocb(TEST_CMD)) == NULL) 6 return (0); 7 8 /* save off ioctl ID value */ 9 testinfo->xx_iocid = ((struct iocblk *)mp->b_rptr)->ioc_id; 10 11 putnext(q, mp); /* send message downstream */ 12 return (1); 13 }
During the read service routine, the ioctl ID value for M_IOCACK or M_IOCNACK should equal the ioctl that was previously sent by this module before processing.
1 test_lrsrv(queue_t *q) 2 { 3 ... 4 5 switch (DB_TYPE(mp)) { 6 case M_IOCACK: 7 case M_IOCNACK: 8 /* Does this match the ioctl that this module sent */ 9 ioc = (struct iocblk*)mp->b_rptr; 10 if (ioc->ioc_id == testinfo->xx_iocid) { 11 /* matches, so process the message */ 12 ... 13 freemsg(mp); 14 } 15 break; 16 } 17 ... 18 }
The next example shows an iocblk allocation which fails. Since the open routine is in user context, the caller may block using qbufcall(9F) until memory is available.
1 test_open(queue_t *q, dev_t devp, int oflag, int sflag, cred_t *credp) 2 { 3 while ((mp = mkiocb(TEST_IOCTL)) == NULL) { 4 int id; 5 6 id = qbufcall(q, sizeof (union ioctypes), BPRI_HI, 7 dummy_callback, 0); 8 /* Handle interrupts */ 9 if (!qwait_sig(q)) { 10 qunbufcall(q, id); 11 return (EINTR); 12 } 13 } 14 putnext(q, mp); 15 }
It is the module's responsibility to remember the ID value of the M_IOCTL that was allocated. This will ensure proper cleanup and ID matching when the M_IOCACK or M_IOCNACK is received.
NAME | SYNOPSIS | INTERFACE LEVEL | PARAMETERS | DESCRIPTION | RETURN VALUES | CONTEXT | EXAMPLES | SEE ALSO | WARNINGS