1 1.16 thorpej /* $NetBSD: cec.c,v 1.16 2021/08/07 16:19:12 thorpej Exp $ */ 2 1.1 gmcgarry 3 1.1 gmcgarry /*- 4 1.1 gmcgarry * Copyright (c) 2003 The NetBSD Foundation, Inc. 5 1.1 gmcgarry * All rights reserved. 6 1.1 gmcgarry * 7 1.1 gmcgarry * This code is derived from software contributed to The NetBSD Foundation 8 1.1 gmcgarry * by Gregory McGarry. 9 1.1 gmcgarry * 10 1.1 gmcgarry * Redistribution and use in source and binary forms, with or without 11 1.1 gmcgarry * modification, are permitted provided that the following conditions 12 1.1 gmcgarry * are met: 13 1.1 gmcgarry * 1. Redistributions of source code must retain the above copyright 14 1.1 gmcgarry * notice, this list of conditions and the following disclaimer. 15 1.1 gmcgarry * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 gmcgarry * notice, this list of conditions and the following disclaimer in the 17 1.1 gmcgarry * documentation and/or other materials provided with the distribution. 18 1.1 gmcgarry * 19 1.1 gmcgarry * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 gmcgarry * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 gmcgarry * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 gmcgarry * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 gmcgarry * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 gmcgarry * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 gmcgarry * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 gmcgarry * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 gmcgarry * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 gmcgarry * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 gmcgarry * POSSIBILITY OF SUCH DAMAGE. 30 1.1 gmcgarry */ 31 1.1 gmcgarry 32 1.1 gmcgarry #include <sys/cdefs.h> 33 1.16 thorpej __KERNEL_RCSID(0, "$NetBSD: cec.c,v 1.16 2021/08/07 16:19:12 thorpej Exp $"); 34 1.1 gmcgarry 35 1.1 gmcgarry #include <sys/param.h> 36 1.1 gmcgarry #include <sys/systm.h> 37 1.1 gmcgarry #include <sys/callout.h> 38 1.1 gmcgarry #include <sys/conf.h> 39 1.1 gmcgarry #include <sys/device.h> 40 1.1 gmcgarry #include <sys/kernel.h> 41 1.1 gmcgarry 42 1.7 ad #include <sys/bus.h> 43 1.1 gmcgarry 44 1.1 gmcgarry #include <dev/isa/isavar.h> 45 1.1 gmcgarry #include <dev/isa/isadmavar.h> 46 1.1 gmcgarry 47 1.1 gmcgarry #include <dev/gpib/gpibvar.h> 48 1.1 gmcgarry 49 1.1 gmcgarry #include <dev/ic/nec7210reg.h> 50 1.1 gmcgarry 51 1.12 tsutsui #ifndef DEBUG 52 1.1 gmcgarry #define DEBUG 53 1.12 tsutsui #endif 54 1.1 gmcgarry 55 1.1 gmcgarry #ifdef DEBUG 56 1.1 gmcgarry int cecdebug = 0x1f; 57 1.1 gmcgarry #define DPRINTF(flag, str) if (cecdebug & (flag)) printf str 58 1.1 gmcgarry #define DBG_FOLLOW 0x01 59 1.1 gmcgarry #define DBG_CONFIG 0x02 60 1.1 gmcgarry #define DBG_INTR 0x04 61 1.1 gmcgarry #define DBG_REPORTTIME 0x08 62 1.1 gmcgarry #define DBG_FAIL 0x10 63 1.1 gmcgarry #define DBG_WAIT 0x20 64 1.1 gmcgarry #else 65 1.1 gmcgarry #define DPRINTF(flag, str) /* nothing */ 66 1.1 gmcgarry #endif 67 1.1 gmcgarry 68 1.1 gmcgarry #define CEC_IOSIZE 8 69 1.1 gmcgarry 70 1.1 gmcgarry struct cec_softc { 71 1.13 chs device_t sc_dev; /* generic device glue */ 72 1.1 gmcgarry 73 1.1 gmcgarry bus_space_tag_t sc_iot; 74 1.1 gmcgarry bus_space_handle_t sc_ioh; 75 1.1 gmcgarry isa_chipset_tag_t sc_ic; 76 1.1 gmcgarry int sc_drq; 77 1.1 gmcgarry void *sc_ih; 78 1.1 gmcgarry 79 1.1 gmcgarry int sc_myaddr; /* my address */ 80 1.1 gmcgarry struct gpib_softc *sc_gpib; 81 1.1 gmcgarry 82 1.1 gmcgarry volatile int sc_flags; 83 1.1 gmcgarry #define CECF_IO 0x1 84 1.1 gmcgarry #define CECF_PPOLL 0x4 85 1.1 gmcgarry #define CECF_READ 0x8 86 1.1 gmcgarry #define CECF_TIMO 0x10 87 1.1 gmcgarry #define CECF_USEDMA 0x20 88 1.1 gmcgarry int sc_ppoll_slave; /* XXX stash our ppoll address */ 89 1.6 ad callout_t sc_timeout_ch; 90 1.1 gmcgarry }; 91 1.1 gmcgarry 92 1.11 cegger int cecprobe(device_t, cfdata_t, void *); 93 1.11 cegger void cecattach(device_t, device_t, void *); 94 1.1 gmcgarry 95 1.13 chs CFATTACH_DECL_NEW(cec, sizeof(struct cec_softc), 96 1.1 gmcgarry cecprobe, cecattach, NULL, NULL); 97 1.1 gmcgarry 98 1.3 perry void cecreset(void *); 99 1.1 gmcgarry int cecpptest(void *, int); 100 1.1 gmcgarry void cecppwatch(void *, int); 101 1.1 gmcgarry void cecppclear(void *); 102 1.1 gmcgarry void cecxfer(void *, int, int, void *, int, int, int); 103 1.1 gmcgarry void cecgo(void *v); 104 1.1 gmcgarry int cecintr(void *); 105 1.1 gmcgarry int cecsendcmds(void *, void *, int); 106 1.1 gmcgarry int cecsenddata(void *, void *, int); 107 1.1 gmcgarry int cecrecvdata(void *, void *, int); 108 1.1 gmcgarry int cecgts(void *); 109 1.1 gmcgarry int cectc(void *, int); 110 1.1 gmcgarry void cecifc(void *); 111 1.1 gmcgarry 112 1.1 gmcgarry static int cecwait(struct cec_softc *, int, int); 113 1.1 gmcgarry static void cectimeout(void *v); 114 1.1 gmcgarry static int nec7210_setaddress(struct cec_softc *, int, int); 115 1.1 gmcgarry static void nec7210_init(struct cec_softc *); 116 1.1 gmcgarry static void nec7210_ifc(struct cec_softc *); 117 1.1 gmcgarry 118 1.1 gmcgarry /* 119 1.1 gmcgarry * Our chipset structure. 120 1.1 gmcgarry */ 121 1.1 gmcgarry struct gpib_chipset_tag cec_ic = { 122 1.1 gmcgarry cecreset, 123 1.1 gmcgarry NULL, 124 1.1 gmcgarry NULL, 125 1.1 gmcgarry cecpptest, 126 1.1 gmcgarry cecppwatch, 127 1.1 gmcgarry cecppclear, 128 1.1 gmcgarry cecxfer, 129 1.1 gmcgarry cectc, 130 1.1 gmcgarry cecgts, 131 1.1 gmcgarry cecifc, 132 1.1 gmcgarry cecsendcmds, 133 1.1 gmcgarry cecsenddata, 134 1.5 cube cecrecvdata, 135 1.5 cube NULL, 136 1.5 cube NULL 137 1.1 gmcgarry }; 138 1.1 gmcgarry 139 1.1 gmcgarry int cecwtimeout = 0x10000; 140 1.1 gmcgarry int cecdmathresh = 3; 141 1.1 gmcgarry 142 1.1 gmcgarry int 143 1.11 cegger cecprobe(device_t parent, cfdata_t match, void *aux) 144 1.1 gmcgarry { 145 1.1 gmcgarry struct isa_attach_args *ia = aux; 146 1.1 gmcgarry bus_space_tag_t iot = ia->ia_iot; 147 1.1 gmcgarry bus_space_handle_t ioh; 148 1.1 gmcgarry 149 1.1 gmcgarry DPRINTF(DBG_CONFIG, ("cecprobe: called\n")); 150 1.1 gmcgarry 151 1.1 gmcgarry if (ia->ia_nio < 1) 152 1.1 gmcgarry return (0); 153 1.1 gmcgarry if (ia->ia_nirq < 1) 154 1.1 gmcgarry return (0); 155 1.1 gmcgarry if (ia->ia_ndrq < 1) 156 1.1 gmcgarry return (0); 157 1.1 gmcgarry 158 1.1 gmcgarry if (ISA_DIRECT_CONFIG(ia)) 159 1.1 gmcgarry return (0); 160 1.1 gmcgarry 161 1.2 drochner if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT) 162 1.1 gmcgarry return (0); 163 1.1 gmcgarry 164 1.2 drochner if (ia->ia_ndrq > 0 && ia->ia_drq[0].ir_drq == ISA_UNKNOWN_DRQ) 165 1.1 gmcgarry ia->ia_ndrq = 0; 166 1.1 gmcgarry 167 1.1 gmcgarry if (bus_space_map(iot, ia->ia_io[0].ir_addr, CEC_IOSIZE, 0, &ioh)) 168 1.1 gmcgarry return (0); 169 1.1 gmcgarry 170 1.1 gmcgarry /* XXX insert probe here */ 171 1.1 gmcgarry 172 1.1 gmcgarry ia->ia_io[0].ir_size = CEC_IOSIZE; 173 1.1 gmcgarry ia->ia_niomem = 0; 174 1.1 gmcgarry 175 1.1 gmcgarry bus_space_unmap(iot, ioh, CEC_IOSIZE); 176 1.1 gmcgarry 177 1.1 gmcgarry return (1); 178 1.1 gmcgarry } 179 1.1 gmcgarry 180 1.1 gmcgarry void 181 1.11 cegger cecattach(device_t parent, device_t self, void *aux) 182 1.1 gmcgarry { 183 1.13 chs struct cec_softc *sc = device_private(self); 184 1.1 gmcgarry struct isa_attach_args *ia = aux; 185 1.1 gmcgarry struct gpibdev_attach_args ga; 186 1.1 gmcgarry bus_size_t maxsize; 187 1.1 gmcgarry 188 1.1 gmcgarry printf("\n"); 189 1.1 gmcgarry 190 1.1 gmcgarry DPRINTF(DBG_CONFIG, ("cecattach: called\n")); 191 1.1 gmcgarry 192 1.13 chs sc->sc_dev = self; 193 1.1 gmcgarry sc->sc_iot = ia->ia_iot; 194 1.1 gmcgarry sc->sc_ic = ia->ia_ic; 195 1.1 gmcgarry 196 1.1 gmcgarry if (bus_space_map(sc->sc_iot, ia->ia_io[0].ir_addr, CEC_IOSIZE, 197 1.1 gmcgarry 0, &sc->sc_ioh) != 0) { 198 1.13 chs aprint_error_dev(sc->sc_dev, "unable to map I/O space\n"); 199 1.1 gmcgarry return; 200 1.1 gmcgarry } 201 1.1 gmcgarry 202 1.1 gmcgarry if (ia->ia_ndrq > 0) { 203 1.1 gmcgarry sc->sc_flags |= CECF_USEDMA; 204 1.1 gmcgarry sc->sc_drq = ia->ia_drq[0].ir_drq; 205 1.1 gmcgarry 206 1.1 gmcgarry (void) isa_drq_alloc(sc->sc_ic, sc->sc_drq); 207 1.1 gmcgarry maxsize = isa_dmamaxsize(sc->sc_ic, sc->sc_drq); 208 1.1 gmcgarry if (isa_dmamap_create(sc->sc_ic, sc->sc_drq, 209 1.1 gmcgarry maxsize, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW)) { 210 1.14 msaitoh aprint_error_dev(sc->sc_dev, 211 1.14 msaitoh "unable to create map for drq %d\n", sc->sc_drq); 212 1.1 gmcgarry sc->sc_flags &= ~CECF_USEDMA; 213 1.1 gmcgarry } 214 1.1 gmcgarry } 215 1.1 gmcgarry 216 1.1 gmcgarry sc->sc_myaddr = 15; /* XXX */ 217 1.1 gmcgarry 218 1.1 gmcgarry cecreset(sc); 219 1.1 gmcgarry (void) nec7210_setaddress(sc, sc->sc_myaddr, -1); 220 1.1 gmcgarry 221 1.1 gmcgarry sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq, 222 1.1 gmcgarry IST_EDGE, IPL_BIO, cecintr, sc); 223 1.1 gmcgarry if (sc->sc_ih == NULL) { 224 1.13 chs aprint_error_dev(sc->sc_dev, "couldn't establish interrupt\n"); 225 1.1 gmcgarry return; 226 1.1 gmcgarry } 227 1.1 gmcgarry 228 1.6 ad callout_init(&sc->sc_timeout_ch, 0); 229 1.1 gmcgarry 230 1.1 gmcgarry /* attach MI GPIB bus */ 231 1.1 gmcgarry cec_ic.cookie = (void *)sc; 232 1.1 gmcgarry ga.ga_ic = &cec_ic; 233 1.1 gmcgarry ga.ga_address = sc->sc_myaddr; 234 1.1 gmcgarry sc->sc_gpib = 235 1.15 thorpej (struct gpib_softc *)config_found(self, &ga, gpibdevprint, 236 1.16 thorpej CFARGS_NONE); 237 1.1 gmcgarry } 238 1.1 gmcgarry 239 1.1 gmcgarry int 240 1.1 gmcgarry cecintr(void *v) 241 1.1 gmcgarry { 242 1.1 gmcgarry struct cec_softc *sc = v; 243 1.1 gmcgarry bus_space_tag_t iot = sc->sc_iot; 244 1.1 gmcgarry bus_space_handle_t ioh = sc->sc_ioh; 245 1.1 gmcgarry u_int8_t stat1, stat2; 246 1.1 gmcgarry 247 1.1 gmcgarry stat1 = bus_space_read_1(iot, ioh, NEC7210_ISR1); 248 1.1 gmcgarry stat2 = bus_space_read_1(iot, ioh, NEC7210_ISR2); 249 1.1 gmcgarry 250 1.1 gmcgarry DPRINTF(DBG_INTR, ("cecintr: sc=%p stat1=0x%x stat2=0x%x\n", 251 1.1 gmcgarry sc, stat1, stat2)); 252 1.1 gmcgarry 253 1.1 gmcgarry if (sc->sc_flags & CECF_IO) { 254 1.1 gmcgarry 255 1.1 gmcgarry if (sc->sc_flags & CECF_TIMO) 256 1.1 gmcgarry callout_stop(&sc->sc_timeout_ch); 257 1.1 gmcgarry 258 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_IMR1, 0); 259 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_IMR2, 0); 260 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA); 261 1.1 gmcgarry sc->sc_flags &= ~(CECF_IO | CECF_READ | CECF_TIMO); 262 1.1 gmcgarry if (sc->sc_flags & CECF_USEDMA) 263 1.1 gmcgarry isa_dmadone(sc->sc_ic, sc->sc_drq); 264 1.1 gmcgarry gpibintr(sc->sc_gpib); 265 1.1 gmcgarry 266 1.1 gmcgarry } else if (sc->sc_flags & CECF_PPOLL) { 267 1.1 gmcgarry 268 1.1 gmcgarry if (cecpptest(sc, sc->sc_ppoll_slave)) { 269 1.1 gmcgarry sc->sc_flags &= ~CECF_PPOLL; 270 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_IMR2, 0); 271 1.1 gmcgarry gpibintr(sc->sc_gpib); 272 1.1 gmcgarry } 273 1.1 gmcgarry 274 1.1 gmcgarry } 275 1.1 gmcgarry return (1); 276 1.1 gmcgarry } 277 1.1 gmcgarry 278 1.1 gmcgarry void 279 1.1 gmcgarry cecreset(void *v) 280 1.1 gmcgarry { 281 1.1 gmcgarry struct cec_softc *sc = v; 282 1.1 gmcgarry u_int8_t cmd; 283 1.1 gmcgarry 284 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("cecreset: sc=%p\n", sc)); 285 1.1 gmcgarry 286 1.1 gmcgarry nec7210_init(sc); 287 1.1 gmcgarry nec7210_ifc(sc); 288 1.1 gmcgarry /* we're now the system controller */ 289 1.1 gmcgarry 290 1.1 gmcgarry /* XXX should be pushed higher */ 291 1.1 gmcgarry 292 1.1 gmcgarry /* universal device clear */ 293 1.1 gmcgarry cmd = GPIBCMD_DCL; 294 1.1 gmcgarry (void) cecsendcmds(sc, &cmd, 1); 295 1.1 gmcgarry /* delay for devices to clear */ 296 1.1 gmcgarry DELAY(100000); 297 1.1 gmcgarry } 298 1.1 gmcgarry 299 1.1 gmcgarry int 300 1.1 gmcgarry cecsendcmds(void *v, void *ptr, int origcnt) 301 1.1 gmcgarry { 302 1.1 gmcgarry struct cec_softc *sc = v; 303 1.1 gmcgarry bus_space_tag_t iot = sc->sc_iot; 304 1.1 gmcgarry bus_space_handle_t ioh = sc->sc_ioh; 305 1.1 gmcgarry int cnt = origcnt; 306 1.1 gmcgarry u_int8_t *addr = ptr; 307 1.1 gmcgarry 308 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("cecsendcmds: sc=%p, ptr=%p cnt=%d\n", 309 1.1 gmcgarry sc, ptr, origcnt)); 310 1.1 gmcgarry 311 1.1 gmcgarry while (--cnt >= 0) { 312 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_CDOR, *addr++); 313 1.1 gmcgarry if (cecwait(sc, 0, ISR2_CO)) 314 1.1 gmcgarry return (origcnt - cnt - 1); 315 1.1 gmcgarry } 316 1.1 gmcgarry return (origcnt); 317 1.1 gmcgarry } 318 1.1 gmcgarry 319 1.1 gmcgarry 320 1.1 gmcgarry int 321 1.1 gmcgarry cecrecvdata(void *v, void *ptr, int origcnt) 322 1.1 gmcgarry { 323 1.1 gmcgarry struct cec_softc *sc = v; 324 1.1 gmcgarry bus_space_tag_t iot = sc->sc_iot; 325 1.1 gmcgarry bus_space_handle_t ioh = sc->sc_ioh; 326 1.1 gmcgarry int cnt = origcnt; 327 1.1 gmcgarry u_int8_t *addr = ptr; 328 1.1 gmcgarry 329 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("cecrecvdata: sc=%p, ptr=%p cnt=%d\n", 330 1.1 gmcgarry sc, ptr, origcnt)); 331 1.1 gmcgarry 332 1.1 gmcgarry /* XXX holdoff on end */ 333 1.1 gmcgarry bus_space_write_1(sc->sc_iot, sc->sc_ioh, NEC7210_AUXMR, AUXCMD_RHDF); 334 1.1 gmcgarry 335 1.1 gmcgarry if (cnt) { 336 1.1 gmcgarry while (--cnt >= 0) { 337 1.1 gmcgarry if (cecwait(sc, ISR1_DI, 0)) 338 1.1 gmcgarry return (origcnt - cnt - 1); 339 1.1 gmcgarry *addr++ = bus_space_read_1(iot, ioh, NEC7210_DIR); 340 1.1 gmcgarry } 341 1.1 gmcgarry } 342 1.1 gmcgarry return (origcnt); 343 1.1 gmcgarry } 344 1.1 gmcgarry 345 1.1 gmcgarry int 346 1.1 gmcgarry cecsenddata(void *v, void *ptr, int origcnt) 347 1.1 gmcgarry { 348 1.1 gmcgarry struct cec_softc *sc = v; 349 1.1 gmcgarry bus_space_tag_t iot = sc->sc_iot; 350 1.1 gmcgarry bus_space_handle_t ioh = sc->sc_ioh; 351 1.1 gmcgarry int cnt = origcnt; 352 1.1 gmcgarry u_int8_t *addr = ptr; 353 1.1 gmcgarry 354 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("cecdsenddata: sc=%p, ptr=%p cnt=%d\n", 355 1.1 gmcgarry sc, ptr, origcnt)); 356 1.1 gmcgarry 357 1.1 gmcgarry if (cnt) { 358 1.1 gmcgarry while (--cnt > 0) { 359 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_CDOR, *addr++); 360 1.1 gmcgarry if (cecwait(sc, ISR1_DO, 0)) 361 1.1 gmcgarry return (origcnt - cnt - 1); 362 1.1 gmcgarry } 363 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SEOI); 364 1.3 perry bus_space_write_1(iot, ioh, NEC7210_CDOR, *addr); 365 1.1 gmcgarry (void) cecwait(sc, ISR1_DO, 0); 366 1.1 gmcgarry } 367 1.1 gmcgarry return (origcnt); 368 1.1 gmcgarry } 369 1.1 gmcgarry 370 1.1 gmcgarry int 371 1.1 gmcgarry cectc(void *v, int sync) 372 1.1 gmcgarry { 373 1.1 gmcgarry struct cec_softc *sc = v; 374 1.1 gmcgarry bus_space_tag_t iot = sc->sc_iot; 375 1.1 gmcgarry bus_space_handle_t ioh = sc->sc_ioh; 376 1.1 gmcgarry u_int8_t adsr; 377 1.1 gmcgarry int timo = cecwtimeout; 378 1.1 gmcgarry 379 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("cectc: sc=%p, sync=%d\n", sc, sync)); 380 1.1 gmcgarry 381 1.1 gmcgarry adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR); 382 1.1 gmcgarry #if 0 383 1.1 gmcgarry if ((adsr & (ADSR_CIC | ADSR_NATN)) == ADSR_CIC) { 384 1.1 gmcgarry DPRINTF(0xff, ("cectc: already CIC\n")); 385 1.1 gmcgarry return (0); 386 1.1 gmcgarry } 387 1.1 gmcgarry #endif 388 1.1 gmcgarry 389 1.1 gmcgarry if (sync) { 390 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_RHDF); 391 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCS); 392 1.1 gmcgarry } else { 393 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA); 394 1.1 gmcgarry } 395 1.1 gmcgarry 396 1.1 gmcgarry /* wait until ATN is asserted */ 397 1.1 gmcgarry for (;;) { 398 1.1 gmcgarry adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR); 399 1.1 gmcgarry if (--timo == 0) { 400 1.1 gmcgarry DPRINTF(DBG_REPORTTIME, ("cectc: timeout\n")); 401 1.1 gmcgarry return (1); 402 1.1 gmcgarry } 403 1.1 gmcgarry if ((adsr & ADSR_NATN) == 0) 404 1.1 gmcgarry break; 405 1.1 gmcgarry DELAY(1); 406 1.1 gmcgarry } 407 1.1 gmcgarry 408 1.1 gmcgarry return (0); 409 1.1 gmcgarry } 410 1.1 gmcgarry 411 1.1 gmcgarry int 412 1.1 gmcgarry cecgts(void *v) 413 1.1 gmcgarry { 414 1.1 gmcgarry struct cec_softc *sc = v; 415 1.1 gmcgarry bus_space_tag_t iot = sc->sc_iot; 416 1.1 gmcgarry bus_space_handle_t ioh = sc->sc_ioh; 417 1.1 gmcgarry u_int8_t adsr; 418 1.1 gmcgarry int timo = cecwtimeout; 419 1.1 gmcgarry 420 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("cecgts: sc=%p\n", sc)); 421 1.1 gmcgarry 422 1.1 gmcgarry adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR); 423 1.1 gmcgarry #if 0 424 1.1 gmcgarry if ((adsr & (ADSR_CIC | ADSR_NATN)) == ADSR_NATN) { 425 1.1 gmcgarry DPRINTF(0xff, ("cecgts: already standby\n")); 426 1.1 gmcgarry return (0); 427 1.1 gmcgarry } 428 1.1 gmcgarry #endif 429 1.1 gmcgarry 430 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_GTS); 431 1.1 gmcgarry 432 1.1 gmcgarry /* wait unit ATN is released */ 433 1.1 gmcgarry for (;;) { 434 1.1 gmcgarry adsr = bus_space_read_1(iot, ioh, NEC7210_ADSR); 435 1.1 gmcgarry if (--timo == 0) { 436 1.1 gmcgarry DPRINTF(DBG_REPORTTIME, ("cecgts: timeout\n")); 437 1.1 gmcgarry return (1); 438 1.1 gmcgarry } 439 1.1 gmcgarry if ((adsr & ADSR_NATN) == ADSR_NATN) 440 1.1 gmcgarry break; 441 1.1 gmcgarry DELAY(1); 442 1.1 gmcgarry } 443 1.1 gmcgarry 444 1.1 gmcgarry return (0); 445 1.1 gmcgarry } 446 1.1 gmcgarry 447 1.1 gmcgarry int 448 1.1 gmcgarry cecpptest(void *v, int slave) 449 1.1 gmcgarry { 450 1.1 gmcgarry struct cec_softc *sc = v; 451 1.1 gmcgarry bus_space_tag_t iot = sc->sc_iot; 452 1.1 gmcgarry bus_space_handle_t ioh = sc->sc_ioh; 453 1.1 gmcgarry int ppoll; 454 1.1 gmcgarry 455 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("cecpptest: sc=%p slave=%d\n", sc, slave)); 456 1.1 gmcgarry 457 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_EPP); 458 1.1 gmcgarry DELAY(25); 459 1.1 gmcgarry ppoll = bus_space_read_1(iot, ioh, NEC7210_CPTR); 460 1.1 gmcgarry DPRINTF(0xff, ("cecpptest: ppoll=%x\n", ppoll)); 461 1.1 gmcgarry return ((ppoll & (0x80 >> slave)) != 0); 462 1.1 gmcgarry } 463 1.1 gmcgarry 464 1.1 gmcgarry void 465 1.1 gmcgarry cecppwatch(void *v, int slave) 466 1.1 gmcgarry { 467 1.1 gmcgarry struct cec_softc *sc = v; 468 1.1 gmcgarry bus_space_tag_t iot = sc->sc_iot; 469 1.1 gmcgarry bus_space_handle_t ioh = sc->sc_ioh; 470 1.1 gmcgarry 471 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("cecppwatch: sc=%p\n", sc)); 472 1.1 gmcgarry 473 1.1 gmcgarry sc->sc_flags |= CECF_PPOLL; 474 1.1 gmcgarry sc->sc_ppoll_slave = slave; 475 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_CO); 476 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_EPP); 477 1.1 gmcgarry } 478 1.1 gmcgarry 479 1.1 gmcgarry void 480 1.1 gmcgarry cecppclear(void *v) 481 1.1 gmcgarry { 482 1.1 gmcgarry struct cec_softc *sc = v; 483 1.1 gmcgarry 484 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("cecppclear: sc=%p\n", sc)); 485 1.1 gmcgarry 486 1.1 gmcgarry sc->sc_flags &= ~CECF_PPOLL; 487 1.1 gmcgarry bus_space_write_1(sc->sc_iot, sc->sc_ioh, NEC7210_IMR2, 0); 488 1.1 gmcgarry } 489 1.1 gmcgarry 490 1.1 gmcgarry void 491 1.1 gmcgarry cecxfer(void *v, int slave, int sec, void *buf, int count, int dir, int timo) 492 1.1 gmcgarry { 493 1.1 gmcgarry struct cec_softc *sc = v; 494 1.1 gmcgarry bus_space_tag_t iot = sc->sc_iot; 495 1.1 gmcgarry bus_space_handle_t ioh = sc->sc_ioh; 496 1.1 gmcgarry 497 1.1 gmcgarry DPRINTF(DBG_FOLLOW, 498 1.1 gmcgarry ("cecxfer: slave=%d sec=%d buf=%p count=%d dir=%x timo=%d\n", 499 1.1 gmcgarry slave, sec, buf, count, dir, timo)); 500 1.1 gmcgarry 501 1.1 gmcgarry sc->sc_flags |= CECF_IO; 502 1.1 gmcgarry if (dir == GPIB_READ) 503 1.1 gmcgarry sc->sc_flags |= CECF_READ; 504 1.1 gmcgarry if (timo) { 505 1.1 gmcgarry sc->sc_flags |= CECF_TIMO; 506 1.1 gmcgarry callout_reset(&sc->sc_timeout_ch, 5*hz, cectimeout, sc); 507 1.1 gmcgarry } 508 1.1 gmcgarry 509 1.1 gmcgarry if (sc->sc_flags & CECF_READ) { 510 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("cecxfer: DMA read request\n")); 511 1.1 gmcgarry if ((sc->sc_flags & CECF_USEDMA) != 0) { 512 1.1 gmcgarry isa_dmastart(sc->sc_ic, sc->sc_drq, buf, count, NULL, 513 1.1 gmcgarry DMAMODE_READ | DMAMODE_DEMAND, BUS_DMA_NOWAIT); 514 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_DMAI); 515 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_IMR1, IMR1_END); 516 1.1 gmcgarry // XXX (void) cecrecv(sc, slave, sec, NULL, 0); 517 1.1 gmcgarry (void) gpibrecv(&cec_ic, slave, sec, NULL, 0); 518 1.1 gmcgarry } else { 519 1.1 gmcgarry /* XXX this doesn't work */ 520 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("cecxfer: polling instead\n")); 521 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_IMR1, IMR1_END); 522 1.1 gmcgarry // XXX (void) cecrecv(sc, slave, sec, buf, count); 523 1.1 gmcgarry (void) gpibrecv(&cec_ic, slave, sec, buf, count); 524 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_CO); 525 1.1 gmcgarry } 526 1.1 gmcgarry } else { 527 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("cecxfer: DMA write request\n")); 528 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_IMR2, 0); 529 1.1 gmcgarry if (count < cecdmathresh || 530 1.1 gmcgarry (sc->sc_flags & CECF_USEDMA) == 0) { 531 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("cecxfer: polling instead\n")); 532 1.1 gmcgarry // XXX (void) cecsend(sc, slave, sec, buf, count); 533 1.1 gmcgarry (void) gpibsend(&cec_ic, slave, sec, buf, count); 534 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_CO); 535 1.1 gmcgarry return; 536 1.1 gmcgarry } 537 1.1 gmcgarry /* we send the last byte with EOI set */ 538 1.1 gmcgarry isa_dmastart(sc->sc_ic, sc->sc_drq, buf, count-1, NULL, 539 1.1 gmcgarry DMAMODE_WRITE | DMAMODE_DEMAND, BUS_DMA_NOWAIT); 540 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_IMR2, IMR2_DMAO); 541 1.1 gmcgarry // XXX (void) cecsend(sc, slave, sec, NULL, 0); 542 1.1 gmcgarry (void) gpibsend(&cec_ic, slave, sec, NULL, 0); 543 1.1 gmcgarry while (!isa_dmafinished(sc->sc_ic, sc->sc_drq)) 544 1.1 gmcgarry DELAY(1); 545 1.1 gmcgarry (void) cecwait(sc, ISR1_DO, 0); 546 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SEOI); 547 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_CDOR, *(char *)buf+count); 548 1.1 gmcgarry /* generate interrupt */ 549 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_IMR1, IMR1_DO); 550 1.1 gmcgarry } 551 1.1 gmcgarry } 552 1.1 gmcgarry 553 1.1 gmcgarry void 554 1.1 gmcgarry cecifc(void *v) 555 1.1 gmcgarry { 556 1.1 gmcgarry struct cec_softc *sc = v; 557 1.1 gmcgarry 558 1.1 gmcgarry nec7210_ifc(sc); 559 1.1 gmcgarry } 560 1.1 gmcgarry 561 1.1 gmcgarry static int 562 1.1 gmcgarry nec7210_setaddress(struct cec_softc *sc, int pri, int sec) 563 1.1 gmcgarry { 564 1.1 gmcgarry bus_space_tag_t iot = sc->sc_iot; 565 1.1 gmcgarry bus_space_handle_t ioh = sc->sc_ioh; 566 1.1 gmcgarry u_int8_t admr; 567 1.1 gmcgarry 568 1.1 gmcgarry /* assign our primary address */ 569 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_ADDR, (pri & ADDR_MASK)); 570 1.1 gmcgarry 571 1.1 gmcgarry admr = ADMR_TRM0 | ADMR_TRM1; 572 1.1 gmcgarry 573 1.1 gmcgarry /* assign our secondary address */ 574 1.1 gmcgarry if (sec != -1) { 575 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_ADDR, 576 1.1 gmcgarry (ADDR_ARS | (sec & ADDR_MASK))); 577 1.1 gmcgarry admr |= ADMR_ADM1; 578 1.1 gmcgarry } else { 579 1.1 gmcgarry /* disable secondary address */ 580 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_ADDR, 581 1.1 gmcgarry (ADDR_ARS | ADDR_DT | ADDR_DL)); 582 1.1 gmcgarry admr |= ADMR_ADM0; 583 1.1 gmcgarry } 584 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_ADMR, admr); 585 1.1 gmcgarry 586 1.1 gmcgarry return (0); 587 1.1 gmcgarry } 588 1.1 gmcgarry 589 1.1 gmcgarry static void 590 1.1 gmcgarry nec7210_init(struct cec_softc *sc) 591 1.1 gmcgarry { 592 1.1 gmcgarry bus_space_tag_t iot = sc->sc_iot; 593 1.1 gmcgarry bus_space_handle_t ioh = sc->sc_ioh; 594 1.1 gmcgarry 595 1.1 gmcgarry /* reset chip */ 596 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_CRST); 597 1.1 gmcgarry 598 1.1 gmcgarry /* clear interrupts */ 599 1.1 gmcgarry bus_space_read_1(iot, ioh, NEC7210_CPTR); 600 1.1 gmcgarry bus_space_read_1(iot, ioh, NEC7210_ISR1); 601 1.1 gmcgarry bus_space_read_1(iot, ioh, NEC7210_ISR2); 602 1.1 gmcgarry 603 1.1 gmcgarry /* initialise interrupts */ 604 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_IMR1, 0); 605 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_IMR2, 0); 606 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_SPMR, 0); 607 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_EOSR, 0); 608 1.1 gmcgarry 609 1.1 gmcgarry /* set internal clock to 8MHz */ 610 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_ICR | 0x8)); 611 1.1 gmcgarry /* parallel poll unconfigure */ 612 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_PPOLL | PPOLL_PPU)); 613 1.1 gmcgarry 614 1.1 gmcgarry /* assign our address */ 615 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_ADDR, 0); 616 1.1 gmcgarry /* disable secondary address */ 617 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_ADDR, 618 1.1 gmcgarry (ADDR_ARS | ADDR_DT | ADDR_DL)); 619 1.1 gmcgarry 620 1.1 gmcgarry /* setup transceivers */ 621 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_ADMR, 622 1.1 gmcgarry (ADMR_ADM0 | ADMR_TRM0 | ADMR_TRM1)); 623 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, 624 1.1 gmcgarry (AUXMR_REGA | AUX_A_HSNORM)); 625 1.1 gmcgarry 626 1.1 gmcgarry /* set INT pin to active high */ 627 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXMR_REGB); 628 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXMR_REGE); 629 1.1 gmcgarry 630 1.1 gmcgarry /* holdoff on end condition */ 631 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_REGA | AUX_A_HLDE)); 632 1.1 gmcgarry 633 1.1 gmcgarry /* reconnect to bus */ 634 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, (AUXMR_CMD | AUXCMD_IEPON)); 635 1.1 gmcgarry } 636 1.1 gmcgarry 637 1.1 gmcgarry /* 638 1.1 gmcgarry * Place all devices on the bus into quiescient state ready for 639 1.1 gmcgarry * remote programming. 640 1.1 gmcgarry * Obviously, we're the system controller upon exit. 641 1.1 gmcgarry */ 642 1.1 gmcgarry void 643 1.1 gmcgarry nec7210_ifc(struct cec_softc *sc) 644 1.1 gmcgarry { 645 1.1 gmcgarry bus_space_tag_t iot = sc->sc_iot; 646 1.1 gmcgarry bus_space_handle_t ioh = sc->sc_ioh; 647 1.1 gmcgarry 648 1.1 gmcgarry /*XXX*/ bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA); 649 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_CREN); 650 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SIFC); 651 1.1 gmcgarry /* wait for devices to enter quiescient state */ 652 1.1 gmcgarry DELAY(100); 653 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_CIFC); 654 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_SREN); 655 1.1 gmcgarry } 656 1.1 gmcgarry 657 1.1 gmcgarry static int 658 1.1 gmcgarry cecwait(struct cec_softc *sc, int x1, int x2) 659 1.1 gmcgarry { 660 1.1 gmcgarry int timo = cecwtimeout; 661 1.1 gmcgarry bus_space_tag_t iot = sc->sc_iot; 662 1.1 gmcgarry bus_space_handle_t ioh = sc->sc_ioh; 663 1.1 gmcgarry u_int8_t stat1, stat2; 664 1.1 gmcgarry 665 1.1 gmcgarry DPRINTF(DBG_WAIT, ("cecwait: sc=%p, x1=0x%x x2=0x%x\n", sc, x1, x2)); 666 1.1 gmcgarry 667 1.1 gmcgarry for (;;) { 668 1.1 gmcgarry stat1 = bus_space_read_1(iot, ioh, NEC7210_ISR1); 669 1.1 gmcgarry stat2 = bus_space_read_1(iot, ioh, NEC7210_ISR2); 670 1.1 gmcgarry #if 0 671 1.1 gmcgarry if ((stat1 & ISR1_ERR)) { 672 1.1 gmcgarry DPRINTF(DBG_WAIT, ("cecwait: got ERR\n")); 673 1.1 gmcgarry return (1); 674 1.1 gmcgarry } 675 1.1 gmcgarry #endif 676 1.1 gmcgarry if (--timo == 0) { 677 1.1 gmcgarry DPRINTF(DBG_REPORTTIME, 678 1.1 gmcgarry ("cecwait: timeout x1=0x%x x2=0x%x\n", x1, x2)); 679 1.1 gmcgarry return (1); 680 1.1 gmcgarry } 681 1.1 gmcgarry if ((stat1 & x1) || (stat2 & x2)) 682 1.1 gmcgarry break; 683 1.1 gmcgarry DELAY(1); 684 1.1 gmcgarry } 685 1.1 gmcgarry return (0); 686 1.1 gmcgarry } 687 1.1 gmcgarry 688 1.1 gmcgarry static void 689 1.1 gmcgarry cectimeout(void *v) 690 1.1 gmcgarry { 691 1.1 gmcgarry struct cec_softc *sc = v; 692 1.1 gmcgarry bus_space_tag_t iot = sc->sc_iot; 693 1.1 gmcgarry bus_space_handle_t ioh = sc->sc_ioh; 694 1.1 gmcgarry int s; 695 1.1 gmcgarry 696 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("cectimeout: sc=%p\n", sc)); 697 1.1 gmcgarry 698 1.1 gmcgarry s = splbio(); 699 1.1 gmcgarry if (sc->sc_flags & CECF_IO) { 700 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_IMR1, 0); 701 1.1 gmcgarry bus_space_write_2(iot, ioh, NEC7210_IMR2, 0); 702 1.1 gmcgarry bus_space_write_1(iot, ioh, NEC7210_AUXMR, AUXCMD_TCA); 703 1.1 gmcgarry sc->sc_flags &= ~(CECF_IO | CECF_READ | CECF_TIMO); 704 1.1 gmcgarry isa_dmaabort(sc->sc_ic, sc->sc_drq); 705 1.13 chs aprint_error_dev(sc->sc_dev, "%s timeout\n", 706 1.1 gmcgarry sc->sc_flags & CECF_READ ? "read" : "write"); 707 1.1 gmcgarry gpibintr(sc->sc_gpib); 708 1.1 gmcgarry } 709 1.1 gmcgarry splx(s); 710 1.1 gmcgarry } 711