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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
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/6.3/sys/arm/xscale/ixp425/avila_ata.c 167038 2007-02-26 23:13:09Z cognet $");
   32 
   33 /*
   34  * Compact Flash Support for the Avila Gateworks XScale boards.
   35  * There are 1 or 2 optional CF slots operated in "True IDE" mode.
   36  * Registers are on the Expansion Bus connected to CS1.  Interrupts
   37  * are tied to GPIO pin 12.  No DMA, just PIO.
   38  *
   39  * See also http://www.intel.com/design/network/applnots/302456.htm.
   40  */
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/kernel.h>
   44 #include <sys/module.h>
   45 #include <sys/time.h>
   46 #include <sys/bus.h>
   47 #include <sys/resource.h>
   48 #define __RMAN_RESOURCE_VISIBLE
   49 #include <sys/rman.h>
   50 #include <sys/sysctl.h>
   51 #include <sys/endian.h>
   52 
   53 #include <machine/bus.h>
   54 #include <machine/cpu.h>
   55 #include <machine/cpufunc.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_GPIN  12              /* GPIO pin # */
   69 #define AVILA_IDE_IRQ   IXP425_INT_GPIO_12
   70 #define AVILA_IDE_CTRL  0x1e            /* control register */
   71 
   72 struct ata_avila_softc {
   73         device_t                sc_dev;
   74         bus_space_tag_t         sc_iot;
   75         bus_space_handle_t      sc_exp_ioh;     /* Exp Bus config registers */
   76         bus_space_handle_t      sc_ioh;         /* CS1 data registers */
   77         struct bus_space        sc_expbus_tag;
   78         struct resource         sc_ata;         /* hand-crafted for ATA */
   79         int                     sc_rid;         /* rid for IRQ */
   80         struct resource         *sc_irq;        /* IRQ resource */
   81         void                    *sc_ih;         /* interrupt handler */
   82         struct {
   83                 void    (*cb)(void *);
   84                 void    *arg;
   85         } sc_intr[1];                   /* NB: 1/channel */
   86 };
   87 
   88 static void ata_avila_intr(void *);
   89 bs_protos(ata);
   90 static  void ata_bs_rm_2_s(void *, bus_space_handle_t, bus_size_t,
   91                 u_int16_t *, bus_size_t);
   92 static  void ata_bs_wm_2_s(void *, bus_space_handle_t, bus_size_t,
   93                 const u_int16_t *, bus_size_t);
   94 
   95 static int
   96 ata_avila_probe(device_t dev)
   97 {
   98         /* XXX any way to check? */
   99         device_set_desc_copy(dev, "Gateworks Avila IDE/CF Controller");
  100         return 0;
  101 }
  102 
  103 static int
  104 ata_avila_attach(device_t dev)
  105 {
  106         struct ata_avila_softc *sc = device_get_softc(dev);
  107         struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
  108 
  109         sc->sc_dev = dev;
  110         /* NB: borrow from parent */
  111         sc->sc_iot = sa->sc_iot;
  112         sc->sc_exp_ioh = sa->sc_exp_ioh;
  113         if (bus_space_map(sc->sc_iot,
  114             IXP425_EXP_BUS_CS1_HWBASE, IXP425_EXP_BUS_CS1_SIZE, 0, &sc->sc_ioh))
  115                 panic("%s: unable to map Expansion Bus CS1 window", __func__);
  116 
  117         /*
  118          * Craft special resource for ATA bus space ops
  119          * that go through the expansion bus and require
  120          * special hackery to ena/dis 16-bit operations.
  121          *
  122          * XXX probably should just make this generic for
  123          * accessing the expansion bus.
  124          */
  125         sc->sc_expbus_tag.bs_cookie = sc;       /* NB: backpointer */
  126         /* read single */
  127         sc->sc_expbus_tag.bs_r_1        = ata_bs_r_1,
  128         sc->sc_expbus_tag.bs_r_2        = ata_bs_r_2,
  129         /* read multiple */
  130         sc->sc_expbus_tag.bs_rm_2       = ata_bs_rm_2,
  131         sc->sc_expbus_tag.bs_rm_2_s     = ata_bs_rm_2_s,
  132         /* write (single) */
  133         sc->sc_expbus_tag.bs_w_1        = ata_bs_w_1,
  134         sc->sc_expbus_tag.bs_w_2        = ata_bs_w_2,
  135         /* write multiple */
  136         sc->sc_expbus_tag.bs_wm_2       = ata_bs_wm_2,
  137         sc->sc_expbus_tag.bs_wm_2_s     = ata_bs_wm_2_s,
  138 
  139         rman_set_bustag(&sc->sc_ata, &sc->sc_expbus_tag);
  140         rman_set_bushandle(&sc->sc_ata, sc->sc_ioh);
  141 
  142         GPIO_CONF_WRITE_4(sa, IXP425_GPIO_GPOER, 
  143             GPIO_CONF_READ_4(sa, IXP425_GPIO_GPOER) | (1<<AVILA_IDE_GPIN));
  144         /* interrupt is active low */
  145         GPIO_CONF_WRITE_4(sa, GPIO_TYPE_REG(AVILA_IDE_GPIN),
  146             GPIO_CONF_READ_4(sa, GPIO_TYPE_REG(AVILA_IDE_GPIN) |
  147             GPIO_TYPE(AVILA_IDE_GPIN, GPIO_TYPE_ACT_LOW)));
  148 
  149         /* clear ISR */
  150         GPIO_CONF_WRITE_4(sa, IXP425_GPIO_GPISR, (1<<AVILA_IDE_GPIN));
  151 
  152         /* configure CS1 window, leaving timing unchanged */
  153         EXP_BUS_WRITE_4(sc, EXP_TIMING_CS1_OFFSET,
  154             EXP_BUS_READ_4(sc, EXP_TIMING_CS1_OFFSET) |
  155                 EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN);
  156 
  157         /* setup interrupt */
  158         sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_rid,
  159             AVILA_IDE_IRQ, AVILA_IDE_IRQ, 1, RF_ACTIVE);
  160         if (!sc->sc_irq)
  161                 panic("Unable to allocate irq %u.\n", AVILA_IDE_IRQ);
  162         bus_setup_intr(dev, sc->sc_irq,
  163             INTR_TYPE_BIO | INTR_MPSAFE | INTR_ENTROPY,
  164             ata_avila_intr, sc, &sc->sc_ih);
  165 
  166         /* attach channel on this controller */
  167         device_add_child(dev, "ata", devclass_find_free_unit(ata_devclass, 0));
  168         bus_generic_attach(dev);
  169 
  170         return 0;
  171 }
  172 
  173 static int
  174 ata_avila_detach(device_t dev)
  175 {
  176         struct ata_avila_softc *sc = device_get_softc(dev);
  177         device_t *children;
  178         int nc;
  179 
  180         /* XXX quiesce gpio? */
  181 
  182         /* detach & delete all children */
  183         if (device_get_children(dev, &children, &nc) == 0) {
  184             if (nc > 0)
  185                     device_delete_child(dev, children[0]);
  186             free(children, M_TEMP);
  187         }
  188 
  189         bus_teardown_intr(dev, sc->sc_irq, sc->sc_ih);
  190         bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid, sc->sc_irq);
  191 
  192         return 0;
  193 }
  194 
  195 static void
  196 ata_avila_intr(void *xsc)
  197 {
  198         struct ata_avila_softc *sc = xsc;
  199 
  200         if (sc->sc_intr[0].cb != NULL)
  201                 sc->sc_intr[0].cb(sc->sc_intr[0].arg);
  202 }
  203 
  204 static struct resource *
  205 ata_avila_alloc_resource(device_t dev, device_t child, int type, int *rid,
  206                        u_long start, u_long end, u_long count, u_int flags)
  207 {
  208         struct ata_avila_softc *sc = device_get_softc(dev);
  209 
  210         KASSERT(type == SYS_RES_IRQ && *rid == ATA_IRQ_RID,
  211             ("type %u rid %u start %lu end %lu count %lu flags %u",
  212              type, *rid, start, end, count, flags));
  213 
  214         /* doesn't matter what we return so reuse the real thing */
  215         return sc->sc_irq;
  216 }
  217 
  218 static int
  219 ata_avila_release_resource(device_t dev, device_t child, int type, int rid,
  220                          struct resource *r)
  221 {
  222         KASSERT(type == SYS_RES_IRQ && rid == ATA_IRQ_RID,
  223             ("type %u rid %u", type, rid));
  224         return 0;
  225 }
  226 
  227 static int
  228 ata_avila_setup_intr(device_t dev, device_t child, struct resource *irq, 
  229                    int flags, driver_intr_t *function, void *argument,
  230                    void **cookiep)
  231 {
  232         struct ata_avila_softc *sc = device_get_softc(dev);
  233         int unit = ((struct ata_channel *)device_get_softc(child))->unit;
  234 
  235         KASSERT(unit == 0, ("unit %d", unit));
  236         sc->sc_intr[unit].cb = function;
  237         sc->sc_intr[unit].arg = argument;
  238         *cookiep = sc;
  239         return 0;
  240 }
  241 
  242 static int
  243 ata_avila_teardown_intr(device_t dev, device_t child, struct resource *irq,
  244                       void *cookie)
  245 {
  246         struct ata_avila_softc *sc = device_get_softc(dev);
  247         int unit = ((struct ata_channel *)device_get_softc(child))->unit;
  248 
  249         KASSERT(unit == 0, ("unit %d", unit));
  250         sc->sc_intr[unit].cb = NULL;
  251         sc->sc_intr[unit].arg = NULL;
  252         return 0;
  253 }
  254 
  255 /*
  256  * Bus space accessors for CF-IDE PIO operations.
  257  */
  258 
  259 /*
  260  * Enable/disable 16-bit ops on the expansion bus.
  261  */
  262 static void __inline
  263 enable_16(struct ata_avila_softc *sc)
  264 {
  265         EXP_BUS_WRITE_4(sc, EXP_TIMING_CS1_OFFSET,
  266             EXP_BUS_READ_4(sc, EXP_TIMING_CS1_OFFSET) &~ EXP_BYTE_EN);
  267         DELAY(100);             /* XXX? */
  268 }
  269 
  270 static void __inline
  271 disable_16(struct ata_avila_softc *sc)
  272 {
  273         DELAY(100);             /* XXX? */
  274         EXP_BUS_WRITE_4(sc, EXP_TIMING_CS1_OFFSET,
  275             EXP_BUS_READ_4(sc, EXP_TIMING_CS1_OFFSET) | EXP_BYTE_EN);
  276 }
  277 
  278 uint8_t
  279 ata_bs_r_1(void *t, bus_space_handle_t h, bus_size_t o)
  280 {
  281         struct ata_avila_softc *sc = t;
  282 
  283         return bus_space_read_1(sc->sc_iot, h, o);
  284 }
  285 
  286 void
  287 ata_bs_w_1(void *t, bus_space_handle_t h, bus_size_t o, u_int8_t v)
  288 {
  289         struct ata_avila_softc *sc = t;
  290 
  291         bus_space_write_1(sc->sc_iot, h, o, v);
  292 }
  293 
  294 uint16_t
  295 ata_bs_r_2(void *t, bus_space_handle_t h, bus_size_t o)
  296 {
  297         struct ata_avila_softc *sc = t;
  298         uint16_t v;
  299 
  300         enable_16(sc);
  301         v = bus_space_read_2(sc->sc_iot, h, o);
  302         disable_16(sc);
  303         return v;
  304 }
  305 
  306 void
  307 ata_bs_w_2(void *t, bus_space_handle_t h, bus_size_t o, uint16_t v)
  308 {
  309         struct ata_avila_softc *sc = t;
  310 
  311         enable_16(sc);
  312         bus_space_write_2(sc->sc_iot, h, o, v);
  313         disable_16(sc);
  314 }
  315 
  316 void
  317 ata_bs_rm_2(void *t, bus_space_handle_t h, bus_size_t o,
  318         u_int16_t *d, bus_size_t c)
  319 {
  320         struct ata_avila_softc *sc = t;
  321 
  322         enable_16(sc);
  323         bus_space_read_multi_2(sc->sc_iot, h, o, d, c);
  324         disable_16(sc);
  325 }
  326 
  327 void
  328 ata_bs_wm_2(void *t, bus_space_handle_t h, bus_size_t o,
  329         const u_int16_t *d, bus_size_t c)
  330 {
  331         struct ata_avila_softc *sc = t;
  332 
  333         enable_16(sc);
  334         bus_space_write_multi_2(sc->sc_iot, h, o, d, c);
  335         disable_16(sc);
  336 }
  337 
  338 /* XXX workaround ata driver by (incorrectly) byte swapping stream cases */
  339 
  340 void
  341 ata_bs_rm_2_s(void *t, bus_space_handle_t h, bus_size_t o,
  342         u_int16_t *d, bus_size_t c)
  343 {
  344         struct ata_avila_softc *sc = t;
  345         uint16_t v;
  346         bus_size_t i;
  347 
  348         enable_16(sc);
  349 #if 1
  350         for (i = 0; i < c; i++) {
  351                 v = bus_space_read_2(sc->sc_iot, h, o);
  352                 d[i] = bswap16(v);
  353         }
  354 #else
  355         bus_space_read_multi_stream_2(sc->sc_iot, h, o, d, c);
  356 #endif
  357         disable_16(sc);
  358 }
  359 
  360 void
  361 ata_bs_wm_2_s(void *t, bus_space_handle_t h, bus_size_t o,
  362         const u_int16_t *d, bus_size_t c)
  363 {
  364         struct ata_avila_softc *sc = t;
  365         bus_size_t i;
  366 
  367         enable_16(sc);
  368 #if 1
  369         for (i = 0; i < c; i++)
  370                 bus_space_write_2(sc->sc_iot, h, o, bswap16(d[i]));
  371 #else
  372         bus_space_write_multi_stream_2(sc->sc_iot, h, o, d, c);
  373 #endif
  374         disable_16(sc);
  375 }
  376 
  377 static device_method_t ata_avila_methods[] = {
  378         /* device interface */
  379         DEVMETHOD(device_probe,             ata_avila_probe),
  380         DEVMETHOD(device_attach,            ata_avila_attach),
  381         DEVMETHOD(device_detach,            ata_avila_detach),
  382         DEVMETHOD(device_shutdown,          bus_generic_shutdown),
  383         DEVMETHOD(device_suspend,           bus_generic_suspend),
  384         DEVMETHOD(device_resume,            bus_generic_resume),
  385 
  386         /* bus methods */
  387         DEVMETHOD(bus_alloc_resource,       ata_avila_alloc_resource),
  388         DEVMETHOD(bus_release_resource,     ata_avila_release_resource),
  389         DEVMETHOD(bus_activate_resource,    bus_generic_activate_resource),
  390         DEVMETHOD(bus_deactivate_resource,  bus_generic_deactivate_resource),
  391         DEVMETHOD(bus_setup_intr,           ata_avila_setup_intr),
  392         DEVMETHOD(bus_teardown_intr,        ata_avila_teardown_intr),
  393 
  394         { 0, 0 }
  395 };
  396 
  397 devclass_t ata_avila_devclass;
  398 
  399 static driver_t ata_avila_driver = {
  400         "ata_avila",
  401         ata_avila_methods,
  402         sizeof(struct ata_avila_softc),
  403 };
  404 
  405 DRIVER_MODULE(ata_avila, ixp, ata_avila_driver, ata_avila_devclass, 0, 0);
  406 MODULE_VERSION(ata_avila, 1);
  407 MODULE_DEPEND(ata_avila, ata, 1, 1, 1);
  408 
  409 static int
  410 avila_channel_probe(device_t dev)
  411 {
  412         struct ata_channel *ch = device_get_softc(dev);
  413 
  414         ch->unit = 0;
  415         ch->flags |= ATA_USE_16BIT | ATA_NO_SLAVE;
  416         device_set_desc_copy(dev, "ATA channel 0");
  417 
  418         return ata_probe(dev);
  419 }
  420 
  421 static int
  422 avila_channel_attach(device_t dev)
  423 {
  424         struct ata_avila_softc *sc = device_get_softc(device_get_parent(dev));
  425         struct ata_channel *ch = device_get_softc(dev);
  426         int i;
  427 
  428         for (i = 0; i < ATA_MAX_RES; i++)
  429                 ch->r_io[i].res = &sc->sc_ata;
  430 
  431         ch->r_io[ATA_DATA].offset = ATA_DATA;
  432         ch->r_io[ATA_FEATURE].offset = ATA_FEATURE;
  433         ch->r_io[ATA_COUNT].offset = ATA_COUNT;
  434         ch->r_io[ATA_SECTOR].offset = ATA_SECTOR;
  435         ch->r_io[ATA_CYL_LSB].offset = ATA_CYL_LSB;
  436         ch->r_io[ATA_CYL_MSB].offset = ATA_CYL_MSB;
  437         ch->r_io[ATA_DRIVE].offset = ATA_DRIVE;
  438         ch->r_io[ATA_COMMAND].offset = ATA_COMMAND;
  439         ch->r_io[ATA_ERROR].offset = ATA_FEATURE;
  440         /* NB: should be used only for ATAPI devices */
  441         ch->r_io[ATA_IREASON].offset = ATA_COUNT;
  442         ch->r_io[ATA_STATUS].offset = ATA_COMMAND;
  443         /* alias this; required by ata_generic_status */
  444         ch->r_io[ATA_ALTSTAT].offset = ch->r_io[ATA_STATUS].offset;
  445 
  446         /* NB: the control register is special */
  447         ch->r_io[ATA_CONTROL].offset = AVILA_IDE_CTRL;
  448 
  449         /* NB: by convention this points at the base of registers */
  450         ch->r_io[ATA_IDX_ADDR].offset = 0;
  451 
  452         ata_generic_hw(dev);
  453         return ata_attach(dev);
  454 }
  455 
  456 /* XXX override ata_generic_reset to handle non-standard status */
  457 static void
  458 avila_channel_reset(device_t dev)
  459 {
  460         struct ata_channel *ch = device_get_softc(dev);
  461         u_int8_t ostat0 = 0, stat0 = 0;
  462         u_int8_t err = 0, lsb = 0, msb = 0;
  463         int mask = 0, timeout;
  464 
  465         /* do we have any signs of ATA/ATAPI HW being present ? */
  466         ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_MASTER);
  467         DELAY(10);
  468         ostat0 = ATA_IDX_INB(ch, ATA_STATUS);
  469         if ((ostat0 & 0xf8) != 0xf8 && ostat0 != 0xa5) {
  470                 stat0 = ATA_S_BUSY;
  471                 mask |= 0x01;
  472         }
  473 
  474         if (bootverbose)
  475                 device_printf(dev, "%s: reset tp1 mask=%02x ostat0=%02x\n",
  476                     __func__, mask, ostat0);
  477 
  478         /* if nothing showed up there is no need to get any further */
  479         /* XXX SOS is that too strong?, we just might loose devices here */
  480         ch->devices = 0;
  481         if (!mask)
  482                 return;
  483 
  484         /* reset (both) devices on this channel */
  485         ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_MASTER);
  486         DELAY(10);
  487         ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_IDS | ATA_A_RESET);
  488         ata_udelay(10000); 
  489         ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_IDS);
  490         ata_udelay(100000);
  491         ATA_IDX_INB(ch, ATA_ERROR);
  492 
  493         /* wait for BUSY to go inactive */
  494         for (timeout = 0; timeout < 310; timeout++) {
  495                 if ((mask & 0x01) && (stat0 & ATA_S_BUSY)) {
  496                         ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
  497                         DELAY(10);
  498                         err = ATA_IDX_INB(ch, ATA_ERROR);
  499                         lsb = ATA_IDX_INB(ch, ATA_CYL_LSB);
  500                         msb = ATA_IDX_INB(ch, ATA_CYL_MSB);
  501                         stat0 = ATA_IDX_INB(ch, ATA_STATUS);
  502                         if (bootverbose)
  503                                 device_printf(dev,
  504                                     "%s: stat0=0x%02x err=0x%02x lsb=0x%02x "
  505                                     "msb=0x%02x\n", __func__,
  506                                     stat0, err, lsb, msb);
  507                         if (stat0 == err && lsb == err && msb == err &&
  508                             timeout > (stat0 & ATA_S_BUSY ? 100 : 10))
  509                                 mask &= ~0x01;
  510                         if (!(stat0 & ATA_S_BUSY)) {
  511                                 if ((err & 0x7f) == ATA_E_ILI || err == 0) {
  512                                         if (lsb == ATAPI_MAGIC_LSB &&
  513                                             msb == ATAPI_MAGIC_MSB) {
  514                                                 ch->devices |= ATA_ATAPI_MASTER;
  515                                         } else if (stat0 & ATA_S_READY) {
  516                                                 ch->devices |= ATA_ATA_MASTER;
  517                                         }
  518                                 } else if ((stat0 & 0x0f) &&
  519                                     err == lsb && err == msb) {
  520                                         stat0 |= ATA_S_BUSY;
  521                                 }
  522                         }
  523                 }
  524                 if (mask == 0x00)       /* nothing to wait for */
  525                         break;
  526                 /* wait for master */
  527                 if (!(stat0 & ATA_S_BUSY) || (stat0 == 0xff && timeout > 10))
  528                         break;
  529                 ata_udelay(100000);
  530         }
  531 
  532         if (bootverbose)
  533                 device_printf(dev, "%s: reset tp2 stat0=%02x devices=0x%b\n",
  534                     __func__, stat0, ch->devices,
  535                     "\2\4ATAPI_SLAVE\3ATAPI_MASTER\2ATA_SLAVE\1ATA_MASTER");
  536 }
  537 
  538 static device_method_t avila_channel_methods[] = {
  539         /* device interface */
  540         DEVMETHOD(device_probe,     avila_channel_probe),
  541         DEVMETHOD(device_attach,    avila_channel_attach),
  542         DEVMETHOD(device_detach,    ata_detach),
  543         DEVMETHOD(device_shutdown,  bus_generic_shutdown),
  544         DEVMETHOD(device_suspend,   ata_suspend),
  545         DEVMETHOD(device_resume,    ata_resume),
  546 
  547         DEVMETHOD(ata_reset,        avila_channel_reset),
  548 
  549         { 0, 0 }
  550 };
  551 
  552 driver_t avila_channel_driver = {
  553         "ata",
  554         avila_channel_methods,
  555         sizeof(struct ata_channel),
  556 };
  557 DRIVER_MODULE(ata, ata_avila, avila_channel_driver, ata_devclass, 0, 0);

Cache object: 1083fc9706a4b2857a24ca77a308cd21


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