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