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