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/atapi-fd.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 - 2008 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: releng/8.4/sys/dev/ata/atapi-fd.c 233718 2012-03-30 23:56:19Z marius $");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/ata.h>
   33 #include <sys/kernel.h>
   34 #include <sys/module.h>
   35 #include <sys/malloc.h>
   36 #include <sys/bio.h>
   37 #include <sys/bus.h>
   38 #include <sys/conf.h>
   39 #include <sys/endian.h>
   40 #include <sys/cdio.h>
   41 #include <sys/sema.h>
   42 #include <sys/taskqueue.h>
   43 #include <vm/uma.h>
   44 #include <machine/bus.h>
   45 #include <geom/geom_disk.h>
   46 #include <dev/ata/ata-all.h>
   47 #include <dev/ata/atapi-fd.h>
   48 #include <ata_if.h>
   49 
   50 
   51 /* prototypes */
   52 static disk_open_t afd_open;
   53 static disk_close_t afd_close;
   54 static disk_strategy_t afd_strategy;
   55 static disk_ioctl_t afd_ioctl;
   56 static int afd_sense(device_t);
   57 static void afd_describe(device_t);
   58 static void afd_done(struct ata_request *);
   59 static int afd_prevent_allow(device_t, int);
   60 static int afd_test_ready(device_t);
   61 
   62 /* internal vars */
   63 static MALLOC_DEFINE(M_AFD, "afd_driver", "ATAPI floppy driver buffers");
   64 
   65 static int 
   66 afd_probe(device_t dev)
   67 {
   68     struct ata_device *atadev = device_get_softc(dev);
   69     if ((atadev->param.config & ATA_PROTO_ATAPI) &&
   70         (atadev->param.config & ATA_ATAPI_TYPE_MASK) == ATA_ATAPI_TYPE_DIRECT)
   71         return 0;  
   72     else
   73         return ENXIO;
   74 }
   75 
   76 static int 
   77 afd_attach(device_t dev)
   78 {
   79     struct ata_channel *ch = device_get_softc(device_get_parent(dev));
   80     struct ata_device *atadev = device_get_softc(dev);
   81     struct afd_softc *fdp;
   82 
   83     if (!(fdp = malloc(sizeof(struct afd_softc), M_AFD, M_NOWAIT | M_ZERO))) {
   84         device_printf(dev, "out of memory\n");
   85         return ENOMEM;
   86     }
   87     device_set_ivars(dev, fdp);
   88     ata_setmode(dev);
   89 
   90     if (afd_sense(dev)) {
   91         device_set_ivars(dev, NULL);
   92         free(fdp, M_AFD);
   93         return ENXIO;
   94     }
   95     atadev->flags |= ATA_D_MEDIA_CHANGED;
   96 
   97     /* announce we are here */
   98     afd_describe(dev);
   99 
  100     /* create the disk device */
  101     fdp->disk = disk_alloc();
  102     fdp->disk->d_open = afd_open;
  103     fdp->disk->d_close = afd_close;
  104     fdp->disk->d_strategy = afd_strategy;
  105     fdp->disk->d_ioctl = afd_ioctl;
  106     fdp->disk->d_name = "afd";
  107     fdp->disk->d_drv1 = dev;
  108     fdp->disk->d_maxsize = ch->dma.max_iosize ? ch->dma.max_iosize : DFLTPHYS;
  109     fdp->disk->d_unit = device_get_unit(dev);
  110     disk_create(fdp->disk, DISK_VERSION);
  111     return 0;
  112 }
  113 
  114 static int
  115 afd_detach(device_t dev)
  116 {   
  117     struct afd_softc *fdp = device_get_ivars(dev);
  118 
  119     /* check that we have a valid device to detach */
  120     if (!device_get_ivars(dev))
  121         return ENXIO;
  122     
  123     /* detroy disk from the system so we dont get any further requests */
  124     disk_destroy(fdp->disk);
  125 
  126     /* fail requests on the queue and any thats "in flight" for this device */
  127     ata_fail_requests(dev);
  128 
  129     /* dont leave anything behind */
  130     device_set_ivars(dev, NULL);
  131     free(fdp, M_AFD);
  132     return 0;
  133 }
  134 
  135 static int
  136 afd_shutdown(device_t dev)
  137 {
  138     struct ata_device *atadev = device_get_softc(dev);
  139 
  140     if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE)
  141         ata_controlcmd(dev, ATA_FLUSHCACHE, 0, 0, 0);
  142     return 0;
  143 }
  144 
  145 static int
  146 afd_reinit(device_t dev)
  147 {
  148     struct ata_channel *ch = device_get_softc(device_get_parent(dev));
  149     struct ata_device *atadev = device_get_softc(dev);
  150 
  151     /* if detach pending, return error */
  152     if (!(ch->devices & (ATA_ATAPI_MASTER << atadev->unit)))
  153         return 1;
  154 
  155     ata_setmode(dev);
  156     return 0;
  157 }
  158 
  159 static int
  160 afd_open(struct disk *dp)
  161 {
  162     device_t dev = dp->d_drv1;
  163     struct ata_device *atadev = device_get_softc(dev);
  164     struct afd_softc *fdp = device_get_ivars(dev);
  165 
  166     if (!fdp) 
  167         return ENXIO;
  168     if (!device_is_attached(dev))
  169         return EBUSY;
  170 
  171     afd_test_ready(dev);
  172     afd_prevent_allow(dev, 1);
  173 
  174     if (afd_sense(dev))
  175         device_printf(dev, "sense media type failed\n");
  176     atadev->flags &= ~ATA_D_MEDIA_CHANGED;
  177 
  178     if (!fdp->mediasize)
  179         return ENXIO;
  180 
  181     fdp->disk->d_sectorsize = fdp->sectorsize;
  182     fdp->disk->d_mediasize = fdp->mediasize;
  183     fdp->disk->d_fwsectors = fdp->sectors;
  184     fdp->disk->d_fwheads = fdp->heads;
  185     return 0;
  186 }
  187 
  188 static int 
  189 afd_close(struct disk *dp)
  190 {
  191     device_t dev = dp->d_drv1;
  192 
  193     afd_prevent_allow(dev, 0); 
  194     return 0;
  195 }
  196 
  197 static void 
  198 afd_strategy(struct bio *bp)
  199 {
  200     device_t dev = bp->bio_disk->d_drv1;
  201     struct ata_device *atadev = device_get_softc(dev);
  202     struct afd_softc *fdp = device_get_ivars(dev);
  203     struct ata_request *request;
  204     u_int16_t count;
  205     int8_t ccb[16];
  206 
  207     /* if it's a null transfer, return immediatly. */
  208     if (bp->bio_bcount == 0) {
  209         bp->bio_resid = 0;
  210         biodone(bp);
  211         return;
  212     }
  213 
  214     /* should reject all queued entries if media have changed. */
  215     if (atadev->flags & ATA_D_MEDIA_CHANGED) {
  216         biofinish(bp, NULL, EIO);
  217         return;
  218     }
  219 
  220     count = bp->bio_bcount / fdp->sectorsize;
  221     bp->bio_resid = bp->bio_bcount; 
  222 
  223     bzero(ccb, sizeof(ccb));
  224 
  225     if (bp->bio_cmd == BIO_READ)
  226         ccb[0] = ATAPI_READ_BIG;
  227     else
  228         ccb[0] = ATAPI_WRITE_BIG;
  229 
  230     ccb[2] = bp->bio_pblkno >> 24;
  231     ccb[3] = bp->bio_pblkno >> 16;
  232     ccb[4] = bp->bio_pblkno >> 8;
  233     ccb[5] = bp->bio_pblkno;
  234     ccb[7] = count>>8;
  235     ccb[8] = count;
  236 
  237     if (!(request = ata_alloc_request())) {
  238         biofinish(bp, NULL, ENOMEM);
  239         return;
  240     }
  241     request->dev = dev;
  242     request->bio = bp;
  243     bcopy(ccb, request->u.atapi.ccb, 16);
  244     request->data = bp->bio_data;
  245     request->bytecount = count * fdp->sectorsize;
  246     request->transfersize = min(request->bytecount, 65534);
  247     request->timeout = (ccb[0] == ATAPI_WRITE_BIG) ? 60 : 30;
  248     request->retries = 2;
  249     request->callback = afd_done;
  250     switch (bp->bio_cmd) {
  251     case BIO_READ:
  252         request->flags = (ATA_R_ATAPI | ATA_R_READ);
  253         break;
  254     case BIO_WRITE:
  255         request->flags = (ATA_R_ATAPI | ATA_R_WRITE);
  256         break;
  257     default:
  258         device_printf(dev, "unknown BIO operation\n");
  259         ata_free_request(request);
  260         biofinish(bp, NULL, EIO);
  261         return;
  262     }
  263     if (atadev->mode >= ATA_DMA)
  264         request->flags |= ATA_R_DMA;
  265     request->flags |= ATA_R_ORDERED;
  266     ata_queue_request(request);
  267 }
  268 
  269 static void 
  270 afd_done(struct ata_request *request)
  271 {
  272     struct bio *bp = request->bio;
  273 
  274     /* finish up transfer */
  275     if ((bp->bio_error = request->result))
  276         bp->bio_flags |= BIO_ERROR;
  277     bp->bio_resid = bp->bio_bcount - request->donecount;
  278     biodone(bp);
  279     ata_free_request(request);
  280 }
  281 
  282 static int
  283 afd_ioctl(struct disk *disk, u_long cmd, void *data, int flag,struct thread *td)
  284 {
  285     return ata_device_ioctl(disk->d_drv1, cmd, data);
  286 }
  287 
  288 static int 
  289 afd_sense(device_t dev)
  290 {
  291     struct ata_device *atadev = device_get_softc(dev);
  292     struct afd_softc *fdp = device_get_ivars(dev);
  293     struct afd_capacity capacity;
  294     struct afd_capacity_big capacity_big;
  295     struct afd_capabilities capabilities;
  296     int8_t ccb1[16] = { ATAPI_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0,
  297                         0, 0, 0, 0, 0, 0, 0, 0 };
  298     int8_t ccb2[16] = { ATAPI_SERVICE_ACTION_IN, 0x10, 0, 0, 0, 0, 0, 0, 0, 0,
  299                         0, 0, 0, sizeof(struct afd_capacity_big) & 0xff, 0, 0 };
  300     int8_t ccb3[16] = { ATAPI_MODE_SENSE_BIG, 0, ATAPI_REWRITEABLE_CAP_PAGE,
  301                         0, 0, 0, 0, sizeof(struct afd_capabilities) >> 8,
  302                         sizeof(struct afd_capabilities) & 0xff,
  303                         0, 0, 0, 0, 0, 0, 0 };
  304     int timeout = 20;
  305     int error, count;
  306 
  307     fdp->mediasize = 0;
  308 
  309     /* wait for device to get ready */
  310     while ((error = afd_test_ready(dev)) && timeout--) {
  311         DELAY(100000);
  312     }
  313     if (error == EBUSY)
  314         return 1;
  315 
  316     /* The IOMEGA Clik! doesn't support reading the cap page, fake it */
  317     if (!strncmp(atadev->param.model, "IOMEGA Clik!", 12)) {
  318         fdp->heads = 1;
  319         fdp->sectors = 2;
  320         fdp->mediasize = 39441 * 1024;
  321         fdp->sectorsize = 512;
  322         afd_test_ready(dev);
  323         return 0;
  324     }
  325 
  326     /* get drive capacity */
  327     if (!ata_atapicmd(dev, ccb1, (caddr_t)&capacity,
  328                       sizeof(struct afd_capacity), ATA_R_READ, 30)) {
  329         fdp->heads = 16;
  330         fdp->sectors = 63;
  331         fdp->sectorsize = be32toh(capacity.blocksize);
  332         fdp->mediasize = (u_int64_t)be32toh(capacity.capacity)*fdp->sectorsize; 
  333         afd_test_ready(dev);
  334         return 0;
  335     }
  336 
  337     /* get drive capacity big */
  338     if (!ata_atapicmd(dev, ccb2, (caddr_t)&capacity_big,
  339                       sizeof(struct afd_capacity_big),
  340                       ATA_R_READ | ATA_R_QUIET, 30)) {
  341         fdp->heads = 16;
  342         fdp->sectors = 63;
  343         fdp->sectorsize = be32toh(capacity_big.blocksize);
  344         fdp->mediasize = be64toh(capacity_big.capacity)*fdp->sectorsize;
  345         afd_test_ready(dev);
  346         return 0;
  347     }
  348 
  349     /* get drive capabilities, some bugridden drives needs this repeated */
  350     for (count = 0 ; count < 5 ; count++) {
  351         if (!ata_atapicmd(dev, ccb3, (caddr_t)&capabilities,
  352                           sizeof(struct afd_capabilities), ATA_R_READ, 30) &&
  353             capabilities.page_code == ATAPI_REWRITEABLE_CAP_PAGE) {
  354             fdp->heads = capabilities.heads;
  355             fdp->sectors = capabilities.sectors;
  356             fdp->sectorsize = be16toh(capabilities.sector_size);
  357             fdp->mediasize = be16toh(capabilities.cylinders) *
  358                              fdp->heads * fdp->sectors * fdp->sectorsize;
  359             if (!capabilities.medium_type)
  360                 fdp->mediasize = 0;
  361             return 0;
  362         }
  363     }
  364     return 1;
  365 }
  366 
  367 static int
  368 afd_prevent_allow(device_t dev, int lock)
  369 {
  370     struct ata_device *atadev = device_get_softc(dev);
  371     int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock,
  372                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  373     
  374     if (!strncmp(atadev->param.model, "IOMEGA Clik!", 12))
  375         return 0;
  376     return ata_atapicmd(dev, ccb, NULL, 0, 0, 30);
  377 }
  378 
  379 static int
  380 afd_test_ready(device_t dev)
  381 {
  382     int8_t ccb[16] = { ATAPI_TEST_UNIT_READY, 0, 0, 0, 0,
  383                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  384 
  385     return ata_atapicmd(dev, ccb, NULL, 0, 0, 30);
  386 }
  387 
  388 static void 
  389 afd_describe(device_t dev)
  390 {
  391     struct ata_channel *ch = device_get_softc(device_get_parent(dev));
  392     struct ata_device *atadev = device_get_softc(dev);
  393     struct afd_softc *fdp = device_get_ivars(dev);
  394     char sizestring[16];
  395 
  396     if (fdp->mediasize > 1048576 * 5)
  397         sprintf(sizestring, "%juMB", fdp->mediasize / 1048576);
  398     else if (fdp->mediasize)
  399         sprintf(sizestring, "%juKB", fdp->mediasize / 1024);
  400     else
  401         strcpy(sizestring, "(no media)");
  402  
  403     device_printf(dev, "%s <%.40s %.8s> at ata%d-%s %s %s\n",
  404                   sizestring, atadev->param.model, atadev->param.revision,
  405                   device_get_unit(ch->dev), ata_unit2str(atadev),
  406                   ata_mode2str(atadev->mode),
  407                   ata_satarev2str(ATA_GETREV(device_get_parent(dev), atadev->unit)));
  408     if (bootverbose) {
  409         device_printf(dev, "%ju sectors [%juC/%dH/%dS]\n",
  410                       fdp->mediasize / fdp->sectorsize,
  411                       fdp->mediasize /(fdp->sectorsize*fdp->sectors*fdp->heads),
  412                       fdp->heads, fdp->sectors);
  413     }
  414 }
  415 
  416 static device_method_t afd_methods[] = {
  417     /* device interface */
  418     DEVMETHOD(device_probe,     afd_probe),
  419     DEVMETHOD(device_attach,    afd_attach),
  420     DEVMETHOD(device_detach,    afd_detach),
  421     DEVMETHOD(device_shutdown,  afd_shutdown),
  422     
  423     /* ATA methods */
  424     DEVMETHOD(ata_reinit,       afd_reinit),
  425     
  426     DEVMETHOD_END
  427 };
  428     
  429 static driver_t afd_driver = {
  430     "afd",
  431     afd_methods,
  432     0,
  433 };
  434 
  435 static devclass_t afd_devclass;
  436 
  437 DRIVER_MODULE(afd, ata, afd_driver, afd_devclass, NULL, NULL);
  438 MODULE_VERSION(afd, 1);
  439 MODULE_DEPEND(afd, ata, 1, 1, 1);
  440 

Cache object: eaf05cfac12300d28b815e87b92ca309


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