1 /* $NetBSD: nhpib.c,v 1.6 1995/01/07 10:30:14 mycroft Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)nhpib.c 8.2 (Berkeley) 1/12/94 36 */ 37 38 /* 39 * Internal/98624 HPIB driver 40 */ 41 #include "hpib.h" 42 #if NHPIB > 0 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/kernel.h> 47 #include <sys/buf.h> 48 49 #include <hp300/dev/device.h> 50 #include <hp300/dev/nhpibreg.h> 51 #include <hp300/dev/hpibvar.h> 52 #include <hp300/dev/dmavar.h> 53 54 /* 55 * ODD parity table for listen and talk addresses and secondary commands. 56 * The TI9914A doesn't produce the parity bit. 57 */ 58 static u_char listnr_par[] = { 59 0040,0241,0242,0043,0244,0045,0046,0247, 60 0250,0051,0052,0253,0054,0255,0256,0057, 61 0260,0061,0062,0263,0064,0265,0266,0067, 62 0070,0271,0272,0073,0274,0075,0076,0277, 63 }; 64 static u_char talker_par[] = { 65 0100,0301,0302,0103,0304,0105,0106,0307, 66 0310,0111,0112,0313,0114,0315,0316,0117, 67 0320,0121,0122,0323,0124,0325,0326,0127, 68 0130,0331,0332,0133,0334,0135,0136,0337, 69 }; 70 static u_char sec_par[] = { 71 0340,0141,0142,0343,0144,0345,0346,0147, 72 0150,0351,0352,0153,0354,0155,0156,0357, 73 0160,0361,0362,0163,0364,0165,0166,0367, 74 0370,0171,0172,0373,0174,0375,0376,0177 75 }; 76 77 nhpibtype(hc) 78 register struct hp_ctlr *hc; 79 { 80 register struct hpib_softc *hs = &hpib_softc[hc->hp_unit]; 81 register struct nhpibdevice *hd = (struct nhpibdevice *)hc->hp_addr; 82 83 if (hc->hp_addr == internalhpib) { 84 hs->sc_type = HPIBA; 85 hs->sc_ba = HPIBA_BA; 86 hc->hp_ipl = HPIBA_IPL; 87 } 88 else if (hd->hpib_cid == HPIBB) { 89 hs->sc_type = HPIBB; 90 hs->sc_ba = hd->hpib_csa & CSA_BA; 91 hc->hp_ipl = HPIB_IPL(hd->hpib_ids); 92 } 93 else 94 return(0); 95 return(1); 96 } 97 98 nhpibreset(unit) 99 int unit; 100 { 101 register struct hpib_softc *hs = &hpib_softc[unit]; 102 register struct nhpibdevice *hd; 103 104 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr; 105 hd->hpib_acr = AUX_SSWRST; 106 hd->hpib_ar = hs->sc_ba; 107 hd->hpib_lim = LIS_ERR; 108 hd->hpib_mim = 0; 109 hd->hpib_acr = AUX_CDAI; 110 hd->hpib_acr = AUX_CSHDW; 111 hd->hpib_acr = AUX_SSTD1; 112 hd->hpib_acr = AUX_SVSTD1; 113 hd->hpib_acr = AUX_CPP; 114 hd->hpib_acr = AUX_CHDFA; 115 hd->hpib_acr = AUX_CHDFE; 116 hd->hpib_acr = AUX_RHDF; 117 hd->hpib_acr = AUX_CSWRST; 118 nhpibifc(hd); 119 hd->hpib_ie = IDS_IE; 120 hd->hpib_data = C_DCL_P; 121 DELAY(100000); 122 } 123 124 nhpibifc(hd) 125 register struct nhpibdevice *hd; 126 { 127 hd->hpib_acr = AUX_TCA; 128 hd->hpib_acr = AUX_CSRE; 129 hd->hpib_acr = AUX_SSIC; 130 DELAY(100); 131 hd->hpib_acr = AUX_CSIC; 132 hd->hpib_acr = AUX_SSRE; 133 } 134 135 nhpibsend(unit, slave, sec, addr, origcnt) 136 int unit, slave, sec, origcnt; 137 register char *addr; 138 { 139 register struct hpib_softc *hs = &hpib_softc[unit]; 140 register struct nhpibdevice *hd; 141 register int cnt = origcnt; 142 143 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr; 144 hd->hpib_acr = AUX_TCA; 145 hd->hpib_data = C_UNL_P; 146 if (nhpibwait(hd, MIS_BO)) 147 goto senderror; 148 hd->hpib_data = talker_par[hs->sc_ba]; 149 hd->hpib_acr = AUX_STON; 150 if (nhpibwait(hd, MIS_BO)) 151 goto senderror; 152 hd->hpib_data = listnr_par[slave]; 153 if (nhpibwait(hd, MIS_BO)) 154 goto senderror; 155 if (sec >= 0 || sec == -2) { 156 if (sec == -2) /* selected device clear KLUDGE */ 157 hd->hpib_data = C_SDC_P; 158 else 159 hd->hpib_data = sec_par[sec]; 160 if (nhpibwait(hd, MIS_BO)) 161 goto senderror; 162 } 163 hd->hpib_acr = AUX_GTS; 164 if (cnt) { 165 while (--cnt > 0) { 166 hd->hpib_data = *addr++; 167 if (nhpibwait(hd, MIS_BO)) 168 goto senderror; 169 } 170 hd->hpib_acr = AUX_EOI; 171 hd->hpib_data = *addr; 172 if (nhpibwait(hd, MIS_BO)) 173 goto senderror; 174 hd->hpib_acr = AUX_TCA; 175 #if 0 176 /* 177 * May be causing 345 disks to hang due to interference 178 * with PPOLL mechanism. 179 */ 180 hd->hpib_data = C_UNL_P; 181 (void) nhpibwait(hd, MIS_BO); 182 #endif 183 } 184 return(origcnt); 185 186 senderror: 187 nhpibifc(hd); 188 return(origcnt - cnt - 1); 189 } 190 191 nhpibrecv(unit, slave, sec, addr, origcnt) 192 int unit, slave, sec, origcnt; 193 register char *addr; 194 { 195 register struct hpib_softc *hs = &hpib_softc[unit]; 196 register struct nhpibdevice *hd; 197 register int cnt = origcnt; 198 199 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr; 200 /* 201 * Slave < 0 implies continuation of a previous receive 202 * that probably timed out. 203 */ 204 if (slave >= 0) { 205 hd->hpib_acr = AUX_TCA; 206 hd->hpib_data = C_UNL_P; 207 if (nhpibwait(hd, MIS_BO)) 208 goto recverror; 209 hd->hpib_data = listnr_par[hs->sc_ba]; 210 hd->hpib_acr = AUX_SLON; 211 if (nhpibwait(hd, MIS_BO)) 212 goto recverror; 213 hd->hpib_data = talker_par[slave]; 214 if (nhpibwait(hd, MIS_BO)) 215 goto recverror; 216 if (sec >= 0) { 217 hd->hpib_data = sec_par[sec]; 218 if (nhpibwait(hd, MIS_BO)) 219 goto recverror; 220 } 221 hd->hpib_acr = AUX_RHDF; 222 hd->hpib_acr = AUX_GTS; 223 } 224 if (cnt) { 225 while (--cnt >= 0) { 226 if (nhpibwait(hd, MIS_BI)) 227 goto recvbyteserror; 228 *addr++ = hd->hpib_data; 229 } 230 hd->hpib_acr = AUX_TCA; 231 hd->hpib_data = (slave == 31) ? C_UNA_P : C_UNT_P; 232 (void) nhpibwait(hd, MIS_BO); 233 } 234 return(origcnt); 235 236 recverror: 237 nhpibifc(hd); 238 recvbyteserror: 239 return(origcnt - cnt - 1); 240 } 241 242 nhpibgo(unit, slave, sec, addr, count, rw, timo) 243 register int unit, slave; 244 int sec, count, rw; 245 char *addr; 246 { 247 register struct hpib_softc *hs = &hpib_softc[unit]; 248 register struct nhpibdevice *hd; 249 250 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr; 251 hs->sc_flags |= HPIBF_IO; 252 if (timo) 253 hs->sc_flags |= HPIBF_TIMO; 254 if (rw == B_READ) 255 hs->sc_flags |= HPIBF_READ; 256 #ifdef DEBUG 257 else if (hs->sc_flags & HPIBF_READ) { 258 printf("nhpibgo: HPIBF_READ still set\n"); 259 hs->sc_flags &= ~HPIBF_READ; 260 } 261 #endif 262 hs->sc_count = count; 263 hs->sc_addr = addr; 264 if (hs->sc_flags & HPIBF_READ) { 265 hs->sc_curcnt = count; 266 dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE|DMAGO_READ); 267 nhpibrecv(unit, slave, sec, 0, 0); 268 hd->hpib_mim = MIS_END; 269 } else { 270 hd->hpib_mim = 0; 271 if (count < hpibdmathresh) { 272 hs->sc_curcnt = count; 273 nhpibsend(unit, slave, sec, addr, count); 274 nhpibdone(unit); 275 return; 276 } 277 hs->sc_curcnt = --count; 278 dmago(hs->sc_dq.dq_ctlr, addr, count, DMAGO_BYTE); 279 nhpibsend(unit, slave, sec, 0, 0); 280 } 281 hd->hpib_ie = IDS_IE | IDS_DMA(hs->sc_dq.dq_ctlr); 282 } 283 284 /* 285 * This timeout can only happen if a DMA read finishes DMAing with the read 286 * still pending (more data in read transaction than the driver was prepared 287 * to accept). At the moment, variable-record tape drives are the only things 288 * capabale of doing this. We repeat the necessary code from nhpibintr() - 289 * easier and quicker than calling nhpibintr() for this special case. 290 */ 291 void 292 nhpibreadtimo(arg) 293 void *arg; 294 { 295 int unit; 296 register struct hpib_softc *hs; 297 int s = splbio(); 298 299 unit = (int)arg; 300 hs = &hpib_softc[unit]; 301 if (hs->sc_flags & HPIBF_IO) { 302 register struct nhpibdevice *hd; 303 register struct devqueue *dq; 304 305 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr; 306 hd->hpib_mim = 0; 307 hd->hpib_acr = AUX_TCA; 308 hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO); 309 dmafree(&hs->sc_dq); 310 dq = hs->sc_sq.dq_forw; 311 (dq->dq_driver->d_intr)(dq->dq_unit); 312 } 313 (void) splx(s); 314 } 315 316 nhpibdone(unit) 317 register int unit; 318 { 319 register struct hpib_softc *hs = &hpib_softc[unit]; 320 register struct nhpibdevice *hd; 321 register int cnt; 322 323 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr; 324 cnt = hs->sc_curcnt; 325 hs->sc_addr += cnt; 326 hs->sc_count -= cnt; 327 hs->sc_flags |= HPIBF_DONE; 328 hd->hpib_ie = IDS_IE; 329 if (hs->sc_flags & HPIBF_READ) { 330 if ((hs->sc_flags & HPIBF_TIMO) && 331 (hd->hpib_ids & IDS_IR) == 0) 332 timeout(nhpibreadtimo, (void *)unit, hz >> 2); 333 } else { 334 if (hs->sc_count == 1) { 335 (void) nhpibwait(hd, MIS_BO); 336 hd->hpib_acr = AUX_EOI; 337 hd->hpib_data = *hs->sc_addr; 338 hd->hpib_mim = MIS_BO; 339 } 340 #ifdef DEBUG 341 else if (hs->sc_count) 342 panic("nhpibdone"); 343 #endif 344 } 345 } 346 347 nhpibintr(unit) 348 register int unit; 349 { 350 register struct hpib_softc *hs = &hpib_softc[unit]; 351 register struct nhpibdevice *hd; 352 register struct devqueue *dq; 353 register int stat0; 354 int stat1; 355 356 #ifdef lint 357 if (stat1 = unit) return(1); 358 #endif 359 hd = (struct nhpibdevice *)hs->sc_hc->hp_addr; 360 if ((hd->hpib_ids & IDS_IR) == 0) 361 return(0); 362 stat0 = hd->hpib_mis; 363 stat1 = hd->hpib_lis; 364 dq = hs->sc_sq.dq_forw; 365 if (hs->sc_flags & HPIBF_IO) { 366 hd->hpib_mim = 0; 367 if ((hs->sc_flags & HPIBF_DONE) == 0) { 368 hs->sc_flags &= ~HPIBF_TIMO; 369 dmastop(hs->sc_dq.dq_ctlr); 370 } else if (hs->sc_flags & HPIBF_TIMO) 371 untimeout(nhpibreadtimo, (void *)unit); 372 hd->hpib_acr = AUX_TCA; 373 hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO); 374 dmafree(&hs->sc_dq); 375 (dq->dq_driver->d_intr)(dq->dq_unit); 376 } else if (hs->sc_flags & HPIBF_PPOLL) { 377 hd->hpib_mim = 0; 378 stat0 = nhpibppoll(unit); 379 if (stat0 & (0x80 >> dq->dq_slave)) { 380 hs->sc_flags &= ~HPIBF_PPOLL; 381 (dq->dq_driver->d_intr)(dq->dq_unit); 382 } 383 #ifdef DEBUG 384 else 385 printf("hpib%d: PPOLL intr bad status %x\n", 386 unit, stat0); 387 #endif 388 } 389 return(1); 390 } 391 392 nhpibppoll(unit) 393 int unit; 394 { 395 register struct nhpibdevice *hd; 396 register int ppoll; 397 398 hd = (struct nhpibdevice *)hpib_softc[unit].sc_hc->hp_addr; 399 hd->hpib_acr = AUX_SPP; 400 DELAY(25); 401 ppoll = hd->hpib_cpt; 402 hd->hpib_acr = AUX_CPP; 403 return(ppoll); 404 } 405 406 #ifdef DEBUG 407 int nhpibreporttimo = 0; 408 #endif 409 410 nhpibwait(hd, x) 411 register struct nhpibdevice *hd; 412 int x; 413 { 414 register int timo = hpibtimeout; 415 416 while ((hd->hpib_mis & x) == 0 && --timo) 417 DELAY(1); 418 if (timo == 0) { 419 #ifdef DEBUG 420 if (nhpibreporttimo) 421 printf("hpib0: %s timo\n", x==MIS_BO?"OUT":"IN"); 422 #endif 423 return(-1); 424 } 425 return(0); 426 } 427 428 void 429 nhpibppwatch(arg) 430 void *arg; 431 { 432 register struct hpib_softc *hs; 433 register int unit; 434 extern int cold; 435 436 unit = (int)arg; 437 hs = &hpib_softc[unit]; 438 if ((hs->sc_flags & HPIBF_PPOLL) == 0) 439 return; 440 again: 441 if (nhpibppoll(unit) & (0x80 >> hs->sc_sq.dq_forw->dq_slave)) 442 ((struct nhpibdevice *)hs->sc_hc->hp_addr)->hpib_mim = MIS_BO; 443 else if (cold) 444 /* timeouts not working yet */ 445 goto again; 446 else 447 timeout(nhpibppwatch, (void *)unit, 1); 448 } 449 #endif 450