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/8.1/sys/arm/xscale/ixp425/avila_ata.c 194753 2009-06-23 19:29:23Z sam $");
   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/cpu.h>
   57 #include <machine/cpufunc.h>
   58 #include <machine/resource.h>
   59 #include <machine/intr.h>
   60 #include <arm/xscale/ixp425/ixp425reg.h>
   61 #include <arm/xscale/ixp425/ixp425var.h>
   62 
   63 #include <sys/ata.h>
   64 #include <sys/sema.h>
   65 #include <sys/taskqueue.h>
   66 #include <vm/uma.h>
   67 #include <dev/ata/ata-all.h>
   68 #include <ata_if.h>
   69 
   70 #define AVILA_IDE_CTRL  0x06
   71 
   72 struct ata_config {
   73         const char      *desc;          /* description for probe */
   74         uint8_t         gpin;           /* GPIO pin */
   75         uint8_t         irq;            /* IRQ */
   76         uint32_t        base16;         /* CS base addr for 16-bit */
   77         uint32_t        size16;         /* CS size for 16-bit */
   78         uint32_t        off16;          /* CS offset for 16-bit */
   79         uint32_t        basealt;        /* CS base addr for alt */
   80         uint32_t        sizealt;        /* CS size for alt */
   81         uint32_t        offalt;         /* CS offset for alt */
   82 };
   83 
   84 static const struct ata_config *
   85 ata_getconfig(struct ixp425_softc *sa)
   86 {
   87         static const struct ata_config configs[] = {
   88                 { .desc         = "Gateworks Avila IDE/CF Controller",
   89                   .gpin         = 12,
   90                   .irq          = IXP425_INT_GPIO_12,
   91                   .base16       = IXP425_EXP_BUS_CS1_HWBASE,
   92                   .size16       = IXP425_EXP_BUS_CS1_SIZE,
   93                   .off16        = EXP_TIMING_CS1_OFFSET,
   94                   .basealt      = IXP425_EXP_BUS_CS2_HWBASE,
   95                   .sizealt      = IXP425_EXP_BUS_CS2_SIZE,
   96                   .offalt       = EXP_TIMING_CS2_OFFSET,
   97                 },
   98                 { .desc         = "Gateworks Cambria IDE/CF Controller",
   99                   .gpin         = 12,
  100                   .irq          = IXP425_INT_GPIO_12,
  101                   .base16       = CAMBRIA_CFSEL0_HWBASE,
  102                   .size16       = CAMBRIA_CFSEL0_SIZE,
  103                   .off16        = EXP_TIMING_CS3_OFFSET,
  104                   .basealt      = CAMBRIA_CFSEL1_HWBASE,
  105                   .sizealt      = CAMBRIA_CFSEL1_SIZE,
  106                   .offalt       = EXP_TIMING_CS4_OFFSET,
  107                 },
  108                 { .desc         = "ADI Pronghorn Metro IDE/CF Controller",
  109                   .gpin         = 0,
  110                   .irq          = IXP425_INT_GPIO_0,
  111                   .base16       = IXP425_EXP_BUS_CS3_HWBASE,
  112                   .size16       = IXP425_EXP_BUS_CS3_SIZE,
  113                   .off16        = EXP_TIMING_CS3_OFFSET,
  114                   .basealt      = IXP425_EXP_BUS_CS4_HWBASE,
  115                   .sizealt      = IXP425_EXP_BUS_CS4_SIZE,
  116                   .offalt       = EXP_TIMING_CS4_OFFSET,
  117                 },
  118         };
  119 
  120         /* XXX honor hint? (but then no multi-board support) */
  121         /* XXX total hack */
  122         if (cpu_is_ixp43x())
  123                 return &configs[1];             /* Cambria */
  124         if (EXP_BUS_READ_4(sa, EXP_TIMING_CS2_OFFSET) != 0)
  125                 return &configs[0];             /* Avila */
  126         return &configs[2];                     /* Pronghorn */
  127 }
  128 
  129 struct ata_avila_softc {
  130         device_t                sc_dev;
  131         bus_space_tag_t         sc_iot;
  132         bus_space_handle_t      sc_exp_ioh;     /* Exp Bus config registers */
  133         bus_space_handle_t      sc_ioh;         /* CS1/3 data registers */
  134         bus_space_handle_t      sc_alt_ioh;     /* CS2/4 data registers */
  135         struct bus_space        sc_expbus_tag;
  136         struct resource         sc_ata;         /* hand-crafted for ATA */
  137         struct resource         sc_alt_ata;     /* hand-crafted for ATA */
  138         u_int32_t               sc_16bit_off;   /* EXP_TIMING_CSx_OFFSET */
  139         int                     sc_rid;         /* rid for IRQ */
  140         struct resource         *sc_irq;        /* IRQ resource */
  141         void                    *sc_ih;         /* interrupt handler */
  142         struct {
  143                 void    (*cb)(void *);
  144                 void    *arg;
  145         } sc_intr[1];                   /* NB: 1/channel */
  146 };
  147 
  148 static void ata_avila_intr(void *);
  149 bs_protos(ata);
  150 static  void ata_bs_rm_2_s(void *, bus_space_handle_t, bus_size_t,
  151                 u_int16_t *, bus_size_t);
  152 static  void ata_bs_wm_2_s(void *, bus_space_handle_t, bus_size_t,
  153                 const u_int16_t *, bus_size_t);
  154 
  155 static int
  156 ata_avila_probe(device_t dev)
  157 {
  158         struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
  159         const struct ata_config *config;
  160 
  161         config = ata_getconfig(sa);
  162         if (config != NULL) {
  163                 device_set_desc_copy(dev, config->desc);
  164                 return 0;
  165         }
  166         return ENXIO;
  167 }
  168 
  169 static int
  170 ata_avila_attach(device_t dev)
  171 {
  172         struct ata_avila_softc *sc = device_get_softc(dev);
  173         struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
  174         const struct ata_config *config;
  175 
  176         config = ata_getconfig(sa);
  177         KASSERT(config != NULL, ("no board config"));
  178 
  179         sc->sc_dev = dev;
  180         /* NB: borrow from parent */
  181         sc->sc_iot = sa->sc_iot;
  182         sc->sc_exp_ioh = sa->sc_exp_ioh;
  183 
  184         if (bus_space_map(sc->sc_iot, config->base16, config->size16,
  185             0, &sc->sc_ioh))
  186                 panic("%s: cannot map 16-bit window (0x%x/0x%x)",
  187                     __func__, config->base16, config->size16);
  188         if (bus_space_map(sc->sc_iot, config->basealt, config->sizealt,
  189             0, &sc->sc_alt_ioh))
  190                 panic("%s: cannot map alt window (0x%x/0x%x)",
  191                     __func__, config->basealt, config->sizealt);
  192         sc->sc_16bit_off = config->off16;
  193 
  194         if (config->base16 != CAMBRIA_CFSEL0_HWBASE) {
  195                 /*
  196                  * Craft special resource for ATA bus space ops
  197                  * that go through the expansion bus and require
  198                  * special hackery to ena/dis 16-bit operations.
  199                  *
  200                  * XXX probably should just make this generic for
  201                  * accessing the expansion bus.
  202                  */
  203                 sc->sc_expbus_tag.bs_cookie = sc;       /* NB: backpointer */
  204                 /* read single */
  205                 sc->sc_expbus_tag.bs_r_1        = ata_bs_r_1,
  206                 sc->sc_expbus_tag.bs_r_2        = ata_bs_r_2,
  207                 /* read multiple */
  208                 sc->sc_expbus_tag.bs_rm_2       = ata_bs_rm_2,
  209                 sc->sc_expbus_tag.bs_rm_2_s     = ata_bs_rm_2_s,
  210                 /* write (single) */
  211                 sc->sc_expbus_tag.bs_w_1        = ata_bs_w_1,
  212                 sc->sc_expbus_tag.bs_w_2        = ata_bs_w_2,
  213                 /* write multiple */
  214                 sc->sc_expbus_tag.bs_wm_2       = ata_bs_wm_2,
  215                 sc->sc_expbus_tag.bs_wm_2_s     = ata_bs_wm_2_s,
  216 
  217                 rman_set_bustag(&sc->sc_ata, &sc->sc_expbus_tag);
  218                 rman_set_bustag(&sc->sc_alt_ata, &sc->sc_expbus_tag);
  219         } else {
  220                 /*
  221                  * On Cambria use the shared CS3 expansion bus tag
  222                  * that handles interlock for sharing access with the
  223                  * optional UART's.
  224                  */
  225                 rman_set_bustag(&sc->sc_ata, &cambria_exp_bs_tag);
  226                 rman_set_bustag(&sc->sc_alt_ata, &cambria_exp_bs_tag);
  227         }
  228         rman_set_bushandle(&sc->sc_ata, sc->sc_ioh);
  229         rman_set_bushandle(&sc->sc_alt_ata, sc->sc_alt_ioh);
  230 
  231         ixp425_set_gpio(sa, config->gpin, GPIO_TYPE_EDG_RISING);
  232 
  233         /* configure CS1/3 window, leaving timing unchanged */
  234         EXP_BUS_WRITE_4(sc, sc->sc_16bit_off,
  235             EXP_BUS_READ_4(sc, sc->sc_16bit_off) |
  236                 EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN);
  237         /* configure CS2/4 window, leaving timing unchanged */
  238         EXP_BUS_WRITE_4(sc, config->offalt,
  239             EXP_BUS_READ_4(sc, config->offalt) |
  240                 EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN);
  241 
  242         /* setup interrupt */
  243         sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_rid,
  244             config->irq, config->irq, 1, RF_ACTIVE);
  245         if (!sc->sc_irq)
  246                 panic("Unable to allocate irq %u.\n", config->irq);
  247         bus_setup_intr(dev, sc->sc_irq,
  248             INTR_TYPE_BIO | INTR_MPSAFE | INTR_ENTROPY,
  249             NULL, ata_avila_intr, sc, &sc->sc_ih);
  250 
  251         /* attach channel on this controller */
  252         device_add_child(dev, "ata", -1);
  253         bus_generic_attach(dev);
  254 
  255         return 0;
  256 }
  257 
  258 static int
  259 ata_avila_detach(device_t dev)
  260 {
  261         struct ata_avila_softc *sc = device_get_softc(dev);
  262         device_t *children;
  263         int nc;
  264 
  265         /* XXX quiesce gpio? */
  266 
  267         /* detach & delete all children */
  268         if (device_get_children(dev, &children, &nc) == 0) {
  269                 if (nc > 0)
  270                         device_delete_child(dev, children[0]);
  271                 free(children, M_TEMP);
  272         }
  273 
  274         bus_teardown_intr(dev, sc->sc_irq, sc->sc_ih);
  275         bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid, sc->sc_irq);
  276 
  277         return 0;
  278 }
  279 
  280 static void
  281 ata_avila_intr(void *xsc)
  282 {
  283         struct ata_avila_softc *sc = xsc;
  284 
  285         if (sc->sc_intr[0].cb != NULL)
  286                 sc->sc_intr[0].cb(sc->sc_intr[0].arg);
  287 }
  288 
  289 static struct resource *
  290 ata_avila_alloc_resource(device_t dev, device_t child, int type, int *rid,
  291                        u_long start, u_long end, u_long count, u_int flags)
  292 {
  293         struct ata_avila_softc *sc = device_get_softc(dev);
  294 
  295         KASSERT(type == SYS_RES_IRQ && *rid == ATA_IRQ_RID,
  296             ("type %u rid %u start %lu end %lu count %lu flags %u",
  297              type, *rid, start, end, count, flags));
  298 
  299         /* doesn't matter what we return so reuse the real thing */
  300         return sc->sc_irq;
  301 }
  302 
  303 static int
  304 ata_avila_release_resource(device_t dev, device_t child, int type, int rid,
  305                          struct resource *r)
  306 {
  307         KASSERT(type == SYS_RES_IRQ && rid == ATA_IRQ_RID,
  308             ("type %u rid %u", type, rid));
  309         return 0;
  310 }
  311 
  312 static int
  313 ata_avila_setup_intr(device_t dev, device_t child, struct resource *irq, 
  314                    int flags, driver_filter_t *filt,
  315                    driver_intr_t *function, void *argument, void **cookiep)
  316 {
  317         struct ata_avila_softc *sc = device_get_softc(dev);
  318         int unit = ((struct ata_channel *)device_get_softc(child))->unit;
  319 
  320         KASSERT(unit == 0, ("unit %d", unit));
  321         sc->sc_intr[unit].cb = function;
  322         sc->sc_intr[unit].arg = argument;
  323         *cookiep = sc;
  324         return 0;
  325 }
  326 
  327 static int
  328 ata_avila_teardown_intr(device_t dev, device_t child, struct resource *irq,
  329                       void *cookie)
  330 {
  331         struct ata_avila_softc *sc = device_get_softc(dev);
  332         int unit = ((struct ata_channel *)device_get_softc(child))->unit;
  333 
  334         KASSERT(unit == 0, ("unit %d", unit));
  335         sc->sc_intr[unit].cb = NULL;
  336         sc->sc_intr[unit].arg = NULL;
  337         return 0;
  338 }
  339 
  340 /*
  341  * Bus space accessors for CF-IDE PIO operations.
  342  */
  343 
  344 /*
  345  * Enable/disable 16-bit ops on the expansion bus.
  346  */
  347 static __inline void
  348 enable_16(struct ata_avila_softc *sc)
  349 {
  350         EXP_BUS_WRITE_4(sc, sc->sc_16bit_off,
  351             EXP_BUS_READ_4(sc, sc->sc_16bit_off) &~ EXP_BYTE_EN);
  352         DELAY(100);             /* XXX? */
  353 }
  354 
  355 static __inline void
  356 disable_16(struct ata_avila_softc *sc)
  357 {
  358         DELAY(100);             /* XXX? */
  359         EXP_BUS_WRITE_4(sc, sc->sc_16bit_off,
  360             EXP_BUS_READ_4(sc, sc->sc_16bit_off) | EXP_BYTE_EN);
  361 }
  362 
  363 uint8_t
  364 ata_bs_r_1(void *t, bus_space_handle_t h, bus_size_t o)
  365 {
  366         struct ata_avila_softc *sc = t;
  367 
  368         return bus_space_read_1(sc->sc_iot, h, o);
  369 }
  370 
  371 void
  372 ata_bs_w_1(void *t, bus_space_handle_t h, bus_size_t o, u_int8_t v)
  373 {
  374         struct ata_avila_softc *sc = t;
  375 
  376         bus_space_write_1(sc->sc_iot, h, o, v);
  377 }
  378 
  379 uint16_t
  380 ata_bs_r_2(void *t, bus_space_handle_t h, bus_size_t o)
  381 {
  382         struct ata_avila_softc *sc = t;
  383         uint16_t v;
  384 
  385         enable_16(sc);
  386         v = bus_space_read_2(sc->sc_iot, h, o);
  387         disable_16(sc);
  388         return v;
  389 }
  390 
  391 void
  392 ata_bs_w_2(void *t, bus_space_handle_t h, bus_size_t o, uint16_t v)
  393 {
  394         struct ata_avila_softc *sc = t;
  395 
  396         enable_16(sc);
  397         bus_space_write_2(sc->sc_iot, h, o, v);
  398         disable_16(sc);
  399 }
  400 
  401 void
  402 ata_bs_rm_2(void *t, bus_space_handle_t h, bus_size_t o,
  403         u_int16_t *d, bus_size_t c)
  404 {
  405         struct ata_avila_softc *sc = t;
  406 
  407         enable_16(sc);
  408         bus_space_read_multi_2(sc->sc_iot, h, o, d, c);
  409         disable_16(sc);
  410 }
  411 
  412 void
  413 ata_bs_wm_2(void *t, bus_space_handle_t h, bus_size_t o,
  414         const u_int16_t *d, bus_size_t c)
  415 {
  416         struct ata_avila_softc *sc = t;
  417 
  418         enable_16(sc);
  419         bus_space_write_multi_2(sc->sc_iot, h, o, d, c);
  420         disable_16(sc);
  421 }
  422 
  423 /* XXX workaround ata driver by (incorrectly) byte swapping stream cases */
  424 
  425 void
  426 ata_bs_rm_2_s(void *t, bus_space_handle_t h, bus_size_t o,
  427         u_int16_t *d, bus_size_t c)
  428 {
  429         struct ata_avila_softc *sc = t;
  430         uint16_t v;
  431         bus_size_t i;
  432 
  433         enable_16(sc);
  434 #if 1
  435         for (i = 0; i < c; i++) {
  436                 v = bus_space_read_2(sc->sc_iot, h, o);
  437                 d[i] = bswap16(v);
  438         }
  439 #else
  440         bus_space_read_multi_stream_2(sc->sc_iot, h, o, d, c);
  441 #endif
  442         disable_16(sc);
  443 }
  444 
  445 void
  446 ata_bs_wm_2_s(void *t, bus_space_handle_t h, bus_size_t o,
  447         const u_int16_t *d, bus_size_t c)
  448 {
  449         struct ata_avila_softc *sc = t;
  450         bus_size_t i;
  451 
  452         enable_16(sc);
  453 #if 1
  454         for (i = 0; i < c; i++)
  455                 bus_space_write_2(sc->sc_iot, h, o, bswap16(d[i]));
  456 #else
  457         bus_space_write_multi_stream_2(sc->sc_iot, h, o, d, c);
  458 #endif
  459         disable_16(sc);
  460 }
  461 
  462 static device_method_t ata_avila_methods[] = {
  463         /* device interface */
  464         DEVMETHOD(device_probe,             ata_avila_probe),
  465         DEVMETHOD(device_attach,            ata_avila_attach),
  466         DEVMETHOD(device_detach,            ata_avila_detach),
  467         DEVMETHOD(device_shutdown,          bus_generic_shutdown),
  468         DEVMETHOD(device_suspend,           bus_generic_suspend),
  469         DEVMETHOD(device_resume,            bus_generic_resume),
  470 
  471         /* bus methods */
  472         DEVMETHOD(bus_alloc_resource,       ata_avila_alloc_resource),
  473         DEVMETHOD(bus_release_resource,     ata_avila_release_resource),
  474         DEVMETHOD(bus_activate_resource,    bus_generic_activate_resource),
  475         DEVMETHOD(bus_deactivate_resource,  bus_generic_deactivate_resource),
  476         DEVMETHOD(bus_setup_intr,           ata_avila_setup_intr),
  477         DEVMETHOD(bus_teardown_intr,        ata_avila_teardown_intr),
  478 
  479         { 0, 0 }
  480 };
  481 
  482 devclass_t ata_avila_devclass;
  483 
  484 static driver_t ata_avila_driver = {
  485         "ata_avila",
  486         ata_avila_methods,
  487         sizeof(struct ata_avila_softc),
  488 };
  489 
  490 DRIVER_MODULE(ata_avila, ixp, ata_avila_driver, ata_avila_devclass, 0, 0);
  491 MODULE_VERSION(ata_avila, 1);
  492 MODULE_DEPEND(ata_avila, ata, 1, 1, 1);
  493 
  494 static int
  495 avila_channel_probe(device_t dev)
  496 {
  497         struct ata_channel *ch = device_get_softc(dev);
  498 
  499         ch->unit = 0;
  500         ch->flags |= ATA_USE_16BIT | ATA_NO_SLAVE;
  501         device_set_desc_copy(dev, "ATA channel 0");
  502 
  503         return ata_probe(dev);
  504 }
  505 
  506 static int
  507 avila_channel_attach(device_t dev)
  508 {
  509         struct ata_avila_softc *sc = device_get_softc(device_get_parent(dev));
  510         struct ata_channel *ch = device_get_softc(dev);
  511         int i;
  512 
  513         for (i = 0; i < ATA_MAX_RES; i++)
  514                 ch->r_io[i].res = &sc->sc_ata;
  515 
  516         ch->r_io[ATA_DATA].offset = ATA_DATA;
  517         ch->r_io[ATA_FEATURE].offset = ATA_FEATURE;
  518         ch->r_io[ATA_COUNT].offset = ATA_COUNT;
  519         ch->r_io[ATA_SECTOR].offset = ATA_SECTOR;
  520         ch->r_io[ATA_CYL_LSB].offset = ATA_CYL_LSB;
  521         ch->r_io[ATA_CYL_MSB].offset = ATA_CYL_MSB;
  522         ch->r_io[ATA_DRIVE].offset = ATA_DRIVE;
  523         ch->r_io[ATA_COMMAND].offset = ATA_COMMAND;
  524         ch->r_io[ATA_ERROR].offset = ATA_FEATURE;
  525         /* NB: should be used only for ATAPI devices */
  526         ch->r_io[ATA_IREASON].offset = ATA_COUNT;
  527         ch->r_io[ATA_STATUS].offset = ATA_COMMAND;
  528 
  529         /* NB: the control and alt status registers are special */
  530         ch->r_io[ATA_ALTSTAT].res = &sc->sc_alt_ata;
  531         ch->r_io[ATA_ALTSTAT].offset = AVILA_IDE_CTRL;
  532         ch->r_io[ATA_CONTROL].res = &sc->sc_alt_ata;
  533         ch->r_io[ATA_CONTROL].offset = AVILA_IDE_CTRL;
  534 
  535         /* NB: by convention this points at the base of registers */
  536         ch->r_io[ATA_IDX_ADDR].offset = 0;
  537 
  538         ata_generic_hw(dev);
  539         return ata_attach(dev);
  540 }
  541 
  542 static device_method_t avila_channel_methods[] = {
  543         /* device interface */
  544         DEVMETHOD(device_probe,     avila_channel_probe),
  545         DEVMETHOD(device_attach,    avila_channel_attach),
  546         DEVMETHOD(device_detach,    ata_detach),
  547         DEVMETHOD(device_shutdown,  bus_generic_shutdown),
  548         DEVMETHOD(device_suspend,   ata_suspend),
  549         DEVMETHOD(device_resume,    ata_resume),
  550 
  551         { 0, 0 }
  552 };
  553 
  554 driver_t avila_channel_driver = {
  555         "ata",
  556         avila_channel_methods,
  557         sizeof(struct ata_channel),
  558 };
  559 DRIVER_MODULE(ata, ata_avila, avila_channel_driver, ata_devclass, 0, 0);

Cache object: 0229546f05f85431eca2e2a724ff6d25


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