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/mca/ed_mca.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: ed_mca.c,v 1.22 2003/06/29 22:30:22 fvdl Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2001 The NetBSD Foundation, Inc.
    5  *
    6  * This code is derived from software contributed to The NetBSD Foundation
    7  * by Jaromir Dolecek.
    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. All advertising materials mentioning features or use of this software
   18  *    must display the following acknowledgement:
   19  *        This product includes software developed by the NetBSD
   20  *        Foundation, Inc. and its contributors.
   21  * 4. The name of the author may not be used to endorse or promote products
   22  *    derived from this software without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   27  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   33  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   34  */
   35 
   36 /*
   37  * Disk drive goo for MCA ESDI controller driver.
   38  */
   39 
   40 #include <sys/cdefs.h>
   41 __KERNEL_RCSID(0, "$NetBSD: ed_mca.c,v 1.22 2003/06/29 22:30:22 fvdl Exp $");
   42 
   43 #include "rnd.h"
   44 #include "locators.h"
   45 
   46 #include <sys/param.h>
   47 #include <sys/systm.h>
   48 #include <sys/kernel.h>
   49 #include <sys/conf.h>
   50 #include <sys/file.h>
   51 #include <sys/stat.h>
   52 #include <sys/ioctl.h>
   53 #include <sys/buf.h>
   54 #include <sys/uio.h>
   55 #include <sys/malloc.h>
   56 #include <sys/device.h>
   57 #include <sys/disklabel.h>
   58 #include <sys/disk.h>
   59 #include <sys/syslog.h>
   60 #include <sys/proc.h>
   61 #include <sys/vnode.h>
   62 #if NRND > 0
   63 #include <sys/rnd.h>
   64 #endif
   65 
   66 #include <machine/intr.h>
   67 #include <machine/bus.h>
   68 
   69 #include <dev/mca/mcavar.h>
   70 
   71 #include <dev/mca/edcreg.h>
   72 #include <dev/mca/edvar.h>
   73 #include <dev/mca/edcvar.h>
   74 
   75 /* #define WDCDEBUG */
   76 
   77 #ifdef WDCDEBUG
   78 #define WDCDEBUG_PRINT(args, level)  printf args
   79 #else
   80 #define WDCDEBUG_PRINT(args, level)
   81 #endif
   82 
   83 #define EDLABELDEV(dev) (MAKEDISKDEV(major(dev), DISKUNIT(dev), RAW_PART))
   84 
   85 static int     ed_mca_probe   __P((struct device *, struct cfdata *, void *));
   86 static void    ed_mca_attach  __P((struct device *, struct device *, void *));
   87 
   88 CFATTACH_DECL(ed_mca, sizeof(struct ed_softc),
   89     ed_mca_probe, ed_mca_attach, NULL, NULL);
   90 
   91 extern struct cfdriver ed_cd;
   92 
   93 static int      ed_get_params __P((struct ed_softc *, int *));
   94 static int      ed_lock __P((struct ed_softc *));
   95 static void     ed_unlock       __P((struct ed_softc *));
   96 static void     edgetdisklabel  __P((dev_t, struct ed_softc *));
   97 static void     edgetdefaultlabel __P((struct ed_softc *, struct disklabel *));
   98 
   99 dev_type_open(edmcaopen);
  100 dev_type_close(edmcaclose);
  101 dev_type_read(edmcaread);
  102 dev_type_write(edmcawrite);
  103 dev_type_ioctl(edmcaioctl);
  104 dev_type_strategy(edmcastrategy);
  105 dev_type_dump(edmcadump);
  106 dev_type_size(edmcasize);
  107 
  108 const struct bdevsw ed_bdevsw = {
  109         edmcaopen, edmcaclose, edmcastrategy, edmcaioctl,
  110         edmcadump, edmcasize, D_DISK
  111 };
  112 
  113 const struct cdevsw ed_cdevsw = {
  114         edmcaopen, edmcaclose, edmcaread, edmcawrite, edmcaioctl,
  115         nostop, notty, nopoll, nommap, nokqfilter, D_DISK
  116 };
  117 
  118 static struct dkdriver eddkdriver = { edmcastrategy };
  119 
  120 /*
  121  * Just check if it's possible to identify the disk.
  122  */
  123 static int
  124 ed_mca_probe(parent, cf, aux)
  125         struct device *parent;
  126         struct cfdata *cf;
  127         void *aux;
  128 {
  129         u_int16_t cmd_args[2];
  130         struct edc_mca_softc *sc = (void *) parent;
  131         struct ed_attach_args *eda = (struct ed_attach_args *) aux;
  132         int found = 1;
  133 
  134         /*
  135          * Check we match hardwired config.
  136          */
  137         if (cf->edccf_unit != EDCCF_DRIVE_DEFAULT &&
  138             cf->edccf_unit != eda->edc_drive)
  139                 return (0);
  140 
  141         /*
  142          * Get Device Configuration (09).
  143          */
  144         cmd_args[0] = 14;       /* Options: 00s110, s: 0=Physical 1=Pseudo */
  145         cmd_args[1] = 0;
  146         if (edc_run_cmd(sc, CMD_GET_DEV_CONF, eda->edc_drive, cmd_args, 2, 1))
  147                 found = 0;
  148 
  149         return (found);
  150 }
  151 
  152 static void
  153 ed_mca_attach(parent, self, aux)
  154         struct device *parent, *self;
  155         void *aux;
  156 {
  157         struct ed_softc *ed = (void *) self;
  158         struct edc_mca_softc *sc = (void *) parent;
  159         struct ed_attach_args *eda = (struct ed_attach_args *) aux;
  160         char pbuf[8], lckname[10];
  161         int drv_flags;
  162 
  163         ed->edc_softc = sc;
  164         ed->sc_devno  = eda->edc_drive;
  165         edc_add_disk(sc, ed);
  166 
  167         bufq_alloc(&ed->sc_q, BUFQ_DISKSORT|BUFQ_SORT_RAWBLOCK);
  168         simple_lock_init(&ed->sc_q_lock);
  169         snprintf(lckname, sizeof(lckname), "%slck", ed->sc_dev.dv_xname);
  170         lockinit(&ed->sc_lock, PRIBIO | PCATCH, lckname, 0, 0);
  171 
  172         if (ed_get_params(ed, &drv_flags)) {
  173                 printf(": IDENTIFY failed, no disk found\n");
  174                 return;
  175         }
  176 
  177         format_bytes(pbuf, sizeof(pbuf),
  178                 (u_int64_t) ed->sc_capacity * DEV_BSIZE);
  179         printf(": %s, %u cyl, %u head, %u sec, 512 bytes/sect x %u sectors\n",
  180                 pbuf,
  181                 ed->cyl, ed->heads, ed->sectors,
  182                 ed->sc_capacity);
  183 
  184         printf("%s: %u spares/cyl, %s, %s, %s, %s, %s\n",
  185                 ed->sc_dev.dv_xname, ed->spares,
  186                 (drv_flags & (1 << 0)) ? "NoRetries" : "Retries",
  187                 (drv_flags & (1 << 1)) ? "Removable" : "Fixed",
  188                 (drv_flags & (1 << 2)) ? "SkewedFormat" : "NoSkew",
  189                 (drv_flags & (1 << 3)) ? "ZeroDefect" : "Defects",
  190                 (drv_flags & (1 << 4)) ? "InvalidSecondary" : "SecondaryOK"
  191                 );
  192 
  193         /*
  194          * Initialize and attach the disk structure.
  195          */
  196         ed->sc_dk.dk_driver = &eddkdriver;
  197         ed->sc_dk.dk_name = ed->sc_dev.dv_xname;
  198         disk_attach(&ed->sc_dk);
  199 #if NRND > 0
  200         rnd_attach_source(&ed->rnd_source, ed->sc_dev.dv_xname,
  201                           RND_TYPE_DISK, 0);
  202 #endif
  203 
  204         ed->sc_flags |= EDF_INIT;
  205 }
  206 
  207 /*
  208  * Read/write routine for a buffer.  Validates the arguments and schedules the
  209  * transfer.  Does not wait for the transfer to complete.
  210  */
  211 void
  212 edmcastrategy(bp)
  213         struct buf *bp;
  214 {
  215         struct ed_softc *ed = device_lookup(&ed_cd, DISKUNIT(bp->b_dev));
  216         struct disklabel *lp = ed->sc_dk.dk_label;
  217         daddr_t blkno;
  218 
  219         WDCDEBUG_PRINT(("edmcastrategy (%s)\n", ed->sc_dev.dv_xname),
  220             DEBUG_XFERS);
  221 
  222         /* Valid request?  */
  223         if (bp->b_blkno < 0 ||
  224             (bp->b_bcount % lp->d_secsize) != 0 ||
  225             (bp->b_bcount / lp->d_secsize) >= (1 << NBBY)) {
  226                 bp->b_error = EINVAL;
  227                 goto bad;
  228         }
  229 
  230         /* If device invalidated (e.g. media change, door open), error. */
  231         if ((ed->sc_flags & WDF_LOADED) == 0) {
  232                 bp->b_error = EIO;
  233                 goto bad;
  234         }
  235 
  236         /* If it's a null transfer, return immediately. */
  237         if (bp->b_bcount == 0)
  238                 goto done;
  239 
  240         /*
  241          * Do bounds checking, adjust transfer. if error, process.
  242          * If end of partition, just return.
  243          */
  244         if (DISKPART(bp->b_dev) != RAW_PART &&
  245             bounds_check_with_label(&ed->sc_dk, bp,
  246             (ed->sc_flags & (WDF_WLABEL|WDF_LABELLING)) != 0) <= 0)
  247                 goto done;
  248 
  249         /*
  250          * Now convert the block number to absolute and put it in
  251          * terms of the device's logical block size.
  252          */
  253         if (lp->d_secsize >= DEV_BSIZE)
  254                 blkno = bp->b_blkno / (lp->d_secsize / DEV_BSIZE);
  255         else
  256                 blkno = bp->b_blkno * (DEV_BSIZE / lp->d_secsize);
  257 
  258         if (DISKPART(bp->b_dev) != RAW_PART)
  259                 blkno += lp->d_partitions[DISKPART(bp->b_dev)].p_offset;
  260 
  261         bp->b_rawblkno = blkno;
  262 
  263         /* Queue transfer on drive, activate drive and controller if idle. */
  264         simple_lock(&ed->sc_q_lock);
  265         BUFQ_PUT(&ed->sc_q, bp);
  266         simple_unlock(&ed->sc_q_lock);
  267 
  268         /* Ring the worker thread */
  269         wakeup_one(ed->edc_softc);
  270 
  271         return;
  272 bad:
  273         bp->b_flags |= B_ERROR;
  274 done:
  275         /* Toss transfer; we're done early. */
  276         bp->b_resid = bp->b_bcount;
  277         biodone(bp);
  278 }
  279 
  280 int
  281 edmcaread(dev, uio, flags)
  282         dev_t dev;
  283         struct uio *uio;
  284         int flags;
  285 {
  286         WDCDEBUG_PRINT(("edread\n"), DEBUG_XFERS);
  287         return (physio(edmcastrategy, NULL, dev, B_READ, minphys, uio));
  288 }
  289 
  290 int
  291 edmcawrite(dev, uio, flags)
  292         dev_t dev;
  293         struct uio *uio;
  294         int flags;
  295 {
  296         WDCDEBUG_PRINT(("edwrite\n"), DEBUG_XFERS);
  297         return (physio(edmcastrategy, NULL, dev, B_WRITE, minphys, uio));
  298 }
  299 
  300 /*
  301  * Wait interruptibly for an exclusive lock.
  302  */
  303 static int
  304 ed_lock(ed)
  305         struct ed_softc *ed;
  306 {
  307         int error;
  308         int s;
  309 
  310         WDCDEBUG_PRINT(("ed_lock\n"), DEBUG_FUNCS);
  311 
  312         s = splbio();
  313         error = lockmgr(&ed->sc_lock, LK_EXCLUSIVE, NULL);
  314         splx(s);
  315 
  316         return (error);
  317 }
  318 
  319 /*
  320  * Unlock and wake up any waiters.
  321  */
  322 static void
  323 ed_unlock(ed)
  324         struct ed_softc *ed;
  325 {
  326         WDCDEBUG_PRINT(("ed_unlock\n"), DEBUG_FUNCS);
  327 
  328         (void) lockmgr(&ed->sc_lock, LK_RELEASE, NULL);
  329 }
  330 
  331 int
  332 edmcaopen(dev, flag, fmt, p)
  333         dev_t dev;
  334         int flag, fmt;
  335         struct proc *p;
  336 {
  337         struct ed_softc *wd;
  338         int part, error;
  339 
  340         WDCDEBUG_PRINT(("edopen\n"), DEBUG_FUNCS);
  341         wd = device_lookup(&ed_cd, DISKUNIT(dev));
  342         if (wd == NULL || (wd->sc_flags & EDF_INIT) == 0)
  343                 return (ENXIO);
  344 
  345         if ((error = ed_lock(wd)) != 0)
  346                 goto bad4;
  347 
  348         if (wd->sc_dk.dk_openmask != 0) {
  349                 /*
  350                  * If any partition is open, but the disk has been invalidated,
  351                  * disallow further opens.
  352                  */
  353                 if ((wd->sc_flags & WDF_LOADED) == 0) {
  354                         error = EIO;
  355                         goto bad3;
  356                 }
  357         } else {
  358                 if ((wd->sc_flags & WDF_LOADED) == 0) {
  359                         int s;
  360 
  361                         wd->sc_flags |= WDF_LOADED;
  362 
  363                         /* Load the physical device parameters. */
  364                         s = splbio();
  365                         ed_get_params(wd, NULL);
  366                         splx(s);
  367 
  368                         /* Load the partition info if not already loaded. */
  369                         edgetdisklabel(dev, wd);
  370                 }
  371         }
  372 
  373         part = DISKPART(dev);
  374 
  375         /* Check that the partition exists. */
  376         if (part != RAW_PART &&
  377             (part >= wd->sc_dk.dk_label->d_npartitions ||
  378              wd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
  379                 error = ENXIO;
  380                 goto bad;
  381         }
  382 
  383         /* Insure only one open at a time. */
  384         switch (fmt) {
  385         case S_IFCHR:
  386                 wd->sc_dk.dk_copenmask |= (1 << part);
  387                 break;
  388         case S_IFBLK:
  389                 wd->sc_dk.dk_bopenmask |= (1 << part);
  390                 break;
  391         }
  392         wd->sc_dk.dk_openmask =
  393             wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
  394 
  395         ed_unlock(wd);
  396         return 0;
  397 
  398 bad:
  399         if (wd->sc_dk.dk_openmask == 0) {
  400         }
  401 
  402 bad3:
  403         ed_unlock(wd);
  404 bad4:
  405         return (error);
  406 }
  407 
  408 int
  409 edmcaclose(dev, flag, fmt, p)
  410         dev_t dev;
  411         int flag, fmt;
  412         struct proc *p;
  413 {
  414         struct ed_softc *wd = device_lookup(&ed_cd, DISKUNIT(dev));
  415         int part = DISKPART(dev);
  416         int error;
  417 
  418         WDCDEBUG_PRINT(("edmcaclose\n"), DEBUG_FUNCS);
  419         if ((error = ed_lock(wd)) != 0)
  420                 return error;
  421 
  422         switch (fmt) {
  423         case S_IFCHR:
  424                 wd->sc_dk.dk_copenmask &= ~(1 << part);
  425                 break;
  426         case S_IFBLK:
  427                 wd->sc_dk.dk_bopenmask &= ~(1 << part);
  428                 break;
  429         }
  430         wd->sc_dk.dk_openmask =
  431             wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
  432 
  433         if (wd->sc_dk.dk_openmask == 0) {
  434 #if 0
  435                 wd_flushcache(wd, AT_WAIT);
  436 #endif
  437                 /* XXXX Must wait for I/O to complete! */
  438 
  439                 if (! (wd->sc_flags & WDF_KLABEL))
  440                         wd->sc_flags &= ~WDF_LOADED;
  441         }
  442 
  443         ed_unlock(wd);
  444 
  445         return 0;
  446 }
  447 
  448 static void
  449 edgetdefaultlabel(ed, lp)
  450         struct ed_softc *ed;
  451         struct disklabel *lp;
  452 {
  453         WDCDEBUG_PRINT(("edgetdefaultlabel\n"), DEBUG_FUNCS);
  454         memset(lp, 0, sizeof(struct disklabel));
  455 
  456         lp->d_secsize = DEV_BSIZE;
  457         lp->d_ntracks = ed->heads;
  458         lp->d_nsectors = ed->sectors;
  459         lp->d_ncylinders = ed->cyl;
  460         lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
  461 
  462         lp->d_type = DTYPE_ESDI;
  463 
  464         strncpy(lp->d_typename, "ESDI", 16);
  465         strncpy(lp->d_packname, "fictitious", 16);
  466         lp->d_secperunit = ed->sc_capacity;
  467         lp->d_rpm = 3600;
  468         lp->d_interleave = 1;
  469         lp->d_flags = 0;
  470 
  471         lp->d_partitions[RAW_PART].p_offset = 0;
  472         lp->d_partitions[RAW_PART].p_size =
  473         lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);
  474         lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
  475         lp->d_npartitions = RAW_PART + 1;
  476 
  477         lp->d_magic = DISKMAGIC;
  478         lp->d_magic2 = DISKMAGIC;
  479         lp->d_checksum = dkcksum(lp);
  480 }
  481 
  482 /*
  483  * Fabricate a default disk label, and try to read the correct one.
  484  */
  485 static void
  486 edgetdisklabel(dev, ed)
  487         dev_t dev;
  488         struct ed_softc *ed;
  489 {
  490         struct disklabel *lp = ed->sc_dk.dk_label;
  491         const char *errstring;
  492 
  493         WDCDEBUG_PRINT(("edgetdisklabel\n"), DEBUG_FUNCS);
  494 
  495         memset(ed->sc_dk.dk_cpulabel, 0, sizeof(struct cpu_disklabel));
  496 
  497         edgetdefaultlabel(ed, lp);
  498 
  499         errstring = readdisklabel(
  500             EDLABELDEV(dev), edmcastrategy, lp, ed->sc_dk.dk_cpulabel);
  501         if (errstring) {
  502                 /*
  503                  * This probably happened because the drive's default
  504                  * geometry doesn't match the DOS geometry.  We
  505                  * assume the DOS geometry is now in the label and try
  506                  * again.  XXX This is a kluge.
  507                  */
  508 #if 0
  509                 if (wd->drvp->state > RECAL)
  510                         wd->drvp->drive_flags |= DRIVE_RESET;
  511 #endif
  512                 errstring = readdisklabel(EDLABELDEV(dev),
  513                         edmcastrategy, lp, ed->sc_dk.dk_cpulabel);
  514         }
  515         if (errstring) {
  516                 printf("%s: %s\n", ed->sc_dev.dv_xname, errstring);
  517                 return;
  518         }
  519 }
  520 
  521 int
  522 edmcaioctl(dev, xfer, addr, flag, p)
  523         dev_t dev;
  524         u_long xfer;
  525         caddr_t addr;
  526         int flag;
  527         struct proc *p;
  528 {
  529         struct ed_softc *ed = device_lookup(&ed_cd, DISKUNIT(dev));
  530         int error;
  531 
  532         WDCDEBUG_PRINT(("edioctl\n"), DEBUG_FUNCS);
  533 
  534         if ((ed->sc_flags & WDF_LOADED) == 0)
  535                 return EIO;
  536 
  537         switch (xfer) {
  538         case DIOCGDINFO:
  539                 *(struct disklabel *)addr = *(ed->sc_dk.dk_label);
  540                 return 0;
  541 
  542         case DIOCGPART:
  543                 ((struct partinfo *)addr)->disklab = ed->sc_dk.dk_label;
  544                 ((struct partinfo *)addr)->part =
  545                     &ed->sc_dk.dk_label->d_partitions[DISKPART(dev)];
  546                 return 0;
  547 
  548         case DIOCWDINFO:
  549         case DIOCSDINFO:
  550         {
  551                 struct disklabel *lp;
  552 
  553                 lp = (struct disklabel *)addr;
  554 
  555                 if ((flag & FWRITE) == 0)
  556                         return EBADF;
  557 
  558                 if ((error = ed_lock(ed)) != 0)
  559                         return error;
  560                 ed->sc_flags |= WDF_LABELLING;
  561 
  562                 error = setdisklabel(ed->sc_dk.dk_label,
  563                     lp, /*wd->sc_dk.dk_openmask : */0,
  564                     ed->sc_dk.dk_cpulabel);
  565                 if (error == 0) {
  566 #if 0
  567                         if (wd->drvp->state > RECAL)
  568                                 wd->drvp->drive_flags |= DRIVE_RESET;
  569 #endif
  570                         if (xfer == DIOCWDINFO)
  571                                 error = writedisklabel(EDLABELDEV(dev),
  572                                     edmcastrategy, ed->sc_dk.dk_label,
  573                                     ed->sc_dk.dk_cpulabel);
  574                 }
  575 
  576                 ed->sc_flags &= ~WDF_LABELLING;
  577                 ed_unlock(ed);
  578                 return (error);
  579         }
  580 
  581         case DIOCKLABEL:
  582                 if (*(int *)addr)
  583                         ed->sc_flags |= WDF_KLABEL;
  584                 else
  585                         ed->sc_flags &= ~WDF_KLABEL;
  586                 return 0;
  587 
  588         case DIOCWLABEL:
  589                 if ((flag & FWRITE) == 0)
  590                         return EBADF;
  591                 if (*(int *)addr)
  592                         ed->sc_flags |= WDF_WLABEL;
  593                 else
  594                         ed->sc_flags &= ~WDF_WLABEL;
  595                 return 0;
  596 
  597         case DIOCGDEFLABEL:
  598                 edgetdefaultlabel(ed, (struct disklabel *)addr);
  599                 return 0;
  600 
  601 #if 0
  602         case DIOCWFORMAT:
  603                 if ((flag & FWRITE) == 0)
  604                         return EBADF;
  605                 {
  606                 register struct format_op *fop;
  607                 struct iovec aiov;
  608                 struct uio auio;
  609 
  610                 fop = (struct format_op *)addr;
  611                 aiov.iov_base = fop->df_buf;
  612                 aiov.iov_len = fop->df_count;
  613                 auio.uio_iov = &aiov;
  614                 auio.uio_iovcnt = 1;
  615                 auio.uio_resid = fop->df_count;
  616                 auio.uio_segflg = 0;
  617                 auio.uio_offset =
  618                         fop->df_startblk * wd->sc_dk.dk_label->d_secsize;
  619                 auio.uio_procp = p;
  620                 error = physio(wdformat, NULL, dev, B_WRITE, minphys,
  621                     &auio);
  622                 fop->df_count -= auio.uio_resid;
  623                 fop->df_reg[0] = wdc->sc_status;
  624                 fop->df_reg[1] = wdc->sc_error;
  625                 return error;
  626                 }
  627 #endif
  628 
  629         default:
  630                 return ENOTTY;
  631         }
  632 
  633 #ifdef DIAGNOSTIC
  634         panic("edioctl: impossible");
  635 #endif
  636 }
  637 
  638 int
  639 edmcasize(dev)
  640         dev_t dev;
  641 {
  642         struct ed_softc *wd;
  643         int part, omask;
  644         int size;
  645 
  646         WDCDEBUG_PRINT(("edsize\n"), DEBUG_FUNCS);
  647 
  648         wd = device_lookup(&ed_cd, DISKUNIT(dev));
  649         if (wd == NULL)
  650                 return (-1);
  651 
  652         part = DISKPART(dev);
  653         omask = wd->sc_dk.dk_openmask & (1 << part);
  654 
  655         if (omask == 0 && edmcaopen(dev, 0, S_IFBLK, NULL) != 0)
  656                 return (-1);
  657         if (wd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
  658                 size = -1;
  659         else
  660                 size = wd->sc_dk.dk_label->d_partitions[part].p_size *
  661                     (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
  662         if (omask == 0 && edmcaclose(dev, 0, S_IFBLK, NULL) != 0)
  663                 return (-1);
  664         return (size);
  665 }
  666 
  667 /* #define WD_DUMP_NOT_TRUSTED if you just want to watch */
  668 static int eddoingadump = 0;
  669 static int eddumprecalibrated = 0;
  670 static int eddumpmulti = 1;
  671 
  672 /*
  673  * Dump core after a system crash.
  674  */
  675 int
  676 edmcadump(dev, blkno, va, size)
  677         dev_t dev;
  678         daddr_t blkno;
  679         caddr_t va;
  680         size_t size;
  681 {
  682         struct ed_softc *ed;    /* disk unit to do the I/O */
  683         struct disklabel *lp;   /* disk's disklabel */
  684         int part;
  685         int nblks;      /* total number of sectors left to write */
  686         int error;
  687 
  688         /* Check if recursive dump; if so, punt. */
  689         if (eddoingadump)
  690                 return EFAULT;
  691         eddoingadump = 1;
  692 
  693         ed = device_lookup(&ed_cd, DISKUNIT(dev));
  694         if (ed == NULL)
  695                 return (ENXIO);
  696 
  697         part = DISKPART(dev);
  698 
  699         /* Make sure it was initialized. */
  700         if ((ed->sc_flags & EDF_INIT) == 0)
  701                 return ENXIO;
  702 
  703         /* Convert to disk sectors.  Request must be a multiple of size. */
  704         lp = ed->sc_dk.dk_label;
  705         if ((size % lp->d_secsize) != 0)
  706                 return EFAULT;
  707         nblks = size / lp->d_secsize;
  708         blkno = blkno / (lp->d_secsize / DEV_BSIZE);
  709 
  710         /* Check transfer bounds against partition size. */
  711         if ((blkno < 0) || ((blkno + nblks) > lp->d_partitions[part].p_size))
  712                 return EINVAL;
  713 
  714         /* Offset block number to start of partition. */
  715         blkno += lp->d_partitions[part].p_offset;
  716 
  717         /* Recalibrate, if first dump transfer. */
  718         if (eddumprecalibrated == 0) {
  719                 eddumprecalibrated = 1;
  720                 eddumpmulti = 8;
  721 #if 0
  722                 wd->drvp->state = RESET;
  723 #endif
  724         }
  725 
  726         while (nblks > 0) {
  727                 error = edc_bio(ed->edc_softc, ed, va, blkno,
  728                         min(nblks, eddumpmulti) * lp->d_secsize, 0, 1);
  729                 if (error)
  730                         return (error);
  731 
  732                 /* update block count */
  733                 nblks -= min(nblks, eddumpmulti);
  734                 blkno += min(nblks, eddumpmulti);
  735                 va += min(nblks, eddumpmulti) * lp->d_secsize;
  736         }
  737 
  738         eddoingadump = 0;
  739         return (0);
  740 }
  741 
  742 static int
  743 ed_get_params(ed, drv_flags)
  744         struct ed_softc *ed;
  745         int *drv_flags;
  746 {
  747         u_int16_t cmd_args[2];
  748 
  749         /*
  750          * Get Device Configuration (09).
  751          */
  752         cmd_args[0] = 14;       /* Options: 00s110, s: 0=Physical 1=Pseudo */
  753         cmd_args[1] = 0;
  754         if (edc_run_cmd(ed->edc_softc, CMD_GET_DEV_CONF, ed->sc_devno,
  755             cmd_args, 2, 1))
  756                 return (1);
  757 
  758         ed->spares = ed->sense_data[1] >> 8;
  759         if (drv_flags)
  760                 *drv_flags = ed->sense_data[1] & 0x1f;
  761         ed->rba = ed->sense_data[2] | (ed->sense_data[3] << 16);
  762         /* Instead of using:
  763                 ed->cyl = ed->sense_data[4];
  764                 ed->heads = ed->sense_data[5] & 0xff;
  765                 ed->sectors = ed->sense_data[5] >> 8;
  766          * we fabricate the numbers from RBA count, so that
  767          * number of sectors is 32 and heads 64. This seems
  768          * to be necessary for integrated ESDI controller.
  769          */
  770         ed->sectors = 32;
  771         ed->heads = 64;
  772         ed->cyl = ed->rba / (ed->heads * ed->sectors);
  773         ed->sc_capacity = ed->rba;
  774 
  775         return (0);
  776 }

Cache object: efa31f4f368c33a923999b6f5c1cd851


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