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
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
00077
00078 tti = drv_ctrl.tti;
00079 tti_ds = drv_ctrl.tti_ds;
00080
00081
00082
00083
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
00094
00095 qnx_hint_attach( -1, &poll_devices, FP_SEG(&dev_table) );
00096 }
00097
00098 }
00099
00100
00101
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
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
00125
00126
00127 outp(port + 1, 0x00);
00128 inp(port + 5);
00129 inp(port + 0);
00130 inp(port + 2);
00131 inp(port + 6);
00132 _enable();
00133 return(1);
00134 }
00135 }
00136 _enable();
00137 return(0);
00138 }
00139
00140
00141
00142
00143
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
00171
00172 if(ttp->baud == 0)
00173 value = 0;
00174 else
00175 value = divisor / ttp->baud;
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
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
00192
00193 outp(port + 1, 0x00);
00194 inp(port + 5);
00195 inp(port + 0);
00196 inp(port + 2);
00197 ttp->modem_status = inp(port + 6) & 0xF0;
00198
00199
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
00214
00215
00216
00217
00218
00219
00220
00221 outp(port+2, value);
00222 if((inp(port+2) & 0xC0) != 0xC0)
00223 outp(port+2, 0x00);
00224 }
00225
00226
00227
00228 outp(port+1, 0x0f);
00229
00230 if((ttp->mode & MODE_IRQ_LINKED) == 0) {
00231 ttp->mode |= MODE_IRQ_LINKED;
00232
00233
00234
00235 ttp->link = dev_list[ttp->irq];
00236 dev_list[ttp->irq] = ttp;
00237
00238 if(int_enabled[ttp->irq] == 0) {
00239
00240
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
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
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
00294
00295
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
00307
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);
00316 }
00317
00318 #pragma on (check_stack);