38#include <sys/kernel.h>
40#include <sys/sysctl.h>
41#include <sys/taskqueue.h>
45#include <sys/devicestat.h>
46#include <sys/eventhandler.h>
47#include <sys/malloc.h>
48#include <sys/endian.h>
51#include <sys/reboot.h>
54#include <geom/geom_disk.h>
75#define ATA_MAX_28BIT_LBA 268435455UL
116#define ADA_FLAG_STRING \
119 "\003CAN_FLUSHCACHE" \
154#define ADA_Q_BIT_STRING \
157 "\002NCQ_TRIM_BROKEN" \
215#define ccb_state ppriv_field0
216#define ccb_bp ppriv_ptr1
229 {
"NONE",
"DISABLE",
"CFA_ERASE",
"DSM_TRIM",
"NCQ_DSM_TRIM" };
231static const char *ada_delete_method_desc[] =
232 {
"NONE",
"DISABLED",
"CFA Erase",
"DSM Trim",
"DSM Trim via NCQ" };
243#define TRIM_MAX_BLOCKS 8
244#define TRIM_MAX_RANGES (TRIM_MAX_BLOCKS * ATA_DSM_BLK_RANGES)
270#ifdef CAM_TEST_FAILURE
271 int force_read_error;
272 int force_write_error;
273 int periodic_read_error;
274 int periodic_read_count;
288 struct sysctl_ctx_list sysctl_stats_ctx;
289 struct sysctl_oid *sysctl_stats_tree;
294#define ADA_ANNOUNCETMP_SZ 80
296#define ADA_ANNOUNCE_SZ 400
835static void adaasync(
void *callback_arg, u_int32_t code,
853 struct bio *bp,
int *queue_ccb);
858 union ccb *done_ccb);
860 u_int32_t sense_flags);
866#ifndef ADA_DEFAULT_TIMEOUT
867#define ADA_DEFAULT_TIMEOUT 30
870#ifndef ADA_DEFAULT_RETRY
871#define ADA_DEFAULT_RETRY 4
874#ifndef ADA_DEFAULT_SEND_ORDERED
875#define ADA_DEFAULT_SEND_ORDERED 1
878#ifndef ADA_DEFAULT_SPINDOWN_SHUTDOWN
879#define ADA_DEFAULT_SPINDOWN_SHUTDOWN 1
882#ifndef ADA_DEFAULT_SPINDOWN_SUSPEND
883#define ADA_DEFAULT_SPINDOWN_SUSPEND 1
886#ifndef ADA_DEFAULT_READ_AHEAD
887#define ADA_DEFAULT_READ_AHEAD 1
890#ifndef ADA_DEFAULT_WRITE_CACHE
891#define ADA_DEFAULT_WRITE_CACHE 1
894#define ADA_RA (softc->read_ahead >= 0 ? \
895 softc->read_ahead : ada_read_ahead)
896#define ADA_WC (softc->write_cache >= 0 ? \
897 softc->write_cache : ada_write_cache)
909static SYSCTL_NODE(_kern_cam, OID_AUTO, ada, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
910 "CAM Direct Access Disk driver");
911SYSCTL_INT(_kern_cam_ada, OID_AUTO, retry_count, CTLFLAG_RWTUN,
913SYSCTL_INT(_kern_cam_ada, OID_AUTO, default_timeout, CTLFLAG_RWTUN,
915SYSCTL_INT(_kern_cam_ada, OID_AUTO, send_ordered, CTLFLAG_RWTUN,
917SYSCTL_INT(_kern_cam_ada, OID_AUTO, spindown_shutdown, CTLFLAG_RWTUN,
919SYSCTL_INT(_kern_cam_ada, OID_AUTO, spindown_suspend, CTLFLAG_RWTUN,
921SYSCTL_INT(_kern_cam_ada, OID_AUTO, read_ahead, CTLFLAG_RWTUN,
923SYSCTL_INT(_kern_cam_ada, OID_AUTO, write_cache, CTLFLAG_RWTUN,
925SYSCTL_INT(_kern_cam_ada, OID_AUTO, enable_biospeedup, CTLFLAG_RDTUN,
927SYSCTL_INT(_kern_cam_ada, OID_AUTO, enable_uma_ccbs, CTLFLAG_RWTUN,
942#ifndef ADA_ORDEREDTAG_INTERVAL
943#define ADA_ORDEREDTAG_INTERVAL 4
949 TAILQ_HEAD_INITIALIZER(
adadriver.units), 0
1023 0,
softc->disk->d_devstat);
1027 softc->flags &= ~ADA_FLAG_DIRTY;
1032 softc->flags &= ~ADA_FLAG_OPEN;
1034 while (
softc->refcount != 0)
1063 periph = (
struct cam_periph *)bp->bio_disk->d_drv1;
1075 biofinish(bp, NULL, ENXIO);
1084 if (bp->bio_cmd == BIO_ZONE)
1085 bp->bio_flags |= BIO_ORDERED;
1102adadump(
void *arg,
void *
virtual, vm_offset_t physical, off_t offset,
size_t length)
1114 periph = dp->d_drv1;
1117 lba = offset / secsize;
1118 count = length / secsize;
1122 memset(&ataio, 0,
sizeof(ataio));
1131 (u_int8_t *)
virtual,
1146 printf(
"Aborting dump due to I/O error.\n");
1187 sizeof(
struct ccb_ataio), NULL, NULL, NULL, NULL,
1197 printf(
"ada: Failed to attach master async callback "
1198 "due to status 0x%x!\n", status);
1201 if ((EVENTHANDLER_REGISTER(power_suspend,
adasuspend,
1202 NULL, EVENTHANDLER_PRI_LAST)) == NULL)
1203 printf(
"adainit: power event registration failed!\n");
1204 if ((EVENTHANDLER_REGISTER(power_resume,
adaresume,
1205 NULL, EVENTHANDLER_PRI_LAST)) == NULL)
1206 printf(
"adainit: power event registration failed!\n");
1207 if ((EVENTHANDLER_REGISTER(shutdown_post_sync,
adashutdown,
1208 NULL, SHUTDOWN_PRI_DEFAULT)) == NULL)
1209 printf(
"adainit: shutdown event registration failed!\n");
1239 softc->invalidations++;
1249 disk_gone(softc->
disk);
1268 if (sysctl_ctx_free(&softc->sysctl_stats_ctx) != 0)
1270 "can't remove sysctl stats context\n");
1272 if (sysctl_ctx_free(&softc->
sysctl_ctx) != 0)
1274 "can't remove sysctl context\n");
1277 disk_destroy(softc->
disk);
1279 free(softc, M_DEVBUF);
1332 printf(
"adaasync: Unable to attach to new device "
1333 "due to status 0x%x\n", status);
1339 memset(&cgd, 0,
sizeof(cgd));
1349 disk_resize(softc->
disk, M_NOWAIT);
1358 buftype = (uintptr_t)arg;
1362 softc = periph->
softc;
1363 disk_attr_changed(softc->
disk,
"GEOM::physpath",
1375 memset(&cgd, 0,
sizeof(cgd));
1410 snprintf(tmpbuf,
sizeof(tmpbuf),
"Drive Managed");
1413 snprintf(tmpbuf,
sizeof(tmpbuf),
"Host Aware");
1416 snprintf(tmpbuf,
sizeof(tmpbuf),
"Host Managed");
1420 snprintf(tmpbuf,
sizeof(tmpbuf),
"Not Zoned");
1424 error = sysctl_handle_string(oidp, tmpbuf,
sizeof(tmpbuf), req);
1442 sbuf_new(&sb, tmpbuf,
sizeof(tmpbuf), 0);
1448 sbuf_printf(&sb,
", ");
1456 sbuf_printf(&sb,
"None");
1460 error = sysctl_handle_string(oidp, sbuf_data(&sb), sbuf_len(&sb), req);
1470 char tmpstr[32], tmpstr2[16];
1481 snprintf(tmpstr,
sizeof(tmpstr),
"CAM ADA unit %d",periph->
unit_number);
1482 snprintf(tmpstr2,
sizeof(tmpstr2),
"%d", periph->
unit_number);
1487 SYSCTL_STATIC_CHILDREN(_kern_cam_ada), OID_AUTO, tmpstr2,
1488 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, tmpstr,
"device_index");
1490 printf(
"adasysctlinit: unable to allocate sysctl tree\n");
1496 OID_AUTO,
"delete_method",
1497 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE,
1499 "BIO_DELETE execution method");
1502 "trim_count", CTLFLAG_RD, &softc->
trim_count,
1503 "Total number of dsm commands sent");
1507 "Total number of ranges in dsm commands");
1510 "trim_lbas", CTLFLAG_RD, &softc->
trim_lbas,
1511 "Total lbas in the dsm commands sent");
1513 OID_AUTO,
"read_ahead", CTLFLAG_RW | CTLFLAG_MPSAFE,
1514 &softc->
read_ahead, 0,
"Enable disk read ahead.");
1516 OID_AUTO,
"write_cache", CTLFLAG_RW | CTLFLAG_MPSAFE,
1517 &softc->
write_cache, 0,
"Enable disk write cache.");
1519 OID_AUTO,
"zone_mode",
1520 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
1524 OID_AUTO,
"zone_support",
1525 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
1531 "Optimal Number of Open Sequential Write Preferred Zones");
1534 "optimal_nonseq_zones", CTLFLAG_RD,
1536 "Optimal Number of Non-Sequentially Written Sequential Write "
1541 "Maximum Number of Open Sequential Write Required Zones");
1543 OID_AUTO,
"flags", CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
1547 OID_AUTO,
"unmapped_io", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
1549 "Unmapped I/O support *DEPRECATED* gone in FreeBSD 14");
1551 OID_AUTO,
"rotating", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
1553 "Rotating media *DEPRECATED* gone in FreeBSD 14");
1555#ifdef CAM_TEST_FAILURE
1562 OID_AUTO,
"force_read_error", CTLFLAG_RW | CTLFLAG_MPSAFE,
1563 &softc->force_read_error, 0,
1564 "Force a read error for the next N reads.");
1566 OID_AUTO,
"force_write_error", CTLFLAG_RW | CTLFLAG_MPSAFE,
1567 &softc->force_write_error, 0,
1568 "Force a write error for the next N writes.");
1570 OID_AUTO,
"periodic_read_error", CTLFLAG_RW | CTLFLAG_MPSAFE,
1571 &softc->periodic_read_error, 0,
1572 "Force a read error every N reads (don't set too low).");
1574 OID_AUTO,
"invalidate", CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE,
1576 "Write 1 to invalidate the drive immediately");
1580 softc->sysctl_stats_tree = SYSCTL_ADD_NODE(&softc->sysctl_stats_ctx,
1581 SYSCTL_CHILDREN(softc->
sysctl_tree), OID_AUTO,
"stats",
1582 CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
"Statistics");
1583 SYSCTL_ADD_INT(&softc->sysctl_stats_ctx,
1584 SYSCTL_CHILDREN(softc->sysctl_stats_tree),
1585 OID_AUTO,
"timeouts", CTLFLAG_RD | CTLFLAG_MPSAFE,
1586 &softc->timeouts, 0,
1587 "Device timeouts reported by the SIM");
1588 SYSCTL_ADD_INT(&softc->sysctl_stats_ctx,
1589 SYSCTL_CHILDREN(softc->sysctl_stats_tree),
1590 OID_AUTO,
"errors", CTLFLAG_RD | CTLFLAG_MPSAFE,
1592 "Transport errors reported by the SIM.");
1593 SYSCTL_ADD_INT(&softc->sysctl_stats_ctx,
1594 SYSCTL_CHILDREN(softc->sysctl_stats_tree),
1595 OID_AUTO,
"pack_invalidations", CTLFLAG_RD | CTLFLAG_MPSAFE,
1596 &softc->invalidations, 0,
1597 "Device pack invalidations.");
1613 return (EJUSTRETURN);
1615 periph = (
struct cam_periph *)bp->bio_disk->d_drv1;
1617 ret =
xpt_getattr(bp->bio_data, bp->bio_length, bp->bio_attribute,
1621 bp->bio_completed = bp->bio_length;
1631 int i, error, value, methods;
1640 strncpy(buf, p,
sizeof(buf));
1641 error = sysctl_handle_string(oidp, buf,
sizeof(buf), req);
1642 if (error != 0 || req->newptr == NULL)
1653 if (!(methods & (1 << i)) ||
1665 u_int *
flags = arg1;
1669 tmpout = !!(*
flags & test);
1670 error = SYSCTL_OUT(req, &tmpout,
sizeof(tmpout));
1671 if (error || !req->newptr)
1684 sbuf_new_for_sysctl(&sbuf, NULL, 0, req);
1685 if (softc->
flags != 0)
1688 sbuf_printf(&sbuf,
"0");
1689 error = sbuf_finish(&sbuf);
1698 if ((cgd->
ident_data.capabilities1 & ATA_SUPPORT_DMA) &&
1702 softc->
flags &= ~ADA_FLAG_CAN_DMA;
1704 if (cgd->
ident_data.support.command2 & ATA_SUPPORT_ADDRESS48) {
1709 softc->
flags &= ~ADA_FLAG_CAN_DMA48;
1713 if (cgd->
ident_data.support.command2 & ATA_SUPPORT_FLUSHCACHE)
1716 softc->
flags &= ~ADA_FLAG_CAN_FLUSHCACHE;
1718 if (cgd->
ident_data.support.command1 & ATA_SUPPORT_POWERMGT)
1721 softc->
flags &= ~ADA_FLAG_CAN_POWERMGT;
1723 if ((cgd->
ident_data.satacapabilities & ATA_SUPPORT_NCQ) &&
1729 if ((cgd->
ident_data.support_dsm & ATA_SUPPORT_DSM_TRIM) &&
1749 ATA_SUPPORT_RCVSND_FPDMA_QUEUED) != 0 &&
1753 softc->
flags &= ~ADA_FLAG_CAN_NCQ_TRIM;
1757 if (cgd->
ident_data.support.command2 & ATA_SUPPORT_CFA)
1760 softc->
flags &= ~ADA_FLAG_CAN_CFA;
1768 if ((cgd->
ident_data.support.extension & ATA_SUPPORT_GENLOG)
1772 softc->
flags &= ~ADA_FLAG_CAN_LOG;
1774 if ((cgd->
ident_data.support3 & ATA_SUPPORT_ZONE_MASK) ==
1775 ATA_SUPPORT_ZONE_HOST_AWARE)
1777 else if (((cgd->
ident_data.support3 & ATA_SUPPORT_ZONE_MASK) ==
1778 ATA_SUPPORT_ZONE_DEV_MANAGED)
1784 if (cgd->
ident_data.support.command1 & ATA_SUPPORT_LOOKAHEAD)
1787 softc->
flags &= ~ADA_FLAG_CAN_RAHEAD;
1789 if (cgd->
ident_data.support.command1 & ATA_SUPPORT_WRITECACHE)
1792 softc->
flags &= ~ADA_FLAG_CAN_WCACHE;
1808 printf(
"adaregister: no getdev CCB, can't register device\n");
1812 softc = (
struct ada_softc *)malloc(
sizeof(*softc), M_DEVBUF,
1815 if (softc == NULL) {
1816 printf(
"adaregister: Unable to probe new device. "
1817 "Unable to allocate softc\n");
1825 printf(
"adaregister: Unable to probe new device. "
1826 "Unable to allocate iosched memory\n");
1827 free(softc, M_DEVBUF);
1831 periph->
softc = softc;
1856 TUNABLE_INT_FETCH(announce_buf, &
quirks);
1860 "kern.cam.ada.%d.read_ahead", periph->
unit_number);
1861 TUNABLE_INT_FETCH(announce_buf, &softc->
read_ahead);
1864 "kern.cam.ada.%d.write_cache", periph->
unit_number);
1865 TUNABLE_INT_FETCH(announce_buf, &softc->
write_cache);
1872 (
"%s: NULL ada_ccb_zone", __func__));
1884 if (cgd->
ident_data.media_rotation_rate == ATA_RATE_NON_ROTATING) {
1885 softc->
flags &= ~ADA_FLAG_ROTATING;
1891 softc->
disk = disk_alloc();
1895 DEVSTAT_ALL_SUPPORTED,
1896 DEVSTAT_TYPE_DIRECT |
1898 DEVSTAT_PRIORITY_DISK);
1906 softc->
disk->d_name =
"ada";
1907 softc->
disk->d_drv1 = periph;
1917 "registration!\n", __func__);
1921 disk_create(softc->
disk, DISK_VERSION);
1926 "%juMB (%ju %u byte sectors)",
1941 taskqueue_enqueue(taskqueue_thread, &softc->
sysctl_task);
1988 uint64_t lastlba = (uint64_t)-1, lbas = 0;
1989 int c, lastcount = 0, off, ranges = 0;
1991 bzero(req,
sizeof(*req));
1992 TAILQ_INIT(&req->bps);
1994 uint64_t lba = bp->bio_pblkno;
1998 if (lba == lastlba) {
1999 c = min(count, ATA_DSM_RANGE_MAX - lastcount);
2001 off = (ranges - 1) * ATA_DSM_RANGE_SIZE;
2002 req->
data[off + 6] = lastcount & 0xff;
2003 req->
data[off + 7] =
2004 (lastcount >> 8) & 0xff;
2011 c = min(count, ATA_DSM_RANGE_MAX);
2012 off = ranges * ATA_DSM_RANGE_SIZE;
2013 req->
data[off + 0] = lba & 0xff;
2014 req->
data[off + 1] = (lba >> 8) & 0xff;
2015 req->
data[off + 2] = (lba >> 16) & 0xff;
2016 req->
data[off + 3] = (lba >> 24) & 0xff;
2017 req->
data[off + 4] = (lba >> 32) & 0xff;
2018 req->
data[off + 5] = (lba >> 40) & 0xff;
2019 req->
data[off + 6] = c & 0xff;
2020 req->
data[off + 7] = (c >> 8) & 0xff;
2033 TAILQ_INSERT_TAIL(&req->bps, bp, bio_queue);
2064 howmany(ranges, ATA_DSM_BLK_RANGES) * ATA_DSM_BLK_SIZE,
2067 ATA_DSM_TRIM, 0, howmany(ranges, ATA_DSM_BLK_RANGES));
2083 howmany(ranges, ATA_DSM_BLK_RANGES) * ATA_DSM_BLK_SIZE,
2086 ATA_SEND_FPDMA_QUEUED,
2088 howmany(ranges, ATA_DSM_BLK_RANGES));
2098 uint64_t lba = bp->bio_pblkno;
2101 bzero(req,
sizeof(*req));
2102 TAILQ_INIT(&req->bps);
2103 TAILQ_INSERT_TAIL(&req->bps, bp, bio_queue);
2122 switch (disk_zone_cmd) {
2123 case DISK_ZONE_OPEN:
2124 return ATA_ZM_OPEN_ZONE;
2125 case DISK_ZONE_CLOSE:
2126 return ATA_ZM_CLOSE_ZONE;
2127 case DISK_ZONE_FINISH:
2128 return ATA_ZM_FINISH_ZONE;
2145 if (bp->bio_cmd != BIO_ZONE) {
2150 softc = periph->
softc;
2152 switch (bp->bio_zone.zone_cmd) {
2153 case DISK_ZONE_OPEN:
2154 case DISK_ZONE_CLOSE:
2155 case DISK_ZONE_FINISH:
2156 case DISK_ZONE_RWP: {
2162 if (zone_sa == -1) {
2164 "cmd %#x to ATA\n", bp->bio_zone.zone_cmd);
2170 lba = bp->bio_zone.zone_params.rwp.id;
2172 if (bp->bio_zone.zone_params.rwp.flags &
2173 DISK_ZONE_RWP_FLAG_ALL)
2192 case DISK_ZONE_REPORT_ZONES: {
2194 uint32_t num_entries, alloc_size;
2195 struct disk_zone_report *rep;
2197 rep = &bp->bio_zone.zone_params.report;
2199 num_entries = rep->entries_allocated;
2200 if (num_entries == 0) {
2202 "Report Zones request\n");
2208 alloc_size = min(alloc_size, softc->
disk->d_maxsize);
2209 rz_ptr = malloc(alloc_size, M_ATADA, M_NOWAIT | M_ZERO);
2210 if (rz_ptr == NULL) {
2212 "for Report Zones request\n");
2222 ATA_ZM_REPORT_ZONES,
2253 bp->bio_bcount = bp->bio_length;
2259 case DISK_ZONE_GET_PARAMS: {
2260 struct disk_zone_disk_params *params;
2262 params = &bp->bio_zone.zone_params.disk_params;
2263 bzero(params,
sizeof(*params));
2267 params->zone_mode = DISK_ZONE_MODE_DRIVE_MANAGED;
2270 params->zone_mode = DISK_ZONE_MODE_HOST_AWARE;
2273 params->zone_mode = DISK_ZONE_MODE_HOST_MANAGED;
2277 params->zone_mode = DISK_ZONE_MODE_NONE;
2282 params->flags |= DISK_ZONE_DISK_URSWRZ;
2286 params->flags |= DISK_ZONE_OPT_SEQ_SET;
2290 params->optimal_nonseq_zones =
2292 params->flags |= DISK_ZONE_OPT_NONSEQ_SET;
2297 params->flags |= DISK_ZONE_MAX_SEQ_SET;
2300 params->flags |= DISK_ZONE_RZ_SUP;
2303 params->flags |= DISK_ZONE_OPEN_SUP;
2306 params->flags |= DISK_ZONE_CLOSE_SUP;
2309 params->flags |= DISK_ZONE_FINISH_SUP;
2312 params->flags |= DISK_ZONE_RWP_SUP;
2330 switch (softc->
state) {
2342 if ((bp->bio_flags & BIO_ORDERED) != 0 ||
2344 softc->
flags &= ~ADA_FLAG_NEED_OTAG;
2350 switch (bp->bio_cmd) {
2354 uint64_t lba = bp->bio_pblkno;
2359 if (bp->bio_cmd == BIO_WRITE) {
2366 data_ptr = bp->bio_data;
2367 if ((bp->bio_flags & (BIO_UNMAPPED|BIO_VLIST)) != 0) {
2372#ifdef CAM_TEST_FAILURE
2384 if (bp->bio_cmd == BIO_READ) {
2385 if (softc->force_read_error) {
2386 softc->force_read_error--;
2389 if (softc->periodic_read_error > 0) {
2390 if (++softc->periodic_read_count >=
2391 softc->periodic_read_error) {
2392 softc->periodic_read_count = 0;
2397 if (softc->force_write_error) {
2398 softc->force_write_error--;
2403 biofinish(bp, NULL, EIO);
2409 KASSERT((bp->bio_flags & BIO_UNMAPPED) == 0 ||
2410 round_page(bp->bio_bcount + bp->bio_ma_offset) /
2411 PAGE_SIZE == bp->bio_ma_n,
2412 (
"Short bio %p", bp));
2423 if (bp->bio_cmd == BIO_READ) {
2434 if (bp->bio_cmd == BIO_READ) {
2442 if (bp->bio_cmd == BIO_READ) {
2454 if (bp->bio_cmd == BIO_READ) {
2462 if (bp->bio_cmd == BIO_READ) {
2485 biofinish(bp, NULL, EOPNOTSUPP);
2510 int error, queue_ccb;
2514 error =
ada_zone_cmd(periph, start_ccb, bp, &queue_ccb);
2516 || (queue_ccb == 0)) {
2517 biofinish(bp, NULL, error);
2524 biofinish(bp, NULL, EOPNOTSUPP);
2531 start_ccb->
ccb_h.ccb_bp = bp;
2556 ATA_SF_ENAB_RCACHE : ATA_SF_DIS_RCACHE, 0, 0);
2560 ATA_SF_ENAB_WCACHE : ATA_SF_DIS_WCACHE, 0, 0);
2569 struct ata_gp_log_dir *log_dir;
2576 log_dir = malloc(
sizeof(*log_dir), M_ATADA, M_NOWAIT|M_ZERO);
2577 if (log_dir == NULL) {
2603 struct ata_identify_log_pages *id_dir;
2605 id_dir = malloc(
sizeof(*id_dir), M_ATADA, M_NOWAIT | M_ZERO);
2606 if (id_dir == NULL) {
2616 ATA_IDENTIFY_DATA_LOG,
2631 struct ata_identify_log_sup_cap *sup_cap;
2633 sup_cap = malloc(
sizeof(*sup_cap), M_ATADA, M_NOWAIT|M_ZERO);
2634 if (sup_cap == NULL) {
2644 ATA_IDENTIFY_DATA_LOG,
2659 struct ata_zoned_info_log *ata_zone;
2661 ata_zone = malloc(
sizeof(*ata_zone), M_ATADA, M_NOWAIT|M_ZERO);
2662 if (ata_zone == NULL) {
2672 ATA_IDENTIFY_DATA_LOG,
2677 (uint8_t *)ata_zone,
2714 bp = (
struct bio *)
ccb->
ccb_h.ccb_bp;
2716 switch (bp->bio_zone.zone_cmd) {
2717 case DISK_ZONE_OPEN:
2718 case DISK_ZONE_CLOSE:
2719 case DISK_ZONE_FINISH:
2722 case DISK_ZONE_REPORT_ZONES: {
2724 struct disk_zone_report *rep;
2727 struct disk_zone_rep_entry *entry;
2728 uint32_t hdr_len, num_avail;
2729 uint32_t num_to_fill, i;
2731 rep = &bp->bio_zone.zone_params.report;
2744 if (avail_len <
sizeof(*hdr)) {
2750 bp->bio_error = EIO;
2751 bp->bio_flags |= BIO_ERROR;
2752 bp->bio_resid = bp->bio_bcount;
2756 hdr_len = le32dec(hdr->
length);
2758 rep->entries_available = hdr_len /
sizeof(*desc);
2760 rep->entries_available = 0;
2768 rep->header.maximum_lba = le64dec(hdr->
maximum_lba);
2774 rep->entries_filled = 0;
2775 bp->bio_resid = bp->bio_bcount;
2779 num_avail = min((avail_len -
sizeof(*hdr)) /
sizeof(*desc),
2780 hdr_len /
sizeof(*desc));
2784 if (num_avail == 0) {
2785 rep->entries_filled = 0;
2786 bp->bio_resid = bp->bio_bcount;
2790 num_to_fill = min(num_avail, rep->entries_allocated);
2795 if (num_to_fill == 0) {
2796 rep->entries_filled = 0;
2797 bp->bio_resid = bp->bio_bcount;
2801 for (i = 0, desc = &hdr->
desc_list[0], entry=&rep->entries[0];
2802 i < num_to_fill; i++, desc++, entry++) {
2813 entry->zone_condition =
2820 entry->write_pointer_lba =
2823 rep->entries_filled = num_to_fill;
2830 bp->bio_resid = bp->bio_bcount - (num_to_fill *
sizeof(*entry));
2833 case DISK_ZONE_GET_PARAMS:
2840 panic(
"%s: Invalid zone command %d", __func__,
2841 bp->bio_zone.zone_cmd);
2845 if (bp->bio_zone.zone_cmd == DISK_ZONE_REPORT_ZONES)
2859 ataio = &done_ccb->
ataio;
2874 bp = (
struct bio *)done_ccb->
ccb_h.ccb_bp;
2877 if (error == ERESTART) {
2898 softc->
flags &= ~ADA_FLAG_CAN_NCQ_TRIM;
2904 panic(
"REQ_CMP with QFRZN");
2908 bp->bio_error = error;
2910 bp->bio_resid = bp->bio_bcount;
2911 bp->bio_flags |= BIO_ERROR;
2913 if (bp->bio_cmd == BIO_ZONE)
2918 bp->bio_resid = ataio->
resid;
2920 if ((bp->bio_resid > 0)
2921 && (bp->bio_cmd != BIO_ZONE))
2922 bp->bio_flags |= BIO_ERROR;
2937 KASSERT(softc->
refcount >= 1, (
"adadone softc %p refcount %d", softc, softc->
refcount));
2944 TAILQ_CONCAT(&queue, &softc->
trim_req.bps, bio_queue);
2958 while ((bp1 = TAILQ_FIRST(&queue)) != NULL) {
2959 TAILQ_REMOVE(&queue, bp1, bio_queue);
2960 bp1->bio_error = error;
2962 bp1->bio_flags |= BIO_ERROR;
2963 bp1->bio_resid = bp1->bio_bcount;
2978 if (
adaerror(done_ccb, 0, 0) == ERESTART) {
3010 if (
adaerror(done_ccb, 0, 0) == ERESTART) {
3058 ((ATA_IDENTIFY_DATA_LOG + 1) *
sizeof(uint16_t)))
3060 ATA_GP_LOG_DIR_VERSION)
3062 (ATA_IDENTIFY_DATA_LOG *
3063 sizeof(uint16_t)) -
sizeof(uint16_t)]) > 0)){
3066 softc->
flags &= ~ADA_FLAG_CAN_IDLOG;
3071 if (error == ERESTART)
3073 else if (error != 0) {
3110 off_t entries_offset, max_entries;
3125 __offsetof(
struct ata_identify_log_pages,entries);
3130 && (softc->
ata_iddir.entry_count > 0)) {
3133 num_entries = softc->
ata_iddir.entry_count;
3134 num_entries = min(num_entries,
3136 for (i = 0; i < num_entries &&
3137 i < max_entries; i++) {
3157 if (error == ERESTART)
3159 else if (error != 0) {
3167 softc->
flags &= ~ADA_FLAG_CAN_IDLOG;
3197 struct ata_identify_log_sup_cap *sup_cap;
3200 sup_cap = (
struct ata_identify_log_sup_cap *)
3204 __offsetof(
struct ata_identify_log_sup_cap,
3205 sup_zac_cap) + 1 +
sizeof(sup_cap->sup_zac_cap);
3206 if (valid_len >= needed_size) {
3207 uint64_t zoned, zac_cap;
3209 zoned = le64dec(sup_cap->zoned_cap);
3210 if (zoned & ATA_ZONED_VALID) {
3216 if ((zoned & ATA_ZONED_MASK) ==
3217 ATA_SUPPORT_ZONE_HOST_AWARE)
3220 else if ((zoned & ATA_ZONED_MASK) ==
3221 ATA_SUPPORT_ZONE_DEV_MANAGED)
3226 zac_cap = le64dec(sup_cap->sup_zac_cap);
3227 if (zac_cap & ATA_SUP_ZAC_CAP_VALID) {
3228 if (zac_cap & ATA_REPORT_ZONES_SUP)
3231 if (zac_cap & ATA_ND_OPEN_ZONE_SUP)
3234 if (zac_cap & ATA_ND_CLOSE_ZONE_SUP)
3237 if (zac_cap & ATA_ND_FINISH_ZONE_SUP)
3240 if (zac_cap & ATA_ND_RWP_SUP)
3259 if (error == ERESTART)
3261 else if (error != 0) {
3267 softc->
flags &= ~ADA_FLAG_CAN_SUPCAP;
3271 softc->
zone_flags &= ~ADA_ZONE_FLAG_SUP_MASK;
3299 struct ata_zoned_info_log *zi_log;
3303 zi_log = (
struct ata_zoned_info_log *)ataio->
data_ptr;
3306 needed_size = __offsetof(
struct ata_zoned_info_log,
3307 version_info) + 1 +
sizeof(zi_log->version_info);
3308 if (valid_len >= needed_size) {
3311 tmpvar = le64dec(zi_log->zoned_cap);
3312 if (tmpvar & ATA_ZDI_CAP_VALID) {
3313 if (tmpvar & ATA_ZDI_CAP_URSWRZ)
3318 ~ADA_ZONE_FLAG_URSWRZ;
3320 tmpvar = le64dec(zi_log->optimal_seq_zones);
3321 if (tmpvar & ATA_ZDI_OPT_SEQ_VALID) {
3325 ATA_ZDI_OPT_SEQ_MASK);
3328 ~ADA_ZONE_FLAG_OPT_SEQ_SET;
3332 tmpvar =le64dec(zi_log->optimal_nonseq_zones);
3333 if (tmpvar & ATA_ZDI_OPT_NS_VALID) {
3337 (tmpvar & ATA_ZDI_OPT_NS_MASK);
3340 ~ADA_ZONE_FLAG_OPT_NONSEQ_SET;
3344 tmpvar = le64dec(zi_log->max_seq_req_zones);
3345 if (tmpvar & ATA_ZDI_MAX_SEQ_VALID) {
3349 (tmpvar & ATA_ZDI_MAX_SEQ_MASK);
3352 ~ADA_ZONE_FLAG_MAX_SEQ_SET;
3359 if (error == ERESTART)
3361 else if (error != 0) {
3362 softc->
flags &= ~ADA_FLAG_CAN_ZONE;
3363 softc->
flags &= ~ADA_ZONE_FLAG_SET_MASK;
3424 u_int64_t lbasize48;
3426 u_int maxio, d_flags;
3430 if ((cgd->
ident_data.atavalid & ATA_FLAG_54_58) &&
3437 ((u_int32_t)cgd->
ident_data.current_size_2 << 16);
3445 lbasize = (u_int32_t)cgd->
ident_data.lba_size_1 |
3446 ((u_int32_t)cgd->
ident_data.lba_size_2 << 16);
3453 lbasize48 = ((u_int64_t)cgd->
ident_data.lba_size48_1) |
3454 ((u_int64_t)cgd->
ident_data.lba_size48_2 << 16) |
3455 ((u_int64_t)cgd->
ident_data.lba_size48_3 << 32) |
3456 ((u_int64_t)cgd->
ident_data.lba_size48_4 << 48);
3457 if ((cgd->
ident_data.support.command2 & ATA_SUPPORT_ADDRESS48) &&
3464 else if (maxio > maxphys)
3471 maxio = min(maxio, 128 * 1024);
3472 softc->
disk->d_maxsize = maxio;
3473 d_flags = DISKFLAG_DIRECT_COMPLETION | DISKFLAG_CANZONE;
3475 d_flags |= DISKFLAG_CANFLUSHCACHE;
3477 d_flags |= DISKFLAG_CANDELETE;
3482 d_flags |= DISKFLAG_CANDELETE;
3485 softc->
disk->d_delmaxsize = maxio;
3487 d_flags |= DISKFLAG_UNMAPPED_BIO;
3490 softc->
disk->d_flags = d_flags;
3501 tmpsize = MIN(
sizeof(softc->
disk->d_descr) - 1,
3504 softc->
disk->d_descr[tmpsize] =
'\0';
3506 tmpsize = MIN(
sizeof(softc->
disk->d_ident) - 1,
3509 softc->
disk->d_ident[tmpsize] =
'\0';
3516 softc->
disk->d_stripesize =
3518 softc->
disk->d_stripeoffset = (softc->
disk->d_stripesize -
3520 softc->
disk->d_stripesize;
3522 softc->
disk->d_stripesize = 4096;
3523 softc->
disk->d_stripeoffset = 0;
3527 softc->
disk->d_rotation_rate = cgd->
ident_data.media_rotation_rate;
3528 snprintf(softc->
disk->d_attachment,
sizeof(softc->
disk->d_attachment),
3541 softc->
flags &= ~ADA_FLAG_WAS_OTAG;
3565 if (SCHEDULER_STOPPED()) {
3600 softc->
disk->d_devstat);
3635 if (cmd == ATA_IDLE_IMMEDIATE) {
3636 memset(&local_ccb, 0,
sizeof(local_ccb));
3650 softc->
disk->d_devstat);
3653 "Failed to read current power mode\n");
3655 mode = local_ccb.res.sector_count;
3659 "disk power mode 0x%02x\n", mode);
3663 case ATA_PM_STANDBY:
3664 case ATA_PM_STANDBY_Y:
3667 "already spun down\n");
3680 memset(&local_ccb, 0,
sizeof(local_ccb));
3695 softc->
disk->d_devstat);
3724 how = (howto & (RB_HALT | RB_POWEROFF | RB_POWERCYCLE)) ?
3725 ATA_STANDBY_IMMEDIATE : ATA_IDLE_IMMEDIATE;
void ata_zac_mgmt_out(struct ccb_ataio *ataio, uint32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), int use_ncq, uint8_t zm_action, uint64_t zone_id, uint8_t zone_flags, uint16_t sector_count, uint8_t *data_ptr, uint32_t dxfer_len, uint32_t timeout)
void ata_zac_mgmt_in(struct ccb_ataio *ataio, uint32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), int use_ncq, uint8_t zm_action, uint64_t zone_id, uint8_t zone_flags, uint8_t *data_ptr, uint32_t dxfer_len, uint32_t timeout)
uint64_t ata_logical_sector_offset(struct ata_params *ident_data)
void ata_read_log(struct ccb_ataio *ataio, uint32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), uint32_t log_address, uint32_t page_number, uint16_t block_count, uint32_t protocol, uint8_t *data_ptr, uint32_t dxfer_len, uint32_t timeout)
void ata_48bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint16_t features, uint64_t lba, uint16_t sector_count)
int ata_identify_match(caddr_t identbuffer, caddr_t table_entry)
uint32_t ata_logical_sector_size(struct ata_params *ident_data)
void ata_ncq_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint64_t lba, uint16_t sector_count)
uint64_t ata_physical_sector_size(struct ata_params *ident_data)
void ata_28bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint8_t features, uint32_t lba, uint8_t sector_count)
#define CAM_ATAIO_NEEDRESULT
static disk_strategy_t adastrategy
static int ada_send_ordered
static int adazonemodesysctl(SYSCTL_HANDLER_ARGS)
static int adagetattr(struct bio *bp)
#define ADA_DEFAULT_TIMEOUT
static const char * ada_delete_method_names[]
static int adazonesupsysctl(SYSCTL_HANDLER_ARGS)
static void adadiskgonecb(struct disk *dp)
static int ada_write_cache
#define ADA_DEFAULT_RETRY
static periph_ctor_t adaregister
static int ada_enable_biospeedup
static int adabitsysctl(SYSCTL_HANDLER_ARGS)
static periph_start_t adastart
SYSCTL_INT(_kern_cam_ada, OID_AUTO, retry_count, CTLFLAG_RWTUN, &ada_retry_count, 0, "Normal I/O retry count")
static periph_oninv_t adaoninvalidate
static int adaflagssysctl(SYSCTL_HANDLER_ARGS)
static void adasuspend(void *arg)
static void adaresume(void *arg)
static void adadone(struct cam_periph *periph, union ccb *done_ccb)
static uma_zone_t ada_ccb_zone
static void adaschedule(struct cam_periph *periph)
#define ADA_ORDEREDTAG_INTERVAL
static void adaflush(void)
static void adasysctlinit(void *context, int pending)
static int adaopen(struct disk *dp)
@ ADA_FLAG_CAN_FLUSHCACHE
static int ada_zone_bio_to_ata(int disk_zone_cmd)
static MALLOC_DEFINE(M_ATADA, "ata_da", "ata_da buffers")
static SYSCTL_NODE(_kern_cam, OID_AUTO, ada, CTLFLAG_RD|CTLFLAG_MPSAFE, 0, "CAM Direct Access Disk driver")
static void ada_ncq_dsmtrim(struct ada_softc *softc, struct bio *bp, struct ccb_ataio *ataio)
static int ada_dsmtrim_req_create(struct ada_softc *softc, struct bio *bp, struct trim_request *req)
static int ada_read_ahead
static int adaerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
static int ada_retry_count
static void adaspindown(uint8_t cmd, int flags)
static periph_dtor_t adacleanup
static struct periph_driver adadriver
static struct ada_zone_desc ada_zone_desc_table[]
#define ADA_DEFAULT_SPINDOWN_SHUTDOWN
static int ada_default_timeout
static periph_init_t adainit
@ ADA_ZONE_FLAG_MAX_SEQ_SET
@ ADA_ZONE_FLAG_FINISH_SUP
@ ADA_ZONE_FLAG_OPT_SEQ_SET
@ ADA_ZONE_FLAG_OPT_NONSEQ_SET
@ ADA_ZONE_FLAG_CLOSE_SUP
static struct ada_quirk_entry ada_quirk_table[]
static void adaprobedone(struct cam_periph *periph, union ccb *ccb)
static void adasetflags(struct ada_softc *softc, struct ccb_getdev *cgd)
static int ada_spindown_shutdown
static int ada_spindown_suspend
#define ADA_DEFAULT_SEND_ORDERED
static int adadeletemethodsysctl(SYSCTL_HANDLER_ARGS)
@ ADA_DELETE_NCQ_DSM_TRIM
static void ada_cfaerase(struct ada_softc *softc, struct bio *bp, struct ccb_ataio *ataio)
static void adazonedone(struct cam_periph *periph, union ccb *ccb)
static void ada_dsmtrim(struct ada_softc *softc, struct bio *bp, struct ccb_ataio *ataio)
static callout_func_t adasendorderedtag
#define ADA_DEFAULT_READ_AHEAD
static void adaasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
static int adaclose(struct disk *dp)
#define ADA_DEFAULT_SPINDOWN_SUSPEND
PERIPHDRIVER_DECLARE(ada, adadriver)
static int ada_enable_uma_ccbs
#define ADA_ANNOUNCETMP_SZ
static int ada_zone_cmd(struct cam_periph *periph, union ccb *ccb, struct bio *bp, int *queue_ccb)
static void adashutdown(void *arg, int howto)
static void adasetdeletemethod(struct ada_softc *softc)
#define ADA_DEFAULT_WRITE_CACHE
static void adasetgeom(struct ada_softc *softc, struct ccb_getdev *cgd)
#define ATA_MAX_28BIT_LBA
caddr_t cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries, int entry_size, cam_quirkmatch_t *comp_func)
#define CAM_PRIORITY_NORMAL
static __inline void cam_fill_ataio(struct ccb_ataio *ataio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int32_t flags, u_int tag_action __unused, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int32_t timeout)
#define XPORT_DEVSTAT_TYPE(t)
#define CDAI_TYPE_PHYS_PATH
#define CAM_DEBUG(path, flag, printfargs)
struct bio * cam_iosched_next_trim(struct cam_iosched_softc *isc)
void cam_iosched_fini(struct cam_iosched_softc *isc)
void cam_iosched_flush(struct cam_iosched_softc *isc, struct devstat *stp, int err)
void cam_iosched_trim_done(struct cam_iosched_softc *isc)
int cam_iosched_init(struct cam_iosched_softc **iscp, struct cam_periph *periph)
void cam_iosched_put_back_trim(struct cam_iosched_softc *isc, struct bio *bp)
int cam_iosched_bio_complete(struct cam_iosched_softc *isc, struct bio *bp, union ccb *done_ccb)
void cam_iosched_sysctl_init(struct cam_iosched_softc *isc, struct sysctl_ctx_list *ctx, struct sysctl_oid *node)
void cam_iosched_schedule(struct cam_iosched_softc *isc, struct cam_periph *periph)
void cam_iosched_set_sort_queue(struct cam_iosched_softc *isc, int val)
void cam_iosched_submit_trim(struct cam_iosched_softc *isc)
struct bio * cam_iosched_next_bio(struct cam_iosched_softc *isc)
void cam_iosched_queue_work(struct cam_iosched_softc *isc, struct bio *bp)
void cam_periph_release_locked(struct cam_periph *periph)
u_int32_t cam_release_devq(struct cam_path *path, u_int32_t relsim_flags, u_int32_t openings, u_int32_t arg, int getcount_only)
int cam_periph_acquire(struct cam_periph *periph)
void cam_periph_async(struct cam_periph *periph, u_int32_t code, struct cam_path *path, void *arg)
void cam_periph_release(struct cam_periph *periph)
void cam_periph_unhold(struct cam_periph *periph)
int cam_periph_hold(struct cam_periph *periph, int priority)
int cam_periph_runccb(union ccb *ccb, int(*error_routine)(union ccb *ccb, cam_flags camflags, u_int32_t sense_flags), cam_flags camflags, u_int32_t sense_flags, struct devstat *ds)
int cam_periph_invalidate_sysctl(SYSCTL_HANDLER_ARGS)
int cam_periph_error(union ccb *ccb, cam_flags camflags, u_int32_t sense_flags)
cam_status cam_periph_alloc(periph_ctor_t *periph_ctor, periph_oninv_t *periph_oninvalidate, periph_dtor_t *periph_dtor, periph_start_t *periph_start, char *name, cam_periph_type type, struct cam_path *path, ac_callback_t *ac_callback, ac_code code, void *arg)
cam_status periph_ctor_t(struct cam_periph *periph, void *arg)
#define CAM_PERIPH_INVALID
void periph_oninv_t(struct cam_periph *periph)
#define CAM_PERIPH_FOREACH(periph, driver)
#define cam_periph_lock(periph)
union ccb * cam_periph_getccb(struct cam_periph *periph, u_int32_t priority)
#define cam_periph_owned(periph)
#define cam_periph_unlock(periph)
static __inline struct mtx * cam_periph_mtx(struct cam_periph *periph)
void periph_dtor_t(struct cam_periph *periph)
void periph_start_t(struct cam_periph *periph, union ccb *start_ccb)
#define cam_periph_sleep(periph, chan, priority, wmesg, timo)
void() periph_init_t(void)
TAILQ_HEAD(ccb_hdr_tailq, ccb_hdr)
static __inline bool cam_sim_pollable(const struct cam_sim *sim)
void xpt_schedule(struct cam_periph *periph, u_int32_t new_priority)
int xpt_getattr(char *buf, size_t len, const char *attr, struct cam_path *path)
void xpt_print(struct cam_path *path, const char *fmt,...)
void xpt_setup_ccb(struct ccb_hdr *ccb_h, struct cam_path *path, u_int32_t priority)
void xpt_action(union ccb *start_ccb)
void xpt_announce_quirks_sbuf(struct cam_periph *periph, struct sbuf *sb, int quirks, char *bit_string)
cam_status xpt_register_async(int event, ac_callback_t *cbfunc, void *cbarg, struct cam_path *path)
struct cam_periph * xpt_path_periph(struct cam_path *path)
void xpt_release_ccb(union ccb *free_ccb)
void xpt_announce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb, char *announce_string)
static void xpt_path_inq(struct ccb_pathinq *cpi, struct cam_path *path)
#define SIP_MEDIA_REMOVABLE
#define SRZ_ZONE_COND_SHIFT
#define SRZ_ZONE_COND_MASK
struct scsi_inquiry_pattern inq_pat
uint64_t optimal_nonseq_zones
struct ata_identify_log_pages ata_iddir
char announce_temp[ADA_ANNOUNCETMP_SZ]
uint64_t optimal_seq_zones
struct ata_gp_log_dir ata_logdir
struct cam_iosched_softc * cam_iosched
struct sysctl_oid * sysctl_tree
ada_delete_methods delete_method
struct disk_params params
struct callout sendordered_c
ada_zone_flags zone_flags
struct trim_request trim_req
char announce_buffer[ADA_ANNOUNCE_SZ]
struct sysctl_ctx_list sysctl_ctx
u_int8_t sector_count_exp
struct ata_params ident_data
uint8_t write_pointer_lba[8]
uint8_t zone_start_lba[8]
struct scsi_report_zones_desc desc_list[]
uint8_t data[TRIM_MAX_RANGES *ATA_DSM_RANGE_SIZE]