Exemplo n.º 1
0
Arquivo: lpt.c Projeto: ryo/netbsd-src
/*
 * lptread --retrieve printer status in IEEE1284 NIBBLE mode
 */
int
lptread(dev_t dev_id, struct uio *uio, int ioflag)
{
	size_t len = 0;
	int error = 0;
	device_t dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
	struct lpt_softc *sc = device_private(dev);

	if(!(sc->sc_state & HAVEBUS)) {
		LPT_DPRINTF(("%s(%s): attempt to read using device which does "
			"not own the bus(%s).\n", __func__, device_xname(dev),
			device_xname(device_parent(dev))));
		return (ENODEV);
	}

	sc->sc_state &= ~INTERRUPTED;
	while (uio->uio_resid) {
		error = ppbus_read(device_parent(dev), sc->sc_outbuf,
			min(BUFSIZE, uio->uio_resid), 0, &len);

		/* If error or no more data, stop */
		if (error) {
			if (error != EWOULDBLOCK)
				sc->sc_state |= INTERRUPTED;
			break;
		}
		if (len == 0)
			break;

		if ((error = uiomove(sc->sc_outbuf, len, uio)))
			break;
	}

	return error;
}
Exemplo n.º 2
0
/*
 * Copy a line from user space to a local buffer, then call putc to get the
 * chars moved to the output queue.
 */
int
lptwrite(dev_t dev, struct uio *uio, int flags)
{
	struct lpt_softc *sc;
	size_t n;
	int error;

	sc = device_lookup_private(&lpt_cd, LPTUNIT(dev));
	error = 0;

	while ((n = min(LPT_BSIZE, uio->uio_resid)) != 0) {
		uiomove(sc->sc_cp = sc->sc_inbuf->b_data, n, uio);
		sc->sc_count = n;
		error = pushbytes(sc);
		if (error) {
			/*
			 * Return accurate residual if interrupted or timed
			 * out.
			 */
			uio->uio_resid += sc->sc_count;
			sc->sc_count = 0;
			return (error);
		}
	}
	return (0);
}
Exemplo n.º 3
0
Arquivo: lpt.c Projeto: ryo/netbsd-src
/*
 * lptclose -- close the device, free the local line buffer.
 *
 * Check for interrupted write call added.
 */
int
lptclose(dev_t dev_id, int flags, int fmt, struct lwp *l)
{
	device_t dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
	struct lpt_softc *sc = device_private(dev);
	int err;

	err = lpt_release_ppbus(sc, PPBUS_WAIT|PPBUS_INTR);
	if(err) {
		LPT_DPRINTF(("%s(%s): error (%d) while releasing ppbus.\n",
			__func__, device_xname(dev), err));
	}

	sc->sc_state = 0;

	return err;
}
Exemplo n.º 4
0
Arquivo: olpt.c Projeto: MarginC/kame
static	int
lptwrite(dev_t dev, struct uio * uio, int ioflag)
{
	register unsigned n;
	int pl, err;
	struct lpt_softc *sc;

	sc = devclass_get_softc(olpt_devclass, LPTUNIT(minor(dev)));
	if(sc->sc_flags & LP_BYPASS) {
		/* we can't do writes in bypass mode */
		return(EPERM);
	}

	sc->sc_state &= ~INTERRUPTED;
	while ((n = min(BUFSIZE, uio->uio_resid)) != 0) {
		sc->sc_cp = sc->sc_inbuf->b_data ;
		uiomove(sc->sc_cp, n, uio);
		sc->sc_xfercnt = n ;
		while ((sc->sc_xfercnt > 0)&&(sc->sc_irq & LP_USE_IRQ)) {
			lprintf(("i"));
			/* if the printer is ready for a char, */
			/* give it one */
			if ((sc->sc_state & OBUSY) == 0){
				lprintf(("\nC %d. ", sc->sc_xfercnt));
				pl = spltty();
				lpt_intr(sc);
				(void) splx(pl);
			}
			lprintf(("W "));
			if (sc->sc_state & OBUSY)
				if ((err = tsleep ((caddr_t)sc,
					 LPPRI|PCATCH, "lpwrite", 0))) {
					sc->sc_state |= INTERRUPTED;
					return(err);
				}
		}
		/* check to see if we must do a polled write */
		if(!(sc->sc_irq & LP_USE_IRQ) && (sc->sc_xfercnt)) {
			lprintf(("p"));
			if((err = pushbytes(sc)))
				return(err);
		}
	}
	return(0);
}
Exemplo n.º 5
0
Arquivo: lpt.c Projeto: ryo/netbsd-src
/*
 * lptwrite --copy a line from user space to a local buffer, then call
 * putc to get the chars moved to the output queue.
 *
 * Flagging of interrupted write added.
 */
