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