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