| 1 | /* |
| 2 | * Copyright (c) 2007 David Gwynne <dlg@openbsd.org> |
| 3 | * |
| 4 | * Permission to use, copy, modify, and distribute this software for any |
| 5 | * purpose with or without fee is hereby granted, provided that the above |
| 6 | * copyright notice and this permission notice appear in all copies. |
| 7 | * |
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 15 | * |
| 16 | * $OpenBSD: atascsi.h,v 1.33 2009/02/16 21:19:06 miod Exp $ |
| 17 | */ |
| 18 | |
| 19 | struct atascsi; |
| 20 | struct scsi_link; |
| 21 | |
| 22 | /* |
| 23 | * ATA commands |
| 24 | */ |
| 25 | |
| 26 | #define ATA_C_SATA_FEATURE_ENA 0x10 |
| 27 | #define ATA_C_READDMA_EXT 0x25 |
| 28 | #define ATA_C_READ_LOG_EXT 0x2f |
| 29 | #define ATA_C_WRITEDMA_EXT 0x35 |
| 30 | #define ATA_C_READ_FPDMA 0x60 |
| 31 | #define ATA_C_WRITE_FPDMA 0x61 |
| 32 | #define ATA_C_SATA_FEATURE_DIS 0x90 |
| 33 | #define ATA_C_PACKET 0xa0 |
| 34 | #define ATA_C_ATAPI_IDENTIFY 0xa1 |
| 35 | #define ATA_C_READDMA 0xc8 |
| 36 | #define ATA_C_WRITEDMA 0xca |
| 37 | #define ATA_C_READ_PM 0xe4 |
| 38 | #define ATA_C_WRITE_PM 0xe8 |
| 39 | #define ATA_C_FLUSH_CACHE 0xe7 |
| 40 | #define ATA_C_FLUSH_CACHE_EXT 0xea /* lba48 */ |
| 41 | #define ATA_C_IDENTIFY 0xec |
| 42 | #define ATA_C_SET_FEATURES 0xef |
| 43 | #define ATA_C_SEC_FREEZE_LOCK 0xf5 |
| 44 | |
| 45 | /* |
| 46 | * ATA SATA FEATURES subcommands |
| 47 | */ |
| 48 | #define ATA_SATAFT_NONZDMA 0x01 /* DMA non-zero buffer offset */ |
| 49 | #define ATA_SATAFT_DMAAAOPT 0x02 /* DMA AA optimization */ |
| 50 | #define ATA_SATAFT_DEVIPS 0x03 /* Device-initiated pwr state*/ |
| 51 | #define ATA_SATAFT_INORDER 0x04 /* in-order data delivery */ |
| 52 | #define ATA_SATAFT_ASYNCNOTIFY 0x05 /* Async notification */ |
| 53 | |
| 54 | /* |
| 55 | * ATA SET FEATURES subcommands |
| 56 | */ |
| 57 | #define ATA_SF_WRITECACHE_EN 0x02 |
| 58 | #define ATA_SF_LOOKAHEAD_EN 0xaa |
| 59 | |
| 60 | struct ata_identify { |
| 61 | u_int16_t config; /* 0 */ |
| 62 | u_int16_t ncyls; /* 1 */ |
| 63 | u_int16_t reserved1; /* 2 */ |
| 64 | u_int16_t nheads; /* 3 */ |
| 65 | u_int16_t track_size; /* 4 */ |
| 66 | u_int16_t sector_size; /* 5 */ |
| 67 | u_int16_t nsectors; /* 6 */ |
| 68 | u_int16_t reserved2[3]; /* 7 vendor unique */ |
| 69 | u_int8_t serial[20]; /* 10 */ |
| 70 | u_int16_t buffer_type; /* 20 */ |
| 71 | u_int16_t buffer_size; /* 21 */ |
| 72 | u_int16_t ecc; /* 22 */ |
| 73 | u_int8_t firmware[8]; /* 23 */ |
| 74 | u_int8_t model[40]; /* 27 */ |
| 75 | u_int16_t multi; /* 47 */ |
| 76 | u_int16_t dwcap; /* 48 */ |
| 77 | u_int16_t cap; /* 49 */ |
| 78 | u_int16_t reserved3; /* 50 */ |
| 79 | u_int16_t piomode; /* 51 */ |
| 80 | u_int16_t dmamode; /* 52 */ |
| 81 | u_int16_t validinfo; /* 53 */ |
| 82 | u_int16_t curcyls; /* 54 */ |
| 83 | u_int16_t curheads; /* 55 */ |
| 84 | u_int16_t cursectrk; /* 56 */ |
| 85 | u_int16_t curseccp[2]; /* 57 */ |
| 86 | u_int16_t mult2; /* 59 */ |
| 87 | u_int16_t addrsec[2]; /* 60 */ |
| 88 | u_int16_t worddma; /* 62 */ |
| 89 | u_int16_t dworddma; /* 63 */ |
| 90 | u_int16_t advpiomode; /* 64 */ |
| 91 | u_int16_t minmwdma; /* 65 */ |
| 92 | u_int16_t recmwdma; /* 66 */ |
| 93 | u_int16_t minpio; /* 67 */ |
| 94 | u_int16_t minpioflow; /* 68 */ |
| 95 | u_int16_t reserved4[2]; /* 69 */ |
| 96 | u_int16_t typtime[2]; /* 71 */ |
| 97 | u_int16_t reserved5[2]; /* 73 */ |
| 98 | u_int16_t qdepth; /* 75 */ |
| 99 | u_int16_t satacap; /* 76 */ |
| 100 | u_int16_t reserved6; /* 77 */ |
| 101 | u_int16_t satafsup; /* 78 */ |
| 102 | u_int16_t satafen; /* 79 */ |
| 103 | u_int16_t majver; /* 80 */ |
| 104 | u_int16_t minver; /* 81 */ |
| 105 | u_int16_t cmdset82; /* 82 */ |
| 106 | u_int16_t cmdset83; /* 83 */ |
| 107 | u_int16_t cmdset84; /* 84 */ |
| 108 | u_int16_t features85; /* 85 */ |
| 109 | u_int16_t features86; /* 86 */ |
| 110 | u_int16_t features87; /* 87 */ |
| 111 | #define ATA_ID_F87_WWN (1<<8) |
| 112 | u_int16_t ultradma; /* 88 */ |
| 113 | u_int16_t erasetime; /* 89 */ |
| 114 | u_int16_t erasetimex; /* 90 */ |
| 115 | u_int16_t apm; /* 91 */ |
| 116 | u_int16_t masterpw; /* 92 */ |
| 117 | u_int16_t hwreset; /* 93 */ |
| 118 | u_int16_t acoustic; /* 94 */ |
| 119 | u_int16_t stream_min; /* 95 */ |
| 120 | u_int16_t stream_xfer_d; /* 96 */ |
| 121 | u_int16_t stream_lat; /* 97 */ |
| 122 | u_int16_t streamperf[2]; /* 98 */ |
| 123 | u_int16_t addrsecxt[4]; /* 100 */ |
| 124 | u_int16_t stream_xfer_p; /* 104 */ |
| 125 | u_int16_t padding1; /* 105 */ |
| 126 | u_int16_t phys_sect_sz; /* 106 */ |
| 127 | u_int16_t seek_delay; /* 107 */ |
| 128 | u_int16_t naa_ieee_oui; /* 108 */ |
| 129 | u_int16_t ieee_oui_uid; /* 109 */ |
| 130 | u_int16_t uid_mid; /* 110 */ |
| 131 | u_int16_t uid_low; /* 111 */ |
| 132 | u_int16_t resv_wwn[4]; /* 112 */ |
| 133 | u_int16_t incits; /* 116 */ |
| 134 | u_int16_t words_lsec[2]; /* 117 */ |
| 135 | u_int16_t cmdset119; /* 119 */ |
| 136 | u_int16_t features120; /* 120 */ |
| 137 | u_int16_t padding2[6]; |
| 138 | u_int16_t rmsn; /* 127 */ |
| 139 | u_int16_t securestatus; /* 128 */ |
| 140 | #define ATA_SECURE_LOCKED (1<<2) |
| 141 | #define ATA_SECURE_FROZEN (1<<3) |
| 142 | u_int16_t vendor[31]; /* 129 */ |
| 143 | u_int16_t padding3[16]; /* 160 */ |
| 144 | u_int16_t curmedser[30]; /* 176 */ |
| 145 | u_int16_t sctsupport; /* 206 */ |
| 146 | u_int16_t padding4[48]; /* 207 */ |
| 147 | u_int16_t integrity; /* 255 */ |
| 148 | } __packed; |
| 149 | |
| 150 | /* |
| 151 | * IDENTIFY DEVICE data |
| 152 | */ |
| 153 | #define ATA_IDENTIFY_SECURITY (1 << 1) |
| 154 | #define ATA_IDENTIFY_WRITECACHE (1 << 5) |
| 155 | #define ATA_IDENTIFY_LOOKAHEAD (1 << 6) |
| 156 | |
| 157 | /* |
| 158 | * Frame Information Structures |
| 159 | */ |
| 160 | |
| 161 | #define ATA_FIS_LENGTH 20 |
| 162 | |
| 163 | struct ata_fis_h2d { |
| 164 | u_int8_t type; |
| 165 | #define ATA_FIS_TYPE_H2D 0x27 |
| 166 | u_int8_t flags; |
| 167 | #define ATA_H2D_FLAGS_CMD (1<<7) |
| 168 | u_int8_t command; |
| 169 | u_int8_t features; |
| 170 | #define ATA_H2D_FEATURES_DMA (1<<0) |
| 171 | #define ATA_H2D_FEATURES_DIR (1<<2) |
| 172 | #define ATA_H2D_FEATURES_DIR_READ (1<<2) |
| 173 | #define ATA_H2D_FEATURES_DIR_WRITE (0<<2) |
| 174 | |
| 175 | u_int8_t lba_low; |
| 176 | u_int8_t lba_mid; |
| 177 | u_int8_t lba_high; |
| 178 | u_int8_t device; |
| 179 | #define ATA_H2D_DEVICE_LBA 0x40 |
| 180 | |
| 181 | u_int8_t lba_low_exp; |
| 182 | u_int8_t lba_mid_exp; |
| 183 | u_int8_t lba_high_exp; |
| 184 | u_int8_t features_exp; |
| 185 | |
| 186 | u_int8_t sector_count; |
| 187 | u_int8_t sector_count_exp; |
| 188 | u_int8_t reserved0; |
| 189 | u_int8_t control; |
| 190 | #define ATA_FIS_CONTROL_SRST 0x04 |
| 191 | #define ATA_FIS_CONTROL_4BIT 0x08 |
| 192 | |
| 193 | u_int8_t reserved1; |
| 194 | u_int8_t reserved2; |
| 195 | u_int8_t reserved3; |
| 196 | u_int8_t reserved4; |
| 197 | } __packed; |
| 198 | |
| 199 | struct ata_fis_d2h { |
| 200 | u_int8_t type; |
| 201 | #define ATA_FIS_TYPE_D2H 0x34 |
| 202 | u_int8_t flags; |
| 203 | #define ATA_D2H_FLAGS_INTR (1<<6) |
| 204 | u_int8_t status; |
| 205 | u_int8_t error; |
| 206 | |
| 207 | u_int8_t lba_low; |
| 208 | u_int8_t lba_mid; |
| 209 | u_int8_t lba_high; |
| 210 | u_int8_t device; |
| 211 | |
| 212 | u_int8_t lba_low_exp; |
| 213 | u_int8_t lba_mid_exp; |
| 214 | u_int8_t lba_high_exp; |
| 215 | u_int8_t reserved0; |
| 216 | |
| 217 | u_int8_t sector_count; |
| 218 | u_int8_t sector_count_exp; |
| 219 | u_int8_t reserved1; |
| 220 | u_int8_t reserved2; |
| 221 | |
| 222 | u_int8_t reserved3; |
| 223 | u_int8_t reserved4; |
| 224 | u_int8_t reserved5; |
| 225 | u_int8_t reserved6; |
| 226 | } __packed; |
| 227 | |
| 228 | /* |
| 229 | * SATA log page 10h - |
| 230 | * looks like a D2H FIS, with errored tag number in first byte. |
| 231 | */ |
| 232 | struct ata_log_page_10h { |
| 233 | struct ata_fis_d2h err_regs; |
| 234 | #define ATA_LOG_10H_TYPE_NOTQUEUED 0x80 |
| 235 | #define ATA_LOG_10H_TYPE_TAG_MASK 0x1f |
| 236 | u_int8_t reserved[256 - sizeof(struct ata_fis_d2h)]; |
| 237 | u_int8_t vendor_specific[255]; |
| 238 | u_int8_t checksum; |
| 239 | } __packed; |
| 240 | |
| 241 | /* |
| 242 | * SATA registers |
| 243 | */ |
| 244 | |
| 245 | #define SATA_SStatus_DET 0x00f |
| 246 | #define SATA_SStatus_DET_NODEV 0x000 |
| 247 | #define SATA_SStatus_DET_NOPHY 0x001 |
| 248 | #define SATA_SStatus_DET_DEV 0x003 |
| 249 | #define SATA_SStatus_DET_OFFLINE 0x008 |
| 250 | |
| 251 | #define SATA_SStatus_SPD 0x0f0 |
| 252 | #define SATA_SStatus_SPD_NONE 0x000 |
| 253 | #define SATA_SStatus_SPD_1_5 0x010 |
| 254 | #define SATA_SStatus_SPD_3_0 0x020 |
| 255 | |
| 256 | #define SATA_SStatus_IPM 0xf00 |
| 257 | #define SATA_SStatus_IPM_NODEV 0x000 |
| 258 | #define SATA_SStatus_IPM_ACTIVE 0x100 |
| 259 | #define SATA_SStatus_IPM_PARTIAL 0x200 |
| 260 | #define SATA_SStatus_IPM_SLUMBER 0x600 |
| 261 | |
| 262 | #define SATA_SIGNATURE_PORT_MULTIPLIER 0x96690101 |
| 263 | #define SATA_SIGNATURE_ATAPI 0xeb140101 |
| 264 | #define SATA_SIGNATURE_DISK 0x00000101 |
| 265 | |
| 266 | /* |
| 267 | * ATA interface |
| 268 | */ |
| 269 | |
| 270 | struct ahci_port; |
| 271 | |
| 272 | struct ata_port { |
| 273 | struct ata_identify at_identify; /* only if ATA_PORT_T_DISK */ |
| 274 | struct ahci_port *at_ahci_port; |
| 275 | int at_type; |
| 276 | #define ATA_PORT_T_NONE 0 |
| 277 | #define ATA_PORT_T_DISK 1 |
| 278 | #define ATA_PORT_T_ATAPI 2 |
| 279 | #define ATA_PORT_T_PM 3 |
| 280 | int at_features; |
| 281 | #define ATA_PORT_F_WCACHE (1 << 0) |
| 282 | #define ATA_PORT_F_RAHEAD (1 << 1) |
| 283 | #define ATA_PORT_F_FRZLCK (1 << 2) |
| 284 | #define ATA_PORT_F_RESCAN (1 << 3) /* re-check on bus scan */ |
| 285 | int at_probe; |
| 286 | #define ATA_PROBE_NEED_INIT 0 |
| 287 | #define ATA_PROBE_NEED_HARD_RESET 1 |
| 288 | #define ATA_PROBE_NEED_SOFT_RESET 2 |
| 289 | #define ATA_PROBE_NEED_IDENT 3 |
| 290 | #define ATA_PROBE_GOOD 4 |
| 291 | #define ATA_PROBE_FAILED 7 |
| 292 | int at_ncqdepth; |
| 293 | u_int64_t at_capacity; /* only if ATA_PORT_T_DISK */ |
| 294 | int at_target; /* port multiplier port */ |
| 295 | char at_name[16]; |
| 296 | }; |
| 297 | |
| 298 | struct ata_xfer { |
| 299 | struct ata_fis_h2d *fis; |
| 300 | struct ata_fis_d2h rfis; |
| 301 | u_int8_t *packetcmd; |
| 302 | u_int8_t tag; |
| 303 | |
| 304 | void *data; |
| 305 | size_t datalen; |
| 306 | size_t resid; |
| 307 | |
| 308 | void (*complete)(struct ata_xfer *); |
| 309 | u_int timeout; |
| 310 | |
| 311 | int flags; |
| 312 | #define ATA_F_READ (1<<0) |
| 313 | #define ATA_F_WRITE (1<<1) |
| 314 | #define ATA_F_NOWAIT (1<<2) |
| 315 | #define ATA_F_POLL (1<<3) |
| 316 | #define ATA_F_PIO (1<<4) |
| 317 | #define ATA_F_PACKET (1<<5) |
| 318 | #define ATA_F_NCQ (1<<6) |
| 319 | #define ATA_F_TIMEOUT_RUNNING (1<<7) |
| 320 | #define ATA_F_TIMEOUT_DESIRED (1<<8) |
| 321 | #define ATA_F_TIMEOUT_EXPIRED (1<<9) |
| 322 | #define ATA_F_AUTOSENSE (1<<10) |
| 323 | #define ATA_F_EXCLUSIVE (1<<11) |
| 324 | #define ATA_FMT_FLAGS "\020" \ |
| 325 | "\014EXCLUSIVE" \ |
| 326 | "\013AUTOSENSE" \ |
| 327 | "\012EXPIRED" \ |
| 328 | "\011DESIRED" "\010TRUNNING" \ |
| 329 | "\007NCQ" "\006PACKET" \ |
| 330 | "\005PIO" "\004POLL" "\003NOWAIT" \ |
| 331 | "\002WRITE" "\001READ" |
| 332 | |
| 333 | volatile int state; |
| 334 | #define ATA_S_SETUP 0 |
| 335 | #define ATA_S_PENDING 1 |
| 336 | #define ATA_S_COMPLETE 2 |
| 337 | #define ATA_S_ERROR 3 |
| 338 | #define ATA_S_TIMEOUT 4 |
| 339 | #define ATA_S_ONCHIP 5 |
| 340 | #define ATA_S_PUT 6 |
| 341 | |
| 342 | void *atascsi_private; |
| 343 | struct ata_port *at; /* NULL if direct-attached */ |
| 344 | }; |
| 345 | |