1 /* $NetBSD: hpib.c,v 1.15 1997/04/14 02:31:33 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1996, 1997 Jason R. Thorpe. All rights reserved. 5 * Copyright (c) 1982, 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)hpib.c 8.2 (Berkeley) 1/12/94 37 */ 38 39 /* 40 * HP-IB bus driver 41 */ 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/buf.h> 46 #include <sys/malloc.h> 47 #include <sys/device.h> 48 49 #include <hp300/dev/dmavar.h> 50 51 #include <hp300/dev/hpibvar.h> 52 53 #include <machine/cpu.h> 54 55 int hpibbusmatch __P((struct device *, struct cfdata *, void *)); 56 void hpibbusattach __P((struct device *, struct device *, void *)); 57 58 struct cfattach hpibbus_ca = { 59 sizeof(struct hpibbus_softc), hpibbusmatch, hpibbusattach 60 }; 61 62 struct cfdriver hpibbus_cd = { 63 NULL, "hpibbus", DV_DULL 64 }; 65 66 void hpibbus_attach_children __P((struct hpibbus_softc *)); 67 int hpibbussearch __P((struct device *, struct cfdata *, void *)); 68 int hpibbusprint __P((void *, const char *)); 69 70 int hpibbus_alloc __P((struct hpibbus_softc *, int, int)); 71 void hpibbus_free __P((struct hpibbus_softc *, int, int)); 72 73 void hpibstart __P((void *)); 74 void hpibdone __P((void *)); 75 76 int hpibtimeout = 100000; /* # of status tests before we give up */ 77 int hpibidtimeout = 10000; /* # of status tests for hpibid() calls */ 78 int hpibdmathresh = 3; /* byte count beyond which to attempt dma */ 79 80 /* 81 * HP-IB is essentially an IEEE 488 bus, with an HP command 82 * set (CS/80 on `newer' devices, Amigo on before-you-were-born 83 * devices) thrown on top. Devices that respond to CS/80 (and 84 * probably Amigo, too) are tagged with a 16-bit ID. 85 * 86 * HP-IB has a 2-level addressing scheme; slave, the analog 87 * of a SCSI ID, and punit, the analog of a SCSI LUN. Unforunately, 88 * IDs are on a per-slave basis; punits are often used for disk 89 * drives that have an accompanying tape drive on the second punit. 90 * 91 * In addition, not all HP-IB devices speak CS/80 or Amigo. 92 * Examples of such devices are HP-IB plotters, which simply 93 * take raw plotter commands over 488. These devices do not 94 * have ID tags, and often the host cannot even tell if such 95 * a device is attached to the system! 96 * 97 * These two nasty bits mean that we have to treat HP-IB as 98 * an indirect bus. However, since we are given some ID 99 * information, it is unreasonable to disallow cloning of 100 * CS/80 devices. 101 * 102 * To deal with all of this, we use the semi-twisted scheme 103 * in hpibbus_attach_children(). For each HP-IB slave, we loop 104 * through all of the possibly-configured children, allowing 105 * them to modify the punit parameter (but NOT the slave!). 106 * 107 * This is evil, but what can you do? 108 */ 109 110 int 111 hpibbusmatch(parent, match, aux) 112 struct device *parent; 113 struct cfdata *match; 114 void *aux; 115 { 116 117 return (1); 118 } 119 120 void 121 hpibbusattach(parent, self, aux) 122 struct device *parent, *self; 123 void *aux; 124 { 125 struct hpibbus_softc *sc = (struct hpibbus_softc *)self; 126 struct hpibdev_attach_args *ha = aux; 127 128 printf("\n"); 129 130 /* Get the operations vector for the controller. */ 131 sc->sc_ops = ha->ha_ops; 132 sc->sc_type = ha->ha_type; /* XXX */ 133 sc->sc_ba = ha->ha_ba; 134 *(ha->ha_softcpp) = sc; /* XXX */ 135 136 hpibreset(self->dv_unit); /* XXX souldn't be here */ 137 138 /* 139 * Initialize the DMA queue entry. 140 */ 141 sc->sc_dq = (struct dmaqueue *)malloc(sizeof(struct dmaqueue), 142 M_DEVBUF, M_NOWAIT); 143 if (sc->sc_dq == NULL) { 144 printf("%s: can't allocate DMA queue entry\n", self->dv_xname); 145 return; 146 } 147 sc->sc_dq->dq_softc = sc; 148 sc->sc_dq->dq_start = hpibstart; 149 sc->sc_dq->dq_done = hpibdone; 150 151 /* Initialize the slave request queue. */ 152 TAILQ_INIT(&sc->sc_queue); 153 154 /* Attach any devices on the bus. */ 155 hpibbus_attach_children(sc); 156 } 157 158 void 159 hpibbus_attach_children(sc) 160 struct hpibbus_softc *sc; 161 { 162 struct hpibbus_attach_args ha; 163 int slave; 164 165 for (slave = 0; slave < 8; slave++) { 166 /* 167 * Get the ID tag for the device, if any. 168 * Plotters won't identify themselves, and 169 * get the same value as non-existent devices. 170 */ 171 ha.ha_id = hpibid(sc->sc_dev.dv_unit, slave); 172 173 ha.ha_slave = slave; /* not to be modified by children */ 174 ha.ha_punit = 0; /* children modify this */ 175 176 /* 177 * Search though all configured children for this bus. 178 */ 179 (void)config_search(hpibbussearch, &sc->sc_dev, &ha); 180 } 181 } 182 183 int 184 hpibbussearch(parent, cf, aux) 185 struct device *parent; 186 struct cfdata *cf; 187 void *aux; 188 { 189 struct hpibbus_softc *sc = (struct hpibbus_softc *)parent; 190 struct hpibbus_attach_args *ha = aux; 191 192 /* Make sure this is in a consistent state. */ 193 ha->ha_punit = 0; 194 195 if ((*cf->cf_attach->ca_match)(parent, cf, ha) > 0) { 196 /* 197 * The device probe has succeeded, and filled in 198 * the punit information. Make sure the configuration 199 * allows for this slave/punit combination. 200 */ 201 if (cf->hpibbuscf_slave != HPIBBUS_SLAVE_UNK && 202 cf->hpibbuscf_slave != ha->ha_slave) 203 goto out; 204 if (cf->hpibbuscf_punit != HPIBBUS_PUNIT_UNK && 205 cf->hpibbuscf_punit != ha->ha_punit) 206 goto out; 207 208 /* 209 * Allocate the device's address from the bus's 210 * resource map. 211 */ 212 if (hpibbus_alloc(sc, ha->ha_slave, ha->ha_punit)) 213 goto out; 214 215 /* 216 * This device is allowed; attach it. 217 */ 218 config_attach(parent, cf, ha, hpibbusprint); 219 } 220 out: 221 return (0); 222 } 223 224 int 225 hpibbusprint(aux, pnp) 226 void *aux; 227 const char *pnp; 228 { 229 struct hpibbus_attach_args *ha = aux; 230 231 printf(" slave %d punit %d", ha->ha_slave, ha->ha_punit); 232 return (UNCONF); 233 } 234 235 int 236 hpibdevprint(aux, pnp) 237 void *aux; 238 const char *pnp; 239 { 240 241 /* only hpibbus's can attach to hpibdev's -- easy. */ 242 if (pnp != NULL) 243 printf("hpibbus at %s", pnp); 244 return (UNCONF); 245 } 246 247 void 248 hpibreset(unit) 249 int unit; 250 { 251 struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit]; 252 253 (*sc->sc_ops->hpib_reset)(sc); 254 } 255 256 int 257 hpibreq(pdev, hq) 258 struct device *pdev; 259 struct hpibqueue *hq; 260 { 261 struct hpibbus_softc *sc = (struct hpibbus_softc *)pdev; 262 int s; 263 264 s = splhigh(); /* XXXthorpej */ 265 TAILQ_INSERT_TAIL(&sc->sc_queue, hq, hq_list); 266 splx(s); 267 268 if (sc->sc_queue.tqh_first == hq) 269 return (1); 270 271 return (0); 272 } 273 274 void 275 hpibfree(pdev, hq) 276 struct device *pdev; 277 struct hpibqueue *hq; 278 { 279 struct hpibbus_softc *sc = (struct hpibbus_softc *)pdev; 280 int s; 281 282 s = splhigh(); /* XXXthorpej */ 283 TAILQ_REMOVE(&sc->sc_queue, hq, hq_list); 284 splx(s); 285 286 if ((hq = sc->sc_queue.tqh_first) != NULL) 287 (*hq->hq_start)(hq->hq_softc); 288 } 289 290 int 291 hpibid(unit, slave) 292 int unit, slave; 293 { 294 short id; 295 int ohpibtimeout; 296 297 /* 298 * XXX shorten timeout value so autoconfig doesn't 299 * take forever on slow CPUs. 300 */ 301 ohpibtimeout = hpibtimeout; 302 hpibtimeout = hpibidtimeout * (cpuspeed / 8); 303 if (hpibrecv(unit, 31, slave, &id, 2) != 2) 304 id = 0; 305 hpibtimeout = ohpibtimeout; 306 return(id); 307 } 308 309 int 310 hpibsend(unit, slave, sec, addr, cnt) 311 int unit, slave, sec, cnt; 312 void *addr; 313 { 314 struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit]; 315 316 return ((*sc->sc_ops->hpib_send)(sc, slave, sec, addr, cnt)); 317 } 318 319 int 320 hpibrecv(unit, slave, sec, addr, cnt) 321 int unit, slave, sec, cnt; 322 void *addr; 323 { 324 struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit]; 325 326 return ((*sc->sc_ops->hpib_recv)(sc, slave, sec, addr, cnt)); 327 } 328 329 int 330 hpibpptest(unit, slave) 331 int unit; 332 int slave; 333 { 334 struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit]; 335 336 return ((*sc->sc_ops->hpib_ppoll)(sc) & (0x80 >> slave)); 337 } 338 339 void 340 hpibppclear(unit) 341 int unit; 342 { 343 struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit]; 344 345 sc->sc_flags &= ~HPIBF_PPOLL; 346 } 347 348 void 349 hpibawait(unit) 350 int unit; 351 { 352 struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit]; 353 354 sc->sc_flags |= HPIBF_PPOLL; 355 (*sc->sc_ops->hpib_ppwatch)(sc); 356 } 357 358 int 359 hpibswait(unit, slave) 360 int unit; 361 int slave; 362 { 363 struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit]; 364 int timo = hpibtimeout; 365 int mask, (*ppoll) __P((struct hpibbus_softc *)); 366 367 ppoll = sc->sc_ops->hpib_ppoll; 368 mask = 0x80 >> slave; 369 while (((*ppoll)(sc) & mask) == 0) { 370 if (--timo == 0) { 371 printf("%s: swait timeout\n", sc->sc_dev.dv_xname); 372 return(-1); 373 } 374 } 375 return(0); 376 } 377 378 int 379 hpibustart(unit) 380 int unit; 381 { 382 struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit]; 383 384 if (sc->sc_type == HPIBA) 385 sc->sc_dq->dq_chan = DMA0; 386 else 387 sc->sc_dq->dq_chan = DMA0 | DMA1; 388 if (dmareq(sc->sc_dq)) 389 return(1); 390 return(0); 391 } 392 393 void 394 hpibstart(arg) 395 void *arg; 396 { 397 struct hpibbus_softc *sc = arg; 398 struct hpibqueue *hq; 399 400 hq = sc->sc_queue.tqh_first; 401 (*hq->hq_go)(hq->hq_softc); 402 } 403 404 void 405 hpibgo(unit, slave, sec, vbuf, count, rw, timo) 406 int unit, slave, sec; 407 void *vbuf; 408 int count, rw, timo; 409 { 410 struct hpibbus_softc *sc = hpibbus_cd.cd_devs[unit]; 411 412 (*sc->sc_ops->hpib_go)(sc, slave, sec, vbuf, count, rw, timo); 413 } 414 415 void 416 hpibdone(arg) 417 void *arg; 418 { 419 struct hpibbus_softc *sc = arg; 420 421 (*sc->sc_ops->hpib_done)(sc); 422 } 423 424 int 425 hpibintr(arg) 426 void *arg; 427 { 428 struct hpibbus_softc *sc = arg; 429 430 return ((sc->sc_ops->hpib_intr)(arg)); 431 } 432 433 int 434 hpibbus_alloc(sc, slave, punit) 435 struct hpibbus_softc *sc; 436 int slave, punit; 437 { 438 439 if (slave >= HPIB_NSLAVES || 440 punit >= HPIB_NPUNITS) 441 panic("hpibbus_alloc: device address out of range"); 442 443 if (sc->sc_rmap[slave][punit] == 0) { 444 sc->sc_rmap[slave][punit] = 1; 445 return (0); 446 } 447 return (1); 448 } 449 450 void 451 hpibbus_free(sc, slave, punit) 452 struct hpibbus_softc *sc; 453 int slave, punit; 454 { 455 456 if (slave >= HPIB_NSLAVES || 457 punit >= HPIB_NPUNITS) 458 panic("hpibbus_free: device address out of range"); 459 460 #ifdef DIAGNOSTIC 461 if (sc->sc_rmap[slave][punit] == 0) 462 panic("hpibbus_free: not allocated"); 463 #endif 464 465 sc->sc_rmap[slave][punit] = 0; 466 } 467