Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

parport.c

Go to the documentation of this file.
00001 /*
00002   parport.c
00003 
00004   External interface to parallel port I/O
00005 
00006   Processes need to be root, or run setuid-root, in order to run this,
00007   even with the call to ioperm().
00008 
00009   Modification history:
00010 
00011 
00012   28-Jun-2000 WPS changed %i to %l in sscanf to avoid warning.
00013   27-Jun-2000 WPS changed asm/io.h to sys/io.h to avoid a bunch of warnings under linux_2_2_14.
00014   20-Mar-2000 WPS added unused attribute to parport_h to avoid 'defined but not used' compiler warning
00015   29-Sep-1999  FMP moved #include "rcs_prnt.h" into don't DO_IT section
00016   21-Sep-1999  WPS eliminate sscanf and printf calls not supported under CE.
00017   7-Aug-1998  FMP changed extInit/Quit() to extDioInit/Quit()
00018   5-Aug-1998  FMP added #ifndef RTLINUX around ioperm() call in pptInit(),
00019   since it's not needed for RT-Linux
00020   10-Jul-1998  FMP added -addr flag to set io address
00021   8-Jul-1998  FMP changed PPT_ to PARPORT_ for consistency with INI file
00022   6-Nov-1997  FMP added pptDioCheck(); removed inversion correction
00023   29-Oct-1997 FMP fixed bugs, inverted the reverse polarity ones
00024   24-Oct-1997 FMP created
00025   */
00026 
00027 /* ident tag */
00028 #ifndef __GNUC__
00029 #ifndef __attribute__
00030 #define __attribute__(x)
00031 #endif
00032 #endif
00033 
00034 static char __attribute__((unused)) ident[] = "$Id: parport.c,v 1.14 2001/10/10 17:35:46 wshackle Exp $";
00035 
00036 /* set DO_IT FLAG for really writing, else don't do inb(), outb() */
00037 #ifdef LINUX
00038 #define DO_IT
00039 #else
00040 #if defined(rtlinux) || defined(rtai)
00041 #define DO_IT
00042 #endif
00043 #endif
00044 
00045 #ifdef MAIN
00046 
00047 #ifndef UNDER_CE
00048 #include <stdio.h>
00049 #endif
00050 
00051 #include <stdlib.h>
00052 #include <string.h>
00053 
00054 #endif
00055 
00056 #include "parport.h"            /* these decls */
00057 
00058 /* the IO address of the board; override by setting global before call
00059    to pptDioInit() */
00060 unsigned long int PARPORT_IO_ADDRESS = DEFAULT_PARPORT_IO_ADDRESS;
00061 
00062 #define PARPORT_IO_WIDTH 3              /* number of bytes taken up */
00063 
00064 #ifdef DO_IT
00065 
00066 /* real parallel port IO */
00067 
00068 #if !defined(rtlinux) && !defined(rtai)
00069 #include <unistd.h>             /* ioperm() */
00070 #ifdef DEFINE_EXTERN_BEFORE_IO
00071 #define extern
00072 #endif
00073 #endif
00074 
00075 #ifdef __KERNEL__
00076 #include <linux/kernel.h>
00077 #include <linux/fs.h>
00078 #endif
00079 
00080 #ifndef LINUX_VERSION_CODE
00081 #include <linux/version.h>
00082 #endif
00083 
00084 // Pre 2.2 kernels don't seem to have the KERNEL_VERSION macro.
00085 #ifndef KERNEL_VERSION
00086 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
00087 #endif
00088 
00089 #include <sys/io.h>             /* outb, inb */
00090 
00091 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0)
00092 #else
00093 #include <asm/io.h>
00094 #endif
00095 
00096 #else
00097 
00098 /* don't do it */
00099 #ifndef UNDER_CE
00100 #include <stdio.h>
00101 #endif
00102 
00103 static unsigned char parport[PARPORT_IO_WIDTH] = {0xFF, 0xFF, 0xFF};
00104 
00105 static int ioperm(unsigned int addr, int width, int on)
00106 {
00107   return 0;
00108 }
00109 
00110 static unsigned char inb(unsigned int port)
00111 {
00112   int index;
00113 
00114   index = port - PARPORT_IO_ADDRESS;
00115   if (index < 0 ||
00116       index >= PARPORT_IO_WIDTH)
00117     {
00118       printf("inb: address out of bounds: %X\n", port);
00119       return 0;
00120     }
00121 
00122   return parport[index];
00123 }
00124 
00125 static void outb(unsigned char byte, unsigned int port)
00126 {
00127   int index;
00128 
00129   index = port - PARPORT_IO_ADDRESS;
00130   if (index < 0 ||
00131       index >= PARPORT_IO_WIDTH)
00132     {
00133       printf("outb: address out of bounds: %X\n", port);
00134       return;
00135     }
00136 
00137   printf("outb: writing %X to %X\n", (int) byte, port);
00138   parport[index] = byte;
00139 }
00140 
00141 #endif
00142 
00143 /* set up bits for R/W. In this case, they're not programmable by
00144    register so nothing need be done. */
00145 int pptDioInit(const char * stuff)
00146 {
00147   int retval = 0;
00148 
00149 #ifdef linux
00150 #if !defined(rtlinux) && !defined(rtai)
00151   /* turn on port access */
00152   retval = ioperm(PARPORT_IO_ADDRESS, PARPORT_IO_WIDTH, 1);
00153   if(retval) retval=iopl(3);
00154 #endif
00155 #endif
00156 
00157   return retval;
00158 }
00159 
00160 int pptDioQuit()
00161 {
00162   int retval = 0;
00163 
00164 #if !defined(rtlinux) && !defined(rtai)
00165   /* turn off port access */
00166   retval = ioperm(PARPORT_IO_ADDRESS, PARPORT_IO_WIDTH, 0);
00167 #endif
00168 
00169   return retval;
00170 }
00171 
00172 /*
00173   Digital I/O
00174 
00175   Bitmap:
00176   Data Out        W   Base+0      D0-D7   8 LS TTL outputs
00177   Status In       R   Base+1      S3-S7   5 LS TTL inputs
00178   Control Out     W   Base+2      C0-C3   4 TTL Open Collector outputs
00179 
00180  */
00181 
00182 int pptDioMaxInputs()
00183 {
00184   return 5;
00185 }
00186 
00187 int pptDioMaxOutputs()
00188 {
00189   return 12;
00190 }
00191 
00192 /*
00193   pptDioRead() maps 5 index values 0-4 onto S3-S7, respectively,
00194   providing 5 digital inputs
00195 
00196   Note that S7=4 is reverse polarity.
00197   */
00198 
00199 int pptDioRead(int index, int *value)
00200 {
00201   unsigned char inByte;
00202   unsigned char mask = 8;       /* start at 00001000 for S3 */
00203 
00204   if (index < 0 ||
00205       index > 4)
00206     {
00207       *value = 0;
00208       return -1;
00209     }
00210 
00211   /* latch input */
00212   inByte = inb(PARPORT_IO_ADDRESS + 1);
00213   mask <<= index;
00214   *value = (inByte & mask) ? 1 : 0;
00215 
00216   return 0;
00217 }
00218 
00219 /*
00220   pptDioCheck() maps 8 index values 0-7 onto D0-D7, respectively, and
00221   4 index values 8-11 onto C0-C3, respectively, providing read checks
00222   on the 12 digital outputs.
00223 
00224   Note that C0, C1, and C3 are inverted outputs; 'value' will return
00225   what was written to these, so checking a 1 means a 1 was last written
00226   and the output is 0V.
00227   */
00228 
00229 int pptDioCheck(int index, int *value)
00230 {
00231   unsigned char inByte;
00232   unsigned char mask = 1;       /* start at 00000001 for D0, C0 */
00233 
00234   if (index < 0 ||
00235       index > 11)
00236     {
00237       return -1;
00238     }
00239 
00240   if (index < 8)
00241     {
00242       inByte = inb(PARPORT_IO_ADDRESS);
00243       mask <<= index;
00244       *value = (inByte & mask) ? 1 : 0;
00245       return 0;
00246     }
00247 
00248   /* else index is 8-11 */
00249   inByte = inb(PARPORT_IO_ADDRESS + 2);
00250   mask <<= index - 8;
00251   *value = (inByte & mask) ? 1 : 0;
00252   return 0;
00253 }
00254 
00255 /*
00256   pptDioWrite() maps 8 index values 0-7 onto D0-D7, respectively, and
00257   4 index values 8-11 onto C0-C3, respectively, providing 12 digital outputs.
00258 
00259   Note that C0, C1, and C3 are inverted outputs.
00260   */
00261 int pptDioWrite(int index, int value)
00262 {
00263   unsigned char outByte;
00264   unsigned char mask = 1;       /* start at 00000001 for D0, C0 */
00265 
00266   if (index < 0 ||
00267       index > 11)
00268     {
00269       return -1;
00270     }
00271 
00272   if (index < 8)
00273     {
00274       /* read current outputs */
00275       outByte = inb(PARPORT_IO_ADDRESS);
00276       mask <<= index;
00277       if (value)
00278         {
00279           outByte |= mask;
00280         }
00281       else
00282         {
00283           outByte &= ~mask;
00284         }
00285       outb(outByte, PARPORT_IO_ADDRESS);
00286       return 0;
00287     }
00288 
00289   /* read current outputs */
00290   outByte = inb(PARPORT_IO_ADDRESS + 2);
00291   mask <<= index - 8;
00292   if (value)
00293     {
00294       outByte |= mask;
00295     }
00296   else
00297     {
00298       outByte &= ~mask;
00299     }
00300   outb(outByte, PARPORT_IO_ADDRESS + 2);
00301   return 0;
00302 }
00303 
00304 int pptDioByteRead(int index, unsigned char *byte)
00305 {
00306   if (index != 0)
00307     {
00308       *byte = 0;
00309       return -1;
00310     }
00311 
00312   *byte = inb(PARPORT_IO_ADDRESS + 1);
00313   *byte >>= 3;                  /* shift down since S3 is bit 0, etc. */
00314   return 0;
00315 }
00316 
00317 int pptDioShortRead(int index, unsigned short *sh)
00318 {
00319   if (index != 0)
00320     {
00321       *sh = 0;
00322       return -1;
00323     }
00324 
00325   *sh = (unsigned short) inb(PARPORT_IO_ADDRESS + 1);
00326   *sh >>= 3;                    /* shift down since S3 is bit 0, etc. */
00327   return 0;
00328 }
00329 
00330 int pptDioWordRead(int index, unsigned int *word)
00331 {
00332   if (index != 0)
00333     {
00334       *word = 0;
00335       return -1;
00336     }
00337 
00338   *word = (unsigned int) inb(PARPORT_IO_ADDRESS + 1);
00339   *word >>= 3;                  /* shift down since S3 is bit 0, etc. */
00340   return 0;
00341 }
00342 
00343 int pptDioByteWrite(int index, unsigned char byte)
00344 {
00345   if (index == 0)
00346     {
00347       outb(byte, PARPORT_IO_ADDRESS);
00348       return 0;
00349     }
00350 
00351   if (index == 1)
00352     {
00353       outb(byte, PARPORT_IO_ADDRESS + 2);
00354       return 0;
00355     }
00356 
00357   return -1;
00358 }
00359 
00360 int pptDioShortWrite(int index, unsigned short sh)
00361 {
00362   return pptDioByteWrite(index, (unsigned char) sh);
00363 }
00364 
00365 int pptDioWordWrite(int index, unsigned int word)
00366 {
00367   return pptDioByteWrite(index, (unsigned char) word);
00368 }
00369 
00370 int pptDioByteCheck(int index, unsigned char *byte)
00371 {
00372   if (index == 0)
00373     {
00374       *byte = inb(PARPORT_IO_ADDRESS);
00375       return 0;
00376     }
00377 
00378   if (index == 1)
00379     {
00380       *byte = inb(PARPORT_IO_ADDRESS + 2);
00381       return 0;
00382     }
00383 
00384   *byte = 0;
00385   return -1;
00386 }
00387 
00388 int pptDioShortCheck(int index, unsigned short *sh)
00389 {
00390   unsigned char b0, b1;
00391 
00392   if (index != 0)
00393     {
00394       *sh = 0;
00395       return -1;
00396     }
00397 
00398   b0 = inb(PARPORT_IO_ADDRESS);
00399   b1 = inb(PARPORT_IO_ADDRESS + 2);
00400 
00401   *sh = b1;
00402   *sh <<= 8;
00403   *sh += b0;
00404 
00405   return 0;
00406 }
00407 
00408 int pptDioWordCheck(int index, unsigned int *word)
00409 {
00410   unsigned char b0, b1;
00411 
00412   if (index != 0)
00413     {
00414       *word = 0;
00415       return -1;
00416     }
00417 
00418   b0 = inb(PARPORT_IO_ADDRESS);
00419   b1 = inb(PARPORT_IO_ADDRESS + 2);
00420 
00421   *word = b1;
00422   *word <<= 8;
00423   *word += b0;
00424 
00425   return 0;
00426 }
00427 
00428 #ifdef MAIN
00429 
00430 static void fillIn(int *ins)
00431 {
00432   int t;
00433 
00434   for (t = 0; t < 5; t++)
00435     {
00436       pptDioRead(t, &ins[t]);
00437     }
00438 }
00439 
00440 static void printIn(int *ins)
00441 {
00442   int t;
00443 
00444   for (t = 0; t < 5; t++)
00445     {
00446       printf("%d ", ins[t]);
00447     }
00448   printf("\n");
00449 }
00450 
00451 static void fillOut(int *outs)
00452 {
00453   int t;
00454 
00455   for (t = 0; t < 12; t++)
00456     {
00457       pptDioCheck(t, &outs[t]);
00458     }
00459 }
00460 
00461 static void printOut(int *outs)
00462 {
00463   int t;
00464 
00465   for (t = 0; t < 12; t++)
00466     {
00467       printf("%d ", outs[t]);
00468     }
00469   printf("\n");
00470 }
00471 
00472 int main(int argc, char *argv[])
00473 {
00474   int t;
00475 #define INPUTLEN 256
00476   char input[INPUTLEN];
00477   char cmd[INPUTLEN];
00478   int ins[5];
00479   int outs[12];
00480   int index;
00481 
00482   /* check -addr 0x378 */
00483   for (t = 1; t < argc; t++)
00484     {
00485       if (!strcmp(argv[t], "-addr"))
00486         {
00487           if (t == argc - 1)
00488             {
00489               fprintf(stderr, "no address specified\n");
00490               exit(1);
00491             }
00492           else if (1 != sscanf(argv[t+1], "%li", &PARPORT_IO_ADDRESS))
00493             {
00494               fprintf(stderr, "bad address specified: %s\n", argv[t+1]);
00495               exit(1);
00496             }
00497           else
00498             {
00499               t++;              /* step over address */
00500               continue;
00501             }
00502         }
00503       else
00504         {
00505           fprintf(stderr, "syntax: %s -addr <io address>\n", argv[0]);
00506           exit(1);
00507         }
00508     }
00509 
00510   if (-1 == pptDioInit(0))
00511     {
00512       fprintf(stderr, "can't init\n");
00513       exit(1);
00514     }
00515 
00516   while (! feof(stdin))
00517     {
00518       printf("ppt> ");
00519       fflush(stdout);
00520 
00521       if (NULL == fgets(input, INPUTLEN, stdin))
00522         {
00523           /* EOF */
00524           break;
00525         }
00526 
00527       if (1 != sscanf(input, "%s", cmd))
00528         {
00529           /* blank line-- print input */
00530           fillIn(ins);
00531           printIn(ins);
00532           continue;
00533         }
00534 
00535       if (! strcmp(cmd, "help") ||
00536           ! strcmp(cmd, "?"))
00537         {
00538           printf("help/?           print this help\n");
00539           printf("s <#>            set bit #\n");
00540           printf("c <#>            clear bit #\n");
00541           printf("k                check outputs\n");
00542           printf("ENTER            print inputs\n");
00543           printf("q                quit\n");
00544         }
00545       else if (! strcmp(cmd, "s"))
00546         {
00547           /* set */
00548           if (1 != sscanf(input, "%*s %d", &index))
00549             {
00550               printf("bad input: %s\n", input);
00551               continue;
00552             }
00553 
00554           if (0 != pptDioWrite(index, 1))
00555             {
00556               printf("index out of range\n");
00557             }
00558         }
00559       else if (! strcmp(cmd, "c"))
00560         {
00561           /* set */
00562           if (1 != sscanf(input, "%*s %d", &index))
00563             {
00564               printf("bad input: %s\n", input);
00565               continue;
00566             }
00567 
00568           if (0 != pptDioWrite(index, 0))
00569             {
00570               printf("index out of range\n");
00571             }
00572         }
00573       else if (! strcmp(cmd, "k"))
00574         {
00575           /* check outputs */
00576           fillOut(outs);
00577           printOut(outs);
00578         }
00579       else if (! strcmp(cmd, "q"))
00580         {
00581           break;
00582         }
00583       else
00584         {
00585           printf("?\n");
00586         }
00587     }
00588 
00589   pptDioQuit();
00590 
00591   exit(0);
00592 }
00593 
00594 #endif

Generated on Sun Dec 2 15:27:41 2001 for EMC by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001