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
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
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
00051
00052
00053
00054 int num_asyncs = 0;
00055 long divisor;
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
00082
00083 dev_drvr_shutdown( dev_handle );
00084
00085
00086
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
00125
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
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;
00154
00155
00156
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 }
00249
00250 }
00251
00252 continue;
00253 }
00254
00255 else {
00256
00257
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 }
00295
00296
00297
00298
00299
00300 if(num_asyncs == 0) {
00301 num_asyncs = find_asyncs();
00302 if(num_asyncs == 0)
00303 exit(0);
00304 }
00305
00306 if(num_asyncs <= 0 || num_asyncs >= MAX_ASYNCS) {
00307 exit(ERANGE);
00308 }
00309
00310
00311
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
00323
00324
00325 for(index = 0; index < num_asyncs; ++index) {
00326
00327
00328
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
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;
00386 }
00387
00388 if(dmode[index].sflow) {
00389 tios->c_iflag |= (IXON|IXOFF);
00390 tios->c_qflag |= TC_PROTECT_SFLOW;
00391 }
00392
00393
00394
00395
00396 obuf = ctrl[index].obuf;
00397 obuf->handle = index;
00398 if(dmode[index].raw == 0)
00399 obuf->mode |= OUTPUT_XNL;
00400
00401
00402
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
00413
00414 init(index, dev_table[index].iobase, dev_table[index].irq,
00415 dev_table[index].baud, dmode[index].mode);
00416
00417
00418
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
00435
00436
00437 Trigger(pcmcia_proxy);
00438 }
00439 #endif
00440
00441
00442
00443
00444
00445
00446
00447 close(0);
00448 close(1);
00449 close(2);
00450
00451 qnx_pflags( _PPF_SERVER, _PPF_SERVER, 0, 0 );
00452
00453
00454
00455
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
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
00488
00489
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
00502
00503
00504 ctrl[index].obuf->length = ctrl[index].osize;
00505 }
00506 }
00507 else {
00508
00509
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
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
00535
00536
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
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
00604
00605
00606
00607 new_async(index, iobase, irq, slots)
00608 int index;
00609 unsigned iobase, irq;
00610 unsigned slots;
00611 {
00612
00613
00614
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 }