APLawrence - Information and Resources for Unix and Linux Systems, Bloggers and the self-employed
RSS Feeds Get APLawrence.com by RSS











(OLDER) <- More Stuff -> (NEWER) (NEWEST)
Home > Unix Scripts > Unix Programs: Driver.c LP Driver
Printer Friendly Version




We no longer offer ftp downloads. If there is a file you need referenced here, please contact me by email and I will get it to you.

Driver.c: Parallel port driver for SCO Unix 3.2v4.x



See Also:

January 1993



/* Debugging Driver for parallel printer port.
Copyright Anthony Lawrence 10/7/93
Lawrence & Clark, Inc
(617) 762-0707  (206) 323-2864

NOT a drop-in replacement for SCO's lp driver!
Includes ioctl calls to examine & set driver variables.
You can speed it up, slow it down, and generally tune
it to the conditions at hand.  The debugging mode gives
you the clues when something is wrong, and "lp2status"
lets you play.

Does not include the stty's that SCO supports!
Developed and tested on a Dell 486 running 3.2v4.0
To compile and link:

cc -c -Zp4 -K -M3 -DINKERNEL Driver.c
cp Driver.o /etc/conf/pack.d/lp2
cd /etc/conf/cf.d
./link_unix

Yoy will need an entry in /etc/conf/cf.d/mdevice:

lp2     ocIwi   icH             lp2     0       84      1       3       -1

(you can modify the "lp" entry for this purpose)

and in /etc/conf/sdevice.d/lp2:

lp2     Y       1       2       4       7       378     37f     0       0

And of course if your printer is *not* at 378 or at interrupt 7,
you need to change a few things.

The corresponding sdevice entry for "lp" should be marked "N"

Minor node 0 is non-DeBugging.
Minor node 129 is for ioctl; see "lp2status.c".
Minor nodes 1-3 are for DeBugging; 1 is the lowest level, 3 is the highest

(note that when a driver uses printf, as this does in DeBug mode, all output 
is also written to /usr/adm/messages.)


Great fun to play with, and I have been using it for a long time now
as my normal parallel driver, but your mileage may vary, so caveat emptor
and cover your butt and all the other warnings.  This is, after all,
a driver, and in (more than) theory, has the potential to muck your
system up pretty well.  Read and understand *all* the code before
implementing.


Tony

*/
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/tty.h>
#include <sys/sysmacros.h>
#include <sys/file.h>
#include "lp2status.h"


#define LPPRI PZERO+5

#define LPBASE 0x378
#define LPDATA (LPBASE + 0)
#define LPSTAT (LPBASE + 1)
#define LPCTRL (LPBASE + 2)

#define LPNERR 0x08
#define LPON   0x10
#define LPRDY  0x80

#define LPSTRB 0x01
#define LPLF   0x02
#define LPINIT 0x04
#define LPSEL  0x08
#define LPIENB 0x10

#define TRUE 1


static unsigned short Lpflags=0;
static struct clist Lpqueue;
unsigned short DeBug=0;
unsigned short Ccount=0;
unsigned short Icount=0;
unsigned short spindowns=0;
unsigned short wsleeps=0;
unsigned short spinloop=100;

int Low_water=50;
int Highwater=250;
int Wait_int=HZ/10;

void printflags(char *message);

lp2init()
{
int x=0;
outb(LPCTRL,0);
if ((x=inb(LPCTRL)) != 0xe2)
        {
        printf("Line printer not found!!( %x )!!\n",x);
        return;
        }
outb(LPCTRL,0xfe);
if ((x=inb(LPCTRL)) != 0xfe)
        {
        printf("Line printer not found!!(2: %x )!!\n",x);
        return;
        }
/* These tests work on my particular machine, but you may need
 to modify for your port.  Actually, since the primary purpose
 is debugging, you might even take them out and just assume the
 port is there... */

outb(LPCTRL,0);
printf("Found Line printer at %x\n",LPBASE);
Lpflags=LPEXIST;
}

