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/arm/mv/mv_sata.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) 2008-2009 Semihalf
    3  * All rights reserved.
    4  *
    5  * Initial version developed by Ilya Bakulin. Full functionality and bringup
    6  * by Piotr Ziecik.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD: releng/8.2/sys/arm/mv/mv_sata.c 214671 2010-11-02 09:26:12Z mav $");
   32 
   33 #include <sys/param.h>
   34 #include <sys/bus.h>
   35 #include <sys/lock.h>
   36 #include <sys/resource.h>
   37 #include <sys/systm.h>
   38 #include <sys/rman.h>
   39 #include <sys/kernel.h>
   40 #include <sys/module.h>
   41 #include <sys/mutex.h>
   42 #include <sys/endian.h>
   43 #include <sys/sema.h>
   44 #include <sys/taskqueue.h>
   45 #include <vm/uma.h>
   46 #include <machine/bus.h>
   47 #include <machine/resource.h>
   48 
   49 #include <sys/ata.h>
   50 #include <dev/ata/ata-all.h>
   51 
   52 #include "ata_if.h"
   53 
   54 #include "mvreg.h"
   55 #include "mvvar.h"
   56 
   57 /* Useful macros */
   58 #define EDMA_TIMEOUT            100000 /* 100 ms */
   59 #define SATA_INL(sc, reg)       ATA_INL((sc)->sc_mem_res, reg)
   60 #define SATA_OUTL(sc, reg, val) ATA_OUTL((sc)->sc_mem_res, reg, val)
   61 
   62 /* HW-related data structures */
   63 struct sata_prdentry {
   64         uint32_t        prd_addrlo;
   65         uint32_t        prd_count;
   66         uint32_t        prd_addrhi;
   67         uint32_t        prd_reserved;
   68 };
   69 
   70 struct sata_crqb {
   71         uint32_t        crqb_prdlo;
   72         uint32_t        crqb_prdhi;
   73         uint32_t        crqb_flags;
   74         uint16_t        crqb_count;
   75         uint16_t        crqb_reserved1[2];
   76         uint8_t         crqb_ata_command;
   77         uint8_t         crqb_ata_feature;
   78         uint8_t         crqb_ata_lba_low;
   79         uint8_t         crqb_ata_lba_mid;
   80         uint8_t         crqb_ata_lba_high;
   81         uint8_t         crqb_ata_device;
   82         uint8_t         crqb_ata_lba_low_p;
   83         uint8_t         crqb_ata_lba_mid_p;
   84         uint8_t         crqb_ata_lba_high_p;
   85         uint8_t         crqb_ata_feature_p;
   86         uint8_t         crqb_ata_count;
   87         uint8_t         crqb_ata_count_p;
   88         uint16_t        crqb_reserved2;
   89 };
   90 
   91 struct sata_crpb {
   92         uint8_t         crpb_tag;
   93         uint8_t         crpb_reserved;
   94         uint8_t         crpb_edma_status;
   95         uint8_t         crpb_dev_status;
   96         uint32_t        crpb_timestamp;
   97 };
   98 
   99 /* Identification section. */
  100 struct sata_softc {
  101         device_t                sc_dev;
  102         unsigned int            sc_version;
  103         unsigned int            sc_edma_qlen;
  104         uint32_t                sc_edma_reqis_mask;
  105         uint32_t                sc_edma_resos_mask;
  106         struct resource         *sc_mem_res;
  107         bus_space_tag_t         sc_mem_res_bustag;
  108         bus_space_handle_t      sc_mem_res_bushdl;
  109         struct resource         *sc_irq_res;
  110         void                    *sc_irq_cookiep;
  111         struct {
  112                 void    (*function)(void *);
  113                 void    *argument;
  114         } sc_interrupt[SATA_CHAN_NUM];
  115 };
  116 
  117 /* Controller functions */
  118 static int      sata_probe(device_t dev);
  119 static int      sata_attach(device_t dev);
  120 static int      sata_detach(device_t dev);
  121 static void     sata_intr(void*);
  122 static struct resource * sata_alloc_resource(device_t dev, device_t child,
  123     int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
  124 static int      sata_release_resource(device_t dev, device_t child, int type,
  125     int rid, struct resource *r);
  126 static int      sata_setup_intr(device_t dev, device_t child,
  127     struct resource *irq, int flags, driver_filter_t *filt,
  128     driver_intr_t *function, void *argument, void **cookiep);
  129 static int      sata_teardown_intr(device_t dev, device_t child,
  130     struct resource *irq, void *cookie);
  131 
  132 /* Channel functions */
  133 static int      sata_channel_probe(device_t dev);
  134 static int      sata_channel_attach(device_t dev);
  135 static int      sata_channel_detach(device_t dev);
  136 static int      sata_channel_begin_transaction(struct ata_request *request);
  137 static int      sata_channel_end_transaction(struct ata_request *request);
  138 static int      sata_channel_status(device_t dev);
  139 static int      sata_channel_setmode(device_t dev, int target, int mode);
  140 static int      sata_channel_getrev(device_t dev, int target);
  141 static void     sata_channel_reset(device_t dev);
  142 static void     sata_channel_dmasetprd(void *xsc, bus_dma_segment_t *segs,
  143     int nsegs, int error);
  144 
  145 /* EDMA functions */
  146 static int      sata_edma_ctrl(device_t dev, int on);
  147 static int      sata_edma_is_running(device_t);
  148 
  149 static device_method_t sata_methods[] = {
  150         /* Device method */
  151         DEVMETHOD(device_probe,         sata_probe),
  152         DEVMETHOD(device_attach,        sata_attach),
  153         DEVMETHOD(device_detach,        sata_detach),
  154         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  155         DEVMETHOD(device_suspend,       bus_generic_suspend),
  156         DEVMETHOD(device_resume,        bus_generic_resume),
  157 
  158         /* ATA bus methods. */
  159         DEVMETHOD(bus_alloc_resource,           sata_alloc_resource),
  160         DEVMETHOD(bus_release_resource,         sata_release_resource),
  161         DEVMETHOD(bus_activate_resource,        bus_generic_activate_resource),
  162         DEVMETHOD(bus_deactivate_resource,      bus_generic_deactivate_resource),
  163         DEVMETHOD(bus_setup_intr,               sata_setup_intr),
  164         DEVMETHOD(bus_teardown_intr,            sata_teardown_intr),
  165         { 0, 0 },
  166 };
  167 
  168 static driver_t sata_driver = {
  169         "sata",
  170         sata_methods,
  171         sizeof(struct sata_softc),
  172 };
  173 
  174 devclass_t sata_devclass;
  175 
  176 DRIVER_MODULE(sata, mbus, sata_driver, sata_devclass, 0, 0);
  177 MODULE_VERSION(sata, 1);
  178 MODULE_DEPEND(sata, ata, 1, 1, 1);
  179 
  180 static int
  181 sata_probe(device_t dev)
  182 {
  183         struct sata_softc *sc;
  184         uint32_t d, r;
  185 
  186         soc_id(&d, &r);
  187         sc = device_get_softc(dev);
  188 
  189         /* No SATA controller on the 88F5281 SoC */
  190         if (d == MV_DEV_88F5281)
  191                 return (ENXIO);
  192 
  193         switch(d) {
  194         case MV_DEV_88F5182:
  195                 sc->sc_version = 1;
  196                 sc->sc_edma_qlen = 128;
  197                 break;
  198         case MV_DEV_88F6281:
  199         case MV_DEV_MV78100:
  200         case MV_DEV_MV78100_Z0:
  201                 sc->sc_version = 2;
  202                 sc->sc_edma_qlen = 32;
  203                 break;
  204         default:
  205                 device_printf(dev, "unsupported SoC (ID: 0x%08X)!\n", d);
  206                 return (ENXIO);
  207         }
  208 
  209         sc->sc_edma_reqis_mask = (sc->sc_edma_qlen - 1) << SATA_EDMA_REQIS_OFS;
  210         sc->sc_edma_resos_mask = (sc->sc_edma_qlen - 1) << SATA_EDMA_RESOS_OFS;
  211 
  212         device_set_desc(dev, "Marvell Integrated SATA Controller");
  213         return (0);
  214 }
  215 
  216 static int
  217 sata_attach(device_t dev)
  218 {
  219         struct sata_softc *sc;
  220         int mem_id, irq_id, error, i;
  221         device_t ata_chan;
  222         uint32_t reg;
  223 
  224         sc = device_get_softc(dev);
  225         sc->sc_dev = dev;
  226         mem_id = 0;
  227         irq_id = 0;
  228 
  229         /* Allocate resources */
  230         sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  231             &mem_id, RF_ACTIVE);
  232         if (sc->sc_mem_res == NULL) {
  233                 device_printf(dev, "could not allocate memory.\n");
  234                 return (ENOMEM);
  235         }
  236 
  237         sc->sc_mem_res_bustag = rman_get_bustag(sc->sc_mem_res);
  238         sc->sc_mem_res_bushdl = rman_get_bushandle(sc->sc_mem_res);
  239         KASSERT(sc->sc_mem_res_bustag && sc->sc_mem_res_bushdl,
  240             ("cannot get bus handle or tag."));
  241 
  242         sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irq_id,
  243             RF_ACTIVE);
  244         if (sc->sc_irq_res == NULL) {
  245                 device_printf(dev, "could not allocate IRQ.\n");
  246                 error = ENOMEM;
  247                 goto err;
  248         }
  249 
  250         error = bus_setup_intr(dev, sc->sc_irq_res,
  251             INTR_TYPE_BIO | INTR_MPSAFE | INTR_ENTROPY,
  252             NULL, sata_intr, sc, &sc->sc_irq_cookiep);
  253         if (error != 0) {
  254                 device_printf(dev, "could not setup interrupt.\n");
  255                 goto err;
  256         }
  257 
  258         /* Attach channels */
  259         for (i = 0; i < SATA_CHAN_NUM; i++) {
  260                 ata_chan = device_add_child(dev, "ata",
  261                     devclass_find_free_unit(ata_devclass, 0));
  262 
  263                 if (!ata_chan) {
  264                         device_printf(dev, "cannot add channel %d.\n", i);
  265                         error = ENOMEM;
  266                         goto err;
  267                 }
  268         }
  269 
  270         /* Disable interrupt coalescing */
  271         reg = SATA_INL(sc, SATA_CR);
  272         for (i = 0; i < SATA_CHAN_NUM; i++)
  273                 reg |= SATA_CR_COALDIS(i);
  274 
  275         /* Disable DMA byte swapping */
  276         if (sc->sc_version == 2)
  277                 reg |= SATA_CR_NODMABS | SATA_CR_NOEDMABS |
  278                     SATA_CR_NOPRDPBS;
  279 
  280         SATA_OUTL(sc, SATA_CR, reg);
  281 
  282         /* Clear and mask all interrupts */
  283         SATA_OUTL(sc, SATA_ICR, 0);
  284         SATA_OUTL(sc, SATA_MIMR, 0);
  285 
  286         return(bus_generic_attach(dev));
  287 
  288 err:
  289         sata_detach(dev);
  290         return (error);
  291 }
  292 
  293 static int
  294 sata_detach(device_t dev)
  295 {
  296         struct sata_softc *sc;
  297 
  298         sc = device_get_softc(dev);
  299 
  300         if (device_is_attached(dev))
  301                 bus_generic_detach(dev);
  302 
  303         if (sc->sc_mem_res != NULL) {
  304                 bus_release_resource(dev, SYS_RES_MEMORY,
  305                     rman_get_rid(sc->sc_mem_res), sc->sc_mem_res);
  306                 sc->sc_mem_res = NULL;
  307         }
  308 
  309         if (sc->sc_irq_res != NULL) {
  310                 bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_cookiep);
  311                 bus_release_resource(dev, SYS_RES_IRQ,
  312                     rman_get_rid(sc->sc_irq_res), sc->sc_irq_res);
  313                 sc->sc_irq_res = NULL;
  314         }
  315 
  316         return (0);
  317 }
  318 
  319 static struct resource *
  320 sata_alloc_resource(device_t dev, device_t child, int type, int *rid,
  321     u_long start, u_long end, u_long count, u_int flags)
  322 {
  323         struct sata_softc *sc;
  324 
  325         sc = device_get_softc(dev);
  326 
  327         KASSERT(type == SYS_RES_IRQ && *rid == ATA_IRQ_RID,
  328             ("illegal resource request (type %u, rid %u).",
  329             type, *rid));
  330 
  331         return (sc->sc_irq_res);
  332 }
  333 
  334 static int
  335 sata_release_resource(device_t dev, device_t child, int type, int rid,
  336     struct resource *r)
  337 {
  338 
  339         KASSERT(type == SYS_RES_IRQ && rid == ATA_IRQ_RID,
  340             ("strange type %u and/or rid %u while releasing resource.", type,
  341             rid));
  342 
  343         return (0);
  344 }
  345 
  346 static int
  347 sata_setup_intr(device_t dev, device_t child, struct resource *irq, int flags,
  348     driver_filter_t *filt, driver_intr_t *function, void *argument,
  349     void **cookiep)
  350 {
  351         struct sata_softc *sc;
  352         struct ata_channel *ch;
  353 
  354         sc = device_get_softc(dev);
  355         ch = device_get_softc(child);
  356 
  357         if (filt != NULL) {
  358                 device_printf(dev, "filter interrupts are not supported.\n");
  359                 return (EINVAL);
  360         }
  361 
  362         sc->sc_interrupt[ch->unit].function = function;
  363         sc->sc_interrupt[ch->unit].argument = argument;
  364         *cookiep = sc;
  365 
  366         return (0);
  367 }
  368 
  369 static int
  370 sata_teardown_intr(device_t dev, device_t child, struct resource *irq,
  371     void *cookie)
  372 {
  373         struct sata_softc *sc;
  374         struct ata_channel *ch;
  375 
  376         sc = device_get_softc(dev);
  377         ch = device_get_softc(child);
  378 
  379         sc->sc_interrupt[ch->unit].function = NULL;
  380         sc->sc_interrupt[ch->unit].argument = NULL;
  381 
  382         return (0);
  383 }
  384 
  385 static void
  386 sata_intr(void *xsc)
  387 {
  388         struct sata_softc *sc;
  389         int unit;
  390 
  391         sc = xsc;
  392 
  393         /*
  394          * Behave like ata_generic_intr() for PCI controllers.
  395          * Simply invoke ISRs on all channels.
  396          */
  397         for (unit = 0; unit < SATA_CHAN_NUM; unit++)
  398                 if (sc->sc_interrupt[unit].function != NULL)
  399                         sc->sc_interrupt[unit].function(
  400                             sc->sc_interrupt[unit].argument);
  401 }
  402 
  403 static int
  404 sata_channel_probe(device_t dev)
  405 {
  406 
  407         device_set_desc(dev, "Marvell Integrated SATA Channel");
  408         return (ata_probe(dev));
  409 }
  410 
  411 static int
  412 sata_channel_attach(device_t dev)
  413 {
  414         struct sata_softc *sc;
  415         struct ata_channel *ch;
  416         uint64_t work;
  417         int error, i;
  418 
  419         sc = device_get_softc(device_get_parent(dev));
  420         ch = device_get_softc(dev);
  421 
  422         if (ch->attached)
  423                 return (0);
  424 
  425         ch->dev = dev;
  426         ch->unit = device_get_unit(dev);
  427         ch->flags |= ATA_USE_16BIT | ATA_NO_SLAVE | ATA_SATA;
  428 
  429         /* Set legacy ATA resources. */
  430         for (i = ATA_DATA; i <= ATA_COMMAND; i++) {
  431                 ch->r_io[i].res = sc->sc_mem_res;
  432                 ch->r_io[i].offset = SATA_SHADOWR_BASE(ch->unit) + (i << 2);
  433         }
  434 
  435         ch->r_io[ATA_CONTROL].res = sc->sc_mem_res;
  436         ch->r_io[ATA_CONTROL].offset = SATA_SHADOWR_CONTROL(ch->unit);
  437 
  438         ch->r_io[ATA_IDX_ADDR].res = sc->sc_mem_res;
  439         ata_default_registers(dev);
  440 
  441         /* Set SATA resources. */
  442         ch->r_io[ATA_SSTATUS].res = sc->sc_mem_res;
  443         ch->r_io[ATA_SSTATUS].offset = SATA_SATA_SSTATUS(ch->unit);
  444         ch->r_io[ATA_SERROR].res = sc->sc_mem_res;
  445         ch->r_io[ATA_SERROR].offset = SATA_SATA_SERROR(ch->unit);
  446         ch->r_io[ATA_SCONTROL].res = sc->sc_mem_res;
  447         ch->r_io[ATA_SCONTROL].offset = SATA_SATA_SCONTROL(ch->unit);
  448         ata_generic_hw(dev);
  449 
  450         ch->hw.begin_transaction = sata_channel_begin_transaction;
  451         ch->hw.end_transaction = sata_channel_end_transaction;
  452         ch->hw.status = sata_channel_status;
  453 
  454         /* Set DMA resources */
  455         ata_dmainit(dev);
  456         ch->dma.setprd = sata_channel_dmasetprd;
  457 
  458         /* Clear work area */
  459         KASSERT(sc->sc_edma_qlen * (sizeof(struct sata_crqb) +
  460             sizeof(struct sata_crpb)) <= ch->dma.max_iosize,
  461             ("insufficient DMA memory for request/response queues.\n"));
  462         bzero(ch->dma.work, sc->sc_edma_qlen * (sizeof(struct sata_crqb) +
  463             sizeof(struct sata_crpb)));
  464         bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map,
  465             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  466 
  467         /* Turn off EDMA engine */
  468         error = sata_edma_ctrl(dev, 0);
  469         if (error) {
  470                 ata_dmafini(dev);
  471                 return (error);
  472         }
  473 
  474         /*
  475          * Initialize EDMA engine:
  476          *      - Native Command Queuing off,
  477          *      - Non-Queued operation,
  478          *      - Host Queue Cache enabled.
  479          */
  480         SATA_OUTL(sc, SATA_EDMA_CFG(ch->unit), SATA_EDMA_CFG_HQCACHE |
  481             (sc->sc_version == 1) ? SATA_EDMA_CFG_QL128 : 0);
  482 
  483         /* Set request queue pointers */
  484         work = ch->dma.work_bus;
  485         SATA_OUTL(sc, SATA_EDMA_REQBAHR(ch->unit), work >> 32);
  486         SATA_OUTL(sc, SATA_EDMA_REQIPR(ch->unit), work & 0xFFFFFFFF);
  487         SATA_OUTL(sc, SATA_EDMA_REQOPR(ch->unit), work & 0xFFFFFFFF);
  488 
  489         /* Set response queue pointers */
  490         work += sc->sc_edma_qlen * sizeof(struct sata_crqb);
  491         SATA_OUTL(sc, SATA_EDMA_RESBAHR(ch->unit), work >> 32);
  492         SATA_OUTL(sc, SATA_EDMA_RESIPR(ch->unit), work & 0xFFFFFFFF);
  493         SATA_OUTL(sc, SATA_EDMA_RESOPR(ch->unit), work & 0xFFFFFFFF);
  494 
  495         /* Clear any outstanding interrupts */
  496         ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
  497         SATA_OUTL(sc, SATA_SATA_FISICR(ch->unit), 0);
  498         SATA_OUTL(sc, SATA_EDMA_IECR(ch->unit), 0);
  499         SATA_OUTL(sc, SATA_ICR,
  500             ~(SATA_ICR_DEV(ch->unit) | SATA_ICR_DMADONE(ch->unit)));
  501 
  502         /* Umask channel interrupts */
  503         SATA_OUTL(sc, SATA_EDMA_IEMR(ch->unit), 0xFFFFFFFF);
  504         SATA_OUTL(sc, SATA_MIMR, SATA_INL(sc, SATA_MIMR) |
  505             SATA_MICR_DONE(ch->unit) | SATA_MICR_DMADONE(ch->unit) |
  506             SATA_MICR_ERR(ch->unit));
  507 
  508         ch->attached = 1;
  509 
  510         return (ata_attach(dev));
  511 }
  512 
  513 static int
  514 sata_channel_detach(device_t dev)
  515 {
  516         struct sata_softc *sc;
  517         struct ata_channel *ch;
  518         int error;
  519 
  520         sc = device_get_softc(device_get_parent(dev));
  521         ch = device_get_softc(dev);
  522 
  523         if (!ch->attached)
  524                 return (0);
  525 
  526         /* Turn off EDMA engine */
  527         sata_edma_ctrl(dev, 0);
  528 
  529         /* Mask chanel interrupts */
  530         SATA_OUTL(sc, SATA_EDMA_IEMR(ch->unit), 0);
  531         SATA_OUTL(sc, SATA_MIMR, SATA_INL(sc, SATA_MIMR) & ~(
  532             SATA_MICR_DONE(ch->unit) | SATA_MICR_DMADONE(ch->unit) |
  533             SATA_MICR_ERR(ch->unit)));
  534 
  535         error = ata_detach(dev);
  536         ata_dmafini(dev);
  537 
  538         ch->attached = 0;
  539 
  540         return (error);
  541 }
  542 
  543 static int
  544 sata_channel_begin_transaction(struct ata_request *request)
  545 {
  546         struct sata_softc *sc;
  547         struct ata_channel *ch;
  548         struct sata_crqb *crqb;
  549         uint32_t req_in;
  550         int error, slot;
  551 
  552         sc = device_get_softc(device_get_parent(request->parent));
  553         ch = device_get_softc(request->parent);
  554 
  555         mtx_assert(&ch->state_mtx, MA_OWNED);
  556 
  557         /* Only DMA R/W goes through the EDMA machine. */
  558         if (request->u.ata.command != ATA_READ_DMA &&
  559             request->u.ata.command != ATA_WRITE_DMA &&
  560             request->u.ata.command != ATA_READ_DMA48 &&
  561             request->u.ata.command != ATA_WRITE_DMA48) {
  562 
  563                 /* Disable EDMA before accessing legacy registers */
  564                 if (sata_edma_is_running(request->parent)) {
  565                         error = sata_edma_ctrl(request->parent, 0);
  566                         if (error) {
  567                                 request->result = error;
  568                                 return (ATA_OP_FINISHED);
  569                         }
  570                 }
  571 
  572                 return (ata_begin_transaction(request));
  573         }
  574 
  575         /* Prepare data for DMA */
  576         if ((error = ch->dma.load(request, NULL, NULL))) {
  577                 device_printf(request->parent, "setting up DMA failed!\n");
  578                 request->result = error;
  579                 return ATA_OP_FINISHED;
  580         }
  581 
  582         /* Get next free queue slot */
  583         req_in = SATA_INL(sc, SATA_EDMA_REQIPR(ch->unit));
  584         slot = (req_in & sc->sc_edma_reqis_mask) >> SATA_EDMA_REQIS_OFS;
  585         crqb = (struct sata_crqb *)(ch->dma.work +
  586             (slot << SATA_EDMA_REQIS_OFS));
  587 
  588         /* Fill in request */
  589         bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map,
  590             BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
  591 
  592         crqb->crqb_prdlo = htole32((uint64_t)request->dma->sg_bus & 0xFFFFFFFF);
  593         crqb->crqb_prdhi = htole32((uint64_t)request->dma->sg_bus >> 32);
  594         crqb->crqb_flags = htole32((request->flags & ATA_R_READ ? 0x01 : 0x00) |
  595             (request->tag << 1));
  596 
  597         crqb->crqb_ata_command = request->u.ata.command;
  598         crqb->crqb_ata_feature = request->u.ata.feature;
  599         crqb->crqb_ata_lba_low = request->u.ata.lba;
  600         crqb->crqb_ata_lba_mid = request->u.ata.lba >> 8;
  601         crqb->crqb_ata_lba_high = request->u.ata.lba >> 16;
  602         crqb->crqb_ata_device = ((request->u.ata.lba >> 24) & 0x0F) | (1 << 6);
  603         crqb->crqb_ata_lba_low_p = request->u.ata.lba >> 24;
  604         crqb->crqb_ata_lba_mid_p = request->u.ata.lba >> 32;
  605         crqb->crqb_ata_lba_high_p = request->u.ata.lba >> 40;
  606         crqb->crqb_ata_feature_p = request->u.ata.feature >> 8;
  607         crqb->crqb_ata_count = request->u.ata.count;
  608         crqb->crqb_ata_count_p = request->u.ata.count >> 8;
  609 
  610         bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map,
  611             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  612 
  613         /* Enable EDMA if disabled */
  614         if (!sata_edma_is_running(request->parent)) {
  615                 error = sata_edma_ctrl(request->parent, 1);
  616                 if (error) {
  617                         ch->dma.unload(request);
  618                         request->result = error;
  619                         return (ATA_OP_FINISHED);
  620                 }
  621         }
  622 
  623         /* Tell EDMA about new request */
  624         req_in = (req_in & ~sc->sc_edma_reqis_mask) | (((slot + 1) <<
  625             SATA_EDMA_REQIS_OFS) & sc->sc_edma_reqis_mask);
  626 
  627         SATA_OUTL(sc, SATA_EDMA_REQIPR(ch->unit), req_in);
  628 
  629         return (ATA_OP_CONTINUES);
  630 }
  631 
  632 static int
  633 sata_channel_end_transaction(struct ata_request *request)
  634 {
  635         struct sata_softc *sc;
  636         struct ata_channel *ch;
  637         struct sata_crpb *crpb;
  638         uint32_t res_in, res_out, icr;
  639         int slot;
  640 
  641         sc = device_get_softc(device_get_parent(request->parent));
  642         ch = device_get_softc(request->parent);
  643 
  644         mtx_assert(&ch->state_mtx, MA_OWNED);
  645 
  646         icr = SATA_INL(sc, SATA_ICR);
  647         if (icr & SATA_ICR_DMADONE(ch->unit)) {
  648                 /* Get current response slot */
  649                 res_out = SATA_INL(sc, SATA_EDMA_RESOPR(ch->unit));
  650                 slot = (res_out & sc->sc_edma_resos_mask) >>
  651                     SATA_EDMA_RESOS_OFS;
  652                 crpb = (struct sata_crpb *)(ch->dma.work +
  653                     (sc->sc_edma_qlen * sizeof(struct sata_crqb)) +
  654                     (slot << SATA_EDMA_RESOS_OFS));
  655 
  656                 /* Record this request status */
  657                 bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map,
  658                     BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
  659 
  660                 request->status = crpb->crpb_dev_status;
  661                 request->error = 0;
  662 
  663                 bus_dmamap_sync(ch->dma.work_tag, ch->dma.work_map,
  664                     BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  665 
  666                 /* Update response queue pointer */
  667                 res_out = (res_out & ~sc->sc_edma_resos_mask) | (((slot + 1) <<
  668                     SATA_EDMA_RESOS_OFS) & sc->sc_edma_resos_mask);
  669 
  670                 SATA_OUTL(sc, SATA_EDMA_RESOPR(ch->unit), res_out);
  671 
  672                 /* Ack DMA interrupt if there is nothing more to do */
  673                 res_in = SATA_INL(sc, SATA_EDMA_RESIPR(ch->unit));
  674                 res_in &= sc->sc_edma_resos_mask;
  675                 res_out &= sc->sc_edma_resos_mask;
  676 
  677                 if (res_in == res_out)
  678                         SATA_OUTL(sc, SATA_ICR,
  679                             ~SATA_ICR_DMADONE(ch->unit));
  680 
  681                 /* Update progress */
  682                 if (!(request->status & ATA_S_ERROR) &&
  683                     !(request->flags & ATA_R_TIMEOUT))
  684                         request->donecount = request->bytecount;
  685 
  686                 /* Unload DMA data */
  687                 ch->dma.unload(request);
  688 
  689                 return(ATA_OP_FINISHED);
  690         }
  691 
  692         /* Legacy ATA interrupt */
  693         return (ata_end_transaction(request));
  694 }
  695 
  696 static int
  697 sata_channel_status(device_t dev)
  698 {
  699         struct sata_softc *sc;
  700         struct ata_channel *ch;
  701         uint32_t icr, iecr;
  702 
  703         sc = device_get_softc(device_get_parent(dev));
  704         ch = device_get_softc(dev);
  705 
  706         icr = SATA_INL(sc, SATA_ICR);
  707         iecr = SATA_INL(sc, SATA_EDMA_IECR(ch->unit));
  708 
  709         if ((icr & SATA_ICR_DEV(ch->unit)) || iecr) {
  710                 /* Disable EDMA before accessing SATA registers */
  711                 sata_edma_ctrl(dev, 0);
  712                 ata_sata_phy_check_events(dev, -1);
  713 
  714                 /* Ack device and error interrupt */
  715                 SATA_OUTL(sc, SATA_ICR, ~SATA_ICR_DEV(ch->unit));
  716                 SATA_OUTL(sc, SATA_EDMA_IECR(ch->unit), 0);
  717         }
  718 
  719         icr &= SATA_ICR_DEV(ch->unit) | SATA_ICR_DMADONE(ch->unit);
  720         return (icr);
  721 }
  722 
  723 static void
  724 sata_channel_reset(device_t dev)
  725 {
  726         struct sata_softc *sc;
  727         struct ata_channel *ch;
  728 
  729         sc = device_get_softc(device_get_parent(dev));
  730         ch = device_get_softc(dev);
  731 
  732         /* Disable EDMA before using legacy registers */
  733         sata_edma_ctrl(dev, 0);
  734 
  735         /* Mask all EDMA interrups */
  736         SATA_OUTL(sc, SATA_EDMA_IEMR(ch->unit), 0);
  737 
  738         /* Reset EDMA */
  739         SATA_OUTL(sc, SATA_EDMA_CMD(ch->unit), SATA_EDMA_CMD_RESET);
  740         DELAY(25);
  741         SATA_OUTL(sc, SATA_EDMA_CMD(ch->unit), 0);
  742 
  743         /* Reset PHY and device */
  744         if (ata_sata_phy_reset(dev, -1, 1))
  745                 ata_generic_reset(dev);
  746         else
  747                 ch->devices = 0;
  748 
  749         /* Clear EDMA errors */
  750         SATA_OUTL(sc, SATA_SATA_FISICR(ch->unit), 0);
  751         SATA_OUTL(sc, SATA_EDMA_IECR(ch->unit), 0);
  752 
  753         /* Unmask all EDMA interrups */
  754         SATA_OUTL(sc, SATA_EDMA_IEMR(ch->unit), 0xFFFFFFFF);
  755 }
  756 
  757 static int
  758 sata_channel_setmode(device_t parent, int target, int mode)
  759 {
  760 
  761         /* Disable EDMA before using legacy registers */
  762         sata_edma_ctrl(parent, 0);
  763         return (ata_sata_setmode(parent, target, mode));
  764 }
  765 
  766 static int
  767 sata_channel_getrev(device_t parent, int target)
  768 {
  769 
  770         /* Disable EDMA before using legacy registers */
  771         sata_edma_ctrl(parent, 0);
  772         return (ata_sata_getrev(parent, target));
  773 }
  774 
  775 static void
  776 sata_channel_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs,
  777     int error)
  778 {
  779         struct ata_dmasetprd_args *args;
  780         struct sata_prdentry *prd;
  781         int i;
  782 
  783         args = xsc;
  784         prd = args->dmatab;
  785 
  786         if ((args->error = error))
  787                 return;
  788 
  789         for (i = 0; i < nsegs; i++) {
  790                 prd[i].prd_addrlo = htole32(segs[i].ds_addr);
  791                 prd[i].prd_addrhi = htole32((uint64_t)segs[i].ds_addr >> 32);
  792                 prd[i].prd_count = htole32(segs[i].ds_len);
  793         }
  794 
  795         prd[i - 1].prd_count |= htole32(ATA_DMA_EOT);
  796         KASSERT(nsegs <= ATA_DMA_ENTRIES, ("too many DMA segment entries.\n"));
  797         args->nsegs = nsegs;
  798 }
  799 
  800 static int
  801 sata_edma_ctrl(device_t dev, int on)
  802 {
  803         struct sata_softc *sc;
  804         struct ata_channel *ch;
  805         int bit, timeout;
  806         uint32_t reg;
  807 
  808         sc = device_get_softc(device_get_parent(dev));
  809         ch = device_get_softc(dev);
  810         bit = on ? SATA_EDMA_CMD_ENABLE : SATA_EDMA_CMD_DISABLE;
  811         timeout = EDMA_TIMEOUT;
  812 
  813         SATA_OUTL(sc, SATA_EDMA_CMD(ch->unit), bit);
  814 
  815         while (1) {
  816                 DELAY(1);
  817 
  818                 reg = SATA_INL(sc, SATA_EDMA_CMD(ch->unit));
  819 
  820                 /* Enable bit will be 1 after disable command completion */
  821                 if (on && (reg & SATA_EDMA_CMD_ENABLE))
  822                         break;
  823 
  824                 /* Disable bit will be 0 after disable command completion */
  825                 if (!on && !(reg & SATA_EDMA_CMD_DISABLE))
  826                         break;
  827 
  828                 if (timeout-- <= 0) {
  829                         device_printf(dev, "EDMA command timeout!\n");
  830                         return (ETIMEDOUT);
  831                 }
  832         }
  833 
  834         return (0);
  835 }
  836 
  837 static int
  838 sata_edma_is_running(device_t dev)
  839 {
  840         struct sata_softc *sc;
  841         struct ata_channel *ch;
  842 
  843         sc = device_get_softc(device_get_parent(dev));
  844         ch = device_get_softc(dev);
  845 
  846         return (SATA_INL(sc, SATA_EDMA_CMD(ch->unit)) & SATA_EDMA_CMD_ENABLE);
  847 }
  848 
  849 static device_method_t sata_channel_methods[] = {
  850         /* Device interface. */
  851         DEVMETHOD(device_probe,         sata_channel_probe),
  852         DEVMETHOD(device_attach,        sata_channel_attach),
  853         DEVMETHOD(device_detach,        sata_channel_detach),
  854         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  855         DEVMETHOD(device_suspend,       ata_suspend),
  856         DEVMETHOD(device_resume,        ata_resume),
  857 
  858         /* ATA channel interface */
  859         DEVMETHOD(ata_reset,            sata_channel_reset),
  860         DEVMETHOD(ata_setmode,          sata_channel_setmode),
  861         DEVMETHOD(ata_getrev,           sata_channel_getrev),
  862         { 0, 0 }
  863 };
  864 
  865 driver_t sata_channel_driver = {
  866         "ata",
  867         sata_channel_methods,
  868         sizeof(struct ata_channel),
  869 };
  870 
  871 DRIVER_MODULE(ata, sata, sata_channel_driver, ata_devclass, 0, 0);

Cache object: 23b4e7c1a11ee3381b80e247809cf995


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