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/init.c

Go to the documentation of this file.
00001 
00002 #include "struct.h"
00003 #include <conio.h>
00004 #include <i86.h>
00005 #include <sys/irqinfo.h>
00006 #include <sys/trace.h>
00007 #include <sys/tracecod.h>
00008 
00009 extern struct dev_entry dev_table[];
00010 extern struct dev_entry *dev_list[];
00011 extern struct driver_ctrl drv_ctrl;
00012 extern int num_asyncs;
00013 extern long divisor;
00014 
00015 pid_t (far *tti)(int, int, unsigned);
00016 unsigned tti_ds;
00017 
00018 static char timer_enabled = 0;
00019 
00020 static char int_enabled[16] ={
00021    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
00022 
00023 static unsigned irq_hdl[16] ={
00024    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
00025 
00026 pid_t (far *async_irq[16])();
00027 
00028 void init_tables() {
00029    async_irq[0] = &async_irq0;
00030    async_irq[1] = &async_irq1;
00031    async_irq[2] = &async_irq2;
00032    async_irq[3] = &async_irq3;
00033    async_irq[4] = &async_irq4;
00034    async_irq[5] = &async_irq5;
00035    async_irq[6] = &async_irq6;
00036    async_irq[7] = &async_irq7;
00037    async_irq[8] = &async_irq8;
00038    async_irq[9] = &async_irq9;
00039    async_irq[10] = &async_irq10;
00040    async_irq[11] = &async_irq11;
00041    async_irq[12] = &async_irq12;
00042    async_irq[13] = &async_irq13;
00043    async_irq[14] = &async_irq14;
00044    async_irq[15] = &async_irq15;
00045    }
00046 
00047 void init(index, base, irq, baud, mode)
00048 int index;
00049 unsigned base, irq;
00050 long baud;
00051 int mode;
00052    {
00053    register struct dev_entry *ttp;
00054    extern pid_t far poll_devices();
00055 
00056    /*
00057     * Get a free dev_entry
00058     */
00059    ttp = &dev_table[index];
00060 
00061    ttp->iobase = base;
00062    ttp->irq = irq;
00063    ttp->busy = 0;
00064    ttp->baud = baud;
00065    ttp->parity = 0;
00066    ttp->stop_bits = 1;
00067    ttp->data_bits = 8;
00068    ttp->mode = mode;
00069    ttp->modem_control = (inp(ttp->iobase+4) & 0xE4) | 0x08;
00070    if(mode & MODE_DTR)
00071       ttp->modem_control |= 1;
00072    if(mode & MODE_RTS)
00073       ttp->modem_control |= 2;
00074 
00075    /*
00076     * Tell irq handler(s) how to call Dev
00077     */
00078    tti = drv_ctrl.tti;
00079    tti_ds = drv_ctrl.tti_ds;
00080 
00081    /*
00082     * Only setup IRQ handler for non-pcmcia devices
00083     * pcmcia devices will have this done later when card is inserted
00084     */
00085 
00086    if(ttp->slots == 0  &&  irq > 0  &&  irq <= 15) {
00087       reset_async(index, 1);
00088       }
00089 
00090    if(timer_enabled == 0) {
00091       timer_enabled = 1;
00092       /*
00093        * Link into 100 msec timer chain
00094        */
00095       qnx_hint_attach( -1, &poll_devices, FP_SEG(&dev_table) );
00096       }
00097 
00098    }
00099 
00100 /*
00101  * Default device scan
00102  */
00103 
00104 
00105 int find_asyncs() {
00106    if(check_async(0x3f8))
00107          new_async(num_asyncs++, 0x3f8, 4, 0);
00108    if(check_async(0x2f8))
00109          new_async(num_asyncs++, 0x2f8, 3, 0);
00110    return(num_asyncs);
00111    }
00112 
00113 static int check_async(unsigned port)
00114    {
00115    /*
00116     * Use Line control latch to determine if controller card is present
00117     */
00118    _disable();
00119    outp(port + 3, 0x05);
00120    if(inp(port + 3) == 0x05) {
00121       outp(port + 3, 0x0a);
00122       if(inp(port + 3) == 0x0a) {
00123          /*
00124           * Found one....
00125           * Clear any pending interrupts
00126           */
00127          outp(port + 1, 0x00);   /* Disable all interrupts */
00128          inp(port + 5);    /* Clear Line Status Interrupt */
00129          inp(port + 0);    /* Clear RX Interrupt */
00130          inp(port + 2);    /* Clear TX Interrupt */
00131          inp(port + 6);    /* Clear Modem Interrupt */
00132          _enable();
00133          return(1);
00134          }
00135       }
00136    _enable();
00137    return(0);
00138    }
00139 
00140 
00141 /*
00142  * These routines are called by Stty(), so make SURE that
00143  * stack checking is OFF
00144  */
00145 #pragma off (check_stack);
00146 
00147 static void set_port(port, mask, data)
00148 unsigned port, mask, data;
00149    {
00150    unsigned char c;
00151    c = inp(port);
00152    outp(port, (c & ~mask) | (data & mask));
00153    }
00154 
00155 int reset_async(index, init)
00156 int index;
00157 int init;
00158    {
00159    register struct dev_entry *ttp;
00160    unsigned port;
00161    unsigned value;
00162 
00163    ttp = &dev_table[index];
00164    port = ttp->iobase;
00165 
00166    if(port == 0)
00167       return(0);
00168 
00169    /*
00170     * Set Baud rate
00171     */
00172    if(ttp->baud == 0)
00173       value = 0;
00174    else
00175       value = divisor / ttp->baud; /* calculate divisor for baud rate */
00176 
00177    _disable();
00178    set_port(port + 3, 0x80, 0x80);
00179    set_port(port + 0, 0xff, value & 0xff);
00180    set_port(port + 1, 0xff, value >> 8);
00181    set_port(port + 3, 0x80, 0);
00182    /*
00183     * Set parity, stop bits and data bits
00184     */
00185    set_port(port + 3, 0xFF, ((ttp->parity & 7) << 3)
00186                      | (((ttp->stop_bits - 1) & 1) << 2)
00187                      | ((ttp->data_bits - 5) & 3) );
00188 
00189    if(init) {
00190       /*
00191        * Save initial modem status, and also clear all interrupts
00192        */
00193       outp(port + 1, 0x00);   /* Disable all interrupts */
00194       inp(port + 5); /* Clear Line Status Interrupt */
00195       inp(port + 0); /* Clear RX Interrupt */
00196       inp(port + 2); /* Clear TX Interrupt */
00197       ttp->modem_status = inp(port + 6) & 0xF0; /* Clear Modem Interrupt */
00198       /*
00199        * turn on DTR, RTS
00200        */
00201       outp(port+4, ttp->modem_control);
00202 
00203       switch(ttp->threshold) {
00204          case 1:  value = 0x01; break;
00205          case 4:  value = 0x41; break;
00206          case 8:  value = 0x81; break;
00207          case 14: value = 0xC1; break;
00208          default: value = 0; break;
00209          }
00210 
00211       if(value) {
00212          /*
00213           * Try to enable 1/4/8/14-deep FIFO mode if a 16550
00214           * NOTE: That this is NOT always desirable since it significantly
00215           *       affects recieved character timing, and does NOT
00216           *       significantly increase receive performance.
00217           *       (Keep in mind that the 16550 with FIFO disabled
00218           *        is still very useful, since it SHOULD buffer
00219           *        up to 16 received characters even when FIFO is off)
00220           */
00221          outp(port+2, value);
00222          if((inp(port+2) & 0xC0) != 0xC0)
00223             outp(port+2, 0x00);                 
00224          }
00225       /*
00226        * Enable ALL interrupt sources
00227        */
00228       outp(port+1, 0x0f);
00229 
00230       if((ttp->mode & MODE_IRQ_LINKED) == 0) {
00231          ttp->mode |= MODE_IRQ_LINKED;
00232          /*
00233           * Add this device to the list of devices at the specified interrupt
00234           */
00235          ttp->link = dev_list[ttp->irq];
00236          dev_list[ttp->irq] = ttp;
00237       
00238          if(int_enabled[ttp->irq] == 0) {
00239             /*
00240              * Vector IRQ to our async handler
00241              */
00242             _enable();
00243             irq_hdl[ttp->irq] = qnx_hint_attach(ttp->irq, async_irq[ttp->irq], FP_SEG(&drv_ctrl));
00244             int_enabled[ttp->irq] = 1;
00245             }
00246          }
00247       }
00248 
00249    _enable();
00250 
00251    return(0);
00252    }
00253 
00254 void disable_irq( int index )
00255    {
00256    register struct dev_entry *ttp, *tt;
00257    int irq;
00258 
00259    ttp = &dev_table[index];
00260    irq = ttp->irq;
00261 
00262    if((ttp->mode & MODE_IRQ_LINKED) != 0) {
00263       ttp->mode &= ~MODE_IRQ_LINKED;
00264       /*
00265        * Remove this device from list of devices at the specified interrupt
00266        */
00267       tt = (struct dev_entry *) &dev_list[irq];
00268       while(tt) {
00269          if(tt->link == ttp) {
00270             tt->link = ttp->link;
00271             ttp->link = 0;
00272             break;
00273             }
00274          }
00275       
00276       if(dev_list[irq] == 0) {
00277          /*
00278           * IRQ list is now empty
00279           */
00280          int_enabled[irq] = 0;
00281          qnx_hint_detach(irq_hdl[irq]);
00282          }
00283       }
00284    }
00285 
00286 pid_t far poll_devices() {
00287    int i;
00288    struct dev_entry *dev = &dev_table[0];
00289 
00290    for( i = 0; i < num_asyncs; ++i) {
00291       if(dev->iobase != 0  &&  dev->tx_pending != 0  &&  --dev->tx_pending == 0) {
00292          /*
00293           * Compensate for "bugs" (especially CMOS parts) which cause 
00294           * missed Tx interrupts.
00295           * Rely on periodic "polling" to reset the chip.
00296           */
00297          outp(dev->iobase+1, 0x0f);
00298          Trace1( (long)_TRACE_DEV_SER_TIMEOUT, _TRACE_TRANSIENT, dev->iobase );
00299          }
00300       ++dev;
00301       }
00302    return(0);
00303    }
00304 
00305 /*
00306  * If -w is specified, then Dev.ser will disable interrupts
00307  * on the serial chip when SIGPWR is received (soft reboot)
00308  */
00309 
00310 shutdown_async(int index) {
00311    unsigned iobase;
00312 
00313    iobase = dev_table[index].iobase;
00314    if(iobase != 0)
00315       outp(iobase + 1, 0x00); /* Disable IER */
00316    }
00317 
00318 #pragma on (check_stack);

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