*BSD News Article 10693


Return to BSD News archive

Received: by minnie.vk1xwt.ampr.org with NNTP
	id AA490 ; Wed, 03 Feb 93 19:01:28 EST
Path: sserve!manuel.anu.edu.au!munnari.oz.au!spool.mu.edu!caen!saimiri.primate.wisc.edu!copper!mercury.cair.du.edu!mnemosyne.cs.du.edu!nyx!smace
From: smace@nyx.cs.du.edu (Scott Mace)
Newsgroups: comp.unix.bsd
Subject: [386BSD] lpdriver.shar --- a set of working lp drivers
Message-ID: <1993Feb2.214555.16947@mnemosyne.cs.du.edu>
Date: 2 Feb 93 21:45:55 GMT
Sender: usenet@mnemosyne.cs.du.edu (netnews admin account)
Organization: Nyx, Public Access Unix @ U. of Denver Math/CS dept.
Lines: 1438

Here are two lpt drivers that I use on my systems.  lpt.c and lp.c
both work basically the same.

---cut here---
# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	LPTEST
#	README
#	files.i386
#	conf.c
#	lp.c
#	lpt.c
#	lpt.h
#	lptreg.h
#
echo x - LPTEST
sed 's/^X//' >LPTEST << 'END-of-LPTEST'
X#
X# LPTEST -- Generic ISA machine -- lptest test kernel
X#
Xmachine		"i386"
Xcpu		"i386"
Xident	 	LPTEST	
Xtimezone	6 dst
Xmaxusers	16
Xoptions		INET,NFS,XSERVER,UCONSOLE
Xoptions		"COMPAT_43"
Xoptions		"TCP_COMPAT_42"
Xoptions		"i387"
X
Xconfig 		"386bsd"	root on sd0 swap on sd0
X
Xcontroller	isa0
X
X#controller	wd0	at isa? port "IO_WD1" bio irq 14 vector wdintr
X#disk		wd0	at wd0 drive 0
X#disk		wd0	at wd0 drive 1
X
Xcontroller	fd0	at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr
Xdisk		fd0	at fd0 drive 0
Xdisk		fd1	at fd0 drive 1
X
Xdevice		pc0	at isa? port "IO_KBD" tty irq 1 vector pcrint
Xdevice		npx0	at isa? port "IO_NPX" irq 13 vector npxintr
Xdevice		com0	at isa? port "IO_COM1" tty irq 4 vector comintr
Xdevice		com1	at isa? port "IO_COM2" tty irq 3 vector comintr
X
X# Use lpt1 for the lpt.c and lp0 for lp.c
Xdevice		lpt1    at isa? port "IO_LPT1" tty irq 7 vector lptintr
X#device		lp0	at isa? port "IO_LPT1" irq 7 vector lpintr
X
X# sound blaster
Xdevice          sb0     at isa? port 0x220 bio irq 5 drq 1 vector sbintr
X
X# julian Escher's SCSI drivers
Xcontroller	aha0	at isa? port "IO_AHA0" bio irq 11 drq 5 vector ahaintr
X#controller	aha1	at isa? port "IO_AHA1" bio irq 12 drq 7 vector ahaintr
X#controller	bt0	at isa? port "IO_BT0" bio irq 12  vector btintr
Xcontroller	scbus0
X
Xdevice		sd0
Xdevice		sd1
Xdevice		sd2
Xdevice		sd3
X
Xdevice		st0
Xdevice		st1
Xdevice		st2
Xdevice		st3
X
Xdevice		cd0
Xdevice		cd1
X
Xdevice		we0 at isa? port 0x280 net irq 9 iomem 0xd0000 iosiz 8192 vector weintr
X
X
Xpseudo-device	loop
Xpseudo-device	ether
Xpseudo-device	sl	
Xpseudo-device	log
X#pseudo-device	ddb
Xpseudo-device	pty 16
X
Xpseudo-device	swappager
Xpseudo-device	vnodepager
Xpseudo-device	devpager
END-of-LPTEST
echo x - README
sed 's/^X//' >README << 'END-of-README'
XHere is the lpt driver that I use on my system.  
X
Xlpt.c        original lpt driver with various patches     
X
Xlp.c         new lp driver (works like lpt.c) 
X
Xlpt.c should work fine on many systems.  If it doesn't, then use lp.c,
Xwhich is a complete rewrite of a line printer driver.  
X
Xlpt.c       /sys/i386/isa
Xlptreg.h    /sys/i386/isa
Xlp.c	    /sys/i386/isa
X
Xconf.c      /sys/i386/i386
X
Xfiles.i386  /sys/i386/conf
XLPTEST	    my config file
X
Xmy conf.c  should work with both the lpt and lp drivers.  
X
XThese drivers should fix the problems with systems rebooting.
X
XThe major and minor numbers of the devices as per my conf.c
X
Xdevice		major	minor
X/dev/lpt1  	16	0
X/dev/lp0	17 	0
X
XSend any questions to    emace@tenet.edu
X 
END-of-README
echo x - files.i386
sed 's/^X//' >files.i386 << 'END-of-files.i386'
Xi386/i386/autoconf.c	standard device-driver
Xi386/i386/cons.c		standard
Xi386/isa/pccons.c	optional pc device-driver
Xi386/isa/clock.c	standard
Xi386/i386/in_cksum.c	optional inet
Xi386/i386/machdep.c		standard config-dependent
Xi386/i386/math_emulate.c		standard
Xi386/i386/mem.c		standard
Xi386/i386/pmap.c	standard
Xi386/i386/ns_cksum.c	optional ns
Xi386/i386/sys_machdep.c	standard
Xi386/i386/trap.c		standard
Xi386/i386/vm_machdep.c	standard
Xi386/isa/if_ne.c	optional ne device-driver
Xi386/isa/if_we.c	optional we device-driver
Xi386/isa/if_ec.c	optional ec device-driver
Xi386/isa/if_is.c	optional is device-driver
Xi386/isa/wd.c		optional wd device-driver
Xi386/isa/fd.c		optional fd device-driver
Xi386/isa/wt.c		optional wt device-driver
Xi386/isa/isa.c		optional isa device-driver
Xi386/isa/com.c		optional com device-driver
Xi386/isa/npx.c		optional npx device-driver
Xi386/isa/as.c		optional as device-driver
Xi386/isa/lpt.c          optional lpt device-driver 
Xi386/isa/lp.c	 	optional lp device-driver
Xi386/isa/sb_driver.c	optional sb device-driver
Xi386/i386/db_disasm.c	optional ddb
Xi386/i386/db_interface.c	optional ddb
Xi386/i386/db_trace.c	optional ddb
Xi386/isa/aha1742.c	optional ahb
Xi386/isa/aha1542.c	optional aha
Xi386/isa/bt742a.c	optional bt
Xi386/isa/ultra14f.c	optional uha
Xscsi/st.c		optional st
Xscsi/sd.c		optional sd
Xscsi/cd.c		optional cd
Xscsi/ch.c		optional ch
Xscsi/scsiconf.c		optional scbus
END-of-files.i386
echo x - conf.c
sed 's/^X//' >conf.c << 'END-of-conf.c'
X/*-
X * Copyright (c) 1990 The Regents of the University of California.
X * All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * William Jolitz.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X *	@(#)conf.c	5.8 (Berkeley) 5/12/91
X */
Xstatic char rcsid[] = "$Header: /usr/src/sys.386bsd/i386/i386/RCS/conf.c,v 1.2 92/01/21 14:21:57 william Exp Locker: toor $";
X
X#include "param.h"
X#include "systm.h"
X#include "buf.h"
X#include "ioctl.h"
X#include "tty.h"
X#include "conf.h"
X
Xint	nullop(), enxio(), enodev(), rawread(), rawwrite(), swstrategy();
Xint	rawread(), rawwrite(), swstrategy();
X
X#include "wd.h"
X#if NWD > 0
Xint	wdopen(),wdclose(),wdstrategy(),wdioctl();
Xint	wddump(),wdsize();
X#else
X#define	wdopen		enxio
X#define	wdclose		enxio
X#define	wdstrategy	enxio
X#define	wdioctl		enxio
X#define	wddump		enxio
X#define	wdsize		NULL
X#endif
X
X#include "as.h"
X#if NAS > 0
Xint	asopen(),asclose(),asstrategy(),asioctl();
Xint	/*asdump(),*/assize();
X#define	asdump		enxio
X#else
X#define	asopen		enxio
X#define	asclose		enxio
X#define	asstrategy	enxio
X#define	asioctl		enxio
X#define	asdump		enxio
X#define	assize		NULL
X#endif
X
X#include "sd.h"
X#if NSD > 0
Xint	sdopen(),sdclose(),sdstrategy(),sdioctl();
Xint	/*sddump(),*/sdsize();
X#define	sddump		enxio
X#else
X#define	sdopen		enxio
X#define	sdclose		enxio
X#define	sdstrategy	enxio
X#define	sdioctl		enxio
X#define	sddump		enxio
X#define	sdsize		NULL
X#endif
X
X#include "st.h"
X#if NST > 0
Xint	stopen(),stclose(),ststrategy(),stioctl();
X/*int	stdump(),stsize();*/
X#define	stdump		enxio
X#define	stsize		NULL
X#else
X#define	stopen		enxio
X#define	stclose		enxio
X#define	ststrategy	enxio
X#define	stioctl		enxio
X#define	stdump		enxio
X#define	stsize		NULL
X#endif
X
X#include "cd.h"
X#if NCD > 0
Xint	cdopen(),cdclose(),cdstrategy(),cdioctl();
Xint	/*cddump(),*/cdsize();
X#define	cddump		enxio
X#else
X#define	cdopen		enxio
X#define	cdclose		enxio
X#define	cdstrategy	enxio
X#define	cdioctl		enxio
X#define	cddump		enxio
X#define	cdsize		NULL
X#endif
X
X#include "sb.h"
X#if NSB > 0
Xint     sb_open(), sb_close(), sb_ioctl(), sb_read(), sb_write();
X#else
X#define sb_open         enxio
X#define sb_close        enxio
X#define sb_ioctl        enxio
X#define sb_read         enxio
X#define sb_write        enxio
X#endif 
X
X#include "wt.h"
X#if NWT > 0
Xint	wtopen(),wtclose(),wtstrategy(),wtioctl();
Xint	wtdump(),wtsize();
X#else
X#define	wtopen		enxio
X#define	wtclose		enxio
X#define	wtstrategy	enxio
X#define	wtioctl		enxio
X#define	wtdump		enxio
X#define	wtsize		NULL
X#endif
X
X#include "fd.h"
X#if NFD > 0
Xint	Fdopen(),fdclose(),fdstrategy();
X#define	fdioctl		enxio
X#define	fddump		enxio
X#define	fdsize		NULL
X#else
X#define	Fdopen		enxio
X#define	fdclose		enxio
X#define	fdstrategy	enxio
X#define	fdioctl		enxio
X#define	fddump		enxio
X#define	fdsize		NULL
X#endif
X
Xint	swstrategy(),swread(),swwrite();
X
Xstruct bdevsw	bdevsw[] =
X{
X	{ wdopen,	wdclose,	wdstrategy,	wdioctl,	/*0*/
X	  wddump,	wdsize,		NULL },
X	{ enodev,	enodev,		swstrategy,	enodev,		/*1*/
X	  enodev,	enodev,		NULL },
X	{ Fdopen,	fdclose,	fdstrategy,	fdioctl,	/*2*/
X	  fddump,	fdsize,		NULL },
X	{ wtopen,	wtclose,	wtstrategy,	wtioctl,	/*3*/
X	  wtdump,	wtsize,		B_TAPE },
X#if NSD > 0
X	{ sdopen,	sdclose,	sdstrategy,	sdioctl,	/*4*/
X	  sddump,	sdsize,		NULL },
X#else NSD > 0
X	{ asopen,	asclose,	asstrategy,	asioctl,	/*4*/
X	  asdump,	assize,		NULL },
X#endif NSD > 0
X	{ stopen,	stclose,	ststrategy,	stioctl,	/*5*/
X	  stdump,	stsize,		NULL },
X	{ cdopen,	cdclose,	cdstrategy,	cdioctl,	/*6*/
X	  cddump,	cdsize,		NULL },
X};
Xint	nblkdev = sizeof (bdevsw) / sizeof (bdevsw[0]);
X
Xint	cnopen(),cnclose(),cnread(),cnwrite(),cnioctl(),cnselect();
X
Xint	pcopen(),pcclose(),pcread(),pcwrite(),pcioctl(),pcmmap();
Xextern	struct tty pccons;
X
Xint	cttyopen(), cttyread(), cttywrite(), cttyioctl(), cttyselect();
X
Xint 	mmrw();
X#define	mmselect	seltrue
X
X#include "pty.h"
X#if NPTY > 0
Xint	ptsopen(),ptsclose(),ptsread(),ptswrite(),ptsstop();
Xint	ptcopen(),ptcclose(),ptcread(),ptcwrite(),ptcselect();
Xint	ptyioctl();
Xstruct	tty pt_tty[];
X#else
X#define ptsopen		enxio
X#define ptsclose	enxio
X#define ptsread		enxio
X#define ptswrite	enxio
X#define ptcopen		enxio
X#define ptcclose	enxio
X#define ptcread		enxio
X#define ptcwrite	enxio
X#define ptyioctl	enxio
X#define	pt_tty		NULL
X#define	ptcselect	enxio
X#define	ptsstop		nullop
X#endif
X
X#include "com.h"
X#if NCOM > 0
Xint	comopen(),comclose(),comread(),comwrite(),comioctl();
X#define comreset	enxio
Xextern	struct tty com_tty[];
X#else
X#define comopen		enxio
X#define comclose	enxio
X#define comread		enxio
X#define comwrite	enxio
X#define comioctl	enxio
X#define comreset	enxio
X#define	com_tty		NULL
X#endif
X
X#include "lpt.h"
X#if NLPT > 0
Xint	lptopen(),lptclose(),lptwrite(),lptioctl();
X#else
X#define lptopen		enxio
X#define lptclose	enxio
X#define lptwrite	enxio
X#endif
X
X#include "lp.h"
X#if NLP > 0
Xint 	lpopen(),lpclose(),lpwrite();
X#else
X#define lpopen 		enxio
X#define lpclose		enxio
X#define lpwrite		enxio
X#endif
X
Xint	logopen(),logclose(),logread(),logioctl(),logselect();
X
Xint	ttselect(), seltrue();
X
X
Xstruct cdevsw	cdevsw[] =
X{
X	{ cnopen,	cnclose,	cnread,		cnwrite,	/*0*/
X	  cnioctl,	nullop,		nullop,		NULL,
X	  cnselect,	enodev,		NULL },
X	{ cttyopen,	nullop,		cttyread,	cttywrite,	/*1*/
X	  cttyioctl,	nullop,		nullop,		NULL,
X	  cttyselect,	enodev,		NULL },
X        { nullop,       nullop,         mmrw,           mmrw,           /*2*/
X          enodev,       nullop,         nullop,         NULL,
X          mmselect,     enodev,         NULL },
X	{ wdopen,	wdclose,	rawread,	rawwrite,	/*3*/
X	  wdioctl,	enodev,		nullop,		NULL,
X	  seltrue,	enodev,		wdstrategy },
X	{ nullop,	nullop,		rawread,	rawwrite,	/*4*/
X	  enodev,	enodev,		nullop,		NULL,
X	  enodev,	enodev,		swstrategy },
X	{ ptsopen,	ptsclose,	ptsread,	ptswrite,	/*5*/
X	  ptyioctl,	ptsstop,	nullop,		pt_tty,
X	  ttselect,	enodev,		NULL },
X	{ ptcopen,	ptcclose,	ptcread,	ptcwrite,	/*6*/
X	  ptyioctl,	nullop,		nullop,		pt_tty,
X	  ptcselect,	enodev,		NULL },
X	{ logopen,	logclose,	logread,	enodev,		/*7*/
X	  logioctl,	enodev,		nullop,		NULL,
X	  logselect,	enodev,		NULL },
X	{ comopen,	comclose,	comread,	comwrite,	/*8*/
X	  comioctl,	enodev,		comreset,	com_tty,
X	  ttselect,	enodev,		NULL },
X	{ Fdopen,	fdclose,	rawread,	rawwrite,	/*9*/
X	  fdioctl,	enodev,		nullop,		NULL,
X	  seltrue,	enodev,		fdstrategy },
X	{ wtopen,	wtclose,	rawread,	rawwrite,	/*A*/
X	  wtioctl,	enodev,		nullop,		NULL,
X	  seltrue,	enodev,		wtstrategy },
X	{ enodev,	enodev,		enodev,		enodev,		/*B*/
X	  enodev,	enodev,		nullop,		NULL,
X	  seltrue,	enodev,		enodev },
X	{ pcopen,	pcclose,	pcread,		pcwrite,	/*C*/
X	  pcioctl,	nullop,		nullop,		&pccons,
X	  ttselect,	pcmmap,		NULL },
X#if   NSD > 0
X	{ sdopen,	sdclose,	rawread,	rawwrite,	/*D*/
X	  sdioctl,	enodev,		nullop,		NULL,
X	  seltrue,	enodev,		sdstrategy },
X#else NSD > 0
X	{ asopen,	asclose,	rawread,	rawwrite,	/*D*/
X	  asioctl,	enodev,		nullop,		NULL,
X	  seltrue,	enodev,		asstrategy },
X#endif		NSD > 0
X        { stopen,       stclose,        rawread,        rawwrite,       /*E*/
X          stioctl,      enodev,         nullop,         NULL,
X          seltrue,      enodev,         ststrategy },
X	{ cdopen,	cdclose,	rawread,	rawwrite, 	/*F*/
X	  cdioctl,	enodev,		nullop,		NULL,
X	  seltrue,	enodev,		cdstrategy },
X	{ lptopen,	lptclose,	nullop,		lptwrite,	/*10*/
X	  enodev,	nullop,		nullop,		NULL,
X	  seltrue,	enodev,		enodev },
X        { lpopen,       lpclose,        enodev,         lpwrite,        /*11*/
X          enodev,       enodev,         nullop,         NULL,
X          seltrue,      enodev,         NULL },
X        { enodev,       enodev,         enodev,         enodev,         /*12*/
X          enodev,       enodev,         nullop,         NULL,
X          seltrue,      enodev,         enodev },
X        { enodev,       enodev,         enodev,         enodev,         /*13*/
X          enodev,       enodev,         nullop,         NULL,
X          seltrue,      enodev,         enodev },
X        { enodev,       enodev,         enodev,         enodev,         /*14*/
X          enodev,       enodev,         nullop,         NULL,
X          seltrue,      enodev,         enodev },
X        { sb_open,      sb_close,       sb_read,        sb_write,       /*15*/
X          sb_ioctl,     enodev,         nullop,         NULL,
X          seltrue,      enodev,         enodev },
X};
Xint	nchrdev = sizeof (cdevsw) / sizeof (cdevsw[0]);
X
Xint	mem_no = 2; 	/* major device number of memory special file */
X
X/*
X * Swapdev is a fake device implemented
X * in sw.c used only internally to get to swstrategy.
X * It cannot be provided to the users, because the
X * swstrategy routine munches the b_dev and b_blkno entries
X * before calling the appropriate driver.  This would horribly
X * confuse, e.g. the hashing routines. Instead, /dev/drum is
X * provided as a character (raw) device.
X */
Xdev_t	swapdev = makedev(1, 0);
END-of-conf.c
echo x - lp.c
sed 's/^X//' >lp.c << 'END-of-lp.c'
X/*
X** parallel port printer driver
X** by Tibor Sashegyi 19/04/92
X** (ideas from everywhere)
X** stage 2
X*/
X
X#include "lp.h"
X
X#if NLP > 0
X
X#include "param.h"
X#include "systm.h"
X#include "proc.h"
X#include "user.h"
X#include "conf.h"
X#include "file.h"
X#include "uio.h"
X#include "kernel.h"
X#include "syslog.h"
X#include "buf.h"
X
X#include "i386/isa/isa_device.h"
X
X/*
X** printer port base addresses
X*/
X
X
X#define LPB_1_BASE 0x378	/* base i/o address printer 1 */
X#define LPB_2_BASE 0x3BC	/* base i/o address printer 2 */
X#define LPB_3_BASE 0x278	/* base i/o address printer 3 */
X
X/*
X** i/o registers
X*/
X
X#define LPR_DATA 0x00		/* data register */
X#define LPR_STAT 0x01		/* status register */
X#define LPR_CTRL 0x02		/* control register */
X
X/*
X** control bits
X*/
X
X#define LPC_INIT   0x08		/* select and init printer */
X#define LPC_STROBE 0x1D		/* strobe data */
X#define LPC_READY  0x1C		/* idle IRQ enabled */
X#define LPC_SELECT 0x0C		/* select */
X
X/*
X** status bits
X*/
X
X#define LPS_ERROR  0x08		/* 0 general error */
X#define LPS_SELECT 0x10		/* 1 selected */
X#define LPS_PAPER  0x20		/* 1 out of paper */
X#define LPS_BUSY   0x80		/* 0 busy */
X
X/*
X** lp control block
X*/
X
X#define LPF_ACTIVE 0x01
X#define LPF_OPEN   0x02
X#define LPF_BUSY   0x04
X#define LPF_PAPER  0x08
X#define LPF_ERROR  0x10
X
X#define MAXBUF     0x100
X
Xstruct lpctrl
X	{
X	int			unit;
X	int			port;
X	char		flags;
X	int			error;
X	int			count;
X	char		*cp;
X	char		buf[MAXBUF];
X	} lp_ctrl[NLP];
X
X/*
X** misc
X*/
X
X#define LPWATCH   1
X
Xint lpprobe(), lpattach(), lpphysio(), lpstrategy();
Xvoid lpwatchdog(), lpintr(), lpiowait(), lpiodone();
X
X/*
X** define autoconfig entries
X*/
X
Xstruct isa_driver lpdriver =
X	{
X	lpprobe, lpattach, "lp"
X	};
X
X#define	UNIT(x)		minor(x)
X
X/*
X** the following delay value is about right for my machine
X** fix it for anything else
X*/
X
X#define CPUSPEED 7
X#define	LPDELAY(n)	{ register int N = (n) * CPUSPEED; while (--N > 0); }
X
X/*
X** probe for device 
X** I really should probe for the parallel port
X** and maybe even the printer, but I trust the
X** configuration (silly me).
X*/
X
Xint lpprobe(idev)
Xstruct isa_device *idev;
X	{
X	if (idev->id_unit >= NLP)
X		return(0);
X
X	if (   idev->id_iobase != LPB_1_BASE
X	    && idev->id_iobase != LPB_2_BASE
X	    && idev->id_iobase != LPB_3_BASE)
X		{
X		printf("lp base out of range:%x\n", idev->id_iobase);
X		return(0);
X		}
X
X	return(1);
X	}
X
X/*
X** attach device
X*/
X
Xint lpattach(idev)
Xstruct isa_device *idev;
X	{
X	int unit = idev->id_unit;
X	int port = idev->id_iobase;
X	struct lpctrl *lpc = &lp_ctrl[unit];
X
X
X	lpc->unit = unit;
X	lpc->port = port;
X	lpc->flags = LPF_ACTIVE;
X
X	/*
X	** init printer (pulse width at least 50 us)
X	*/
X
X	outb(port + LPR_CTRL, LPC_INIT);
X	LPDELAY(51);
X
X	/*
X	** keep selected
X	*/
X
X	outb(port + LPR_CTRL, LPC_SELECT);
X
X	return (1);
X	}
X
X/*
X** open device
X*/
X
Xlpopen(dev, flag, mode, p)
X	dev_t dev;
X	int flag, mode;
X	struct proc *p;
X	{
X	int unit = UNIT(dev);
X	struct lpctrl *lpc = &lp_ctrl[unit];
X	char val;
X 
X	/*
X	** make sure device is configured 
X	*/
X
X	if (unit >= NLP || (lpc->flags & LPF_ACTIVE) == 0)
X		return(ENXIO);
X
X	/*
X	** only one open !
X	*/
X
X	if (lpc->flags & LPF_OPEN)
X		return(EBUSY);
X
X	/*
X	**	check direction
X	*/
X
X	if (flag & FREAD)
X		return(ENODEV);
X
X	/*
X	** check printer status
X	*/
X
X	val = inb(lpc->port + LPR_STAT);
X	if (val & LPS_PAPER)
X		{
X		uprintf("lp%d: out of paper\n", unit);
X		return(EIO);
X		}
X
X	if ((val & LPS_ERROR) == 0 || (val & LPS_SELECT) == 0)
X		{
X		uprintf("lp%d: not ready\n", unit);
X		return(EIO);
X		}
X
X	/*
X	** start watchdog timer
X	*/
X
X	timeout(lpwatchdog, lpc, LPWATCH*hz);
X	
X	/*
X	** enable interrupts and mark as opened
X	*/
X
X	outb(lpc->port + LPR_CTRL, LPC_READY);
X	lpc->flags |= LPF_OPEN;
X
X	return(0);
X	}
X 
X/*
X** close device
X*/
X
Xint lpclose(dev, flag, mode, p)
X	dev_t dev;
X	int flag, mode;
X	struct proc *p;
X	{
X	int unit = UNIT(dev);
X	struct lpctrl *lpc = &lp_ctrl[unit];
X
X	/*
X	** disable interrupts but keep selected, mark as closed
X	*/
X
X	outb(lpc->port + LPR_CTRL, LPC_SELECT);
X	lpc->flags &= ~LPF_OPEN;
X
X	return(0);
X	}
X 
X/*
X** write to device
X*/
X
Xint lpwrite(dev, uio)
X	dev_t dev;
X	struct uio *uio;
X{
X	return (uioapply(lpphysio, lpstrategy, dev, uio));
X}
X
X/*
X** check access, lock and call lpstrategy 
X** to output next printer buffer
X*/
X
Xint lpphysio(strat, dev, off, rw, base, len, p)
X	int (*strat)(); 
X	dev_t dev;
X	int rw, off;
X	caddr_t base;
X	int *len;
X	struct proc *p;
X{
X	int error;
X	int rest = *len;
X	int cnt;
X	caddr_t addr = base;
X
X	rw = rw == UIO_READ ? B_READ : 0;
X
X	/*
X	** check if accessible
X	*/
X
X	if (rw == B_READ && !useracc(base, *len, B_WRITE))
X		return (EFAULT);
X
X	if (rw == B_WRITE && !useracc(base, *len, B_READ))
X		return (EFAULT);
X
X	/*
X	** lock in core
X	*/
X
X	vslock (base, *len);
X
X	/*
X	** perform transfer
X	*/
X
X	error = 0;
X	while(error == 0 && rest > 0)
X		{
X		cnt = min(rest, MAXBUF);
X		rest -= cnt;
X		error = lpstrategy(UNIT(dev), addr, cnt);
X		addr += cnt;
X		}
X
X	/*
X	** unlock
X	*/
X
X	vsunlock (base, *len, 0);
X
X	*len = 0;
X	return (error);
X	}
X
X/*
X** fetch next buffer and start output
X*/
X
Xint lpstrategy(unit, addr, len)
X	int unit;
X	caddr_t addr;
X	int len;
X	{
X	struct lpctrl *lpc = &lp_ctrl[unit];
X	int s;
X
X	lpc->count = len;
X	if (copyin(addr, lpc->buf, len))
X		{
X		lpiodone(lpc);
X		return(EFAULT);
X		}
X
X	lpc->cp = lpc->buf;
X	lpc->flags |= LPF_BUSY;
X	lpc->error = 0;
X
X	s = splhigh();
X	lpintr(unit);
X	splx(s);
X	
X	/*
X	** wait for i/o to complete
X	*/
X
X	lpiowait(lpc);
X
X	return(lpc->error);
X	}
X
X/*
X** output next characters until printer becomes busy
X** interrupt driven except for the first time
X*/
X 
Xvoid lpintr(unit)
X	int unit;
X{
X	struct lpctrl *lpc = &lp_ctrl[unit];
X	int port = lpc->port;
X	char val;
X
X	/*
X	** check for spurious interrupt
X	*/
X
X	if (!(lpc->flags & LPF_BUSY))
X		return;
X
X	/*
X	** any more to print
X	*/
X
X	while (lpc->count)
X		{
X		val = inb(lpc->port + LPR_STAT);
X		if ((val & LPS_BUSY) == 0)
X			return;
X		/*
X		** output the character
X		*/
X
X		outb(port + LPR_DATA, *lpc->cp++);
X		--lpc->count;
X
X		/*
X		** valid data must be present for at least 0.5 us
X		*/
X
X		LPDELAY(1);
X
X		/*
X		** strobe for 1 us
X		*/
X
X		outb(port + LPR_CTRL, LPC_STROBE);
X		LPDELAY(1);
X		outb(port + LPR_CTRL, LPC_READY);
X
X		/*
X		** valid data must be present for at least 0.5 us
X		*/
X
X		LPDELAY(1);
X		}
X
X	lpiodone(lpc);
X	}
X
X/*
X** wait for i/o to finish
X*/
X
Xvoid lpiowait(lpc)
X	struct lpctrl *lpc;
X	{
X	while (lpc->flags & LPF_BUSY) 
X		{
X		if (lpc->error = tsleep(lpc, PRIBIO|PCATCH, NULL, 0))
X			lpc->flags &= ~LPF_BUSY;
X		}
X	}
X
X/*
X** wakeup strategy function
X*/
X
Xvoid lpiodone(lpc)
X	struct lpctrl *lpc;
X	{
X	lpc->flags &= ~LPF_BUSY;
X	wakeup(lpc);
X	}
X
X/*
X** handle watchdog timeout
X*/
X
Xvoid lpwatchdog(lpc)
X	struct lpctrl *lpc;
X	{
X	char val;
X	int s;
X
X	/*
X	** are we still running ?
X	*/
X
X	s = splhigh();	/* bit of an overkill ?!? */
X
X	if ((lpc->flags & LPF_OPEN) == 0)
X		{
X		splx(s);
X		return;
X		}
X
X	/*
X	** check printer status
X	*/
X
X	val = inb(lpc->port + LPR_STAT);
X
X	/*
X	** report errors only once
X	*/
X
X	if (val & LPS_PAPER && (lpc->flags & LPF_PAPER) == 0)
X		{
X		printf("lp%d: out of paper, please fix\n", lpc->unit);
X		lpc->flags |= LPF_PAPER;
X		}
X	if (lpc->flags & LPF_PAPER && (val & LPS_PAPER) == 0)
X		lpc->flags &= ~LPF_PAPER;
X
X	if ((val & LPS_ERROR) == 0 && (lpc->flags & LPF_ERROR) == 0)
X		{
X		printf("lp%d: not ready, please fix\n", lpc->unit);
X		lpc->flags |= LPF_ERROR;
X		}
X	if (lpc->flags & LPF_ERROR && (val & LPS_ERROR) == 0)
X		lpc->flags &= ~LPF_ERROR;
X	
X	/*
X	** restart watchdog timer
X	*/
X
X	timeout(lpwatchdog, lpc, LPWATCH*hz);
X	splx(s);
X	}
X
X#endif
END-of-lp.c
echo x - lpt.c
sed 's/^X//' >lpt.c << 'END-of-lpt.c'
X/*
X * Copyright (c) 1990 William F. Jolitz, TeleMuse
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *   This software is a component of "386BSD" developed by 
X *   William F. Jolitz, TeleMuse.
X * 4. Neither the name of the developer nor the name "386BSD"
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ 
X * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS 
X * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT. 
X * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT 
X * NOT MAKE USE OF THIS WORK.
X *
X * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
X * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN 
X * REFERENCES SUCH AS THE  "PORTING UNIX TO THE 386" SERIES 
X * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING 
X * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND 
X * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE 
X * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS 
X * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
X *
X * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE DEVELOPER BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X */
X
X/*
X * Device Driver for AT parallel printer port
X * Written by William Jolitz 12/18/90
X * Modified to run without interrupts
X * 92-08-19  Wolfgang Stanglmeier  <wolf@dentaro.GUN.de>
X * Slight cleanup and reorganization, try to handle restarted syscalls
X * 92-09-08  Andy Valencia <jtk@netcom.com>
X */
X
X#include "lpt.h"
X#if NLPT > 0
X
X#include "param.h"
X#include "buf.h"
X#include "systm.h"
X#include "ioctl.h"
X#include "tty.h"
X#include "proc.h"
X#include "user.h"
X#include "uio.h"
X#include "kernel.h"
X#include "malloc.h"
X
X#include "i386/isa/isa_device.h"
X#include "i386/isa/lptreg.h"
X
X/* internal used flags */
X#define   OPEN        (0x01)   /* device is open */
X#define   INIT        (0x02)   /* device in open procedure */
X
X/* flags from minor device */
X#define   LPT_PRIME   (0x20)   /* prime printer on open   */
X#define   LPT_ERROR   (0x10)   /* log error conditions    */
X
X#define   LPT_FLAG(x) ((x) & 0xfc)
X#define   LPT_UNIT(x) ((x) & 0x03)
X
X/* Printer Ready condition */
X#define   LPS_INVERT  (LPS_NBSY | LPS_NACK |           LPS_SEL | LPS_NERR)
X#define   LPS_MASK    (LPS_NBSY | LPS_NACK | LPS_OUT | LPS_SEL | LPS_NERR)
X#define   NOT_READY()   ((inb(sc->sc_stat)^LPS_INVERT)&LPS_MASK)
X
X/* tsleep priority */
X#define   LPPRI       ((PZERO+8) | PCATCH)
X
Xint lptprobe(), lptattach();
Xstruct   isa_driver lptdriver = {lptprobe, lptattach, "lpt"};
X
X/*
X *   copy usermode data into sysmode buffer
X */
X#define   BUFSIZE      1024
X
X/*
X**   Waittimes
X*/
X#define   TIMEOUT   (hz*16)   /* Timeout while open device */
X#define   LONG      (hz* 1)   /* Timesteps while open      */
X
X#define   MAX_SPIN  255       /* max loop counter for busy wait */
X
X/*   Valid Controlbits for probe ...
X**
X**   The lower 5 bits of controlport should be
X**   readable and writable,
X** 
X**   .... but if my deskjet is power down, it clobbers
X**   some lines, and the port will not be configured.
X**   So I mask them out
X*/
X#define    LPC_MASK    (0xfa)
X
Xstruct lpt_softc {
X	char	*sc_cp;		/* current data to print	*/
X	int	sc_count;	/* bytes queued in sc_inbuf	*/
X	short	sc_data;	/* printer data port		*/
X	short	sc_stat;	/* printer control port		*/
X	short	sc_ctrl;	/* printer status port		*/
X	u_char	sc_flags;	/* flags (open and internal)	*/
X	u_char	sc_unit;	/* unit-number			*/
X	u_char	sc_smax;	/* current max busy loop cnt	*/
X	char			/* buffer for data		*/
X	 *sc_inbuf;
X} lpt_sc[NLPT];
X
X/* In fact, I need no interrupt, but how can I explain it to config ??? */
Xlptintr(unit)
X	int unit;
X{
X	/* dummy */ ;
X}
X
X/*
X * lptprobe()
X *	Probe for hardware
X */
Xlptprobe(idp)
X	struct isa_device *idp;
X{   
X	unsigned v, w, n = 0;
X
X	/* status */
X	do {
X		if (++n >= 4)
X			return (0);
X
X		/*
X		 * Status port should be read only,
X		 * so readback value may not change
X		 */
X		outb(idp->id_iobase+lpt_status,0xf0);
X		v = inb(idp->id_iobase+lpt_status);
X		outb(idp->id_iobase+lpt_status,0);
X		w = inb(idp->id_iobase+lpt_status);
X	} while (v != w);
X
X	/* control: the lower 5 bits of controlport should read back */
X	outb(idp->id_iobase+lpt_control,0xff);
X	DELAY(100);
X
X	w = inb(idp->id_iobase+lpt_control);
X	if ((w ^ 0xff) & LPC_MASK) return(0);
X
X	outb(idp->id_iobase+lpt_control,0);
X	DELAY(100);
X	w = inb(idp->id_iobase+lpt_control);
X	if ((w ^ 0xe0) & LPC_MASK)
X		return(0);
X	return(1);
X}
X
X/*
X * lptattach()
X *	Install device
X */
Xlptattach(isdp)
X	struct isa_device *isdp;
X{
X	struct   lpt_softc   *sc;
X
X	sc = lpt_sc + isdp->id_unit;
X	sc->sc_unit = isdp->id_unit;
X	sc->sc_data = isdp->id_iobase + lpt_data;
X	sc->sc_stat = isdp->id_iobase + lpt_status;
X	sc->sc_ctrl = isdp->id_iobase + lpt_control;
X	outb(sc->sc_ctrl, LPC_NINIT);
X	return (1);
X}
X
X/*
X * lptopen()
X *	New open on device.
X *
X * We forbid all but first open
X */
Xlptopen(dev, flag)
X	dev_t dev;
X	int flag;
X{
X	struct lpt_softc *sc;
X	int delay;	/* slept time in 1/hz seconds of tsleep */
X	int err;
X	u_char sta, unit;
X
X	unit= LPT_UNIT(minor(dev));
X	sta = LPT_FLAG(minor(dev));
X
X	/* minor number out of limits ? */
X	if (unit >= NLPT)
X		return (ENXIO);
X	sc = lpt_sc + unit;
X
X	/* Attached ? */
X	if (!sc->sc_ctrl) { /* not attached */
X		return(ENXIO);
X	}
X
X	/* Printer busy ? */
X	if (sc->sc_flags) { /* too late .. */
X		return(EBUSY);
X	}
X
X	/* Have memory for buffer? */
X	sc->sc_inbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK);
X	if (sc->sc_inbuf == 0)
X		return(ENOMEM);
X
X	/* Init printer */
X	sc->sc_flags = sta | INIT;
X	if (sc->sc_flags & LPT_PRIME) {
X		outb(sc->sc_ctrl, 0);
X	}
X
X	/* Select printer */
X	outb(sc->sc_ctrl, LPC_SEL|LPC_NINIT);
X
X	/* and wait for ready .. */
X	for (delay=0; NOT_READY(); delay+= LONG) {
X		if (delay >= TIMEOUT) { /* too long waited .. */
X			sc->sc_flags = 0;
X			return (EBUSY);
X		}
X
X		/* sleep a moment */
X		if ((err = tsleep (sc, LPPRI, "lpt: open", LONG)) !=
X				EWOULDBLOCK) {
X			sc->sc_flags = 0;
X			return (EBUSY);
X		}
X	}
X
X	/* Printer ready .. set variables */
X	sc->sc_flags |= OPEN;
X	sc->sc_count = 0;
X
X	return(0);
X}
X
X/*
X * pushbytes()
X *	Workhorse for actually spinning and writing bytes to printer
X */
Xstatic
Xpushbytes(sc)
X	struct lpt_softc *sc;
X{
X	int spin, err, tic;
X	char ch;
X
X	/* loop for every character .. */
X	while (sc->sc_count > 0) {
X		/* printer data */
X		ch = *(sc->sc_cp);
X		sc->sc_cp += 1;
X		sc->sc_count -= 1;
X		outb(sc->sc_data, ch);
X
X		/* Busy wait for printer ready .. */
X		spin = tic = 0;
X		while (NOT_READY()) {
X			if (++spin >= sc->sc_smax) {
X				/*
X				 * Now sleep, every cycle a
X				 * little longer ..
X				 */
X				tic = tic + tic + 1;
X				err = tsleep(sc, LPPRI, "lpt: write", tic);
X				if (err != EWOULDBLOCK) {
X					return (err);
X				}
X			}
X		}
X
X		/* strobe */
X		outb(sc->sc_ctrl, LPC_NINIT|LPC_SEL|LPC_STB);
X		outb(sc->sc_ctrl, LPC_NINIT|LPC_SEL);
X
X		/* Adapt busy-wait length... */
X		if (spin >= sc->sc_smax) { /* was sleep wait */
X			if (sc->sc_smax<MAX_SPIN)
X				sc->sc_smax++;
X		}
X		if (spin*2 < sc->sc_smax) {
X			sc->sc_smax--;
X		}
X	}
X	return(0);
X}
X
X/*
X * lptclose()
X *	Close on lp.  Try to flush data in buffer out.
X */
Xlptclose(dev, flag)
X	dev_t dev;
X	int flag;
X{
X	struct lpt_softc *sc = lpt_sc + LPT_UNIT(minor(dev));
X
X	/* If there's queued data, try to flush it */
X	(void)pushbytes(sc);
X
X	/* really close .. quite simple :-)  */
X	outb(sc->sc_ctrl, LPC_NINIT);
X	sc->sc_flags = 0;
X	free(sc->sc_inbuf, M_DEVBUF);
X	sc->sc_inbuf = 0;	/* Sanity */
X	return(0);
X}
X
X/*
X * lptwrite()
X *	Copy from user's buffer, then print
X */
Xlptwrite(dev, uio)
X	dev_t dev;
X	struct uio *uio;
X{
X	struct lpt_softc *sc = lpt_sc + LPT_UNIT(minor(dev));
X	int err;
X
X	/* Write out old bytes from interrupted syscall */
X	if (sc->sc_count > 0) {
X		err = pushbytes(sc);
X		if (err)
X			return(err);
X	}
X
X	/* main loop */
X	while ((sc->sc_count = MIN(BUFSIZE, uio->uio_resid)) > 0) {
X		/*  get from user-space  */
X		sc->sc_cp = sc->sc_inbuf;
X		uiomove(sc->sc_inbuf, sc->sc_count, uio);
X		err = pushbytes(sc);
X		if (err)
X			return(err);
X	}
X	return(0);
X}
X#endif /* NLP > 0 */
END-of-lpt.c
echo x - lpt.h
sed 's/^X//' >lpt.h << 'END-of-lpt.h'
X#define NLPT 2
END-of-lpt.h
echo x - lptreg.h
sed 's/^X//' >lptreg.h << 'END-of-lptreg.h'
X/*-
X * Copyright (c) 1990 The Regents of the University of California.
X * All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * William Jolitz.
X *
X * %sccs.include.noredist.c%
X *
X *      @(#)lptreg.h	1.1 (Berkeley) 12/19/90
X */
X
X/*
X * AT Parallel Port (for lineprinter)
X * Interface port and bit definitions
X * Written by William Jolitz 12/18/90
X * Copyright (C) William Jolitz 1990
X */
X
X#define lpt_data	0	/* Data to/from printer (R/W) */
X
X#define lpt_status	1	/* Status of printer (R) */
X#define	LPS_NERR		0x08	/* printer no error */
X#define	LPS_SEL			0x10	/* printer selected */
X#define	LPS_OUT			0x20	/* printer out of paper */
X#define	LPS_NACK		0x40	/* printer no ack of data */
X#define	LPS_NBSY		0x80	/* printer no ack of data */
X
X#define lpt_control	2	/* Control printer (R/W) */
X#define	LPC_STB			0x01	/* strobe data to printer */
X#define	LPC_AUTOL		0x02	/* automatic linefeed */
X#define	LPC_NINIT		0x04	/* initialize printer */
X#define	LPC_SEL			0x08	/* printer selected */
X#define	LPC_ENA			0x10	/* printer out of paper */
END-of-lptreg.h
exit
---cut here---

--
*********************************************************************
*    Scott Mace                internet:    smace@nyx.cs.du.edu     *
*                                           emace@tenet.edu         *
*********************************************************************