1 1.26 thorpej /* $NetBSD: gpib.c,v 1.26 2021/08/07 16:19:10 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.26 thorpej __KERNEL_RCSID(0, "$NetBSD: gpib.c,v 1.26 2021/08/07 16:19:10 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/conf.h> 38 1.1 gmcgarry #include <sys/device.h> 39 1.1 gmcgarry #include <sys/ioctl.h> 40 1.1 gmcgarry #include <sys/malloc.h> 41 1.1 gmcgarry #include <sys/proc.h> 42 1.1 gmcgarry 43 1.1 gmcgarry #include <dev/gpib/gpibvar.h> 44 1.1 gmcgarry 45 1.1 gmcgarry #include <dev/gpib/gpibio.h> /* XXX */ 46 1.1 gmcgarry 47 1.1 gmcgarry #include "locators.h" 48 1.1 gmcgarry 49 1.19 tsutsui #ifndef DEBUG 50 1.1 gmcgarry #define DEBUG 51 1.19 tsutsui #endif 52 1.1 gmcgarry 53 1.1 gmcgarry #ifdef DEBUG 54 1.1 gmcgarry int gpibdebug = 0xff; 55 1.1 gmcgarry #define DBG_FOLLOW 0x01 56 1.1 gmcgarry #define DBG_INTR 0x02 57 1.1 gmcgarry #define DBG_FAIL 0x04 58 1.1 gmcgarry #define DPRINTF(mask, str) if (gpibdebug & (mask)) printf str 59 1.1 gmcgarry #else 60 1.1 gmcgarry #define DPRINTF(mask, str) /* nothing */ 61 1.1 gmcgarry #endif 62 1.1 gmcgarry 63 1.17 cegger int gpibmatch(device_t, cfdata_t, void *); 64 1.17 cegger void gpibattach(device_t, device_t, void *); 65 1.1 gmcgarry 66 1.20 chs CFATTACH_DECL_NEW(gpib, sizeof(struct gpib_softc), 67 1.1 gmcgarry gpibmatch, gpibattach, NULL, NULL); 68 1.1 gmcgarry 69 1.20 chs static int gpibsubmatch1(device_t, cfdata_t, const int *, void *); 70 1.20 chs static int gpibsubmatch2(device_t, cfdata_t, const int *, void *); 71 1.1 gmcgarry static int gpibprint(void *, const char *); 72 1.1 gmcgarry 73 1.1 gmcgarry dev_type_open(gpibopen); 74 1.1 gmcgarry dev_type_close(gpibclose); 75 1.1 gmcgarry dev_type_read(gpibread); 76 1.1 gmcgarry dev_type_write(gpibwrite); 77 1.1 gmcgarry dev_type_ioctl(gpibioctl); 78 1.1 gmcgarry dev_type_poll(gpibpoll); 79 1.1 gmcgarry 80 1.1 gmcgarry const struct cdevsw gpib_cdevsw = { 81 1.21 dholland .d_open = gpibopen, 82 1.21 dholland .d_close = gpibclose, 83 1.21 dholland .d_read = gpibread, 84 1.21 dholland .d_write = gpibwrite, 85 1.21 dholland .d_ioctl = gpibioctl, 86 1.21 dholland .d_stop = nostop, 87 1.21 dholland .d_tty = notty, 88 1.21 dholland .d_poll = gpibpoll, 89 1.21 dholland .d_mmap = nommap, 90 1.21 dholland .d_kqfilter = nokqfilter, 91 1.22 dholland .d_discard = nodiscard, 92 1.21 dholland .d_flag = D_OTHER 93 1.1 gmcgarry }; 94 1.1 gmcgarry 95 1.1 gmcgarry extern struct cfdriver gpib_cd; 96 1.1 gmcgarry 97 1.1 gmcgarry #define GPIBUNIT(dev) (minor(dev) & 0x0f) 98 1.1 gmcgarry 99 1.1 gmcgarry int gpibtimeout = 100000; /* # of status tests before we give up */ 100 1.1 gmcgarry 101 1.1 gmcgarry int 102 1.17 cegger gpibmatch(device_t parent, cfdata_t match, void *aux) 103 1.1 gmcgarry { 104 1.1 gmcgarry 105 1.1 gmcgarry return (1); 106 1.1 gmcgarry } 107 1.1 gmcgarry 108 1.1 gmcgarry void 109 1.17 cegger gpibattach(device_t parent, device_t self, void *aux) 110 1.1 gmcgarry { 111 1.8 thorpej struct gpib_softc *sc = device_private(self); 112 1.20 chs cfdata_t cf = device_cfdata(self); 113 1.1 gmcgarry struct gpibdev_attach_args *gda = aux; 114 1.1 gmcgarry struct gpib_attach_args ga; 115 1.1 gmcgarry int address; 116 1.1 gmcgarry 117 1.20 chs sc->sc_dev = self; 118 1.1 gmcgarry sc->sc_ic = gda->ga_ic; 119 1.1 gmcgarry 120 1.1 gmcgarry /* 121 1.1 gmcgarry * If the configuration file specified a host address, then 122 1.1 gmcgarry * use it in favour of registers/switches or the default (30). 123 1.1 gmcgarry */ 124 1.1 gmcgarry if (cf->cf_loc[GPIBDEVCF_ADDRESS] != GPIBDEVCF_ADDRESS_DEFAULT) 125 1.1 gmcgarry sc->sc_myaddr = cf->cf_loc[GPIBDEVCF_ADDRESS]; 126 1.1 gmcgarry else if (gda->ga_address != GPIBDEVCF_ADDRESS_DEFAULT) 127 1.1 gmcgarry sc->sc_myaddr = gda->ga_address; 128 1.1 gmcgarry else 129 1.1 gmcgarry sc->sc_myaddr = 30; 130 1.1 gmcgarry 131 1.1 gmcgarry printf(": host address %d\n", sc->sc_myaddr); 132 1.1 gmcgarry 133 1.1 gmcgarry /* record our softc pointer */ 134 1.1 gmcgarry sc->sc_ic->bus = sc; 135 1.1 gmcgarry 136 1.1 gmcgarry /* Initialize the slave request queue */ 137 1.1 gmcgarry TAILQ_INIT(&sc->sc_queue); 138 1.1 gmcgarry 139 1.1 gmcgarry /* attach addressed devices */ 140 1.1 gmcgarry for (address=0; address<GPIB_NDEVS; address++) { 141 1.1 gmcgarry ga.ga_ic = sc->sc_ic; 142 1.1 gmcgarry ga.ga_address = address; 143 1.25 thorpej config_search(sc->sc_dev, &ga, 144 1.26 thorpej CFARGS(.search = gpibsubmatch1)); 145 1.1 gmcgarry } 146 1.1 gmcgarry 147 1.1 gmcgarry /* attach the wild-carded devices - probably protocol busses */ 148 1.1 gmcgarry ga.ga_ic = sc->sc_ic; 149 1.25 thorpej config_search(sc->sc_dev, &ga, 150 1.26 thorpej CFARGS(.search = gpibsubmatch2)); 151 1.1 gmcgarry } 152 1.1 gmcgarry 153 1.1 gmcgarry int 154 1.17 cegger gpibsubmatch1(device_t parent, cfdata_t cf, const int *ldesc, void *aux) 155 1.1 gmcgarry { 156 1.20 chs struct gpib_softc *sc = device_private(parent); 157 1.1 gmcgarry struct gpib_attach_args *ga = aux; 158 1.1 gmcgarry 159 1.1 gmcgarry if (cf->cf_loc[GPIBCF_ADDRESS] != ga->ga_address) 160 1.1 gmcgarry return (0); 161 1.1 gmcgarry 162 1.1 gmcgarry if (cf->cf_loc[GPIBCF_ADDRESS] == sc->sc_myaddr) 163 1.1 gmcgarry return (0); 164 1.1 gmcgarry 165 1.25 thorpej if (config_probe(parent, cf, ga)) { 166 1.1 gmcgarry if (gpib_alloc(sc, ga->ga_address)) 167 1.1 gmcgarry return (0); 168 1.26 thorpej config_attach(parent, cf, ga, gpibprint, CFARGS_NONE); 169 1.1 gmcgarry return (0); 170 1.1 gmcgarry } 171 1.1 gmcgarry return (0); 172 1.1 gmcgarry } 173 1.1 gmcgarry 174 1.1 gmcgarry int 175 1.17 cegger gpibsubmatch2(device_t parent, cfdata_t cf, const int *ldesc, void *aux) 176 1.1 gmcgarry { 177 1.1 gmcgarry struct gpib_attach_args *ga = aux; 178 1.1 gmcgarry 179 1.1 gmcgarry if (cf->cf_loc[GPIBCF_ADDRESS] != GPIBCF_ADDRESS_DEFAULT) 180 1.1 gmcgarry return (0); 181 1.1 gmcgarry 182 1.1 gmcgarry ga->ga_address = GPIBCF_ADDRESS_DEFAULT; 183 1.25 thorpej if (config_probe(parent, cf, ga)) { 184 1.26 thorpej config_attach(parent, cf, ga, gpibdevprint, CFARGS_NONE); 185 1.1 gmcgarry return (0); 186 1.1 gmcgarry } 187 1.1 gmcgarry return (0); 188 1.1 gmcgarry } 189 1.1 gmcgarry 190 1.1 gmcgarry int 191 1.14 dsl gpibprint(void *aux, const char *pnp) 192 1.1 gmcgarry { 193 1.1 gmcgarry struct gpib_attach_args *ga = aux; 194 1.1 gmcgarry 195 1.1 gmcgarry if (ga->ga_address != GPIBCF_ADDRESS_DEFAULT) 196 1.1 gmcgarry printf(" address %d", ga->ga_address); 197 1.1 gmcgarry return (UNCONF); 198 1.1 gmcgarry } 199 1.1 gmcgarry 200 1.1 gmcgarry int 201 1.14 dsl gpibdevprint(void *aux, const char *pnp) 202 1.1 gmcgarry { 203 1.1 gmcgarry 204 1.1 gmcgarry if (pnp != NULL) 205 1.1 gmcgarry printf("gpib at %s", pnp); 206 1.1 gmcgarry return (UNCONF); 207 1.1 gmcgarry } 208 1.1 gmcgarry 209 1.1 gmcgarry /* 210 1.1 gmcgarry * Called by hardware driver, pass to device driver. 211 1.1 gmcgarry */ 212 1.1 gmcgarry int 213 1.14 dsl gpibintr(void *v) 214 1.1 gmcgarry { 215 1.1 gmcgarry struct gpib_softc *sc = v; 216 1.1 gmcgarry gpib_handle_t hdl; 217 1.1 gmcgarry 218 1.1 gmcgarry DPRINTF(DBG_INTR, ("gpibintr: sc=%p\n", sc)); 219 1.1 gmcgarry 220 1.1 gmcgarry hdl = TAILQ_FIRST(&sc->sc_queue); 221 1.1 gmcgarry (hdl->hq_callback)(hdl->hq_softc, GPIBCBF_INTR); 222 1.1 gmcgarry return (0); 223 1.1 gmcgarry } 224 1.1 gmcgarry 225 1.1 gmcgarry /* 226 1.1 gmcgarry * Create a callback handle. 227 1.1 gmcgarry */ 228 1.1 gmcgarry int 229 1.23 msaitoh _gpibregister(struct gpib_softc *sc, int slave, gpib_callback_t callback, 230 1.23 msaitoh void *arg, gpib_handle_t *hdl) 231 1.1 gmcgarry { 232 1.1 gmcgarry 233 1.24 chs *hdl = malloc(sizeof(struct gpibqueue), M_DEVBUF, M_WAITOK); 234 1.1 gmcgarry (*hdl)->hq_slave = slave; 235 1.1 gmcgarry (*hdl)->hq_callback = callback; 236 1.1 gmcgarry (*hdl)->hq_softc = arg; 237 1.1 gmcgarry 238 1.1 gmcgarry return (0); 239 1.1 gmcgarry } 240 1.1 gmcgarry 241 1.1 gmcgarry /* 242 1.1 gmcgarry * Request exclusive access to the GPIB bus. 243 1.1 gmcgarry */ 244 1.1 gmcgarry int 245 1.15 dsl _gpibrequest(struct gpib_softc *sc, gpib_handle_t hdl) 246 1.1 gmcgarry { 247 1.1 gmcgarry 248 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("_gpibrequest: sc=%p hdl=%p\n", sc, hdl)); 249 1.1 gmcgarry 250 1.1 gmcgarry TAILQ_INSERT_TAIL(&sc->sc_queue, hdl, hq_list); 251 1.1 gmcgarry if (TAILQ_FIRST(&sc->sc_queue) == hdl) 252 1.1 gmcgarry return (1); 253 1.1 gmcgarry 254 1.1 gmcgarry return (0); 255 1.1 gmcgarry } 256 1.1 gmcgarry 257 1.1 gmcgarry /* 258 1.1 gmcgarry * Release exclusive access to the GPIB bus. 259 1.1 gmcgarry */ 260 1.1 gmcgarry void 261 1.15 dsl _gpibrelease(struct gpib_softc *sc, gpib_handle_t hdl) 262 1.1 gmcgarry { 263 1.1 gmcgarry 264 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("_gpibrelease: sc=%p hdl=%p\n", sc, hdl)); 265 1.1 gmcgarry 266 1.1 gmcgarry TAILQ_REMOVE(&sc->sc_queue, hdl, hq_list); 267 1.1 gmcgarry if ((hdl = TAILQ_FIRST(&sc->sc_queue)) != NULL) 268 1.1 gmcgarry (*hdl->hq_callback)(hdl->hq_softc, GPIBCBF_START); 269 1.1 gmcgarry } 270 1.1 gmcgarry 271 1.1 gmcgarry 272 1.1 gmcgarry /* 273 1.1 gmcgarry * Asynchronous wait. 274 1.1 gmcgarry */ 275 1.1 gmcgarry void 276 1.15 dsl _gpibawait(struct gpib_softc *sc) 277 1.1 gmcgarry { 278 1.1 gmcgarry int slave; 279 1.1 gmcgarry 280 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("_gpibawait: sc=%p\n", sc)); 281 1.1 gmcgarry 282 1.1 gmcgarry slave = TAILQ_FIRST(&sc->sc_queue)->hq_slave; 283 1.1 gmcgarry (*sc->sc_ic->ppwatch)(sc->sc_ic->cookie, slave); 284 1.1 gmcgarry } 285 1.1 gmcgarry 286 1.1 gmcgarry /* 287 1.1 gmcgarry * Synchronous (spin) wait. 288 1.1 gmcgarry */ 289 1.1 gmcgarry int 290 1.15 dsl _gpibswait(struct gpib_softc *sc, int slave) 291 1.1 gmcgarry { 292 1.1 gmcgarry int timo = gpibtimeout; 293 1.1 gmcgarry int (*pptest)(void *, int); 294 1.1 gmcgarry 295 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("_gpibswait: sc=%p\n", sc)); 296 1.1 gmcgarry 297 1.1 gmcgarry pptest = sc->sc_ic->pptest; 298 1.1 gmcgarry while ((*pptest)(sc->sc_ic->cookie, slave) == 0) { 299 1.1 gmcgarry if (--timo == 0) { 300 1.20 chs aprint_error_dev(sc->sc_dev, "swait timeout\n"); 301 1.1 gmcgarry return(-1); 302 1.1 gmcgarry } 303 1.1 gmcgarry } 304 1.1 gmcgarry return (0); 305 1.1 gmcgarry } 306 1.1 gmcgarry 307 1.1 gmcgarry /* 308 1.1 gmcgarry * Resource accounting: check if the address has already been 309 1.1 gmcgarry * claimed and allocated. 310 1.1 gmcgarry */ 311 1.1 gmcgarry int 312 1.14 dsl gpib_isalloc(struct gpib_softc *sc, u_int8_t address) 313 1.1 gmcgarry { 314 1.1 gmcgarry 315 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("gpib_isalloc: sc=%p address=%d\n", sc, address)); 316 1.1 gmcgarry 317 1.1 gmcgarry #ifdef DIAGNOSTIC 318 1.1 gmcgarry if (address >= GPIB_NDEVS) 319 1.1 gmcgarry panic("gpib_isalloc: device address out of range"); 320 1.1 gmcgarry #endif 321 1.1 gmcgarry 322 1.1 gmcgarry return ((sc->sc_rmap & (1 << address)) != 0); 323 1.1 gmcgarry } 324 1.1 gmcgarry 325 1.1 gmcgarry /* 326 1.1 gmcgarry * Resource accounting: allocate the address. 327 1.1 gmcgarry */ 328 1.1 gmcgarry int 329 1.14 dsl gpib_alloc(struct gpib_softc *sc, u_int8_t address) 330 1.1 gmcgarry { 331 1.1 gmcgarry 332 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("gpib_alloc: sc=%p address=%d\n", sc, address)); 333 1.1 gmcgarry 334 1.1 gmcgarry #ifdef DIAGNOSTIC 335 1.1 gmcgarry if (address >= GPIB_NDEVS) 336 1.1 gmcgarry panic("gpib_alloc: device address out of range"); 337 1.1 gmcgarry #endif 338 1.1 gmcgarry 339 1.1 gmcgarry if (!gpib_isalloc(sc, address)) { 340 1.1 gmcgarry sc->sc_rmap |= (1 << address); 341 1.1 gmcgarry return (0); 342 1.1 gmcgarry } 343 1.1 gmcgarry return (1); 344 1.1 gmcgarry } 345 1.1 gmcgarry 346 1.1 gmcgarry /* 347 1.1 gmcgarry * Resource accounting: deallocate the address. 348 1.1 gmcgarry */ 349 1.1 gmcgarry void 350 1.14 dsl gpib_dealloc(struct gpib_softc *sc, u_int8_t address) 351 1.1 gmcgarry { 352 1.1 gmcgarry 353 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("gpib_free: sc=%p address=%d\n", sc, address)); 354 1.1 gmcgarry 355 1.1 gmcgarry #ifdef DIAGNOSTIC 356 1.1 gmcgarry if (address >= GPIB_NDEVS) 357 1.1 gmcgarry panic("gpib_free: device address out of range"); 358 1.1 gmcgarry 359 1.1 gmcgarry if (!gpib_isalloc(sc, address)) 360 1.1 gmcgarry panic("gpib_free: not allocated"); 361 1.1 gmcgarry #endif 362 1.1 gmcgarry 363 1.1 gmcgarry sc->sc_rmap &= ~(1 << address); 364 1.1 gmcgarry } 365 1.1 gmcgarry 366 1.1 gmcgarry int 367 1.15 dsl _gpibsend(struct gpib_softc *sc, int slave, int sec, void *ptr, int origcnt) 368 1.1 gmcgarry { 369 1.1 gmcgarry int rv; 370 1.1 gmcgarry int cnt = 0; 371 1.1 gmcgarry u_int8_t cmds[4]; 372 1.1 gmcgarry int i = 0; 373 1.1 gmcgarry 374 1.1 gmcgarry DPRINTF(DBG_FOLLOW, 375 1.1 gmcgarry ("_gpibsend: sc=%p slave %d sec=%d ptr=%p cnt=%d\n", 376 1.1 gmcgarry sc, slave, sec, ptr, origcnt)); 377 1.1 gmcgarry 378 1.1 gmcgarry /* 379 1.1 gmcgarry * For compatibility, call the hardware driver directly. 380 1.1 gmcgarry */ 381 1.1 gmcgarry if (sc->sc_ic->send != NULL) { 382 1.1 gmcgarry rv = (*sc->sc_ic->send)(sc->sc_ic->cookie, 383 1.1 gmcgarry slave, sec, ptr, origcnt); 384 1.1 gmcgarry return (rv); 385 1.1 gmcgarry } 386 1.1 gmcgarry 387 1.1 gmcgarry if ((*sc->sc_ic->tc)(sc->sc_ic->cookie, 0)) 388 1.1 gmcgarry goto senderror; 389 1.1 gmcgarry cmds[i++] = GPIBCMD_UNL; 390 1.1 gmcgarry cmds[i++] = GPIBCMD_TAG | sc->sc_myaddr; 391 1.1 gmcgarry cmds[i++] = GPIBCMD_LAG | slave; 392 1.1 gmcgarry if (sec >= 0 || sec == -2) { 393 1.1 gmcgarry if (sec == -2) /* selected device clear KLUDGE */ 394 1.1 gmcgarry cmds[i++] = GPIBCMD_SDC; 395 1.1 gmcgarry else 396 1.1 gmcgarry cmds[i++] = GPIBCMD_SCG | sec; 397 1.1 gmcgarry } 398 1.1 gmcgarry if ((*sc->sc_ic->sendcmds)(sc->sc_ic->cookie, cmds, i) != i) 399 1.1 gmcgarry goto senderror; 400 1.1 gmcgarry if ((*sc->sc_ic->gts)(sc->sc_ic->cookie)) 401 1.1 gmcgarry goto senderror; 402 1.1 gmcgarry if (origcnt) { 403 1.1 gmcgarry cnt = (*sc->sc_ic->senddata)(sc->sc_ic->cookie, ptr, origcnt); 404 1.1 gmcgarry if (cnt != origcnt) 405 1.1 gmcgarry goto senderror; 406 1.1 gmcgarry if ((*sc->sc_ic->tc)(sc->sc_ic->cookie, 0)) 407 1.1 gmcgarry goto senderror; 408 1.1 gmcgarry } 409 1.1 gmcgarry return (origcnt); 410 1.1 gmcgarry 411 1.1 gmcgarry senderror: 412 1.1 gmcgarry (*sc->sc_ic->ifc)(sc->sc_ic->cookie); 413 1.1 gmcgarry DPRINTF(DBG_FAIL, 414 1.4 perry ("%s: _gpibsend failed: slave %d, sec %x, sent %d of %d bytes\n", 415 1.20 chs device_xname(sc->sc_dev), slave, sec, cnt, origcnt)); 416 1.1 gmcgarry return (cnt); 417 1.1 gmcgarry } 418 1.1 gmcgarry 419 1.1 gmcgarry int 420 1.15 dsl _gpibrecv(struct gpib_softc *sc, int slave, int sec, void *ptr, int origcnt) 421 1.1 gmcgarry { 422 1.1 gmcgarry int rv; 423 1.1 gmcgarry u_int8_t cmds[4]; 424 1.1 gmcgarry int cnt = 0; 425 1.1 gmcgarry int i = 0; 426 1.1 gmcgarry 427 1.1 gmcgarry DPRINTF(DBG_FOLLOW, 428 1.1 gmcgarry ("_gpibrecv: sc=%p slave=%d sec=%d buf=%p cnt=%d\n", 429 1.1 gmcgarry sc, slave, sec, ptr, origcnt)); 430 1.1 gmcgarry 431 1.1 gmcgarry /* 432 1.1 gmcgarry * For compatibility, call the hardware driver directly. 433 1.1 gmcgarry */ 434 1.1 gmcgarry if (sc->sc_ic->recv != NULL) { 435 1.1 gmcgarry rv = (*sc->sc_ic->recv)(sc->sc_ic->cookie, 436 1.1 gmcgarry slave, sec, ptr, origcnt); 437 1.1 gmcgarry return (rv); 438 1.1 gmcgarry } 439 1.1 gmcgarry 440 1.1 gmcgarry /* 441 1.1 gmcgarry * slave < 0 implies continuation of a previous receive 442 1.1 gmcgarry * that probably timed out. 443 1.1 gmcgarry */ 444 1.1 gmcgarry if (slave >= 0) { 445 1.1 gmcgarry if ((*sc->sc_ic->tc)(sc->sc_ic->cookie, 0)) 446 1.1 gmcgarry goto recverror; 447 1.1 gmcgarry cmds[i++] = GPIBCMD_UNL; 448 1.1 gmcgarry cmds[i++] = GPIBCMD_LAG | sc->sc_myaddr; 449 1.1 gmcgarry cmds[i++] = GPIBCMD_TAG | slave; 450 1.1 gmcgarry if (sec >= 0) 451 1.1 gmcgarry cmds[i++] = GPIBCMD_SCG | sec; 452 1.1 gmcgarry if ((*sc->sc_ic->sendcmds)(sc->sc_ic->cookie, cmds, i) != i) 453 1.1 gmcgarry goto recverror; 454 1.1 gmcgarry if ((*sc->sc_ic->gts)(sc->sc_ic->cookie)) 455 1.1 gmcgarry goto recverror; 456 1.1 gmcgarry } 457 1.1 gmcgarry if (origcnt) { 458 1.1 gmcgarry cnt = (*sc->sc_ic->recvdata)(sc->sc_ic->cookie, ptr, origcnt); 459 1.1 gmcgarry if (cnt != origcnt) 460 1.1 gmcgarry goto recverror; 461 1.1 gmcgarry if ((sc->sc_ic->tc)(sc->sc_ic->cookie, 0)) 462 1.1 gmcgarry goto recverror; 463 1.4 perry cmds[0] = (slave == GPIB_BROADCAST_ADDR) ? 464 1.1 gmcgarry GPIBCMD_UNA : GPIBCMD_UNT; 465 1.1 gmcgarry if ((*sc->sc_ic->sendcmds)(sc->sc_ic->cookie, cmds, 1) != 1) 466 1.1 gmcgarry goto recverror; 467 1.1 gmcgarry } 468 1.1 gmcgarry return (origcnt); 469 1.1 gmcgarry 470 1.1 gmcgarry recverror: 471 1.1 gmcgarry (*sc->sc_ic->ifc)(sc->sc_ic->cookie); 472 1.1 gmcgarry DPRINTF(DBG_FAIL, 473 1.1 gmcgarry ("_gpibrecv: failed, sc=%p slave %d, sec %x, got %d of %d bytes\n", 474 1.1 gmcgarry sc, slave, sec, cnt, origcnt)); 475 1.1 gmcgarry return (cnt); 476 1.1 gmcgarry } 477 1.1 gmcgarry 478 1.1 gmcgarry /* 479 1.1 gmcgarry * /dev/gpib? interface 480 1.1 gmcgarry */ 481 1.1 gmcgarry 482 1.1 gmcgarry int 483 1.13 cegger gpibopen(dev_t dev, int flags, int mode, struct lwp *l) 484 1.1 gmcgarry { 485 1.1 gmcgarry struct gpib_softc *sc; 486 1.1 gmcgarry 487 1.13 cegger sc = device_lookup_private(&gpib_cd, GPIBUNIT(dev)); 488 1.1 gmcgarry if (sc == NULL) 489 1.1 gmcgarry return (ENXIO); 490 1.1 gmcgarry 491 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("gpibopen: sc=%p\n", sc)); 492 1.1 gmcgarry 493 1.1 gmcgarry if (sc->sc_flags & GPIBF_ACTIVE) 494 1.1 gmcgarry return (EBUSY); 495 1.1 gmcgarry sc->sc_flags |= GPIBF_ACTIVE; 496 1.1 gmcgarry 497 1.1 gmcgarry return (0); 498 1.1 gmcgarry } 499 1.1 gmcgarry 500 1.1 gmcgarry int 501 1.13 cegger gpibclose(dev_t dev, int flag, int mode, struct lwp *l) 502 1.1 gmcgarry { 503 1.1 gmcgarry struct gpib_softc *sc; 504 1.1 gmcgarry 505 1.13 cegger sc = device_lookup_private(&gpib_cd, GPIBUNIT(dev)); 506 1.1 gmcgarry if (sc == NULL) 507 1.1 gmcgarry return (ENXIO); 508 1.1 gmcgarry 509 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("gpibclose: sc=%p\n", sc)); 510 1.1 gmcgarry 511 1.1 gmcgarry sc->sc_flags &= ~GPIBF_ACTIVE; 512 1.1 gmcgarry 513 1.1 gmcgarry return (0); 514 1.1 gmcgarry } 515 1.1 gmcgarry 516 1.1 gmcgarry int 517 1.13 cegger gpibread(dev_t dev, struct uio *uio, int flags) 518 1.1 gmcgarry { 519 1.1 gmcgarry struct gpib_softc *sc; 520 1.1 gmcgarry 521 1.13 cegger sc = device_lookup_private(&gpib_cd, GPIBUNIT(dev)); 522 1.1 gmcgarry if (sc == NULL) 523 1.1 gmcgarry return (ENXIO); 524 1.1 gmcgarry 525 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("gpibread: sc=%p\n", sc)); 526 1.1 gmcgarry 527 1.1 gmcgarry return (EOPNOTSUPP); 528 1.1 gmcgarry } 529 1.1 gmcgarry 530 1.1 gmcgarry int 531 1.13 cegger gpibwrite(dev_t dev, struct uio *uio, int flags) 532 1.1 gmcgarry { 533 1.1 gmcgarry struct gpib_softc *sc; 534 1.1 gmcgarry 535 1.13 cegger sc = device_lookup_private(&gpib_cd, GPIBUNIT(dev)); 536 1.1 gmcgarry if (sc == NULL) 537 1.1 gmcgarry return (ENXIO); 538 1.1 gmcgarry 539 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("gpibwrite: sc=%p\n", sc)); 540 1.1 gmcgarry 541 1.1 gmcgarry return (EOPNOTSUPP); 542 1.1 gmcgarry } 543 1.1 gmcgarry 544 1.1 gmcgarry int 545 1.13 cegger gpibioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 546 1.1 gmcgarry { 547 1.1 gmcgarry struct gpib_softc *sc; 548 1.1 gmcgarry 549 1.13 cegger sc = device_lookup_private(&gpib_cd, GPIBUNIT(dev)); 550 1.1 gmcgarry if (sc == NULL) 551 1.1 gmcgarry return (ENXIO); 552 1.1 gmcgarry 553 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("gpibioctl(%lu, '%c',%lu): sc=%p\n", 554 1.1 gmcgarry IOCPARM_LEN(cmd), (char)IOCGROUP(cmd), cmd & 0xff, sc)); 555 1.1 gmcgarry 556 1.1 gmcgarry switch (cmd) { 557 1.1 gmcgarry case GPIB_INFO: 558 1.1 gmcgarry (*(int *)data) = 0xa5a5a5a5; 559 1.1 gmcgarry break; 560 1.1 gmcgarry } 561 1.1 gmcgarry 562 1.1 gmcgarry return (EINVAL); 563 1.1 gmcgarry } 564 1.1 gmcgarry 565 1.1 gmcgarry int 566 1.13 cegger gpibpoll(dev_t dev, int events, struct lwp *l) 567 1.1 gmcgarry { 568 1.1 gmcgarry struct gpib_softc *sc; 569 1.1 gmcgarry 570 1.13 cegger sc = device_lookup_private(&gpib_cd, GPIBUNIT(dev)); 571 1.1 gmcgarry if (sc == NULL) 572 1.1 gmcgarry return (ENXIO); 573 1.1 gmcgarry 574 1.1 gmcgarry DPRINTF(DBG_FOLLOW, ("gpibpoll: sc=%p\n", sc)); 575 1.1 gmcgarry 576 1.1 gmcgarry return (0); 577 1.1 gmcgarry } 578