int
lptwrite(dev_t dev_id, struct uio * uio, int ioflag)
{
	int error=0;
	size_t n, cnt;
	device_t dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
	struct lpt_softc * sc = device_private(dev);

	/* Check state and flags */
	if(!(sc->sc_state & HAVEBUS)) {
		LPT_DPRINTF(("%s(%s): attempt to write using device which does "
			"not own the bus(%s).\n", __func__, device_xname(dev),
			device_xname(device_parent(dev))));
		return EINVAL;
	}

	LPT_VPRINTF(("%s(%s): writing %zu bytes\n", __func__,
	    device_xname(dev), uio->uio_resid));

	/* Write the data */
	sc->sc_state &= ~INTERRUPTED;
	while (uio->uio_resid) {
		n = MIN(BUFSIZE, uio->uio_resid);
		error = uiomove(sc->sc_inbuf, n, uio);
		if (error)
			break;

		error = ppbus_write(device_parent(dev), sc->sc_inbuf, n, ioflag,
			&cnt);
		if (error) {
			if (error != EWOULDBLOCK)
				sc->sc_state |= INTERRUPTED;
			break;
		}
	}

	LPT_VPRINTF(("%s(%s): transfer finished, error %d.\n", __func__,
	    device_xname(dev), error));

	return error;
}
Exemplo n.º 6
0
Arquivo: olpt.c Projeto: MarginC/kame
static	int
lptioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct thread *td)
{
	int	error = 0;
        struct	lpt_softc *sc;
        u_int	unit = LPTUNIT(minor(dev));
	u_char	old_sc_irq;	/* old printer IRQ status */

        sc = devclass_get_softc(olpt_devclass, unit);

	switch (cmd) {
	case LPT_IRQ :
		if(sc->sc_irq & LP_HAS_IRQ) {
			/*
			 * NOTE:
			 * If the IRQ status is changed,
			 * this will only be visible on the
			 * next open.
			 *
			 * If interrupt status changes,
			 * this gets syslog'd.
			 */
			old_sc_irq = sc->sc_irq;
			if(*(int*)data == 0)
				sc->sc_irq &= (~LP_ENABLE_IRQ);
			else
				sc->sc_irq |= LP_ENABLE_IRQ;
			if (old_sc_irq != sc->sc_irq )
				log(LOG_NOTICE, "lpt%c switched to %s mode\n",
					(char)unit+'0',
					(sc->sc_irq & LP_ENABLE_IRQ)?
					"interrupt-driven":"polled");
		} else /* polled port */
			error = EOPNOTSUPP;
		break;
	default:
		error = ENODEV;
	}

	return(error);
}
Exemplo n.º 7
0
/*
 * Close the device, and free the local line buffer.
 */
