1 /* 2 * HighPoint RR3xxx RAID Driver for FreeBSD 3 * Copyright (C) 2005-2007 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 #ifdef DBG 33 int hpt_dbg_level = 0; 34 #define KdPrint(x) do { if (hpt_dbg_level) printf x; } while (0) 35 #define HPT_ASSERT(x) assert(x) 36 #else 37 #define KdPrint(x) 38 #define HPT_ASSERT(x) 39 #endif 40 41 #define HPT_SRB_MAX_REQ_SIZE 600 42 #define HPT_SRB_MAX_QUEUE_SIZE 0x100 43 44 /* beyond 64G mem */ 45 #define HPT_SRB_FLAG_HIGH_MEM_ACESS 0x1 46 #define HPT_SRB_MAX_SIZE ((sizeof(struct hpt_iop_srb) + 0x1f) & ~0x1f) 47 48 #define HPT_IOCTL_MAGIC 0xA1B2C3D4 49 #define HPT_IOCTL_MAGIC32 0x1A2B3C4D 50 51 52 struct hpt_iopmu 53 { 54 u_int32_t resrved0[4]; 55 u_int32_t inbound_msgaddr0; 56 u_int32_t inbound_msgaddr1; 57 u_int32_t outbound_msgaddr0; 58 u_int32_t outbound_msgaddr1; 59 u_int32_t inbound_doorbell; 60 u_int32_t inbound_intstatus; 61 u_int32_t inbound_intmask; 62 u_int32_t outbound_doorbell; 63 u_int32_t outbound_intstatus; 64 u_int32_t outbound_intmask; 65 u_int32_t reserved1[2]; 66 u_int32_t inbound_queue; 67 u_int32_t outbound_queue; 68 }; 69 70 struct hpt_iop_ioctl_param { 71 u_int32_t Magic; /* used to check if it's a valid ioctl packet */ 72 u_int32_t dwIoControlCode; /* operation control code */ 73 unsigned long lpInBuffer; /* input data buffer */ 74 u_int32_t nInBufferSize; /* size of input data buffer */ 75 unsigned long lpOutBuffer; /* output data buffer */ 76 u_int32_t nOutBufferSize; /* size of output data buffer */ 77 unsigned long lpBytesReturned; /* count of HPT_U8s returned */ 78 } __attribute__((packed)); 79 80 81 struct hpt_iop_srb { 82 u_int8_t req[HPT_SRB_MAX_REQ_SIZE]; 83 struct hpt_iop_hba *hba; 84 union ccb *ccb; 85 struct hpt_iop_srb * next; 86 bus_dmamap_t dma_map; 87 u_int32_t phy_addr; 88 u_int32_t srb_flag; 89 int index; 90 }; 91 92 #define IOPMU_QUEUE_EMPTY 0xffffffff 93 #define IOPMU_QUEUE_MASK_HOST_BITS 0xf0000000 94 #define IOPMU_QUEUE_ADDR_HOST_BIT 0x80000000 95 #define IOPMU_QUEUE_REQUEST_SIZE_BIT 0x40000000 96 #define IOPMU_QUEUE_REQUEST_RESULT_BIT 0x40000000 97 #define IOPMU_MAX_MEM_SUPPORT_MASK_64G 0xfffffff000000000ull 98 #define IOPMU_MAX_MEM_SUPPORT_MASK_32G 0xfffffff800000000ull 99 100 #define IOPMU_OUTBOUND_INT_MSG0 1 101 #define IOPMU_OUTBOUND_INT_MSG1 2 102 #define IOPMU_OUTBOUND_INT_DOORBELL 4 103 #define IOPMU_OUTBOUND_INT_POSTQUEUE 8 104 #define IOPMU_OUTBOUND_INT_PCI 0x10 105 106 #define IOPMU_INBOUND_INT_MSG0 1 107 #define IOPMU_INBOUND_INT_MSG1 2 108 #define IOPMU_INBOUND_INT_DOORBELL 4 109 #define IOPMU_INBOUND_INT_ERROR 8 110 #define IOPMU_INBOUND_INT_POSTQUEUE 0x10 111 112 enum hpt_iopmu_message { 113 /* host-to-iop messages */ 114 IOPMU_INBOUND_MSG0_NOP = 0, 115 IOPMU_INBOUND_MSG0_RESET, 116 IOPMU_INBOUND_MSG0_FLUSH, 117 IOPMU_INBOUND_MSG0_SHUTDOWN, 118 IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK, 119 IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 120 IOPMU_INBOUND_MSG0_MAX = 0xff, 121 /* iop-to-host messages */ 122 IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_0 = 0x100, 123 IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_MAX = 0x1ff, 124 IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_0 = 0x200, 125 IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_MAX = 0x2ff, 126 IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_0 = 0x300, 127 IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_MAX = 0x3ff, 128 }; 129 130 struct hpt_iop_request_header 131 { 132 u_int32_t size; 133 u_int32_t type; 134 u_int32_t flags; 135 u_int32_t result; 136 u_int32_t context; /* host context */ 137 u_int32_t context_hi32; 138 }; 139 140 #define IOP_REQUEST_FLAG_SYNC_REQUEST 1 141 #define IOP_REQUEST_FLAG_BIST_REQUEST 2 142 #define IOP_REQUEST_FLAG_REMAPPED 4 143 #define IOP_REQUEST_FLAG_OUTPUT_CONTEXT 8 144 145 enum hpt_iop_request_type { 146 IOP_REQUEST_TYPE_GET_CONFIG = 0, 147 IOP_REQUEST_TYPE_SET_CONFIG, 148 IOP_REQUEST_TYPE_BLOCK_COMMAND, 149 IOP_REQUEST_TYPE_SCSI_COMMAND, 150 IOP_REQUEST_TYPE_IOCTL_COMMAND, 151 IOP_REQUEST_TYPE_MAX 152 }; 153 154 enum hpt_iop_result_type { 155 IOP_RESULT_PENDING = 0, 156 IOP_RESULT_SUCCESS, 157 IOP_RESULT_FAIL, 158 IOP_RESULT_BUSY, 159 IOP_RESULT_RESET, 160 IOP_RESULT_INVALID_REQUEST, 161 IOP_RESULT_BAD_TARGET, 162 IOP_RESULT_MODE_SENSE_CHECK_CONDITION, 163 }; 164 165 struct hpt_iop_request_get_config 166 { 167 struct hpt_iop_request_header header; 168 u_int32_t interface_version; 169 u_int32_t firmware_version; 170 u_int32_t max_requests; 171 u_int32_t request_size; 172 u_int32_t max_sg_count; 173 u_int32_t data_transfer_length; 174 u_int32_t alignment_mask; 175 u_int32_t max_devices; 176 u_int32_t sdram_size; 177 }; 178 179 struct hpt_iop_request_set_config 180 { 181 struct hpt_iop_request_header header; 182 u_int32_t iop_id; 183 u_int16_t vbus_id; 184 u_int16_t max_host_request_size; 185 u_int32_t reserve[6]; 186 }; 187 188 struct hpt_iopsg 189 { 190 u_int32_t size; 191 u_int32_t eot; /* non-zero: end of table */ 192 u_int64_t pci_address; 193 }; 194 195 struct hpt_iop_request_block_command 196 { 197 struct hpt_iop_request_header header; 198 u_int8_t channel; 199 u_int8_t target; 200 u_int8_t lun; 201 u_int8_t pad1; 202 u_int16_t command; /* IOP_BLOCK_COMMAND_{READ,WRITE} */ 203 u_int16_t sectors; 204 u_int64_t lba; 205 struct hpt_iopsg sg_list[1]; 206 }; 207 208 #define IOP_BLOCK_COMMAND_READ 1 209 #define IOP_BLOCK_COMMAND_WRITE 2 210 #define IOP_BLOCK_COMMAND_VERIFY 3 211 #define IOP_BLOCK_COMMAND_FLUSH 4 212 #define IOP_BLOCK_COMMAND_SHUTDOWN 5 213 214 struct hpt_iop_request_scsi_command 215 { 216 struct hpt_iop_request_header header; 217 u_int8_t channel; 218 u_int8_t target; 219 u_int8_t lun; 220 u_int8_t pad1; 221 u_int8_t cdb[16]; 222 u_int32_t dataxfer_length; 223 struct hpt_iopsg sg_list[1]; 224 }; 225 226 struct hpt_iop_request_ioctl_command 227 { 228 struct hpt_iop_request_header header; 229 u_int32_t ioctl_code; 230 u_int32_t inbuf_size; 231 u_int32_t outbuf_size; 232 u_int32_t bytes_returned; 233 u_int8_t buf[1]; 234 /* out data should be put at buf[(inbuf_size+3)&~3] */ 235 }; 236 237 #define HPT_CTL_CODE_BSD_TO_IOP(x) ((x)-0xff00) 238 239 #if __FreeBSD_version>503000 240 typedef struct cdev * ioctl_dev_t; 241 #else 242 typedef dev_t ioctl_dev_t; 243 #endif 244 245 #if __FreeBSD_version >= 500000 246 typedef struct thread * ioctl_thread_t; 247 #else 248 typedef struct proc * ioctl_thread_t; 249 #endif 250 251 struct hpt_iop_hba { 252 struct hpt_iopmu *iop; 253 struct hpt_iop_hba *next; 254 255 u_int32_t firmware_version; 256 u_int32_t interface_version; 257 u_int32_t max_devices; 258 u_int32_t max_requests; 259 u_int32_t max_request_size; 260 u_int32_t max_sg_count; 261 262 int msg_done; 263 264 device_t pcidev; 265 u_int32_t pciunit; 266 ioctl_dev_t ioctl_dev; 267 268 struct resource *bar0_res; 269 int bar0_rid; 270 271 bus_dma_tag_t parent_dmat; 272 bus_dma_tag_t io_dmat; 273 bus_dma_tag_t srb_dmat; 274 bus_dmamap_t srb_dmamap; 275 /* to release */ 276 u_int8_t *uncached_ptr; 277 /* for scsi request block */ 278 struct hpt_iop_srb *srb_list; 279 /* for interrupt */ 280 struct resource *irq_res; 281 void *irq_handle; 282 /* other resources */ 283 struct cam_sim *sim; 284 struct cam_path *path; 285 void *req; 286 #if (__FreeBSD_version >= 500000) 287 struct mtx lock; 288 #else 289 int hpt_splx; 290 #endif 291 #define HPT_IOCTL_FLAG_OPEN 1 292 u_int32_t flag; 293 struct hpt_iop_srb* srb[HPT_SRB_MAX_QUEUE_SIZE]; 294 }; 295 296 #if __FreeBSD_version >= 500000 297 #define hptiop_lock_adapter(hba) mtx_lock(&(hba)->lock) 298 #define hptiop_unlock_adapter(hba) mtx_unlock(&(hba)->lock) 299 #else 300 static __inline void hptiop_lock_adapter(struct hpt_iop_hba *hba) 301 { 302 hba->hpt_splx = splcam(); 303 } 304 static __inline void hptiop_unlock_adapter(struct hpt_iop_hba *hba) 305 { 306 splx(hba->hpt_splx); 307 } 308 #endif 309 310 #define HPT_OSM_TIMEOUT (20*hz) /* timeout value for OS commands */ 311 312 #define HPT_DO_IOCONTROL _IOW('H', 0, struct hpt_iop_ioctl_param) 313 #define HPT_SCAN_BUS _IO('H', 1) 314 315 static __inline int hptiop_sleep(struct hpt_iop_hba *hba, void *ident, 316 int priority, const char *wmesg, int timo) 317 { 318 319 int retval; 320 321 #if __FreeBSD_version >= 500000 322 retval = msleep(ident, &hba->lock, priority, wmesg, timo); 323 #else 324 asleep(ident, priority, wmesg, timo); 325 hptiop_unlock_adapter(hba); 326 retval = await(priority, timo); 327 hptiop_lock_adapter(hba); 328 #endif 329 330 return retval; 331 332 } 333 334 #if __FreeBSD_version < 501000 335 #define READ_16 0x88 336 #define WRITE_16 0x8a 337 #define SERVICE_ACTION_IN 0x9e 338 #endif 339 340 #define HPT_DEV_MAJOR 200 341 342 #endif 343 344