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

Cache object: f62156e12345f8ca48517a2c84eb738e


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