1 /* 2 * HighPoint RR3xxx/4xxx RAID Driver for FreeBSD 3 * Copyright (C) 2007-2012 HighPoint Technologies, Inc. All Rights Reserved. 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #ifndef _HPTIOP_H 27 #define _HPTIOP_H 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #define DBG 0 33 34 #ifdef DBG 35 int hpt_iop_dbg_level = 0; 36 #define KdPrint(x) do { if (hpt_iop_dbg_level) printf x; } while (0) 37 #define HPT_ASSERT(x) assert(x) 38 #else 39 #define KdPrint(x) 40 #define HPT_ASSERT(x) 41 #endif 42 43 #define HPT_SRB_MAX_REQ_SIZE 600 44 #define HPT_SRB_MAX_QUEUE_SIZE 0x100 45 46 /* beyond 64G mem */ 47 #define HPT_SRB_FLAG_HIGH_MEM_ACESS 0x1 48 #define HPT_SRB_MAX_SIZE ((sizeof(struct hpt_iop_srb) + 0x1f) & ~0x1f) 49 #ifndef offsetof 50 #define offsetof(TYPE, MEM) ((size_t)&((TYPE*)0)->MEM) 51 #endif 52 53 #ifndef MIN 54 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 55 #endif 56 57 #define HPT_IOCTL_MAGIC 0xA1B2C3D4 58 #define HPT_IOCTL_MAGIC32 0x1A2B3C4D 59 60 struct hpt_iopmu_itl { 61 u_int32_t resrved0[4]; 62 u_int32_t inbound_msgaddr0; 63 u_int32_t inbound_msgaddr1; 64 u_int32_t outbound_msgaddr0; 65 u_int32_t outbound_msgaddr1; 66 u_int32_t inbound_doorbell; 67 u_int32_t inbound_intstatus; 68 u_int32_t inbound_intmask; 69 u_int32_t outbound_doorbell; 70 u_int32_t outbound_intstatus; 71 u_int32_t outbound_intmask; 72 u_int32_t reserved1[2]; 73 u_int32_t inbound_queue; 74 u_int32_t outbound_queue; 75 }; 76 77 #define IOPMU_QUEUE_EMPTY 0xffffffff 78 #define IOPMU_QUEUE_MASK_HOST_BITS 0xf0000000 79 #define IOPMU_QUEUE_ADDR_HOST_BIT 0x80000000 80 #define IOPMU_QUEUE_REQUEST_SIZE_BIT 0x40000000 81 #define IOPMU_QUEUE_REQUEST_RESULT_BIT 0x40000000 82 #define IOPMU_MAX_MEM_SUPPORT_MASK_64G 0xfffffff000000000ull 83 #define IOPMU_MAX_MEM_SUPPORT_MASK_32G 0xfffffff800000000ull 84 85 #define IOPMU_OUTBOUND_INT_MSG0 1 86 #define IOPMU_OUTBOUND_INT_MSG1 2 87 #define IOPMU_OUTBOUND_INT_DOORBELL 4 88 #define IOPMU_OUTBOUND_INT_POSTQUEUE 8 89 #define IOPMU_OUTBOUND_INT_PCI 0x10 90 91 #define IOPMU_INBOUND_INT_MSG0 1 92 #define IOPMU_INBOUND_INT_MSG1 2 93 #define IOPMU_INBOUND_INT_DOORBELL 4 94 #define IOPMU_INBOUND_INT_ERROR 8 95 #define IOPMU_INBOUND_INT_POSTQUEUE 0x10 96 97 #define MVIOP_QUEUE_LEN 512 98 struct hpt_iopmu_mv { 99 u_int32_t inbound_head; 100 u_int32_t inbound_tail; 101 u_int32_t outbound_head; 102 u_int32_t outbound_tail; 103 u_int32_t inbound_msg; 104 u_int32_t outbound_msg; 105 u_int32_t reserve[10]; 106 u_int64_t inbound_q[MVIOP_QUEUE_LEN]; 107 u_int64_t outbound_q[MVIOP_QUEUE_LEN]; 108 }; 109 110 struct hpt_iopmv_regs { 111 u_int32_t reserved[0x20400 / 4]; 112 u_int32_t inbound_doorbell; 113 u_int32_t inbound_intmask; 114 u_int32_t outbound_doorbell; 115 u_int32_t outbound_intmask; 116 }; 117 118 #define CL_POINTER_TOGGLE 0x00004000 119 #define CPU_TO_F0_DRBL_MSG_A_BIT 0x02000000 120 121 #pragma pack(1) 122 struct hpt_iopmu_mvfrey { 123 u_int32_t reserved[0x4000 / 4]; 124 125 /* hpt_frey_com_reg */ 126 u_int32_t inbound_base; /* 0x4000 : 0 */ 127 u_int32_t inbound_base_high; /* 4 */ 128 u_int32_t reserved2[(0x18 - 8)/ 4]; 129 u_int32_t inbound_write_ptr; /* 0x18 */ 130 u_int32_t inbound_read_ptr; /* 0x1c */ 131 u_int32_t reserved3[(0x2c - 0x20) / 4]; 132 u_int32_t inbound_conf_ctl; /* 0x2c */ 133 u_int32_t reserved4[(0x50 - 0x30) / 4]; 134 u_int32_t outbound_base; /* 0x50 */ 135 u_int32_t outbound_base_high; /* 0x54 */ 136 u_int32_t outbound_shadow_base; /* 0x58 */ 137 u_int32_t outbound_shadow_base_high; /* 0x5c */ 138 u_int32_t reserved5[(0x68 - 0x60) / 4]; 139 u_int32_t outbound_write; /* 0x68 */ 140 u_int32_t reserved6[(0x70 - 0x6c) / 4]; 141 u_int32_t outbound_read; /* 0x70 */ 142 u_int32_t reserved7[(0x88 - 0x74) / 4]; 143 u_int32_t isr_cause; /* 0x88 */ 144 u_int32_t isr_enable; /* 0x8c */ 145 146 u_int32_t reserved8[(0x10200 - 0x4090) / 4]; 147 148 /* hpt_frey_intr_ctl intr_ctl */ 149 u_int32_t main_int_cuase; /* 0x10200: 0 */ 150 u_int32_t main_irq_enable; /* 4 */ 151 u_int32_t main_fiq_enable; /* 8 */ 152 u_int32_t pcie_f0_int_enable; /* 0xc */ 153 u_int32_t pcie_f1_int_enable; /* 0x10 */ 154 u_int32_t pcie_f2_int_enable; /* 0x14 */ 155 u_int32_t pcie_f3_int_enable; /* 0x18 */ 156 157 u_int32_t reserved9[(0x10400 - 0x1021c) / 4]; 158 159 /* hpt_frey_msg_drbl */ 160 u_int32_t f0_to_cpu_msg_a; /* 0x10400: 0 */ 161 u_int32_t reserved10[(0x20 - 4) / 4]; 162 u_int32_t cpu_to_f0_msg_a; /* 0x20 */ 163 u_int32_t reserved11[(0x80 - 0x24) / 4]; 164 u_int32_t f0_doorbell; /* 0x80 */ 165 u_int32_t f0_doorbell_enable; /* 0x84 */ 166 }; 167 168 struct mvfrey_inlist_entry { 169 u_int64_t addr; 170 u_int32_t intrfc_len; 171 u_int32_t reserved; 172 }; 173 174 struct mvfrey_outlist_entry { 175 u_int32_t val; 176 }; 177 178 #pragma pack() 179 180 #define MVIOP_IOCTLCFG_SIZE 0x800 181 #define MVIOP_MU_QUEUE_ADDR_HOST_MASK (~(0x1full)) 182 #define MVIOP_MU_QUEUE_ADDR_HOST_BIT 4 183 184 #define MVIOP_MU_QUEUE_ADDR_IOP_HIGH32 0xffffffff 185 #define MVIOP_MU_QUEUE_REQUEST_RESULT_BIT 1 186 #define MVIOP_MU_QUEUE_REQUEST_RETURN_CONTEXT 2 187 188 #define MVIOP_MU_INBOUND_INT_MSG 1 189 #define MVIOP_MU_INBOUND_INT_POSTQUEUE 2 190 #define MVIOP_MU_OUTBOUND_INT_MSG 1 191 #define MVIOP_MU_OUTBOUND_INT_POSTQUEUE 2 192 193 #define MVIOP_CMD_TYPE_GET_CONFIG (1 << 5) 194 #define MVIOP_CMD_TYPE_SET_CONFIG (1 << 6) 195 #define MVIOP_CMD_TYPE_SCSI (1 << 7) 196 #define MVIOP_CMD_TYPE_IOCTL (1 << 8) 197 #define MVIOP_CMD_TYPE_BLOCK (1 << 9) 198 199 #define MVIOP_REQUEST_NUMBER_START_BIT 16 200 201 #define MVFREYIOPMU_QUEUE_REQUEST_RESULT_BIT 0x40000000 202 203 enum hpt_iopmu_message { 204 /* host-to-iop messages */ 205 IOPMU_INBOUND_MSG0_NOP = 0, 206 IOPMU_INBOUND_MSG0_RESET, 207 IOPMU_INBOUND_MSG0_FLUSH, 208 IOPMU_INBOUND_MSG0_SHUTDOWN, 209 IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK, 210 IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 211 IOPMU_INBOUND_MSG0_RESET_COMM, 212 IOPMU_INBOUND_MSG0_MAX = 0xff, 213 /* iop-to-host messages */ 214 IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_0 = 0x100, 215 IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_MAX = 0x1ff, 216 IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_0 = 0x200, 217 IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_MAX = 0x2ff, 218 IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_0 = 0x300, 219 IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_MAX = 0x3ff, 220 }; 221 222 #define IOP_REQUEST_FLAG_SYNC_REQUEST 1 223 #define IOP_REQUEST_FLAG_BIST_REQUEST 2 224 #define IOP_REQUEST_FLAG_REMAPPED 4 225 #define IOP_REQUEST_FLAG_OUTPUT_CONTEXT 8 226 227 #define IOP_REQUEST_FLAG_ADDR_BITS 0x40 /* flags[31:16] is phy_addr[47:32] */ 228 229 enum hpt_iop_request_type { 230 IOP_REQUEST_TYPE_GET_CONFIG = 0, 231 IOP_REQUEST_TYPE_SET_CONFIG, 232 IOP_REQUEST_TYPE_BLOCK_COMMAND, 233 IOP_REQUEST_TYPE_SCSI_COMMAND, 234 IOP_REQUEST_TYPE_IOCTL_COMMAND, 235 IOP_REQUEST_TYPE_MAX 236 }; 237 238 enum hpt_iop_result_type { 239 IOP_RESULT_PENDING = 0, 240 IOP_RESULT_SUCCESS, 241 IOP_RESULT_FAIL, 242 IOP_RESULT_BUSY, 243 IOP_RESULT_RESET, 244 IOP_RESULT_INVALID_REQUEST, 245 IOP_RESULT_BAD_TARGET, 246 IOP_RESULT_CHECK_CONDITION, 247 }; 248 249 #pragma pack(1) 250 struct hpt_iop_request_header { 251 u_int32_t size; 252 u_int32_t type; 253 u_int32_t flags; 254 u_int32_t result; 255 u_int64_t context; /* host context */ 256 }; 257 258 struct hpt_iop_request_get_config { 259 struct hpt_iop_request_header header; 260 u_int32_t interface_version; 261 u_int32_t firmware_version; 262 u_int32_t max_requests; 263 u_int32_t request_size; 264 u_int32_t max_sg_count; 265 u_int32_t data_transfer_length; 266 u_int32_t alignment_mask; 267 u_int32_t max_devices; 268 u_int32_t sdram_size; 269 }; 270 271 struct hpt_iop_request_set_config { 272 struct hpt_iop_request_header header; 273 u_int32_t iop_id; 274 u_int16_t vbus_id; 275 u_int16_t max_host_request_size; 276 u_int32_t reserve[6]; 277 }; 278 279 struct hpt_iopsg { 280 u_int32_t size; 281 u_int32_t eot; /* non-zero: end of table */ 282 u_int64_t pci_address; 283 }; 284 285 #define IOP_BLOCK_COMMAND_READ 1 286 #define IOP_BLOCK_COMMAND_WRITE 2 287 #define IOP_BLOCK_COMMAND_VERIFY 3 288 #define IOP_BLOCK_COMMAND_FLUSH 4 289 #define IOP_BLOCK_COMMAND_SHUTDOWN 5 290 struct hpt_iop_request_block_command { 291 struct hpt_iop_request_header header; 292 u_int8_t channel; 293 u_int8_t target; 294 u_int8_t lun; 295 u_int8_t pad1; 296 u_int16_t command; /* IOP_BLOCK_COMMAND_{READ,WRITE} */ 297 u_int16_t sectors; 298 u_int64_t lba; 299 struct hpt_iopsg sg_list[1]; 300 }; 301 302 struct hpt_iop_request_scsi_command { 303 struct hpt_iop_request_header header; 304 u_int8_t channel; 305 u_int8_t target; 306 u_int8_t lun; 307 u_int8_t pad1; 308 u_int8_t cdb[16]; 309 u_int32_t dataxfer_length; 310 struct hpt_iopsg sg_list[1]; 311 }; 312 313 struct hpt_iop_request_ioctl_command { 314 struct hpt_iop_request_header header; 315 u_int32_t ioctl_code; 316 u_int32_t inbuf_size; 317 u_int32_t outbuf_size; 318 u_int32_t bytes_returned; 319 u_int8_t buf[1]; 320 /* out data should be put at buf[(inbuf_size+3)&~3] */ 321 }; 322 323 struct hpt_iop_ioctl_param { 324 u_int32_t Magic; /* used to check if it's a valid ioctl packet */ 325 u_int32_t dwIoControlCode; /* operation control code */ 326 unsigned long lpInBuffer; /* input data buffer */ 327 u_int32_t nInBufferSize; /* size of input data buffer */ 328 unsigned long lpOutBuffer; /* output data buffer */ 329 u_int32_t nOutBufferSize; /* size of output data buffer */ 330 unsigned long lpBytesReturned; /* count of HPT_U8s returned */ 331 } __packed; 332 333 #define HPT_IOCTL_FLAG_OPEN 1 334 #define HPT_CTL_CODE_BSD_TO_IOP(x) ((x)-0xff00) 335 336 #if __FreeBSD_version>503000 337 typedef struct cdev * ioctl_dev_t; 338 #else 339 typedef dev_t ioctl_dev_t; 340 #endif 341 342 #if __FreeBSD_version >= 500000 343 typedef struct thread * ioctl_thread_t; 344 #else 345 typedef struct proc * ioctl_thread_t; 346 #endif 347 348 struct hpt_iop_hba { 349 struct hptiop_adapter_ops *ops; 350 union { 351 struct { 352 struct hpt_iopmu_itl *mu; 353 } itl; 354 struct { 355 struct hpt_iopmv_regs *regs; 356 struct hpt_iopmu_mv *mu; 357 } mv; 358 struct { 359 struct hpt_iop_request_get_config *config; 360 struct hpt_iopmu_mvfrey *mu; 361 362 int internal_mem_size; 363 int list_count; 364 struct mvfrey_inlist_entry *inlist; 365 u_int64_t inlist_phy; 366 u_int32_t inlist_wptr; 367 struct mvfrey_outlist_entry *outlist; 368 u_int64_t outlist_phy; 369 u_int32_t *outlist_cptr; /* copy pointer shadow */ 370 u_int64_t outlist_cptr_phy; 371 u_int32_t outlist_rptr; 372 } mvfrey; 373 } u; 374 375 struct hpt_iop_hba *next; 376 377 u_int32_t firmware_version; 378 u_int32_t interface_version; 379 u_int32_t max_devices; 380 u_int32_t max_requests; 381 u_int32_t max_request_size; 382 u_int32_t max_sg_count; 383 384 u_int32_t msg_done; 385 386 device_t pcidev; 387 u_int32_t pciunit; 388 ioctl_dev_t ioctl_dev; 389 390 bus_dma_tag_t parent_dmat; 391 bus_dma_tag_t io_dmat; 392 bus_dma_tag_t srb_dmat; 393 bus_dma_tag_t ctlcfg_dmat; 394 395 bus_dmamap_t srb_dmamap; 396 bus_dmamap_t ctlcfg_dmamap; 397 398 struct resource *bar0_res; 399 bus_space_tag_t bar0t; 400 bus_space_handle_t bar0h; 401 int bar0_rid; 402 403 struct resource *bar2_res; 404 bus_space_tag_t bar2t; 405 bus_space_handle_t bar2h; 406 int bar2_rid; 407 408 /* to release */ 409 u_int8_t *uncached_ptr; 410 void *ctlcfg_ptr; 411 /* for scsi request block */ 412 struct hpt_iop_srb *srb_list; 413 /* for interrupt */ 414 struct resource *irq_res; 415 void *irq_handle; 416 417 /* for ioctl and set/get config */ 418 struct resource *ctlcfg_res; 419 void *ctlcfg_handle; 420 u_int64_t ctlcfgcmd_phy; 421 u_int32_t config_done; /* can be negative value */ 422 u_int32_t initialized:1; 423 424 /* other resources */ 425 struct cam_sim *sim; 426 struct cam_path *path; 427 void *req; 428 #if (__FreeBSD_version >= 500000) 429 struct mtx lock; 430 #else 431 int hpt_splx; 432 #endif 433 #define HPT_IOCTL_FLAG_OPEN 1 434 u_int32_t flag; 435 struct hpt_iop_srb* srb[HPT_SRB_MAX_QUEUE_SIZE]; 436 }; 437 #pragma pack() 438 439 enum hptiop_family { 440 INTEL_BASED_IOP = 0, 441 MV_BASED_IOP, 442 MVFREY_BASED_IOP, 443 UNKNOWN_BASED_IOP = 0xf 444 }; 445 446 struct hptiop_adapter_ops { 447 enum hptiop_family family; 448 int (*iop_wait_ready)(struct hpt_iop_hba *hba, u_int32_t millisec); 449 int (*internal_memalloc)(struct hpt_iop_hba *hba); 450 int (*internal_memfree)(struct hpt_iop_hba *hba); 451 int (*alloc_pci_res)(struct hpt_iop_hba *hba); 452 void (*release_pci_res)(struct hpt_iop_hba *hba); 453 void (*enable_intr)(struct hpt_iop_hba *hba); 454 void (*disable_intr)(struct hpt_iop_hba *hba); 455 int (*get_config)(struct hpt_iop_hba *hba, 456 struct hpt_iop_request_get_config *config); 457 int (*set_config)(struct hpt_iop_hba *hba, 458 struct hpt_iop_request_set_config *config); 459 int (*iop_intr)(struct hpt_iop_hba *hba); 460 void (*post_msg)(struct hpt_iop_hba *hba, u_int32_t msg); 461 void (*post_req)(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb, bus_dma_segment_t *segs, int nsegs); 462 int (*do_ioctl)(struct hpt_iop_hba *hba, struct hpt_iop_ioctl_param * pParams); 463 int (*reset_comm)(struct hpt_iop_hba *hba); 464 }; 465 466 struct hpt_iop_srb { 467 u_int8_t req[HPT_SRB_MAX_REQ_SIZE]; 468 struct hpt_iop_hba *hba; 469 union ccb *ccb; 470 struct hpt_iop_srb *next; 471 bus_dmamap_t dma_map; 472 u_int64_t phy_addr; 473 u_int32_t srb_flag; 474 int index; 475 }; 476 477 #if __FreeBSD_version >= 500000 478 #define hptiop_lock_adapter(hba) mtx_lock(&(hba)->lock) 479 #define hptiop_unlock_adapter(hba) mtx_unlock(&(hba)->lock) 480 #else 481 static __inline void hptiop_lock_adapter(struct hpt_iop_hba *hba) 482 { 483 hba->hpt_splx = splcam(); 484 } 485 static __inline void hptiop_unlock_adapter(struct hpt_iop_hba *hba) 486 { 487 splx(hba->hpt_splx); 488 } 489 #endif 490 491 #define HPT_OSM_TIMEOUT (20*hz) /* timeout value for OS commands */ 492 493 #define HPT_DO_IOCONTROL _IOW('H', 0, struct hpt_iop_ioctl_param) 494 #define HPT_SCAN_BUS _IO('H', 1) 495 496 static __inline int hptiop_sleep(struct hpt_iop_hba *hba, void *ident, 497 int priority, const char *wmesg, int timo) 498 { 499 500 int retval; 501 502 #if __FreeBSD_version >= 500000 503 retval = msleep(ident, &hba->lock, priority, wmesg, timo); 504 #else 505 asleep(ident, priority, wmesg, timo); 506 hptiop_unlock_adapter(hba); 507 retval = await(priority, timo); 508 hptiop_lock_adapter(hba); 509 #endif 510 511 return retval; 512 513 } 514 515 #if __FreeBSD_version < 501000 516 #define READ_16 0x88 517 #define WRITE_16 0x8a 518 #define SERVICE_ACTION_IN 0x9e 519 #endif 520 521 #define HPT_DEV_MAJOR 200 522 523 #endif 524 525