ata_all.c revision 257049
1195534Sscottl/*- 2195534Sscottl * Copyright (c) 2009 Alexander Motin <mav@FreeBSD.org> 3195534Sscottl * All rights reserved. 4195534Sscottl * 5195534Sscottl * Redistribution and use in source and binary forms, with or without 6195534Sscottl * modification, are permitted provided that the following conditions 7195534Sscottl * are met: 8195534Sscottl * 1. Redistributions of source code must retain the above copyright 9195534Sscottl * notice, this list of conditions and the following disclaimer, 10195534Sscottl * without modification, immediately at the beginning of the file. 11195534Sscottl * 2. Redistributions in binary form must reproduce the above copyright 12195534Sscottl * notice, this list of conditions and the following disclaimer in the 13195534Sscottl * documentation and/or other materials provided with the distribution. 14195534Sscottl * 15195534Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16195534Sscottl * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17195534Sscottl * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18195534Sscottl * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19195534Sscottl * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20195534Sscottl * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21195534Sscottl * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22195534Sscottl * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23195534Sscottl * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24195534Sscottl * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25195534Sscottl */ 26195534Sscottl 27195534Sscottl#include <sys/cdefs.h> 28195534Sscottl__FBSDID("$FreeBSD: stable/10/sys/cam/ata/ata_all.c 257049 2013-10-24 10:33:31Z mav $"); 29195534Sscottl 30195534Sscottl#include <sys/param.h> 31195534Sscottl 32195534Sscottl#ifdef _KERNEL 33195534Sscottl#include <opt_scsi.h> 34195534Sscottl 35195534Sscottl#include <sys/systm.h> 36195534Sscottl#include <sys/libkern.h> 37195534Sscottl#include <sys/kernel.h> 38195534Sscottl#include <sys/sysctl.h> 39195534Sscottl#else 40195534Sscottl#include <errno.h> 41195534Sscottl#include <stdio.h> 42195534Sscottl#include <stdlib.h> 43195534Sscottl#include <string.h> 44195534Sscottl#ifndef min 45195534Sscottl#define min(a,b) (((a)<(b))?(a):(b)) 46195534Sscottl#endif 47195534Sscottl#endif 48195534Sscottl 49195534Sscottl#include <cam/cam.h> 50195534Sscottl#include <cam/cam_ccb.h> 51195534Sscottl#include <cam/cam_queue.h> 52195534Sscottl#include <cam/cam_xpt.h> 53195534Sscottl#include <sys/ata.h> 54195534Sscottl#include <cam/ata/ata_all.h> 55195534Sscottl#include <sys/sbuf.h> 56195534Sscottl#include <sys/endian.h> 57195534Sscottl 58195534Sscottlint 59195534Sscottlata_version(int ver) 60195534Sscottl{ 61195534Sscottl int bit; 62195534Sscottl 63195534Sscottl if (ver == 0xffff) 64195534Sscottl return 0; 65195534Sscottl for (bit = 15; bit >= 0; bit--) 66195534Sscottl if (ver & (1<<bit)) 67195534Sscottl return bit; 68195534Sscottl return 0; 69195534Sscottl} 70195534Sscottl 71198849Smavchar * 72198849Smavata_op_string(struct ata_cmd *cmd) 73198849Smav{ 74198849Smav 75220616Smav if (cmd->control & 0x04) 76220616Smav return ("SOFT_RESET"); 77198849Smav switch (cmd->command) { 78198849Smav case 0x00: return ("NOP"); 79198849Smav case 0x03: return ("CFA_REQUEST_EXTENDED_ERROR"); 80201139Smav case 0x06: 81201139Smav switch (cmd->features) { 82201139Smav case 0x01: return ("DSM TRIM"); 83201139Smav } 84201139Smav return "DSM"; 85198849Smav case 0x08: return ("DEVICE_RESET"); 86198849Smav case 0x20: return ("READ"); 87198849Smav case 0x24: return ("READ48"); 88198849Smav case 0x25: return ("READ_DMA48"); 89198849Smav case 0x26: return ("READ_DMA_QUEUED48"); 90198849Smav case 0x27: return ("READ_NATIVE_MAX_ADDRESS48"); 91198849Smav case 0x29: return ("READ_MUL48"); 92198849Smav case 0x2a: return ("READ_STREAM_DMA48"); 93198849Smav case 0x2b: return ("READ_STREAM48"); 94198849Smav case 0x2f: return ("READ_LOG_EXT"); 95198849Smav case 0x30: return ("WRITE"); 96198849Smav case 0x34: return ("WRITE48"); 97198849Smav case 0x35: return ("WRITE_DMA48"); 98198849Smav case 0x36: return ("WRITE_DMA_QUEUED48"); 99198849Smav case 0x37: return ("SET_MAX_ADDRESS48"); 100198849Smav case 0x39: return ("WRITE_MUL48"); 101198849Smav case 0x3a: return ("WRITE_STREAM_DMA48"); 102198849Smav case 0x3b: return ("WRITE_STREAM48"); 103200008Smav case 0x3d: return ("WRITE_DMA_FUA48"); 104200008Smav case 0x3e: return ("WRITE_DMA_QUEUED_FUA48"); 105198849Smav case 0x3f: return ("WRITE_LOG_EXT"); 106198849Smav case 0x40: return ("READ_VERIFY"); 107198849Smav case 0x42: return ("READ_VERIFY48"); 108198849Smav case 0x51: return ("CONFIGURE_STREAM"); 109198849Smav case 0x60: return ("READ_FPDMA_QUEUED"); 110198849Smav case 0x61: return ("WRITE_FPDMA_QUEUED"); 111235897Smav case 0x67: 112235897Smav if (cmd->features == 0xec) 113235897Smav return ("SEP_ATTN IDENTIFY"); 114235897Smav switch (cmd->lba_low) { 115235897Smav case 0x00: return ("SEP_ATTN READ BUFFER"); 116235897Smav case 0x02: return ("SEP_ATTN RECEIVE DIAGNOSTIC RESULTS"); 117235897Smav case 0x80: return ("SEP_ATTN WRITE BUFFER"); 118235897Smav case 0x82: return ("SEP_ATTN SEND DIAGNOSTIC"); 119235897Smav } 120235897Smav return ("SEP_ATTN"); 121198849Smav case 0x70: return ("SEEK"); 122198849Smav case 0x87: return ("CFA_TRANSLATE_SECTOR"); 123198849Smav case 0x90: return ("EXECUTE_DEVICE_DIAGNOSTIC"); 124198849Smav case 0x92: return ("DOWNLOAD_MICROCODE"); 125198849Smav case 0xa0: return ("PACKET"); 126198849Smav case 0xa1: return ("ATAPI_IDENTIFY"); 127198849Smav case 0xa2: return ("SERVICE"); 128198849Smav case 0xb0: return ("SMART"); 129198849Smav case 0xb1: return ("DEVICE CONFIGURATION"); 130198849Smav case 0xc0: return ("CFA_ERASE"); 131198849Smav case 0xc4: return ("READ_MUL"); 132198849Smav case 0xc5: return ("WRITE_MUL"); 133198849Smav case 0xc6: return ("SET_MULTI"); 134198849Smav case 0xc7: return ("READ_DMA_QUEUED"); 135198849Smav case 0xc8: return ("READ_DMA"); 136198849Smav case 0xca: return ("WRITE_DMA"); 137198849Smav case 0xcc: return ("WRITE_DMA_QUEUED"); 138198849Smav case 0xcd: return ("CFA_WRITE_MULTIPLE_WITHOUT_ERASE"); 139200008Smav case 0xce: return ("WRITE_MUL_FUA48"); 140198849Smav case 0xd1: return ("CHECK_MEDIA_CARD_TYPE"); 141198849Smav case 0xda: return ("GET_MEDIA_STATUS"); 142198849Smav case 0xde: return ("MEDIA_LOCK"); 143198849Smav case 0xdf: return ("MEDIA_UNLOCK"); 144198849Smav case 0xe0: return ("STANDBY_IMMEDIATE"); 145198849Smav case 0xe1: return ("IDLE_IMMEDIATE"); 146198849Smav case 0xe2: return ("STANDBY"); 147198849Smav case 0xe3: return ("IDLE"); 148198849Smav case 0xe4: return ("READ_BUFFER/PM"); 149198849Smav case 0xe5: return ("CHECK_POWER_MODE"); 150198849Smav case 0xe6: return ("SLEEP"); 151198849Smav case 0xe7: return ("FLUSHCACHE"); 152198849Smav case 0xe8: return ("WRITE_PM"); 153198849Smav case 0xea: return ("FLUSHCACHE48"); 154198849Smav case 0xec: return ("ATA_IDENTIFY"); 155198849Smav case 0xed: return ("MEDIA_EJECT"); 156198849Smav case 0xef: 157198849Smav switch (cmd->features) { 158198849Smav case 0x03: return ("SETFEATURES SET TRANSFER MODE"); 159198849Smav case 0x02: return ("SETFEATURES ENABLE WCACHE"); 160198849Smav case 0x82: return ("SETFEATURES DISABLE WCACHE"); 161203421Smav case 0x06: return ("SETFEATURES ENABLE PUIS"); 162203421Smav case 0x86: return ("SETFEATURES DISABLE PUIS"); 163203421Smav case 0x07: return ("SETFEATURES SPIN-UP"); 164220616Smav case 0x10: return ("SETFEATURES ENABLE SATA FEATURE"); 165220616Smav case 0x90: return ("SETFEATURES DISABLE SATA FEATURE"); 166198849Smav case 0xaa: return ("SETFEATURES ENABLE RCACHE"); 167198849Smav case 0x55: return ("SETFEATURES DISABLE RCACHE"); 168198849Smav } 169198849Smav return "SETFEATURES"; 170198849Smav case 0xf1: return ("SECURITY_SET_PASSWORD"); 171198849Smav case 0xf2: return ("SECURITY_UNLOCK"); 172198849Smav case 0xf3: return ("SECURITY_ERASE_PREPARE"); 173198849Smav case 0xf4: return ("SECURITY_ERASE_UNIT"); 174238363Sbrueffer case 0xf5: return ("SECURITY_FREEZE_LOCK"); 175238363Sbrueffer case 0xf6: return ("SECURITY_DISABLE_PASSWORD"); 176198849Smav case 0xf8: return ("READ_NATIVE_MAX_ADDRESS"); 177198849Smav case 0xf9: return ("SET_MAX_ADDRESS"); 178198849Smav } 179198849Smav return "UNKNOWN"; 180198849Smav} 181198849Smav 182198849Smavchar * 183198849Smavata_cmd_string(struct ata_cmd *cmd, char *cmd_string, size_t len) 184198849Smav{ 185198849Smav 186198849Smav snprintf(cmd_string, len, "%02x %02x %02x %02x " 187198849Smav "%02x %02x %02x %02x %02x %02x %02x %02x", 188198849Smav cmd->command, cmd->features, 189198849Smav cmd->lba_low, cmd->lba_mid, cmd->lba_high, cmd->device, 190198849Smav cmd->lba_low_exp, cmd->lba_mid_exp, cmd->lba_high_exp, 191198849Smav cmd->features_exp, cmd->sector_count, cmd->sector_count_exp); 192198849Smav 193198849Smav return(cmd_string); 194198849Smav} 195198849Smav 196198849Smavchar * 197198849Smavata_res_string(struct ata_res *res, char *res_string, size_t len) 198198849Smav{ 199198849Smav 200198849Smav snprintf(res_string, len, "%02x %02x %02x %02x " 201198849Smav "%02x %02x %02x %02x %02x %02x %02x", 202198849Smav res->status, res->error, 203198849Smav res->lba_low, res->lba_mid, res->lba_high, res->device, 204198849Smav res->lba_low_exp, res->lba_mid_exp, res->lba_high_exp, 205198849Smav res->sector_count, res->sector_count_exp); 206198849Smav 207198849Smav return(res_string); 208198849Smav} 209198849Smav 210198849Smav/* 211198849Smav * ata_command_sbuf() returns 0 for success and -1 for failure. 212198849Smav */ 213198849Smavint 214198849Smavata_command_sbuf(struct ccb_ataio *ataio, struct sbuf *sb) 215198849Smav{ 216198849Smav char cmd_str[(12 * 3) + 1]; 217198849Smav 218203108Smav sbuf_printf(sb, "%s. ACB: %s", 219198849Smav ata_op_string(&ataio->cmd), 220198849Smav ata_cmd_string(&ataio->cmd, cmd_str, sizeof(cmd_str))); 221198849Smav 222198849Smav return(0); 223198849Smav} 224198849Smav 225198849Smav/* 226198849Smav * ata_status_abuf() returns 0 for success and -1 for failure. 227198849Smav */ 228198849Smavint 229198849Smavata_status_sbuf(struct ccb_ataio *ataio, struct sbuf *sb) 230198849Smav{ 231198849Smav 232203108Smav sbuf_printf(sb, "ATA status: %02x (%s%s%s%s%s%s%s%s)", 233198849Smav ataio->res.status, 234198849Smav (ataio->res.status & 0x80) ? "BSY " : "", 235198849Smav (ataio->res.status & 0x40) ? "DRDY " : "", 236198849Smav (ataio->res.status & 0x20) ? "DF " : "", 237198849Smav (ataio->res.status & 0x10) ? "SERV " : "", 238198849Smav (ataio->res.status & 0x08) ? "DRQ " : "", 239198849Smav (ataio->res.status & 0x04) ? "CORR " : "", 240198849Smav (ataio->res.status & 0x02) ? "IDX " : "", 241198849Smav (ataio->res.status & 0x01) ? "ERR" : ""); 242198849Smav if (ataio->res.status & 1) { 243203108Smav sbuf_printf(sb, ", error: %02x (%s%s%s%s%s%s%s%s)", 244198849Smav ataio->res.error, 245198849Smav (ataio->res.error & 0x80) ? "ICRC " : "", 246198849Smav (ataio->res.error & 0x40) ? "UNC " : "", 247198849Smav (ataio->res.error & 0x20) ? "MC " : "", 248198849Smav (ataio->res.error & 0x10) ? "IDNF " : "", 249198849Smav (ataio->res.error & 0x08) ? "MCR " : "", 250198849Smav (ataio->res.error & 0x04) ? "ABRT " : "", 251198849Smav (ataio->res.error & 0x02) ? "NM " : "", 252198849Smav (ataio->res.error & 0x01) ? "ILI" : ""); 253198849Smav } 254198849Smav 255198849Smav return(0); 256198849Smav} 257198849Smav 258198849Smav/* 259198849Smav * ata_res_sbuf() returns 0 for success and -1 for failure. 260198849Smav */ 261198849Smavint 262198849Smavata_res_sbuf(struct ccb_ataio *ataio, struct sbuf *sb) 263198849Smav{ 264198849Smav char res_str[(11 * 3) + 1]; 265198849Smav 266198849Smav sbuf_printf(sb, "RES: %s", 267198849Smav ata_res_string(&ataio->res, res_str, sizeof(res_str))); 268198849Smav 269198849Smav return(0); 270198849Smav} 271198849Smav 272195534Sscottlvoid 273195534Sscottlata_print_ident(struct ata_params *ident_data) 274195534Sscottl{ 275195534Sscottl char product[48], revision[16]; 276195534Sscottl 277195534Sscottl cam_strvis(product, ident_data->model, sizeof(ident_data->model), 278195534Sscottl sizeof(product)); 279195534Sscottl cam_strvis(revision, ident_data->revision, sizeof(ident_data->revision), 280195534Sscottl sizeof(revision)); 281200218Smav printf("<%s %s> %s-%d", 282200218Smav product, revision, 283223019Smav (ident_data->config == ATA_PROTO_CFA) ? "CFA" : 284200218Smav (ident_data->config & ATA_PROTO_ATAPI) ? "ATAPI" : "ATA", 285200218Smav ata_version(ident_data->version_major)); 286195534Sscottl if (ident_data->satacapabilities && ident_data->satacapabilities != 0xffff) { 287197541Smav if (ident_data->satacapabilities & ATA_SATA_GEN3) 288197541Smav printf(" SATA 3.x"); 289197541Smav else if (ident_data->satacapabilities & ATA_SATA_GEN2) 290195534Sscottl printf(" SATA 2.x"); 291195534Sscottl else if (ident_data->satacapabilities & ATA_SATA_GEN1) 292195534Sscottl printf(" SATA 1.x"); 293195534Sscottl else 294195534Sscottl printf(" SATA"); 295195534Sscottl } 296195534Sscottl printf(" device\n"); 297195534Sscottl} 298195534Sscottl 299235897Smavvoid 300257049Smavata_print_ident_short(struct ata_params *ident_data) 301257049Smav{ 302257049Smav char product[48], revision[16]; 303257049Smav 304257049Smav cam_strvis(product, ident_data->model, sizeof(ident_data->model), 305257049Smav sizeof(product)); 306257049Smav cam_strvis(revision, ident_data->revision, sizeof(ident_data->revision), 307257049Smav sizeof(revision)); 308257049Smav printf("<%s %s>", product, revision); 309257049Smav} 310257049Smav 311257049Smavvoid 312235897Smavsemb_print_ident(struct sep_identify_data *ident_data) 313235897Smav{ 314235897Smav char vendor[9], product[17], revision[5], fw[5], in[7], ins[5]; 315235897Smav 316235897Smav cam_strvis(vendor, ident_data->vendor_id, 8, sizeof(vendor)); 317235897Smav cam_strvis(product, ident_data->product_id, 16, sizeof(product)); 318235897Smav cam_strvis(revision, ident_data->product_rev, 4, sizeof(revision)); 319235897Smav cam_strvis(fw, ident_data->firmware_rev, 4, sizeof(fw)); 320235897Smav cam_strvis(in, ident_data->interface_id, 6, sizeof(in)); 321235897Smav cam_strvis(ins, ident_data->interface_rev, 4, sizeof(ins)); 322235897Smav printf("<%s %s %s %s> SEMB %s %s device\n", 323235897Smav vendor, product, revision, fw, in, ins); 324235897Smav} 325235897Smav 326257049Smavvoid 327257049Smavsemb_print_ident_short(struct sep_identify_data *ident_data) 328257049Smav{ 329257049Smav char vendor[9], product[17], revision[5], fw[5]; 330257049Smav 331257049Smav cam_strvis(vendor, ident_data->vendor_id, 8, sizeof(vendor)); 332257049Smav cam_strvis(product, ident_data->product_id, 16, sizeof(product)); 333257049Smav cam_strvis(revision, ident_data->product_rev, 4, sizeof(revision)); 334257049Smav cam_strvis(fw, ident_data->firmware_rev, 4, sizeof(fw)); 335257049Smav printf("<%s %s %s %s>", vendor, product, revision, fw); 336257049Smav} 337257049Smav 338198897Smavuint32_t 339198897Smavata_logical_sector_size(struct ata_params *ident_data) 340198897Smav{ 341198897Smav if ((ident_data->pss & 0xc000) == 0x4000 && 342198897Smav (ident_data->pss & ATA_PSS_LSSABOVE512)) { 343198897Smav return ((u_int32_t)ident_data->lss_1 | 344198897Smav ((u_int32_t)ident_data->lss_2 << 16)); 345198897Smav } 346198897Smav return (512); 347198897Smav} 348198897Smav 349198897Smavuint64_t 350198897Smavata_physical_sector_size(struct ata_params *ident_data) 351198897Smav{ 352198897Smav if ((ident_data->pss & 0xc000) == 0x4000 && 353198897Smav (ident_data->pss & ATA_PSS_MULTLS)) { 354198897Smav return ((uint64_t)ata_logical_sector_size(ident_data) * 355198897Smav (1 << (ident_data->pss & ATA_PSS_LSPPS))); 356198897Smav } 357198897Smav return (512); 358198897Smav} 359198897Smav 360198897Smavuint64_t 361198897Smavata_logical_sector_offset(struct ata_params *ident_data) 362198897Smav{ 363198897Smav if ((ident_data->lsalign & 0xc000) == 0x4000) { 364198897Smav return ((uint64_t)ata_logical_sector_size(ident_data) * 365198897Smav (ident_data->lsalign & 0x3fff)); 366198897Smav } 367198897Smav return (0); 368198897Smav} 369198897Smav 370195534Sscottlvoid 371196659Smavata_28bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint8_t features, 372195534Sscottl uint32_t lba, uint8_t sector_count) 373195534Sscottl{ 374195534Sscottl bzero(&ataio->cmd, sizeof(ataio->cmd)); 375195534Sscottl ataio->cmd.flags = 0; 376200008Smav if (cmd == ATA_READ_DMA || 377200008Smav cmd == ATA_READ_DMA_QUEUED || 378200008Smav cmd == ATA_WRITE_DMA || 379200008Smav cmd == ATA_WRITE_DMA_QUEUED) 380200008Smav ataio->cmd.flags |= CAM_ATAIO_DMA; 381195534Sscottl ataio->cmd.command = cmd; 382195534Sscottl ataio->cmd.features = features; 383195534Sscottl ataio->cmd.lba_low = lba; 384195534Sscottl ataio->cmd.lba_mid = lba >> 8; 385195534Sscottl ataio->cmd.lba_high = lba >> 16; 386238393Sbrueffer ataio->cmd.device = ATA_DEV_LBA | ((lba >> 24) & 0x0f); 387195534Sscottl ataio->cmd.sector_count = sector_count; 388195534Sscottl} 389195534Sscottl 390195534Sscottlvoid 391195534Sscottlata_48bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint16_t features, 392195534Sscottl uint64_t lba, uint16_t sector_count) 393195534Sscottl{ 394248695Smav 395195534Sscottl ataio->cmd.flags = CAM_ATAIO_48BIT; 396200008Smav if (cmd == ATA_READ_DMA48 || 397200008Smav cmd == ATA_READ_DMA_QUEUED48 || 398200008Smav cmd == ATA_READ_STREAM_DMA48 || 399200008Smav cmd == ATA_WRITE_DMA48 || 400200008Smav cmd == ATA_WRITE_DMA_FUA48 || 401200008Smav cmd == ATA_WRITE_DMA_QUEUED48 || 402200008Smav cmd == ATA_WRITE_DMA_QUEUED_FUA48 || 403201139Smav cmd == ATA_WRITE_STREAM_DMA48 || 404201139Smav cmd == ATA_DATA_SET_MANAGEMENT) 405200008Smav ataio->cmd.flags |= CAM_ATAIO_DMA; 406195534Sscottl ataio->cmd.command = cmd; 407195534Sscottl ataio->cmd.features = features; 408195534Sscottl ataio->cmd.lba_low = lba; 409195534Sscottl ataio->cmd.lba_mid = lba >> 8; 410195534Sscottl ataio->cmd.lba_high = lba >> 16; 411238393Sbrueffer ataio->cmd.device = ATA_DEV_LBA; 412195534Sscottl ataio->cmd.lba_low_exp = lba >> 24; 413195534Sscottl ataio->cmd.lba_mid_exp = lba >> 32; 414195534Sscottl ataio->cmd.lba_high_exp = lba >> 40; 415195534Sscottl ataio->cmd.features_exp = features >> 8; 416195534Sscottl ataio->cmd.sector_count = sector_count; 417195534Sscottl ataio->cmd.sector_count_exp = sector_count >> 8; 418248695Smav ataio->cmd.control = 0; 419195534Sscottl} 420195534Sscottl 421195534Sscottlvoid 422195534Sscottlata_ncq_cmd(struct ccb_ataio *ataio, uint8_t cmd, 423195534Sscottl uint64_t lba, uint16_t sector_count) 424195534Sscottl{ 425248695Smav 426195534Sscottl ataio->cmd.flags = CAM_ATAIO_48BIT | CAM_ATAIO_FPDMA; 427195534Sscottl ataio->cmd.command = cmd; 428195534Sscottl ataio->cmd.features = sector_count; 429195534Sscottl ataio->cmd.lba_low = lba; 430195534Sscottl ataio->cmd.lba_mid = lba >> 8; 431195534Sscottl ataio->cmd.lba_high = lba >> 16; 432238393Sbrueffer ataio->cmd.device = ATA_DEV_LBA; 433195534Sscottl ataio->cmd.lba_low_exp = lba >> 24; 434195534Sscottl ataio->cmd.lba_mid_exp = lba >> 32; 435195534Sscottl ataio->cmd.lba_high_exp = lba >> 40; 436195534Sscottl ataio->cmd.features_exp = sector_count >> 8; 437248695Smav ataio->cmd.sector_count = 0; 438248695Smav ataio->cmd.sector_count_exp = 0; 439248695Smav ataio->cmd.control = 0; 440195534Sscottl} 441195534Sscottl 442195534Sscottlvoid 443195534Sscottlata_reset_cmd(struct ccb_ataio *ataio) 444195534Sscottl{ 445195534Sscottl bzero(&ataio->cmd, sizeof(ataio->cmd)); 446195534Sscottl ataio->cmd.flags = CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT; 447195534Sscottl ataio->cmd.control = 0x04; 448195534Sscottl} 449195534Sscottl 450195534Sscottlvoid 451195534Sscottlata_pm_read_cmd(struct ccb_ataio *ataio, int reg, int port) 452195534Sscottl{ 453195534Sscottl bzero(&ataio->cmd, sizeof(ataio->cmd)); 454198904Smav ataio->cmd.flags = CAM_ATAIO_NEEDRESULT; 455195534Sscottl ataio->cmd.command = ATA_READ_PM; 456195534Sscottl ataio->cmd.features = reg; 457195534Sscottl ataio->cmd.device = port & 0x0f; 458195534Sscottl} 459195534Sscottl 460195534Sscottlvoid 461198904Smavata_pm_write_cmd(struct ccb_ataio *ataio, int reg, int port, uint32_t val) 462195534Sscottl{ 463195534Sscottl bzero(&ataio->cmd, sizeof(ataio->cmd)); 464198904Smav ataio->cmd.flags = 0; 465195534Sscottl ataio->cmd.command = ATA_WRITE_PM; 466195534Sscottl ataio->cmd.features = reg; 467198904Smav ataio->cmd.sector_count = val; 468195534Sscottl ataio->cmd.lba_low = val >> 8; 469195534Sscottl ataio->cmd.lba_mid = val >> 16; 470195534Sscottl ataio->cmd.lba_high = val >> 24; 471195534Sscottl ataio->cmd.device = port & 0x0f; 472195534Sscottl} 473195534Sscottl 474195534Sscottlvoid 475195534Sscottlata_bswap(int8_t *buf, int len) 476195534Sscottl{ 477195534Sscottl u_int16_t *ptr = (u_int16_t*)(buf + len); 478195534Sscottl 479195534Sscottl while (--ptr >= (u_int16_t*)buf) 480195534Sscottl *ptr = be16toh(*ptr); 481195534Sscottl} 482195534Sscottl 483195534Sscottlvoid 484195534Sscottlata_btrim(int8_t *buf, int len) 485195534Sscottl{ 486195534Sscottl int8_t *ptr; 487195534Sscottl 488195534Sscottl for (ptr = buf; ptr < buf+len; ++ptr) 489195534Sscottl if (!*ptr || *ptr == '_') 490195534Sscottl *ptr = ' '; 491195534Sscottl for (ptr = buf + len - 1; ptr >= buf && *ptr == ' '; --ptr) 492195534Sscottl *ptr = 0; 493195534Sscottl} 494195534Sscottl 495195534Sscottlvoid 496195534Sscottlata_bpack(int8_t *src, int8_t *dst, int len) 497195534Sscottl{ 498195534Sscottl int i, j, blank; 499195534Sscottl 500195534Sscottl for (i = j = blank = 0 ; i < len; i++) { 501195534Sscottl if (blank && src[i] == ' ') continue; 502195534Sscottl if (blank && src[i] != ' ') { 503195534Sscottl dst[j++] = src[i]; 504195534Sscottl blank = 0; 505195534Sscottl continue; 506195534Sscottl } 507195534Sscottl if (src[i] == ' ') { 508195534Sscottl blank = 1; 509195534Sscottl if (i == 0) 510195534Sscottl continue; 511195534Sscottl } 512195534Sscottl dst[j++] = src[i]; 513195534Sscottl } 514195534Sscottl while (j < len) 515195534Sscottl dst[j++] = 0x00; 516195534Sscottl} 517195534Sscottl 518195534Sscottlint 519195534Sscottlata_max_pmode(struct ata_params *ap) 520195534Sscottl{ 521195534Sscottl if (ap->atavalid & ATA_FLAG_64_70) { 522195534Sscottl if (ap->apiomodes & 0x02) 523195534Sscottl return ATA_PIO4; 524195534Sscottl if (ap->apiomodes & 0x01) 525195534Sscottl return ATA_PIO3; 526195534Sscottl } 527195534Sscottl if (ap->mwdmamodes & 0x04) 528195534Sscottl return ATA_PIO4; 529195534Sscottl if (ap->mwdmamodes & 0x02) 530195534Sscottl return ATA_PIO3; 531195534Sscottl if (ap->mwdmamodes & 0x01) 532195534Sscottl return ATA_PIO2; 533195534Sscottl if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x200) 534195534Sscottl return ATA_PIO2; 535195534Sscottl if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x100) 536195534Sscottl return ATA_PIO1; 537195534Sscottl if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x000) 538195534Sscottl return ATA_PIO0; 539195534Sscottl return ATA_PIO0; 540195534Sscottl} 541195534Sscottl 542195534Sscottlint 543195534Sscottlata_max_wmode(struct ata_params *ap) 544195534Sscottl{ 545195534Sscottl if (ap->mwdmamodes & 0x04) 546195534Sscottl return ATA_WDMA2; 547195534Sscottl if (ap->mwdmamodes & 0x02) 548195534Sscottl return ATA_WDMA1; 549195534Sscottl if (ap->mwdmamodes & 0x01) 550195534Sscottl return ATA_WDMA0; 551195534Sscottl return -1; 552195534Sscottl} 553195534Sscottl 554195534Sscottlint 555195534Sscottlata_max_umode(struct ata_params *ap) 556195534Sscottl{ 557195534Sscottl if (ap->atavalid & ATA_FLAG_88) { 558195534Sscottl if (ap->udmamodes & 0x40) 559195534Sscottl return ATA_UDMA6; 560195534Sscottl if (ap->udmamodes & 0x20) 561195534Sscottl return ATA_UDMA5; 562195534Sscottl if (ap->udmamodes & 0x10) 563195534Sscottl return ATA_UDMA4; 564195534Sscottl if (ap->udmamodes & 0x08) 565195534Sscottl return ATA_UDMA3; 566195534Sscottl if (ap->udmamodes & 0x04) 567195534Sscottl return ATA_UDMA2; 568195534Sscottl if (ap->udmamodes & 0x02) 569195534Sscottl return ATA_UDMA1; 570195534Sscottl if (ap->udmamodes & 0x01) 571195534Sscottl return ATA_UDMA0; 572195534Sscottl } 573195534Sscottl return -1; 574195534Sscottl} 575195534Sscottl 576195534Sscottlint 577199747Smavata_max_mode(struct ata_params *ap, int maxmode) 578195534Sscottl{ 579195534Sscottl 580199747Smav if (maxmode == 0) 581199747Smav maxmode = ATA_DMA_MAX; 582199747Smav if (maxmode >= ATA_UDMA0 && ata_max_umode(ap) > 0) 583199747Smav return (min(maxmode, ata_max_umode(ap))); 584199747Smav if (maxmode >= ATA_WDMA0 && ata_max_wmode(ap) > 0) 585199747Smav return (min(maxmode, ata_max_wmode(ap))); 586199747Smav return (min(maxmode, ata_max_pmode(ap))); 587199747Smav} 588195534Sscottl 589199747Smavchar * 590199747Smavata_mode2string(int mode) 591199747Smav{ 592199747Smav switch (mode) { 593199747Smav case -1: return "UNSUPPORTED"; 594199747Smav case 0: return "NONE"; 595199747Smav case ATA_PIO0: return "PIO0"; 596199747Smav case ATA_PIO1: return "PIO1"; 597199747Smav case ATA_PIO2: return "PIO2"; 598199747Smav case ATA_PIO3: return "PIO3"; 599199747Smav case ATA_PIO4: return "PIO4"; 600199747Smav case ATA_WDMA0: return "WDMA0"; 601199747Smav case ATA_WDMA1: return "WDMA1"; 602199747Smav case ATA_WDMA2: return "WDMA2"; 603199747Smav case ATA_UDMA0: return "UDMA0"; 604199747Smav case ATA_UDMA1: return "UDMA1"; 605199747Smav case ATA_UDMA2: return "UDMA2"; 606199747Smav case ATA_UDMA3: return "UDMA3"; 607199747Smav case ATA_UDMA4: return "UDMA4"; 608199747Smav case ATA_UDMA5: return "UDMA5"; 609199747Smav case ATA_UDMA6: return "UDMA6"; 610199747Smav default: 611199747Smav if (mode & ATA_DMA_MASK) 612199747Smav return "BIOSDMA"; 613199747Smav else 614199747Smav return "BIOSPIO"; 615199747Smav } 616199747Smav} 617195534Sscottl 618199821Smavint 619199821Smavata_string2mode(char *str) 620199821Smav{ 621199821Smav if (!strcasecmp(str, "PIO0")) return (ATA_PIO0); 622199821Smav if (!strcasecmp(str, "PIO1")) return (ATA_PIO1); 623199821Smav if (!strcasecmp(str, "PIO2")) return (ATA_PIO2); 624199821Smav if (!strcasecmp(str, "PIO3")) return (ATA_PIO3); 625199821Smav if (!strcasecmp(str, "PIO4")) return (ATA_PIO4); 626199821Smav if (!strcasecmp(str, "WDMA0")) return (ATA_WDMA0); 627199821Smav if (!strcasecmp(str, "WDMA1")) return (ATA_WDMA1); 628199821Smav if (!strcasecmp(str, "WDMA2")) return (ATA_WDMA2); 629199821Smav if (!strcasecmp(str, "UDMA0")) return (ATA_UDMA0); 630199821Smav if (!strcasecmp(str, "UDMA16")) return (ATA_UDMA0); 631199821Smav if (!strcasecmp(str, "UDMA1")) return (ATA_UDMA1); 632199821Smav if (!strcasecmp(str, "UDMA25")) return (ATA_UDMA1); 633199821Smav if (!strcasecmp(str, "UDMA2")) return (ATA_UDMA2); 634199821Smav if (!strcasecmp(str, "UDMA33")) return (ATA_UDMA2); 635199821Smav if (!strcasecmp(str, "UDMA3")) return (ATA_UDMA3); 636199821Smav if (!strcasecmp(str, "UDMA44")) return (ATA_UDMA3); 637199821Smav if (!strcasecmp(str, "UDMA4")) return (ATA_UDMA4); 638199821Smav if (!strcasecmp(str, "UDMA66")) return (ATA_UDMA4); 639199821Smav if (!strcasecmp(str, "UDMA5")) return (ATA_UDMA5); 640199821Smav if (!strcasecmp(str, "UDMA100")) return (ATA_UDMA5); 641199821Smav if (!strcasecmp(str, "UDMA6")) return (ATA_UDMA6); 642199821Smav if (!strcasecmp(str, "UDMA133")) return (ATA_UDMA6); 643199821Smav return (-1); 644199821Smav} 645199821Smav 646199821Smav 647199747Smavu_int 648199747Smavata_mode2speed(int mode) 649199747Smav{ 650199747Smav switch (mode) { 651199747Smav case ATA_PIO0: 652199747Smav default: 653199747Smav return (3300); 654199747Smav case ATA_PIO1: 655199747Smav return (5200); 656199747Smav case ATA_PIO2: 657199747Smav return (8300); 658199747Smav case ATA_PIO3: 659199747Smav return (11100); 660199747Smav case ATA_PIO4: 661199747Smav return (16700); 662199747Smav case ATA_WDMA0: 663199747Smav return (4200); 664199747Smav case ATA_WDMA1: 665199747Smav return (13300); 666199747Smav case ATA_WDMA2: 667199747Smav return (16700); 668199747Smav case ATA_UDMA0: 669199747Smav return (16700); 670199747Smav case ATA_UDMA1: 671199747Smav return (25000); 672199747Smav case ATA_UDMA2: 673199747Smav return (33300); 674199747Smav case ATA_UDMA3: 675199747Smav return (44400); 676199747Smav case ATA_UDMA4: 677199747Smav return (66700); 678199747Smav case ATA_UDMA5: 679199747Smav return (100000); 680199747Smav case ATA_UDMA6: 681199747Smav return (133000); 682199747Smav } 683199747Smav} 684195534Sscottl 685199747Smavu_int 686199747Smavata_revision2speed(int revision) 687199747Smav{ 688199747Smav switch (revision) { 689199747Smav case 1: 690199747Smav default: 691199747Smav return (150000); 692199747Smav case 2: 693199747Smav return (300000); 694199747Smav case 3: 695199747Smav return (600000); 696199747Smav } 697199747Smav} 698195534Sscottl 699199747Smavint 700199747Smavata_speed2revision(u_int speed) 701199747Smav{ 702199747Smav switch (speed) { 703199821Smav case 0: 704199821Smav return (0); 705199747Smav case 150000: 706199747Smav return (1); 707199747Smav case 300000: 708199747Smav return (2); 709199747Smav case 600000: 710199747Smav return (3); 711199821Smav default: 712199821Smav return (-1); 713199747Smav } 714195534Sscottl} 715195534Sscottl 716199178Smavint 717199178Smavata_identify_match(caddr_t identbuffer, caddr_t table_entry) 718199178Smav{ 719199178Smav struct scsi_inquiry_pattern *entry; 720199178Smav struct ata_params *ident; 721199178Smav 722199178Smav entry = (struct scsi_inquiry_pattern *)table_entry; 723199178Smav ident = (struct ata_params *)identbuffer; 724199178Smav 725199178Smav if ((cam_strmatch(ident->model, entry->product, 726199178Smav sizeof(ident->model)) == 0) 727199178Smav && (cam_strmatch(ident->revision, entry->revision, 728199178Smav sizeof(ident->revision)) == 0)) { 729199178Smav return (0); 730199178Smav } 731199178Smav return (-1); 732199178Smav} 733199178Smav 734199178Smavint 735199178Smavata_static_identify_match(caddr_t identbuffer, caddr_t table_entry) 736199178Smav{ 737199178Smav struct scsi_static_inquiry_pattern *entry; 738199178Smav struct ata_params *ident; 739199178Smav 740199178Smav entry = (struct scsi_static_inquiry_pattern *)table_entry; 741199178Smav ident = (struct ata_params *)identbuffer; 742199178Smav 743199178Smav if ((cam_strmatch(ident->model, entry->product, 744199178Smav sizeof(ident->model)) == 0) 745199178Smav && (cam_strmatch(ident->revision, entry->revision, 746199178Smav sizeof(ident->revision)) == 0)) { 747199178Smav return (0); 748199178Smav } 749199178Smav return (-1); 750199178Smav} 751235897Smav 752235897Smavvoid 753235897Smavsemb_receive_diagnostic_results(struct ccb_ataio *ataio, 754235897Smav u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*), 755235897Smav uint8_t tag_action, int pcv, uint8_t page_code, 756235897Smav uint8_t *data_ptr, uint16_t length, uint32_t timeout) 757235897Smav{ 758235897Smav 759235897Smav length = min(length, 1020); 760235897Smav length = (length + 3) & ~3; 761235897Smav cam_fill_ataio(ataio, 762235897Smav retries, 763235897Smav cbfcnp, 764235897Smav /*flags*/CAM_DIR_IN, 765235897Smav tag_action, 766235897Smav data_ptr, 767235897Smav length, 768235897Smav timeout); 769235897Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 770235897Smav pcv ? page_code : 0, 0x02, length / 4); 771235897Smav} 772235897Smav 773235897Smavvoid 774235897Smavsemb_send_diagnostic(struct ccb_ataio *ataio, 775235897Smav u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), 776235897Smav uint8_t tag_action, uint8_t *data_ptr, uint16_t length, uint32_t timeout) 777235897Smav{ 778235897Smav 779235897Smav length = min(length, 1020); 780235897Smav length = (length + 3) & ~3; 781235897Smav cam_fill_ataio(ataio, 782235897Smav retries, 783235897Smav cbfcnp, 784235897Smav /*flags*/length ? CAM_DIR_OUT : CAM_DIR_NONE, 785235897Smav tag_action, 786235897Smav data_ptr, 787235897Smav length, 788235897Smav timeout); 789235897Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 790235897Smav length > 0 ? data_ptr[0] : 0, 0x82, length / 4); 791235897Smav} 792235897Smav 793235897Smavvoid 794235897Smavsemb_read_buffer(struct ccb_ataio *ataio, 795235897Smav u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*), 796235897Smav uint8_t tag_action, uint8_t page_code, 797235897Smav uint8_t *data_ptr, uint16_t length, uint32_t timeout) 798235897Smav{ 799235897Smav 800235897Smav length = min(length, 1020); 801235897Smav length = (length + 3) & ~3; 802235897Smav cam_fill_ataio(ataio, 803235897Smav retries, 804235897Smav cbfcnp, 805235897Smav /*flags*/CAM_DIR_IN, 806235897Smav tag_action, 807235897Smav data_ptr, 808235897Smav length, 809235897Smav timeout); 810235897Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 811235897Smav page_code, 0x00, length / 4); 812235897Smav} 813235897Smav 814235897Smavvoid 815235897Smavsemb_write_buffer(struct ccb_ataio *ataio, 816235897Smav u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), 817235897Smav uint8_t tag_action, uint8_t *data_ptr, uint16_t length, uint32_t timeout) 818235897Smav{ 819235897Smav 820235897Smav length = min(length, 1020); 821235897Smav length = (length + 3) & ~3; 822235897Smav cam_fill_ataio(ataio, 823235897Smav retries, 824235897Smav cbfcnp, 825235897Smav /*flags*/length ? CAM_DIR_OUT : CAM_DIR_NONE, 826235897Smav tag_action, 827235897Smav data_ptr, 828235897Smav length, 829235897Smav timeout); 830235897Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 831235897Smav length > 0 ? data_ptr[0] : 0, 0x80, length / 4); 832235897Smav} 833235897Smav 834