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