ahciem.c revision 315813
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: stable/10/sys/dev/ahci/ahciem.c 315813 2017-03-23 06:41:13Z mav $");
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 */
57static void ahciemaction(struct cam_sim *sim, union ccb *ccb);
58static void ahciempoll(struct cam_sim *sim);
59static int ahci_em_reset(device_t dev);
60static void ahci_em_led(void *priv, int onoff);
61static void ahci_em_setleds(device_t dev, int c);
62
63static int
64ahci_em_probe(device_t dev)
65{
66
67	device_set_desc_copy(dev, "AHCI enclosure management bridge");
68	return (BUS_PROBE_DEFAULT);
69}
70
71static int
72ahci_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
184err3:
185	xpt_bus_deregister(cam_sim_path(enc->sim));
186err2:
187	cam_sim_free(enc->sim, /*free_devq*/TRUE);
188err1:
189	mtx_unlock(&enc->mtx);
190	if (enc->r_memr)
191		bus_release_resource(dev, SYS_RES_MEMORY, 2, enc->r_memr);
192err0:
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
200static int
201ahci_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
225static int
226ahci_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
246static int
247ahci_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
257static int
258ahci_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
269devclass_t ahciem_devclass;
270static 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};
278static driver_t ahciem_driver = {
279        "ahciem",
280        ahciem_methods,
281        sizeof(struct ahci_enclosure)
282};
283DRIVER_MODULE(ahciem, ahci, ahciem_driver, ahciem_devclass, NULL, NULL);
284
285static void
286ahci_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] & 0x80)		/* Activity */
296		val |= (1 << 0);
297	if (enc->status[c][2] & SESCTL_RQSID)	/* Identification */
298		val |= (1 << 3);
299	else if (enc->status[c][3] & SESCTL_RQSFLT)	/* Fault */
300		val |= (1 << 6);
301	else if (enc->status[c][1] & 0x02)		/* Rebuild */
302		val |= (1 << 6) | (1 << 3);
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
315static void
316ahci_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
346static int
347ahci_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
363static void
364ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
365{
366	struct ahci_enclosure *enc;
367	struct ses_status_page *page;
368	struct ses_status_array_dev_slot *ads, *ads0;
369	struct ses_elm_desc_hdr *elmd;
370	uint8_t *buf;
371	int i;
372
373	enc = device_get_softc(dev);
374	buf = ccb->ataio.data_ptr;
375
376	/* General request validation. */
377	if (ccb->ataio.cmd.command != ATA_SEP_ATTN ||
378	    ccb->ataio.dxfer_len < ccb->ataio.cmd.sector_count * 4) {
379		ccb->ccb_h.status = CAM_REQ_INVALID;
380		goto out;
381	}
382
383	/* SEMB IDENTIFY */
384	if (ccb->ataio.cmd.features == 0xEC &&
385	    ccb->ataio.cmd.sector_count >= 16) {
386		bzero(buf, ccb->ataio.dxfer_len);
387		buf[0] = 64;		/* Valid bytes. */
388		buf[2] = 0x30;		/* NAA Locally Assigned. */
389		strncpy(&buf[3], device_get_nameunit(dev), 7);
390		strncpy(&buf[10], "AHCI    ", SID_VENDOR_SIZE);
391		strncpy(&buf[18], "SGPIO Enclosure ", SID_PRODUCT_SIZE);
392		strncpy(&buf[34], "1.00", SID_REVISION_SIZE);
393		strncpy(&buf[39], "0001", 4);
394		strncpy(&buf[43], "S-E-S ", 6);
395		strncpy(&buf[49], "2.00", 4);
396		ccb->ccb_h.status = CAM_REQ_CMP;
397		goto out;
398	}
399
400	/* SEMB RECEIVE DIAGNOSTIC RESULT (0) */
401	page = (struct ses_status_page *)buf;
402	if (ccb->ataio.cmd.lba_low == 0x02 &&
403	    ccb->ataio.cmd.features == 0x00 &&
404	    ccb->ataio.cmd.sector_count >= 2) {
405		bzero(buf, ccb->ataio.dxfer_len);
406		page->hdr.page_code = 0;
407		scsi_ulto2b(4, page->hdr.length);
408		buf[4] = 0;
409		buf[5] = 1;
410		buf[6] = 2;
411		buf[7] = 7;
412		ccb->ccb_h.status = CAM_REQ_CMP;
413		goto out;
414	}
415
416	/* SEMB RECEIVE DIAGNOSTIC RESULT (1) */
417	if (ccb->ataio.cmd.lba_low == 0x02 &&
418	    ccb->ataio.cmd.features == 0x01 &&
419	    ccb->ataio.cmd.sector_count >= 13) {
420		struct ses_enc_desc *ed;
421		struct ses_elm_type_desc *td;
422
423		bzero(buf, ccb->ataio.dxfer_len);
424		page->hdr.page_code = 0x01;
425		scsi_ulto2b(4 + 4 + 36 + 4, page->hdr.length);
426		ed = (struct ses_enc_desc *)&buf[8];
427		ed->byte0 = 0x11;
428		ed->subenc_id = 0;
429		ed->num_types = 1;
430		ed->length = 36;
431		strncpy(ed->vendor_id, "AHCI    ", SID_VENDOR_SIZE);
432		strncpy(ed->product_id, "SGPIO Enclosure ", SID_PRODUCT_SIZE);
433		strncpy(ed->product_rev, "    ", SID_REVISION_SIZE);
434		td = (struct ses_elm_type_desc *)ses_enc_desc_next(ed);
435		td->etype_elm_type = 0x17;
436		td->etype_maxelt = enc->channels;
437		td->etype_subenc = 0;
438		td->etype_txt_len = 0;
439		ccb->ccb_h.status = CAM_REQ_CMP;
440		goto out;
441	}
442
443	/* SEMB RECEIVE DIAGNOSTIC RESULT (2) */
444	if (ccb->ataio.cmd.lba_low == 0x02 &&
445	    ccb->ataio.cmd.features == 0x02 &&
446	    ccb->ataio.cmd.sector_count >= (3 + enc->channels)) {
447		bzero(buf, ccb->ataio.dxfer_len);
448		page->hdr.page_code = 0x02;
449		scsi_ulto2b(4 + 4 * (1 + enc->channels),
450		    page->hdr.length);
451		for (i = 0; i < enc->channels; i++) {
452			ads = &page->elements[i + 1].array_dev_slot;
453			memcpy(ads, enc->status[i], 4);
454			ads->common.bytes[0] |=
455			    (enc->ichannels & (1 << i)) ?
456			     SES_OBJSTAT_UNKNOWN :
457			     SES_OBJSTAT_NOTINSTALLED;
458		}
459		ccb->ccb_h.status = CAM_REQ_CMP;
460		goto out;
461	}
462
463	/* SEMB SEND DIAGNOSTIC (2) */
464	if (ccb->ataio.cmd.lba_low == 0x82 &&
465	    ccb->ataio.cmd.features == 0x02 &&
466	    ccb->ataio.cmd.sector_count >= (3 + enc->channels)) {
467		ads0 = &page->elements[0].array_dev_slot;
468		for (i = 0; i < enc->channels; i++) {
469			ads = &page->elements[i + 1].array_dev_slot;
470			if (ads->common.bytes[0] & SESCTL_CSEL) {
471				enc->status[i][0] = 0;
472				enc->status[i][1] =
473				    ads->bytes[0] & 0x02;
474				enc->status[i][2] =
475				    ads->bytes[1] & (0x80 | SESCTL_RQSID);
476				enc->status[i][3] =
477				    ads->bytes[2] & SESCTL_RQSFLT;
478				ahci_em_setleds(dev, i);
479			} else if (ads0->common.bytes[0] & SESCTL_CSEL) {
480				enc->status[i][0] = 0;
481				enc->status[i][1] =
482				    ads0->bytes[0] & 0x02;
483				enc->status[i][2] =
484				    ads0->bytes[1] & (0x80 | SESCTL_RQSID);
485				enc->status[i][3] =
486				    ads0->bytes[2] & SESCTL_RQSFLT;
487				ahci_em_setleds(dev, i);
488			}
489		}
490		ccb->ccb_h.status = CAM_REQ_CMP;
491		goto out;
492	}
493
494	/* SEMB RECEIVE DIAGNOSTIC RESULT (7) */
495	if (ccb->ataio.cmd.lba_low == 0x02 &&
496	    ccb->ataio.cmd.features == 0x07 &&
497	    ccb->ataio.cmd.sector_count >= (3 + 3 * enc->channels)) {
498		bzero(buf, ccb->ataio.dxfer_len);
499		page->hdr.page_code = 0x07;
500		scsi_ulto2b(4 + 4 + 12 * enc->channels,
501		    page->hdr.length);
502		for (i = 0; i < enc->channels; i++) {
503			elmd = (struct ses_elm_desc_hdr *)&buf[8 + 4 + 12 * i];
504			scsi_ulto2b(8, elmd->length);
505			snprintf((char *)(elmd + 1), 9, "SLOT %03d", i);
506		}
507		ccb->ccb_h.status = CAM_REQ_CMP;
508		goto out;
509	}
510
511	ccb->ccb_h.status = CAM_REQ_INVALID;
512out:
513	xpt_done(ccb);
514}
515
516static void
517ahci_em_begin_transaction(device_t dev, union ccb *ccb)
518{
519	struct ahci_enclosure *enc;
520	struct ata_res *res;
521
522	enc = device_get_softc(dev);
523	res = &ccb->ataio.res;
524	bzero(res, sizeof(*res));
525	if ((ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) &&
526	    (ccb->ataio.cmd.control & ATA_A_RESET)) {
527		res->lba_high = 0xc3;
528		res->lba_mid = 0x3c;
529		ccb->ccb_h.status = CAM_REQ_CMP;
530		xpt_done(ccb);
531		return;
532	}
533
534	if (enc->capsem & AHCI_EM_LED) {
535		ahci_em_emulate_ses_on_led(dev, ccb);
536		return;
537	} else
538		device_printf(dev, "Unsupported enclosure interface\n");
539
540	ccb->ccb_h.status = CAM_REQ_INVALID;
541	xpt_done(ccb);
542}
543
544static void
545ahciemaction(struct cam_sim *sim, union ccb *ccb)
546{
547	device_t dev, parent;
548	struct ahci_enclosure *enc;
549
550	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
551	    ("ahciemaction func_code=%x\n", ccb->ccb_h.func_code));
552
553	enc = cam_sim_softc(sim);
554	dev = enc->dev;
555	switch (ccb->ccb_h.func_code) {
556	case XPT_ATA_IO:	/* Execute the requested I/O operation */
557		if (ahci_check_ids(ccb))
558			return;
559		ahci_em_begin_transaction(dev, ccb);
560		return;
561	case XPT_RESET_BUS:		/* Reset the specified bus */
562	case XPT_RESET_DEV:	/* Bus Device Reset the specified device */
563		ahci_em_reset(dev);
564		ccb->ccb_h.status = CAM_REQ_CMP;
565		break;
566	case XPT_PATH_INQ:		/* Path routing inquiry */
567	{
568		struct ccb_pathinq *cpi = &ccb->cpi;
569
570		parent = device_get_parent(dev);
571		cpi->version_num = 1; /* XXX??? */
572		cpi->hba_inquiry = PI_SDTR_ABLE;
573		cpi->target_sprt = 0;
574		cpi->hba_misc = PIM_SEQSCAN;
575		cpi->hba_eng_cnt = 0;
576		cpi->max_target = 0;
577		cpi->max_lun = 0;
578		cpi->initiator_id = 0;
579		cpi->bus_id = cam_sim_bus(sim);
580		cpi->base_transfer_speed = 150000;
581		strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
582		strlcpy(cpi->hba_vid, "AHCI", HBA_IDLEN);
583		strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
584		cpi->unit_number = cam_sim_unit(sim);
585		cpi->transport = XPORT_SATA;
586		cpi->transport_version = XPORT_VERSION_UNSPECIFIED;
587		cpi->protocol = PROTO_ATA;
588		cpi->protocol_version = PROTO_VERSION_UNSPECIFIED;
589		cpi->maxio = MAXPHYS;
590		cpi->hba_vendor = pci_get_vendor(parent);
591		cpi->hba_device = pci_get_device(parent);
592		cpi->hba_subvendor = pci_get_subvendor(parent);
593		cpi->hba_subdevice = pci_get_subdevice(parent);
594		cpi->ccb_h.status = CAM_REQ_CMP;
595		break;
596	}
597	default:
598		ccb->ccb_h.status = CAM_REQ_INVALID;
599		break;
600	}
601	xpt_done(ccb);
602}
603
604static void
605ahciempoll(struct cam_sim *sim)
606{
607
608}
609