int
lptclose(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct lpt_softc *sc;

	sc = device_lookup_private(&lpt_cd, LPTUNIT(dev));

	if (sc->sc_count)
		(void) pushbytes(sc);

	if ((sc->sc_flags & LPT_NOINTR) == 0)
		callout_stop(&sc->sc_wakeup_ch);

	(sc->sc_funcs->lf_close) (sc);

	sc->sc_state = 0;
	brelse(sc->sc_inbuf, 0);

	LPRINTF((sc->sc_dev, "%s: closed\n"));
	return (0);
}
Exemplo n.º 8
0
Arquivo: olpt.c Projeto: MarginC/kame
static	int
lptclose(dev_t dev, int flags, int fmt, struct thread *td)
{
	struct lpt_softc *sc;
#ifndef PC98
	int port;
#endif

	sc = devclass_get_softc(olpt_devclass, LPTUNIT(minor(dev)));
	if(sc->sc_flags & LP_BYPASS)
		goto end_close;

#ifndef PC98
	port = sc->sc_port;
#endif
	sc->sc_state &= ~OPEN;

#ifndef PC98
	/* if the last write was interrupted, don't complete it */
	if((!(sc->sc_state  & INTERRUPTED)) && (sc->sc_irq & LP_USE_IRQ))
		while ((inb(port+lpt_status) & (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR)) !=
			(LPS_SEL|LPS_NBSY|LPS_NERR) || sc->sc_xfercnt)
			/* wait 1/4 second, give up if we get a signal */
			if (tsleep ((caddr_t)sc, LPPRI|PCATCH,
				"lpclose", hz) != EWOULDBLOCK)
				break;

	outb(sc->sc_port+lpt_control, LPC_NINIT);
#endif
	brelse(sc->sc_inbuf);

end_close:
	sc->sc_state = 0;
	sc->sc_xfercnt = 0;
	lprintf(("closed.\n"));
	return(0);
}
Exemplo n.º 9
0
Arquivo: lpt.c Projeto: ryo/netbsd-src
/* Printer ioctl */
int
lptioctl(dev_t dev_id, u_long cmd, void *data, int flags, struct lwp *l)
{
	device_t dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
	struct lpt_softc *sc = device_private(dev);
	int val, fl;
	int error=0;

	if(!(sc->sc_state & HAVEBUS)) {
		LPT_DPRINTF(("%s(%s): attempt to perform ioctl on device which "
			"does not own the bus(%s).\n", __func__, device_xname(dev),
			device_xname(device_parent(dev))));
		return EBUSY;
	}

	switch (cmd) {
	case LPTGMODE:
        	switch (ppbus_get_mode(device_parent(dev))) {
		case PPBUS_COMPATIBLE:
			val = mode_standard;
			break;
		case PPBUS_NIBBLE:
			val = mode_nibble;
			break;
		case PPBUS_PS2:
			val = mode_ps2;
			break;
		case PPBUS_FAST:
			val = mode_fast;
			break;
		case PPBUS_EPP:
			val = mode_epp;
			break;
		case PPBUS_ECP:
			val = mode_ecp;
			break;
		default:
			error = EINVAL;
			val = mode_unknown;
			break;
		}
		*(int *)data = val;
		break;

	case LPTSMODE:
        	switch (*(int *)data) {
		case mode_standard:
			val = PPBUS_COMPATIBLE;
			break;
		case mode_nibble:
			val = PPBUS_NIBBLE;
			break;
		case mode_ps2:
			val = PPBUS_PS2;
			break;
		case mode_fast:
			val = PPBUS_FAST;
			break;
		case mode_epp:
			val = PPBUS_EPP;
			break;
		case mode_ecp:
			val = PPBUS_ECP;
			break;
		default:
			error = EINVAL;
			val = mode_unknown;
			break;
		}

		if (!error)
			error = ppbus_set_mode(device_parent(dev), val, 0);

		break;

	case LPTGFLAGS:
		fl = 0;

		/* DMA */
		error = ppbus_read_ivar(device_parent(dev), PPBUS_IVAR_DMA, &val);
		if (error)
			break;
		if (val)
			fl |= LPT_DMA;

		/* IEEE mode negotiation */
		error = ppbus_read_ivar(device_parent(dev), PPBUS_IVAR_IEEE, &val);
		if (error)
			break;
		if (val)
			fl |= LPT_IEEE;

		/* interrupts */
		error = ppbus_read_ivar(device_parent(dev), PPBUS_IVAR_INTR, &val);
		if (error)
			break;
		if (val)
			fl |= LPT_INTR;

		/* lpt-only flags */
		fl |= sc->sc_flags;

		*(int *)data = fl;
		break;

	case LPTSFLAGS:
		fl = *(int *)data;

		/* DMA */
		val = (fl & LPT_DMA);
		error = ppbus_write_ivar(device_parent(dev), PPBUS_IVAR_DMA, &val);
		if (error)
			break;

		/* IEEE mode negotiation */
		val = (fl & LPT_IEEE);
		error = ppbus_write_ivar(device_parent(dev), PPBUS_IVAR_IEEE, &val);
		if (error)
			break;

		/* interrupts */
		val = (fl & LPT_INTR);
		error = ppbus_write_ivar(device_parent(dev), PPBUS_IVAR_INTR, &val);
		if (error)
			break;

		/* lpt-only flags */
		sc->sc_flags = fl & (LPT_PRIME|LPT_AUTOLF);

		break;

	default:
		error = EINVAL;
		break;
	}

	return error;
}
Exemplo n.º 10
0
Arquivo: lpt.c Projeto: ryo/netbsd-src
/*
 * lptopen -- reset the printer, then wait until it's selected and not busy.
 */
