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/mscp/mscp_disk.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: mscp_disk.c,v 1.42 2003/08/07 16:31:09 agc Exp $       */
    2 /*
    3  * Copyright (c) 1988 Regents of the University of California.
    4  * All rights reserved.
    5  *
    6  * This code is derived from software contributed to Berkeley by
    7  * Chris Torek.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. Neither the name of the University nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  *
   33  *      @(#)uda.c       7.32 (Berkeley) 2/13/91
   34  */
   35 
   36 /*
   37  * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
   38  *
   39  * This code is derived from software contributed to Berkeley by
   40  * Chris Torek.
   41  *
   42  * Redistribution and use in source and binary forms, with or without
   43  * modification, are permitted provided that the following conditions
   44  * are met:
   45  * 1. Redistributions of source code must retain the above copyright
   46  *    notice, this list of conditions and the following disclaimer.
   47  * 2. Redistributions in binary form must reproduce the above copyright
   48  *    notice, this list of conditions and the following disclaimer in the
   49  *    documentation and/or other materials provided with the distribution.
   50  * 3. All advertising materials mentioning features or use of this software
   51  *    must display the following acknowledgement:
   52  *      This product includes software developed by the University of
   53  *      California, Berkeley and its contributors.
   54  * 4. Neither the name of the University nor the names of its contributors
   55  *    may be used to endorse or promote products derived from this software
   56  *    without specific prior written permission.
   57  *
   58  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   59  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   60  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   61  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   62  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   63  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   64  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   65  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   66  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   67  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   68  * SUCH DAMAGE.
   69  *
   70  *      @(#)uda.c       7.32 (Berkeley) 2/13/91
   71  */
   72 
   73 /*
   74  * RA disk device driver
   75  * RX MSCP floppy disk device driver
   76  */
   77 
   78 /*
   79  * TODO
   80  *      write bad block forwarding code
   81  */
   82 
   83 #include <sys/cdefs.h>
   84 __KERNEL_RCSID(0, "$NetBSD: mscp_disk.c,v 1.42 2003/08/07 16:31:09 agc Exp $");
   85 
   86 #include <sys/param.h>
   87 #include <sys/buf.h>
   88 #include <sys/device.h>
   89 #include <sys/disk.h>
   90 #include <sys/disklabel.h>
   91 #include <sys/ioctl.h>
   92 #include <sys/stat.h>
   93 #include <sys/fcntl.h>
   94 #include <sys/reboot.h>
   95 #include <sys/proc.h>
   96 #include <sys/systm.h>
   97 #include <sys/conf.h>
   98 
   99 #include <ufs/ufs/dinode.h>
  100 #include <ufs/ffs/fs.h>
  101 
  102 #include <machine/bus.h>
  103 #include <machine/cpu.h>
  104 
  105 #include <dev/mscp/mscp.h>
  106 #include <dev/mscp/mscpreg.h>
  107 #include <dev/mscp/mscpvar.h>
  108 
  109 #include "locators.h"
  110 #include "ioconf.h"
  111 #include "ra.h"
  112 
  113 /*
  114  * Drive status, per drive
  115  */
  116 struct ra_softc {
  117         struct  device ra_dev;  /* Autoconf struct */
  118         struct  disk ra_disk;
  119         int     ra_state;       /* open/closed state */
  120         u_long  ra_mediaid;     /* media id */
  121         int     ra_hwunit;      /* Hardware unit number */
  122         int     ra_havelabel;   /* true if we have a label */
  123         int     ra_wlabel;      /* label sector is currently writable */
  124 };
  125 
  126 #define rx_softc ra_softc
  127 
  128 void    rxattach __P((struct device *, struct device *, void *));
  129 int     rx_putonline __P((struct rx_softc *));
  130 void    rrmakelabel __P((struct disklabel *, long));
  131 
  132 #if NRA
  133 
  134 int     ramatch __P((struct device *, struct cfdata *, void *));
  135 void    raattach __P((struct device *, struct device *, void *));
  136 int     ra_putonline __P((struct ra_softc *));
  137 
  138 CFATTACH_DECL(ra, sizeof(struct ra_softc),
  139     ramatch, rxattach, NULL, NULL);
  140 
  141 dev_type_open(raopen);
  142 dev_type_close(raclose);
  143 dev_type_read(raread);
  144 dev_type_write(rawrite);
  145 dev_type_ioctl(raioctl);
  146 dev_type_strategy(rastrategy);
  147 dev_type_dump(radump);
  148 dev_type_size(rasize);
  149 
  150 const struct bdevsw ra_bdevsw = {
  151         raopen, raclose, rastrategy, raioctl, radump, rasize, D_DISK
  152 };
  153 
  154 const struct cdevsw ra_cdevsw = {
  155         raopen, raclose, raread, rawrite, raioctl,
  156         nostop, notty, nopoll, nommap, nokqfilter, D_DISK
  157 };
  158 
  159 /*
  160  * More driver definitions, for generic MSCP code.
  161  */
  162 
  163 int
  164 ramatch(parent, cf, aux)
  165         struct  device *parent;
  166         struct  cfdata *cf;
  167         void    *aux;
  168 {
  169         struct  drive_attach_args *da = aux;
  170         struct  mscp *mp = da->da_mp;
  171 
  172         if ((da->da_typ & MSCPBUS_DISK) == 0)
  173                 return 0;
  174         if (cf->cf_loc[MSCPBUSCF_DRIVE] != MSCPBUSCF_DRIVE_DEFAULT &&
  175             cf->cf_loc[MSCPBUSCF_DRIVE] != mp->mscp_unit)
  176                 return 0;
  177         /*
  178          * Check if this disk is a floppy; then don't configure it.
  179          * Seems to be a safe way to test it per Chris Torek.
  180          */
  181         if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@')
  182                 return 0;
  183         return 1;
  184 }
  185 
  186 /* 
  187  * (Try to) put the drive online. This is done the first time the
  188  * drive is opened, or if it har fallen offline.
  189  */
  190 int
  191 ra_putonline(ra)
  192         struct ra_softc *ra;
  193 {
  194         struct  disklabel *dl;
  195         const char *msg;
  196         int maj;
  197 
  198         if (rx_putonline(ra) != MSCP_DONE)
  199                 return MSCP_FAILED;
  200 
  201         dl = ra->ra_disk.dk_label;
  202 
  203         ra->ra_state = DK_RDLABEL;
  204         printf("%s", ra->ra_dev.dv_xname);
  205         maj = cdevsw_lookup_major(&ra_cdevsw);
  206         if ((msg = readdisklabel(MAKEDISKDEV(maj, ra->ra_dev.dv_unit,
  207             RAW_PART), rastrategy, dl, NULL)) != NULL)
  208                 printf(": %s", msg);
  209         else {
  210                 ra->ra_havelabel = 1;
  211                 ra->ra_state = DK_OPEN;
  212         }
  213 
  214         printf(": size %d sectors\n", dl->d_secperunit);
  215 
  216         return MSCP_DONE;
  217 }
  218 
  219 /*
  220  * Open a drive.
  221  */
  222 /*ARGSUSED*/
  223 int
  224 raopen(dev, flag, fmt, p)
  225         dev_t dev;
  226         int flag, fmt;
  227         struct  proc *p;
  228 {
  229         struct ra_softc *ra;
  230         int part, unit, mask;
  231         /*
  232          * Make sure this is a reasonable open request.
  233          */
  234         unit = DISKUNIT(dev);
  235         if (unit >= ra_cd.cd_ndevs)
  236                 return ENXIO;
  237         ra = ra_cd.cd_devs[unit];
  238         if (ra == 0)
  239                 return ENXIO;
  240 
  241         /*
  242          * If this is the first open; we must first try to put
  243          * the disk online (and read the label).
  244          */
  245         if (ra->ra_state == DK_CLOSED)
  246                 if (ra_putonline(ra) == MSCP_FAILED)
  247                         return ENXIO;
  248 
  249         /* If the disk has no label; allow writing everywhere */
  250         if (ra->ra_havelabel == 0)
  251                 ra->ra_wlabel = 1;
  252 
  253         part = DISKPART(dev);
  254         if (part >= ra->ra_disk.dk_label->d_npartitions)
  255                 return ENXIO;
  256 
  257         /*
  258          * Wait for the state to settle
  259          */
  260 #if notyet
  261         while (ra->ra_state != DK_OPEN)
  262                 if ((error = tsleep((caddr_t)ra, (PZERO + 1) | PCATCH,
  263                     devopn, 0))) {
  264                         splx(s);
  265                         return (error);
  266                 }
  267 #endif
  268 
  269         mask = 1 << part;
  270 
  271         switch (fmt) {
  272         case S_IFCHR:
  273                 ra->ra_disk.dk_copenmask |= mask;
  274                 break;
  275         case S_IFBLK:
  276                 ra->ra_disk.dk_bopenmask |= mask;
  277                 break;
  278         }
  279         ra->ra_disk.dk_openmask |= mask;
  280         return 0;
  281 }
  282 
  283 /* ARGSUSED */
  284 int
  285 raclose(dev, flags, fmt, p)
  286         dev_t dev;
  287         int flags, fmt;
  288         struct  proc *p;
  289 {
  290         int unit = DISKUNIT(dev);
  291         struct ra_softc *ra = ra_cd.cd_devs[unit];
  292         int mask = (1 << DISKPART(dev));
  293 
  294         switch (fmt) {
  295         case S_IFCHR:
  296                 ra->ra_disk.dk_copenmask &= ~mask;
  297                 break;
  298         case S_IFBLK:
  299                 ra->ra_disk.dk_bopenmask &= ~mask;
  300                 break;
  301         }
  302         ra->ra_disk.dk_openmask =
  303             ra->ra_disk.dk_copenmask | ra->ra_disk.dk_bopenmask;
  304 
  305         /*
  306          * Should wait for I/O to complete on this partition even if
  307          * others are open, but wait for work on blkflush().
  308          */
  309 #if notyet
  310         if (ra->ra_openpart == 0) {
  311                 s = spluba();
  312                 while (BUFQ_PEEK(&udautab[unit]) != NULL)
  313                         (void) tsleep(&udautab[unit], PZERO - 1,
  314                             "raclose", 0);
  315                 splx(s);
  316                 ra->ra_state = CLOSED;
  317                 ra->ra_wlabel = 0;
  318         }
  319 #endif
  320         return (0);
  321 }
  322 
  323 /*
  324  * Queue a transfer request, and if possible, hand it to the controller.
  325  */
  326 void
  327 rastrategy(bp)
  328         struct buf *bp;
  329 {
  330         int unit;
  331         struct ra_softc *ra;
  332         int b;
  333 
  334         /*
  335          * Make sure this is a reasonable drive to use.
  336          */
  337         unit = DISKUNIT(bp->b_dev);
  338         if (unit > ra_cd.cd_ndevs || (ra = ra_cd.cd_devs[unit]) == NULL) {
  339                 bp->b_error = ENXIO;
  340                 bp->b_flags |= B_ERROR;
  341                 goto done;
  342         }
  343         /*
  344          * If drive is open `raw' or reading label, let it at it.
  345          */
  346         if (ra->ra_state == DK_RDLABEL) {
  347                 /* Make some statistics... /bqt */
  348                 b = splbio();
  349                 disk_busy(&ra->ra_disk);
  350                 splx(b);
  351                 mscp_strategy(bp, ra->ra_dev.dv_parent);
  352                 return;
  353         }
  354 
  355         /* If disk is not online, try to put it online */
  356         if (ra->ra_state == DK_CLOSED)
  357                 if (ra_putonline(ra) == MSCP_FAILED) {
  358                         bp->b_flags |= B_ERROR;
  359                         bp->b_error = EIO;
  360                         goto done;
  361                 }
  362 
  363         /*
  364          * Determine the size of the transfer, and make sure it is
  365          * within the boundaries of the partition.
  366          */
  367         if (bounds_check_with_label(&ra->ra_disk, bp, ra->ra_wlabel) <= 0)
  368                 goto done;
  369 
  370         /* Make some statistics... /bqt */
  371         b = splbio();
  372         disk_busy(&ra->ra_disk);
  373         splx(b);
  374         mscp_strategy(bp, ra->ra_dev.dv_parent);
  375         return;
  376 
  377 done:
  378         biodone(bp);
  379 }
  380 
  381 int
  382 raread(dev, uio, flags)
  383         dev_t dev;
  384         struct uio *uio;
  385         int flags;
  386 {
  387 
  388         return (physio(rastrategy, NULL, dev, B_READ, minphys, uio));
  389 }
  390 
  391 int
  392 rawrite(dev, uio, flags)
  393         dev_t dev;
  394         struct uio *uio;
  395         int flags;
  396 {
  397 
  398         return (physio(rastrategy, NULL, dev, B_WRITE, minphys, uio));
  399 }
  400 
  401 /*
  402  * I/O controls.
  403  */
  404 int
  405 raioctl(dev, cmd, data, flag, p)
  406         dev_t dev;
  407         u_long cmd;
  408         caddr_t data;
  409         int flag;
  410         struct proc *p;
  411 {
  412         int unit = DISKUNIT(dev);
  413         struct disklabel *lp, *tp;
  414         struct ra_softc *ra = ra_cd.cd_devs[unit];
  415         int error = 0;
  416 #ifdef __HAVE_OLD_DISKLABEL
  417         struct disklabel newlabel;
  418 #endif
  419 
  420         lp = ra->ra_disk.dk_label;
  421 
  422         switch (cmd) {
  423 
  424         case DIOCGDINFO:
  425                 bcopy(lp, data, sizeof (struct disklabel));
  426                 break;
  427 #ifdef __HAVE_OLD_DISKLABEL
  428         case ODIOCGDINFO:
  429                 bcopy(lp, &newlabel, sizeof disklabel);
  430                 if (newlabel.d_npartitions > OLDMAXPARTITIONS)
  431                         return ENOTTY;
  432                 bcopy(&newlabel, data, sizeof (struct olddisklabel));
  433                 break;
  434 #endif
  435 
  436         case DIOCGPART:
  437                 ((struct partinfo *)data)->disklab = lp;
  438                 ((struct partinfo *)data)->part =
  439                     &lp->d_partitions[DISKPART(dev)];
  440                 break;
  441 
  442         case DIOCWDINFO:
  443         case DIOCSDINFO:
  444 #ifdef __HAVE_OLD_DISKLABEL
  445         case ODIOCWDINFO:
  446         case ODIOCSDINFO:
  447                 if (cmd == ODIOCSDINFO || xfer == ODIOCWDINFO) {
  448                         memset(&newlabel, 0, sizeof newlabel);
  449                         memcpy(&newlabel, data, sizeof (struct olddisklabel));
  450                         tp = &newlabel;
  451                 } else
  452 #endif
  453                 tp = (struct disklabel *)data;
  454 
  455                 if ((flag & FWRITE) == 0)
  456                         error = EBADF;
  457                 else {
  458                         error = setdisklabel(lp, tp, 0, 0);
  459                         if ((error == 0) && (cmd == DIOCWDINFO
  460 #ifdef __HAVE_OLD_DISKLABEL
  461                             || cmd == ODIOCWDINFO
  462 #else
  463                             )) {
  464 #endif
  465                                 ra->ra_wlabel = 1;
  466                                 error = writedisklabel(dev, rastrategy, lp,0);
  467                                 ra->ra_wlabel = 0;
  468                         }
  469                 }
  470                 break;
  471 
  472         case DIOCWLABEL:
  473                 if ((flag & FWRITE) == 0)
  474                         error = EBADF;
  475                 else
  476                         ra->ra_wlabel = 1;
  477                 break;
  478 
  479         case DIOCGDEFLABEL:
  480 #ifdef __HAVE_OLD_DISKLABEL
  481         case ODIOCGDEFLABEL:
  482                 if (cmd == ODIOCGDEFLABEL)
  483                         tp = &newlabel;
  484                 else
  485 #else
  486                 tp = (struct disklabel *)data;
  487 #endif
  488                 bzero(tp, sizeof(struct disklabel));
  489                 tp->d_secsize = lp->d_secsize;
  490                 tp->d_nsectors = lp->d_nsectors;
  491                 tp->d_ntracks = lp->d_ntracks;
  492                 tp->d_ncylinders = lp->d_ncylinders;
  493                 tp->d_secpercyl = lp->d_secpercyl;
  494                 tp->d_secperunit = lp->d_secperunit;
  495                 tp->d_type = DTYPE_MSCP;
  496                 tp->d_rpm = 3600;
  497                 rrmakelabel(tp, ra->ra_mediaid);
  498 #ifdef __HAVE_OLD_DISKLABEL
  499                 if (cmd == ODIOCGDEFLABEL) {
  500                         if (tp->d_npartitions > OLDMAXPARTITIONS)
  501                                 return ENOTTY;
  502                         memcpy(data, tp, sizeof (struct olddisklabel));
  503                 }
  504 #endif
  505                 break;
  506 
  507         default:
  508                 error = ENOTTY;
  509                 break;
  510         }
  511         return (error);
  512 }
  513 
  514 
  515 int
  516 radump(dev, blkno, va, size)
  517         dev_t   dev;
  518         daddr_t blkno;
  519         caddr_t va;
  520         size_t  size;
  521 {
  522         return ENXIO;
  523 }
  524 
  525 /*
  526  * Return the size of a partition, if known, or -1 if not.
  527  */
  528 int
  529 rasize(dev)
  530         dev_t dev;
  531 {
  532         int unit = DISKUNIT(dev);
  533         struct ra_softc *ra;
  534 
  535         if (unit >= ra_cd.cd_ndevs || ra_cd.cd_devs[unit] == 0)
  536                 return -1;
  537 
  538         ra = ra_cd.cd_devs[unit];
  539 
  540         if (ra->ra_state == DK_CLOSED)
  541                 if (ra_putonline(ra) == MSCP_FAILED)
  542                         return -1;
  543 
  544         return ra->ra_disk.dk_label->d_partitions[DISKPART(dev)].p_size *
  545             (ra->ra_disk.dk_label->d_secsize / DEV_BSIZE);
  546 }
  547 
  548 #endif /* NRA */
  549 
  550 #if NRX
  551 
  552 int     rxmatch __P((struct device *, struct cfdata *, void *));
  553 
  554 CFATTACH_DECL(rx, sizeof(struct rx_softc),
  555     rxmatch, rxattach, NULL, NULL);
  556 
  557 dev_type_open(rxopen);
  558 dev_type_read(rxread);
  559 dev_type_write(rxwrite);
  560 dev_type_ioctl(rxioctl);
  561 dev_type_strategy(rxstrategy);
  562 dev_type_dump(rxdump);
  563 dev_type_size(rxsize);
  564 
  565 const struct bdevsw rx_bdevsw = {
  566         rxopen, nullclose, rxstrategy, rxioctl, rxdump, rxsize, D_DISK
  567 };
  568 
  569 const struct cdevsw rx_cdevsw = {
  570         rxopen, nullclose, rxread, rxwrite, rxioctl,
  571         nostop, notty, nopoll, nommap, nokqfilter, D_DISK
  572 };
  573 
  574 /*
  575  * More driver definitions, for generic MSCP code.
  576  */
  577 
  578 int
  579 rxmatch(parent, cf, aux)
  580         struct  device *parent;
  581         struct  cfdata *cf;
  582         void    *aux;
  583 {
  584         struct  drive_attach_args *da = aux;
  585         struct  mscp *mp = da->da_mp;
  586 
  587         if ((da->da_typ & MSCPBUS_DISK) == 0)
  588                 return 0;
  589         if (cf->cf_loc[MSCPBUSCF_DRIVE] != MSCPBUSCF_DRIVE_DEFAULT &&
  590             cf->cf_loc[MSCPBUSCF_DRIVE] != mp->mscp_unit)
  591                 return 0;
  592         /*
  593          * Check if this disk is a floppy; then configure it.
  594          * Seems to be a safe way to test it per Chris Torek.
  595          */
  596         if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@')
  597                 return 1;
  598         return 0;
  599 }
  600 
  601 #endif /* NRX */
  602 
  603 /*
  604  * The attach routine only checks and prints drive type.
  605  * Bringing the disk online is done when the disk is accessed
  606  * the first time. 
  607  */
  608 void
  609 rxattach(parent, self, aux)
  610         struct  device *parent, *self;
  611         void    *aux; 
  612 {
  613         struct  rx_softc *rx = (void *)self;
  614         struct  drive_attach_args *da = aux;
  615         struct  mscp *mp = da->da_mp;
  616         struct  mscp_softc *mi = (void *)parent;
  617         struct  disklabel *dl;
  618 
  619         rx->ra_mediaid = mp->mscp_guse.guse_mediaid;
  620         rx->ra_state = DK_CLOSED;
  621         rx->ra_hwunit = mp->mscp_unit;
  622         mi->mi_dp[mp->mscp_unit] = self;
  623 
  624         rx->ra_disk.dk_name = rx->ra_dev.dv_xname;
  625         disk_attach((struct disk *)&rx->ra_disk);
  626 
  627         /* Fill in what we know. The actual size is gotten later */
  628         dl = rx->ra_disk.dk_label;
  629 
  630         dl->d_secsize = DEV_BSIZE;
  631         dl->d_nsectors = mp->mscp_guse.guse_nspt;
  632         dl->d_ntracks = mp->mscp_guse.guse_ngpc * mp->mscp_guse.guse_group;
  633         dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks;
  634         disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid);
  635 #ifdef DEBUG
  636         printf("%s: nspt %d group %d ngpc %d rct %d nrpt %d nrct %d\n",
  637             self->dv_xname, mp->mscp_guse.guse_nspt, mp->mscp_guse.guse_group,
  638             mp->mscp_guse.guse_ngpc, mp->mscp_guse.guse_rctsize,
  639             mp->mscp_guse.guse_nrpt, mp->mscp_guse.guse_nrct);
  640 #endif
  641 }
  642 
  643 /* 
  644  * (Try to) put the drive online. This is done the first time the
  645  * drive is opened, or if it har fallen offline.
  646  */
  647 int
  648 rx_putonline(rx)
  649         struct rx_softc *rx;
  650 {
  651         struct  mscp *mp;
  652         struct  mscp_softc *mi = (struct mscp_softc *)rx->ra_dev.dv_parent;
  653         volatile int i;
  654 
  655         rx->ra_state = DK_CLOSED;
  656         mp = mscp_getcp(mi, MSCP_WAIT);
  657         mp->mscp_opcode = M_OP_ONLINE;
  658         mp->mscp_unit = rx->ra_hwunit;
  659         mp->mscp_cmdref = 1;
  660         *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
  661 
  662         /* Poll away */
  663         i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
  664         if (tsleep(&rx->ra_dev.dv_unit, PRIBIO, "rxonline", 100*100))
  665                 rx->ra_state = DK_CLOSED;
  666 
  667         if (rx->ra_state == DK_CLOSED)
  668                 return MSCP_FAILED;
  669 
  670         return MSCP_DONE;
  671 }
  672 
  673 #if NRX
  674 
  675 /*
  676  * Open a drive.
  677  */
  678 /*ARGSUSED*/
  679 int
  680 rxopen(dev, flag, fmt, p)
  681         dev_t dev;
  682         int flag, fmt;
  683         struct  proc *p;
  684 {
  685         struct rx_softc *rx;
  686         int unit;
  687 
  688         /*
  689          * Make sure this is a reasonable open request.
  690          */
  691         unit = DISKUNIT(dev);
  692         if (unit >= rx_cd.cd_ndevs)
  693                 return ENXIO;
  694         rx = rx_cd.cd_devs[unit];
  695         if (rx == 0)
  696                 return ENXIO;
  697 
  698         /*
  699          * If this is the first open; we must first try to put
  700          * the disk online (and read the label).
  701          */
  702         if (rx->ra_state == DK_CLOSED)
  703                 if (rx_putonline(rx) == MSCP_FAILED)
  704                         return ENXIO;
  705 
  706         return 0;
  707 }
  708 
  709 /*
  710  * Queue a transfer request, and if possible, hand it to the controller.
  711  *
  712  * This routine is broken into two so that the internal version
  713  * udastrat1() can be called by the (nonexistent, as yet) bad block
  714  * revectoring routine.
  715  */
  716 void
  717 rxstrategy(bp)
  718         struct buf *bp;
  719 {
  720         int unit;
  721         struct rx_softc *rx;
  722         int b;
  723 
  724         /*
  725          * Make sure this is a reasonable drive to use.
  726          */
  727         unit = DISKUNIT(bp->b_dev);
  728         if (unit > rx_cd.cd_ndevs || (rx = rx_cd.cd_devs[unit]) == NULL) {
  729                 bp->b_error = ENXIO;
  730                 bp->b_flags |= B_ERROR;
  731                 goto done;
  732         }
  733 
  734         /* If disk is not online, try to put it online */
  735         if (rx->ra_state == DK_CLOSED)
  736                 if (rx_putonline(rx) == MSCP_FAILED) {
  737                         bp->b_flags |= B_ERROR;
  738                         bp->b_error = EIO;
  739                         goto done;
  740                 }
  741 
  742         /*
  743          * Determine the size of the transfer, and make sure it is
  744          * within the boundaries of the partition.
  745          */
  746         if (bp->b_blkno >= rx->ra_disk.dk_label->d_secperunit) {
  747                 bp->b_resid = bp->b_bcount;
  748                 goto done;
  749         }
  750 
  751         /* Make some statistics... /bqt */
  752         b = splbio();
  753         disk_busy(&rx->ra_disk);
  754         splx(b);
  755         mscp_strategy(bp, rx->ra_dev.dv_parent);
  756         return;
  757 
  758 done:
  759         biodone(bp);
  760 }
  761 
  762 int
  763 rxread(dev, uio, flag)
  764         dev_t dev;
  765         struct uio *uio;
  766         int flag;
  767 {
  768 
  769         return (physio(rxstrategy, NULL, dev, B_READ, minphys, uio));
  770 }
  771 
  772 int
  773 rxwrite(dev, uio, flag)
  774         dev_t dev;
  775         struct uio *uio;
  776         int flag;
  777 {
  778 
  779         return (physio(rxstrategy, NULL, dev, B_WRITE, minphys, uio));
  780 }
  781 
  782 /*
  783  * I/O controls.
  784  */
  785 int
  786 rxioctl(dev, cmd, data, flag, p)
  787         dev_t dev;
  788         u_long cmd;
  789         caddr_t data;
  790         int flag;
  791         struct proc *p;
  792 {
  793         int unit = DISKUNIT(dev);
  794         struct disklabel *lp;
  795         struct rx_softc *rx = rx_cd.cd_devs[unit];
  796         int error = 0;
  797 
  798         lp = rx->ra_disk.dk_label;
  799 
  800         switch (cmd) {
  801 
  802         case DIOCGDINFO:
  803                 bcopy(lp, data, sizeof (struct disklabel));
  804                 break;
  805 
  806         case DIOCGPART:
  807                 ((struct partinfo *)data)->disklab = lp;
  808                 ((struct partinfo *)data)->part =
  809                     &lp->d_partitions[DISKPART(dev)];
  810                 break;
  811 
  812 
  813         case DIOCWDINFO:
  814         case DIOCSDINFO:
  815         case DIOCWLABEL:
  816                 break;
  817 
  818         default:
  819                 error = ENOTTY;
  820                 break;
  821         }
  822         return (error);
  823 }
  824 
  825 int
  826 rxdump(dev, blkno, va, size)
  827         dev_t dev;
  828         daddr_t blkno;
  829         caddr_t va;
  830         size_t size;
  831 {
  832 
  833         /* Not likely. */
  834         return ENXIO;
  835 }
  836 
  837 int
  838 rxsize(dev)
  839         dev_t dev;
  840 {
  841 
  842         return -1;
  843 }
  844 
  845 #endif /* NRX */
  846 
  847 void    rrdgram __P((struct device *, struct mscp *, struct mscp_softc *));
  848 void    rriodone __P((struct device *, struct buf *));
  849 int     rronline __P((struct device *, struct mscp *));
  850 int     rrgotstatus __P((struct device *, struct mscp *));
  851 void    rrreplace __P((struct device *, struct mscp *));
  852 int     rrioerror __P((struct device *, struct mscp *, struct buf *));
  853 void    rrfillin __P((struct buf *, struct mscp *));
  854 void    rrbb __P((struct device *, struct mscp *, struct buf *));
  855 
  856 
  857 struct  mscp_device ra_device = {
  858         rrdgram,
  859         rriodone,
  860         rronline,
  861         rrgotstatus,
  862         rrreplace,
  863         rrioerror,
  864         rrbb,
  865         rrfillin,
  866 };
  867 
  868 /*
  869  * Handle an error datagram.
  870  * This can come from an unconfigured drive as well.
  871  */     
  872 void        
  873 rrdgram(usc, mp, mi)
  874         struct device *usc;
  875         struct mscp *mp; 
  876         struct mscp_softc *mi;
  877 {        
  878         if (mscp_decodeerror(usc == NULL?"unconf disk" : usc->dv_xname, mp, mi))
  879                 return;  
  880         /*
  881          * SDI status information bytes 10 and 11 are the microprocessor
  882          * error code and front panel code respectively.  These vary per
  883          * drive type and are printed purely for field service information.
  884          */
  885         if (mp->mscp_format == M_FM_SDI) 
  886                 printf("\tsdi uproc error code 0x%x, front panel code 0x%x\n",
  887                         mp->mscp_erd.erd_sdistat[10],
  888                         mp->mscp_erd.erd_sdistat[11]);
  889 }
  890 
  891 void    
  892 rriodone(usc, bp)
  893         struct device *usc;
  894         struct buf *bp;
  895 {
  896         struct ra_softc *ra;
  897         int unit;
  898 
  899         /* We assume that this is a reasonable drive. ra_strategy should
  900            already have verified it. Thus, no checks here... /bqt */
  901         unit = DISKUNIT(bp->b_dev);
  902         ra = ra_cd.cd_devs[unit];
  903         disk_unbusy(&ra->ra_disk, bp->b_bcount, (bp->b_flags & B_READ));
  904 
  905         biodone(bp);
  906 }
  907 
  908 /*
  909  * A drive came on line.  Check its type and size.  Return DONE if
  910  * we think the drive is truly on line.  In any case, awaken anyone
  911  * sleeping on the drive on-line-ness.
  912  */
  913 int
  914 rronline(usc, mp)
  915         struct device *usc;
  916         struct mscp *mp;
  917 {
  918         struct rx_softc *rx = (struct rx_softc *)usc;
  919         struct disklabel *dl;
  920 
  921         wakeup((caddr_t)&usc->dv_unit);
  922         if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
  923                 printf("%s: attempt to bring on line failed: ", usc->dv_xname);
  924                 mscp_printevent(mp);
  925                 return (MSCP_FAILED);
  926         }
  927 
  928         rx->ra_state = DK_OPEN;
  929  
  930         dl = rx->ra_disk.dk_label;
  931         dl->d_secperunit = (daddr_t)mp->mscp_onle.onle_unitsize;
  932 
  933         if (dl->d_secpercyl) {
  934                 dl->d_ncylinders = dl->d_secperunit/dl->d_secpercyl;
  935                 dl->d_type = DTYPE_MSCP;
  936                 dl->d_rpm = 3600;
  937         } else {
  938                 dl->d_type = DTYPE_FLOPPY;
  939                 dl->d_rpm = 300;
  940         }
  941         rrmakelabel(dl, rx->ra_mediaid);
  942 
  943         return (MSCP_DONE);
  944 }
  945 
  946 void
  947 rrmakelabel(dl, type)
  948         struct disklabel *dl;
  949         long type;
  950 {
  951         int n, p = 0;
  952 
  953         dl->d_bbsize = BBSIZE;
  954         dl->d_sbsize = SBLOCKSIZE;
  955 
  956         /* Create the disk name for disklabel. Phew... */
  957         dl->d_typename[p++] = MSCP_MID_CHAR(2, type);
  958         dl->d_typename[p++] = MSCP_MID_CHAR(1, type);
  959         if (MSCP_MID_ECH(0, type))
  960                 dl->d_typename[p++] = MSCP_MID_CHAR(0, type);
  961         n = MSCP_MID_NUM(type);
  962         if (n > 99) {
  963                 dl->d_typename[p++] = '1';
  964                 n -= 100;
  965         }
  966         if (n > 9) {
  967                 dl->d_typename[p++] = (n / 10) + '';
  968                 n %= 10;
  969         }
  970         dl->d_typename[p++] = n + '';
  971         dl->d_typename[p] = 0;
  972         dl->d_npartitions = MAXPARTITIONS;
  973         dl->d_partitions[0].p_size = dl->d_partitions[2].p_size =
  974             dl->d_secperunit;
  975         dl->d_partitions[0].p_offset = dl->d_partitions[2].p_offset = 0;
  976         dl->d_interleave = dl->d_headswitch = 1;
  977         dl->d_magic = dl->d_magic2 = DISKMAGIC;
  978         dl->d_checksum = dkcksum(dl);
  979 }
  980 
  981 /*      
  982  * We got some (configured) unit's status.  Return DONE if it succeeded.
  983  */
  984 int
  985 rrgotstatus(usc, mp)
  986         struct device *usc;
  987         struct mscp *mp;
  988 {       
  989         if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
  990                 printf("%s: attempt to get status failed: ", usc->dv_xname);
  991                 mscp_printevent(mp);
  992                 return (MSCP_FAILED);
  993         }
  994         /* record for (future) bad block forwarding and whatever else */
  995 #ifdef notyet
  996         uda_rasave(ui->ui_unit, mp, 1);
  997 #endif
  998         return (MSCP_DONE);
  999 }
 1000 
 1001 /*      
 1002  * A replace operation finished.
 1003  */
 1004 /*ARGSUSED*/
 1005 void    
 1006 rrreplace(usc, mp)
 1007         struct device *usc;
 1008         struct mscp *mp;
 1009 {
 1010 
 1011         panic("udareplace");
 1012 }
 1013 
 1014 /*
 1015  * A transfer failed.  We get a chance to fix or restart it.
 1016  * Need to write the bad block forwaring code first....
 1017  */
 1018 /*ARGSUSED*/
 1019 int 
 1020 rrioerror(usc, mp, bp)
 1021         struct device *usc;
 1022         struct mscp *mp;
 1023         struct buf *bp;
 1024 {
 1025         struct ra_softc *ra = (void *)usc;
 1026         int code = mp->mscp_event;
 1027 
 1028         switch (code & M_ST_MASK) {
 1029         /* The unit has fallen offline. Try to figure out why. */
 1030         case M_ST_OFFLINE:
 1031                 bp->b_flags |= B_ERROR;
 1032                 bp->b_error = EIO;
 1033                 ra->ra_state = DK_CLOSED;
 1034                 if (code & M_OFFLINE_UNMOUNTED)
 1035                         printf("%s: not mounted/spun down\n", usc->dv_xname);
 1036                 if (code & M_OFFLINE_DUPLICATE)
 1037                         printf("%s: duplicate unit number!!!\n", usc->dv_xname);
 1038                 return MSCP_DONE;
 1039 
 1040         case M_ST_AVAILABLE:
 1041                 ra->ra_state = DK_CLOSED; /* Force another online */
 1042                 return MSCP_DONE;
 1043 
 1044         default:
 1045                 printf("%s:", usc->dv_xname);
 1046                 break;
 1047         }
 1048         return (MSCP_FAILED);
 1049 }
 1050 
 1051 /*
 1052  * Fill in disk addresses in a mscp packet waiting for transfer.
 1053  */
 1054 void
 1055 rrfillin(bp, mp)
 1056         struct buf *bp;
 1057         struct mscp *mp;
 1058 {
 1059         struct rx_softc *rx = 0; /* Wall */
 1060         struct disklabel *lp;
 1061         int unit = DISKUNIT(bp->b_dev);
 1062         int part = DISKPART(bp->b_dev);
 1063 
 1064 #if NRA
 1065         if (cdevsw_lookup(bp->b_dev) == &ra_cdevsw)
 1066                 rx = ra_cd.cd_devs[unit];
 1067 #endif
 1068 #if NRX
 1069         if (cdevsw_lookup(bp->b_dev) == &rx_cdevsw)
 1070                 rx = rx_cd.cd_devs[unit];
 1071 #endif
 1072         lp = rx->ra_disk.dk_label;
 1073 
 1074         mp->mscp_seq.seq_lbn = lp->d_partitions[part].p_offset + bp->b_blkno;
 1075         mp->mscp_unit = rx->ra_hwunit;
 1076         mp->mscp_seq.seq_bytecount = bp->b_bcount;
 1077 }
 1078 
 1079 /*
 1080  * A bad block related operation finished.
 1081  */
 1082 /*ARGSUSED*/
 1083 void
 1084 rrbb(usc, mp, bp)
 1085         struct device *usc;
 1086         struct mscp *mp;
 1087         struct buf *bp;
 1088 {
 1089 
 1090         panic("udabb");
 1091 }

Cache object: d1cc7cfa7809a32fe77575bcc29b0500


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