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/rd.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: rd.c,v 1.2 2003/08/07 16:30:56 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  * CS80/SS80 disk driver
  118  */
  119 
  120 #include <sys/cdefs.h>
  121 __KERNEL_RCSID(0, "$NetBSD: rd.c,v 1.2 2003/08/07 16:30:56 agc Exp $");
  122 
  123 #include "rnd.h"
  124 
  125 #include <sys/param.h>
  126 #include <sys/systm.h>
  127 #include <sys/buf.h>
  128 #include <sys/callout.h>
  129 #include <sys/conf.h>
  130 #include <sys/device.h>
  131 #include <sys/disk.h>
  132 #include <sys/disklabel.h>
  133 #include <sys/endian.h>
  134 #include <sys/fcntl.h>
  135 #include <sys/ioctl.h>
  136 #include <sys/proc.h>
  137 #include <sys/stat.h>
  138 
  139 #if NRND > 0
  140 #include <sys/rnd.h>
  141 #endif
  142 
  143 #include <dev/gpib/gpibvar.h>
  144 #include <dev/gpib/cs80busvar.h>
  145 
  146 #include <dev/gpib/rdreg.h>
  147 
  148 #ifdef DEBUG
  149 int     rddebug = 0xff;
  150 #define RDB_FOLLOW      0x01
  151 #define RDB_STATUS      0x02
  152 #define RDB_IDENT       0x04
  153 #define RDB_IO          0x08
  154 #define RDB_ASYNC       0x10
  155 #define RDB_ERROR       0x80
  156 #define DPRINTF(mask, str)      if (rddebug & (mask)) printf str
  157 #else
  158 #define DPRINTF(mask, str)      /* nothing */
  159 #endif
  160 
  161 struct  rd_softc {
  162         struct  device sc_dev;
  163         gpib_chipset_tag_t sc_ic;
  164         gpib_handle_t sc_hdl;
  165 
  166         struct  disk sc_dk;
  167 
  168         int     sc_slave;               /* GPIB slave */
  169         int     sc_punit;               /* physical unit on slave */
  170 
  171         int     sc_flags;
  172 #define RDF_ALIVE       0x01
  173 #define RDF_SEEK        0x02
  174 #define RDF_SWAIT       0x04
  175 #define RDF_OPENING     0x08
  176 #define RDF_CLOSING     0x10
  177 #define RDF_WANTED      0x20
  178 #define RDF_WLABEL      0x40
  179 
  180         u_int16_t sc_type;
  181         u_int8_t *sc_addr;
  182         int     sc_resid;
  183         struct  rd_iocmd sc_ioc;
  184         struct  bufq_state sc_tab;
  185         int     sc_active;
  186         int     sc_errcnt;
  187 
  188         struct  callout sc_restart_ch;
  189 
  190 #if NRND > 0
  191         rndsource_element_t rnd_source;
  192 #endif
  193 };
  194 
  195 #define RDUNIT(dev)                     DISKUNIT(dev)
  196 #define RDPART(dev)                     DISKPART(dev)
  197 #define RDMAKEDEV(maj, unit, part)      MAKEDISKDEV(maj, unit, part)
  198 #define RDLABELDEV(dev) (RDMAKEDEV(major(dev), RDUNIT(dev), RAW_PART))
  199 
  200 #define RDRETRY         5
  201 #define RDWAITC         1       /* min time for timeout in seconds */
  202 
  203 int     rderrthresh = RDRETRY-1;        /* when to start reporting errors */
  204 
  205 /*
  206  * Misc. HW description, indexed by sc_type.
  207  * Used for mapping 256-byte sectors for 512-byte sectors
  208  */
  209 const struct rdidentinfo {
  210         u_int16_t ri_hwid;              /* 2 byte HW id */
  211         u_int16_t ri_maxunum;           /* maximum allowed unit number */
  212         char    *ri_desc;               /* drive type description */
  213         int     ri_nbpt;                /* DEV_BSIZE blocks per track */
  214         int     ri_ntpc;                /* tracks per cylinder */
  215         int     ri_ncyl;                /* cylinders per unit */
  216         int     ri_nblocks;             /* DEV_BSIZE blocks on disk */
  217 } rdidentinfo[] = {
  218         { RD7946AID,    0,      "7945A",        NRD7945ABPT,
  219           NRD7945ATRK,  968,     108416 },
  220 
  221         { RD9134DID,    1,      "9134D",        NRD9134DBPT,
  222           NRD9134DTRK,  303,      29088 },
  223 
  224         { RD9134LID,    1,      "9122S",        NRD9122SBPT,
  225           NRD9122STRK,  77,        1232 },
  226 
  227         { RD7912PID,    0,      "7912P",        NRD7912PBPT,
  228           NRD7912PTRK,  572,     128128 },
  229 
  230         { RD7914PID,    0,      "7914P",        NRD7914PBPT,
  231           NRD7914PTRK,  1152,    258048 },
  232 
  233         { RD7958AID,    0,      "7958A",        NRD7958ABPT,
  234           NRD7958ATRK,  1013,    255276 },
  235 
  236         { RD7957AID,    0,      "7957A",        NRD7957ABPT,
  237           NRD7957ATRK,  1036,    159544 },
  238 
  239         { RD7933HID,    0,      "7933H",        NRD7933HBPT,
  240           NRD7933HTRK,  1321,    789958 },
  241 
  242         { RD9134LID,    1,      "9134L",        NRD9134LBPT,
  243           NRD9134LTRK,  973,      77840 },
  244 
  245         { RD7936HID,    0,      "7936H",        NRD7936HBPT,
  246           NRD7936HTRK,  698,     600978 },
  247 
  248         { RD7937HID,    0,      "7937H",        NRD7937HBPT,
  249           NRD7937HTRK,  698,    1116102 },
  250 
  251         { RD7914CTID,   0,      "7914CT",       NRD7914PBPT,
  252           NRD7914PTRK,  1152,    258048 },
  253 
  254         { RD7946AID,    0,      "7946A",        NRD7945ABPT,
  255           NRD7945ATRK,  968,     108416 },
  256 
  257         { RD9134LID,    1,      "9122D",        NRD9122SBPT,
  258           NRD9122STRK,  77,        1232 },
  259 
  260         { RD7957BID,    0,      "7957B",        NRD7957BBPT,
  261           NRD7957BTRK,  1269,    159894 },
  262 
  263         { RD7958BID,    0,      "7958B",        NRD7958BBPT,
  264           NRD7958BTRK,  786,     297108 },
  265 
  266         { RD7959BID,    0,      "7959B",        NRD7959BBPT,
  267           NRD7959BTRK,  1572,    594216 },
  268 
  269         { RD2200AID,    0,      "2200A",        NRD2200ABPT,
  270           NRD2200ATRK,  1449,    654948 },
  271 
  272         { RD2203AID,    0,      "2203A",        NRD2203ABPT,
  273           NRD2203ATRK,  1449,   1309896 }
  274 };
  275 int numrdidentinfo = sizeof(rdidentinfo) / sizeof(rdidentinfo[0]);
  276 
  277 int     rdlookup(int, int, int);
  278 int     rdgetinfo(struct rd_softc *);
  279 void    rdrestart(void *);
  280 struct buf *rdfinish(struct rd_softc *, struct buf *);
  281 
  282 void    rdgetcompatlabel(struct rd_softc *, struct disklabel *);
  283 void    rdgetdefaultlabel(struct rd_softc *, struct disklabel *);
  284 void    rdrestart(void *);
  285 void    rdustart(struct rd_softc *);
  286 struct buf *rdfinish(struct rd_softc *, struct buf *);
  287 void    rdcallback(void *, int);
  288 void    rdstart(struct rd_softc *);
  289 void    rdintr(struct rd_softc *);
  290 int     rderror(struct rd_softc *);
  291 
  292 int     rdmatch(struct device *, struct cfdata *, void *);
  293 void    rdattach(struct device *, struct device *, void *);
  294 
  295 CFATTACH_DECL(rd, sizeof(struct rd_softc),
  296         rdmatch, rdattach, NULL, NULL);
  297 
  298 
  299 dev_type_open(rdopen);
  300 dev_type_close(rdclose);
  301 dev_type_read(rdread);
  302 dev_type_write(rdwrite);
  303 dev_type_ioctl(rdioctl);
  304 dev_type_strategy(rdstrategy);
  305 dev_type_dump(rddump);
  306 dev_type_size(rdsize);
  307 
  308 const struct bdevsw rd_bdevsw = {
  309         rdopen, rdclose, rdstrategy, rdioctl, rddump, rdsize, D_DISK
  310 };
  311 
  312 const struct cdevsw rd_cdevsw = {
  313         rdopen, rdclose, rdread, rdwrite, rdioctl,
  314         nostop, notty, nopoll, nommap, nokqfilter, D_DISK
  315 };
  316 
  317 extern struct cfdriver rd_cd;
  318 
  319 int
  320 rdlookup(id, slave, punit)
  321         int id;
  322         int slave;
  323         int punit;
  324 {
  325         int i;
  326 
  327         for (i = 0; i < numrdidentinfo; i++) {
  328                 if (rdidentinfo[i].ri_hwid == id)
  329                         break;
  330         }
  331         if (i == numrdidentinfo || punit > rdidentinfo[i].ri_maxunum)
  332                 return (-1);
  333         return (i);
  334 }
  335 
  336 int
  337 rdmatch(parent, match, aux)
  338         struct device *parent;
  339         struct cfdata *match;
  340         void *aux;
  341 {
  342         struct cs80bus_attach_args *ca = aux;
  343 
  344         if (rdlookup(ca->ca_id, ca->ca_slave, ca->ca_punit) < 0)
  345                 return (0);
  346         return (1);
  347 }
  348 
  349 void
  350 rdattach(parent, self, aux)
  351         struct device *parent, *self;
  352         void *aux;
  353 {
  354         struct rd_softc *sc = (struct rd_softc *)self;
  355         struct cs80bus_attach_args *ca = aux;
  356         struct cs80_description csd;
  357         char name[7];
  358         int type, i, n;
  359 
  360         sc->sc_ic = ca->ca_ic;
  361         sc->sc_slave = ca->ca_slave;
  362         sc->sc_punit = ca->ca_punit;
  363 
  364         if ((type = rdlookup(ca->ca_id, ca->ca_slave, ca->ca_punit)) < 0)
  365                 return;
  366 
  367         if (cs80reset(parent, sc->sc_slave, sc->sc_punit)) {
  368                 printf("\n%s: can't reset device\n", sc->sc_dev.dv_xname);
  369                 return;
  370         }
  371 
  372         if (cs80describe(parent, sc->sc_slave, sc->sc_punit, &csd)) {
  373                 printf("\n%s: didn't respond to describe command\n",
  374                     sc->sc_dev.dv_xname);
  375                 return;
  376         }
  377         memset(name, 0, sizeof(name)); 
  378         for (i=0, n=0; i<3; i++) {
  379                 name[n++] = (csd.d_name[i] >> 4) + '';
  380                 name[n++] = (csd.d_name[i] & 0x0f) + '';
  381         }
  382 
  383 #ifdef DEBUG
  384         if (rddebug & RDB_IDENT) {
  385                 printf("\n%s: name: ('%s')\n",
  386                     sc->sc_dev.dv_xname, name);
  387                 printf("  iuw %x, maxxfr %d, ctype %d\n",
  388                     csd.d_iuw, csd.d_cmaxxfr, csd.d_ctype);
  389                 printf("  utype %d, bps %d, blkbuf %d, burst %d, blktime %d\n",
  390                     csd.d_utype, csd.d_sectsize,
  391                     csd.d_blkbuf, csd.d_burstsize, csd.d_blocktime);
  392                 printf("  avxfr %d, ort %d, atp %d, maxint %d, fv %x, rv %x\n",
  393                     csd.d_uavexfr, csd.d_retry, csd.d_access,
  394                     csd.d_maxint, csd.d_fvbyte, csd.d_rvbyte);
  395                 printf("  maxcyl/head/sect %d/%d/%d, maxvsect %d, inter %d\n",
  396                     csd.d_maxcylhead >> 8, csd.d_maxcylhead & 0xff,
  397                     csd.d_maxsect, csd.d_maxvsectl, csd.d_interleave);
  398                 printf("%s", sc->sc_dev.dv_xname);
  399         }
  400 #endif
  401 
  402         /*
  403          * Take care of a couple of anomolies:
  404          * 1. 7945A and 7946A both return same HW id
  405          * 2. 9122S and 9134D both return same HW id
  406          * 3. 9122D and 9134L both return same HW id
  407          */
  408         switch (ca->ca_id) {
  409         case RD7946AID:
  410                 if (memcmp(name, "079450", 6) == 0)
  411                         type = RD7945A;
  412                 else
  413                         type = RD7946A;
  414                 break;
  415 
  416         case RD9134LID:
  417                 if (memcmp(name, "091340", 6) == 0)
  418                         type = RD9134L;
  419                 else
  420                         type = RD9122D;
  421                 break;
  422 
  423         case RD9134DID:
  424                 if (memcmp(name, "091220", 6) == 0)
  425                         type = RD9122S;
  426                 else
  427                         type = RD9134D;
  428                 break;
  429         }
  430 
  431         sc->sc_type = type;
  432 
  433         /*
  434          * XXX We use DEV_BSIZE instead of the sector size value pulled
  435          * XXX off the driver because all of this code assumes 512 byte
  436          * XXX blocks.  ICK!
  437          */
  438         printf(": %s\n", rdidentinfo[type].ri_desc);
  439         printf("%s: %d cylinders, %d heads, %d blocks, %d bytes/block\n",
  440             sc->sc_dev.dv_xname, rdidentinfo[type].ri_ncyl,
  441             rdidentinfo[type].ri_ntpc, rdidentinfo[type].ri_nblocks,
  442             DEV_BSIZE);
  443 
  444         bufq_alloc(&sc->sc_tab, BUFQ_FCFS);
  445 
  446         /*
  447          * Initialize and attach the disk structure.
  448          */
  449         memset(&sc->sc_dk, 0, sizeof(sc->sc_dk));
  450         sc->sc_dk.dk_name = sc->sc_dev.dv_xname;
  451         disk_attach(&sc->sc_dk);
  452 
  453         callout_init(&sc->sc_restart_ch);
  454 
  455         if (gpibregister(sc->sc_ic, sc->sc_slave, rdcallback, sc,
  456             &sc->sc_hdl)) {
  457                 printf("%s: can't register callback\n", sc->sc_dev.dv_xname);
  458                 return;
  459         }
  460 
  461         sc->sc_flags = RDF_ALIVE;
  462 #ifdef DEBUG
  463         /* always report errors */
  464         if (rddebug & RDB_ERROR)
  465                 rderrthresh = 0;
  466 #endif
  467 #if NRND > 0
  468         /*
  469          * attach the device into the random source list
  470          */
  471         rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
  472                           RND_TYPE_DISK, 0);
  473 #endif
  474 }
  475 
  476 /*
  477  * Read or constuct a disklabel
  478  */
  479 int
  480 rdgetinfo(sc)
  481         struct rd_softc *sc;
  482 {
  483         struct disklabel *lp = sc->sc_dk.dk_label;
  484         struct partition *pi;
  485         const char *msg;
  486 
  487         memset(sc->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel));
  488 
  489         rdgetdefaultlabel(sc, lp);
  490 
  491         /*
  492          * Call the generic disklabel extraction routine
  493          */
  494         msg = readdisklabel(RDMAKEDEV(0, sc->sc_dev.dv_unit, RAW_PART),
  495             rdstrategy, lp, NULL);
  496         if (msg == NULL)
  497                 return (0);
  498 
  499         pi = lp->d_partitions;
  500         printf("%s: WARNING: %s, ", sc->sc_dev.dv_xname, msg);
  501 #ifdef COMPAT_NOLABEL
  502         printf("using old default partitioning\n");
  503         rdgetcompatlabel(sc, lp);
  504 #else
  505         printf("defining '%c' partition as entire disk\n", 'a' + RAW_PART);
  506         pi[RAW_PART].p_size = rdidentinfo[sc->sc_type].ri_nblocks;
  507         lp->d_npartitions = RAW_PART+1;
  508         pi[0].p_size = 0;
  509 #endif
  510         return (0);
  511 }
  512 
  513 int
  514 rdopen(dev, flags, mode, p)
  515         dev_t dev;
  516         int flags, mode;
  517         struct proc *p;
  518 {
  519         struct rd_softc *sc;
  520         int error, mask, part;
  521 
  522         sc = device_lookup(&rd_cd, RDUNIT(dev));
  523         if (sc == NULL || (sc->sc_flags & RDF_ALIVE) ==0)
  524                 return (ENXIO);
  525 
  526         /*
  527          * Wait for any pending opens/closes to complete
  528          */
  529         while (sc->sc_flags & (RDF_OPENING | RDF_CLOSING))
  530                 (void) tsleep(sc, PRIBIO, "rdopen", 0);
  531 
  532         /*
  533          * On first open, get label and partition info.
  534          * We may block reading the label, so be careful
  535          * to stop any other opens.
  536          */
  537         if (sc->sc_dk.dk_openmask == 0) {
  538                 sc->sc_flags |= RDF_OPENING;
  539                 error = rdgetinfo(sc);
  540                 sc->sc_flags &= ~RDF_OPENING;
  541                 wakeup((caddr_t)sc);
  542                 if (error)
  543                         return (error);
  544         }
  545 
  546         part = RDPART(dev);
  547         mask = 1 << part;
  548 
  549         /* Check that the partition exists. */
  550         if (part != RAW_PART && (part > sc->sc_dk.dk_label->d_npartitions ||
  551             sc->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED))
  552                 return (ENXIO);
  553 
  554         /* Ensure only one open at a time. */
  555         switch (mode) {
  556         case S_IFCHR:
  557                 sc->sc_dk.dk_copenmask |= mask;
  558                 break;
  559         case S_IFBLK:
  560                 sc->sc_dk.dk_bopenmask |= mask;
  561                 break;
  562         }
  563         sc->sc_dk.dk_openmask =
  564             sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;
  565 
  566         return (0);
  567 }
  568 
  569 int
  570 rdclose(dev, flag, mode, p)
  571         dev_t dev;
  572         int flag, mode;
  573         struct proc *p;
  574 {
  575         struct rd_softc *sc;
  576         struct disk *dk;
  577         int mask, s;
  578 
  579         sc = device_lookup(&rd_cd, RDUNIT(dev));
  580         if (sc == NULL)
  581                 return (ENXIO);
  582 
  583         dk = &sc->sc_dk;
  584 
  585         mask = 1 << RDPART(dev);
  586         if (mode == S_IFCHR)
  587                 dk->dk_copenmask &= ~mask;
  588         else
  589                 dk->dk_bopenmask &= ~mask;
  590         dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask;
  591         /*
  592          * On last close, we wait for all activity to cease since
  593          * the label/parition info will become invalid.  Since we
  594          * might sleep, we must block any opens while we are here.
  595          * Note we don't have to about other closes since we know
  596          * we are the last one.
  597          */
  598         if (dk->dk_openmask == 0) {
  599                 sc->sc_flags |= RDF_CLOSING;
  600                 s = splbio();
  601                 while (sc->sc_active) {
  602                         sc->sc_flags |= RDF_WANTED;
  603                         (void) tsleep(&sc->sc_tab, PRIBIO, "rdclose", 0);
  604                 }
  605                 splx(s);
  606                 sc->sc_flags &= ~(RDF_CLOSING | RDF_WLABEL);
  607                 wakeup((caddr_t)sc);
  608         }
  609         return (0);
  610 }
  611 
  612 void
  613 rdstrategy(bp)
  614         struct buf *bp;
  615 {
  616         struct rd_softc *sc;
  617         struct partition *pinfo;
  618         daddr_t bn;
  619         int sz, s;
  620         int offset;
  621 
  622         sc = device_lookup(&rd_cd, RDUNIT(bp->b_dev));
  623 
  624         DPRINTF(RDB_FOLLOW,
  625             ("rdstrategy(%p): dev %x, bn %" PRId64 ", bcount %ld, %c\n",
  626             bp, bp->b_dev, bp->b_blkno, bp->b_bcount,
  627             (bp->b_flags & B_READ) ? 'R' : 'W'));
  628 
  629         bn = bp->b_blkno;
  630         sz = howmany(bp->b_bcount, DEV_BSIZE);
  631         pinfo = &sc->sc_dk.dk_label->d_partitions[RDPART(bp->b_dev)];
  632 
  633         /* Don't perform partition translation on RAW_PART. */
  634         offset = (RDPART(bp->b_dev) == RAW_PART) ? 0 : pinfo->p_offset;
  635 
  636         if (RDPART(bp->b_dev) != RAW_PART) {
  637                 /*
  638                  * XXX This block of code belongs in
  639                  * XXX bounds_check_with_label()
  640                  */
  641 
  642                 if (bn < 0 || bn + sz > pinfo->p_size) {
  643                         sz = pinfo->p_size - bn;
  644                         if (sz == 0) {
  645                                 bp->b_resid = bp->b_bcount;
  646                                 goto done;
  647                         }
  648                         if (sz < 0) {
  649                                 bp->b_error = EINVAL;
  650                                 goto bad;
  651                         }
  652                         bp->b_bcount = dbtob(sz);
  653                 }
  654                 /*
  655                  * Check for write to write protected label
  656                  */
  657                 if (bn + offset <= LABELSECTOR &&
  658 #if LABELSECTOR != 0
  659                     bn + offset + sz > LABELSECTOR &&
  660 #endif
  661                     !(bp->b_flags & B_READ) && !(sc->sc_flags & RDF_WLABEL)) {
  662                         bp->b_error = EROFS;
  663                         goto bad;
  664                 }
  665         }
  666         bp->b_rawblkno = bn + offset;
  667         s = splbio();
  668         BUFQ_PUT(&sc->sc_tab, bp);
  669         if (sc->sc_active == 0) {
  670                 sc->sc_active = 1;
  671                 rdustart(sc);
  672         }
  673         splx(s);
  674         return;
  675 bad:
  676         bp->b_flags |= B_ERROR;
  677 done:
  678         biodone(bp);
  679 }
  680 
  681 /*
  682  * Called from timeout() when handling maintenance releases
  683  * callout from timeouts
  684  */
  685 void
  686 rdrestart(arg)
  687         void *arg;
  688 {
  689         int s = splbio();
  690         rdustart((struct rd_softc *)arg);
  691         splx(s);
  692 }
  693 
  694 
  695 /* called by rdstrategy() to start a block transfer */
  696 /* called by rdrestart() when handingly timeouts */
  697 /* called by rdintr() */
  698 void
  699 rdustart(sc)
  700         struct rd_softc *sc;
  701 {
  702         struct buf *bp;
  703 
  704         bp = BUFQ_PEEK(&sc->sc_tab);
  705         sc->sc_addr = bp->b_data;
  706         sc->sc_resid = bp->b_bcount;
  707         if (gpibrequest(sc->sc_ic, sc->sc_hdl))
  708                 rdstart(sc);
  709 }
  710 
  711 struct buf *
  712 rdfinish(sc, bp)
  713         struct rd_softc *sc;
  714         struct buf *bp;
  715 {
  716 
  717         sc->sc_errcnt = 0;
  718         (void)BUFQ_GET(&sc->sc_tab);
  719         bp->b_resid = 0;
  720         biodone(bp);
  721         gpibrelease(sc->sc_ic, sc->sc_hdl);
  722         if ((bp = BUFQ_PEEK(&sc->sc_tab)) != NULL)
  723                 return (bp);
  724         sc->sc_active = 0;
  725         if (sc->sc_flags & RDF_WANTED) {
  726                 sc->sc_flags &= ~RDF_WANTED;
  727                 wakeup((caddr_t)&sc->sc_tab);
  728         }
  729         return (NULL);
  730 }
  731 
  732 void
  733 rdcallback(v, action)
  734         void *v;
  735         int action;
  736 {
  737         struct rd_softc *sc = v;
  738 
  739         DPRINTF(RDB_FOLLOW, ("rdcallback: v=%p, action=%d\n", v, action));
  740 
  741         switch (action) {
  742         case GPIBCBF_START:
  743                 rdstart(sc);
  744                 break;
  745         case GPIBCBF_INTR:
  746                 rdintr(sc);
  747                 break;
  748 #ifdef DEBUG
  749         default:
  750                 DPRINTF(RDB_ERROR, ("rdcallback: unknown action %d\n",
  751                     action));
  752                 break;
  753 #endif
  754         }
  755 }
  756 
  757 
  758 /* called from rdustart() to start a transfer */
  759 /* called from gpib interface as the initiator */
  760 void
  761 rdstart(sc)
  762         struct rd_softc *sc;
  763 {
  764         struct buf *bp = BUFQ_PEEK(&sc->sc_tab);
  765         int part, slave, punit;
  766 
  767         slave = sc->sc_slave;
  768         punit = sc->sc_punit;
  769 
  770         DPRINTF(RDB_FOLLOW, ("rdstart(%s): bp %p, %c\n",
  771             sc->sc_dev.dv_xname, bp, (bp->b_flags & B_READ) ? 'R' : 'W'));
  772 
  773 again:
  774 
  775         part = RDPART(bp->b_dev);
  776         sc->sc_flags |= RDF_SEEK;
  777         sc->sc_ioc.c_unit = CS80CMD_SUNIT(punit);
  778         sc->sc_ioc.c_volume = CS80CMD_SVOL(0);
  779         sc->sc_ioc.c_saddr = CS80CMD_SADDR;
  780         sc->sc_ioc.c_hiaddr = htobe16(0);
  781         sc->sc_ioc.c_addr = htobe32(RDBTOS(bp->b_rawblkno));
  782         sc->sc_ioc.c_nop2 = CS80CMD_NOP;
  783         sc->sc_ioc.c_slen = CS80CMD_SLEN;
  784         sc->sc_ioc.c_len = htobe32(sc->sc_resid);
  785         sc->sc_ioc.c_cmd = bp->b_flags & B_READ ? CS80CMD_READ : CS80CMD_WRITE;
  786 
  787         if (gpibsend(sc->sc_ic, slave, CS80CMD_SCMD, &sc->sc_ioc.c_unit,
  788             sizeof(sc->sc_ioc)-1) == sizeof(sc->sc_ioc)-1) {
  789                 /* Instrumentation. */
  790                 disk_busy(&sc->sc_dk);
  791                 sc->sc_dk.dk_seek++;
  792                 gpibawait(sc->sc_ic);
  793                 return;
  794         }
  795         /*
  796          * Experience has shown that the gpibwait in this gpibsend will
  797          * occasionally timeout.  It appears to occur mostly on old 7914
  798          * drives with full maintenance tracks.  We should probably
  799          * integrate this with the backoff code in rderror.
  800          */
  801 
  802         DPRINTF(RDB_ERROR,
  803             ("rdstart: cmd %x adr %ul blk %" PRId64 " len %d ecnt %d\n",
  804             sc->sc_ioc.c_cmd, sc->sc_ioc.c_addr, bp->b_blkno, sc->sc_resid,
  805              sc->sc_errcnt));
  806 
  807         sc->sc_flags &= ~RDF_SEEK;
  808         cs80reset(sc->sc_dev.dv_parent, slave, punit);
  809         if (sc->sc_errcnt++ < RDRETRY)
  810                 goto again;
  811         printf("%s: rdstart err: cmd 0x%x sect %uld blk %" PRId64 " len %d\n",
  812                sc->sc_dev.dv_xname, sc->sc_ioc.c_cmd, sc->sc_ioc.c_addr,
  813                bp->b_blkno, sc->sc_resid);
  814         bp->b_flags |= B_ERROR;
  815         bp->b_error = EIO;
  816         bp = rdfinish(sc, bp);
  817         if (bp) {
  818                 sc->sc_addr = bp->b_data;
  819                 sc->sc_resid = bp->b_bcount;
  820                 if (gpibrequest(sc->sc_ic, sc->sc_hdl))
  821                         goto again;
  822         }
  823 }
  824 
  825 void
  826 rdintr(sc)
  827         struct rd_softc *sc;
  828 {
  829         struct buf *bp;
  830         u_int8_t stat = 13;     /* in case gpibrecv fails */
  831         int rv, dir, restart, slave;
  832 
  833         slave = sc->sc_slave;
  834         bp = BUFQ_PEEK(&sc->sc_tab);
  835 
  836         DPRINTF(RDB_FOLLOW, ("rdintr(%s): bp %p, %c, flags %x\n",
  837             sc->sc_dev.dv_xname, bp, (bp->b_flags & B_READ) ? 'R' : 'W',
  838             sc->sc_flags));
  839 
  840         disk_unbusy(&sc->sc_dk, (bp->b_bcount - bp->b_resid),
  841                 (bp->b_flags & B_READ));
  842 
  843         if (sc->sc_flags & RDF_SEEK) {
  844                 sc->sc_flags &= ~RDF_SEEK;
  845                 dir = (bp->b_flags & B_READ ? GPIB_READ : GPIB_WRITE);
  846                 gpibxfer(sc->sc_ic, slave, CS80CMD_EXEC, sc->sc_addr,
  847                     sc->sc_resid, dir, dir == GPIB_READ);
  848                 disk_busy(&sc->sc_dk);
  849                 return;
  850         }
  851         if ((sc->sc_flags & RDF_SWAIT) == 0) {
  852                 if (gpibpptest(sc->sc_ic, slave) == 0) {
  853                         /* Instrumentation. */
  854                         disk_busy(&sc->sc_dk);
  855                         sc->sc_flags |= RDF_SWAIT;
  856                         gpibawait(sc->sc_ic);
  857                         return;
  858                 }
  859         } else
  860                 sc->sc_flags &= ~RDF_SWAIT;
  861         rv = gpibrecv(sc->sc_ic, slave, CS80CMD_QSTAT, &stat, 1);
  862         if (rv != 1 || stat) {
  863                 DPRINTF(RDB_ERROR,
  864                     ("rdintr: receive failed (rv=%d) or bad stat %d\n", rv,
  865                      stat));
  866                 restart = rderror(sc);
  867                 if (sc->sc_errcnt++ < RDRETRY) {
  868                         if (restart)
  869                                 rdstart(sc);
  870                         return;
  871                 }
  872                 bp->b_flags |= B_ERROR;
  873                 bp->b_error = EIO;
  874         }
  875         if (rdfinish(sc, bp) != NULL)
  876                 rdustart(sc);
  877 #if NRND > 0
  878         rnd_add_uint32(&sc->rnd_source, bp->b_blkno);
  879 #endif
  880 }
  881 
  882 /*
  883  * Deal with errors.
  884  * Returns 1 if request should be restarted,
  885  * 0 if we should just quietly give up.
  886  */
  887 int
  888 rderror(sc)
  889         struct rd_softc *sc;
  890 {
  891         struct cs80_stat css;
  892         struct buf *bp;
  893         daddr_t hwbn, pbn;
  894 
  895         DPRINTF(RDB_FOLLOW, ("rderror: sc=%p\n", sc));
  896 
  897         if (cs80status(sc->sc_dev.dv_parent, sc->sc_slave,
  898             sc->sc_punit, &css)) {
  899                 cs80reset(sc->sc_dev.dv_parent, sc->sc_slave, sc->sc_punit);
  900                 return (1);
  901         }
  902 #ifdef DEBUG
  903         if (rddebug & RDB_ERROR) {                      /* status info */
  904                 printf("\n    volume: %d, unit: %d\n",
  905                        (css.c_vu>>4)&0xF, css.c_vu&0xF);
  906                 printf("    reject 0x%x\n", css.c_ref);
  907                 printf("    fault 0x%x\n", css.c_fef);
  908                 printf("    access 0x%x\n", css.c_aef);
  909                 printf("    info 0x%x\n", css.c_ief);
  910                 printf("    block,  P1-P10: ");
  911                 printf("0x%x", *(u_int32_t *)&css.c_raw[0]);
  912                 printf("0x%x", *(u_int32_t *)&css.c_raw[4]);
  913                 printf("0x%x\n", *(u_int16_t *)&css.c_raw[8]);
  914         }
  915 #endif
  916         if (css.c_fef & FEF_REXMT)
  917                 return (1);
  918         if (css.c_fef & FEF_PF) {
  919                 cs80reset(sc->sc_dev.dv_parent, sc->sc_slave, sc->sc_punit);
  920                 return (1);
  921         }
  922         /*
  923          * Unit requests release for internal maintenance.
  924          * We just delay awhile and try again later.  Use expontially
  925          * increasing backoff ala ethernet drivers since we don't really
  926          * know how long the maintenance will take.  With RDWAITC and
  927          * RDRETRY as defined, the range is 1 to 32 seconds.
  928          */
  929         if (css.c_fef & FEF_IMR) {
  930                 extern int hz;
  931                 int rdtimo = RDWAITC << sc->sc_errcnt;
  932                 DPRINTF(RDB_STATUS,
  933                     ("%s: internal maintenance, %d-second timeout\n",
  934                     sc->sc_dev.dv_xname, rdtimo));
  935                 gpibrelease(sc->sc_ic, sc->sc_hdl);
  936                 callout_reset(&sc->sc_restart_ch, rdtimo * hz, rdrestart, sc);
  937                 return (0);
  938         }
  939         /*
  940          * Only report error if we have reached the error reporting
  941          * threshhold.  By default, this will only report after the
  942          * retry limit has been exceeded.
  943          */
  944         if (sc->sc_errcnt < rderrthresh)
  945                 return (1);
  946 
  947         /*
  948          * First conjure up the block number at which the error occurred.
  949          */
  950         bp = BUFQ_PEEK(&sc->sc_tab);
  951         pbn = sc->sc_dk.dk_label->d_partitions[RDPART(bp->b_dev)].p_offset;
  952         if ((css.c_fef & FEF_CU) || (css.c_fef & FEF_DR) ||
  953             (css.c_ief & IEF_RRMASK)) {
  954                 /*
  955                  * Not all errors report a block number, just use b_blkno.
  956                  */
  957                 hwbn = RDBTOS(pbn + bp->b_blkno);
  958                 pbn = bp->b_blkno;
  959         } else {
  960                 hwbn = css.c_blk;
  961                 pbn = RDSTOB(hwbn) - pbn;
  962         }
  963 #ifdef DEBUG
  964         if (rddebug & RDB_ERROR) {                      /* status info */
  965                 printf("\n    volume: %d, unit: %d\n",
  966                        (css.c_vu>>4)&0xF, css.c_vu&0xF);
  967                 printf("    reject 0x%x\n", css.c_ref);
  968                 printf("    fault 0x%x\n", css.c_fef);
  969                 printf("    access 0x%x\n", css.c_aef);
  970                 printf("    info 0x%x\n", css.c_ief);
  971                 printf("    block,  P1-P10: ");
  972                 printf("    block: %" PRId64 ", P1-P10: ", hwbn);
  973                 printf("0x%x", *(u_int32_t *)&css.c_raw[0]);
  974                 printf("0x%x", *(u_int32_t *)&css.c_raw[4]);
  975                 printf("0x%x\n", *(u_int16_t *)&css.c_raw[8]);
  976         }
  977 #endif
  978 #ifdef DEBUG
  979         if (rddebug & RDB_ERROR) {                      /* command */
  980                 printf("    ioc: ");
  981                 printf("0x%x", *(u_int32_t *)&sc->sc_ioc.c_pad);
  982                 printf("0x%x", *(u_int16_t *)&sc->sc_ioc.c_hiaddr);
  983                 printf("0x%x", *(u_int32_t *)&sc->sc_ioc.c_addr);
  984                 printf("0x%x", *(u_int16_t *)&sc->sc_ioc.c_nop2);
  985                 printf("0x%x", *(u_int32_t *)&sc->sc_ioc.c_len);
  986                 printf("0x%x\n", *(u_int16_t *)&sc->sc_ioc.c_cmd);
  987                 return (1);
  988         }
  989 #endif
  990         /*
  991          * Now output a generic message suitable for badsect.
  992          * Note that we don't use harderr because it just prints
  993          * out b_blkno which is just the beginning block number
  994          * of the transfer, not necessary where the error occurred.
  995          */
  996         printf("%s%c: hard error, sector number %" PRId64 "\n",
  997             sc->sc_dev.dv_xname, 'a'+RDPART(bp->b_dev), pbn);
  998         /*
  999          * Now report the status as returned by the hardware with
 1000          * attempt at interpretation.
 1001          */
 1002         printf("%s %s error:", sc->sc_dev.dv_xname,
 1003             (bp->b_flags & B_READ) ? "read" : "write");
 1004         printf(" unit %d, volume %d R0x%x F0x%x A0x%x I0x%x\n",
 1005                css.c_vu&0xF, (css.c_vu>>4)&0xF,
 1006                css.c_ref, css.c_fef, css.c_aef, css.c_ief);
 1007         printf("P1-P10: ");
 1008         printf("0x%x ", *(u_int32_t *)&css.c_raw[0]);
 1009         printf("0x%x ", *(u_int32_t *)&css.c_raw[4]);
 1010         printf("0x%x\n", *(u_int16_t *)&css.c_raw[8]);
 1011 
 1012         return (1);
 1013 }
 1014 
 1015 int
 1016 rdread(dev, uio, flags)
 1017         dev_t dev;
 1018         struct uio *uio;
 1019         int flags;
 1020 {
 1021 
 1022         return (physio(rdstrategy, NULL, dev, B_READ, minphys, uio));
 1023 }
 1024 
 1025 int
 1026 rdwrite(dev, uio, flags)
 1027         dev_t dev;
 1028         struct uio *uio;
 1029         int flags;
 1030 {
 1031 
 1032         return (physio(rdstrategy, NULL, dev, B_WRITE, minphys, uio));
 1033 }
 1034 
 1035 int
 1036 rdioctl(dev, cmd, data, flag, p)
 1037         dev_t dev;
 1038         u_long cmd;
 1039         caddr_t data;
 1040         int flag;
 1041         struct proc *p;
 1042 {
 1043         struct rd_softc *sc;
 1044         struct disklabel *lp;
 1045         int error, flags;
 1046 
 1047         sc = device_lookup(&rd_cd, RDUNIT(dev));
 1048         if (sc == NULL)
 1049                 return (ENXIO);
 1050         lp = sc->sc_dk.dk_label;
 1051 
 1052         DPRINTF(RDB_FOLLOW, ("rdioctl: sc=%p\n", sc));
 1053 
 1054         switch (cmd) {
 1055         case DIOCGDINFO:
 1056                 *(struct disklabel *)data = *lp;
 1057                 return (0);
 1058 
 1059         case DIOCGPART:
 1060                 ((struct partinfo *)data)->disklab = lp;
 1061                 ((struct partinfo *)data)->part =
 1062                     &lp->d_partitions[RDPART(dev)];
 1063                 return (0);
 1064 
 1065         case DIOCWLABEL:
 1066                 if ((flag & FWRITE) == 0)
 1067                         return (EBADF);
 1068                 if (*(int *)data)
 1069                         sc->sc_flags |= RDF_WLABEL;
 1070                 else
 1071                         sc->sc_flags &= ~RDF_WLABEL;
 1072                 return (0);
 1073 
 1074         case DIOCSDINFO:
 1075                 if ((flag & FWRITE) == 0)
 1076                         return (EBADF);
 1077                 return (setdisklabel(lp, (struct disklabel *)data,
 1078                     (sc->sc_flags & RDF_WLABEL) ? 0 : sc->sc_dk.dk_openmask,
 1079                     (struct cpu_disklabel *)0));
 1080 
 1081         case DIOCWDINFO:
 1082                 if ((flag & FWRITE) == 0)
 1083                         return (EBADF);
 1084                 error = setdisklabel(lp, (struct disklabel *)data,
 1085                     (sc->sc_flags & RDF_WLABEL) ? 0 : sc->sc_dk.dk_openmask,
 1086                     (struct cpu_disklabel *)0);
 1087                 if (error)
 1088                         return (error);
 1089                 flags = sc->sc_flags;
 1090                 sc->sc_flags = RDF_ALIVE | RDF_WLABEL;
 1091                 error = writedisklabel(RDLABELDEV(dev), rdstrategy, lp,
 1092                     (struct cpu_disklabel *)0);
 1093                 sc->sc_flags = flags;
 1094                 return (error);
 1095 
 1096         case DIOCGDEFLABEL:
 1097                 rdgetdefaultlabel(sc, (struct disklabel *)data);
 1098                 return (0);
 1099         }
 1100         return (EINVAL);
 1101 }
 1102 
 1103 void
 1104 rdgetdefaultlabel(sc, lp)
 1105         struct rd_softc *sc;
 1106         struct disklabel *lp;
 1107 {
 1108         int type = sc->sc_type;
 1109 
 1110         memset((caddr_t)lp, 0, sizeof(struct disklabel));
 1111 
 1112         lp->d_type = DTYPE_GPIB;
 1113         lp->d_secsize = DEV_BSIZE;
 1114         lp->d_nsectors = rdidentinfo[type].ri_nbpt;
 1115         lp->d_ntracks = rdidentinfo[type].ri_ntpc;
 1116         lp->d_ncylinders = rdidentinfo[type].ri_ncyl;
 1117         lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
 1118         lp->d_secperunit = lp->d_ncylinders * lp->d_secpercyl;
 1119 
 1120         strncpy(lp->d_typename, rdidentinfo[type].ri_desc, 16);
 1121         strncpy(lp->d_packname, "fictitious", 16);
 1122         lp->d_rpm = 3000;
 1123         lp->d_interleave = 1;
 1124         lp->d_flags = 0;
 1125 
 1126         lp->d_partitions[RAW_PART].p_offset = 0;
 1127         lp->d_partitions[RAW_PART].p_size =
 1128             lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
 1129         lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
 1130         lp->d_npartitions = RAW_PART + 1;
 1131 
 1132         lp->d_magic = DISKMAGIC;
 1133         lp->d_magic2 = DISKMAGIC;
 1134         lp->d_checksum = dkcksum(lp);
 1135 }
 1136 
 1137 int
 1138 rdsize(dev)
 1139         dev_t dev;
 1140 {
 1141         struct rd_softc *sc;
 1142         int psize, didopen = 0;
 1143 
 1144         sc = device_lookup(&rd_cd, RDUNIT(dev));
 1145         if (sc == NULL || (sc->sc_flags & RDF_ALIVE) == 0)
 1146                 return (-1);
 1147 
 1148         /*
 1149          * We get called very early on (via swapconf)
 1150          * without the device being open so we may need
 1151          * to handle it here.
 1152          */
 1153         if (sc->sc_dk.dk_openmask == 0) {
 1154                 if (rdopen(dev, FREAD | FWRITE, S_IFBLK, NULL))
 1155                         return (-1);
 1156                 didopen = 1;
 1157         }
 1158         psize = sc->sc_dk.dk_label->d_partitions[RDPART(dev)].p_size *
 1159             (sc->sc_dk.dk_label->d_secsize / DEV_BSIZE);
 1160         if (didopen)
 1161                 (void) rdclose(dev, FREAD | FWRITE, S_IFBLK, NULL);
 1162         return (psize);
 1163 }
 1164 
 1165 
 1166 static int rddoingadump;        /* simple mutex */
 1167 
 1168 /*
 1169  * Non-interrupt driven, non-dma dump routine.
 1170  */
 1171 int
 1172 rddump(dev, blkno, va, size)
 1173         dev_t dev;
 1174         daddr_t blkno;
 1175         caddr_t va;
 1176         size_t size;
 1177 {
 1178         struct rd_softc *sc;
 1179         int sectorsize;         /* size of a disk sector */
 1180         int nsects;             /* number of sectors in partition */
 1181         int sectoff;            /* sector offset of partition */
 1182         int totwrt;             /* total number of sectors left to write */
 1183         int nwrt;               /* current number of sectors to write */
 1184         int slave;
 1185         struct disklabel *lp;
 1186         u_int8_t stat;
 1187 
 1188         /* Check for recursive dump; if so, punt. */
 1189         if (rddoingadump)
 1190                 return (EFAULT);
 1191         rddoingadump = 1;
 1192 
 1193         sc = device_lookup(&rd_cd, RDUNIT(dev));
 1194         if (sc == NULL || (sc->sc_flags & RDF_ALIVE) == 0)
 1195                 return (ENXIO);
 1196 
 1197         DPRINTF(RDB_FOLLOW, ("rddump: sc=%p\n", sc));
 1198 
 1199         slave = sc->sc_slave;
 1200 
 1201         /*
 1202          * Convert to disk sectors.  Request must be a multiple of size.
 1203          */
 1204         lp = sc->sc_dk.dk_label;
 1205         sectorsize = lp->d_secsize;
 1206         if ((size % sectorsize) != 0)
 1207                 return (EFAULT);
 1208         totwrt = size / sectorsize;
 1209         blkno = dbtob(blkno) / sectorsize;      /* blkno in DEV_BSIZE units */
 1210 
 1211         nsects = lp->d_partitions[RDPART(dev)].p_size;
 1212         sectoff = lp->d_partitions[RDPART(dev)].p_offset;
 1213 
 1214         /* Check transfer bounds against partition size. */
 1215         if ((blkno < 0) || (blkno + totwrt) > nsects)
 1216                 return (EINVAL);
 1217 
 1218         /* Offset block number to start of partition. */
 1219         blkno += sectoff;
 1220 
 1221         while (totwrt > 0) {
 1222                 nwrt = totwrt;          /* XXX */
 1223 #ifndef RD_DUMP_NOT_TRUSTED
 1224                 /*
 1225                  * Fill out and send GPIB command.
 1226                  */
 1227                 sc->sc_ioc.c_unit = CS80CMD_SUNIT(sc->sc_punit);
 1228                 sc->sc_ioc.c_volume = CS80CMD_SVOL(0);
 1229                 sc->sc_ioc.c_saddr = CS80CMD_SADDR;
 1230                 sc->sc_ioc.c_hiaddr = 0;
 1231                 sc->sc_ioc.c_addr = RDBTOS(blkno);
 1232                 sc->sc_ioc.c_nop2 = CS80CMD_NOP;
 1233                 sc->sc_ioc.c_slen = CS80CMD_SLEN;
 1234                 sc->sc_ioc.c_len = nwrt * sectorsize;
 1235                 sc->sc_ioc.c_cmd = CS80CMD_WRITE;
 1236                 (void) gpibsend(sc->sc_ic, slave, CS80CMD_SCMD,
 1237                     &sc->sc_ioc.c_unit, sizeof(sc->sc_ioc)-3);
 1238                 if (gpibswait(sc->sc_ic, slave))
 1239                         return (EIO);
 1240                 /*
 1241                  * Send the data.
 1242                  */
 1243                 (void) gpibsend(sc->sc_ic, slave, CS80CMD_EXEC, va,
 1244                     nwrt * sectorsize);
 1245                 (void) gpibswait(sc->sc_ic, slave);
 1246                 (void) gpibrecv(sc->sc_ic, slave, CS80CMD_QSTAT, &stat, 1);
 1247                 if (stat)
 1248                         return (EIO);
 1249 #else /* RD_DUMP_NOT_TRUSTED */
 1250                 /* Let's just talk about this first... */
 1251                 printf("%s: dump addr %p, blk %d\n", sc->sc_dev.dv_xname,
 1252                     va, blkno);
 1253                 delay(500 * 1000);      /* half a second */
 1254 #endif /* RD_DUMP_NOT_TRUSTED */
 1255 
 1256                 /* update block count */
 1257                 totwrt -= nwrt;
 1258                 blkno += nwrt;
 1259                 va += sectorsize * nwrt;
 1260         }
 1261         rddoingadump = 0;
 1262         return (0);
 1263 }
 1264 
 1265 #ifdef COMPAT_NOLABEL
 1266 
 1267 /*
 1268  * CS/80 partitions.  We reserve the first cylinder for a LIF
 1269  * style boot directory (the 8k allowed in the BSD filesystem
 1270  * is just way too small).  This boot area is outside of all but
 1271  * the C partition.  This implies that you cannot use the C 
 1272  * partition on a bootable disk since the filesystem would overlay
 1273  * the boot area.  You must use the A partition.
 1274  *
 1275  * These maps support four basic layouts:
 1276  *
 1277  *      A/B/G:   This is the "traditional" setup for a bootable disk.
 1278  *               A is the root partition, B the swap, and G a user partition.
 1279  *      A/D/H:   This is a setup for bootable systems requiring more swap
 1280  *               (e.g. those who use HPCL).  It has A as the root, D as a
 1281  *               larger swap, and H as a smaller user partition.
 1282  *      A/D/E/F: Similar to A/D/H with E and F breaking H into two partitions.
 1283  *               E could be used for /usr and F for users.
 1284  *      C:       This gives a single, non-bootable, large user filesystem.
 1285  *               Good for second drives on a machine (e.g. /usr/src).
 1286  */
 1287 struct  size {
 1288         daddr_t nblocks;
 1289         int     cyloff;
 1290 } rd7945A_sizes[8] = {
 1291         { RDSZ(15904),  1       },      /* A=cyl 1 thru 142 */
 1292         { RDSZ(20160),  143     },      /* B=cyl 143 thru 322 */
 1293         { RDSZ(108416), 0       },      /* C=cyl 0 thru 967 */
 1294         { RDSZ(40320),  143     },      /* D=cyl 143 thru 502 */
 1295         { RDSZ(0),      0       },      /* E=<undefined> */
 1296         { RDSZ(0),      0       },      /* F=<undefined> */
 1297         { RDSZ(72240),  323     },      /* G=cyl 323 thru 967 */
 1298         { RDSZ(52080),  503     },      /* H=cyl 503 thru 967 */
 1299 }, rd9134D_sizes[8] = {
 1300         { RDSZ(15936),  1       },      /* A=cyl 1 thru 166 */
 1301         { RDSZ(13056),  167     },      /* B=cyl 167 thru 302 */
 1302         { RDSZ(29088),  0       },      /* C=cyl 0 thru 302 */
 1303         { RDSZ(0),      0       },      /* D=<undefined> */
 1304         { RDSZ(0),      0       },      /* E=<undefined> */
 1305         { RDSZ(0),      0       },      /* F=<undefined> */
 1306         { RDSZ(0),      0       },      /* G=<undefined> */
 1307         { RDSZ(0),      0       },      /* H=<undefined> */
 1308 }, rd9122S_sizes[8] = {
 1309         { RDSZ(0),      0       },      /* A=<undefined> */
 1310         { RDSZ(0),      0       },      /* B=<undefined> */
 1311         { RDSZ(1232),   0       },      /* C=cyl 0 thru 76 */
 1312         { RDSZ(0),      0       },      /* D=<undefined> */
 1313         { RDSZ(0),      0       },      /* E=<undefined> */
 1314         { RDSZ(0),      0       },      /* F=<undefined> */
 1315         { RDSZ(0),      0       },      /* G=<undefined> */
 1316         { RDSZ(0),      0       },      /* H=<undefined> */
 1317 }, rd7912P_sizes[8] = {
 1318         { RDSZ(15904),  0       },      /* A=cyl 1 thru 71 */
 1319         { RDSZ(22400),  72      },      /* B=cyl 72 thru 171 */
 1320         { RDSZ(128128), 0       },      /* C=cyl 0 thru 571 */
 1321         { RDSZ(42560),  72      },      /* D=cyl 72 thru 261 */
 1322         { RDSZ(0),      292     },      /* E=<undefined> */
 1323         { RDSZ(0),      542     },      /* F=<undefined> */
 1324         { RDSZ(89600),  172     },      /* G=cyl 221 thru 571 */
 1325         { RDSZ(69440),  262     },      /* H=cyl 262 thru 571 */
 1326 }, rd7914P_sizes[8] = {
 1327         { RDSZ(15904),  1       },      /* A=cyl 1 thru 71 */
 1328         { RDSZ(40320),  72      },      /* B=cyl 72 thru 251 */
 1329         { RDSZ(258048), 0       },      /* C=cyl 0 thru 1151 */
 1330         { RDSZ(64960),  72      },      /* D=cyl 72 thru 361 */
 1331         { RDSZ(98560),  362     },      /* E=cyl 362 thru 801 */
 1332         { RDSZ(78400),  802     },      /* F=cyl 802 thru 1151 */
 1333         { RDSZ(201600), 252     },      /* G=cyl 221 thru 1151 */
 1334         { RDSZ(176960), 362     },      /* H=cyl 362 thru 1151 */
 1335 }, rd7933H_sizes[8] = {
 1336         { RDSZ(16146),  1       },      /* A=cyl 1 thru 27 */
 1337         { RDSZ(66976),  28      },      /* B=cyl 28 thru 139 */
 1338         { RDSZ(789958), 0       },      /* C=cyl 0 thru 1320 */
 1339         { RDSZ(16146),  140     },      /* D=cyl 140 thru 166 */
 1340         { RDSZ(165646), 167     },      /* E=cyl 167 thru 443 */
 1341         { RDSZ(165646), 444     },      /* F=cyl 444 thru 720 */
 1342         { RDSZ(706238), 140     },      /* G=cyl 140 thru 1320 */
 1343         { RDSZ(358800), 721     },      /* H=cyl 721 thru 1320 */
 1344 }, rd9134L_sizes[8] = {
 1345         { RDSZ(15920),  1       },      /* A=cyl 1 thru 199 */
 1346         { RDSZ(20000),  200     },      /* B=cyl 200 thru 449 */
 1347         { RDSZ(77840),  0       },      /* C=cyl 0 thru 972 */
 1348         { RDSZ(32000),  200     },      /* D=cyl 200 thru 599 */
 1349         { RDSZ(0),      0       },      /* E=<undefined> */
 1350         { RDSZ(0),      0       },      /* F=<undefined> */
 1351         { RDSZ(41840),  450     },      /* G=cyl 450 thru 972 */
 1352         { RDSZ(29840),  600     },      /* H=cyl 600 thru 972 */
 1353 }, rd7957A_sizes[8] = {
 1354         { RDSZ(16016),  1       },      /* A=cyl 1 thru 104 */
 1355         { RDSZ(24640),  105     },      /* B=cyl 105 thru 264 */
 1356         { RDSZ(159544), 0       },      /* C=cyl 0 thru 1035 */
 1357         { RDSZ(42350),  105     },      /* D=cyl 105 thru 379 */
 1358         { RDSZ(54824),  380     },      /* E=cyl 380 thru 735 */
 1359         { RDSZ(46200),  736     },      /* F=cyl 736 thru 1035 */
 1360         { RDSZ(118734), 265     },      /* G=cyl 265 thru 1035 */
 1361         { RDSZ(101024), 380     },      /* H=cyl 380 thru 1035 */
 1362 }, rd7958A_sizes[8] = {
 1363         { RDSZ(16128),  1       },      /* A=cyl 1 thru 64 */
 1364         { RDSZ(32256),  65      },      /* B=cyl 65 thru 192 */
 1365         { RDSZ(255276), 0       },      /* C=cyl 0 thru 1012 */
 1366         { RDSZ(48384),  65      },      /* D=cyl 65 thru 256 */
 1367         { RDSZ(100800), 257     },      /* E=cyl 257 thru 656 */
 1368         { RDSZ(89712),  657     },      /* F=cyl 657 thru 1012 */
 1369         { RDSZ(206640), 193     },      /* G=cyl 193 thru 1012 */
 1370         { RDSZ(190512), 257     },      /* H=cyl 257 thru 1012 */
 1371 }, rd7957B_sizes[8] = {
 1372         { RDSZ(16002),  1       },      /* A=cyl 1 thru 127 */
 1373         { RDSZ(32760),  128     },      /* B=cyl 128 thru 387 */
 1374         { RDSZ(159894), 0       },      /* C=cyl 0 thru 1268 */
 1375         { RDSZ(49140),  128     },      /* D=cyl 128 thru 517 */
 1376         { RDSZ(50400),  518     },      /* E=cyl 518 thru 917 */
 1377         { RDSZ(44226),  918     },      /* F=cyl 918 thru 1268 */
 1378         { RDSZ(111006), 388     },      /* G=cyl 388 thru 1268 */
 1379         { RDSZ(94626),  518     },      /* H=cyl 518 thru 1268 */
 1380 }, rd7958B_sizes[8] = {
 1381         { RDSZ(16254),  1       },      /* A=cyl 1 thru 43 */
 1382         { RDSZ(32886),  44      },      /* B=cyl 44 thru 130 */
 1383         { RDSZ(297108), 0       },      /* C=cyl 0 thru 785 */
 1384         { RDSZ(49140),  44      },      /* D=cyl 44 thru 173 */
 1385         { RDSZ(121716), 174     },      /* E=cyl 174 thru 495 */
 1386         { RDSZ(109620), 496     },      /* F=cyl 496 thru 785 */
 1387         { RDSZ(247590), 131     },      /* G=cyl 131 thru 785 */
 1388         { RDSZ(231336), 174     },      /* H=cyl 174 thru 785 */
 1389 }, rd7959B_sizes[8] = {
 1390         { RDSZ(16254),  1       },      /* A=cyl 1 thru 43 */
 1391         { RDSZ(49140),  44      },      /* B=cyl 44 thru 173 */
 1392         { RDSZ(594216), 0       },      /* C=cyl 0 thru 1571 */
 1393         { RDSZ(65772),  44      },      /* D=cyl 44 thru 217 */
 1394         { RDSZ(303912), 218     },      /* E=cyl 218 thru 1021 */
 1395         { RDSZ(207900), 1022    },      /* F=cyl 1022 thru 1571 */
 1396         { RDSZ(528444), 174     },      /* G=cyl 174 thru 1571 */
 1397         { RDSZ(511812), 218     },      /* H=cyl 218 thru 1571 */
 1398 }, rd2200A_sizes[8] = {
 1399         { RDSZ(16272),  1       },      /* A=cyl 1 thru 36 */
 1400         { RDSZ(49720),  37      },      /* B=cyl 37 thru 146 */
 1401         { RDSZ(654948), 0       },      /* C=cyl 0 thru 1448 */
 1402         { RDSZ(65992),  37      },      /* D=cyl 37 thru 182 */
 1403         { RDSZ(304648), 183     },      /* E=cyl 183 thru 856 */
 1404         { RDSZ(267584), 857     },      /* F=cyl 857 thru 1448 */
 1405         { RDSZ(588504), 147     },      /* G=cyl 147 thru 1448 */
 1406         { RDSZ(572232), 183     },      /* H=cyl 183 thru 1448 */
 1407 }, rd2203A_sizes[8] = {
 1408         /* modelled after the 7937; i.e. bogus */
 1409         { RDSZ(16272),  1       },      /* A=cyl 1 thru 18 */
 1410         { RDSZ(67800),  19      },      /* B=cyl 19 thru 93 */
 1411         { RDSZ(1309896), 0      },      /* C=cyl 0 thru 1448 */
 1412         { RDSZ(16272),  94      },      /* D=cyl 19 thru 111 */
 1413         { RDSZ(305552), 112     },      /* E=cyl 112 thru 449 */
 1414         { RDSZ(305552), 450     },      /* F=cyl 450 thru 787 */
 1415         { RDSZ(1224920), 94     },      /* G=cyl 94 thru 1448 */
 1416         { RDSZ(597544), 788     },      /* H=cyl 788 thru 1448 */
 1417 }, rd7936H_sizes[8] = {
 1418         { RDSZ(16359),  1       },      /* A=cyl 1 thru 19 */
 1419         { RDSZ(67158),  20      },      /* B=cyl 20 thru 97 */
 1420         { RDSZ(600978), 0       },      /* C=cyl 0 thru 697 */
 1421         { RDSZ(16359),  98      },      /* D=cyl 98 thru 116 */
 1422         { RDSZ(120540), 117     },      /* E=cyl 117 thru 256 */
 1423         { RDSZ(120540), 256     },      /* F=cyl 256 thru 396 */
 1424         { RDSZ(516600), 98      },      /* G=cyl 98 thru 697 */
 1425         { RDSZ(259161), 397     },      /* H=cyl 397 thru 697 */
 1426 }, rd7937H_sizes[8] = {
 1427         { RDSZ(15990),  1       },      /* A=cyl 1 thru 10 */
 1428         { RDSZ(67158),  11      },      /* B=cyl 11 thru 52 */
 1429         { RDSZ(1116102), 0      },      /* C=cyl 0 thru 697 */
 1430         { RDSZ(124722), 53      },      /* D=cyl 53 thru 130 */
 1431         { RDSZ(163098), 131     },      /* E=cyl 131 thru 232 */
 1432         { RDSZ(287820), 233     },      /* F=cyl 233 thru 412 */
 1433         { RDSZ(1031355), 53     },      /* G=cyl 53 thru 697 */
 1434         { RDSZ(455715), 413     },      /* H=cyl 413 thru 697 */
 1435 };
 1436 
 1437 /*
 1438  * Indexed the same as rdidentinfo array.
 1439  */
 1440 struct rdcompatinfo {
 1441         struct size *sizes;     /* partition info */
 1442 } rdcompatinfo[] = {
 1443         { rd7945A_sizes },
 1444         { rd9134D_sizes },
 1445         { rd9122S_sizes },
 1446         { rd7912P_sizes },
 1447         { rd7914P_sizes },
 1448         { rd7958A_sizes },
 1449         { rd7957A_sizes },
 1450         { rd7933H_sizes },
 1451         { rd9134L_sizes },
 1452         { rd7936H_sizes },
 1453         { rd7937H_sizes },
 1454         { rd7914P_sizes },
 1455         { rd7945A_sizes },
 1456         { rd9122S_sizes },
 1457         { rd7957B_sizes },
 1458         { rd7958B_sizes },
 1459         { rd7959B_sizes },
 1460         { rd2200A_sizes },
 1461         { rd2203A_sizes },
 1462 };
 1463 int nrdcompatinfo = sizeof(rdcompatinfo) / sizeof(rdcompatinfo[0]);
 1464 
 1465 void
 1466 rdgetcompatlabel(sc, lp)
 1467         struct rd_softc *sc;
 1468         struct disklabel *lp;
 1469 {
 1470         struct rdcompatinfo *ci = &rdcompatinfo[sc->sc_type];
 1471         const struct rdidentinfo *ri = &rdidentinfo[sc->sc_type];
 1472         struct partition *pi;
 1473         int dcount;
 1474         
 1475         rdgetdefaultlabel(sc, lp);
 1476 
 1477         lp->d_npartitions = 8;
 1478         pi = lp->d_partitions;
 1479         for (dcount = 0; dcount < lp->d_npartitions; dcount++) {
 1480                 pi->p_size = ci->sizes[dcount].nblocks;
 1481                 pi->p_offset = ci->sizes[dcount].cyloff * lp->d_secpercyl;
 1482                 pi->p_fsize = 1024;
 1483                 if (dcount == 1 || dcount == 3)
 1484                         pi->p_fstype = FS_SWAP;
 1485                 else if (dcount == 2)
 1486                         pi->p_fstype = FS_BOOT;
 1487                 else
 1488                         pi->p_fstype = FS_BSDFFS;
 1489                 pi->p_frag = 8;
 1490                 pi++;
 1491         }
 1492 }
 1493 
 1494 #endif /* COMPAT_NOLABEL */

Cache object: 84dbf4e9be9327ed6eac01e9af2bd4d6


[ 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.