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/ata/ata-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 /*-
    2  * Copyright (c) 1998 - 2007 Søren Schmidt <sos@FreeBSD.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer,
   10  *    without modification, immediately at the beginning of the file.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include "opt_ata.h"
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/ata.h>
   34 #include <sys/kernel.h>
   35 #include <sys/module.h>
   36 #include <sys/malloc.h>
   37 #include <sys/bio.h>
   38 #include <sys/bus.h>
   39 #include <sys/conf.h>
   40 #include <sys/disk.h>
   41 #include <sys/cons.h>
   42 #include <sys/sysctl.h>
   43 #include <sys/sema.h>
   44 #include <sys/taskqueue.h>
   45 #include <vm/uma.h>
   46 #include <machine/md_var.h>
   47 #include <machine/bus.h>
   48 #include <sys/rman.h>
   49 #include <geom/geom_disk.h>
   50 #include <dev/ata/ata-all.h>
   51 #include <dev/ata/ata-pci.h>
   52 #include <dev/ata/ata-disk.h>
   53 #include <dev/ata/ata-raid.h>
   54 #include <ata_if.h>
   55 
   56 /* prototypes */
   57 static void ad_init(device_t);
   58 static void ad_done(struct ata_request *);
   59 static void ad_describe(device_t dev);
   60 static int ad_version(u_int16_t);
   61 static disk_strategy_t ad_strategy;
   62 static disk_ioctl_t ad_ioctl;
   63 static dumper_t ad_dump;
   64 
   65 /*
   66  * Most platforms map firmware geom to actual, but some don't.  If
   67  * not overridden, default to nothing.
   68  */
   69 #ifndef ad_firmware_geom_adjust
   70 #define ad_firmware_geom_adjust(dev, disk)
   71 #endif
   72 
   73 /* local vars */
   74 static MALLOC_DEFINE(M_AD, "ad_driver", "ATA disk driver");
   75 
   76 static int
   77 ad_probe(device_t dev)
   78 {
   79     struct ata_device *atadev = device_get_softc(dev);
   80 
   81     if (!(atadev->param.config & ATA_PROTO_ATAPI) ||
   82         (atadev->param.config == ATA_CFA_MAGIC1) ||
   83         (atadev->param.config == ATA_CFA_MAGIC2) ||
   84         (atadev->param.config == ATA_CFA_MAGIC3))
   85         return 0;
   86     else
   87         return ENXIO;
   88 }
   89 
   90 static int
   91 ad_attach(device_t dev)
   92 {
   93     struct ata_channel *ch = device_get_softc(device_get_parent(dev));
   94     struct ata_device *atadev = device_get_softc(dev);
   95     struct ad_softc *adp;
   96     u_int32_t lbasize;
   97     u_int64_t lbasize48;
   98 
   99     /* check that we have a virgin disk to attach */
  100     if (device_get_ivars(dev))
  101         return EEXIST;
  102 
  103     if (!(adp = malloc(sizeof(struct ad_softc), M_AD, M_NOWAIT | M_ZERO))) {
  104         device_printf(dev, "out of memory\n");
  105         return ENOMEM;
  106     }
  107     device_set_ivars(dev, adp);
  108 
  109     if ((atadev->param.atavalid & ATA_FLAG_54_58) &&
  110         atadev->param.current_heads && atadev->param.current_sectors) {
  111         adp->heads = atadev->param.current_heads;
  112         adp->sectors = atadev->param.current_sectors;
  113         adp->total_secs = (u_int32_t)atadev->param.current_size_1 |
  114                           ((u_int32_t)atadev->param.current_size_2 << 16);
  115     }
  116     else {
  117         adp->heads = atadev->param.heads;
  118         adp->sectors = atadev->param.sectors;
  119         adp->total_secs = atadev->param.cylinders * adp->heads * adp->sectors;  
  120     }
  121     lbasize = (u_int32_t)atadev->param.lba_size_1 |
  122               ((u_int32_t)atadev->param.lba_size_2 << 16);
  123 
  124     /* does this device need oldstyle CHS addressing */
  125     if (!ad_version(atadev->param.version_major) || !lbasize)
  126         atadev->flags |= ATA_D_USE_CHS;
  127 
  128     /* use the 28bit LBA size if valid or bigger than the CHS mapping */
  129     if (atadev->param.cylinders == 16383 || adp->total_secs < lbasize)
  130         adp->total_secs = lbasize;
  131 
  132     /* use the 48bit LBA size if valid */
  133     lbasize48 = ((u_int64_t)atadev->param.lba_size48_1) |
  134                 ((u_int64_t)atadev->param.lba_size48_2 << 16) |
  135                 ((u_int64_t)atadev->param.lba_size48_3 << 32) |
  136                 ((u_int64_t)atadev->param.lba_size48_4 << 48);
  137     if ((atadev->param.support.command2 & ATA_SUPPORT_ADDRESS48) &&
  138         lbasize48 > ATA_MAX_28BIT_LBA)
  139         adp->total_secs = lbasize48;
  140 
  141     /* init device parameters */
  142     ad_init(dev);
  143 
  144     /* announce we are here */
  145     ad_describe(dev);
  146 
  147     /* create the disk device */
  148     adp->disk = disk_alloc();
  149     adp->disk->d_strategy = ad_strategy;
  150     adp->disk->d_ioctl = ad_ioctl;
  151     adp->disk->d_dump = ad_dump;
  152     adp->disk->d_name = "ad";
  153     adp->disk->d_drv1 = dev;
  154     if (ch->dma)
  155         adp->disk->d_maxsize = ch->dma->max_iosize;
  156     else
  157         adp->disk->d_maxsize = DFLTPHYS;
  158     adp->disk->d_sectorsize = DEV_BSIZE;
  159     adp->disk->d_mediasize = DEV_BSIZE * (off_t)adp->total_secs;
  160     adp->disk->d_fwsectors = adp->sectors;
  161     adp->disk->d_fwheads = adp->heads;
  162     adp->disk->d_unit = device_get_unit(dev);
  163     if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE)
  164         adp->disk->d_flags = DISKFLAG_CANFLUSHCACHE;
  165     if ((atadev->param.support.command2 & ATA_SUPPORT_CFA) ||
  166         atadev->param.config == ATA_PROTO_CFA)
  167         adp->disk->d_flags = DISKFLAG_CANDELETE;
  168     snprintf(adp->disk->d_ident, sizeof(adp->disk->d_ident), "ad:%s",
  169         atadev->param.serial);
  170     disk_create(adp->disk, DISK_VERSION);
  171     device_add_child(dev, "subdisk", device_get_unit(dev));
  172     ad_firmware_geom_adjust(dev, adp->disk);
  173     bus_generic_attach(dev);
  174 
  175     callout_init(&atadev->spindown_timer, 1);
  176     return 0;
  177 }
  178 
  179 static int
  180 ad_detach(device_t dev)
  181 {
  182     struct ad_softc *adp = device_get_ivars(dev);
  183     struct ata_device *atadev = device_get_softc(dev);
  184     device_t *children;
  185     int nchildren, i;
  186 
  187     /* check that we have a valid disk to detach */
  188     if (!device_get_ivars(dev))
  189         return ENXIO;
  190     
  191     /* destroy the power timeout */
  192     callout_drain(&atadev->spindown_timer);
  193 
  194     /* detach & delete all children */
  195     if (!device_get_children(dev, &children, &nchildren)) {
  196         for (i = 0; i < nchildren; i++)
  197             if (children[i])
  198                 device_delete_child(dev, children[i]);
  199         free(children, M_TEMP);
  200     }
  201 
  202     /* detroy disk from the system so we dont get any further requests */
  203     disk_destroy(adp->disk);
  204 
  205     /* fail requests on the queue and any thats "in flight" for this device */
  206     ata_fail_requests(dev);
  207 
  208     /* dont leave anything behind */
  209     device_set_ivars(dev, NULL);
  210     free(adp, M_AD);
  211     return 0;
  212 }
  213 
  214 static void
  215 ad_shutdown(device_t dev)
  216 {
  217     struct ata_device *atadev = device_get_softc(dev);
  218 
  219     if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE)
  220         ata_controlcmd(dev, ATA_FLUSHCACHE, 0, 0, 0);
  221 }
  222 
  223 static int
  224 ad_reinit(device_t dev)
  225 {
  226     struct ata_channel *ch = device_get_softc(device_get_parent(dev));
  227     struct ata_device *atadev = device_get_softc(dev);
  228 
  229     /* if detach pending, return error */
  230     if (((atadev->unit == ATA_MASTER) && !(ch->devices & ATA_ATA_MASTER)) ||
  231         ((atadev->unit == ATA_SLAVE) && !(ch->devices & ATA_ATA_SLAVE))) {
  232         return 1;
  233     }
  234     ad_init(dev);
  235     return 0;
  236 }
  237 
  238 static void
  239 ad_power_callback(struct ata_request *request)
  240 {
  241     device_printf(request->dev, "drive spun down.\n");
  242     ata_free_request(request);
  243 }
  244 
  245 static void
  246 ad_spindown(void *priv)
  247 {
  248     device_t dev = priv;
  249     struct ata_device *atadev = device_get_softc(dev);
  250     struct ata_request *request;
  251 
  252     if(atadev->spindown == 0)
  253         return;
  254     device_printf(dev, "Idle, spin down\n");
  255     atadev->spindown_state = 1;
  256     if (!(request = ata_alloc_request())) {
  257         device_printf(dev, "FAILURE - out of memory in ad_spindown\n");
  258         return;
  259     }
  260     request->flags = ATA_R_CONTROL;
  261     request->dev = dev;
  262     request->timeout = 5;
  263     request->retries = 1;
  264     request->callback = ad_power_callback;
  265     request->u.ata.command = ATA_STANDBY_IMMEDIATE;
  266     ata_queue_request(request);
  267 }
  268 
  269 
  270 static void 
  271 ad_strategy(struct bio *bp)
  272 {
  273     device_t dev =  bp->bio_disk->d_drv1;
  274     struct ata_device *atadev = device_get_softc(dev);
  275     struct ata_request *request;
  276 
  277     if (atadev->spindown != 0)
  278         callout_reset(&atadev->spindown_timer, hz * atadev->spindown,
  279             ad_spindown, dev);
  280 
  281     if (!(request = ata_alloc_request())) {
  282         device_printf(dev, "FAILURE - out of memory in start\n");
  283         biofinish(bp, NULL, ENOMEM);
  284         return;
  285     }
  286 
  287     /* setup request */
  288     request->dev = dev;
  289     request->bio = bp;
  290     request->callback = ad_done;
  291     if (atadev->spindown_state) {
  292         device_printf(dev, "request while spun down, starting.\n");
  293         atadev->spindown_state = 0;
  294         request->timeout = 31;
  295     } else {
  296         request->timeout = 5;
  297     }
  298     request->retries = 2;
  299     request->data = bp->bio_data;
  300     request->bytecount = bp->bio_bcount;
  301     request->u.ata.lba = bp->bio_pblkno;
  302     request->u.ata.count = request->bytecount / DEV_BSIZE;
  303     request->transfersize = min(bp->bio_bcount, atadev->max_iosize);
  304 
  305     switch (bp->bio_cmd) {
  306     case BIO_READ:
  307         request->flags = ATA_R_READ;
  308         if (atadev->mode >= ATA_DMA) {
  309             request->u.ata.command = ATA_READ_DMA;
  310             request->flags |= ATA_R_DMA;
  311         }
  312         else if (request->transfersize > DEV_BSIZE)
  313             request->u.ata.command = ATA_READ_MUL;
  314         else
  315             request->u.ata.command = ATA_READ;
  316         break;
  317     case BIO_WRITE:
  318         request->flags = ATA_R_WRITE;
  319         if (atadev->mode >= ATA_DMA) {
  320             request->u.ata.command = ATA_WRITE_DMA;
  321             request->flags |= ATA_R_DMA;
  322         }
  323         else if (request->transfersize > DEV_BSIZE)
  324             request->u.ata.command = ATA_WRITE_MUL;
  325         else
  326             request->u.ata.command = ATA_WRITE;
  327         break;
  328     case BIO_DELETE:
  329         request->flags = ATA_R_CONTROL;
  330         request->u.ata.command = ATA_CFA_ERASE;
  331         request->transfersize = 0;
  332         request->donecount = bp->bio_bcount;
  333         break;
  334     case BIO_FLUSH:
  335         request->u.ata.lba = 0;
  336         request->u.ata.count = 0;
  337         request->u.ata.feature = 0;
  338         request->bytecount = 0;
  339         request->transfersize = 0;
  340         request->flags = ATA_R_CONTROL;
  341         request->u.ata.command = ATA_FLUSHCACHE;
  342         break;
  343     default:
  344         device_printf(dev, "FAILURE - unknown BIO operation\n");
  345         ata_free_request(request);
  346         biofinish(bp, NULL, EIO);
  347         return;
  348     }
  349     request->flags |= ATA_R_ORDERED;
  350     ata_queue_request(request);
  351 }
  352 
  353 static void
  354 ad_done(struct ata_request *request)
  355 {
  356     struct bio *bp = request->bio;
  357 
  358     /* finish up transfer */
  359     if ((bp->bio_error = request->result))
  360         bp->bio_flags |= BIO_ERROR;
  361     bp->bio_resid = bp->bio_bcount - request->donecount;
  362     biodone(bp);
  363     ata_free_request(request);
  364 }
  365 
  366 static int
  367 ad_ioctl(struct disk *disk, u_long cmd, void *data, int flag, struct thread *td)
  368 {
  369     return ata_device_ioctl(disk->d_drv1, cmd, data);
  370 }
  371 
  372 static int
  373 ad_dump(void *arg, void *virtual, vm_offset_t physical,
  374         off_t offset, size_t length)
  375 {
  376     struct disk *dp = arg;
  377     struct bio bp;
  378 
  379     /* length zero is special and really means flush buffers to media */
  380     if (!length) {
  381         struct ata_device *atadev = device_get_softc(dp->d_drv1);
  382         int error = 0;
  383 
  384         if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE)
  385             error = ata_controlcmd(dp->d_drv1, ATA_FLUSHCACHE, 0, 0, 0);
  386         return error;
  387     }
  388 
  389     bzero(&bp, sizeof(struct bio));
  390     bp.bio_disk = dp;
  391     bp.bio_pblkno = offset / DEV_BSIZE;
  392     bp.bio_bcount = length;
  393     bp.bio_data = virtual;
  394     bp.bio_cmd = BIO_WRITE;
  395     ad_strategy(&bp);
  396     return bp.bio_error;
  397 }
  398 
  399 static void
  400 ad_init(device_t dev)
  401 {
  402     struct ata_device *atadev = device_get_softc(dev);
  403 
  404     ATA_SETMODE(device_get_parent(dev), dev);
  405 
  406     /* enable readahead caching */
  407     if (atadev->param.support.command1 & ATA_SUPPORT_LOOKAHEAD)
  408         ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_ENAB_RCACHE, 0, 0);
  409 
  410     /* enable write caching if supported and configured */
  411     if (atadev->param.support.command1 & ATA_SUPPORT_WRITECACHE) {
  412         if (ata_wc)
  413             ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_ENAB_WCACHE, 0, 0);
  414         else
  415             ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_DIS_WCACHE, 0, 0);
  416     }
  417 
  418     /* use multiple sectors/interrupt if device supports it */
  419     if (ad_version(atadev->param.version_major)) {
  420         int secsperint = max(1, min(atadev->param.sectors_intr, 16));
  421 
  422         if (!ata_controlcmd(dev, ATA_SET_MULTI, 0, 0, secsperint))
  423             atadev->max_iosize = secsperint * DEV_BSIZE;
  424     }
  425     else
  426         atadev->max_iosize = DEV_BSIZE;
  427 }
  428 
  429 void
  430 ad_describe(device_t dev)
  431 {
  432     struct ata_channel *ch = device_get_softc(device_get_parent(dev));
  433     struct ata_device *atadev = device_get_softc(dev);
  434     struct ad_softc *adp = device_get_ivars(dev);
  435     u_int8_t *marker, vendor[64], product[64];
  436 
  437     /* try to seperate the ATA model string into vendor and model parts */
  438     if ((marker = index(atadev->param.model, ' ')) ||
  439         (marker = index(atadev->param.model, '-'))) {
  440         int len = (marker - atadev->param.model);
  441 
  442         strncpy(vendor, atadev->param.model, len);
  443         vendor[len++] = 0;
  444         strcat(vendor, " ");
  445         strncpy(product, atadev->param.model + len, 40 - len);
  446         vendor[40 - len] = 0;
  447     }
  448     else {
  449         if (!strncmp(atadev->param.model, "ST", 2))
  450             strcpy(vendor, "Seagate ");
  451         else if (!strncmp(atadev->param.model, "HDS", 3))
  452             strcpy(vendor, "Hitachi ");
  453         else
  454             strcpy(vendor, "");
  455         strncpy(product, atadev->param.model, 40);
  456     }
  457 
  458     device_printf(dev, "%juMB <%s%s %.8s> at ata%d-%s %s%s\n",
  459                   adp->total_secs / (1048576 / DEV_BSIZE),
  460                   vendor, product, atadev->param.revision,
  461                   device_get_unit(ch->dev),
  462                   (atadev->unit == ATA_MASTER) ? "master" : "slave",
  463                   (adp->flags & AD_F_TAG_ENABLED) ? "tagged " : "",
  464                   ata_mode2str(atadev->mode));
  465     if (bootverbose) {
  466         device_printf(dev, "%ju sectors [%juC/%dH/%dS] "
  467                       "%d sectors/interrupt %d depth queue\n", adp->total_secs,
  468                       adp->total_secs / (adp->heads * adp->sectors),
  469                       adp->heads, adp->sectors, atadev->max_iosize / DEV_BSIZE,
  470                       adp->num_tags + 1);
  471     }
  472 }
  473 
  474 static int
  475 ad_version(u_int16_t version)
  476 {
  477     int bit;
  478 
  479     if (version == 0xffff)
  480         return 0;
  481     for (bit = 15; bit >= 0; bit--)
  482         if (version & (1<<bit))
  483             return bit;
  484     return 0;
  485 }
  486 
  487 static device_method_t ad_methods[] = {
  488     /* device interface */
  489     DEVMETHOD(device_probe,     ad_probe),
  490     DEVMETHOD(device_attach,    ad_attach),
  491     DEVMETHOD(device_detach,    ad_detach),
  492     DEVMETHOD(device_shutdown,  ad_shutdown),
  493 
  494     /* ATA methods */
  495     DEVMETHOD(ata_reinit,       ad_reinit),
  496 
  497     { 0, 0 }
  498 };
  499 
  500 static driver_t ad_driver = {
  501     "ad",
  502     ad_methods,
  503     0,
  504 };
  505 
  506 devclass_t ad_devclass;
  507 
  508 DRIVER_MODULE(ad, ata, ad_driver, ad_devclass, NULL, NULL);
  509 MODULE_VERSION(ad, 1);
  510 MODULE_DEPEND(ad, ata, 1, 1, 1);

Cache object: b2d9c3d220f417d807706ce23961d6a3


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