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