1 /* 2 * HighPoint RR3xxx/4xxx RAID Driver for FreeBSD 3 * Copyright (C) 2007-2008 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_dbg_level = 0; 36 #define KdPrint(x) do { if (hpt_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 MVIOP_IOCTLCFG_SIZE 0x800 119 #define MVIOP_MU_QUEUE_ADDR_HOST_MASK (~(0x1full)) 120 #define MVIOP_MU_QUEUE_ADDR_HOST_BIT 4 121 122 #define MVIOP_MU_QUEUE_ADDR_IOP_HIGH32 0xffffffff 123 #define MVIOP_MU_QUEUE_REQUEST_RESULT_BIT 1 124 #define MVIOP_MU_QUEUE_REQUEST_RETURN_CONTEXT 2 125 126 #define MVIOP_MU_INBOUND_INT_MSG 1 127 #define MVIOP_MU_INBOUND_INT_POSTQUEUE 2 128 #define MVIOP_MU_OUTBOUND_INT_MSG 1 129 #define MVIOP_MU_OUTBOUND_INT_POSTQUEUE 2 130 131 #define MVIOP_CMD_TYPE_GET_CONFIG (1 << 5) 132 #define MVIOP_CMD_TYPE_SET_CONFIG (1 << 6) 133 #define MVIOP_CMD_TYPE_SCSI (1 << 7) 134 #define MVIOP_CMD_TYPE_IOCTL (1 << 8) 135 #define MVIOP_CMD_TYPE_BLOCK (1 << 9) 136 137 #define MVIOP_REQUEST_NUMBER_START_BIT 16 138 139 enum hpt_iopmu_message { 140 /* host-to-iop messages */ 141 IOPMU_INBOUND_MSG0_NOP = 0, 142 IOPMU_INBOUND_MSG0_RESET, 143 IOPMU_INBOUND_MSG0_FLUSH, 144 IOPMU_INBOUND_MSG0_SHUTDOWN, 145 IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK, 146 IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 147 IOPMU_INBOUND_MSG0_MAX = 0xff, 148 /* iop-to-host messages */ 149 IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_0 = 0x100, 150 IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_MAX = 0x1ff, 151 IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_0 = 0x200, 152 IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_MAX = 0x2ff, 153 IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_0 = 0x300, 154 IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_MAX = 0x3ff, 155 }; 156 157 #define IOP_REQUEST_FLAG_SYNC_REQUEST 1 158 #define IOP_REQUEST_FLAG_BIST_REQUEST 2 159 #define IOP_REQUEST_FLAG_REMAPPED 4 160 #define IOP_REQUEST_FLAG_OUTPUT_CONTEXT 8 161 162 enum hpt_iop_request_type { 163 IOP_REQUEST_TYPE_GET_CONFIG = 0, 164 IOP_REQUEST_TYPE_SET_CONFIG, 165 IOP_REQUEST_TYPE_BLOCK_COMMAND, 166 IOP_REQUEST_TYPE_SCSI_COMMAND, 167 IOP_REQUEST_TYPE_IOCTL_COMMAND, 168 IOP_REQUEST_TYPE_MAX 169 }; 170 171 enum hpt_iop_result_type { 172 IOP_RESULT_PENDING = 0, 173 IOP_RESULT_SUCCESS, 174 IOP_RESULT_FAIL, 175 IOP_RESULT_BUSY, 176 IOP_RESULT_RESET, 177 IOP_RESULT_INVALID_REQUEST, 178 IOP_RESULT_BAD_TARGET, 179 IOP_RESULT_CHECK_CONDITION, 180 }; 181 182 struct hpt_iop_request_header { 183 u_int32_t size; 184 u_int32_t type; 185 u_int32_t flags; 186 u_int32_t result; 187 u_int64_t context; /* host context */ 188 }; 189 190 struct hpt_iop_request_get_config { 191 struct hpt_iop_request_header header; 192 u_int32_t interface_version; 193 u_int32_t firmware_version; 194 u_int32_t max_requests; 195 u_int32_t request_size; 196 u_int32_t max_sg_count; 197 u_int32_t data_transfer_length; 198 u_int32_t alignment_mask; 199 u_int32_t max_devices; 200 u_int32_t sdram_size; 201 }; 202 203 struct hpt_iop_request_set_config { 204 struct hpt_iop_request_header header; 205 u_int32_t iop_id; 206 u_int16_t vbus_id; 207 u_int16_t max_host_request_size; 208 u_int32_t reserve[6]; 209 }; 210 211 struct hpt_iopsg { 212 u_int32_t size; 213 u_int32_t eot; /* non-zero: end of table */ 214 u_int64_t pci_address; 215 }; 216 217 #define IOP_BLOCK_COMMAND_READ 1 218 #define IOP_BLOCK_COMMAND_WRITE 2 219 #define IOP_BLOCK_COMMAND_VERIFY 3 220 #define IOP_BLOCK_COMMAND_FLUSH 4 221 #define IOP_BLOCK_COMMAND_SHUTDOWN 5 222 struct hpt_iop_request_block_command { 223 struct hpt_iop_request_header header; 224 u_int8_t channel; 225 u_int8_t target; 226 u_int8_t lun; 227 u_int8_t pad1; 228 u_int16_t command; /* IOP_BLOCK_COMMAND_{READ,WRITE} */ 229 u_int16_t sectors; 230 u_int64_t lba; 231 struct hpt_iopsg sg_list[1]; 232 }; 233 234 struct hpt_iop_request_scsi_command { 235 struct hpt_iop_request_header header; 236 u_int8_t channel; 237 u_int8_t target; 238 u_int8_t lun; 239 u_int8_t pad1; 240 u_int8_t cdb[16]; 241 u_int32_t dataxfer_length; 242 struct hpt_iopsg sg_list[1]; 243 }; 244 245 struct hpt_iop_request_ioctl_command { 246 struct hpt_iop_request_header header; 247 u_int32_t ioctl_code; 248 u_int32_t inbuf_size; 249 u_int32_t outbuf_size; 250 u_int32_t bytes_returned; 251 u_int8_t buf[1]; 252 /* out data should be put at buf[(inbuf_size+3)&~3] */ 253 }; 254 255 struct hpt_iop_ioctl_param { 256 u_int32_t Magic; /* used to check if it's a valid ioctl packet */ 257 u_int32_t dwIoControlCode; /* operation control code */ 258 unsigned long lpInBuffer; /* input data buffer */ 259 u_int32_t nInBufferSize; /* size of input data buffer */ 260 unsigned long lpOutBuffer; /* output data buffer */ 261 u_int32_t nOutBufferSize; /* size of output data buffer */ 262 unsigned long lpBytesReturned; /* count of HPT_U8s returned */ 263 }; 264 265 #define HPT_IOCTL_FLAG_OPEN 1 266 #define HPT_CTL_CODE_BSD_TO_IOP(x) ((x)-0xff00) 267 268 #if __FreeBSD_version>503000 269 typedef struct cdev * ioctl_dev_t; 270 #else 271 typedef dev_t ioctl_dev_t; 272 #endif 273 274 #if __FreeBSD_version >= 500000 275 typedef struct thread * ioctl_thread_t; 276 #else 277 typedef struct proc * ioctl_thread_t; 278 #endif 279 280 struct hpt_iop_hba { 281 struct hptiop_adapter_ops *ops; 282 union { 283 struct { 284 struct hpt_iopmu_itl *mu; 285 } itl; 286 struct { 287 struct hpt_iopmv_regs *regs; 288 struct hpt_iopmu_mv *mu; 289 } mv; 290 } u; 291 292 struct hpt_iop_hba *next; 293 294 u_int32_t firmware_version; 295 u_int32_t interface_version; 296 u_int32_t max_devices; 297 u_int32_t max_requests; 298 u_int32_t max_request_size; 299 u_int32_t max_sg_count; 300 301 u_int32_t msg_done; 302 303 device_t pcidev; 304 u_int32_t pciunit; 305 ioctl_dev_t ioctl_dev; 306 307 bus_dma_tag_t parent_dmat; 308 bus_dma_tag_t io_dmat; 309 bus_dma_tag_t srb_dmat; 310 bus_dma_tag_t ctlcfg_dmat; 311 312 bus_dmamap_t srb_dmamap; 313 bus_dmamap_t ctlcfg_dmamap; 314 315 struct resource *bar0_res; 316 bus_space_tag_t bar0t; 317 bus_space_handle_t bar0h; 318 int bar0_rid; 319 320 struct resource *bar2_res; 321 bus_space_tag_t bar2t; 322 bus_space_handle_t bar2h; 323 int bar2_rid; 324 325 /* to release */ 326 u_int8_t *uncached_ptr; 327 void *ctlcfg_ptr; 328 /* for scsi request block */ 329 struct hpt_iop_srb *srb_list; 330 /* for interrupt */ 331 struct resource *irq_res; 332 void *irq_handle; 333 334 /* for ioctl and set/get config */ 335 struct resource *ctlcfg_res; 336 void *ctlcfg_handle; 337 u_int64_t ctlcfgcmd_phy; 338 u_int32_t config_done; 339 340 /* other resources */ 341 struct cam_sim *sim; 342 struct cam_path *path; 343 void *req; 344 #if (__FreeBSD_version >= 500000) 345 struct mtx lock; 346 #else 347 int hpt_splx; 348 #endif 349 #define HPT_IOCTL_FLAG_OPEN 1 350 u_int32_t flag; 351 struct hpt_iop_srb* srb[HPT_SRB_MAX_QUEUE_SIZE]; 352 }; 353 354 struct hptiop_adapter_ops { 355 int (*iop_wait_ready)(struct hpt_iop_hba *hba, u_int32_t millisec); 356 int (*internal_memalloc)(struct hpt_iop_hba *hba); 357 int (*internal_memfree)(struct hpt_iop_hba *hba); 358 int (*alloc_pci_res)(struct hpt_iop_hba *hba); 359 void (*release_pci_res)(struct hpt_iop_hba *hba); 360 void (*enable_intr)(struct hpt_iop_hba *hba); 361 void (*disable_intr)(struct hpt_iop_hba *hba); 362 int (*get_config)(struct hpt_iop_hba *hba, 363 struct hpt_iop_request_get_config *config); 364 int (*set_config)(struct hpt_iop_hba *hba, 365 struct hpt_iop_request_set_config *config); 366 int (*iop_intr)(struct hpt_iop_hba *hba); 367 void (*post_msg)(struct hpt_iop_hba *hba, u_int32_t msg); 368 void (*post_req)(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb, bus_dma_segment_t *segs, int nsegs); 369 int (*do_ioctl)(struct hpt_iop_hba *hba, struct hpt_iop_ioctl_param * pParams); 370 }; 371 372 struct hpt_iop_srb { 373 u_int8_t req[HPT_SRB_MAX_REQ_SIZE]; 374 struct hpt_iop_hba *hba; 375 union ccb *ccb; 376 struct hpt_iop_srb *next; 377 bus_dmamap_t dma_map; 378 u_int64_t phy_addr; 379 u_int32_t srb_flag; 380 int index; 381 }; 382 383 #if __FreeBSD_version >= 500000 384 #define hptiop_lock_adapter(hba) mtx_lock(&(hba)->lock) 385 #define hptiop_unlock_adapter(hba) mtx_unlock(&(hba)->lock) 386 #else 387 static __inline void hptiop_lock_adapter(struct hpt_iop_hba *hba) 388 { 389 hba->hpt_splx = splcam(); 390 } 391 static __inline void hptiop_unlock_adapter(struct hpt_iop_hba *hba) 392 { 393 splx(hba->hpt_splx); 394 } 395 #endif 396 397 #define HPT_OSM_TIMEOUT (20*hz) /* timeout value for OS commands */ 398 399 #define HPT_DO_IOCONTROL _IOW('H', 0, struct hpt_iop_ioctl_param) 400 #define HPT_SCAN_BUS _IO('H', 1) 401 402 static __inline int hptiop_sleep(struct hpt_iop_hba *hba, void *ident, 403 int priority, const char *wmesg, int timo) 404 { 405 406 int retval; 407 408 #if __FreeBSD_version >= 500000 409 retval = msleep(ident, &hba->lock, priority, wmesg, timo); 410 #else 411 asleep(ident, priority, wmesg, timo); 412 hptiop_unlock_adapter(hba); 413 retval = await(priority, timo); 414 hptiop_lock_adapter(hba); 415 #endif 416 417 return retval; 418 419 } 420 421 #if __FreeBSD_version < 501000 422 #define READ_16 0x88 423 #define WRITE_16 0x8a 424 #define SERVICE_ACTION_IN 0x9e 425 #endif 426 427 #define HPT_DEV_MAJOR 200 428 429 #endif 430 431