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$"); 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"); 111236778Smav case 0x67: 112236778Smav if (cmd->features == 0xec) 113236778Smav return ("SEP_ATTN IDENTIFY"); 114236778Smav switch (cmd->lba_low) { 115236778Smav case 0x00: return ("SEP_ATTN READ BUFFER"); 116236778Smav case 0x02: return ("SEP_ATTN RECEIVE DIAGNOSTIC RESULTS"); 117236778Smav case 0x80: return ("SEP_ATTN WRITE BUFFER"); 118236778Smav case 0x82: return ("SEP_ATTN SEND DIAGNOSTIC"); 119236778Smav } 120236778Smav 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"); 174238591Sbrueffer case 0xf5: return ("SECURITY_FREEZE_LOCK"); 175238591Sbrueffer 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 299236778Smavvoid 300257050Smavata_print_ident_short(struct ata_params *ident_data) 301257050Smav{ 302257050Smav char product[48], revision[16]; 303257050Smav 304257050Smav cam_strvis(product, ident_data->model, sizeof(ident_data->model), 305257050Smav sizeof(product)); 306257050Smav cam_strvis(revision, ident_data->revision, sizeof(ident_data->revision), 307257050Smav sizeof(revision)); 308257050Smav printf("<%s %s>", product, revision); 309257050Smav} 310257050Smav 311257050Smavvoid 312236778Smavsemb_print_ident(struct sep_identify_data *ident_data) 313236778Smav{ 314236778Smav char vendor[9], product[17], revision[5], fw[5], in[7], ins[5]; 315236778Smav 316236778Smav cam_strvis(vendor, ident_data->vendor_id, 8, sizeof(vendor)); 317236778Smav cam_strvis(product, ident_data->product_id, 16, sizeof(product)); 318236778Smav cam_strvis(revision, ident_data->product_rev, 4, sizeof(revision)); 319236778Smav cam_strvis(fw, ident_data->firmware_rev, 4, sizeof(fw)); 320236778Smav cam_strvis(in, ident_data->interface_id, 6, sizeof(in)); 321236778Smav cam_strvis(ins, ident_data->interface_rev, 4, sizeof(ins)); 322236778Smav printf("<%s %s %s %s> SEMB %s %s device\n", 323236778Smav vendor, product, revision, fw, in, ins); 324236778Smav} 325236778Smav 326257050Smavvoid 327257050Smavsemb_print_ident_short(struct sep_identify_data *ident_data) 328257050Smav{ 329257050Smav char vendor[9], product[17], revision[5], fw[5]; 330257050Smav 331257050Smav cam_strvis(vendor, ident_data->vendor_id, 8, sizeof(vendor)); 332257050Smav cam_strvis(product, ident_data->product_id, 16, sizeof(product)); 333257050Smav cam_strvis(revision, ident_data->product_rev, 4, sizeof(revision)); 334257050Smav cam_strvis(fw, ident_data->firmware_rev, 4, sizeof(fw)); 335257050Smav printf("<%s %s %s %s>", vendor, product, revision, fw); 336257050Smav} 337257050Smav 338198897Smavuint32_t 339198897Smavata_logical_sector_size(struct ata_params *ident_data) 340198897Smav{ 341263157Smav if ((ident_data->pss & ATA_PSS_VALID_MASK) == ATA_PSS_VALID_VALUE && 342198897Smav (ident_data->pss & ATA_PSS_LSSABOVE512)) { 343263157Smav return (((u_int32_t)ident_data->lss_1 | 344263157Smav ((u_int32_t)ident_data->lss_2 << 16)) * 2); 345198897Smav } 346198897Smav return (512); 347198897Smav} 348198897Smav 349198897Smavuint64_t 350198897Smavata_physical_sector_size(struct ata_params *ident_data) 351198897Smav{ 352263157Smav if ((ident_data->pss & ATA_PSS_VALID_MASK) == ATA_PSS_VALID_VALUE) { 353263157Smav if (ident_data->pss & ATA_PSS_MULTLS) { 354263157Smav return ((uint64_t)ata_logical_sector_size(ident_data) * 355263157Smav (1 << (ident_data->pss & ATA_PSS_LSPPS))); 356263157Smav } else { 357263157Smav return (uint64_t)ata_logical_sector_size(ident_data); 358263157Smav } 359198897Smav } 360198897Smav return (512); 361198897Smav} 362198897Smav 363198897Smavuint64_t 364198897Smavata_logical_sector_offset(struct ata_params *ident_data) 365198897Smav{ 366198897Smav if ((ident_data->lsalign & 0xc000) == 0x4000) { 367198897Smav return ((uint64_t)ata_logical_sector_size(ident_data) * 368198897Smav (ident_data->lsalign & 0x3fff)); 369198897Smav } 370198897Smav return (0); 371198897Smav} 372198897Smav 373195534Sscottlvoid 374196659Smavata_28bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint8_t features, 375195534Sscottl uint32_t lba, uint8_t sector_count) 376195534Sscottl{ 377195534Sscottl bzero(&ataio->cmd, sizeof(ataio->cmd)); 378195534Sscottl ataio->cmd.flags = 0; 379200008Smav if (cmd == ATA_READ_DMA || 380200008Smav cmd == ATA_READ_DMA_QUEUED || 381200008Smav cmd == ATA_WRITE_DMA || 382200008Smav cmd == ATA_WRITE_DMA_QUEUED) 383200008Smav ataio->cmd.flags |= CAM_ATAIO_DMA; 384195534Sscottl ataio->cmd.command = cmd; 385195534Sscottl ataio->cmd.features = features; 386195534Sscottl ataio->cmd.lba_low = lba; 387195534Sscottl ataio->cmd.lba_mid = lba >> 8; 388195534Sscottl ataio->cmd.lba_high = lba >> 16; 389238793Sbrueffer ataio->cmd.device = ATA_DEV_LBA | ((lba >> 24) & 0x0f); 390195534Sscottl ataio->cmd.sector_count = sector_count; 391195534Sscottl} 392195534Sscottl 393195534Sscottlvoid 394195534Sscottlata_48bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint16_t features, 395195534Sscottl uint64_t lba, uint16_t sector_count) 396195534Sscottl{ 397249609Smav 398195534Sscottl ataio->cmd.flags = CAM_ATAIO_48BIT; 399200008Smav if (cmd == ATA_READ_DMA48 || 400200008Smav cmd == ATA_READ_DMA_QUEUED48 || 401200008Smav cmd == ATA_READ_STREAM_DMA48 || 402200008Smav cmd == ATA_WRITE_DMA48 || 403200008Smav cmd == ATA_WRITE_DMA_FUA48 || 404200008Smav cmd == ATA_WRITE_DMA_QUEUED48 || 405200008Smav cmd == ATA_WRITE_DMA_QUEUED_FUA48 || 406201139Smav cmd == ATA_WRITE_STREAM_DMA48 || 407201139Smav cmd == ATA_DATA_SET_MANAGEMENT) 408200008Smav ataio->cmd.flags |= CAM_ATAIO_DMA; 409195534Sscottl ataio->cmd.command = cmd; 410195534Sscottl ataio->cmd.features = features; 411195534Sscottl ataio->cmd.lba_low = lba; 412195534Sscottl ataio->cmd.lba_mid = lba >> 8; 413195534Sscottl ataio->cmd.lba_high = lba >> 16; 414238793Sbrueffer ataio->cmd.device = ATA_DEV_LBA; 415195534Sscottl ataio->cmd.lba_low_exp = lba >> 24; 416195534Sscottl ataio->cmd.lba_mid_exp = lba >> 32; 417195534Sscottl ataio->cmd.lba_high_exp = lba >> 40; 418195534Sscottl ataio->cmd.features_exp = features >> 8; 419195534Sscottl ataio->cmd.sector_count = sector_count; 420195534Sscottl ataio->cmd.sector_count_exp = sector_count >> 8; 421249609Smav ataio->cmd.control = 0; 422195534Sscottl} 423195534Sscottl 424195534Sscottlvoid 425195534Sscottlata_ncq_cmd(struct ccb_ataio *ataio, uint8_t cmd, 426195534Sscottl uint64_t lba, uint16_t sector_count) 427195534Sscottl{ 428249609Smav 429195534Sscottl ataio->cmd.flags = CAM_ATAIO_48BIT | CAM_ATAIO_FPDMA; 430195534Sscottl ataio->cmd.command = cmd; 431195534Sscottl ataio->cmd.features = sector_count; 432195534Sscottl ataio->cmd.lba_low = lba; 433195534Sscottl ataio->cmd.lba_mid = lba >> 8; 434195534Sscottl ataio->cmd.lba_high = lba >> 16; 435238793Sbrueffer ataio->cmd.device = ATA_DEV_LBA; 436195534Sscottl ataio->cmd.lba_low_exp = lba >> 24; 437195534Sscottl ataio->cmd.lba_mid_exp = lba >> 32; 438195534Sscottl ataio->cmd.lba_high_exp = lba >> 40; 439195534Sscottl ataio->cmd.features_exp = sector_count >> 8; 440249609Smav ataio->cmd.sector_count = 0; 441249609Smav ataio->cmd.sector_count_exp = 0; 442249609Smav ataio->cmd.control = 0; 443195534Sscottl} 444195534Sscottl 445195534Sscottlvoid 446195534Sscottlata_reset_cmd(struct ccb_ataio *ataio) 447195534Sscottl{ 448195534Sscottl bzero(&ataio->cmd, sizeof(ataio->cmd)); 449195534Sscottl ataio->cmd.flags = CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT; 450195534Sscottl ataio->cmd.control = 0x04; 451195534Sscottl} 452195534Sscottl 453195534Sscottlvoid 454195534Sscottlata_pm_read_cmd(struct ccb_ataio *ataio, int reg, int port) 455195534Sscottl{ 456195534Sscottl bzero(&ataio->cmd, sizeof(ataio->cmd)); 457198904Smav ataio->cmd.flags = CAM_ATAIO_NEEDRESULT; 458195534Sscottl ataio->cmd.command = ATA_READ_PM; 459195534Sscottl ataio->cmd.features = reg; 460195534Sscottl ataio->cmd.device = port & 0x0f; 461195534Sscottl} 462195534Sscottl 463195534Sscottlvoid 464198904Smavata_pm_write_cmd(struct ccb_ataio *ataio, int reg, int port, uint32_t val) 465195534Sscottl{ 466195534Sscottl bzero(&ataio->cmd, sizeof(ataio->cmd)); 467198904Smav ataio->cmd.flags = 0; 468195534Sscottl ataio->cmd.command = ATA_WRITE_PM; 469195534Sscottl ataio->cmd.features = reg; 470198904Smav ataio->cmd.sector_count = val; 471195534Sscottl ataio->cmd.lba_low = val >> 8; 472195534Sscottl ataio->cmd.lba_mid = val >> 16; 473195534Sscottl ataio->cmd.lba_high = val >> 24; 474195534Sscottl ataio->cmd.device = port & 0x0f; 475195534Sscottl} 476195534Sscottl 477195534Sscottlvoid 478195534Sscottlata_bswap(int8_t *buf, int len) 479195534Sscottl{ 480195534Sscottl u_int16_t *ptr = (u_int16_t*)(buf + len); 481195534Sscottl 482195534Sscottl while (--ptr >= (u_int16_t*)buf) 483195534Sscottl *ptr = be16toh(*ptr); 484195534Sscottl} 485195534Sscottl 486195534Sscottlvoid 487195534Sscottlata_btrim(int8_t *buf, int len) 488195534Sscottl{ 489195534Sscottl int8_t *ptr; 490195534Sscottl 491195534Sscottl for (ptr = buf; ptr < buf+len; ++ptr) 492195534Sscottl if (!*ptr || *ptr == '_') 493195534Sscottl *ptr = ' '; 494195534Sscottl for (ptr = buf + len - 1; ptr >= buf && *ptr == ' '; --ptr) 495195534Sscottl *ptr = 0; 496195534Sscottl} 497195534Sscottl 498195534Sscottlvoid 499195534Sscottlata_bpack(int8_t *src, int8_t *dst, int len) 500195534Sscottl{ 501195534Sscottl int i, j, blank; 502195534Sscottl 503195534Sscottl for (i = j = blank = 0 ; i < len; i++) { 504195534Sscottl if (blank && src[i] == ' ') continue; 505195534Sscottl if (blank && src[i] != ' ') { 506195534Sscottl dst[j++] = src[i]; 507195534Sscottl blank = 0; 508195534Sscottl continue; 509195534Sscottl } 510195534Sscottl if (src[i] == ' ') { 511195534Sscottl blank = 1; 512195534Sscottl if (i == 0) 513195534Sscottl continue; 514195534Sscottl } 515195534Sscottl dst[j++] = src[i]; 516195534Sscottl } 517195534Sscottl while (j < len) 518195534Sscottl dst[j++] = 0x00; 519195534Sscottl} 520195534Sscottl 521195534Sscottlint 522195534Sscottlata_max_pmode(struct ata_params *ap) 523195534Sscottl{ 524195534Sscottl if (ap->atavalid & ATA_FLAG_64_70) { 525195534Sscottl if (ap->apiomodes & 0x02) 526195534Sscottl return ATA_PIO4; 527195534Sscottl if (ap->apiomodes & 0x01) 528195534Sscottl return ATA_PIO3; 529195534Sscottl } 530195534Sscottl if (ap->mwdmamodes & 0x04) 531195534Sscottl return ATA_PIO4; 532195534Sscottl if (ap->mwdmamodes & 0x02) 533195534Sscottl return ATA_PIO3; 534195534Sscottl if (ap->mwdmamodes & 0x01) 535195534Sscottl return ATA_PIO2; 536195534Sscottl if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x200) 537195534Sscottl return ATA_PIO2; 538195534Sscottl if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x100) 539195534Sscottl return ATA_PIO1; 540195534Sscottl if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x000) 541195534Sscottl return ATA_PIO0; 542195534Sscottl return ATA_PIO0; 543195534Sscottl} 544195534Sscottl 545195534Sscottlint 546195534Sscottlata_max_wmode(struct ata_params *ap) 547195534Sscottl{ 548195534Sscottl if (ap->mwdmamodes & 0x04) 549195534Sscottl return ATA_WDMA2; 550195534Sscottl if (ap->mwdmamodes & 0x02) 551195534Sscottl return ATA_WDMA1; 552195534Sscottl if (ap->mwdmamodes & 0x01) 553195534Sscottl return ATA_WDMA0; 554195534Sscottl return -1; 555195534Sscottl} 556195534Sscottl 557195534Sscottlint 558195534Sscottlata_max_umode(struct ata_params *ap) 559195534Sscottl{ 560195534Sscottl if (ap->atavalid & ATA_FLAG_88) { 561195534Sscottl if (ap->udmamodes & 0x40) 562195534Sscottl return ATA_UDMA6; 563195534Sscottl if (ap->udmamodes & 0x20) 564195534Sscottl return ATA_UDMA5; 565195534Sscottl if (ap->udmamodes & 0x10) 566195534Sscottl return ATA_UDMA4; 567195534Sscottl if (ap->udmamodes & 0x08) 568195534Sscottl return ATA_UDMA3; 569195534Sscottl if (ap->udmamodes & 0x04) 570195534Sscottl return ATA_UDMA2; 571195534Sscottl if (ap->udmamodes & 0x02) 572195534Sscottl return ATA_UDMA1; 573195534Sscottl if (ap->udmamodes & 0x01) 574195534Sscottl return ATA_UDMA0; 575195534Sscottl } 576195534Sscottl return -1; 577195534Sscottl} 578195534Sscottl 579195534Sscottlint 580199747Smavata_max_mode(struct ata_params *ap, int maxmode) 581195534Sscottl{ 582195534Sscottl 583199747Smav if (maxmode == 0) 584199747Smav maxmode = ATA_DMA_MAX; 585199747Smav if (maxmode >= ATA_UDMA0 && ata_max_umode(ap) > 0) 586199747Smav return (min(maxmode, ata_max_umode(ap))); 587199747Smav if (maxmode >= ATA_WDMA0 && ata_max_wmode(ap) > 0) 588199747Smav return (min(maxmode, ata_max_wmode(ap))); 589199747Smav return (min(maxmode, ata_max_pmode(ap))); 590199747Smav} 591195534Sscottl 592199747Smavchar * 593199747Smavata_mode2string(int mode) 594199747Smav{ 595199747Smav switch (mode) { 596199747Smav case -1: return "UNSUPPORTED"; 597199747Smav case 0: return "NONE"; 598199747Smav case ATA_PIO0: return "PIO0"; 599199747Smav case ATA_PIO1: return "PIO1"; 600199747Smav case ATA_PIO2: return "PIO2"; 601199747Smav case ATA_PIO3: return "PIO3"; 602199747Smav case ATA_PIO4: return "PIO4"; 603199747Smav case ATA_WDMA0: return "WDMA0"; 604199747Smav case ATA_WDMA1: return "WDMA1"; 605199747Smav case ATA_WDMA2: return "WDMA2"; 606199747Smav case ATA_UDMA0: return "UDMA0"; 607199747Smav case ATA_UDMA1: return "UDMA1"; 608199747Smav case ATA_UDMA2: return "UDMA2"; 609199747Smav case ATA_UDMA3: return "UDMA3"; 610199747Smav case ATA_UDMA4: return "UDMA4"; 611199747Smav case ATA_UDMA5: return "UDMA5"; 612199747Smav case ATA_UDMA6: return "UDMA6"; 613199747Smav default: 614199747Smav if (mode & ATA_DMA_MASK) 615199747Smav return "BIOSDMA"; 616199747Smav else 617199747Smav return "BIOSPIO"; 618199747Smav } 619199747Smav} 620195534Sscottl 621199821Smavint 622199821Smavata_string2mode(char *str) 623199821Smav{ 624199821Smav if (!strcasecmp(str, "PIO0")) return (ATA_PIO0); 625199821Smav if (!strcasecmp(str, "PIO1")) return (ATA_PIO1); 626199821Smav if (!strcasecmp(str, "PIO2")) return (ATA_PIO2); 627199821Smav if (!strcasecmp(str, "PIO3")) return (ATA_PIO3); 628199821Smav if (!strcasecmp(str, "PIO4")) return (ATA_PIO4); 629199821Smav if (!strcasecmp(str, "WDMA0")) return (ATA_WDMA0); 630199821Smav if (!strcasecmp(str, "WDMA1")) return (ATA_WDMA1); 631199821Smav if (!strcasecmp(str, "WDMA2")) return (ATA_WDMA2); 632199821Smav if (!strcasecmp(str, "UDMA0")) return (ATA_UDMA0); 633199821Smav if (!strcasecmp(str, "UDMA16")) return (ATA_UDMA0); 634199821Smav if (!strcasecmp(str, "UDMA1")) return (ATA_UDMA1); 635199821Smav if (!strcasecmp(str, "UDMA25")) return (ATA_UDMA1); 636199821Smav if (!strcasecmp(str, "UDMA2")) return (ATA_UDMA2); 637199821Smav if (!strcasecmp(str, "UDMA33")) return (ATA_UDMA2); 638199821Smav if (!strcasecmp(str, "UDMA3")) return (ATA_UDMA3); 639199821Smav if (!strcasecmp(str, "UDMA44")) return (ATA_UDMA3); 640199821Smav if (!strcasecmp(str, "UDMA4")) return (ATA_UDMA4); 641199821Smav if (!strcasecmp(str, "UDMA66")) return (ATA_UDMA4); 642199821Smav if (!strcasecmp(str, "UDMA5")) return (ATA_UDMA5); 643199821Smav if (!strcasecmp(str, "UDMA100")) return (ATA_UDMA5); 644199821Smav if (!strcasecmp(str, "UDMA6")) return (ATA_UDMA6); 645199821Smav if (!strcasecmp(str, "UDMA133")) return (ATA_UDMA6); 646199821Smav return (-1); 647199821Smav} 648199821Smav 649199821Smav 650199747Smavu_int 651199747Smavata_mode2speed(int mode) 652199747Smav{ 653199747Smav switch (mode) { 654199747Smav case ATA_PIO0: 655199747Smav default: 656199747Smav return (3300); 657199747Smav case ATA_PIO1: 658199747Smav return (5200); 659199747Smav case ATA_PIO2: 660199747Smav return (8300); 661199747Smav case ATA_PIO3: 662199747Smav return (11100); 663199747Smav case ATA_PIO4: 664199747Smav return (16700); 665199747Smav case ATA_WDMA0: 666199747Smav return (4200); 667199747Smav case ATA_WDMA1: 668199747Smav return (13300); 669199747Smav case ATA_WDMA2: 670199747Smav return (16700); 671199747Smav case ATA_UDMA0: 672199747Smav return (16700); 673199747Smav case ATA_UDMA1: 674199747Smav return (25000); 675199747Smav case ATA_UDMA2: 676199747Smav return (33300); 677199747Smav case ATA_UDMA3: 678199747Smav return (44400); 679199747Smav case ATA_UDMA4: 680199747Smav return (66700); 681199747Smav case ATA_UDMA5: 682199747Smav return (100000); 683199747Smav case ATA_UDMA6: 684199747Smav return (133000); 685199747Smav } 686199747Smav} 687195534Sscottl 688199747Smavu_int 689199747Smavata_revision2speed(int revision) 690199747Smav{ 691199747Smav switch (revision) { 692199747Smav case 1: 693199747Smav default: 694199747Smav return (150000); 695199747Smav case 2: 696199747Smav return (300000); 697199747Smav case 3: 698199747Smav return (600000); 699199747Smav } 700199747Smav} 701195534Sscottl 702199747Smavint 703199747Smavata_speed2revision(u_int speed) 704199747Smav{ 705199747Smav switch (speed) { 706199821Smav case 0: 707199821Smav return (0); 708199747Smav case 150000: 709199747Smav return (1); 710199747Smav case 300000: 711199747Smav return (2); 712199747Smav case 600000: 713199747Smav return (3); 714199821Smav default: 715199821Smav return (-1); 716199747Smav } 717195534Sscottl} 718195534Sscottl 719199178Smavint 720199178Smavata_identify_match(caddr_t identbuffer, caddr_t table_entry) 721199178Smav{ 722199178Smav struct scsi_inquiry_pattern *entry; 723199178Smav struct ata_params *ident; 724199178Smav 725199178Smav entry = (struct scsi_inquiry_pattern *)table_entry; 726199178Smav ident = (struct ata_params *)identbuffer; 727199178Smav 728199178Smav if ((cam_strmatch(ident->model, entry->product, 729199178Smav sizeof(ident->model)) == 0) 730199178Smav && (cam_strmatch(ident->revision, entry->revision, 731199178Smav sizeof(ident->revision)) == 0)) { 732199178Smav return (0); 733199178Smav } 734199178Smav return (-1); 735199178Smav} 736199178Smav 737199178Smavint 738199178Smavata_static_identify_match(caddr_t identbuffer, caddr_t table_entry) 739199178Smav{ 740199178Smav struct scsi_static_inquiry_pattern *entry; 741199178Smav struct ata_params *ident; 742199178Smav 743199178Smav entry = (struct scsi_static_inquiry_pattern *)table_entry; 744199178Smav ident = (struct ata_params *)identbuffer; 745199178Smav 746199178Smav if ((cam_strmatch(ident->model, entry->product, 747199178Smav sizeof(ident->model)) == 0) 748199178Smav && (cam_strmatch(ident->revision, entry->revision, 749199178Smav sizeof(ident->revision)) == 0)) { 750199178Smav return (0); 751199178Smav } 752199178Smav return (-1); 753199178Smav} 754236778Smav 755236778Smavvoid 756236778Smavsemb_receive_diagnostic_results(struct ccb_ataio *ataio, 757236778Smav u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*), 758236778Smav uint8_t tag_action, int pcv, uint8_t page_code, 759236778Smav uint8_t *data_ptr, uint16_t length, uint32_t timeout) 760236778Smav{ 761236778Smav 762236778Smav length = min(length, 1020); 763236778Smav length = (length + 3) & ~3; 764236778Smav cam_fill_ataio(ataio, 765236778Smav retries, 766236778Smav cbfcnp, 767236778Smav /*flags*/CAM_DIR_IN, 768236778Smav tag_action, 769236778Smav data_ptr, 770236778Smav length, 771236778Smav timeout); 772236778Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 773236778Smav pcv ? page_code : 0, 0x02, length / 4); 774236778Smav} 775236778Smav 776236778Smavvoid 777236778Smavsemb_send_diagnostic(struct ccb_ataio *ataio, 778236778Smav u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), 779236778Smav uint8_t tag_action, uint8_t *data_ptr, uint16_t length, uint32_t timeout) 780236778Smav{ 781236778Smav 782236778Smav length = min(length, 1020); 783236778Smav length = (length + 3) & ~3; 784236778Smav cam_fill_ataio(ataio, 785236778Smav retries, 786236778Smav cbfcnp, 787236778Smav /*flags*/length ? CAM_DIR_OUT : CAM_DIR_NONE, 788236778Smav tag_action, 789236778Smav data_ptr, 790236778Smav length, 791236778Smav timeout); 792236778Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 793236778Smav length > 0 ? data_ptr[0] : 0, 0x82, length / 4); 794236778Smav} 795236778Smav 796236778Smavvoid 797236778Smavsemb_read_buffer(struct ccb_ataio *ataio, 798236778Smav u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*), 799236778Smav uint8_t tag_action, uint8_t page_code, 800236778Smav uint8_t *data_ptr, uint16_t length, uint32_t timeout) 801236778Smav{ 802236778Smav 803236778Smav length = min(length, 1020); 804236778Smav length = (length + 3) & ~3; 805236778Smav cam_fill_ataio(ataio, 806236778Smav retries, 807236778Smav cbfcnp, 808236778Smav /*flags*/CAM_DIR_IN, 809236778Smav tag_action, 810236778Smav data_ptr, 811236778Smav length, 812236778Smav timeout); 813236778Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 814236778Smav page_code, 0x00, length / 4); 815236778Smav} 816236778Smav 817236778Smavvoid 818236778Smavsemb_write_buffer(struct ccb_ataio *ataio, 819236778Smav u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), 820236778Smav uint8_t tag_action, uint8_t *data_ptr, uint16_t length, uint32_t timeout) 821236778Smav{ 822236778Smav 823236778Smav length = min(length, 1020); 824236778Smav length = (length + 3) & ~3; 825236778Smav cam_fill_ataio(ataio, 826236778Smav retries, 827236778Smav cbfcnp, 828236778Smav /*flags*/length ? CAM_DIR_OUT : CAM_DIR_NONE, 829236778Smav tag_action, 830236778Smav data_ptr, 831236778Smav length, 832236778Smav timeout); 833236778Smav ata_28bit_cmd(ataio, ATA_SEP_ATTN, 834236778Smav length > 0 ? data_ptr[0] : 0, 0x80, length / 4); 835236778Smav} 836236778Smav 837