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