Sync usage with man page.
[netbsd-mini2440.git] / sys / dev / ppbus / ppbus_1284.c
blobf87358ae3197a9fd5bcfacafa7796504c22c9475
1 /* $NetBSD: ppbus_1284.c,v 1.11 2008/04/15 15:02:29 cegger Exp $ */
3 /*-
4 * Copyright (c) 1997 Nicolas Souchu
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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
26 * SUCH DAMAGE.
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 */
51 static int
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) */
59 static int
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 */
68 static int
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;
73 return 0;
77 /* Get IEEE1284 state */
78 int
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 */
88 int
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;
101 return 0;
105 /* Set the IEEE1284 error field */
106 static int
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;
116 #ifdef DEBUG_1284
117 printf("%s<1284>: error=%d status=0x%x event=%d\n",
118 device_xname(bus->sc_dev), error, ppbus_rstr(bus->sc_dev),
119 event);
121 #endif
123 return 0;
127 /* Converts mode+options into ext. value */
128 static int
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;
137 else {
138 switch (mode) {
139 case PPBUS_NIBBLE:
140 request_mode = (options & PPBUS_REQUEST_ID) ?
141 NIBBLE_1284_REQUEST_ID :
142 NIBBLE_1284_NORMAL;
143 break;
144 case PPBUS_PS2:
145 request_mode = (options & PPBUS_REQUEST_ID) ?
146 BYTE_1284_REQUEST_ID :
147 BYTE_1284_NORMAL;
148 break;
149 case PPBUS_ECP:
150 if (options & PPBUS_USE_RLE)
151 request_mode = (options & PPBUS_REQUEST_ID) ?
152 ECP_1284_RLE_REQUEST_ID :
153 ECP_1284_RLE;
154 else
155 request_mode = (options & PPBUS_REQUEST_ID) ?
156 ECP_1284_REQUEST_ID :
157 ECP_1284_NORMAL;
158 break;
159 case PPBUS_EPP:
160 request_mode = EPP_1284_NORMAL;
161 break;
162 default:
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;
177 char r;
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);
185 /* wait host */
186 spin = 10;
187 while (spin-- && (ppbus_rstr(dev) & nBUSY))
188 DELAY(1);
190 /* check termination */
191 if (!(ppbus_rstr(dev) & SELECT) || !spin) {
192 error = ENODEV;
193 goto error;
196 /* Event 4 - read ext. value */
197 r = ppbus_rdtr(dev);
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));
205 DELAY(1);
207 /* Event 6 */
208 ppbus_wctr(dev, (nINIT) & ~(SELECTIN | STROBE));
210 if (r == NIBBLE_1284_NORMAL) {
211 #ifdef DEBUG_1284
212 printf("R");
213 #endif
214 ppbus_1284_set_error(bus, PPBUS_MODE_UNSUPPORTED, 4);
215 error = EINVAL;
216 goto error;
218 else {
219 ppbus_1284_set_state(dev, PPBUS_PERIPHERAL_IDLE);
220 #ifdef DEBUG_1284
221 printf("A");
222 #endif
223 /* negotiation succeeds */
226 else {
227 /* Event 5 - mode not supported */
228 ppbus_wctr(dev, SELECTIN);
229 DELAY(1);
231 /* Event 6 */
232 ppbus_wctr(dev, (SELECTIN) & ~(STROBE | nINIT));
233 ppbus_1284_set_error(bus, PPBUS_MODE_UNSUPPORTED, 4);
235 #ifdef DEBUG_1284
236 printf("r");
237 #endif
238 error = EINVAL;
239 goto error;
242 return (0);
244 error:
245 ppbus_peripheral_terminate(dev, PPBUS_WAIT);
246 return (error);
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);
255 int error = 0;
257 #ifdef DEBUG_1284
258 printf("t");
259 #endif
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);
266 goto error;
269 /* Event 24 */
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);
275 goto error;
278 /* Event 26 */
279 ppbus_wctr(dev, (SELECTIN | nINIT | STROBE) & ~(AUTOFEED));
280 DELAY(1);
281 /* Event 27 */
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);
287 goto error;
290 error:
291 ppbus_1284_terminate(dev);
292 ppbus_1284_set_state(dev, PPBUS_FORWARD_IDLE);
294 return (0);
298 /* Write 1 byte to host in BYTE mode (peripheral side) */
299 static int
300 byte_peripheral_outbyte(device_t dev, char *buffer, int last)
302 struct ppbus_softc * bus = device_private(dev);
303 int error = 0;
305 /* Event 7 */
306 if ((error = do_1284_wait(bus, nBUSY, nBUSY))) {
307 ppbus_1284_set_error(bus, PPBUS_TIMEOUT, 7);
308 goto error;
311 /* check termination */
312 if (!(ppbus_rstr(dev) & SELECT)) {
313 ppbus_peripheral_terminate(dev, PPBUS_WAIT);
314 goto error;
317 /* Event 15 - put byte on data lines */
318 #ifdef DEBUG_1284
319 printf("B");
320 #endif
321 ppbus_wdtr(dev, *buffer);
323 /* Event 9 */
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);
329 goto error;
332 /* Event 11 */
333 if (!last) {
334 ppbus_wctr(dev, (AUTOFEED) & ~(nINIT | STROBE | SELECTIN));
335 } else {
336 ppbus_wctr(dev, (nINIT) & ~(STROBE | SELECTIN | AUTOFEED));
339 #if 0
340 /* Event 16 - wait strobe */
341 if ((error = do_peripheral_wait(bus, nACK | nBUSY, 0))) {
342 ppbus_1284_set_error(bus, PPBUS_TIMEOUT, 16);
343 goto error;
345 #endif
347 /* check termination */
348 if (!(ppbus_rstr(dev) & SELECT)) {
349 ppbus_peripheral_terminate(dev, PPBUS_WAIT);
350 goto error;
353 error:
354 return (error);
358 /* Write n bytes to host in BYTE mode (peripheral side) */
360 byte_peripheral_write(device_t dev, char *buffer, int len,
361 int *sent)
363 int error = 0, i;
364 char r;
366 ppbus_1284_set_state(dev, PPBUS_PERIPHERAL_TRANSFER);
368 /* wait forever, the remote host is master and should initiate
369 * termination
371 for(i = 0; i < len; i++) {
372 /* force remote nFAULT low to release the remote waiting
373 * process, if any
375 r = ppbus_rctr(dev);
376 ppbus_wctr(dev, r & ~nINIT);
378 #ifdef DEBUG_1284
379 printf("y");
380 #endif
381 /* Event 7 */
382 error = ppbus_poll_bus(dev, PPBUS_FOREVER, nBUSY, nBUSY,
383 PPBUS_INTR);
385 if (error && error != EWOULDBLOCK)
386 goto error;
388 #ifdef DEBUG_1284
389 printf("b");
390 #endif
391 if ((error = byte_peripheral_outbyte(dev, buffer+i, (i == len-1))))
392 goto error;
394 error:
395 if (!error)
396 ppbus_1284_set_state(dev, PPBUS_PERIPHERAL_IDLE);
398 *sent = i;
399 return (error);
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)
408 u_int16_t msg_sz;
409 u_int8_t length_field;
410 u_int8_t old_mode;
411 int error;
412 int old_ivar;
413 int new_ivar = 1;
415 error = ppbus_read_ivar(dev, PPBUS_IVAR_IEEE, &old_ivar);
416 if(error) {
417 printf("%s(%s): error reading PPBUS_IVAR_IEEE.\n", __func__,
418 device_xname(dev));
419 return error;
421 if(old_ivar == 0) {
422 error = ppbus_write_ivar(dev, PPBUS_IVAR_IEEE, &new_ivar);
423 if(error) {
424 printf("%s(%s): error enabling IEEE usage.\n", __func__,
425 device_xname(dev));
426 return error;
430 old_mode = ppbus_get_mode(dev);
431 switch (mode) {
432 case PPBUS_NIBBLE:
433 case PPBUS_ECP:
434 case PPBUS_BYTE:
435 error = ppbus_set_mode(dev, mode, PPBUS_REQUEST_ID);
436 if(error) {
437 printf("%s(%s): error setting bus mode.\n", __func__,
438 device_xname(dev));
439 goto end_read_id;
441 break;
442 default:
443 printf("%s(%s): mode does not support returning device ID.\n",
444 __func__, device_xname(dev));
445 error = ENODEV;
446 goto end_read_id;
449 error = ppbus_read(dev, &length_field, 1, 0, read);
450 if(error) {
451 printf("%s(%s): error reading first byte.\n", __func__,
452 device_xname(dev));
453 goto end_read_id;
455 msg_sz = length_field;
456 error = ppbus_read(dev, &length_field, 1, 0, read);
457 if(error) {
458 printf("%s(%s): error reading second byte.\n",
459 __func__, device_xname(dev));
460 goto end_read_id;
462 msg_sz <<= 8;
463 msg_sz |= length_field;
464 msg_sz -= 2;
465 if(msg_sz <= 0) {
466 printf("%s(%s): device ID length <= 0.\n", __func__,
467 device_xname(dev));
468 goto end_read_id;
470 *buffer = malloc(msg_sz, M_DEVBUF, M_WAITOK);
471 *size = msg_sz;
472 error = ppbus_read(dev, *buffer, msg_sz, 0, read);
474 end_read_id:
475 ppbus_set_mode(dev, old_mode, 0);
476 if(old_ivar == 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));
482 return (error);
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);
493 int error;
494 int request_mode;
496 #ifdef DEBUG_1284
497 printf("n");
498 #endif
500 if (ppbus_1284_get_state(dev) >= PPBUS_PERIPHERAL_NEGOTIATION)
501 ppbus_peripheral_terminate(dev, PPBUS_WAIT);
503 #ifdef DEBUG_1284
504 printf("%d", mode);
505 #endif
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);
516 /* default state */
517 ppbus_wctr(dev, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED));
518 DELAY(1);
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);
526 #ifdef PERIPH_1284
527 /* request remote host attention */
528 ppbus_wctr(dev, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN));
529 DELAY(1);
530 ppbus_wctr(dev, (nINIT) & ~(STROBE | AUTOFEED | SELECTIN));
531 #else
532 DELAY(1);
534 #endif /* !PERIPH_1284 */
536 /* Event 1 - enter IEEE1284 mode */
537 ppbus_wctr(dev, (nINIT | AUTOFEED) & ~(STROBE | SELECTIN));
539 #ifdef PERIPH_1284
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);
545 error = ENODEV;
546 goto error;
548 #else
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);
553 error = ENODEV;
554 goto error;
556 #endif /* !PERIPH_1284 */
558 /* Event 3 - latch the ext. value to the peripheral */
559 ppbus_wctr(dev, (nINIT | STROBE | AUTOFEED) & ~SELECTIN);
560 DELAY(1);
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);
568 error = EBUSY;
569 goto error;
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);
577 error = ENODEV;
578 goto error;
579 /* return (0); */
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);
584 error = ENODEV;
585 goto error;
587 } else {
588 if (do_1284_wait(bus, nACK | SELECT, SELECT | nACK)) {
589 ppbus_1284_set_error(bus, PPBUS_MODE_UNSUPPORTED, 7);
590 error = ENODEV;
591 goto error;
595 switch (mode) {
596 case PPBUS_NIBBLE:
597 case PPBUS_PS2:
598 /* enter reverse idle phase */
599 ppbus_1284_set_state(dev, PPBUS_REVERSE_IDLE);
600 break;
601 case PPBUS_ECP:
602 /* negotiation ok, now setup the communication */
603 ppbus_1284_set_state(dev, PPBUS_SETUP);
604 ppbus_wctr(dev, (nINIT | AUTOFEED) & ~(SELECTIN | STROBE));
606 #ifdef PERIPH_1284
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);
611 error = ENODEV;
612 goto error;
614 #else
615 if (do_1284_wait(bus, nACK | SELECT | PERROR | nBUSY,
616 nACK | SELECT | PERROR | nBUSY)) {
617 ppbus_1284_set_error(bus, PPBUS_TIMEOUT, 30);
618 error = ENODEV;
619 goto error;
621 #endif /* !PERIPH_1284 */
623 /* ok, the host enters the ForwardIdle state */
624 ppbus_1284_set_state(dev, PPBUS_ECP_FORWARD_IDLE);
625 break;
626 case PPBUS_EPP:
627 ppbus_1284_set_state(dev, PPBUS_EPP_IDLE);
628 break;
629 default:
630 panic("%s: unknown mode (%d)!", __func__, mode);
633 return 0;
635 error:
636 ppbus_1284_terminate(dev);
637 return error;
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);
649 #ifdef DEBUG_1284
650 printf("T");
651 #endif
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);
657 #ifdef PERIPH_1284
658 /* request remote host attention */
659 ppbus_wctr(dev, (nINIT | STROBE | SELECTIN) & ~(AUTOFEED));
660 DELAY(1);
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);
669 goto error;
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));
685 error:
686 ppbus_1284_set_state(dev, PPBUS_FORWARD_IDLE);
688 return (0);