00001 /* 00002 * Sample QNX4 Device Driver 00003 * 00004 * Far call interface routines. 00005 * 00006 * These routines are far called by Dev which requires 00007 * them to be compiled specially. In particular, it is very important 00008 * that they be compiled with -zu (SS != DS) since this will be 00009 * the case. Also stack checking should be disabled 00010 * 00011 * Kick() is called by Dev whenever "something" has changed in the 00012 * output buffer (new data, change in flow control, etc.) 00013 * 00014 * Stty() is called by Dev when something "significant" has changed 00015 * in the termios control structure which requires hardware 00016 * attention (eg: baud rate, parity). 00017 * 00018 * Ctrl() is called to perform various "houskeeping" functions 00019 * (like dropline by rasining/lowering DTR, sendbreak, etc.) 00020 * 00021 * Inside these routines, teh following limitations apply: 00022 * 00023 * 1) No system calls other than Trigger() can be used. Since most 00024 * C library routines use system calls internally (eg: read 00025 * will use Sendfd), the "safe" rule is to avoid ALL library 00026 * routines completetly. The best policy is to only access/change 00027 * global memory variables and Trigger() a proxy to wake up your 00028 * process if more work needs to be done. 00029 * 00030 * 2) No mapped or segmented memory can be accesses (ie: no far pointers) 00031 * since Dev's process context will not have access to them. Only 00032 * variables in DS can be accessed. 00033 * 00034 * 3) Try to avoid much processing since Dev (at high priority) will be 00035 * effectively blocked until your routine finishes. 00036 * 00037 * 4) Don't use much stack (keep it under a few hundred bytes). 00038 */ 00039 00040 00041 #include <sys/types.h> 00042 #include <sys/kernel.h> 00043 #include <sys/dev.h> 00044 #include <sys/_devdrvr.h> 00045 00046 /* 00047 * declare the calls 'dev' will make into driver. 00048 */ 00049 int far Kick (struct output_buffer far *obuf); 00050 int far Stty (struct termios far *tios); 00051 int far Ctrl (union ioctl_entry far *ioc); 00052 00053 #pragma aux (_dev_call) Kick; 00054 #pragma aux (_dev_call) Stty; 00055 #pragma aux (_dev_call) Ctrl; 00056 00057 #pragma off (check_stack); 00058 00059 /* 00060 * Kick is called by DEV everytime something "new" happens 00061 * to the output buffer 00062 * 00063 * It will set 'obuf' to be the output buffer 00064 * It will also set ds to be the data segment of the driver being called 00065 * 00066 * Since this routine is "called" by DEV, it will ALWAYS run at higher 00067 * priority than the driver task, so cannot be interrupted. 00068 */ 00069 00070 int far Kick (struct output_buffer far *obuf) { 00071 extern int idle; 00072 extern int more; 00073 extern pid_t out_proxy; 00074 00075 if((obuf->size > 0 00076 && (obuf->mode & (OUTPUT_STOPPED|OUTPUT_STOPPED_HW)) == 0) 00077 || (obuf->mode & (OUTPUT_HFLOW_OFF|OUTPUT_HFLOW_ON|OUTPUT_XON|OUTPUT_XOFF)) ) { 00078 if(idle) { 00079 idle = 0; 00080 Trigger(out_proxy); 00081 } 00082 else 00083 more = 1; 00084 return(1); 00085 } 00086 return(0); 00087 } 00088 00089 00090 /* 00091 * Stty is called by DEV to indicate a significant change in the 00092 * termios control structure (baud rate, modem control) 00093 * It can optionally be called for EVERY call to tcsetattr() if the 00094 * DRVR_STTY option os passed to dev_drvr_register(). 00095 * 00096 * It will set 'tios' to be a far pointer to the termios entry 00097 * It will also set ds to be the data segment of the driver being called 00098 * 00099 * Since this routine is "called" by DEV, it will ALWAYS run at higher 00100 * priority than the driver task, so cannot be interrupted. 00101 */ 00102 00103 int far Stty (struct termios far *tios) 00104 { 00105 tios = tios; /* keep compiler happy */ 00106 return(0); 00107 } 00108 00109 00110 /* 00111 * Ctrl is called by DEV to indicate a high level 00112 * control function 00113 * 00114 * It will set 'ioc' to be an ioctl control block 00115 * It will also set ds to be the data segment of the driver being called 00116 * 00117 * Since this routine is "called" by DEV, it will ALWAYS run at higher 00118 * priority than the driver task, so cannot be interrupted. 00119 */ 00120 00121 int far Ctrl (union ioctl_entry far *ioc) 00122 { 00123 int type; 00124 00125 type = ioc->type; 00126 ioc->status = IOCTL_ERROR; 00127 00128 switch (type) { 00129 00130 case IOCTL_OPEN: 00131 /* 00132 * First open on device 00133 */ 00134 ioc->status = IOCTL_OK; 00135 return(0); 00136 00137 case IOCTL_CLOSE: 00138 /* 00139 * Last close on device 00140 */ 00141 ioc->status = IOCTL_OK; 00142 return(0); 00143 00144 case IOCTL_CTL: 00145 ioc->user_return.status = IOCTL_OK; 00146 return(0); 00147 } 00148 00149 return(-1); 00150 } 00151 00152 #pragma on (check_stack);