int
lptopen(dev_t dev_id, int flags, int fmt, struct lwp *l)
{
	int trys, err;
	u_int8_t status;
	device_t dev;
	struct lpt_softc * lpt;
	struct ppbus_device_softc * ppbus_dev;
	device_t ppbus;

	dev = device_lookup(&lpt_cd, LPTUNIT(dev_id));
	if(!dev) {
		LPT_DPRINTF(("%s(): device not configured.\n", __func__));
		return ENXIO;
	}

	lpt = device_private(dev);

	ppbus = device_parent(dev);
	ppbus_dev = &(lpt->ppbus_dev);

	/* Request the ppbus */
	err = lpt_request_ppbus(lpt, PPBUS_WAIT|PPBUS_INTR);
	if(err) {
		LPT_DPRINTF(("%s(%s): error (%d) while requesting bus.\n",
			__func__, device_xname(dev), err));
		return (err);
	}

	/* Update bus mode */
	ppbus_dev->ctx.mode = ppbus_get_mode(ppbus);

	/* init printer */
	if ((lpt->sc_flags & LPT_PRIME) && !LPTCTL(dev_id)) {
		LPT_VPRINTF(("%s(%s): initializing printer.\n", __func__,
			device_xname(dev)));
		lpt->sc_state |= LPTINIT;
		ppbus_wctr(ppbus, LPC_SEL | LPC_NINIT);

		/* wait till ready (printer running diagnostics) */
		for(trys = 0, status = ppbus_rstr(ppbus); (status & RDY_MASK)
			!= LP_READY; trys += LPT_STEP, status =
			ppbus_rstr(ppbus)) {

			/* Time up waiting for the printer */
			if(trys >= LPT_TIMEOUT)
				break;
			/* wait LPT_STEP ticks, give up if we get a signal */
			else {
				err = tsleep((void *)lpt, LPPRI|PCATCH,
					"lptinit", LPT_STEP);
				if((err) && (err != EWOULDBLOCK)) {
					lpt->sc_state &= ~LPTINIT;
					LPT_DPRINTF(("%s(%s): interrupted "
					"during initialization.\n", __func__,
					device_xname(dev)));
					lpt_release_ppbus(lpt, PPBUS_WAIT);
					return (err);
				}
			}
		}

		lpt->sc_state &= ~LPTINIT;
		if(trys >= LPT_TIMEOUT) {
			LPT_DPRINTF(("%s(%s): timed out while initializing "
				"printer. [status %x]\n", __func__,
				device_xname(dev), status));
			err = lpt_logstatus(dev, status);
			lpt_release_ppbus(lpt, PPBUS_WAIT);
			return (err);
		}
		else {
			LPT_VPRINTF(("%s(%s): printer ready.\n", __func__,
				device_xname(dev)));
		}
	}

	/* Set autolinefeed if requested */
	if (lpt->sc_flags & LPT_AUTOLF)
		ppbus_wctr(ppbus, LPC_AUTOL);
	else
		ppbus_wctr(ppbus, 0);

	/* ready now */
	lpt->sc_state |= OPEN;

	return 0;
}
Exemplo n.º 11
0
/*
 * Reset the printer, then wait until it's selected and not busy.
 */
