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

Cache object: 761d92e47a690b636a5f9ed886a7941b


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