152c9ce25SScott Long /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3bec9534dSPedro F. Giffuni *
452c9ce25SScott Long * Copyright (c) 2009 Alexander Motin <mav@FreeBSD.org>
552c9ce25SScott Long * All rights reserved.
652c9ce25SScott Long *
752c9ce25SScott Long * Redistribution and use in source and binary forms, with or without
852c9ce25SScott Long * modification, are permitted provided that the following conditions
952c9ce25SScott Long * are met:
1052c9ce25SScott Long * 1. Redistributions of source code must retain the above copyright
1152c9ce25SScott Long * notice, this list of conditions and the following disclaimer,
1252c9ce25SScott Long * without modification, immediately at the beginning of the file.
1352c9ce25SScott Long * 2. Redistributions in binary form must reproduce the above copyright
1452c9ce25SScott Long * notice, this list of conditions and the following disclaimer in the
1552c9ce25SScott Long * documentation and/or other materials provided with the distribution.
1652c9ce25SScott Long *
1752c9ce25SScott Long * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1852c9ce25SScott Long * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1952c9ce25SScott Long * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2052c9ce25SScott Long * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2152c9ce25SScott Long * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2252c9ce25SScott Long * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2352c9ce25SScott Long * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2452c9ce25SScott Long * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2552c9ce25SScott Long * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2652c9ce25SScott Long * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2752c9ce25SScott Long */
2852c9ce25SScott Long
2952c9ce25SScott Long #include <sys/param.h>
3052c9ce25SScott Long
3152c9ce25SScott Long #ifdef _KERNEL
324e38d895SWarner Losh #include "opt_scsi.h"
3352c9ce25SScott Long
3452c9ce25SScott Long #include <sys/systm.h>
3552c9ce25SScott Long #include <sys/libkern.h>
3652c9ce25SScott Long #include <sys/kernel.h>
3752c9ce25SScott Long #include <sys/sysctl.h>
3852c9ce25SScott Long #else
3952c9ce25SScott Long #include <errno.h>
4052c9ce25SScott Long #include <stdio.h>
4152c9ce25SScott Long #include <stdlib.h>
4252c9ce25SScott Long #include <string.h>
4352c9ce25SScott Long #ifndef min
4452c9ce25SScott Long #define min(a,b) (((a)<(b))?(a):(b))
4552c9ce25SScott Long #endif
4652c9ce25SScott Long #endif
4752c9ce25SScott Long
4852c9ce25SScott Long #include <cam/cam.h>
4952c9ce25SScott Long #include <cam/cam_ccb.h>
5052c9ce25SScott Long #include <cam/cam_queue.h>
5152c9ce25SScott Long #include <cam/cam_xpt.h>
5252c9ce25SScott Long #include <sys/ata.h>
5352c9ce25SScott Long #include <cam/ata/ata_all.h>
5452c9ce25SScott Long #include <sys/sbuf.h>
5552c9ce25SScott Long #include <sys/endian.h>
5652c9ce25SScott Long
5752c9ce25SScott Long int
ata_version(int ver)5852c9ce25SScott Long ata_version(int ver)
5952c9ce25SScott Long {
6052c9ce25SScott Long int bit;
6152c9ce25SScott Long
6252c9ce25SScott Long if (ver == 0xffff)
6352c9ce25SScott Long return 0;
6452c9ce25SScott Long for (bit = 15; bit >= 0; bit--)
6552c9ce25SScott Long if (ver & (1<<bit))
6652c9ce25SScott Long return bit;
6752c9ce25SScott Long return 0;
6852c9ce25SScott Long }
6952c9ce25SScott Long
708691755dSAlexander Motin char *
ata_op_string(struct ata_cmd * cmd)718691755dSAlexander Motin ata_op_string(struct ata_cmd *cmd)
728691755dSAlexander Motin {
738691755dSAlexander Motin
74276b0834SAlexander Motin if (cmd->control & 0x04)
75276b0834SAlexander Motin return ("SOFT_RESET");
768691755dSAlexander Motin switch (cmd->command) {
77dd4637c0SRavi Pokala case 0x00:
78dd4637c0SRavi Pokala switch (cmd->features) {
79dd4637c0SRavi Pokala case 0x00: return ("NOP FLUSHQUEUE");
80dd4637c0SRavi Pokala case 0x01: return ("NOP AUTOPOLL");
81dd4637c0SRavi Pokala }
82dd4637c0SRavi Pokala return ("NOP");
838691755dSAlexander Motin case 0x03: return ("CFA_REQUEST_EXTENDED_ERROR");
841c80ec0aSAlexander Motin case 0x06:
851c80ec0aSAlexander Motin switch (cmd->features) {
861c80ec0aSAlexander Motin case 0x01: return ("DSM TRIM");
871c80ec0aSAlexander Motin }
881c80ec0aSAlexander Motin return "DSM";
890404d598SAlexander Motin case 0x07:
900404d598SAlexander Motin switch (cmd->features) {
910404d598SAlexander Motin case 0x01: return ("DSM_XL TRIM");
920404d598SAlexander Motin }
930404d598SAlexander Motin return "DSM_XL";
948691755dSAlexander Motin case 0x08: return ("DEVICE_RESET");
951e3d53e2SAlexander Motin case 0x0b: return ("REQUEST_SENSE_DATA_EXT");
960404d598SAlexander Motin case 0x12: return ("GET_PHYSICAL_ELEMENT_STATUS");
978691755dSAlexander Motin case 0x20: return ("READ");
988691755dSAlexander Motin case 0x24: return ("READ48");
998691755dSAlexander Motin case 0x25: return ("READ_DMA48");
1008691755dSAlexander Motin case 0x26: return ("READ_DMA_QUEUED48");
1018691755dSAlexander Motin case 0x27: return ("READ_NATIVE_MAX_ADDRESS48");
1028691755dSAlexander Motin case 0x29: return ("READ_MUL48");
1038691755dSAlexander Motin case 0x2a: return ("READ_STREAM_DMA48");
1048691755dSAlexander Motin case 0x2b: return ("READ_STREAM48");
1058691755dSAlexander Motin case 0x2f: return ("READ_LOG_EXT");
1068691755dSAlexander Motin case 0x30: return ("WRITE");
1078691755dSAlexander Motin case 0x34: return ("WRITE48");
1088691755dSAlexander Motin case 0x35: return ("WRITE_DMA48");
1098691755dSAlexander Motin case 0x36: return ("WRITE_DMA_QUEUED48");
1108691755dSAlexander Motin case 0x37: return ("SET_MAX_ADDRESS48");
1118691755dSAlexander Motin case 0x39: return ("WRITE_MUL48");
1128691755dSAlexander Motin case 0x3a: return ("WRITE_STREAM_DMA48");
1138691755dSAlexander Motin case 0x3b: return ("WRITE_STREAM48");
114f3631e8dSAlexander Motin case 0x3d: return ("WRITE_DMA_FUA48");
115f3631e8dSAlexander Motin case 0x3e: return ("WRITE_DMA_QUEUED_FUA48");
1168691755dSAlexander Motin case 0x3f: return ("WRITE_LOG_EXT");
1178691755dSAlexander Motin case 0x40: return ("READ_VERIFY");
1188691755dSAlexander Motin case 0x42: return ("READ_VERIFY48");
1190404d598SAlexander Motin case 0x44:
1200404d598SAlexander Motin switch (cmd->features) {
1210404d598SAlexander Motin case 0x01: return ("ZERO_EXT TRIM");
1220404d598SAlexander Motin }
1230404d598SAlexander Motin return "ZERO_EXT";
124dd4637c0SRavi Pokala case 0x45:
125dd4637c0SRavi Pokala switch (cmd->features) {
126dd4637c0SRavi Pokala case 0x55: return ("WRITE_UNCORRECTABLE48 PSEUDO");
127dd4637c0SRavi Pokala case 0xaa: return ("WRITE_UNCORRECTABLE48 FLAGGED");
128dd4637c0SRavi Pokala }
129dd4637c0SRavi Pokala return "WRITE_UNCORRECTABLE48";
1309a6844d5SKenneth D. Merry case 0x47: return ("READ_LOG_DMA_EXT");
1319a6844d5SKenneth D. Merry case 0x4a: return ("ZAC_MANAGEMENT_IN");
1328691755dSAlexander Motin case 0x51: return ("CONFIGURE_STREAM");
1331e3d53e2SAlexander Motin case 0x57: return ("WRITE_LOG_DMA_EXT");
1341e3d53e2SAlexander Motin case 0x5b: return ("TRUSTED_NON_DATA");
1351e3d53e2SAlexander Motin case 0x5c: return ("TRUSTED_RECEIVE");
1361e3d53e2SAlexander Motin case 0x5d: return ("TRUSTED_RECEIVE_DMA");
1371e3d53e2SAlexander Motin case 0x5e: return ("TRUSTED_SEND");
1381e3d53e2SAlexander Motin case 0x5f: return ("TRUSTED_SEND_DMA");
1398691755dSAlexander Motin case 0x60: return ("READ_FPDMA_QUEUED");
1408691755dSAlexander Motin case 0x61: return ("WRITE_FPDMA_QUEUED");
1419a6844d5SKenneth D. Merry case 0x63:
1429a6844d5SKenneth D. Merry switch (cmd->features & 0xf) {
1439a6844d5SKenneth D. Merry case 0x00: return ("NCQ_NON_DATA ABORT NCQ QUEUE");
1449a6844d5SKenneth D. Merry case 0x01: return ("NCQ_NON_DATA DEADLINE HANDLING");
1450404d598SAlexander Motin case 0x02: return ("NCQ_NON_DATA HYBRID DEMOTE BY SIZE");
1460404d598SAlexander Motin case 0x03: return ("NCQ_NON_DATA HYBRID CHANGE BY LBA RANGE");
1470404d598SAlexander Motin case 0x04: return ("NCQ_NON_DATA HYBRID CONTROL");
1489a6844d5SKenneth D. Merry case 0x05: return ("NCQ_NON_DATA SET FEATURES");
1499a6844d5SKenneth D. Merry /*
1509a6844d5SKenneth D. Merry * XXX KDM need common decoding between NCQ and non-NCQ
1519a6844d5SKenneth D. Merry * versions of SET FEATURES.
1529a6844d5SKenneth D. Merry */
1539a6844d5SKenneth D. Merry case 0x06: return ("NCQ_NON_DATA ZERO EXT");
1549a6844d5SKenneth D. Merry case 0x07: return ("NCQ_NON_DATA ZAC MANAGEMENT OUT");
1559a6844d5SKenneth D. Merry }
1569a6844d5SKenneth D. Merry return ("NCQ_NON_DATA");
1579a6844d5SKenneth D. Merry case 0x64:
1589a6844d5SKenneth D. Merry switch (cmd->sector_count_exp & 0xf) {
1599a6844d5SKenneth D. Merry case 0x00: return ("SEND_FPDMA_QUEUED DATA SET MANAGEMENT");
1600404d598SAlexander Motin case 0x01: return ("SEND_FPDMA_QUEUED HYBRID EVICT");
1619a6844d5SKenneth D. Merry case 0x02: return ("SEND_FPDMA_QUEUED WRITE LOG DMA EXT");
1629a6844d5SKenneth D. Merry case 0x03: return ("SEND_FPDMA_QUEUED ZAC MANAGEMENT OUT");
1639a6844d5SKenneth D. Merry case 0x04: return ("SEND_FPDMA_QUEUED DATA SET MANAGEMENT XL");
1649a6844d5SKenneth D. Merry }
1659a6844d5SKenneth D. Merry return ("SEND_FPDMA_QUEUED");
1669a6844d5SKenneth D. Merry case 0x65:
1679a6844d5SKenneth D. Merry switch (cmd->sector_count_exp & 0xf) {
1689a6844d5SKenneth D. Merry case 0x01: return ("RECEIVE_FPDMA_QUEUED READ LOG DMA EXT");
1699a6844d5SKenneth D. Merry case 0x02: return ("RECEIVE_FPDMA_QUEUED ZAC MANAGEMENT IN");
1709a6844d5SKenneth D. Merry }
1719a6844d5SKenneth D. Merry return ("RECEIVE_FPDMA_QUEUED");
1723089bb2eSAlexander Motin case 0x67:
1733089bb2eSAlexander Motin if (cmd->features == 0xec)
1743089bb2eSAlexander Motin return ("SEP_ATTN IDENTIFY");
1753089bb2eSAlexander Motin switch (cmd->lba_low) {
1763089bb2eSAlexander Motin case 0x00: return ("SEP_ATTN READ BUFFER");
1773089bb2eSAlexander Motin case 0x02: return ("SEP_ATTN RECEIVE DIAGNOSTIC RESULTS");
1783089bb2eSAlexander Motin case 0x80: return ("SEP_ATTN WRITE BUFFER");
1793089bb2eSAlexander Motin case 0x82: return ("SEP_ATTN SEND DIAGNOSTIC");
1803089bb2eSAlexander Motin }
1813089bb2eSAlexander Motin return ("SEP_ATTN");
1828691755dSAlexander Motin case 0x70: return ("SEEK");
1831e3d53e2SAlexander Motin case 0x77: return ("SET_DATE_TIME_EXT");
18489b35a52SAlexander Motin case 0x78:
18589b35a52SAlexander Motin switch (cmd->features) {
18689b35a52SAlexander Motin case 0x00: return ("GET_NATIVE_MAX_ADDRESS_EXT");
18789b35a52SAlexander Motin case 0x01: return ("SET_ACCESSIBLE_MAX_ADDRESS_EXT");
18889b35a52SAlexander Motin case 0x02: return ("FREEZE_ACCESSIBLE_MAX_ADDRESS_EXT");
18989b35a52SAlexander Motin }
19089b35a52SAlexander Motin return ("ACCESSIBLE_MAX_ADDRESS_CONFIGURATION");
1910404d598SAlexander Motin case 0x7C: return ("REMOVE_ELEMENT_AND_TRUNCATE");
1928691755dSAlexander Motin case 0x87: return ("CFA_TRANSLATE_SECTOR");
1938691755dSAlexander Motin case 0x90: return ("EXECUTE_DEVICE_DIAGNOSTIC");
1948691755dSAlexander Motin case 0x92: return ("DOWNLOAD_MICROCODE");
1951e3d53e2SAlexander Motin case 0x93: return ("DOWNLOAD_MICROCODE_DMA");
1969a6844d5SKenneth D. Merry case 0x9a: return ("ZAC_MANAGEMENT_OUT");
1978691755dSAlexander Motin case 0xa0: return ("PACKET");
1988691755dSAlexander Motin case 0xa1: return ("ATAPI_IDENTIFY");
1998691755dSAlexander Motin case 0xa2: return ("SERVICE");
200dd4637c0SRavi Pokala case 0xb0:
201dd4637c0SRavi Pokala switch(cmd->features) {
202dd4637c0SRavi Pokala case 0xd0: return ("SMART READ ATTR VALUES");
203dd4637c0SRavi Pokala case 0xd1: return ("SMART READ ATTR THRESHOLDS");
204dd4637c0SRavi Pokala case 0xd3: return ("SMART SAVE ATTR VALUES");
205dd4637c0SRavi Pokala case 0xd4: return ("SMART EXECUTE OFFLINE IMMEDIATE");
2060404d598SAlexander Motin case 0xd5: return ("SMART READ LOG");
2070404d598SAlexander Motin case 0xd6: return ("SMART WRITE LOG");
208dd4637c0SRavi Pokala case 0xd8: return ("SMART ENABLE OPERATION");
209dd4637c0SRavi Pokala case 0xd9: return ("SMART DISABLE OPERATION");
210dd4637c0SRavi Pokala case 0xda: return ("SMART RETURN STATUS");
211dd4637c0SRavi Pokala }
212dd4637c0SRavi Pokala return ("SMART");
2138691755dSAlexander Motin case 0xb1: return ("DEVICE CONFIGURATION");
2140404d598SAlexander Motin case 0xb2: return ("SET_SECTOR_CONFIGURATION_EXT");
215c15a591cSAlexander Motin case 0xb4:
216c15a591cSAlexander Motin switch(cmd->features) {
217c15a591cSAlexander Motin case 0x00: return ("SANITIZE_STATUS_EXT");
218c15a591cSAlexander Motin case 0x11: return ("CRYPTO_SCRAMBLE_EXT");
219c15a591cSAlexander Motin case 0x12: return ("BLOCK_ERASE_EXT");
220c15a591cSAlexander Motin case 0x14: return ("OVERWRITE_EXT");
221c15a591cSAlexander Motin case 0x20: return ("SANITIZE_FREEZE_LOCK_EXT");
222c15a591cSAlexander Motin case 0x40: return ("SANITIZE_ANTIFREEZE_LOCK_EXT");
223c15a591cSAlexander Motin }
224c15a591cSAlexander Motin return ("SANITIZE_DEVICE");
2258691755dSAlexander Motin case 0xc0: return ("CFA_ERASE");
2268691755dSAlexander Motin case 0xc4: return ("READ_MUL");
2278691755dSAlexander Motin case 0xc5: return ("WRITE_MUL");
2288691755dSAlexander Motin case 0xc6: return ("SET_MULTI");
2298691755dSAlexander Motin case 0xc7: return ("READ_DMA_QUEUED");
2308691755dSAlexander Motin case 0xc8: return ("READ_DMA");
2318691755dSAlexander Motin case 0xca: return ("WRITE_DMA");
2328691755dSAlexander Motin case 0xcc: return ("WRITE_DMA_QUEUED");
2338691755dSAlexander Motin case 0xcd: return ("CFA_WRITE_MULTIPLE_WITHOUT_ERASE");
234f3631e8dSAlexander Motin case 0xce: return ("WRITE_MUL_FUA48");
2358691755dSAlexander Motin case 0xd1: return ("CHECK_MEDIA_CARD_TYPE");
2368691755dSAlexander Motin case 0xda: return ("GET_MEDIA_STATUS");
2378691755dSAlexander Motin case 0xde: return ("MEDIA_LOCK");
2388691755dSAlexander Motin case 0xdf: return ("MEDIA_UNLOCK");
2398691755dSAlexander Motin case 0xe0: return ("STANDBY_IMMEDIATE");
2408691755dSAlexander Motin case 0xe1: return ("IDLE_IMMEDIATE");
2418691755dSAlexander Motin case 0xe2: return ("STANDBY");
2428691755dSAlexander Motin case 0xe3: return ("IDLE");
2438691755dSAlexander Motin case 0xe4: return ("READ_BUFFER/PM");
2448691755dSAlexander Motin case 0xe5: return ("CHECK_POWER_MODE");
2458691755dSAlexander Motin case 0xe6: return ("SLEEP");
2468691755dSAlexander Motin case 0xe7: return ("FLUSHCACHE");
2479345f88fSAlexander Motin case 0xe8: return ("WRITE_BUFFER/PM");
2489345f88fSAlexander Motin case 0xe9: return ("READ_BUFFER_DMA");
2498691755dSAlexander Motin case 0xea: return ("FLUSHCACHE48");
2509345f88fSAlexander Motin case 0xeb: return ("WRITE_BUFFER_DMA");
2518691755dSAlexander Motin case 0xec: return ("ATA_IDENTIFY");
2528691755dSAlexander Motin case 0xed: return ("MEDIA_EJECT");
2538691755dSAlexander Motin case 0xef:
2549a6844d5SKenneth D. Merry /*
2559a6844d5SKenneth D. Merry * XXX KDM need common decoding between NCQ and non-NCQ
2569a6844d5SKenneth D. Merry * versions of SET FEATURES.
2579a6844d5SKenneth D. Merry */
2588691755dSAlexander Motin switch (cmd->features) {
2598691755dSAlexander Motin case 0x02: return ("SETFEATURES ENABLE WCACHE");
2609a6844d5SKenneth D. Merry case 0x03: return ("SETFEATURES SET TRANSFER MODE");
2610404d598SAlexander Motin case 0x05: return ("SETFEATURES ENABLE APM");
2624ef08dc5SAlexander Motin case 0x06: return ("SETFEATURES ENABLE PUIS");
2634ef08dc5SAlexander Motin case 0x07: return ("SETFEATURES SPIN-UP");
2649a6844d5SKenneth D. Merry case 0x0b: return ("SETFEATURES ENABLE WRITE READ VERIFY");
2659a6844d5SKenneth D. Merry case 0x0c: return ("SETFEATURES ENABLE DEVICE LIFE CONTROL");
266276b0834SAlexander Motin case 0x10: return ("SETFEATURES ENABLE SATA FEATURE");
2679a6844d5SKenneth D. Merry case 0x41: return ("SETFEATURES ENABLE FREEFALL CONTROL");
2689a6844d5SKenneth D. Merry case 0x43: return ("SETFEATURES SET MAX HOST INT SECT TIMES");
2699a6844d5SKenneth D. Merry case 0x45: return ("SETFEATURES SET RATE BASIS");
2709a6844d5SKenneth D. Merry case 0x4a: return ("SETFEATURES EXTENDED POWER CONDITIONS");
2710404d598SAlexander Motin case 0x50: return ("SETFEATURES ADVANCED BACKGROUD OPERATION");
2728691755dSAlexander Motin case 0x55: return ("SETFEATURES DISABLE RCACHE");
273dd4637c0SRavi Pokala case 0x5d: return ("SETFEATURES ENABLE RELIRQ");
274dd4637c0SRavi Pokala case 0x5e: return ("SETFEATURES ENABLE SRVIRQ");
2759a6844d5SKenneth D. Merry case 0x62: return ("SETFEATURES LONG PHYS SECT ALIGN ERC");
2769a6844d5SKenneth D. Merry case 0x63: return ("SETFEATURES DSN");
2779a6844d5SKenneth D. Merry case 0x66: return ("SETFEATURES DISABLE DEFAULTS");
2789a6844d5SKenneth D. Merry case 0x82: return ("SETFEATURES DISABLE WCACHE");
2799a6844d5SKenneth D. Merry case 0x85: return ("SETFEATURES DISABLE APM");
2809a6844d5SKenneth D. Merry case 0x86: return ("SETFEATURES DISABLE PUIS");
2819a6844d5SKenneth D. Merry case 0x8b: return ("SETFEATURES DISABLE WRITE READ VERIFY");
2829a6844d5SKenneth D. Merry case 0x8c: return ("SETFEATURES DISABLE DEVICE LIFE CONTROL");
2839a6844d5SKenneth D. Merry case 0x90: return ("SETFEATURES DISABLE SATA FEATURE");
2849a6844d5SKenneth D. Merry case 0xaa: return ("SETFEATURES ENABLE RCACHE");
2859a6844d5SKenneth D. Merry case 0xC1: return ("SETFEATURES DISABLE FREEFALL CONTROL");
2869a6844d5SKenneth D. Merry case 0xC3: return ("SETFEATURES SENSE DATA REPORTING");
2879a6844d5SKenneth D. Merry case 0xC4: return ("SETFEATURES NCQ SENSE DATA RETURN");
2889a6844d5SKenneth D. Merry case 0xCC: return ("SETFEATURES ENABLE DEFAULTS");
2899a6844d5SKenneth D. Merry case 0xdd: return ("SETFEATURES DISABLE RELIRQ");
290dd4637c0SRavi Pokala case 0xde: return ("SETFEATURES DISABLE SRVIRQ");
2918691755dSAlexander Motin }
2928691755dSAlexander Motin return "SETFEATURES";
2938691755dSAlexander Motin case 0xf1: return ("SECURITY_SET_PASSWORD");
2948691755dSAlexander Motin case 0xf2: return ("SECURITY_UNLOCK");
2958691755dSAlexander Motin case 0xf3: return ("SECURITY_ERASE_PREPARE");
2968691755dSAlexander Motin case 0xf4: return ("SECURITY_ERASE_UNIT");
297f4bd5f21SChristian Brueffer case 0xf5: return ("SECURITY_FREEZE_LOCK");
298f4bd5f21SChristian Brueffer case 0xf6: return ("SECURITY_DISABLE_PASSWORD");
2998691755dSAlexander Motin case 0xf8: return ("READ_NATIVE_MAX_ADDRESS");
3008691755dSAlexander Motin case 0xf9: return ("SET_MAX_ADDRESS");
3018691755dSAlexander Motin }
3028691755dSAlexander Motin return "UNKNOWN";
3038691755dSAlexander Motin }
3048691755dSAlexander Motin
3058691755dSAlexander Motin char *
ata_cmd_string(struct ata_cmd * cmd,char * cmd_string,size_t len)3068691755dSAlexander Motin ata_cmd_string(struct ata_cmd *cmd, char *cmd_string, size_t len)
3078691755dSAlexander Motin {
308c9767ca8SScott Long struct sbuf sb;
309c9767ca8SScott Long int error;
3108691755dSAlexander Motin
311c9767ca8SScott Long if (len == 0)
312c9767ca8SScott Long return ("");
313c9767ca8SScott Long
314c9767ca8SScott Long sbuf_new(&sb, cmd_string, len, SBUF_FIXEDLEN);
315c9767ca8SScott Long ata_cmd_sbuf(cmd, &sb);
316c9767ca8SScott Long
317c9767ca8SScott Long error = sbuf_finish(&sb);
318cd500da9SAlexander Motin if (error != 0 &&
319cd500da9SAlexander Motin #ifdef _KERNEL
320cd500da9SAlexander Motin error != ENOMEM)
321cd500da9SAlexander Motin #else
322cd500da9SAlexander Motin errno != ENOMEM)
323cd500da9SAlexander Motin #endif
324c9767ca8SScott Long return ("");
325c9767ca8SScott Long
326c9767ca8SScott Long return(sbuf_data(&sb));
327c9767ca8SScott Long }
328c9767ca8SScott Long
329c9767ca8SScott Long void
ata_cmd_sbuf(struct ata_cmd * cmd,struct sbuf * sb)330c9767ca8SScott Long ata_cmd_sbuf(struct ata_cmd *cmd, struct sbuf *sb)
331c9767ca8SScott Long {
332c9767ca8SScott Long sbuf_printf(sb, "%02x %02x %02x %02x "
3338691755dSAlexander Motin "%02x %02x %02x %02x %02x %02x %02x %02x",
3348691755dSAlexander Motin cmd->command, cmd->features,
3358691755dSAlexander Motin cmd->lba_low, cmd->lba_mid, cmd->lba_high, cmd->device,
3368691755dSAlexander Motin cmd->lba_low_exp, cmd->lba_mid_exp, cmd->lba_high_exp,
3378691755dSAlexander Motin cmd->features_exp, cmd->sector_count, cmd->sector_count_exp);
3388691755dSAlexander Motin }
3398691755dSAlexander Motin
3408691755dSAlexander Motin char *
ata_res_string(struct ata_res * res,char * res_string,size_t len)3418691755dSAlexander Motin ata_res_string(struct ata_res *res, char *res_string, size_t len)
3428691755dSAlexander Motin {
343c9767ca8SScott Long struct sbuf sb;
344c9767ca8SScott Long int error;
3458691755dSAlexander Motin
346c9767ca8SScott Long if (len == 0)
347c9767ca8SScott Long return ("");
348c9767ca8SScott Long
349c9767ca8SScott Long sbuf_new(&sb, res_string, len, SBUF_FIXEDLEN);
350c9767ca8SScott Long ata_res_sbuf(res, &sb);
351c9767ca8SScott Long
352c9767ca8SScott Long error = sbuf_finish(&sb);
353cd500da9SAlexander Motin if (error != 0 &&
354cd500da9SAlexander Motin #ifdef _KERNEL
355cd500da9SAlexander Motin error != ENOMEM)
356cd500da9SAlexander Motin #else
357cd500da9SAlexander Motin errno != ENOMEM)
358cd500da9SAlexander Motin #endif
359c9767ca8SScott Long return ("");
360c9767ca8SScott Long
361c9767ca8SScott Long return(sbuf_data(&sb));
362c9767ca8SScott Long }
363c9767ca8SScott Long
364c9767ca8SScott Long int
ata_res_sbuf(struct ata_res * res,struct sbuf * sb)365c9767ca8SScott Long ata_res_sbuf(struct ata_res *res, struct sbuf *sb)
366c9767ca8SScott Long {
367c9767ca8SScott Long
368c9767ca8SScott Long sbuf_printf(sb, "%02x %02x %02x %02x "
3698691755dSAlexander Motin "%02x %02x %02x %02x %02x %02x %02x",
3708691755dSAlexander Motin res->status, res->error,
3718691755dSAlexander Motin res->lba_low, res->lba_mid, res->lba_high, res->device,
3728691755dSAlexander Motin res->lba_low_exp, res->lba_mid_exp, res->lba_high_exp,
3738691755dSAlexander Motin res->sector_count, res->sector_count_exp);
3748691755dSAlexander Motin
375c9767ca8SScott Long return (0);
3768691755dSAlexander Motin }
3778691755dSAlexander Motin
3788691755dSAlexander Motin /*
3798691755dSAlexander Motin * ata_command_sbuf() returns 0 for success and -1 for failure.
3808691755dSAlexander Motin */
3818691755dSAlexander Motin int
ata_command_sbuf(struct ccb_ataio * ataio,struct sbuf * sb)3828691755dSAlexander Motin ata_command_sbuf(struct ccb_ataio *ataio, struct sbuf *sb)
3838691755dSAlexander Motin {
3848691755dSAlexander Motin
385c9767ca8SScott Long sbuf_printf(sb, "%s. ACB: ",
386c9767ca8SScott Long ata_op_string(&ataio->cmd));
387c9767ca8SScott Long ata_cmd_sbuf(&ataio->cmd, sb);
3888691755dSAlexander Motin
3898691755dSAlexander Motin return(0);
3908691755dSAlexander Motin }
3918691755dSAlexander Motin
3928691755dSAlexander Motin /*
3938691755dSAlexander Motin * ata_status_abuf() returns 0 for success and -1 for failure.
3948691755dSAlexander Motin */
3958691755dSAlexander Motin int
ata_status_sbuf(struct ccb_ataio * ataio,struct sbuf * sb)3968691755dSAlexander Motin ata_status_sbuf(struct ccb_ataio *ataio, struct sbuf *sb)
3978691755dSAlexander Motin {
3988691755dSAlexander Motin
39983c5d981SAlexander Motin sbuf_printf(sb, "ATA status: %02x (%s%s%s%s%s%s%s%s)",
4008691755dSAlexander Motin ataio->res.status,
4018691755dSAlexander Motin (ataio->res.status & 0x80) ? "BSY " : "",
4028691755dSAlexander Motin (ataio->res.status & 0x40) ? "DRDY " : "",
4038691755dSAlexander Motin (ataio->res.status & 0x20) ? "DF " : "",
4048691755dSAlexander Motin (ataio->res.status & 0x10) ? "SERV " : "",
4058691755dSAlexander Motin (ataio->res.status & 0x08) ? "DRQ " : "",
4068691755dSAlexander Motin (ataio->res.status & 0x04) ? "CORR " : "",
4078691755dSAlexander Motin (ataio->res.status & 0x02) ? "IDX " : "",
4088691755dSAlexander Motin (ataio->res.status & 0x01) ? "ERR" : "");
4098691755dSAlexander Motin if (ataio->res.status & 1) {
41083c5d981SAlexander Motin sbuf_printf(sb, ", error: %02x (%s%s%s%s%s%s%s%s)",
4118691755dSAlexander Motin ataio->res.error,
4128691755dSAlexander Motin (ataio->res.error & 0x80) ? "ICRC " : "",
4138691755dSAlexander Motin (ataio->res.error & 0x40) ? "UNC " : "",
4148691755dSAlexander Motin (ataio->res.error & 0x20) ? "MC " : "",
4158691755dSAlexander Motin (ataio->res.error & 0x10) ? "IDNF " : "",
4168691755dSAlexander Motin (ataio->res.error & 0x08) ? "MCR " : "",
4178691755dSAlexander Motin (ataio->res.error & 0x04) ? "ABRT " : "",
4188691755dSAlexander Motin (ataio->res.error & 0x02) ? "NM " : "",
4198691755dSAlexander Motin (ataio->res.error & 0x01) ? "ILI" : "");
4208691755dSAlexander Motin }
4218691755dSAlexander Motin
4228691755dSAlexander Motin return(0);
4238691755dSAlexander Motin }
4248691755dSAlexander Motin
42552c9ce25SScott Long void
ata_print_ident(struct ata_params * ident_data)42652c9ce25SScott Long ata_print_ident(struct ata_params *ident_data)
42752c9ce25SScott Long {
4284f42bb10SAlexander Motin const char *proto;
4295d01277fSScott Long char ata[12], sata[12];
43052c9ce25SScott Long
4315d01277fSScott Long ata_print_ident_short(ident_data);
4325d01277fSScott Long
4334f42bb10SAlexander Motin proto = (ident_data->config == ATA_PROTO_CFA) ? "CFA" :
4344f42bb10SAlexander Motin (ident_data->config & ATA_PROTO_ATAPI) ? "ATAPI" : "ATA";
4354f42bb10SAlexander Motin if (ata_version(ident_data->version_major) == 0) {
4364f42bb10SAlexander Motin snprintf(ata, sizeof(ata), "%s", proto);
4374f42bb10SAlexander Motin } else if (ata_version(ident_data->version_major) <= 7) {
4384f42bb10SAlexander Motin snprintf(ata, sizeof(ata), "%s-%d", proto,
4397bdb664eSAlexander Motin ata_version(ident_data->version_major));
4404f42bb10SAlexander Motin } else if (ata_version(ident_data->version_major) == 8) {
4414f42bb10SAlexander Motin snprintf(ata, sizeof(ata), "%s8-ACS", proto);
4424f42bb10SAlexander Motin } else {
4434f42bb10SAlexander Motin snprintf(ata, sizeof(ata), "ACS-%d %s",
4444f42bb10SAlexander Motin ata_version(ident_data->version_major) - 7, proto);
4454f42bb10SAlexander Motin }
44652c9ce25SScott Long if (ident_data->satacapabilities && ident_data->satacapabilities != 0xffff) {
44714a0f03dSAlexander Motin if (ident_data->satacapabilities & ATA_SATA_GEN3)
4484f42bb10SAlexander Motin snprintf(sata, sizeof(sata), " SATA 3.x");
44914a0f03dSAlexander Motin else if (ident_data->satacapabilities & ATA_SATA_GEN2)
4504f42bb10SAlexander Motin snprintf(sata, sizeof(sata), " SATA 2.x");
45152c9ce25SScott Long else if (ident_data->satacapabilities & ATA_SATA_GEN1)
4524f42bb10SAlexander Motin snprintf(sata, sizeof(sata), " SATA 1.x");
45352c9ce25SScott Long else
4544f42bb10SAlexander Motin snprintf(sata, sizeof(sata), " SATA");
4554f42bb10SAlexander Motin } else
4564f42bb10SAlexander Motin sata[0] = 0;
4575d01277fSScott Long printf(" %s%s device\n", ata, sata);
4585d01277fSScott Long }
4595d01277fSScott Long
4605d01277fSScott Long void
ata_print_ident_sbuf(struct ata_params * ident_data,struct sbuf * sb)4615d01277fSScott Long ata_print_ident_sbuf(struct ata_params *ident_data, struct sbuf *sb)
4625d01277fSScott Long {
4635d01277fSScott Long const char *proto, *sata;
4645d01277fSScott Long int version;
4655d01277fSScott Long
4665d01277fSScott Long ata_print_ident_short_sbuf(ident_data, sb);
467*519b24f0SAlexander Motin sbuf_putc(sb, ' ');
4685d01277fSScott Long
4695d01277fSScott Long proto = (ident_data->config == ATA_PROTO_CFA) ? "CFA" :
4705d01277fSScott Long (ident_data->config & ATA_PROTO_ATAPI) ? "ATAPI" : "ATA";
4715d01277fSScott Long version = ata_version(ident_data->version_major);
4725d01277fSScott Long
4735d01277fSScott Long switch (version) {
4745d01277fSScott Long case 0:
4755d01277fSScott Long sbuf_printf(sb, "%s", proto);
4765d01277fSScott Long break;
4775d01277fSScott Long case 1:
4785d01277fSScott Long case 2:
4795d01277fSScott Long case 3:
4805d01277fSScott Long case 4:
4815d01277fSScott Long case 5:
4825d01277fSScott Long case 6:
4835d01277fSScott Long case 7:
4845d01277fSScott Long sbuf_printf(sb, "%s-%d", proto, version);
4855d01277fSScott Long break;
4865d01277fSScott Long case 8:
4875d01277fSScott Long sbuf_printf(sb, "%s8-ACS", proto);
4885d01277fSScott Long break;
4895d01277fSScott Long default:
4905d01277fSScott Long sbuf_printf(sb, "ACS-%d %s", version - 7, proto);
4915d01277fSScott Long break;
4925d01277fSScott Long }
4935d01277fSScott Long
4945d01277fSScott Long if (ident_data->satacapabilities && ident_data->satacapabilities != 0xffff) {
4955d01277fSScott Long if (ident_data->satacapabilities & ATA_SATA_GEN3)
4965d01277fSScott Long sata = " SATA 3.x";
4975d01277fSScott Long else if (ident_data->satacapabilities & ATA_SATA_GEN2)
4985d01277fSScott Long sata = " SATA 2.x";
4995d01277fSScott Long else if (ident_data->satacapabilities & ATA_SATA_GEN1)
5005d01277fSScott Long sata = " SATA 1.x";
5015d01277fSScott Long else
5025d01277fSScott Long sata = " SATA";
5035d01277fSScott Long } else
5045d01277fSScott Long sata = "";
5055d01277fSScott Long sbuf_printf(sb, "%s device\n", sata);
50652c9ce25SScott Long }
50752c9ce25SScott Long
5083089bb2eSAlexander Motin void
ata_print_ident_short(struct ata_params * ident_data)5098d36a71bSAlexander Motin ata_print_ident_short(struct ata_params *ident_data)
5108d36a71bSAlexander Motin {
5118d36a71bSAlexander Motin char product[48], revision[16];
5128d36a71bSAlexander Motin
5138d36a71bSAlexander Motin cam_strvis(product, ident_data->model, sizeof(ident_data->model),
5148d36a71bSAlexander Motin sizeof(product));
5158d36a71bSAlexander Motin cam_strvis(revision, ident_data->revision, sizeof(ident_data->revision),
5168d36a71bSAlexander Motin sizeof(revision));
5178d36a71bSAlexander Motin printf("<%s %s>", product, revision);
5188d36a71bSAlexander Motin }
5198d36a71bSAlexander Motin
5208d36a71bSAlexander Motin void
ata_print_ident_short_sbuf(struct ata_params * ident_data,struct sbuf * sb)5215d01277fSScott Long ata_print_ident_short_sbuf(struct ata_params *ident_data, struct sbuf *sb)
5225d01277fSScott Long {
5235d01277fSScott Long
524*519b24f0SAlexander Motin sbuf_putc(sb, '<');
5255d01277fSScott Long cam_strvis_sbuf(sb, ident_data->model, sizeof(ident_data->model), 0);
526*519b24f0SAlexander Motin sbuf_putc(sb, ' ');
5275d01277fSScott Long cam_strvis_sbuf(sb, ident_data->revision, sizeof(ident_data->revision), 0);
528*519b24f0SAlexander Motin sbuf_putc(sb, '>');
5295d01277fSScott Long }
5305d01277fSScott Long
5315d01277fSScott Long void
semb_print_ident(struct sep_identify_data * ident_data)5323089bb2eSAlexander Motin semb_print_ident(struct sep_identify_data *ident_data)
5333089bb2eSAlexander Motin {
5345d01277fSScott Long char in[7], ins[5];
5353089bb2eSAlexander Motin
5365d01277fSScott Long semb_print_ident_short(ident_data);
5373089bb2eSAlexander Motin cam_strvis(in, ident_data->interface_id, 6, sizeof(in));
5383089bb2eSAlexander Motin cam_strvis(ins, ident_data->interface_rev, 4, sizeof(ins));
5395d01277fSScott Long printf(" SEMB %s %s device\n", in, ins);
5405d01277fSScott Long }
5415d01277fSScott Long
5425d01277fSScott Long void
semb_print_ident_sbuf(struct sep_identify_data * ident_data,struct sbuf * sb)5435d01277fSScott Long semb_print_ident_sbuf(struct sep_identify_data *ident_data, struct sbuf *sb)
5445d01277fSScott Long {
5455d01277fSScott Long
5465d01277fSScott Long semb_print_ident_short_sbuf(ident_data, sb);
5475d01277fSScott Long
548*519b24f0SAlexander Motin sbuf_cat(sb, " SEMB ");
5495d01277fSScott Long cam_strvis_sbuf(sb, ident_data->interface_id, 6, 0);
550*519b24f0SAlexander Motin sbuf_putc(sb, ' ');
5515d01277fSScott Long cam_strvis_sbuf(sb, ident_data->interface_rev, 4, 0);
552*519b24f0SAlexander Motin sbuf_cat(sb, " device\n");
5533089bb2eSAlexander Motin }
5543089bb2eSAlexander Motin
5558d36a71bSAlexander Motin void
semb_print_ident_short(struct sep_identify_data * ident_data)5568d36a71bSAlexander Motin semb_print_ident_short(struct sep_identify_data *ident_data)
5578d36a71bSAlexander Motin {
5588d36a71bSAlexander Motin char vendor[9], product[17], revision[5], fw[5];
5598d36a71bSAlexander Motin
5608d36a71bSAlexander Motin cam_strvis(vendor, ident_data->vendor_id, 8, sizeof(vendor));
5618d36a71bSAlexander Motin cam_strvis(product, ident_data->product_id, 16, sizeof(product));
5628d36a71bSAlexander Motin cam_strvis(revision, ident_data->product_rev, 4, sizeof(revision));
5638d36a71bSAlexander Motin cam_strvis(fw, ident_data->firmware_rev, 4, sizeof(fw));
5648d36a71bSAlexander Motin printf("<%s %s %s %s>", vendor, product, revision, fw);
5658d36a71bSAlexander Motin }
5668d36a71bSAlexander Motin
5675d01277fSScott Long void
semb_print_ident_short_sbuf(struct sep_identify_data * ident_data,struct sbuf * sb)5685d01277fSScott Long semb_print_ident_short_sbuf(struct sep_identify_data *ident_data, struct sbuf *sb)
5695d01277fSScott Long {
5705d01277fSScott Long
571*519b24f0SAlexander Motin sbuf_putc(sb, '<');
5725d01277fSScott Long cam_strvis_sbuf(sb, ident_data->vendor_id, 8, 0);
573*519b24f0SAlexander Motin sbuf_putc(sb, ' ');
5745d01277fSScott Long cam_strvis_sbuf(sb, ident_data->product_id, 16, 0);
575*519b24f0SAlexander Motin sbuf_putc(sb, ' ');
5765d01277fSScott Long cam_strvis_sbuf(sb, ident_data->product_rev, 4, 0);
577*519b24f0SAlexander Motin sbuf_putc(sb, ' ');
5785d01277fSScott Long cam_strvis_sbuf(sb, ident_data->firmware_rev, 4, 0);
579*519b24f0SAlexander Motin sbuf_putc(sb, '>');
5805d01277fSScott Long }
5815d01277fSScott Long
582c1bd46c2SAlexander Motin uint32_t
ata_logical_sector_size(struct ata_params * ident_data)583c1bd46c2SAlexander Motin ata_logical_sector_size(struct ata_params *ident_data)
584c1bd46c2SAlexander Motin {
5856d45fdc9SAlexander Motin if ((ident_data->pss & ATA_PSS_VALID_MASK) == ATA_PSS_VALID_VALUE &&
586c1bd46c2SAlexander Motin (ident_data->pss & ATA_PSS_LSSABOVE512)) {
5879db2db6bSWarner Losh return (((uint32_t)ident_data->lss_1 |
5889db2db6bSWarner Losh ((uint32_t)ident_data->lss_2 << 16)) * 2);
589c1bd46c2SAlexander Motin }
590c1bd46c2SAlexander Motin return (512);
591c1bd46c2SAlexander Motin }
592c1bd46c2SAlexander Motin
593c1bd46c2SAlexander Motin uint64_t
ata_physical_sector_size(struct ata_params * ident_data)594c1bd46c2SAlexander Motin ata_physical_sector_size(struct ata_params *ident_data)
595c1bd46c2SAlexander Motin {
5966d45fdc9SAlexander Motin if ((ident_data->pss & ATA_PSS_VALID_MASK) == ATA_PSS_VALID_VALUE) {
5976d45fdc9SAlexander Motin if (ident_data->pss & ATA_PSS_MULTLS) {
598c1bd46c2SAlexander Motin return ((uint64_t)ata_logical_sector_size(ident_data) *
599c1bd46c2SAlexander Motin (1 << (ident_data->pss & ATA_PSS_LSPPS)));
6006d45fdc9SAlexander Motin } else {
6016d45fdc9SAlexander Motin return (uint64_t)ata_logical_sector_size(ident_data);
6026d45fdc9SAlexander Motin }
603c1bd46c2SAlexander Motin }
604c1bd46c2SAlexander Motin return (512);
605c1bd46c2SAlexander Motin }
606c1bd46c2SAlexander Motin
607c1bd46c2SAlexander Motin uint64_t
ata_logical_sector_offset(struct ata_params * ident_data)608c1bd46c2SAlexander Motin ata_logical_sector_offset(struct ata_params *ident_data)
609c1bd46c2SAlexander Motin {
610c1bd46c2SAlexander Motin if ((ident_data->lsalign & 0xc000) == 0x4000) {
611c1bd46c2SAlexander Motin return ((uint64_t)ata_logical_sector_size(ident_data) *
612c1bd46c2SAlexander Motin (ident_data->lsalign & 0x3fff));
613c1bd46c2SAlexander Motin }
614c1bd46c2SAlexander Motin return (0);
615c1bd46c2SAlexander Motin }
616c1bd46c2SAlexander Motin
61752c9ce25SScott Long void
ata_28bit_cmd(struct ccb_ataio * ataio,uint8_t cmd,uint8_t features,uint32_t lba,uint8_t sector_count)6187606b445SAlexander Motin ata_28bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint8_t features,
61952c9ce25SScott Long uint32_t lba, uint8_t sector_count)
62052c9ce25SScott Long {
62152c9ce25SScott Long bzero(&ataio->cmd, sizeof(ataio->cmd));
62252c9ce25SScott Long ataio->cmd.flags = 0;
623f3631e8dSAlexander Motin if (cmd == ATA_READ_DMA ||
624f3631e8dSAlexander Motin cmd == ATA_READ_DMA_QUEUED ||
625f3631e8dSAlexander Motin cmd == ATA_WRITE_DMA ||
6269345f88fSAlexander Motin cmd == ATA_WRITE_DMA_QUEUED ||
6279345f88fSAlexander Motin cmd == ATA_TRUSTED_RECEIVE_DMA ||
6289345f88fSAlexander Motin cmd == ATA_TRUSTED_SEND_DMA ||
6299345f88fSAlexander Motin cmd == ATA_DOWNLOAD_MICROCODE_DMA ||
6309345f88fSAlexander Motin cmd == ATA_READ_BUFFER_DMA ||
6319345f88fSAlexander Motin cmd == ATA_WRITE_BUFFER_DMA)
632f3631e8dSAlexander Motin ataio->cmd.flags |= CAM_ATAIO_DMA;
63352c9ce25SScott Long ataio->cmd.command = cmd;
63452c9ce25SScott Long ataio->cmd.features = features;
63552c9ce25SScott Long ataio->cmd.lba_low = lba;
63652c9ce25SScott Long ataio->cmd.lba_mid = lba >> 8;
63752c9ce25SScott Long ataio->cmd.lba_high = lba >> 16;
63897ab2275SChristian Brueffer ataio->cmd.device = ATA_DEV_LBA | ((lba >> 24) & 0x0f);
63952c9ce25SScott Long ataio->cmd.sector_count = sector_count;
64052c9ce25SScott Long }
64152c9ce25SScott Long
64252c9ce25SScott Long void
ata_48bit_cmd(struct ccb_ataio * ataio,uint8_t cmd,uint16_t features,uint64_t lba,uint16_t sector_count)64352c9ce25SScott Long ata_48bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint16_t features,
64452c9ce25SScott Long uint64_t lba, uint16_t sector_count)
64552c9ce25SScott Long {
6466d14d0d0SAlexander Motin
64752c9ce25SScott Long ataio->cmd.flags = CAM_ATAIO_48BIT;
648f3631e8dSAlexander Motin if (cmd == ATA_READ_DMA48 ||
649f3631e8dSAlexander Motin cmd == ATA_READ_DMA_QUEUED48 ||
650f3631e8dSAlexander Motin cmd == ATA_READ_STREAM_DMA48 ||
651f3631e8dSAlexander Motin cmd == ATA_WRITE_DMA48 ||
652f3631e8dSAlexander Motin cmd == ATA_WRITE_DMA_FUA48 ||
653f3631e8dSAlexander Motin cmd == ATA_WRITE_DMA_QUEUED48 ||
654f3631e8dSAlexander Motin cmd == ATA_WRITE_DMA_QUEUED_FUA48 ||
6551c80ec0aSAlexander Motin cmd == ATA_WRITE_STREAM_DMA48 ||
6569a6844d5SKenneth D. Merry cmd == ATA_DATA_SET_MANAGEMENT ||
6579345f88fSAlexander Motin cmd == ATA_READ_LOG_DMA_EXT ||
6589345f88fSAlexander Motin cmd == ATA_WRITE_LOG_DMA_EXT)
659f3631e8dSAlexander Motin ataio->cmd.flags |= CAM_ATAIO_DMA;
66052c9ce25SScott Long ataio->cmd.command = cmd;
66152c9ce25SScott Long ataio->cmd.features = features;
66252c9ce25SScott Long ataio->cmd.lba_low = lba;
66352c9ce25SScott Long ataio->cmd.lba_mid = lba >> 8;
66452c9ce25SScott Long ataio->cmd.lba_high = lba >> 16;
66597ab2275SChristian Brueffer ataio->cmd.device = ATA_DEV_LBA;
66652c9ce25SScott Long ataio->cmd.lba_low_exp = lba >> 24;
66752c9ce25SScott Long ataio->cmd.lba_mid_exp = lba >> 32;
66852c9ce25SScott Long ataio->cmd.lba_high_exp = lba >> 40;
66952c9ce25SScott Long ataio->cmd.features_exp = features >> 8;
67052c9ce25SScott Long ataio->cmd.sector_count = sector_count;
67152c9ce25SScott Long ataio->cmd.sector_count_exp = sector_count >> 8;
6726d14d0d0SAlexander Motin ataio->cmd.control = 0;
67352c9ce25SScott Long }
67452c9ce25SScott Long
67552c9ce25SScott Long void
ata_ncq_cmd(struct ccb_ataio * ataio,uint8_t cmd,uint64_t lba,uint16_t sector_count)67652c9ce25SScott Long ata_ncq_cmd(struct ccb_ataio *ataio, uint8_t cmd,
67752c9ce25SScott Long uint64_t lba, uint16_t sector_count)
67852c9ce25SScott Long {
6796d14d0d0SAlexander Motin
68052c9ce25SScott Long ataio->cmd.flags = CAM_ATAIO_48BIT | CAM_ATAIO_FPDMA;
68152c9ce25SScott Long ataio->cmd.command = cmd;
68252c9ce25SScott Long ataio->cmd.features = sector_count;
68352c9ce25SScott Long ataio->cmd.lba_low = lba;
68452c9ce25SScott Long ataio->cmd.lba_mid = lba >> 8;
68552c9ce25SScott Long ataio->cmd.lba_high = lba >> 16;
68697ab2275SChristian Brueffer ataio->cmd.device = ATA_DEV_LBA;
68752c9ce25SScott Long ataio->cmd.lba_low_exp = lba >> 24;
68852c9ce25SScott Long ataio->cmd.lba_mid_exp = lba >> 32;
68952c9ce25SScott Long ataio->cmd.lba_high_exp = lba >> 40;
69052c9ce25SScott Long ataio->cmd.features_exp = sector_count >> 8;
6916d14d0d0SAlexander Motin ataio->cmd.sector_count = 0;
6926d14d0d0SAlexander Motin ataio->cmd.sector_count_exp = 0;
6936d14d0d0SAlexander Motin ataio->cmd.control = 0;
69452c9ce25SScott Long }
69552c9ce25SScott Long
69652c9ce25SScott Long void
ata_reset_cmd(struct ccb_ataio * ataio)69752c9ce25SScott Long ata_reset_cmd(struct ccb_ataio *ataio)
69852c9ce25SScott Long {
69952c9ce25SScott Long bzero(&ataio->cmd, sizeof(ataio->cmd));
70052c9ce25SScott Long ataio->cmd.flags = CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT;
70152c9ce25SScott Long ataio->cmd.control = 0x04;
70252c9ce25SScott Long }
70352c9ce25SScott Long
70452c9ce25SScott Long void
ata_pm_read_cmd(struct ccb_ataio * ataio,int reg,int port)70552c9ce25SScott Long ata_pm_read_cmd(struct ccb_ataio *ataio, int reg, int port)
70652c9ce25SScott Long {
70752c9ce25SScott Long bzero(&ataio->cmd, sizeof(ataio->cmd));
708fd2cc0bdSAlexander Motin ataio->cmd.flags = CAM_ATAIO_NEEDRESULT;
70952c9ce25SScott Long ataio->cmd.command = ATA_READ_PM;
71052c9ce25SScott Long ataio->cmd.features = reg;
71152c9ce25SScott Long ataio->cmd.device = port & 0x0f;
71252c9ce25SScott Long }
71352c9ce25SScott Long
71452c9ce25SScott Long void
ata_pm_write_cmd(struct ccb_ataio * ataio,int reg,int port,uint32_t val)715fd2cc0bdSAlexander Motin ata_pm_write_cmd(struct ccb_ataio *ataio, int reg, int port, uint32_t val)
71652c9ce25SScott Long {
71752c9ce25SScott Long bzero(&ataio->cmd, sizeof(ataio->cmd));
718fd2cc0bdSAlexander Motin ataio->cmd.flags = 0;
71952c9ce25SScott Long ataio->cmd.command = ATA_WRITE_PM;
72052c9ce25SScott Long ataio->cmd.features = reg;
721fd2cc0bdSAlexander Motin ataio->cmd.sector_count = val;
72252c9ce25SScott Long ataio->cmd.lba_low = val >> 8;
72352c9ce25SScott Long ataio->cmd.lba_mid = val >> 16;
72452c9ce25SScott Long ataio->cmd.lba_high = val >> 24;
72552c9ce25SScott Long ataio->cmd.device = port & 0x0f;
72652c9ce25SScott Long }
72752c9ce25SScott Long
72852c9ce25SScott Long 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)7299a6844d5SKenneth D. Merry ata_read_log(struct ccb_ataio *ataio, uint32_t retries,
7309a6844d5SKenneth D. Merry void (*cbfcnp)(struct cam_periph *, union ccb *),
7319a6844d5SKenneth D. Merry uint32_t log_address, uint32_t page_number, uint16_t block_count,
7329a6844d5SKenneth D. Merry uint32_t protocol, uint8_t *data_ptr, uint32_t dxfer_len,
7339a6844d5SKenneth D. Merry uint32_t timeout)
7349a6844d5SKenneth D. Merry {
7359a6844d5SKenneth D. Merry uint64_t lba;
7369a6844d5SKenneth D. Merry
7379a6844d5SKenneth D. Merry cam_fill_ataio(ataio,
7389a6844d5SKenneth D. Merry /*retries*/ 1,
7399a6844d5SKenneth D. Merry /*cbfcnp*/ cbfcnp,
7409a6844d5SKenneth D. Merry /*flags*/ CAM_DIR_IN,
7419a6844d5SKenneth D. Merry /*tag_action*/ 0,
7429a6844d5SKenneth D. Merry /*data_ptr*/ data_ptr,
7439a6844d5SKenneth D. Merry /*dxfer_len*/ dxfer_len,
7449a6844d5SKenneth D. Merry /*timeout*/ timeout);
7459a6844d5SKenneth D. Merry
7469a6844d5SKenneth D. Merry lba = (((uint64_t)page_number & 0xff00) << 32) |
7479a6844d5SKenneth D. Merry ((page_number & 0x00ff) << 8) |
7489a6844d5SKenneth D. Merry (log_address & 0xff);
7499a6844d5SKenneth D. Merry
7509a6844d5SKenneth D. Merry ata_48bit_cmd(ataio,
7519a6844d5SKenneth D. Merry /*cmd*/ (protocol & CAM_ATAIO_DMA) ? ATA_READ_LOG_DMA_EXT :
7529a6844d5SKenneth D. Merry ATA_READ_LOG_EXT,
7539a6844d5SKenneth D. Merry /*features*/ 0,
7549a6844d5SKenneth D. Merry /*lba*/ lba,
7559a6844d5SKenneth D. Merry /*sector_count*/ block_count);
7569a6844d5SKenneth D. Merry }
7579a6844d5SKenneth D. Merry
7589a6844d5SKenneth D. Merry void
ata_bswap(int8_t * buf,int len)75952c9ce25SScott Long ata_bswap(int8_t *buf, int len)
76052c9ce25SScott Long {
7619db2db6bSWarner Losh uint16_t *ptr = (uint16_t*)(buf + len);
76252c9ce25SScott Long
7639db2db6bSWarner Losh while (--ptr >= (uint16_t*)buf)
76452c9ce25SScott Long *ptr = be16toh(*ptr);
76552c9ce25SScott Long }
76652c9ce25SScott Long
76752c9ce25SScott Long void
ata_btrim(int8_t * buf,int len)76852c9ce25SScott Long ata_btrim(int8_t *buf, int len)
76952c9ce25SScott Long {
77052c9ce25SScott Long int8_t *ptr;
77152c9ce25SScott Long
77252c9ce25SScott Long for (ptr = buf; ptr < buf+len; ++ptr)
77352c9ce25SScott Long if (!*ptr || *ptr == '_')
77452c9ce25SScott Long *ptr = ' ';
77552c9ce25SScott Long for (ptr = buf + len - 1; ptr >= buf && *ptr == ' '; --ptr)
77652c9ce25SScott Long *ptr = 0;
77752c9ce25SScott Long }
77852c9ce25SScott Long
77952c9ce25SScott Long void
ata_bpack(int8_t * src,int8_t * dst,int len)78052c9ce25SScott Long ata_bpack(int8_t *src, int8_t *dst, int len)
78152c9ce25SScott Long {
78252c9ce25SScott Long int i, j, blank;
78352c9ce25SScott Long
78452c9ce25SScott Long for (i = j = blank = 0 ; i < len; i++) {
78552c9ce25SScott Long if (blank && src[i] == ' ') continue;
78652c9ce25SScott Long if (blank && src[i] != ' ') {
78752c9ce25SScott Long dst[j++] = src[i];
78852c9ce25SScott Long blank = 0;
78952c9ce25SScott Long continue;
79052c9ce25SScott Long }
79152c9ce25SScott Long if (src[i] == ' ') {
79252c9ce25SScott Long blank = 1;
79352c9ce25SScott Long if (i == 0)
79452c9ce25SScott Long continue;
79552c9ce25SScott Long }
79652c9ce25SScott Long dst[j++] = src[i];
79752c9ce25SScott Long }
79852c9ce25SScott Long while (j < len)
79952c9ce25SScott Long dst[j++] = 0x00;
80052c9ce25SScott Long }
80152c9ce25SScott Long
80252c9ce25SScott Long int
ata_max_pmode(struct ata_params * ap)80352c9ce25SScott Long ata_max_pmode(struct ata_params *ap)
80452c9ce25SScott Long {
80552c9ce25SScott Long if (ap->atavalid & ATA_FLAG_64_70) {
80652c9ce25SScott Long if (ap->apiomodes & 0x02)
80752c9ce25SScott Long return ATA_PIO4;
80852c9ce25SScott Long if (ap->apiomodes & 0x01)
80952c9ce25SScott Long return ATA_PIO3;
81052c9ce25SScott Long }
81152c9ce25SScott Long if (ap->mwdmamodes & 0x04)
81252c9ce25SScott Long return ATA_PIO4;
81352c9ce25SScott Long if (ap->mwdmamodes & 0x02)
81452c9ce25SScott Long return ATA_PIO3;
81552c9ce25SScott Long if (ap->mwdmamodes & 0x01)
81652c9ce25SScott Long return ATA_PIO2;
81752c9ce25SScott Long if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x200)
81852c9ce25SScott Long return ATA_PIO2;
81952c9ce25SScott Long if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x100)
82052c9ce25SScott Long return ATA_PIO1;
82152c9ce25SScott Long if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x000)
82252c9ce25SScott Long return ATA_PIO0;
82352c9ce25SScott Long return ATA_PIO0;
82452c9ce25SScott Long }
82552c9ce25SScott Long
82652c9ce25SScott Long int
ata_max_wmode(struct ata_params * ap)82752c9ce25SScott Long ata_max_wmode(struct ata_params *ap)
82852c9ce25SScott Long {
82952c9ce25SScott Long if (ap->mwdmamodes & 0x04)
83052c9ce25SScott Long return ATA_WDMA2;
83152c9ce25SScott Long if (ap->mwdmamodes & 0x02)
83252c9ce25SScott Long return ATA_WDMA1;
83352c9ce25SScott Long if (ap->mwdmamodes & 0x01)
83452c9ce25SScott Long return ATA_WDMA0;
83552c9ce25SScott Long return -1;
83652c9ce25SScott Long }
83752c9ce25SScott Long
83852c9ce25SScott Long int
ata_max_umode(struct ata_params * ap)83952c9ce25SScott Long ata_max_umode(struct ata_params *ap)
84052c9ce25SScott Long {
84152c9ce25SScott Long if (ap->atavalid & ATA_FLAG_88) {
84252c9ce25SScott Long if (ap->udmamodes & 0x40)
84352c9ce25SScott Long return ATA_UDMA6;
84452c9ce25SScott Long if (ap->udmamodes & 0x20)
84552c9ce25SScott Long return ATA_UDMA5;
84652c9ce25SScott Long if (ap->udmamodes & 0x10)
84752c9ce25SScott Long return ATA_UDMA4;
84852c9ce25SScott Long if (ap->udmamodes & 0x08)
84952c9ce25SScott Long return ATA_UDMA3;
85052c9ce25SScott Long if (ap->udmamodes & 0x04)
85152c9ce25SScott Long return ATA_UDMA2;
85252c9ce25SScott Long if (ap->udmamodes & 0x02)
85352c9ce25SScott Long return ATA_UDMA1;
85452c9ce25SScott Long if (ap->udmamodes & 0x01)
85552c9ce25SScott Long return ATA_UDMA0;
85652c9ce25SScott Long }
85752c9ce25SScott Long return -1;
85852c9ce25SScott Long }
85952c9ce25SScott Long
86052c9ce25SScott Long int
ata_max_mode(struct ata_params * ap,int maxmode)861c8039fc6SAlexander Motin ata_max_mode(struct ata_params *ap, int maxmode)
86252c9ce25SScott Long {
86352c9ce25SScott Long
864c8039fc6SAlexander Motin if (maxmode == 0)
865c8039fc6SAlexander Motin maxmode = ATA_DMA_MAX;
866c8039fc6SAlexander Motin if (maxmode >= ATA_UDMA0 && ata_max_umode(ap) > 0)
867c8039fc6SAlexander Motin return (min(maxmode, ata_max_umode(ap)));
868c8039fc6SAlexander Motin if (maxmode >= ATA_WDMA0 && ata_max_wmode(ap) > 0)
869c8039fc6SAlexander Motin return (min(maxmode, ata_max_wmode(ap)));
870c8039fc6SAlexander Motin return (min(maxmode, ata_max_pmode(ap)));
871c8039fc6SAlexander Motin }
87252c9ce25SScott Long
873c8039fc6SAlexander Motin char *
ata_mode2string(int mode)874c8039fc6SAlexander Motin ata_mode2string(int mode)
875c8039fc6SAlexander Motin {
876c8039fc6SAlexander Motin switch (mode) {
877c8039fc6SAlexander Motin case -1: return "UNSUPPORTED";
878c8039fc6SAlexander Motin case 0: return "NONE";
879c8039fc6SAlexander Motin case ATA_PIO0: return "PIO0";
880c8039fc6SAlexander Motin case ATA_PIO1: return "PIO1";
881c8039fc6SAlexander Motin case ATA_PIO2: return "PIO2";
882c8039fc6SAlexander Motin case ATA_PIO3: return "PIO3";
883c8039fc6SAlexander Motin case ATA_PIO4: return "PIO4";
884c8039fc6SAlexander Motin case ATA_WDMA0: return "WDMA0";
885c8039fc6SAlexander Motin case ATA_WDMA1: return "WDMA1";
886c8039fc6SAlexander Motin case ATA_WDMA2: return "WDMA2";
887c8039fc6SAlexander Motin case ATA_UDMA0: return "UDMA0";
888c8039fc6SAlexander Motin case ATA_UDMA1: return "UDMA1";
889c8039fc6SAlexander Motin case ATA_UDMA2: return "UDMA2";
890c8039fc6SAlexander Motin case ATA_UDMA3: return "UDMA3";
891c8039fc6SAlexander Motin case ATA_UDMA4: return "UDMA4";
892c8039fc6SAlexander Motin case ATA_UDMA5: return "UDMA5";
893c8039fc6SAlexander Motin case ATA_UDMA6: return "UDMA6";
894c8039fc6SAlexander Motin default:
895c8039fc6SAlexander Motin if (mode & ATA_DMA_MASK)
896c8039fc6SAlexander Motin return "BIOSDMA";
897c8039fc6SAlexander Motin else
898c8039fc6SAlexander Motin return "BIOSPIO";
899c8039fc6SAlexander Motin }
900c8039fc6SAlexander Motin }
90152c9ce25SScott Long
902b447e682SAlexander Motin int
ata_string2mode(char * str)903b447e682SAlexander Motin ata_string2mode(char *str)
904b447e682SAlexander Motin {
905b447e682SAlexander Motin if (!strcasecmp(str, "PIO0")) return (ATA_PIO0);
906b447e682SAlexander Motin if (!strcasecmp(str, "PIO1")) return (ATA_PIO1);
907b447e682SAlexander Motin if (!strcasecmp(str, "PIO2")) return (ATA_PIO2);
908b447e682SAlexander Motin if (!strcasecmp(str, "PIO3")) return (ATA_PIO3);
909b447e682SAlexander Motin if (!strcasecmp(str, "PIO4")) return (ATA_PIO4);
910b447e682SAlexander Motin if (!strcasecmp(str, "WDMA0")) return (ATA_WDMA0);
911b447e682SAlexander Motin if (!strcasecmp(str, "WDMA1")) return (ATA_WDMA1);
912b447e682SAlexander Motin if (!strcasecmp(str, "WDMA2")) return (ATA_WDMA2);
913b447e682SAlexander Motin if (!strcasecmp(str, "UDMA0")) return (ATA_UDMA0);
914b447e682SAlexander Motin if (!strcasecmp(str, "UDMA16")) return (ATA_UDMA0);
915b447e682SAlexander Motin if (!strcasecmp(str, "UDMA1")) return (ATA_UDMA1);
916b447e682SAlexander Motin if (!strcasecmp(str, "UDMA25")) return (ATA_UDMA1);
917b447e682SAlexander Motin if (!strcasecmp(str, "UDMA2")) return (ATA_UDMA2);
918b447e682SAlexander Motin if (!strcasecmp(str, "UDMA33")) return (ATA_UDMA2);
919b447e682SAlexander Motin if (!strcasecmp(str, "UDMA3")) return (ATA_UDMA3);
920b447e682SAlexander Motin if (!strcasecmp(str, "UDMA44")) return (ATA_UDMA3);
921b447e682SAlexander Motin if (!strcasecmp(str, "UDMA4")) return (ATA_UDMA4);
922b447e682SAlexander Motin if (!strcasecmp(str, "UDMA66")) return (ATA_UDMA4);
923b447e682SAlexander Motin if (!strcasecmp(str, "UDMA5")) return (ATA_UDMA5);
924b447e682SAlexander Motin if (!strcasecmp(str, "UDMA100")) return (ATA_UDMA5);
925b447e682SAlexander Motin if (!strcasecmp(str, "UDMA6")) return (ATA_UDMA6);
926b447e682SAlexander Motin if (!strcasecmp(str, "UDMA133")) return (ATA_UDMA6);
927b447e682SAlexander Motin return (-1);
928b447e682SAlexander Motin }
929b447e682SAlexander Motin
930c8039fc6SAlexander Motin u_int
ata_mode2speed(int mode)931c8039fc6SAlexander Motin ata_mode2speed(int mode)
932c8039fc6SAlexander Motin {
933c8039fc6SAlexander Motin switch (mode) {
934c8039fc6SAlexander Motin case ATA_PIO0:
935c8039fc6SAlexander Motin default:
936c8039fc6SAlexander Motin return (3300);
937c8039fc6SAlexander Motin case ATA_PIO1:
938c8039fc6SAlexander Motin return (5200);
939c8039fc6SAlexander Motin case ATA_PIO2:
940c8039fc6SAlexander Motin return (8300);
941c8039fc6SAlexander Motin case ATA_PIO3:
942c8039fc6SAlexander Motin return (11100);
943c8039fc6SAlexander Motin case ATA_PIO4:
944c8039fc6SAlexander Motin return (16700);
945c8039fc6SAlexander Motin case ATA_WDMA0:
946c8039fc6SAlexander Motin return (4200);
947c8039fc6SAlexander Motin case ATA_WDMA1:
948c8039fc6SAlexander Motin return (13300);
949c8039fc6SAlexander Motin case ATA_WDMA2:
950c8039fc6SAlexander Motin return (16700);
951c8039fc6SAlexander Motin case ATA_UDMA0:
952c8039fc6SAlexander Motin return (16700);
953c8039fc6SAlexander Motin case ATA_UDMA1:
954c8039fc6SAlexander Motin return (25000);
955c8039fc6SAlexander Motin case ATA_UDMA2:
956c8039fc6SAlexander Motin return (33300);
957c8039fc6SAlexander Motin case ATA_UDMA3:
958c8039fc6SAlexander Motin return (44400);
959c8039fc6SAlexander Motin case ATA_UDMA4:
960c8039fc6SAlexander Motin return (66700);
961c8039fc6SAlexander Motin case ATA_UDMA5:
962c8039fc6SAlexander Motin return (100000);
963c8039fc6SAlexander Motin case ATA_UDMA6:
964c8039fc6SAlexander Motin return (133000);
965c8039fc6SAlexander Motin }
966c8039fc6SAlexander Motin }
96752c9ce25SScott Long
968c8039fc6SAlexander Motin u_int
ata_revision2speed(int revision)969c8039fc6SAlexander Motin ata_revision2speed(int revision)
970c8039fc6SAlexander Motin {
971c8039fc6SAlexander Motin switch (revision) {
972c8039fc6SAlexander Motin case 1:
973c8039fc6SAlexander Motin default:
974c8039fc6SAlexander Motin return (150000);
975c8039fc6SAlexander Motin case 2:
976c8039fc6SAlexander Motin return (300000);
977c8039fc6SAlexander Motin case 3:
978c8039fc6SAlexander Motin return (600000);
979c8039fc6SAlexander Motin }
980c8039fc6SAlexander Motin }
98152c9ce25SScott Long
982c8039fc6SAlexander Motin int
ata_speed2revision(u_int speed)983c8039fc6SAlexander Motin ata_speed2revision(u_int speed)
984c8039fc6SAlexander Motin {
985c8039fc6SAlexander Motin switch (speed) {
986b447e682SAlexander Motin case 0:
987b447e682SAlexander Motin return (0);
988c8039fc6SAlexander Motin case 150000:
989c8039fc6SAlexander Motin return (1);
990c8039fc6SAlexander Motin case 300000:
991c8039fc6SAlexander Motin return (2);
992c8039fc6SAlexander Motin case 600000:
993c8039fc6SAlexander Motin return (3);
994b447e682SAlexander Motin default:
995b447e682SAlexander Motin return (-1);
996c8039fc6SAlexander Motin }
99752c9ce25SScott Long }
99852c9ce25SScott Long
99930a4094fSAlexander Motin int
ata_identify_match(caddr_t identbuffer,caddr_t table_entry)100030a4094fSAlexander Motin ata_identify_match(caddr_t identbuffer, caddr_t table_entry)
100130a4094fSAlexander Motin {
100230a4094fSAlexander Motin struct scsi_inquiry_pattern *entry;
100330a4094fSAlexander Motin struct ata_params *ident;
100430a4094fSAlexander Motin
100530a4094fSAlexander Motin entry = (struct scsi_inquiry_pattern *)table_entry;
100630a4094fSAlexander Motin ident = (struct ata_params *)identbuffer;
100730a4094fSAlexander Motin
100830a4094fSAlexander Motin if ((cam_strmatch(ident->model, entry->product,
100930a4094fSAlexander Motin sizeof(ident->model)) == 0)
101030a4094fSAlexander Motin && (cam_strmatch(ident->revision, entry->revision,
101130a4094fSAlexander Motin sizeof(ident->revision)) == 0)) {
101230a4094fSAlexander Motin return (0);
101330a4094fSAlexander Motin }
101430a4094fSAlexander Motin return (-1);
101530a4094fSAlexander Motin }
101630a4094fSAlexander Motin
101730a4094fSAlexander Motin int
ata_static_identify_match(caddr_t identbuffer,caddr_t table_entry)101830a4094fSAlexander Motin ata_static_identify_match(caddr_t identbuffer, caddr_t table_entry)
101930a4094fSAlexander Motin {
102030a4094fSAlexander Motin struct scsi_static_inquiry_pattern *entry;
102130a4094fSAlexander Motin struct ata_params *ident;
102230a4094fSAlexander Motin
102330a4094fSAlexander Motin entry = (struct scsi_static_inquiry_pattern *)table_entry;
102430a4094fSAlexander Motin ident = (struct ata_params *)identbuffer;
102530a4094fSAlexander Motin
102630a4094fSAlexander Motin if ((cam_strmatch(ident->model, entry->product,
102730a4094fSAlexander Motin sizeof(ident->model)) == 0)
102830a4094fSAlexander Motin && (cam_strmatch(ident->revision, entry->revision,
102930a4094fSAlexander Motin sizeof(ident->revision)) == 0)) {
103030a4094fSAlexander Motin return (0);
103130a4094fSAlexander Motin }
103230a4094fSAlexander Motin return (-1);
103330a4094fSAlexander Motin }
10343089bb2eSAlexander Motin
10353089bb2eSAlexander Motin void
semb_receive_diagnostic_results(struct ccb_ataio * ataio,uint32_t retries,void (* cbfcnp)(struct cam_periph *,union ccb *),uint8_t tag_action,int pcv,uint8_t page_code,uint8_t * data_ptr,uint16_t length,uint32_t timeout)10363089bb2eSAlexander Motin semb_receive_diagnostic_results(struct ccb_ataio *ataio,
10379db2db6bSWarner Losh uint32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*),
10383089bb2eSAlexander Motin uint8_t tag_action, int pcv, uint8_t page_code,
10393089bb2eSAlexander Motin uint8_t *data_ptr, uint16_t length, uint32_t timeout)
10403089bb2eSAlexander Motin {
10413089bb2eSAlexander Motin
10423089bb2eSAlexander Motin length = min(length, 1020);
10433089bb2eSAlexander Motin length = (length + 3) & ~3;
10443089bb2eSAlexander Motin cam_fill_ataio(ataio,
10453089bb2eSAlexander Motin retries,
10463089bb2eSAlexander Motin cbfcnp,
10473089bb2eSAlexander Motin /*flags*/CAM_DIR_IN,
10483089bb2eSAlexander Motin tag_action,
10493089bb2eSAlexander Motin data_ptr,
10503089bb2eSAlexander Motin length,
10513089bb2eSAlexander Motin timeout);
10523089bb2eSAlexander Motin ata_28bit_cmd(ataio, ATA_SEP_ATTN,
10533089bb2eSAlexander Motin pcv ? page_code : 0, 0x02, length / 4);
10543089bb2eSAlexander Motin }
10553089bb2eSAlexander Motin
10563089bb2eSAlexander Motin void
semb_send_diagnostic(struct ccb_ataio * ataio,uint32_t retries,void (* cbfcnp)(struct cam_periph *,union ccb *),uint8_t tag_action,uint8_t * data_ptr,uint16_t length,uint32_t timeout)10573089bb2eSAlexander Motin semb_send_diagnostic(struct ccb_ataio *ataio,
10589db2db6bSWarner Losh uint32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *),
10593089bb2eSAlexander Motin uint8_t tag_action, uint8_t *data_ptr, uint16_t length, uint32_t timeout)
10603089bb2eSAlexander Motin {
10613089bb2eSAlexander Motin
10623089bb2eSAlexander Motin length = min(length, 1020);
10633089bb2eSAlexander Motin length = (length + 3) & ~3;
10643089bb2eSAlexander Motin cam_fill_ataio(ataio,
10653089bb2eSAlexander Motin retries,
10663089bb2eSAlexander Motin cbfcnp,
10673089bb2eSAlexander Motin /*flags*/length ? CAM_DIR_OUT : CAM_DIR_NONE,
10683089bb2eSAlexander Motin tag_action,
10693089bb2eSAlexander Motin data_ptr,
10703089bb2eSAlexander Motin length,
10713089bb2eSAlexander Motin timeout);
10723089bb2eSAlexander Motin ata_28bit_cmd(ataio, ATA_SEP_ATTN,
10733089bb2eSAlexander Motin length > 0 ? data_ptr[0] : 0, 0x82, length / 4);
10743089bb2eSAlexander Motin }
10753089bb2eSAlexander Motin
10763089bb2eSAlexander Motin void
semb_read_buffer(struct ccb_ataio * ataio,uint32_t retries,void (* cbfcnp)(struct cam_periph *,union ccb *),uint8_t tag_action,uint8_t page_code,uint8_t * data_ptr,uint16_t length,uint32_t timeout)10773089bb2eSAlexander Motin semb_read_buffer(struct ccb_ataio *ataio,
10789db2db6bSWarner Losh uint32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*),
10793089bb2eSAlexander Motin uint8_t tag_action, uint8_t page_code,
10803089bb2eSAlexander Motin uint8_t *data_ptr, uint16_t length, uint32_t timeout)
10813089bb2eSAlexander Motin {
10823089bb2eSAlexander Motin
10833089bb2eSAlexander Motin length = min(length, 1020);
10843089bb2eSAlexander Motin length = (length + 3) & ~3;
10853089bb2eSAlexander Motin cam_fill_ataio(ataio,
10863089bb2eSAlexander Motin retries,
10873089bb2eSAlexander Motin cbfcnp,
10883089bb2eSAlexander Motin /*flags*/CAM_DIR_IN,
10893089bb2eSAlexander Motin tag_action,
10903089bb2eSAlexander Motin data_ptr,
10913089bb2eSAlexander Motin length,
10923089bb2eSAlexander Motin timeout);
10933089bb2eSAlexander Motin ata_28bit_cmd(ataio, ATA_SEP_ATTN,
10943089bb2eSAlexander Motin page_code, 0x00, length / 4);
10953089bb2eSAlexander Motin }
10963089bb2eSAlexander Motin
10973089bb2eSAlexander Motin void
semb_write_buffer(struct ccb_ataio * ataio,uint32_t retries,void (* cbfcnp)(struct cam_periph *,union ccb *),uint8_t tag_action,uint8_t * data_ptr,uint16_t length,uint32_t timeout)10983089bb2eSAlexander Motin semb_write_buffer(struct ccb_ataio *ataio,
10999db2db6bSWarner Losh uint32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *),
11003089bb2eSAlexander Motin uint8_t tag_action, uint8_t *data_ptr, uint16_t length, uint32_t timeout)
11013089bb2eSAlexander Motin {
11023089bb2eSAlexander Motin
11033089bb2eSAlexander Motin length = min(length, 1020);
11043089bb2eSAlexander Motin length = (length + 3) & ~3;
11053089bb2eSAlexander Motin cam_fill_ataio(ataio,
11063089bb2eSAlexander Motin retries,
11073089bb2eSAlexander Motin cbfcnp,
11083089bb2eSAlexander Motin /*flags*/length ? CAM_DIR_OUT : CAM_DIR_NONE,
11093089bb2eSAlexander Motin tag_action,
11103089bb2eSAlexander Motin data_ptr,
11113089bb2eSAlexander Motin length,
11123089bb2eSAlexander Motin timeout);
11133089bb2eSAlexander Motin ata_28bit_cmd(ataio, ATA_SEP_ATTN,
11143089bb2eSAlexander Motin length > 0 ? data_ptr[0] : 0, 0x80, length / 4);
11153089bb2eSAlexander Motin }
11163089bb2eSAlexander Motin
11179a6844d5SKenneth D. Merry 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)11189a6844d5SKenneth D. Merry ata_zac_mgmt_out(struct ccb_ataio *ataio, uint32_t retries,
11199a6844d5SKenneth D. Merry void (*cbfcnp)(struct cam_periph *, union ccb *),
11209a6844d5SKenneth D. Merry int use_ncq, uint8_t zm_action, uint64_t zone_id,
11219a6844d5SKenneth D. Merry uint8_t zone_flags, uint16_t sector_count, uint8_t *data_ptr,
11229a6844d5SKenneth D. Merry uint32_t dxfer_len, uint32_t timeout)
11239a6844d5SKenneth D. Merry {
11249a6844d5SKenneth D. Merry uint8_t command_out, ata_flags;
11259a6844d5SKenneth D. Merry uint16_t features_out, sectors_out;
11269a6844d5SKenneth D. Merry uint32_t auxiliary;
11279a6844d5SKenneth D. Merry
11289a6844d5SKenneth D. Merry if (use_ncq == 0) {
11299a6844d5SKenneth D. Merry command_out = ATA_ZAC_MANAGEMENT_OUT;
11309a6844d5SKenneth D. Merry features_out = (zm_action & 0xf) | (zone_flags << 8);
11319a6844d5SKenneth D. Merry if (dxfer_len == 0) {
11329a6844d5SKenneth D. Merry ata_flags = 0;
11339a6844d5SKenneth D. Merry sectors_out = 0;
11349a6844d5SKenneth D. Merry } else {
11359a6844d5SKenneth D. Merry ata_flags = CAM_ATAIO_DMA;
11369a6844d5SKenneth D. Merry /* XXX KDM use sector count? */
11379a6844d5SKenneth D. Merry sectors_out = ((dxfer_len >> 9) & 0xffff);
11389a6844d5SKenneth D. Merry }
11399a6844d5SKenneth D. Merry auxiliary = 0;
11409a6844d5SKenneth D. Merry } else {
11419a6844d5SKenneth D. Merry if (dxfer_len == 0) {
11429a6844d5SKenneth D. Merry command_out = ATA_NCQ_NON_DATA;
11439a6844d5SKenneth D. Merry features_out = ATA_NCQ_ZAC_MGMT_OUT;
11449a6844d5SKenneth D. Merry sectors_out = 0;
11459a6844d5SKenneth D. Merry } else {
11469a6844d5SKenneth D. Merry command_out = ATA_SEND_FPDMA_QUEUED;
11479a6844d5SKenneth D. Merry
11489a6844d5SKenneth D. Merry /* Note that we're defaulting to normal priority */
11499a6844d5SKenneth D. Merry sectors_out = ATA_SFPDMA_ZAC_MGMT_OUT << 8;
11509a6844d5SKenneth D. Merry
11519a6844d5SKenneth D. Merry /*
11529a6844d5SKenneth D. Merry * For SEND FPDMA QUEUED, the transfer length is
11539a6844d5SKenneth D. Merry * encoded in the FEATURE register, and 0 means
11549a6844d5SKenneth D. Merry * that 65536 512 byte blocks are to be tranferred.
11559a6844d5SKenneth D. Merry * In practice, it seems unlikely that we'll see
11569a6844d5SKenneth D. Merry * a transfer that large.
11579a6844d5SKenneth D. Merry */
11589a6844d5SKenneth D. Merry if (dxfer_len == (65536 * 512)) {
11599a6844d5SKenneth D. Merry features_out = 0;
11609a6844d5SKenneth D. Merry } else {
11619a6844d5SKenneth D. Merry /*
11629a6844d5SKenneth D. Merry * Yes, the caller can theoretically send a
11639a6844d5SKenneth D. Merry * transfer larger than we can handle.
11649a6844d5SKenneth D. Merry * Anyone using this function needs enough
11659a6844d5SKenneth D. Merry * knowledge to avoid doing that.
11669a6844d5SKenneth D. Merry */
11679a6844d5SKenneth D. Merry features_out = ((dxfer_len >> 9) & 0xffff);
11689a6844d5SKenneth D. Merry }
11699a6844d5SKenneth D. Merry }
11709a6844d5SKenneth D. Merry auxiliary = (zm_action & 0xf) | (zone_flags << 8);
11719a6844d5SKenneth D. Merry
11729a6844d5SKenneth D. Merry ata_flags = CAM_ATAIO_FPDMA;
11739a6844d5SKenneth D. Merry }
11749a6844d5SKenneth D. Merry
11759a6844d5SKenneth D. Merry cam_fill_ataio(ataio,
11769a6844d5SKenneth D. Merry /*retries*/ retries,
11779a6844d5SKenneth D. Merry /*cbfcnp*/ cbfcnp,
11789a6844d5SKenneth D. Merry /*flags*/ (dxfer_len > 0) ? CAM_DIR_OUT : CAM_DIR_NONE,
11799a6844d5SKenneth D. Merry /*tag_action*/ 0,
11809a6844d5SKenneth D. Merry /*data_ptr*/ data_ptr,
11819a6844d5SKenneth D. Merry /*dxfer_len*/ dxfer_len,
11829a6844d5SKenneth D. Merry /*timeout*/ timeout);
11839a6844d5SKenneth D. Merry
11849a6844d5SKenneth D. Merry ata_48bit_cmd(ataio,
11859a6844d5SKenneth D. Merry /*cmd*/ command_out,
11869a6844d5SKenneth D. Merry /*features*/ features_out,
11879a6844d5SKenneth D. Merry /*lba*/ zone_id,
11889a6844d5SKenneth D. Merry /*sector_count*/ sectors_out);
11899a6844d5SKenneth D. Merry
11909a6844d5SKenneth D. Merry ataio->cmd.flags |= ata_flags;
11919a6844d5SKenneth D. Merry if (auxiliary != 0) {
11929a6844d5SKenneth D. Merry ataio->ata_flags |= ATA_FLAG_AUX;
11939a6844d5SKenneth D. Merry ataio->aux = auxiliary;
11949a6844d5SKenneth D. Merry }
11959a6844d5SKenneth D. Merry }
11969a6844d5SKenneth D. Merry
11979a6844d5SKenneth D. Merry 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)11989a6844d5SKenneth D. Merry ata_zac_mgmt_in(struct ccb_ataio *ataio, uint32_t retries,
11999a6844d5SKenneth D. Merry void (*cbfcnp)(struct cam_periph *, union ccb *),
12009a6844d5SKenneth D. Merry int use_ncq, uint8_t zm_action, uint64_t zone_id,
12019a6844d5SKenneth D. Merry uint8_t zone_flags, uint8_t *data_ptr, uint32_t dxfer_len,
12029a6844d5SKenneth D. Merry uint32_t timeout)
12039a6844d5SKenneth D. Merry {
12049a6844d5SKenneth D. Merry uint8_t command_out, ata_flags;
12059a6844d5SKenneth D. Merry uint16_t features_out, sectors_out;
12069a6844d5SKenneth D. Merry uint32_t auxiliary;
12079a6844d5SKenneth D. Merry
12089a6844d5SKenneth D. Merry if (use_ncq == 0) {
12099a6844d5SKenneth D. Merry command_out = ATA_ZAC_MANAGEMENT_IN;
12109a6844d5SKenneth D. Merry /* XXX KDM put a macro here */
12119a6844d5SKenneth D. Merry features_out = (zm_action & 0xf) | (zone_flags << 8);
12129a6844d5SKenneth D. Merry ata_flags = CAM_ATAIO_DMA;
12139a6844d5SKenneth D. Merry sectors_out = ((dxfer_len >> 9) & 0xffff);
12149a6844d5SKenneth D. Merry auxiliary = 0;
12159a6844d5SKenneth D. Merry } else {
12169a6844d5SKenneth D. Merry command_out = ATA_RECV_FPDMA_QUEUED;
12179a6844d5SKenneth D. Merry sectors_out = ATA_RFPDMA_ZAC_MGMT_IN << 8;
1218a061aa46SPedro F. Giffuni auxiliary = (zm_action & 0xf) | (zone_flags << 8);
12199a6844d5SKenneth D. Merry ata_flags = CAM_ATAIO_FPDMA;
12209a6844d5SKenneth D. Merry /*
12219a6844d5SKenneth D. Merry * For RECEIVE FPDMA QUEUED, the transfer length is
12229a6844d5SKenneth D. Merry * encoded in the FEATURE register, and 0 means
12239a6844d5SKenneth D. Merry * that 65536 512 byte blocks are to be tranferred.
12249a6844d5SKenneth D. Merry * In practice, it is unlikely we will see a transfer that
12259a6844d5SKenneth D. Merry * large.
12269a6844d5SKenneth D. Merry */
12279a6844d5SKenneth D. Merry if (dxfer_len == (65536 * 512)) {
12289a6844d5SKenneth D. Merry features_out = 0;
12299a6844d5SKenneth D. Merry } else {
12309a6844d5SKenneth D. Merry /*
12319a6844d5SKenneth D. Merry * Yes, the caller can theoretically request a
12329a6844d5SKenneth D. Merry * transfer larger than we can handle.
12339a6844d5SKenneth D. Merry * Anyone using this function needs enough
12349a6844d5SKenneth D. Merry * knowledge to avoid doing that.
12359a6844d5SKenneth D. Merry */
12369a6844d5SKenneth D. Merry features_out = ((dxfer_len >> 9) & 0xffff);
12379a6844d5SKenneth D. Merry }
12389a6844d5SKenneth D. Merry }
12399a6844d5SKenneth D. Merry
12409a6844d5SKenneth D. Merry cam_fill_ataio(ataio,
12419a6844d5SKenneth D. Merry /*retries*/ retries,
12429a6844d5SKenneth D. Merry /*cbfcnp*/ cbfcnp,
12439a6844d5SKenneth D. Merry /*flags*/ CAM_DIR_IN,
12449a6844d5SKenneth D. Merry /*tag_action*/ 0,
12459a6844d5SKenneth D. Merry /*data_ptr*/ data_ptr,
12469a6844d5SKenneth D. Merry /*dxfer_len*/ dxfer_len,
12479a6844d5SKenneth D. Merry /*timeout*/ timeout);
12489a6844d5SKenneth D. Merry
12499a6844d5SKenneth D. Merry ata_48bit_cmd(ataio,
12509a6844d5SKenneth D. Merry /*cmd*/ command_out,
12519a6844d5SKenneth D. Merry /*features*/ features_out,
12529a6844d5SKenneth D. Merry /*lba*/ zone_id,
12539a6844d5SKenneth D. Merry /*sector_count*/ sectors_out);
12549a6844d5SKenneth D. Merry
12559a6844d5SKenneth D. Merry ataio->cmd.flags |= ata_flags;
12569a6844d5SKenneth D. Merry if (auxiliary != 0) {
12579a6844d5SKenneth D. Merry ataio->ata_flags |= ATA_FLAG_AUX;
12589a6844d5SKenneth D. Merry ataio->aux = auxiliary;
12599a6844d5SKenneth D. Merry }
12609a6844d5SKenneth D. Merry }
1261296218d4SWarner Losh
1262296218d4SWarner Losh void
ata_param_fixup(struct ata_params * ident_buf)1263296218d4SWarner Losh ata_param_fixup(struct ata_params *ident_buf)
1264296218d4SWarner Losh {
1265296218d4SWarner Losh int16_t *ptr;
1266296218d4SWarner Losh
1267296218d4SWarner Losh for (ptr = (int16_t *)ident_buf;
1268296218d4SWarner Losh ptr < (int16_t *)ident_buf + sizeof(struct ata_params)/2; ptr++) {
1269296218d4SWarner Losh *ptr = le16toh(*ptr);
1270296218d4SWarner Losh }
1271296218d4SWarner Losh if (strncmp(ident_buf->model, "FX", 2) &&
1272296218d4SWarner Losh strncmp(ident_buf->model, "NEC", 3) &&
1273296218d4SWarner Losh strncmp(ident_buf->model, "Pioneer", 7) &&
1274296218d4SWarner Losh strncmp(ident_buf->model, "SHARP", 5)) {
1275296218d4SWarner Losh ata_bswap(ident_buf->model, sizeof(ident_buf->model));
1276296218d4SWarner Losh ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
1277296218d4SWarner Losh ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
1278296218d4SWarner Losh }
1279296218d4SWarner Losh ata_btrim(ident_buf->model, sizeof(ident_buf->model));
1280296218d4SWarner Losh ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
1281296218d4SWarner Losh ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
1282296218d4SWarner Losh ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
1283296218d4SWarner Losh ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
1284296218d4SWarner Losh ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
1285296218d4SWarner Losh }
1286