1 /*- 2 * Copyright (c) 1999 Michael Smith 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 #define MLX_CFG_BASE0 0x10 /* first region */ 30 #define MLX_CFG_BASE1 0x14 /* second region (type 3 only) */ 31 32 #define MLX_BLKSIZE 512 /* fixed feature */ 33 34 /* 35 * Selected command codes. 36 */ 37 #define MLX_CMD_ENQUIRY 0x53 38 #define MLX_CMD_ENQUIRY2 0x1c 39 #define MLX_CMD_ENQSYSDRIVE 0x19 40 #define MLX_CMD_READOLDSG 0xb6 41 #define MLX_CMD_WRITEOLDSG 0xb7 42 #define MLX_CMD_FLUSH 0x0a 43 #define MLX_CMD_LOGOP 0x72 44 #define MLX_CMD_REBUILDASYNC 0x16 45 #define MLX_CMD_CHECKASYNC 0x1e 46 #define MLX_CMD_REBUILDSTAT 0x0c 47 #define MLX_CMD_STOPCHANNEL 0x13 48 #define MLX_CMD_STARTCHANNEL 0x12 49 50 /* 51 * Status values. 52 */ 53 #define MLX_STATUS_OK 0x0000 54 #define MLX_STATUS_RDWROFFLINE 0x0002 /* read/write claims drive is offline */ 55 #define MLX_STATUS_WEDGED 0xdead /* controller not listening */ 56 #define MLX_STATUS_LOST 0xbeef /* never came back */ 57 #define MLX_STATUS_BUSY 0xffff /* command is in controller */ 58 59 /* 60 * Accessor defines for the V3 interface. 61 */ 62 #define MLX_V3_MAILBOX 0x00 63 #define MLX_V3_STATUS_IDENT 0x0d 64 #define MLX_V3_STATUS 0x0e 65 #define MLX_V3_IDBR 0x40 66 #define MLX_V3_ODBR 0x41 67 #define MLX_V3_IER 0x43 68 69 #define MLX_V3_PUT_MAILBOX(sc, idx, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_MAILBOX + idx, val) 70 #define MLX_V3_GET_STATUS_IDENT(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_STATUS_IDENT) 71 #define MLX_V3_GET_STATUS(sc) bus_space_read_2 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_STATUS) 72 #define MLX_V3_GET_IDBR(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_IDBR) 73 #define MLX_V3_PUT_IDBR(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_IDBR, val) 74 #define MLX_V3_GET_ODBR(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V3_ODBR) 75 #define MLX_V3_PUT_ODBR(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_ODBR, val) 76 #define MLX_V3_PUT_IER(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V3_IER, val) 77 78 #define MLX_V3_IDB_FULL (1<<0) /* mailbox is full */ 79 #define MLX_V3_IDB_SACK (1<<1) /* acknowledge status read */ 80 81 #define MLX_V3_ODB_SAVAIL (1<<0) /* status is available */ 82 83 /* 84 * Accessor defines for the V4 interface. 85 */ 86 #define MLX_V4_MAILBOX 0x1000 87 #define MLX_V4_STATUS_IDENT 0x1018 88 #define MLX_V4_STATUS 0x101a 89 #define MLX_V4_IDBR 0x0020 90 #define MLX_V4_ODBR 0x002c 91 #define MLX_V4_IER 0x0034 92 93 /* use longword access? */ 94 #define MLX_V4_PUT_MAILBOX(sc, idx, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_MAILBOX + idx, val) 95 #define MLX_V4_GET_STATUS_IDENT(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_STATUS_IDENT) 96 #define MLX_V4_GET_STATUS(sc) bus_space_read_2 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_STATUS) 97 #define MLX_V4_GET_IDBR(sc) bus_space_read_4 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_IDBR) 98 #define MLX_V4_PUT_IDBR(sc, val) bus_space_write_4(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_IDBR, val) 99 #define MLX_V4_GET_ODBR(sc) bus_space_read_4 (sc->mlx_btag, sc->mlx_bhandle, MLX_V4_ODBR) 100 #define MLX_V4_PUT_ODBR(sc, val) bus_space_write_4(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_ODBR, val) 101 #define MLX_V4_PUT_IER(sc, val) bus_space_write_4(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_IER, val) 102 103 #define MLX_V4_IDB_FULL (1<<0) /* mailbox is full */ 104 105 #define MLX_V4_IDB_HWMBOX_CMD (1<<0) /* posted hardware mailbox command */ 106 #define MLX_V4_IDB_SACK (1<<1) /* acknowledge status read */ 107 #define MLX_V4_IDB_MEMMBOX_CMD (1<<4) /* posted memory mailbox command */ 108 109 #define MLX_V4_ODB_HWSAVAIL (1<<0) /* status is available for hardware mailbox */ 110 #define MLX_V4_ODB_MEMSAVAIL (1<<1) /* status is available for memory mailbox */ 111 112 #define MLX_V4_ODB_HWMBOX_ACK (1<<0) /* ack status read from hardware mailbox */ 113 #define MLX_V4_ODB_MEMMBOX_ACK (1<<1) /* ack status read from memory mailbox */ 114 115 #define MLX_V4_IER_MASK 0xfb /* message unit interrupt mask */ 116 #define MLX_V4_IER_DISINT (1<<2) /* interrupt disable bit */ 117 118 /* 119 * Accessor defines for the V5 interface 120 */ 121 #define MLX_V5_MAILBOX 0x50 122 #define MLX_V5_STATUS_IDENT 0x5d 123 #define MLX_V5_STATUS 0x5e 124 #define MLX_V5_IDBR 0x60 125 #define MLX_V5_ODBR 0x61 126 #define MLX_V5_IER 0x34 127 128 #define MLX_V5_PUT_MAILBOX(sc, idx, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_MAILBOX + idx, val) 129 #define MLX_V5_GET_STATUS_IDENT(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_STATUS_IDENT) 130 #define MLX_V5_GET_STATUS(sc) bus_space_read_2 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_STATUS) 131 #define MLX_V5_GET_IDBR(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_IDBR) 132 #define MLX_V5_PUT_IDBR(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_IDBR, val) 133 #define MLX_V5_GET_ODBR(sc) bus_space_read_1 (sc->mlx_btag, sc->mlx_bhandle, MLX_V5_ODBR) 134 #define MLX_V5_PUT_ODBR(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_ODBR, val) 135 #define MLX_V5_PUT_IER(sc, val) bus_space_write_1(sc->mlx_btag, sc->mlx_bhandle, MLX_V5_IER, val) 136 137 #define MLX_V5_IDB_EMPTY (1<<0) /* mailbox is empty */ 138 139 #define MLX_V5_IDB_HWMBOX_CMD (1<<0) /* posted hardware mailbox command */ 140 #define MLX_V5_IDB_SACK (1<<1) /* acknowledge status read */ 141 #define MLX_V5_IDB_MEMMBOX_CMD (1<<4) /* posted memory mailbox command */ 142 143 #define MLX_V5_ODB_HWSAVAIL (1<<0) /* status is available for hardware mailbox */ 144 #define MLX_V5_ODB_MEMSAVAIL (1<<1) /* status is available for memory mailbox */ 145 146 #define MLX_V5_ODB_HWMBOX_ACK (1<<0) /* ack status read from hardware mailbox */ 147 #define MLX_V5_ODB_MEMMBOX_ACK (1<<1) /* ack status read from memory mailbox */ 148 149 #define MLX_V5_IER_DISINT (1<<2) /* interrupt disable bit */ 150 151 152 /* 153 * Scatter-gather list format, type 1, kind 00. 154 */ 155 struct mlx_sgentry 156 { 157 u_int32_t sg_addr; 158 u_int32_t sg_count; 159 } __attribute__ ((packed)); 160 161 /* 162 * Command result buffers, as placed in system memory by the controller. 163 */ 164 struct mlx_enquiry /* MLX_CMD_ENQUIRY */ 165 { 166 u_int8_t me_num_sys_drvs; 167 u_int8_t res1[3]; 168 u_int32_t me_drvsize[32]; 169 u_int16_t me_flash_age; 170 u_int8_t me_status_flags; 171 #define MLX_ENQ_SFLAG_DEFWRERR (1<<0) /* deferred write error indicator */ 172 #define MLX_ENQ_SFLAG_BATTLOW (1<<1) /* battery low */ 173 u_int8_t res2; 174 u_int8_t me_fwminor; 175 u_int8_t me_fwmajor; 176 u_int8_t me_rebuild_flag; 177 u_int8_t me_max_commands; 178 u_int8_t me_offline_sd_count; 179 u_int8_t res3; 180 u_int16_t me_event_log_seq_num; 181 u_int8_t me_critical_sd_count; 182 u_int8_t res4[3]; 183 u_int8_t me_dead_count; 184 u_int8_t res5; 185 u_int8_t me_rebuild_count; 186 u_int8_t me_misc_flags; 187 #define MLX_ENQ_MISC_BBU (1<<3) /* battery backup present */ 188 struct 189 { 190 u_int8_t dd_targ; 191 u_int8_t dd_chan; 192 } __attribute__ ((packed)) me_dead[20]; 193 } __attribute__ ((packed)); 194 195 struct mlx_enquiry2 /* MLX_CMD_ENQUIRY2 */ 196 { 197 u_int32_t me_hardware_id; 198 u_int32_t me_firmware_id; 199 u_int32_t res1; 200 u_int8_t me_configured_channels; 201 u_int8_t me_actual_channels; 202 u_int8_t me_max_targets; 203 u_int8_t me_max_tags; 204 u_int8_t me_max_sys_drives; 205 u_int8_t me_max_arms; 206 u_int8_t me_max_spans; 207 u_int8_t res2; 208 u_int32_t res3; 209 u_int32_t me_mem_size; 210 u_int32_t me_cache_size; 211 u_int32_t me_flash_size; 212 u_int32_t me_nvram_size; 213 u_int16_t me_mem_type; 214 u_int16_t me_clock_speed; 215 u_int16_t me_mem_speed; 216 u_int16_t me_hardware_speed; 217 u_int8_t res4[10]; 218 u_int16_t me_max_commands; 219 u_int16_t me_max_sg; 220 u_int16_t me_max_dp; 221 u_int16_t me_max_iod; 222 u_int16_t me_max_comb; 223 u_int8_t me_latency; 224 u_int8_t res5; 225 u_int8_t me_scsi_timeout; 226 u_int8_t res6; 227 u_int16_t me_min_freelines; 228 u_int8_t res7[8]; 229 u_int8_t me_rate_const; 230 u_int8_t res8[11]; 231 u_int16_t me_physblk; 232 u_int16_t me_logblk; 233 u_int16_t me_maxblk; 234 u_int16_t me_blocking_factor; 235 u_int16_t me_cacheline; 236 u_int8_t me_scsi_cap; 237 u_int8_t res9[5]; 238 u_int16_t me_fimware_build; 239 u_int8_t me_fault_mgmt_type; 240 u_int8_t res10; 241 u_int32_t me_firmware_features; 242 u_int8_t res11[8]; 243 } __attribute__ ((packed)); 244 245 struct mlx_enq_sys_drive /* MLX_CMD_ENQSYSDRIVE returns an array of 32 of these */ 246 { 247 u_int32_t sd_size; 248 u_int8_t sd_state; 249 u_int8_t sd_raidlevel; 250 u_int16_t res1; 251 } __attribute__ ((packed)); 252 253 struct mlx_eventlog_entry /* MLX_CMD_LOGOP/MLX_LOGOP_GET */ 254 { 255 u_int8_t el_type; 256 u_int8_t el_length; 257 u_char el_target:5; 258 u_char el_channel:3; 259 u_char el_lun:6; 260 u_char res1:2; 261 u_int16_t el_seqno; 262 u_char el_errorcode:7; 263 u_char el_valid:1; 264 u_int8_t el_segment; 265 u_char el_sensekey:4; 266 u_char res2:1; 267 u_char el_ILI:1; 268 u_char el_EOM:1; 269 u_char el_filemark:1; 270 u_int8_t el_information[4]; 271 u_int8_t el_addsense; 272 u_int8_t el_csi[4]; 273 u_int8_t el_asc; 274 u_int8_t el_asq; 275 u_int8_t res3[12]; 276 } __attribute__ ((packed)); 277 278 #define MLX_LOGOP_GET 0x00 /* operation codes for MLX_CMD_LOGOP */ 279 #define MLX_LOGMSG_SENSE 0x00 /* log message contents codes */ 280 281 struct mlx_rebuild_stat /* MLX_CMD_REBUILDSTAT */ 282 { 283 u_int32_t rb_drive; 284 u_int32_t rb_size; 285 u_int32_t rb_remaining; 286 } __attribute__ ((packed)); 287 288 /* 289 * Inlines to build various command structures 290 */ 291 static __inline void 292 mlx_make_type1(struct mlx_command *mc, 293 u_int8_t code, 294 u_int16_t f1, 295 u_int32_t f2, 296 u_int8_t f3, 297 u_int32_t f4, 298 u_int8_t f5) 299 { 300 mc->mc_mailbox[0x0] = code; 301 mc->mc_mailbox[0x2] = f1 & 0xff; 302 mc->mc_mailbox[0x3] = (((f2 >> 24) & 0x3) << 6) | ((f1 >> 8) & 0x3f); 303 mc->mc_mailbox[0x4] = f2 & 0xff; 304 mc->mc_mailbox[0x5] = (f2 >> 8) & 0xff; 305 mc->mc_mailbox[0x6] = (f2 >> 16) & 0xff; 306 mc->mc_mailbox[0x7] = f3; 307 mc->mc_mailbox[0x8] = f4 & 0xff; 308 mc->mc_mailbox[0x9] = (f4 >> 8) & 0xff; 309 mc->mc_mailbox[0xa] = (f4 >> 16) & 0xff; 310 mc->mc_mailbox[0xb] = (f4 >> 24) & 0xff; 311 mc->mc_mailbox[0xc] = f5; 312 } 313 314 static __inline void 315 mlx_make_type2(struct mlx_command *mc, 316 u_int8_t code, 317 u_int8_t f1, 318 u_int8_t f2, 319 u_int8_t f3, 320 u_int8_t f4, 321 u_int8_t f5, 322 u_int8_t f6, 323 u_int32_t f7, 324 u_int8_t f8) 325 { 326 mc->mc_mailbox[0x0] = code; 327 mc->mc_mailbox[0x2] = f1; 328 mc->mc_mailbox[0x3] = f2; 329 mc->mc_mailbox[0x4] = f3; 330 mc->mc_mailbox[0x5] = f4; 331 mc->mc_mailbox[0x6] = f5; 332 mc->mc_mailbox[0x7] = f6; 333 mc->mc_mailbox[0x8] = f7 & 0xff; 334 mc->mc_mailbox[0x9] = (f7 >> 8) & 0xff; 335 mc->mc_mailbox[0xa] = (f7 >> 16) & 0xff; 336 mc->mc_mailbox[0xb] = (f7 >> 24) & 0xff; 337 mc->mc_mailbox[0xc] = f8; 338 } 339 340 static __inline void 341 mlx_make_type3(struct mlx_command *mc, 342 u_int8_t code, 343 u_int8_t f1, 344 u_int8_t f2, 345 u_int16_t f3, 346 u_int8_t f4, 347 u_int8_t f5, 348 u_int32_t f6, 349 u_int8_t f7) 350 { 351 mc->mc_mailbox[0x0] = code; 352 mc->mc_mailbox[0x2] = f1; 353 mc->mc_mailbox[0x3] = f2; 354 mc->mc_mailbox[0x4] = f3 & 0xff; 355 mc->mc_mailbox[0x5] = (f3 >> 8) & 0xff; 356 mc->mc_mailbox[0x6] = f4; 357 mc->mc_mailbox[0x7] = f5; 358 mc->mc_mailbox[0x8] = f6 & 0xff; 359 mc->mc_mailbox[0x9] = (f6 >> 8) & 0xff; 360 mc->mc_mailbox[0xa] = (f6 >> 16) & 0xff; 361 mc->mc_mailbox[0xb] = (f6 >> 24) & 0xff; 362 mc->mc_mailbox[0xc] = f7; 363 } 364 365 static __inline void 366 mlx_make_type4(struct mlx_command *mc, 367 u_int8_t code, 368 u_int16_t f1, 369 u_int32_t f2, 370 u_int32_t f3, 371 u_int8_t f4) 372 { 373 mc->mc_mailbox[0x0] = code; 374 mc->mc_mailbox[0x2] = f1 & 0xff; 375 mc->mc_mailbox[0x3] = (f1 >> 8) & 0xff; 376 mc->mc_mailbox[0x4] = f2 & 0xff; 377 mc->mc_mailbox[0x5] = (f2 >> 8) & 0xff; 378 mc->mc_mailbox[0x6] = (f2 >> 16) & 0xff; 379 mc->mc_mailbox[0x7] = (f2 >> 24) & 0xff; 380 mc->mc_mailbox[0x8] = f3 & 0xff; 381 mc->mc_mailbox[0x9] = (f3 >> 8) & 0xff; 382 mc->mc_mailbox[0xa] = (f3 >> 16) & 0xff; 383 mc->mc_mailbox[0xb] = (f3 >> 24) & 0xff; 384 mc->mc_mailbox[0xc] = f4; 385 } 386 387 static __inline void 388 mlx_make_type5(struct mlx_command *mc, 389 u_int8_t code, 390 u_int8_t f1, 391 u_int8_t f2, 392 u_int32_t f3, 393 u_int32_t f4, 394 u_int8_t f5) 395 { 396 mc->mc_mailbox[0x0] = code; 397 mc->mc_mailbox[0x2] = f1; 398 mc->mc_mailbox[0x3] = f2; 399 mc->mc_mailbox[0x4] = f3 & 0xff; 400 mc->mc_mailbox[0x5] = (f3 >> 8) & 0xff; 401 mc->mc_mailbox[0x6] = (f3 >> 16) & 0xff; 402 mc->mc_mailbox[0x7] = (f3 >> 24) & 0xff; 403 mc->mc_mailbox[0x8] = f4 & 0xff; 404 mc->mc_mailbox[0x9] = (f4 >> 8) & 0xff; 405 mc->mc_mailbox[0xa] = (f4 >> 16) & 0xff; 406 mc->mc_mailbox[0xb] = (f4 >> 24) & 0xff; 407 mc->mc_mailbox[0xc] = f5; 408 } 409