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