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/ahci/ahciem.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) 2012 Alexander Motin <mav@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/module.h>
   34 #include <sys/systm.h>
   35 #include <sys/kernel.h>
   36 #include <sys/bus.h>
   37 #include <sys/conf.h>
   38 #include <sys/endian.h>
   39 #include <sys/malloc.h>
   40 #include <sys/lock.h>
   41 #include <sys/mutex.h>
   42 #include <machine/stdarg.h>
   43 #include <machine/resource.h>
   44 #include <machine/bus.h>
   45 #include <sys/rman.h>
   46 #include <dev/led/led.h>
   47 #include <dev/pci/pcivar.h>
   48 #include <dev/pci/pcireg.h>
   49 #include "ahci.h"
   50 
   51 #include <cam/cam.h>
   52 #include <cam/cam_ccb.h>
   53 #include <cam/cam_sim.h>
   54 #include <cam/cam_xpt_sim.h>
   55 #include <cam/cam_debug.h>
   56 #include <cam/scsi/scsi_ses.h>
   57 
   58 /* local prototypes */
   59 static void ahciemaction(struct cam_sim *sim, union ccb *ccb);
   60 static void ahciempoll(struct cam_sim *sim);
   61 static int ahci_em_reset(device_t dev);
   62 static void ahci_em_led(void *priv, int onoff);
   63 static void ahci_em_setleds(device_t dev, int c);
   64 
   65 static int
   66 ahci_em_probe(device_t dev)
   67 {
   68 
   69         device_set_desc_copy(dev, "AHCI enclosure management bridge");
   70         return (BUS_PROBE_DEFAULT);
   71 }
   72 
   73 static int
   74 ahci_em_attach(device_t dev)
   75 {
   76         device_t parent = device_get_parent(dev);
   77         struct ahci_controller *ctlr = device_get_softc(parent);
   78         struct ahci_enclosure *enc = device_get_softc(dev);
   79         struct cam_devq *devq;
   80         int i, c, rid, error;
   81         char buf[32];
   82 
   83         enc->dev = dev;
   84         enc->quirks = ctlr->quirks;
   85         enc->channels = ctlr->channels;
   86         enc->ichannels = ctlr->ichannels;
   87         mtx_init(&enc->mtx, "AHCI enclosure lock", NULL, MTX_DEF);
   88         rid = 0;
   89         if ((enc->r_memc = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
   90             &rid, RF_ACTIVE)) != NULL) {
   91                 enc->capsem = ATA_INL(enc->r_memc, 0);
   92                 rid = 1;
   93                 if (!(enc->r_memt = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
   94                     &rid, RF_ACTIVE))) {
   95                         error = ENXIO;
   96                         goto err0;
   97                 }
   98         } else {
   99                 enc->capsem = AHCI_EM_XMT | AHCI_EM_SMB | AHCI_EM_LED;
  100                 enc->r_memt = NULL;
  101         }
  102         if ((enc->capsem & (AHCI_EM_XMT | AHCI_EM_SMB)) == 0) {
  103                 rid = 2;
  104                 if (!(enc->r_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  105                     &rid, RF_ACTIVE))) {
  106                         error = ENXIO;
  107                         goto err0;
  108                 }
  109         } else
  110                 enc->r_memr = NULL;
  111         mtx_lock(&enc->mtx);
  112         if (ahci_em_reset(dev) != 0) {
  113             error = ENXIO;
  114             goto err1;
  115         }
  116         rid = ATA_IRQ_RID;
  117         /* Create the device queue for our SIM. */
  118         devq = cam_simq_alloc(1);
  119         if (devq == NULL) {
  120                 device_printf(dev, "Unable to allocate SIM queue\n");
  121                 error = ENOMEM;
  122                 goto err1;
  123         }
  124         /* Construct SIM entry */
  125         enc->sim = cam_sim_alloc(ahciemaction, ahciempoll, "ahciem", enc,
  126             device_get_unit(dev), &enc->mtx,
  127             1, 0, devq);
  128         if (enc->sim == NULL) {
  129                 cam_simq_free(devq);
  130                 device_printf(dev, "Unable to allocate SIM\n");
  131                 error = ENOMEM;
  132                 goto err1;
  133         }
  134         if (xpt_bus_register(enc->sim, dev, 0) != CAM_SUCCESS) {
  135                 device_printf(dev, "unable to register xpt bus\n");
  136                 error = ENXIO;
  137                 goto err2;
  138         }
  139         if (xpt_create_path(&enc->path, /*periph*/NULL, cam_sim_path(enc->sim),
  140             CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
  141                 device_printf(dev, "Unable to create path\n");
  142                 error = ENXIO;
  143                 goto err3;
  144         }
  145         mtx_unlock(&enc->mtx);
  146         if (bootverbose) {
  147                 device_printf(dev, "Caps:%s%s%s%s%s%s%s%s\n",
  148                     (enc->capsem & AHCI_EM_PM) ? " PM":"",
  149                     (enc->capsem & AHCI_EM_ALHD) ? " ALHD":"",
  150                     (enc->capsem & AHCI_EM_XMT) ? " XMT":"",
  151                     (enc->capsem & AHCI_EM_SMB) ? " SMB":"",
  152                     (enc->capsem & AHCI_EM_SGPIO) ? " SGPIO":"",
  153                     (enc->capsem & AHCI_EM_SES2) ? " SES-2":"",
  154                     (enc->capsem & AHCI_EM_SAFTE) ? " SAF-TE":"",
  155                     (enc->capsem & AHCI_EM_LED) ? " LED":"");
  156         }
  157         if ((enc->capsem & AHCI_EM_LED)) {
  158                 for (c = 0; c < enc->channels; c++) {
  159                         if ((enc->ichannels & (1 << c)) == 0)
  160                                 continue;
  161                         for (i = 0; i < AHCI_NUM_LEDS; i++) {
  162                                 enc->leds[c * AHCI_NUM_LEDS + i].dev = dev;
  163                                 enc->leds[c * AHCI_NUM_LEDS + i].num =
  164                                     c * AHCI_NUM_LEDS + i;
  165                         }
  166                         if ((enc->capsem & AHCI_EM_ALHD) == 0) {
  167                                 snprintf(buf, sizeof(buf), "%s.%d.act",
  168                                     device_get_nameunit(parent), c);
  169                                 enc->leds[c * AHCI_NUM_LEDS + 0].led =
  170                                     led_create(ahci_em_led,
  171                                     &enc->leds[c * AHCI_NUM_LEDS + 0], buf);
  172                         }
  173                         snprintf(buf, sizeof(buf), "%s.%d.locate",
  174                             device_get_nameunit(parent), c);
  175                         enc->leds[c * AHCI_NUM_LEDS + 1].led =
  176                             led_create(ahci_em_led,
  177                             &enc->leds[c * AHCI_NUM_LEDS + 1], buf);
  178                         snprintf(buf, sizeof(buf), "%s.%d.fault",
  179                             device_get_nameunit(parent), c);
  180                         enc->leds[c * AHCI_NUM_LEDS + 2].led =
  181                             led_create(ahci_em_led,
  182                             &enc->leds[c * AHCI_NUM_LEDS + 2], buf);
  183                 }
  184         }
  185         return (0);
  186 
  187 err3:
  188         xpt_bus_deregister(cam_sim_path(enc->sim));
  189 err2:
  190         cam_sim_free(enc->sim, /*free_devq*/TRUE);
  191 err1:
  192         mtx_unlock(&enc->mtx);
  193         if (enc->r_memr)
  194                 bus_release_resource(dev, SYS_RES_MEMORY, 2, enc->r_memr);
  195 err0:
  196         if (enc->r_memt)
  197                 bus_release_resource(dev, SYS_RES_MEMORY, 1, enc->r_memt);
  198         if (enc->r_memc)
  199                 bus_release_resource(dev, SYS_RES_MEMORY, 0, enc->r_memc);
  200         mtx_destroy(&enc->mtx);
  201         return (error);
  202 }
  203 
  204 static int
  205 ahci_em_detach(device_t dev)
  206 {
  207         struct ahci_enclosure *enc = device_get_softc(dev);
  208         int i;
  209 
  210         for (i = 0; i < enc->channels * AHCI_NUM_LEDS; i++) {
  211                 if (enc->leds[i].led)
  212                         led_destroy(enc->leds[i].led);
  213         }
  214         mtx_lock(&enc->mtx);
  215         xpt_async(AC_LOST_DEVICE, enc->path, NULL);
  216         xpt_free_path(enc->path);
  217         xpt_bus_deregister(cam_sim_path(enc->sim));
  218         cam_sim_free(enc->sim, /*free_devq*/TRUE);
  219         mtx_unlock(&enc->mtx);
  220 
  221         if (enc->r_memc)
  222                 bus_release_resource(dev, SYS_RES_MEMORY, 0, enc->r_memc);
  223         if (enc->r_memt)
  224                 bus_release_resource(dev, SYS_RES_MEMORY, 1, enc->r_memt);
  225         if (enc->r_memr)
  226                 bus_release_resource(dev, SYS_RES_MEMORY, 2, enc->r_memr);
  227         mtx_destroy(&enc->mtx);
  228         return (0);
  229 }
  230 
  231 static int
  232 ahci_em_reset(device_t dev)
  233 {
  234         struct ahci_enclosure *enc;
  235         int i, timeout;
  236 
  237         enc = device_get_softc(dev);
  238         if (enc->r_memc == NULL)
  239                 return (0);
  240         ATA_OUTL(enc->r_memc, 0, AHCI_EM_RST);
  241         timeout = 1000;
  242         while ((ATA_INL(enc->r_memc, 0) & AHCI_EM_RST) &&
  243             --timeout > 0)
  244                 DELAY(1000);
  245         if (timeout == 0) {
  246                 device_printf(dev, "EM timeout\n");
  247                 return (1);
  248         }
  249         for (i = 0; i < enc->channels; i++)
  250                 ahci_em_setleds(dev, i);
  251         return (0);
  252 }
  253 
  254 static int
  255 ahci_em_suspend(device_t dev)
  256 {
  257         struct ahci_enclosure *enc = device_get_softc(dev);
  258 
  259         mtx_lock(&enc->mtx);
  260         xpt_freeze_simq(enc->sim, 1);
  261         mtx_unlock(&enc->mtx);
  262         return (0);
  263 }
  264 
  265 static int
  266 ahci_em_resume(device_t dev)
  267 {
  268         struct ahci_enclosure *enc = device_get_softc(dev);
  269 
  270         mtx_lock(&enc->mtx);
  271         ahci_em_reset(dev);
  272         xpt_release_simq(enc->sim, TRUE);
  273         mtx_unlock(&enc->mtx);
  274         return (0);
  275 }
  276 
  277 static device_method_t ahciem_methods[] = {
  278         DEVMETHOD(device_probe,     ahci_em_probe),
  279         DEVMETHOD(device_attach,    ahci_em_attach),
  280         DEVMETHOD(device_detach,    ahci_em_detach),
  281         DEVMETHOD(device_suspend,   ahci_em_suspend),
  282         DEVMETHOD(device_resume,    ahci_em_resume),
  283         DEVMETHOD_END
  284 };
  285 static driver_t ahciem_driver = {
  286         "ahciem",
  287         ahciem_methods,
  288         sizeof(struct ahci_enclosure)
  289 };
  290 DRIVER_MODULE(ahciem, ahci, ahciem_driver, NULL, NULL);
  291 
  292 static void
  293 ahci_em_setleds(device_t dev, int c)
  294 {
  295         struct ahci_enclosure *enc;
  296         int timeout;
  297         int16_t val;
  298 
  299         enc = device_get_softc(dev);
  300         if (enc->r_memc == NULL)
  301                 return;
  302 
  303         val = 0;
  304         if (enc->status[c][2] & SESCTL_RQSACT)          /* Activity */
  305                 val |= (1 << 0);
  306         if (enc->status[c][1] & SESCTL_RQSRR)           /* Rebuild */
  307                 val |= (1 << 6) | (1 << 3);
  308         else if (enc->status[c][2] & SESCTL_RQSID)      /* Identification */
  309                 val |= (1 << 3);
  310         else if (enc->status[c][3] & SESCTL_RQSFLT)     /* Fault */
  311                 val |= (1 << 6);
  312 
  313         timeout = 10000;
  314         while (ATA_INL(enc->r_memc, 0) & (AHCI_EM_TM | AHCI_EM_RST) &&
  315             --timeout > 0)
  316                 DELAY(100);
  317         if (timeout == 0)
  318                 device_printf(dev, "Transmit timeout\n");
  319         ATA_OUTL(enc->r_memt, 0, (1 << 8) | (0 << 16) | (0 << 24));
  320         ATA_OUTL(enc->r_memt, 4, c | (0 << 8) | (val << 16));
  321         ATA_OUTL(enc->r_memc, 0, AHCI_EM_TM);
  322 }
  323 
  324 static void
  325 ahci_em_led(void *priv, int onoff)
  326 {
  327         struct ahci_led *led;
  328         struct ahci_enclosure *enc;
  329         int c, l;
  330 
  331         led = (struct ahci_led *)priv;
  332         enc = device_get_softc(led->dev);
  333         c = led->num / AHCI_NUM_LEDS;
  334         l = led->num % AHCI_NUM_LEDS;
  335 
  336         if (l == 0) {
  337                 if (onoff)
  338                         enc->status[c][2] |= 0x80;
  339                 else
  340                         enc->status[c][2] &= ~0x80;
  341         } else if (l == 1) {
  342                 if (onoff)
  343                         enc->status[c][2] |= SESCTL_RQSID;
  344                 else
  345                         enc->status[c][2] &= ~SESCTL_RQSID;
  346         } else if (l == 2) {
  347                 if (onoff)
  348                         enc->status[c][3] |= SESCTL_RQSFLT;
  349                 else
  350                         enc->status[c][3] &= SESCTL_RQSFLT;
  351         }
  352         ahci_em_setleds(led->dev, c);
  353 }
  354 
  355 static int
  356 ahci_check_ids(union ccb *ccb)
  357 {
  358 
  359         if (ccb->ccb_h.target_id != 0) {
  360                 ccb->ccb_h.status = CAM_TID_INVALID;
  361                 xpt_done(ccb);
  362                 return (-1);
  363         }
  364         if (ccb->ccb_h.target_lun != 0) {
  365                 ccb->ccb_h.status = CAM_LUN_INVALID;
  366                 xpt_done(ccb);
  367                 return (-1);
  368         }
  369         return (0);
  370 }
  371 
  372 static void
  373 ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
  374 {
  375         struct ahci_enclosure *enc;
  376         struct ahci_channel *ch;
  377         struct ses_status_page *page;
  378         struct ses_status_array_dev_slot *ads, *ads0;
  379         struct ses_elm_desc_hdr *elmd;
  380         struct ses_elm_addlstatus_eip_hdr *elma;
  381         struct ses_elm_ata_hdr *elmb;
  382         uint8_t *buf;
  383         int i;
  384 
  385         enc = device_get_softc(dev);
  386         buf = ccb->ataio.data_ptr;
  387 
  388         /* General request validation. */
  389         if (ccb->ataio.cmd.command != ATA_SEP_ATTN ||
  390             ccb->ataio.dxfer_len < ccb->ataio.cmd.sector_count * 4) {
  391                 ccb->ccb_h.status = CAM_REQ_INVALID;
  392                 goto out;
  393         }
  394 
  395         /* SEMB IDENTIFY */
  396         if (ccb->ataio.cmd.features == 0xEC &&
  397             ccb->ataio.cmd.sector_count >= 16) {
  398                 bzero(buf, ccb->ataio.dxfer_len);
  399                 buf[0] = 64;            /* Valid bytes. */
  400                 buf[2] = 0x30;          /* NAA Locally Assigned. */
  401                 strncpy(&buf[3], device_get_nameunit(dev), 7);
  402                 strncpy(&buf[10], "AHCI    ", SID_VENDOR_SIZE);
  403                 strncpy(&buf[18], "SGPIO Enclosure ", SID_PRODUCT_SIZE);
  404                 strncpy(&buf[34], "2.00", SID_REVISION_SIZE);
  405                 strncpy(&buf[39], "0001", 4);
  406                 strncpy(&buf[43], "S-E-S ", 6);
  407                 strncpy(&buf[49], "2.00", 4);
  408                 ccb->ccb_h.status = CAM_REQ_CMP;
  409                 goto out;
  410         }
  411 
  412         /* SEMB RECEIVE DIAGNOSTIC RESULT (0) */
  413         page = (struct ses_status_page *)buf;
  414         if (ccb->ataio.cmd.lba_low == 0x02 &&
  415             ccb->ataio.cmd.features == 0x00 &&
  416             ccb->ataio.cmd.sector_count >= 3) {
  417                 bzero(buf, ccb->ataio.dxfer_len);
  418                 page->hdr.page_code = 0;
  419                 scsi_ulto2b(5, page->hdr.length);
  420                 buf[4] = 0x00;
  421                 buf[5] = 0x01;
  422                 buf[6] = 0x02;
  423                 buf[7] = 0x07;
  424                 buf[8] = 0x0a;
  425                 ccb->ccb_h.status = CAM_REQ_CMP;
  426                 goto out;
  427         }
  428 
  429         /* SEMB RECEIVE DIAGNOSTIC RESULT (1) */
  430         if (ccb->ataio.cmd.lba_low == 0x02 &&
  431             ccb->ataio.cmd.features == 0x01 &&
  432             ccb->ataio.cmd.sector_count >= 16) {
  433                 struct ses_enc_desc *ed;
  434                 struct ses_elm_type_desc *td;
  435 
  436                 bzero(buf, ccb->ataio.dxfer_len);
  437                 page->hdr.page_code = 0x01;
  438                 scsi_ulto2b(4 + sizeof(*ed) + sizeof(*td) + 11,
  439                     page->hdr.length);
  440                 ed = (struct ses_enc_desc *)&buf[8];
  441                 ed->byte0 = 0x11;
  442                 ed->subenc_id = 0;
  443                 ed->num_types = 1;
  444                 ed->length = 36;
  445                 ed->logical_id[0] = 0x30;       /* NAA Locally Assigned. */
  446                 strncpy(&ed->logical_id[1], device_get_nameunit(dev), 7);
  447                 strncpy(ed->vendor_id, "AHCI    ", SID_VENDOR_SIZE);
  448                 strncpy(ed->product_id, "SGPIO Enclosure ", SID_PRODUCT_SIZE);
  449                 strncpy(ed->product_rev, "2.00", SID_REVISION_SIZE);
  450                 td = (struct ses_elm_type_desc *)ses_enc_desc_next(ed);
  451                 td->etype_elm_type = 0x17;
  452                 td->etype_maxelt = enc->channels;
  453                 td->etype_subenc = 0;
  454                 td->etype_txt_len = 11;
  455                 snprintf((char *)(td + 1), 12, "Drive Slots");
  456                 ccb->ccb_h.status = CAM_REQ_CMP;
  457                 goto out;
  458         }
  459 
  460         /* SEMB RECEIVE DIAGNOSTIC RESULT (2) */
  461         if (ccb->ataio.cmd.lba_low == 0x02 &&
  462             ccb->ataio.cmd.features == 0x02 &&
  463             ccb->ataio.cmd.sector_count >= (3 + enc->channels)) {
  464                 bzero(buf, ccb->ataio.dxfer_len);
  465                 page->hdr.page_code = 0x02;
  466                 scsi_ulto2b(4 + 4 * (1 + enc->channels),
  467                     page->hdr.length);
  468                 for (i = 0; i < enc->channels; i++) {
  469                         ads = &page->elements[i + 1].array_dev_slot;
  470                         memcpy(ads, enc->status[i], 4);
  471                         ch = ahci_getch(device_get_parent(dev), i);
  472                         if (ch == NULL) {
  473                                 ads->common.bytes[0] |= SES_OBJSTAT_UNKNOWN;
  474                                 continue;
  475                         }
  476                         if (ch->pm_present)
  477                                 ads->common.bytes[0] |= SES_OBJSTAT_UNKNOWN;
  478                         else if (ch->devices)
  479                                 ads->common.bytes[0] |= SES_OBJSTAT_OK;
  480                         else if (ch->disablephy)
  481                                 ads->common.bytes[0] |= SES_OBJSTAT_NOTAVAIL;
  482                         else
  483                                 ads->common.bytes[0] |= SES_OBJSTAT_NOTINSTALLED;
  484                         if (ch->disablephy)
  485                                 ads->common.bytes[3] |= SESCTL_DEVOFF;
  486                         ahci_putch(ch);
  487                 }
  488                 ccb->ccb_h.status = CAM_REQ_CMP;
  489                 goto out;
  490         }
  491 
  492         /* SEMB SEND DIAGNOSTIC (2) */
  493         if (ccb->ataio.cmd.lba_low == 0x82 &&
  494             ccb->ataio.cmd.features == 0x02 &&
  495             ccb->ataio.cmd.sector_count >= (3 + enc->channels)) {
  496                 ads0 = &page->elements[0].array_dev_slot;
  497                 for (i = 0; i < enc->channels; i++) {
  498                         ads = &page->elements[i + 1].array_dev_slot;
  499                         if (ads->common.bytes[0] & SESCTL_CSEL) {
  500                                 enc->status[i][0] = 0;
  501                                 enc->status[i][1] = ads->bytes[0] &
  502                                     SESCTL_RQSRR;
  503                                 enc->status[i][2] = ads->bytes[1] &
  504                                     (SESCTL_RQSACT | SESCTL_RQSID);
  505                                 enc->status[i][3] = ads->bytes[2] &
  506                                     SESCTL_RQSFLT;
  507                                 ahci_em_setleds(dev, i);
  508                         } else if (ads0->common.bytes[0] & SESCTL_CSEL) {
  509                                 enc->status[i][0] = 0;
  510                                 enc->status[i][1] = ads0->bytes[0] &
  511                                     SESCTL_RQSRR;
  512                                 enc->status[i][2] = ads0->bytes[1] &
  513                                     (SESCTL_RQSACT | SESCTL_RQSID);
  514                                 enc->status[i][3] = ads0->bytes[2] &
  515                                     SESCTL_RQSFLT;
  516                                 ahci_em_setleds(dev, i);
  517                         }
  518                 }
  519                 ccb->ccb_h.status = CAM_REQ_CMP;
  520                 goto out;
  521         }
  522 
  523         /* SEMB RECEIVE DIAGNOSTIC RESULT (7) */
  524         if (ccb->ataio.cmd.lba_low == 0x02 &&
  525             ccb->ataio.cmd.features == 0x07 &&
  526             ccb->ataio.cmd.sector_count >= (6 + 3 * enc->channels)) {
  527                 bzero(buf, ccb->ataio.dxfer_len);
  528                 page->hdr.page_code = 0x07;
  529                 scsi_ulto2b(4 + 15 + 11 * enc->channels, page->hdr.length);
  530                 elmd = (struct ses_elm_desc_hdr *)&buf[8];
  531                 scsi_ulto2b(11, elmd->length);
  532                 snprintf((char *)(elmd + 1), 12, "Drive Slots");
  533                 for (i = 0; i < enc->channels; i++) {
  534                         elmd = (struct ses_elm_desc_hdr *)&buf[8 + 15 + 11 * i];
  535                         scsi_ulto2b(7, elmd->length);
  536                         snprintf((char *)(elmd + 1), 8, "Slot %02d", i);
  537                 }
  538                 ccb->ccb_h.status = CAM_REQ_CMP;
  539                 goto out;
  540         }
  541 
  542         /* SEMB RECEIVE DIAGNOSTIC RESULT (a) */
  543         if (ccb->ataio.cmd.lba_low == 0x02 &&
  544             ccb->ataio.cmd.features == 0x0a &&
  545             ccb->ataio.cmd.sector_count >= (2 + 3 * enc->channels)) {
  546                 bzero(buf, ccb->ataio.dxfer_len);
  547                 page->hdr.page_code = 0x0a;
  548                 scsi_ulto2b(4 + (sizeof(*elma) + sizeof(*elmb)) * enc->channels,
  549                     page->hdr.length);
  550                 for (i = 0; i < enc->channels; i++) {
  551                         elma = (struct ses_elm_addlstatus_eip_hdr *)&buf[
  552                             8 + (sizeof(*elma) + sizeof(*elmb)) * i];
  553                         elma->base.byte0 = 0x10 | SPSP_PROTO_ATA;
  554                         elma->base.length = 2 + sizeof(*elmb);
  555                         elma->byte2 = 0x01;
  556                         elma->element_index = 1 + i;
  557                         ch = ahci_getch(device_get_parent(dev), i);
  558                         if (ch == NULL) {
  559                                 elma->base.byte0 |= 0x80;
  560                                 continue;
  561                         }
  562                         if (ch->devices == 0 || ch->pm_present)
  563                                 elma->base.byte0 |= 0x80;
  564                         elmb = (struct ses_elm_ata_hdr *)(elma + 1);
  565                         scsi_ulto4b(cam_sim_path(ch->sim), elmb->bus);
  566                         scsi_ulto4b(0, elmb->target);
  567                         ahci_putch(ch);
  568                 }
  569                 ccb->ccb_h.status = CAM_REQ_CMP;
  570                 goto out;
  571         }
  572 
  573         ccb->ccb_h.status = CAM_REQ_INVALID;
  574 out:
  575         xpt_done(ccb);
  576 }
  577 
  578 static void
  579 ahci_em_begin_transaction(device_t dev, union ccb *ccb)
  580 {
  581         struct ahci_enclosure *enc;
  582         struct ata_res *res;
  583 
  584         enc = device_get_softc(dev);
  585         res = &ccb->ataio.res;
  586         bzero(res, sizeof(*res));
  587         if ((ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) &&
  588             (ccb->ataio.cmd.control & ATA_A_RESET)) {
  589                 res->lba_high = 0xc3;
  590                 res->lba_mid = 0x3c;
  591                 ccb->ccb_h.status = CAM_REQ_CMP;
  592                 xpt_done(ccb);
  593                 return;
  594         }
  595 
  596         if (enc->capsem & AHCI_EM_LED) {
  597                 ahci_em_emulate_ses_on_led(dev, ccb);
  598                 return;
  599         } else
  600                 device_printf(dev, "Unsupported enclosure interface\n");
  601 
  602         ccb->ccb_h.status = CAM_REQ_INVALID;
  603         xpt_done(ccb);
  604 }
  605 
  606 static void
  607 ahciemaction(struct cam_sim *sim, union ccb *ccb)
  608 {
  609         device_t dev, parent;
  610         struct ahci_enclosure *enc;
  611 
  612         CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
  613             ("ahciemaction func_code=%x\n", ccb->ccb_h.func_code));
  614 
  615         enc = cam_sim_softc(sim);
  616         dev = enc->dev;
  617         switch (ccb->ccb_h.func_code) {
  618         case XPT_ATA_IO:        /* Execute the requested I/O operation */
  619                 if (ahci_check_ids(ccb))
  620                         return;
  621                 ahci_em_begin_transaction(dev, ccb);
  622                 return;
  623         case XPT_RESET_BUS:             /* Reset the specified bus */
  624         case XPT_RESET_DEV:     /* Bus Device Reset the specified device */
  625                 ahci_em_reset(dev);
  626                 ccb->ccb_h.status = CAM_REQ_CMP;
  627                 break;
  628         case XPT_PATH_INQ:              /* Path routing inquiry */
  629         {
  630                 struct ccb_pathinq *cpi = &ccb->cpi;
  631 
  632                 parent = device_get_parent(dev);
  633                 cpi->version_num = 1; /* XXX??? */
  634                 cpi->hba_inquiry = PI_SDTR_ABLE;
  635                 cpi->target_sprt = 0;
  636                 cpi->hba_misc = PIM_SEQSCAN;
  637                 cpi->hba_eng_cnt = 0;
  638                 cpi->max_target = 0;
  639                 cpi->max_lun = 0;
  640                 cpi->initiator_id = 0;
  641                 cpi->bus_id = cam_sim_bus(sim);
  642                 cpi->base_transfer_speed = 150000;
  643                 strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
  644                 strlcpy(cpi->hba_vid, "AHCI", HBA_IDLEN);
  645                 strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
  646                 cpi->unit_number = cam_sim_unit(sim);
  647                 cpi->transport = XPORT_SATA;
  648                 cpi->transport_version = XPORT_VERSION_UNSPECIFIED;
  649                 cpi->protocol = PROTO_ATA;
  650                 cpi->protocol_version = PROTO_VERSION_UNSPECIFIED;
  651                 cpi->maxio = maxphys;
  652                 cpi->hba_vendor = pci_get_vendor(parent);
  653                 cpi->hba_device = pci_get_device(parent);
  654                 cpi->hba_subvendor = pci_get_subvendor(parent);
  655                 cpi->hba_subdevice = pci_get_subdevice(parent);
  656                 cpi->ccb_h.status = CAM_REQ_CMP;
  657                 break;
  658         }
  659         default:
  660                 ccb->ccb_h.status = CAM_REQ_INVALID;
  661                 break;
  662         }
  663         xpt_done(ccb);
  664 }
  665 
  666 static void
  667 ahciempoll(struct cam_sim *sim)
  668 {
  669 
  670 }

Cache object: 6ec4bf7c6e96a774c45c33c94d85e06b


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