1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2012 Alexander Motin <[email protected]>
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
ahci_em_probe(device_t dev)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
ahci_em_attach(device_t dev)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
ahci_em_detach(device_t dev)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
ahci_em_reset(device_t dev)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
ahci_em_suspend(device_t dev)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
ahci_em_resume(device_t dev)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
ahci_em_setleds(device_t dev,int c)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
ahci_em_led(void * priv,int onoff)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
ahci_check_ids(union ccb * ccb)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
ahci_em_emulate_ses_on_led(device_t dev,union ccb * ccb)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
ahci_em_begin_transaction(device_t dev,union ccb * ccb)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
ahciemaction(struct cam_sim * sim,union ccb * ccb)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
ahciempoll(struct cam_sim * sim)668 ahciempoll(struct cam_sim *sim)
669 {
670
671 }
672