1 1.44 thorpej /* $NetBSD: fhpib.c,v 1.44 2024/01/16 05:48:28 thorpej Exp $ */ 2 1.19 thorpej 3 1.19 thorpej /*- 4 1.19 thorpej * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. 5 1.19 thorpej * All rights reserved. 6 1.19 thorpej * 7 1.19 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.19 thorpej * by Jason R. Thorpe. 9 1.19 thorpej * 10 1.19 thorpej * Redistribution and use in source and binary forms, with or without 11 1.19 thorpej * modification, are permitted provided that the following conditions 12 1.19 thorpej * are met: 13 1.19 thorpej * 1. Redistributions of source code must retain the above copyright 14 1.19 thorpej * notice, this list of conditions and the following disclaimer. 15 1.19 thorpej * 2. Redistributions in binary form must reproduce the above copyright 16 1.19 thorpej * notice, this list of conditions and the following disclaimer in the 17 1.19 thorpej * documentation and/or other materials provided with the distribution. 18 1.19 thorpej * 19 1.19 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.19 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.19 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.19 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.19 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.19 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.19 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.19 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.19 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.19 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.19 thorpej * POSSIBILITY OF SUCH DAMAGE. 30 1.19 thorpej */ 31 1.5 cgd 32 1.1 cgd /* 33 1.4 mycroft * Copyright (c) 1982, 1990, 1993 34 1.4 mycroft * The Regents of the University of California. All rights reserved. 35 1.1 cgd * 36 1.1 cgd * Redistribution and use in source and binary forms, with or without 37 1.1 cgd * modification, are permitted provided that the following conditions 38 1.1 cgd * are met: 39 1.1 cgd * 1. Redistributions of source code must retain the above copyright 40 1.1 cgd * notice, this list of conditions and the following disclaimer. 41 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 42 1.1 cgd * notice, this list of conditions and the following disclaimer in the 43 1.1 cgd * documentation and/or other materials provided with the distribution. 44 1.27 agc * 3. Neither the name of the University nor the names of its contributors 45 1.1 cgd * may be used to endorse or promote products derived from this software 46 1.1 cgd * without specific prior written permission. 47 1.1 cgd * 48 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 1.1 cgd * SUCH DAMAGE. 59 1.1 cgd * 60 1.5 cgd * @(#)fhpib.c 8.2 (Berkeley) 1/12/94 61 1.1 cgd */ 62 1.1 cgd 63 1.1 cgd /* 64 1.1 cgd * 98625A/B HPIB driver 65 1.1 cgd */ 66 1.22 gmcgarry 67 1.22 gmcgarry #include <sys/cdefs.h> 68 1.44 thorpej __KERNEL_RCSID(0, "$NetBSD: fhpib.c,v 1.44 2024/01/16 05:48:28 thorpej Exp $"); 69 1.1 cgd 70 1.4 mycroft #include <sys/param.h> 71 1.4 mycroft #include <sys/systm.h> 72 1.21 thorpej #include <sys/callout.h> 73 1.6 mycroft #include <sys/kernel.h> 74 1.4 mycroft #include <sys/buf.h> 75 1.14 thorpej #include <sys/device.h> 76 1.14 thorpej 77 1.14 thorpej #include <machine/autoconf.h> 78 1.17 thorpej #include <machine/intr.h> 79 1.14 thorpej 80 1.14 thorpej #include <hp300/dev/diovar.h> 81 1.14 thorpej #include <hp300/dev/diodevs.h> 82 1.14 thorpej 83 1.14 thorpej #include <hp300/dev/dmavar.h> 84 1.4 mycroft 85 1.4 mycroft #include <hp300/dev/fhpibreg.h> 86 1.4 mycroft #include <hp300/dev/hpibvar.h> 87 1.1 cgd 88 1.1 cgd /* 89 1.1 cgd * Inline version of fhpibwait to be used in places where 90 1.1 cgd * we don't worry about getting hung. 91 1.1 cgd */ 92 1.11 thorpej #define FHPIBWAIT(hd, m) while (((hd)->hpib_intr & (m)) == 0) DELAY(1) 93 1.1 cgd 94 1.1 cgd #ifdef DEBUG 95 1.1 cgd int fhpibdebugunit = -1; 96 1.1 cgd int fhpibdebug = 0; 97 1.1 cgd #define FDB_FAIL 0x01 98 1.1 cgd #define FDB_DMA 0x02 99 1.1 cgd #define FDB_WAIT 0x04 100 1.1 cgd #define FDB_PPOLL 0x08 101 1.1 cgd 102 1.1 cgd int dopriodma = 0; /* use high priority DMA */ 103 1.25 wiz int doworddma = 1; /* non-zero if we should attempt word DMA */ 104 1.1 cgd int doppollint = 1; /* use ppoll interrupts instead of watchdog */ 105 1.4 mycroft int fhpibppolldelay = 50; 106 1.1 cgd #endif 107 1.1 cgd 108 1.29 thorpej static void fhpibifc(struct fhpibdevice *); 109 1.29 thorpej static void fhpibdmadone(void *); 110 1.29 thorpej static int fhpibwait(struct fhpibdevice *, int); 111 1.29 thorpej 112 1.29 thorpej static void fhpibreset(struct hpibbus_softc *); 113 1.29 thorpej static int fhpibsend(struct hpibbus_softc *, int, int, void *, int); 114 1.29 thorpej static int fhpibrecv(struct hpibbus_softc *, int, int, void *, int); 115 1.29 thorpej static int fhpibppoll(struct hpibbus_softc *); 116 1.29 thorpej static void fhpibppwatch(void *); 117 1.29 thorpej static void fhpibgo(struct hpibbus_softc *, int, int, void *, int, int, 118 1.29 thorpej int); 119 1.29 thorpej static void fhpibdone(struct hpibbus_softc *); 120 1.29 thorpej static int fhpibintr(void *); 121 1.7 thorpej 122 1.7 thorpej /* 123 1.7 thorpej * Our controller ops structure. 124 1.7 thorpej */ 125 1.29 thorpej static struct hpib_controller fhpib_controller = { 126 1.7 thorpej fhpibreset, 127 1.7 thorpej fhpibsend, 128 1.7 thorpej fhpibrecv, 129 1.7 thorpej fhpibppoll, 130 1.7 thorpej fhpibppwatch, 131 1.7 thorpej fhpibgo, 132 1.7 thorpej fhpibdone, 133 1.7 thorpej fhpibintr 134 1.7 thorpej }; 135 1.7 thorpej 136 1.14 thorpej struct fhpib_softc { 137 1.38 tsutsui device_t sc_dev; /* generic device glue */ 138 1.14 thorpej struct fhpibdevice *sc_regs; /* device registers */ 139 1.14 thorpej int sc_cmd; 140 1.14 thorpej struct hpibbus_softc *sc_hpibbus; /* XXX */ 141 1.21 thorpej struct callout sc_dmadone_ch; 142 1.21 thorpej struct callout sc_ppwatch_ch; 143 1.14 thorpej }; 144 1.14 thorpej 145 1.38 tsutsui static int fhpibmatch(device_t, cfdata_t, void *); 146 1.38 tsutsui static void fhpibattach(device_t, device_t, void *); 147 1.14 thorpej 148 1.38 tsutsui CFATTACH_DECL_NEW(fhpib, sizeof(struct fhpib_softc), 149 1.24 thorpej fhpibmatch, fhpibattach, NULL, NULL); 150 1.14 thorpej 151 1.29 thorpej static int 152 1.38 tsutsui fhpibmatch(device_t parent, cfdata_t cf, void *aux) 153 1.1 cgd { 154 1.14 thorpej struct dio_attach_args *da = aux; 155 1.7 thorpej 156 1.14 thorpej if (da->da_id == DIO_DEVICE_ID_FHPIB) 157 1.33 tsutsui return 1; 158 1.7 thorpej 159 1.33 tsutsui return 0; 160 1.8 thorpej } 161 1.8 thorpej 162 1.29 thorpej static void 163 1.38 tsutsui fhpibattach(device_t parent, device_t self, void *aux) 164 1.14 thorpej { 165 1.38 tsutsui struct fhpib_softc *sc = device_private(self); 166 1.14 thorpej struct dio_attach_args *da = aux; 167 1.14 thorpej struct hpibdev_attach_args ha; 168 1.34 tsutsui bus_space_handle_t bsh; 169 1.14 thorpej 170 1.38 tsutsui sc->sc_dev = self; 171 1.34 tsutsui if (bus_space_map(da->da_bst, da->da_addr, da->da_size, 0, &bsh)) { 172 1.38 tsutsui aprint_error(": can't map registers\n"); 173 1.14 thorpej return; 174 1.14 thorpej } 175 1.34 tsutsui sc->sc_regs = bus_space_vaddr(da->da_bst, bsh); 176 1.14 thorpej 177 1.38 tsutsui aprint_normal(": %s\n", DIO_DEVICE_DESC_FHPIB); 178 1.8 thorpej 179 1.14 thorpej /* Establish the interrupt handler. */ 180 1.44 thorpej (void)dio_intr_establish(fhpibintr, sc, da->da_ipl, ISRPRI_BIO); 181 1.14 thorpej 182 1.35 he callout_init(&sc->sc_dmadone_ch, 0); 183 1.35 he callout_init(&sc->sc_ppwatch_ch, 0); 184 1.21 thorpej 185 1.14 thorpej ha.ha_ops = &fhpib_controller; 186 1.14 thorpej ha.ha_type = HPIBC; /* XXX */ 187 1.14 thorpej ha.ha_ba = HPIBC_BA; 188 1.14 thorpej ha.ha_softcpp = &sc->sc_hpibbus; /* XXX */ 189 1.43 thorpej (void)config_found(self, &ha, hpibdevprint, CFARGS_NONE); 190 1.1 cgd } 191 1.1 cgd 192 1.29 thorpej static void 193 1.29 thorpej fhpibreset(struct hpibbus_softc *hs) 194 1.1 cgd { 195 1.38 tsutsui struct fhpib_softc *sc = device_private(device_parent(hs->sc_dev)); 196 1.14 thorpej struct fhpibdevice *hd = sc->sc_regs; 197 1.1 cgd 198 1.1 cgd hd->hpib_cid = 0xFF; 199 1.1 cgd DELAY(100); 200 1.1 cgd hd->hpib_cmd = CT_8BIT; 201 1.1 cgd hd->hpib_ar = AR_ARONC; 202 1.1 cgd fhpibifc(hd); 203 1.1 cgd hd->hpib_ie = IDS_IE; 204 1.1 cgd hd->hpib_data = C_DCL; 205 1.1 cgd DELAY(100000); 206 1.1 cgd /* 207 1.25 wiz * See if we can do word DMA. 208 1.1 cgd * If so, we should be able to write and read back the appropos bit. 209 1.1 cgd */ 210 1.1 cgd hd->hpib_ie |= IDS_WDMA; 211 1.1 cgd if (hd->hpib_ie & IDS_WDMA) { 212 1.1 cgd hd->hpib_ie &= ~IDS_WDMA; 213 1.1 cgd hs->sc_flags |= HPIBF_DMA16; 214 1.1 cgd #ifdef DEBUG 215 1.1 cgd if (fhpibdebug & FDB_DMA) 216 1.25 wiz printf("fhpibtype: %s has word DMA\n", 217 1.38 tsutsui device_xname(sc->sc_dev)); 218 1.1 cgd #endif 219 1.1 cgd } 220 1.1 cgd } 221 1.1 cgd 222 1.29 thorpej static void 223 1.29 thorpej fhpibifc(struct fhpibdevice *hd) 224 1.1 cgd { 225 1.33 tsutsui 226 1.1 cgd hd->hpib_cmd |= CT_IFC; 227 1.1 cgd hd->hpib_cmd |= CT_INITFIFO; 228 1.1 cgd DELAY(100); 229 1.1 cgd hd->hpib_cmd &= ~CT_IFC; 230 1.1 cgd hd->hpib_cmd |= CT_REN; 231 1.1 cgd hd->hpib_stat = ST_ATN; 232 1.1 cgd } 233 1.1 cgd 234 1.29 thorpej static int 235 1.29 thorpej fhpibsend(struct hpibbus_softc *hs, int slave, int sec, void *ptr, int origcnt) 236 1.1 cgd { 237 1.38 tsutsui struct fhpib_softc *sc = device_private(device_parent(hs->sc_dev)); 238 1.14 thorpej struct fhpibdevice *hd = sc->sc_regs; 239 1.15 scottr int cnt = origcnt; 240 1.15 scottr int timo; 241 1.7 thorpej char *addr = ptr; 242 1.1 cgd 243 1.1 cgd hd->hpib_stat = 0; 244 1.1 cgd hd->hpib_imask = IM_IDLE | IM_ROOM; 245 1.1 cgd if (fhpibwait(hd, IM_IDLE) < 0) 246 1.1 cgd goto senderr; 247 1.1 cgd hd->hpib_stat = ST_ATN; 248 1.1 cgd hd->hpib_data = C_UNL; 249 1.1 cgd hd->hpib_data = C_TAG + hs->sc_ba; 250 1.1 cgd hd->hpib_data = C_LAG + slave; 251 1.6 mycroft if (sec < 0) { 252 1.6 mycroft if (sec == -2) /* selected device clear KLUDGE */ 253 1.6 mycroft hd->hpib_data = C_SDC; 254 1.6 mycroft } else 255 1.1 cgd hd->hpib_data = C_SCG + sec; 256 1.1 cgd if (fhpibwait(hd, IM_IDLE) < 0) 257 1.1 cgd goto senderr; 258 1.1 cgd if (cnt) { 259 1.1 cgd hd->hpib_stat = ST_WRITE; 260 1.1 cgd while (--cnt) { 261 1.1 cgd hd->hpib_data = *addr++; 262 1.1 cgd timo = hpibtimeout; 263 1.1 cgd while ((hd->hpib_intr & IM_ROOM) == 0) { 264 1.1 cgd if (--timo <= 0) 265 1.1 cgd goto senderr; 266 1.11 thorpej DELAY(1); 267 1.1 cgd } 268 1.1 cgd } 269 1.1 cgd hd->hpib_stat = ST_EOI; 270 1.1 cgd hd->hpib_data = *addr; 271 1.1 cgd FHPIBWAIT(hd, IM_ROOM); 272 1.1 cgd hd->hpib_stat = ST_ATN; 273 1.1 cgd /* XXX: HP-UX claims bug with CS80 transparent messages */ 274 1.1 cgd if (sec == 0x12) 275 1.1 cgd DELAY(150); 276 1.1 cgd hd->hpib_data = C_UNL; 277 1.1 cgd (void) fhpibwait(hd, IM_IDLE); 278 1.1 cgd } 279 1.1 cgd hd->hpib_imask = 0; 280 1.33 tsutsui return origcnt; 281 1.6 mycroft 282 1.1 cgd senderr: 283 1.1 cgd hd->hpib_imask = 0; 284 1.1 cgd fhpibifc(hd); 285 1.1 cgd #ifdef DEBUG 286 1.1 cgd if (fhpibdebug & FDB_FAIL) { 287 1.13 christos printf("%s: fhpibsend failed: slave %d, sec %x, ", 288 1.38 tsutsui device_xname(sc->sc_dev), slave, sec); 289 1.13 christos printf("sent %d of %d bytes\n", origcnt-cnt-1, origcnt); 290 1.1 cgd } 291 1.1 cgd #endif 292 1.33 tsutsui return origcnt - cnt - 1; 293 1.1 cgd } 294 1.1 cgd 295 1.29 thorpej static int 296 1.29 thorpej fhpibrecv(struct hpibbus_softc *hs, int slave, int sec, void *ptr, int origcnt) 297 1.1 cgd { 298 1.38 tsutsui struct fhpib_softc *sc = device_private(device_parent(hs->sc_dev)); 299 1.14 thorpej struct fhpibdevice *hd = sc->sc_regs; 300 1.15 scottr int cnt = origcnt; 301 1.15 scottr int timo; 302 1.7 thorpej char *addr = ptr; 303 1.1 cgd 304 1.6 mycroft /* 305 1.6 mycroft * Slave < 0 implies continuation of a previous receive 306 1.6 mycroft * that probably timed out. 307 1.6 mycroft */ 308 1.6 mycroft if (slave >= 0) { 309 1.6 mycroft hd->hpib_stat = 0; 310 1.6 mycroft hd->hpib_imask = IM_IDLE | IM_ROOM | IM_BYTE; 311 1.6 mycroft if (fhpibwait(hd, IM_IDLE) < 0) 312 1.6 mycroft goto recverror; 313 1.6 mycroft hd->hpib_stat = ST_ATN; 314 1.6 mycroft hd->hpib_data = C_UNL; 315 1.6 mycroft hd->hpib_data = C_LAG + hs->sc_ba; 316 1.6 mycroft hd->hpib_data = C_TAG + slave; 317 1.6 mycroft if (sec != -1) 318 1.6 mycroft hd->hpib_data = C_SCG + sec; 319 1.6 mycroft if (fhpibwait(hd, IM_IDLE) < 0) 320 1.6 mycroft goto recverror; 321 1.6 mycroft hd->hpib_stat = ST_READ0; 322 1.6 mycroft hd->hpib_data = 0; 323 1.6 mycroft } 324 1.1 cgd if (cnt) { 325 1.1 cgd while (--cnt >= 0) { 326 1.1 cgd timo = hpibtimeout; 327 1.1 cgd while ((hd->hpib_intr & IM_BYTE) == 0) { 328 1.1 cgd if (--timo == 0) 329 1.1 cgd goto recvbyteserror; 330 1.11 thorpej DELAY(1); 331 1.1 cgd } 332 1.1 cgd *addr++ = hd->hpib_data; 333 1.1 cgd } 334 1.1 cgd FHPIBWAIT(hd, IM_ROOM); 335 1.1 cgd hd->hpib_stat = ST_ATN; 336 1.1 cgd hd->hpib_data = (slave == 31) ? C_UNA : C_UNT; 337 1.1 cgd (void) fhpibwait(hd, IM_IDLE); 338 1.1 cgd } 339 1.1 cgd hd->hpib_imask = 0; 340 1.33 tsutsui return origcnt; 341 1.1 cgd 342 1.1 cgd recverror: 343 1.1 cgd fhpibifc(hd); 344 1.1 cgd recvbyteserror: 345 1.1 cgd hd->hpib_imask = 0; 346 1.1 cgd #ifdef DEBUG 347 1.1 cgd if (fhpibdebug & FDB_FAIL) { 348 1.13 christos printf("%s: fhpibrecv failed: slave %d, sec %x, ", 349 1.38 tsutsui device_xname(sc->sc_dev), slave, sec); 350 1.13 christos printf("got %d of %d bytes\n", origcnt-cnt-1, origcnt); 351 1.1 cgd } 352 1.1 cgd #endif 353 1.33 tsutsui return origcnt - cnt - 1; 354 1.1 cgd } 355 1.1 cgd 356 1.29 thorpej static void 357 1.29 thorpej fhpibgo(struct hpibbus_softc *hs, int slave, int sec, void *ptr, int count, 358 1.29 thorpej int rw, int timo) 359 1.1 cgd { 360 1.38 tsutsui struct fhpib_softc *sc = device_private(device_parent(hs->sc_dev)); 361 1.15 scottr struct fhpibdevice *hd = sc->sc_regs; 362 1.15 scottr int i; 363 1.7 thorpej char *addr = ptr; 364 1.1 cgd int flags = 0; 365 1.1 cgd 366 1.1 cgd hs->sc_flags |= HPIBF_IO; 367 1.6 mycroft if (timo) 368 1.6 mycroft hs->sc_flags |= HPIBF_TIMO; 369 1.1 cgd if (rw == B_READ) 370 1.1 cgd hs->sc_flags |= HPIBF_READ; 371 1.1 cgd #ifdef DEBUG 372 1.1 cgd else if (hs->sc_flags & HPIBF_READ) { 373 1.38 tsutsui printf("%s: HPIBF_READ still set\n", __func__); 374 1.1 cgd hs->sc_flags &= ~HPIBF_READ; 375 1.1 cgd } 376 1.1 cgd #endif 377 1.1 cgd hs->sc_count = count; 378 1.1 cgd hs->sc_addr = addr; 379 1.1 cgd #ifdef DEBUG 380 1.14 thorpej /* fhpibtransfer[unit]++; XXX */ 381 1.1 cgd #endif 382 1.1 cgd if ((hs->sc_flags & HPIBF_DMA16) && 383 1.1 cgd ((int)addr & 1) == 0 && count && (count & 1) == 0 384 1.1 cgd #ifdef DEBUG 385 1.1 cgd && doworddma 386 1.1 cgd #endif 387 1.1 cgd ) { 388 1.1 cgd #ifdef DEBUG 389 1.14 thorpej /* fhpibworddma[unit]++; XXX */ 390 1.1 cgd #endif 391 1.1 cgd flags |= DMAGO_WORD; 392 1.1 cgd hd->hpib_latch = 0; 393 1.1 cgd } 394 1.1 cgd #ifdef DEBUG 395 1.1 cgd if (dopriodma) 396 1.1 cgd flags |= DMAGO_PRI; 397 1.1 cgd #endif 398 1.1 cgd if (hs->sc_flags & HPIBF_READ) { 399 1.14 thorpej sc->sc_cmd = CT_REN | CT_8BIT; 400 1.1 cgd hs->sc_curcnt = count; 401 1.14 thorpej dmago(hs->sc_dq->dq_chan, addr, count, flags|DMAGO_READ); 402 1.14 thorpej if (fhpibrecv(hs, slave, sec, 0, 0) < 0) { 403 1.1 cgd #ifdef DEBUG 404 1.38 tsutsui printf("%s: recv failed, retrying...\n", __func__); 405 1.1 cgd #endif 406 1.38 tsutsui (void)fhpibrecv(hs, slave, sec, 0, 0); 407 1.1 cgd } 408 1.1 cgd i = hd->hpib_cmd; 409 1.14 thorpej hd->hpib_cmd = sc->sc_cmd; 410 1.14 thorpej hd->hpib_ie = IDS_DMA(hs->sc_dq->dq_chan) | 411 1.1 cgd ((flags & DMAGO_WORD) ? IDS_WDMA : 0); 412 1.40 christos __USE(i); 413 1.1 cgd return; 414 1.1 cgd } 415 1.14 thorpej sc->sc_cmd = CT_REN | CT_8BIT | CT_FIFOSEL; 416 1.1 cgd if (count < hpibdmathresh) { 417 1.1 cgd #ifdef DEBUG 418 1.14 thorpej /* fhpibnondma[unit]++; XXX */ 419 1.1 cgd if (flags & DMAGO_WORD) 420 1.14 thorpej /* fhpibworddma[unit]--; XXX */ ; 421 1.1 cgd #endif 422 1.1 cgd hs->sc_curcnt = count; 423 1.14 thorpej (void) fhpibsend(hs, slave, sec, addr, count); 424 1.14 thorpej fhpibdone(hs); 425 1.1 cgd return; 426 1.1 cgd } 427 1.1 cgd count -= (flags & DMAGO_WORD) ? 2 : 1; 428 1.1 cgd hs->sc_curcnt = count; 429 1.14 thorpej dmago(hs->sc_dq->dq_chan, addr, count, flags); 430 1.14 thorpej if (fhpibsend(hs, slave, sec, 0, 0) < 0) { 431 1.1 cgd #ifdef DEBUG 432 1.38 tsutsui printf("%s: send failed, retrying...\n", __func__); 433 1.1 cgd #endif 434 1.38 tsutsui (void)fhpibsend(hs, slave, sec, 0, 0); 435 1.1 cgd } 436 1.1 cgd i = hd->hpib_cmd; 437 1.14 thorpej hd->hpib_cmd = sc->sc_cmd; 438 1.14 thorpej hd->hpib_ie = IDS_DMA(hs->sc_dq->dq_chan) | IDS_WRITE | 439 1.1 cgd ((flags & DMAGO_WORD) ? IDS_WDMA : 0); 440 1.40 christos __USE(i); 441 1.1 cgd } 442 1.1 cgd 443 1.6 mycroft /* 444 1.6 mycroft * A DMA read can finish but the device can still be waiting (MAG-tape 445 1.6 mycroft * with more data than we're waiting for). This timeout routine 446 1.6 mycroft * takes care of that. Somehow, the thing gets hosed. For now, since 447 1.41 msaitoh * this should be a very rare occurrence, we RESET it. 448 1.6 mycroft */ 449 1.29 thorpej static void 450 1.29 thorpej fhpibdmadone(void *arg) 451 1.6 mycroft { 452 1.15 scottr struct hpibbus_softc *hs = arg; 453 1.38 tsutsui struct fhpib_softc *sc = device_private(device_parent(hs->sc_dev)); 454 1.6 mycroft int s = splbio(); 455 1.6 mycroft 456 1.6 mycroft if (hs->sc_flags & HPIBF_IO) { 457 1.15 scottr struct fhpibdevice *hd = sc->sc_regs; 458 1.15 scottr struct hpibqueue *hq; 459 1.6 mycroft 460 1.6 mycroft hd->hpib_imask = 0; 461 1.6 mycroft hd->hpib_cid = 0xFF; 462 1.6 mycroft DELAY(100); 463 1.6 mycroft hd->hpib_cmd = CT_8BIT; 464 1.6 mycroft hd->hpib_ar = AR_ARONC; 465 1.6 mycroft fhpibifc(hd); 466 1.6 mycroft hd->hpib_ie = IDS_IE; 467 1.6 mycroft hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO); 468 1.14 thorpej dmafree(hs->sc_dq); 469 1.14 thorpej 470 1.37 tsutsui hq = TAILQ_FIRST(&hs->sc_queue); 471 1.14 thorpej (hq->hq_intr)(hq->hq_softc); 472 1.6 mycroft } 473 1.14 thorpej splx(s); 474 1.6 mycroft } 475 1.6 mycroft 476 1.29 thorpej static void 477 1.29 thorpej fhpibdone(struct hpibbus_softc *hs) 478 1.1 cgd { 479 1.38 tsutsui struct fhpib_softc *sc = device_private(device_parent(hs->sc_dev)); 480 1.15 scottr struct fhpibdevice *hd = sc->sc_regs; 481 1.15 scottr char *addr; 482 1.15 scottr int cnt; 483 1.1 cgd 484 1.1 cgd cnt = hs->sc_curcnt; 485 1.1 cgd hs->sc_addr += cnt; 486 1.1 cgd hs->sc_count -= cnt; 487 1.1 cgd #ifdef DEBUG 488 1.32 thorpej if ((fhpibdebug & FDB_DMA) && 489 1.38 tsutsui fhpibdebugunit == device_unit(sc->sc_dev)) 490 1.38 tsutsui printf("%s: addr %p cnt %d\n", 491 1.38 tsutsui __func__, hs->sc_addr, hs->sc_count); 492 1.1 cgd #endif 493 1.6 mycroft if (hs->sc_flags & HPIBF_READ) { 494 1.1 cgd hd->hpib_imask = IM_IDLE | IM_BYTE; 495 1.6 mycroft if (hs->sc_flags & HPIBF_TIMO) 496 1.21 thorpej callout_reset(&sc->sc_dmadone_ch, hz >> 2, 497 1.21 thorpej fhpibdmadone, hs); 498 1.6 mycroft } else { 499 1.1 cgd cnt = hs->sc_count; 500 1.1 cgd if (cnt) { 501 1.1 cgd addr = hs->sc_addr; 502 1.1 cgd hd->hpib_imask = IM_IDLE | IM_ROOM; 503 1.1 cgd FHPIBWAIT(hd, IM_IDLE); 504 1.1 cgd hd->hpib_stat = ST_WRITE; 505 1.1 cgd while (--cnt) { 506 1.1 cgd hd->hpib_data = *addr++; 507 1.1 cgd FHPIBWAIT(hd, IM_ROOM); 508 1.1 cgd } 509 1.1 cgd hd->hpib_stat = ST_EOI; 510 1.1 cgd hd->hpib_data = *addr; 511 1.1 cgd } 512 1.1 cgd hd->hpib_imask = IM_IDLE; 513 1.1 cgd } 514 1.1 cgd hs->sc_flags |= HPIBF_DONE; 515 1.1 cgd hd->hpib_stat = ST_IENAB; 516 1.1 cgd hd->hpib_ie = IDS_IE; 517 1.1 cgd } 518 1.1 cgd 519 1.29 thorpej static int 520 1.29 thorpej fhpibintr(void *arg) 521 1.1 cgd { 522 1.14 thorpej struct fhpib_softc *sc = arg; 523 1.15 scottr struct hpibbus_softc *hs = sc->sc_hpibbus; 524 1.15 scottr struct fhpibdevice *hd = sc->sc_regs; 525 1.15 scottr struct hpibqueue *hq; 526 1.15 scottr int stat0; 527 1.1 cgd 528 1.1 cgd stat0 = hd->hpib_ids; 529 1.1 cgd if ((stat0 & (IDS_IE|IDS_IR)) != (IDS_IE|IDS_IR)) { 530 1.1 cgd #ifdef DEBUG 531 1.1 cgd if ((fhpibdebug & FDB_FAIL) && (stat0 & IDS_IR) && 532 1.1 cgd (hs->sc_flags & (HPIBF_IO|HPIBF_DONE)) != HPIBF_IO) 533 1.13 christos printf("%s: fhpibintr: bad status %x\n", 534 1.38 tsutsui device_xname(sc->sc_dev), stat0); 535 1.14 thorpej /* fhpibbadint[0]++; XXX */ 536 1.1 cgd #endif 537 1.33 tsutsui return 0; 538 1.1 cgd } 539 1.1 cgd if ((hs->sc_flags & (HPIBF_IO|HPIBF_DONE)) == HPIBF_IO) { 540 1.1 cgd #ifdef DEBUG 541 1.14 thorpej /* fhpibbadint[1]++; XXX */ 542 1.1 cgd #endif 543 1.33 tsutsui return 0; 544 1.1 cgd } 545 1.1 cgd #ifdef DEBUG 546 1.32 thorpej if ((fhpibdebug & FDB_DMA) && 547 1.38 tsutsui fhpibdebugunit == device_unit(sc->sc_dev)) 548 1.38 tsutsui printf("%s: flags %x\n", __func__, hs->sc_flags); 549 1.1 cgd #endif 550 1.37 tsutsui hq = TAILQ_FIRST(&hs->sc_queue); 551 1.1 cgd if (hs->sc_flags & HPIBF_IO) { 552 1.6 mycroft if (hs->sc_flags & HPIBF_TIMO) 553 1.21 thorpej callout_stop(&sc->sc_dmadone_ch); 554 1.1 cgd stat0 = hd->hpib_cmd; 555 1.14 thorpej hd->hpib_cmd = sc->sc_cmd & ~CT_8BIT; 556 1.1 cgd hd->hpib_stat = 0; 557 1.1 cgd hd->hpib_cmd = CT_REN | CT_8BIT; 558 1.1 cgd stat0 = hd->hpib_intr; 559 1.1 cgd hd->hpib_imask = 0; 560 1.6 mycroft hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO); 561 1.14 thorpej dmafree(hs->sc_dq); 562 1.14 thorpej (hq->hq_intr)(hq->hq_softc); 563 1.1 cgd } else if (hs->sc_flags & HPIBF_PPOLL) { 564 1.1 cgd stat0 = hd->hpib_intr; 565 1.1 cgd #ifdef DEBUG 566 1.1 cgd if ((fhpibdebug & FDB_FAIL) && 567 1.1 cgd doppollint && (stat0 & IM_PPRESP) == 0) 568 1.13 christos printf("%s: fhpibintr: bad intr reg %x\n", 569 1.38 tsutsui device_xname(sc->sc_dev), stat0); 570 1.1 cgd #endif 571 1.1 cgd hd->hpib_stat = 0; 572 1.1 cgd hd->hpib_imask = 0; 573 1.1 cgd #ifdef DEBUG 574 1.14 thorpej stat0 = fhpibppoll(hs); 575 1.16 scottr if ((fhpibdebug & FDB_PPOLL) && 576 1.38 tsutsui fhpibdebugunit == device_unit(sc->sc_dev)) 577 1.38 tsutsui printf("%s: got PPOLL status %x\n", __func__, stat0); 578 1.14 thorpej if ((stat0 & (0x80 >> hq->hq_slave)) == 0) { 579 1.4 mycroft /* 580 1.4 mycroft * XXX give it another shot (68040) 581 1.4 mycroft */ 582 1.14 thorpej /* fhpibppollfail[unit]++; XXX */ 583 1.4 mycroft DELAY(fhpibppolldelay); 584 1.14 thorpej stat0 = fhpibppoll(hs); 585 1.14 thorpej if ((stat0 & (0x80 >> hq->hq_slave)) == 0 && 586 1.16 scottr (fhpibdebug & FDB_PPOLL) && 587 1.38 tsutsui fhpibdebugunit == device_unit(sc->sc_dev)) 588 1.38 tsutsui printf("%s: PPOLL: unit %d slave %d stat %x\n", 589 1.38 tsutsui __func__, device_unit(sc->sc_dev), 590 1.38 tsutsui hq->hq_slave, stat0); 591 1.1 cgd } 592 1.1 cgd #endif 593 1.1 cgd hs->sc_flags &= ~HPIBF_PPOLL; 594 1.14 thorpej (hq->hq_intr)(hq->hq_softc); 595 1.1 cgd } 596 1.33 tsutsui return 1; 597 1.1 cgd } 598 1.1 cgd 599 1.29 thorpej static int 600 1.29 thorpej fhpibppoll(struct hpibbus_softc *hs) 601 1.1 cgd { 602 1.38 tsutsui struct fhpib_softc *sc = device_private(device_parent(hs->sc_dev)); 603 1.15 scottr struct fhpibdevice *hd = sc->sc_regs; 604 1.15 scottr int ppoll; 605 1.1 cgd 606 1.1 cgd hd->hpib_stat = 0; 607 1.1 cgd hd->hpib_psense = 0; 608 1.1 cgd hd->hpib_pmask = 0xFF; 609 1.1 cgd hd->hpib_imask = IM_PPRESP | IM_PABORT; 610 1.1 cgd DELAY(25); 611 1.1 cgd hd->hpib_intr = IM_PABORT; 612 1.1 cgd ppoll = hd->hpib_data; 613 1.1 cgd if (hd->hpib_intr & IM_PABORT) 614 1.1 cgd ppoll = 0; 615 1.1 cgd hd->hpib_imask = 0; 616 1.1 cgd hd->hpib_pmask = 0; 617 1.1 cgd hd->hpib_stat = ST_IENAB; 618 1.33 tsutsui return ppoll; 619 1.1 cgd } 620 1.1 cgd 621 1.29 thorpej static int 622 1.29 thorpej fhpibwait(struct fhpibdevice *hd, int x) 623 1.1 cgd { 624 1.15 scottr int timo = hpibtimeout; 625 1.1 cgd 626 1.1 cgd while ((hd->hpib_intr & x) == 0 && --timo) 627 1.11 thorpej DELAY(1); 628 1.1 cgd if (timo == 0) { 629 1.1 cgd #ifdef DEBUG 630 1.1 cgd if (fhpibdebug & FDB_FAIL) 631 1.38 tsutsui printf("%s(%p, %x) timeout\n", __func__, hd, x); 632 1.1 cgd #endif 633 1.33 tsutsui return -1; 634 1.1 cgd } 635 1.33 tsutsui return 0; 636 1.1 cgd } 637 1.1 cgd 638 1.1 cgd /* 639 1.4 mycroft * XXX: this will have to change if we ever allow more than one 640 1.1 cgd * pending operation per HP-IB. 641 1.1 cgd */ 642 1.29 thorpej static void 643 1.29 thorpej fhpibppwatch(void *arg) 644 1.1 cgd { 645 1.15 scottr struct hpibbus_softc *hs = arg; 646 1.38 tsutsui struct fhpib_softc *sc = device_private(device_parent(hs->sc_dev)); 647 1.15 scottr struct fhpibdevice *hd = sc->sc_regs; 648 1.15 scottr int slave; 649 1.1 cgd 650 1.1 cgd if ((hs->sc_flags & HPIBF_PPOLL) == 0) 651 1.1 cgd return; 652 1.37 tsutsui slave = (0x80 >> TAILQ_FIRST(&hs->sc_queue)->hq_slave); 653 1.1 cgd #ifdef DEBUG 654 1.1 cgd if (!doppollint) { 655 1.14 thorpej if (fhpibppoll(hs) & slave) { 656 1.1 cgd hd->hpib_stat = ST_IENAB; 657 1.1 cgd hd->hpib_imask = IM_IDLE | IM_ROOM; 658 1.1 cgd } else 659 1.21 thorpej callout_reset(&sc->sc_ppwatch_ch, 1, fhpibppwatch, sc); 660 1.1 cgd return; 661 1.1 cgd } 662 1.32 thorpej if ((fhpibdebug & FDB_PPOLL) && 663 1.38 tsutsui device_unit(sc->sc_dev) == fhpibdebugunit) 664 1.38 tsutsui printf("%s: sense request on %s\n", 665 1.38 tsutsui __func__, device_xname(sc->sc_dev)); 666 1.1 cgd #endif 667 1.1 cgd hd->hpib_psense = ~slave; 668 1.1 cgd hd->hpib_pmask = slave; 669 1.1 cgd hd->hpib_stat = ST_IENAB; 670 1.1 cgd hd->hpib_imask = IM_PPRESP | IM_PABORT; 671 1.1 cgd hd->hpib_ie = IDS_IE; 672 1.1 cgd } 673