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/dev/ata/ata-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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer,
   12  *    without modification, immediately at the beginning of the file.
   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 ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/kernel.h>
   35 #include <sys/ata.h>
   36 #include <sys/bus.h>
   37 #include <sys/endian.h>
   38 #include <sys/malloc.h>
   39 #include <sys/lock.h>
   40 #include <sys/mutex.h>
   41 #include <sys/sema.h>
   42 #include <sys/taskqueue.h>
   43 #include <vm/uma.h>
   44 #include <machine/stdarg.h>
   45 #include <machine/resource.h>
   46 #include <machine/bus.h>
   47 #include <sys/rman.h>
   48 #include <dev/ata/ata-all.h>
   49 #include <ata_if.h>
   50 
   51 void
   52 ata_sata_phy_check_events(device_t dev, int port)
   53 {
   54     struct ata_channel *ch = device_get_softc(dev);
   55     u_int32_t error, status;
   56 
   57     if (ata_sata_scr_read(ch, port, ATA_SERROR, &error))
   58         return;
   59 
   60     /* Check that SError value is sane. */
   61     if (error == 0xffffffff)
   62         return;
   63 
   64     /* Clear set error bits/interrupt. */
   65     if (error)
   66         ata_sata_scr_write(ch, port, ATA_SERROR, error);
   67 
   68     /* if we have a connection event deal with it */
   69     if ((error & ATA_SE_PHY_CHANGED) && (ch->pm_level == 0)) {
   70         if (bootverbose) {
   71             if (ata_sata_scr_read(ch, port, ATA_SSTATUS, &status)) {
   72                     device_printf(dev, "PHYRDY change\n");
   73             } else if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) &&
   74                 ((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) &&
   75                 ((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE)) {
   76                     device_printf(dev, "CONNECT requested\n");
   77             } else
   78                     device_printf(dev, "DISCONNECT requested\n");
   79         }
   80         taskqueue_enqueue(taskqueue_thread, &ch->conntask);
   81     }
   82 }
   83 
   84 int
   85 ata_sata_scr_read(struct ata_channel *ch, int port, int reg, uint32_t *val)
   86 {
   87 
   88     if (ch->hw.pm_read != NULL)
   89         return (ch->hw.pm_read(ch->dev, port, reg, val));
   90     if (ch->r_io[reg].res) {
   91         *val = ATA_IDX_INL(ch, reg);
   92         return (0);
   93     }
   94     return (-1);
   95 }
   96 
   97 int
   98 ata_sata_scr_write(struct ata_channel *ch, int port, int reg, uint32_t val)
   99 {
  100 
  101     if (ch->hw.pm_write != NULL)
  102         return (ch->hw.pm_write(ch->dev, port, reg, val));
  103     if (ch->r_io[reg].res) {
  104         ATA_IDX_OUTL(ch, reg, val);
  105         return (0);
  106     }
  107     return (-1);
  108 }
  109 
  110 static int
  111 ata_sata_connect(struct ata_channel *ch, int port, int quick)
  112 {
  113     u_int32_t status;
  114     int timeout, t;
  115 
  116     /* wait up to 1 second for "connect well" */
  117     timeout = (quick == 2) ? 0 : 100;
  118     t = 0;
  119     while (1) {
  120         if (ata_sata_scr_read(ch, port, ATA_SSTATUS, &status))
  121             return (0);
  122         if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) &&
  123             ((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) &&
  124             ((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE))
  125             break;
  126         if (++t > timeout)
  127             break;
  128         ata_udelay(10000);
  129     }
  130     if (bootverbose) {
  131         if (t > timeout) {
  132             if (port < 0) {
  133                 device_printf(ch->dev, "SATA connect timeout status=%08x\n",
  134                     status);
  135             } else {
  136                 device_printf(ch->dev, "p%d: SATA connect timeout status=%08x\n",
  137                     port, status);
  138             }
  139         } else if (port < 0) {
  140             device_printf(ch->dev, "SATA connect time=%dms status=%08x\n",
  141                 t * 10, status);
  142         } else {
  143             device_printf(ch->dev, "p%d: SATA connect time=%dms status=%08x\n",
  144                 port, t * 10, status);
  145         }
  146     }
  147 
  148     /* clear SATA error register */
  149     ata_sata_scr_write(ch, port, ATA_SERROR, 0xffffffff);
  150 
  151     return ((t > timeout) ? 0 : 1);
  152 }
  153 
  154 int
  155 ata_sata_phy_reset(device_t dev, int port, int quick)
  156 {
  157     struct ata_channel *ch = device_get_softc(dev);
  158     int loop, retry, sata_rev;
  159     uint32_t val, val1;
  160 
  161     sata_rev = ch->user[port < 0 ? 0 : port].revision;
  162     if (sata_rev > 0)
  163         quick = 0;
  164 
  165     if (quick) {
  166         if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
  167             return (0);
  168         if ((val & ATA_SC_DET_MASK) == ATA_SC_DET_IDLE) {
  169             ata_sata_scr_write(ch, port, ATA_SCONTROL,
  170                 ATA_SC_DET_IDLE | ((ch->pm_level > 0) ? 0 :
  171                 ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER));
  172             return ata_sata_connect(ch, port, quick);
  173         }
  174     }
  175 
  176     if (bootverbose) {
  177         if (port < 0) {
  178             device_printf(dev, "hard reset ...\n");
  179         } else {
  180             device_printf(dev, "p%d: hard reset ...\n", port);
  181         }
  182     }
  183     if (sata_rev == 1)
  184         val1 = ATA_SC_SPD_SPEED_GEN1;
  185     else if (sata_rev == 2)
  186         val1 = ATA_SC_SPD_SPEED_GEN2;
  187     else if (sata_rev == 3)
  188         val1 = ATA_SC_SPD_SPEED_GEN3;
  189     else
  190         val1 = 0;
  191     for (retry = 0; retry < 10; retry++) {
  192         for (loop = 0; loop < 10; loop++) {
  193             if (ata_sata_scr_write(ch, port, ATA_SCONTROL, ATA_SC_DET_RESET |
  194                     val1 | ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER))
  195                 goto fail;
  196             ata_udelay(100);
  197             if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
  198                 goto fail;
  199             if ((val & ATA_SC_DET_MASK) == ATA_SC_DET_RESET)
  200                 break;
  201         }
  202         ata_udelay(5000);
  203         for (loop = 0; loop < 10; loop++) {
  204             if (ata_sata_scr_write(ch, port, ATA_SCONTROL,
  205                     ATA_SC_DET_IDLE | val1 | ((ch->pm_level > 0) ? 0 :
  206                     ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER)))
  207                 goto fail;
  208             ata_udelay(100);
  209             if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
  210                 goto fail;
  211             if ((val & ATA_SC_DET_MASK) == 0)
  212                 return ata_sata_connect(ch, port, 0);
  213         }
  214     }
  215 fail:
  216     /* Clear SATA error register. */
  217     ata_sata_scr_write(ch, port, ATA_SERROR, 0xffffffff);
  218 
  219     if (bootverbose) {
  220         if (port < 0) {
  221             device_printf(dev, "hard reset failed\n");
  222         } else {
  223             device_printf(dev, "p%d: hard reset failed\n", port);
  224         }
  225     }
  226     return (0);
  227 }
  228 
  229 int
  230 ata_sata_setmode(device_t dev, int target, int mode)
  231 {
  232 
  233         return (min(mode, ATA_UDMA5));
  234 }
  235 
  236 int
  237 ata_sata_getrev(device_t dev, int target)
  238 {
  239         struct ata_channel *ch = device_get_softc(dev);
  240 
  241         if (ch->r_io[ATA_SSTATUS].res)
  242                 return ((ATA_IDX_INL(ch, ATA_SSTATUS) & 0x0f0) >> 4);
  243         return (0xff);
  244 }
  245 
  246 int
  247 ata_request2fis_h2d(struct ata_request *request, u_int8_t *fis)
  248 {
  249 
  250     if (request->flags & ATA_R_ATAPI) {
  251         fis[0] = 0x27;                  /* host to device */
  252         fis[1] = 0x80 | (request->unit & 0x0f);
  253         fis[2] = ATA_PACKET_CMD;
  254         if (request->flags & (ATA_R_READ | ATA_R_WRITE))
  255             fis[3] = ATA_F_DMA;
  256         else {
  257             fis[5] = request->transfersize;
  258             fis[6] = request->transfersize >> 8;
  259         }
  260         fis[7] = ATA_D_LBA;
  261         fis[15] = ATA_A_4BIT;
  262         return 20;
  263     }
  264     else {
  265         fis[0] = 0x27;                  /* host to device */
  266         fis[1] = 0x80 | (request->unit & 0x0f);
  267         fis[2] = request->u.ata.command;
  268         fis[3] = request->u.ata.feature;
  269         fis[4] = request->u.ata.lba;
  270         fis[5] = request->u.ata.lba >> 8;
  271         fis[6] = request->u.ata.lba >> 16;
  272         fis[7] = ATA_D_LBA;
  273         if (!(request->flags & ATA_R_48BIT))
  274             fis[7] |= (ATA_D_IBM | (request->u.ata.lba >> 24 & 0x0f));
  275         fis[8] = request->u.ata.lba >> 24;
  276         fis[9] = request->u.ata.lba >> 32; 
  277         fis[10] = request->u.ata.lba >> 40; 
  278         fis[11] = request->u.ata.feature >> 8;
  279         fis[12] = request->u.ata.count;
  280         fis[13] = request->u.ata.count >> 8;
  281         fis[15] = ATA_A_4BIT;
  282         return 20;
  283     }
  284     return 0;
  285 }
  286 
  287 void
  288 ata_pm_identify(device_t dev)
  289 {
  290     struct ata_channel *ch = device_get_softc(dev);
  291     u_int32_t pm_chipid, pm_revision, pm_ports;
  292     int port;
  293 
  294     /* get PM vendor & product data */
  295     if (ch->hw.pm_read(dev, ATA_PM, 0, &pm_chipid)) {
  296         device_printf(dev, "error getting PM vendor data\n");
  297         return;
  298     }
  299 
  300     /* get PM revision data */
  301     if (ch->hw.pm_read(dev, ATA_PM, 1, &pm_revision)) {
  302         device_printf(dev, "error getting PM revision data\n");
  303         return;
  304     }
  305 
  306     /* get number of HW ports on the PM */
  307     if (ch->hw.pm_read(dev, ATA_PM, 2, &pm_ports)) {
  308         device_printf(dev, "error getting PM port info\n");
  309         return;
  310     }
  311     pm_ports &= 0x0000000f;
  312 
  313     /* chip specific quirks */
  314     switch (pm_chipid) {
  315     case 0x37261095:
  316         /* This PM declares 6 ports, while only 5 of them are real.
  317          * Port 5 is enclosure management bridge port, which has implementation
  318          * problems, causing probe faults. Hide it for now. */
  319         device_printf(dev, "SiI 3726 (rev=%x) Port Multiplier with %d (5) ports\n",
  320                       pm_revision, pm_ports);
  321         pm_ports = 5;
  322         break;
  323 
  324     case 0x47261095:
  325         /* This PM declares 7 ports, while only 5 of them are real.
  326          * Port 5 is some fake "Config  Disk" with 640 sectors size,
  327          * port 6 is enclosure management bridge port.
  328          * Both fake ports has implementation problems, causing
  329          * probe faults. Hide them for now. */
  330         device_printf(dev, "SiI 4726 (rev=%x) Port Multiplier with %d (5) ports\n",
  331                       pm_revision, pm_ports);
  332         pm_ports = 5;
  333         break;
  334 
  335     default:
  336         device_printf(dev, "Port Multiplier (id=%08x rev=%x) with %d ports\n",
  337                       pm_chipid, pm_revision, pm_ports);
  338     }
  339 
  340     /* reset all ports and register if anything connected */
  341     for (port=0; port < pm_ports; port++) {
  342         u_int32_t signature;
  343 
  344         if (!ata_sata_phy_reset(dev, port, 1))
  345             continue;
  346 
  347         /*
  348          * XXX: I have no idea how to properly wait for PMP port hardreset
  349          * completion. Without this delay soft reset does not completes
  350          * successfully.
  351          */
  352         DELAY(1000000);
  353 
  354         signature = ch->hw.softreset(dev, port);
  355 
  356         if (bootverbose)
  357             device_printf(dev, "p%d: SIGNATURE=%08x\n", port, signature);
  358 
  359         /* figure out whats there */
  360         switch (signature >> 16) {
  361         case 0x0000:
  362             ch->devices |= (ATA_ATA_MASTER << port);
  363             continue;
  364         case 0xeb14:
  365             ch->devices |= (ATA_ATAPI_MASTER << port);
  366             continue;
  367         }
  368     }
  369 }

Cache object: 7898747557b8eb2538b6cbac85801c12


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