2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2013 Zhixiang Yu <zcore@freebsd.org>
5 * Copyright (c) 2015-2016 Alexander Motin <mav@FreeBSD.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
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.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
35 #include <sys/param.h>
36 #include <sys/linker_set.h>
39 #include <sys/ioctl.h>
42 #include <sys/endian.h>
54 #include <pthread_np.h>
65 #define DEF_PORTS 6 /* Intel ICH8 AHCI supports 6 ports */
66 #define MAX_PORTS 32 /* AHCI supports 32 ports */
68 #define PxSIG_ATA 0x00000101 /* ATA drive */
69 #define PxSIG_ATAPI 0xeb140101 /* ATAPI drive */
72 FIS_TYPE_REGH2D
= 0x27, /* Register FIS - host to device */
73 FIS_TYPE_REGD2H
= 0x34, /* Register FIS - device to host */
74 FIS_TYPE_DMAACT
= 0x39, /* DMA activate FIS - device to host */
75 FIS_TYPE_DMASETUP
= 0x41, /* DMA setup FIS - bidirectional */
76 FIS_TYPE_DATA
= 0x46, /* Data FIS - bidirectional */
77 FIS_TYPE_BIST
= 0x58, /* BIST activate FIS - bidirectional */
78 FIS_TYPE_PIOSETUP
= 0x5F, /* PIO setup FIS - device to host */
79 FIS_TYPE_SETDEVBITS
= 0xA1, /* Set dev bits FIS - device to host */
85 #define TEST_UNIT_READY 0x00
86 #define REQUEST_SENSE 0x03
88 #define START_STOP_UNIT 0x1B
89 #define PREVENT_ALLOW 0x1E
90 #define READ_CAPACITY 0x25
92 #define POSITION_TO_ELEMENT 0x2B
94 #define GET_EVENT_STATUS_NOTIFICATION 0x4A
95 #define MODE_SENSE_10 0x5A
96 #define REPORT_LUNS 0xA0
101 * SCSI mode page codes
103 #define MODEPAGE_RW_ERROR_RECOVERY 0x01
104 #define MODEPAGE_CD_CAPABILITIES 0x2A
109 #define ATA_SF_ENAB_SATA_SF 0x10
110 #define ATA_SATA_SF_AN 0x05
111 #define ATA_SF_DIS_SATA_SF 0x90
118 #define DPRINTF(format, arg...) do{fprintf(dbg, format, ##arg);fflush(dbg);}while(0)
120 #define DPRINTF(format, arg...)
122 #define WPRINTF(format, arg...) printf(format, ##arg)
124 #define AHCI_PORT_IDENT 20 + 1
127 struct blockif_req io_req
;
128 struct ahci_port
*io_pr
;
129 STAILQ_ENTRY(ahci_ioreq
) io_flist
;
130 TAILQ_ENTRY(ahci_ioreq
) io_blist
;
139 struct blockif_ctxt
*bctx
;
140 struct pci_ahci_softc
*pr_sc
;
141 struct ata_params ata_ident
;
150 uint8_t err_cfis
[20];
177 struct ahci_ioreq
*ioreq
;
179 STAILQ_HEAD(ahci_fhead
, ahci_ioreq
) iofhd
;
180 TAILQ_HEAD(ahci_bhead
, ahci_ioreq
) iobhd
;
183 struct ahci_cmd_hdr
{
188 uint32_t reserved
[4];
191 struct ahci_prdt_entry
{
194 #define DBCMASK 0x3fffff
198 struct pci_ahci_softc
{
199 struct pci_devinst
*asc_pi
;
214 struct ahci_port port
[MAX_PORTS
];
216 #define ahci_ctx(sc) ((sc)->asc_pi->pi_vmctx)
218 static void ahci_handle_port(struct ahci_port
*p
);
220 static inline void lba_to_msf(uint8_t *buf
, int lba
)
223 buf
[0] = (lba
/ 75) / 60;
224 buf
[1] = (lba
/ 75) % 60;
229 * Generate HBA interrupts on global IS register write.
232 ahci_generate_intr(struct pci_ahci_softc
*sc
, uint32_t mask
)
234 struct pci_devinst
*pi
= sc
->asc_pi
;
239 /* Update global IS from PxIS/PxIE. */
240 for (i
= 0; i
< sc
->ports
; i
++) {
245 DPRINTF("%s(%08x) %08x", __func__
, mask
, sc
->is
);
247 /* If there is nothing enabled -- clear legacy interrupt and exit. */
248 if (sc
->is
== 0 || (sc
->ghc
& AHCI_GHC_IE
) == 0) {
250 pci_lintr_deassert(pi
);
256 /* If there is anything and no MSI -- assert legacy interrupt. */
257 nmsg
= pci_msi_maxmsgnum(pi
);
261 pci_lintr_assert(pi
);
266 /* Assert respective MSIs for ports that were touched. */
267 for (i
= 0; i
< nmsg
; i
++) {
268 if (sc
->ports
<= nmsg
|| i
< nmsg
- 1)
271 mmask
= 0xffffffff << i
;
272 if (sc
->is
& mask
&& mmask
& mask
)
273 pci_generate_msi(pi
, i
);
278 * Generate HBA interrupt on specific port event.
281 ahci_port_intr(struct ahci_port
*p
)
283 struct pci_ahci_softc
*sc
= p
->pr_sc
;
284 struct pci_devinst
*pi
= sc
->asc_pi
;
287 DPRINTF("%s(%d) %08x/%08x %08x", __func__
,
288 p
->port
, p
->is
, p
->ie
, sc
->is
);
290 /* If there is nothing enabled -- we are done. */
291 if ((p
->is
& p
->ie
) == 0)
294 /* In case of non-shared MSI always generate interrupt. */
295 nmsg
= pci_msi_maxmsgnum(pi
);
296 if (sc
->ports
<= nmsg
|| p
->port
< nmsg
- 1) {
297 sc
->is
|= (1 << p
->port
);
298 if ((sc
->ghc
& AHCI_GHC_IE
) == 0)
300 pci_generate_msi(pi
, p
->port
);
304 /* If IS for this port is already set -- do nothing. */
305 if (sc
->is
& (1 << p
->port
))
308 sc
->is
|= (1 << p
->port
);
310 /* If interrupts are enabled -- generate one. */
311 if ((sc
->ghc
& AHCI_GHC_IE
) == 0)
314 pci_generate_msi(pi
, nmsg
- 1);
315 } else if (!sc
->lintr
) {
317 pci_lintr_assert(pi
);
322 ahci_write_fis(struct ahci_port
*p
, enum sata_fis_type ft
, uint8_t *fis
)
324 int offset
, len
, irq
;
326 if (p
->rfis
== NULL
|| !(p
->cmd
& AHCI_P_CMD_FRE
))
330 case FIS_TYPE_REGD2H
:
333 irq
= (fis
[1] & (1 << 6)) ? AHCI_P_IX_DHR
: 0;
335 case FIS_TYPE_SETDEVBITS
:
338 irq
= (fis
[1] & (1 << 6)) ? AHCI_P_IX_SDB
: 0;
340 case FIS_TYPE_PIOSETUP
:
343 irq
= (fis
[1] & (1 << 6)) ? AHCI_P_IX_PS
: 0;
346 WPRINTF("unsupported fis type %d", ft
);
349 if (fis
[2] & ATA_S_ERROR
) {
351 irq
|= AHCI_P_IX_TFE
;
353 memcpy(p
->rfis
+ offset
, fis
, len
);
363 ahci_write_fis_piosetup(struct ahci_port
*p
)
367 memset(fis
, 0, sizeof(fis
));
368 fis
[0] = FIS_TYPE_PIOSETUP
;
369 ahci_write_fis(p
, FIS_TYPE_PIOSETUP
, fis
);
373 ahci_write_fis_sdb(struct ahci_port
*p
, int slot
, uint8_t *cfis
, uint32_t tfd
)
378 error
= (tfd
>> 8) & 0xff;
380 memset(fis
, 0, sizeof(fis
));
381 fis
[0] = FIS_TYPE_SETDEVBITS
;
385 if (fis
[2] & ATA_S_ERROR
) {
386 p
->err_cfis
[0] = slot
;
387 p
->err_cfis
[2] = tfd
;
388 p
->err_cfis
[3] = error
;
389 memcpy(&p
->err_cfis
[4], cfis
+ 4, 16);
391 *(uint32_t *)(fis
+ 4) = (1 << slot
);
392 p
->sact
&= ~(1 << slot
);
396 ahci_write_fis(p
, FIS_TYPE_SETDEVBITS
, fis
);
400 ahci_write_fis_d2h(struct ahci_port
*p
, int slot
, uint8_t *cfis
, uint32_t tfd
)
405 error
= (tfd
>> 8) & 0xff;
406 memset(fis
, 0, sizeof(fis
));
407 fis
[0] = FIS_TYPE_REGD2H
;
421 if (fis
[2] & ATA_S_ERROR
) {
422 p
->err_cfis
[0] = 0x80;
423 p
->err_cfis
[2] = tfd
& 0xff;
424 p
->err_cfis
[3] = error
;
425 memcpy(&p
->err_cfis
[4], cfis
+ 4, 16);
427 p
->ci
&= ~(1 << slot
);
429 ahci_write_fis(p
, FIS_TYPE_REGD2H
, fis
);
433 ahci_write_fis_d2h_ncq(struct ahci_port
*p
, int slot
)
437 p
->tfd
= ATA_S_READY
| ATA_S_DSC
;
438 memset(fis
, 0, sizeof(fis
));
439 fis
[0] = FIS_TYPE_REGD2H
;
440 fis
[1] = 0; /* No interrupt */
441 fis
[2] = p
->tfd
; /* Status */
442 fis
[3] = 0; /* No error */
443 p
->ci
&= ~(1 << slot
);
444 ahci_write_fis(p
, FIS_TYPE_REGD2H
, fis
);
448 ahci_write_reset_fis_d2h(struct ahci_port
*p
)
452 memset(fis
, 0, sizeof(fis
));
453 fis
[0] = FIS_TYPE_REGD2H
;
461 ahci_write_fis(p
, FIS_TYPE_REGD2H
, fis
);
465 ahci_check_stopped(struct ahci_port
*p
)
468 * If we are no longer processing the command list and nothing
469 * is in-flight, clear the running bit, the current command
470 * slot, the command issue and active bits.
472 if (!(p
->cmd
& AHCI_P_CMD_ST
)) {
473 if (p
->pending
== 0) {
475 p
->cmd
&= ~(AHCI_P_CMD_CR
| AHCI_P_CMD_CCS_MASK
);
484 ahci_port_stop(struct ahci_port
*p
)
486 struct ahci_ioreq
*aior
;
491 assert(pthread_mutex_isowned_np(&p
->pr_sc
->mtx
));
493 TAILQ_FOREACH(aior
, &p
->iobhd
, io_blist
) {
495 * Try to cancel the outstanding blockif request.
497 error
= blockif_cancel(p
->bctx
, &aior
->io_req
);
503 if (cfis
[2] == ATA_WRITE_FPDMA_QUEUED
||
504 cfis
[2] == ATA_READ_FPDMA_QUEUED
||
505 cfis
[2] == ATA_SEND_FPDMA_QUEUED
)
506 p
->sact
&= ~(1 << slot
); /* NCQ */
508 p
->ci
&= ~(1 << slot
);
511 * This command is now done.
513 p
->pending
&= ~(1 << slot
);
516 * Delete the blockif request from the busy list
518 TAILQ_REMOVE(&p
->iobhd
, aior
, io_blist
);
521 * Move the blockif request back to the free list
523 STAILQ_INSERT_TAIL(&p
->iofhd
, aior
, io_flist
);
526 ahci_check_stopped(p
);
530 ahci_port_reset(struct ahci_port
*pr
)
534 pr
->xfermode
= ATA_UDMA6
;
535 pr
->mult_sectors
= 128;
538 pr
->ssts
= ATA_SS_DET_NO_DEVICE
;
539 pr
->sig
= 0xFFFFFFFF;
543 pr
->ssts
= ATA_SS_DET_PHY_ONLINE
| ATA_SS_IPM_ACTIVE
;
544 if (pr
->sctl
& ATA_SC_SPD_MASK
)
545 pr
->ssts
|= (pr
->sctl
& ATA_SC_SPD_MASK
);
547 pr
->ssts
|= ATA_SS_SPD_GEN3
;
548 pr
->tfd
= (1 << 8) | ATA_S_DSC
| ATA_S_DMA
;
551 pr
->tfd
|= ATA_S_READY
;
553 pr
->sig
= PxSIG_ATAPI
;
554 ahci_write_reset_fis_d2h(pr
);
558 ahci_reset(struct pci_ahci_softc
*sc
)
562 sc
->ghc
= AHCI_GHC_AE
;
566 pci_lintr_deassert(sc
->asc_pi
);
570 for (i
= 0; i
< sc
->ports
; i
++) {
573 sc
->port
[i
].cmd
= (AHCI_P_CMD_SUD
| AHCI_P_CMD_POD
);
574 if (sc
->port
[i
].bctx
)
575 sc
->port
[i
].cmd
|= AHCI_P_CMD_CPS
;
576 sc
->port
[i
].sctl
= 0;
577 ahci_port_reset(&sc
->port
[i
]);
582 ata_string(uint8_t *dest
, const char *src
, int len
)
586 for (i
= 0; i
< len
; i
++) {
588 dest
[i
^ 1] = *src
++;
595 atapi_string(uint8_t *dest
, const char *src
, int len
)
599 for (i
= 0; i
< len
; i
++) {
608 * Build up the iovec based on the PRDT, 'done' and 'len'.
611 ahci_build_iov(struct ahci_port
*p
, struct ahci_ioreq
*aior
,
612 struct ahci_prdt_entry
*prdt
, uint16_t prdtl
)
614 struct blockif_req
*breq
= &aior
->io_req
;
615 uint32_t dbcsz
, extra
, left
, skip
, todo
;
618 assert(aior
->len
>= aior
->done
);
620 /* Copy part of PRDT between 'done' and 'len' bytes into the iov. */
622 left
= aior
->len
- aior
->done
;
624 for (i
= 0, j
= 0; i
< prdtl
&& j
< BLOCKIF_IOV_MAX
&& left
> 0;
626 dbcsz
= (prdt
->dbc
& DBCMASK
) + 1;
627 /* Skip already done part of the PRDT */
635 breq
->br_iov
[j
].iov_base
= paddr_guest2host(ahci_ctx(p
->pr_sc
),
636 prdt
->dba
+ skip
, dbcsz
);
637 breq
->br_iov
[j
].iov_len
= dbcsz
;
644 /* If we got limited by IOV length, round I/O down to sector size. */
645 if (j
== BLOCKIF_IOV_MAX
) {
646 extra
= todo
% blockif_sectsz(p
->bctx
);
650 if (breq
->br_iov
[j
- 1].iov_len
> extra
) {
651 breq
->br_iov
[j
- 1].iov_len
-= extra
;
654 extra
-= breq
->br_iov
[j
- 1].iov_len
;
660 breq
->br_resid
= todo
;
662 aior
->more
= (aior
->done
< aior
->len
&& i
< prdtl
);
666 ahci_handle_rw(struct ahci_port
*p
, int slot
, uint8_t *cfis
, uint32_t done
)
668 struct ahci_ioreq
*aior
;
669 struct blockif_req
*breq
;
670 struct ahci_prdt_entry
*prdt
;
671 struct ahci_cmd_hdr
*hdr
;
674 int err
, first
, ncq
, readop
;
676 prdt
= (struct ahci_prdt_entry
*)(cfis
+ 0x80);
677 hdr
= (struct ahci_cmd_hdr
*)(p
->cmd_lst
+ slot
* AHCI_CL_SIZE
);
682 if (cfis
[2] == ATA_WRITE
|| cfis
[2] == ATA_WRITE48
||
683 cfis
[2] == ATA_WRITE_MUL
|| cfis
[2] == ATA_WRITE_MUL48
||
684 cfis
[2] == ATA_WRITE_DMA
|| cfis
[2] == ATA_WRITE_DMA48
||
685 cfis
[2] == ATA_WRITE_FPDMA_QUEUED
)
688 if (cfis
[2] == ATA_WRITE_FPDMA_QUEUED
||
689 cfis
[2] == ATA_READ_FPDMA_QUEUED
) {
690 lba
= ((uint64_t)cfis
[10] << 40) |
691 ((uint64_t)cfis
[9] << 32) |
692 ((uint64_t)cfis
[8] << 24) |
693 ((uint64_t)cfis
[6] << 16) |
694 ((uint64_t)cfis
[5] << 8) |
696 len
= cfis
[11] << 8 | cfis
[3];
700 } else if (cfis
[2] == ATA_READ48
|| cfis
[2] == ATA_WRITE48
||
701 cfis
[2] == ATA_READ_MUL48
|| cfis
[2] == ATA_WRITE_MUL48
||
702 cfis
[2] == ATA_READ_DMA48
|| cfis
[2] == ATA_WRITE_DMA48
) {
703 lba
= ((uint64_t)cfis
[10] << 40) |
704 ((uint64_t)cfis
[9] << 32) |
705 ((uint64_t)cfis
[8] << 24) |
706 ((uint64_t)cfis
[6] << 16) |
707 ((uint64_t)cfis
[5] << 8) |
709 len
= cfis
[13] << 8 | cfis
[12];
713 lba
= ((cfis
[7] & 0xf) << 24) | (cfis
[6] << 16) |
714 (cfis
[5] << 8) | cfis
[4];
719 lba
*= blockif_sectsz(p
->bctx
);
720 len
*= blockif_sectsz(p
->bctx
);
722 /* Pull request off free list */
723 aior
= STAILQ_FIRST(&p
->iofhd
);
724 assert(aior
!= NULL
);
725 STAILQ_REMOVE_HEAD(&p
->iofhd
, io_flist
);
731 breq
= &aior
->io_req
;
732 breq
->br_offset
= lba
+ done
;
733 ahci_build_iov(p
, aior
, prdt
, hdr
->prdtl
);
735 /* Mark this command in-flight. */
736 p
->pending
|= 1 << slot
;
738 /* Stuff request onto busy list. */
739 TAILQ_INSERT_HEAD(&p
->iobhd
, aior
, io_blist
);
742 ahci_write_fis_d2h_ncq(p
, slot
);
745 err
= blockif_read(p
->bctx
, breq
);
747 err
= blockif_write(p
->bctx
, breq
);
752 ahci_handle_flush(struct ahci_port
*p
, int slot
, uint8_t *cfis
)
754 struct ahci_ioreq
*aior
;
755 struct blockif_req
*breq
;
759 * Pull request off free list
761 aior
= STAILQ_FIRST(&p
->iofhd
);
762 assert(aior
!= NULL
);
763 STAILQ_REMOVE_HEAD(&p
->iofhd
, io_flist
);
769 breq
= &aior
->io_req
;
772 * Mark this command in-flight.
774 p
->pending
|= 1 << slot
;
777 * Stuff request onto busy list
779 TAILQ_INSERT_HEAD(&p
->iobhd
, aior
, io_blist
);
781 err
= blockif_flush(p
->bctx
, breq
);
786 read_prdt(struct ahci_port
*p
, int slot
, uint8_t *cfis
, void *buf
,
789 struct ahci_cmd_hdr
*hdr
;
790 struct ahci_prdt_entry
*prdt
;
795 hdr
= (struct ahci_cmd_hdr
*)(p
->cmd_lst
+ slot
* AHCI_CL_SIZE
);
798 prdt
= (struct ahci_prdt_entry
*)(cfis
+ 0x80);
799 for (i
= 0; i
< hdr
->prdtl
&& len
; i
++) {
804 dbcsz
= (prdt
->dbc
& DBCMASK
) + 1;
805 ptr
= paddr_guest2host(ahci_ctx(p
->pr_sc
), prdt
->dba
, dbcsz
);
806 sublen
= MIN(len
, dbcsz
);
807 memcpy(to
, ptr
, sublen
);
815 ahci_handle_dsm_trim(struct ahci_port
*p
, int slot
, uint8_t *cfis
, uint32_t done
)
817 struct ahci_ioreq
*aior
;
818 struct blockif_req
*breq
;
826 if (cfis
[2] == ATA_DATA_SET_MANAGEMENT
) {
827 len
= (uint16_t)cfis
[13] << 8 | cfis
[12];
830 } else { /* ATA_SEND_FPDMA_QUEUED */
831 len
= (uint16_t)cfis
[11] << 8 | cfis
[3];
835 read_prdt(p
, slot
, cfis
, buf
, sizeof(buf
));
839 elba
= ((uint64_t)entry
[5] << 40) |
840 ((uint64_t)entry
[4] << 32) |
841 ((uint64_t)entry
[3] << 24) |
842 ((uint64_t)entry
[2] << 16) |
843 ((uint64_t)entry
[1] << 8) |
845 elen
= (uint16_t)entry
[7] << 8 | entry
[6];
851 ahci_write_fis_d2h_ncq(p
, slot
);
852 ahci_write_fis_sdb(p
, slot
, cfis
,
853 ATA_S_READY
| ATA_S_DSC
);
855 ahci_write_fis_d2h(p
, slot
, cfis
,
856 ATA_S_READY
| ATA_S_DSC
);
858 p
->pending
&= ~(1 << slot
);
859 ahci_check_stopped(p
);
868 * Pull request off free list
870 aior
= STAILQ_FIRST(&p
->iofhd
);
871 assert(aior
!= NULL
);
872 STAILQ_REMOVE_HEAD(&p
->iofhd
, io_flist
);
877 aior
->more
= (len
!= done
);
879 breq
= &aior
->io_req
;
880 breq
->br_offset
= elba
* blockif_sectsz(p
->bctx
);
881 breq
->br_resid
= elen
* blockif_sectsz(p
->bctx
);
884 * Mark this command in-flight.
886 p
->pending
|= 1 << slot
;
889 * Stuff request onto busy list
891 TAILQ_INSERT_HEAD(&p
->iobhd
, aior
, io_blist
);
894 ahci_write_fis_d2h_ncq(p
, slot
);
896 err
= blockif_delete(p
->bctx
, breq
);
901 write_prdt(struct ahci_port
*p
, int slot
, uint8_t *cfis
, void *buf
,
904 struct ahci_cmd_hdr
*hdr
;
905 struct ahci_prdt_entry
*prdt
;
910 hdr
= (struct ahci_cmd_hdr
*)(p
->cmd_lst
+ slot
* AHCI_CL_SIZE
);
913 prdt
= (struct ahci_prdt_entry
*)(cfis
+ 0x80);
914 for (i
= 0; i
< hdr
->prdtl
&& len
; i
++) {
919 dbcsz
= (prdt
->dbc
& DBCMASK
) + 1;
920 ptr
= paddr_guest2host(ahci_ctx(p
->pr_sc
), prdt
->dba
, dbcsz
);
921 sublen
= MIN(len
, dbcsz
);
922 memcpy(ptr
, from
, sublen
);
927 hdr
->prdbc
= size
- len
;
931 ahci_checksum(uint8_t *buf
, int size
)
936 for (i
= 0; i
< size
- 1; i
++)
938 buf
[size
- 1] = 0x100 - sum
;
942 ahci_handle_read_log(struct ahci_port
*p
, int slot
, uint8_t *cfis
)
944 struct ahci_cmd_hdr
*hdr
;
946 uint8_t *buf8
= (uint8_t *)buf
;
947 uint16_t *buf16
= (uint16_t *)buf
;
949 hdr
= (struct ahci_cmd_hdr
*)(p
->cmd_lst
+ slot
* AHCI_CL_SIZE
);
950 if (p
->atapi
|| hdr
->prdtl
== 0 || cfis
[5] != 0 ||
951 cfis
[9] != 0 || cfis
[12] != 1 || cfis
[13] != 0) {
952 ahci_write_fis_d2h(p
, slot
, cfis
,
953 (ATA_E_ABORT
<< 8) | ATA_S_READY
| ATA_S_ERROR
);
957 memset(buf
, 0, sizeof(buf
));
958 if (cfis
[4] == 0x00) { /* Log directory */
959 buf16
[0x00] = 1; /* Version -- 1 */
960 buf16
[0x10] = 1; /* NCQ Command Error Log -- 1 page */
961 buf16
[0x13] = 1; /* SATA NCQ Send and Receive Log -- 1 page */
962 } else if (cfis
[4] == 0x10) { /* NCQ Command Error Log */
963 memcpy(buf8
, p
->err_cfis
, sizeof(p
->err_cfis
));
964 ahci_checksum(buf8
, sizeof(buf
));
965 } else if (cfis
[4] == 0x13) { /* SATA NCQ Send and Receive Log */
966 if (blockif_candelete(p
->bctx
) && !blockif_is_ro(p
->bctx
)) {
967 buf
[0x00] = 1; /* SFQ DSM supported */
968 buf
[0x01] = 1; /* SFQ DSM TRIM supported */
971 ahci_write_fis_d2h(p
, slot
, cfis
,
972 (ATA_E_ABORT
<< 8) | ATA_S_READY
| ATA_S_ERROR
);
976 if (cfis
[2] == ATA_READ_LOG_EXT
)
977 ahci_write_fis_piosetup(p
);
978 write_prdt(p
, slot
, cfis
, (void *)buf
, sizeof(buf
));
979 ahci_write_fis_d2h(p
, slot
, cfis
, ATA_S_DSC
| ATA_S_READY
);
983 handle_identify(struct ahci_port
*p
, int slot
, uint8_t *cfis
)
985 struct ahci_cmd_hdr
*hdr
;
987 hdr
= (struct ahci_cmd_hdr
*)(p
->cmd_lst
+ slot
* AHCI_CL_SIZE
);
988 if (p
->atapi
|| hdr
->prdtl
== 0) {
989 ahci_write_fis_d2h(p
, slot
, cfis
,
990 (ATA_E_ABORT
<< 8) | ATA_S_READY
| ATA_S_ERROR
);
992 ahci_write_fis_piosetup(p
);
993 write_prdt(p
, slot
, cfis
, (void*)&p
->ata_ident
, sizeof(struct ata_params
));
994 ahci_write_fis_d2h(p
, slot
, cfis
, ATA_S_DSC
| ATA_S_READY
);
999 ata_identify_init(struct ahci_port
* p
, int atapi
)
1001 struct ata_params
* ata_ident
= &p
->ata_ident
;
1004 ata_ident
->config
= ATA_PROTO_ATAPI
| ATA_ATAPI_TYPE_CDROM
|
1005 ATA_ATAPI_REMOVABLE
| ATA_DRQ_FAST
;
1006 ata_ident
->capabilities1
= ATA_SUPPORT_LBA
|
1008 ata_ident
->capabilities2
= (1 << 14 | 1);
1009 ata_ident
->atavalid
= ATA_FLAG_64_70
| ATA_FLAG_88
;
1010 ata_ident
->obsolete62
= 0x3f;
1011 ata_ident
->mwdmamodes
= 7;
1012 if (p
->xfermode
& ATA_WDMA0
)
1013 ata_ident
->mwdmamodes
|= (1 << ((p
->xfermode
& 7) + 8));
1014 ata_ident
->apiomodes
= 3;
1015 ata_ident
->mwdmamin
= 0x0078;
1016 ata_ident
->mwdmarec
= 0x0078;
1017 ata_ident
->pioblind
= 0x0078;
1018 ata_ident
->pioiordy
= 0x0078;
1019 ata_ident
->satacapabilities
= (ATA_SATA_GEN1
| ATA_SATA_GEN2
| ATA_SATA_GEN3
);
1020 ata_ident
->satacapabilities2
= ((p
->ssts
& ATA_SS_SPD_MASK
) >> 3);
1021 ata_ident
->satasupport
= ATA_SUPPORT_NCQ_STREAM
;
1022 ata_ident
->version_major
= 0x3f0;
1023 ata_ident
->support
.command1
= (ATA_SUPPORT_POWERMGT
| ATA_SUPPORT_PACKET
|
1024 ATA_SUPPORT_RESET
| ATA_SUPPORT_NOP
);
1025 ata_ident
->support
.command2
= (1 << 14);
1026 ata_ident
->support
.extension
= (1 << 14);
1027 ata_ident
->enabled
.command1
= (ATA_SUPPORT_POWERMGT
| ATA_SUPPORT_PACKET
|
1028 ATA_SUPPORT_RESET
| ATA_SUPPORT_NOP
);
1029 ata_ident
->enabled
.extension
= (1 << 14);
1030 ata_ident
->udmamodes
= 0x7f;
1031 if (p
->xfermode
& ATA_UDMA0
)
1032 ata_ident
->udmamodes
|= (1 << ((p
->xfermode
& 7) + 8));
1033 ata_ident
->transport_major
= 0x1020;
1034 ata_ident
->integrity
= 0x00a5;
1037 int sectsz
, psectsz
, psectoff
, candelete
, ro
;
1039 uint8_t sech
, heads
;
1041 ro
= blockif_is_ro(p
->bctx
);
1042 candelete
= blockif_candelete(p
->bctx
);
1043 sectsz
= blockif_sectsz(p
->bctx
);
1044 sectors
= blockif_size(p
->bctx
) / sectsz
;
1045 blockif_chs(p
->bctx
, &cyl
, &heads
, &sech
);
1046 blockif_psectsz(p
->bctx
, &psectsz
, &psectoff
);
1047 ata_ident
->config
= ATA_DRQ_FAST
;
1048 ata_ident
->cylinders
= cyl
;
1049 ata_ident
->heads
= heads
;
1050 ata_ident
->sectors
= sech
;
1052 ata_ident
->sectors_intr
= (0x8000 | 128);
1055 ata_ident
->capabilities1
= ATA_SUPPORT_DMA
|
1056 ATA_SUPPORT_LBA
| ATA_SUPPORT_IORDY
;
1057 ata_ident
->capabilities2
= (1 << 14);
1058 ata_ident
->atavalid
= ATA_FLAG_64_70
| ATA_FLAG_88
;
1059 if (p
->mult_sectors
)
1060 ata_ident
->multi
= (ATA_MULTI_VALID
| p
->mult_sectors
);
1061 if (sectors
<= 0x0fffffff) {
1062 ata_ident
->lba_size_1
= sectors
;
1063 ata_ident
->lba_size_2
= (sectors
>> 16);
1065 ata_ident
->lba_size_1
= 0xffff;
1066 ata_ident
->lba_size_2
= 0x0fff;
1068 ata_ident
->mwdmamodes
= 0x7;
1069 if (p
->xfermode
& ATA_WDMA0
)
1070 ata_ident
->mwdmamodes
|= (1 << ((p
->xfermode
& 7) + 8));
1071 ata_ident
->apiomodes
= 0x3;
1072 ata_ident
->mwdmamin
= 0x0078;
1073 ata_ident
->mwdmarec
= 0x0078;
1074 ata_ident
->pioblind
= 0x0078;
1075 ata_ident
->pioiordy
= 0x0078;
1076 ata_ident
->support3
= 0;
1077 ata_ident
->queue
= 31;
1078 ata_ident
->satacapabilities
= (ATA_SATA_GEN1
| ATA_SATA_GEN2
| ATA_SATA_GEN3
|
1080 ata_ident
->satacapabilities2
= (ATA_SUPPORT_RCVSND_FPDMA_QUEUED
|
1081 (p
->ssts
& ATA_SS_SPD_MASK
) >> 3);
1082 ata_ident
->version_major
= 0x3f0;
1083 ata_ident
->version_minor
= 0x28;
1084 ata_ident
->support
.command1
= (ATA_SUPPORT_POWERMGT
| ATA_SUPPORT_WRITECACHE
|
1085 ATA_SUPPORT_LOOKAHEAD
| ATA_SUPPORT_NOP
);
1086 ata_ident
->support
.command2
= (ATA_SUPPORT_ADDRESS48
| ATA_SUPPORT_FLUSHCACHE
|
1087 ATA_SUPPORT_FLUSHCACHE48
| 1 << 14);
1088 ata_ident
->support
.extension
= (1 << 14);
1089 ata_ident
->enabled
.command1
= (ATA_SUPPORT_POWERMGT
| ATA_SUPPORT_WRITECACHE
|
1090 ATA_SUPPORT_LOOKAHEAD
| ATA_SUPPORT_NOP
);
1091 ata_ident
->enabled
.command2
= (ATA_SUPPORT_ADDRESS48
| ATA_SUPPORT_FLUSHCACHE
|
1092 ATA_SUPPORT_FLUSHCACHE48
| 1 << 15);
1093 ata_ident
->enabled
.extension
= (1 << 14);
1094 ata_ident
->udmamodes
= 0x7f;
1095 if (p
->xfermode
& ATA_UDMA0
)
1096 ata_ident
->udmamodes
|= (1 << ((p
->xfermode
& 7) + 8));
1097 ata_ident
->lba_size48_1
= sectors
;
1098 ata_ident
->lba_size48_2
= (sectors
>> 16);
1099 ata_ident
->lba_size48_3
= (sectors
>> 32);
1100 ata_ident
->lba_size48_4
= (sectors
>> 48);
1102 if (candelete
&& !ro
) {
1103 ata_ident
->support3
|= ATA_SUPPORT_RZAT
| ATA_SUPPORT_DRAT
;
1104 ata_ident
->max_dsm_blocks
= 1;
1105 ata_ident
->support_dsm
= ATA_SUPPORT_DSM_TRIM
;
1107 ata_ident
->pss
= ATA_PSS_VALID_VALUE
;
1108 ata_ident
->lsalign
= 0x4000;
1109 if (psectsz
> sectsz
) {
1110 ata_ident
->pss
|= ATA_PSS_MULTLS
;
1111 ata_ident
->pss
|= ffsl(psectsz
/ sectsz
) - 1;
1112 ata_ident
->lsalign
|= (psectoff
/ sectsz
);
1115 ata_ident
->pss
|= ATA_PSS_LSSABOVE512
;
1116 ata_ident
->lss_1
= sectsz
/ 2;
1117 ata_ident
->lss_2
= ((sectsz
/ 2) >> 16);
1119 ata_ident
->support2
= (ATA_SUPPORT_RWLOGDMAEXT
| 1 << 14);
1120 ata_ident
->enabled2
= (ATA_SUPPORT_RWLOGDMAEXT
| 1 << 14);
1121 ata_ident
->transport_major
= 0x1020;
1122 ata_ident
->integrity
= 0x00a5;
1124 ahci_checksum((uint8_t*)ata_ident
, sizeof(struct ata_params
));
1128 handle_atapi_identify(struct ahci_port
*p
, int slot
, uint8_t *cfis
)
1131 ahci_write_fis_d2h(p
, slot
, cfis
,
1132 (ATA_E_ABORT
<< 8) | ATA_S_READY
| ATA_S_ERROR
);
1134 ahci_write_fis_piosetup(p
);
1135 write_prdt(p
, slot
, cfis
, (void *)&p
->ata_ident
, sizeof(struct ata_params
));
1136 ahci_write_fis_d2h(p
, slot
, cfis
, ATA_S_DSC
| ATA_S_READY
);
1141 atapi_inquiry(struct ahci_port
*p
, int slot
, uint8_t *cfis
)
1150 if (acmd
[1] & 1) { /* VPD */
1151 if (acmd
[2] == 0) { /* Supported VPD pages */
1159 p
->sense_key
= ATA_SENSE_ILLEGAL_REQUEST
;
1161 tfd
= (p
->sense_key
<< 12) | ATA_S_READY
| ATA_S_ERROR
;
1162 cfis
[4] = (cfis
[4] & ~7) | ATA_I_CMD
| ATA_I_IN
;
1163 ahci_write_fis_d2h(p
, slot
, cfis
, tfd
);
1175 atapi_string(buf
+ 8, "BHYVE", 8);
1176 atapi_string(buf
+ 16, "BHYVE DVD-ROM", 16);
1177 atapi_string(buf
+ 32, "001", 4);
1183 cfis
[4] = (cfis
[4] & ~7) | ATA_I_CMD
| ATA_I_IN
;
1184 write_prdt(p
, slot
, cfis
, buf
, len
);
1185 ahci_write_fis_d2h(p
, slot
, cfis
, ATA_S_READY
| ATA_S_DSC
);
1189 atapi_read_capacity(struct ahci_port
*p
, int slot
, uint8_t *cfis
)
1194 sectors
= blockif_size(p
->bctx
) / 2048;
1195 be32enc(buf
, sectors
- 1);
1196 be32enc(buf
+ 4, 2048);
1197 cfis
[4] = (cfis
[4] & ~7) | ATA_I_CMD
| ATA_I_IN
;
1198 write_prdt(p
, slot
, cfis
, buf
, sizeof(buf
));
1199 ahci_write_fis_d2h(p
, slot
, cfis
, ATA_S_READY
| ATA_S_DSC
);
1203 atapi_read_toc(struct ahci_port
*p
, int slot
, uint8_t *cfis
)
1211 len
= be16dec(acmd
+ 7);
1212 format
= acmd
[9] >> 6;
1219 uint8_t start_track
, buf
[20], *bp
;
1221 msf
= (acmd
[1] >> 1) & 1;
1222 start_track
= acmd
[6];
1223 if (start_track
> 1 && start_track
!= 0xaa) {
1225 p
->sense_key
= ATA_SENSE_ILLEGAL_REQUEST
;
1227 tfd
= (p
->sense_key
<< 12) | ATA_S_READY
| ATA_S_ERROR
;
1228 cfis
[4] = (cfis
[4] & ~7) | ATA_I_CMD
| ATA_I_IN
;
1229 ahci_write_fis_d2h(p
, slot
, cfis
, tfd
);
1235 if (start_track
<= 1) {
1255 sectors
= blockif_size(p
->bctx
) / blockif_sectsz(p
->bctx
);
1259 lba_to_msf(bp
, sectors
);
1262 be32enc(bp
, sectors
);
1266 be16enc(buf
, size
- 2);
1269 write_prdt(p
, slot
, cfis
, buf
, len
);
1270 cfis
[4] = (cfis
[4] & ~7) | ATA_I_CMD
| ATA_I_IN
;
1271 ahci_write_fis_d2h(p
, slot
, cfis
, ATA_S_READY
| ATA_S_DSC
);
1278 memset(buf
, 0, sizeof(buf
));
1282 if (len
> sizeof(buf
))
1284 write_prdt(p
, slot
, cfis
, buf
, len
);
1285 cfis
[4] = (cfis
[4] & ~7) | ATA_I_CMD
| ATA_I_IN
;
1286 ahci_write_fis_d2h(p
, slot
, cfis
, ATA_S_READY
| ATA_S_DSC
);
1294 uint8_t *bp
, buf
[50];
1296 msf
= (acmd
[1] >> 1) & 1;
1332 sectors
= blockif_size(p
->bctx
) / blockif_sectsz(p
->bctx
);
1336 lba_to_msf(bp
, sectors
);
1339 be32enc(bp
, sectors
);
1362 be16enc(buf
, size
- 2);
1365 write_prdt(p
, slot
, cfis
, buf
, len
);
1366 cfis
[4] = (cfis
[4] & ~7) | ATA_I_CMD
| ATA_I_IN
;
1367 ahci_write_fis_d2h(p
, slot
, cfis
, ATA_S_READY
| ATA_S_DSC
);
1374 p
->sense_key
= ATA_SENSE_ILLEGAL_REQUEST
;
1376 tfd
= (p
->sense_key
<< 12) | ATA_S_READY
| ATA_S_ERROR
;
1377 cfis
[4] = (cfis
[4] & ~7) | ATA_I_CMD
| ATA_I_IN
;
1378 ahci_write_fis_d2h(p
, slot
, cfis
, tfd
);
1385 atapi_report_luns(struct ahci_port
*p
, int slot
, uint8_t *cfis
)
1389 memset(buf
, 0, sizeof(buf
));
1392 cfis
[4] = (cfis
[4] & ~7) | ATA_I_CMD
| ATA_I_IN
;
1393 write_prdt(p
, slot
, cfis
, buf
, sizeof(buf
));
1394 ahci_write_fis_d2h(p
, slot
, cfis
, ATA_S_READY
| ATA_S_DSC
);
1398 atapi_read(struct ahci_port
*p
, int slot
, uint8_t *cfis
, uint32_t done
)
1400 struct ahci_ioreq
*aior
;
1401 struct ahci_cmd_hdr
*hdr
;
1402 struct ahci_prdt_entry
*prdt
;
1403 struct blockif_req
*breq
;
1410 hdr
= (struct ahci_cmd_hdr
*)(p
->cmd_lst
+ slot
* AHCI_CL_SIZE
);
1411 prdt
= (struct ahci_prdt_entry
*)(cfis
+ 0x80);
1413 lba
= be32dec(acmd
+ 2);
1414 if (acmd
[0] == READ_10
)
1415 len
= be16dec(acmd
+ 7);
1417 len
= be32dec(acmd
+ 6);
1419 cfis
[4] = (cfis
[4] & ~7) | ATA_I_CMD
| ATA_I_IN
;
1420 ahci_write_fis_d2h(p
, slot
, cfis
, ATA_S_READY
| ATA_S_DSC
);
1426 * Pull request off free list
1428 aior
= STAILQ_FIRST(&p
->iofhd
);
1429 assert(aior
!= NULL
);
1430 STAILQ_REMOVE_HEAD(&p
->iofhd
, io_flist
);
1435 breq
= &aior
->io_req
;
1436 breq
->br_offset
= lba
+ done
;
1437 ahci_build_iov(p
, aior
, prdt
, hdr
->prdtl
);
1439 /* Mark this command in-flight. */
1440 p
->pending
|= 1 << slot
;
1442 /* Stuff request onto busy list. */
1443 TAILQ_INSERT_HEAD(&p
->iobhd
, aior
, io_blist
);
1445 err
= blockif_read(p
->bctx
, breq
);
1450 atapi_request_sense(struct ahci_port
*p
, int slot
, uint8_t *cfis
)
1458 if (len
> sizeof(buf
))
1460 memset(buf
, 0, len
);
1461 buf
[0] = 0x70 | (1 << 7);
1462 buf
[2] = p
->sense_key
;
1465 write_prdt(p
, slot
, cfis
, buf
, len
);
1466 cfis
[4] = (cfis
[4] & ~7) | ATA_I_CMD
| ATA_I_IN
;
1467 ahci_write_fis_d2h(p
, slot
, cfis
, ATA_S_READY
| ATA_S_DSC
);
1471 atapi_start_stop_unit(struct ahci_port
*p
, int slot
, uint8_t *cfis
)
1473 uint8_t *acmd
= cfis
+ 0x40;
1476 switch (acmd
[4] & 3) {
1480 cfis
[4] = (cfis
[4] & ~7) | ATA_I_CMD
| ATA_I_IN
;
1481 tfd
= ATA_S_READY
| ATA_S_DSC
;
1484 /* TODO eject media */
1485 cfis
[4] = (cfis
[4] & ~7) | ATA_I_CMD
| ATA_I_IN
;
1486 p
->sense_key
= ATA_SENSE_ILLEGAL_REQUEST
;
1488 tfd
= (p
->sense_key
<< 12) | ATA_S_READY
| ATA_S_ERROR
;
1491 ahci_write_fis_d2h(p
, slot
, cfis
, tfd
);
1495 atapi_mode_sense(struct ahci_port
*p
, int slot
, uint8_t *cfis
)
1503 len
= be16dec(acmd
+ 7);
1505 code
= acmd
[2] & 0x3f;
1510 case MODEPAGE_RW_ERROR_RECOVERY
:
1514 if (len
> sizeof(buf
))
1517 memset(buf
, 0, sizeof(buf
));
1518 be16enc(buf
, 16 - 2);
1523 write_prdt(p
, slot
, cfis
, buf
, len
);
1524 tfd
= ATA_S_READY
| ATA_S_DSC
;
1527 case MODEPAGE_CD_CAPABILITIES
:
1531 if (len
> sizeof(buf
))
1534 memset(buf
, 0, sizeof(buf
));
1535 be16enc(buf
, 30 - 2);
1541 be16enc(&buf
[18], 2);
1542 be16enc(&buf
[20], 512);
1543 write_prdt(p
, slot
, cfis
, buf
, len
);
1544 tfd
= ATA_S_READY
| ATA_S_DSC
;
1553 p
->sense_key
= ATA_SENSE_ILLEGAL_REQUEST
;
1555 tfd
= (p
->sense_key
<< 12) | ATA_S_READY
| ATA_S_ERROR
;
1560 p
->sense_key
= ATA_SENSE_ILLEGAL_REQUEST
;
1562 tfd
= (p
->sense_key
<< 12) | ATA_S_READY
| ATA_S_ERROR
;
1565 cfis
[4] = (cfis
[4] & ~7) | ATA_I_CMD
| ATA_I_IN
;
1566 ahci_write_fis_d2h(p
, slot
, cfis
, tfd
);
1570 atapi_get_event_status_notification(struct ahci_port
*p
, int slot
,
1578 /* we don't support asynchronous operation */
1579 if (!(acmd
[1] & 1)) {
1580 p
->sense_key
= ATA_SENSE_ILLEGAL_REQUEST
;
1582 tfd
= (p
->sense_key
<< 12) | ATA_S_READY
| ATA_S_ERROR
;
1587 len
= be16dec(acmd
+ 7);
1588 if (len
> sizeof(buf
))
1591 memset(buf
, 0, sizeof(buf
));
1592 be16enc(buf
, 8 - 2);
1596 write_prdt(p
, slot
, cfis
, buf
, len
);
1597 tfd
= ATA_S_READY
| ATA_S_DSC
;
1599 cfis
[4] = (cfis
[4] & ~7) | ATA_I_CMD
| ATA_I_IN
;
1600 ahci_write_fis_d2h(p
, slot
, cfis
, tfd
);
1604 handle_packet_cmd(struct ahci_port
*p
, int slot
, uint8_t *cfis
)
1614 for (i
= 0; i
< 16; i
++)
1615 DPRINTF("%02x ", acmd
[i
]);
1621 case TEST_UNIT_READY
:
1622 cfis
[4] = (cfis
[4] & ~7) | ATA_I_CMD
| ATA_I_IN
;
1623 ahci_write_fis_d2h(p
, slot
, cfis
, ATA_S_READY
| ATA_S_DSC
);
1626 atapi_inquiry(p
, slot
, cfis
);
1629 atapi_read_capacity(p
, slot
, cfis
);
1633 cfis
[4] = (cfis
[4] & ~7) | ATA_I_CMD
| ATA_I_IN
;
1634 ahci_write_fis_d2h(p
, slot
, cfis
, ATA_S_READY
| ATA_S_DSC
);
1637 atapi_read_toc(p
, slot
, cfis
);
1640 atapi_report_luns(p
, slot
, cfis
);
1644 atapi_read(p
, slot
, cfis
, 0);
1647 atapi_request_sense(p
, slot
, cfis
);
1649 case START_STOP_UNIT
:
1650 atapi_start_stop_unit(p
, slot
, cfis
);
1653 atapi_mode_sense(p
, slot
, cfis
);
1655 case GET_EVENT_STATUS_NOTIFICATION
:
1656 atapi_get_event_status_notification(p
, slot
, cfis
);
1659 cfis
[4] = (cfis
[4] & ~7) | ATA_I_CMD
| ATA_I_IN
;
1660 p
->sense_key
= ATA_SENSE_ILLEGAL_REQUEST
;
1662 ahci_write_fis_d2h(p
, slot
, cfis
, (p
->sense_key
<< 12) |
1663 ATA_S_READY
| ATA_S_ERROR
);
1669 ahci_handle_cmd(struct ahci_port
*p
, int slot
, uint8_t *cfis
)
1672 p
->tfd
|= ATA_S_BUSY
;
1674 case ATA_ATA_IDENTIFY
:
1675 handle_identify(p
, slot
, cfis
);
1677 case ATA_SETFEATURES
:
1680 case ATA_SF_ENAB_SATA_SF
:
1682 case ATA_SATA_SF_AN
:
1683 p
->tfd
= ATA_S_DSC
| ATA_S_READY
;
1686 p
->tfd
= ATA_S_ERROR
| ATA_S_READY
;
1687 p
->tfd
|= (ATA_ERROR_ABORT
<< 8);
1691 case ATA_SF_ENAB_WCACHE
:
1692 case ATA_SF_DIS_WCACHE
:
1693 case ATA_SF_ENAB_RCACHE
:
1694 case ATA_SF_DIS_RCACHE
:
1695 p
->tfd
= ATA_S_DSC
| ATA_S_READY
;
1697 case ATA_SF_SETXFER
:
1699 switch (cfis
[12] & 0xf8) {
1705 p
->xfermode
= (cfis
[12] & 0x7);
1708 p
->tfd
= ATA_S_DSC
| ATA_S_READY
;
1712 p
->tfd
= ATA_S_ERROR
| ATA_S_READY
;
1713 p
->tfd
|= (ATA_ERROR_ABORT
<< 8);
1716 ahci_write_fis_d2h(p
, slot
, cfis
, p
->tfd
);
1720 if (cfis
[12] != 0 &&
1721 (cfis
[12] > 128 || (cfis
[12] & (cfis
[12] - 1)))) {
1722 p
->tfd
= ATA_S_ERROR
| ATA_S_READY
;
1723 p
->tfd
|= (ATA_ERROR_ABORT
<< 8);
1725 p
->mult_sectors
= cfis
[12];
1726 p
->tfd
= ATA_S_DSC
| ATA_S_READY
;
1728 ahci_write_fis_d2h(p
, slot
, cfis
, p
->tfd
);
1736 case ATA_READ_MUL48
:
1737 case ATA_WRITE_MUL48
:
1740 case ATA_READ_DMA48
:
1741 case ATA_WRITE_DMA48
:
1742 case ATA_READ_FPDMA_QUEUED
:
1743 case ATA_WRITE_FPDMA_QUEUED
:
1744 ahci_handle_rw(p
, slot
, cfis
, 0);
1746 case ATA_FLUSHCACHE
:
1747 case ATA_FLUSHCACHE48
:
1748 ahci_handle_flush(p
, slot
, cfis
);
1750 case ATA_DATA_SET_MANAGEMENT
:
1751 if (cfis
[11] == 0 && cfis
[3] == ATA_DSM_TRIM
&&
1752 cfis
[13] == 0 && cfis
[12] == 1) {
1753 ahci_handle_dsm_trim(p
, slot
, cfis
, 0);
1756 ahci_write_fis_d2h(p
, slot
, cfis
,
1757 (ATA_E_ABORT
<< 8) | ATA_S_READY
| ATA_S_ERROR
);
1759 case ATA_SEND_FPDMA_QUEUED
:
1760 if ((cfis
[13] & 0x1f) == ATA_SFPDMA_DSM
&&
1761 cfis
[17] == 0 && cfis
[16] == ATA_DSM_TRIM
&&
1762 cfis
[11] == 0 && cfis
[3] == 1) {
1763 ahci_handle_dsm_trim(p
, slot
, cfis
, 0);
1766 ahci_write_fis_d2h(p
, slot
, cfis
,
1767 (ATA_E_ABORT
<< 8) | ATA_S_READY
| ATA_S_ERROR
);
1769 case ATA_READ_LOG_EXT
:
1770 case ATA_READ_LOG_DMA_EXT
:
1771 ahci_handle_read_log(p
, slot
, cfis
);
1773 case ATA_SECURITY_FREEZE_LOCK
:
1776 ahci_write_fis_d2h(p
, slot
, cfis
,
1777 (ATA_E_ABORT
<< 8) | ATA_S_READY
| ATA_S_ERROR
);
1779 case ATA_CHECK_POWER_MODE
:
1780 cfis
[12] = 0xff; /* always on */
1781 ahci_write_fis_d2h(p
, slot
, cfis
, ATA_S_READY
| ATA_S_DSC
);
1783 case ATA_STANDBY_CMD
:
1784 case ATA_STANDBY_IMMEDIATE
:
1786 case ATA_IDLE_IMMEDIATE
:
1788 case ATA_READ_VERIFY
:
1789 case ATA_READ_VERIFY48
:
1790 ahci_write_fis_d2h(p
, slot
, cfis
, ATA_S_READY
| ATA_S_DSC
);
1792 case ATA_ATAPI_IDENTIFY
:
1793 handle_atapi_identify(p
, slot
, cfis
);
1795 case ATA_PACKET_CMD
:
1797 ahci_write_fis_d2h(p
, slot
, cfis
,
1798 (ATA_E_ABORT
<< 8) | ATA_S_READY
| ATA_S_ERROR
);
1800 handle_packet_cmd(p
, slot
, cfis
);
1803 WPRINTF("Unsupported cmd:%02x", cfis
[2]);
1804 ahci_write_fis_d2h(p
, slot
, cfis
,
1805 (ATA_E_ABORT
<< 8) | ATA_S_READY
| ATA_S_ERROR
);
1811 ahci_handle_slot(struct ahci_port
*p
, int slot
)
1813 struct ahci_cmd_hdr
*hdr
;
1815 struct ahci_prdt_entry
*prdt
;
1817 struct pci_ahci_softc
*sc
;
1824 hdr
= (struct ahci_cmd_hdr
*)(p
->cmd_lst
+ slot
* AHCI_CL_SIZE
);
1826 cfl
= (hdr
->flags
& 0x1f) * 4;
1828 cfis
= paddr_guest2host(ahci_ctx(sc
), hdr
->ctba
,
1829 0x80 + hdr
->prdtl
* sizeof(struct ahci_prdt_entry
));
1831 prdt
= (struct ahci_prdt_entry
*)(cfis
+ 0x80);
1834 for (i
= 0; i
< cfl
; i
++) {
1837 DPRINTF("%02x ", cfis
[i
]);
1841 for (i
= 0; i
< hdr
->prdtl
; i
++) {
1842 DPRINTF("%d@%08"PRIx64
"", prdt
->dbc
& 0x3fffff, prdt
->dba
);
1847 if (cfis
[0] != FIS_TYPE_REGH2D
) {
1848 WPRINTF("Not a H2D FIS:%02x", cfis
[0]);
1852 if (cfis
[1] & 0x80) {
1853 ahci_handle_cmd(p
, slot
, cfis
);
1855 if (cfis
[15] & (1 << 2))
1857 else if (p
->reset
) {
1861 p
->ci
&= ~(1 << slot
);
1866 ahci_handle_port(struct ahci_port
*p
)
1869 if (!(p
->cmd
& AHCI_P_CMD_ST
))
1873 * Search for any new commands to issue ignoring those that
1874 * are already in-flight. Stop if device is busy or in error.
1876 for (; (p
->ci
& ~p
->pending
) != 0; p
->ccs
= ((p
->ccs
+ 1) & 31)) {
1877 if ((p
->tfd
& (ATA_S_BUSY
| ATA_S_DRQ
)) != 0)
1879 if (p
->waitforclear
)
1881 if ((p
->ci
& ~p
->pending
& (1 << p
->ccs
)) != 0) {
1882 p
->cmd
&= ~AHCI_P_CMD_CCS_MASK
;
1883 p
->cmd
|= p
->ccs
<< AHCI_P_CMD_CCS_SHIFT
;
1884 ahci_handle_slot(p
, p
->ccs
);
1890 * blockif callback routine - this runs in the context of the blockif
1891 * i/o thread, so the mutex needs to be acquired.
1894 ata_ioreq_cb(struct blockif_req
*br
, int err
)
1896 struct ahci_cmd_hdr
*hdr
;
1897 struct ahci_ioreq
*aior
;
1898 struct ahci_port
*p
;
1899 struct pci_ahci_softc
*sc
;
1904 DPRINTF("%s %d", __func__
, err
);
1907 aior
= br
->br_param
;
1912 hdr
= (struct ahci_cmd_hdr
*)(p
->cmd_lst
+ slot
* AHCI_CL_SIZE
);
1914 if (cfis
[2] == ATA_WRITE_FPDMA_QUEUED
||
1915 cfis
[2] == ATA_READ_FPDMA_QUEUED
||
1916 cfis
[2] == ATA_SEND_FPDMA_QUEUED
)
1918 if (cfis
[2] == ATA_DATA_SET_MANAGEMENT
||
1919 (cfis
[2] == ATA_SEND_FPDMA_QUEUED
&&
1920 (cfis
[13] & 0x1f) == ATA_SFPDMA_DSM
))
1923 pthread_mutex_lock(&sc
->mtx
);
1926 * Delete the blockif request from the busy list
1928 TAILQ_REMOVE(&p
->iobhd
, aior
, io_blist
);
1931 * Move the blockif request back to the free list
1933 STAILQ_INSERT_TAIL(&p
->iofhd
, aior
, io_flist
);
1936 hdr
->prdbc
= aior
->done
;
1938 if (!err
&& aior
->more
) {
1940 ahci_handle_dsm_trim(p
, slot
, cfis
, aior
->done
);
1942 ahci_handle_rw(p
, slot
, cfis
, aior
->done
);
1947 tfd
= ATA_S_READY
| ATA_S_DSC
;
1949 tfd
= (ATA_E_ABORT
<< 8) | ATA_S_READY
| ATA_S_ERROR
;
1951 ahci_write_fis_sdb(p
, slot
, cfis
, tfd
);
1953 ahci_write_fis_d2h(p
, slot
, cfis
, tfd
);
1956 * This command is now complete.
1958 p
->pending
&= ~(1 << slot
);
1960 ahci_check_stopped(p
);
1961 ahci_handle_port(p
);
1963 pthread_mutex_unlock(&sc
->mtx
);
1964 DPRINTF("%s exit", __func__
);
1968 atapi_ioreq_cb(struct blockif_req
*br
, int err
)
1970 struct ahci_cmd_hdr
*hdr
;
1971 struct ahci_ioreq
*aior
;
1972 struct ahci_port
*p
;
1973 struct pci_ahci_softc
*sc
;
1978 DPRINTF("%s %d", __func__
, err
);
1980 aior
= br
->br_param
;
1985 hdr
= (struct ahci_cmd_hdr
*)(p
->cmd_lst
+ aior
->slot
* AHCI_CL_SIZE
);
1987 pthread_mutex_lock(&sc
->mtx
);
1990 * Delete the blockif request from the busy list
1992 TAILQ_REMOVE(&p
->iobhd
, aior
, io_blist
);
1995 * Move the blockif request back to the free list
1997 STAILQ_INSERT_TAIL(&p
->iofhd
, aior
, io_flist
);
2000 hdr
->prdbc
= aior
->done
;
2002 if (!err
&& aior
->more
) {
2003 atapi_read(p
, slot
, cfis
, aior
->done
);
2008 tfd
= ATA_S_READY
| ATA_S_DSC
;
2010 p
->sense_key
= ATA_SENSE_ILLEGAL_REQUEST
;
2012 tfd
= (p
->sense_key
<< 12) | ATA_S_READY
| ATA_S_ERROR
;
2014 cfis
[4] = (cfis
[4] & ~7) | ATA_I_CMD
| ATA_I_IN
;
2015 ahci_write_fis_d2h(p
, slot
, cfis
, tfd
);
2018 * This command is now complete.
2020 p
->pending
&= ~(1 << slot
);
2022 ahci_check_stopped(p
);
2023 ahci_handle_port(p
);
2025 pthread_mutex_unlock(&sc
->mtx
);
2026 DPRINTF("%s exit", __func__
);
2030 pci_ahci_ioreq_init(struct ahci_port
*pr
)
2032 struct ahci_ioreq
*vr
;
2035 pr
->ioqsz
= blockif_queuesz(pr
->bctx
);
2036 pr
->ioreq
= calloc(pr
->ioqsz
, sizeof(struct ahci_ioreq
));
2037 STAILQ_INIT(&pr
->iofhd
);
2040 * Add all i/o request entries to the free queue
2042 for (i
= 0; i
< pr
->ioqsz
; i
++) {
2046 vr
->io_req
.br_callback
= ata_ioreq_cb
;
2048 vr
->io_req
.br_callback
= atapi_ioreq_cb
;
2049 vr
->io_req
.br_param
= vr
;
2050 STAILQ_INSERT_TAIL(&pr
->iofhd
, vr
, io_flist
);
2053 TAILQ_INIT(&pr
->iobhd
);
2057 pci_ahci_port_write(struct pci_ahci_softc
*sc
, uint64_t offset
, uint64_t value
)
2059 int port
= (offset
- AHCI_OFFSET
) / AHCI_STEP
;
2060 offset
= (offset
- AHCI_OFFSET
) % AHCI_STEP
;
2061 struct ahci_port
*p
= &sc
->port
[port
];
2063 DPRINTF("pci_ahci_port %d: write offset 0x%"PRIx64
" value 0x%"PRIx64
"",
2064 port
, offset
, value
);
2084 p
->ie
= value
& 0xFDC000FF;
2089 p
->cmd
&= ~(AHCI_P_CMD_ST
| AHCI_P_CMD_SUD
| AHCI_P_CMD_POD
|
2090 AHCI_P_CMD_CLO
| AHCI_P_CMD_FRE
| AHCI_P_CMD_APSTE
|
2091 AHCI_P_CMD_ATAPI
| AHCI_P_CMD_DLAE
| AHCI_P_CMD_ALPE
|
2092 AHCI_P_CMD_ASP
| AHCI_P_CMD_ICC_MASK
);
2093 p
->cmd
|= (AHCI_P_CMD_ST
| AHCI_P_CMD_SUD
| AHCI_P_CMD_POD
|
2094 AHCI_P_CMD_CLO
| AHCI_P_CMD_FRE
| AHCI_P_CMD_APSTE
|
2095 AHCI_P_CMD_ATAPI
| AHCI_P_CMD_DLAE
| AHCI_P_CMD_ALPE
|
2096 AHCI_P_CMD_ASP
| AHCI_P_CMD_ICC_MASK
) & value
;
2098 if (!(value
& AHCI_P_CMD_ST
)) {
2103 p
->cmd
|= AHCI_P_CMD_CR
;
2104 clb
= (uint64_t)p
->clbu
<< 32 | p
->clb
;
2105 p
->cmd_lst
= paddr_guest2host(ahci_ctx(sc
), clb
,
2106 AHCI_CL_SIZE
* AHCI_MAX_SLOTS
);
2109 if (value
& AHCI_P_CMD_FRE
) {
2112 p
->cmd
|= AHCI_P_CMD_FR
;
2113 fb
= (uint64_t)p
->fbu
<< 32 | p
->fb
;
2114 /* we don't support FBSCP, so rfis size is 256Bytes */
2115 p
->rfis
= paddr_guest2host(ahci_ctx(sc
), fb
, 256);
2117 p
->cmd
&= ~AHCI_P_CMD_FR
;
2120 if (value
& AHCI_P_CMD_CLO
) {
2121 p
->tfd
&= ~(ATA_S_BUSY
| ATA_S_DRQ
);
2122 p
->cmd
&= ~AHCI_P_CMD_CLO
;
2125 if (value
& AHCI_P_CMD_ICC_MASK
) {
2126 p
->cmd
&= ~AHCI_P_CMD_ICC_MASK
;
2129 ahci_handle_port(p
);
2135 WPRINTF("pci_ahci_port: read only registers 0x%"PRIx64
"", offset
);
2139 if (!(p
->cmd
& AHCI_P_CMD_ST
)) {
2140 if (value
& ATA_SC_DET_RESET
)
2152 ahci_handle_port(p
);
2162 pci_ahci_host_write(struct pci_ahci_softc
*sc
, uint64_t offset
, uint64_t value
)
2164 DPRINTF("pci_ahci_host: write offset 0x%"PRIx64
" value 0x%"PRIx64
"",
2172 DPRINTF("pci_ahci_host: read only registers 0x%"PRIx64
"", offset
);
2175 if (value
& AHCI_GHC_HR
) {
2179 if (value
& AHCI_GHC_IE
)
2180 sc
->ghc
|= AHCI_GHC_IE
;
2182 sc
->ghc
&= ~AHCI_GHC_IE
;
2183 ahci_generate_intr(sc
, 0xffffffff);
2187 ahci_generate_intr(sc
, value
);
2195 pci_ahci_write(struct vmctx
*ctx __unused
,
2196 struct pci_devinst
*pi
, int baridx
, uint64_t offset
, int size
,
2199 struct pci_ahci_softc
*sc
= pi
->pi_arg
;
2201 assert(baridx
== 5);
2202 assert((offset
% 4) == 0 && size
== 4);
2204 pthread_mutex_lock(&sc
->mtx
);
2206 if (offset
< AHCI_OFFSET
)
2207 pci_ahci_host_write(sc
, offset
, value
);
2208 else if (offset
< (uint64_t)AHCI_OFFSET
+ sc
->ports
* AHCI_STEP
)
2209 pci_ahci_port_write(sc
, offset
, value
);
2211 WPRINTF("pci_ahci: unknown i/o write offset 0x%"PRIx64
"", offset
);
2213 pthread_mutex_unlock(&sc
->mtx
);
2217 pci_ahci_host_read(struct pci_ahci_softc
*sc
, uint64_t offset
)
2233 uint32_t *p
= &sc
->cap
;
2234 p
+= (offset
- AHCI_CAP
) / sizeof(uint32_t);
2242 DPRINTF("pci_ahci_host: read offset 0x%"PRIx64
" value 0x%x",
2249 pci_ahci_port_read(struct pci_ahci_softc
*sc
, uint64_t offset
)
2252 int port
= (offset
- AHCI_OFFSET
) / AHCI_STEP
;
2253 offset
= (offset
- AHCI_OFFSET
) % AHCI_STEP
;
2273 uint32_t *p
= &sc
->port
[port
].clb
;
2274 p
+= (offset
- AHCI_P_CLB
) / sizeof(uint32_t);
2283 DPRINTF("pci_ahci_port %d: read offset 0x%"PRIx64
" value 0x%x",
2284 port
, offset
, value
);
2290 pci_ahci_read(struct vmctx
*ctx __unused
,
2291 struct pci_devinst
*pi
, int baridx
, uint64_t regoff
, int size
)
2293 struct pci_ahci_softc
*sc
= pi
->pi_arg
;
2297 assert(baridx
== 5);
2298 assert(size
== 1 || size
== 2 || size
== 4);
2299 assert((regoff
& (size
- 1)) == 0);
2301 pthread_mutex_lock(&sc
->mtx
);
2303 offset
= regoff
& ~0x3; /* round down to a multiple of 4 bytes */
2304 if (offset
< AHCI_OFFSET
)
2305 value
= pci_ahci_host_read(sc
, offset
);
2306 else if (offset
< (uint64_t)AHCI_OFFSET
+ sc
->ports
* AHCI_STEP
)
2307 value
= pci_ahci_port_read(sc
, offset
);
2310 WPRINTF("pci_ahci: unknown i/o read offset 0x%"PRIx64
"",
2313 value
>>= 8 * (regoff
& 0x3);
2315 pthread_mutex_unlock(&sc
->mtx
);
2321 * Each AHCI controller has a "port" node which contains nodes for
2322 * each port named after the decimal number of the port (no leading
2323 * zeroes). Port nodes contain a "type" ("hd" or "cd"), as well as
2324 * options for blockif. For example:
2331 * .path="/path/to/image"
2334 pci_ahci_legacy_config_port(nvlist_t
*nvl
, int port
, const char *type
,
2337 char node_name
[sizeof("XX")];
2340 snprintf(node_name
, sizeof(node_name
), "%d", port
);
2341 port_nvl
= create_relative_config_node(nvl
, node_name
);
2342 set_config_value_node(port_nvl
, "type", type
);
2343 return (blockif_legacy_config(port_nvl
, opts
));
2347 pci_ahci_legacy_config(nvlist_t
*nvl
, const char *opts
)
2349 nvlist_t
*ports_nvl
;
2351 char *next
, *next2
, *str
, *tofree
;
2357 ports_nvl
= create_relative_config_node(nvl
, "port");
2359 tofree
= str
= strdup(opts
);
2360 for (p
= 0; p
< MAX_PORTS
&& str
!= NULL
; p
++, str
= next
) {
2361 /* Identify and cut off type of present port. */
2362 if (strncmp(str
, "hd:", 3) == 0) {
2365 } else if (strncmp(str
, "cd:", 3) == 0) {
2371 /* Find and cut off the next port options. */
2372 next
= strstr(str
, ",hd:");
2373 next2
= strstr(str
, ",cd:");
2374 if (next
== NULL
|| (next2
!= NULL
&& next2
< next
))
2385 EPRINTLN("Missing or invalid type for port %d: \"%s\"",
2390 if (pci_ahci_legacy_config_port(ports_nvl
, p
, type
, str
) != 0)
2400 pci_ahci_cd_legacy_config(nvlist_t
*nvl
, const char *opts
)
2402 nvlist_t
*ports_nvl
;
2404 ports_nvl
= create_relative_config_node(nvl
, "port");
2405 return (pci_ahci_legacy_config_port(ports_nvl
, 0, "cd", opts
));
2409 pci_ahci_hd_legacy_config(nvlist_t
*nvl
, const char *opts
)
2411 nvlist_t
*ports_nvl
;
2413 ports_nvl
= create_relative_config_node(nvl
, "port");
2414 return (pci_ahci_legacy_config_port(ports_nvl
, 0, "hd", opts
));
2418 pci_ahci_init(struct vmctx
*ctx __unused
, struct pci_devinst
*pi
, nvlist_t
*nvl
)
2420 char bident
[sizeof("XXX:XXX:XXX")];
2421 char node_name
[sizeof("XX")];
2422 struct blockif_ctxt
*bctxt
;
2423 struct pci_ahci_softc
*sc
;
2424 int atapi
, ret
, slots
, p
;
2427 const char *path
, *type
, *value
;
2428 nvlist_t
*ports_nvl
, *port_nvl
;
2433 dbg
= fopen("/tmp/log", "w+");
2436 sc
= calloc(1, sizeof(struct pci_ahci_softc
));
2439 pthread_mutex_init(&sc
->mtx
, NULL
);
2444 ports_nvl
= find_relative_config_node(nvl
, "port");
2445 for (p
= 0; ports_nvl
!= NULL
&& p
< MAX_PORTS
; p
++) {
2446 struct ata_params
*ata_ident
= &sc
->port
[p
].ata_ident
;
2447 char ident
[AHCI_PORT_IDENT
];
2449 snprintf(node_name
, sizeof(node_name
), "%d", p
);
2450 port_nvl
= find_relative_config_node(ports_nvl
, node_name
);
2451 if (port_nvl
== NULL
)
2454 type
= get_config_value_node(port_nvl
, "type");
2458 if (strcmp(type
, "hd") == 0)
2464 * Attempt to open the backing image. Use the PCI slot/func
2465 * and the port number for the identifier string.
2467 snprintf(bident
, sizeof(bident
), "%u:%u:%u", pi
->pi_slot
,
2470 bctxt
= blockif_open(port_nvl
, bident
);
2471 if (bctxt
== NULL
) {
2476 sc
->port
[p
].bctx
= bctxt
;
2477 sc
->port
[p
].pr_sc
= sc
;
2478 sc
->port
[p
].port
= p
;
2479 sc
->port
[p
].atapi
= atapi
;
2482 * Create an identifier for the backing file.
2483 * Use parts of the md5 sum of the filename
2485 path
= get_config_value_node(port_nvl
, "path");
2487 MD5Update(&mdctx
, path
, strlen(path
));
2488 MD5Final(digest
, &mdctx
);
2489 snprintf(ident
, AHCI_PORT_IDENT
,
2490 "BHYVE-%02X%02X-%02X%02X-%02X%02X",
2491 digest
[0], digest
[1], digest
[2], digest
[3], digest
[4],
2494 memset(ata_ident
, 0, sizeof(struct ata_params
));
2495 ata_string((uint8_t*)&ata_ident
->serial
, ident
, 20);
2496 ata_string((uint8_t*)&ata_ident
->revision
, "001", 8);
2498 ata_string((uint8_t*)&ata_ident
->model
, "BHYVE SATA DVD ROM", 40);
2500 ata_string((uint8_t*)&ata_ident
->model
, "BHYVE SATA DISK", 40);
2501 value
= get_config_value_node(port_nvl
, "nmrr");
2503 ata_ident
->media_rotation_rate
= atoi(value
);
2504 value
= get_config_value_node(port_nvl
, "ser");
2506 ata_string((uint8_t*)(&ata_ident
->serial
), value
, 20);
2507 value
= get_config_value_node(port_nvl
, "rev");
2509 ata_string((uint8_t*)(&ata_ident
->revision
), value
, 8);
2510 value
= get_config_value_node(port_nvl
, "model");
2512 ata_string((uint8_t*)(&ata_ident
->model
), value
, 40);
2513 ata_identify_init(&sc
->port
[p
], atapi
);
2517 * Attempt to enable the write cache for this device, as the
2518 * guest will issue FLUSH commands when it requires durability.
2520 * Failure here is fine, since an always-sync device will not
2521 * have an impact on correctness.
2523 (void) blockif_set_wce(bctxt
, 1);
2527 * Allocate blockif request structures and add them
2530 pci_ahci_ioreq_init(&sc
->port
[p
]);
2533 if (sc
->port
[p
].ioqsz
< slots
)
2534 slots
= sc
->port
[p
].ioqsz
;
2538 /* Intel ICH8 AHCI */
2540 if (sc
->ports
< DEF_PORTS
)
2541 sc
->ports
= DEF_PORTS
;
2542 sc
->cap
= AHCI_CAP_64BIT
| AHCI_CAP_SNCQ
| AHCI_CAP_SSNTF
|
2543 AHCI_CAP_SMPS
| AHCI_CAP_SSS
| AHCI_CAP_SALP
|
2544 AHCI_CAP_SAL
| AHCI_CAP_SCLO
| (0x3 << AHCI_CAP_ISS_SHIFT
)|
2545 AHCI_CAP_PMD
| AHCI_CAP_SSC
| AHCI_CAP_PSC
|
2546 (slots
<< AHCI_CAP_NCS_SHIFT
) | AHCI_CAP_SXS
| (sc
->ports
- 1);
2549 sc
->cap2
= AHCI_CAP2_APST
;
2552 pci_set_cfgdata16(pi
, PCIR_DEVICE
, 0x2821);
2553 pci_set_cfgdata16(pi
, PCIR_VENDOR
, 0x8086);
2554 pci_set_cfgdata8(pi
, PCIR_CLASS
, PCIC_STORAGE
);
2555 pci_set_cfgdata8(pi
, PCIR_SUBCLASS
, PCIS_STORAGE_SATA
);
2556 pci_set_cfgdata8(pi
, PCIR_PROGIF
, PCIP_STORAGE_SATA_AHCI_1_0
);
2557 p
= MIN(sc
->ports
, 16);
2558 p
= flsl(p
) - ((p
& (p
- 1)) ? 0 : 1);
2559 pci_emul_add_msicap(pi
, 1 << p
);
2560 pci_emul_alloc_bar(pi
, 5, PCIBAR_MEM32
,
2561 AHCI_OFFSET
+ sc
->ports
* AHCI_STEP
);
2563 pci_lintr_request(pi
);
2567 for (p
= 0; p
< sc
->ports
; p
++) {
2568 if (sc
->port
[p
].bctx
!= NULL
)
2569 blockif_close(sc
->port
[p
].bctx
);
2578 * Use separate emulation names to distinguish drive and atapi devices
2580 static const struct pci_devemu pci_de_ahci
= {
2582 .pe_init
= pci_ahci_init
,
2583 .pe_legacy_config
= pci_ahci_legacy_config
,
2584 .pe_barwrite
= pci_ahci_write
,
2585 .pe_barread
= pci_ahci_read
,
2587 PCI_EMUL_SET(pci_de_ahci
);
2589 static const struct pci_devemu pci_de_ahci_hd
= {
2590 .pe_emu
= "ahci-hd",
2591 .pe_legacy_config
= pci_ahci_hd_legacy_config
,
2594 PCI_EMUL_SET(pci_de_ahci_hd
);
2596 static const struct pci_devemu pci_de_ahci_cd
= {
2597 .pe_emu
= "ahci-cd",
2598 .pe_legacy_config
= pci_ahci_cd_legacy_config
,
2601 PCI_EMUL_SET(pci_de_ahci_cd
);