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 - 2004 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  * 3. The name of the author may not be used to endorse or promote products
   15  *    derived from this software without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/ata.h>
   35 #include <sys/kernel.h>
   36 #include <sys/malloc.h>
   37 #include <sys/bio.h>
   38 #include <sys/bus.h>
   39 #include <sys/conf.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 
   49 /* prototypes */
   50 static  disk_open_t     afd_open;
   51 static  disk_close_t    afd_close;
   52 #ifdef notyet
   53 static  disk_ioctl_t    afd_ioctl;
   54 #endif
   55 static disk_strategy_t  afdstrategy;
   56 static void afd_detach(struct ata_device *);
   57 static void afd_start(struct ata_device *);
   58 static int afd_sense(struct afd_softc *);
   59 static void afd_describe(struct afd_softc *);
   60 static void afd_done(struct ata_request *);
   61 static int afd_eject(struct afd_softc *, int);
   62 static int afd_start_stop(struct afd_softc *, int);
   63 static int afd_prevent_allow(struct afd_softc *, int);
   64 static int afd_test_ready(struct ata_device *);
   65 
   66 /* internal vars */
   67 static u_int32_t afd_lun_map = 0;
   68 static MALLOC_DEFINE(M_AFD, "AFD driver", "ATAPI floppy driver buffers");
   69 
   70 void 
   71 afd_attach(struct ata_device *atadev)
   72 {
   73     struct afd_softc *fdp;
   74 
   75     fdp = malloc(sizeof(struct afd_softc), M_AFD, M_NOWAIT | M_ZERO);
   76     if (!fdp) {
   77         ata_prtdev(atadev, "out of memory\n");
   78         return;
   79     }
   80 
   81     fdp->device = atadev;
   82     fdp->lun = ata_get_lun(&afd_lun_map);
   83     ata_set_name(atadev, "afd", fdp->lun);
   84     bioq_init(&fdp->queue);
   85     mtx_init(&fdp->queue_mtx, "ATAPI FD bioqueue lock", NULL, MTX_DEF);  
   86 
   87     if (afd_sense(fdp)) {
   88         free(fdp, M_AFD);
   89         return;
   90     }
   91 
   92     /* setup the function ptrs */
   93     atadev->detach = afd_detach;
   94     atadev->start = afd_start;
   95     atadev->softc = fdp;
   96     atadev->flags |= ATA_D_MEDIA_CHANGED;
   97 
   98     /* lets create the disk device */
   99     fdp->disk = disk_alloc();
  100     fdp->disk->d_open = afd_open;
  101     fdp->disk->d_close = afd_close;
  102 #ifdef notyet
  103     fdp->disk->d_ioctl = afd_ioctl;
  104 #endif
  105     fdp->disk->d_strategy = afdstrategy;
  106     fdp->disk->d_name = "afd";
  107     fdp->disk->d_drv1 = fdp;
  108     if (atadev->channel->dma)
  109         fdp->disk->d_maxsize = atadev->channel->dma->max_iosize;
  110     else
  111         fdp->disk->d_maxsize = DFLTPHYS;
  112     fdp->disk->d_unit = fdp->lun;
  113     disk_create(fdp->disk, DISK_VERSION);
  114 
  115     /* announce we are here */
  116     afd_describe(fdp);
  117 }
  118 
  119 static void
  120 afd_detach(struct ata_device *atadev)
  121 {   
  122     struct afd_softc *fdp = atadev->softc;
  123     
  124     mtx_lock(&fdp->queue_mtx);
  125     bioq_flush(&fdp->queue, NULL, ENXIO);
  126     mtx_unlock(&fdp->queue_mtx);
  127     mtx_destroy(&fdp->queue_mtx);  
  128     disk_destroy(fdp->disk);
  129     ata_prtdev(atadev, "WARNING - removed from configuration\n");
  130     ata_free_name(atadev);
  131     ata_free_lun(&afd_lun_map, fdp->lun);
  132     atadev->attach = NULL;
  133     atadev->detach = NULL;
  134     atadev->start = NULL;
  135     atadev->softc = NULL;
  136     atadev->flags = 0;
  137     free(fdp, M_AFD);
  138 }   
  139 
  140 static int 
  141 afd_sense(struct afd_softc *fdp)
  142 {
  143     int8_t ccb[16] = { ATAPI_MODE_SENSE_BIG, 0, ATAPI_REWRITEABLE_CAP_PAGE,
  144                        0, 0, 0, 0, sizeof(struct afd_cappage) >> 8,
  145                        sizeof(struct afd_cappage) & 0xff, 0, 0, 0, 0, 0, 0, 0 };
  146     int count;
  147 
  148     /* The IOMEGA Clik! doesn't support reading the cap page, fake it */
  149     if (!strncmp(fdp->device->param->model, "IOMEGA Clik!", 12)) {
  150         fdp->cap.transfer_rate = 500;
  151         fdp->cap.heads = 1;
  152         fdp->cap.sectors = 2;
  153         fdp->cap.cylinders = 39441;
  154         fdp->cap.sector_size = 512;
  155         afd_test_ready(fdp->device);
  156         return 0;
  157     }
  158 
  159     /* get drive capabilities, some bugridden drives needs this repeated */
  160     for (count = 0 ; count < 5 ; count++) {
  161         if (!ata_atapicmd(fdp->device, ccb, (caddr_t)&fdp->cap,
  162                           sizeof(struct afd_cappage), ATA_R_READ, 30) &&
  163             fdp->cap.page_code == ATAPI_REWRITEABLE_CAP_PAGE) {
  164             fdp->cap.cylinders = ntohs(fdp->cap.cylinders);
  165             fdp->cap.sector_size = ntohs(fdp->cap.sector_size);
  166             fdp->cap.transfer_rate = ntohs(fdp->cap.transfer_rate);
  167             return 0;
  168         }
  169     }
  170     return 1;
  171 }
  172 
  173 static void 
  174 afd_describe(struct afd_softc *fdp)
  175 {
  176     if (bootverbose) {
  177         ata_prtdev(fdp->device,
  178                    "<%.40s/%.8s> removable drive at ata%d as %s\n",
  179                    fdp->device->param->model, fdp->device->param->revision,
  180                    device_get_unit(fdp->device->channel->dev),
  181                    (fdp->device->unit == ATA_MASTER) ? "master" : "slave");
  182         ata_prtdev(fdp->device,
  183                    "%luMB (%u sectors), %u cyls, %u heads, %u S/T, %u B/S\n",
  184                    (fdp->cap.cylinders * fdp->cap.heads * fdp->cap.sectors) / 
  185                    ((1024L * 1024L) / fdp->cap.sector_size),
  186                    fdp->cap.cylinders * fdp->cap.heads * fdp->cap.sectors,
  187                    fdp->cap.cylinders, fdp->cap.heads, fdp->cap.sectors,
  188                    fdp->cap.sector_size);
  189         ata_prtdev(fdp->device, "%dKB/s,", fdp->cap.transfer_rate / 8);
  190         printf(" %s\n", ata_mode2str(fdp->device->mode));
  191         if (fdp->cap.medium_type) {
  192             ata_prtdev(fdp->device, "Medium: ");
  193             switch (fdp->cap.medium_type) {
  194             case MFD_2DD:
  195                 printf("720KB DD disk"); break;
  196 
  197             case MFD_HD_12:
  198                 printf("1.2MB HD disk"); break;
  199 
  200             case MFD_HD_144:
  201                 printf("1.44MB HD disk"); break;
  202 
  203             case MFD_UHD: 
  204                 printf("120MB UHD disk"); break;
  205 
  206             default:
  207                 printf("Unknown (0x%x)", fdp->cap.medium_type);
  208             }
  209             if (fdp->cap.wp) printf(", writeprotected");
  210             printf("\n");
  211         }
  212     }
  213     else {
  214         ata_prtdev(fdp->device, "REMOVABLE <%.40s/%.8s> at ata%d-%s %s\n",
  215                    fdp->device->param->model, fdp->device->param->revision,
  216                    device_get_unit(fdp->device->channel->dev),
  217                    (fdp->device->unit == ATA_MASTER) ? "master" : "slave",
  218                    ata_mode2str(fdp->device->mode));
  219     }
  220 }
  221 
  222 static int
  223 afd_open(struct disk *dp)
  224 {
  225     struct afd_softc *fdp = dp->d_drv1;
  226 
  227     if (fdp->device->flags & ATA_D_DETACHING)
  228         return ENXIO;
  229 
  230     afd_test_ready(fdp->device);
  231 
  232     afd_prevent_allow(fdp, 1);
  233 
  234     if (afd_sense(fdp))
  235         ata_prtdev(fdp->device, "sense media type failed\n");
  236 
  237     fdp->device->flags &= ~ATA_D_MEDIA_CHANGED;
  238 
  239     fdp->disk->d_sectorsize = fdp->cap.sector_size;
  240     fdp->disk->d_mediasize = (off_t)fdp->cap.sector_size * fdp->cap.sectors *
  241         fdp->cap.heads * fdp->cap.cylinders;
  242     fdp->disk->d_fwsectors = fdp->cap.sectors;
  243     fdp->disk->d_fwheads = fdp->cap.heads;
  244   
  245     return 0;
  246 }
  247 
  248 static int 
  249 afd_close(struct disk *dp)
  250 {
  251     struct afd_softc *fdp = dp->d_drv1;
  252 
  253     afd_prevent_allow(fdp, 0); 
  254     if (0)
  255         afd_eject(fdp, 0);      /* to keep gcc quiet */
  256 
  257     return 0;
  258 }
  259 
  260 #ifdef notyet
  261 static int 
  262 afd_ioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
  263 {
  264     struct afd_softc *fdp = dp->d_drv1;
  265 
  266     switch (cmd) {
  267     case CDIOCEJECT:
  268         if (count_dev(dev) > 1)
  269             return EBUSY;
  270         return afd_eject(fdp, 0);
  271 
  272     case CDIOCCLOSE:
  273         if (count_dev(dev) > 1)
  274             return 0;
  275         return afd_eject(fdp, 1);
  276 
  277     default:
  278         return ENOIOCTL;
  279     }
  280 }
  281 #endif
  282 
  283 static void 
  284 afdstrategy(struct bio *bp)
  285 {
  286     struct afd_softc *fdp = bp->bio_disk->d_drv1;
  287 
  288     if (fdp->device->flags & ATA_D_DETACHING) {
  289         biofinish(bp, NULL, ENXIO);
  290         return;
  291     }
  292 
  293     /* if it's a null transfer, return immediatly. */
  294     if (bp->bio_bcount == 0) {
  295         bp->bio_resid = 0;
  296         biodone(bp);
  297         return;
  298     }
  299 
  300     mtx_lock(&fdp->queue_mtx);
  301     bioq_disksort(&fdp->queue, bp);
  302     mtx_unlock(&fdp->queue_mtx);
  303     ata_start(fdp->device->channel);
  304 }
  305 
  306 static void 
  307 afd_start(struct ata_device *atadev)
  308 {
  309     struct afd_softc *fdp = atadev->softc;
  310     struct bio *bp;
  311     struct ata_request *request;
  312     u_int32_t lba;
  313     u_int16_t count;
  314     int8_t ccb[16];
  315 
  316 
  317     mtx_lock(&fdp->queue_mtx);
  318     bp = bioq_first(&fdp->queue);
  319     if (!bp) {
  320         mtx_unlock(&fdp->queue_mtx);
  321         return;
  322     }
  323     bioq_remove(&fdp->queue, bp);
  324     mtx_unlock(&fdp->queue_mtx);
  325 
  326     /* should reject all queued entries if media have changed. */
  327     if (fdp->device->flags & ATA_D_MEDIA_CHANGED) {
  328         biofinish(bp, NULL, EIO);
  329         return;
  330     }
  331 
  332     lba = bp->bio_pblkno;
  333     count = bp->bio_bcount / fdp->cap.sector_size;
  334     bp->bio_resid = bp->bio_bcount; 
  335 
  336     bzero(ccb, sizeof(ccb));
  337 
  338     if (bp->bio_cmd == BIO_READ)
  339         ccb[0] = ATAPI_READ_BIG;
  340     else
  341         ccb[0] = ATAPI_WRITE_BIG;
  342 
  343     ccb[2] = lba>>24;
  344     ccb[3] = lba>>16;
  345     ccb[4] = lba>>8;
  346     ccb[5] = lba;
  347     ccb[7] = count>>8;
  348     ccb[8] = count;
  349 
  350     if (!(request = ata_alloc_request())) {
  351         biofinish(bp, NULL, ENOMEM);
  352         return;
  353     }
  354     request->device = atadev;
  355     request->driver = bp;
  356     bcopy(ccb, request->u.atapi.ccb,
  357           (request->device->param->config & ATA_PROTO_MASK) == 
  358           ATA_PROTO_ATAPI_12 ? 16 : 12);
  359     request->data = bp->bio_data;
  360     request->bytecount = count * fdp->cap.sector_size;
  361     request->transfersize = min(request->bytecount, 65534);
  362     request->timeout = (ccb[0] == ATAPI_WRITE_BIG) ? 60 : 30;
  363     request->retries = 2;
  364     request->callback = afd_done;
  365     switch (bp->bio_cmd) {
  366     case BIO_READ:
  367         request->flags |= (ATA_R_ATAPI | ATA_R_READ);
  368         break;
  369     case BIO_WRITE:
  370         request->flags |= (ATA_R_ATAPI | ATA_R_WRITE);
  371         break;
  372     default:
  373         ata_prtdev(atadev, "unknown BIO operation\n");
  374         ata_free_request(request);
  375         biofinish(bp, NULL, EIO);
  376         return;
  377     }
  378     ata_queue_request(request);
  379 
  380 }
  381 
  382 static void 
  383 afd_done(struct ata_request *request)
  384 {
  385     struct bio *bp = request->driver;
  386 
  387     /* finish up transfer */
  388     if ((bp->bio_error = request->result))
  389         bp->bio_flags |= BIO_ERROR;
  390     bp->bio_resid = bp->bio_bcount - request->donecount;
  391     biodone(bp);
  392     ata_free_request(request);
  393 }
  394 
  395 static int 
  396 afd_eject(struct afd_softc *fdp, int close)
  397 {
  398     int error;
  399      
  400     if ((error = afd_start_stop(fdp, 0)) == EBUSY) {
  401         if (!close)
  402             return 0;
  403         if ((error = afd_start_stop(fdp, 3)))
  404             return error;
  405         return afd_prevent_allow(fdp, 1);
  406     }
  407     if (error)
  408         return error;
  409     if (close)
  410         return 0;
  411     if ((error = afd_prevent_allow(fdp, 0)))
  412         return error;
  413     fdp->device->flags |= ATA_D_MEDIA_CHANGED;
  414     return afd_start_stop(fdp, 2);
  415 }
  416 
  417 static int
  418 afd_start_stop(struct afd_softc *fdp, int start)
  419 {
  420     int8_t ccb[16] = { ATAPI_START_STOP, 0, 0, 0, start,
  421                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  422 
  423     return ata_atapicmd(fdp->device, ccb, NULL, 0, 0, 30);
  424 }
  425 
  426 static int
  427 afd_prevent_allow(struct afd_softc *fdp, int lock)
  428 {
  429     int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock,
  430                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  431     
  432     if (!strncmp(fdp->device->param->model, "IOMEGA Clik!", 12))
  433         return 0;
  434     return ata_atapicmd(fdp->device, ccb, NULL, 0, 0, 30);
  435 }
  436 
  437 static int
  438 afd_test_ready(struct ata_device *atadev)
  439 {
  440     int8_t ccb[16] = { ATAPI_TEST_UNIT_READY, 0, 0, 0, 0,
  441                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  442 
  443     return ata_atapicmd(atadev, ccb, NULL, 0, 0, 30);
  444 }

Cache object: 23cc1815c998ef03cecdc07ebc8287cd


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