Date: Thu, 4 Apr 1996 14:37:00 +0200 (MET DST) From: J Wunsch <j@ida.interface-business.de> To: freebsd-current@FreeBSD.org (FreeBSD-current users), bdodson@beowulf.utmb.edu (M. L. Dodson) Subject: Interrupt-mode lpt driver and HP printers Message-ID: <199604041237.OAA00366@ida.interface-business.de>
next in thread | raw e-mail | index | archive | help
Many people recently complained that they could not use the lpt driver in interrupt mode with newer HP DeskJet or LaserJet printers. The printer went awfully slow, while polled mode works fine. Now i've finally got my hands on a DeskJet 600 (customer's device :), and could reproduce the problem myself. I seem to have found a suitable workaround, and have just committed a fix for it. I would ask people to test it. If it works, i'll also commit this one to the -stable branch, since i believe it couldn't do any harm to configur- ations that used to work before either. (It could spin-loop a few milliseconds inside the interrupt routine for owners of HP printers, but that still seems to be less load than falling back to polled mode entirely.) The idea is to wait a moment inside the interrupt routine to see if the not-yet-ready condition will clear within reasonable time, and if it doesn't, to use an incrementally backoff timeout instead of the fixed 1/2 second timeout we've been using previously. --- lpt.c.orig Sun Dec 10 14:38:56 1995 +++ lpt.c Thu Apr 4 14:00:41 1996 @@ -149,7 +149,8 @@ #define LPINITRDY 4 /* wait up to 4 seconds for a ready */ -#define LPTOUTTIME 4 /* wait up to 4 seconds for a ready */ +#define LPTOUTINITIAL 10 /* initial timeout to wait for ready 1/10 s */ +#define LPTOUTMAX 1 /* maximal timeout 1 s */ #define LPPRI (PZERO+8) #define BUFSIZE 1024 @@ -221,6 +222,7 @@ #define LP_HAS_IRQ 0x01 /* we have an irq available */ #define LP_USE_IRQ 0x02 /* we are using our irq */ #define LP_ENABLE_IRQ 0x04 /* enable IRQ on open */ + u_char sc_backoff ; /* time to call lptout() again */ #ifdef INET struct ifnet sc_if; @@ -588,7 +590,8 @@ lprintf("irq %x\n", sc->sc_irq); if (sc->sc_irq & LP_USE_IRQ) { sc->sc_state |= TOUT; - timeout ((timeout_func_t)lptout, (caddr_t)sc, hz/2); + timeout ((timeout_func_t)lptout, (caddr_t)sc, + (sc->sc_backoff = hz/LPTOUTINITIAL)); } lprintf("opened.\n"); @@ -600,9 +603,12 @@ { int pl; lprintf ("T %x ", inb(sc->sc_port+lpt_status)); - if (sc->sc_state & OPEN) - timeout ((timeout_func_t)lptout, (caddr_t)sc, hz/2); - else + if (sc->sc_state & OPEN) { + sc->sc_backoff++; + if (sc->sc_backoff > hz/LPTOUTMAX) + sc->sc_backoff = sc->sc_backoff > hz/LPTOUTMAX; + timeout ((timeout_func_t)lptout, (caddr_t)sc, sc->sc_backoff); + } else sc->sc_state &= ~TOUT; if (sc->sc_state & ERROR) @@ -783,6 +789,7 @@ { struct lpt_softc *sc = lpt_sc + unit; int port = sc->sc_port, sts; + int i; #ifdef INET if(sc->sc_if.if_flags & IFF_UP) { @@ -791,9 +798,19 @@ } #endif /* INET */ - /* is printer online and ready for output */ - if (((sts=inb(port+lpt_status)) & RDY_MASK) == LP_READY) { + /* + * Is printer online and ready for output? + * + * Avoid falling back to lptout() too quickly. First spin-loop + * to see if the printer will become ready ``really soon now''. + */ + for (i = 0; + i < 100 && + ((sts=inb(port+lpt_status)) & RDY_MASK) != LP_READY; + i++) ; + if ((sts & RDY_MASK) == LP_READY) { sc->sc_state = (sc->sc_state | OBUSY) & ~ERROR; + sc->sc_backoff = hz/LPTOUTINITIAL; if (sc->sc_xfercnt) { /* send char */ @@ -820,6 +837,7 @@ if(((sts & (LPS_NERR | LPS_OUT) ) != LPS_NERR) && (sc->sc_state & OPEN)) sc->sc_state |= ERROR; + /* lptout() will jump in and try to restart. */ } lprintf("sts %x ", sts); } -- J"org Wunsch Unix support engineer joerg_wunsch@interface-business.de http://www.interface-business.de/~j
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199604041237.OAA00366>