pi1ppc.c revision 1.11 1 1.11 dyoung /* $NetBSD: pi1ppc.c,v 1.11 2011/07/01 18:53:47 dyoung Exp $ */
2 1.1 kurahone
3 1.1 kurahone /*
4 1.1 kurahone * Copyright (c) 2001 Alcove - Nicolas Souchu
5 1.1 kurahone * Copyright (c) 2003, 2004 Gary Thorpe <gathorpe (at) users.sourceforge.net>
6 1.1 kurahone * Copyright (c) 2005 Joe Britt <britt (at) danger.com> - SGI PI1 version
7 1.1 kurahone * All rights reserved.
8 1.1 kurahone *
9 1.1 kurahone *
10 1.1 kurahone * Redistribution and use in source and binary forms, with or without
11 1.1 kurahone * modification, are permitted provided that the following conditions
12 1.1 kurahone * are met:
13 1.1 kurahone * 1. Redistributions of source code must retain the above copyright
14 1.1 kurahone * notice, this list of conditions and the following disclaimer.
15 1.1 kurahone * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 kurahone * notice, this list of conditions and the following disclaimer in the
17 1.1 kurahone * documentation and/or other materials provided with the distribution.
18 1.1 kurahone *
19 1.1 kurahone * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 1.1 kurahone * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 1.1 kurahone * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 1.1 kurahone * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 1.1 kurahone * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 1.1 kurahone * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 1.1 kurahone * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 1.1 kurahone * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 1.1 kurahone * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 1.1 kurahone * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 1.1 kurahone * SUCH DAMAGE.
30 1.1 kurahone *
31 1.1 kurahone * FreeBSD: src/sys/isa/ppc.c,v 1.26.2.5 2001/10/02 05:21:45 nsouch Exp
32 1.1 kurahone *
33 1.1 kurahone */
34 1.1 kurahone
35 1.1 kurahone #include <sys/cdefs.h>
36 1.11 dyoung __KERNEL_RCSID(0, "$NetBSD: pi1ppc.c,v 1.11 2011/07/01 18:53:47 dyoung Exp $");
37 1.1 kurahone
38 1.1 kurahone #include "opt_pi1ppc.h"
39 1.1 kurahone
40 1.1 kurahone #include <sys/types.h>
41 1.1 kurahone #include <sys/param.h>
42 1.1 kurahone #include <sys/kernel.h>
43 1.10 rmind #include <sys/kmem.h>
44 1.1 kurahone #include <sys/device.h>
45 1.1 kurahone #include <sys/systm.h>
46 1.1 kurahone
47 1.11 dyoung #include <sys/bus.h>
48 1.1 kurahone /*#include <machine/intr.h>*/
49 1.1 kurahone
50 1.1 kurahone #include <dev/ppbus/ppbus_conf.h>
51 1.1 kurahone #include <dev/ppbus/ppbus_msq.h>
52 1.1 kurahone #include <dev/ppbus/ppbus_io.h>
53 1.1 kurahone #include <dev/ppbus/ppbus_var.h>
54 1.1 kurahone
55 1.1 kurahone #include <machine/autoconf.h>
56 1.1 kurahone #include <machine/machtype.h>
57 1.1 kurahone
58 1.1 kurahone #include <sgimips/ioc/iocreg.h>
59 1.1 kurahone
60 1.1 kurahone #include <sgimips/hpc/hpcvar.h>
61 1.1 kurahone #include <sgimips/hpc/hpcreg.h>
62 1.1 kurahone
63 1.1 kurahone #include <sgimips/hpc/pi1ppcreg.h>
64 1.1 kurahone #include <sgimips/hpc/pi1ppcvar.h>
65 1.1 kurahone
66 1.1 kurahone #ifdef PI1PPC_DEBUG
67 1.1 kurahone int pi1ppc_debug = 1;
68 1.1 kurahone #endif
69 1.1 kurahone
70 1.1 kurahone #ifdef PI1PPC_VERBOSE
71 1.1 kurahone int pi1ppc_verbose = 1;
72 1.1 kurahone #endif
73 1.1 kurahone
74 1.1 kurahone /* Prototypes for functions. */
75 1.1 kurahone
76 1.1 kurahone /* PC-style register emulation */
77 1.8 tsutsui static uint8_t r_reg(int reg, struct pi1ppc_softc *pi1ppc);
78 1.8 tsutsui static void w_reg(int reg, struct pi1ppc_softc *pi1ppc, uint8_t byte);
79 1.1 kurahone
80 1.1 kurahone #define AT_DATA_REG 0
81 1.1 kurahone #define AT_STAT_REG 1
82 1.1 kurahone #define AT_CTL_REG 2
83 1.1 kurahone
84 1.1 kurahone #define pi1ppc_r_str(_x) r_reg(AT_STAT_REG,_x)
85 1.1 kurahone #define pi1ppc_r_ctr(_x) r_reg(AT_CTL_REG,_x)
86 1.1 kurahone #define pi1ppc_r_dtr(_x) r_reg(AT_DATA_REG,_x)
87 1.1 kurahone
88 1.1 kurahone #define pi1ppc_w_str(_x,_y)
89 1.1 kurahone #define pi1ppc_w_ctr(_x,_y) w_reg(AT_CTL_REG,_x,_y)
90 1.1 kurahone #define pi1ppc_w_dtr(_x,_y) w_reg(AT_DATA_REG,_x,_y)
91 1.1 kurahone
92 1.1 kurahone /* do we need to do these? */
93 1.1 kurahone #define pi1ppc_barrier_r(_x) bus_space_barrier(_x->sc_iot,_x->sc_ioh, \
94 1.1 kurahone 0,4,BUS_SPACE_BARRIER_READ)
95 1.1 kurahone #define pi1ppc_barrier_w(_x) bus_space_barrier(_x->sc_iot,_x->sc_ioh, \
96 1.1 kurahone 0,4,BUS_SPACE_BARRIER_WRITE)
97 1.1 kurahone #define pi1ppc_barrier(_x) pi1ppc_barrier_r(_x)
98 1.1 kurahone
99 1.1 kurahone /* Print function for config_found() */
100 1.1 kurahone static int pi1ppc_print(void *, const char *);
101 1.1 kurahone
102 1.1 kurahone /* Routines for ppbus interface (bus + device) */
103 1.3 cegger static int pi1ppc_read(device_t, char *, int, int, size_t *);
104 1.3 cegger static int pi1ppc_write(device_t, char *, int, int, size_t *);
105 1.3 cegger static int pi1ppc_setmode(device_t, int);
106 1.3 cegger static int pi1ppc_getmode(device_t);
107 1.3 cegger static int pi1ppc_exec_microseq(device_t, struct ppbus_microseq * *);
108 1.8 tsutsui static uint8_t pi1ppc_io(device_t, int, u_char *, int, u_char);
109 1.3 cegger static int pi1ppc_read_ivar(device_t, int, unsigned int *);
110 1.3 cegger static int pi1ppc_write_ivar(device_t, int, unsigned int *);
111 1.3 cegger static int pi1ppc_add_handler(device_t, void (*)(void *), void *);
112 1.3 cegger static int pi1ppc_remove_handler(device_t, void (*)(void *));
113 1.1 kurahone
114 1.1 kurahone /* no-ops, do any IOC machines have ECP/EPP-capable ports? */
115 1.3 cegger static void pi1ppc_reset_epp_timeout(device_t);
116 1.3 cegger static void pi1ppc_ecp_sync(device_t);
117 1.1 kurahone
118 1.1 kurahone /* Utility functions */
119 1.1 kurahone
120 1.1 kurahone /* Functions to read bytes into device's input buffer */
121 1.1 kurahone static void pi1ppc_nibble_read(struct pi1ppc_softc * const);
122 1.1 kurahone static void pi1ppc_byte_read(struct pi1ppc_softc * const);
123 1.1 kurahone
124 1.1 kurahone /* Functions to write bytes to device's output buffer */
125 1.1 kurahone static void pi1ppc_std_write(struct pi1ppc_softc * const);
126 1.1 kurahone
127 1.1 kurahone /* Miscellaneous */
128 1.8 tsutsui static void pi1ppc_set_intr_mask(struct pi1ppc_softc * const, uint8_t);
129 1.8 tsutsui static uint8_t pi1ppc_get_intr_stat(struct pi1ppc_softc * const);
130 1.1 kurahone
131 1.1 kurahone #ifdef USE_INDY_ACK_HACK
132 1.8 tsutsui static uint8_t pi1ppc_get_intr_mask(struct pi1ppc_softc * const);
133 1.1 kurahone #endif
134 1.1 kurahone
135 1.8 tsutsui static int pi1ppc_poll_str(struct pi1ppc_softc * const, const uint8_t,
136 1.8 tsutsui const uint8_t);
137 1.10 rmind static int pi1ppc_wait_interrupt(struct pi1ppc_softc * const, kcondvar_t *,
138 1.8 tsutsui const uint8_t);
139 1.1 kurahone
140 1.1 kurahone static int pi1ppc_poll_interrupt_stat(struct pi1ppc_softc * const,
141 1.8 tsutsui const uint8_t);
142 1.1 kurahone
143 1.3 cegger static int pi1ppc_match(device_t parent, cfdata_t match, void *aux);
144 1.3 cegger static void pi1ppc_attach(device_t parent, device_t self, void *aux);
145 1.1 kurahone
146 1.3 cegger CFATTACH_DECL_NEW(pi1ppc, sizeof(struct pi1ppc_softc),
147 1.1 kurahone pi1ppc_match,
148 1.1 kurahone pi1ppc_attach,
149 1.1 kurahone NULL,
150 1.1 kurahone NULL);
151 1.1 kurahone
152 1.1 kurahone /* Currently only matching on Indy, though I think the Indigo1 also
153 1.1 kurahone uses PI1. If it does, then the driver should work (if it is attached
154 1.1 kurahone at the appropriate base addr).
155 1.1 kurahone */
156 1.1 kurahone
157 1.1 kurahone static int
158 1.3 cegger pi1ppc_match(device_t parent, cfdata_t match, void *aux)
159 1.1 kurahone {
160 1.9 jmcneill struct hpc_attach_args *ha = aux;
161 1.9 jmcneill
162 1.9 jmcneill if (strcmp(ha->ha_name, match->cf_name) != 0)
163 1.9 jmcneill return 0;
164 1.9 jmcneill
165 1.1 kurahone if (mach_type == MACH_SGI_IP22)
166 1.1 kurahone return 1;
167 1.1 kurahone
168 1.1 kurahone return 0;
169 1.1 kurahone }
170 1.1 kurahone
171 1.1 kurahone static void
172 1.3 cegger pi1ppc_attach(device_t parent, device_t self, void *aux)
173 1.1 kurahone {
174 1.1 kurahone struct pi1ppc_softc *sc;
175 1.1 kurahone struct hpc_attach_args *haa;
176 1.1 kurahone
177 1.3 cegger sc = device_private(self);
178 1.4 cegger sc->sc_dev = self;
179 1.1 kurahone haa = aux;
180 1.1 kurahone sc->sc_iot = haa->ha_st;
181 1.1 kurahone
182 1.1 kurahone if (bus_space_subregion(haa->ha_st, haa->ha_sh, haa->ha_devoff,
183 1.1 kurahone 0x28, /* # bytes in par port regs */
184 1.1 kurahone &sc->sc_ioh)) {
185 1.1 kurahone aprint_error(": unable to map control registers\n");
186 1.1 kurahone return;
187 1.1 kurahone }
188 1.1 kurahone
189 1.1 kurahone pi1ppc_sc_attach(sc);
190 1.1 kurahone }
191 1.1 kurahone
192 1.1 kurahone /*
193 1.1 kurahone * Generic attach and detach functions for pi1ppc device.
194 1.1 kurahone *
195 1.1 kurahone * If sc_dev_ok in soft configuration data is not ATPPC_ATTACHED, these should
196 1.1 kurahone * be skipped altogether.
197 1.1 kurahone */
198 1.1 kurahone
199 1.1 kurahone /* Soft configuration attach for pi1ppc */
200 1.1 kurahone void
201 1.1 kurahone pi1ppc_sc_attach(struct pi1ppc_softc *lsc)
202 1.1 kurahone {
203 1.1 kurahone /* Adapter used to configure ppbus device */
204 1.1 kurahone struct parport_adapter sc_parport_adapter;
205 1.1 kurahone char buf[64];
206 1.1 kurahone
207 1.1 kurahone /* For a PC, this is where the installed chipset is probed.
208 1.1 kurahone * We *know* what we have, no need to probe.
209 1.1 kurahone */
210 1.1 kurahone lsc->sc_type = PI1PPC_TYPE_INDY;
211 1.1 kurahone lsc->sc_model = GENERIC;
212 1.1 kurahone
213 1.1 kurahone /* XXX Once we support Interrupts & DMA, update this */
214 1.1 kurahone lsc->sc_has = PI1PPC_HAS_PS2;
215 1.10 rmind
216 1.10 rmind mutex_init(&lsc->sc_lock, MUTEX_DEFAULT, IPL_TTY);
217 1.10 rmind cv_init(&lsc->sc_in_cv, "pi1ppcin");
218 1.10 rmind cv_init(&lsc->sc_out_cv, "pi1ppcou");
219 1.10 rmind
220 1.1 kurahone /* Print out chipset capabilities */
221 1.7 christos snprintb(buf, sizeof(buf), "\20\1INTR\2DMA\3FIFO\4PS2\5ECP\6EPP",
222 1.7 christos lsc->sc_has);
223 1.3 cegger printf("\n%s: capabilities=%s\n", device_xname(lsc->sc_dev), buf);
224 1.1 kurahone
225 1.1 kurahone /* Initialize device's buffer pointers */
226 1.1 kurahone lsc->sc_outb = lsc->sc_outbstart = lsc->sc_inb = lsc->sc_inbstart
227 1.1 kurahone = NULL;
228 1.1 kurahone lsc->sc_inb_nbytes = lsc->sc_outb_nbytes = 0;
229 1.1 kurahone
230 1.1 kurahone /* Last configuration step: set mode to standard mode */
231 1.6 cegger if (pi1ppc_setmode(lsc->sc_dev, PPBUS_COMPATIBLE) != 0) {
232 1.1 kurahone PI1PPC_DPRINTF(("%s: unable to initialize mode.\n",
233 1.10 rmind device_xname(lsc->sc_dev)));
234 1.1 kurahone }
235 1.1 kurahone
236 1.1 kurahone /* Set up parport_adapter structure */
237 1.1 kurahone
238 1.1 kurahone /* Set capabilites */
239 1.1 kurahone sc_parport_adapter.capabilities = 0;
240 1.1 kurahone if (lsc->sc_has & PI1PPC_HAS_INTR) {
241 1.1 kurahone sc_parport_adapter.capabilities |= PPBUS_HAS_INTR;
242 1.1 kurahone }
243 1.1 kurahone if (lsc->sc_has & PI1PPC_HAS_DMA) {
244 1.1 kurahone sc_parport_adapter.capabilities |= PPBUS_HAS_DMA;
245 1.1 kurahone }
246 1.1 kurahone if (lsc->sc_has & PI1PPC_HAS_FIFO) {
247 1.1 kurahone sc_parport_adapter.capabilities |= PPBUS_HAS_FIFO;
248 1.1 kurahone }
249 1.1 kurahone if (lsc->sc_has & PI1PPC_HAS_PS2) {
250 1.1 kurahone sc_parport_adapter.capabilities |= PPBUS_HAS_PS2;
251 1.1 kurahone }
252 1.1 kurahone
253 1.1 kurahone /* Set function pointers */
254 1.1 kurahone sc_parport_adapter.parport_io = pi1ppc_io;
255 1.1 kurahone sc_parport_adapter.parport_exec_microseq = pi1ppc_exec_microseq;
256 1.1 kurahone sc_parport_adapter.parport_setmode = pi1ppc_setmode;
257 1.1 kurahone sc_parport_adapter.parport_getmode = pi1ppc_getmode;
258 1.1 kurahone sc_parport_adapter.parport_read = pi1ppc_read;
259 1.1 kurahone sc_parport_adapter.parport_write = pi1ppc_write;
260 1.1 kurahone sc_parport_adapter.parport_read_ivar = pi1ppc_read_ivar;
261 1.1 kurahone sc_parport_adapter.parport_write_ivar = pi1ppc_write_ivar;
262 1.1 kurahone sc_parport_adapter.parport_dma_malloc = lsc->sc_dma_malloc;
263 1.1 kurahone sc_parport_adapter.parport_dma_free = lsc->sc_dma_free;
264 1.1 kurahone sc_parport_adapter.parport_add_handler = pi1ppc_add_handler;
265 1.1 kurahone sc_parport_adapter.parport_remove_handler = pi1ppc_remove_handler;
266 1.1 kurahone
267 1.1 kurahone /* these are no-ops (does later machines have ECP/EPP support?) */
268 1.1 kurahone sc_parport_adapter.parport_ecp_sync = pi1ppc_ecp_sync;
269 1.1 kurahone sc_parport_adapter.parport_reset_epp_timeout =
270 1.1 kurahone pi1ppc_reset_epp_timeout;
271 1.1 kurahone
272 1.1 kurahone /* Initialize handler list, may be added to by grandchildren */
273 1.1 kurahone SLIST_INIT(&(lsc->sc_handler_listhead));
274 1.1 kurahone
275 1.1 kurahone /* Initialize interrupt state */
276 1.1 kurahone lsc->sc_irqstat = PI1PPC_IRQ_NONE;
277 1.1 kurahone lsc->sc_ecr_intr = lsc->sc_ctr_intr = lsc->sc_str_intr = 0;
278 1.1 kurahone
279 1.1 kurahone /* Disable DMA/interrupts (each ppbus driver selects usage itself) */
280 1.1 kurahone lsc->sc_use = 0;
281 1.1 kurahone
282 1.1 kurahone /* Configure child of the device. */
283 1.6 cegger lsc->child = config_found(lsc->sc_dev, &(sc_parport_adapter),
284 1.1 kurahone pi1ppc_print);
285 1.1 kurahone
286 1.1 kurahone return;
287 1.1 kurahone }
288 1.1 kurahone
289 1.1 kurahone /* Soft configuration detach */
290 1.1 kurahone int
291 1.1 kurahone pi1ppc_sc_detach(struct pi1ppc_softc *lsc, int flag)
292 1.1 kurahone {
293 1.3 cegger device_t dev = lsc->sc_dev;
294 1.1 kurahone
295 1.1 kurahone /* Detach children devices */
296 1.1 kurahone if (config_detach(lsc->child, flag) && !(flag & DETACH_QUIET)) {
297 1.3 cegger printf("%s not able to detach child device, ", device_xname(dev));
298 1.1 kurahone
299 1.1 kurahone if (!(flag & DETACH_FORCE)) {
300 1.1 kurahone printf("cannot detach\n");
301 1.1 kurahone return 1;
302 1.1 kurahone } else {
303 1.1 kurahone printf("continuing (DETACH_FORCE)\n");
304 1.1 kurahone }
305 1.1 kurahone }
306 1.1 kurahone if (!(flag & DETACH_QUIET))
307 1.3 cegger printf("%s detached", device_xname(dev));
308 1.1 kurahone
309 1.10 rmind mutex_destroy(&lsc->sc_lock);
310 1.10 rmind cv_destroy(&lsc->sc_in_cv);
311 1.10 rmind cv_destroy(&lsc->sc_out_cv);
312 1.1 kurahone return 0;
313 1.1 kurahone }
314 1.1 kurahone
315 1.1 kurahone /* Used by config_found() to print out device information */
316 1.1 kurahone static int
317 1.1 kurahone pi1ppc_print(void *aux, const char *name)
318 1.1 kurahone {
319 1.1 kurahone /* Print out something on failure. */
320 1.1 kurahone if (name != NULL) {
321 1.1 kurahone printf("%s: child devices", name);
322 1.1 kurahone return UNCONF;
323 1.1 kurahone }
324 1.1 kurahone
325 1.1 kurahone return QUIET;
326 1.1 kurahone }
327 1.1 kurahone
328 1.1 kurahone /* Interrupt handler for pi1ppc device: wakes up read/write functions */
329 1.1 kurahone int
330 1.1 kurahone pi1ppcintr(void *arg)
331 1.1 kurahone {
332 1.1 kurahone /* NO INTERRUPTS YET */
333 1.1 kurahone #if 0
334 1.5 cegger device_t dev = arg;
335 1.5 cegger struct pi1ppc_softc *pi1ppc = device_private(dev);
336 1.1 kurahone int claim = 1;
337 1.1 kurahone enum { NONE, READER, WRITER } wake_up = NONE;
338 1.1 kurahone
339 1.1 kurahone PI1PPC_LOCK(pi1ppc);
340 1.1 kurahone
341 1.1 kurahone /* Record registers' status */
342 1.1 kurahone pi1ppc->sc_str_intr = pi1ppc_r_str(pi1ppc);
343 1.1 kurahone pi1ppc->sc_ctr_intr = pi1ppc_r_ctr(pi1ppc);
344 1.1 kurahone pi1ppc_barrier_r(pi1ppc);
345 1.1 kurahone
346 1.1 kurahone /* Determine cause of interrupt and wake up top half */
347 1.1 kurahone switch (atppc->sc_mode) {
348 1.1 kurahone case ATPPC_MODE_STD:
349 1.1 kurahone /* nAck pulsed for 5 usec, too fast to check reliably, assume */
350 1.1 kurahone atppc->sc_irqstat = ATPPC_IRQ_nACK;
351 1.1 kurahone if (atppc->sc_outb)
352 1.1 kurahone wake_up = WRITER;
353 1.1 kurahone else
354 1.1 kurahone claim = 0;
355 1.1 kurahone break;
356 1.1 kurahone
357 1.1 kurahone case ATPPC_MODE_NIBBLE:
358 1.1 kurahone case ATPPC_MODE_PS2:
359 1.1 kurahone /* nAck is set low by device and then high on ack */
360 1.1 kurahone if (!(atppc->sc_str_intr & nACK)) {
361 1.1 kurahone claim = 0;
362 1.1 kurahone break;
363 1.1 kurahone }
364 1.1 kurahone atppc->sc_irqstat = ATPPC_IRQ_nACK;
365 1.1 kurahone if (atppc->sc_inb)
366 1.1 kurahone wake_up = READER;
367 1.1 kurahone break;
368 1.1 kurahone
369 1.1 kurahone case ATPPC_MODE_ECP:
370 1.1 kurahone case ATPPC_MODE_FAST:
371 1.1 kurahone /* Confirm interrupt cause: these are not pulsed as in nAck. */
372 1.1 kurahone if (atppc->sc_ecr_intr & ATPPC_SERVICE_INTR) {
373 1.1 kurahone if (atppc->sc_ecr_intr & ATPPC_ENABLE_DMA)
374 1.1 kurahone atppc->sc_irqstat |= ATPPC_IRQ_DMA;
375 1.1 kurahone else
376 1.1 kurahone atppc->sc_irqstat |= ATPPC_IRQ_FIFO;
377 1.1 kurahone
378 1.1 kurahone /* Decide where top half will be waiting */
379 1.1 kurahone if (atppc->sc_mode & ATPPC_MODE_ECP) {
380 1.1 kurahone if (atppc->sc_ctr_intr & PCD) {
381 1.1 kurahone if (atppc->sc_inb)
382 1.1 kurahone wake_up = READER;
383 1.1 kurahone else
384 1.1 kurahone claim = 0;
385 1.1 kurahone } else {
386 1.1 kurahone if (atppc->sc_outb)
387 1.1 kurahone wake_up = WRITER;
388 1.1 kurahone else
389 1.1 kurahone claim = 0;
390 1.1 kurahone }
391 1.1 kurahone } else {
392 1.1 kurahone if (atppc->sc_outb)
393 1.1 kurahone wake_up = WRITER;
394 1.1 kurahone else
395 1.1 kurahone claim = 0;
396 1.1 kurahone }
397 1.1 kurahone }
398 1.1 kurahone /* Determine if nFault has occurred */
399 1.1 kurahone if ((atppc->sc_mode & ATPPC_MODE_ECP) &&
400 1.1 kurahone (atppc->sc_ecr_intr & ATPPC_nFAULT_INTR) &&
401 1.1 kurahone !(atppc->sc_str_intr & nFAULT)) {
402 1.1 kurahone
403 1.1 kurahone /* Device is requesting the channel */
404 1.1 kurahone atppc->sc_irqstat |= ATPPC_IRQ_nFAULT;
405 1.1 kurahone claim = 1;
406 1.1 kurahone }
407 1.1 kurahone break;
408 1.1 kurahone
409 1.1 kurahone case ATPPC_MODE_EPP:
410 1.1 kurahone /* nAck pulsed for 5 usec, too fast to check reliably */
411 1.1 kurahone atppc->sc_irqstat = ATPPC_IRQ_nACK;
412 1.1 kurahone if (atppc->sc_inb)
413 1.1 kurahone wake_up = WRITER;
414 1.1 kurahone else if (atppc->sc_outb)
415 1.1 kurahone wake_up = READER;
416 1.1 kurahone else
417 1.1 kurahone claim = 0;
418 1.1 kurahone break;
419 1.1 kurahone
420 1.1 kurahone default:
421 1.3 cegger panic("%s: chipset is in invalid mode.", device_xname(dev));
422 1.1 kurahone }
423 1.1 kurahone
424 1.1 kurahone if (claim) {
425 1.1 kurahone switch (wake_up) {
426 1.1 kurahone case NONE:
427 1.1 kurahone break;
428 1.1 kurahone
429 1.1 kurahone case READER:
430 1.10 rmind cv_broadcast(atppc->sc_in_cv);
431 1.1 kurahone break;
432 1.1 kurahone
433 1.1 kurahone case WRITER:
434 1.10 rmind cv_broadcast(atppc->sc_out_cv);
435 1.1 kurahone break;
436 1.1 kurahone }
437 1.1 kurahone }
438 1.1 kurahone
439 1.1 kurahone /* Call all of the installed handlers */
440 1.1 kurahone if (claim) {
441 1.1 kurahone struct atppc_handler_node * callback;
442 1.1 kurahone SLIST_FOREACH(callback, &(atppc->sc_handler_listhead),
443 1.1 kurahone entries) {
444 1.1 kurahone (*callback->func)(callback->arg);
445 1.1 kurahone }
446 1.1 kurahone }
447 1.10 rmind PI1PPC_UNLOCK(atppc);
448 1.1 kurahone
449 1.1 kurahone return claim;
450 1.1 kurahone #else
451 1.1 kurahone return 0; /* NO INTERRUPTS YET */
452 1.1 kurahone #endif
453 1.1 kurahone }
454 1.1 kurahone
455 1.1 kurahone /* Functions which support ppbus interface */
456 1.1 kurahone
457 1.1 kurahone static void
458 1.3 cegger pi1ppc_reset_epp_timeout(device_t dev)
459 1.1 kurahone {
460 1.1 kurahone return;
461 1.1 kurahone }
462 1.1 kurahone
463 1.1 kurahone /* Read from pi1ppc device: returns 0 on success. */
464 1.1 kurahone static int
465 1.3 cegger pi1ppc_read(device_t dev, char *buf, int len, int ioflag,
466 1.1 kurahone size_t *cnt)
467 1.1 kurahone {
468 1.6 cegger struct pi1ppc_softc *pi1ppc = device_private(dev);
469 1.1 kurahone int error = 0;
470 1.1 kurahone
471 1.1 kurahone PI1PPC_LOCK(pi1ppc);
472 1.1 kurahone
473 1.1 kurahone *cnt = 0;
474 1.1 kurahone
475 1.1 kurahone /* Initialize buffer */
476 1.1 kurahone pi1ppc->sc_inb = pi1ppc->sc_inbstart = buf;
477 1.1 kurahone pi1ppc->sc_inb_nbytes = len;
478 1.1 kurahone
479 1.1 kurahone /* Initialize device input error state for new operation */
480 1.1 kurahone pi1ppc->sc_inerr = 0;
481 1.1 kurahone
482 1.1 kurahone /* Call appropriate function to read bytes */
483 1.1 kurahone switch(pi1ppc->sc_mode) {
484 1.1 kurahone case PI1PPC_MODE_STD:
485 1.1 kurahone error = ENODEV;
486 1.1 kurahone break;
487 1.1 kurahone
488 1.1 kurahone case PI1PPC_MODE_NIBBLE:
489 1.1 kurahone pi1ppc_nibble_read(pi1ppc);
490 1.1 kurahone break;
491 1.1 kurahone
492 1.1 kurahone case PI1PPC_MODE_PS2:
493 1.1 kurahone pi1ppc_byte_read(pi1ppc);
494 1.1 kurahone break;
495 1.1 kurahone
496 1.1 kurahone default:
497 1.1 kurahone panic("%s(%s): chipset in invalid mode.\n", __func__,
498 1.3 cegger device_xname(dev));
499 1.1 kurahone }
500 1.1 kurahone
501 1.1 kurahone /* Update counter*/
502 1.1 kurahone *cnt = (pi1ppc->sc_inbstart - pi1ppc->sc_inb);
503 1.1 kurahone
504 1.1 kurahone /* Reset buffer */
505 1.1 kurahone pi1ppc->sc_inb = pi1ppc->sc_inbstart = NULL;
506 1.1 kurahone pi1ppc->sc_inb_nbytes = 0;
507 1.1 kurahone
508 1.1 kurahone if (!(error))
509 1.1 kurahone error = pi1ppc->sc_inerr;
510 1.1 kurahone
511 1.1 kurahone PI1PPC_UNLOCK(pi1ppc);
512 1.1 kurahone
513 1.1 kurahone return (error);
514 1.1 kurahone }
515 1.1 kurahone
516 1.1 kurahone /* Write to pi1ppc device: returns 0 on success. */
517 1.1 kurahone static int
518 1.3 cegger pi1ppc_write(device_t dev, char *buf, int len, int ioflag, size_t *cnt)
519 1.1 kurahone {
520 1.6 cegger struct pi1ppc_softc * const pi1ppc = device_private(dev);
521 1.1 kurahone int error = 0;
522 1.1 kurahone
523 1.1 kurahone *cnt = 0;
524 1.1 kurahone
525 1.1 kurahone PI1PPC_LOCK(pi1ppc);
526 1.1 kurahone
527 1.1 kurahone /* Set up line buffer */
528 1.1 kurahone pi1ppc->sc_outb = pi1ppc->sc_outbstart = buf;
529 1.1 kurahone pi1ppc->sc_outb_nbytes = len;
530 1.1 kurahone
531 1.1 kurahone /* Initialize device output error state for new operation */
532 1.1 kurahone pi1ppc->sc_outerr = 0;
533 1.1 kurahone
534 1.1 kurahone /* Call appropriate function to write bytes */
535 1.1 kurahone switch (pi1ppc->sc_mode) {
536 1.1 kurahone case PI1PPC_MODE_STD:
537 1.1 kurahone pi1ppc_std_write(pi1ppc);
538 1.1 kurahone break;
539 1.1 kurahone
540 1.1 kurahone case PI1PPC_MODE_NIBBLE:
541 1.1 kurahone case PI1PPC_MODE_PS2:
542 1.1 kurahone error = ENODEV;
543 1.1 kurahone break;
544 1.1 kurahone
545 1.1 kurahone default:
546 1.1 kurahone panic("%s(%s): chipset in invalid mode.\n", __func__,
547 1.3 cegger device_xname(dev));
548 1.1 kurahone }
549 1.1 kurahone
550 1.1 kurahone /* Update counter*/
551 1.1 kurahone *cnt = (pi1ppc->sc_outbstart - pi1ppc->sc_outb);
552 1.1 kurahone
553 1.1 kurahone /* Reset output buffer */
554 1.1 kurahone pi1ppc->sc_outb = pi1ppc->sc_outbstart = NULL;
555 1.1 kurahone pi1ppc->sc_outb_nbytes = 0;
556 1.1 kurahone
557 1.1 kurahone if (!(error))
558 1.1 kurahone error = pi1ppc->sc_outerr;
559 1.1 kurahone
560 1.1 kurahone PI1PPC_UNLOCK(pi1ppc);
561 1.1 kurahone
562 1.1 kurahone return (error);
563 1.1 kurahone }
564 1.1 kurahone
565 1.1 kurahone /*
566 1.1 kurahone * Set mode of chipset to mode argument. Modes not supported are ignored. If
567 1.1 kurahone * multiple modes are flagged, the mode is not changed. Modes are those
568 1.1 kurahone * defined for ppbus_softc.sc_mode in ppbus_conf.h. Only ECP-capable chipsets
569 1.1 kurahone * can change their mode of operation. However, ALL operation modes support
570 1.1 kurahone * centronics mode and nibble mode. Modes determine both hardware AND software
571 1.1 kurahone * behaviour.
572 1.1 kurahone * NOTE: the mode for ECP should only be changed when the channel is in
573 1.1 kurahone * forward idle mode. This function does not make sure FIFO's have flushed or
574 1.1 kurahone * any consistency checks.
575 1.1 kurahone */
576 1.1 kurahone static int
577 1.3 cegger pi1ppc_setmode(device_t dev, int mode)
578 1.1 kurahone {
579 1.6 cegger struct pi1ppc_softc *pi1ppc = device_private(dev);
580 1.8 tsutsui uint8_t ecr;
581 1.8 tsutsui uint8_t chipset_mode;
582 1.1 kurahone int rval = 0;
583 1.1 kurahone
584 1.1 kurahone PI1PPC_LOCK(pi1ppc);
585 1.1 kurahone
586 1.1 kurahone switch (mode) {
587 1.1 kurahone case PPBUS_PS2:
588 1.1 kurahone /* Indy has this, other PI1 machines do too? */
589 1.1 kurahone chipset_mode = PI1PPC_MODE_PS2;
590 1.1 kurahone break;
591 1.1 kurahone
592 1.1 kurahone case PPBUS_NIBBLE:
593 1.1 kurahone /* Set nibble mode (virtual) */
594 1.1 kurahone chipset_mode = PI1PPC_MODE_NIBBLE;
595 1.1 kurahone break;
596 1.1 kurahone
597 1.1 kurahone case PPBUS_COMPATIBLE:
598 1.1 kurahone chipset_mode = PI1PPC_MODE_STD;
599 1.1 kurahone break;
600 1.1 kurahone
601 1.1 kurahone case PPBUS_ECP:
602 1.1 kurahone case PPBUS_EPP:
603 1.1 kurahone rval = ENODEV;
604 1.1 kurahone goto end;
605 1.1 kurahone
606 1.1 kurahone default:
607 1.1 kurahone PI1PPC_DPRINTF(("%s(%s): invalid mode passed as "
608 1.3 cegger "argument.\n", __func__, device_xname(dev)));
609 1.1 kurahone rval = ENODEV;
610 1.1 kurahone goto end;
611 1.1 kurahone }
612 1.1 kurahone
613 1.1 kurahone pi1ppc->sc_mode = chipset_mode;
614 1.1 kurahone if (chipset_mode == PI1PPC_MODE_PS2) {
615 1.1 kurahone /* Set direction bit to reverse */
616 1.1 kurahone ecr = pi1ppc_r_ctr(pi1ppc);
617 1.1 kurahone pi1ppc_barrier_r(pi1ppc);
618 1.1 kurahone ecr |= PCD; /* data is INPUT */
619 1.1 kurahone pi1ppc_w_ctr(pi1ppc, ecr);
620 1.1 kurahone pi1ppc_barrier_w(pi1ppc);
621 1.1 kurahone }
622 1.1 kurahone
623 1.1 kurahone end:
624 1.1 kurahone PI1PPC_UNLOCK(pi1ppc);
625 1.1 kurahone
626 1.1 kurahone return rval;
627 1.1 kurahone }
628 1.1 kurahone
629 1.1 kurahone /* Get the current mode of chipset */
630 1.1 kurahone static int
631 1.3 cegger pi1ppc_getmode(device_t dev)
632 1.1 kurahone {
633 1.3 cegger struct pi1ppc_softc *pi1ppc = device_private(dev);
634 1.1 kurahone int mode;
635 1.1 kurahone
636 1.1 kurahone PI1PPC_LOCK(pi1ppc);
637 1.1 kurahone
638 1.1 kurahone /* The chipset can only be in one mode at a time logically */
639 1.1 kurahone switch (pi1ppc->sc_mode) {
640 1.1 kurahone case PI1PPC_MODE_PS2:
641 1.1 kurahone mode = PPBUS_PS2;
642 1.1 kurahone break;
643 1.1 kurahone
644 1.1 kurahone case PI1PPC_MODE_STD:
645 1.1 kurahone mode = PPBUS_COMPATIBLE;
646 1.1 kurahone break;
647 1.1 kurahone
648 1.1 kurahone case PI1PPC_MODE_NIBBLE:
649 1.1 kurahone mode = PPBUS_NIBBLE;
650 1.1 kurahone break;
651 1.1 kurahone
652 1.1 kurahone default:
653 1.1 kurahone panic("%s(%s): device is in invalid mode!", __func__,
654 1.3 cegger device_xname(dev));
655 1.1 kurahone break;
656 1.1 kurahone }
657 1.1 kurahone
658 1.1 kurahone PI1PPC_UNLOCK(pi1ppc);
659 1.1 kurahone
660 1.1 kurahone return mode;
661 1.1 kurahone }
662 1.1 kurahone
663 1.1 kurahone
664 1.1 kurahone /* Wait for FIFO buffer to empty for ECP-capable chipset */
665 1.1 kurahone static void
666 1.3 cegger pi1ppc_ecp_sync(device_t dev)
667 1.1 kurahone {
668 1.1 kurahone return;
669 1.1 kurahone }
670 1.1 kurahone
671 1.1 kurahone /* Execute a microsequence to handle fast I/O operations. */
672 1.1 kurahone
673 1.1 kurahone /* microsequence registers are equivalent to PC-like port registers */
674 1.1 kurahone /* therefore, translate bit positions & polarities */
675 1.1 kurahone
676 1.1 kurahone /* Bit 4 of ctl_reg_int_en is used to emulate the PC's int enable
677 1.1 kurahone bit. Without it, lpt doesn't like the port.
678 1.1 kurahone */
679 1.8 tsutsui static uint8_t ctl_reg_int_en = 0;
680 1.1 kurahone
681 1.8 tsutsui static uint8_t
682 1.1 kurahone r_reg(int reg, struct pi1ppc_softc *pi1ppc)
683 1.1 kurahone {
684 1.1 kurahone int val = 0;
685 1.1 kurahone
686 1.1 kurahone /* if we read the status reg, make it look like the PC */
687 1.1 kurahone if(reg == AT_STAT_REG) {
688 1.1 kurahone val = bus_space_read_4((pi1ppc)->sc_iot,
689 1.1 kurahone (pi1ppc)->sc_ioh, IOC_PLP_STAT);
690 1.1 kurahone val &= 0xff;
691 1.1 kurahone
692 1.1 kurahone /* invert /BUSY */
693 1.1 kurahone val ^= 0x80;
694 1.1 kurahone
695 1.1 kurahone /* bit 2 reads as '1' on Indy (why?) */
696 1.1 kurahone val &= 0xf8;
697 1.1 kurahone
698 1.1 kurahone return val;
699 1.1 kurahone }
700 1.1 kurahone
701 1.1 kurahone /* if we read the ctl reg, make it look like the PC */
702 1.1 kurahone if(reg == AT_CTL_REG) {
703 1.1 kurahone val = bus_space_read_4((pi1ppc)->sc_iot,
704 1.1 kurahone (pi1ppc)->sc_ioh, IOC_PLP_CTL);
705 1.1 kurahone val &= 0xff;
706 1.1 kurahone
707 1.1 kurahone /* get the dir bit in the right place */
708 1.1 kurahone val = ((val >> 1) & 0x20) | (val & 0x0f);
709 1.1 kurahone
710 1.1 kurahone /* invert /SEL, /AUTOFD, and /STB */
711 1.1 kurahone val ^= 0x0b;
712 1.1 kurahone
713 1.1 kurahone /* emulate the PC's int enable ctl bit */
714 1.1 kurahone val |= (ctl_reg_int_en & 0x10);
715 1.1 kurahone
716 1.1 kurahone return val;
717 1.1 kurahone }
718 1.1 kurahone
719 1.1 kurahone if(reg == AT_DATA_REG) {
720 1.1 kurahone val = bus_space_read_4((pi1ppc)->sc_iot,
721 1.1 kurahone (pi1ppc)->sc_ioh, IOC_PLP_DATA);
722 1.1 kurahone val &= 0xff;
723 1.1 kurahone
724 1.1 kurahone return val;
725 1.1 kurahone }
726 1.1 kurahone
727 1.1 kurahone return 0;
728 1.1 kurahone }
729 1.1 kurahone
730 1.1 kurahone static void
731 1.8 tsutsui w_reg(int reg, struct pi1ppc_softc *pi1ppc, uint8_t byte)
732 1.1 kurahone {
733 1.1 kurahone /* don't try to write to the status reg */
734 1.1 kurahone
735 1.1 kurahone /* if we are writing the ctl reg, adjust PC style -> IOC style */
736 1.1 kurahone if(reg == AT_CTL_REG) {
737 1.1 kurahone /* preserve pc-style int enable bit */
738 1.1 kurahone ctl_reg_int_en = (byte & 0x10);
739 1.1 kurahone
740 1.1 kurahone /* get the dir bit in the right place */
741 1.1 kurahone byte = ((byte << 1) & 0x40) | (byte & 0x0f);
742 1.1 kurahone
743 1.1 kurahone /* invert /SEL, /AUTOFD, and /STB */
744 1.1 kurahone byte ^= 0x0b;
745 1.1 kurahone
746 1.1 kurahone bus_space_write_4((pi1ppc)->sc_iot,
747 1.1 kurahone (pi1ppc)->sc_ioh, IOC_PLP_CTL, byte);
748 1.1 kurahone }
749 1.1 kurahone
750 1.1 kurahone if(reg == AT_DATA_REG) {
751 1.1 kurahone bus_space_write_4((pi1ppc)->sc_iot,
752 1.1 kurahone (pi1ppc)->sc_ioh, IOC_PLP_DATA, byte);
753 1.1 kurahone }
754 1.1 kurahone }
755 1.1 kurahone
756 1.1 kurahone static int
757 1.3 cegger pi1ppc_exec_microseq(device_t dev, struct ppbus_microseq **p_msq)
758 1.1 kurahone {
759 1.3 cegger struct pi1ppc_softc *pi1ppc = device_private(dev);
760 1.1 kurahone struct ppbus_microseq *mi = *p_msq;
761 1.1 kurahone char cc, *p;
762 1.1 kurahone int i, iter, len;
763 1.1 kurahone int error;
764 1.1 kurahone register int reg;
765 1.1 kurahone register unsigned char mask;
766 1.1 kurahone register int accum = 0;
767 1.1 kurahone register char *ptr = NULL;
768 1.1 kurahone struct ppbus_microseq *stack = NULL;
769 1.1 kurahone
770 1.1 kurahone PI1PPC_LOCK(pi1ppc);
771 1.1 kurahone
772 1.1 kurahone /* Loop until microsequence execution finishes (ending op code) */
773 1.1 kurahone for (;;) {
774 1.1 kurahone switch (mi->opcode) {
775 1.1 kurahone case MS_OP_RSET:
776 1.1 kurahone cc = r_reg(mi->arg[0].i, pi1ppc);
777 1.1 kurahone pi1ppc_barrier_r(pi1ppc);
778 1.1 kurahone cc &= (char)mi->arg[2].i; /* clear mask */
779 1.1 kurahone cc |= (char)mi->arg[1].i; /* assert mask */
780 1.1 kurahone w_reg(mi->arg[0].i, pi1ppc, cc);
781 1.1 kurahone pi1ppc_barrier_w(pi1ppc);
782 1.1 kurahone mi++;
783 1.1 kurahone break;
784 1.1 kurahone
785 1.1 kurahone case MS_OP_RASSERT_P:
786 1.1 kurahone reg = mi->arg[1].i;
787 1.1 kurahone ptr = pi1ppc->sc_ptr;
788 1.1 kurahone
789 1.1 kurahone if ((len = mi->arg[0].i) == MS_ACCUM) {
790 1.1 kurahone accum = pi1ppc->sc_accum;
791 1.1 kurahone for (; accum; accum--) {
792 1.1 kurahone w_reg(reg, pi1ppc, *ptr++);
793 1.1 kurahone pi1ppc_barrier_w(pi1ppc);
794 1.1 kurahone }
795 1.1 kurahone pi1ppc->sc_accum = accum;
796 1.1 kurahone } else {
797 1.1 kurahone for (i = 0; i < len; i++) {
798 1.1 kurahone w_reg(reg, pi1ppc, *ptr++);
799 1.1 kurahone pi1ppc_barrier_w(pi1ppc);
800 1.1 kurahone }
801 1.1 kurahone }
802 1.1 kurahone
803 1.1 kurahone pi1ppc->sc_ptr = ptr;
804 1.1 kurahone mi++;
805 1.1 kurahone break;
806 1.1 kurahone
807 1.1 kurahone case MS_OP_RFETCH_P:
808 1.1 kurahone reg = mi->arg[1].i;
809 1.1 kurahone mask = (char)mi->arg[2].i;
810 1.1 kurahone ptr = pi1ppc->sc_ptr;
811 1.1 kurahone
812 1.1 kurahone if ((len = mi->arg[0].i) == MS_ACCUM) {
813 1.1 kurahone accum = pi1ppc->sc_accum;
814 1.1 kurahone for (; accum; accum--) {
815 1.1 kurahone *ptr++ = r_reg(reg, pi1ppc) & mask;
816 1.1 kurahone pi1ppc_barrier_r(pi1ppc);
817 1.1 kurahone }
818 1.1 kurahone pi1ppc->sc_accum = accum;
819 1.1 kurahone } else {
820 1.1 kurahone for (i = 0; i < len; i++) {
821 1.1 kurahone *ptr++ = r_reg(reg, pi1ppc) & mask;
822 1.1 kurahone pi1ppc_barrier_r(pi1ppc);
823 1.1 kurahone }
824 1.1 kurahone }
825 1.1 kurahone
826 1.1 kurahone pi1ppc->sc_ptr = ptr;
827 1.1 kurahone mi++;
828 1.1 kurahone break;
829 1.1 kurahone
830 1.1 kurahone case MS_OP_RFETCH:
831 1.1 kurahone *((char *)mi->arg[2].p) = r_reg(mi->arg[0].i, pi1ppc) &
832 1.1 kurahone (char)mi->arg[1].i;
833 1.1 kurahone pi1ppc_barrier_r(pi1ppc);
834 1.1 kurahone mi++;
835 1.1 kurahone break;
836 1.1 kurahone
837 1.1 kurahone case MS_OP_RASSERT:
838 1.1 kurahone case MS_OP_DELAY:
839 1.1 kurahone /* let's suppose the next instr. is the same */
840 1.1 kurahone do {
841 1.1 kurahone for (;mi->opcode == MS_OP_RASSERT; mi++) {
842 1.1 kurahone w_reg(mi->arg[0].i, pi1ppc,
843 1.1 kurahone (char)mi->arg[1].i);
844 1.1 kurahone pi1ppc_barrier_w(pi1ppc);
845 1.1 kurahone }
846 1.1 kurahone
847 1.1 kurahone for (;mi->opcode == MS_OP_DELAY; mi++) {
848 1.1 kurahone delay(mi->arg[0].i);
849 1.1 kurahone }
850 1.1 kurahone } while (mi->opcode == MS_OP_RASSERT);
851 1.1 kurahone break;
852 1.1 kurahone
853 1.1 kurahone case MS_OP_ADELAY:
854 1.1 kurahone if (mi->arg[0].i) {
855 1.10 rmind DELAY(mi->arg[0].i * 1000);
856 1.1 kurahone }
857 1.1 kurahone mi++;
858 1.1 kurahone break;
859 1.1 kurahone
860 1.1 kurahone case MS_OP_TRIG:
861 1.1 kurahone reg = mi->arg[0].i;
862 1.1 kurahone iter = mi->arg[1].i;
863 1.1 kurahone p = (char *)mi->arg[2].p;
864 1.1 kurahone
865 1.1 kurahone /* XXX delay limited to 255 us */
866 1.1 kurahone for (i = 0; i < iter; i++) {
867 1.1 kurahone w_reg(reg, pi1ppc, *p++);
868 1.1 kurahone pi1ppc_barrier_w(pi1ppc);
869 1.1 kurahone delay((unsigned char)*p++);
870 1.1 kurahone }
871 1.1 kurahone
872 1.1 kurahone mi++;
873 1.1 kurahone break;
874 1.1 kurahone
875 1.1 kurahone case MS_OP_SET:
876 1.1 kurahone pi1ppc->sc_accum = mi->arg[0].i;
877 1.1 kurahone mi++;
878 1.1 kurahone break;
879 1.1 kurahone
880 1.1 kurahone case MS_OP_DBRA:
881 1.1 kurahone if (--pi1ppc->sc_accum > 0) {
882 1.1 kurahone mi += mi->arg[0].i;
883 1.1 kurahone }
884 1.1 kurahone
885 1.1 kurahone mi++;
886 1.1 kurahone break;
887 1.1 kurahone
888 1.1 kurahone case MS_OP_BRSET:
889 1.1 kurahone cc = pi1ppc_r_str(pi1ppc);
890 1.1 kurahone pi1ppc_barrier_r(pi1ppc);
891 1.1 kurahone if ((cc & (char)mi->arg[0].i) == (char)mi->arg[0].i) {
892 1.1 kurahone mi += mi->arg[1].i;
893 1.1 kurahone }
894 1.1 kurahone mi++;
895 1.1 kurahone break;
896 1.1 kurahone
897 1.1 kurahone case MS_OP_BRCLEAR:
898 1.1 kurahone cc = pi1ppc_r_str(pi1ppc);
899 1.1 kurahone pi1ppc_barrier_r(pi1ppc);
900 1.1 kurahone if ((cc & (char)mi->arg[0].i) == 0) {
901 1.1 kurahone mi += mi->arg[1].i;
902 1.1 kurahone }
903 1.1 kurahone mi++;
904 1.1 kurahone break;
905 1.1 kurahone
906 1.1 kurahone case MS_OP_BRSTAT:
907 1.1 kurahone cc = pi1ppc_r_str(pi1ppc);
908 1.1 kurahone pi1ppc_barrier_r(pi1ppc);
909 1.1 kurahone if ((cc & ((char)mi->arg[0].i | (char)mi->arg[1].i)) ==
910 1.1 kurahone (char)mi->arg[0].i) {
911 1.1 kurahone mi += mi->arg[2].i;
912 1.1 kurahone }
913 1.1 kurahone mi++;
914 1.1 kurahone break;
915 1.1 kurahone
916 1.1 kurahone case MS_OP_C_CALL:
917 1.1 kurahone /*
918 1.1 kurahone * If the C call returns !0 then end the microseq.
919 1.1 kurahone * The current state of ptr is passed to the C function
920 1.1 kurahone */
921 1.1 kurahone if ((error = mi->arg[0].f(mi->arg[1].p,
922 1.1 kurahone pi1ppc->sc_ptr))) {
923 1.1 kurahone PI1PPC_UNLOCK(pi1ppc);
924 1.1 kurahone return (error);
925 1.1 kurahone }
926 1.1 kurahone mi++;
927 1.1 kurahone break;
928 1.1 kurahone
929 1.1 kurahone case MS_OP_PTR:
930 1.1 kurahone pi1ppc->sc_ptr = (char *)mi->arg[0].p;
931 1.1 kurahone mi++;
932 1.1 kurahone break;
933 1.1 kurahone
934 1.1 kurahone case MS_OP_CALL:
935 1.1 kurahone if (stack) {
936 1.3 cegger panic("%s - %s: too many calls", device_xname(dev),
937 1.1 kurahone __func__);
938 1.1 kurahone }
939 1.1 kurahone
940 1.1 kurahone if (mi->arg[0].p) {
941 1.1 kurahone /* store state of the actual microsequence */
942 1.1 kurahone stack = mi;
943 1.1 kurahone
944 1.1 kurahone /* jump to the new microsequence */
945 1.1 kurahone mi = (struct ppbus_microseq *)mi->arg[0].p;
946 1.1 kurahone } else {
947 1.1 kurahone mi++;
948 1.1 kurahone }
949 1.1 kurahone break;
950 1.1 kurahone
951 1.1 kurahone case MS_OP_SUBRET:
952 1.1 kurahone /* retrieve microseq and pc state before the call */
953 1.1 kurahone mi = stack;
954 1.1 kurahone
955 1.1 kurahone /* reset the stack */
956 1.1 kurahone stack = 0;
957 1.1 kurahone
958 1.1 kurahone /* XXX return code */
959 1.1 kurahone
960 1.1 kurahone mi++;
961 1.1 kurahone break;
962 1.1 kurahone
963 1.1 kurahone case MS_OP_PUT:
964 1.1 kurahone case MS_OP_GET:
965 1.1 kurahone case MS_OP_RET:
966 1.1 kurahone /*
967 1.1 kurahone * Can't return to pi1ppc level during the execution
968 1.1 kurahone * of a submicrosequence.
969 1.1 kurahone */
970 1.1 kurahone if (stack) {
971 1.1 kurahone panic("%s: cannot return to pi1ppc level",
972 1.1 kurahone __func__);
973 1.1 kurahone }
974 1.1 kurahone /* update pc for pi1ppc level of execution */
975 1.1 kurahone *p_msq = mi;
976 1.1 kurahone
977 1.1 kurahone PI1PPC_UNLOCK(pi1ppc);
978 1.1 kurahone return (0);
979 1.1 kurahone
980 1.1 kurahone default:
981 1.1 kurahone panic("%s: unknown microsequence "
982 1.1 kurahone "opcode 0x%x", __func__, mi->opcode);
983 1.1 kurahone break;
984 1.1 kurahone }
985 1.1 kurahone }
986 1.1 kurahone
987 1.1 kurahone /* Should not be reached! */
988 1.1 kurahone #ifdef PI1PPC_DEBUG
989 1.1 kurahone panic("%s: unexpected code reached!\n", __func__);
990 1.1 kurahone #endif
991 1.1 kurahone }
992 1.1 kurahone
993 1.1 kurahone /* General I/O routine */
994 1.8 tsutsui static uint8_t
995 1.3 cegger pi1ppc_io(device_t dev, int iop, u_char *addr, int cnt, u_char byte)
996 1.1 kurahone {
997 1.3 cegger struct pi1ppc_softc *pi1ppc = device_private(dev);
998 1.8 tsutsui uint8_t val = 0;
999 1.1 kurahone
1000 1.1 kurahone PI1PPC_LOCK(pi1ppc);
1001 1.1 kurahone
1002 1.1 kurahone switch (iop) {
1003 1.1 kurahone case PPBUS_RDTR:
1004 1.1 kurahone val = r_reg(AT_DATA_REG, pi1ppc);
1005 1.1 kurahone break;
1006 1.1 kurahone case PPBUS_RSTR:
1007 1.1 kurahone val = r_reg(AT_STAT_REG, pi1ppc);
1008 1.1 kurahone break;
1009 1.1 kurahone case PPBUS_RCTR:
1010 1.1 kurahone val = r_reg(AT_CTL_REG, pi1ppc);
1011 1.1 kurahone break;
1012 1.1 kurahone case PPBUS_WDTR:
1013 1.1 kurahone w_reg(AT_DATA_REG, pi1ppc, byte);
1014 1.1 kurahone break;
1015 1.1 kurahone case PPBUS_WSTR:
1016 1.1 kurahone /* writing to the status register is weird */
1017 1.1 kurahone break;
1018 1.1 kurahone case PPBUS_WCTR:
1019 1.1 kurahone w_reg(AT_CTL_REG, pi1ppc, byte);
1020 1.1 kurahone break;
1021 1.1 kurahone default:
1022 1.3 cegger panic("%s(%s): unknown I/O operation", device_xname(dev),
1023 1.1 kurahone __func__);
1024 1.1 kurahone break;
1025 1.1 kurahone }
1026 1.1 kurahone
1027 1.1 kurahone pi1ppc_barrier(pi1ppc);
1028 1.1 kurahone
1029 1.1 kurahone PI1PPC_UNLOCK(pi1ppc);
1030 1.1 kurahone
1031 1.1 kurahone return val;
1032 1.1 kurahone }
1033 1.1 kurahone
1034 1.1 kurahone /* Read "instance variables" of pi1ppc device */
1035 1.1 kurahone static int
1036 1.3 cegger pi1ppc_read_ivar(device_t dev, int index, unsigned int *val)
1037 1.1 kurahone {
1038 1.3 cegger struct pi1ppc_softc *pi1ppc = device_private(dev);
1039 1.1 kurahone int rval = 0;
1040 1.1 kurahone
1041 1.1 kurahone PI1PPC_LOCK(pi1ppc);
1042 1.1 kurahone
1043 1.1 kurahone switch(index) {
1044 1.1 kurahone case PPBUS_IVAR_INTR:
1045 1.1 kurahone *val = ((pi1ppc->sc_use & PI1PPC_USE_INTR) != 0);
1046 1.1 kurahone break;
1047 1.1 kurahone
1048 1.1 kurahone case PPBUS_IVAR_DMA:
1049 1.1 kurahone *val = ((pi1ppc->sc_use & PI1PPC_USE_DMA) != 0);
1050 1.1 kurahone break;
1051 1.1 kurahone
1052 1.1 kurahone default:
1053 1.1 kurahone rval = ENODEV;
1054 1.1 kurahone }
1055 1.1 kurahone
1056 1.1 kurahone PI1PPC_UNLOCK(pi1ppc);
1057 1.1 kurahone return rval;
1058 1.1 kurahone }
1059 1.1 kurahone
1060 1.1 kurahone /* Write "instance varaibles" of pi1ppc device */
1061 1.1 kurahone static int
1062 1.3 cegger pi1ppc_write_ivar(device_t dev, int index, unsigned int *val)
1063 1.1 kurahone {
1064 1.3 cegger struct pi1ppc_softc *pi1ppc = device_private(dev);
1065 1.1 kurahone int rval = 0;
1066 1.1 kurahone
1067 1.1 kurahone PI1PPC_LOCK(pi1ppc);
1068 1.1 kurahone
1069 1.1 kurahone switch(index) {
1070 1.1 kurahone case PPBUS_IVAR_INTR:
1071 1.1 kurahone if (*val == 0)
1072 1.1 kurahone pi1ppc->sc_use &= ~PI1PPC_USE_INTR;
1073 1.1 kurahone else if (pi1ppc->sc_has & PI1PPC_HAS_INTR)
1074 1.1 kurahone pi1ppc->sc_use |= PI1PPC_USE_INTR;
1075 1.1 kurahone else
1076 1.1 kurahone rval = ENODEV;
1077 1.1 kurahone break;
1078 1.1 kurahone
1079 1.1 kurahone case PPBUS_IVAR_DMA:
1080 1.1 kurahone if (*val == 0)
1081 1.1 kurahone pi1ppc->sc_use &= ~PI1PPC_USE_DMA;
1082 1.1 kurahone else if (pi1ppc->sc_has & PI1PPC_HAS_DMA)
1083 1.1 kurahone pi1ppc->sc_use |= PI1PPC_USE_DMA;
1084 1.1 kurahone else
1085 1.1 kurahone rval = ENODEV;
1086 1.1 kurahone break;
1087 1.1 kurahone
1088 1.1 kurahone default:
1089 1.1 kurahone rval = ENODEV;
1090 1.1 kurahone }
1091 1.1 kurahone
1092 1.1 kurahone PI1PPC_UNLOCK(pi1ppc);
1093 1.1 kurahone return rval;
1094 1.1 kurahone }
1095 1.1 kurahone
1096 1.1 kurahone /* Add a handler routine to be called by the interrupt handler */
1097 1.1 kurahone static int
1098 1.3 cegger pi1ppc_add_handler(device_t dev, void (*handler)(void *), void *arg)
1099 1.1 kurahone {
1100 1.3 cegger struct pi1ppc_softc *pi1ppc = device_private(dev);
1101 1.1 kurahone struct pi1ppc_handler_node *callback;
1102 1.1 kurahone
1103 1.1 kurahone if (handler == NULL) {
1104 1.1 kurahone PI1PPC_DPRINTF(("%s(%s): attempt to register NULL handler.\n",
1105 1.3 cegger __func__, device_xname(dev)));
1106 1.10 rmind return EINVAL;
1107 1.1 kurahone }
1108 1.10 rmind callback = kmem_alloc(sizeof(struct pi1ppc_handler_node), KM_SLEEP);
1109 1.1 kurahone
1110 1.10 rmind PI1PPC_LOCK(pi1ppc);
1111 1.10 rmind callback->func = handler;
1112 1.10 rmind callback->arg = arg;
1113 1.10 rmind SLIST_INSERT_HEAD(&(pi1ppc->sc_handler_listhead), callback, entries);
1114 1.1 kurahone PI1PPC_UNLOCK(pi1ppc);
1115 1.1 kurahone
1116 1.10 rmind return 0;
1117 1.1 kurahone }
1118 1.1 kurahone
1119 1.1 kurahone /* Remove a handler added by pi1ppc_add_handler() */
1120 1.1 kurahone static int
1121 1.3 cegger pi1ppc_remove_handler(device_t dev, void (*handler)(void *))
1122 1.1 kurahone {
1123 1.3 cegger struct pi1ppc_softc *pi1ppc = device_private(dev);
1124 1.1 kurahone struct pi1ppc_handler_node *callback;
1125 1.10 rmind int rval;
1126 1.1 kurahone
1127 1.1 kurahone PI1PPC_LOCK(pi1ppc);
1128 1.10 rmind KASSERT(!SLIST_EMPTY(&(pi1ppc->sc_handler_listhead)));
1129 1.1 kurahone SLIST_FOREACH(callback, &(pi1ppc->sc_handler_listhead), entries) {
1130 1.1 kurahone if (callback->func == handler) {
1131 1.1 kurahone SLIST_REMOVE(&(pi1ppc->sc_handler_listhead), callback,
1132 1.1 kurahone pi1ppc_handler_node, entries);
1133 1.10 rmind
1134 1.1 kurahone break;
1135 1.1 kurahone }
1136 1.1 kurahone }
1137 1.1 kurahone PI1PPC_UNLOCK(pi1ppc);
1138 1.1 kurahone
1139 1.10 rmind if (callback) {
1140 1.10 rmind kmem_free(callback, sizeof(struct pi1ppc_handler_node));
1141 1.10 rmind rval = 0;
1142 1.10 rmind } else {
1143 1.10 rmind rval = EINVAL;
1144 1.10 rmind }
1145 1.1 kurahone return rval;
1146 1.1 kurahone }
1147 1.1 kurahone
1148 1.1 kurahone /* Utility functions */
1149 1.1 kurahone
1150 1.1 kurahone /*
1151 1.1 kurahone * Functions that read bytes from port into buffer: called from interrupt
1152 1.1 kurahone * handler depending on current chipset mode and cause of interrupt. Return
1153 1.1 kurahone * value: number of bytes moved.
1154 1.1 kurahone */
1155 1.1 kurahone
1156 1.1 kurahone /* note: BUSY is inverted in the PC world, but not on Indy, but the r_reg()
1157 1.1 kurahone and w_reg() functions make the Indy look like the PC. */
1158 1.1 kurahone
1159 1.1 kurahone /* Only the lower 4 bits of the final value are valid */
1160 1.1 kurahone #define nibble2char(s) ((((s) & ~nACK) >> 3) | (~(s) & nBUSY) >> 4)
1161 1.1 kurahone
1162 1.1 kurahone
1163 1.1 kurahone /* Read bytes in nibble mode */
1164 1.1 kurahone static void
1165 1.1 kurahone pi1ppc_nibble_read(struct pi1ppc_softc *pi1ppc)
1166 1.1 kurahone {
1167 1.1 kurahone int i;
1168 1.8 tsutsui uint8_t nibble[2];
1169 1.8 tsutsui uint8_t ctr;
1170 1.8 tsutsui uint8_t str;
1171 1.1 kurahone
1172 1.1 kurahone /* Enable interrupts if needed */
1173 1.1 kurahone if (pi1ppc->sc_use & PI1PPC_USE_INTR) {
1174 1.1 kurahone
1175 1.1 kurahone /* XXX JOE - need code to enable interrupts
1176 1.1 kurahone --> emulate PC behavior in r_reg/w_reg
1177 1.1 kurahone */
1178 1.1 kurahone #if 0
1179 1.1 kurahone ctr = pi1ppc_r_ctr(pi1ppc);
1180 1.1 kurahone pi1ppc_barrier_r(ioppc);
1181 1.1 kurahone if (!(ctr & IRQENABLE)) {
1182 1.1 kurahone ctr |= IRQENABLE;
1183 1.1 kurahone pi1ppc_w_ctr(pi1ppc, ctr);
1184 1.1 kurahone pi1ppc_barrier_w(pi1ppc);
1185 1.1 kurahone }
1186 1.1 kurahone #endif
1187 1.1 kurahone }
1188 1.1 kurahone
1189 1.1 kurahone while (pi1ppc->sc_inbstart < (pi1ppc->sc_inb + pi1ppc->sc_inb_nbytes)) {
1190 1.1 kurahone /* Check if device has data to send in idle phase */
1191 1.1 kurahone str = pi1ppc_r_str(pi1ppc);
1192 1.1 kurahone pi1ppc_barrier_r(pi1ppc);
1193 1.1 kurahone if (str & nDATAVAIL) {
1194 1.1 kurahone return;
1195 1.1 kurahone }
1196 1.1 kurahone
1197 1.1 kurahone /* Nibble-mode handshake transfer */
1198 1.1 kurahone for (i = 0; i < 2; i++) {
1199 1.1 kurahone /* Event 7 - ready to take data (HOSTBUSY low) */
1200 1.1 kurahone ctr = pi1ppc_r_ctr(pi1ppc);
1201 1.1 kurahone pi1ppc_barrier_r(pi1ppc);
1202 1.1 kurahone ctr |= HOSTBUSY;
1203 1.1 kurahone pi1ppc_w_ctr(pi1ppc, ctr);
1204 1.1 kurahone pi1ppc_barrier_w(pi1ppc);
1205 1.1 kurahone
1206 1.1 kurahone /* Event 8 - peripheral writes the first nibble */
1207 1.1 kurahone
1208 1.1 kurahone /* Event 9 - peripheral set nAck low */
1209 1.1 kurahone pi1ppc->sc_inerr = pi1ppc_poll_str(pi1ppc, 0, PTRCLK);
1210 1.1 kurahone if (pi1ppc->sc_inerr)
1211 1.1 kurahone return;
1212 1.1 kurahone
1213 1.1 kurahone /* read nibble */
1214 1.1 kurahone nibble[i] = pi1ppc_r_str(pi1ppc);
1215 1.1 kurahone
1216 1.1 kurahone /* Event 10 - ack, nibble received */
1217 1.1 kurahone ctr &= ~HOSTBUSY;
1218 1.1 kurahone pi1ppc_w_ctr(pi1ppc, ctr);
1219 1.1 kurahone
1220 1.1 kurahone /* Event 11 - wait ack from peripherial */
1221 1.1 kurahone if (pi1ppc->sc_use & PI1PPC_USE_INTR)
1222 1.1 kurahone pi1ppc->sc_inerr = pi1ppc_wait_interrupt(pi1ppc,
1223 1.10 rmind &pi1ppc->sc_in_cv, PI1PPC_IRQ_nACK);
1224 1.1 kurahone else
1225 1.1 kurahone pi1ppc->sc_inerr = pi1ppc_poll_str(pi1ppc, PTRCLK,
1226 1.1 kurahone PTRCLK);
1227 1.1 kurahone if (pi1ppc->sc_inerr)
1228 1.1 kurahone return;
1229 1.1 kurahone }
1230 1.1 kurahone
1231 1.1 kurahone /* Store byte transfered */
1232 1.1 kurahone *(pi1ppc->sc_inbstart) = ((nibble2char(nibble[1]) << 4) & 0xf0) |
1233 1.1 kurahone (nibble2char(nibble[0]) & 0x0f);
1234 1.1 kurahone pi1ppc->sc_inbstart++;
1235 1.1 kurahone }
1236 1.1 kurahone }
1237 1.1 kurahone
1238 1.1 kurahone /* Read bytes in bidirectional mode */
1239 1.1 kurahone static void
1240 1.1 kurahone pi1ppc_byte_read(struct pi1ppc_softc * const pi1ppc)
1241 1.1 kurahone {
1242 1.8 tsutsui uint8_t ctr;
1243 1.8 tsutsui uint8_t str;
1244 1.1 kurahone
1245 1.1 kurahone /* Check direction bit */
1246 1.1 kurahone ctr = pi1ppc_r_ctr(pi1ppc);
1247 1.1 kurahone pi1ppc_barrier_r(pi1ppc);
1248 1.1 kurahone if (!(ctr & PCD)) {
1249 1.1 kurahone PI1PPC_DPRINTF(("%s: byte-mode read attempted without direction "
1250 1.3 cegger "bit set.", device_xname(pi1ppc->sc_dev)));
1251 1.1 kurahone pi1ppc->sc_inerr = ENODEV;
1252 1.1 kurahone return;
1253 1.1 kurahone }
1254 1.1 kurahone /* Enable interrupts if needed */
1255 1.1 kurahone
1256 1.1 kurahone /* XXX JOE - need code to enable interrupts */
1257 1.1 kurahone #if 0
1258 1.1 kurahone if (pi1ppc->sc_use & PI1PPC_USE_INTR) {
1259 1.1 kurahone if (!(ctr & IRQENABLE)) {
1260 1.1 kurahone ctr |= IRQENABLE;
1261 1.1 kurahone pi1ppc_w_ctr(pi1ppc, ctr);
1262 1.1 kurahone pi1ppc_barrier_w(pi1ppc);
1263 1.1 kurahone }
1264 1.1 kurahone }
1265 1.1 kurahone #endif
1266 1.1 kurahone
1267 1.1 kurahone /* Byte-mode handshake transfer */
1268 1.1 kurahone while (pi1ppc->sc_inbstart < (pi1ppc->sc_inb + pi1ppc->sc_inb_nbytes)) {
1269 1.1 kurahone /* Check if device has data to send */
1270 1.1 kurahone str = pi1ppc_r_str(pi1ppc);
1271 1.1 kurahone pi1ppc_barrier_r(pi1ppc);
1272 1.1 kurahone if (str & nDATAVAIL) {
1273 1.1 kurahone return;
1274 1.1 kurahone }
1275 1.1 kurahone
1276 1.1 kurahone /* Event 7 - ready to take data (nAUTO low) */
1277 1.1 kurahone ctr |= HOSTBUSY;
1278 1.1 kurahone pi1ppc_w_ctr(pi1ppc, ctr);
1279 1.1 kurahone pi1ppc_barrier_w(pi1ppc);
1280 1.1 kurahone
1281 1.1 kurahone /* Event 9 - peripheral set nAck low */
1282 1.1 kurahone pi1ppc->sc_inerr = pi1ppc_poll_str(pi1ppc, 0, PTRCLK);
1283 1.1 kurahone if (pi1ppc->sc_inerr)
1284 1.1 kurahone return;
1285 1.1 kurahone
1286 1.1 kurahone /* Store byte transfered */
1287 1.1 kurahone *(pi1ppc->sc_inbstart) = pi1ppc_r_dtr(pi1ppc);
1288 1.1 kurahone pi1ppc_barrier_r(pi1ppc);
1289 1.1 kurahone
1290 1.1 kurahone /* Event 10 - data received, can't accept more */
1291 1.1 kurahone ctr &= ~HOSTBUSY;
1292 1.1 kurahone pi1ppc_w_ctr(pi1ppc, ctr);
1293 1.1 kurahone pi1ppc_barrier_w(pi1ppc);
1294 1.1 kurahone
1295 1.1 kurahone /* Event 11 - peripheral ack */
1296 1.1 kurahone if (pi1ppc->sc_use & PI1PPC_USE_INTR)
1297 1.1 kurahone pi1ppc->sc_inerr = pi1ppc_wait_interrupt(pi1ppc,
1298 1.10 rmind &pi1ppc->sc_in_cv, PI1PPC_IRQ_nACK);
1299 1.1 kurahone else
1300 1.1 kurahone pi1ppc->sc_inerr = pi1ppc_poll_str(pi1ppc, PTRCLK, PTRCLK);
1301 1.1 kurahone if (pi1ppc->sc_inerr)
1302 1.1 kurahone return;
1303 1.1 kurahone
1304 1.1 kurahone /* Event 16 - strobe */
1305 1.1 kurahone str |= HOSTCLK;
1306 1.1 kurahone pi1ppc_w_str(pi1ppc, str);
1307 1.1 kurahone pi1ppc_barrier_w(pi1ppc);
1308 1.1 kurahone DELAY(1);
1309 1.1 kurahone str &= ~HOSTCLK;
1310 1.1 kurahone pi1ppc_w_str(pi1ppc, str);
1311 1.1 kurahone pi1ppc_barrier_w(pi1ppc);
1312 1.1 kurahone
1313 1.1 kurahone /* Update counter */
1314 1.1 kurahone pi1ppc->sc_inbstart++;
1315 1.1 kurahone }
1316 1.1 kurahone }
1317 1.1 kurahone
1318 1.1 kurahone /*
1319 1.1 kurahone * Functions that write bytes to port from buffer: called from pi1ppc_write()
1320 1.1 kurahone * function depending on current chipset mode. Returns number of bytes moved.
1321 1.1 kurahone */
1322 1.1 kurahone
1323 1.1 kurahone static void
1324 1.8 tsutsui pi1ppc_set_intr_mask(struct pi1ppc_softc * const pi1ppc, uint8_t mask)
1325 1.1 kurahone {
1326 1.1 kurahone /* invert valid bits (0 = enabled) */
1327 1.1 kurahone mask = ~mask;
1328 1.1 kurahone mask &= 0xfc;
1329 1.1 kurahone
1330 1.1 kurahone bus_space_write_4((pi1ppc)->sc_iot, (pi1ppc)->sc_ioh, IOC_PLP_INTMASK, mask);
1331 1.1 kurahone pi1ppc_barrier_w(pi1ppc);
1332 1.1 kurahone }
1333 1.1 kurahone
1334 1.1 kurahone
1335 1.1 kurahone #ifdef USE_INDY_ACK_HACK
1336 1.8 tsutsui static uint8_t
1337 1.1 kurahone pi1ppc_get_intr_mask(struct pi1ppc_softc * const pi1ppc)
1338 1.1 kurahone {
1339 1.1 kurahone int val;
1340 1.1 kurahone val = bus_space_read_4((pi1ppc)->sc_iot, (pi1ppc)->sc_ioh, IOC_PLP_INTMASK);
1341 1.1 kurahone pi1ppc_barrier_r(pi1ppc);
1342 1.1 kurahone
1343 1.1 kurahone /* invert (0 = enabled) */
1344 1.1 kurahone val = ~val;
1345 1.1 kurahone
1346 1.1 kurahone return (val & 0xfc);
1347 1.1 kurahone }
1348 1.1 kurahone #endif
1349 1.1 kurahone
1350 1.8 tsutsui static uint8_t
1351 1.1 kurahone pi1ppc_get_intr_stat(struct pi1ppc_softc * const pi1ppc)
1352 1.1 kurahone {
1353 1.1 kurahone int val;
1354 1.1 kurahone val = bus_space_read_4((pi1ppc)->sc_iot, (pi1ppc)->sc_ioh, IOC_PLP_INTSTAT);
1355 1.1 kurahone pi1ppc_barrier_r(pi1ppc);
1356 1.1 kurahone
1357 1.1 kurahone return (val & 0xfc);
1358 1.1 kurahone }
1359 1.1 kurahone
1360 1.1 kurahone /* Write bytes in std/bidirectional mode */
1361 1.1 kurahone static void
1362 1.1 kurahone pi1ppc_std_write(struct pi1ppc_softc * const pi1ppc)
1363 1.1 kurahone {
1364 1.1 kurahone unsigned char ctr;
1365 1.1 kurahone
1366 1.1 kurahone ctr = pi1ppc_r_ctr(pi1ppc);
1367 1.1 kurahone pi1ppc_barrier_r(pi1ppc);
1368 1.1 kurahone
1369 1.1 kurahone /* Ensure that the data lines are in OUTPUT mode */
1370 1.1 kurahone ctr &= ~PCD;
1371 1.1 kurahone pi1ppc_w_ctr(pi1ppc, ctr);
1372 1.1 kurahone pi1ppc_barrier_w(pi1ppc);
1373 1.1 kurahone
1374 1.1 kurahone /* XXX JOE - need code to enable interrupts */
1375 1.1 kurahone #if 0
1376 1.1 kurahone /* Enable interrupts if needed */
1377 1.1 kurahone if (pi1ppc->sc_use & PI1PPC_USE_INTR) {
1378 1.1 kurahone if (!(ctr & IRQENABLE)) {
1379 1.1 kurahone ctr |= IRQENABLE;
1380 1.1 kurahone pi1ppc_w_ctr(pi1ppc, ctr);
1381 1.1 kurahone pi1ppc_barrier_w(pi1ppc);
1382 1.1 kurahone }
1383 1.1 kurahone }
1384 1.1 kurahone #endif
1385 1.1 kurahone
1386 1.1 kurahone while (pi1ppc->sc_outbstart < (pi1ppc->sc_outb + pi1ppc->sc_outb_nbytes)) {
1387 1.1 kurahone
1388 1.1 kurahone /* Wait for peripheral to become ready for MAXBUSYWAIT */
1389 1.1 kurahone pi1ppc->sc_outerr = pi1ppc_poll_str(pi1ppc, SPP_READY, SPP_MASK);
1390 1.1 kurahone if (pi1ppc->sc_outerr) {
1391 1.1 kurahone printf("pi1ppc: timeout waiting for peripheral to become ready\n");
1392 1.1 kurahone return;
1393 1.1 kurahone }
1394 1.1 kurahone
1395 1.1 kurahone /* Put data in data register */
1396 1.1 kurahone pi1ppc_w_dtr(pi1ppc, *(pi1ppc->sc_outbstart));
1397 1.1 kurahone pi1ppc_barrier_w(pi1ppc);
1398 1.1 kurahone DELAY(1);
1399 1.1 kurahone
1400 1.1 kurahone /* If no intr, prepare to catch the rising edge of nACK */
1401 1.1 kurahone if (!(pi1ppc->sc_use & PI1PPC_USE_INTR)) {
1402 1.1 kurahone pi1ppc_get_intr_stat(pi1ppc); /* clear any pending intr */
1403 1.1 kurahone pi1ppc_set_intr_mask(pi1ppc, PI1_PLP_ACK_INTR);
1404 1.1 kurahone }
1405 1.1 kurahone
1406 1.1 kurahone /* Pulse strobe to indicate valid data on lines */
1407 1.1 kurahone ctr |= STROBE;
1408 1.1 kurahone pi1ppc_w_ctr(pi1ppc, ctr);
1409 1.1 kurahone pi1ppc_barrier_w(pi1ppc);
1410 1.1 kurahone DELAY(1);
1411 1.1 kurahone ctr &= ~STROBE;
1412 1.1 kurahone pi1ppc_w_ctr(pi1ppc, ctr);
1413 1.1 kurahone pi1ppc_barrier_w(pi1ppc);
1414 1.1 kurahone
1415 1.1 kurahone /* Wait for nACK for MAXBUSYWAIT */
1416 1.1 kurahone if (pi1ppc->sc_use & PI1PPC_USE_INTR) {
1417 1.1 kurahone pi1ppc->sc_outerr = pi1ppc_wait_interrupt(pi1ppc,
1418 1.10 rmind &pi1ppc->sc_out_cv, PI1PPC_IRQ_nACK);
1419 1.1 kurahone if (pi1ppc->sc_outerr)
1420 1.1 kurahone return;
1421 1.1 kurahone } else {
1422 1.1 kurahone /* Try to catch the pulsed acknowledgement */
1423 1.1 kurahone pi1ppc->sc_outerr = pi1ppc_poll_interrupt_stat(pi1ppc,
1424 1.1 kurahone PI1_PLP_ACK_INTR);
1425 1.1 kurahone
1426 1.1 kurahone if (pi1ppc->sc_outerr) {
1427 1.1 kurahone printf("pi1ppc: timeout waiting for ACK: %02x\n",pi1ppc_r_str(pi1ppc));
1428 1.1 kurahone return;
1429 1.1 kurahone }
1430 1.1 kurahone }
1431 1.1 kurahone
1432 1.1 kurahone /* Update buffer position, byte count and counter */
1433 1.1 kurahone pi1ppc->sc_outbstart++;
1434 1.1 kurahone }
1435 1.1 kurahone }
1436 1.1 kurahone
1437 1.1 kurahone /*
1438 1.1 kurahone * Poll status register using mask and status for MAXBUSYWAIT.
1439 1.1 kurahone * Returns 0 if device ready, error value otherwise.
1440 1.1 kurahone */
1441 1.1 kurahone static int
1442 1.8 tsutsui pi1ppc_poll_str(struct pi1ppc_softc * const pi1ppc, const uint8_t status,
1443 1.8 tsutsui const uint8_t mask)
1444 1.1 kurahone {
1445 1.1 kurahone unsigned int timecount;
1446 1.8 tsutsui uint8_t str;
1447 1.1 kurahone int error = EIO;
1448 1.1 kurahone
1449 1.1 kurahone /* Wait for str to have status for MAXBUSYWAIT */
1450 1.1 kurahone for (timecount = 0; timecount < ((MAXBUSYWAIT/hz)*1000000);
1451 1.1 kurahone timecount++) {
1452 1.1 kurahone
1453 1.1 kurahone str = pi1ppc_r_str(pi1ppc);
1454 1.1 kurahone pi1ppc_barrier_r(pi1ppc);
1455 1.1 kurahone if ((str & mask) == status) {
1456 1.1 kurahone error = 0;
1457 1.1 kurahone break;
1458 1.1 kurahone }
1459 1.1 kurahone DELAY(1);
1460 1.1 kurahone }
1461 1.1 kurahone
1462 1.1 kurahone return error;
1463 1.1 kurahone }
1464 1.1 kurahone
1465 1.1 kurahone /* Wait for interrupt for MAXBUSYWAIT: returns 0 if acknowledge received. */
1466 1.1 kurahone static int
1467 1.10 rmind pi1ppc_wait_interrupt(struct pi1ppc_softc * const sc, kcondvar_t *cv,
1468 1.10 rmind const uint8_t irqstat)
1469 1.1 kurahone {
1470 1.1 kurahone int error = EIO;
1471 1.1 kurahone
1472 1.10 rmind sc->sc_irqstat &= ~irqstat;
1473 1.10 rmind error = cv_timedwait_sig(cv, &sc->sc_lock, MAXBUSYWAIT);
1474 1.10 rmind if (!error && (sc->sc_irqstat & irqstat) == 0) {
1475 1.10 rmind sc->sc_irqstat &= ~irqstat;
1476 1.1 kurahone error = 0;
1477 1.1 kurahone }
1478 1.1 kurahone return error;
1479 1.1 kurahone }
1480 1.1 kurahone
1481 1.1 kurahone /*
1482 1.1 kurahone INDY ACK HACK DESCRIPTION
1483 1.1 kurahone
1484 1.1 kurahone There appears to be a bug in the Indy's PI1 hardware - it sometimes
1485 1.1 kurahone *misses* the rising edge of /ACK. Ugh!
1486 1.1 kurahone
1487 1.1 kurahone (Also, unlike the other status bits, /ACK doesn't generate an
1488 1.1 kurahone interrupt on its falling edge.)
1489 1.1 kurahone
1490 1.1 kurahone So, we do something kind of skanky here. We use a shorter timeout,
1491 1.1 kurahone and, if we timeout, we first check BUSY. If BUSY is high, we go
1492 1.1 kurahone back to waiting for /ACK (because maybe this really is just a slow
1493 1.1 kurahone peripheral).
1494 1.1 kurahone
1495 1.1 kurahone If it's a normal printer, it will raise BUSY from when it sees our
1496 1.1 kurahone /STROBE until it raises its /ACK:
1497 1.1 kurahone _____ _____________________
1498 1.1 kurahone /STB \_/
1499 1.1 kurahone ________________ __________
1500 1.1 kurahone /ACK \_/
1501 1.1 kurahone ___________
1502 1.1 kurahone BUSY ______/ \__________
1503 1.1 kurahone
1504 1.1 kurahone So, if we time out and see BUSY low, then we probably just missed
1505 1.1 kurahone the /ACK.
1506 1.1 kurahone
1507 1.1 kurahone In that case, we then check /ERROR and SELECTIN. If both are hi,
1508 1.1 kurahone (the peripheral thinks it is selected, and is not asserting /ERROR)
1509 1.1 kurahone we assume that the Indy's parallel port missed the /ACK, and return
1510 1.1 kurahone success.
1511 1.1 kurahone */
1512 1.1 kurahone
1513 1.1 kurahone #ifdef USE_INDY_ACK_HACK
1514 1.1 kurahone #define ACK_TIMEOUT_SCALER 1000
1515 1.1 kurahone #else
1516 1.1 kurahone #define ACK_TIMEOUT_SCALER 1000000
1517 1.1 kurahone #endif
1518 1.1 kurahone
1519 1.1 kurahone static int
1520 1.1 kurahone pi1ppc_poll_interrupt_stat(struct pi1ppc_softc * const pi1ppc,
1521 1.8 tsutsui const uint8_t match)
1522 1.1 kurahone {
1523 1.1 kurahone unsigned int timecount;
1524 1.8 tsutsui uint8_t cur;
1525 1.1 kurahone int error = EIO;
1526 1.1 kurahone
1527 1.1 kurahone #ifdef USE_INDY_ACK_HACK
1528 1.1 kurahone /* retry 10000x */
1529 1.1 kurahone int retry_count = 10000;
1530 1.1 kurahone
1531 1.1 kurahone retry:
1532 1.1 kurahone #endif
1533 1.1 kurahone
1534 1.1 kurahone /* Wait for intr status to have match bits set for MAXBUSYWAIT */
1535 1.1 kurahone for (timecount = 0; timecount < ((MAXBUSYWAIT/hz)*ACK_TIMEOUT_SCALER);
1536 1.1 kurahone timecount++) {
1537 1.1 kurahone cur = pi1ppc_get_intr_stat(pi1ppc);
1538 1.1 kurahone if ((cur & match) == match) {
1539 1.1 kurahone error = 0;
1540 1.1 kurahone break;
1541 1.1 kurahone }
1542 1.1 kurahone DELAY(1);
1543 1.1 kurahone }
1544 1.1 kurahone
1545 1.1 kurahone #ifdef USE_INDY_ACK_HACK
1546 1.1 kurahone if(error != 0) {
1547 1.1 kurahone cur = pi1ppc_r_str(pi1ppc);
1548 1.1 kurahone
1549 1.1 kurahone /* retry if BUSY is hi (inverted, so lo) and we haven't
1550 1.1 kurahone waited the usual amt */
1551 1.1 kurahone
1552 1.1 kurahone if(((cur&nBUSY) == 0) && retry_count) {
1553 1.1 kurahone retry_count--;
1554 1.1 kurahone goto retry;
1555 1.1 kurahone }
1556 1.1 kurahone
1557 1.1 kurahone /* if /ERROR and SELECT are high, and the peripheral isn't
1558 1.1 kurahone BUSY, assume that we just missed the /ACK.
1559 1.1 kurahone (Remember, we emulate the PC's inverted BUSY!)
1560 1.1 kurahone */
1561 1.1 kurahone
1562 1.1 kurahone if((cur&(nFAULT|SELECT|nBUSY)) == (nFAULT|SELECT|nBUSY))
1563 1.1 kurahone error = 0;
1564 1.1 kurahone
1565 1.1 kurahone /* if things still look bad, print out some info */
1566 1.1 kurahone if(error!=0)
1567 1.1 kurahone printf("int mask=%02x, int stat=%02x, str=%02x\n",
1568 1.1 kurahone pi1ppc_get_intr_mask(pi1ppc),
1569 1.1 kurahone pi1ppc_get_intr_stat(pi1ppc),
1570 1.1 kurahone cur);
1571 1.1 kurahone }
1572 1.1 kurahone #endif
1573 1.1 kurahone
1574 1.1 kurahone return error;
1575 1.1 kurahone }
1576 1.1 kurahone
1577