The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/gpib/ct.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: ct.c,v 1.2 2003/08/07 16:30:55 agc Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 1996-2003 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the NetBSD
   21  *      Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * Copyright (c) 1982, 1990, 1993
   41  *      The Regents of the University of California.  All rights reserved.
   42  *
   43  * This code is derived from software contributed to Berkeley by
   44  * the Systems Programming Group of the University of Utah Computer
   45  * Science Department.
   46  *
   47  * Redistribution and use in source and binary forms, with or without
   48  * modification, are permitted provided that the following conditions
   49  * are met:
   50  * 1. Redistributions of source code must retain the above copyright
   51  *    notice, this list of conditions and the following disclaimer.
   52  * 2. Redistributions in binary form must reproduce the above copyright
   53  *    notice, this list of conditions and the following disclaimer in the
   54  *    documentation and/or other materials provided with the distribution.
   55  * 3. Neither the name of the University nor the names of its contributors
   56  *    may be used to endorse or promote products derived from this software
   57  *    without specific prior written permission.
   58  *
   59  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   60  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   61  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   62  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   63  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   64  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   65  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   66  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   67  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   68  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   69  * SUCH DAMAGE.
   70  *
   71  * from: Utah $Hdr: rd.c 1.44 92/12/26$
   72  *
   73  *      @(#)rd.c        8.2 (Berkeley) 5/19/94
   74  */
   75 
   76 /*
   77  * Copyright (c) 1988 University of Utah.
   78  *
   79  * This code is derived from software contributed to Berkeley by
   80  * the Systems Programming Group of the University of Utah Computer
   81  * Science Department.
   82  *
   83  * Redistribution and use in source and binary forms, with or without
   84  * modification, are permitted provided that the following conditions
   85  * are met:
   86  * 1. Redistributions of source code must retain the above copyright
   87  *    notice, this list of conditions and the following disclaimer.
   88  * 2. Redistributions in binary form must reproduce the above copyright
   89  *    notice, this list of conditions and the following disclaimer in the
   90  *    documentation and/or other materials provided with the distribution.
   91  * 3. All advertising materials mentioning features or use of this software
   92  *    must display the following acknowledgement:
   93  *      This product includes software developed by the University of
   94  *      California, Berkeley and its contributors.
   95  * 4. Neither the name of the University nor the names of its contributors
   96  *    may be used to endorse or promote products derived from this software
   97  *    without specific prior written permission.
   98  *
   99  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  100  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  101  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  102  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  103  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  104  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  105  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  106  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  107  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  108  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  109  * SUCH DAMAGE.
  110  *
  111  * from: Utah $Hdr: rd.c 1.44 92/12/26$
  112  *
  113  *      @(#)rd.c        8.2 (Berkeley) 5/19/94
  114  */
  115 
  116 /*
  117  * CS/80 cartridge tape driver (HP9144, HP88140, HP9145)
  118  *
  119  * Reminder:
  120  *      C_CC bit (character count option) when used in the CS/80 command
  121  *      'set options' will cause the tape not to stream.
  122  *
  123  * TODO:
  124  *      make filesystem compatible
  125  *      make block mode work according to mtio(4) spec. (if possible)
  126  *      merge with CS/80 disk driver
  127  *      finish support of HP9145
  128  */
  129 
  130 #include <sys/cdefs.h>
  131 __KERNEL_RCSID(0, "$NetBSD: ct.c,v 1.2 2003/08/07 16:30:55 agc Exp $");
  132 
  133 #include <sys/param.h>
  134 #include <sys/systm.h>
  135 #include <sys/buf.h>
  136 #include <sys/conf.h>
  137 #include <sys/device.h>
  138 #include <sys/ioctl.h>
  139 #include <sys/mtio.h>
  140 #include <sys/proc.h>
  141 #include <sys/tprintf.h>
  142 
  143 #include <dev/gpib/ctreg.h>     /* XXX must be before cs80busvar.h ATM */
  144 
  145 #include <dev/gpib/gpibvar.h>
  146 #include <dev/gpib/cs80busvar.h>
  147 
  148 /* number of eof marks to remember */
  149 #define EOFS    128
  150 
  151 #ifdef DEBUG
  152 int ctdebug = 0xff;
  153 #define CDB_FILES       0x01
  154 #define CDB_BSF         0x02
  155 #define CDB_IDENT       0x04
  156 #define CDB_FAIL        0x08
  157 #define CDB_FOLLOW      0x10
  158 #define DPRINTF(mask, str)      if (ctdebug & (mask)) printf str
  159 #else
  160 #define DPRINTF(mask, str)      /* nothing */
  161 #endif
  162 
  163 struct  ct_softc {
  164         struct  device sc_dev;
  165 
  166         gpib_chipset_tag_t sc_ic;
  167         gpib_handle_t sc_hdl;
  168 
  169         int     sc_slave;               /* GPIB slave ID */
  170         int     sc_punit;               /* physical unit */
  171         struct  ct_iocmd sc_ioc;
  172         struct  ct_rscmd sc_rsc;
  173         struct  cs80_stat sc_stat;
  174         struct  bufq_state sc_tab;
  175         int     sc_active;
  176         struct  buf *sc_bp;
  177         struct  buf sc_bufstore;        /* XXX */
  178         int     sc_blkno;
  179         int     sc_cmd;
  180         int     sc_resid;
  181         char    *sc_addr;
  182         int     sc_flags;
  183 #define CTF_OPEN        0x01
  184 #define CTF_ALIVE       0x02
  185 #define CTF_WRT         0x04
  186 #define CTF_CMD         0x08
  187 #define CTF_IO          0x10
  188 #define CTF_BEOF        0x20
  189 #define CTF_AEOF        0x40
  190 #define CTF_EOT         0x80
  191 #define CTF_STATWAIT    0x100
  192 #define CTF_CANSTREAM   0x200
  193 #define CTF_WRTTN       0x400
  194         short   sc_type;
  195         tpr_t   sc_tpr;
  196         int     sc_eofp;
  197         int     sc_eofs[EOFS];
  198 };
  199 
  200 int     ctmatch(struct device *, struct cfdata *, void *);
  201 void    ctattach(struct device *, struct device *, void *);
  202 
  203 CFATTACH_DECL(ct, sizeof(struct ct_softc),
  204         ctmatch, ctattach, NULL, NULL);
  205 
  206 int     ctident(struct device *, struct ct_softc *,
  207             struct cs80bus_attach_args *);
  208 
  209 int     ctlookup(int, int, int);
  210 void    ctaddeof(struct ct_softc *);
  211 void    ctustart(struct ct_softc *);
  212 void    cteof(struct ct_softc *, struct buf *);
  213 void    ctdone(struct ct_softc *, struct buf *);
  214 
  215 void    ctcallback(void *, int);
  216 void    ctstart(struct ct_softc *);
  217 void    ctintr(struct ct_softc *);
  218 
  219 void    ctcommand(dev_t, int, int);
  220 
  221 dev_type_open(ctopen);
  222 dev_type_close(ctclose);
  223 dev_type_read(ctread);
  224 dev_type_write(ctwrite);
  225 dev_type_ioctl(ctioctl);
  226 dev_type_strategy(ctstrategy);
  227 
  228 const struct bdevsw ct_bdevsw = {
  229         ctopen, ctclose, ctstrategy, ctioctl, nodump, nosize, D_TAPE
  230 };
  231 
  232 const struct cdevsw ct_cdevsw = {
  233         ctopen, ctclose, ctread, ctwrite, ctioctl,
  234         nostop, notty, nopoll, nommap, nokqfilter, D_TAPE
  235 };
  236 
  237 extern struct cfdriver ct_cd;
  238 
  239 struct  ctinfo {
  240         short   hwid;
  241         short   punit;
  242         char    *desc;
  243 } ctinfo[] = {
  244         { CT7946ID,     1,      "7946A" },
  245         { CT7912PID,    1,      "7912P" },
  246         { CT7914PID,    1,      "7914P" },
  247         { CT9144ID,     0,      "9144"  },
  248         { CT9145ID,     0,      "9145"  },
  249         { CT35401ID,    0,      "35401A"},
  250 };
  251 int     nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]);
  252 
  253 #define CT_NOREW        4
  254 #define CT_STREAM       8
  255 #define CTUNIT(x)       (minor(x) & 0x03)
  256 
  257 int
  258 ctlookup(id, slave, punit)
  259         int id;
  260         int slave;
  261         int punit;
  262 {
  263         int i;
  264 
  265         for (i = 0; i < nctinfo; i++)
  266                 if (ctinfo[i].hwid == id)
  267                         break;
  268         if (i == nctinfo)
  269                 return (-1);
  270         return (i);
  271 }
  272 
  273 int
  274 ctmatch(parent, match, aux)
  275         struct device *parent;
  276         struct cfdata *match;
  277         void *aux;
  278 {
  279         struct cs80bus_attach_args *ca = aux;
  280         int i;
  281 
  282         if ((i = ctlookup(ca->ca_id, ca->ca_slave, ca->ca_punit)) < 0)
  283                 return (0);
  284         ca->ca_punit = ctinfo[i].punit;
  285         return (1);
  286 }
  287 
  288 void
  289 ctattach(parent, self, aux)
  290         struct device *parent, *self;
  291         void *aux;
  292 {
  293         struct ct_softc *sc = (struct ct_softc *)self;
  294         struct cs80bus_attach_args *ca = aux;
  295         struct cs80_description csd;
  296         char name[7];
  297         int type, i, n, canstream = 0;
  298 
  299         sc->sc_ic = ca->ca_ic;
  300         sc->sc_slave = ca->ca_slave;
  301         sc->sc_punit = ca->ca_punit;
  302 
  303         if ((type = ctlookup(ca->ca_id, ca->ca_slave, ca->ca_punit)) < 0)
  304                 return;
  305 
  306         if (cs80reset(parent, sc->sc_slave, sc->sc_punit)) {
  307                 printf("\n%s: can't reset device\n", sc->sc_dev.dv_xname);
  308                 return;
  309         }
  310 
  311         if (cs80describe(parent, sc->sc_slave, sc->sc_punit, &csd)) {
  312                 printf("\n%s: didn't respond to describe command\n",
  313                     sc->sc_dev.dv_xname);
  314                 return;
  315         }
  316         memset(name, 0, sizeof(name));
  317         for (i=0, n=0; i<3; i++) {
  318                 name[n++] = (csd.d_name[i] >> 4) + '';
  319                 name[n++] = (csd.d_name[i] & 0x0f) + '';
  320         }
  321 
  322 #ifdef DEBUG
  323         if (ctdebug & CDB_IDENT) {
  324                 printf("\n%s: name: ('%s')\n",
  325                     sc->sc_dev.dv_xname,name);
  326                 printf("  iuw %x, maxxfr %d, ctype %d\n",
  327                     csd.d_iuw, csd.d_cmaxxfr, csd.d_ctype);
  328                 printf("  utype %d, bps %d, blkbuf %d, burst %d, blktime %d\n",
  329                     csd.d_utype, csd.d_sectsize,
  330                     csd.d_blkbuf, csd.d_burstsize, csd.d_blocktime);
  331                 printf("  avxfr %d, ort %d, atp %d, maxint %d, fv %x, rv %x\n",
  332                     csd.d_uavexfr, csd.d_retry, csd.d_access,
  333                     csd.d_maxint, csd.d_fvbyte, csd.d_rvbyte);
  334                 printf("  maxcyl/head/sect %d/%d/%d, maxvsect %d, inter %d\n",
  335                     csd.d_maxcylhead >> 8 , csd.d_maxcylhead & 0xff,
  336                     csd.d_maxsect, csd.d_maxvsectl, csd.d_interleave);
  337                 printf("%s", sc->sc_dev.dv_xname);
  338         }
  339 #endif
  340 
  341         switch (ca->ca_id) {
  342         case CT7946ID:
  343                 if (memcmp(name, "079450", 6) == 0)
  344                         return;                 /* not really a 7946 */
  345                 /* fall into... */
  346         case CT9144ID:
  347         case CT9145ID:
  348         case CT35401ID:
  349                 sc->sc_type = CT9144;
  350                 canstream = 1;
  351                 break;
  352 
  353         case CT7912PID:
  354         case CT7914PID:
  355                 sc->sc_type = CT88140;
  356                 break;
  357         default:
  358                 sc->sc_type = type;
  359                 break;
  360         }
  361 
  362         sc->sc_type = type;
  363         sc->sc_flags = canstream ? CTF_CANSTREAM : 0;
  364         printf(": %s %stape\n", ctinfo[type].desc,
  365             canstream ? "streaming " : "");
  366 
  367         bufq_alloc(&sc->sc_tab, BUFQ_FCFS);
  368 
  369         if (gpibregister(sc->sc_ic, sc->sc_slave, ctcallback, sc,
  370             &sc->sc_hdl)) {
  371                 printf("%s: can't register callback\n", sc->sc_dev.dv_xname);
  372                 return;
  373         }
  374 
  375         sc->sc_flags |= CTF_ALIVE;
  376 }
  377 
  378 /*ARGSUSED*/
  379 int
  380 ctopen(dev, flag, type, p)
  381         dev_t dev;
  382         int flag, type;
  383         struct proc *p;
  384 {
  385         struct ct_softc *sc;
  386         u_int8_t opt;
  387 
  388         sc = device_lookup(&ct_cd, CTUNIT(dev));
  389         if (sc == NULL || (sc->sc_flags & CTF_ALIVE) == 0)
  390                 return (ENXIO);
  391 
  392         if (sc->sc_flags & CTF_OPEN)
  393                 return (EBUSY);
  394 
  395         if ((dev & CT_STREAM) && (sc->sc_flags & CTF_CANSTREAM))
  396                 opt = C_SPAR | C_IMRPT;
  397         else
  398                 opt = C_SPAR;
  399 
  400         if (cs80setoptions(sc->sc_dev.dv_parent, sc->sc_slave,
  401             sc->sc_punit, opt))
  402                 return (EBUSY);
  403 
  404         sc->sc_tpr = tprintf_open(p);
  405         sc->sc_flags |= CTF_OPEN;
  406 
  407         return (0);
  408 }
  409 
  410 /*ARGSUSED*/
  411 int
  412 ctclose(dev, flag, fmt, p)
  413         dev_t dev;
  414         int flag, fmt;
  415         struct proc *p;
  416 {
  417         struct ct_softc *sc;
  418 
  419         sc = device_lookup(&ct_cd, CTUNIT(dev));
  420         if (sc == NULL)
  421                 return (ENXIO);
  422 
  423         if ((sc->sc_flags & (CTF_WRT|CTF_WRTTN)) == (CTF_WRT|CTF_WRTTN) &&
  424             (sc->sc_flags & CTF_EOT) == 0 ) { /* XXX return error if EOT ?? */
  425                 ctcommand(dev, MTWEOF, 2);
  426                 ctcommand(dev, MTBSR, 1);
  427                 if (sc->sc_eofp == EOFS - 1)
  428                         sc->sc_eofs[EOFS - 1]--;
  429                 else
  430                         sc->sc_eofp--;
  431                 DPRINTF(CDB_BSF, ("%s: ctclose backup eofs prt %d blk %d\n",
  432                     sc->sc_dev.dv_xname, sc->sc_eofp,
  433                     sc->sc_eofs[sc->sc_eofp]));
  434         }
  435 
  436         if ((minor(dev) & CT_NOREW) == 0)
  437                 ctcommand(dev, MTREW, 1);
  438         sc->sc_flags &= ~(CTF_OPEN | CTF_WRT | CTF_WRTTN);
  439         tprintf_close(sc->sc_tpr);
  440         DPRINTF(CDB_FILES, ("ctclose: flags %x\n", sc->sc_flags));
  441 
  442         return (0);     /* XXX */
  443 }
  444 
  445 void
  446 ctcommand(dev, cmd, cnt)
  447         dev_t dev;
  448         int cmd;
  449         int cnt;
  450 {
  451         struct ct_softc *sc;
  452         struct buf *bp;
  453         struct buf *nbp = 0;
  454 
  455         sc = device_lookup(&ct_cd, CTUNIT(dev));
  456         bp = &sc->sc_bufstore;
  457 
  458         DPRINTF(CDB_FOLLOW, ("ctcommand: called\n"));
  459 
  460         if (cmd == MTBSF && sc->sc_eofp == EOFS - 1) {
  461                 cnt = sc->sc_eofs[EOFS - 1] - cnt;
  462                 ctcommand(dev, MTREW, 1);
  463                 ctcommand(dev, MTFSF, cnt);
  464                 cnt = 2;
  465                 cmd = MTBSR;
  466         }
  467 
  468         if (cmd == MTBSF && sc->sc_eofp - cnt < 0) {
  469                 cnt = 1;
  470                 cmd = MTREW;
  471         }
  472 
  473         sc->sc_flags |= CTF_CMD;
  474         sc->sc_bp = bp;
  475         sc->sc_cmd = cmd;
  476         bp->b_dev = dev;
  477         if (cmd == MTFSF) {
  478                 nbp = (struct buf *)geteblk(MAXBSIZE);
  479                 bp->b_data = nbp->b_data;
  480                 bp->b_bcount = MAXBSIZE;
  481         }
  482 
  483         while (cnt-- > 0) {
  484                 bp->b_flags = B_BUSY;
  485                 if (cmd == MTBSF) {
  486                         sc->sc_blkno = sc->sc_eofs[sc->sc_eofp];
  487                         sc->sc_eofp--;
  488                         DPRINTF(CDB_BSF, ("%s: backup eof pos %d blk %d\n",
  489                             sc->sc_dev.dv_xname, sc->sc_eofp, 
  490                             sc->sc_eofs[sc->sc_eofp]));
  491                 }
  492                 ctstrategy(bp);
  493                 biowait(bp);
  494         }
  495         bp->b_flags = 0;
  496         sc->sc_flags &= ~CTF_CMD;
  497         if (nbp)
  498                 brelse(nbp);
  499 }
  500 
  501 void
  502 ctstrategy(bp)
  503         struct buf *bp;
  504 {
  505         struct ct_softc *sc;
  506         int s;
  507 
  508         DPRINTF(CDB_FOLLOW, ("cdstrategy(%p): dev %x, bn %x, bcount %lx, %c\n",
  509             bp, bp->b_dev, bp->b_blkno, bp->b_bcount,
  510             (bp->b_flags & B_READ) ? 'R' : 'W'));
  511 
  512         sc = device_lookup(&ct_cd, CTUNIT(bp->b_dev));
  513 
  514         s = splbio();
  515         BUFQ_PUT(&sc->sc_tab, bp);
  516         if (sc->sc_active == 0) {
  517                 sc->sc_active = 1;
  518                 ctustart(sc);
  519         }
  520         splx(s);
  521 }
  522 
  523 void
  524 ctustart(sc)
  525         struct ct_softc *sc;
  526 {
  527         struct buf *bp;
  528 
  529         bp = BUFQ_PEEK(&sc->sc_tab);
  530         sc->sc_addr = bp->b_data;
  531         sc->sc_resid = bp->b_bcount;
  532         if (gpibrequest(sc->sc_ic, sc->sc_hdl))
  533                 ctstart(sc);
  534 }
  535 
  536 void
  537 ctstart(sc)
  538         struct ct_softc *sc;
  539 {
  540         struct buf *bp;
  541         struct ct_ulcmd ul;
  542         struct ct_wfmcmd wfm;
  543         int i, slave, punit;
  544 
  545         slave = sc->sc_slave;
  546         punit = sc->sc_punit;
  547 
  548         bp = BUFQ_PEEK(&sc->sc_tab);
  549         if ((sc->sc_flags & CTF_CMD) && sc->sc_bp == bp) {
  550                 switch(sc->sc_cmd) {
  551                 case MTFSF:
  552                         bp->b_flags |= B_READ;
  553                         goto mustio;
  554 
  555                 case MTBSF:
  556                         goto gotaddr;
  557 
  558                 case MTOFFL:
  559                         sc->sc_blkno = 0;
  560                         ul.unit = CS80CMD_SUNIT(punit);
  561                         ul.cmd = CS80CMD_UNLOAD;
  562                         (void) cs80send(sc->sc_dev.dv_parent, slave, punit,
  563                             CS80CMD_SCMD, &ul, sizeof(ul));
  564                         break;
  565 
  566                 case MTWEOF:
  567                         sc->sc_blkno++;
  568                         sc->sc_flags |= CTF_WRT;
  569                         wfm.unit = CS80CMD_SUNIT(sc->sc_punit);
  570                         wfm.cmd = CS80CMD_WFM;
  571                         (void) cs80send(sc->sc_dev.dv_parent, slave, punit,
  572                             CS80CMD_SCMD, &wfm, sizeof(wfm));
  573                         ctaddeof(sc);
  574                         break;
  575 
  576                 case MTBSR:
  577                         sc->sc_blkno--;
  578                         goto gotaddr;
  579 
  580                 case MTFSR:
  581                         sc->sc_blkno++;
  582                         goto gotaddr;
  583 
  584                 case MTREW:
  585                         sc->sc_blkno = 0;
  586                         DPRINTF(CDB_BSF, ("%s: clearing eofs\n",
  587                             sc->sc_dev.dv_xname));
  588                         for (i=0; i<EOFS; i++)
  589                                 sc->sc_eofs[i] = 0;
  590                         sc->sc_eofp = 0;
  591 
  592 gotaddr:
  593                         sc->sc_ioc.unit = CS80CMD_SUNIT(sc->sc_punit);
  594                         sc->sc_ioc.saddr = CS80CMD_SADDR;
  595                         sc->sc_ioc.addr0 = 0;
  596                         sc->sc_ioc.addr = htobe32(sc->sc_blkno);
  597                         sc->sc_ioc.nop2 = CS80CMD_NOP;
  598                         sc->sc_ioc.slen = CS80CMD_SLEN;
  599                         sc->sc_ioc.len = htobe32(0);
  600                         sc->sc_ioc.nop3 = CS80CMD_NOP;
  601                         sc->sc_ioc.cmd = CS80CMD_READ;
  602                         (void) cs80send(sc->sc_dev.dv_parent, slave, punit,
  603                             CS80CMD_SCMD, &sc->sc_ioc, sizeof(sc->sc_ioc));
  604                         break;
  605                 }
  606         } else {
  607 mustio:
  608                 if ((bp->b_flags & B_READ) &&
  609                     sc->sc_flags & (CTF_BEOF|CTF_EOT)) {
  610                         DPRINTF(CDB_FILES, ("ctstart: before %x\n",
  611                                     sc->sc_flags));
  612                         if (sc->sc_flags & CTF_BEOF) {
  613                                 sc->sc_flags &= ~CTF_BEOF;
  614                                 sc->sc_flags |= CTF_AEOF;
  615                                 DPRINTF(CDB_FILES, ("ctstart: after %x\n",
  616                                     sc->sc_flags));
  617                         }
  618                         bp->b_resid = bp->b_bcount;
  619                         ctdone(sc, bp);
  620                         return;
  621                 }                       
  622                 sc->sc_flags |= CTF_IO;
  623                 sc->sc_ioc.unit = CS80CMD_SUNIT(sc->sc_punit);
  624                 sc->sc_ioc.saddr = CS80CMD_SADDR;
  625                 sc->sc_ioc.addr0 = 0;
  626                 sc->sc_ioc.addr = htobe32(sc->sc_blkno);
  627                 sc->sc_ioc.nop2 = CS80CMD_NOP;
  628                 sc->sc_ioc.slen = CS80CMD_SLEN;
  629                 sc->sc_ioc.len = htobe32(sc->sc_resid);
  630                 sc->sc_ioc.nop3 = CS80CMD_NOP;
  631                 if (bp->b_flags & B_READ)
  632                         sc->sc_ioc.cmd = CS80CMD_READ;
  633                 else {
  634                         sc->sc_ioc.cmd = CS80CMD_WRITE;
  635                         sc->sc_flags |= (CTF_WRT | CTF_WRTTN);
  636                 }
  637                 (void) cs80send(sc->sc_dev.dv_parent, slave, punit, 
  638                     CS80CMD_SCMD, &sc->sc_ioc, sizeof(sc->sc_ioc));
  639         }
  640         gpibawait(sc->sc_ic);
  641 }
  642 
  643 /*
  644  * Hideous grue to handle EOF/EOT (mostly for reads)
  645  */
  646 void
  647 cteof(sc, bp)
  648         struct ct_softc *sc;
  649         struct buf *bp;
  650 {
  651         long blks;
  652 
  653         /*
  654          * EOT on a write is an error.
  655          */
  656         if ((bp->b_flags & B_READ) == 0) {
  657                 bp->b_resid = bp->b_bcount;
  658                 bp->b_flags |= B_ERROR;
  659                 bp->b_error = ENOSPC;
  660                 sc->sc_flags |= CTF_EOT;
  661                 return;
  662         }
  663         /*
  664          * Use returned block position to determine how many blocks
  665          * we really read and update b_resid.
  666          */
  667         blks = sc->sc_stat.c_blk - sc->sc_blkno - 1;
  668         DPRINTF(CDB_FILES, ("cteof: bc %ld oblk %d nblk %d read %ld, resid %ld\n",
  669             bp->b_bcount, sc->sc_blkno, sc->sc_stat.c_blk,
  670             blks, bp->b_bcount - CTKTOB(blks)));
  671         if (blks == -1) { /* 9145 on EOF does not change sc_stat.c_blk */
  672                 blks = 0;
  673                 sc->sc_blkno++;
  674         }
  675         else {
  676                 sc->sc_blkno = sc->sc_stat.c_blk;
  677         }
  678         bp->b_resid = bp->b_bcount - CTKTOB(blks);
  679         /*
  680          * If we are at physical EOV or were after an EOF,
  681          * we are now at logical EOT.
  682          */
  683         if ((sc->sc_stat.c_aef & AEF_EOV) ||
  684             (sc->sc_flags & CTF_AEOF)) {
  685                 sc->sc_flags |= CTF_EOT;
  686                 sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF);
  687         }
  688         /*
  689          * If we were before an EOF or we have just completed a FSF,
  690          * we are now after EOF.
  691          */
  692         else if ((sc->sc_flags & CTF_BEOF) ||
  693                  ((sc->sc_flags & CTF_CMD) && sc->sc_cmd == MTFSF)) {
  694                 sc->sc_flags |= CTF_AEOF;
  695                 sc->sc_flags &= ~CTF_BEOF;
  696         }
  697         /*
  698          * Otherwise if we read something we are now before EOF
  699          * (and no longer after EOF).
  700          */
  701         else if (blks) {
  702                 sc->sc_flags |= CTF_BEOF;
  703                 sc->sc_flags &= ~CTF_AEOF;
  704         }
  705         /*
  706          * Finally, if we didn't read anything we just passed an EOF
  707          */
  708         else
  709                 sc->sc_flags |= CTF_AEOF;
  710         DPRINTF(CDB_FILES, ("cteof: leaving flags %x\n", sc->sc_flags));
  711 }
  712 
  713 
  714 void
  715 ctcallback(v, action)
  716         void *v;
  717         int action;
  718 {
  719         struct ct_softc *sc = v;
  720 
  721         DPRINTF(CDB_FOLLOW, ("ctcallback: v=%p, action=%d\n", v, action));
  722 
  723         switch (action) {       
  724         case GPIBCBF_START:
  725                 ctstart(sc);
  726                 break;
  727         case GPIBCBF_INTR:
  728                 ctintr(sc);
  729                 break;
  730 #ifdef DEBUG
  731         default:
  732                 DPRINTF(CDB_FAIL, ("ctcallback: unknown action %d\n", action));
  733                 break;
  734 #endif
  735         }
  736 }
  737 
  738 void
  739 ctintr(sc)
  740         struct ct_softc *sc;
  741 {
  742         struct buf *bp;
  743         u_int8_t stat;
  744         int slave, punit;
  745         int dir;
  746 
  747         slave = sc->sc_slave;
  748         punit = sc->sc_punit;
  749 
  750         bp = BUFQ_PEEK(&sc->sc_tab);
  751         if (bp == NULL) {
  752                 printf("%s: bp == NULL\n", sc->sc_dev.dv_xname);
  753                 return;
  754         }
  755         if (sc->sc_flags & CTF_IO) {
  756                 sc->sc_flags &= ~CTF_IO;
  757                 dir = (bp->b_flags & B_READ ? GPIB_READ : GPIB_WRITE);
  758                 gpibxfer(sc->sc_ic, slave, CS80CMD_EXEC, sc->sc_addr,
  759                     sc->sc_resid, dir, dir == GPIB_READ);
  760                 return;
  761         }
  762         if ((sc->sc_flags & CTF_STATWAIT) == 0) {
  763                 if (gpibpptest(sc->sc_ic, slave) == 0) {
  764                         sc->sc_flags |= CTF_STATWAIT;
  765                         gpibawait(sc->sc_ic);
  766                         return;
  767                 }
  768         } else
  769                 sc->sc_flags &= ~CTF_STATWAIT;
  770         (void) gpibrecv(sc->sc_ic, slave, CS80CMD_QSTAT, &stat, 1);
  771         DPRINTF(CDB_FILES, ("ctintr: before flags %x\n", sc->sc_flags));
  772         if (stat) {
  773                 sc->sc_rsc.unit = CS80CMD_SUNIT(punit);
  774                 sc->sc_rsc.cmd = CS80CMD_STATUS;
  775                 (void) gpibsend(sc->sc_ic, slave, CS80CMD_SCMD, &sc->sc_rsc,
  776                     sizeof(sc->sc_rsc));
  777                 (void) gpibrecv(sc->sc_ic, slave, CS80CMD_EXEC, &sc->sc_stat,
  778                     sizeof(sc->sc_stat));
  779                 (void) gpibrecv(sc->sc_ic, slave, CS80CMD_QSTAT, &stat, 1);
  780                 DPRINTF(CDB_FILES, ("ctintr: return stat 0x%x, A%x F%x blk %d\n",
  781                                stat, sc->sc_stat.c_aef,
  782                                sc->sc_stat.c_fef, sc->sc_stat.c_blk));
  783                 if (stat == 0) {
  784                         if (sc->sc_stat.c_aef & (AEF_EOF | AEF_EOV)) {
  785                                 cteof(sc, bp);
  786                                 ctaddeof(sc);
  787                                 goto done;
  788                         }
  789                         if (sc->sc_stat.c_fef & FEF_PF) {
  790                                 cs80reset(sc, slave, punit);
  791                                 ctstart(sc);
  792                                 return;
  793                         }
  794                         if (sc->sc_stat.c_fef & FEF_REXMT) {
  795                                 ctstart(sc);
  796                                 return;
  797                         }
  798                         if (sc->sc_stat.c_aef & 0x5800) {
  799                                 if (sc->sc_stat.c_aef & 0x4000)
  800                                         tprintf(sc->sc_tpr,
  801                                             "%s: uninitialized media\n",
  802                                             sc->sc_dev.dv_xname);
  803                                 if (sc->sc_stat.c_aef & 0x1000)
  804                                         tprintf(sc->sc_tpr,
  805                                             "%s: not ready\n",
  806                                             sc->sc_dev.dv_xname);
  807                                 if (sc->sc_stat.c_aef & 0x0800)
  808                                         tprintf(sc->sc_tpr,
  809                                             "%s: write protect\n",
  810                                             sc->sc_dev.dv_xname);
  811                         } else {
  812                                 printf("%s err: v%d u%d ru%d bn%d, ",
  813                                     sc->sc_dev.dv_xname,
  814                                     (sc->sc_stat.c_vu>>4)&0xF,
  815                                     sc->sc_stat.c_vu&0xF,
  816                                     sc->sc_stat.c_pend,
  817                                     sc->sc_stat.c_blk);
  818                                 printf("R0x%x F0x%x A0x%x I0x%x\n",
  819                                     sc->sc_stat.c_ref,
  820                                     sc->sc_stat.c_fef,
  821                                     sc->sc_stat.c_aef,
  822                                     sc->sc_stat.c_ief);
  823                         }
  824                 } else
  825                         printf("%s: request status failed\n",
  826                             sc->sc_dev.dv_xname);
  827                 bp->b_flags |= B_ERROR;
  828                 bp->b_error = EIO;
  829                 goto done;
  830         } else
  831                 bp->b_resid = 0;
  832         if (sc->sc_flags & CTF_CMD) {
  833                 switch (sc->sc_cmd) {
  834                 case MTFSF:
  835                         sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF);
  836                         sc->sc_blkno += CTBTOK(sc->sc_resid);
  837                         ctstart(sc);
  838                         return;
  839                 case MTBSF:
  840                         sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF|CTF_EOT);
  841                         break;
  842                 case MTBSR:
  843                         sc->sc_flags &= ~CTF_BEOF;
  844                         if (sc->sc_flags & CTF_EOT) {
  845                                 sc->sc_flags |= CTF_AEOF;
  846                                 sc->sc_flags &= ~CTF_EOT;
  847                         } else if (sc->sc_flags & CTF_AEOF) {
  848                                 sc->sc_flags |= CTF_BEOF;
  849                                 sc->sc_flags &= ~CTF_AEOF;
  850                         }
  851                         break;
  852                 case MTWEOF:
  853                         sc->sc_flags &= ~CTF_BEOF;
  854                         if (sc->sc_flags & (CTF_AEOF|CTF_EOT)) {
  855                                 sc->sc_flags |= CTF_EOT;
  856                                 sc->sc_flags &= ~CTF_AEOF;
  857                         } else
  858                                 sc->sc_flags |= CTF_AEOF;
  859                         break;
  860                 case MTREW:
  861                 case MTOFFL:
  862                         sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF|CTF_EOT);
  863                         break;
  864                 }
  865         } else {
  866                 sc->sc_flags &= ~CTF_AEOF;
  867                 sc->sc_blkno += CTBTOK(sc->sc_resid);
  868         }
  869 done:
  870         DPRINTF(CDB_FILES, ("ctintr: after flags %x\n", sc->sc_flags));
  871         ctdone(sc, bp);
  872 }
  873 
  874 void
  875 ctdone(sc, bp)
  876         struct ct_softc *sc;
  877         struct buf *bp;
  878 {
  879 
  880         (void)BUFQ_GET(&sc->sc_tab);
  881         biodone(bp);
  882         gpibrelease(sc->sc_ic, sc->sc_hdl);
  883         if (BUFQ_PEEK(&sc->sc_tab) == NULL) {
  884                 sc->sc_active = 0;
  885                 return;
  886         }
  887         ctustart(sc);
  888 }
  889 
  890 int
  891 ctread(dev, uio, flags)
  892         dev_t dev;
  893         struct uio *uio;
  894         int flags;
  895 {
  896         return (physio(ctstrategy, NULL, dev, B_READ, minphys, uio));
  897 }
  898 
  899 int
  900 ctwrite(dev, uio, flags)
  901         dev_t dev;
  902         struct uio *uio;
  903         int flags;
  904 {
  905         /* XXX: check for hardware write-protect? */
  906         return (physio(ctstrategy, NULL, dev, B_WRITE, minphys, uio));
  907 }
  908 
  909 /*ARGSUSED*/
  910 int
  911 ctioctl(dev, cmd, data, flag, p)
  912         dev_t dev;
  913         u_long cmd;
  914         int flag;
  915         caddr_t data;
  916         struct proc *p;
  917 {
  918         struct mtop *op;
  919         int cnt;
  920 
  921         switch (cmd) {
  922 
  923         case MTIOCTOP:
  924                 op = (struct mtop *)data;
  925                 switch(op->mt_op) {
  926 
  927                 case MTWEOF:
  928                 case MTFSF:
  929                 case MTBSR:
  930                 case MTBSF:
  931                 case MTFSR:
  932                         cnt = op->mt_count;
  933                         break;
  934 
  935                 case MTREW:
  936                 case MTOFFL:
  937                         cnt = 1;
  938                         break;
  939 
  940                 default:
  941                         return (EINVAL);
  942                 }
  943                 ctcommand(dev, op->mt_op, cnt);
  944                 break;
  945 
  946         case MTIOCGET:
  947                 break;
  948 
  949         default:
  950                 return (EINVAL);
  951         }
  952         return (0);
  953 }
  954 
  955 void
  956 ctaddeof(sc)
  957         struct ct_softc *sc;
  958 {
  959 
  960         if (sc->sc_eofp == EOFS - 1)
  961                 sc->sc_eofs[EOFS - 1]++;
  962         else {
  963                 sc->sc_eofp++;
  964                 if (sc->sc_eofp == EOFS - 1)
  965                         sc->sc_eofs[EOFS - 1] = EOFS;
  966                 else
  967                         /* save blkno */
  968                         sc->sc_eofs[sc->sc_eofp] = sc->sc_blkno - 1;
  969         }
  970         DPRINTF(CDB_BSF, ("%s: add eof pos %d blk %d\n",
  971                        sc->sc_dev.dv_xname, sc->sc_eofp,
  972                        sc->sc_eofs[sc->sc_eofp]));
  973 }

Cache object: d61df2d58d0427e5509d695ca5faaa07


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.