00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #define DEBUGMODE
00028
00029 #include <sys/types.h>
00030 #include <sys/sched.h>
00031 #include <sys/kernel.h>
00032 #include <sys/proxy.h>
00033 #include <sys/psinfo.h>
00034 #include <stdlib.h>
00035 #include <unistd.h>
00036 #include <errno.h>
00037 #include <signal.h>
00038
00039 #include <sys/_devdrvr.h>
00040
00041 #ifdef DEBUGMODE
00042 #include <sys/dev.h>
00043 unsigned old_mode;
00044 #endif
00045
00046 extern int far Kick (struct output_buffer far *obuf);
00047 extern int far Stty (struct termios far *tios);
00048 extern int far Ctrl (union ioctl_entry far *ioc);
00049
00050 extern int sys_msg( void * );
00051
00052 union _private_msg {
00053 msg_t type;
00054 msg_t status;
00055 char filer[100];
00056 } msg;
00057
00058 int idle = 1;
00059 int more = 0;
00060
00061 pid_t out_proxy;
00062 pid_t in_proxy;
00063 pid_t proxy;
00064
00065 unsigned isize = 2048;
00066 unsigned osize = 2048;
00067 unsigned csize = 256;
00068
00069 #define MAX_DEVICES 10
00070
00071 struct driver_ctrl drv_ctrl;
00072 struct device_ctrl ctrl[MAX_DEVICES];
00073 int dev_handle;
00074 int num_devices = 1;
00075 unsigned driver_options = 0;
00076
00077 char *prefix = "tst";
00078
00079 main(argc, argv)
00080 int argc; char *argv[];
00081 {
00082 unsigned c;
00083 int i;
00084 pid_t pid;
00085 int t;
00086 int nbytes;
00087 extern void terminate();
00088
00089 setscheduler(0, SCHED_FIFO, 15);
00090
00091
00092
00093
00094
00095 for( i = _SIGMIN; i <= _SIGMAX; ++i)
00096 if( i != SIGTERM)
00097 signal( i, SIG_IGN );
00098
00099 signal( SIGTERM, &terminate );
00100
00101
00102
00103
00104 while ((c=getopt(argc,argv,"C:I:O:N:n:")) != -1) {
00105 switch (c) {
00106
00107 case 'C':
00108 csize = strtol(optarg,NULL,0);
00109 break;
00110
00111 case 'I':
00112 isize = strtol(optarg,NULL,0);
00113 break;
00114
00115 case 'O':
00116 osize = strtol(optarg,NULL,0);
00117 break;
00118
00119 case 'N':
00120 prefix = optarg;
00121 break;
00122
00123 case 'n':
00124 num_devices = strtol(optarg,NULL,0);
00125 if(num_devices > MAX_DEVICES)
00126 num_devices = MAX_DEVICES;
00127 break;
00128
00129 }
00130 }
00131
00132
00133
00134
00135
00136 if((dev_handle = dev_drvr_register("custom", prefix, num_devices,
00137 &Kick, &Stty, &Ctrl, &drv_ctrl, driver_options)) == -1) {
00138 exit(ENFILE);
00139 }
00140
00141
00142
00143
00144
00145 for(i = 0; i < num_devices; ++i) {
00146 ctrl[i].isize = isize;
00147 ctrl[i].osize = osize;
00148 ctrl[i].csize = csize;
00149 }
00150
00151 if(dev_drvr_mount(dev_handle, drv_ctrl.base_tty, num_devices, &ctrl[0])) {
00152 dev_drvr_shutdown( dev_handle );
00153 exit(ENOMEM);
00154 }
00155
00156 out_proxy = qnx_proxy_attach(0, 0, 0, -1);
00157 in_proxy = qnx_proxy_attach(0, 0, 0, -1);
00158
00159 #ifndef DEBUGMODE
00160
00161
00162
00163
00164
00165
00166 close(0);
00167 close(1);
00168 close(2);
00169 #endif
00170
00171
00172
00173
00174 qnx_pflags( _PPF_SERVER, _PPF_SERVER, 0, 0 );
00175
00176
00177
00178
00179
00180
00181 for( i = 0; i < num_devices; ++i ) {
00182
00183 struct output_buffer far *obuf;
00184 struct termios far *tios;
00185
00186 obuf = ctrl[i].obuf;
00187 obuf->mode |= OUTPUT_XNL;
00188
00189 tios = ctrl[i].termios;
00190
00191 tios->c_ispeed = tios->c_ospeed = 9600;
00192
00193 tios->c_cflag = (CREAD);
00194 tios->c_oflag = (OPOST);
00195 tios->c_iflag = (ICRNL|IXON|BRKINT);
00196 tios->c_lflag = (ICANON|ISIG|ECHO|ECHOE|ECHOK|IEXTEN);
00197
00198 tios->c_cc[VEOF] = 0x04;
00199 tios->c_cc[VEOL] = 0x00;
00200 tios->c_cc[VERASE] = 0x7F;
00201 tios->c_cc[VINTR] = 0x03;
00202 tios->c_cc[VKILL] = 0x18;
00203 tios->c_cc[VQUIT] = 0x00;
00204 tios->c_cc[VSUSP] = 0x00;
00205 tios->c_cc[VSTART] = 0x11;
00206 tios->c_cc[VSTOP] = 0x13;
00207
00208 tios->c_cc[VMIN] = 0x01;
00209 tios->c_cc[VTIME] = 0x00;
00210 }
00211
00212
00213
00214
00215
00216 init_driver();
00217
00218
00219
00220
00221
00222 for(i = 0; i < num_devices; ++i) {
00223 if(dev_drvr_arm(ctrl[i].tty)) {
00224 dev_drvr_shutdown( dev_handle );
00225 exit(ENODEV);
00226 }
00227 }
00228
00229
00230
00231
00232
00233
00234 for(;;) {
00235
00236 pid = Receive( 0, &msg, sizeof(msg) );
00237
00238 if(pid == out_proxy) {
00239 idle = 1;
00240
00241
00242
00243 flush_output();
00244 continue;
00245 }
00246
00247 if(pid == in_proxy) {
00248
00249
00250
00251
00252
00253 input_ready();
00254 continue;
00255 }
00256
00257
00258
00259
00260
00261 t = msg.type;
00262 msg.status = ENOSYS;
00263 nbytes = sizeof(msg.status);
00264
00265 switch(t) {
00266
00267 case 0:
00268 nbytes = sys_msg(&msg);
00269 break;
00270
00271 default:
00272 break;
00273 }
00274
00275 if(nbytes)
00276 Reply(pid, &msg, nbytes);
00277
00278 continue;
00279 }
00280 }
00281
00282
00283 void terminate( int signal )
00284 {
00285 if(signal) {
00286
00287
00288
00289 dev_drvr_shutdown( dev_handle );
00290
00291
00292
00293
00294 exit_driver();
00295 }
00296 exit(0);
00297 }
00298
00299
00300
00301
00302
00303
00304
00305
00306 int input_ready() {
00307 pid_t proxy;
00308 int i, n;
00309 char buf[100];
00310
00311 proxy = 0;
00312
00313
00314
00315
00316 for( i = 0; i < num_devices; ++i ) {
00317 while( (n = get_data(i, &buf[0], sizeof(buf))) > 0 ) {
00318 if(drv_ctrl.ttim_offset != 0) {
00319
00320
00321
00322 pid_t (far *ttimcall) (int tty, int len, char far *data, unsigned ds);
00323 ttimcall = MK_FP( FP_SEG(drv_ctrl.tti), drv_ctrl.ttim_offset );
00324 proxy |= (*ttimcall) (ctrl[i].tty, n, &buf[0], drv_ctrl.tti_ds);
00325 }
00326 else {
00327
00328
00329
00330 int j;
00331 for(j = 0; j < n; ++j)
00332 proxy |= (*drv_ctrl.tti) (buf[j], ctrl[i].tty, drv_ctrl.tti_ds);
00333 }
00334 }
00335 }
00336
00337
00338
00339
00340 if(proxy)
00341 Trigger(proxy);
00342
00343 return(0);
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 flush_output() {
00356 struct output_buffer far *obuf;
00357 char far *tail;
00358 char far *end;
00359 char far *begin;
00360 int i, n, size;
00361 int nothing, unit;
00362 int expand_newlines;
00363
00364 for(;;) {
00365
00366
00367
00368 nothing = 0;
00369 more = 0;
00370 for(unit = 0; unit < num_devices; ++unit) {
00371
00372 obuf = ctrl[unit].obuf;
00373
00374
00375
00376
00377
00378 if(obuf->mode & OUTPUT_HFLOW_OFF) {
00379 obuf->mode &= ~OUTPUT_HFLOW_OFF;
00380 drop_hw(unit);
00381 }
00382
00383 if(obuf->mode & OUTPUT_HFLOW_ON) {
00384 obuf->mode &= ~OUTPUT_HFLOW_ON;
00385 raise_hw(unit);
00386 }
00387
00388 if(obuf->mode & OUTPUT_XOFF) {
00389 obuf->mode &= ~OUTPUT_XOFF;
00390
00391
00392
00393 put_data(unit, (char far *) "\023", 1, 0);
00394 }
00395
00396 if(obuf->mode & OUTPUT_XON) {
00397 obuf->mode &= ~OUTPUT_XON;
00398
00399
00400
00401 put_data(unit, (char far *) "\021", 1, 0);
00402 }
00403
00404
00405
00406
00407
00408 _disable();
00409 if(obuf->size == 0 ||
00410 (obuf->mode & (OUTPUT_STOPPED|OUTPUT_STOPPED_HW)) != 0) {
00411 _enable();
00412 ++nothing;
00413 continue;
00414 }
00415 _enable();
00416
00417 if(obuf->discard) {
00418
00419
00420
00421 n = obuf->discard;
00422 _disable();
00423 obuf->discard -= n;
00424 obuf->size -= n;
00425 _enable();
00426 i = &obuf->buffer[obuf->length] - obuf->tail;
00427 if(i > n)
00428 obuf->tail += n;
00429 else
00430 obuf->tail = &obuf->buffer[n-i];
00431 }
00432
00433
00434
00435
00436
00437 tail = obuf->tail;
00438 end = &obuf->buffer[obuf->length];
00439 begin = &obuf->buffer[0];
00440 size = obuf->size;
00441
00442 expand_newlines = obuf->mode & OUTPUT_XNL;
00443
00444
00445
00446
00447 i = end - tail;
00448 if(i >= size) {
00449 n = put_data(unit, tail, size, expand_newlines);
00450 }
00451 else {
00452 n = put_data(unit, tail, i, expand_newlines);
00453 n += put_data(unit, begin, size - i, expand_newlines);
00454 }
00455
00456
00457
00458
00459
00460
00461 _disable();
00462
00463 if(i > n)
00464 obuf->tail = tail + n;
00465 else
00466 obuf->tail = begin + (n-i);
00467 obuf->size -= n;
00468
00469
00470
00471
00472 if(obuf->discard > n)
00473 obuf->discard -= n;
00474 else
00475 obuf->discard = 0;
00476
00477 _enable();
00478
00479
00480
00481
00482
00483 _disable();
00484 if(obuf->size < obuf->bcount) {
00485 obuf->bcount = 0;
00486 obuf->action |= ACT_OUTPUT_READY;
00487 _enable();
00488 Trigger(drv_ctrl.hw_pid);
00489 }
00490 else
00491 _enable();
00492 }
00493
00494
00495
00496 _disable();
00497 if(nothing >= num_devices && more == 0) {
00498 idle = 1;
00499 _enable();
00500 return;
00501 }
00502 else
00503 _enable();
00504 }
00505 }
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 int init_driver()
00519 {
00520 #ifdef DEBUGMODE
00521 old_mode = dev_mode( 0, 0, _DEV_MODES);
00522 dev_arm( 0, in_proxy, _DEV_EVENT_RXRDY );
00523 #else
00524
00525 #endif
00526 return(0);
00527 }
00528
00529
00530
00531 int exit_driver()
00532 {
00533 #ifdef DEBUGMODE
00534 dev_mode( 0, old_mode, _DEV_MODES);
00535 #else
00536
00537 #endif
00538 return(0);
00539 }
00540
00541
00542
00543 get_data(int unit, char *buf, int nbytes)
00544 {
00545
00546
00547
00548
00549 int n = 0;
00550
00551 unit = unit;
00552
00553 #ifdef DEBUGMODE
00554 n = dev_read(0, buf, nbytes, 0, 0, 0, 0, 0);
00555 dev_arm( 0, in_proxy, _DEV_EVENT_RXRDY );
00556 #else
00557
00558 #endif
00559
00560 return(n);
00561 }
00562
00563
00564
00565 put_data(int unit, char far *buf, int nbytes, int expand_newlines)
00566 {
00567
00568
00569
00570
00571 #ifdef DEBUGMODE
00572 int i;
00573 char c;
00574
00575 unit = unit;
00576
00577 for(i = 0; i < nbytes; ++i) {
00578 c = *buf++;
00579 if(expand_newlines && c == '\n')
00580 write(1, "\r", 1);
00581 write(1, &c, 1);
00582 }
00583 #else
00584
00585 #endif
00586 return(nbytes);
00587 }
00588
00589
00590
00591 void drop_hw(int unit) {
00592
00593
00594
00595 unit = unit;
00596 #ifndef DEBUGMODE
00597
00598 #endif
00599 }
00600
00601
00602
00603 void raise_hw(int unit) {
00604
00605
00606
00607 unit = unit;
00608 #ifndef DEBUGMODE
00609
00610 #endif
00611 }
00612
00613
00614 #if 0
00615
00616
00617
00618
00619
00620 #include "../_devdrvr.h"
00621 #include <sys/trace.h>
00622 #include <sys/tracecod.h>
00623
00624
00625
00626
00627
00628 #pragma off (check_stack);
00629
00630 pid_t async_int(int irq) {
00631 extern pid_t (far *tti)(int, int, unsigned);
00632 extern unsigned tti_ds;
00633 pid_t status = 0;
00634 unsigned char *data;
00635 int nbytes = 0;
00636 int irq_type = 0;
00637 unsigned short c;
00638 unsigned iobase = 0;
00639
00640 switch(irq_type) {
00641
00642 case 0:
00643
00644
00645
00646 while(nbytes--) {
00647 c = (unsigned short) *data++;
00648 status |= (*tti) (c, dev->tty, tti_ds);
00649 }
00650 break;
00651
00652 case 1:
00653 status |= (*tti) (*data | RCV_PARITY, dev->tty, tti_ds);
00654 Trace1( (long)_TRACE_DEV_SER_PARITY, _TRACE_TRANSIENT, iobase );
00655 break;
00656
00657 case 2:
00658 status |= (*tti) (*data | RCV_FRAME, dev->tty, tti_ds);
00659 Trace1( (long)_TRACE_DEV_SER_FRAME, _TRACE_TRANSIENT, iobase );
00660 break;
00661
00662 case 3:
00663 status |= (*tti) (*data | RCV_OVERRUN, dev->tty, tti_ds);
00664 Trace1( (long)_TRACE_DEV_SER_OVERRUN, _TRACE_TRANSIENT, iobase );
00665 break;
00666
00667 case 4:
00668 status |= (*tti) (*data | RCV_BREAK, dev->tty, tti_ds);
00669 break;
00670
00671 case 5:
00672 status |= (*tti) (RCV_CARRIER, dev->tty, tti_ds);
00673 Trace1( _TRACE_DEV_SER_CARRIER, _TRACE_EXPECTED, dev->iobase );
00674 break;
00675
00676 case 6:
00677 status |= (*tti) (RCV_HNGUP, dev->tty, tti_ds);
00678 Trace1( _TRACE_DEV_SER_HUP, _TRACE_EXPECTED, dev->iobase );
00679 break;
00680
00681 case 7:
00682 status |= (*tti) (RCV_HW_ON, dev->tty, tti_ds);
00683 break;
00684
00685 case 8:
00686 status |= (*tti) (RCV_HW_OFF, dev->tty, tti_ds);
00687 break;
00688 }
00689
00690 return(status);
00691 }
00692
00693 #pragma on (check_stack);
00694
00695 #endif