39#include <sys/kernel.h>
41#include <sys/sysctl.h>
42#include <sys/taskqueue.h>
46#include <sys/devicestat.h>
47#include <sys/eventhandler.h>
48#include <sys/malloc.h>
50#include <sys/endian.h>
52#include <sys/reboot.h>
55#include <geom/geom_disk.h>
56#include <machine/atomic.h>
128#define DA_FLAG_STRING \
133 "\004PACK_REMOVABLE" \
146 "\021CAN_ATA_IDLOG" \
147 "\022CAN_ATA_SUPACP" \
166#define DA_Q_BIT_STRING \
168 "\001NO_SYNC_CACHE" \
295 {
"NONE",
"DISABLE",
"ATA_TRIM",
"UNMAP",
"WS16",
"WS10",
"ZERO" };
297 {
"NONE",
"DISABLED",
"ATA TRIM",
"UNMAP",
"WRITE SAME(16) with UNMAP",
298 "WRITE SAME(10) with UNMAP",
"ZERO" };
301#define ccb_state ppriv_field0
302#define ccb_bp ppriv_ptr1
314#define UNMAP_RANGE_MAX 0xffffffff
315#define UNMAP_HEAD_SIZE 8
316#define UNMAP_RANGE_SIZE 16
317#define UNMAP_MAX_RANGES 2048
318#define UNMAP_BUF_SIZE ((UNMAP_MAX_RANGES * UNMAP_RANGE_SIZE) + \
321#define WS10_MAX_BLKS 0xffff
322#define WS16_MAX_BLKS 0xffffffff
323#define ATA_TRIM_MAX_RANGES ((UNMAP_BUF_SIZE / \
324 (ATA_DSM_RANGE_SIZE * ATA_DSM_BLK_SIZE)) * ATA_DSM_BLK_SIZE)
326#define DA_WORK_TUR (1 << 16)
348 int minimum_cmd_size;
352 int delete_available;
356 struct ata_gp_log_dir ata_logdir;
357 int valid_logdir_len;
358 struct ata_identify_log_pages ata_iddir;
360 uint64_t optimal_seq_zones;
361 uint64_t optimal_nonseq_zones;
362 uint64_t max_seq_zones;
364 uint32_t unmap_max_ranges;
365 uint32_t unmap_max_lba;
367 uint32_t unmap_gran_align;
368 uint64_t ws_max_blks;
370 uint64_t trim_ranges;
378 struct task sysctl_task;
379 struct sysctl_ctx_list sysctl_ctx;
380 struct sysctl_oid *sysctl_tree;
381 struct callout sendordered_c;
385 struct callout mediapoll_c;
388 struct sysctl_ctx_list sysctl_stats_ctx;
389 struct sysctl_oid *sysctl_stats_tree;
394#define DA_ANNOUNCETMP_SZ 160
396#define DA_ANNOUNCE_SZ 400
400#define dadeleteflag(softc, delete_method, enable) \
402 softc->delete_available |= (1 << delete_method); \
404 softc->delete_available &= ~(1 << delete_method); \
1474static void daasync(
void *callback_arg, u_int32_t code,
1499 union ccb *done_ccb);
1501 union ccb *done_ccb);
1503 union ccb *done_ccb);
1505 union ccb *done_ccb);
1507 union ccb *done_ccb);
1509 union ccb *done_ccb);
1511 union ccb *done_ccb);
1513 union ccb *done_ccb);
1515 union ccb *done_ccb);
1517 union ccb *done_ccb);
1519 union ccb *done_ccb);
1521 union ccb *done_ccb);
1523 union ccb *done_ccb);
1525 u_int32_t sense_flags);
1536#ifndef DA_DEFAULT_POLL_PERIOD
1537#define DA_DEFAULT_POLL_PERIOD 3
1540#ifndef DA_DEFAULT_TIMEOUT
1541#define DA_DEFAULT_TIMEOUT 60
1544#ifndef DA_DEFAULT_SOFTTIMEOUT
1545#define DA_DEFAULT_SOFTTIMEOUT 0
1548#ifndef DA_DEFAULT_RETRY
1549#define DA_DEFAULT_RETRY 4
1552#ifndef DA_DEFAULT_SEND_ORDERED
1553#define DA_DEFAULT_SEND_ORDERED 1
1565static SYSCTL_NODE(_kern_cam, OID_AUTO, da, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
1566 "CAM Direct Access Disk driver");
1571SYSCTL_INT(_kern_cam_da, OID_AUTO, default_timeout, CTLFLAG_RWTUN,
1575SYSCTL_INT(_kern_cam_da, OID_AUTO, disable_wp_detection, CTLFLAG_RWTUN,
1577 "Disable detection of write-protected disks");
1578SYSCTL_INT(_kern_cam_da, OID_AUTO, enable_biospeedup, CTLFLAG_RDTUN,
1580SYSCTL_INT(_kern_cam_da, OID_AUTO, enable_uma_ccbs, CTLFLAG_RWTUN,
1584 CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, 0,
1586 "Soft I/O timeout (ms)");
1601#ifndef DA_ORDEREDTAG_INTERVAL
1602#define DA_ORDEREDTAG_INTERVAL 4
1608 TAILQ_HEAD_INITIALIZER(
dadriver.units), 0
1621#if defined(DA_TRACK_REFS) || defined(INVARIANTS)
1623#ifndef DA_TRACK_REFS
1624#define DA_TRACK_REFS 1
1627#if DA_TRACK_REFS > 1
1628static const char *da_ref_text[] = {
1641#define DA_PERIPH_PRINT(periph, msg, args...) \
1642 CAM_PERIPH_PRINT(periph, msg, ##args)
1644#define DA_PERIPH_PRINT(periph, msg, args...)
1651 panic(
"Bad token value passed in %d\n", token);
1659 token_sanity(token);
1660 DA_PERIPH_PRINT(periph,
"Holding device %s (%d): %d\n",
1661 da_ref_text[token], token, err);
1666 cnt = atomic_fetchadd_int(&softc->ref_flags[token], 1);
1668 panic(
"Re-holding for reason %d, cnt = %d", token, cnt);
1679 token_sanity(token);
1680 DA_PERIPH_PRINT(periph,
"Unholding device %s (%d)\n",
1681 da_ref_text[token], token);
1682 cnt = atomic_fetchadd_int(&softc->ref_flags[token], -1);
1684 panic(
"Unholding %d with cnt = %d", token, cnt);
1693 token_sanity(token);
1694 DA_PERIPH_PRINT(periph,
"acquiring device %s (%d): %d\n",
1695 da_ref_text[token], token, err);
1700 cnt = atomic_fetchadd_int(&softc->ref_flags[token], 1);
1702 panic(
"Re-refing for reason %d, cnt = %d", token, cnt);
1713 token_sanity(token);
1714 DA_PERIPH_PRINT(periph,
"releasing device %s (%d)\n",
1715 da_ref_text[token], token);
1716 cnt = atomic_fetchadd_int(&softc->ref_flags[token], -1);
1718 panic(
"Releasing %d with cnt = %d", token, cnt);
1728 token_sanity(token);
1729 DA_PERIPH_PRINT(periph,
"releasing device (locked) %s (%d)\n",
1730 da_ref_text[token], token);
1731 cnt = atomic_fetchadd_int(&softc->ref_flags[token], -1);
1733 panic(
"releasing (locked) %d with cnt = %d", token, cnt);
1737#define cam_periph_hold POISON
1738#define cam_periph_unhold POISON
1739#define cam_periph_acquire POISON
1740#define cam_periph_release POISON
1741#define cam_periph_release_locked POISON
1744#define da_periph_hold(periph, prio, token) cam_periph_hold((periph), (prio))
1745#define da_periph_unhold(periph, token) cam_periph_unhold((periph))
1746#define da_periph_acquire(periph, token) cam_periph_acquire((periph))
1747#define da_periph_release(periph, token) cam_periph_release((periph))
1748#define da_periph_release_locked(periph, token) cam_periph_release_locked((periph))
1780 xpt_print(periph->
path,
"unable to retrieve capacity data\n");
1790 softc->flags &= ~DA_FLAG_PACK_INVALID;
1828 softc->disk->d_devstat);
1829 softc->flags &= ~DA_FLAG_DIRTY;
1847 softc->disk->d_devstat->flags |= DEVSTAT_BS_UNAVAILABLE;
1849 softc->flags &= ~DA_FLAG_OPEN;
1850 while (
softc->refcount != 0)
1879 periph = (
struct cam_periph *)bp->bio_disk->d_drv1;
1889 biofinish(bp, NULL, ENXIO);
1900 if (bp->bio_cmd == BIO_ZONE)
1901 bp->bio_flags |= BIO_ORDERED;
1918dadump(
void *arg,
void *
virtual, vm_offset_t physical, off_t offset,
size_t length)
1928 periph = dp->d_drv1;
1930 secsize = softc->params.secsize;
1935 memset(&csio, 0,
sizeof(csio));
1945 softc->minimum_cmd_size,
1948 (u_int8_t *)
virtual,
1955 printf(
"Aborting dump due to I/O error.\n");
1988 return (EJUSTRETURN);
1990 periph = (
struct cam_periph *)bp->bio_disk->d_drv1;
1992 ret =
xpt_getattr(bp->bio_data, bp->bio_length, bp->bio_attribute,
1996 bp->bio_completed = bp->bio_length;
2006 sizeof(
struct ccb_scsiio), NULL, NULL, NULL, NULL,
2016 printf(
"da: Failed to attach master async callback "
2017 "due to status 0x%x!\n", status);
2020 if ((EVENTHANDLER_REGISTER(shutdown_post_sync,
dashutdown,
2021 NULL, SHUTDOWN_PRI_DEFAULT)) == NULL)
2022 printf(
"dainit: shutdown event registration failed!\n");
2054 softc->invalidations++;
2068 disk_gone(softc->disk);
2087 if (sysctl_ctx_free(&softc->sysctl_stats_ctx) != 0)
2089 "can't remove sysctl stats context\n");
2091 if (sysctl_ctx_free(&softc->sysctl_ctx) != 0)
2093 "can't remove sysctl context\n");
2096 callout_drain(&softc->mediapoll_c);
2097 disk_destroy(softc->disk);
2098 callout_drain(&softc->sendordered_c);
2099 free(softc, M_DEVBUF);
2144 printf(
"daasync: Unable to attach to new device "
2145 "due to status 0x%x\n", status);
2152 buftype = (uintptr_t)arg;
2156 softc = periph->
softc;
2157 disk_attr_changed(softc->disk,
"GEOM::physpath",
2165 int error_code, sense_key, asc, ascq;
2176 &error_code, &sense_key, &asc, &ascq)) {
2177 if (asc == 0x2A && ascq == 0x09) {
2179 "Capacity data has changed\n");
2181 softc->flags &= ~DA_FLAG_PROBED;
2183 }
else if (asc == 0x28 && ascq == 0x00) {
2185 softc->flags &= ~DA_FLAG_PROBED;
2186 disk_media_changed(softc->disk, M_NOWAIT);
2187 }
else if (asc == 0x3F && ascq == 0x03) {
2189 "INQUIRY data has changed\n");
2191 softc->flags &= ~DA_FLAG_PROBED;
2224 LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
2245 char tmpstr[32], tmpstr2[16];
2258 snprintf(tmpstr,
sizeof(tmpstr),
"CAM DA unit %d", periph->
unit_number);
2259 snprintf(tmpstr2,
sizeof(tmpstr2),
"%d", periph->
unit_number);
2261 sysctl_ctx_init(&softc->sysctl_ctx);
2265 softc->sysctl_tree = SYSCTL_ADD_NODE_WITH_LABEL(&softc->sysctl_ctx,
2266 SYSCTL_STATIC_CHILDREN(_kern_cam_da), OID_AUTO, tmpstr2,
2267 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, tmpstr,
"device_index");
2268 if (softc->sysctl_tree == NULL) {
2269 printf(
"dasysctlinit: unable to allocate sysctl tree\n");
2278 SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
2279 OID_AUTO,
"delete_method",
2280 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
2282 "BIO_DELETE execution method");
2283 SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
2284 OID_AUTO,
"delete_max",
2285 CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE,
2287 "Maximum BIO_DELETE size");
2288 SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
2289 OID_AUTO,
"minimum_cmd_size",
2290 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
2292 "Minimum CDB size");
2293 SYSCTL_ADD_UQUAD(&softc->sysctl_ctx,
2294 SYSCTL_CHILDREN(softc->sysctl_tree), OID_AUTO,
2295 "trim_count", CTLFLAG_RD, &softc->trim_count,
2296 "Total number of unmap/dsm commands sent");
2297 SYSCTL_ADD_UQUAD(&softc->sysctl_ctx,
2298 SYSCTL_CHILDREN(softc->sysctl_tree), OID_AUTO,
2299 "trim_ranges", CTLFLAG_RD, &softc->trim_ranges,
2300 "Total number of ranges in unmap/dsm commands");
2301 SYSCTL_ADD_UQUAD(&softc->sysctl_ctx,
2302 SYSCTL_CHILDREN(softc->sysctl_tree), OID_AUTO,
2303 "trim_lbas", CTLFLAG_RD, &softc->trim_lbas,
2304 "Total lbas in the unmap/dsm commands sent");
2306 SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
2307 OID_AUTO,
"zone_mode",
2308 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
2311 SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
2312 OID_AUTO,
"zone_support",
2313 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
2316 SYSCTL_ADD_UQUAD(&softc->sysctl_ctx,
2317 SYSCTL_CHILDREN(softc->sysctl_tree), OID_AUTO,
2318 "optimal_seq_zones", CTLFLAG_RD, &softc->optimal_seq_zones,
2319 "Optimal Number of Open Sequential Write Preferred Zones");
2320 SYSCTL_ADD_UQUAD(&softc->sysctl_ctx,
2321 SYSCTL_CHILDREN(softc->sysctl_tree), OID_AUTO,
2322 "optimal_nonseq_zones", CTLFLAG_RD,
2323 &softc->optimal_nonseq_zones,
2324 "Optimal Number of Non-Sequentially Written Sequential Write "
2326 SYSCTL_ADD_UQUAD(&softc->sysctl_ctx,
2327 SYSCTL_CHILDREN(softc->sysctl_tree), OID_AUTO,
2328 "max_seq_zones", CTLFLAG_RD, &softc->max_seq_zones,
2329 "Maximum Number of Open Sequential Write Required Zones");
2331 SYSCTL_ADD_INT(&softc->sysctl_ctx,
2332 SYSCTL_CHILDREN(softc->sysctl_tree),
2336 &softc->error_inject,
2338 "error_inject leaf");
2340 SYSCTL_ADD_INT(&softc->sysctl_ctx,
2341 SYSCTL_CHILDREN(softc->sysctl_tree),
2347 "DIF protection type");
2349 SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
2350 OID_AUTO,
"flags", CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
2353 SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
2354 OID_AUTO,
"rotating", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
2356 "Rotating media *DEPRECATED* gone in FreeBSD 14");
2357 SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
2358 OID_AUTO,
"unmapped_io", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
2360 "Unmapped I/O support *DEPRECATED* gone in FreeBSD 14");
2362#ifdef CAM_TEST_FAILURE
2363 SYSCTL_ADD_PROC(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
2364 OID_AUTO,
"invalidate", CTLTYPE_U64 | CTLFLAG_RW | CTLFLAG_MPSAFE,
2366 "Write 1 to invalidate the drive immediately");
2372 memset(&
cts, 0,
sizeof (
cts));
2386 softc->wwpn = fc->
wwpn;
2387 SYSCTL_ADD_UQUAD(&softc->sysctl_ctx,
2388 SYSCTL_CHILDREN(softc->sysctl_tree),
2389 OID_AUTO,
"wwpn", CTLFLAG_RD,
2390 &softc->wwpn,
"World Wide Port Name");
2399 softc->sysctl_stats_tree = SYSCTL_ADD_NODE(&softc->sysctl_stats_ctx,
2400 SYSCTL_CHILDREN(softc->sysctl_tree), OID_AUTO,
"stats",
2401 CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
"Statistics");
2402 SYSCTL_ADD_INT(&softc->sysctl_stats_ctx,
2403 SYSCTL_CHILDREN(softc->sysctl_stats_tree),
2409 "Transport errors reported by the SIM");
2410 SYSCTL_ADD_INT(&softc->sysctl_stats_ctx,
2411 SYSCTL_CHILDREN(softc->sysctl_stats_tree),
2417 "Device timeouts reported by the SIM");
2418 SYSCTL_ADD_INT(&softc->sysctl_stats_ctx,
2419 SYSCTL_CHILDREN(softc->sysctl_stats_tree),
2421 "pack_invalidations",
2423 &softc->invalidations,
2425 "Device pack invalidations");
2429 softc->sysctl_tree);
2443 value = softc->disk->d_delmaxsize;
2444 error = sysctl_handle_64(oidp, &value, 0, req);
2445 if ((error != 0) || (req->newptr == NULL))
2452 softc->disk->d_delmaxsize = value;
2462 value = *(
int *)arg1;
2464 error = sysctl_handle_int(oidp, &value, 0, req);
2467 || (req->newptr == NULL))
2475 else if ((value > 6)
2478 else if ((value > 10)
2481 else if (value > 12)
2484 *(
int *)arg1 = value;
2497 error = sysctl_handle_int(oidp, (
int *)&value, 0, req);
2498 if ((error != 0) || (req->newptr == NULL))
2513 softc->delete_method = delete_method;
2518 softc->disk->d_flags |= DISKFLAG_CANDELETE;
2520 softc->disk->d_flags &= ~DISKFLAG_CANDELETE;
2528 switch(delete_method) {
2530 sectors = (off_t)softc->unmap_max_lba;
2533 sectors = (off_t)ATA_DSM_RANGE_MAX * softc->trim_max_ranges;
2546 return (off_t)softc->params.secsize *
2547 omin(sectors, softc->params.sectors);
2565 snprintf(buf,
sizeof(buf),
"Delete methods: <");
2568 if ((softc->delete_available & (1 << i)) == 0 &&
2569 i != softc->delete_method)
2572 strlcat(buf,
",",
sizeof(buf));
2575 if (i == softc->delete_method)
2576 strlcat(buf,
"(*)",
sizeof(buf));
2579 strlcat(buf,
">",
sizeof(buf));
2583 if ((softc->disk->d_flags & DISKFLAG_WRITE_PROTECT) != 0 &&
2585 printf(
"%s%d: Write Protected\n", periph->
periph_name,
2601 wakeup(&softc->disk->d_mediasize);
2615 i = softc->delete_method_pref;
2617 if (methods & (1 << i)) {
2626 if (softc->delete_available & (1 << i)) {
2639 u_int *flags = arg1;
2643 tmpout = !!(*flags & test);
2644 error = SYSCTL_OUT(req, &tmpout,
sizeof(tmpout));
2645 if (error || !req->newptr)
2658 sbuf_new_for_sysctl(&sbuf, NULL, 0, req);
2659 if (softc->flags != 0)
2660 sbuf_printf(&sbuf,
"0x%b", (
unsigned)softc->flags,
DA_FLAG_STRING);
2662 sbuf_printf(&sbuf,
"0");
2663 error = sbuf_finish(&sbuf);
2675 int i, error, value;
2679 value = softc->delete_method;
2684 strncpy(buf, p,
sizeof(buf));
2685 error = sysctl_handle_string(oidp, buf,
sizeof(buf), req);
2686 if (error != 0 || req->newptr == NULL)
2694 softc->delete_method_pref = i;
2708 switch (softc->zone_mode) {
2710 snprintf(tmpbuf,
sizeof(tmpbuf),
"Drive Managed");
2713 snprintf(tmpbuf,
sizeof(tmpbuf),
"Host Aware");
2716 snprintf(tmpbuf,
sizeof(tmpbuf),
"Host Managed");
2720 snprintf(tmpbuf,
sizeof(tmpbuf),
"Not Zoned");
2724 error = sysctl_handle_string(oidp, tmpbuf,
sizeof(tmpbuf), req);
2742 sbuf_new(&sb, tmpbuf,
sizeof(tmpbuf), 0);
2748 sbuf_printf(&sb,
", ");
2756 sbuf_printf(&sb,
"None");
2760 error = sysctl_handle_string(oidp, sbuf_data(&sb), sbuf_len(&sb), req);
2777 printf(
"daregister: no getdev CCB, can't register device\n");
2781 softc = (
struct da_softc *)malloc(
sizeof(*softc), M_DEVBUF,
2784 if (softc == NULL) {
2785 printf(
"daregister: Unable to probe new device. "
2786 "Unable to allocate softc\n");
2791 printf(
"daregister: Unable to probe new device. "
2792 "Unable to allocate iosched memory\n");
2793 free(softc, M_DEVBUF);
2797 LIST_INIT(&softc->pending_ccbs);
2804 softc->unmap_gran = 0;
2805 softc->unmap_gran_align = 0;
2810 periph->
softc = softc;
2831 snprintf(tmpstr,
sizeof(tmpstr),
"kern.cam.da.%d.quirks",
2834 TUNABLE_INT_FETCH(tmpstr, &
quirks);
2854 TASK_INIT(&softc->sysctl_task, 0,
dasysctlinit, periph);
2861 (
"%s: NULL da_ccb_zone", __func__));
2879 callout_init_mtx(&softc->sendordered_c,
cam_periph_mtx(periph), 0);
2880 callout_reset_sbt(&softc->sendordered_c,
2889 softc->minimum_cmd_size = 10;
2891 softc->minimum_cmd_size = 6;
2896 snprintf(tmpstr,
sizeof(tmpstr),
"kern.cam.da.%d.minimum_cmd_size",
2898 TUNABLE_INT_FETCH(tmpstr, &softc->minimum_cmd_size);
2903 if (softc->minimum_cmd_size > 12)
2904 softc->minimum_cmd_size = 16;
2905 else if (softc->minimum_cmd_size > 10)
2906 softc->minimum_cmd_size = 12;
2907 else if (softc->minimum_cmd_size > 6)
2908 softc->minimum_cmd_size = 10;
2910 softc->minimum_cmd_size = 6;
2924 softc->disk = disk_alloc();
2925 softc->disk->d_devstat = devstat_new_entry(periph->
periph_name,
2927 DEVSTAT_BS_UNAVAILABLE,
2930 DEVSTAT_PRIORITY_DISK);
2931 softc->disk->d_open =
daopen;
2932 softc->disk->d_close =
daclose;
2935 softc->disk->d_dump =
dadump;
2938 softc->disk->d_name =
"da";
2939 softc->disk->d_drv1 = periph;
2941 softc->maxio = DFLTPHYS;
2942 else if (cpi.
maxio > maxphys)
2943 softc->maxio = maxphys;
2945 softc->maxio = cpi.
maxio;
2947 softc->maxio = min(softc->maxio, 128 * 1024);
2948 softc->disk->d_maxsize = softc->maxio;
2950 softc->disk->d_flags = DISKFLAG_DIRECT_COMPLETION | DISKFLAG_CANZONE;
2952 softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
2955 softc->disk->d_flags |= DISKFLAG_UNMAPPED_BIO;
2959 strlcat(softc->disk->d_descr,
" ",
sizeof(softc->disk->d_descr));
2960 cam_strvis(&softc->disk->d_descr[strlen(softc->disk->d_descr)],
2962 sizeof(softc->disk->d_descr) - strlen(softc->disk->d_descr));
2967 snprintf(softc->disk->d_attachment,
sizeof(softc->disk->d_attachment),
2977 "registration!\n", __func__);
2982 disk_create(softc->disk, DISK_VERSION);
3002 disk_attr_changed(softc->disk,
"GEOM::physpath", M_NOWAIT);
3007 callout_init_mtx(&softc->mediapoll_c,
cam_periph_mtx(periph), 0);
3023 switch (disk_zone_cmd) {
3024 case DISK_ZONE_OPEN:
3026 case DISK_ZONE_CLOSE:
3028 case DISK_ZONE_FINISH:
3046 if (bp->bio_cmd != BIO_ZONE) {
3051 softc = periph->
softc;
3053 switch (bp->bio_zone.zone_cmd) {
3054 case DISK_ZONE_OPEN:
3055 case DISK_ZONE_CLOSE:
3056 case DISK_ZONE_FINISH:
3057 case DISK_ZONE_RWP: {
3063 if (zone_sa == -1) {
3065 "cmd %#x to SCSI\n", bp->bio_zone.zone_cmd);
3071 lba = bp->bio_zone.zone_params.rwp.id;
3073 if (bp->bio_zone.zone_params.rwp.flags &
3074 DISK_ZONE_RWP_FLAG_ALL)
3129 "scsi_ata_zac_mgmt_out() returned an "
3138 case DISK_ZONE_REPORT_ZONES: {
3140 uint32_t num_entries, alloc_size;
3141 struct disk_zone_report *rep;
3143 rep = &bp->bio_zone.zone_params.report;
3145 num_entries = rep->entries_allocated;
3146 if (num_entries == 0) {
3148 "Report Zones request\n");
3154 alloc_size = min(alloc_size, softc->disk->d_maxsize);
3155 rz_ptr = malloc(alloc_size, M_SCSIDA, M_NOWAIT | M_ZERO);
3156 if (rz_ptr == NULL) {
3158 "for Report Zones request\n");
3203 ATA_ZM_REPORT_ZONES,
3215 "scsi_ata_zac_mgmt_in() returned an "
3245 bp->bio_bcount = bp->bio_length;
3251 case DISK_ZONE_GET_PARAMS: {
3252 struct disk_zone_disk_params *params;
3254 params = &bp->bio_zone.zone_params.disk_params;
3255 bzero(params,
sizeof(*params));
3257 switch (softc->zone_mode) {
3259 params->zone_mode = DISK_ZONE_MODE_DRIVE_MANAGED;
3262 params->zone_mode = DISK_ZONE_MODE_HOST_AWARE;
3265 params->zone_mode = DISK_ZONE_MODE_HOST_MANAGED;
3269 params->zone_mode = DISK_ZONE_MODE_NONE;
3274 params->flags |= DISK_ZONE_DISK_URSWRZ;
3277 params->optimal_seq_zones = softc->optimal_seq_zones;
3278 params->flags |= DISK_ZONE_OPT_SEQ_SET;
3282 params->optimal_nonseq_zones =
3283 softc->optimal_nonseq_zones;
3284 params->flags |= DISK_ZONE_OPT_NONSEQ_SET;
3288 params->max_seq_zones = softc->max_seq_zones;
3289 params->flags |= DISK_ZONE_MAX_SEQ_SET;
3292 params->flags |= DISK_ZONE_RZ_SUP;
3295 params->flags |= DISK_ZONE_OPEN_SUP;
3298 params->flags |= DISK_ZONE_CLOSE_SUP;
3301 params->flags |= DISK_ZONE_FINISH_SUP;
3304 params->flags |= DISK_ZONE_RWP_SUP;
3325 switch (softc->state) {
3345 start_ccb->
ccb_h.ccb_bp = NULL;
3353 if (bp->bio_cmd == BIO_DELETE) {
3354 if (softc->delete_func != NULL) {
3355 softc->delete_func(periph, start_ccb, bp);
3362 biofinish(bp, NULL, 0);
3374 if ((bp->bio_flags & BIO_ORDERED) != 0 ||
3376 softc->flags &= ~DA_FLAG_NEED_OTAG;
3383 switch (bp->bio_cmd) {
3390 biotrack(bp, __func__);
3392 if (bp->bio_cmd == BIO_WRITE) {
3399 data_ptr = bp->bio_data;
3400 if ((bp->bio_flags & (BIO_UNMAPPED|BIO_VLIST)) != 0) {
3411 softc->minimum_cmd_size,
3414 softc->params.secsize,
3419#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
3420 start_ccb->
csio.bio = bp;
3458 softc->flags &= ~DA_FLAG_DIRTY;
3461 int error, queue_ccb;
3465 error =
da_zone_cmd(periph, start_ccb, bp,&queue_ccb);
3467 || (queue_ccb == 0)) {
3468 biofinish(bp, NULL, error);
3475 biofinish(bp, NULL, EOPNOTSUPP);
3484 LIST_INSERT_HEAD(&softc->pending_ccbs,
3485 &start_ccb->
ccb_h, periph_links.le);
3490 softc->flags &= ~DA_FLAG_RETRY_UA;
3493 start_ccb->
ccb_h.ccb_bp = bp;
3516 mode_buf = malloc(mode_buf_len, M_SCSIDA, M_NOWAIT);
3517 if (mode_buf == NULL) {
3519 "malloc failure\n");
3535 softc->minimum_cmd_size,
3538 start_ccb->
ccb_h.ccb_bp = NULL;
3548 malloc(
sizeof(*rcap), M_SCSIDA, M_NOWAIT|M_ZERO);
3550 printf(
"dastart: Couldn't malloc read_capacity data\n");
3561 start_ccb->
ccb_h.ccb_bp = NULL;
3571 malloc(
sizeof(*rcaplong), M_SCSIDA, M_NOWAIT|M_ZERO);
3572 if (rcaplong == NULL) {
3573 printf(
"dastart: Couldn't malloc read_capacity data\n");
3584 (uint8_t *)rcaplong,
3588 start_ccb->
ccb_h.ccb_bp = NULL;
3612 malloc(
sizeof(*lbp), M_SCSIDA, M_NOWAIT|M_ZERO);
3615 printf(
"dastart: Couldn't malloc lbp data\n");
3630 start_ccb->
ccb_h.ccb_bp = NULL;
3646 malloc(
sizeof(*block_limits), M_SCSIDA, M_NOWAIT|M_ZERO);
3648 if (block_limits == NULL) {
3649 printf(
"dastart: Couldn't malloc block_limits data\n");
3658 (u_int8_t *)block_limits,
3659 sizeof(*block_limits),
3664 start_ccb->
ccb_h.ccb_bp = NULL;
3679 malloc(
sizeof(*bdc), M_SCSIDA, M_NOWAIT|M_ZERO);
3682 printf(
"dastart: Couldn't malloc bdc data\n");
3697 start_ccb->
ccb_h.ccb_bp = NULL;
3704 struct ata_params *ata_params;
3729 (u_int8_t *)ata_params,
3730 sizeof(*ata_params),
3733 start_ccb->
ccb_h.ccb_bp = NULL;
3740 struct ata_gp_log_dir *log_dir;
3760 log_dir = malloc(
sizeof(*log_dir), M_SCSIDA, M_NOWAIT|M_ZERO);
3761 if (log_dir == NULL) {
3784 free(log_dir, M_SCSIDA);
3788 start_ccb->
ccb_h.ccb_bp = NULL;
3795 struct ata_identify_log_pages *id_dir;
3810 id_dir = malloc(
sizeof(*id_dir), M_SCSIDA, M_NOWAIT | M_ZERO);
3811 if (id_dir == NULL) {
3822 ATA_IDENTIFY_DATA_LOG,
3834 free(id_dir, M_SCSIDA);
3838 start_ccb->
ccb_h.ccb_bp = NULL;
3845 struct ata_identify_log_sup_cap *sup_cap;
3859 sup_cap = malloc(
sizeof(*sup_cap), M_SCSIDA, M_NOWAIT|M_ZERO);
3860 if (sup_cap == NULL) {
3871 ATA_IDENTIFY_DATA_LOG,
3883 free(sup_cap, M_SCSIDA);
3888 start_ccb->
ccb_h.ccb_bp = NULL;
3895 struct ata_zoned_info_log *ata_zone;
3909 ata_zone = malloc(
sizeof(*ata_zone), M_SCSIDA,
3911 if (ata_zone == NULL) {
3922 ATA_IDENTIFY_DATA_LOG,
3927 (uint8_t *)ata_zone,
3934 free(ata_zone, M_SCSIDA);
3938 start_ccb->
ccb_h.ccb_bp = NULL;
3960 malloc(
sizeof(*bdc), M_SCSIDA, M_NOWAIT|M_ZERO);
3978 start_ccb->
ccb_h.ccb_bp = NULL;
4002 uint8_t *buf = softc->unmap_buf;
4004 uint64_t lba, lastlba = (uint64_t)-1;
4005 uint64_t totalcount = 0;
4007 uint32_t c, lastcount = 0, ranges = 0;
4019 bzero(softc->unmap_buf,
sizeof(softc->unmap_buf));
4034 lba = bp1->bio_pblkno;
4035 count = bp1->bio_bcount / softc->params.secsize;
4038 if (lba == lastlba) {
4047 softc->unmap_gran != 0) {
4049 if ((c = lastcount % softc->unmap_gran) != 0) {
4050 if (lastcount <= c) {
4051 totalcount -= lastcount;
4052 lastlba = (uint64_t)-1;
4060 d[ranges - 1].length);
4064 c = (lba - softc->unmap_gran_align) % softc->unmap_gran;
4066 c = softc->unmap_gran - c;
4078 if (totalcount + c > softc->unmap_max_lba ||
4079 ranges >= softc->unmap_max_ranges) {
4081 "%s issuing short delete %ld > %ld"
4084 totalcount + c, softc->unmap_max_lba,
4085 ranges, softc->unmap_max_ranges);
4100 if (ranges >= softc->unmap_max_ranges ||
4101 totalcount + bp1->bio_bcount /
4102 softc->params.secsize > softc->unmap_max_lba) {
4110 (c = lastcount % softc->unmap_gran) != 0) {
4131 softc->trim_count++;
4132 softc->trim_ranges += ranges;
4133 softc->trim_lbas += totalcount;
4142 uint8_t *buf = softc->unmap_buf;
4143 uint64_t lastlba = (uint64_t)-1;
4146 uint32_t lastcount = 0, c, requestcount;
4147 int ranges = 0, off, block_count;
4149 bzero(softc->unmap_buf,
sizeof(softc->unmap_buf));
4154 lba = bp1->bio_pblkno;
4155 count = bp1->bio_bcount / softc->params.secsize;
4156 requestcount = count;
4159 if (lba == lastlba) {
4160 c = omin(count, ATA_DSM_RANGE_MAX - lastcount);
4162 off = (ranges - 1) * 8;
4163 buf[off + 6] = lastcount & 0xff;
4164 buf[off + 7] = (lastcount >> 8) & 0xff;
4170 c = omin(count, ATA_DSM_RANGE_MAX);
4173 buf[off + 0] = lba & 0xff;
4174 buf[off + 1] = (lba >> 8) & 0xff;
4175 buf[off + 2] = (lba >> 16) & 0xff;
4176 buf[off + 3] = (lba >> 24) & 0xff;
4177 buf[off + 4] = (lba >> 32) & 0xff;
4178 buf[off + 5] = (lba >> 40) & 0xff;
4179 buf[off + 6] = c & 0xff;
4180 buf[off + 7] = (c >> 8) & 0xff;
4185 if (count != 0 && ranges == softc->trim_max_ranges) {
4187 "%s issuing short delete %ld > %ld\n",
4190 (softc->trim_max_ranges - ranges) *
4199 if (bp1->bio_bcount / softc->params.secsize >
4200 (softc->trim_max_ranges - ranges) * ATA_DSM_RANGE_MAX) {
4206 block_count = howmany(ranges, ATA_DSM_BLK_RANGES);
4213 block_count * ATA_DSM_BLK_SIZE,
4231 uint64_t ws_max_blks;
4236 ws_max_blks = softc->disk->d_delmaxsize / softc->params.secsize;
4237 lba = bp->bio_pblkno;
4243 count += bp1->bio_bcount / softc->params.secsize;
4244 if (count > ws_max_blks) {
4246 "%s issuing short delete %ld > %ld\n",
4248 count, ws_max_blks);
4249 count = omin(count, ws_max_blks);
4255 if (lba + count != bp1->bio_pblkno ||
4256 count + bp1->bio_bcount /
4257 softc->params.secsize > ws_max_blks) {
4267 softc->delete_method ==
4272 __DECONST(
void *, zero_region),
4273 softc->params.secsize,
4313 "%s failed, disabling BIO_DELETE\n",
4317 "%s failed, switching to %s BIO_DELETE\n",
4335 "PREVENT ALLOW MEDIUM REMOVAL not supported.\n");
4346 "SYNCHRONIZE CACHE(10) not supported.\n");
4348 softc->disk->d_flags &= ~DISKFLAG_CANFLUSHCACHE;
4358 "increasing minimum_cmd_size to 10.\n");
4359 softc->minimum_cmd_size = 10;
4361 bcopy(cdb, &cmd6,
sizeof(
struct scsi_rw_6));
4391 softc = periph->
softc;
4392 bp = (
struct bio *)
ccb->
ccb_h.ccb_bp;
4394 switch (bp->bio_zone.zone_cmd) {
4395 case DISK_ZONE_OPEN:
4396 case DISK_ZONE_CLOSE:
4397 case DISK_ZONE_FINISH:
4400 case DISK_ZONE_REPORT_ZONES: {
4402 struct disk_zone_report *rep;
4405 struct disk_zone_rep_entry *entry;
4406 uint32_t hdr_len, num_avail;
4407 uint32_t num_to_fill, i;
4410 rep = &bp->bio_zone.zone_params.report;
4424 if (avail_len <
sizeof(*hdr)) {
4430 bp->bio_error = EIO;
4431 bp->bio_flags |= BIO_ERROR;
4432 bp->bio_resid = bp->bio_bcount;
4441 hdr_len = ata ? le32dec(hdr->
length) :
4444 rep->entries_available = hdr_len /
sizeof(*desc);
4446 rep->entries_available = 0;
4454 rep->header.maximum_lba = ata ? le64dec(hdr->
maximum_lba) :
4461 rep->entries_filled = 0;
4465 num_avail = min((avail_len -
sizeof(*hdr)) /
sizeof(*desc),
4466 hdr_len /
sizeof(*desc));
4470 if (num_avail == 0) {
4471 rep->entries_filled = 0;
4475 num_to_fill = min(num_avail, rep->entries_allocated);
4480 if (num_to_fill == 0) {
4481 rep->entries_filled = 0;
4485 for (i = 0, desc = &hdr->
desc_list[0], entry=&rep->entries[0];
4486 i < num_to_fill; i++, desc++, entry++) {
4497 entry->zone_condition =
4502 entry->zone_length =
4505 entry->zone_start_lba =
4508 entry->write_pointer_lba =
4512 rep->entries_filled = num_to_fill;
4515 case DISK_ZONE_GET_PARAMS:
4522 panic(
"%s: Invalid zone command %d", __func__,
4523 bp->bio_zone.zone_cmd);
4527 if (bp->bio_zone.zone_cmd == DISK_ZONE_REPORT_ZONES)
4534 struct bio *bp, *bp1;
4542 csio = &done_ccb->
csio;
4544#
if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
4545 if (csio->bio != NULL)
4546 biotrack(csio->bio, __func__);
4551 bp = (
struct bio *)done_ccb->
ccb_h.ccb_bp;
4562 if (error == ERESTART) {
4567 bp = (
struct bio *)done_ccb->
ccb_h.ccb_bp;
4590 softc->invalidations++;
4592 queued_error = ENXIO;
4597 bp->bio_error = error;
4598 bp->bio_resid = bp->bio_bcount;
4599 bp->bio_flags |= BIO_ERROR;
4601 }
else if (bp != NULL) {
4605 bp->bio_resid = csio->
resid;
4607 if (bp->bio_resid != 0)
4608 bp->bio_flags |= BIO_ERROR;
4616 }
else if (bp != NULL) {
4618 panic(
"REQ_CMP with QFRZN");
4619 if (bp->bio_cmd == BIO_ZONE)
4624 bp->bio_resid = csio->
resid;
4625 if ((csio->
resid > 0) && (bp->bio_cmd != BIO_ZONE))
4626 bp->bio_flags |= BIO_ERROR;
4627 if (softc->error_inject != 0) {
4628 bp->bio_error = softc->error_inject;
4629 bp->bio_resid = bp->bio_bcount;
4630 bp->bio_flags |= BIO_ERROR;
4631 softc->error_inject = 0;
4636 biotrack(bp, __func__);
4637 LIST_REMOVE(&done_ccb->
ccb_h, periph_links.le);
4638 if (LIST_EMPTY(&softc->pending_ccbs))
4649 KASSERT(softc->refcount >= 1, (
"dadone softc %p refcount %d", softc, softc->refcount));
4670 while ((bp1 = TAILQ_FIRST(&queue)) != NULL) {
4671 TAILQ_REMOVE(&queue, bp1, bio_queue);
4672 bp1->bio_error = bp->bio_error;
4673 if (bp->bio_flags & BIO_ERROR) {
4674 bp1->bio_flags |= BIO_ERROR;
4675 bp1->bio_resid = bp1->bio_bcount;
4700 csio = &done_ccb->
csio;
4705 (
"State (%d) not PROBE_WP in dadone_probewp, periph %p ccb %p",
4706 softc->state, periph, done_ccb));
4708 (
"CCB State (%lu) not PROBE_WP in dadone_probewp, periph %p ccb %p",
4730 softc->disk->d_flags |= DISKFLAG_WRITE_PROTECT;
4732 softc->disk->d_flags &= ~DISKFLAG_WRITE_PROTECT;
4735 if (off < len && off < csio->dxfer_len - csio->
resid)
4742 if (error == ERESTART)
4744 else if (error != 0) {
4755 softc->mode_page = -1;
4785 csio = &done_ccb->
csio;
4789 (
"State (%d) not PROBE_RC* in dadone_proberc, periph %p ccb %p",
4790 softc->state, periph, done_ccb));
4792 (
"CCB State (%lu) not PROBE_RC* in dadone_probewp, periph %p ccb %p",
4793 (
unsigned long)state, periph, done_ccb));
4799 announce_buf = softc->announce_temp;
4812 uint32_t block_size;
4829 if (maxsector == 0xffffffff) {
4830 free(rdcap, M_SCSIDA);
4847 if (block_size == 0) {
4852 if (block_size >= maxphys) {
4854 "unsupportable block size %ju\n",
4855 (uintmax_t) block_size);
4856 announce_buf = NULL;
4864 dasetgeom(periph, block_size, maxsector,
4865 rcaplong,
sizeof(*rcaplong));
4867 dp = &softc->params;
4869 "%juMB (%ju %u byte sectors",
4873 if (softc->p_type != 0) {
4874 n += snprintf(announce_buf + n,
4876 ", DIF type %d", softc->p_type);
4889 if (error == ERESTART) {
4895 }
else if (error != 0) {
4897 int sense_key, error_code;
4911 memset(&cgd, 0,
sizeof(cgd));
4918 &error_code, &sense_key, &asc, &ascq))
4936 softc->flags &= ~DA_FLAG_CAN_RC16;
4937 free(rdcap, M_SCSIDA);
4956 && (asc != 0x25) && (asc != 0x44)
4959 const char *sense_key_desc;
4960 const char *asc_desc;
4967 "Attempt to query device "
4968 "size failed: %s, %s",
4969 sense_key_desc, asc_desc);
4975 "got CAM status %#x\n",
4980 "failed to attach to device\n");
4982 announce_buf = NULL;
4992 if (announce_buf != NULL &&
5010 taskqueue_enqueue(taskqueue_thread,
5011 &softc->sysctl_task);
5015 "could not acquire reference count\n");
5026 softc->delete_available = 0;
5070 csio = &done_ccb->
csio;
5090 if (error == ERESTART)
5092 else if (error != 0) {
5109 free(lbp, M_SCSIDA);
5128 csio = &done_ccb->
csio;
5147 if (max_txfer_len != 0) {
5148 softc->disk->d_maxsize = MIN(softc->maxio,
5149 (off_t)max_txfer_len * softc->params.secsize);
5156 if (max_unmap_lba_cnt != 0x00L &&
5157 max_unmap_blk_cnt != 0x00L) {
5158 softc->unmap_max_lba = max_unmap_lba_cnt;
5159 softc->unmap_max_ranges = min(max_unmap_blk_cnt,
5161 if (unmap_gran > 1) {
5162 softc->unmap_gran = unmap_gran;
5163 if (unmap_gran_align & 0x80000000) {
5164 softc->unmap_gran_align =
5165 unmap_gran_align & 0x7fffffff;
5176 if (ws_max_blks != 0x00L)
5177 softc->ws_max_blks = ws_max_blks;
5182 if (error == ERESTART)
5184 else if (error != 0) {
5198 softc->unmap_max_lba = 1;
5199 softc->unmap_max_ranges = 1;
5203 free(block_limits, M_SCSIDA);
5222 csio = &done_ccb->
csio;
5234 u_int16_t old_rate = softc->disk->d_rotation_rate;
5238 medium_rotation_rate)) {
5239 softc->disk->d_rotation_rate =
5244 softc->flags &= ~DA_FLAG_ROTATING;
5246 if (softc->disk->d_rotation_rate != old_rate) {
5247 disk_attr_changed(softc->disk,
5248 "GEOM::rotation_rate", M_NOWAIT);
5271 softc->zone_interface = (ata_proto) ?
5276 softc->zone_interface = (ata_proto) ?
5289 if (error == ERESTART)
5291 else if (error != 0) {
5303 free(bdc, M_SCSIDA);
5313 struct ata_params *ata_params;
5324 csio = &done_ccb->
csio;
5325 ata_params = (
struct ata_params *)csio->
data_ptr;
5335 if (ata_params->support_dsm & ATA_SUPPORT_DSM_TRIM &&
5338 if (ata_params->max_dsm_blocks != 0)
5339 softc->trim_max_ranges = min(
5340 softc->trim_max_ranges,
5341 ata_params->max_dsm_blocks *
5342 ATA_DSM_BLK_RANGES);
5348 old_rate = softc->disk->d_rotation_rate;
5349 softc->disk->d_rotation_rate = ata_params->media_rotation_rate;
5350 if (softc->disk->d_rotation_rate == ATA_RATE_NON_ROTATING) {
5352 softc->flags &= ~DA_FLAG_ROTATING;
5354 if (softc->disk->d_rotation_rate != old_rate) {
5355 disk_attr_changed(softc->disk,
5356 "GEOM::rotation_rate", M_NOWAIT);
5360 if (ata_params->capabilities1 & ATA_SUPPORT_DMA)
5363 if (ata_params->support.extension & ATA_SUPPORT_GENLOG)
5387 if ((ata_params->support3 &
5388 ATA_SUPPORT_ZONE_MASK) ==
5389 ATA_SUPPORT_ZONE_HOST_AWARE) {
5391 softc->zone_interface =
5393 }
else if ((ata_params->support3 &
5394 ATA_SUPPORT_ZONE_MASK) ==
5395 ATA_SUPPORT_ZONE_DEV_MANAGED) {
5404 if (error == ERESTART)
5406 else if (error != 0) {
5441 if (continue_probe != 0) {
5462 csio = &done_ccb->
csio;
5467 softc->valid_logdir_len = 0;
5468 bzero(&softc->ata_logdir,
sizeof(softc->ata_logdir));
5470 if (softc->valid_logdir_len > 0)
5471 bcopy(csio->
data_ptr, &softc->ata_logdir,
5472 min(softc->valid_logdir_len,
5473 sizeof(softc->ata_logdir)));
5481 if ((softc->valid_logdir_len >=
5482 ((ATA_IDENTIFY_DATA_LOG + 1) *
sizeof(uint16_t)))
5483 && (le16dec(softc->ata_logdir.header) ==
5484 ATA_GP_LOG_DIR_VERSION)
5485 && (le16dec(&softc->ata_logdir.num_pages[
5486 (ATA_IDENTIFY_DATA_LOG *
5487 sizeof(uint16_t)) -
sizeof(uint16_t)]) > 0)){
5490 softc->flags &= ~DA_FLAG_CAN_ATA_IDLOG;
5495 if (error == ERESTART)
5497 else if (error != 0) {
5543 csio = &done_ccb->
csio;
5548 off_t entries_offset, max_entries;
5551 softc->valid_iddir_len = 0;
5552 bzero(&softc->ata_iddir,
sizeof(softc->ata_iddir));
5556 if (softc->valid_iddir_len > 0)
5557 bcopy(csio->
data_ptr, &softc->ata_iddir,
5558 min(softc->valid_iddir_len,
5559 sizeof(softc->ata_iddir)));
5562 __offsetof(
struct ata_identify_log_pages,entries);
5563 max_entries = softc->valid_iddir_len - entries_offset;
5564 if ((softc->valid_iddir_len > (entries_offset + 1))
5565 && (le64dec(softc->ata_iddir.header) == ATA_IDLOG_REVISION)
5566 && (softc->ata_iddir.entry_count > 0)) {
5569 num_entries = softc->ata_iddir.entry_count;
5570 num_entries = min(num_entries,
5571 softc->valid_iddir_len - entries_offset);
5572 for (i = 0; i < num_entries && i < max_entries; i++) {
5573 if (softc->ata_iddir.entries[i] ==
5576 else if (softc->ata_iddir.entries[i] ==
5588 if (error == ERESTART)
5590 else if (error != 0) {
5598 softc->flags &= ~DA_FLAG_CAN_ATA_IDLOG;
5634 csio = &done_ccb->
csio;
5641 struct ata_identify_log_sup_cap *sup_cap;
5644 sup_cap = (
struct ata_identify_log_sup_cap *)csio->
data_ptr;
5646 needed_size = __offsetof(
struct ata_identify_log_sup_cap,
5647 sup_zac_cap) + 1 +
sizeof(sup_cap->sup_zac_cap);
5648 if (valid_len >= needed_size) {
5649 uint64_t zoned, zac_cap;
5651 zoned = le64dec(sup_cap->zoned_cap);
5652 if (zoned & ATA_ZONED_VALID) {
5658 if ((zoned & ATA_ZONED_MASK) ==
5659 ATA_SUPPORT_ZONE_HOST_AWARE)
5661 else if ((zoned & ATA_ZONED_MASK) ==
5662 ATA_SUPPORT_ZONE_DEV_MANAGED)
5667 zac_cap = le64dec(sup_cap->sup_zac_cap);
5668 if (zac_cap & ATA_SUP_ZAC_CAP_VALID) {
5669 if (zac_cap & ATA_REPORT_ZONES_SUP)
5670 softc->zone_flags |=
5672 if (zac_cap & ATA_ND_OPEN_ZONE_SUP)
5673 softc->zone_flags |=
5675 if (zac_cap & ATA_ND_CLOSE_ZONE_SUP)
5676 softc->zone_flags |=
5678 if (zac_cap & ATA_ND_FINISH_ZONE_SUP)
5679 softc->zone_flags |=
5681 if (zac_cap & ATA_ND_RWP_SUP)
5682 softc->zone_flags |=
5699 if (error == ERESTART)
5701 else if (error != 0) {
5707 softc->flags &= ~DA_FLAG_CAN_ATA_SUPCAP;
5711 softc->zone_flags &= ~DA_ZONE_FLAG_SUP_MASK;
5745 csio = &done_ccb->
csio;
5750 struct ata_zoned_info_log *zi_log;
5754 zi_log = (
struct ata_zoned_info_log *)csio->
data_ptr;
5757 needed_size = __offsetof(
struct ata_zoned_info_log,
5758 version_info) + 1 +
sizeof(zi_log->version_info);
5759 if (valid_len >= needed_size) {
5762 tmpvar = le64dec(zi_log->zoned_cap);
5763 if (tmpvar & ATA_ZDI_CAP_VALID) {
5764 if (tmpvar & ATA_ZDI_CAP_URSWRZ)
5765 softc->zone_flags |=
5768 softc->zone_flags &=
5769 ~DA_ZONE_FLAG_URSWRZ;
5771 tmpvar = le64dec(zi_log->optimal_seq_zones);
5772 if (tmpvar & ATA_ZDI_OPT_SEQ_VALID) {
5774 softc->optimal_seq_zones = (tmpvar &
5775 ATA_ZDI_OPT_SEQ_MASK);
5777 softc->zone_flags &= ~DA_ZONE_FLAG_OPT_SEQ_SET;
5778 softc->optimal_seq_zones = 0;
5781 tmpvar =le64dec(zi_log->optimal_nonseq_zones);
5782 if (tmpvar & ATA_ZDI_OPT_NS_VALID) {
5783 softc->zone_flags |=
5785 softc->optimal_nonseq_zones =
5786 (tmpvar & ATA_ZDI_OPT_NS_MASK);
5788 softc->zone_flags &=
5789 ~DA_ZONE_FLAG_OPT_NONSEQ_SET;
5790 softc->optimal_nonseq_zones = 0;
5793 tmpvar = le64dec(zi_log->max_seq_req_zones);
5794 if (tmpvar & ATA_ZDI_MAX_SEQ_VALID) {
5796 softc->max_seq_zones =
5797 (tmpvar & ATA_ZDI_MAX_SEQ_MASK);
5799 softc->zone_flags &= ~DA_ZONE_FLAG_MAX_SEQ_SET;
5800 softc->max_seq_zones = 0;
5806 if (error == ERESTART)
5808 else if (error != 0) {
5809 softc->flags &= ~DA_FLAG_CAN_ATA_ZONE;
5810 softc->flags &= ~DA_ZONE_FLAG_SET_MASK;
5839 csio = &done_ccb->
csio;
5854 if ((valid_len >= needed_len)
5859 softc->zone_flags &= ~DA_ZONE_FLAG_URSWRZ;
5860 softc->optimal_seq_zones =
5866 softc->max_seq_zones =
5886 if (error == ERESTART)
5888 else if (error != 0) {
5928 softc->flags &= ~DA_FLAG_TUR_PENDING;
5938 int status __diagused;
5949 KASSERT(status == 0, (
"dareprobe: cam_periph_acquire failed"));
5960 int error, error_code, sense_key, asc, ascq;
5962#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
5964 biotrack(
ccb->
csio.bio, __func__);
5980 &error_code, &sense_key, &asc, &ascq)) {
5988 asc == 0x2A && ascq == 0x09) {
5990 softc->flags &= ~DA_FLAG_PROBED;
5994 asc == 0x28 && ascq == 0x00) {
5995 softc->flags &= ~DA_FLAG_PROBED;
5996 disk_media_changed(softc->disk, M_NOWAIT);
5998 asc == 0x3F && ascq == 0x03) {
6000 softc->flags &= ~DA_FLAG_PROBED;
6006 disk_media_gone(softc->disk, M_NOWAIT);
6009 if (error == ERESTART)
6052 LIST_EMPTY(&softc->pending_ccbs)) {
6061 callout_schedule_sbt(&softc->mediapoll_c,
6098 softc->flags &= ~DA_FLAG_PACK_LOCKED;
6113 u_int lbppbe, lalba;
6118 dp = &softc->params;
6121 if (rcaplong != NULL) {
6140 }
else if (softc->quirks &
DA_Q_4K) {
6143 }
else if (softc->unmap_gran != 0) {
6144 dp->
stripesize = block_len * softc->unmap_gran;
6159 memset(&ccg, 0,
sizeof(ccg));
6192 if ((rcaplong != NULL)
6193 && (bcmp(rcaplong, &softc->rcaplong,
6194 min(
sizeof(softc->rcaplong), rcap_len)) != 0)) {
6197 memset(&cdai, 0,
sizeof(cdai));
6203 cdai.
buf = (uint8_t *)rcaplong;
6209 "capacity advinfo\n", __func__);
6214 bcopy(rcaplong, &softc->rcaplong,
6215 min(
sizeof(softc->rcaplong), rcap_len));
6219 softc->disk->d_sectorsize = softc->params.secsize;
6220 softc->disk->d_mediasize = softc->params.secsize * (off_t)softc->params.sectors;
6221 softc->disk->d_stripesize = softc->params.stripesize;
6222 softc->disk->d_stripeoffset = softc->params.stripeoffset;
6224 softc->disk->d_fwsectors = softc->params.secs_per_track;
6225 softc->disk->d_fwheads = softc->params.heads;
6226 softc->disk->d_devstat->block_size = softc->params.secsize;
6227 softc->disk->d_devstat->flags &= ~DEVSTAT_BS_UNAVAILABLE;
6229 error = disk_resize(softc->disk, M_NOWAIT);
6231 xpt_print(periph->
path,
"disk_resize(9) failed, error = %d\n", error);
6242 if (!LIST_EMPTY(&softc->pending_ccbs)) {
6245 softc->flags &= ~DA_FLAG_WAS_OTAG;
6250 callout_schedule_sbt(&softc->sendordered_c,
6267 if ((howto & RB_NOSYNC) != 0)
6272 if (SCHEDULER_STOPPED()) {
6276 dadump(softc->disk, NULL, 0, 0, 0);
6304 softc->disk->d_devstat);
6322 u_int8_t tag_action, u_int8_t byte2, u_int16_t ileave,
6323 u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
6346scsi_read_defects(
struct ccb_scsiio *csio, uint32_t retries,
6348 uint8_t tag_action, uint8_t list_format,
6349 uint32_t addr_desc_index, uint8_t *data_ptr,
6350 uint32_t dxfer_len,
int minimum_cmd_size,
6351 uint8_t sense_len, uint32_t timeout)
6359 if ((minimum_cmd_size <= 10)
6360 && (addr_desc_index == 0)
6367 cdb_len =
sizeof(*cdb10);
6368 bzero(cdb10, cdb_len);
6370 cdb10->
format = list_format;
6378 cdb_len =
sizeof(*cdb12);
6379 bzero(cdb12, cdb_len);
6381 cdb12->
format = list_format;
6401 u_int8_t tag_action, u_int8_t byte2, u_int16_t
control,
6402 u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
6430 uint8_t tag_action, uint8_t service_action, uint64_t zone_id,
6431 uint8_t zone_flags, uint8_t *data_ptr, uint32_t dxfer_len,
6432 uint8_t sense_len, uint32_t timeout)
6457 uint8_t tag_action, uint8_t
service_action, uint64_t zone_start_lba,
6458 uint8_t zone_options, uint8_t *data_ptr, uint32_t dxfer_len,
6459 uint8_t sense_len, uint32_t timeout)
6486 uint8_t tag_action,
int use_ncq,
6487 uint8_t zm_action, uint64_t zone_id, uint8_t zone_flags,
6488 uint8_t *data_ptr, uint32_t dxfer_len,
6489 uint8_t *cdb_storage,
size_t cdb_storage_len,
6490 uint8_t sense_len, uint32_t timeout)
6492 uint8_t command_out, protocol, ata_flags;
6493 uint16_t features_out;
6494 uint32_t sectors_out, auxiliary;
6500 command_out = ATA_ZAC_MANAGEMENT_OUT;
6501 features_out = (zm_action & 0xf) | (zone_flags << 8);
6503 if (dxfer_len == 0) {
6511 sectors_out = ((dxfer_len >> 9) & 0xffff);
6516 if (dxfer_len == 0) {
6517 command_out = ATA_NCQ_NON_DATA;
6518 features_out = ATA_NCQ_ZAC_MGMT_OUT;
6527 command_out = ATA_SEND_FPDMA_QUEUED;
6535 sectors_out = ATA_SFPDMA_ZAC_MGMT_OUT << 8;
6549 if (dxfer_len == (65536 * 512)) {
6551 }
else if (dxfer_len <= (65535 * 512)) {
6552 features_out = ((dxfer_len >> 9) & 0xffff);
6560 auxiliary = (zm_action & 0xf) | (zone_flags << 8);
6597 uint8_t tag_action,
int use_ncq,
6598 uint8_t zm_action, uint64_t zone_id, uint8_t zone_flags,
6599 uint8_t *data_ptr, uint32_t dxfer_len,
6600 uint8_t *cdb_storage,
size_t cdb_storage_len,
6601 uint8_t sense_len, uint32_t timeout)
6603 uint8_t command_out, protocol;
6604 uint16_t features_out, sectors_out;
6613 command_out = ATA_ZAC_MANAGEMENT_IN;
6615 features_out = (zm_action & 0xf) | (zone_flags << 8);
6616 sectors_out = dxfer_len >> 9;
6623 command_out = ATA_RECV_FPDMA_QUEUED;
6624 sectors_out = ATA_RFPDMA_ZAC_MGMT_IN << 8;
6635 if (dxfer_len == (65536 * 512)) {
6637 }
else if (dxfer_len <= (65535 * 512)) {
6638 features_out = ((dxfer_len >> 9) & 0xffff);
6644 auxiliary = (zm_action & 0xf) | (zone_flags << 8),
6666 (dxfer_len >> 9) * 512,
void ata_param_fixup(struct ata_params *ident_buf)
caddr_t cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries, int entry_size, cam_quirkmatch_t *comp_func)
void cam_strvis(u_int8_t *dst, const u_int8_t *src, int srclen, int dstlen)
void cam_error_print(union ccb *ccb, cam_error_string_flags flags, cam_error_proto_flags proto_flags)
#define CAM_PRIORITY_NORMAL
#define CAM_PRIORITY_NONE
@ CTS_TYPE_CURRENT_SETTINGS
#define CDAI_TYPE_RCAPLONG
static __BEGIN_DECLS __inline void cam_fill_csio(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int32_t flags, u_int8_t tag_action, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, u_int8_t cdb_len, u_int32_t timeout)
#define XPORT_DEVSTAT_TYPE(t)
#define CDAI_TYPE_PHYS_PATH
static __inline cam_status cam_ccb_status(union ccb *ccb)
#define CTS_FC_VALID_WWPN
#define CAM_DEBUG(path, flag, printfargs)
struct bio * cam_iosched_next_trim(struct cam_iosched_softc *isc)
void cam_iosched_clr_work_flags(struct cam_iosched_softc *isc, uint32_t flags)
void cam_iosched_fini(struct cam_iosched_softc *isc)
void cam_iosched_set_work_flags(struct cam_iosched_softc *isc, uint32_t flags)
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)
int cam_iosched_has_work_flags(struct cam_iosched_softc *isc, uint32_t flags)
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)
void cam_periph_invalidate(struct cam_periph *periph)
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_assert(periph, what)
#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)
LIST_HEAD(ccb_hdr_list, 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)
struct ccb_trans_settings_mmc * cts
void scsi_ata_trim(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, u_int16_t block_count, u_int8_t *data_ptr, u_int16_t dxfer_len, u_int8_t sense_len, u_int32_t timeout)
void scsi_sense_desc(int sense_key, int asc, int ascq, struct scsi_inquiry_data *inq_data, const char **sense_key_desc, const char **asc_desc)
void scsi_unmap(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, u_int8_t byte2, u_int8_t *data_ptr, u_int16_t dxfer_len, u_int8_t sense_len, u_int32_t timeout)
void scsi_sense_print(struct ccb_scsiio *csio)
int scsi_ata_pass(struct ccb_scsiio *csio, uint32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), uint32_t flags, uint8_t tag_action, uint8_t protocol, uint8_t ata_flags, uint16_t features, uint16_t sector_count, uint64_t lba, uint8_t command, uint8_t device, uint8_t icc, uint32_t auxiliary, uint8_t control, u_int8_t *data_ptr, uint32_t dxfer_len, uint8_t *cdb_storage, size_t cdb_storage_len, int minimum_cmd_size, u_int8_t sense_len, u_int32_t timeout)
void scsi_prevent(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, u_int8_t action, u_int8_t sense_len, u_int32_t timeout)
int scsi_inquiry_match(caddr_t inqbuffer, caddr_t table_entry)
void scsi_read_capacity(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, struct scsi_read_capacity_data *rcap_buf, u_int8_t sense_len, u_int32_t timeout)
void scsi_write_same(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, u_int8_t byte2, int minimum_cmd_size, u_int64_t lba, u_int32_t block_count, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, u_int32_t timeout)
void scsi_ata_identify(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, u_int8_t *data_ptr, u_int16_t dxfer_len, u_int8_t sense_len, u_int32_t timeout)
int scsi_extract_sense_ccb(union ccb *ccb, int *error_code, int *sense_key, int *asc, int *ascq)
void scsi_inquiry(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, u_int8_t *inq_buf, u_int32_t inq_len, int evpd, u_int8_t page_code, u_int8_t sense_len, u_int32_t timeout)
void scsi_mode_sense_len(struct ccb_scsiio *csio, uint32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, int dbd, uint8_t pc, uint8_t page, uint8_t *param_buf, uint32_t param_len, int minimum_cmd_size, uint8_t sense_len, uint32_t timeout)
int scsi_ata_read_log(struct ccb_scsiio *csio, uint32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, uint32_t log_address, uint32_t page_number, uint16_t block_count, uint8_t protocol, uint8_t *data_ptr, uint32_t dxfer_len, uint8_t sense_len, uint32_t timeout)
void scsi_synchronize_cache(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, u_int32_t begin_lba, u_int16_t lb_count, u_int8_t sense_len, u_int32_t timeout)
int scsi_vpd_supported_page(struct cam_periph *periph, uint8_t page_id)
void scsi_read_write(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int readop, u_int8_t byte2, int minimum_cmd_size, u_int64_t lba, u_int32_t block_count, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, u_int32_t timeout)
void scsi_test_unit_ready(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, u_int8_t sense_len, u_int32_t timeout)
void scsi_read_capacity_16(struct ccb_scsiio *csio, uint32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, uint64_t lba, int reladr, int pmi, uint8_t *rcap_buf, int rcap_buf_len, uint8_t sense_len, uint32_t timeout)
#define SSD_KEY_UNIT_ATTENTION
#define SID_IS_REMOVABLE(inq_data)
#define SVPD_BLOCK_LIMITS
#define AP_FLAG_TDIR_FROM_DEV
#define SSD_DESC_CURRENT_ERROR
#define AP_PROTO_NON_DATA
static __inline uint32_t scsi_3btoul(const uint8_t *bytes)
static __inline uint64_t scsi_8btou64(const uint8_t *bytes)
static __inline uint32_t scsi_2btoul(const uint8_t *bytes)
#define SIP_MEDIA_REMOVABLE
#define SRC16_P_TYPE_SHIFT
#define SYNCHRONIZE_CACHE
#define SMS_ALL_PAGES_PAGE
#define AP_FLAG_TLEN_FEAT
static __inline void scsi_ulto2b(u_int32_t val, u_int8_t *bytes)
#define SVPD_NON_ROTATING
#define AP_FLAG_TLEN_NO_DATA
#define SSD_KEY_NOT_READY
#define AP_FLAG_BYT_BLOK_BLOCKS
static __inline uint32_t scsi_4btoul(const uint8_t *bytes)
#define SID_QUAL_LU_CONNECTED
#define SMS_PAGE_CTRL_CURRENT
#define AP_FLAG_TDIR_TO_DEV
static __inline void scsi_ulto4b(u_int32_t val, u_int8_t *bytes)
static __inline void scsi_u64to8b(u_int64_t val, u_int8_t *bytes)
#define SID_TYPE(inq_data)
#define SID_ANSI_REV(inq_data)
#define SVPD_ATA_INFORMATION
#define SBDC_IS_PRESENT(bdc, length, field)
#define SID_QUAL(inq_data)
#define SSD_KEY_ILLEGAL_REQUEST
#define READ_DEFECT_DATA_10
#define AP_FLAG_TLEN_SECT_CNT
#define SSD_CURRENT_ERROR
static da_delete_func_t da_delete_trim
static int cmd6workaround(union ccb *ccb)
#define DA_DEFAULT_SEND_ORDERED
static void dashutdown(void *arg, int howto)
@ DA_ZONE_FLAG_FINISH_SUP
@ DA_ZONE_FLAG_OPT_NONSEQ_SET
@ DA_ZONE_FLAG_OPT_SEQ_SET
@ DA_ZONE_FLAG_MAX_SEQ_SET
static int da_send_ordered
#define ATA_TRIM_MAX_RANGES
static void dadone_probewp(struct cam_periph *periph, union ccb *done_ccb)
static void dadeletemethodset(struct da_softc *softc, da_delete_methods delete_method)
static struct da_quirk_entry da_quirk_table[]
static sbintime_t da_default_softtimeout
static periph_init_t dainit
static int da_zone_bio_to_scsi(int disk_zone_cmd)
static periph_oninv_t daoninvalidate
static void dadone_probeata(struct cam_periph *periph, union ccb *done_ccb)
static struct da_zone_desc da_zone_desc_table[]
void da_delete_func_t(struct cam_periph *periph, union ccb *ccb, struct bio *bp)
PERIPHDRIVER_DECLARE(da, dadriver)
static void dadone_probeataiddir(struct cam_periph *periph, union ccb *done_ccb)
static void daprevent(struct cam_periph *periph, int action)
#define DA_ORDEREDTAG_INTERVAL
@ DA_STATE_PROBE_ATA_ZONE
@ DA_STATE_PROBE_ATA_IDDIR
@ DA_STATE_PROBE_ATA_LOGDIR
@ DA_STATE_PROBE_BLK_LIMITS
static int da_enable_biospeedup
static int da_disable_wp_detection
static disk_strategy_t dastrategy
@ DA_CCB_PROBE_BLK_LIMITS
@ DA_CCB_PROBE_ATA_LOGDIR
static callout_func_t dasendorderedtag
#define DA_ANNOUNCETMP_SZ
static void dadone(struct cam_periph *periph, union ccb *done_ccb)
static void dasysctlinit(void *context, int pending)
int scsi_ata_zac_mgmt_out(struct ccb_scsiio *csio, uint32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, int use_ncq, uint8_t zm_action, uint64_t zone_id, uint8_t zone_flags, uint8_t *data_ptr, uint32_t dxfer_len, uint8_t *cdb_storage, size_t cdb_storage_len, uint8_t sense_len, uint32_t timeout)
int scsi_ata_zac_mgmt_in(struct ccb_scsiio *csio, uint32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, int use_ncq, uint8_t zm_action, uint64_t zone_id, uint8_t zone_flags, uint8_t *data_ptr, uint32_t dxfer_len, uint8_t *cdb_storage, size_t cdb_storage_len, uint8_t sense_len, uint32_t timeout)
static void daschedule(struct cam_periph *periph)
static da_delete_func_t da_delete_ws
static int dadeletemethodsysctl(SYSCTL_HANDLER_ARGS)
static int daclose(struct disk *dp)
#define da_periph_acquire(periph, token)
static int dabitsysctl(SYSCTL_HANDLER_ARGS)
#define da_periph_hold(periph, prio, token)
static void dadone_tur(struct cam_periph *periph, union ccb *done_ccb)
#define DA_DEFAULT_SOFTTIMEOUT
static int daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
static void dadeletemethodchoose(struct da_softc *softc, da_delete_methods default_method)
static void dadone_probeatasup(struct cam_periph *periph, union ccb *done_ccb)
static void dadone_probeblklimits(struct cam_periph *periph, union ccb *done_ccb)
static const void * da_delete_functions[]
#define DA_DEFAULT_TIMEOUT
static int dazonesupsysctl(SYSCTL_HANDLER_ARGS)
static const char microp[]
static void daasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
void scsi_zbc_in(struct ccb_scsiio *csio, uint32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, uint8_t service_action, uint64_t zone_start_lba, uint8_t zone_options, uint8_t *data_ptr, uint32_t dxfer_len, uint8_t sense_len, uint32_t timeout)
TUNABLE_INT64("kern.cam.da.default_softtimeout", &da_default_softtimeout)
static void dadone_probeatazone(struct cam_periph *periph, union ccb *done_ccb)
static MALLOC_DEFINE(M_SCSIDA, "scsi_da", "scsi_da buffers")
static struct periph_driver dadriver
SYSCTL_INT(_kern_cam_da, OID_AUTO, poll_period, CTLFLAG_RWTUN, &da_poll_period, 0, "Media polling period in seconds")
static da_delete_func_t da_delete_unmap
static callout_func_t damediapoll
static void dadone_proberc(struct cam_periph *periph, union ccb *done_ccb)
#define da_periph_release_locked(periph, token)
static periph_dtor_t dacleanup
static void dazonedone(struct cam_periph *periph, union ccb *ccb)
static void daprobedone(struct cam_periph *periph, union ccb *ccb)
static int dasysctlsofttimeout(SYSCTL_HANDLER_ARGS)
static int da_default_timeout
void scsi_zbc_out(struct ccb_scsiio *csio, uint32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, uint8_t service_action, uint64_t zone_id, uint8_t zone_flags, uint8_t *data_ptr, uint32_t dxfer_len, uint8_t sense_len, uint32_t timeout)
static uma_zone_t da_ccb_zone
static int da_poll_period
static int daflagssysctl(SYSCTL_HANDLER_ARGS)
static SYSCTL_NODE(_kern_cam, OID_AUTO, da, CTLFLAG_RD|CTLFLAG_MPSAFE, 0, "CAM Direct Access Disk driver")
SYSCTL_PROC(_kern_cam_da, OID_AUTO, default_softtimeout, CTLTYPE_UINT|CTLFLAG_RW|CTLFLAG_MPSAFE, NULL, 0, dasysctlsofttimeout, "I", "Soft I/O timeout (ms)")
static int dadeletemaxsysctl(SYSCTL_HANDLER_ARGS)
static int da_enable_uma_ccbs
static void dadone_probezone(struct cam_periph *periph, union ccb *done_ccb)
#define dadeleteflag(softc, delete_method, enable)
static void dadiskgonecb(struct disk *dp)
static const char * da_delete_method_desc[]
static void dadone_probelbp(struct cam_periph *periph, union ccb *done_ccb)
static int dacmdsizesysctl(SYSCTL_HANDLER_ARGS)
static int daopen(struct disk *dp)
static periph_start_t dastart
static void dadone_probeatalogdir(struct cam_periph *periph, union ccb *done_ccb)
static const char * da_delete_method_names[]
static int da_retry_count
static void dasetgeom(struct cam_periph *periph, uint32_t block_len, uint64_t maxsector, struct scsi_read_capacity_data_long *rcaplong, size_t rcap_size)
#define da_periph_release(periph, token)
static off_t dadeletemaxsize(struct da_softc *softc, da_delete_methods delete_method)
#define DA_DEFAULT_POLL_PERIOD
static void dadone_probebdc(struct cam_periph *periph, union ccb *done_ccb)
static const char quantum[]
static int da_zone_cmd(struct cam_periph *periph, union ccb *ccb, struct bio *bp, int *queue_ccb)
static void dareprobe(struct cam_periph *periph)
static int dagetattr(struct bio *bp)
static int dazonemodesysctl(SYSCTL_HANDLER_ARGS)
#define da_periph_unhold(periph, token)
static periph_ctor_t daregister
#define ZBC_IN_SA_REPORT_ZONES
#define SRZ_ZONE_COND_SHIFT
#define SRZ_ZONE_COND_MASK
#define ZBC_OUT_SA_FINISH
#define READ_DEFECT_DATA_12
#define SRDD10_MAX_LENGTH
#define MSG_ORDERED_Q_TAG
struct ata_params ident_data
struct scsi_inquiry_data inq_data
struct timeval softtimeout
struct scsi_inquiry_pattern inq_pat
struct bio_queue_head delete_run_queue
struct cam_iosched_softc * cam_iosched
char vendor[SID_VENDOR_SIZE]
char product[SID_PRODUCT_SIZE]
uint8_t address_descriptor_index[4]
uint8_t write_pointer_lba[8]
uint8_t zone_start_lba[8]
struct scsi_report_zones_desc desc_list[]
uint8_t medium_rotation_rate[2]
u_int8_t max_write_same_length[8]
u_int8_t opt_unmap_grain[4]
u_int8_t max_txfer_len[4]
u_int8_t max_unmap_blk_cnt[4]
u_int8_t unmap_grain_align[4]
u_int8_t max_unmap_lba_cnt[4]
uint8_t optimal_seq_zones[4]
uint8_t max_seq_req_zones[4]
uint8_t optimal_nonseq_zones[4]
uint8_t zone_start_lba[8]
u_int8_t cdb_bytes[IOCDBLEN]