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/xscale/ixp425/avila_ata.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) 2006 Sam Leffler, Errno Consulting
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer,
   10  *    without modification.
   11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   12  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
   13  *    redistribution must be conditioned upon including a substantially
   14  *    similar Disclaimer requirement for further binary redistribution.
   15  *
   16  * NO WARRANTY
   17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   19  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
   20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
   21  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
   22  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
   25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   27  * THE POSSIBILITY OF SUCH DAMAGES.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD: releng/11.2/sys/arm/xscale/ixp425/avila_ata.c 331722 2018-03-29 02:50:57Z eadler $");
   32 
   33 /*
   34  * Compact Flash Support for the Avila Gateworks XScale boards.
   35  * The CF slot is operated in "True IDE" mode. Registers are on
   36  * the Expansion Bus connected to CS1 and CS2. Interrupts are
   37  * tied to GPIO pin 12.  No DMA, just PIO.
   38  *
   39  * The ADI Pronghorn Metro is very similar. It use CS3 and CS4 and
   40  * GPIO pin 0 for interrupts.
   41  *
   42  * See also http://www.intel.com/design/network/applnots/302456.htm.
   43  */
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/kernel.h>
   47 #include <sys/module.h>
   48 #include <sys/time.h>
   49 #include <sys/bus.h>
   50 #include <sys/resource.h>
   51 #include <sys/rman.h>
   52 #include <sys/sysctl.h>
   53 #include <sys/endian.h>
   54 
   55 #include <machine/bus.h>
   56 #include <machine/resource.h>
   57 #include <machine/intr.h>
   58 #include <arm/xscale/ixp425/ixp425reg.h>
   59 #include <arm/xscale/ixp425/ixp425var.h>
   60 
   61 #include <sys/ata.h>
   62 #include <sys/sema.h>
   63 #include <sys/taskqueue.h>
   64 #include <vm/uma.h>
   65 #include <dev/ata/ata-all.h>
   66 #include <ata_if.h>
   67 
   68 #define AVILA_IDE_CTRL  0x06
   69 
   70 struct ata_config {
   71         const char      *desc;          /* description for probe */
   72         uint8_t         gpin;           /* GPIO pin */
   73         uint8_t         irq;            /* IRQ */
   74         uint32_t        base16;         /* CS base addr for 16-bit */
   75         uint32_t        size16;         /* CS size for 16-bit */
   76         uint32_t        off16;          /* CS offset for 16-bit */
   77         uint32_t        basealt;        /* CS base addr for alt */
   78         uint32_t        sizealt;        /* CS size for alt */
   79         uint32_t        offalt;         /* CS offset for alt */
   80 };
   81 
   82 static const struct ata_config *
   83 ata_getconfig(struct ixp425_softc *sa)
   84 {
   85         static const struct ata_config configs[] = {
   86                 { .desc         = "Gateworks Avila IDE/CF Controller",
   87                   .gpin         = 12,
   88                   .irq          = IXP425_INT_GPIO_12,
   89                   .base16       = IXP425_EXP_BUS_CS1_HWBASE,
   90                   .size16       = IXP425_EXP_BUS_CS1_SIZE,
   91                   .off16        = EXP_TIMING_CS1_OFFSET,
   92                   .basealt      = IXP425_EXP_BUS_CS2_HWBASE,
   93                   .sizealt      = IXP425_EXP_BUS_CS2_SIZE,
   94                   .offalt       = EXP_TIMING_CS2_OFFSET,
   95                 },
   96                 { .desc         = "Gateworks Cambria IDE/CF Controller",
   97                   .gpin         = 12,
   98                   .irq          = IXP425_INT_GPIO_12,
   99                   .base16       = CAMBRIA_CFSEL0_HWBASE,
  100                   .size16       = CAMBRIA_CFSEL0_SIZE,
  101                   .off16        = EXP_TIMING_CS3_OFFSET,
  102                   .basealt      = CAMBRIA_CFSEL1_HWBASE,
  103                   .sizealt      = CAMBRIA_CFSEL1_SIZE,
  104                   .offalt       = EXP_TIMING_CS4_OFFSET,
  105                 },
  106                 { .desc         = "ADI Pronghorn Metro IDE/CF Controller",
  107                   .gpin         = 0,
  108                   .irq          = IXP425_INT_GPIO_0,
  109                   .base16       = IXP425_EXP_BUS_CS3_HWBASE,
  110                   .size16       = IXP425_EXP_BUS_CS3_SIZE,
  111                   .off16        = EXP_TIMING_CS3_OFFSET,
  112                   .basealt      = IXP425_EXP_BUS_CS4_HWBASE,
  113                   .sizealt      = IXP425_EXP_BUS_CS4_SIZE,
  114                   .offalt       = EXP_TIMING_CS4_OFFSET,
  115                 },
  116         };
  117 
  118         /* XXX honor hint? (but then no multi-board support) */
  119         /* XXX total hack */
  120         if (cpu_is_ixp43x())
  121                 return &configs[1];             /* Cambria */
  122         if (EXP_BUS_READ_4(sa, EXP_TIMING_CS2_OFFSET) != 0)
  123                 return &configs[0];             /* Avila */
  124         return &configs[2];                     /* Pronghorn */
  125 }
  126 
  127 struct ata_avila_softc {
  128         device_t                sc_dev;
  129         bus_space_tag_t         sc_iot;
  130         bus_space_handle_t      sc_exp_ioh;     /* Exp Bus config registers */
  131         bus_space_handle_t      sc_ioh;         /* CS1/3 data registers */
  132         bus_space_handle_t      sc_alt_ioh;     /* CS2/4 data registers */
  133         struct bus_space        sc_expbus_tag;
  134         struct resource         sc_ata;         /* hand-crafted for ATA */
  135         struct resource         sc_alt_ata;     /* hand-crafted for ATA */
  136         u_int32_t               sc_16bit_off;   /* EXP_TIMING_CSx_OFFSET */
  137         int                     sc_rid;         /* rid for IRQ */
  138         struct resource         *sc_irq;        /* IRQ resource */
  139         void                    *sc_ih;         /* interrupt handler */
  140         struct {
  141                 void    (*cb)(void *);
  142                 void    *arg;
  143         } sc_intr[1];                   /* NB: 1/channel */
  144 };
  145 
  146 static void ata_avila_intr(void *);
  147 bs_protos(ata);
  148 static  void ata_bs_rm_2_s(bus_space_tag_t tag, bus_space_handle_t, bus_size_t,
  149                 u_int16_t *, bus_size_t);
  150 static  void ata_bs_wm_2_s(bus_space_tag_t tag, bus_space_handle_t, bus_size_t,
  151                 const u_int16_t *, bus_size_t);
  152 
  153 static int
  154 ata_avila_probe(device_t dev)
  155 {
  156         struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
  157         const struct ata_config *config;
  158 
  159         config = ata_getconfig(sa);
  160         if (config != NULL) {
  161                 device_set_desc_copy(dev, config->desc);
  162                 return 0;
  163         }
  164         return ENXIO;
  165 }
  166 
  167 static int
  168 ata_avila_attach(device_t dev)
  169 {
  170         struct ata_avila_softc *sc = device_get_softc(dev);
  171         struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
  172         const struct ata_config *config;
  173 
  174         config = ata_getconfig(sa);
  175         KASSERT(config != NULL, ("no board config"));
  176 
  177         sc->sc_dev = dev;
  178         /* NB: borrow from parent */
  179         sc->sc_iot = sa->sc_iot;
  180         sc->sc_exp_ioh = sa->sc_exp_ioh;
  181 
  182         if (bus_space_map(sc->sc_iot, config->base16, config->size16,
  183             0, &sc->sc_ioh))
  184                 panic("%s: cannot map 16-bit window (0x%x/0x%x)",
  185                     __func__, config->base16, config->size16);
  186         if (bus_space_map(sc->sc_iot, config->basealt, config->sizealt,
  187             0, &sc->sc_alt_ioh))
  188                 panic("%s: cannot map alt window (0x%x/0x%x)",
  189                     __func__, config->basealt, config->sizealt);
  190         sc->sc_16bit_off = config->off16;
  191 
  192         if (config->base16 != CAMBRIA_CFSEL0_HWBASE) {
  193                 /*
  194                  * Craft special resource for ATA bus space ops
  195                  * that go through the expansion bus and require
  196                  * special hackery to ena/dis 16-bit operations.
  197                  *
  198                  * XXX probably should just make this generic for
  199                  * accessing the expansion bus.
  200                  */
  201                 sc->sc_expbus_tag.bs_privdata = sc;     /* NB: backpointer */
  202                 /* read single */
  203                 sc->sc_expbus_tag.bs_r_1        = ata_bs_r_1;
  204                 sc->sc_expbus_tag.bs_r_2        = ata_bs_r_2;
  205                 /* read multiple */
  206                 sc->sc_expbus_tag.bs_rm_2       = ata_bs_rm_2;
  207                 sc->sc_expbus_tag.bs_rm_2_s     = ata_bs_rm_2_s;
  208                 /* write (single) */
  209                 sc->sc_expbus_tag.bs_w_1        = ata_bs_w_1;
  210                 sc->sc_expbus_tag.bs_w_2        = ata_bs_w_2;
  211                 /* write multiple */
  212                 sc->sc_expbus_tag.bs_wm_2       = ata_bs_wm_2;
  213                 sc->sc_expbus_tag.bs_wm_2_s     = ata_bs_wm_2_s;
  214 
  215                 rman_set_bustag(&sc->sc_ata, &sc->sc_expbus_tag);
  216                 rman_set_bustag(&sc->sc_alt_ata, &sc->sc_expbus_tag);
  217         } else {
  218                 /*
  219                  * On Cambria use the shared CS3 expansion bus tag
  220                  * that handles interlock for sharing access with the
  221                  * optional UART's.
  222                  */
  223                 rman_set_bustag(&sc->sc_ata, &cambria_exp_bs_tag);
  224                 rman_set_bustag(&sc->sc_alt_ata, &cambria_exp_bs_tag);
  225         }
  226         rman_set_bushandle(&sc->sc_ata, sc->sc_ioh);
  227         rman_set_bushandle(&sc->sc_alt_ata, sc->sc_alt_ioh);
  228 
  229         ixp425_set_gpio(sa, config->gpin, GPIO_TYPE_EDG_RISING);
  230 
  231         /* configure CS1/3 window, leaving timing unchanged */
  232         EXP_BUS_WRITE_4(sc, sc->sc_16bit_off,
  233             EXP_BUS_READ_4(sc, sc->sc_16bit_off) |
  234                 EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN);
  235         /* configure CS2/4 window, leaving timing unchanged */
  236         EXP_BUS_WRITE_4(sc, config->offalt,
  237             EXP_BUS_READ_4(sc, config->offalt) |
  238                 EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN);
  239 
  240         /* setup interrupt */
  241         sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_rid,
  242             config->irq, config->irq, 1, RF_ACTIVE);
  243         if (!sc->sc_irq)
  244                 panic("Unable to allocate irq %u.\n", config->irq);
  245         bus_setup_intr(dev, sc->sc_irq,
  246             INTR_TYPE_BIO | INTR_MPSAFE | INTR_ENTROPY,
  247             NULL, ata_avila_intr, sc, &sc->sc_ih);
  248 
  249         /* attach channel on this controller */
  250         device_add_child(dev, "ata", -1);
  251         bus_generic_attach(dev);
  252 
  253         return 0;
  254 }
  255 
  256 static int
  257 ata_avila_detach(device_t dev)
  258 {
  259         struct ata_avila_softc *sc = device_get_softc(dev);
  260 
  261         /* XXX quiesce gpio? */
  262 
  263         /* detach & delete all children */
  264         device_delete_children(dev);
  265 
  266         bus_teardown_intr(dev, sc->sc_irq, sc->sc_ih);
  267         bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid, sc->sc_irq);
  268 
  269         return 0;
  270 }
  271 
  272 static void
  273 ata_avila_intr(void *xsc)
  274 {
  275         struct ata_avila_softc *sc = xsc;
  276 
  277         if (sc->sc_intr[0].cb != NULL)
  278                 sc->sc_intr[0].cb(sc->sc_intr[0].arg);
  279 }
  280 
  281 static struct resource *
  282 ata_avila_alloc_resource(device_t dev, device_t child, int type, int *rid,
  283                    rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
  284 {
  285         struct ata_avila_softc *sc = device_get_softc(dev);
  286 
  287         KASSERT(type == SYS_RES_IRQ && *rid == ATA_IRQ_RID,
  288             ("type %u rid %u start %ju end %ju count %ju flags %u",
  289              type, *rid, start, end, count, flags));
  290 
  291         /* doesn't matter what we return so reuse the real thing */
  292         return sc->sc_irq;
  293 }
  294 
  295 static int
  296 ata_avila_release_resource(device_t dev, device_t child, int type, int rid,
  297                          struct resource *r)
  298 {
  299         KASSERT(type == SYS_RES_IRQ && rid == ATA_IRQ_RID,
  300             ("type %u rid %u", type, rid));
  301         return 0;
  302 }
  303 
  304 static int
  305 ata_avila_setup_intr(device_t dev, device_t child, struct resource *irq,
  306                    int flags, driver_filter_t *filt,
  307                    driver_intr_t *function, void *argument, void **cookiep)
  308 {
  309         struct ata_avila_softc *sc = device_get_softc(dev);
  310         int unit = ((struct ata_channel *)device_get_softc(child))->unit;
  311 
  312         KASSERT(unit == 0, ("unit %d", unit));
  313         sc->sc_intr[unit].cb = function;
  314         sc->sc_intr[unit].arg = argument;
  315         *cookiep = sc;
  316         return 0;
  317 }
  318 
  319 static int
  320 ata_avila_teardown_intr(device_t dev, device_t child, struct resource *irq,
  321                       void *cookie)
  322 {
  323         struct ata_avila_softc *sc = device_get_softc(dev);
  324         int unit = ((struct ata_channel *)device_get_softc(child))->unit;
  325 
  326         KASSERT(unit == 0, ("unit %d", unit));
  327         sc->sc_intr[unit].cb = NULL;
  328         sc->sc_intr[unit].arg = NULL;
  329         return 0;
  330 }
  331 
  332 /*
  333  * Bus space accessors for CF-IDE PIO operations.
  334  */
  335 
  336 /*
  337  * Enable/disable 16-bit ops on the expansion bus.
  338  */
  339 static __inline void
  340 enable_16(struct ata_avila_softc *sc)
  341 {
  342         EXP_BUS_WRITE_4(sc, sc->sc_16bit_off,
  343             EXP_BUS_READ_4(sc, sc->sc_16bit_off) &~ EXP_BYTE_EN);
  344         DELAY(100);             /* XXX? */
  345 }
  346 
  347 static __inline void
  348 disable_16(struct ata_avila_softc *sc)
  349 {
  350         DELAY(100);             /* XXX? */
  351         EXP_BUS_WRITE_4(sc, sc->sc_16bit_off,
  352             EXP_BUS_READ_4(sc, sc->sc_16bit_off) | EXP_BYTE_EN);
  353 }
  354 
  355 uint8_t
  356 ata_bs_r_1(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o)
  357 {
  358         struct ata_avila_softc *sc = tag->bs_privdata;
  359 
  360         return bus_space_read_1(sc->sc_iot, h, o);
  361 }
  362 
  363 void
  364 ata_bs_w_1(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o, u_int8_t v)
  365 {
  366         struct ata_avila_softc *sc = tag->bs_privdata;
  367 
  368         bus_space_write_1(sc->sc_iot, h, o, v);
  369 }
  370 
  371 uint16_t
  372 ata_bs_r_2(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o)
  373 {
  374         struct ata_avila_softc *sc = tag->bs_privdata;
  375         uint16_t v;
  376 
  377         enable_16(sc);
  378         v = bus_space_read_2(sc->sc_iot, h, o);
  379         disable_16(sc);
  380         return v;
  381 }
  382 
  383 void
  384 ata_bs_w_2(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o, uint16_t v)
  385 {
  386         struct ata_avila_softc *sc = tag->bs_privdata;
  387 
  388         enable_16(sc);
  389         bus_space_write_2(sc->sc_iot, h, o, v);
  390         disable_16(sc);
  391 }
  392 
  393 void
  394 ata_bs_rm_2(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o,
  395         u_int16_t *d, bus_size_t c)
  396 {
  397         struct ata_avila_softc *sc = tag->bs_privdata;
  398 
  399         enable_16(sc);
  400         bus_space_read_multi_2(sc->sc_iot, h, o, d, c);
  401         disable_16(sc);
  402 }
  403 
  404 void
  405 ata_bs_wm_2(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o,
  406         const u_int16_t *d, bus_size_t c)
  407 {
  408         struct ata_avila_softc *sc = tag->bs_privdata;
  409 
  410         enable_16(sc);
  411         bus_space_write_multi_2(sc->sc_iot, h, o, d, c);
  412         disable_16(sc);
  413 }
  414 
  415 /* XXX workaround ata driver by (incorrectly) byte swapping stream cases */
  416 
  417 void
  418 ata_bs_rm_2_s(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o,
  419         u_int16_t *d, bus_size_t c)
  420 {
  421         struct ata_avila_softc *sc = tag->bs_privdata;
  422         uint16_t v;
  423         bus_size_t i;
  424 
  425         enable_16(sc);
  426 #if 1
  427         for (i = 0; i < c; i++) {
  428                 v = bus_space_read_2(sc->sc_iot, h, o);
  429                 d[i] = bswap16(v);
  430         }
  431 #else
  432         bus_space_read_multi_stream_2(sc->sc_iot, h, o, d, c);
  433 #endif
  434         disable_16(sc);
  435 }
  436 
  437 void
  438 ata_bs_wm_2_s(bus_space_tag_t tag, bus_space_handle_t h, bus_size_t o,
  439         const u_int16_t *d, bus_size_t c)
  440 {
  441         struct ata_avila_softc *sc = tag->bs_privdata;
  442         bus_size_t i;
  443 
  444         enable_16(sc);
  445 #if 1
  446         for (i = 0; i < c; i++)
  447                 bus_space_write_2(sc->sc_iot, h, o, bswap16(d[i]));
  448 #else
  449         bus_space_write_multi_stream_2(sc->sc_iot, h, o, d, c);
  450 #endif
  451         disable_16(sc);
  452 }
  453 
  454 static device_method_t ata_avila_methods[] = {
  455         /* device interface */
  456         DEVMETHOD(device_probe,             ata_avila_probe),
  457         DEVMETHOD(device_attach,            ata_avila_attach),
  458         DEVMETHOD(device_detach,            ata_avila_detach),
  459         DEVMETHOD(device_shutdown,          bus_generic_shutdown),
  460         DEVMETHOD(device_suspend,           bus_generic_suspend),
  461         DEVMETHOD(device_resume,            bus_generic_resume),
  462 
  463         /* bus methods */
  464         DEVMETHOD(bus_alloc_resource,       ata_avila_alloc_resource),
  465         DEVMETHOD(bus_release_resource,     ata_avila_release_resource),
  466         DEVMETHOD(bus_activate_resource,    bus_generic_activate_resource),
  467         DEVMETHOD(bus_deactivate_resource,  bus_generic_deactivate_resource),
  468         DEVMETHOD(bus_setup_intr,           ata_avila_setup_intr),
  469         DEVMETHOD(bus_teardown_intr,        ata_avila_teardown_intr),
  470 
  471         { 0, 0 }
  472 };
  473 
  474 devclass_t ata_avila_devclass;
  475 
  476 static driver_t ata_avila_driver = {
  477         "ata_avila",
  478         ata_avila_methods,
  479         sizeof(struct ata_avila_softc),
  480 };
  481 
  482 DRIVER_MODULE(ata_avila, ixp, ata_avila_driver, ata_avila_devclass, 0, 0);
  483 MODULE_VERSION(ata_avila, 1);
  484 MODULE_DEPEND(ata_avila, ata, 1, 1, 1);
  485 
  486 static int
  487 avila_channel_probe(device_t dev)
  488 {
  489         struct ata_channel *ch = device_get_softc(dev);
  490 
  491         ch->unit = 0;
  492         ch->flags |= ATA_USE_16BIT | ATA_NO_SLAVE;
  493         device_set_desc_copy(dev, "ATA channel 0");
  494 
  495         return ata_probe(dev);
  496 }
  497 
  498 static int
  499 avila_channel_attach(device_t dev)
  500 {
  501         struct ata_avila_softc *sc = device_get_softc(device_get_parent(dev));
  502         struct ata_channel *ch = device_get_softc(dev);
  503         int i;
  504 
  505         for (i = 0; i < ATA_MAX_RES; i++)
  506                 ch->r_io[i].res = &sc->sc_ata;
  507 
  508         ch->r_io[ATA_DATA].offset = ATA_DATA;
  509         ch->r_io[ATA_FEATURE].offset = ATA_FEATURE;
  510         ch->r_io[ATA_COUNT].offset = ATA_COUNT;
  511         ch->r_io[ATA_SECTOR].offset = ATA_SECTOR;
  512         ch->r_io[ATA_CYL_LSB].offset = ATA_CYL_LSB;
  513         ch->r_io[ATA_CYL_MSB].offset = ATA_CYL_MSB;
  514         ch->r_io[ATA_DRIVE].offset = ATA_DRIVE;
  515         ch->r_io[ATA_COMMAND].offset = ATA_COMMAND;
  516         ch->r_io[ATA_ERROR].offset = ATA_FEATURE;
  517         /* NB: should be used only for ATAPI devices */
  518         ch->r_io[ATA_IREASON].offset = ATA_COUNT;
  519         ch->r_io[ATA_STATUS].offset = ATA_COMMAND;
  520 
  521         /* NB: the control and alt status registers are special */
  522         ch->r_io[ATA_ALTSTAT].res = &sc->sc_alt_ata;
  523         ch->r_io[ATA_ALTSTAT].offset = AVILA_IDE_CTRL;
  524         ch->r_io[ATA_CONTROL].res = &sc->sc_alt_ata;
  525         ch->r_io[ATA_CONTROL].offset = AVILA_IDE_CTRL;
  526 
  527         /* NB: by convention this points at the base of registers */
  528         ch->r_io[ATA_IDX_ADDR].offset = 0;
  529 
  530         ata_generic_hw(dev);
  531         return ata_attach(dev);
  532 }
  533 
  534 static device_method_t avila_channel_methods[] = {
  535         /* device interface */
  536         DEVMETHOD(device_probe,     avila_channel_probe),
  537         DEVMETHOD(device_attach,    avila_channel_attach),
  538         DEVMETHOD(device_detach,    ata_detach),
  539         DEVMETHOD(device_shutdown,  bus_generic_shutdown),
  540         DEVMETHOD(device_suspend,   ata_suspend),
  541         DEVMETHOD(device_resume,    ata_resume),
  542 
  543         { 0, 0 }
  544 };
  545 
  546 driver_t avila_channel_driver = {
  547         "ata",
  548         avila_channel_methods,
  549         sizeof(struct ata_channel),
  550 };
  551 DRIVER_MODULE(ata, ata_avila, avila_channel_driver, ata_devclass, 0, 0);

Cache object: a754c98181769ac30e8350d93d552857


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