Main Page   Packages   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Search  

C:/temp/src/j2k/QNX4/driver/Par2/main.c

Go to the documentation of this file.
00001 #include <i86.h>
00002 #include <conio.h>
00003 #include <errno.h>
00004 #include <string.h>
00005 #include <stdlib.h>
00006 #include <unistd.h>
00007 #include <signal.h>
00008 #include <sys/types.h>
00009 #include <sys/sched.h>
00010 #include <sys/osinfo.h>
00011 #include <sys/psinfo.h>
00012 #include <sys/utsname.h>
00013 #include <sys/_devdrvr.h>
00014 #include <sys/kernel.h>
00015 #include <sys/proxy.h>
00016 
00017 #include "par.h"
00018 
00019 /*
00020    declare the calls 'dev' will make into driver.
00021 */
00022 int far  Kick  (struct output_buffer far *obuf);
00023 int far  Stty  (struct termios far *tios); 
00024 int far  Ctrl (union ioctl_entry far *ioc); 
00025 
00026 #pragma aux (_dev_call) Kick;
00027 #pragma aux (_dev_call) Stty;
00028 #pragma aux (_dev_call) Ctrl;
00029 
00030 union _printer_msg {
00031   msg_t  type;
00032   msg_t  status;
00033   char   filer[100];
00034 } msg;
00035 
00036 int idle = 1;
00037 volatile int  dangerous = 0;
00038 
00039 unsigned port = 0;
00040 int biosport  = 1;
00041 int osize     = 1000;
00042 
00043 /* 10 msec nap time */
00044 #define  NAP_TIME       10
00045 #define  NAPS_PER_SEC   (1000/NAP_TIME)
00046 #define  nap()          (delay(NAP_TIME))
00047 
00048 unsigned ioport = 0;
00049 unsigned cpu_speed;
00050 long     usec_wait = 1000; /* 1 msec default */
00051 long     io_retry;
00052 
00053 int      check_open = 0;
00054 int      rtimeout   = -1;
00055 
00056 struct driver_ctrl drv_ctrl;
00057 struct device_ctrl ctrl;
00058 
00059 /* Name will be  /dev/board1 */
00060 char* prefix = "board";
00061 
00062 #define  peekch(obuf)         (*(obuf)->tail)
00063 #define  abort_output(obuf)   ( (obuf)->discard = (obuf)->size)
00064 
00065 int dev_handle;
00066 
00067 void terminate( int signal ) {
00068  if (signal) {
00069    /* Shutdown by signal */
00070    dev_drvr_shutdown( dev_handle );
00071 
00072     /* We should give back any GDT's, etc.    */
00073     /* that the system doesn't release for us */
00074  }
00075  exit(0);
00076 }
00077 
00078 void main( int argc, char* argv[] ) {
00079   unsigned c;
00080   struct _osinfo osinfo;
00081   int i;
00082   int priority = 9;
00083   struct termios far *tios;
00084 
00085   /* Allow only SIGTERM, which we catch and cause */
00086   /* graceful termination, all others are ignored */
00087 
00088   for( i = _SIGMIN; i <= _SIGMAX; i++)
00089     if ( i != SIGTERM )
00090       signal( i, SIG_IGN );
00091 
00092   signal( SIGTERM, &terminate );
00093 
00094   /* Scan arguments */
00095 
00096   while ((c=getopt(argc,argv,"cO:N:p:b:w:s:P:")) != -1) {
00097     switch (c) {
00098       case  'c':
00099         check_open = 1;
00100         break;
00101       case  'O':
00102         osize = strtol(optarg,NULL,0);
00103         break;
00104       case  'N':
00105         prefix = optarg;
00106         break;
00107       case  'p':
00108         ioport = strtol(optarg,NULL,16);
00109         break;
00110       case  'b':
00111         biosport = strtol(optarg,NULL,16);
00112         break;
00113       case  's':
00114         if ((rtimeout = strtol(optarg,NULL,10) * NAPS_PER_SEC) == 0) {
00115           rtimeout = 1;  /* sleep at least once... */
00116         }
00117         break;
00118       case  'w':
00119         usec_wait = strtol(optarg,NULL,0);
00120         break;
00121       case  'P':
00122         priority = strtol(optarg,NULL,0);
00123         break;
00124     }
00125   } // End of which()
00126 
00127   setscheduler(0, SCHED_FAIR, priority);
00128 
00129   if (ioport == 0) {
00130     ioport = next_printer(biosport);
00131     if (ioport == 0)
00132        exit(0); /* Terminate quietly if no parallel ports */
00133   }
00134 
00135   qnx_osinfo((nid_t) 0, &osinfo);
00136   cpu_speed = osinfo.cpu_speed;
00137   io_retry = (cpu_speed / 100) *  usec_wait;
00138 
00139   /* Register ourselves with the DEVICE Manager */
00140 
00141   if ((dev_handle = dev_drvr_register( "elan104board", prefix, 1,
00142                &Kick, &Stty, &Ctrl, &drv_ctrl, 0)) == -1)
00143   {
00144     exit(ENFILE);
00145   }
00146 
00147   /* Allocate the resources for this device */
00148 
00149   ctrl.isize = 0;
00150   ctrl.osize = osize;
00151   ctrl.csize = 0;
00152 
00153   if (dev_drvr_mount(dev_handle, drv_ctrl.base_tty, 1, &ctrl)) {
00154     dev_drvr_shutdown( dev_handle );
00155     exit(ENOMEM);
00156   }
00157    
00158   /* Initialize 'stty' settings to consistent values */
00159   ctrl.obuf->mode |= OUTPUT_XNL;
00160 
00161   tios = ctrl.termios;
00162   tios->c_cflag = (CS8);
00163   tios->c_oflag = (OPOST);
00164   tios->c_iflag = 0;
00165   tios->c_lflag = 0;
00166   tios->c_ispeed = 0L;
00167   tios->c_ospeed = 9600L;
00168 
00169   /* OUTPUT DRIVER */
00170   init_printer(ioport);
00171   idle = 0;
00172   port = qnx_proxy_attach(0, 0, 0, -1);
00173 
00174   /* Let DEV call us now */
00175 
00176   if (dev_drvr_arm(ctrl.tty)) {
00177     dev_drvr_shutdown( dev_handle );
00178     exit(ENODEV);
00179   }
00180 
00181   /*
00182    * Close off stdin,stdout,stderr since this process
00183    * is usually started in sysinit as a background process,
00184    * by the shell, which typically sets stdin to /dev/null
00185    * (on the machine we booted from), which ties up resources
00186    */
00187    close(0);
00188    close(1);
00189    close(2);
00190 
00191    qnx_pflags( _PPF_SERVER, _PPF_SERVER, 0, 0 );
00192 
00193 
00194 #define GAURD(X)  ((dangerous=1),(X),(dangerous=0))
00195 
00196    for(;;) {
00197       GAURD(idle = (ctrl.obuf->size == 0));
00198 
00199       if (idle) {
00200         /* If nothing to print (at this time)        */
00201         /* then set flag and wait for DEV to Kick us */
00202 
00203         wait_msg(port);
00204         continue;    
00205       }
00206 
00207       if (flush_buffer(ctrl.obuf)) {
00208         continue;
00209       }
00210 
00211       /* Get the next character to print */
00212       /* from the output buffer          */
00213       if ((c=peekch(ctrl.obuf)) == '\n' && (ctrl.obuf->mode & OUTPUT_XNL)) {
00214          if (outch('\r',ctrl.obuf) == -1) {  /* failed on a write */
00215            abort_output(ctrl.obuf);
00216            continue;
00217          }
00218       }
00219 
00220       if (outch(c,ctrl.obuf) == -1) {
00221         abort_output(ctrl.obuf);
00222         continue;
00223       }
00224 
00225       /* If we broke out because of a request to flush
00226        * output, then start the loop over without printing
00227        * this character
00228        */
00229 
00230       advance(ctrl.obuf);
00231       }
00232    }
00233 
00234 short prtready(port,strict)
00235    {
00236    short c;
00237 
00238    c = inp(port+REG_STAT);
00239    return strict ?
00240          (c&STATUS_MASK) == STATUS_OK :
00241          (c&NOTBUSY) == NOTBUSY;
00242    }
00243 
00244 
00245 outch(int ch, const struct output_buffer far *obuf)
00246    {
00247    int   tick;
00248    long  x;
00249 
00250    /*
00251     * Wait (possible forever) for BUSY to go off
00252     */
00253    for (tick=rtimeout,x=io_retry;  !prtready(ioport,0);) {
00254       if (obuf->discard)
00255          return -1;
00256       if (x--)
00257          continue;
00258       x = io_retry;
00259       nap();
00260       if (tick != -1) {
00261          if (--tick == 0) {
00262             return -1;
00263             }
00264          }
00265       }
00266    /*
00267     * Write the character
00268     */
00269    outp(ioport, ch);
00270 
00271    /*
00272     * Pulse the strobe line
00273     */
00274    udelay(2);
00275 
00276    outp(ioport + REG_CNTL, 0x0D );
00277    udelay(1); /* Wait a bit (scaled on CPU speed) */
00278    outp(ioport + REG_CNTL, 0x0C );
00279    udelay(2);
00280    return 0;
00281    }  
00282 
00283 /*
00284  * Kick is called by DEV everytime something "new" happens
00285  * to the output buffer
00286  *
00287  * It will set 'obuf' to be the output buffer
00288  * It will also set ds to be the data segment of the driver being called
00289  *
00290  * Since this routine is "called" by DEV, it will ALWAYS run at higher
00291  * priority than the driver task, so cannot be interrupted.
00292  */
00293 
00294 int far Kick (struct output_buffer far *obuf)   {
00295    if(obuf->size > 0) {
00296       if(idle || dangerous) {
00297          idle = 0;
00298          Trigger(port);
00299          }
00300       return(1);
00301       }
00302    return(0);
00303    }
00304 
00305 /*
00306  * Stty is called by DEV to indicate a significant change in the
00307  * termios control structure (baud rate, modem control)
00308  *
00309  * It will set 'tios' to be a far pointer to the termios entry
00310  * It will also set ds to be the data segment of the driver being called
00311  *
00312  * Since this routine is "called" by DEV, it will ALWAYS run at higher
00313  * priority than the driver task, so cannot be interrupted.
00314  */
00315 
00316 
00317 int far Stty (struct termios far *tios)
00318    {
00319    unsigned cflags;
00320 
00321    /*
00322     * Use 'tios' to keep the compiler happy
00323     */
00324    cflags = tios->c_cflag;
00325 
00326    return(0);
00327    }
00328 
00329 /*
00330  * Ctrl is called by DEV to indicate a high level
00331  * control function
00332  *
00333  * It will set 'ioc' to be an ioctl control block
00334  * It will also set ds to be the data segment of the driver being called
00335  *
00336  * Since this routine is "called" by DEV, it will ALWAYS run at higher
00337  * priority than the driver task, so cannot be interrupted.
00338  */
00339 
00340 int far Ctrl (union ioctl_entry far *ioc)
00341    {
00342    int type;
00343 
00344    type = ioc->type;
00345    ioc->status = IOCTL_ERROR;
00346    switch (type) {
00347    case  IOCTL_OPEN:
00348       ioc->status = (check_open && !prtready(ioport,1)) ? IOCTL_NONE_FREE
00349                : IOCTL_OK;
00350       return(0);
00351    case  IOCTL_CLOSE:
00352       ioc->status = IOCTL_OK;
00353       return(0);
00354    case  IOCTL_CTL:  
00355       {
00356          unsigned unit = ioc->user.unit;
00357          unsigned char bits, mask, oldbits;
00358 
00359          if(unit > 1  ||  unit <= 0) {
00360             ioc->status = IOCTL_BAD_UNIT;
00361             return(0);
00362             }
00363          
00364          mask = ioc->user.data[4];
00365          bits = ioc->user.data[0];
00366          _disable();
00367          oldbits = inp( ioport + REG_STAT );
00368          outp( ioport + REG_STAT, (oldbits & ~mask) | (bits & mask));
00369          _enable();
00370          ioc->user_return.data[0] = oldbits;
00371 
00372          mask = ioc->user.data[5];
00373          bits = ioc->user.data[1];
00374          _disable();
00375          oldbits = inp( ioport + REG_CNTL );
00376          outp( ioport + REG_CNTL, (oldbits & ~mask) | (bits & mask));
00377          _enable();
00378          ioc->user_return.data[1] = oldbits;
00379 
00380          ioc->user_return.data[2] = 0;
00381          ioc->user_return.data[3] = 0;
00382          ioc->user_return.nbytes = 4;
00383          ioc->user_return.status = IOCTL_OK;
00384          return(0);
00385          }
00386       }
00387    return(-1);
00388    }
00389 
00390 next_printer(unsigned n) {
00391    unsigned far *port;
00392 
00393    port = MK_FP(0x0040, (2*(n-1))+0x0008);
00394    n = *port;
00395    return(n);
00396    }
00397 
00398 
00399 init_printer(port)
00400 unsigned port;
00401    {
00402    outp(port + REG_CNTL, 0x0C );
00403    return(0);
00404    }
00405 
00406 
00407 /*
00408  * Attempt to busy-wait for a number of microseconds
00409  */
00410 
00411 udelay(usec)
00412 unsigned usec;
00413    {
00414    unsigned i, u;
00415 
00416    for(i = 0; i < usec; ++i) {
00417       for(u = 0; u < cpu_speed; u+= 100)
00418          ;
00419       }
00420    return(0);
00421    }
00422 
00423 wait_msg(pid_t port)
00424    {
00425    pid_t pid;
00426    int nbytes;
00427    extern int sys_msg(void *);
00428 
00429    while(1) {
00430       /*
00431        * Consume all messages from processes
00432        */
00433       if ((pid = Receive(0, &msg, sizeof(msg))) == port)
00434          break;
00435       /*
00436        * Otherwise, respond to message and wait for proxy
00437        */
00438       nbytes = 1;
00439       if(msg.type == 0)
00440          nbytes = sys_msg(&msg);
00441       else
00442          msg.status = ENOSYS;
00443       if(nbytes)
00444          Reply(pid, &msg, nbytes);
00445       }
00446    }
00447 
00448 flush_buffer(struct output_buffer far *obuf)
00449    {
00450    int   i;
00451    int   n;
00452 
00453    _disable();
00454    if((n=obuf->discard) == 0) {
00455       _enable();
00456       return 0;
00457       }
00458    /*
00459     * Discard some (or all) data instead of displaying it
00460     */
00461    obuf->discard = 0;
00462    obuf->size -= n;
00463    _enable();
00464       
00465    i = &obuf->buffer[obuf->length] - obuf->tail;
00466    if(i > n)
00467       obuf->tail += n;
00468    else
00469       obuf->tail = &obuf->buffer[n-i];
00470 
00471    low_water(obuf);
00472    return 1;
00473    }
00474 
00475 advance(struct output_buffer far *obuf)
00476    {
00477    /*
00478     * Advance tail pointer after character has been printed
00479     */
00480    ++obuf->tail;
00481    if(obuf->tail >= &obuf->buffer[obuf->length])
00482       obuf->tail = &obuf->buffer[0];
00483 
00484    /*
00485     * Decrement the queue size
00486     */
00487    _disable();
00488    --obuf->size;
00489 
00490    /*
00491     * If size of buffer drops below notification threshold,
00492     * inform DEV of the new information
00493     */
00494    low_water(obuf);
00495    return obuf->size != 0;
00496    } 
00497    
00498 low_water(struct output_buffer far *obuf)
00499    {
00500    /*
00501     * Inform DEV if the output buffer is now
00502     * below the notification threshold
00503     */
00504    _disable();
00505    if(obuf->size < obuf->bcount) {
00506       obuf->bcount = 0;
00507       obuf->action |= ACT_OUTPUT_READY;
00508       _enable();
00509       Trigger(drv_ctrl.hw_pid);
00510       }
00511    else
00512       _enable();
00513    return 1;
00514    }

Generated on Sun Oct 14 18:46:41 2001 for Standard J2K Library by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001