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

Cache object: 8950fd949d42de2b8370e59331165c86


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