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