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