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