home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / hp300 / dev / fhpib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-08  |  12.6 KB  |  506 lines

  1. /*
  2.  * Copyright (c) 1982, 1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  *    @(#)fhpib.c    7.3 (Berkeley) 12/16/90
  34.  */
  35.  
  36. /*
  37.  * 98625A/B HPIB driver
  38.  */
  39. #include "hpib.h"
  40. #if NHPIB > 0
  41.  
  42. #include "sys/param.h"
  43. #include "sys/systm.h"
  44. #include "sys/buf.h"
  45. #include "device.h"
  46. #include "fhpibreg.h"
  47. #include "hpibvar.h"
  48. #include "dmavar.h"
  49.  
  50. /*
  51.  * Inline version of fhpibwait to be used in places where
  52.  * we don't worry about getting hung.
  53.  */
  54. #define    FHPIBWAIT(hd, m)    while (((hd)->hpib_intr & (m)) == 0) DELAY(1)
  55.  
  56. #ifdef DEBUG
  57. int    fhpibdebugunit = -1;
  58. int    fhpibdebug = 0;
  59. #define FDB_FAIL    0x01
  60. #define FDB_DMA        0x02
  61. #define FDB_WAIT    0x04
  62. #define FDB_PPOLL    0x08
  63.  
  64. int    dopriodma = 0;    /* use high priority DMA */
  65. int    doworddma = 1;    /* non-zero if we should attempt word dma */
  66. int    doppollint = 1;    /* use ppoll interrupts instead of watchdog */
  67.  
  68. long    fhpibbadint[2] = { 0 };
  69. long    fhpibtransfer[NHPIB] = { 0 };
  70. long    fhpibnondma[NHPIB] = { 0 };
  71. long    fhpibworddma[NHPIB] = { 0 };
  72. #endif
  73.  
  74. int    fhpibcmd[NHPIB];
  75.  
  76. fhpibtype(hc)
  77.     register struct hp_ctlr *hc;
  78. {
  79.     register struct hpib_softc *hs = &hpib_softc[hc->hp_unit];
  80.     register struct fhpibdevice *hd = (struct fhpibdevice *)hc->hp_addr;
  81.  
  82.     if (hd->hpib_cid != HPIBC)
  83.         return(0);
  84.     hs->sc_type = HPIBC;
  85.     hs->sc_ba = HPIBC_BA;
  86.     hc->hp_ipl = HPIB_IPL(hd->hpib_ids);
  87.     return(1);
  88. }
  89.  
  90. fhpibreset(unit)
  91. {
  92.     register struct hpib_softc *hs = &hpib_softc[unit];
  93.     register struct fhpibdevice *hd;
  94.  
  95.     hd = (struct fhpibdevice *)hs->sc_hc->hp_addr;
  96.     hd->hpib_cid = 0xFF;
  97.     DELAY(100);
  98.     hd->hpib_cmd = CT_8BIT;
  99.     hd->hpib_ar = AR_ARONC;
  100.     fhpibifc(hd);
  101.     hd->hpib_ie = IDS_IE;
  102.     hd->hpib_data = C_DCL;
  103.     DELAY(100000);
  104.     /*
  105.      * See if we can do word dma.
  106.      * If so, we should be able to write and read back the appropos bit.
  107.      */
  108.     hd->hpib_ie |= IDS_WDMA;
  109.     if (hd->hpib_ie & IDS_WDMA) {
  110.         hd->hpib_ie &= ~IDS_WDMA;
  111.         hs->sc_flags |= HPIBF_DMA16;
  112. #ifdef DEBUG
  113.         if (fhpibdebug & FDB_DMA)
  114.             printf("fhpibtype: unit %d has word dma\n", unit);
  115.  
  116. #endif
  117.     }
  118. }
  119.  
  120. fhpibifc(hd)
  121.     register struct fhpibdevice *hd;
  122. {
  123.     hd->hpib_cmd |= CT_IFC;
  124.     hd->hpib_cmd |= CT_INITFIFO;
  125.     DELAY(100);
  126.     hd->hpib_cmd &= ~CT_IFC;
  127.     hd->hpib_cmd |= CT_REN;
  128.     hd->hpib_stat = ST_ATN;
  129. }
  130.  
  131. fhpibsend(unit, slave, sec, addr, origcnt)
  132.     register char *addr;
  133. {
  134.     register struct hpib_softc *hs = &hpib_softc[unit];
  135.     register struct fhpibdevice *hd;
  136.     register int cnt = origcnt;
  137.     register int timo;
  138.  
  139.     hd = (struct fhpibdevice *)hs->sc_hc->hp_addr;
  140.     hd->hpib_stat = 0;
  141.     hd->hpib_imask = IM_IDLE | IM_ROOM;
  142.     if (fhpibwait(hd, IM_IDLE) < 0)
  143.         goto senderr;
  144.     hd->hpib_stat = ST_ATN;
  145.     hd->hpib_data = C_UNL;
  146.     hd->hpib_data = C_TAG + hs->sc_ba;
  147.     hd->hpib_data = C_LAG + slave;
  148.     if (sec != -1)
  149.         hd->hpib_data = C_SCG + sec;
  150.     if (fhpibwait(hd, IM_IDLE) < 0)
  151.         goto senderr;
  152.     if (cnt) {
  153.         hd->hpib_stat = ST_WRITE;
  154.         while (--cnt) {
  155.             hd->hpib_data = *addr++;
  156.             timo = hpibtimeout;
  157.             while ((hd->hpib_intr & IM_ROOM) == 0) {
  158.                 if (--timo <= 0)
  159.                     goto senderr;
  160.                 DELAY(1);
  161.             }
  162.         }
  163.         hd->hpib_stat = ST_EOI;
  164.         hd->hpib_data = *addr;
  165.         FHPIBWAIT(hd, IM_ROOM);
  166.         hd->hpib_stat = ST_ATN;
  167.         /* XXX: HP-UX claims bug with CS80 transparent messages */
  168.         if (sec == 0x12)
  169.             DELAY(150);
  170.         hd->hpib_data = C_UNL;
  171.         (void) fhpibwait(hd, IM_IDLE);
  172.     }
  173.     hd->hpib_imask = 0;
  174.     return (origcnt);
  175. senderr:
  176.     hd->hpib_imask = 0;
  177.     fhpibifc(hd);
  178. #ifdef DEBUG
  179.     if (fhpibdebug & FDB_FAIL) {
  180.         printf("hpib%d: fhpibsend failed: slave %d, sec %x, ",
  181.             unit, slave, sec);
  182.         printf("sent %d of %d bytes\n", origcnt-cnt-1, origcnt);
  183.     }
  184. #endif
  185.     return(origcnt - cnt - 1);
  186. }
  187.  
  188. fhpibrecv(unit, slave, sec, addr, origcnt)
  189.     register char *addr;
  190. {
  191.     register struct hpib_softc *hs = &hpib_softc[unit];
  192.     register struct fhpibdevice *hd;
  193.     register int cnt = origcnt;
  194.     register int timo;
  195.  
  196.     hd = (struct fhpibdevice *)hs->sc_hc->hp_addr;
  197.     hd->hpib_stat = 0;
  198.     hd->hpib_imask = IM_IDLE | IM_ROOM | IM_BYTE;
  199.     if (fhpibwait(hd, IM_IDLE) < 0)
  200.         goto recverror;
  201.     hd->hpib_stat = ST_ATN;
  202.     hd->hpib_data = C_UNL;
  203.     hd->hpib_data = C_LAG + hs->sc_ba;
  204.     hd->hpib_data = C_TAG + slave;
  205.     if (sec != -1)
  206.         hd->hpib_data = C_SCG + sec;
  207.     if (fhpibwait(hd, IM_IDLE) < 0)
  208.         goto recverror;
  209.     hd->hpib_stat = ST_READ0;
  210.     hd->hpib_data = 0;
  211.     if (cnt) {
  212.         while (--cnt >= 0) {
  213.             timo = hpibtimeout;
  214.             while ((hd->hpib_intr & IM_BYTE) == 0) {
  215.                 if (--timo == 0)
  216.                     goto recvbyteserror;
  217.                 DELAY(1);
  218.             }
  219.             *addr++ = hd->hpib_data;
  220.         }
  221.         FHPIBWAIT(hd, IM_ROOM);
  222.         hd->hpib_stat = ST_ATN;
  223.         hd->hpib_data = (slave == 31) ? C_UNA : C_UNT;
  224.         (void) fhpibwait(hd, IM_IDLE);
  225.     }
  226.     hd->hpib_imask = 0;
  227.     return (origcnt);
  228.  
  229. recverror:
  230.     fhpibifc(hd);
  231. recvbyteserror:
  232.     hd->hpib_imask = 0;
  233. #ifdef DEBUG
  234.     if (fhpibdebug & FDB_FAIL) {
  235.         printf("hpib%d: fhpibrecv failed: slave %d, sec %x, ",
  236.                unit, slave, sec);
  237.         printf("got %d of %d bytes\n", origcnt-cnt-1, origcnt);
  238.     }
  239. #endif
  240.     return(origcnt - cnt - 1);
  241. }
  242.  
  243. fhpibgo(unit, slave, sec, addr, count, rw)
  244.     register int unit;
  245.     char *addr;
  246. {
  247.     register struct hpib_softc *hs = &hpib_softc[unit];
  248.     register struct fhpibdevice *hd;
  249.     register int i;
  250.     int flags = 0;
  251.  
  252. #ifdef lint
  253.     i = unit; if (i) return;
  254. #endif
  255.     hd = (struct fhpibdevice *)hs->sc_hc->hp_addr;
  256.     hs->sc_flags |= HPIBF_IO;
  257.     if (rw == B_READ)
  258.         hs->sc_flags |= HPIBF_READ;
  259. #ifdef DEBUG
  260.     else if (hs->sc_flags & HPIBF_READ) {
  261.         printf("fhpibgo: HPIBF_READ still set\n");
  262.         hs->sc_flags &= ~HPIBF_READ;
  263.     }
  264. #endif
  265.     hs->sc_count = count;
  266.     hs->sc_addr = addr;
  267. #ifdef DEBUG
  268.     fhpibtransfer[unit]++;
  269. #endif
  270.     if ((hs->sc_flags & HPIBF_DMA16) &&
  271.         ((int)addr & 1) == 0 && count && (count & 1) == 0
  272. #ifdef DEBUG
  273.         && doworddma
  274. #endif
  275.         ) {
  276. #ifdef DEBUG
  277.         fhpibworddma[unit]++;
  278. #endif
  279.         flags |= DMAGO_WORD;
  280.         hd->hpib_latch = 0;
  281.     }
  282. #ifdef DEBUG
  283.     if (dopriodma)
  284.         flags |= DMAGO_PRI;
  285. #endif
  286.     if (hs->sc_flags & HPIBF_READ) {
  287.         fhpibcmd[unit] = CT_REN | CT_8BIT;
  288.         hs->sc_curcnt = count;
  289.         dmago(hs->sc_dq.dq_ctlr, addr, count, flags|DMAGO_READ);
  290.         if (fhpibrecv(unit, slave, sec, 0, 0) < 0) {
  291. #ifdef DEBUG
  292.             printf("fhpibgo: recv failed, retrying...\n");
  293. #endif
  294.             (void) fhpibrecv(unit, slave, sec, 0, 0);
  295.         }
  296.         i = hd->hpib_cmd;
  297.         hd->hpib_cmd = fhpibcmd[unit];
  298.         hd->hpib_ie = IDS_DMA(hs->sc_dq.dq_ctlr) |
  299.             ((flags & DMAGO_WORD) ? IDS_WDMA : 0);
  300.         return;
  301.     }
  302.     fhpibcmd[unit] = CT_REN | CT_8BIT | CT_FIFOSEL;
  303.     if (count < hpibdmathresh) {
  304. #ifdef DEBUG
  305.         fhpibnondma[unit]++;
  306.         if (flags & DMAGO_WORD)
  307.             fhpibworddma[unit]--;
  308. #endif
  309.         hs->sc_curcnt = count;
  310.         (void) fhpibsend(unit, slave, sec, addr, count);
  311.         fhpibdone(unit);
  312.         return;
  313.     }
  314.     count -= (flags & DMAGO_WORD) ? 2 : 1;
  315.     hs->sc_curcnt = count;
  316.     dmago(hs->sc_dq.dq_ctlr, addr, count, flags);
  317.     if (fhpibsend(unit, slave, sec, 0, 0) < 0) {
  318. #ifdef DEBUG
  319.         printf("fhpibgo: send failed, retrying...\n");
  320. #endif
  321.         (void) fhpibsend(unit, slave, sec, 0, 0);
  322.     }
  323.     i = hd->hpib_cmd;
  324.     hd->hpib_cmd = fhpibcmd[unit];
  325.     hd->hpib_ie = IDS_DMA(hs->sc_dq.dq_ctlr) | IDS_WRITE |
  326.         ((flags & DMAGO_WORD) ? IDS_WDMA : 0);
  327. }
  328.  
  329. fhpibdone(unit)
  330. {
  331.     register struct hpib_softc *hs = &hpib_softc[unit];
  332.     register struct fhpibdevice *hd;
  333.     register char *addr;
  334.     register int cnt;
  335.  
  336.     hd = (struct fhpibdevice *)hs->sc_hc->hp_addr;
  337.     cnt = hs->sc_curcnt;
  338.     hs->sc_addr += cnt;
  339.     hs->sc_count -= cnt;
  340. #ifdef DEBUG
  341.     if ((fhpibdebug & FDB_DMA) && fhpibdebugunit == unit)
  342.         printf("fhpibdone: addr %x cnt %d\n",
  343.                hs->sc_addr, hs->sc_count);
  344. #endif
  345.     if (hs->sc_flags & HPIBF_READ)
  346.         hd->hpib_imask = IM_IDLE | IM_BYTE;
  347.     else {
  348.         cnt = hs->sc_count;
  349.         if (cnt) {
  350.             addr = hs->sc_addr;
  351.             hd->hpib_imask = IM_IDLE | IM_ROOM;
  352.             FHPIBWAIT(hd, IM_IDLE);
  353.             hd->hpib_stat = ST_WRITE;
  354.             while (--cnt) {
  355.                 hd->hpib_data = *addr++;
  356.                 FHPIBWAIT(hd, IM_ROOM);
  357.             }
  358.             hd->hpib_stat = ST_EOI;
  359.             hd->hpib_data = *addr;
  360.         }
  361.         hd->hpib_imask = IM_IDLE;
  362.     }
  363.     hs->sc_flags |= HPIBF_DONE;
  364.     hd->hpib_stat = ST_IENAB;
  365.     hd->hpib_ie = IDS_IE;
  366. }
  367.  
  368. fhpibintr(unit)
  369.     register int unit;
  370. {
  371.     register struct hpib_softc *hs = &hpib_softc[unit];
  372.     register struct fhpibdevice *hd;
  373.     register struct devqueue *dq;
  374.     register int stat0;
  375.  
  376.     hd = (struct fhpibdevice *)hs->sc_hc->hp_addr;
  377.     stat0 = hd->hpib_ids;
  378.     if ((stat0 & (IDS_IE|IDS_IR)) != (IDS_IE|IDS_IR)) {
  379. #ifdef DEBUG
  380.         if ((fhpibdebug & FDB_FAIL) && (stat0 & IDS_IR) &&
  381.             (hs->sc_flags & (HPIBF_IO|HPIBF_DONE)) != HPIBF_IO)
  382.             printf("hpib%d: fhpibintr: bad status %x\n",
  383.                    unit, stat0);
  384.         fhpibbadint[0]++;
  385. #endif
  386.         return(0);
  387.     }
  388.     if ((hs->sc_flags & (HPIBF_IO|HPIBF_DONE)) == HPIBF_IO) {
  389. #ifdef DEBUG
  390.         fhpibbadint[1]++;
  391. #endif
  392.         return(0);
  393.     }
  394. #ifdef DEBUG
  395.     if ((fhpibdebug & FDB_DMA) && fhpibdebugunit == unit)
  396.         printf("fhpibintr: flags %x\n", hs->sc_flags);
  397. #endif
  398.     dq = hs->sc_sq.dq_forw;
  399.     if (hs->sc_flags & HPIBF_IO) {
  400.         stat0 = hd->hpib_cmd;
  401.         hd->hpib_cmd = fhpibcmd[unit] & ~CT_8BIT;
  402.         hd->hpib_stat = 0;
  403.         hd->hpib_cmd = CT_REN | CT_8BIT;
  404.         stat0 = hd->hpib_intr;
  405.         hd->hpib_imask = 0;
  406.         hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ);
  407.         dmafree(&hs->sc_dq);
  408.         (dq->dq_driver->d_intr)(dq->dq_unit);
  409.     } else if (hs->sc_flags & HPIBF_PPOLL) {
  410.         stat0 = hd->hpib_intr;
  411. #ifdef DEBUG
  412.         if ((fhpibdebug & FDB_FAIL) &&
  413.             doppollint && (stat0 & IM_PPRESP) == 0)
  414.             printf("hpib%d: fhpibintr: bad intr reg %x\n",
  415.                    unit, stat0);
  416. #endif
  417.         hd->hpib_stat = 0;
  418.         hd->hpib_imask = 0;
  419. #ifdef DEBUG
  420.         stat0 = fhpibppoll(unit);
  421.         if ((fhpibdebug & FDB_PPOLL) && unit == fhpibdebugunit)
  422.             printf("fhpibintr: got PPOLL status %x\n", stat0);
  423.         if ((stat0 & (0x80 >> dq->dq_slave)) == 0) {
  424.             printf("fhpibintr: PPOLL: unit %d slave %d stat %x\n",
  425.                    unit, dq->dq_slave, stat0);
  426.             return(1);
  427.         }
  428. #endif
  429.         hs->sc_flags &= ~HPIBF_PPOLL;
  430.         (dq->dq_driver->d_intr)(dq->dq_unit);
  431.     }
  432.     return(1);
  433. }
  434.  
  435. fhpibppoll(unit)
  436. {
  437.     register struct fhpibdevice *hd;
  438.     register int ppoll;
  439.  
  440.     hd = (struct fhpibdevice *)hpib_softc[unit].sc_hc->hp_addr;
  441.     hd->hpib_stat = 0;
  442.     hd->hpib_psense = 0;
  443.     hd->hpib_pmask = 0xFF;
  444.     hd->hpib_imask = IM_PPRESP | IM_PABORT;
  445.     DELAY(25);
  446.     hd->hpib_intr = IM_PABORT;
  447.     ppoll = hd->hpib_data;
  448.     if (hd->hpib_intr & IM_PABORT)
  449.         ppoll = 0;
  450.     hd->hpib_imask = 0;
  451.     hd->hpib_pmask = 0;
  452.     hd->hpib_stat = ST_IENAB;
  453.     return(ppoll);
  454. }
  455.  
  456. fhpibwait(hd, x)
  457.     register struct fhpibdevice *hd;
  458. {
  459.     register int timo = hpibtimeout;
  460.  
  461.     while ((hd->hpib_intr & x) == 0 && --timo)
  462.         DELAY(1);
  463.     if (timo == 0) {
  464. #ifdef DEBUG
  465.         if (fhpibdebug & FDB_FAIL)
  466.             printf("fhpibwait(%x, %x) timeout\n", hd, x);
  467. #endif
  468.         return(-1);
  469.     }
  470.     return(0);
  471. }
  472.  
  473. /*
  474.  * XXX: this will have to change if we every allow more than one
  475.  * pending operation per HP-IB.
  476.  */
  477. fhpibppwatch(unit)
  478. {
  479.     register struct hpib_softc *hs = &hpib_softc[unit];
  480.     register struct fhpibdevice *hd;
  481.     register int slave;
  482.  
  483.     if ((hs->sc_flags & HPIBF_PPOLL) == 0)
  484.         return;
  485.     hd = (struct fhpibdevice *)hs->sc_hc->hp_addr;
  486.     slave = (0x80 >> hs->sc_sq.dq_forw->dq_slave);
  487. #ifdef DEBUG
  488.     if (!doppollint) {
  489.         if (fhpibppoll(unit) & slave) {
  490.             hd->hpib_stat = ST_IENAB;
  491.             hd->hpib_imask = IM_IDLE | IM_ROOM;
  492.         } else
  493.             timeout(fhpibppwatch, unit, 1);
  494.         return;
  495.     }
  496.     if ((fhpibdebug & FDB_PPOLL) && unit == fhpibdebugunit)
  497.         printf("fhpibppwatch: sense request on %d\n", unit);
  498. #endif
  499.     hd->hpib_psense = ~slave;
  500.     hd->hpib_pmask = slave;
  501.     hd->hpib_stat = ST_IENAB;
  502.     hd->hpib_imask = IM_PPRESP | IM_PABORT;
  503.     hd->hpib_ie = IDS_IE;
  504. }
  505. #endif
  506.