diff options
author | nsouch <nsouch@FreeBSD.org> | 1999-01-10 12:04:56 +0000 |
---|---|---|
committer | nsouch <nsouch@FreeBSD.org> | 1999-01-10 12:04:56 +0000 |
commit | 88ae26fef69887203a871fca927f456a66c2cad4 (patch) | |
tree | 9e8c963e572bd5f141fcfc50127d8185cf16e87c /sys/dev/ppbus/ppb_1284.c | |
parent | 44bde66cb074ad8bc5cdb36460c6ef9f4628ea69 (diff) | |
download | FreeBSD-src-88ae26fef69887203a871fca927f456a66c2cad4.zip FreeBSD-src-88ae26fef69887203a871fca927f456a66c2cad4.tar.gz |
Major ppbus commit with:
+ ECP parallel port chipset FIFO detection
+ DMA+FIFO parallel I/O handled as chipset specific
+ nlpt updated in order to use the above enhanced parallel I/O.
Use 'lptcontrol -e' to use enhanced I/O
+ Various options documented in LINT
+ Full IEEE1284 NIBBLE and BYTE modes support. See ppbus(4) for
an overview of the IEEE1284 standard
+ Detection of PnP parallel devices at boot
+ Read capability added to nlpt driver to get IEEE1284 compliant
printer status with a simple 'cat /dev/lpt0'
+ IEEE1284 peripheral emulation added to BYTE mode. Two computers
may dialog according to IEEE1284 signaling method.
See PERIPH_1284 option and /sys/dev/ppbus/ppi.c
All this code is supposed to provide basic functions for IEEE1284 programming.
ppi.c and nlpt.c may act as examples.
Diffstat (limited to 'sys/dev/ppbus/ppb_1284.c')
-rw-r--r-- | sys/dev/ppbus/ppb_1284.c | 770 |
1 files changed, 705 insertions, 65 deletions
diff --git a/sys/dev/ppbus/ppb_1284.c b/sys/dev/ppbus/ppb_1284.c index 56524d1..96cd6f2 100644 --- a/sys/dev/ppbus/ppb_1284.c +++ b/sys/dev/ppbus/ppb_1284.c @@ -23,11 +23,15 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ppb_1284.c,v 1.5 1998/09/13 18:26:26 nsouch Exp $ + * $Id: ppb_1284.c,v 1.6 1998/09/13 20:44:55 nsouch Exp $ * */ -#include "opt_debug_1284.h" +/* + * General purpose routines for the IEEE1284-1994 Standard + */ + +#include "opt_ppb_1284.h" #include <sys/param.h> #include <sys/systm.h> @@ -42,24 +46,414 @@ * * Wait for the peripherial up to 40ms */ -int +static int do_1284_wait(struct ppb_device *dev, char mask, char status) { - int i; + return (ppb_poll_device(dev, 4, mask, status, PPB_NOINTR | PPB_POLL)); +} + +static int +do_peripheral_wait(struct ppb_device *dev, char mask, char status) +{ + return (ppb_poll_device(dev, 100, mask, status, PPB_NOINTR | PPB_POLL)); +} + +#define nibble2char(s) (((s & ~nACK) >> 3) | (~s & nBUSY) >> 4) + +/* + * ppb_1284_reset_error() + * + * Unconditionaly reset the error field + */ +static int +ppb_1284_reset_error(struct ppb_device *dev, int state) +{ + dev->ppb->error = PPB_NO_ERROR; + dev->ppb->state = state; + + return (0); +} + +/* + * ppb_1284_get_state() + * + * Get IEEE1284 state + */ +static int +ppb_1284_get_state(struct ppb_device *dev) +{ + return (dev->ppb->state); +} + +/* + * ppb_1284_set_state() + * + * Change IEEE1284 state if no error occured + */ +static int +ppb_1284_set_state(struct ppb_device *dev, int state) +{ + /* call ppb_1284_reset_error() if you absolutly want to change + * the state from PPB_ERROR to another */ + if ((dev->ppb->state != PPB_ERROR) && + (dev->ppb->error == PPB_NO_ERROR)) { + dev->ppb->state = state; + dev->ppb->error = PPB_NO_ERROR; + } + + return (0); +} + +static int +ppb_1284_set_error(struct ppb_device *dev, int error, int event) +{ + /* do not accumulate errors */ + if ((dev->ppb->error == PPB_NO_ERROR) && + (dev->ppb->state != PPB_ERROR)) { + dev->ppb->error = error; + dev->ppb->state = PPB_ERROR; + } + +#ifdef DEBUG_1284 + printf("ppb1284: error=%d status=0x%x event=%d\n", error, + ppb_rstr(dev) & 0xff, event); +#endif + + return (0); +} + +/* + * ppb_request_mode() + * + * Converts mode+options into ext. value + */ +static int +ppb_request_mode(int mode, int options) +{ + int request_mode = 0; + + if (options & PPB_EXTENSIBILITY_LINK) { + request_mode = EXT_LINK_1284_NORMAL; + + } else { + switch (mode) { + case PPB_NIBBLE: + request_mode = (options & PPB_REQUEST_ID) ? + NIBBLE_1284_REQUEST_ID : + NIBBLE_1284_NORMAL; + break; + case PPB_PS2: + request_mode = (options & PPB_REQUEST_ID) ? + BYTE_1284_REQUEST_ID : + BYTE_1284_NORMAL; + break; + case PPB_ECP: + if (options & PPB_USE_RLE) + request_mode = (options & PPB_REQUEST_ID) ? + ECP_1284_RLE_REQUEST_ID : + ECP_1284_RLE; + else + request_mode = (options & PPB_REQUEST_ID) ? + ECP_1284_REQUEST_ID : + ECP_1284_NORMAL; + break; + case PPB_EPP: + request_mode = EPP_1284_NORMAL; + break; + default: + panic("%s: unsupported mode %d\n", __FUNCTION__, mode); + } + } + + return (request_mode); +} + +/* + * ppb_peripheral_negociate() + * + * Negociate the peripheral side + */ +int +ppb_peripheral_negociate(struct ppb_device *dev, int mode, int options) +{ + int spin, request_mode, error = 0; char r; - /* try up to 5ms */ - for (i = 0; i < 20; i++) { - r = ppb_rstr(dev); - DELAY(25); - if ((r & mask) == status) - return (0); + ppb_set_mode(dev, PPB_COMPATIBLE); + ppb_1284_set_state(dev, PPB_PERIPHERAL_NEGOCIATION); + + /* compute ext. value */ + request_mode = ppb_request_mode(mode, options); + + /* wait host */ + spin = 10; + while (spin-- && (ppb_rstr(dev) & nBUSY)) + DELAY(1); + + /* check termination */ + if (!(ppb_rstr(dev) & SELECT) || !spin) { + error = ENODEV; + goto error; + } + + /* Event 4 - read ext. value */ + r = ppb_rdtr(dev); + + /* nibble mode is not supported */ + if ((r == (char)request_mode) || + (r == NIBBLE_1284_NORMAL)) { + + /* Event 5 - restore direction bit, no data avail */ + ppb_wctr(dev, (STROBE | nINIT) & ~(SELECTIN)); + DELAY(1); + + /* Event 6 */ + ppb_wctr(dev, (nINIT) & ~(SELECTIN | STROBE)); + + if (r == NIBBLE_1284_NORMAL) { +#ifdef DEBUG_1284 + printf("R"); +#endif + ppb_1284_set_error(dev, PPB_MODE_UNSUPPORTED, 4); + error = EINVAL; + goto error; + } else { + ppb_1284_set_state(dev, PPB_PERIPHERAL_IDLE); + switch (r) { + case BYTE_1284_NORMAL: + ppb_set_mode(dev, PPB_BYTE); + break; + default: + break; + } +#ifdef DEBUG_1284 + printf("A"); +#endif + /* negociation succeeds */ + } + } else { + /* Event 5 - mode not supported */ + ppb_wctr(dev, SELECTIN); + DELAY(1); + + /* Event 6 */ + ppb_wctr(dev, (SELECTIN) & ~(STROBE | nINIT)); + ppb_1284_set_error(dev, PPB_MODE_UNSUPPORTED, 4); + +#ifdef DEBUG_1284 + printf("r"); +#endif + error = EINVAL; + goto error; } - return (ppb_poll_device(dev, 4, mask, status, PPB_NOINTR)); + return (0); + +error: + ppb_peripheral_terminate(dev, PPB_WAIT); + return (error); } -#define nibble2char(s) (((s & ~nACK) >> 3) | (~s & nBUSY) >> 4) +/* + * ppb_peripheral_terminate() + * + * Terminate peripheral transfer side + * + * Always return 0 in compatible mode + */ +int +ppb_peripheral_terminate(struct ppb_device *dev, int how) +{ + int error = 0; + +#ifdef DEBUG_1284 + printf("t"); +#endif + + ppb_1284_set_state(dev, PPB_PERIPHERAL_TERMINATION); + + /* Event 22 - wait up to host response time (1s) */ + if ((error = do_peripheral_wait(dev, SELECT | nBUSY, 0))) { + ppb_1284_set_error(dev, PPB_TIMEOUT, 22); + goto error; + } + + /* Event 24 */ + ppb_wctr(dev, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN)); + + /* Event 25 - wait up to host response time (1s) */ + if ((error = do_peripheral_wait(dev, nBUSY, nBUSY))) { + ppb_1284_set_error(dev, PPB_TIMEOUT, 25); + goto error; + } + + /* Event 26 */ + ppb_wctr(dev, (SELECTIN | nINIT | STROBE) & ~(AUTOFEED)); + DELAY(1); + /* Event 27 */ + ppb_wctr(dev, (SELECTIN | nINIT) & ~(STROBE | AUTOFEED)); + + /* Event 28 - wait up to host response time (1s) */ + if ((error = do_peripheral_wait(dev, nBUSY, 0))) { + ppb_1284_set_error(dev, PPB_TIMEOUT, 28); + goto error; + } + +error: + ppb_set_mode(dev, PPB_COMPATIBLE); + ppb_1284_set_state(dev, PPB_FORWARD_IDLE); + + return (0); +} + +/* + * byte_peripheral_outbyte() + * + * Write 1 byte in BYTE mode + */ +static int +byte_peripheral_outbyte(struct ppb_device *dev, char *buffer, int last) +{ + int error = 0; + + /* Event 7 */ + if ((error = do_1284_wait(dev, nBUSY, nBUSY))) { + ppb_1284_set_error(dev, PPB_TIMEOUT, 7); + goto error; + } + + /* check termination */ + if (!(ppb_rstr(dev) & SELECT)) { + ppb_peripheral_terminate(dev, PPB_WAIT); + goto error; + } + + /* Event 15 - put byte on data lines */ +#ifdef DEBUG_1284 + printf("B"); +#endif + ppb_wdtr(dev, *buffer); + + /* Event 9 */ + ppb_wctr(dev, (AUTOFEED | STROBE) & ~(nINIT | SELECTIN)); + + /* Event 10 - wait data read */ + if ((error = do_peripheral_wait(dev, nBUSY, 0))) { + ppb_1284_set_error(dev, PPB_TIMEOUT, 16); + goto error; + } + + /* Event 11 */ + if (!last) { + ppb_wctr(dev, (AUTOFEED) & ~(nINIT | STROBE | SELECTIN)); + } else { + ppb_wctr(dev, (nINIT) & ~(STROBE | SELECTIN | AUTOFEED)); + } + +#if 0 + /* Event 16 - wait strobe */ + if ((error = do_peripheral_wait(dev, nACK | nBUSY, 0))) { + ppb_1284_set_error(dev, PPB_TIMEOUT, 16); + goto error; + } +#endif + + /* check termination */ + if (!(ppb_rstr(dev) & SELECT)) { + ppb_peripheral_terminate(dev, PPB_WAIT); + goto error; + } + +error: + return (error); +} + +/* + * byte_peripheral_write() + * + * Write n bytes in BYTE mode + */ +int +byte_peripheral_write(struct ppb_device *dev, char *buffer, int len, int *sent) +{ + int error = 0, i; + char r; + + ppb_1284_set_state(dev, PPB_PERIPHERAL_TRANSFER); + + /* wait forever, the remote host is master and should initiate + * termination + */ + for (i=0; i<len; i++) { + /* force remote nFAULT low to release the remote waiting + * process, if any + */ + r = ppb_rctr(dev); + ppb_wctr(dev, r & ~nINIT); + +#ifdef DEBUG_1284 + printf("y"); +#endif + /* Event 7 */ + error = ppb_poll_device(dev, PPB_FOREVER, nBUSY, nBUSY, + PPB_INTR); + + if (error && error != EWOULDBLOCK) + goto error; + +#ifdef DEBUG_1284 + printf("b"); +#endif + if ((error = byte_peripheral_outbyte(dev, buffer+i, (i == len-1)))) + goto error; + } +error: + if (!error) + ppb_1284_set_state(dev, PPB_PERIPHERAL_IDLE); + + *sent = i; + return (error); +} + +/* + * byte_1284_inbyte() + * + * Read 1 byte in BYTE mode + */ +int +byte_1284_inbyte(struct ppb_device *dev, char *buffer) +{ + int error = 0; + + /* Event 7 - ready to take data (nAUTO low) */ + ppb_wctr(dev, (PCD | nINIT | AUTOFEED) & ~(STROBE | SELECTIN)); + + /* Event 9 - peripheral set nAck low */ + if ((error = do_1284_wait(dev, nACK, 0))) { + ppb_1284_set_error(dev, PPB_TIMEOUT, 9); + goto error; + } + + /* read the byte */ + *buffer = ppb_rdtr(dev); + + /* Event 10 - data received, can't accept more */ + ppb_wctr(dev, (nINIT) & ~(AUTOFEED | STROBE | SELECTIN)); + + /* Event 11 - peripheral ack */ + if ((error = do_1284_wait(dev, nACK, nACK))) { + ppb_1284_set_error(dev, PPB_TIMEOUT, 11); + goto error; + } + + /* Event 16 - strobe */ + ppb_wctr(dev, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN)); + DELAY(3); + ppb_wctr(dev, (nINIT) & ~(AUTOFEED | STROBE | SELECTIN)); + +error: + return (error); +} /* * nibble_1284_inbyte() @@ -73,126 +467,372 @@ nibble_1284_inbyte(struct ppb_device *dev, char *buffer) int i, error; for (i = 0; i < 2; i++) { - /* ready to take data (nAUTO low) */ - ppb_wctr(dev, AUTOFEED & ~(STROBE | SELECTIN)); - if ((error = do_1284_wait(dev, nACK, 0))) - return (error); + /* Event 7 - ready to take data (nAUTO low) */ + ppb_wctr(dev, (nINIT | AUTOFEED) & ~(STROBE | SELECTIN)); + + /* Event 8 - peripheral writes the first nibble */ + + /* Event 9 - peripheral set nAck low */ + if ((error = do_1284_wait(dev, nACK, 0))) { + ppb_1284_set_error(dev, PPB_TIMEOUT, 9); + goto error; + } /* read nibble */ nibble[i] = ppb_rstr(dev); - /* ack, not ready for another nibble */ - ppb_wctr(dev, 0 & ~(AUTOFEED | STROBE | SELECTIN)); + /* Event 10 - ack, nibble received */ + ppb_wctr(dev, nINIT & ~(AUTOFEED | STROBE | SELECTIN)); - /* wait ack from peripherial */ - if ((error = do_1284_wait(dev, nACK, nACK))) - return (error); + /* Event 11 - wait ack from peripherial */ + if ((error = do_1284_wait(dev, nACK, nACK))) { + ppb_1284_set_error(dev, PPB_TIMEOUT, 11); + goto error; + } } *buffer = ((nibble2char(nibble[1]) << 4) & 0xf0) | (nibble2char(nibble[0]) & 0x0f); - return (0); +error: + return (error); +} + +/* + * spp_1284_read() + * + * Read in IEEE1284 NIBBLE/BYTE mode + */ +int +spp_1284_read(struct ppb_device *dev, int mode, char *buffer, int max, int *read) +{ + int error = 0, len = 0; + int terminate_after_transfer = 1; + int state; + + *read = len = 0; + + state = ppb_1284_get_state(dev); + + switch (state) { + case PPB_FORWARD_IDLE: + if ((error = ppb_1284_negociate(dev, mode, 0))) + return (error); + break; + + case PPB_REVERSE_IDLE: + terminate_after_transfer = 0; + break; + + default: + ppb_1284_terminate(dev); + if ((error = ppb_1284_negociate(dev, mode, 0))) + return (error); + break; + } + + while ((len < max) && !(ppb_rstr(dev) & (nFAULT))) { + + ppb_1284_set_state(dev, PPB_REVERSE_TRANSFER); + +#ifdef DEBUG_1284 + printf("B"); +#endif + + switch (mode) { + case PPB_NIBBLE: + /* read a byte, error means no more data */ + if (nibble_1284_inbyte(dev, buffer+len)) + goto end_while; + break; + case PPB_BYTE: + if (byte_1284_inbyte(dev, buffer+len)) + goto end_while; + break; + default: + error = EINVAL; + goto end_while; + } + len ++; + } +end_while: + + if (!error) + ppb_1284_set_state(dev, PPB_REVERSE_IDLE); + + *read = len; + + if (terminate_after_transfer || error) + ppb_1284_terminate(dev); + + return (error); } /* - * nibble_1284_sync() + * ppb_1284_read_id() + * */ -void -nibble_1284_sync(struct ppb_device *dev) +int +ppb_1284_read_id(struct ppb_device *dev, int mode, char *buffer, + int max, int *read) { - char ctr; + int error = 0; - ctr = ppb_rctr(dev); + /* fill the buffer with 0s */ + bzero(buffer, max); - ppb_wctr(dev, (ctr & ~AUTOFEED) | SELECTIN); - if (do_1284_wait(dev, nACK, 0)) - return; + switch (mode) { + case PPB_NIBBLE: + case PPB_ECP: + if ((error = ppb_1284_negociate(dev, PPB_NIBBLE, PPB_REQUEST_ID))) + return (error); + error = spp_1284_read(dev, PPB_NIBBLE, buffer, max, read); + break; + case PPB_BYTE: + if ((error = ppb_1284_negociate(dev, PPB_BYTE, PPB_REQUEST_ID))) + return (error); + error = spp_1284_read(dev, PPB_BYTE, buffer, max, read); + break; + default: + panic("%s: unsupported mode %d\n", __FUNCTION__, mode); + } - ppb_wctr(dev, ctr | AUTOFEED); - do_1284_wait(dev, nACK, nACK); + ppb_1284_terminate(dev); + return (error); +} - ppb_wctr(dev, (ctr & ~AUTOFEED) | SELECTIN); +/* + * ppb_1284_read() + * + * IEEE1284 read + */ +int +ppb_1284_read(struct ppb_device *dev, int mode, char *buffer, + int max, int *read) +{ + int error = 0; - return; + switch (mode) { + case PPB_NIBBLE: + case PPB_BYTE: + error = spp_1284_read(dev, mode, buffer, max, read); + break; + default: + return (EINVAL); + } + + return (error); } /* * ppb_1284_negociate() * + * IEEE1284 negociation phase + * * Normal nibble mode or request device id mode (see ppb_1284.h) + * + * After negociation, nFAULT is low if data is available */ int -ppb_1284_negociate(struct ppb_device *dev, int mode) +ppb_1284_negociate(struct ppb_device *dev, int mode, int options) { int error; - int phase = 0; + int request_mode; + +#ifdef DEBUG_1284 + printf("n"); +#endif + + if (ppb_1284_get_state(dev) >= PPB_PERIPHERAL_NEGOCIATION) + ppb_peripheral_terminate(dev, PPB_WAIT); + if (ppb_1284_get_state(dev) != PPB_FORWARD_IDLE) + ppb_1284_terminate(dev); + +#ifdef DEBUG_1284 + printf("%d", mode); +#endif + + /* ensure the host is in compatible mode */ + ppb_set_mode(dev, PPB_COMPATIBLE); + + /* reset error to catch the actual negociation error */ + ppb_1284_reset_error(dev, PPB_FORWARD_IDLE); + + /* calculate ext. value */ + request_mode = ppb_request_mode(mode, options); + + /* default state */ ppb_wctr(dev, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED)); DELAY(1); - ppb_wdtr(dev, mode); + /* enter negociation phase */ + ppb_1284_set_state(dev, PPB_NEGOCIATION); + + /* Event 0 - put the exten. value on the data lines */ + ppb_wdtr(dev, request_mode); + +#ifdef PERIPH_1284 + /* request remote host attention */ + ppb_wctr(dev, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN)); + DELAY(1); + ppb_wctr(dev, (nINIT) & ~(STROBE | AUTOFEED | SELECTIN)); +#else DELAY(1); +#endif /* !PERIPH_1284 */ + + /* Event 1 - enter IEEE1284 mode */ ppb_wctr(dev, (nINIT | AUTOFEED) & ~(STROBE | SELECTIN)); - if ((error = do_1284_wait(dev, nACK | PERROR | SELECT | nFAULT, - PERROR | SELECT | nFAULT))) +#ifdef PERIPH_1284 + /* ignore the PError line, wait a bit more, remote host's + * interrupts don't respond fast enough */ + if (ppb_poll_device(dev, 40, nACK | SELECT | nFAULT, + SELECT | nFAULT, PPB_NOINTR | PPB_POLL)) { + ppb_1284_set_error(dev, PPB_NOT_IEEE1284, 2); + error = ENODEV; + goto error; + } +#else + /* Event 2 - trying IEEE1284 dialog */ + if (do_1284_wait(dev, nACK | PERROR | SELECT | nFAULT, + PERROR | SELECT | nFAULT)) { + ppb_1284_set_error(dev, PPB_NOT_IEEE1284, 2); + error = ENODEV; goto error; + } +#endif /* !PERIPH_1284 */ - phase = 1; - + /* Event 3 - latch the ext. value to the peripheral */ ppb_wctr(dev, (nINIT | STROBE | AUTOFEED) & ~SELECTIN); - DELAY(5); + DELAY(1); + /* Event 4 - IEEE1284 device recognized */ ppb_wctr(dev, nINIT & ~(SELECTIN | AUTOFEED | STROBE)); -#if 0 /* not respected by most devices */ - if ((error = do_1284_wait(dev, nACK, nACK))) + /* Event 6 - waiting for status lines */ + if (do_1284_wait(dev, nACK, nACK)) { + ppb_1284_set_error(dev, PPB_TIMEOUT, 6); + error = EBUSY; goto error; + } - if (mode == 0) - if ((error = do_1284_wait(dev, SELECT, 0))) + /* Event 7 - quering result consider nACK not to misunderstand + * a remote computer terminate sequence */ + if (request_mode == NIBBLE_1284_NORMAL) { + if (do_1284_wait(dev, nACK | SELECT, nACK)) { + ppb_1284_set_error(dev, PPB_MODE_UNSUPPORTED, 7); + error = ENODEV; goto error; - else - if ((error = do_1284_wait(dev, SELECT, SELECT))) + } + } else { + if (do_1284_wait(dev, nACK | SELECT, SELECT | nACK)) { + ppb_1284_set_error(dev, PPB_MODE_UNSUPPORTED, 7); + error = ENODEV; goto error; -#endif + } + } + + switch (mode) { + case PPB_NIBBLE: + case PPB_PS2: + /* enter reverse idle phase */ + ppb_1284_set_state(dev, PPB_REVERSE_IDLE); + break; + case PPB_ECP: + /* negociation ok, now setup the communication */ + ppb_1284_set_state(dev, PPB_SETUP); + ppb_wctr(dev, (nINIT | AUTOFEED) & ~(SELECTIN | STROBE)); + +#ifdef PERIPH_1284 + /* ignore PError line */ + if (do_1284_wait(dev, nACK | SELECT | nBUSY, + nACK | SELECT | nBUSY)) { + ppb_1284_set_error(dev, PPB_TIMEOUT, 30); + error = ENODEV; + goto error; + } +#else + if (do_1284_wait(dev, nACK | SELECT | PERROR | nBUSY, + nACK | SELECT | PERROR | nBUSY)) { + ppb_1284_set_error(dev, PPB_TIMEOUT, 30); + error = ENODEV; + goto error; + } +#endif /* !PERIPH_1284 */ + + /* ok, the host enters the ForwardIdle state */ + ppb_1284_set_state(dev, PPB_ECP_FORWARD_IDLE); + break; + case PPB_EPP: + ppb_1284_set_state(dev, PPB_EPP_IDLE); + break; + + default: + panic("%s: unknown mode (%d)!", __FUNCTION__, mode); + } + ppb_set_mode(dev, mode); return (0); error: - if (bootverbose) - printf("%s: status=0x%x %d\n", __FUNCTION__, ppb_rstr(dev), phase); + ppb_1284_terminate(dev); return (error); } +/* + * ppb_1284_terminate() + * + * IEEE1284 termination phase, return code should ignored since the host + * is _always_ in compatible mode after ppb_1284_terminate() + */ int -ppb_1284_terminate(struct ppb_device *dev, int how) +ppb_1284_terminate(struct ppb_device *dev) { - int error; - switch (how) { - case VALID_STATE: +#ifdef DEBUG_1284 + printf("T"); +#endif - ppb_wctr(dev, SELECTIN & ~(STROBE | AUTOFEED)); + /* do not reset error here to keep the error that + * may occured before the ppb_1284_terminate() call */ + ppb_1284_set_state(dev, PPB_TERMINATION); - if ((error = do_1284_wait(dev, nACK | nBUSY | nFAULT, nFAULT))) - return (error); +#ifdef PERIPH_1284 + /* request remote host attention */ + ppb_wctr(dev, (nINIT | STROBE | SELECTIN) & ~(AUTOFEED)); + DELAY(1); +#endif /* PERIPH_1284 */ - ppb_wctr(dev, (SELECTIN | AUTOFEED) & ~STROBE); + /* Event 22 - set nSelectin low and nAutoFeed high */ + ppb_wctr(dev, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED)); - if ((error = do_1284_wait(dev, nACK, nACK))) - return (error); + /* Event 24 - waiting for peripheral, Xflag ignored */ + if (do_1284_wait(dev, nACK | nBUSY | nFAULT, nFAULT)) { + ppb_1284_set_error(dev, PPB_TIMEOUT, 24); + goto error; + } - ppb_wctr(dev, SELECTIN & ~(STROBE | AUTOFEED)); - break; + /* Event 25 - set nAutoFd low */ + ppb_wctr(dev, (nINIT | SELECTIN | AUTOFEED) & ~STROBE); - default: - return (EINVAL); + /* Event 26 - compatible mode status is set */ + + /* Event 27 - peripheral set nAck high */ + if (do_1284_wait(dev, nACK, nACK)) { + ppb_1284_set_error(dev, PPB_TIMEOUT, 27); } + /* Event 28 - end termination, return to idle phase */ + ppb_wctr(dev, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED)); + +error: + /* return to compatible mode */ + ppb_set_mode(dev, PPB_COMPATIBLE); + ppb_1284_set_state(dev, PPB_FORWARD_IDLE); + return (0); } |