1 1.17 andvar /* $NetBSD: pi1ppc.c,v 1.17 2022/11/01 19:45:35 andvar 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.17 andvar __KERNEL_RCSID(0, "$NetBSD: pi1ppc.c,v 1.17 2022/11/01 19:45:35 andvar 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.16 andvar /* Set capabilities */ 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.15 thorpej pi1ppc_print, CFARGS_NONE); 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.17 andvar /* Write "instance variables" 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.13 msaitoh /* Store byte transferred */ 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.13 msaitoh /* Store byte transferred */ 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