_MULTIUSER DOS FOR CONTROL SYSTEMS, PART II_ by Richard Kryszak [LISTING ONE] /* file name: system.c */ #include #include "queues.h" #include /*===============*/ /* local defines */ /*===============*/ #define CCPM 0xE0 /* cdos call int value */ #define C_DETACH 0x93 /* console detach CL register value */ #define P_DELAY 0x8D /* process delay CL register value */ #define P_DISPATCH 0x8E /* process dispatch CL register value */ #define P_PRIOR 0x91 /* process priority CL register value */ #define Q_CREAD 0x8A /* queue cread CL register value */ #define Q_CWRITE 0x8C /* queue cwrite CL register value */ #define Q_MAKE 0x86 /* queue make CL register value */ #define Q_OPEN 0x87 /* queue open CL register value */ #define Q_READ 0x89 /* queue read CL register value */ #define Q_WRITE 0x8B /* queue write CL register value */ #define S_MEMORY 0x59 /* system memory allocation request */ /*=====================*/ /* function prototypes */ /*=====================*/ unsigned int c_detach(void); void p_dispatch(void); void p_priority(unsigned char data); void p_delay(unsigned int del); unsigned int far * s_memory(int mem_size); int q_make(struct q_descriptor *descript_ptr, unsigned int msg_length, unsigned int num_msg, char que_name[8], int *err_ptr); int q_open(struct q_parameter_blk *param_blk_ptr, char que_name[8], int *err_ptr); int q_read(struct q_parameter_blk *param_blk_ptr, unsigned char *buff_ptr, int *err_ptr); int q_write(struct q_parameter_blk *param_blk_ptr, unsigned char *buff_ptr, int *err_ptr); int q_cread(struct q_parameter_blk *param_blk_ptr, unsigned char *buff_ptr, int *err_ptr); int q_cwrite(struct q_parameter_blk *param_blk_ptr, unsigned char *buff_ptr, int *err_ptr); /*======================*/ /* function definitions */ /*======================*/ unsigned int c_detach() { union REGS inregs,outregs; inregs.h.cl = C_DETACH; /* detach function call */ int86(CCPM,&inregs,&outregs); /* call cdos */ return(outregs.x.ax); /* return call status */ } void p_dispatch() { union REGS inregs,outregs; inregs.h.cl = P_DISPATCH; /* dispatch function call */ int86(CCPM,&inregs,&outregs); /* call cdos */ } void p_priority(unsigned char priority) { union REGS inregs,outregs; inregs.h.cl = P_PRIOR; /* priority change call */ inregs.h.dl = priority; /* desired priority */ int86(CCPM,&inregs,&outregs); /* call cdos */ } void p_delay(unsigned int del) { union REGS inregs,outregs; inregs.h.cl = P_DELAY; /* delay function call */ inregs.x.dx = del; /* number of ticks */ int86(CCPM,&inregs,&outregs); /* call cdos */ } unsigned int far * s_memory(int mem_size) { union REGS inregs,outregs; struct SREGS seg_regs; /* segment registers */ unsigned int _far *mem_ptr=NULL; /* pointer to memory block */ mem_size *= 2; /* compute # of bytes */ inregs.h.cl = S_MEMORY; /* system memory allocation */ inregs.x.dx = mem_size; /* # of bytes requested */ int86x(CCPM,&inregs,&outregs,&seg_regs); /* call cdos */ if(outregs.x.ax == 0xFFFF) /* if not successful */ { return(NULL); /* return a null pointer */ } mem_ptr = (unsigned int far *) ((0x10000 * seg_regs.es) + outregs.x.ax); /* convert into a pointer */ return(mem_ptr); /* return the pointer */ } int q_make(struct q_descriptor *descript_ptr, unsigned int msg_length, unsigned int num_msg, char que_name[8], int *err_ptr) { int int86_error; /* return status */ int i; /* index variable */ union REGS inregs, outregs; /* processor registers */ struct SREGS seg_regs; /* segment registers */ segread(&seg_regs); /* read segment registers */ descript_ptr->internal_1 = 0; /* must be 0 */ descript_ptr->internal_2 = 0; /* must be 0 */ descript_ptr->internal_3 = 0; /* must be 0 */ descript_ptr->internal_4 = 0; /* must be 0 */ descript_ptr->internal_5 = 0; /* must be 0 */ descript_ptr->internal_6 = 0; /* must be 0 */ descript_ptr->msglen = msg_length; /* add message length */ descript_ptr->nmsgs = num_msg; /* add number of messages */ descript_ptr->flags = 0; /* no flags used */ for(i = 0; i < 8; ++i) /* copy queue name */ { descript_ptr->name[i]=que_name[i]; } descript_ptr->buffer = 0; /* buffer in system area */ inregs.h.cl = Q_MAKE; /* queue make call */ inregs.x.dx = FP_OFF(descript_ptr); /* put offset into dx */ int86_error=int86x(CCPM,&inregs, &outregs,&seg_regs); /* call cdos */ *err_ptr = outregs.x.cx; /* write error code */ return(int86_error); /* int86 return status */ } int q_open(struct q_parameter_blk *param_blk_ptr, char que_name[8], int *err_ptr) { int int86_error; /* return status */ int i; /* index variable */ union REGS inregs, outregs; /* processor registers */ struct SREGS seg_regs; /* segment registers */ segread(&seg_regs); /* read segment registers */ param_blk_ptr->internal_1 = 0; /* must be 0 */ param_blk_ptr->internal_2 = 0; /* must be 0 */ for(i = 0; i < 8; ++i) { param_blk_ptr->name[i] = que_name[i]; /* copy queue name */ } inregs.h.cl = Q_OPEN; /* q_open call */ inregs.x.dx = FP_OFF(param_blk_ptr); /* put offset into dx */ int86_error=int86x(CCPM,&inregs, &outregs,&seg_regs); /* call cdos */ *err_ptr = outregs.x.cx; /* write error code */ return(int86_error); /* int86 return status */ } int q_write(struct q_parameter_blk *param_blk_ptr, unsigned char *buff_ptr, int *err_ptr) { int int86_error; /* return status */ union REGS inregs, outregs; /* processor registers */ struct SREGS seg_regs; /* segment registers */ segread(&seg_regs); /* read segment registers */ param_blk_ptr->buffer=FP_OFF(buff_ptr); /* pointer to the buffer */ inregs.h.cl = Q_WRITE; /* q_write call */ inregs.x.dx = FP_OFF(param_blk_ptr); /* put offset into dx */ int86_error=int86x(CCPM,&inregs, &outregs,&seg_regs); /* call cdos */ *err_ptr = outregs.x.cx; /* write error code */ return(int86_error); /* int86 return status */ } int q_read(struct q_parameter_blk *param_blk_ptr, unsigned char *buff_ptr, int *err_ptr) { unsigned int int86_error; /* return status */ union REGS inregs, outregs; /* processor registers */ struct SREGS seg_regs; /* segment registers */ segread(&seg_regs); /* read segment registers */ param_blk_ptr->buffer=FP_OFF(buff_ptr); /* pointer to the buffer */ inregs.h.cl = Q_READ; /* q_read call */ inregs.x.dx = FP_OFF(param_blk_ptr); /* put offset into dx */ int86_error=int86x(CCPM,&inregs,&outregs,&seg_regs); /* int86 call */ *err_ptr = outregs.x.cx; /* write error code */ return(int86_error); /* int86 return status */ } int q_cwrite(struct q_parameter_blk *param_blk_ptr,unsigned char *buff_ptr, int *err_ptr) { int int86_error; /* return status */ union REGS inregs, outregs; /* processor registers */ struct SREGS seg_regs; /* segment registers */ segread(&seg_regs); /* read segment registers */ param_blk_ptr->buffer=FP_OFF(buff_ptr); /* pointer to the buffer */ inregs.h.cl = Q_CWRITE; /* q_write call */ inregs.x.dx = FP_OFF(param_blk_ptr); /* put offset into dx */ int86_error=int86x(CCPM,&inregs,&outregs,&seg_regs); /* call cdos */ *err_ptr = outregs.x.cx; /* write error code */ return(int86_error); /* int86 return status */ } int q_cread(struct q_parameter_blk *param_blk_ptr,unsigned char *buff_ptr, int *err_ptr) { int int86_error; /* return status */ union REGS inregs, outregs; /* processor registers */ struct SREGS seg_regs; /* segment registers */ segread(&seg_regs); /* read segment registers */ param_blk_ptr->buffer=FP_OFF(buff_ptr); /* pointer to the buffer */ inregs.h.cl = Q_CREAD; /* q_cread call */ inregs.x.dx = FP_OFF(param_blk_ptr); /* put offset into dx */ int86_error=int86x(CCPM,&inregs,&outregs,&seg_regs); /* call cdos */ *err_ptr = outregs.x.cx; /* write error */ return(int86_error); /* int86 return status */ } [LISTING TWO] /* file name: queues.h */ struct q_descriptor { unsigned int internal_1; /* for internal use ; must be zero */ unsigned int internal_2; /* for internal use ; must be zero */ int flags; /* for internal use ; queue flags */ char name[8]; /* queue name */ int msglen; /* number of bytes in each logical message */ int nmsgs; /* maximum number of messages supported */ unsigned int internal_3; /* for internal use ; must be zero */ unsigned int internal_4; /* for internal use ; must be zero */ unsigned int internal_5; /* for internal use ; must be zero */ unsigned int internal_6; /* for internal use ; must be zero */ unsigned int buffer; /* address of the queue buffer */ }; struct q_parameter_blk { unsigned int internal_1; /* for internal use ; must be zero */ int queueid; /* queue number field ; filled by q_open */ unsigned int internal_2; /* for internal use ; must be zero */ unsigned int buffer; /* offset of queue message buffer */ char name[8]; /* queue name */ }; [LISTING THREE] /* file name: database.c */ #include #include "queues.h" /*=====================*/ /* function prototypes */ /*=====================*/ void main(void); /*===============*/ /* local defines */ /*===============*/ #define Q_DEPTH 1 /* queue contains 1 message */ #define DBASE_SIZE 2048 /* size of the database */ #define TRUE 1 /*================================*/ /* external function declarations */ /*================================*/ extern unsigned int c_detach(void); extern void p_delay(unsigned int del); extern unsigned int far *s_memory(int mem_size); extern int q_make(struct q_descriptor *descript_ptr, unsigned int msg_length, unsigned int num_msg, char que_name[8], int *err_ptr); extern int q_open(struct q_parameter_blk *param_blk_ptr, char que_name[8], int *err_ptr); extern int q_write(struct q_parameter_blk *param_blk_ptr, unsigned char *buff_ptr, int *err_ptr); /*=====================*/ /* function definition */ /*=====================*/ void main() { int result; /* result of q_make */ int error_type; /* cdos return code */ union base { unsigned int far *base_ptr; unsigned char base[sizeof(unsigned int far *)]; }base_union; /* composite pointer */ struct q_descriptor dbase_descript; /* descriptor block */ struct q_parameter_blk dbase_parameters; /* parameter block */ base_union.base_ptr = s_memory(DBASE_SIZE); /* request system memory */ if(base_union.base_ptr == NULL) /* if NULL pointer */ { puts("No System Memory Available"); /* print an error message */ exit(-1); /* exit, memory error */ } result = q_make(&dbase_descript, /* pointer to descriptor */ sizeof(base_union), /* length of messages */ Q_DEPTH, /* number of messages */ "database", /* queue name */ &error_type); /* error return */ result = q_open(&dbase_parameters, /* pointer to parameter */ "database", /* queue name */ &error_type); /* error return */ result = q_cwrite(&dbase_parameters, /* write to queue */ &base_union.base[0], /* pointer to database */ &error_type); /* error return */ c_detach(); /* detach from console */ while(TRUE) /* loop */ { p_delay(1800); /* delay 30 seconds */ } } /* NOTE: DATABASE.EXE is made up of database.c and system.c */ [LISTING FOUR] /* file name: dbsuport.c */ #include #include "queues.h" /*=====================*/ /* function prototypes */ /*=====================*/ void dbopen(void); unsigned int dbread(int index); void dbwrit(int index, unsigned int value); unsigned int far *open_dbase(void); /*==============================*/ /* external function prototypes */ /*==============================*/ extern int q_open(struct q_parameter_blk *param_blk_ptr, char que_name[8], int *err_ptr); extern void p_dispatch(void); extern int q_read(struct q_parameter_blk *param_blk_ptr, unsigned char *buff_ptr, int *err_ptr); extern int q_write(struct q_parameter_blk *param_blk_ptr, unsigned char *buff_ptr, int *err_ptr); /*================*/ /* global storage */ /*================*/ unsigned int far *dbase_ptr; /* pointer to database */ /*===============*/ /* local defines */ /*===============*/ #define FAILURE 1 #define SUCCESS 0 /*======================*/ /* function definitions */ /*======================*/ void dbopen() { dbase_ptr = NULL; /* initialize pointer */ while(dbase_ptr == NULL) /* loop while still NULL */ { dbase_ptr = open_dbase(); /* call open database */ } } void dbwrit(int index, unsigned int value) { *(dbase_ptr + index) = value; /* write value to database */ } unsigned int dbread(int index) { return(*(dbase_ptr + index)); /* return value at index */ } unsigned int far *open_dbase() { struct q_parameter_blk dbase_parameters; /* parameter block */ int result; /* result of q_make */ int error_type; /* cdos return code */ union base { unsigned int far *base_ptr; unsigned char base[sizeof(unsigned int far *)]; }base_union; /* composite pointer */ result = FAILURE; /* preset the variable */ while(result != SUCCESS) /* loop til we can open */ { result = q_open(&dbase_parameters, /* pointer to param block */ "database", /* queue name */ &error_type); /* error type return */ p_dispatch(); /* let someone else run */ } result = q_read(&dbase_parameters, /* read the dbase_queue */ &base_union.base[0], /* msg read is in union */ &error_type); /* error return type */ result = q_write(&dbase_parameters, /* write to dbase_queue */ &base_union.base[0], /* msg sent is pointer */ &error_type); /* error return type */ return(base_union.base_ptr); /* return the pointer */ } [LISTING FIVE] /* file name ioboard.c */ #include /*====================*/ /* function prototype */ /*====================*/ void main(void); /*==============================*/ /* external function prototypes */ /*==============================*/ extern void dbopen(void); extern void dbwrit(int index, unsigned int value); extern unsigned int dbread(int index); extern unsigned int c_detach(void); extern void p_priority(unsigned char data); extern void p_delay(unsigned int del); /*===============*/ /* local defines */ /*===============*/ #define INPUT_BASE_ADDR 0x300 /* hardware input address */ #define OUTPUT_BASE_ADDR 0x300 /* hardware output address */ #define DBASE_WRITE_ADDR 0 /* database write location */ #define DBASE_READ_ADDR 1 /* database read location */ #define TRUE 1 /*=====================*/ /* function definition */ /*=====================*/ void main() { unsigned int temp_data; /* for reading database */ p_priority(199); /* set priority */ dbopen(); /* link to database */ c_detach(); /* detach from console */ while(TRUE) { temp_data = inp(INPUT_BASE_ADDR); /* read data from port */ dbwrit(DBASE_WRITE_ADDR, temp_data); /* write to the database */ temp_data = dbread(DBASE_READ_ADDR); /* read data from database */ outp(OUTPUT_BASE_ADDR+3, temp_data); /* write to output port */ p_delay(3); /* delay for 50 ms */ } } /* NOTE: IOBOARD.EXE is made up of ioboard.c, system.c, and dbsuport.c */ [LISTING SIX] /* file name logic.c */ /*====================*/ /* function prototype */ /*====================*/ void main(void); /*==============================*/ /* external function prototypes */ /*==============================*/ extern void dbopen(void); extern unsigned int dbread(int index); extern void dbwrit(int index, unsigned int value); extern unsigned int c_detach(void); extern void p_dispatch(void); /*===============*/ /* local defines */ /*===============*/ #define DATA_IN 0 /* data written by I/O process */ #define DATA_OUT 1 /* data read by I/O process */ #define TRUE 1 /*=====================*/ /* function definition */ /*=====================*/ void main() { static unsigned int last_data_read; /* old data retainer */ unsigned int temp_data; /* for reading database */ dbopen(); /* link to database */ c_detach(); /* detach from console */ while(TRUE) /* continuous loop */ { temp_data = dbread(DATA_IN); /* read input data */ if(temp_data ^ last_data_read) /* if there was a change */ { dbwrit(DATA_OUT, ~temp_data); /* write the to the port */ last_data_read = temp_data; /* save the new value */ } p_dispatch(); /* let another process run */ } } /* NOTE: LOGIC.EXE is made up of logic.c, system.c, and dbsuport.c */