00001
00002 #include <sys/types.h>
00003 #include <sys/_devdrvr.h>
00004 #include <sys/sched.h>
00005 #include <sys/utsname.h>
00006 #include <sys/osinfo.h>
00007 #include <sys/psinfo.h>
00008 #include <sys/kernel.h>
00009 #include <sys/proxy.h>
00010 #include <i86.h>
00011 #include <conio.h>
00012 #include <errno.h>
00013 #include <string.h>
00014 #include <stdlib.h>
00015 #include <unistd.h>
00016 #include <signal.h>
00017
00018 #include "par.h"
00019
00020
00021
00022
00023 int far Kick (struct output_buffer far *obuf);
00024 int far Stty (struct termios far *tios);
00025 int far Ctrl (union ioctl_entry far *ioc);
00026
00027 #pragma aux (_dev_call) Kick;
00028 #pragma aux (_dev_call) Stty;
00029 #pragma aux (_dev_call) Ctrl;
00030
00031 union _printer_msg {
00032 msg_t type;
00033 msg_t status;
00034 char filer[100];
00035 } msg;
00036
00037 int idle = 1;
00038 volatile int dangerous = 0;
00039
00040 unsigned port = 0;
00041 int biosport = 1;
00042 int osize = 1000;
00043
00044
00045 #define NAP_TIME 10
00046 #define NAPS_PER_SEC (1000/NAP_TIME)
00047 #define nap() (delay(NAP_TIME))
00048
00049 unsigned ioport = 0;
00050 unsigned cpu_speed;
00051 long usec_wait = 1000;
00052 long io_retry;
00053
00054 int check_open = 0;
00055
00056 int rtimeout = -1;
00057 struct driver_ctrl drv_ctrl;
00058 struct device_ctrl ctrl;
00059
00060 char *prefix = "par";
00061
00062 #define peekch(obuf) (*(obuf)->tail)
00063 #define abort_output(obuf) ((obuf)->discard = (obuf)->size)
00064
00065 int dev_handle;
00066
00067 void terminate( int signal )
00068 {
00069 if(signal) {
00070
00071
00072
00073 dev_drvr_shutdown( dev_handle );
00074
00075
00076
00077
00078 }
00079 exit(0);
00080 }
00081
00082 main(argc, argv)
00083 int argc; char *argv[];
00084 {
00085 unsigned c;
00086 struct _osinfo osinfo;
00087 int i;
00088 int priority = 9;
00089 struct termios far *tios;
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,"cO:N:p:b:w:s:P:")) != -1) {
00105 switch (c) {
00106 case 'c':
00107 check_open = 1;
00108 break;
00109 case 'O':
00110 osize = strtol(optarg,NULL,0);
00111 break;
00112 case 'N':
00113 prefix = optarg;
00114 break;
00115 case 'p':
00116 ioport = strtol(optarg,NULL,16);
00117 break;
00118 case 'b':
00119 biosport = strtol(optarg,NULL,16);
00120 break;
00121 case 's':
00122 if ((rtimeout = strtol(optarg,NULL,10) * NAPS_PER_SEC) == 0) {
00123 rtimeout = 1;
00124 }
00125 break;
00126 case 'w':
00127 usec_wait = strtol(optarg,NULL,0);
00128 break;
00129 case 'P':
00130 priority = strtol(optarg,NULL,0);
00131 break;
00132 }
00133 }
00134
00135 setscheduler(0, SCHED_FAIR, priority);
00136
00137 if(ioport == 0) {
00138 ioport = next_printer(biosport);
00139 if(ioport == 0)
00140 exit(0);
00141 }
00142
00143 qnx_osinfo((nid_t) 0, &osinfo);
00144 cpu_speed = osinfo.cpu_speed;
00145 io_retry = (cpu_speed / 100) * usec_wait;
00146
00147
00148
00149
00150 if((dev_handle = dev_drvr_register("parallel", prefix, 1,
00151 &Kick, &Stty, &Ctrl, &drv_ctrl, 0)) == -1) {
00152 exit(ENFILE);
00153 }
00154
00155
00156
00157
00158
00159 ctrl.isize = 0;
00160 ctrl.osize = osize;
00161 ctrl.csize = 0;
00162
00163 if(dev_drvr_mount(dev_handle, drv_ctrl.base_tty, 1, &ctrl)) {
00164 dev_drvr_shutdown( dev_handle );
00165 exit(ENOMEM);
00166 }
00167
00168
00169
00170
00171 ctrl.obuf->mode |= OUTPUT_XNL;
00172
00173 tios = ctrl.termios;
00174 tios->c_cflag = (CS8);
00175 tios->c_oflag = (OPOST);
00176 tios->c_iflag = 0;
00177 tios->c_lflag = 0;
00178 tios->c_ispeed = 0L;
00179 tios->c_ospeed = 9600L;
00180
00181
00182
00183
00184
00185 init_printer(ioport);
00186
00187 idle = 0;
00188
00189 port = qnx_proxy_attach(0, 0, 0, -1);
00190
00191
00192
00193
00194 if(dev_drvr_arm(ctrl.tty)) {
00195 dev_drvr_shutdown( dev_handle );
00196 exit(ENODEV);
00197 }
00198
00199
00200
00201
00202
00203
00204
00205 close(0);
00206 close(1);
00207 close(2);
00208
00209 qnx_pflags( _PPF_SERVER, _PPF_SERVER, 0, 0 );
00210
00211
00212 for(;;) {
00213
00214 #define GAURD(X) ((dangerous=1),(X),(dangerous=0))
00215
00216 GAURD(idle = (ctrl.obuf->size == 0));
00217 if (idle) {
00218
00219
00220
00221
00222 wait_msg(port);
00223 continue;
00224 }
00225 if (flush_buffer(ctrl.obuf)) {
00226 continue;
00227 }
00228
00229
00230
00231
00232 if ((c=peekch(ctrl.obuf)) == '\n' && (ctrl.obuf->mode & OUTPUT_XNL)) {
00233 if (outch('\r',ctrl.obuf) == -1) {
00234 abort_output(ctrl.obuf);
00235 continue;
00236 }
00237 }
00238 if (outch(c,ctrl.obuf) == -1) {
00239 abort_output(ctrl.obuf);
00240 continue;
00241 }
00242
00243
00244
00245
00246
00247 advance(ctrl.obuf);
00248 }
00249 }
00250
00251 short prtready(port,strict)
00252 {
00253 short c;
00254
00255 c = inp(port+REG_STAT);
00256 return strict ?
00257 (c&STATUS_MASK) == STATUS_OK :
00258 (c&NOTBUSY) == NOTBUSY;
00259 }
00260
00261
00262 outch(int ch, const struct output_buffer far *obuf)
00263 {
00264 int tick;
00265 long x;
00266
00267
00268
00269
00270 for (tick=rtimeout,x=io_retry; !prtready(ioport,0);) {
00271 if (obuf->discard)
00272 return -1;
00273 if (x--)
00274 continue;
00275 x = io_retry;
00276 nap();
00277 if (tick != -1) {
00278 if (--tick == 0) {
00279 return -1;
00280 }
00281 }
00282 }
00283
00284
00285
00286 outp(ioport, ch);
00287
00288
00289
00290
00291 udelay(2);
00292
00293 outp(ioport + REG_CNTL, 0x0D );
00294 udelay(1);
00295 outp(ioport + REG_CNTL, 0x0C );
00296 udelay(2);
00297 return 0;
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 int far Kick (struct output_buffer far *obuf) {
00312 if(obuf->size > 0) {
00313 if(idle || dangerous) {
00314 idle = 0;
00315 Trigger(port);
00316 }
00317 return(1);
00318 }
00319 return(0);
00320 }
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 int far Stty (struct termios far *tios)
00335 {
00336 unsigned cflags;
00337
00338
00339
00340
00341 cflags = tios->c_cflag;
00342
00343 return(0);
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 int far Ctrl (union ioctl_entry far *ioc)
00358 {
00359 int type;
00360
00361 type = ioc->type;
00362 ioc->status = IOCTL_ERROR;
00363 switch (type) {
00364 case IOCTL_OPEN:
00365 ioc->status = (check_open && !prtready(ioport,1)) ? IOCTL_NONE_FREE
00366 : IOCTL_OK;
00367 return(0);
00368 case IOCTL_CLOSE:
00369 ioc->status = IOCTL_OK;
00370 return(0);
00371 case IOCTL_CTL:
00372 {
00373 unsigned unit = ioc->user.unit;
00374 unsigned char bits, mask, oldbits;
00375
00376 if(unit > 1 || unit <= 0) {
00377 ioc->status = IOCTL_BAD_UNIT;
00378 return(0);
00379 }
00380
00381 mask = ioc->user.data[4];
00382 bits = ioc->user.data[0];
00383 _disable();
00384 oldbits = inp( ioport + REG_STAT );
00385 outp( ioport + REG_STAT, (oldbits & ~mask) | (bits & mask));
00386 _enable();
00387 ioc->user_return.data[0] = oldbits;
00388
00389 mask = ioc->user.data[5];
00390 bits = ioc->user.data[1];
00391 _disable();
00392 oldbits = inp( ioport + REG_CNTL );
00393 outp( ioport + REG_CNTL, (oldbits & ~mask) | (bits & mask));
00394 _enable();
00395 ioc->user_return.data[1] = oldbits;
00396
00397 ioc->user_return.data[2] = 0;
00398 ioc->user_return.data[3] = 0;
00399 ioc->user_return.nbytes = 4;
00400 ioc->user_return.status = IOCTL_OK;
00401 return(0);
00402 }
00403 }
00404 return(-1);
00405 }
00406
00407 next_printer(unsigned n) {
00408 unsigned far *port;
00409
00410 port = MK_FP(0x0040, (2*(n-1))+0x0008);
00411 n = *port;
00412 return(n);
00413 }
00414
00415
00416 init_printer(port)
00417 unsigned port;
00418 {
00419 outp(port + REG_CNTL, 0x0C );
00420 return(0);
00421 }
00422
00423
00424
00425
00426
00427
00428 udelay(usec)
00429 unsigned usec;
00430 {
00431 unsigned i, u;
00432
00433 for(i = 0; i < usec; ++i) {
00434 for(u = 0; u < cpu_speed; u+= 100)
00435 ;
00436 }
00437 return(0);
00438 }
00439
00440 wait_msg(pid_t port)
00441 {
00442 pid_t pid;
00443 int nbytes;
00444 extern int sys_msg(void *);
00445
00446 while(1) {
00447
00448
00449
00450 if ((pid = Receive(0, &msg, sizeof(msg))) == port)
00451 break;
00452
00453
00454
00455 nbytes = 1;
00456 if(msg.type == 0)
00457 nbytes = sys_msg(&msg);
00458 else
00459 msg.status = ENOSYS;
00460 if(nbytes)
00461 Reply(pid, &msg, nbytes);
00462 }
00463 }
00464
00465 flush_buffer(struct output_buffer far *obuf)
00466 {
00467 int i;
00468 int n;
00469
00470 _disable();
00471 if((n=obuf->discard) == 0) {
00472 _enable();
00473 return 0;
00474 }
00475
00476
00477
00478 obuf->discard = 0;
00479 obuf->size -= n;
00480 _enable();
00481
00482 i = &obuf->buffer[obuf->length] - obuf->tail;
00483 if(i > n)
00484 obuf->tail += n;
00485 else
00486 obuf->tail = &obuf->buffer[n-i];
00487
00488 low_water(obuf);
00489 return 1;
00490 }
00491
00492 advance(struct output_buffer far *obuf)
00493 {
00494
00495
00496
00497 ++obuf->tail;
00498 if(obuf->tail >= &obuf->buffer[obuf->length])
00499 obuf->tail = &obuf->buffer[0];
00500
00501
00502
00503
00504 _disable();
00505 --obuf->size;
00506
00507
00508
00509
00510
00511 low_water(obuf);
00512 return obuf->size != 0;
00513 }
00514
00515 low_water(struct output_buffer far *obuf)
00516 {
00517
00518
00519
00520
00521 _disable();
00522 if(obuf->size < obuf->bcount) {
00523 obuf->bcount = 0;
00524 obuf->action |= ACT_OUTPUT_READY;
00525 _enable();
00526 Trigger(drv_ctrl.hw_pid);
00527 }
00528 else
00529 _enable();
00530 return 1;
00531 }