ata_all.c revision 203108
1129198Scognet/*- 2129198Scognet * Copyright (c) 2009 Alexander Motin <mav@FreeBSD.org> 3139735Simp * All rights reserved. 4129198Scognet * 5129198Scognet * Redistribution and use in source and binary forms, with or without 6129198Scognet * modification, are permitted provided that the following conditions 7129198Scognet * are met: 8129198Scognet * 1. Redistributions of source code must retain the above copyright 9129198Scognet * notice, this list of conditions and the following disclaimer, 10129198Scognet * without modification, immediately at the beginning of the file. 11129198Scognet * 2. Redistributions in binary form must reproduce the above copyright 12129198Scognet * notice, this list of conditions and the following disclaimer in the 13129198Scognet * documentation and/or other materials provided with the distribution. 14129198Scognet * 15129198Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16129198Scognet * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17129198Scognet * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18129198Scognet * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19129198Scognet * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20129198Scognet * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21129198Scognet * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22129198Scognet * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23129198Scognet * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24129198Scognet * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25129198Scognet */ 26129198Scognet 27129198Scognet#include <sys/cdefs.h> 28129198Scognet__FBSDID("$FreeBSD: head/sys/cam/ata/ata_all.c 203108 2010-01-28 08:41:30Z mav $"); 29129198Scognet 30129198Scognet#include <sys/param.h> 31129198Scognet 32129198Scognet#ifdef _KERNEL 33129198Scognet#include <opt_scsi.h> 34129198Scognet 35129198Scognet#include <sys/systm.h> 36129198Scognet#include <sys/libkern.h> 37129198Scognet#include <sys/kernel.h> 38129198Scognet#include <sys/sysctl.h> 39129198Scognet#else 40129198Scognet#include <errno.h> 41129198Scognet#include <stdio.h> 42129198Scognet#include <stdlib.h> 43129198Scognet#include <string.h> 44129198Scognet#ifndef min 45129198Scognet#define min(a,b) (((a)<(b))?(a):(b)) 46129198Scognet#endif 47129198Scognet#endif 48129198Scognet 49129198Scognet#include <cam/cam.h> 50290661Smmel#include <cam/cam_ccb.h> 51129198Scognet#include <cam/cam_queue.h> 52129198Scognet#include <cam/cam_xpt.h> 53132055Scognet#include <sys/ata.h> 54132055Scognet#include <cam/ata/ata_all.h> 55132055Scognet#include <sys/sbuf.h> 56137940Scognet#include <sys/endian.h> 57132055Scognet 58132471Scognetint 59129198Scognetata_version(int ver) 60129198Scognet{ 61129198Scognet int bit; 62290648Smmel 63129198Scognet if (ver == 0xffff) 64129198Scognet return 0; 65129198Scognet for (bit = 15; bit >= 0; bit--) 66129198Scognet if (ver & (1<<bit)) 67129198Scognet return bit; 68129198Scognet return 0; 69129198Scognet} 70129198Scognet 71129198Scognetchar * 72290648Smmelata_op_string(struct ata_cmd *cmd) 73290648Smmel{ 74129198Scognet 75290648Smmel switch (cmd->command) { 76129198Scognet case 0x00: return ("NOP"); 77129198Scognet case 0x03: return ("CFA_REQUEST_EXTENDED_ERROR"); 78129198Scognet case 0x06: 79129198Scognet switch (cmd->features) { 80129198Scognet case 0x01: return ("DSM TRIM"); 81129198Scognet } 82129198Scognet return "DSM"; 83129198Scognet case 0x08: return ("DEVICE_RESET"); 84129198Scognet case 0x20: return ("READ"); 85129198Scognet case 0x24: return ("READ48"); 86129198Scognet case 0x25: return ("READ_DMA48"); 87129198Scognet case 0x26: return ("READ_DMA_QUEUED48"); 88129198Scognet case 0x27: return ("READ_NATIVE_MAX_ADDRESS48"); 89129198Scognet case 0x29: return ("READ_MUL48"); 90129198Scognet case 0x2a: return ("READ_STREAM_DMA48"); 91129198Scognet case 0x2b: return ("READ_STREAM48"); 92129198Scognet case 0x2f: return ("READ_LOG_EXT"); 93129198Scognet case 0x30: return ("WRITE"); 94129198Scognet case 0x34: return ("WRITE48"); 95129198Scognet case 0x35: return ("WRITE_DMA48"); 96129198Scognet case 0x36: return ("WRITE_DMA_QUEUED48"); 97129198Scognet case 0x37: return ("SET_MAX_ADDRESS48"); 98129198Scognet case 0x39: return ("WRITE_MUL48"); 99129198Scognet case 0x3a: return ("WRITE_STREAM_DMA48"); 100262420Sian case 0x3b: return ("WRITE_STREAM48"); 101262420Sian case 0x3d: return ("WRITE_DMA_FUA48"); 102262420Sian case 0x3e: return ("WRITE_DMA_QUEUED_FUA48"); 103262420Sian case 0x3f: return ("WRITE_LOG_EXT"); 104262420Sian case 0x40: return ("READ_VERIFY"); 105290648Smmel case 0x42: return ("READ_VERIFY48"); 106295207Smmel case 0x51: return ("CONFIGURE_STREAM"); 107129198Scognet case 0x60: return ("READ_FPDMA_QUEUED"); 108129198Scognet case 0x61: return ("WRITE_FPDMA_QUEUED"); 109129198Scognet case 0x70: return ("SEEK"); 110129198Scognet case 0x87: return ("CFA_TRANSLATE_SECTOR"); 111129198Scognet case 0x90: return ("EXECUTE_DEVICE_DIAGNOSTIC"); 112129198Scognet case 0x92: return ("DOWNLOAD_MICROCODE"); 113129198Scognet case 0xa0: return ("PACKET"); 114129198Scognet case 0xa1: return ("ATAPI_IDENTIFY"); 115129198Scognet case 0xa2: return ("SERVICE"); 116129198Scognet case 0xb0: return ("SMART"); 117129198Scognet case 0xb1: return ("DEVICE CONFIGURATION"); 118129198Scognet case 0xc0: return ("CFA_ERASE"); 119129198Scognet case 0xc4: return ("READ_MUL"); 120129198Scognet case 0xc5: return ("WRITE_MUL"); 121129198Scognet case 0xc6: return ("SET_MULTI"); 122129198Scognet case 0xc7: return ("READ_DMA_QUEUED"); 123129198Scognet case 0xc8: return ("READ_DMA"); 124129198Scognet case 0xca: return ("WRITE_DMA"); 125129198Scognet case 0xcc: return ("WRITE_DMA_QUEUED"); 126129198Scognet case 0xcd: return ("CFA_WRITE_MULTIPLE_WITHOUT_ERASE"); 127129198Scognet case 0xce: return ("WRITE_MUL_FUA48"); 128129198Scognet case 0xd1: return ("CHECK_MEDIA_CARD_TYPE"); 129129198Scognet case 0xda: return ("GET_MEDIA_STATUS"); 130129198Scognet case 0xde: return ("MEDIA_LOCK"); 131129198Scognet case 0xdf: return ("MEDIA_UNLOCK"); 132129198Scognet case 0xe0: return ("STANDBY_IMMEDIATE"); 133129198Scognet case 0xe1: return ("IDLE_IMMEDIATE"); 134129198Scognet case 0xe2: return ("STANDBY"); 135129198Scognet case 0xe3: return ("IDLE"); 136129198Scognet case 0xe4: return ("READ_BUFFER/PM"); 137129198Scognet case 0xe5: return ("CHECK_POWER_MODE"); 138129198Scognet case 0xe6: return ("SLEEP"); 139262420Sian case 0xe7: return ("FLUSHCACHE"); 140129198Scognet case 0xe8: return ("WRITE_PM"); 141129198Scognet case 0xea: return ("FLUSHCACHE48"); 142171618Scognet case 0xec: return ("ATA_IDENTIFY"); 143171618Scognet case 0xed: return ("MEDIA_EJECT"); 144171618Scognet case 0xef: 145171618Scognet switch (cmd->features) { 146265870Sian case 0x03: return ("SETFEATURES SET TRANSFER MODE"); 147129198Scognet case 0x02: return ("SETFEATURES ENABLE WCACHE"); 148129198Scognet case 0x82: return ("SETFEATURES DISABLE WCACHE"); 149129198Scognet case 0xaa: return ("SETFEATURES ENABLE RCACHE"); 150129198Scognet case 0x55: return ("SETFEATURES DISABLE RCACHE"); 151129198Scognet } 152129198Scognet return "SETFEATURES"; 153129198Scognet case 0xf1: return ("SECURITY_SET_PASSWORD"); 154129198Scognet case 0xf2: return ("SECURITY_UNLOCK"); 155129198Scognet case 0xf3: return ("SECURITY_ERASE_PREPARE"); 156129198Scognet case 0xf4: return ("SECURITY_ERASE_UNIT"); 157129198Scognet case 0xf5: return ("SECURITY_FREE_LOCK"); 158280823Sandrew case 0xf6: return ("SECURITY DISABLE PASSWORD"); 159129198Scognet case 0xf8: return ("READ_NATIVE_MAX_ADDRESS"); 160129198Scognet case 0xf9: return ("SET_MAX_ADDRESS"); 161129198Scognet } 162129198Scognet return "UNKNOWN"; 163129198Scognet} 164295319Smmel 165129198Scognetchar * 166295319Smmelata_cmd_string(struct ata_cmd *cmd, char *cmd_string, size_t len) 167129198Scognet{ 168129198Scognet 169295319Smmel snprintf(cmd_string, len, "%02x %02x %02x %02x " 170129198Scognet "%02x %02x %02x %02x %02x %02x %02x %02x", 171129198Scognet cmd->command, cmd->features, 172129198Scognet cmd->lba_low, cmd->lba_mid, cmd->lba_high, cmd->device, 173129198Scognet cmd->lba_low_exp, cmd->lba_mid_exp, cmd->lba_high_exp, 174129198Scognet cmd->features_exp, cmd->sector_count, cmd->sector_count_exp); 175129198Scognet 176129198Scognet return(cmd_string); 177129198Scognet} 178129198Scognet 179129198Scognetchar * 180129198Scognetata_res_string(struct ata_res *res, char *res_string, size_t len) 181129198Scognet{ 182129198Scognet 183129198Scognet snprintf(res_string, len, "%02x %02x %02x %02x " 184262420Sian "%02x %02x %02x %02x %02x %02x %02x", 185129198Scognet res->status, res->error, 186129198Scognet res->lba_low, res->lba_mid, res->lba_high, res->device, 187295319Smmel res->lba_low_exp, res->lba_mid_exp, res->lba_high_exp, 188171618Scognet res->sector_count, res->sector_count_exp); 189171618Scognet 190171618Scognet return(res_string); 191171618Scognet} 192265870Sian 193129198Scognet/* 194295319Smmel * ata_command_sbuf() returns 0 for success and -1 for failure. 195129198Scognet */ 196295319Smmelint 197129198Scognetata_command_sbuf(struct ccb_ataio *ataio, struct sbuf *sb) 198129198Scognet{ 199280823Sandrew char cmd_str[(12 * 3) + 1]; 200129198Scognet 201129198Scognet sbuf_printf(sb, "%s. ACB: %s", 202129198Scognet ata_op_string(&ataio->cmd), 203129198Scognet ata_cmd_string(&ataio->cmd, cmd_str, sizeof(cmd_str))); 204129198Scognet 205129198Scognet return(0); 206295096Smmel} 207129198Scognet 208295096Smmel/* 209295096Smmel * ata_status_abuf() returns 0 for success and -1 for failure. 210295096Smmel */ 211295252Smmelint 212239268Sgonzoata_status_sbuf(struct ccb_ataio *ataio, struct sbuf *sb) 213129198Scognet{ 214280842Sandrew 215280823Sandrew sbuf_printf(sb, "ATA status: %02x (%s%s%s%s%s%s%s%s)", 216201468Srpaulo ataio->res.status, 217201468Srpaulo (ataio->res.status & 0x80) ? "BSY " : "", 218201468Srpaulo (ataio->res.status & 0x40) ? "DRDY " : "", 219201468Srpaulo (ataio->res.status & 0x20) ? "DF " : "", 220201468Srpaulo (ataio->res.status & 0x10) ? "SERV " : "", 221201468Srpaulo (ataio->res.status & 0x08) ? "DRQ " : "", 222201468Srpaulo (ataio->res.status & 0x04) ? "CORR " : "", 223201468Srpaulo (ataio->res.status & 0x02) ? "IDX " : "", 224201468Srpaulo (ataio->res.status & 0x01) ? "ERR" : ""); 225201468Srpaulo if (ataio->res.status & 1) { 226201468Srpaulo sbuf_printf(sb, ", error: %02x (%s%s%s%s%s%s%s%s)", 227201468Srpaulo ataio->res.error, 228201468Srpaulo (ataio->res.error & 0x80) ? "ICRC " : "", 229201468Srpaulo (ataio->res.error & 0x40) ? "UNC " : "", 230201468Srpaulo (ataio->res.error & 0x20) ? "MC " : "", 231295149Smmel (ataio->res.error & 0x10) ? "IDNF " : "", 232129198Scognet (ataio->res.error & 0x08) ? "MCR " : "", 233129198Scognet (ataio->res.error & 0x04) ? "ABRT " : "", 234295149Smmel (ataio->res.error & 0x02) ? "NM " : "", 235295149Smmel (ataio->res.error & 0x01) ? "ILI" : ""); 236129198Scognet } 237295207Smmel 238167752Skevlo return(0); 239129198Scognet} 240167752Skevlo 241167752Skevlo/* 242167752Skevlo * ata_res_sbuf() returns 0 for success and -1 for failure. 243167752Skevlo */ 244129198Scognetint 245167752Skevloata_res_sbuf(struct ccb_ataio *ataio, struct sbuf *sb) 246167752Skevlo{ 247129198Scognet char res_str[(11 * 3) + 1]; 248280823Sandrew 249146948Scognet sbuf_printf(sb, "RES: %s", 250146948Scognet ata_res_string(&ataio->res, res_str, sizeof(res_str))); 251146948Scognet 252146948Scognet return(0); 253146948Scognet} 254129198Scognet 255129198Scognetvoid 256280809Sandrewata_print_ident(struct ata_params *ident_data) 257280823Sandrew{ 258129198Scognet char product[48], revision[16]; 259186933Sraj 260212825Smav cam_strvis(product, ident_data->model, sizeof(ident_data->model), 261186933Sraj sizeof(product)); 262186933Sraj cam_strvis(revision, ident_data->revision, sizeof(ident_data->revision), 263186933Sraj sizeof(revision)); 264186933Sraj printf("<%s %s> %s-%d", 265186933Sraj product, revision, 266183835Sraj (ident_data->config & ATA_PROTO_ATAPI) ? "ATAPI" : "ATA", 267186933Sraj ata_version(ident_data->version_major)); 268186933Sraj if (ident_data->satacapabilities && ident_data->satacapabilities != 0xffff) { 269186933Sraj if (ident_data->satacapabilities & ATA_SATA_GEN3) 270186933Sraj printf(" SATA 3.x"); 271129198Scognet else if (ident_data->satacapabilities & ATA_SATA_GEN2) 272129198Scognet printf(" SATA 2.x"); 273280813Sandrew else if (ident_data->satacapabilities & ATA_SATA_GEN1) 274239268Sgonzo printf(" SATA 1.x"); 275280813Sandrew else 276280813Sandrew printf(" SATA"); 277239268Sgonzo } 278239268Sgonzo printf(" device\n"); 279239268Sgonzo} 280239268Sgonzo 281239268Sgonzouint32_t 282262420Sianata_logical_sector_size(struct ata_params *ident_data) 283239268Sgonzo{ 284239268Sgonzo if ((ident_data->pss & 0xc000) == 0x4000 && 285239268Sgonzo (ident_data->pss & ATA_PSS_LSSABOVE512)) { 286239268Sgonzo return ((u_int32_t)ident_data->lss_1 | 287239268Sgonzo ((u_int32_t)ident_data->lss_2 << 16)); 288239268Sgonzo } 289280823Sandrew return (512); 290239268Sgonzo} 291239268Sgonzo 292239268Sgonzouint64_t 293239268Sgonzoata_physical_sector_size(struct ata_params *ident_data) 294239268Sgonzo{ 295239268Sgonzo if ((ident_data->pss & 0xc000) == 0x4000 && 296239268Sgonzo (ident_data->pss & ATA_PSS_MULTLS)) { 297280823Sandrew return ((uint64_t)ata_logical_sector_size(ident_data) * 298172738Simp (1 << (ident_data->pss & ATA_PSS_LSPPS))); 299280832Sandrew } 300280832Sandrew return (512); 301280832Sandrew} 302280832Sandrew 303172738Simpuint64_t 304280824Sandrewata_logical_sector_offset(struct ata_params *ident_data) 305280813Sandrew{ 306280813Sandrew if ((ident_data->lsalign & 0xc000) == 0x4000) { 307280813Sandrew return ((uint64_t)ata_logical_sector_size(ident_data) * 308280813Sandrew (ident_data->lsalign & 0x3fff)); 309280813Sandrew } 310280813Sandrew return (0); 311280813Sandrew} 312280813Sandrew 313280813Sandrewvoid 314280813Sandrewata_28bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint8_t features, 315280813Sandrew uint32_t lba, uint8_t sector_count) 316280813Sandrew{ 317280813Sandrew bzero(&ataio->cmd, sizeof(ataio->cmd)); 318280813Sandrew ataio->cmd.flags = 0; 319280813Sandrew if (cmd == ATA_READ_DMA || 320244480Sgonzo cmd == ATA_READ_DMA_QUEUED || 321244480Sgonzo cmd == ATA_WRITE_DMA || 322244480Sgonzo cmd == ATA_WRITE_DMA_QUEUED) 323244480Sgonzo ataio->cmd.flags |= CAM_ATAIO_DMA; 324244480Sgonzo ataio->cmd.command = cmd; 325280823Sandrew ataio->cmd.features = features; 326244480Sgonzo ataio->cmd.lba_low = lba; 327244480Sgonzo ataio->cmd.lba_mid = lba >> 8; 328244480Sgonzo ataio->cmd.lba_high = lba >> 16; 329280809Sandrew ataio->cmd.device = 0x40 | ((lba >> 24) & 0x0f); 330172738Simp ataio->cmd.sector_count = sector_count; 331172738Simp} 332172738Simp 333172738Simpvoid 334172738Simpata_48bit_cmd(struct ccb_ataio *ataio, uint8_t cmd, uint16_t features, 335172738Simp uint64_t lba, uint16_t sector_count) 336172738Simp{ 337172738Simp bzero(&ataio->cmd, sizeof(ataio->cmd)); 338172738Simp ataio->cmd.flags = CAM_ATAIO_48BIT; 339172738Simp if (cmd == ATA_READ_DMA48 || 340172738Simp cmd == ATA_READ_DMA_QUEUED48 || 341172738Simp cmd == ATA_READ_STREAM_DMA48 || 342172738Simp cmd == ATA_WRITE_DMA48 || 343280809Sandrew cmd == ATA_WRITE_DMA_FUA48 || 344280842Sandrew cmd == ATA_WRITE_DMA_QUEUED48 || 345207611Skevlo cmd == ATA_WRITE_DMA_QUEUED_FUA48 || 346295200Smmel cmd == ATA_WRITE_STREAM_DMA48 || 347236992Simp cmd == ATA_DATA_SET_MANAGEMENT) 348129198Scognet ataio->cmd.flags |= CAM_ATAIO_DMA; 349129198Scognet ataio->cmd.command = cmd; 350129198Scognet ataio->cmd.features = features; 351129198Scognet ataio->cmd.lba_low = lba; 352129198Scognet ataio->cmd.lba_mid = lba >> 8; 353262420Sian ataio->cmd.lba_high = lba >> 16; 354129198Scognet ataio->cmd.device = 0x40; 355129198Scognet ataio->cmd.lba_low_exp = lba >> 24; 356295200Smmel ataio->cmd.lba_mid_exp = lba >> 32; 357295200Smmel ataio->cmd.lba_high_exp = lba >> 40; 358129198Scognet ataio->cmd.features_exp = features >> 8; 359129198Scognet ataio->cmd.sector_count = sector_count; 360129198Scognet ataio->cmd.sector_count_exp = sector_count >> 8; 361129198Scognet} 362129198Scognet 363129198Scognetvoid 364129198Scognetata_ncq_cmd(struct ccb_ataio *ataio, uint8_t cmd, 365129198Scognet uint64_t lba, uint16_t sector_count) 366129198Scognet{ 367129198Scognet bzero(&ataio->cmd, sizeof(ataio->cmd)); 368129198Scognet ataio->cmd.flags = CAM_ATAIO_48BIT | CAM_ATAIO_FPDMA; 369129198Scognet ataio->cmd.command = cmd; 370129198Scognet ataio->cmd.features = sector_count; 371129198Scognet ataio->cmd.lba_low = lba; 372129198Scognet ataio->cmd.lba_mid = lba >> 8; 373129198Scognet ataio->cmd.lba_high = lba >> 16; 374129198Scognet ataio->cmd.device = 0x40; 375129198Scognet ataio->cmd.lba_low_exp = lba >> 24; 376129198Scognet ataio->cmd.lba_mid_exp = lba >> 32; 377129198Scognet ataio->cmd.lba_high_exp = lba >> 40; 378129198Scognet ataio->cmd.features_exp = sector_count >> 8; 379129198Scognet} 380129198Scognet 381129198Scognetvoid 382129198Scognetata_reset_cmd(struct ccb_ataio *ataio) 383129198Scognet{ 384129198Scognet bzero(&ataio->cmd, sizeof(ataio->cmd)); 385129198Scognet ataio->cmd.flags = CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT; 386129198Scognet ataio->cmd.control = 0x04; 387129198Scognet} 388129198Scognet 389129198Scognetvoid 390129198Scognetata_pm_read_cmd(struct ccb_ataio *ataio, int reg, int port) 391129198Scognet{ 392129198Scognet bzero(&ataio->cmd, sizeof(ataio->cmd)); 393129198Scognet ataio->cmd.flags = CAM_ATAIO_NEEDRESULT; 394280823Sandrew ataio->cmd.command = ATA_READ_PM; 395295200Smmel ataio->cmd.features = reg; 396129198Scognet ataio->cmd.device = port & 0x0f; 397164080Scognet} 398164080Scognet 399171618Scognetvoid 400171618Scognetata_pm_write_cmd(struct ccb_ataio *ataio, int reg, int port, uint32_t val) 401171618Scognet{ 402164080Scognet bzero(&ataio->cmd, sizeof(ataio->cmd)); 403164080Scognet ataio->cmd.flags = 0; 404171618Scognet ataio->cmd.command = ATA_WRITE_PM; 405164080Scognet ataio->cmd.features = reg; 406171618Scognet ataio->cmd.sector_count = val; 407171618Scognet ataio->cmd.lba_low = val >> 8; 408171618Scognet ataio->cmd.lba_mid = val >> 16; 409164080Scognet ataio->cmd.lba_high = val >> 24; 410171618Scognet ataio->cmd.device = port & 0x0f; 411164080Scognet} 412171618Scognet 413171618Scognetvoid 414171618Scognetata_bswap(int8_t *buf, int len) 415164080Scognet{ 416171618Scognet u_int16_t *ptr = (u_int16_t*)(buf + len); 417164080Scognet 418164080Scognet while (--ptr >= (u_int16_t*)buf) 419164080Scognet *ptr = be16toh(*ptr); 420164080Scognet} 421164080Scognet 422129198Scognetvoid 423129198Scognetata_btrim(int8_t *buf, int len) 424129198Scognet{ 425290661Smmel int8_t *ptr; 426290661Smmel 427290661Smmel for (ptr = buf; ptr < buf+len; ++ptr) 428290661Smmel if (!*ptr || *ptr == '_') 429290661Smmel *ptr = ' '; 430129198Scognet for (ptr = buf + len - 1; ptr >= buf && *ptr == ' '; --ptr) 431290661Smmel *ptr = 0; 432290661Smmel} 433129198Scognet 434290661Smmelvoid 435129198Scognetata_bpack(int8_t *src, int8_t *dst, int len) 436129198Scognet{ 437290661Smmel int i, j, blank; 438290661Smmel 439290661Smmel for (i = j = blank = 0 ; i < len; i++) { 440290661Smmel if (blank && src[i] == ' ') continue; 441129198Scognet if (blank && src[i] != ' ') { 442137226Scognet dst[j++] = src[i]; 443129198Scognet blank = 0; 444129198Scognet continue; 445129198Scognet } 446129198Scognet if (src[i] == ' ') { 447290661Smmel blank = 1; 448290661Smmel if (i == 0) 449290661Smmel continue; 450243576Smarcel } 451290661Smmel dst[j++] = src[i]; 452290661Smmel } 453129198Scognet while (j < len) 454290661Smmel dst[j++] = 0x00; 455290661Smmel} 456290661Smmel 457129198Scognetint 458290661Smmelata_max_pmode(struct ata_params *ap) 459290661Smmel{ 460129198Scognet if (ap->atavalid & ATA_FLAG_64_70) { 461290661Smmel if (ap->apiomodes & 0x02) 462290661Smmel return ATA_PIO4; 463290661Smmel if (ap->apiomodes & 0x01) 464290661Smmel return ATA_PIO3; 465290661Smmel } 466290661Smmel if (ap->mwdmamodes & 0x04) 467290661Smmel return ATA_PIO4; 468243576Smarcel if (ap->mwdmamodes & 0x02) 469243576Smarcel return ATA_PIO3; 470243576Smarcel if (ap->mwdmamodes & 0x01) 471243576Smarcel return ATA_PIO2; 472290661Smmel if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x200) 473243576Smarcel return ATA_PIO2; 474243576Smarcel if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x100) 475243576Smarcel return ATA_PIO1; 476243576Smarcel if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x000) 477243576Smarcel return ATA_PIO0; 478243576Smarcel return ATA_PIO0; 479243576Smarcel} 480243576Smarcel 481290661Smmelint 482243576Smarcelata_max_wmode(struct ata_params *ap) 483129198Scognet{ 484129198Scognet if (ap->mwdmamodes & 0x04) 485129198Scognet return ATA_WDMA2; 486129198Scognet if (ap->mwdmamodes & 0x02) 487129198Scognet return ATA_WDMA1; 488167752Skevlo if (ap->mwdmamodes & 0x01) 489167752Skevlo return ATA_WDMA0; 490129198Scognet return -1; 491129198Scognet} 492129198Scognet 493129198Scognetint 494129198Scognetata_max_umode(struct ata_params *ap) 495167752Skevlo{ 496129198Scognet if (ap->atavalid & ATA_FLAG_88) { 497129198Scognet if (ap->udmamodes & 0x40) 498129198Scognet return ATA_UDMA6; 499129198Scognet if (ap->udmamodes & 0x20) 500129198Scognet return ATA_UDMA5; 501167752Skevlo if (ap->udmamodes & 0x10) 502129198Scognet return ATA_UDMA4; 503129198Scognet if (ap->udmamodes & 0x08) 504129198Scognet return ATA_UDMA3; 505129198Scognet if (ap->udmamodes & 0x04) 506129198Scognet return ATA_UDMA2; 507129198Scognet if (ap->udmamodes & 0x02) 508129198Scognet return ATA_UDMA1; 509129198Scognet if (ap->udmamodes & 0x01) 510129198Scognet return ATA_UDMA0; 511129198Scognet } 512129198Scognet return -1; 513129198Scognet} 514236992Simp 515129198Scognetint 516129198Scognetata_max_mode(struct ata_params *ap, int maxmode) 517129198Scognet{ 518129198Scognet 519129198Scognet if (maxmode == 0) 520129198Scognet maxmode = ATA_DMA_MAX; 521129198Scognet if (maxmode >= ATA_UDMA0 && ata_max_umode(ap) > 0) 522239268Sgonzo return (min(maxmode, ata_max_umode(ap))); 523239268Sgonzo if (maxmode >= ATA_WDMA0 && ata_max_wmode(ap) > 0) 524239268Sgonzo return (min(maxmode, ata_max_wmode(ap))); 525239268Sgonzo return (min(maxmode, ata_max_pmode(ap))); 526129198Scognet} 527129198Scognet 528129198Scognetchar * 529129198Scognetata_mode2string(int mode) 530{ 531 switch (mode) { 532 case -1: return "UNSUPPORTED"; 533 case 0: return "NONE"; 534 case ATA_PIO0: return "PIO0"; 535 case ATA_PIO1: return "PIO1"; 536 case ATA_PIO2: return "PIO2"; 537 case ATA_PIO3: return "PIO3"; 538 case ATA_PIO4: return "PIO4"; 539 case ATA_WDMA0: return "WDMA0"; 540 case ATA_WDMA1: return "WDMA1"; 541 case ATA_WDMA2: return "WDMA2"; 542 case ATA_UDMA0: return "UDMA0"; 543 case ATA_UDMA1: return "UDMA1"; 544 case ATA_UDMA2: return "UDMA2"; 545 case ATA_UDMA3: return "UDMA3"; 546 case ATA_UDMA4: return "UDMA4"; 547 case ATA_UDMA5: return "UDMA5"; 548 case ATA_UDMA6: return "UDMA6"; 549 default: 550 if (mode & ATA_DMA_MASK) 551 return "BIOSDMA"; 552 else 553 return "BIOSPIO"; 554 } 555} 556 557int 558ata_string2mode(char *str) 559{ 560 if (!strcasecmp(str, "PIO0")) return (ATA_PIO0); 561 if (!strcasecmp(str, "PIO1")) return (ATA_PIO1); 562 if (!strcasecmp(str, "PIO2")) return (ATA_PIO2); 563 if (!strcasecmp(str, "PIO3")) return (ATA_PIO3); 564 if (!strcasecmp(str, "PIO4")) return (ATA_PIO4); 565 if (!strcasecmp(str, "WDMA0")) return (ATA_WDMA0); 566 if (!strcasecmp(str, "WDMA1")) return (ATA_WDMA1); 567 if (!strcasecmp(str, "WDMA2")) return (ATA_WDMA2); 568 if (!strcasecmp(str, "UDMA0")) return (ATA_UDMA0); 569 if (!strcasecmp(str, "UDMA16")) return (ATA_UDMA0); 570 if (!strcasecmp(str, "UDMA1")) return (ATA_UDMA1); 571 if (!strcasecmp(str, "UDMA25")) return (ATA_UDMA1); 572 if (!strcasecmp(str, "UDMA2")) return (ATA_UDMA2); 573 if (!strcasecmp(str, "UDMA33")) return (ATA_UDMA2); 574 if (!strcasecmp(str, "UDMA3")) return (ATA_UDMA3); 575 if (!strcasecmp(str, "UDMA44")) return (ATA_UDMA3); 576 if (!strcasecmp(str, "UDMA4")) return (ATA_UDMA4); 577 if (!strcasecmp(str, "UDMA66")) return (ATA_UDMA4); 578 if (!strcasecmp(str, "UDMA5")) return (ATA_UDMA5); 579 if (!strcasecmp(str, "UDMA100")) return (ATA_UDMA5); 580 if (!strcasecmp(str, "UDMA6")) return (ATA_UDMA6); 581 if (!strcasecmp(str, "UDMA133")) return (ATA_UDMA6); 582 return (-1); 583} 584 585 586u_int 587ata_mode2speed(int mode) 588{ 589 switch (mode) { 590 case ATA_PIO0: 591 default: 592 return (3300); 593 case ATA_PIO1: 594 return (5200); 595 case ATA_PIO2: 596 return (8300); 597 case ATA_PIO3: 598 return (11100); 599 case ATA_PIO4: 600 return (16700); 601 case ATA_WDMA0: 602 return (4200); 603 case ATA_WDMA1: 604 return (13300); 605 case ATA_WDMA2: 606 return (16700); 607 case ATA_UDMA0: 608 return (16700); 609 case ATA_UDMA1: 610 return (25000); 611 case ATA_UDMA2: 612 return (33300); 613 case ATA_UDMA3: 614 return (44400); 615 case ATA_UDMA4: 616 return (66700); 617 case ATA_UDMA5: 618 return (100000); 619 case ATA_UDMA6: 620 return (133000); 621 } 622} 623 624u_int 625ata_revision2speed(int revision) 626{ 627 switch (revision) { 628 case 1: 629 default: 630 return (150000); 631 case 2: 632 return (300000); 633 case 3: 634 return (600000); 635 } 636} 637 638int 639ata_speed2revision(u_int speed) 640{ 641 switch (speed) { 642 case 0: 643 return (0); 644 case 150000: 645 return (1); 646 case 300000: 647 return (2); 648 case 600000: 649 return (3); 650 default: 651 return (-1); 652 } 653} 654 655int 656ata_identify_match(caddr_t identbuffer, caddr_t table_entry) 657{ 658 struct scsi_inquiry_pattern *entry; 659 struct ata_params *ident; 660 661 entry = (struct scsi_inquiry_pattern *)table_entry; 662 ident = (struct ata_params *)identbuffer; 663 664 if ((cam_strmatch(ident->model, entry->product, 665 sizeof(ident->model)) == 0) 666 && (cam_strmatch(ident->revision, entry->revision, 667 sizeof(ident->revision)) == 0)) { 668 return (0); 669 } 670 return (-1); 671} 672 673int 674ata_static_identify_match(caddr_t identbuffer, caddr_t table_entry) 675{ 676 struct scsi_static_inquiry_pattern *entry; 677 struct ata_params *ident; 678 679 entry = (struct scsi_static_inquiry_pattern *)table_entry; 680 ident = (struct ata_params *)identbuffer; 681 682 if ((cam_strmatch(ident->model, entry->product, 683 sizeof(ident->model)) == 0) 684 && (cam_strmatch(ident->revision, entry->revision, 685 sizeof(ident->revision)) == 0)) { 686 return (0); 687 } 688 return (-1); 689} 690