xref: /freebsd/sys/dev/ppbus/ppb_1284.c (revision 0de89efe5c443f213c7ea28773ef2dc6cf3af2ed)
1 /*-
2  * Copyright (c) 1997 Nicolas Souchu
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  *	$Id: ppb_1284.c,v 1.1 1997/08/16 14:05:32 msmith Exp $
27  *
28  */
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 
32 #include <machine/clock.h>
33 
34 #include <dev/ppbus/ppbconf.h>
35 #include <dev/ppbus/ppb_1284.h>
36 
37 /*
38  * nibble_1284_wait()
39  *
40  * Wait for the peripherial up to 40ms
41  */
42 int
43 nibble_1284_wait(struct ppb_device *dev, char mask, char status)
44 {
45 	int i;
46 
47 	return (ppb_poll_device(dev, 4, mask, status, PPB_NOINTR));
48 }
49 
50 #define nibble2char(s) (((s & ~nACK) >> 3) | (~s & nBUSY) >> 4)
51 
52 /*
53  * nibble_1284_inbyte()
54  *
55  * Read data in NIBBLE mode
56  */
57 int
58 nibble_1284_inbyte(struct ppb_device *dev, char *buffer)
59 {
60 	char nibble[2], r;
61 	int i, error;
62 
63 	r = ppb_rctr(dev);
64 
65 	for (i = 0; i < 2; i++) {
66 		/* ready to take data (nAUTO low) */
67 		ppb_wctr(dev, r | AUTOFEED);
68 
69 		if ((error = nibble_1284_wait(dev, nACK, 0))) {
70 			ppb_wctr(dev, r);
71 			return (error);
72 		}
73 
74 		/* read nibble */
75 		nibble[i] = ppb_rstr(dev);
76 
77 #ifdef DEBUG_1284
78 		printf("nibble_1284_inbyte: nibble[%d]=0x%x\n", i, nibble[i]);
79 #endif
80 
81 		/* ack, not ready for another nibble */
82 		ppb_wctr(dev, r & ~AUTOFEED);
83 
84 		/* wait ack from peripherial */
85 		if ((error = nibble_1284_wait(dev, nACK, nACK))) {
86 			ppb_wctr(dev, r);
87 			return (error);
88 		}
89 	}
90 
91 	*buffer = ((nibble2char(nibble[1]) << 4) & 0xf0) |
92 				(nibble2char(nibble[0]) & 0x0f);
93 
94 #ifdef DEBUG_1284
95 	printf("nibble_1284_inbyte: byte=0x%x\n", *buffer);
96 #endif
97 
98 	return (0);
99 }
100 
101 /*
102  * nibble_1284_sync()
103  */
104 void
105 nibble_1284_sync(struct ppb_device *dev)
106 {
107 	char ctr;
108 
109 	ctr = ppb_rctr(dev);
110 
111 	ppb_wctr(dev, (ctr & ~AUTOFEED) | SELECTIN);
112 	if (nibble_1284_wait(dev, nACK, 0))
113 		return;
114 
115 	ppb_wctr(dev, ctr | AUTOFEED);
116 	nibble_1284_wait(dev, nACK, nACK);
117 
118 	ppb_wctr(dev, (ctr & ~AUTOFEED) | SELECTIN);
119 
120 	return;
121 }
122 
123 /*
124  * nibble_1284_mode()
125  *
126  * Normal nibble mode or request device id mode (see ppb_1284.h)
127  */
128 int
129 nibble_1284_mode(struct ppb_device *dev, int mode)
130 {
131 	char ctrl;
132 	int error;
133 
134 	ctrl = ppb_rctr(dev);
135 
136 	ppb_wdtr(dev, mode);
137 	DELAY(5);
138 
139 	ppb_wctr(dev, (ctrl & ~SELECTIN) | AUTOFEED);
140 	if ((error = nibble_1284_wait(dev, nACK | ERROR | SELECT | nFAULT,
141 			ERROR | SELECT | nFAULT))) {
142 		ppb_wctr(dev, ctrl);
143 		return (error);
144 	}
145 
146 	ppb_wctr(dev, ppb_rctr(dev) | STROBE);
147 	DELAY(5);
148 
149 	ppb_wctr(dev, ppb_rctr(dev) & ~STROBE);
150 	DELAY(5);
151 
152 	ppb_wctr(dev, ppb_rctr(dev) & ~AUTOFEED);
153 
154 	return (0);
155 }
156