lp2open(dev,flags,otype)
dev_t dev;
int flags,otype;
{
DeBug=(minor(dev));
Icount=0;
Ccount=0;
spindowns=0;
wsleeps=0;

/* minor #129 is for ioctl, so we don't concern ourselves
   with any error conditions */

if ((Lpflags & LPEXIST) == 0 && DeBug != 129)
        u.u_error = ENODEV;
else if (Lpflags & EXCLOPEN && DeBug != 129)
        u.u_error=EBUSY;
else if (Lpflags & OPEN && DeBug != 129)
{
if (flags & FEXCL)
        u.u_error=EBUSY;
}
else
{
/* again, if doing ioctl, we don't want to mess with anything */
if (DeBug != 129)
        {
        outb(LPDATA,0);
        outb(LPCTRL,LPLF | LPINIT | LPSEL);
        Lpflags |= OPEN;
        if (flags & FEXCL)
         Lpflags |= EXCLOPEN;
        }

}
/* reset if ioctl as nothing else will be called anyway.  If you
   want to, you can reset debug anyway with the ioctl call */
   
if (DeBug == 129)
   DeBug=0;
if (DeBug)
 printflags("Open:");
}

lp2close(dev,flags,otype)
dev_t dev;
int flags,otype;
{
int x;
x=spl5();
while (Lpflags & LPBUSY)
{
Lpflags |= WAIT;
if (DeBug > 1)
 printflags("Sleeping in lp2close");

sleep(&Lpflags,LPPRI);
}
Lpflags=LPEXIST;
outb(LPCTRL,0);
splx(x);
if (DeBug)
 {
 printflags("Close:");
 printf("Close: Interrupts %d\n Characters %d\n Spindowns %d\n Sleeps in lp2write %d\n",Icount,Ccount,spindowns,wsleeps);
 }

}

lp2write(dev)
dev_t dev;
{
char c;
int x;
extern void lpwork();
while (u.u_count)
{
if (copyin(u.u_base, &c,1) == -1)
{
u.u_error=EFAULT;
return;
}
u.u_base++;
u.u_count--;

while (Lpqueue.c_cc > Highwater)
{
x=spl5();
lpwork(0);
if (Lpqueue.c_cc > Highwater)
{
wsleeps++;
if (DeBug > 1)
 printflags("Sleeping in lp2write");

Lpflags |= SLEEP;
sleep(&Lpqueue,LPPRI);
}
splx(x);
}
putc(c, &Lpqueue);
}
x=spl5();
lpwork(0);
splx(x);
}

static void lpwork(where)
int where;
{
int ch;
extern void lprestart();
unsigned short spins=spinloop;

Lpflags |= LPBUSY;

while(1)
{
while (((inb(LPSTAT) & (LPNERR | LPON | LPRDY)) != (LPNERR|LPON|LPRDY)) && --spins) ;
if (spins == 0)
 {
 spindowns++;
 if (DeBug > 2)
   printflags("Spundown"); 
 break;
 }
if ((ch=getc(&Lpqueue)) < 0)
 break;
outb(LPDATA,ch);
Ccount++;
outb(LPCTRL,LPSTRB | LPLF | LPINIT | LPSEL);
outb(LPCTRL,         LPLF | LPINIT | LPSEL);
}
if( Lpqueue.c_cc < Low_water && (Lpflags & SLEEP))
{
        Lpflags &= -SLEEP;
        if (DeBug > 2)
           printflags("Wakeup call");
        wakeup(&Lpqueue);
        
}
if (Lpqueue.c_cc <= 0)
{
Lpflags &= ~LPBUSY;
if (Lpflags & WAIT)
      {
        if (DeBug > 2)
           printflags("Wakeup call");
        wakeup(&Lpflags);
       }
}
else if ((Lpflags & TOPEND) == 0)
{
        if (DeBug > 2)
           printflags("Setting Timeout");
        timeout(lprestart,0,Wait_int);
        Lpflags |= TOPEND;
}
outb(LPCTRL,LPLF | LPINIT | LPSEL | LPIENB);
}


