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 devclass_t ahciem_devclass; 278 static device_method_t ahciem_methods[] = { 279 DEVMETHOD(device_probe, ahci_em_probe), 280 DEVMETHOD(device_attach, ahci_em_attach), 281 DEVMETHOD(device_detach, ahci_em_detach), 282 DEVMETHOD(device_suspend, ahci_em_suspend), 283 DEVMETHOD(device_resume, ahci_em_resume), 284 DEVMETHOD_END 285 }; 286 static driver_t ahciem_driver = { 287 "ahciem", 288 ahciem_methods, 289 sizeof(struct ahci_enclosure) 290 }; 291 DRIVER_MODULE(ahciem, ahci, ahciem_driver, ahciem_devclass, NULL, NULL); 292 293 static void 294 ahci_em_setleds(device_t dev, int c) 295 { 296 struct ahci_enclosure *enc; 297 int timeout; 298 int16_t val; 299 300 enc = device_get_softc(dev); 301 if (enc->r_memc == NULL) 302 return; 303 304 val = 0; 305 if (enc->status[c][2] & SESCTL_RQSACT) /* Activity */ 306 val |= (1 << 0); 307 if (enc->status[c][1] & SESCTL_RQSRR) /* Rebuild */ 308 val |= (1 << 6) | (1 << 3); 309 else if (enc->status[c][2] & SESCTL_RQSID) /* Identification */ 310 val |= (1 << 3); 311 else if (enc->status[c][3] & SESCTL_RQSFLT) /* Fault */ 312 val |= (1 << 6); 313 314 timeout = 10000; 315 while (ATA_INL(enc->r_memc, 0) & (AHCI_EM_TM | AHCI_EM_RST) && 316 --timeout > 0) 317 DELAY(100); 318 if (timeout == 0) 319 device_printf(dev, "Transmit timeout\n"); 320 ATA_OUTL(enc->r_memt, 0, (1 << 8) | (0 << 16) | (0 << 24)); 321 ATA_OUTL(enc->r_memt, 4, c | (0 << 8) | (val << 16)); 322 ATA_OUTL(enc->r_memc, 0, AHCI_EM_TM); 323 } 324 325 static void 326 ahci_em_led(void *priv, int onoff) 327 { 328 struct ahci_led *led; 329 struct ahci_enclosure *enc; 330 int c, l; 331 332 led = (struct ahci_led *)priv; 333 enc = device_get_softc(led->dev); 334 c = led->num / AHCI_NUM_LEDS; 335 l = led->num % AHCI_NUM_LEDS; 336 337 if (l == 0) { 338 if (onoff) 339 enc->status[c][2] |= 0x80; 340 else 341 enc->status[c][2] &= ~0x80; 342 } else if (l == 1) { 343 if (onoff) 344 enc->status[c][2] |= SESCTL_RQSID; 345 else 346 enc->status[c][2] &= ~SESCTL_RQSID; 347 } else if (l == 2) { 348 if (onoff) 349 enc->status[c][3] |= SESCTL_RQSFLT; 350 else 351 enc->status[c][3] &= SESCTL_RQSFLT; 352 } 353 ahci_em_setleds(led->dev, c); 354 } 355 356 static int 357 ahci_check_ids(union ccb *ccb) 358 { 359 360 if (ccb->ccb_h.target_id != 0) { 361 ccb->ccb_h.status = CAM_TID_INVALID; 362 xpt_done(ccb); 363 return (-1); 364 } 365 if (ccb->ccb_h.target_lun != 0) { 366 ccb->ccb_h.status = CAM_LUN_INVALID; 367 xpt_done(ccb); 368 return (-1); 369 } 370 return (0); 371 } 372 373 static void 374 ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb) 375 { 376 struct ahci_enclosure *enc; 377 struct ahci_channel *ch; 378 struct ses_status_page *page; 379 struct ses_status_array_dev_slot *ads, *ads0; 380 struct ses_elm_desc_hdr *elmd; 381 struct ses_elm_addlstatus_eip_hdr *elma; 382 struct ses_elm_ata_hdr *elmb; 383 uint8_t *buf; 384 int i; 385 386 enc = device_get_softc(dev); 387 buf = ccb->ataio.data_ptr; 388 389 /* General request validation. */ 390 if (ccb->ataio.cmd.command != ATA_SEP_ATTN || 391 ccb->ataio.dxfer_len < ccb->ataio.cmd.sector_count * 4) { 392 ccb->ccb_h.status = CAM_REQ_INVALID; 393 goto out; 394 } 395 396 /* SEMB IDENTIFY */ 397 if (ccb->ataio.cmd.features == 0xEC && 398 ccb->ataio.cmd.sector_count >= 16) { 399 bzero(buf, ccb->ataio.dxfer_len); 400 buf[0] = 64; /* Valid bytes. */ 401 buf[2] = 0x30; /* NAA Locally Assigned. */ 402 strncpy(&buf[3], device_get_nameunit(dev), 7); 403 strncpy(&buf[10], "AHCI ", SID_VENDOR_SIZE); 404 strncpy(&buf[18], "SGPIO Enclosure ", SID_PRODUCT_SIZE); 405 strncpy(&buf[34], "2.00", SID_REVISION_SIZE); 406 strncpy(&buf[39], "0001", 4); 407 strncpy(&buf[43], "S-E-S ", 6); 408 strncpy(&buf[49], "2.00", 4); 409 ccb->ccb_h.status = CAM_REQ_CMP; 410 goto out; 411 } 412 413 /* SEMB RECEIVE DIAGNOSTIC RESULT (0) */ 414 page = (struct ses_status_page *)buf; 415 if (ccb->ataio.cmd.lba_low == 0x02 && 416 ccb->ataio.cmd.features == 0x00 && 417 ccb->ataio.cmd.sector_count >= 3) { 418 bzero(buf, ccb->ataio.dxfer_len); 419 page->hdr.page_code = 0; 420 scsi_ulto2b(5, page->hdr.length); 421 buf[4] = 0x00; 422 buf[5] = 0x01; 423 buf[6] = 0x02; 424 buf[7] = 0x07; 425 buf[8] = 0x0a; 426 ccb->ccb_h.status = CAM_REQ_CMP; 427 goto out; 428 } 429 430 /* SEMB RECEIVE DIAGNOSTIC RESULT (1) */ 431 if (ccb->ataio.cmd.lba_low == 0x02 && 432 ccb->ataio.cmd.features == 0x01 && 433 ccb->ataio.cmd.sector_count >= 16) { 434 struct ses_enc_desc *ed; 435 struct ses_elm_type_desc *td; 436 437 bzero(buf, ccb->ataio.dxfer_len); 438 page->hdr.page_code = 0x01; 439 scsi_ulto2b(4 + sizeof(*ed) + sizeof(*td) + 11, 440 page->hdr.length); 441 ed = (struct ses_enc_desc *)&buf[8]; 442 ed->byte0 = 0x11; 443 ed->subenc_id = 0; 444 ed->num_types = 1; 445 ed->length = 36; 446 ed->logical_id[0] = 0x30; /* NAA Locally Assigned. */ 447 strncpy(&ed->logical_id[1], device_get_nameunit(dev), 7); 448 strncpy(ed->vendor_id, "AHCI ", SID_VENDOR_SIZE); 449 strncpy(ed->product_id, "SGPIO Enclosure ", SID_PRODUCT_SIZE); 450 strncpy(ed->product_rev, "2.00", SID_REVISION_SIZE); 451 td = (struct ses_elm_type_desc *)ses_enc_desc_next(ed); 452 td->etype_elm_type = 0x17; 453 td->etype_maxelt = enc->channels; 454 td->etype_subenc = 0; 455 td->etype_txt_len = 11; 456 snprintf((char *)(td + 1), 12, "Drive Slots"); 457 ccb->ccb_h.status = CAM_REQ_CMP; 458 goto out; 459 } 460 461 /* SEMB RECEIVE DIAGNOSTIC RESULT (2) */ 462 if (ccb->ataio.cmd.lba_low == 0x02 && 463 ccb->ataio.cmd.features == 0x02 && 464 ccb->ataio.cmd.sector_count >= (3 + enc->channels)) { 465 bzero(buf, ccb->ataio.dxfer_len); 466 page->hdr.page_code = 0x02; 467 scsi_ulto2b(4 + 4 * (1 + enc->channels), 468 page->hdr.length); 469 for (i = 0; i < enc->channels; i++) { 470 ads = &page->elements[i + 1].array_dev_slot; 471 memcpy(ads, enc->status[i], 4); 472 ch = ahci_getch(device_get_parent(dev), i); 473 if (ch == NULL) { 474 ads->common.bytes[0] |= SES_OBJSTAT_UNKNOWN; 475 continue; 476 } 477 if (ch->pm_present) 478 ads->common.bytes[0] |= SES_OBJSTAT_UNKNOWN; 479 else if (ch->devices) 480 ads->common.bytes[0] |= SES_OBJSTAT_OK; 481 else if (ch->disablephy) 482 ads->common.bytes[0] |= SES_OBJSTAT_NOTAVAIL; 483 else 484 ads->common.bytes[0] |= SES_OBJSTAT_NOTINSTALLED; 485 if (ch->disablephy) 486 ads->common.bytes[3] |= SESCTL_DEVOFF; 487 ahci_putch(ch); 488 } 489 ccb->ccb_h.status = CAM_REQ_CMP; 490 goto out; 491 } 492 493 /* SEMB SEND DIAGNOSTIC (2) */ 494 if (ccb->ataio.cmd.lba_low == 0x82 && 495 ccb->ataio.cmd.features == 0x02 && 496 ccb->ataio.cmd.sector_count >= (3 + enc->channels)) { 497 ads0 = &page->elements[0].array_dev_slot; 498 for (i = 0; i < enc->channels; i++) { 499 ads = &page->elements[i + 1].array_dev_slot; 500 if (ads->common.bytes[0] & SESCTL_CSEL) { 501 enc->status[i][0] = 0; 502 enc->status[i][1] = ads->bytes[0] & 503 SESCTL_RQSRR; 504 enc->status[i][2] = ads->bytes[1] & 505 (SESCTL_RQSACT | SESCTL_RQSID); 506 enc->status[i][3] = ads->bytes[2] & 507 SESCTL_RQSFLT; 508 ahci_em_setleds(dev, i); 509 } else if (ads0->common.bytes[0] & SESCTL_CSEL) { 510 enc->status[i][0] = 0; 511 enc->status[i][1] = ads0->bytes[0] & 512 SESCTL_RQSRR; 513 enc->status[i][2] = ads0->bytes[1] & 514 (SESCTL_RQSACT | SESCTL_RQSID); 515 enc->status[i][3] = ads0->bytes[2] & 516 SESCTL_RQSFLT; 517 ahci_em_setleds(dev, i); 518 } 519 } 520 ccb->ccb_h.status = CAM_REQ_CMP; 521 goto out; 522 } 523 524 /* SEMB RECEIVE DIAGNOSTIC RESULT (7) */ 525 if (ccb->ataio.cmd.lba_low == 0x02 && 526 ccb->ataio.cmd.features == 0x07 && 527 ccb->ataio.cmd.sector_count >= (6 + 3 * enc->channels)) { 528 bzero(buf, ccb->ataio.dxfer_len); 529 page->hdr.page_code = 0x07; 530 scsi_ulto2b(4 + 15 + 11 * enc->channels, page->hdr.length); 531 elmd = (struct ses_elm_desc_hdr *)&buf[8]; 532 scsi_ulto2b(11, elmd->length); 533 snprintf((char *)(elmd + 1), 12, "Drive Slots"); 534 for (i = 0; i < enc->channels; i++) { 535 elmd = (struct ses_elm_desc_hdr *)&buf[8 + 15 + 11 * i]; 536 scsi_ulto2b(7, elmd->length); 537 snprintf((char *)(elmd + 1), 8, "Slot %02d", i); 538 } 539 ccb->ccb_h.status = CAM_REQ_CMP; 540 goto out; 541 } 542 543 /* SEMB RECEIVE DIAGNOSTIC RESULT (a) */ 544 if (ccb->ataio.cmd.lba_low == 0x02 && 545 ccb->ataio.cmd.features == 0x0a && 546 ccb->ataio.cmd.sector_count >= (2 + 3 * enc->channels)) { 547 bzero(buf, ccb->ataio.dxfer_len); 548 page->hdr.page_code = 0x0a; 549 scsi_ulto2b(4 + (sizeof(*elma) + sizeof(*elmb)) * enc->channels, 550 page->hdr.length); 551 for (i = 0; i < enc->channels; i++) { 552 elma = (struct ses_elm_addlstatus_eip_hdr *)&buf[ 553 8 + (sizeof(*elma) + sizeof(*elmb)) * i]; 554 elma->base.byte0 = 0x10 | SPSP_PROTO_ATA; 555 elma->base.length = 2 + sizeof(*elmb); 556 elma->byte2 = 0x01; 557 elma->element_index = 1 + i; 558 ch = ahci_getch(device_get_parent(dev), i); 559 if (ch == NULL) { 560 elma->base.byte0 |= 0x80; 561 continue; 562 } 563 if (ch->devices == 0 || ch->pm_present) 564 elma->base.byte0 |= 0x80; 565 elmb = (struct ses_elm_ata_hdr *)(elma + 1); 566 scsi_ulto4b(cam_sim_path(ch->sim), elmb->bus); 567 scsi_ulto4b(0, elmb->target); 568 ahci_putch(ch); 569 } 570 ccb->ccb_h.status = CAM_REQ_CMP; 571 goto out; 572 } 573 574 ccb->ccb_h.status = CAM_REQ_INVALID; 575 out: 576 xpt_done(ccb); 577 } 578 579 static void 580 ahci_em_begin_transaction(device_t dev, union ccb *ccb) 581 { 582 struct ahci_enclosure *enc; 583 struct ata_res *res; 584 585 enc = device_get_softc(dev); 586 res = &ccb->ataio.res; 587 bzero(res, sizeof(*res)); 588 if ((ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) && 589 (ccb->ataio.cmd.control & ATA_A_RESET)) { 590 res->lba_high = 0xc3; 591 res->lba_mid = 0x3c; 592 ccb->ccb_h.status = CAM_REQ_CMP; 593 xpt_done(ccb); 594 return; 595 } 596 597 if (enc->capsem & AHCI_EM_LED) { 598 ahci_em_emulate_ses_on_led(dev, ccb); 599 return; 600 } else 601 device_printf(dev, "Unsupported enclosure interface\n"); 602 603 ccb->ccb_h.status = CAM_REQ_INVALID; 604 xpt_done(ccb); 605 } 606 607 static void 608 ahciemaction(struct cam_sim *sim, union ccb *ccb) 609 { 610 device_t dev, parent; 611 struct ahci_enclosure *enc; 612 613 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, 614 ("ahciemaction func_code=%x\n", ccb->ccb_h.func_code)); 615 616 enc = cam_sim_softc(sim); 617 dev = enc->dev; 618 switch (ccb->ccb_h.func_code) { 619 case XPT_ATA_IO: /* Execute the requested I/O operation */ 620 if (ahci_check_ids(ccb)) 621 return; 622 ahci_em_begin_transaction(dev, ccb); 623 return; 624 case XPT_RESET_BUS: /* Reset the specified bus */ 625 case XPT_RESET_DEV: /* Bus Device Reset the specified device */ 626 ahci_em_reset(dev); 627 ccb->ccb_h.status = CAM_REQ_CMP; 628 break; 629 case XPT_PATH_INQ: /* Path routing inquiry */ 630 { 631 struct ccb_pathinq *cpi = &ccb->cpi; 632 633 parent = device_get_parent(dev); 634 cpi->version_num = 1; /* XXX??? */ 635 cpi->hba_inquiry = PI_SDTR_ABLE; 636 cpi->target_sprt = 0; 637 cpi->hba_misc = PIM_SEQSCAN; 638 cpi->hba_eng_cnt = 0; 639 cpi->max_target = 0; 640 cpi->max_lun = 0; 641 cpi->initiator_id = 0; 642 cpi->bus_id = cam_sim_bus(sim); 643 cpi->base_transfer_speed = 150000; 644 strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 645 strlcpy(cpi->hba_vid, "AHCI", HBA_IDLEN); 646 strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 647 cpi->unit_number = cam_sim_unit(sim); 648 cpi->transport = XPORT_SATA; 649 cpi->transport_version = XPORT_VERSION_UNSPECIFIED; 650 cpi->protocol = PROTO_ATA; 651 cpi->protocol_version = PROTO_VERSION_UNSPECIFIED; 652 cpi->maxio = maxphys; 653 cpi->hba_vendor = pci_get_vendor(parent); 654 cpi->hba_device = pci_get_device(parent); 655 cpi->hba_subvendor = pci_get_subvendor(parent); 656 cpi->hba_subdevice = pci_get_subdevice(parent); 657 cpi->ccb_h.status = CAM_REQ_CMP; 658 break; 659 } 660 default: 661 ccb->ccb_h.status = CAM_REQ_INVALID; 662 break; 663 } 664 xpt_done(ccb); 665 } 666 667 static void 668 ahciempoll(struct cam_sim *sim) 669 { 670 671 } 672