FreeBSD/Linux Kernel Cross Reference
sys/dev/ahci/ahciem.c
1 /*-
2 * Copyright (c) 2012 Alexander Motin <mav@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
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))) {
89 mtx_destroy(&enc->mtx);
90 return (ENXIO);
91 }
92 enc->capsem = ATA_INL(enc->r_memc, 0);
93 rid = 1;
94 if (!(enc->r_memt = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
95 &rid, RF_ACTIVE))) {
96 error = ENXIO;
97 goto err0;
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 bus_release_resource(dev, SYS_RES_MEMORY, 0, enc->r_memc);
196 mtx_destroy(&enc->mtx);
197 return (error);
198 }
199
200 static int
201 ahci_em_detach(device_t dev)
202 {
203 struct ahci_enclosure *enc = device_get_softc(dev);
204 int i;
205
206 for (i = 0; i < enc->channels * AHCI_NUM_LEDS; i++) {
207 if (enc->leds[i].led)
208 led_destroy(enc->leds[i].led);
209 }
210 mtx_lock(&enc->mtx);
211 xpt_async(AC_LOST_DEVICE, enc->path, NULL);
212 xpt_free_path(enc->path);
213 xpt_bus_deregister(cam_sim_path(enc->sim));
214 cam_sim_free(enc->sim, /*free_devq*/TRUE);
215 mtx_unlock(&enc->mtx);
216
217 bus_release_resource(dev, SYS_RES_MEMORY, 0, enc->r_memc);
218 bus_release_resource(dev, SYS_RES_MEMORY, 1, enc->r_memt);
219 if (enc->r_memr)
220 bus_release_resource(dev, SYS_RES_MEMORY, 2, enc->r_memr);
221 mtx_destroy(&enc->mtx);
222 return (0);
223 }
224
225 static int
226 ahci_em_reset(device_t dev)
227 {
228 struct ahci_enclosure *enc;
229 int i, timeout;
230
231 enc = device_get_softc(dev);
232 ATA_OUTL(enc->r_memc, 0, AHCI_EM_RST);
233 timeout = 1000;
234 while ((ATA_INL(enc->r_memc, 0) & AHCI_EM_RST) &&
235 --timeout > 0)
236 DELAY(1000);
237 if (timeout == 0) {
238 device_printf(dev, "EM timeout\n");
239 return (1);
240 }
241 for (i = 0; i < enc->channels; i++)
242 ahci_em_setleds(dev, i);
243 return (0);
244 }
245
246 static int
247 ahci_em_suspend(device_t dev)
248 {
249 struct ahci_enclosure *enc = device_get_softc(dev);
250
251 mtx_lock(&enc->mtx);
252 xpt_freeze_simq(enc->sim, 1);
253 mtx_unlock(&enc->mtx);
254 return (0);
255 }
256
257 static int
258 ahci_em_resume(device_t dev)
259 {
260 struct ahci_enclosure *enc = device_get_softc(dev);
261
262 mtx_lock(&enc->mtx);
263 ahci_em_reset(dev);
264 xpt_release_simq(enc->sim, TRUE);
265 mtx_unlock(&enc->mtx);
266 return (0);
267 }
268
269 devclass_t ahciem_devclass;
270 static device_method_t ahciem_methods[] = {
271 DEVMETHOD(device_probe, ahci_em_probe),
272 DEVMETHOD(device_attach, ahci_em_attach),
273 DEVMETHOD(device_detach, ahci_em_detach),
274 DEVMETHOD(device_suspend, ahci_em_suspend),
275 DEVMETHOD(device_resume, ahci_em_resume),
276 DEVMETHOD_END
277 };
278 static driver_t ahciem_driver = {
279 "ahciem",
280 ahciem_methods,
281 sizeof(struct ahci_enclosure)
282 };
283 DRIVER_MODULE(ahciem, ahci, ahciem_driver, ahciem_devclass, NULL, NULL);
284
285 static void
286 ahci_em_setleds(device_t dev, int c)
287 {
288 struct ahci_enclosure *enc;
289 int timeout;
290 int16_t val;
291
292 enc = device_get_softc(dev);
293
294 val = 0;
295 if (enc->status[c][2] & SESCTL_RQSACT) /* Activity */
296 val |= (1 << 0);
297 if (enc->status[c][1] & SESCTL_RQSRR) /* Rebuild */
298 val |= (1 << 6) | (1 << 3);
299 else if (enc->status[c][2] & SESCTL_RQSID) /* Identification */
300 val |= (1 << 3);
301 else if (enc->status[c][3] & SESCTL_RQSFLT) /* Fault */
302 val |= (1 << 6);
303
304 timeout = 10000;
305 while (ATA_INL(enc->r_memc, 0) & (AHCI_EM_TM | AHCI_EM_RST) &&
306 --timeout > 0)
307 DELAY(100);
308 if (timeout == 0)
309 device_printf(dev, "Transmit timeout\n");
310 ATA_OUTL(enc->r_memt, 0, (1 << 8) | (0 << 16) | (0 << 24));
311 ATA_OUTL(enc->r_memt, 4, c | (0 << 8) | (val << 16));
312 ATA_OUTL(enc->r_memc, 0, AHCI_EM_TM);
313 }
314
315 static void
316 ahci_em_led(void *priv, int onoff)
317 {
318 struct ahci_led *led;
319 struct ahci_enclosure *enc;
320 int c, l;
321
322 led = (struct ahci_led *)priv;
323 enc = device_get_softc(led->dev);
324 c = led->num / AHCI_NUM_LEDS;
325 l = led->num % AHCI_NUM_LEDS;
326
327 if (l == 0) {
328 if (onoff)
329 enc->status[c][2] |= 0x80;
330 else
331 enc->status[c][2] &= ~0x80;
332 } else if (l == 1) {
333 if (onoff)
334 enc->status[c][2] |= SESCTL_RQSID;
335 else
336 enc->status[c][2] &= ~SESCTL_RQSID;
337 } else if (l == 2) {
338 if (onoff)
339 enc->status[c][3] |= SESCTL_RQSFLT;
340 else
341 enc->status[c][3] &= SESCTL_RQSFLT;
342 }
343 ahci_em_setleds(led->dev, c);
344 }
345
346 static int
347 ahci_check_ids(union ccb *ccb)
348 {
349
350 if (ccb->ccb_h.target_id != 0) {
351 ccb->ccb_h.status = CAM_TID_INVALID;
352 xpt_done(ccb);
353 return (-1);
354 }
355 if (ccb->ccb_h.target_lun != 0) {
356 ccb->ccb_h.status = CAM_LUN_INVALID;
357 xpt_done(ccb);
358 return (-1);
359 }
360 return (0);
361 }
362
363 static void
364 ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
365 {
366 struct ahci_enclosure *enc;
367 struct ahci_channel *ch;
368 struct ses_status_page *page;
369 struct ses_status_array_dev_slot *ads, *ads0;
370 struct ses_elm_desc_hdr *elmd;
371 struct ses_elm_addlstatus_eip_hdr *elma;
372 struct ses_elm_ata_hdr *elmb;
373 uint8_t *buf;
374 int i;
375
376 enc = device_get_softc(dev);
377 buf = ccb->ataio.data_ptr;
378
379 /* General request validation. */
380 if (ccb->ataio.cmd.command != ATA_SEP_ATTN ||
381 ccb->ataio.dxfer_len < ccb->ataio.cmd.sector_count * 4) {
382 ccb->ccb_h.status = CAM_REQ_INVALID;
383 goto out;
384 }
385
386 /* SEMB IDENTIFY */
387 if (ccb->ataio.cmd.features == 0xEC &&
388 ccb->ataio.cmd.sector_count >= 16) {
389 bzero(buf, ccb->ataio.dxfer_len);
390 buf[0] = 64; /* Valid bytes. */
391 buf[2] = 0x30; /* NAA Locally Assigned. */
392 strncpy(&buf[3], device_get_nameunit(dev), 7);
393 strncpy(&buf[10], "AHCI ", SID_VENDOR_SIZE);
394 strncpy(&buf[18], "SGPIO Enclosure ", SID_PRODUCT_SIZE);
395 strncpy(&buf[34], "2.00", SID_REVISION_SIZE);
396 strncpy(&buf[39], "0001", 4);
397 strncpy(&buf[43], "S-E-S ", 6);
398 strncpy(&buf[49], "2.00", 4);
399 ccb->ccb_h.status = CAM_REQ_CMP;
400 goto out;
401 }
402
403 /* SEMB RECEIVE DIAGNOSTIC RESULT (0) */
404 page = (struct ses_status_page *)buf;
405 if (ccb->ataio.cmd.lba_low == 0x02 &&
406 ccb->ataio.cmd.features == 0x00 &&
407 ccb->ataio.cmd.sector_count >= 3) {
408 bzero(buf, ccb->ataio.dxfer_len);
409 page->hdr.page_code = 0;
410 scsi_ulto2b(5, page->hdr.length);
411 buf[4] = 0x00;
412 buf[5] = 0x01;
413 buf[6] = 0x02;
414 buf[7] = 0x07;
415 buf[8] = 0x0a;
416 ccb->ccb_h.status = CAM_REQ_CMP;
417 goto out;
418 }
419
420 /* SEMB RECEIVE DIAGNOSTIC RESULT (1) */
421 if (ccb->ataio.cmd.lba_low == 0x02 &&
422 ccb->ataio.cmd.features == 0x01 &&
423 ccb->ataio.cmd.sector_count >= 16) {
424 struct ses_enc_desc *ed;
425 struct ses_elm_type_desc *td;
426
427 bzero(buf, ccb->ataio.dxfer_len);
428 page->hdr.page_code = 0x01;
429 scsi_ulto2b(4 + sizeof(*ed) + sizeof(*td) + 11,
430 page->hdr.length);
431 ed = (struct ses_enc_desc *)&buf[8];
432 ed->byte0 = 0x11;
433 ed->subenc_id = 0;
434 ed->num_types = 1;
435 ed->length = 36;
436 ed->logical_id[0] = 0x30; /* NAA Locally Assigned. */
437 strncpy(&ed->logical_id[1], device_get_nameunit(dev), 7);
438 strncpy(ed->vendor_id, "AHCI ", SID_VENDOR_SIZE);
439 strncpy(ed->product_id, "SGPIO Enclosure ", SID_PRODUCT_SIZE);
440 strncpy(ed->product_rev, "2.00", SID_REVISION_SIZE);
441 td = (struct ses_elm_type_desc *)ses_enc_desc_next(ed);
442 td->etype_elm_type = 0x17;
443 td->etype_maxelt = enc->channels;
444 td->etype_subenc = 0;
445 td->etype_txt_len = 11;
446 snprintf((char *)(td + 1), 12, "Drive Slots");
447 ccb->ccb_h.status = CAM_REQ_CMP;
448 goto out;
449 }
450
451 /* SEMB RECEIVE DIAGNOSTIC RESULT (2) */
452 if (ccb->ataio.cmd.lba_low == 0x02 &&
453 ccb->ataio.cmd.features == 0x02 &&
454 ccb->ataio.cmd.sector_count >= (3 + enc->channels)) {
455 bzero(buf, ccb->ataio.dxfer_len);
456 page->hdr.page_code = 0x02;
457 scsi_ulto2b(4 + 4 * (1 + enc->channels),
458 page->hdr.length);
459 for (i = 0; i < enc->channels; i++) {
460 ads = &page->elements[i + 1].array_dev_slot;
461 memcpy(ads, enc->status[i], 4);
462 ch = ahci_getch(device_get_parent(dev), i);
463 if (ch == NULL) {
464 ads->common.bytes[0] |= SES_OBJSTAT_UNKNOWN;
465 continue;
466 }
467 if (ch->pm_present)
468 ads->common.bytes[0] |= SES_OBJSTAT_UNKNOWN;
469 else if (ch->devices)
470 ads->common.bytes[0] |= SES_OBJSTAT_OK;
471 else if (ch->disablephy)
472 ads->common.bytes[0] |= SES_OBJSTAT_NOTAVAIL;
473 else
474 ads->common.bytes[0] |= SES_OBJSTAT_NOTINSTALLED;
475 if (ch->disablephy)
476 ads->common.bytes[3] |= SESCTL_DEVOFF;
477 ahci_putch(ch);
478 }
479 ccb->ccb_h.status = CAM_REQ_CMP;
480 goto out;
481 }
482
483 /* SEMB SEND DIAGNOSTIC (2) */
484 if (ccb->ataio.cmd.lba_low == 0x82 &&
485 ccb->ataio.cmd.features == 0x02 &&
486 ccb->ataio.cmd.sector_count >= (3 + enc->channels)) {
487 ads0 = &page->elements[0].array_dev_slot;
488 for (i = 0; i < enc->channels; i++) {
489 ads = &page->elements[i + 1].array_dev_slot;
490 if (ads->common.bytes[0] & SESCTL_CSEL) {
491 enc->status[i][0] = 0;
492 enc->status[i][1] = ads->bytes[0] &
493 SESCTL_RQSRR;
494 enc->status[i][2] = ads->bytes[1] &
495 (SESCTL_RQSACT | SESCTL_RQSID);
496 enc->status[i][3] = ads->bytes[2] &
497 SESCTL_RQSFLT;
498 ahci_em_setleds(dev, i);
499 } else if (ads0->common.bytes[0] & SESCTL_CSEL) {
500 enc->status[i][0] = 0;
501 enc->status[i][1] = ads0->bytes[0] &
502 SESCTL_RQSRR;
503 enc->status[i][2] = ads0->bytes[1] &
504 (SESCTL_RQSACT | SESCTL_RQSID);
505 enc->status[i][3] = ads0->bytes[2] &
506 SESCTL_RQSFLT;
507 ahci_em_setleds(dev, i);
508 }
509 }
510 ccb->ccb_h.status = CAM_REQ_CMP;
511 goto out;
512 }
513
514 /* SEMB RECEIVE DIAGNOSTIC RESULT (7) */
515 if (ccb->ataio.cmd.lba_low == 0x02 &&
516 ccb->ataio.cmd.features == 0x07 &&
517 ccb->ataio.cmd.sector_count >= (6 + 3 * enc->channels)) {
518 bzero(buf, ccb->ataio.dxfer_len);
519 page->hdr.page_code = 0x07;
520 scsi_ulto2b(4 + 15 + 11 * enc->channels, page->hdr.length);
521 elmd = (struct ses_elm_desc_hdr *)&buf[8];
522 scsi_ulto2b(11, elmd->length);
523 snprintf((char *)(elmd + 1), 12, "Drive Slots");
524 for (i = 0; i < enc->channels; i++) {
525 elmd = (struct ses_elm_desc_hdr *)&buf[8 + 15 + 11 * i];
526 scsi_ulto2b(7, elmd->length);
527 snprintf((char *)(elmd + 1), 8, "Slot %02d", i);
528 }
529 ccb->ccb_h.status = CAM_REQ_CMP;
530 goto out;
531 }
532
533 /* SEMB RECEIVE DIAGNOSTIC RESULT (a) */
534 if (ccb->ataio.cmd.lba_low == 0x02 &&
535 ccb->ataio.cmd.features == 0x0a &&
536 ccb->ataio.cmd.sector_count >= (2 + 3 * enc->channels)) {
537 bzero(buf, ccb->ataio.dxfer_len);
538 page->hdr.page_code = 0x0a;
539 scsi_ulto2b(4 + (sizeof(*elma) + sizeof(*elmb)) * enc->channels,
540 page->hdr.length);
541 for (i = 0; i < enc->channels; i++) {
542 elma = (struct ses_elm_addlstatus_eip_hdr *)&buf[
543 8 + (sizeof(*elma) + sizeof(*elmb)) * i];
544 elma->base.byte0 = 0x10 | SPSP_PROTO_ATA;
545 elma->base.length = 2 + sizeof(*elmb);
546 elma->byte2 = 0x01;
547 elma->element_index = 1 + i;
548 ch = ahci_getch(device_get_parent(dev), i);
549 if (ch == NULL) {
550 elma->base.byte0 |= 0x80;
551 continue;
552 }
553 if (ch->devices == 0 || ch->pm_present)
554 elma->base.byte0 |= 0x80;
555 elmb = (struct ses_elm_ata_hdr *)(elma + 1);
556 scsi_ulto4b(cam_sim_path(ch->sim), elmb->bus);
557 scsi_ulto4b(0, elmb->target);
558 ahci_putch(ch);
559 }
560 ccb->ccb_h.status = CAM_REQ_CMP;
561 goto out;
562 }
563
564 ccb->ccb_h.status = CAM_REQ_INVALID;
565 out:
566 xpt_done(ccb);
567 }
568
569 static void
570 ahci_em_begin_transaction(device_t dev, union ccb *ccb)
571 {
572 struct ahci_enclosure *enc;
573 struct ata_res *res;
574
575 enc = device_get_softc(dev);
576 res = &ccb->ataio.res;
577 bzero(res, sizeof(*res));
578 if ((ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) &&
579 (ccb->ataio.cmd.control & ATA_A_RESET)) {
580 res->lba_high = 0xc3;
581 res->lba_mid = 0x3c;
582 ccb->ccb_h.status = CAM_REQ_CMP;
583 xpt_done(ccb);
584 return;
585 }
586
587 if (enc->capsem & AHCI_EM_LED) {
588 ahci_em_emulate_ses_on_led(dev, ccb);
589 return;
590 } else
591 device_printf(dev, "Unsupported enclosure interface\n");
592
593 ccb->ccb_h.status = CAM_REQ_INVALID;
594 xpt_done(ccb);
595 }
596
597 static void
598 ahciemaction(struct cam_sim *sim, union ccb *ccb)
599 {
600 device_t dev, parent;
601 struct ahci_enclosure *enc;
602
603 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
604 ("ahciemaction func_code=%x\n", ccb->ccb_h.func_code));
605
606 enc = cam_sim_softc(sim);
607 dev = enc->dev;
608 switch (ccb->ccb_h.func_code) {
609 case XPT_ATA_IO: /* Execute the requested I/O operation */
610 if (ahci_check_ids(ccb))
611 return;
612 ahci_em_begin_transaction(dev, ccb);
613 return;
614 case XPT_RESET_BUS: /* Reset the specified bus */
615 case XPT_RESET_DEV: /* Bus Device Reset the specified device */
616 ahci_em_reset(dev);
617 ccb->ccb_h.status = CAM_REQ_CMP;
618 break;
619 case XPT_PATH_INQ: /* Path routing inquiry */
620 {
621 struct ccb_pathinq *cpi = &ccb->cpi;
622
623 parent = device_get_parent(dev);
624 cpi->version_num = 1; /* XXX??? */
625 cpi->hba_inquiry = PI_SDTR_ABLE;
626 cpi->target_sprt = 0;
627 cpi->hba_misc = PIM_SEQSCAN;
628 cpi->hba_eng_cnt = 0;
629 cpi->max_target = 0;
630 cpi->max_lun = 0;
631 cpi->initiator_id = 0;
632 cpi->bus_id = cam_sim_bus(sim);
633 cpi->base_transfer_speed = 150000;
634 strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
635 strlcpy(cpi->hba_vid, "AHCI", HBA_IDLEN);
636 strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
637 cpi->unit_number = cam_sim_unit(sim);
638 cpi->transport = XPORT_SATA;
639 cpi->transport_version = XPORT_VERSION_UNSPECIFIED;
640 cpi->protocol = PROTO_ATA;
641 cpi->protocol_version = PROTO_VERSION_UNSPECIFIED;
642 cpi->maxio = MAXPHYS;
643 cpi->hba_vendor = pci_get_vendor(parent);
644 cpi->hba_device = pci_get_device(parent);
645 cpi->hba_subvendor = pci_get_subvendor(parent);
646 cpi->hba_subdevice = pci_get_subdevice(parent);
647 cpi->ccb_h.status = CAM_REQ_CMP;
648 break;
649 }
650 default:
651 ccb->ccb_h.status = CAM_REQ_INVALID;
652 break;
653 }
654 xpt_done(ccb);
655 }
656
657 static void
658 ahciempoll(struct cam_sim *sim)
659 {
660
661 }
Cache object: 827f77999c98336b7a098319486dcbe2
|