lp2intr(dev)
dev_t dev;
{
Icount++;
if (DeBug > 2)
  printflags("Got interrupt");

if ((Lpflags & LPBUSY) == 0)
        return;
if (Lpqueue.c_cc > 0)
  lpwork(1);
}
static void lprestart()
{
int x;
if (DeBug > 2)
  printflags("Restarting");
Lpflags &= ~TOPEND;
x=spl5();
lpwork(0);
splx(x);
}

void printflags(char *message)
{
printf("(%d) %s",DeBug, message);
if (Lpflags & LPEXIST)
    printf(" LPEXIST");
if (Lpflags & SLEEP)
    printf(" SLEEP");
if (Lpflags & LPBUSY)
    printf(" LPBUSY");
if (Lpflags & WAIT)
    printf(" WAIT");
if (Lpflags & TOPEND)
    printf(" TOPEND");
if (Lpflags & EXCLOPEN)
    printf(" EXCLOPEN");
if (Lpflags & OPEN)
     printf(" OPEN");
printf("\n");

}
int lp2ioctl(dev_t dev, int cmd, struct lp2 *arg, int mode)
{
static short read_it=0;

/* we're enforcing must_read_before_write here, just to keep
   from screwing up too badly :-) */

switch (cmd-MAGIC)
   {
   case 0: 
        arg->Lpflags=Lpflags;
        arg->DeBug=DeBug;
        arg->Ccount=Ccount;
        arg->Icount=Icount;
        arg->spindowns=spindowns;
        arg->wsleeps=wsleeps;
        arg->spinloop=spinloop;
        arg->Low_water=Low_water;
        arg->Highwater=Highwater;
        arg->Wait_int=Wait_int;
        read_it=1;
        break;
   case 1:
     if (read_it)
        {
        /* Lpflags=arg->Lpflags; */
        DeBug=arg->DeBug;
        Ccount=arg->Ccount;
        Icount=arg->Icount;
        spindowns=arg->spindowns;
        wsleeps=arg->wsleeps;
        spinloop=arg->spinloop;
        Low_water=arg->Low_water;
        Highwater=arg->Highwater;
        Wait_int=arg->Wait_int;
        break;
        }
      read_it=0;
    }
        
}


     }
  }
}

Driver



If this page was useful to you, please click to help others find it:  

Your +1's can help friends, contacts, and others on the web find the best stuff when they search.

Comments?




More Articles by Tony Lawrence - Find me on Google+



Click here to add your comments


I am able to print only few words not all
the words

--

? No problem printing the whole thing here..

--TonyLawrence





Don't miss responses! Subscribe to Comments by RSS or by Email

Click here to add your comments


If you want a picture to show with your comment, go get a Gravatar



Have you tried Searching this site?

Unix/Linux/Mac OS X support by phone, email or on-site: Support Rates

This is a Unix/Linux resource website. It contains technical articles about Unix, Linux and general computing related subjects, opinion, news, help files, how-to's, tutorials and more. We appreciate comments and article submissions.

Publishing your articles here

Jump to Comments



Many of the products and books I review are things I purchased for my own use. Some were given to me specifically for the purpose of reviewing them. I resell or can earn commissions from the sale of some of these items. Links within these pages may be affiliate links that pay me for referring you to them. That's mostly insignificant amounts of money; whenever it is not I have made my relationship plain. I also may own stock in companies mentioned here. If you have any question, please do feel free to contact me.

Specific links that take you to pages that allow you to purchase the item I reviewed are very likely to pay me a commission. Many of the books I review were given to me by the publishers specifically for the purpose of writing a review. These gifts and referral fees do not affect my opinions; I often give bad reviews anyway.

We use Google third-party advertising companies to serve ads when you visit our website. These companies may use information (not including your name, address, email address, or telephone number) about your visits to this and other websites in order to provide advertisements about goods and services of interest to you. If you would like more information about this practice and to know your choices about not having this information used by these companies, click here.


My Troubleshooting E-Book will show you how to solve tough problems on Linux and Unix systems!


book graphic unix and linux troubleshooting guide




 I sell and support
 Kerio Mail server
pavatar.jpg

This post tagged:

       - Code




Unix/Linux Consultants

Skills Tests

Guest Post Here