xref: /freebsd/sys/dev/ppbus/ppb_base.c (revision 069ac18495ad8fde2748bc94b0f80a50250bb01d)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 1997, 1998, 1999 Nicolas Souchu
5  * All rights reserved.
6  *
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.
15  *
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.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/lock.h>
31 #include <sys/kernel.h>
32 #include <sys/module.h>
33 #include <sys/mutex.h>
34 #include <sys/systm.h>
35 #include <sys/bus.h>
36 
37 #include <dev/ppbus/ppbconf.h>
38 
39 #include "ppbus_if.h"
40 
41 #include <dev/ppbus/ppbio.h>
42 
43 MODULE_VERSION(ppbus, 1);
44 
45 #define DEVTOSOFTC(dev) ((struct ppb_data *)device_get_softc(dev))
46 
47 /*
48  * ppb_poll_bus()
49  *
50  * Polls the bus
51  *
52  * max is a delay in 10-milliseconds
53  */
54 int
55 ppb_poll_bus(device_t bus, int max,
56 	     uint8_t mask, uint8_t status, int how)
57 {
58 	struct ppb_data *ppb = DEVTOSOFTC(bus);
59 	int i, j, error;
60 	uint8_t r;
61 
62 	ppb_assert_locked(bus);
63 
64 	/* try at least up to 10ms */
65 	for (j = 0; j < ((how & PPB_POLL) ? max : 1); j++) {
66 		for (i = 0; i < 10000; i++) {
67 			r = ppb_rstr(bus);
68 			DELAY(1);
69 			if ((r & mask) == status)
70 				return (0);
71 		}
72 	}
73 
74 	if (!(how & PPB_POLL)) {
75 	   for (i = 0; max == PPB_FOREVER || i < max-1; i++) {
76 		if ((ppb_rstr(bus) & mask) == status)
77 			return (0);
78 
79 		/* wait 10 ms */
80 		error = mtx_sleep((caddr_t)bus, ppb->ppc_lock, PPBPRI |
81 		    (how == PPB_NOINTR ? 0 : PCATCH), "ppbpoll", hz/100);
82 		if (error != EWOULDBLOCK)
83 			return (error);
84 	   }
85 	}
86 
87 	return (EWOULDBLOCK);
88 }
89 
90 /*
91  * ppb_get_epp_protocol()
92  *
93  * Return the chipset EPP protocol
94  */
95 int
96 ppb_get_epp_protocol(device_t bus)
97 {
98 	uintptr_t protocol;
99 
100 	ppb_assert_locked(bus);
101 	BUS_READ_IVAR(device_get_parent(bus), bus, PPC_IVAR_EPP_PROTO, &protocol);
102 
103 	return (protocol);
104 }
105 
106 /*
107  * ppb_get_mode()
108  *
109  */
110 int
111 ppb_get_mode(device_t bus)
112 {
113 	struct ppb_data *ppb = DEVTOSOFTC(bus);
114 
115 	/* XXX yet device mode = ppbus mode = chipset mode */
116 	ppb_assert_locked(bus);
117 	return (ppb->mode);
118 }
119 
120 /*
121  * ppb_set_mode()
122  *
123  * Set the operating mode of the chipset, return the previous mode
124  */
125 int
126 ppb_set_mode(device_t bus, int mode)
127 {
128 	struct ppb_data *ppb = DEVTOSOFTC(bus);
129 	int old_mode = ppb_get_mode(bus);
130 
131 	ppb_assert_locked(bus);
132 	if (PPBUS_SETMODE(device_get_parent(bus), mode))
133 		return (-1);
134 
135 	/* XXX yet device mode = ppbus mode = chipset mode */
136 	ppb->mode = (mode & PPB_MASK);
137 
138 	return (old_mode);
139 }
140 
141 /*
142  * ppb_write()
143  *
144  * Write charaters to the port
145  */
146 int
147 ppb_write(device_t bus, char *buf, int len, int how)
148 {
149 
150 	ppb_assert_locked(bus);
151 	return (PPBUS_WRITE(device_get_parent(bus), buf, len, how));
152 }
153 
154 /*
155  * ppb_reset_epp_timeout()
156  *
157  * Reset the EPP timeout bit in the status register
158  */
159 int
160 ppb_reset_epp_timeout(device_t bus)
161 {
162 
163 	ppb_assert_locked(bus);
164 	return(PPBUS_RESET_EPP(device_get_parent(bus)));
165 }
166 
167 /*
168  * ppb_ecp_sync()
169  *
170  * Wait for the ECP FIFO to be empty
171  */
172 int
173 ppb_ecp_sync(device_t bus)
174 {
175 
176 	ppb_assert_locked(bus);
177 	return (PPBUS_ECP_SYNC(device_get_parent(bus)));
178 }
179 
180 /*
181  * ppb_get_status()
182  *
183  * Read the status register and update the status info
184  */
185 int
186 ppb_get_status(device_t bus, struct ppb_status *status)
187 {
188 	uint8_t r;
189 
190 	ppb_assert_locked(bus);
191 
192 	r = status->status = ppb_rstr(bus);
193 
194 	status->timeout	= r & TIMEOUT;
195 	status->error	= !(r & nFAULT);
196 	status->select	= r & SELECT;
197 	status->paper_end = r & PERROR;
198 	status->ack	= !(r & nACK);
199 	status->busy	= !(r & nBUSY);
200 
201 	return (0);
202 }
203 
204 void
205 ppb_lock(device_t bus)
206 {
207 	struct ppb_data *ppb = DEVTOSOFTC(bus);
208 
209 	mtx_lock(ppb->ppc_lock);
210 }
211 
212 void
213 ppb_unlock(device_t bus)
214 {
215 	struct ppb_data *ppb = DEVTOSOFTC(bus);
216 
217 	mtx_unlock(ppb->ppc_lock);
218 }
219 
220 struct mtx *
221 ppb_get_lock(device_t bus)
222 {
223 	struct ppb_data *ppb = DEVTOSOFTC(bus);
224 
225 	return (ppb->ppc_lock);
226 }
227 
228 void
229 _ppb_assert_locked(device_t bus, const char *file, int line)
230 {
231 
232 	mtx_assert_(DEVTOSOFTC(bus)->ppc_lock, MA_OWNED, file, line);
233 }
234 
235 void
236 ppb_init_callout(device_t bus, struct callout *c, int flags)
237 {
238 	struct ppb_data *ppb = DEVTOSOFTC(bus);
239 
240 	callout_init_mtx(c, ppb->ppc_lock, flags);
241 }
242 
243 int
244 ppb_sleep(device_t bus, void *wchan, int priority, const char *wmesg, int timo)
245 {
246 	struct ppb_data *ppb = DEVTOSOFTC(bus);
247 
248 	return (mtx_sleep(wchan, ppb->ppc_lock, priority, wmesg, timo));
249 }
250