Article # 140, added by Geoworks, historical record
| first | previous | index | next | last |

How to call a driver's strategy routine from C




Q:
How do you call a driver's strategy routine from C?

A:
There is a routine in streamc.h called DriverCallEntryPoint that will
do what you want.  Unfortunately, the driver function numbers are
usually not defined in C, so you have to determine them by counting
the DriverFunction (DR_XXX) entries in the def files.  (The first five
DriverFunctions are in driver.def
	0 - DR_INIT
	2 - DR_INIT_WITH_GEODE_HANDLE	
	4 - DR_EXIT
	6 - DR_SUSPEND
	8 - DR_UNSUSPEND
so most other drivers continue their numbering from there, i.e. 10.)


Here's examples of accessing two of the stream driver functions:

Setting serial driver event notifications is accomplished thru a call
to the driver geode.  Most of the serial driver functions have
corresponding library routines; the two  of interest that do not are
DR_STREAM_SET_NOTIFY and DR_STREAM_SET_THRESHOLD.  These are accessed
by calling DriverCallEntryPoint and specifying one of the
DR_STREAM_... functions.  DR_STREAM_SET_NOTIFY allows one to setup a
notification message or routine that will be sent/called when a
specific event occurs (data arrives, error occurs).
DR_STREAM_SET_THRESHOLD sets the number of bytes of received/sent data
that will cause a DR_STREAM_SET_NOTIFY event to occur (for the case of
DR_STREAM_SET_NOTIFY being set to STREAM_EVENT_DATA).
DriverCallEntryPoint info and an example usage follow.
 
extern	void	_pascal 
DriverCallEntryPoint (Handle driver,
 			word func,
 			DriverPassParams *passParams,
 			DriverReturnParams *returnParams);
 
/*
 * func is on of the driver functions to call
 */
#define DR_STREAM_SET_NOTIFY	14
#define DR_STREAM_SET_THRESHOLD	22
 
/*
 * DriverPassParams is used to pass arguments into DriverCallEntryPoint.  See
 * the specific DR_STREAM_... function in Include\Internal\StreamDR.def for
 * descriptions of which registers need to be set and which will return values.
 */
typedef	struct
{
 	word	ax;
 	word	bx;
 	word	cx;
 	word	dx;
 	word	si;
 	word	bp;
 	word	ds;
 	word	es;
} DriverPassParams;
 
/*
 * DriverPassParams is used to return results from DriverCallEntryPoint.
 */
typedef	struct
{
 	word	ax;
 	word	bx;
 	word	cx;
 	word	dx;
 	word	si;
	word	di;
	word	bp;
	word	ds;
	word	es;
	CPUFlags	flags;
} DriverReturnParams;


/******EXAMPLE FOR SETTING UP NOTIFICATION OF SERIAL DATA EVENT*******
 * DR_STREAM_SET_NOTIFY passes the following and returns nothing.
 *	PASS:ax	= StreamNotifyType that identifies for which side of
 *			  the stream and what event the notifier is being
 *			  registered.
 *		bx	= stream token
 *		cx:dx	= address of handling routine, if SNM_ROUTINE
 *			  destination of output if SNM_MESSAGE
 *		bp	= AX to pass if STREAM_MODE_ROUTINE (except for SNE_DATA with
 *			  threshold of 1, in which case this value is passed in
 *			  CX); method to send if STREAM_MODE_MESSAGE.   
/*
    DriverPassParams  dpp;
    DriverReturnParams drp;
    StreamToken serialPort = SERIAL_COM1;

/* set up StreamNotifyType for StreamReader, data event notification
 * (STREAM_EVENT_DATA), and notification mode by a message */
dpp.ax = 
      ((1 << STREAM_TYPE_READER_OFFSET) |    /* 1 = reader, 0 = writer */
      (STREAM_EVENT_DATA << STREAM_TYPE_EVENT_OFFSET) | /* data notification */
      (STREAM_MODE_MESSAGE << STREAM_TYPE_HOW_OFFSET)); /* see below about this */
dpp.bx = serialPort;
/* need to confirm the following three lines. */
/*
 * MySerialNotifyObject is the object that contains a method handler for 
 * MSG_MSNO_DATA_NOTIFY.
 */
dpp.cx = OptrToHandle(@MySerialNotifyObject);
dpp.dx = OptrToChunk(@MySerialNotifyObject);
dpp.bp = MSG_MSNO_DATA_NOTIFY;   /* message to send to MySerialNotifyObject */
 
DriverCallEntryPoint(serialDriver, DR_STREAM_SET_NOTIFY, &dpp, &drp);


/* DR_STREAM_SET_THRESHOLD passes the following and returns nothing.
 *	PASS:ax	= StreamNotifyType that identifies for which side of
 *			  the stream and what event the notifier is being
 *			  registered.
 *		bx	= stream token
 *		cx	= threshold (number of bytes that must be available
 *			  for reading, or for which space must be available
 *			  for writing)
/*
dpp.ax = STREAM_ROLES_READER;
dpp.bx = serialPort;
dpp.cx = 1; /* send notification on each byte received */

DriverCallEntryPoint(serialDriver, DR_STREAM_SET_THRESHOLD, &dpp, &drp);