int
lptopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	u_char flags;
	struct lpt_softc *sc;
	int error;
	int spin;

	flags = LPTFLAGS(dev);

	sc = device_lookup_private(&lpt_cd, LPTUNIT(dev));
	if (!sc)
		return (ENXIO);

#ifdef DIAGNOSTIC
	if (sc->sc_state)
		aprint_verbose_dev(sc->sc_dev, "stat=0x%x not zero\n",
		    sc->sc_state);
#endif

	if (sc->sc_state)
		return (EBUSY);

	sc->sc_state = LPT_INIT;
	sc->sc_flags = flags;
	LPRINTF((sc->sc_dev, "open: flags=0x%x\n", flags));

	if ((flags & LPT_NOPRIME) == 0) {
		/* assert Input Prime for 100 usec to start up printer */
		(sc->sc_funcs->lf_iprime) (sc);
	}

	/* select fast or slow strobe depending on minor device number */
	if (flags & LPT_FAST_STROBE)
		(sc->sc_funcs->lf_speed) (sc, LPT_STROBE_FAST);
	else
		(sc->sc_funcs->lf_speed) (sc, LPT_STROBE_SLOW);

	/* wait till ready (printer running diagnostics) */
	for (spin = 0; (sc->sc_funcs->lf_notrdy) (sc, 1); spin += STEP) {
		if (spin >= TIMEOUT) {
			sc->sc_state = 0;
			return (EBUSY);
		}
		/* wait 1/4 second, give up if we get a signal */
		error = tsleep((void *) sc, LPTPRI | PCATCH, "lptopen", STEP);
		if (error != EWOULDBLOCK) {
			sc->sc_state = 0;
			return (error);
		}
	}

	sc->sc_inbuf = geteblk(LPT_BSIZE);
	sc->sc_count = 0;
	sc->sc_state = LPT_OPEN;

	if ((sc->sc_flags & LPT_NOINTR) == 0)
		lpt_wakeup(sc);

	(sc->sc_funcs->lf_open) (sc, sc->sc_flags & LPT_NOINTR);

	LPRINTF((sc->sc_dev, "opened\n"));
	return (0);
}
Exemplo n.º 12
0
/*
 * Reset the printer, then wait until it's selected and not busy.
 */
