1 /* $NetBSD: ppbus_1284.c,v 1.11 2008/04/15 15:02:29 cegger Exp $ */
4 * Copyright (c) 1997 Nicolas Souchu
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * FreeBSD: src/sys/dev/ppbus/ppb_1284.c,v 1.11 2000/01/14 08:03:14 nsouch Exp
32 /* General purpose routines for the IEEE1284-1994 Standard */
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: ppbus_1284.c,v 1.11 2008/04/15 15:02:29 cegger Exp $");
37 #include "opt_ppbus_1284.h"
39 #include <sys/param.h>
40 #include <sys/malloc.h>
41 #include <sys/systm.h>
43 #include <dev/ppbus/ppbus_conf.h>
44 #include <dev/ppbus/ppbus_base.h>
45 #include <dev/ppbus/ppbus_1284.h>
46 #include <dev/ppbus/ppbus_io.h>
47 #include <dev/ppbus/ppbus_var.h>
50 /* Wait for the peripherial up to 40ms */
52 do_1284_wait(struct ppbus_softc
* bus
, char mask
, char status
)
54 return (ppbus_poll_bus(bus
->sc_dev
, 4, mask
, status
,
55 PPBUS_NOINTR
| PPBUS_POLL
));
58 /* Wait for the host up to 1 second (peripheral side) */
60 do_peripheral_wait(struct ppbus_softc
* bus
, char mask
, char status
)
62 return (ppbus_poll_bus(bus
->sc_dev
, 100, mask
, status
,
63 PPBUS_NOINTR
| PPBUS_POLL
));
67 /* Unconditionaly reset the error field */
69 ppbus_1284_reset_error(struct ppbus_softc
* bus
, int state
)
71 bus
->sc_1284_error
= PPBUS_NO_ERROR
;
72 bus
->sc_1284_state
= state
;
77 /* Get IEEE1284 state */
79 ppbus_1284_get_state(device_t dev
)
81 struct ppbus_softc
*sc
= device_private(dev
);
83 return sc
->sc_1284_state
;
87 /* Set IEEE1284 state if no error occurred */
89 ppbus_1284_set_state(device_t dev
, int state
)
91 struct ppbus_softc
* bus
= device_private(dev
);
93 /* call ppbus_1284_reset_error() if you absolutly want to change
94 * the state from PPBUS_ERROR to another */
95 if ((bus
->sc_1284_state
!= PPBUS_ERROR
) &&
96 (bus
->sc_1284_error
== PPBUS_NO_ERROR
)) {
97 bus
->sc_1284_state
= state
;
98 bus
->sc_1284_error
= PPBUS_NO_ERROR
;
105 /* Set the IEEE1284 error field */
107 ppbus_1284_set_error(struct ppbus_softc
* bus
, int error
, int event
)
109 /* do not accumulate errors */
110 if ((bus
->sc_1284_error
== PPBUS_NO_ERROR
) &&
111 (bus
->sc_1284_state
!= PPBUS_ERROR
)) {
112 bus
->sc_1284_error
= error
;
113 bus
->sc_1284_state
= PPBUS_ERROR
;
117 printf("%s<1284>: error=%d status=0x%x event=%d\n",
118 device_xname(bus
->sc_dev
), error
, ppbus_rstr(bus
->sc_dev
),
127 /* Converts mode+options into ext. value */
129 ppbus_request_mode(int mode
, int options
)
131 int request_mode
= 0;
133 if (options
& PPBUS_EXTENSIBILITY_LINK
) {
134 request_mode
= EXT_LINK_1284_NORMAL
;
140 request_mode
= (options
& PPBUS_REQUEST_ID
) ?
141 NIBBLE_1284_REQUEST_ID
:
145 request_mode
= (options
& PPBUS_REQUEST_ID
) ?
146 BYTE_1284_REQUEST_ID
:
150 if (options
& PPBUS_USE_RLE
)
151 request_mode
= (options
& PPBUS_REQUEST_ID
) ?
152 ECP_1284_RLE_REQUEST_ID
:
155 request_mode
= (options
& PPBUS_REQUEST_ID
) ?
156 ECP_1284_REQUEST_ID
:
160 request_mode
= EPP_1284_NORMAL
;
163 panic("%s: unsupported mode %d\n", __func__
, mode
);
167 return (request_mode
);
171 /* Negotiate the peripheral side */
173 ppbus_peripheral_negotiate(device_t dev
, int mode
, int options
)
175 struct ppbus_softc
* bus
= device_private(dev
);
176 int spin
, request_mode
, error
= 0;
179 ppbus_1284_terminate(dev
);
180 ppbus_1284_set_state(dev
, PPBUS_PERIPHERAL_NEGOTIATION
);
182 /* compute ext. value */
183 request_mode
= ppbus_request_mode(mode
, options
);
187 while (spin
-- && (ppbus_rstr(dev
) & nBUSY
))
190 /* check termination */
191 if (!(ppbus_rstr(dev
) & SELECT
) || !spin
) {
196 /* Event 4 - read ext. value */
199 /* nibble mode is not supported */
200 if ((r
== (char)request_mode
) ||
201 (r
== NIBBLE_1284_NORMAL
)) {
203 /* Event 5 - restore direction bit, no data avail */
204 ppbus_wctr(dev
, (STROBE
| nINIT
) & ~(SELECTIN
));
208 ppbus_wctr(dev
, (nINIT
) & ~(SELECTIN
| STROBE
));
210 if (r
== NIBBLE_1284_NORMAL
) {
214 ppbus_1284_set_error(bus
, PPBUS_MODE_UNSUPPORTED
, 4);
219 ppbus_1284_set_state(dev
, PPBUS_PERIPHERAL_IDLE
);
223 /* negotiation succeeds */
227 /* Event 5 - mode not supported */
228 ppbus_wctr(dev
, SELECTIN
);
232 ppbus_wctr(dev
, (SELECTIN
) & ~(STROBE
| nINIT
));
233 ppbus_1284_set_error(bus
, PPBUS_MODE_UNSUPPORTED
, 4);
245 ppbus_peripheral_terminate(dev
, PPBUS_WAIT
);
250 /* Terminate peripheral transfer side. Always return 0 in compatible mode */
252 ppbus_peripheral_terminate(device_t dev
, int how
)
254 struct ppbus_softc
* bus
= device_private(dev
);
261 ppbus_1284_set_state(dev
, PPBUS_PERIPHERAL_TERMINATION
);
263 /* Event 22 - wait up to host response time (1s) */
264 if ((error
= do_peripheral_wait(bus
, SELECT
| nBUSY
, 0))) {
265 ppbus_1284_set_error(bus
, PPBUS_TIMEOUT
, 22);
270 ppbus_wctr(dev
, (nINIT
| STROBE
) & ~(AUTOFEED
| SELECTIN
));
272 /* Event 25 - wait up to host response time (1s) */
273 if ((error
= do_peripheral_wait(bus
, nBUSY
, nBUSY
))) {
274 ppbus_1284_set_error(bus
, PPBUS_TIMEOUT
, 25);
279 ppbus_wctr(dev
, (SELECTIN
| nINIT
| STROBE
) & ~(AUTOFEED
));
282 ppbus_wctr(dev
, (SELECTIN
| nINIT
) & ~(STROBE
| AUTOFEED
));
284 /* Event 28 - wait up to host response time (1s) */
285 if ((error
= do_peripheral_wait(bus
, nBUSY
, 0))) {
286 ppbus_1284_set_error(bus
, PPBUS_TIMEOUT
, 28);
291 ppbus_1284_terminate(dev
);
292 ppbus_1284_set_state(dev
, PPBUS_FORWARD_IDLE
);
298 /* Write 1 byte to host in BYTE mode (peripheral side) */
300 byte_peripheral_outbyte(device_t dev
, char *buffer
, int last
)
302 struct ppbus_softc
* bus
= device_private(dev
);
306 if ((error
= do_1284_wait(bus
, nBUSY
, nBUSY
))) {
307 ppbus_1284_set_error(bus
, PPBUS_TIMEOUT
, 7);
311 /* check termination */
312 if (!(ppbus_rstr(dev
) & SELECT
)) {
313 ppbus_peripheral_terminate(dev
, PPBUS_WAIT
);
317 /* Event 15 - put byte on data lines */
321 ppbus_wdtr(dev
, *buffer
);
324 ppbus_wctr(dev
, (AUTOFEED
| STROBE
) & ~(nINIT
| SELECTIN
));
326 /* Event 10 - wait data read */
327 if ((error
= do_peripheral_wait(bus
, nBUSY
, 0))) {
328 ppbus_1284_set_error(bus
, PPBUS_TIMEOUT
, 16);
334 ppbus_wctr(dev
, (AUTOFEED
) & ~(nINIT
| STROBE
| SELECTIN
));
336 ppbus_wctr(dev
, (nINIT
) & ~(STROBE
| SELECTIN
| AUTOFEED
));
340 /* Event 16 - wait strobe */
341 if ((error
= do_peripheral_wait(bus
, nACK
| nBUSY
, 0))) {
342 ppbus_1284_set_error(bus
, PPBUS_TIMEOUT
, 16);
347 /* check termination */
348 if (!(ppbus_rstr(dev
) & SELECT
)) {
349 ppbus_peripheral_terminate(dev
, PPBUS_WAIT
);
358 /* Write n bytes to host in BYTE mode (peripheral side) */
360 byte_peripheral_write(device_t dev
, char *buffer
, int len
,
366 ppbus_1284_set_state(dev
, PPBUS_PERIPHERAL_TRANSFER
);
368 /* wait forever, the remote host is master and should initiate
371 for(i
= 0; i
< len
; i
++) {
372 /* force remote nFAULT low to release the remote waiting
376 ppbus_wctr(dev
, r
& ~nINIT
);
382 error
= ppbus_poll_bus(dev
, PPBUS_FOREVER
, nBUSY
, nBUSY
,
385 if (error
&& error
!= EWOULDBLOCK
)
391 if ((error
= byte_peripheral_outbyte(dev
, buffer
+i
, (i
== len
-1))))
396 ppbus_1284_set_state(dev
, PPBUS_PERIPHERAL_IDLE
);
403 /* Read the device ID using the specified mode */
405 ppbus_1284_read_id(device_t dev
, int mode
, char ** buffer
,
406 size_t * size
, size_t * read
)
409 u_int8_t length_field
;
415 error
= ppbus_read_ivar(dev
, PPBUS_IVAR_IEEE
, &old_ivar
);
417 printf("%s(%s): error reading PPBUS_IVAR_IEEE.\n", __func__
,
422 error
= ppbus_write_ivar(dev
, PPBUS_IVAR_IEEE
, &new_ivar
);
424 printf("%s(%s): error enabling IEEE usage.\n", __func__
,
430 old_mode
= ppbus_get_mode(dev
);
435 error
= ppbus_set_mode(dev
, mode
, PPBUS_REQUEST_ID
);
437 printf("%s(%s): error setting bus mode.\n", __func__
,
443 printf("%s(%s): mode does not support returning device ID.\n",
444 __func__
, device_xname(dev
));
449 error
= ppbus_read(dev
, &length_field
, 1, 0, read
);
451 printf("%s(%s): error reading first byte.\n", __func__
,
455 msg_sz
= length_field
;
456 error
= ppbus_read(dev
, &length_field
, 1, 0, read
);
458 printf("%s(%s): error reading second byte.\n",
459 __func__
, device_xname(dev
));
463 msg_sz
|= length_field
;
466 printf("%s(%s): device ID length <= 0.\n", __func__
,
470 *buffer
= malloc(msg_sz
, M_DEVBUF
, M_WAITOK
);
472 error
= ppbus_read(dev
, *buffer
, msg_sz
, 0, read
);
475 ppbus_set_mode(dev
, old_mode
, 0);
477 if(ppbus_write_ivar(dev
, PPBUS_IVAR_IEEE
, &old_ivar
)) {
478 printf("%s(%s): error restoring PPBUS_IVAR_IEEE.\n",
479 __func__
, device_xname(dev
));
486 * IEEE1284 negotiation phase: after negotiation, nFAULT is low if data is
487 * available for reverse modes.
490 ppbus_1284_negotiate(device_t dev
, int mode
, int options
)
492 struct ppbus_softc
* bus
= device_private(dev
);
500 if (ppbus_1284_get_state(dev
) >= PPBUS_PERIPHERAL_NEGOTIATION
)
501 ppbus_peripheral_terminate(dev
, PPBUS_WAIT
);
507 /* ensure the host is in compatible mode */
508 ppbus_1284_terminate(dev
);
510 /* reset error to catch the actual negotiation error */
511 ppbus_1284_reset_error(bus
, PPBUS_FORWARD_IDLE
);
513 /* calculate ext. value */
514 request_mode
= ppbus_request_mode(mode
, options
);
517 ppbus_wctr(dev
, (nINIT
| SELECTIN
) & ~(STROBE
| AUTOFEED
));
520 /* enter negotiation phase */
521 ppbus_1284_set_state(dev
, PPBUS_NEGOTIATION
);
523 /* Event 0 - put the exten. value on the data lines */
524 ppbus_wdtr(dev
, request_mode
);
527 /* request remote host attention */
528 ppbus_wctr(dev
, (nINIT
| STROBE
) & ~(AUTOFEED
| SELECTIN
));
530 ppbus_wctr(dev
, (nINIT
) & ~(STROBE
| AUTOFEED
| SELECTIN
));
534 #endif /* !PERIPH_1284 */
536 /* Event 1 - enter IEEE1284 mode */
537 ppbus_wctr(dev
, (nINIT
| AUTOFEED
) & ~(STROBE
| SELECTIN
));
540 /* ignore the PError line, wait a bit more, remote host's
541 * interrupts don't respond fast enough */
542 if (ppbus_poll_bus(bus
, 40, nACK
| SELECT
| nFAULT
,
543 SELECT
| nFAULT
, PPBUS_NOINTR
| PPBUS_POLL
)) {
544 ppbus_1284_set_error(bus
, PPBUS_NOT_IEEE1284
, 2);
549 /* Event 2 - trying IEEE1284 dialog */
550 if (do_1284_wait(bus
, nACK
| PERROR
| SELECT
| nFAULT
,
551 PERROR
| SELECT
| nFAULT
)) {
552 ppbus_1284_set_error(bus
, PPBUS_NOT_IEEE1284
, 2);
556 #endif /* !PERIPH_1284 */
558 /* Event 3 - latch the ext. value to the peripheral */
559 ppbus_wctr(dev
, (nINIT
| STROBE
| AUTOFEED
) & ~SELECTIN
);
562 /* Event 4 - IEEE1284 device recognized */
563 ppbus_wctr(dev
, nINIT
& ~(SELECTIN
| AUTOFEED
| STROBE
));
565 /* Event 6 - waiting for status lines */
566 if (do_1284_wait(bus
, nACK
, nACK
)) {
567 ppbus_1284_set_error(bus
, PPBUS_TIMEOUT
, 6);
572 /* Event 7 - quering result consider nACK not to misunderstand
573 * a remote computer terminate sequence */
574 if (options
& PPBUS_EXTENSIBILITY_LINK
) {
575 /* XXX not fully supported yet */
576 ppbus_1284_terminate(dev
);
581 if (request_mode
== NIBBLE_1284_NORMAL
) {
582 if (do_1284_wait(bus
, nACK
| SELECT
, nACK
)) {
583 ppbus_1284_set_error(bus
, PPBUS_MODE_UNSUPPORTED
, 7);
588 if (do_1284_wait(bus
, nACK
| SELECT
, SELECT
| nACK
)) {
589 ppbus_1284_set_error(bus
, PPBUS_MODE_UNSUPPORTED
, 7);
598 /* enter reverse idle phase */
599 ppbus_1284_set_state(dev
, PPBUS_REVERSE_IDLE
);
602 /* negotiation ok, now setup the communication */
603 ppbus_1284_set_state(dev
, PPBUS_SETUP
);
604 ppbus_wctr(dev
, (nINIT
| AUTOFEED
) & ~(SELECTIN
| STROBE
));
607 /* ignore PError line */
608 if (do_1284_wait(bus
, nACK
| SELECT
| nBUSY
,
609 nACK
| SELECT
| nBUSY
)) {
610 ppbus_1284_set_error(bus
, PPBUS_TIMEOUT
, 30);
615 if (do_1284_wait(bus
, nACK
| SELECT
| PERROR
| nBUSY
,
616 nACK
| SELECT
| PERROR
| nBUSY
)) {
617 ppbus_1284_set_error(bus
, PPBUS_TIMEOUT
, 30);
621 #endif /* !PERIPH_1284 */
623 /* ok, the host enters the ForwardIdle state */
624 ppbus_1284_set_state(dev
, PPBUS_ECP_FORWARD_IDLE
);
627 ppbus_1284_set_state(dev
, PPBUS_EPP_IDLE
);
630 panic("%s: unknown mode (%d)!", __func__
, mode
);
636 ppbus_1284_terminate(dev
);
641 * IEEE1284 termination phase, return code should ignored since the host
642 * is _always_ in compatible mode after ppbus_1284_terminate()
645 ppbus_1284_terminate(device_t dev
)
647 struct ppbus_softc
* bus
= device_private(dev
);
653 /* do not reset error here to keep the error that
654 * may occurred before the ppbus_1284_terminate() call */
655 ppbus_1284_set_state(dev
, PPBUS_TERMINATION
);
658 /* request remote host attention */
659 ppbus_wctr(dev
, (nINIT
| STROBE
| SELECTIN
) & ~(AUTOFEED
));
661 #endif /* PERIPH_1284 */
663 /* Event 22 - set nSelectin low and nAutoFeed high */
664 ppbus_wctr(dev
, (nINIT
| SELECTIN
) & ~(STROBE
| AUTOFEED
));
666 /* Event 24 - waiting for peripheral, Xflag ignored */
667 if (do_1284_wait(bus
, nACK
| nBUSY
| nFAULT
, nFAULT
)) {
668 ppbus_1284_set_error(bus
, PPBUS_TIMEOUT
, 24);
672 /* Event 25 - set nAutoFd low */
673 ppbus_wctr(dev
, (nINIT
| SELECTIN
| AUTOFEED
) & ~STROBE
);
675 /* Event 26 - compatible mode status is set */
677 /* Event 27 - peripheral set nAck high */
678 if (do_1284_wait(bus
, nACK
, nACK
)) {
679 ppbus_1284_set_error(bus
, PPBUS_TIMEOUT
, 27);
682 /* Event 28 - end termination, return to idle phase */
683 ppbus_wctr(dev
, (nINIT
| SELECTIN
) & ~(STROBE
| AUTOFEED
));
686 ppbus_1284_set_state(dev
, PPBUS_FORWARD_IDLE
);