xref: /freebsd/sys/dev/ppbus/ppb_1284.c (revision 380a989b3223d455375b4fae70fd0b9bdd43bafb)
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.5 1998/09/13 18:26:26 nsouch Exp $
27  *
28  */
29 
30 #include "opt_debug_1284.h"
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 
35 #include <machine/clock.h>
36 
37 #include <dev/ppbus/ppbconf.h>
38 #include <dev/ppbus/ppb_1284.h>
39 
40 /*
41  * do_1284_wait()
42  *
43  * Wait for the peripherial up to 40ms
44  */
45 int
46 do_1284_wait(struct ppb_device *dev, char mask, char status)
47 {
48 	int i;
49 	char r;
50 
51 	/* try up to 5ms */
52 	for (i = 0; i < 20; i++) {
53 		r = ppb_rstr(dev);
54 		DELAY(25);
55 		if ((r & mask) == status)
56 			return (0);
57 	}
58 
59 	return (ppb_poll_device(dev, 4, mask, status, PPB_NOINTR));
60 }
61 
62 #define nibble2char(s) (((s & ~nACK) >> 3) | (~s & nBUSY) >> 4)
63 
64 /*
65  * nibble_1284_inbyte()
66  *
67  * Read 1 byte in NIBBLE mode
68  */
69 int
70 nibble_1284_inbyte(struct ppb_device *dev, char *buffer)
71 {
72 	char nibble[2];
73 	int i, error;
74 
75 	for (i = 0; i < 2; i++) {
76 		/* ready to take data (nAUTO low) */
77 		ppb_wctr(dev, AUTOFEED & ~(STROBE | SELECTIN));
78 
79 		if ((error = do_1284_wait(dev, nACK, 0)))
80 			return (error);
81 
82 		/* read nibble */
83 		nibble[i] = ppb_rstr(dev);
84 
85 		/* ack, not ready for another nibble */
86 		ppb_wctr(dev, 0 & ~(AUTOFEED | STROBE | SELECTIN));
87 
88 		/* wait ack from peripherial */
89 		if ((error = do_1284_wait(dev, nACK, nACK)))
90 			return (error);
91 	}
92 
93 	*buffer = ((nibble2char(nibble[1]) << 4) & 0xf0) |
94 				(nibble2char(nibble[0]) & 0x0f);
95 
96 	return (0);
97 }
98 
99 /*
100  * nibble_1284_sync()
101  */
102 void
103 nibble_1284_sync(struct ppb_device *dev)
104 {
105 	char ctr;
106 
107 	ctr = ppb_rctr(dev);
108 
109 	ppb_wctr(dev, (ctr & ~AUTOFEED) | SELECTIN);
110 	if (do_1284_wait(dev, nACK, 0))
111 		return;
112 
113 	ppb_wctr(dev, ctr | AUTOFEED);
114 	do_1284_wait(dev, nACK, nACK);
115 
116 	ppb_wctr(dev, (ctr & ~AUTOFEED) | SELECTIN);
117 
118 	return;
119 }
120 
121 /*
122  * ppb_1284_negociate()
123  *
124  * Normal nibble mode or request device id mode (see ppb_1284.h)
125  */
126 int
127 ppb_1284_negociate(struct ppb_device *dev, int mode)
128 {
129 	int error;
130 	int phase = 0;
131 
132 	ppb_wctr(dev, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED));
133 	DELAY(1);
134 
135 	ppb_wdtr(dev, mode);
136 	DELAY(1);
137 
138 	ppb_wctr(dev, (nINIT | AUTOFEED) & ~(STROBE | SELECTIN));
139 
140 	if ((error = do_1284_wait(dev, nACK | PERROR | SELECT | nFAULT,
141 			PERROR  | SELECT | nFAULT)))
142 		goto error;
143 
144 	phase = 1;
145 
146 	ppb_wctr(dev, (nINIT | STROBE | AUTOFEED) & ~SELECTIN);
147 	DELAY(5);
148 
149 	ppb_wctr(dev, nINIT & ~(SELECTIN | AUTOFEED | STROBE));
150 
151 #if 0	/* not respected by most devices */
152 	if ((error = do_1284_wait(dev, nACK, nACK)))
153 		goto error;
154 
155 	if (mode == 0)
156 		if ((error = do_1284_wait(dev, SELECT, 0)))
157 			goto error;
158 	else
159 		if ((error = do_1284_wait(dev, SELECT, SELECT)))
160 			goto error;
161 #endif
162 
163 	return (0);
164 
165 error:
166 	if (bootverbose)
167 		printf("%s: status=0x%x %d\n", __FUNCTION__, ppb_rstr(dev), phase);
168 
169 	return (error);
170 }
171 
172 int
173 ppb_1284_terminate(struct ppb_device *dev, int how)
174 {
175 	int error;
176 
177 	switch (how) {
178 	case VALID_STATE:
179 
180 		ppb_wctr(dev, SELECTIN & ~(STROBE | AUTOFEED));
181 
182 		if ((error = do_1284_wait(dev, nACK | nBUSY | nFAULT, nFAULT)))
183 			return (error);
184 
185 		ppb_wctr(dev, (SELECTIN | AUTOFEED) & ~STROBE);
186 
187 		if ((error = do_1284_wait(dev, nACK, nACK)))
188 			return (error);
189 
190 		ppb_wctr(dev, SELECTIN & ~(STROBE | AUTOFEED));
191 		break;
192 
193 	default:
194 		return (EINVAL);
195 	}
196 
197 	return (0);
198 }
199