1 1.44 thorpej /* $NetBSD: nhpib.c,v 1.44 2024/01/16 05:48:28 thorpej Exp $ */ 2 1.18 thorpej 3 1.18 thorpej /*- 4 1.18 thorpej * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. 5 1.18 thorpej * All rights reserved. 6 1.18 thorpej * 7 1.18 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.18 thorpej * by Jason R. Thorpe. 9 1.18 thorpej * 10 1.18 thorpej * Redistribution and use in source and binary forms, with or without 11 1.18 thorpej * modification, are permitted provided that the following conditions 12 1.18 thorpej * are met: 13 1.18 thorpej * 1. Redistributions of source code must retain the above copyright 14 1.18 thorpej * notice, this list of conditions and the following disclaimer. 15 1.18 thorpej * 2. Redistributions in binary form must reproduce the above copyright 16 1.18 thorpej * notice, this list of conditions and the following disclaimer in the 17 1.18 thorpej * documentation and/or other materials provided with the distribution. 18 1.18 thorpej * 19 1.18 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.18 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.18 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.18 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.18 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.18 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.18 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.18 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.18 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.18 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.18 thorpej * POSSIBILITY OF SUCH DAMAGE. 30 1.18 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.29 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 * @(#)nhpib.c 8.2 (Berkeley) 1/12/94 61 1.1 cgd */ 62 1.1 cgd 63 1.1 cgd /* 64 1.1 cgd * Internal/98624 HPIB driver 65 1.1 cgd */ 66 1.24 gmcgarry 67 1.24 gmcgarry #include <sys/cdefs.h> 68 1.44 thorpej __KERNEL_RCSID(0, "$NetBSD: nhpib.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.22 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.27 gmcgarry #include <machine/bus.h> 78 1.14 thorpej 79 1.27 gmcgarry #include <hp300/dev/intiovar.h> 80 1.14 thorpej #include <hp300/dev/diovar.h> 81 1.14 thorpej #include <hp300/dev/diodevs.h> 82 1.14 thorpej #include <hp300/dev/dmavar.h> 83 1.4 mycroft 84 1.4 mycroft #include <hp300/dev/nhpibreg.h> 85 1.4 mycroft #include <hp300/dev/hpibvar.h> 86 1.1 cgd 87 1.6 mycroft /* 88 1.6 mycroft * ODD parity table for listen and talk addresses and secondary commands. 89 1.6 mycroft * The TI9914A doesn't produce the parity bit. 90 1.6 mycroft */ 91 1.31 thorpej static const u_char listnr_par[] = { 92 1.6 mycroft 0040,0241,0242,0043,0244,0045,0046,0247, 93 1.6 mycroft 0250,0051,0052,0253,0054,0255,0256,0057, 94 1.6 mycroft 0260,0061,0062,0263,0064,0265,0266,0067, 95 1.6 mycroft 0070,0271,0272,0073,0274,0075,0076,0277, 96 1.6 mycroft }; 97 1.31 thorpej static const u_char talker_par[] = { 98 1.6 mycroft 0100,0301,0302,0103,0304,0105,0106,0307, 99 1.6 mycroft 0310,0111,0112,0313,0114,0315,0316,0117, 100 1.6 mycroft 0320,0121,0122,0323,0124,0325,0326,0127, 101 1.6 mycroft 0130,0331,0332,0133,0334,0135,0136,0337, 102 1.6 mycroft }; 103 1.31 thorpej static const u_char sec_par[] = { 104 1.6 mycroft 0340,0141,0142,0343,0144,0345,0346,0147, 105 1.6 mycroft 0150,0351,0352,0153,0354,0155,0156,0357, 106 1.6 mycroft 0160,0361,0362,0163,0364,0165,0166,0367, 107 1.6 mycroft 0370,0171,0172,0373,0174,0375,0376,0177 108 1.6 mycroft }; 109 1.6 mycroft 110 1.31 thorpej static void nhpibifc(struct nhpibdevice *); 111 1.31 thorpej static void nhpibreadtimo(void *); 112 1.31 thorpej static int nhpibwait(struct nhpibdevice *, int); 113 1.31 thorpej 114 1.31 thorpej static void nhpibreset(struct hpibbus_softc *); 115 1.31 thorpej static int nhpibsend(struct hpibbus_softc *, int, int, void *, int); 116 1.31 thorpej static int nhpibrecv(struct hpibbus_softc *, int, int, void *, int); 117 1.31 thorpej static int nhpibppoll(struct hpibbus_softc *); 118 1.31 thorpej static void nhpibppwatch(void *); 119 1.31 thorpej static void nhpibgo(struct hpibbus_softc *, int, int, void *, int, int, 120 1.31 thorpej int); 121 1.31 thorpej static void nhpibdone(struct hpibbus_softc *); 122 1.31 thorpej static int nhpibintr(void *); 123 1.7 thorpej 124 1.7 thorpej /* 125 1.7 thorpej * Our controller ops structure. 126 1.7 thorpej */ 127 1.31 thorpej static struct hpib_controller nhpib_controller = { 128 1.7 thorpej nhpibreset, 129 1.7 thorpej nhpibsend, 130 1.7 thorpej nhpibrecv, 131 1.7 thorpej nhpibppoll, 132 1.7 thorpej nhpibppwatch, 133 1.7 thorpej nhpibgo, 134 1.7 thorpej nhpibdone, 135 1.7 thorpej nhpibintr 136 1.7 thorpej }; 137 1.7 thorpej 138 1.14 thorpej struct nhpib_softc { 139 1.39 tsutsui device_t sc_dev; /* generic device glue */ 140 1.27 gmcgarry 141 1.27 gmcgarry bus_space_tag_t sc_bst; 142 1.27 gmcgarry bus_space_handle_t sc_bsh; 143 1.27 gmcgarry 144 1.14 thorpej struct nhpibdevice *sc_regs; /* device registers */ 145 1.14 thorpej struct hpibbus_softc *sc_hpibbus; /* XXX */ 146 1.27 gmcgarry 147 1.27 gmcgarry int sc_myaddr; 148 1.27 gmcgarry int sc_type; 149 1.27 gmcgarry 150 1.22 thorpej struct callout sc_read_ch; 151 1.22 thorpej struct callout sc_ppwatch_ch; 152 1.14 thorpej }; 153 1.14 thorpej 154 1.39 tsutsui static int nhpib_dio_match(device_t, cfdata_t, void *); 155 1.39 tsutsui static void nhpib_dio_attach(device_t, device_t, void *); 156 1.39 tsutsui static int nhpib_intio_match(device_t, cfdata_t, void *); 157 1.39 tsutsui static void nhpib_intio_attach(device_t, device_t, void *); 158 1.27 gmcgarry 159 1.31 thorpej static void nhpib_common_attach(struct nhpib_softc *, const char *); 160 1.27 gmcgarry 161 1.39 tsutsui CFATTACH_DECL_NEW(nhpib_dio, sizeof(struct nhpib_softc), 162 1.27 gmcgarry nhpib_dio_match, nhpib_dio_attach, NULL, NULL); 163 1.27 gmcgarry 164 1.39 tsutsui CFATTACH_DECL_NEW(nhpib_intio, sizeof(struct nhpib_softc), 165 1.27 gmcgarry nhpib_intio_match, nhpib_intio_attach, NULL, NULL); 166 1.27 gmcgarry 167 1.31 thorpej static int 168 1.39 tsutsui nhpib_intio_match(device_t parent, cfdata_t cf, void *aux) 169 1.27 gmcgarry { 170 1.27 gmcgarry struct intio_attach_args *ia = aux; 171 1.27 gmcgarry 172 1.27 gmcgarry if (strcmp("hpib", ia->ia_modname) == 0) 173 1.35 tsutsui return 1; 174 1.14 thorpej 175 1.35 tsutsui return 0; 176 1.27 gmcgarry } 177 1.14 thorpej 178 1.31 thorpej static int 179 1.39 tsutsui nhpib_dio_match(device_t parent, cfdata_t cf, void *aux) 180 1.1 cgd { 181 1.14 thorpej struct dio_attach_args *da = aux; 182 1.1 cgd 183 1.27 gmcgarry if (da->da_id == DIO_DEVICE_ID_NHPIB) 184 1.35 tsutsui return 1; 185 1.8 thorpej 186 1.35 tsutsui return 0; 187 1.8 thorpej } 188 1.8 thorpej 189 1.31 thorpej static void 190 1.39 tsutsui nhpib_intio_attach(device_t parent, device_t self, void *aux) 191 1.27 gmcgarry { 192 1.39 tsutsui struct nhpib_softc *sc = device_private(self); 193 1.27 gmcgarry struct intio_attach_args *ia = aux; 194 1.28 tsutsui bus_space_tag_t bst = ia->ia_bst; 195 1.27 gmcgarry const char *desc = "internal HP-IB"; 196 1.27 gmcgarry 197 1.39 tsutsui sc->sc_dev = self; 198 1.28 tsutsui if (bus_space_map(bst, ia->ia_iobase, INTIO_DEVSIZE, 0, &sc->sc_bsh)) { 199 1.39 tsutsui aprint_error(": can't map registers\n"); 200 1.27 gmcgarry return; 201 1.27 gmcgarry } 202 1.27 gmcgarry 203 1.28 tsutsui sc->sc_bst = bst; 204 1.27 gmcgarry sc->sc_myaddr = HPIBA_BA; 205 1.27 gmcgarry sc->sc_type = HPIBA; 206 1.27 gmcgarry 207 1.27 gmcgarry nhpib_common_attach(sc, desc); 208 1.27 gmcgarry 209 1.27 gmcgarry /* establish the interrupt handler */ 210 1.35 tsutsui (void)intio_intr_establish(nhpibintr, sc, ia->ia_ipl, IPL_BIO); 211 1.27 gmcgarry } 212 1.27 gmcgarry 213 1.31 thorpej static void 214 1.39 tsutsui nhpib_dio_attach(device_t parent, device_t self, void *aux) 215 1.14 thorpej { 216 1.39 tsutsui struct nhpib_softc *sc = device_private(self); 217 1.14 thorpej struct dio_attach_args *da = aux; 218 1.28 tsutsui bus_space_tag_t bst = da->da_bst; 219 1.27 gmcgarry const char *desc = DIO_DEVICE_DESC_NHPIB; 220 1.14 thorpej 221 1.39 tsutsui sc->sc_dev = self; 222 1.28 tsutsui if (bus_space_map(bst, da->da_addr, da->da_size, 0, &sc->sc_bsh)) { 223 1.39 tsutsui aprint_error(": can't map registers\n"); 224 1.14 thorpej return; 225 1.14 thorpej } 226 1.8 thorpej 227 1.39 tsutsui sc->sc_dev = self; 228 1.28 tsutsui sc->sc_bst = bst; 229 1.27 gmcgarry /* read address off switches */ 230 1.27 gmcgarry sc->sc_myaddr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, 5); 231 1.27 gmcgarry sc->sc_type = HPIBB; 232 1.27 gmcgarry 233 1.27 gmcgarry nhpib_common_attach(sc, desc); 234 1.27 gmcgarry 235 1.27 gmcgarry /* establish the interrupt handler */ 236 1.44 thorpej (void)dio_intr_establish(nhpibintr, sc, da->da_ipl, ISRPRI_BIO); 237 1.27 gmcgarry } 238 1.8 thorpej 239 1.31 thorpej static void 240 1.31 thorpej nhpib_common_attach(struct nhpib_softc *sc, const char *desc) 241 1.27 gmcgarry { 242 1.30 tsutsui struct hpibdev_attach_args ha; 243 1.14 thorpej 244 1.39 tsutsui aprint_normal(": %s\n", desc); 245 1.14 thorpej 246 1.39 tsutsui sc->sc_regs = bus_space_vaddr(sc->sc_bst, sc->sc_bsh); 247 1.14 thorpej 248 1.36 he callout_init(&sc->sc_read_ch, 0); 249 1.36 he callout_init(&sc->sc_ppwatch_ch, 0); 250 1.22 thorpej 251 1.14 thorpej ha.ha_ops = &nhpib_controller; 252 1.27 gmcgarry ha.ha_type = sc->sc_type; /* XXX */ 253 1.27 gmcgarry ha.ha_ba = sc->sc_myaddr; 254 1.27 gmcgarry ha.ha_softcpp = &sc->sc_hpibbus; /* XXX */ 255 1.43 thorpej (void)config_found(sc->sc_dev, &ha, hpibdevprint, CFARGS_NONE); 256 1.1 cgd } 257 1.1 cgd 258 1.31 thorpej static void 259 1.31 thorpej nhpibreset(struct hpibbus_softc *hs) 260 1.1 cgd { 261 1.39 tsutsui struct nhpib_softc *sc = device_private(device_parent(hs->sc_dev)); 262 1.14 thorpej struct nhpibdevice *hd = sc->sc_regs; 263 1.1 cgd 264 1.1 cgd hd->hpib_acr = AUX_SSWRST; 265 1.1 cgd hd->hpib_ar = hs->sc_ba; 266 1.1 cgd hd->hpib_lim = LIS_ERR; 267 1.1 cgd hd->hpib_mim = 0; 268 1.1 cgd hd->hpib_acr = AUX_CDAI; 269 1.1 cgd hd->hpib_acr = AUX_CSHDW; 270 1.1 cgd hd->hpib_acr = AUX_SSTD1; 271 1.1 cgd hd->hpib_acr = AUX_SVSTD1; 272 1.1 cgd hd->hpib_acr = AUX_CPP; 273 1.1 cgd hd->hpib_acr = AUX_CHDFA; 274 1.1 cgd hd->hpib_acr = AUX_CHDFE; 275 1.1 cgd hd->hpib_acr = AUX_RHDF; 276 1.1 cgd hd->hpib_acr = AUX_CSWRST; 277 1.1 cgd nhpibifc(hd); 278 1.1 cgd hd->hpib_ie = IDS_IE; 279 1.6 mycroft hd->hpib_data = C_DCL_P; 280 1.1 cgd DELAY(100000); 281 1.1 cgd } 282 1.1 cgd 283 1.31 thorpej static void 284 1.31 thorpej nhpibifc(struct nhpibdevice *hd) 285 1.1 cgd { 286 1.35 tsutsui 287 1.1 cgd hd->hpib_acr = AUX_TCA; 288 1.1 cgd hd->hpib_acr = AUX_CSRE; 289 1.1 cgd hd->hpib_acr = AUX_SSIC; 290 1.1 cgd DELAY(100); 291 1.1 cgd hd->hpib_acr = AUX_CSIC; 292 1.1 cgd hd->hpib_acr = AUX_SSRE; 293 1.1 cgd } 294 1.1 cgd 295 1.31 thorpej static int 296 1.31 thorpej nhpibsend(struct hpibbus_softc *hs, int slave, int sec, void *ptr, int origcnt) 297 1.1 cgd { 298 1.39 tsutsui struct nhpib_softc *sc = device_private(device_parent(hs->sc_dev)); 299 1.14 thorpej struct nhpibdevice *hd = sc->sc_regs; 300 1.14 thorpej int cnt = origcnt; 301 1.7 thorpej char *addr = ptr; 302 1.1 cgd 303 1.1 cgd hd->hpib_acr = AUX_TCA; 304 1.6 mycroft hd->hpib_data = C_UNL_P; 305 1.1 cgd if (nhpibwait(hd, MIS_BO)) 306 1.1 cgd goto senderror; 307 1.6 mycroft hd->hpib_data = talker_par[hs->sc_ba]; 308 1.1 cgd hd->hpib_acr = AUX_STON; 309 1.1 cgd if (nhpibwait(hd, MIS_BO)) 310 1.1 cgd goto senderror; 311 1.6 mycroft hd->hpib_data = listnr_par[slave]; 312 1.1 cgd if (nhpibwait(hd, MIS_BO)) 313 1.1 cgd goto senderror; 314 1.6 mycroft if (sec >= 0 || sec == -2) { 315 1.6 mycroft if (sec == -2) /* selected device clear KLUDGE */ 316 1.6 mycroft hd->hpib_data = C_SDC_P; 317 1.6 mycroft else 318 1.6 mycroft hd->hpib_data = sec_par[sec]; 319 1.1 cgd if (nhpibwait(hd, MIS_BO)) 320 1.1 cgd goto senderror; 321 1.1 cgd } 322 1.1 cgd hd->hpib_acr = AUX_GTS; 323 1.1 cgd if (cnt) { 324 1.1 cgd while (--cnt > 0) { 325 1.1 cgd hd->hpib_data = *addr++; 326 1.1 cgd if (nhpibwait(hd, MIS_BO)) 327 1.1 cgd goto senderror; 328 1.1 cgd } 329 1.1 cgd hd->hpib_acr = AUX_EOI; 330 1.1 cgd hd->hpib_data = *addr; 331 1.1 cgd if (nhpibwait(hd, MIS_BO)) 332 1.1 cgd goto senderror; 333 1.1 cgd hd->hpib_acr = AUX_TCA; 334 1.1 cgd #if 0 335 1.1 cgd /* 336 1.1 cgd * May be causing 345 disks to hang due to interference 337 1.1 cgd * with PPOLL mechanism. 338 1.1 cgd */ 339 1.6 mycroft hd->hpib_data = C_UNL_P; 340 1.1 cgd (void) nhpibwait(hd, MIS_BO); 341 1.1 cgd #endif 342 1.1 cgd } 343 1.35 tsutsui return origcnt; 344 1.6 mycroft 345 1.1 cgd senderror: 346 1.1 cgd nhpibifc(hd); 347 1.35 tsutsui return origcnt - cnt - 1; 348 1.1 cgd } 349 1.1 cgd 350 1.31 thorpej static int 351 1.31 thorpej nhpibrecv(struct hpibbus_softc *hs, int slave, int sec, void *ptr, int origcnt) 352 1.1 cgd { 353 1.39 tsutsui struct nhpib_softc *sc = device_private(device_parent(hs->sc_dev)); 354 1.14 thorpej struct nhpibdevice *hd = sc->sc_regs; 355 1.14 thorpej int cnt = origcnt; 356 1.7 thorpej char *addr = ptr; 357 1.1 cgd 358 1.6 mycroft /* 359 1.6 mycroft * Slave < 0 implies continuation of a previous receive 360 1.6 mycroft * that probably timed out. 361 1.6 mycroft */ 362 1.6 mycroft if (slave >= 0) { 363 1.6 mycroft hd->hpib_acr = AUX_TCA; 364 1.6 mycroft hd->hpib_data = C_UNL_P; 365 1.6 mycroft if (nhpibwait(hd, MIS_BO)) 366 1.6 mycroft goto recverror; 367 1.6 mycroft hd->hpib_data = listnr_par[hs->sc_ba]; 368 1.6 mycroft hd->hpib_acr = AUX_SLON; 369 1.6 mycroft if (nhpibwait(hd, MIS_BO)) 370 1.6 mycroft goto recverror; 371 1.6 mycroft hd->hpib_data = talker_par[slave]; 372 1.1 cgd if (nhpibwait(hd, MIS_BO)) 373 1.1 cgd goto recverror; 374 1.6 mycroft if (sec >= 0) { 375 1.6 mycroft hd->hpib_data = sec_par[sec]; 376 1.6 mycroft if (nhpibwait(hd, MIS_BO)) 377 1.6 mycroft goto recverror; 378 1.6 mycroft } 379 1.6 mycroft hd->hpib_acr = AUX_RHDF; 380 1.6 mycroft hd->hpib_acr = AUX_GTS; 381 1.1 cgd } 382 1.1 cgd if (cnt) { 383 1.1 cgd while (--cnt >= 0) { 384 1.1 cgd if (nhpibwait(hd, MIS_BI)) 385 1.1 cgd goto recvbyteserror; 386 1.1 cgd *addr++ = hd->hpib_data; 387 1.1 cgd } 388 1.1 cgd hd->hpib_acr = AUX_TCA; 389 1.6 mycroft hd->hpib_data = (slave == 31) ? C_UNA_P : C_UNT_P; 390 1.1 cgd (void) nhpibwait(hd, MIS_BO); 391 1.1 cgd } 392 1.35 tsutsui return origcnt; 393 1.6 mycroft 394 1.1 cgd recverror: 395 1.1 cgd nhpibifc(hd); 396 1.1 cgd recvbyteserror: 397 1.35 tsutsui return origcnt - cnt - 1; 398 1.1 cgd } 399 1.1 cgd 400 1.31 thorpej static void 401 1.31 thorpej nhpibgo(struct hpibbus_softc *hs, int slave, int sec, void *ptr, int count, 402 1.31 thorpej int rw, int timo) 403 1.1 cgd { 404 1.39 tsutsui struct nhpib_softc *sc = device_private(device_parent(hs->sc_dev)); 405 1.14 thorpej struct nhpibdevice *hd = sc->sc_regs; 406 1.7 thorpej char *addr = ptr; 407 1.1 cgd 408 1.1 cgd hs->sc_flags |= HPIBF_IO; 409 1.6 mycroft if (timo) 410 1.6 mycroft hs->sc_flags |= HPIBF_TIMO; 411 1.1 cgd if (rw == B_READ) 412 1.1 cgd hs->sc_flags |= HPIBF_READ; 413 1.1 cgd #ifdef DEBUG 414 1.1 cgd else if (hs->sc_flags & HPIBF_READ) { 415 1.13 christos printf("nhpibgo: HPIBF_READ still set\n"); 416 1.1 cgd hs->sc_flags &= ~HPIBF_READ; 417 1.1 cgd } 418 1.1 cgd #endif 419 1.1 cgd hs->sc_count = count; 420 1.1 cgd hs->sc_addr = addr; 421 1.1 cgd if (hs->sc_flags & HPIBF_READ) { 422 1.1 cgd hs->sc_curcnt = count; 423 1.14 thorpej dmago(hs->sc_dq->dq_chan, addr, count, DMAGO_BYTE|DMAGO_READ); 424 1.14 thorpej nhpibrecv(hs, slave, sec, 0, 0); 425 1.1 cgd hd->hpib_mim = MIS_END; 426 1.1 cgd } else { 427 1.1 cgd hd->hpib_mim = 0; 428 1.1 cgd if (count < hpibdmathresh) { 429 1.1 cgd hs->sc_curcnt = count; 430 1.14 thorpej nhpibsend(hs, slave, sec, addr, count); 431 1.14 thorpej nhpibdone(hs); 432 1.1 cgd return; 433 1.1 cgd } 434 1.1 cgd hs->sc_curcnt = --count; 435 1.14 thorpej dmago(hs->sc_dq->dq_chan, addr, count, DMAGO_BYTE); 436 1.14 thorpej nhpibsend(hs, slave, sec, 0, 0); 437 1.1 cgd } 438 1.14 thorpej hd->hpib_ie = IDS_IE | IDS_DMA(hs->sc_dq->dq_chan); 439 1.1 cgd } 440 1.1 cgd 441 1.6 mycroft /* 442 1.6 mycroft * This timeout can only happen if a DMA read finishes DMAing with the read 443 1.6 mycroft * still pending (more data in read transaction than the driver was prepared 444 1.6 mycroft * to accept). At the moment, variable-record tape drives are the only things 445 1.6 mycroft * capabale of doing this. We repeat the necessary code from nhpibintr() - 446 1.6 mycroft * easier and quicker than calling nhpibintr() for this special case. 447 1.6 mycroft */ 448 1.31 thorpej static void 449 1.31 thorpej nhpibreadtimo(void *arg) 450 1.6 mycroft { 451 1.14 thorpej struct hpibbus_softc *hs = arg; 452 1.39 tsutsui struct nhpib_softc *sc = device_private(device_parent(hs->sc_dev)); 453 1.6 mycroft int s = splbio(); 454 1.6 mycroft 455 1.6 mycroft if (hs->sc_flags & HPIBF_IO) { 456 1.15 scottr struct nhpibdevice *hd = sc->sc_regs; 457 1.15 scottr struct hpibqueue *hq; 458 1.6 mycroft 459 1.6 mycroft hd->hpib_mim = 0; 460 1.6 mycroft hd->hpib_acr = AUX_TCA; 461 1.6 mycroft hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO); 462 1.14 thorpej dmafree(hs->sc_dq); 463 1.14 thorpej 464 1.38 tsutsui hq = TAILQ_FIRST(&hs->sc_queue); 465 1.14 thorpej (hq->hq_intr)(hq->hq_softc); 466 1.6 mycroft } 467 1.14 thorpej splx(s); 468 1.6 mycroft } 469 1.6 mycroft 470 1.31 thorpej static void 471 1.31 thorpej nhpibdone(struct hpibbus_softc *hs) 472 1.1 cgd { 473 1.39 tsutsui struct nhpib_softc *sc = device_private(device_parent(hs->sc_dev)); 474 1.14 thorpej struct nhpibdevice *hd = sc->sc_regs; 475 1.14 thorpej int cnt; 476 1.1 cgd 477 1.1 cgd cnt = hs->sc_curcnt; 478 1.1 cgd hs->sc_addr += cnt; 479 1.1 cgd hs->sc_count -= cnt; 480 1.1 cgd hs->sc_flags |= HPIBF_DONE; 481 1.1 cgd hd->hpib_ie = IDS_IE; 482 1.6 mycroft if (hs->sc_flags & HPIBF_READ) { 483 1.6 mycroft if ((hs->sc_flags & HPIBF_TIMO) && 484 1.6 mycroft (hd->hpib_ids & IDS_IR) == 0) 485 1.23 frueauf callout_reset(&sc->sc_read_ch, hz >> 2, 486 1.22 thorpej nhpibreadtimo, hs); 487 1.6 mycroft } else { 488 1.1 cgd if (hs->sc_count == 1) { 489 1.1 cgd (void) nhpibwait(hd, MIS_BO); 490 1.1 cgd hd->hpib_acr = AUX_EOI; 491 1.1 cgd hd->hpib_data = *hs->sc_addr; 492 1.1 cgd hd->hpib_mim = MIS_BO; 493 1.1 cgd } 494 1.1 cgd #ifdef DEBUG 495 1.1 cgd else if (hs->sc_count) 496 1.1 cgd panic("nhpibdone"); 497 1.1 cgd #endif 498 1.1 cgd } 499 1.1 cgd } 500 1.1 cgd 501 1.31 thorpej static int 502 1.31 thorpej nhpibintr(void *arg) 503 1.1 cgd { 504 1.14 thorpej struct nhpib_softc *sc = arg; 505 1.14 thorpej struct hpibbus_softc *hs = sc->sc_hpibbus; 506 1.14 thorpej struct nhpibdevice *hd = sc->sc_regs; 507 1.14 thorpej struct hpibqueue *hq; 508 1.14 thorpej int stat0; 509 1.14 thorpej int stat1; 510 1.1 cgd 511 1.1 cgd if ((hd->hpib_ids & IDS_IR) == 0) 512 1.35 tsutsui return 0; 513 1.1 cgd stat0 = hd->hpib_mis; 514 1.1 cgd stat1 = hd->hpib_lis; 515 1.41 christos __USE(stat1); 516 1.14 thorpej 517 1.38 tsutsui hq = TAILQ_FIRST(&hs->sc_queue); 518 1.14 thorpej 519 1.1 cgd if (hs->sc_flags & HPIBF_IO) { 520 1.1 cgd hd->hpib_mim = 0; 521 1.6 mycroft if ((hs->sc_flags & HPIBF_DONE) == 0) { 522 1.6 mycroft hs->sc_flags &= ~HPIBF_TIMO; 523 1.14 thorpej dmastop(hs->sc_dq->dq_chan); 524 1.6 mycroft } else if (hs->sc_flags & HPIBF_TIMO) 525 1.22 thorpej callout_stop(&sc->sc_read_ch); 526 1.1 cgd hd->hpib_acr = AUX_TCA; 527 1.6 mycroft hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO); 528 1.14 thorpej 529 1.14 thorpej dmafree(hs->sc_dq); 530 1.14 thorpej (hq->hq_intr)(hq->hq_softc); 531 1.1 cgd } else if (hs->sc_flags & HPIBF_PPOLL) { 532 1.1 cgd hd->hpib_mim = 0; 533 1.14 thorpej stat0 = nhpibppoll(hs); 534 1.14 thorpej if (stat0 & (0x80 >> hq->hq_slave)) { 535 1.1 cgd hs->sc_flags &= ~HPIBF_PPOLL; 536 1.14 thorpej (hq->hq_intr)(hq->hq_softc); 537 1.1 cgd } 538 1.1 cgd #ifdef DEBUG 539 1.1 cgd else 540 1.13 christos printf("%s: PPOLL intr bad status %x\n", 541 1.39 tsutsui device_xname(hs->sc_dev), stat0); 542 1.1 cgd #endif 543 1.1 cgd } 544 1.35 tsutsui return 1; 545 1.1 cgd } 546 1.1 cgd 547 1.31 thorpej static int 548 1.31 thorpej nhpibppoll(struct hpibbus_softc *hs) 549 1.1 cgd { 550 1.39 tsutsui struct nhpib_softc *sc = device_private(device_parent(hs->sc_dev)); 551 1.14 thorpej struct nhpibdevice *hd = sc->sc_regs; 552 1.14 thorpej int ppoll; 553 1.1 cgd 554 1.1 cgd hd->hpib_acr = AUX_SPP; 555 1.1 cgd DELAY(25); 556 1.1 cgd ppoll = hd->hpib_cpt; 557 1.1 cgd hd->hpib_acr = AUX_CPP; 558 1.35 tsutsui return ppoll; 559 1.1 cgd } 560 1.1 cgd 561 1.6 mycroft #ifdef DEBUG 562 1.6 mycroft int nhpibreporttimo = 0; 563 1.6 mycroft #endif 564 1.6 mycroft 565 1.31 thorpej static int 566 1.31 thorpej nhpibwait(struct nhpibdevice *hd, int x) 567 1.1 cgd { 568 1.15 scottr int timo = hpibtimeout; 569 1.1 cgd 570 1.1 cgd while ((hd->hpib_mis & x) == 0 && --timo) 571 1.11 thorpej DELAY(1); 572 1.6 mycroft if (timo == 0) { 573 1.6 mycroft #ifdef DEBUG 574 1.6 mycroft if (nhpibreporttimo) 575 1.13 christos printf("hpib0: %s timo\n", x==MIS_BO?"OUT":"IN"); 576 1.6 mycroft #endif 577 1.35 tsutsui return -1; 578 1.6 mycroft } 579 1.35 tsutsui return 0; 580 1.1 cgd } 581 1.1 cgd 582 1.31 thorpej static void 583 1.31 thorpej nhpibppwatch(void *arg) 584 1.1 cgd { 585 1.14 thorpej struct hpibbus_softc *hs = arg; 586 1.39 tsutsui struct nhpib_softc *sc = device_private(device_parent(hs->sc_dev)); 587 1.1 cgd 588 1.1 cgd if ((hs->sc_flags & HPIBF_PPOLL) == 0) 589 1.1 cgd return; 590 1.4 mycroft again: 591 1.38 tsutsui if (nhpibppoll(hs) & (0x80 >> TAILQ_FIRST(&hs->sc_queue)->hq_slave)) 592 1.34 tsutsui sc->sc_regs->hpib_mim = MIS_BO; 593 1.4 mycroft else if (cold) 594 1.4 mycroft /* timeouts not working yet */ 595 1.4 mycroft goto again; 596 1.1 cgd else 597 1.22 thorpej callout_reset(&sc->sc_ppwatch_ch, 1, nhpibppwatch, hs); 598 1.1 cgd } 599