The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/pc/devlpt.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #include        "u.h"
    2 #include        "../port/lib.h"
    3 #include        "mem.h"
    4 #include        "dat.h"
    5 #include        "fns.h"
    6 #include        "io.h"
    7 #include        "../port/error.h"
    8 
    9 /* Centronix parallel (printer) port */
   10 
   11 /* base addresses */
   12 static int lptbase[] = {
   13         0x378,  /* lpt1 */
   14         0x3bc,  /* lpt2 */
   15         0x278   /* lpt3 (sic) */
   16 };
   17 #define NDEV    nelem(lptbase)
   18 static int lptallocd[NDEV];
   19 
   20 /* offsets, and bits in the registers */
   21 enum
   22 {
   23         Qdir=           0x8000,
   24         /* data latch register */
   25         Qdlr=           0x0,
   26         /* printer status register */
   27         Qpsr=           0x1,
   28         Fnotbusy=       0x80,
   29         Fack=           0x40,
   30         Fpe=            0x20,
   31         Fselect=        0x10,
   32         Fnoerror=       0x08,
   33         /* printer control register */
   34         Qpcr=           0x2,
   35         Fie=            0x10,
   36         Fselectin=      0x08,
   37         Finitbar=       0x04,
   38         Faf=            0x02,
   39         Fstrobe=        0x01,
   40         /* fake `data register' */
   41         Qdata=          0x3,
   42 };
   43 
   44 static int      lptready(void*);
   45 static void     outch(int, int);
   46 static void     lptintr(Ureg*, void*);
   47 
   48 static Rendez   lptrendez;
   49 
   50 Dirtab lptdir[]={
   51         ".",    {Qdir, 0, QTDIR},       0,      DMDIR|0555,
   52         "dlr",  {Qdlr},                 1,      0666,
   53         "psr",  {Qpsr},                 5,      0444,
   54         "pcr",  {Qpcr},                 0,      0222,
   55         "data", {Qdata},                0,      0222,
   56 };
   57 
   58 static int
   59 lptgen(Chan *c, char*, Dirtab *tab, int ntab, int i, Dir *dp)
   60 {
   61         Qid qid;
   62 
   63         if(i == DEVDOTDOT){
   64                 mkqid(&qid, Qdir, 0, QTDIR);
   65                 devdir(c, qid, ".", 0, eve, 0555, dp);
   66                 return 1;
   67         }
   68         i++; /* skip first element for . itself */
   69         if(tab==0 || i>=ntab)
   70                 return -1;
   71         tab += i;
   72         qid = tab->qid;
   73         qid.path &= ~Qdir;
   74         if(qid.path < Qdata)
   75                 qid.path += lptbase[c->dev];
   76         qid.vers = c->dev;
   77         sprint(up->genbuf, "lpt%lud%s", c->dev+1, tab->name);
   78         devdir(c, qid, up->genbuf, tab->length, eve, tab->perm, dp);
   79         return 1;
   80 }
   81 
   82 static Chan*
   83 lptattach(char *spec)
   84 {
   85         Chan *c;
   86         int i  = (spec && *spec) ? strtol(spec, 0, 0) : 1;
   87         char name[5];
   88         static int set;
   89 
   90         if(!set){
   91                 outb(lptbase[i-1]+Qpcr, 0);     /* turn off interrupts */
   92                 set = 1;
   93                 intrenable(IrqLPT, lptintr, 0, BUSUNKNOWN, "lpt");
   94         }
   95         if(i < 1 || i > NDEV)
   96                 error(Ebadarg);
   97         if(lptallocd[i-1] == 0){
   98                 int ecr;
   99                 sprint(name, "lpt%d", i-1);
  100                 if(ioalloc(lptbase[i-1], 3, 0, name) < 0)
  101                         error("lpt port space in use");
  102                 lptallocd[i-1] = 1;
  103                 /* Detect ECP - if found, put into PS/2 mode to suit style of driver */
  104                 ecr = lptbase[i-1] + 0x402;
  105                 if ((inb(ecr) & 3) == 1) {
  106                         outb(ecr, 0x34);
  107                         if (inb(ecr) == 0x35) {
  108                                 outb(ecr, (inb(ecr) & 0x1f) | (1 << 5));
  109                                 if(ioalloc(ecr, 1, 0, name) < 0)
  110                                         error("lpt ecr port space in use");
  111                         }
  112                 }
  113         }
  114         c = devattach('L', spec);
  115         c->qid.path = Qdir;
  116         c->dev = i-1;
  117         return c;
  118 }
  119 
  120 static Walkqid*
  121 lptwalk(Chan *c, Chan *nc, char **name, int nname)
  122 {
  123         return devwalk(c, nc, name, nname, lptdir, nelem(lptdir), lptgen);
  124 }
  125 
  126 static int
  127 lptstat(Chan *c, uchar *dp, int n)
  128 {
  129         return devstat(c, dp, n, lptdir, nelem(lptdir), lptgen);
  130 }
  131 
  132 static Chan*
  133 lptopen(Chan *c, int omode)
  134 {
  135         return devopen(c, omode, lptdir, nelem(lptdir), lptgen);
  136 }
  137 
  138 static void
  139 lptclose(Chan *)
  140 {
  141 }
  142 
  143 static long
  144 lptread(Chan *c, void *a, long n, vlong)
  145 {
  146         char str[16];
  147         int size;
  148         ulong o;
  149 
  150         if(c->qid.path == Qdir)
  151                 return devdirread(c, a, n, lptdir, nelem(lptdir), lptgen);
  152         size = sprint(str, "0x%2.2ux\n", inb(c->qid.path));
  153         o = c->offset;
  154         if(o >= size)
  155                 return 0;
  156         if(o+n > size)
  157                 n = size-c->offset;
  158         memmove(a, str+o, n);
  159         return n;
  160 }
  161 
  162 static long
  163 lptwrite(Chan *c, void *a, long n, vlong)
  164 {
  165         char str[16], *p;
  166         long base, k;
  167 
  168         if(n <= 0)
  169                 return 0;
  170         if(c->qid.path != Qdata){
  171                 if(n > sizeof str-1)
  172                         n = sizeof str-1;
  173                 memmove(str, a, n);
  174                 str[n] = 0;
  175                 outb(c->qid.path, strtoul(str, 0, 0));
  176                 return n;
  177         }
  178         p = a;
  179         k = n;
  180         base = lptbase[c->dev];
  181         if(waserror()){
  182                 outb(base+Qpcr, Finitbar);
  183                 nexterror();
  184         }
  185         while(--k >= 0)
  186                 outch(base, *p++);
  187         poperror();
  188         return n;
  189 }
  190 
  191 static void
  192 outch(int base, int c)
  193 {
  194         int status, tries;
  195 
  196         for(tries=0;; tries++) {
  197                 status = inb(base+Qpsr);
  198                 if(status&Fnotbusy)
  199                         break;
  200                 if((status&Fpe)==0 && (status&(Fselect|Fnoerror)) != (Fselect|Fnoerror))
  201                         error(Eio);
  202                 outb(base+Qpcr, Finitbar|Fie);
  203                 tsleep(&lptrendez, lptready, (void *)base, 100);
  204         }
  205         outb(base+Qdlr, c);
  206         outb(base+Qpcr, Finitbar|Fstrobe);
  207         outb(base+Qpcr, Finitbar);
  208 }
  209 
  210 static int
  211 lptready(void *base)
  212 {
  213         return inb((int)base+Qpsr)&Fnotbusy;
  214 }
  215 
  216 static void
  217 lptintr(Ureg *, void *)
  218 {
  219         wakeup(&lptrendez);
  220 }
  221 
  222 Dev lptdevtab = {
  223         'L',
  224         "lpt",
  225 
  226         devreset,
  227         devinit,
  228         devshutdown,
  229         lptattach,
  230         lptwalk,
  231         lptstat,
  232         lptopen,
  233         devcreate,
  234         lptclose,
  235         lptread,
  236         devbread,
  237         lptwrite,
  238         devbwrite,
  239         devremove,
  240         devwstat,
  241 };

Cache object: 6b902f81811e24d8b06ba548c74b61d2


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.