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