int
lptopen(dev_t dev, int flag, int mode, struct proc *p)
{
	int unit = LPTUNIT(dev);
	u_int8_t flags = LPTFLAGS(dev);
	struct lpt_softc *sc;
	u_int8_t control;
	int error;
	int spin;

	if (unit >= lpt_cd.cd_ndevs)
		return ENXIO;
	sc = lpt_cd.cd_devs[unit];
	if (!sc)
		return ENXIO;

	sc->sc_flags = (sc->sc_flags & LPT_POLLED) | flags;
	if ((sc->sc_flags & (LPT_POLLED|LPT_NOINTR)) == LPT_POLLED)
		return ENXIO;

#ifdef DIAGNOSTIC
	if (sc->sc_state)
		printf("%s: stat=0x%x not zero\n", sc->sc_dev.dv_xname,
		    sc->sc_state);
#endif

	if (sc->sc_state)
		return EBUSY;

	sc->sc_state = LPT_INIT;
	LPRINTF(("%s: open: flags=0x%x\n", sc->sc_dev.dv_xname, flags));

	if ((flags & LPT_NOPRIME) == 0) {
		/* assert INIT for 100 usec to start up printer */
		bus_space_write_1(sc->sc_iot, sc->sc_ioh, lpt_control, LPC_SELECT);
		delay(100);
	}

	control = LPC_SELECT | LPC_NINIT;
	bus_space_write_1(sc->sc_iot, sc->sc_ioh, lpt_control, control);

	/* wait till ready (printer running diagnostics) */
	for (spin = 0; NOT_READY_ERR(); spin += STEP) {
		if (spin >= TIMEOUT) {
			sc->sc_state = 0;
			return EBUSY;
		}

		/* wait 1/4 second, give up if we get a signal */
		error = tsleep((caddr_t)sc, LPTPRI | PCATCH, "lptopen", STEP);
		if (sc->sc_state == 0)
			return (EIO);
		if (error != EWOULDBLOCK) {
			sc->sc_state = 0;
			return error;
		}
	}

	if ((flags & LPT_NOINTR) == 0)
		control |= LPC_IENABLE;
	if (flags & LPT_AUTOLF)
		control |= LPC_AUTOLF;
	sc->sc_control = control;
	bus_space_write_1(sc->sc_iot, sc->sc_ioh, lpt_control, control);

	sc->sc_inbuf = geteblk(LPT_BSIZE);
	sc->sc_count = 0;
	sc->sc_state = LPT_OPEN;

	if ((sc->sc_flags & LPT_NOINTR) == 0)
		lptwakeup(sc);

	LPRINTF(("%s: opened\n", sc->sc_dev.dv_xname));
	return 0;
}
Exemplo n.º 13
0
/*
 * Reset the printer, then wait until it's selected and not busy.
 */
int
lptopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	u_char flags = LPTFLAGS(dev);
	struct lpt_softc *sc;
	bus_space_tag_t iot;
	bus_space_handle_t ioh;
	u_char control;
	int error;
	int spin;

	sc = device_lookup_private(&lpt_cd, LPTUNIT(dev));
	if (!sc || !sc->sc_dev_ok)
		return ENXIO;

#if 0	/* XXX what to do? */
	if (sc->sc_irq == IRQUNK && (flags & LPT_NOINTR) == 0)
		return ENXIO;
#endif

#ifdef DIAGNOSTIC
	if (sc->sc_state)
		aprint_verbose_dev(sc->sc_dev, "stat=0x%x not zero\n",
		    sc->sc_state);
