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

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

Go to the documentation of this file.
00001 
00002 #include <errno.h>
00003 #include <stdlib.h>
00004 #include <unistd.h>
00005 #include <string.h>
00006 #include <signal.h>
00007 #include <sys/sched.h>
00008 #include <sys/psinfo.h>
00009 #include <sys/_devdrvr.h>
00010 #include <sys/kernel.h>
00011 #include <sys/ser_msg.h>
00012 #include "struct.h"
00013 
00014 #define PCMCIA
00015 
00016 #ifdef PCMCIA
00017 #include <sys/proxy.h>
00018 #include <sys/pcmcia.h>
00019 
00020 pcmcia_t pcmcia_handle;
00021 pid_t pcmcia_proxy;
00022 struct _pcmcia_io card_info;
00023 #endif
00024 
00025 /*
00026    declare the calls 'dev' will make into driver.
00027 */
00028 int far  Kick(struct output_buffer far *obuf);
00029 int far  Stty(struct termios far *tios); 
00030 int far  Ctrl(union ioctl_entry far *ioc); 
00031 
00032 #pragma aux (_dev_call) Kick;
00033 #pragma aux (_dev_call) Stty;
00034 #pragma aux (_dev_call) Ctrl;
00035 
00036 /*
00037  * Receive message buffer
00038  */
00039 
00040 union _async_msg {
00041    msg_t             type;
00042    msg_t             status;
00043    struct _ser_reset    reset;
00044    struct _ser_reset_reply reset_reply;
00045    struct _ser_query    query;
00046    struct _ser_query_reply query_reply;
00047    } msg;
00048 
00049 /*
00050  * Request from user for an option to set the initial state of RTS/CTS
00051  * (for use with multi-drop lines)
00052  */
00053 
00054 int num_asyncs = 0;
00055 long divisor;        // baudrate divisor, assumes on clock for all chips
00056 
00057 struct dev_entry dev_table[MAX_ASYNCS];
00058 struct dev_entry *dev_list[MAX_IRQS];
00059 
00060 struct device_ctrl ctrl[MAX_ASYNCS];
00061 struct dev_mode dmode[MAX_ASYNCS];
00062 struct driver_ctrl drv_ctrl;
00063 
00064 unsigned isize, osize, csize, high, low, sflow, hflow, raw, mode;
00065 int threshold = 0;
00066 long baud;
00067 int uses_pcmcia = 0;
00068 pid_t pcmcia_proxy = -1;
00069 char *prefix = "ser";
00070 
00071 int dev_handle;
00072 
00073 void terminate( int signal )
00074    {
00075    int index;
00076 
00077    switch(signal) {
00078    default:
00079    case SIGTERM:
00080       /*
00081        * Shutdown by signal
00082        */
00083       dev_drvr_shutdown( dev_handle );
00084       /*
00085        * We should give back any GDT's, etc. that
00086        * the system doesn't release for us
00087        */
00088       break;
00089 
00090    case SIGPWR:
00091       for(index = 0; index < num_asyncs; ++index) {
00092          if(dev_table[index].mode & MODE_PWR) {
00093             shutdown_async(index);
00094             }
00095          }
00096       break;
00097       }
00098    exit(0);
00099    }
00100 
00101 main(argc, argv)
00102 int argc; char *argv[];
00103    {
00104    int tty, i;
00105    int index = 0;
00106    int arg;
00107    unsigned base, irq;
00108    unsigned slot;
00109    register char *p;
00110    char *p1;
00111    struct input_buffer far *ibuf;
00112    struct output_buffer far *obuf;
00113    struct termios far *tios;
00114    pid_t pid;
00115    msg_t t;
00116    int nbytes;
00117 #ifdef PCMCIA
00118    struct dev_entry *dev;
00119 #endif
00120 
00121    setscheduler(0, SCHED_RR, 20);
00122 
00123    /*
00124     * Allow only SIGTERM, which we catch and cause
00125     * graceful termination, all others are ignored
00126     */
00127    for( i = _SIGMIN; i <= _SIGMAX; ++i)
00128       if( i != SIGTERM  &&  i != SIGPWR)
00129          signal( i, SIG_IGN );
00130 
00131    signal( SIGTERM, &terminate );
00132    signal( SIGPWR, &terminate );
00133 
00134    init_tables();
00135 
00136    /*
00137     * Setup Defaults
00138     */
00139 
00140    base = 0;
00141    irq = 4;
00142 
00143    isize = 2048;
00144    osize = 2048;
00145    csize = 256;
00146    high = -1;
00147    low = -1;
00148    baud = 9600;
00149    raw = 1;
00150    hflow = 1;
00151    sflow = 0;
00152    mode = (MODE_DTR | MODE_RTS | MODE_SPLIT);
00153    divisor = 115200L; /* divisor for baud rate */
00154 
00155    /*
00156     * Scan the arguments
00157     */
00158 
00159    for(arg = 1; arg < argc; ++arg) {
00160       p = argv[arg];
00161       if(*p == 0)
00162          continue;
00163       if(*p == '-') {
00164          while(*++p) {
00165             switch(*p) {
00166             case 'b':
00167                baud =  atol(*(p+1) ? p+1 : argv[++arg]);
00168                break;
00169             case 'C':
00170                csize = atoi(*(p+1) ? p+1 : argv[++arg]);
00171                break;
00172             case 'd':
00173                mode |= MODE_DTR;
00174                continue;
00175             case 'D':
00176                mode &= ~MODE_DTR;
00177                continue;
00178             case 'e':
00179                raw = 0;
00180                continue;
00181             case 'E':
00182                raw = 1;
00183                continue;
00184             case 'f':
00185                hflow = 1;
00186                continue;
00187             case 'F':
00188                hflow = 0;
00189                continue;
00190             case 'h':
00191                high =  atoi(*(p+1) ? p+1 : argv[++arg]);
00192                break;
00193             case 'I':
00194                isize = atoi(*(p+1) ? p+1 : argv[++arg]);
00195                break;
00196             case 'm':
00197                mode |= MODE_NOHUP;
00198                continue;
00199             case 'M':
00200                mode &= ~MODE_NOHUP;
00201                continue;
00202             case 'N':
00203                prefix =     *(p+1) ? p+1 : argv[++arg];
00204                break;
00205             case 'O':
00206                osize = atoi(*(p+1) ? p+1 : argv[++arg]);
00207                break;
00208             case 'l':
00209                low =   atoi(*(p+1) ? p+1 : argv[++arg]);
00210                break;
00211             case 'p':
00212                mode |= MODE_PKT;
00213                continue;
00214             case 'P':
00215                mode &= ~MODE_PKT;
00216                continue;
00217             case 'r':
00218                mode |= MODE_RTS;
00219                continue;
00220             case 'R':
00221                mode &= ~MODE_RTS;
00222                continue;
00223             case 's':
00224                mode |= MODE_SPLIT;
00225                continue;
00226             case 'S':
00227                mode &= ~MODE_SPLIT;
00228                continue;
00229             case 't':
00230                threshold = atoi(*(p+1) ? p+1 : argv[++arg]);
00231                break;
00232             case 'w':
00233                mode |= MODE_PWR;
00234                continue;
00235             case 'W':
00236                mode &= ~MODE_PWR;
00237                continue;
00238             case 'x':
00239                sflow = 1;
00240                continue;
00241             case 'X':
00242                sflow = 0;
00243                continue;
00244             case 'y':
00245                divisor = atol(*(p+1) ? p+1 : argv[++arg]);
00246                break;
00247 
00248                } /* switch */
00249 
00250             } /* while */
00251 
00252          continue;
00253          } /* if */
00254 
00255       else {
00256          /*
00257           * Got a new ioport[,irq[,'p']] or 'p'n[,n[,...]]
00258           */
00259          p1 = p;
00260          while(*p  &&  *p != ',') ++p;
00261          if(*p == ',')
00262             *p++ = 0;
00263          slot = 0;
00264          if(*p1 == 'p') {
00265              ++p1;
00266             while(*p1) {
00267                i = atoi(p1);
00268                if(i >= 1  &&  i <= 16)
00269                   slot |= 1 << (i - 1);
00270                p1 = p;
00271                while(*p  &&  *p != ',') ++p;
00272                if(*p == ',')
00273                   *p++ = 0;
00274                }
00275             base = 0;
00276             irq = 0;
00277             }
00278          else {
00279             base = atoh(p1);
00280             irq = 4;
00281             if(*p) {
00282                p1 = p;
00283                while(*p  &&  *p != ',') ++p;
00284                if(*p == ',')
00285                   *p++ = 0;
00286                irq = atoi(p1);
00287                if(*p == 'p')
00288                   slot = -1;
00289                }
00290             }
00291          new_async(num_asyncs++, base, irq, slot);
00292          }
00293 
00294       } /* for */
00295 
00296    /*
00297     * If no serial ports are given, then scan for all that exist
00298     * with the last state of the global options
00299     */
00300    if(num_asyncs == 0) {
00301       num_asyncs = find_asyncs();
00302       if(num_asyncs == 0)
00303          exit(0); /* terminate quietly if no serial ports */
00304       }
00305 
00306    if(num_asyncs <= 0  ||  num_asyncs >= MAX_ASYNCS) {
00307       exit(ERANGE);
00308       }
00309 
00310    /*
00311     * Register ourselves with the DEVICE Manager
00312     */
00313 
00314    if((dev_handle = dev_drvr_register("serial", prefix, num_asyncs,
00315                &Kick, &Stty, &Ctrl, &drv_ctrl, 0)) == -1) {
00316       exit(ENFILE);
00317       }
00318 
00319    tty = drv_ctrl.base_tty;
00320 
00321    /*
00322     * Create each of the devices now
00323     */
00324 
00325    for(index = 0; index < num_asyncs; ++index) {
00326 
00327       /*
00328        * Get a tty number, and allocate input/output buffers
00329        */
00330 
00331       if(dev_drvr_mount(dev_handle, tty, 1, &ctrl[index])) {
00332          dev_drvr_shutdown( dev_handle );
00333          exit(ENOMEM);
00334          }
00335 
00336       dev_table[index].tty = ctrl[index].tty;
00337       dev_table[index].obuf = ctrl[index].obuf;
00338    
00339       /*
00340        * Setup TERMIOS defaults
00341        */
00342       tios = ctrl[index].termios;
00343       tios->handle = index;
00344       if(dmode[index].raw) {
00345          tios->c_iflag      = 0;
00346          tios->c_oflag      = 0;
00347          tios->c_lflag      = (IEXTEN);
00348          tios->c_cflag      = (CREAD|CS8);
00349          tios->c_ispeed     = dev_table[index].baud;
00350          tios->c_ospeed     = dev_table[index].baud;
00351          tios->c_cc[VEOF]   = 0x00;
00352          tios->c_cc[VEOL]   = 0x00;
00353          tios->c_cc[VERASE]    = 0x00;
00354          tios->c_cc[VINTR]  = 0x00;
00355          tios->c_cc[VKILL]  = 0x00;
00356          tios->c_cc[VQUIT]  = 0x00;
00357          tios->c_cc[VSUSP]  = 0x00;
00358          tios->c_cc[VSTART]    = 0x11;
00359          tios->c_cc[VSTOP]  = 0x13;
00360          tios->c_cc[VMIN]   = 0x01;
00361          tios->c_cc[VTIME]  = 0x00;
00362          }
00363       else {
00364          tios->c_iflag      = (BRKINT|IXON|ICRNL);
00365          tios->c_oflag      = (OPOST);
00366          tios->c_lflag      = (ISIG|ICANON|ECHO|ECHOK|ECHOE|IEXTEN);
00367          tios->c_cflag      = (CREAD|CS8);
00368          tios->c_ispeed     = dev_table[index].baud;
00369          tios->c_ospeed     = dev_table[index].baud;
00370          tios->c_cc[VEOF]   = 0x04;
00371          tios->c_cc[VEOL]   = 0x00;
00372          tios->c_cc[VERASE]    = 0x7F;
00373          tios->c_cc[VINTR]  = 0x03;
00374          tios->c_cc[VKILL]  = 0x15;
00375          tios->c_cc[VQUIT]  = 0x00;
00376          tios->c_cc[VSUSP]  = 0x00;
00377          tios->c_cc[VSTART]    = 0x11;
00378          tios->c_cc[VSTOP]  = 0x13;
00379          tios->c_cc[VMIN]   = 0x01;
00380          tios->c_cc[VTIME]  = 0x00;
00381          }
00382 
00383       if(dmode[index].hflow) {
00384          tios->c_cflag |= (IHFLOW|OHFLOW);
00385          tios->c_qflag |= TC_PROTECT_HFLOW; /* Lock it on! */
00386          }
00387 
00388       if(dmode[index].sflow) {
00389          tios->c_iflag |= (IXON|IXOFF);
00390          tios->c_qflag |= TC_PROTECT_SFLOW; /* Lock it on! */
00391          }
00392    
00393       /*
00394        * Setup Output port handle
00395        */
00396       obuf = ctrl[index].obuf;
00397       obuf->handle = index;
00398       if(dmode[index].raw == 0)
00399          obuf->mode |= OUTPUT_XNL;
00400    
00401       /*
00402        * Setup default control parameters
00403        */
00404       ibuf = ctrl[index].ibuf;
00405       ibuf->handle = index;
00406       ibuf->sw_high_water = dmode[index].high;
00407       ibuf->sw_low_water = dmode[index].low;
00408       ibuf->hw_high_water = dmode[index].high+2;
00409       ibuf->hw_low_water = dmode[index].low-2;
00410 
00411       /*
00412        * Initialize Device
00413        */
00414       init(index, dev_table[index].iobase, dev_table[index].irq,
00415          dev_table[index].baud, dmode[index].mode);
00416    
00417       /*
00418        * Start up the device
00419        */
00420       if(dev_drvr_arm(tty)) {
00421          dev_drvr_shutdown( dev_handle );
00422          exit(ENODEV);
00423          }
00424 
00425       ++tty;
00426       }
00427 
00428 #ifdef PCMCIA     
00429    if(uses_pcmcia) {
00430       pcmcia_proxy = qnx_proxy_attach(0, 0, 0, -1);
00431       pcmcia_handle = qnx_pcmcia_io_attach(0);
00432       qnx_pcmcia_io_arm(pcmcia_handle, _PCMCIA_DEV_SERIAL, -pcmcia_proxy);
00433       /*
00434        * Kick a proxy now so that main loop will wake up and
00435        * scan for installed pcmcia cards right away
00436        */
00437       Trigger(pcmcia_proxy); 
00438       }
00439 #endif
00440 
00441    /*
00442     * Close off stdin,stdout,stderr since this process
00443     * is usually started in sysinit as a background process,
00444     * by the shell, which typically sets stdin to /dev/null
00445     * (on the machine we booted from), which ties up resources
00446     */
00447    close(0);
00448    close(1);
00449    close(2);
00450 
00451    qnx_pflags( _PPF_SERVER, _PPF_SERVER, 0, 0 );
00452 
00453    /*
00454     * Wait for Control messages.
00455     * The interrupt handlers will take care of ALL I/O
00456     */
00457 
00458    for(;;) {
00459       if((pid = Receive(0, &msg, sizeof(msg))) == -1)
00460          continue;
00461 
00462 #ifdef PCMCIA
00463       if(pid == pcmcia_proxy) {
00464          while(qnx_pcmcia_io_info(pcmcia_handle, _PCMCIA_DEV_SERIAL,
00465                &card_info) != -1) {
00466 
00467             slot = 1 << card_info.socket;
00468             base = card_info.base;
00469             irq = card_info.irq;
00470    
00471             if(card_info.flags & _PCMCIA_FLAG_CARD) {
00472    
00473                /*
00474                 * Scan for the device corresponding to this slot/port
00475                 */
00476                dev = &dev_table[0];
00477                for(index = 0; index < num_asyncs; ++index) {
00478                   if((dev->slots & slot) != 0
00479                          && (dev->iobase == 0 || dev->iobase == base) )
00480                      break;
00481                   ++dev;
00482                   }
00483                if(index >= num_asyncs)
00484                   continue;
00485    
00486                /*
00487                 * The card is now plugged in
00488                 * Reset the hardware registers to match the software state
00489                 * and link in to the appropriate interrupt chain.
00490                 */
00491                if(qnx_pcmcia_io_lock(pcmcia_handle, card_info.socket,
00492                      card_info.index) != -1) {
00493                   if(dev->slots != -1) {
00494                      dev->iobase = base;
00495                      dev->irq = irq;
00496                      }
00497                   dev->slot = card_info.socket + 1;
00498                   reset_async( index, 1 );
00499                   dev->mode |= MODE_AVAILABLE;
00500                   /*
00501                    * Tell Dev that the output buffer has
00502                    * a size > 0 which will allow write() to succeed.
00503                    */
00504                   ctrl[index].obuf->length = ctrl[index].osize;
00505                   }
00506                }
00507             else {
00508                /*
00509                 * Scan for the device corresponding to this slot/port
00510                 */
00511                dev = &dev_table[0];
00512                for(index = 0; index < num_asyncs; ++index) {
00513                   if((dev->slots & slot) != 0 && dev->iobase == base )
00514                      break;
00515                   ++dev;
00516                   }
00517                if(index >= num_asyncs)
00518                   continue;
00519    
00520                /*
00521                 * A card is now unplugged
00522                 */
00523                if(dev->mode & MODE_AVAILABLE) {
00524                   dev->mode &= ~MODE_AVAILABLE;
00525 
00526                   disable_irq( index );
00527 
00528                   if(dev->slots != -1) {
00529                      dev->iobase = 0;
00530                      dev->irq = 0;
00531                      }
00532                   dev->slot = 0;
00533                   /*
00534                    * Temporarily tell Dev that the output buffer has
00535                    * a size of zero bytes, which means treat as NULL
00536                    * device on writes()
00537                    */
00538                   ctrl[index].obuf->length = 0;
00539 
00540                   qnx_pcmcia_io_unlock(pcmcia_handle, card_info.socket,
00541                         card_info.index);
00542                   }
00543                }
00544             continue;
00545             }
00546          }
00547 #endif
00548 
00549       t = msg.type;
00550       msg.status = ENOSYS;
00551       nbytes = sizeof(msg.status);
00552 
00553       switch(t) {
00554 
00555       case 0:
00556          nbytes = sys_msg(&msg);
00557          break;
00558 
00559       case _SER_RESET:
00560          index = msg.reset.unit;
00561          if(index < 0  ||  index >= num_asyncs) { 
00562             msg.status = EINVAL;
00563             }
00564          reset_async( index, 1 );
00565          memset( &msg, 0, sizeof(msg.reset_reply) );
00566          msg.reset_reply.status = EOK;
00567          break;
00568 
00569       case _SER_QUERY:
00570          index = msg.query.unit;
00571          memset( &msg, 0, sizeof(msg.query_reply) );
00572          if(index < 0  ||  index >= num_asyncs) { 
00573             msg.status = EINVAL;
00574             }
00575          else {
00576             struct dev_entry *dev;
00577             dev = &dev_table[index];
00578             msg.query_reply.status = EOK;
00579             msg.query_reply.iobase = dev->iobase;
00580             msg.query_reply.irq    = dev->irq;
00581             msg.query_reply.mode   = dev->mode;
00582             msg.query_reply.slots  = dev->slots;
00583             msg.query_reply.slot   = dev->slot;
00584 // New in 4.23
00585             msg.query_reply.rx_count = dev->rx_count;
00586             msg.query_reply.tx_count = dev->tx_count;
00587             msg.query_reply.cur_state = (dev->modem_status & 0xF0)
00588                                  | (dev->modem_control & 0x03);
00589             }
00590          nbytes = sizeof(msg.query_reply);
00591          break;
00592 
00593       default:
00594          break;
00595          }
00596 
00597       if(nbytes)
00598          Reply( pid, &msg, nbytes);
00599       }
00600    }
00601 
00602 /*
00603  * Create a new device entry based on current values
00604  * in global variables
00605  */
00606 
00607 new_async(index, iobase, irq, slots)
00608 int index;
00609 unsigned iobase, irq;
00610 unsigned slots;
00611    {
00612 
00613    /*
00614     * Limit values to reasonable range
00615     */
00616    if(isize <  16)
00617       isize = 16;
00618    if(osize < 16)
00619       osize = 16;
00620    if(csize < 16)
00621       csize = 16;
00622    if(high == -1)
00623       high = isize / 4 * 3;
00624    if(high > (isize - 4))
00625       high = isize - 4;
00626    if(low == -1)
00627       low = isize / 4;
00628    if(low > (high - 4))
00629       low = high - 4;
00630 
00631    ctrl[index].isize = isize;
00632    ctrl[index].osize = osize;
00633    ctrl[index].csize = csize;
00634 
00635    dmode[index].raw = raw;
00636    dmode[index].hflow = hflow;
00637    dmode[index].sflow = sflow;
00638    dmode[index].mode = mode;
00639    dmode[index].high = high;
00640    dmode[index].low = low;
00641 
00642    dev_table[index].threshold = threshold;
00643    dev_table[index].iobase = iobase;
00644    dev_table[index].irq = irq;
00645    dev_table[index].baud = baud;
00646    dev_table[index].slots = slots;
00647 
00648    if(slots != 0)
00649       uses_pcmcia = 1;
00650 
00651    return(0);
00652    }

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