/*
* Copyright (c) 1996 Leo Weppelman
* Copyright (c) 1993, 1994 Charles M. Hannum.
* Copyright (c) 1990 William F. Jolitz, TeleMuse
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This software is a component of "386BSD" developed by
* William F. Jolitz, TeleMuse.
* 4. Neither the name of the developer nor the name "386BSD"
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Device Driver originally written for AT parallel printer port. Now
* drives the printer port on the YM2149.
*
* THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ
* AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS
* SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
* THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
* NOT MAKE USE OF THIS WORK.
*
* FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
* BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN
* REFERENCES SUCH AS THE "PORTING UNIX TO THE 386" SERIES
* (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING
* JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND
* LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE
* ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS
* OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
*/
/*
* Reset the printer, then wait until it's selected and not busy.
*/
static int
lpopen(dev_t dev, int flag, int mode, struct lwp *l)
{
u_char flags = LPTFLAGS(dev);
struct lpt_softc *sc;
int error;
int spin;
int sps;
sc = device_lookup_private(&lp_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
/* wait till ready (printer running diagnostics) */
for (spin = 0; NOT_READY(); spin += STEP) {
if (spin >= TIMEOUT) {
sc->sc_state = 0;
return EBUSY;
}
/* wait 1/4 second, give up if we get a signal */
if ((error = tsleep((void *)sc, LPTPRI | PCATCH, "lptopen",
STEP)) != EWOULDBLOCK) {
sc->sc_state = 0;
return error;
}
}
/*
* Close the device, and free the local line buffer.
*/
static int
lpclose(dev_t dev, int flag, int mode, struct lwp *l)
{
struct lpt_softc *sc = device_lookup_private(&lp_cd, LPTUNIT(dev));
int sps;
if (sc->sc_count)
(void) pushbytes(sc);
if ((sc->sc_flags & LPT_NOINTR) == 0) {
callout_stop(&sc->sc_wakeup_ch);
/* adapt busy-wait algorithm */
if (spin*2 + 16 < sc->sc_spinmax)
sc->sc_spinmax--;
}
} else {
while (sc->sc_count > 0) {
/* if the printer is ready for a char, give it one */
if ((sc->sc_state & LPT_OBUSY) == 0) {
lprintf(sc->sc_dev, "write %d\n",
sc->sc_count);
(void) lptpseudointr(sc);
}
if ((error = tsleep((void *)sc, LPTPRI | PCATCH,
"lptwrite2", 0)) != 0)
return error;
}
}
return 0;
}
/*
* Copy a line from user space to a local buffer, then call putc to get the
* chars moved to the output queue.
*/
static int
lpwrite(dev_t dev, struct uio *uio, int flags)
{
struct lpt_softc *sc = device_lookup_private(&lp_cd,LPTUNIT(dev));
size_t n;
int error = 0;
while ((n = uimin(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;
}
/*
* Handle printer interrupts which occur when the printer is ready to accept
* another char.
*/
int
lptintr(struct lpt_softc *sc)
{
/* is printer online and ready for output */
if (NOT_READY())
return 0;