ata_all.c revision 248695
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: head/sys/cam/ata/ata_all.c 248695 2013-03-25 06:31:17Z 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 300235897Smavsemb_print_ident(struct sep_identify_data *ident_data) 301235897Smav{ 302235897Smav char vendor[9], product[17], revision[5], fw[5], in[7], ins[5]; 303235897Smav 304235897Smav cam_strvis(vendor, ident_data->vendor_id, 8, sizeof(vendor)); 305235897Smav cam_strvis(product, ident_data->product_id, 16, sizeof(product)); 306235897Smav cam_strvis(revision, ident_data->product_rev, 4, sizeof(revision)); 307235897Smav cam_strvis(fw, ident_data->firmware_rev, 4, sizeof(fw)); 308235897Smav cam_strvis(in, ident_data->interface_id, 6, sizeof(in)); 309235897Smav cam_strvis(ins, ident_data->interface_rev, 4, sizeof(ins)); 310235897Smav printf("<%s %s %s %s> SEMB %s %s device\n", 311235897Smav vendor, product, revision, fw, in, ins); 312235897Smav} 313235897Smav 314198897Smavuint32_t 315198897Smavata_logical_sector_size(struct ata_params *ident_data) 316198897Smav{ 317198897Smav if ((ident_data->pss & 0xc000) == 0x4000 && 318198897Smav (ident_data->pss & ATA_PSS_LSSABOVE512)) { 319198897Smav return ((u_int32_t)ident_data->lss_1 | 320198897Smav ((u_int32_t)ident_data->lss_2 << 16)); 321198897Smav } 322198897Smav return (512); 323198897Smav} 324198897Smav 325198897Smavuint64_t 326198897Smavata_physical_sector_size(struct ata_params *ident_data) 327198897Smav{ 328198897Smav if ((ident_data->pss & 0xc000) == 0x4000 && 329198897Smav (ident_data->pss & ATA_PSS_MULTLS)) { 330198897Smav return ((uint64_t)ata_logical_sector_size(ident_data) * 331198897Smav (1 << (ident_data->pss & ATA_PSS_LSPPS))); 332198897Smav } 333198897Smav return (512); 334198897Smav} 335198897Smav 336198897Smavuint64_t 337198897Smavata_logical_sector_offset(struct ata_params *ident_data) 338198897Smav{ 339198897Smav if ((ident_data->lsalign & 0xc000) == 0x4000) { 340198897Smav return ((uint64_t)ata_logical_sector_size(ident_data) * 341198897Smav (ident_data->lsalign & 0x3fff)); 342198897Smav } 343198897Smav return (0); 344198897Smav} 345198897Smav 346195534Sscottlvoid 347196659Smavata_28bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint8_t features, 348195534Sscottl uint32_t lba, uint8_t sector_count) 349195534Sscottl{ 350195534Sscottl bzero(&ataio->cmd, sizeof(ataio->cmd)); 351195534Sscottl ataio->cmd.flags = 0; 352200008Smav if (cmd == ATA_READ_DMA || 353200008Smav cmd == ATA_READ_DMA_QUEUED || 354200008Smav cmd == ATA_WRITE_DMA || 355200008Smav cmd == ATA_WRITE_DMA_QUEUED) 356200008Smav ataio->cmd.flags |= CAM_ATAIO_DMA; 357195534Sscottl ataio->cmd.command = cmd; 358195534Sscottl ataio->cmd.features = features; 359195534Sscottl ataio->cmd.lba_low = lba; 360195534Sscottl ataio->cmd.lba_mid = lba >> 8; 361195534Sscottl ataio->cmd.lba_high = lba >> 16; 362238393Sbrueffer ataio->cmd.device = ATA_DEV_LBA | ((lba >> 24) & 0x0f); 363195534Sscottl ataio->cmd.sector_count = sector_count; 364195534Sscottl} 365195534Sscottl 366195534Sscottlvoid 367195534Sscottlata_48bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint16_t features, 368195534Sscottl uint64_t lba, uint16_t sector_count) 369195534Sscottl{ 370248695Smav 371195534Sscottl ataio->cmd.flags = CAM_ATAIO_48BIT; 372200008Smav if (cmd == ATA_READ_DMA48 || 373200008Smav cmd == ATA_READ_DMA_QUEUED48 || 374200008Smav cmd == ATA_READ_STREAM_DMA48 || 375200008Smav cmd == ATA_WRITE_DMA48 || 376200008Smav cmd == ATA_WRITE_DMA_FUA48 || 377200008Smav cmd == ATA_WRITE_DMA_QUEUED48 || 378200008Smav cmd == ATA_WRITE_DMA_QUEUED_FUA48 || 379201139Smav cmd == ATA_WRITE_STREAM_DMA48 || 380201139Smav cmd == ATA_DATA_SET_MANAGEMENT) 381200008Smav ataio->cmd.flags |= CAM_ATAIO_DMA; 382195534Sscottl ataio->cmd.command = cmd; 383195534Sscottl ataio->cmd.features = features; 384195534Sscottl ataio->cmd.lba_low = lba; 385195534Sscottl ataio->cmd.lba_mid = lba >> 8; 386195534Sscottl ataio->cmd.lba_high = lba >> 16; 387238393Sbrueffer ataio->cmd.device = ATA_DEV_LBA; 388195534Sscottl ataio->cmd.lba_low_exp = lba >> 24; 389195534Sscottl ataio->cmd.lba_mid_exp = lba >> 32; 390195534Sscottl ataio->cmd.lba_high_exp = lba >> 40; 391195534Sscottl ataio->cmd.features_exp = features >> 8; 392195534Sscottl ataio->cmd.sector_count = sector_count; 393195534Sscottl ataio->cmd.sector_count_exp = sector_count >> 8; 394248695Smav ataio->cmd.control = 0; 395195534Sscottl} 396195534Sscottl 397195534Sscottlvoid 398195534Sscottlata_ncq_cmd(struct ccb_ataio *ataio, uint8_t cmd, 399195534Sscottl uint64_t lba, uint16_t sector_count) 400195534Sscottl{ 401248695Smav 402195534Sscottl ataio->cmd.flags = CAM_ATAIO_48BIT | CAM_ATAIO_FPDMA; 403195534Sscottl ataio->cmd.command = cmd; 404195534Sscottl ataio->cmd.features = sector_count; 405195534Sscottl ataio->cmd.lba_low = lba; 406195534Sscottl ataio->cmd.lba_mid = lba >> 8; 407195534Sscottl ataio->cmd.lba_high = lba >> 16; 408238393Sbrueffer ataio->cmd.device = ATA_DEV_LBA; 409195534Sscottl ataio->cmd.lba_low_exp = lba >> 24; 410195534Sscottl ataio->cmd.lba_mid_exp = lba >> 32; 411195534Sscottl ataio->cmd.lba_high_exp = lba >> 40; 412195534Sscottl ataio->cmd.features_exp = sector_count >> 8; 413248695Smav ataio->cmd.sector_count = 0; 414248695Smav ataio->cmd.sector_count_exp = 0; 415248695Smav ataio->cmd.control = 0; 416195534Sscottl} 417195534Sscottl 418195534Sscottlvoid 419195534Sscottlata_reset_cmd(struct ccb_ataio *ataio) 420195534Sscottl{ 421195534Sscottl bzero(&ataio->cmd, sizeof(ataio->cmd)); 422195534Sscottl ataio->cmd.flags = CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT; 423195534Sscottl ataio->cmd.control = 0x04; 424195534Sscottl} 425195534Sscottl 426195534Sscottlvoid 427195534Sscottlata_pm_read_cmd(struct ccb_ataio *ataio, int reg, int port) 428195534Sscottl{ 429195534Sscottl bzero(&ataio->cmd, sizeof(ataio->cmd)); 430198904Smav ataio->cmd.flags = CAM_ATAIO_NEEDRESULT; 431195534Sscottl ataio->cmd.command = ATA_READ_PM; 432195534Sscottl ataio->cmd.features = reg; 433195534Sscottl ataio->cmd.device = port & 0x0f; 434195534Sscottl} 435195534Sscottl 436195534Sscottlvoid 437198904Smavata_pm_write_cmd(struct ccb_ataio *ataio, int reg, int port, uint32_t val) 438195534Sscottl{ 439195534Sscottl bzero(&ataio->cmd, sizeof(ataio->cmd)); 440198904Smav ataio->cmd.flags = 0; 441195534Sscottl ataio->cmd.command = ATA_WRITE_PM; 442195534Sscottl ataio->cmd.features = reg; 443198904Smav ataio->cmd.sector_count = val; 444195534Sscottl ataio->cmd.lba_low = val >> 8; 445195534Sscottl ataio->cmd.lba_mid = val >> 16; 446195534Sscottl ataio->cmd.lba_high = val >> 24; 447195534Sscottl ataio->cmd.device = port & 0x0f; 448195534Sscottl} 449195534Sscottl 450195534Sscottlvoid 451195534Sscottlata_bswap(int8_t *buf, int len) 452195534Sscottl{ 453195534Sscottl u_int16_t *ptr = (u_int16_t*)(buf + len); 454195534Sscottl 455195534Sscottl while (--ptr >= (u_int16_t*)buf) 456195534Sscottl *ptr = be16toh(*ptr); 457195534Sscottl} 458195534Sscottl 459195534Sscottlvoid 460195534Sscottlata_btrim(int8_t *buf, int len) 461195534Sscottl{ 462195534Sscottl int8_t *ptr; 463195534Sscottl 464195534Sscottl for (ptr = buf; ptr < buf+len; ++ptr) 465195534Sscottl if (!*ptr || *ptr == '_') 466195534Sscottl *ptr = ' '; 467195534Sscottl for (ptr = buf + len - 1; ptr >= buf && *ptr == ' '; --ptr) 468195534Sscottl *ptr = 0; 469195534Sscottl} 470195534Sscottl 471195534Sscottlvoid 472195534Sscottlata_bpack(int8_t *src, int8_t *dst, int len) 473195534Sscottl{ 474195534Sscottl int i, j, blank; 475195534Sscottl 476195534Sscottl for (i = j = blank = 0 ; i < len; i++) { 477195534Sscottl if (blank && src[i] == ' ') continue; 478195534Sscottl if (blank && src[i] != ' ') { 479195534Sscottl dst[j++] = src[i]; 480195534Sscottl blank = 0; 481195534Sscottl continue; 482195534Sscottl } 483195534Sscottl if (src[i] == ' ') { 484195534Sscottl blank = 1; 485195534Sscottl if (i == 0) 486195534Sscottl continue; 487195534Sscottl } 488195534Sscottl dst[j++] = src[i]; 489195534Sscottl } 490195534Sscottl while (j < len) 491195534Sscottl dst[j++] = 0x00; 492195534Sscottl} 493195534Sscottl 494195534Sscottlint 495195534Sscottlata_max_pmode(struct ata_params *ap) 496195534Sscottl{ 497195534Sscottl if (ap->atavalid & ATA_FLAG_64_70) { 498195534Sscottl if (ap->apiomodes & 0x02) 499195534Sscottl return ATA_PIO4; 500195534Sscottl if (ap->apiomodes & 0x01) 501195534Sscottl return ATA_PIO3; 502195534Sscottl } 503195534Sscottl if (ap->mwdmamodes & 0x04) 504195534Sscottl return ATA_PIO4; 505195534Sscottl if (ap->mwdmamodes & 0x02) 506195534Sscottl return ATA_PIO3; 507195534Sscottl if (ap->mwdmamodes & 0x01) 508195534Sscottl return ATA_PIO2; 509195534Sscottl if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x200) 510195534Sscottl return ATA_PIO2; 511195534Sscottl if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x100) 512195534Sscottl return ATA_PIO1; 513195534Sscottl if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x000) 514195534Sscottl return ATA_PIO0; 515195534Sscottl return ATA_PIO0; 516195534Sscottl} 517195534Sscottl 518195534Sscottlint 519195534Sscottlata_max_wmode(struct ata_params *ap) 520195534Sscottl{ 521195534Sscottl if (ap->mwdmamodes & 0x04) 522195534Sscottl return ATA_WDMA2; 523195534Sscottl if (ap->mwdmamodes & 0x02) 524195534Sscottl return ATA_WDMA1; 525195534Sscottl if (ap->mwdmamodes & 0x01) 526195534Sscottl return ATA_WDMA0; 527195534Sscottl return -1; 528195534Sscottl} 529195534Sscottl 530195534Sscottlint 531195534Sscottlata_max_umode(struct ata_params *ap) 532195534Sscottl{ 533195534Sscottl if (ap->atavalid & ATA_FLAG_88) { 534195534Sscottl if (ap->udmamodes & 0x40) 535195534Sscottl return ATA_UDMA6; 536195534Sscottl if (ap->udmamodes & 0x20) 537195534Sscottl return ATA_UDMA5; 538195534Sscottl if (ap->udmamodes & 0x10) 539195534Sscottl return ATA_UDMA4; 540195534Sscottl if (ap->udmamodes & 0x08) 541195534Sscottl return ATA_UDMA3; 542195534Sscottl if (ap->udmamodes & 0x04) 543195534Sscottl return ATA_UDMA2; 544195534Sscottl if (ap->udmamodes & 0x02) 545195534Sscottl return ATA_UDMA1; 546195534Sscottl if (ap->udmamodes & 0x01) 547195534Sscottl return ATA_UDMA0; 548195534Sscottl } 549195534Sscottl return -1; 550195534Sscottl} 551195534Sscottl 552195534Sscottlint 553199747Smavata_max_mode(struct ata_params *ap, int maxmode) 554195534Sscottl{ 555195534Sscottl 556199747Smav if (maxmode == 0) 557199747Smav maxmode = ATA_DMA_MAX; 558199747Smav if (maxmode >= ATA_UDMA0 && ata_max_umode(ap) > 0) 559199747Smav return (min(maxmode, ata_max_umode(ap))); 560199747Smav if (maxmode >= ATA_WDMA0 && ata_max_wmode(ap) > 0) 561199747Smav return (min(maxmode, ata_max_wmode(ap))); 562199747Smav return (min(maxmode, ata_max_pmode(ap))); 563199747Smav} 564195534Sscottl 565199747Smavchar * 566199747Smavata_mode2string(int mode) 567199747Smav{ 568199747Smav switch (mode) { 569199747Smav case -1: return "UNSUPPORTED"; 570199747Smav case 0: return "NONE"; 571199747Smav case ATA_PIO0: return "PIO0"; 572199747Smav case ATA_PIO1: return "PIO1"; 573199747Smav case ATA_PIO2: return "PIO2"; 574199747Smav case ATA_PIO3: return "PIO3"; 575199747Smav case ATA_PIO4: return "PIO4"; 576199747Smav case ATA_WDMA0: return "WDMA0"; 577199747Smav case ATA_WDMA1: return "WDMA1"; 578199747Smav case ATA_WDMA2: return "WDMA2"; 579199747Smav case ATA_UDMA0: return "UDMA0"; 580199747Smav case ATA_UDMA1: return "UDMA1"; 581199747Smav case ATA_UDMA2: return "UDMA2"; 582199747Smav case ATA_UDMA3: return "UDMA3"; 583199747Smav case ATA_UDMA4: return "UDMA4"; 584199747Smav case ATA_UDMA5: return "UDMA5"; 585199747Smav case ATA_UDMA6: return "UDMA6"; 586199747Smav default: 587199747Smav if (mode & ATA_DMA_MASK) 588199747Smav return "BIOSDMA"; 589199747Smav else 590199747Smav return "BIOSPIO"; 591199747Smav } 592199747Smav} 593195534Sscottl 594199821Smavint 595199821Smavata_string2mode(char *str) 596199821Smav{ 597199821Smav if (!strcasecmp(str, "PIO0")) return (ATA_PIO0); 598199821Smav if (!strcasecmp(str, "PIO1")) return (ATA_PIO1); 599199821Smav if (!strcasecmp(str, "PIO2")) return (ATA_PIO2); 600199821Smav if (!strcasecmp(str, "PIO3")) return (ATA_PIO3); 601199821Smav if (!strcasecmp(str, "PIO4")) return (ATA_PIO4); 602199821Smav if (!strcasecmp(str, "WDMA0")) return (ATA_WDMA0); 603199821Smav if (!strcasecmp(str, "WDMA1")) return (ATA_WDMA1); 604199821Smav if (!strcasecmp(str, "WDMA2")) return (ATA_WDMA2); 605199821Smav if (!strcasecmp(str, "UDMA0")) return (ATA_UDMA0); 606199821Smav if (!strcasecmp(str, "UDMA16")) return (ATA_UDMA0); 607199821Smav if (!strcasecmp(str, "UDMA1")) return (ATA_UDMA1); 608199821Smav if (!strcasecmp(str, "UDMA25")) return (ATA_UDMA1); 609199821Smav if (!strcasecmp(str, "UDMA2")) return (ATA_UDMA2); 610199821Smav if (!strcasecmp(str, "UDMA33")) return (ATA_UDMA2); 611199821Smav if (!strcasecmp(str, "UDMA3")) return (ATA_UDMA3); 612199821Smav if (!strcasecmp(str, "UDMA44")) return (ATA_UDMA3); 613199821Smav if (!strcasecmp(str, "UDMA4")) return (ATA_UDMA4); 614199821Smav if (!strcasecmp(str, "UDMA66")) return (ATA_UDMA4); 615199821Smav if (!strcasecmp(str, "UDMA5")) return (ATA_UDMA5); 616199821Smav if (!strcasecmp(str, "UDMA100")) return (ATA_UDMA5); 617199821Smav if (!strcasecmp(str, "UDMA6")) return (ATA_UDMA6); 618199821Smav if (!strcasecmp(str, "UDMA133")) return (ATA_UDMA6); 619199821Smav return (-1); 620199821Smav} 621199821Smav 622199821Smav 623199747Smavu_int 624199747Smavata_mode2speed(int mode) 625199747Smav{ 626199747Smav switch (mode) { 627199747Smav case ATA_PIO0: 628199747Smav default: 629199747Smav return (3300); 630199747Smav case ATA_PIO1: 631199747Smav return (5200); 632199747Smav case ATA_PIO2: 633199747Smav return (8300); 634199747Smav case ATA_PIO3: 635199747Smav return (11100); 636199747Smav case ATA_PIO4: 637199747Smav return (16700); 638199747Smav case ATA_WDMA0: 639199747Smav return (4200); 640199747Smav case ATA_WDMA1: 641199747Smav return (13300); 642199747Smav case ATA_WDMA2: 643199747Smav return (16700); 644199747Smav case ATA_UDMA0: 645199747Smav return (16700); 646199747Smav case ATA_UDMA1: 647199747Smav return (25000); 648199747Smav case ATA_UDMA2: 649199747Smav return (33300); 650199747Smav case ATA_UDMA3: 651199747Smav return (44400); 652199747Smav case ATA_UDMA4: 653199747Smav return (66700); 654199747Smav case ATA_UDMA5: 655199747Smav return (100000); 656199747Smav case ATA_UDMA6: 657199747Smav return (133000); 658199747Smav } 659199747Smav} 660195534Sscottl 661199747Smavu_int 662199747Smavata_revision2speed(int revision) 663199747Smav{ 664199747Smav switch (revision) { 665199747Smav case 1: 666199747Smav default: 667199747Smav return (150000); 668199747Smav case 2: 669199747Smav return (300000); 670199747Smav case 3: 671199747Smav return (600000); 672199747Smav } 673199747Smav} 674195534Sscottl 675199747Smavint 676199747Smavata_speed2revision(u_int speed) 677199747Smav{ 678199747Smav switch (speed) { 679199821Smav case 0: 680199821Smav return (0); 681199747Smav case 150000: 682199747Smav return (1); 683199747Smav case 300000: 684199747Smav return (2); 685199747Smav case 600000: 686199747Smav return (3); 687199821Smav default: 688199821Smav return (-1); 689199747Smav } 690195534Sscottl} 691195534Sscottl 692199178Smavint 693199178Smavata_identify_match(caddr_t identbuffer, caddr_t table_entry) 694199178Smav{ 695199178Smav struct scsi_inquiry_pattern *entry; 696199178Smav struct ata_params *ident; 697199178Smav 698199178Smav entry = (struct scsi_inquiry_pattern *)table_entry; 699199178Smav ident = (struct ata_params *)identbuffer; 700199178Smav 701199178Smav if ((cam_strmatch(ident->model, entry->product, 702199178Smav sizeof(ident->model)) == 0) 703199178Smav && (cam_strmatch(ident->revision, entry->revision, 704199178Smav sizeof(ident->revision)) == 0)) { 705199178Smav return (0); 706199178Smav } 707199178Smav return (-1); 708199178Smav} 709199178Smav 710199178Smavint 711199178Smavata_static_identify_match(caddr_t identbuffer, caddr_t table_entry) 712199178Smav{ 713199178Smav struct scsi_static_inquiry_pattern *entry; 714199178Smav struct ata_params *ident; 715199178Smav 716199178Smav entry = (struct scsi_static_inquiry_pattern *)table_entry; 717199178Smav ident = (struct ata_params *)identbuffer; 718199178Smav 719199178Smav if ((cam_strmatch(ident->model, entry->product, 720199178Smav sizeof(ident->model)) == 0) 721199178Smav && (cam_strmatch(ident->revision, entry->revision, 722199178Smav sizeof(ident->revision)) == 0)) { 723199178Smav return (0); 724199178Smav } 725199178Smav return (-1); 726199178Smav} 727235897Smav 728235897Smavvoid 729235897Smavsemb_receive_diagnostic_results(struct ccb_ataio *ataio, 730235897Smav u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*), 731235897Smav uint8_t tag_action, int pcv, uint8_t page_code, 732235897Smav uint8_t *data_ptr, uint16_t length, uint32_t timeout) 733235897Smav{ 734235897Smav 735235897Smav length = min(length, 1020); 736235897Smav length = (length + 3) & ~3; 737235897Smav cam_fill_ataio(ataio, 738235897Smav retries, 739235897Smav cbfcnp, 740235897Smav /*flags*/CAM_DIR_IN, 741235897Smav tag_action, 742235897Smav data_ptr, 743235897Smav length, 744235897Smav timeout); 745235897Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 746235897Smav pcv ? page_code : 0, 0x02, length / 4); 747235897Smav} 748235897Smav 749235897Smavvoid 750235897Smavsemb_send_diagnostic(struct ccb_ataio *ataio, 751235897Smav u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), 752235897Smav uint8_t tag_action, uint8_t *data_ptr, uint16_t length, uint32_t timeout) 753235897Smav{ 754235897Smav 755235897Smav length = min(length, 1020); 756235897Smav length = (length + 3) & ~3; 757235897Smav cam_fill_ataio(ataio, 758235897Smav retries, 759235897Smav cbfcnp, 760235897Smav /*flags*/length ? CAM_DIR_OUT : CAM_DIR_NONE, 761235897Smav tag_action, 762235897Smav data_ptr, 763235897Smav length, 764235897Smav timeout); 765235897Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 766235897Smav length > 0 ? data_ptr[0] : 0, 0x82, length / 4); 767235897Smav} 768235897Smav 769235897Smavvoid 770235897Smavsemb_read_buffer(struct ccb_ataio *ataio, 771235897Smav u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*), 772235897Smav uint8_t tag_action, uint8_t page_code, 773235897Smav uint8_t *data_ptr, uint16_t length, uint32_t timeout) 774235897Smav{ 775235897Smav 776235897Smav length = min(length, 1020); 777235897Smav length = (length + 3) & ~3; 778235897Smav cam_fill_ataio(ataio, 779235897Smav retries, 780235897Smav cbfcnp, 781235897Smav /*flags*/CAM_DIR_IN, 782235897Smav tag_action, 783235897Smav data_ptr, 784235897Smav length, 785235897Smav timeout); 786235897Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 787235897Smav page_code, 0x00, length / 4); 788235897Smav} 789235897Smav 790235897Smavvoid 791235897Smavsemb_write_buffer(struct ccb_ataio *ataio, 792235897Smav u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), 793235897Smav uint8_t tag_action, uint8_t *data_ptr, uint16_t length, uint32_t timeout) 794235897Smav{ 795235897Smav 796235897Smav length = min(length, 1020); 797235897Smav length = (length + 3) & ~3; 798235897Smav cam_fill_ataio(ataio, 799235897Smav retries, 800235897Smav cbfcnp, 801235897Smav /*flags*/length ? CAM_DIR_OUT : CAM_DIR_NONE, 802235897Smav tag_action, 803235897Smav data_ptr, 804235897Smav length, 805235897Smav timeout); 806235897Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 807235897Smav length > 0 ? data_ptr[0] : 0, 0x80, length / 4); 808235897Smav} 809235897Smav 810