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