#endif

	if (sc->sc_state)
		return EBUSY;

	sc->sc_state = LPT_INIT;
	sc->sc_flags = flags;
	LPRINTF(("%s: open: flags=0x%x\n", device_xname(sc->sc_dev),
	    (unsigned)flags));
	iot = sc->sc_iot;
	ioh = sc->sc_ioh;

	if ((flags & LPT_NOPRIME) == 0) {
		/* assert INIT for 100 usec to start up printer */
		bus_space_write_1(iot, ioh, lpt_control, LPC_SELECT);
		delay(100);
	}

	control = LPC_SELECT | LPC_NINIT;
	bus_space_write_1(iot, ioh, lpt_control, control);

	/* wait till ready (printer running diagnostics) */
	for (spin = 0; NOT_READY_ERR(); spin += STEP) {
		if (spin >= TIMEOUT) {
			sc->sc_state = 0;
			return EBUSY;
		}

		/* wait 1/4 second, give up if we get a signal */
		error = tsleep((void *)sc, LPTPRI | PCATCH, "lptopen", STEP);
		if (error != EWOULDBLOCK) {
			sc->sc_state = 0;
			return error;
		}
	}

	if ((flags & LPT_NOINTR) == 0)
		control |= LPC_IENABLE;
	if (flags & LPT_AUTOLF)
		control |= LPC_AUTOLF;
	sc->sc_control = control;
	bus_space_write_1(iot, ioh, lpt_control, control);

	sc->sc_inbuf = malloc(LPT_BSIZE, M_DEVBUF, M_WAITOK);
	sc->sc_count = 0;
	sc->sc_state = LPT_OPEN;

	if ((sc->sc_flags & LPT_NOINTR) == 0)
		lptwakeup(sc);

	LPRINTF(("%s: opened\n", device_xname(sc->sc_dev)));
	return 0;
}
Exemplo n.º 14
0
Arquivo: olpt.c Projeto: MarginC/kame
static	int
lptopen (dev_t dev, int flags, int fmt, struct thread *td)
{
	struct lpt_softc *sc;
	int s;
#ifdef PC98
	int port;
#else
	int trys, port;
#endif

	sc = devclass_get_softc(olpt_devclass, LPTUNIT(minor(dev)));
	if (sc->sc_port == 0)
		return (ENXIO);

	if (sc->sc_state) {
		lprintf(("lp: still open %x\n", sc->sc_state));
		return(EBUSY);
	} else
		sc->sc_state |= INIT;

	sc->sc_flags = LPTFLAGS(minor(dev));

	/* Check for open with BYPASS flag set. */
	if (sc->sc_flags & LP_BYPASS) {
		sc->sc_state = OPEN;
		return(0);
	}

	s = spltty();
	lprintf(("lp flags 0x%x\n", sc->sc_flags));
	port = sc->sc_port;

	/* set IRQ status according to ENABLE_IRQ flag */
	if (sc->sc_irq & LP_ENABLE_IRQ)
		sc->sc_irq |= LP_USE_IRQ;
	else
		sc->sc_irq &= ~LP_USE_IRQ;

	/* init printer */
#ifndef PC98
	if ((sc->sc_flags & LP_NO_PRIME) == 0) {
		if((sc->sc_flags & LP_PRIMEOPEN) || sc->sc_primed == 0) {
			outb(port+lpt_control, 0);
			sc->sc_primed++;
			DELAY(500);
		}
	}

	outb (port+lpt_control, LPC_SEL|LPC_NINIT);

	/* wait till ready (printer running diagnostics) */
	trys = 0;
	do {
		/* ran out of waiting for the printer */
		if (trys++ >= LPINITRDY*4) {
			splx(s);
			sc->sc_state = 0;
			lprintf(("status %x\n", inb(port+lpt_status)));
			return (EBUSY);
		}

		/* wait 1/4 second, give up if we get a signal */
		if (tsleep ((caddr_t)sc, LPPRI|PCATCH, "lptinit", hz/4) !=
		    EWOULDBLOCK) {
			sc->sc_state = 0;
			splx(s);
			return (EBUSY);
		}

		/* is printer online and ready for output */
	} while ((inb(port+lpt_status) & (LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR)) !=
		 (LPS_SEL|LPS_NBSY|LPS_NERR));

	sc->sc_control = LPC_SEL|LPC_NINIT;
	if (sc->sc_flags & LP_AUTOLF)
		sc->sc_control |= LPC_AUTOL;

	/* enable interrupt if interrupt-driven */
	if (sc->sc_irq & LP_USE_IRQ)
		sc->sc_control |= LPC_ENA;

	outb(port+lpt_control, sc->sc_control);
#endif

	sc->sc_state = OPEN;
	sc->sc_inbuf = geteblk(BUFSIZE);
	sc->sc_xfercnt = 0;
	splx(s);

	/* only use timeout if using interrupt */
	lprintf(("irq %x\n", sc->sc_irq));
	if (sc->sc_irq & LP_USE_IRQ) {
		sc->sc_state |= TOUT;
		timeout (lptout, (caddr_t)sc,
			 (sc->sc_backoff = hz/LPTOUTINITIAL));
	}

	lprintf(("opened.\n"));
	return(0);
}