2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * HighPoint RR3xxx/4xxx RAID Driver for FreeBSD
5 * Copyright (C) 2007-2012 HighPoint Technologies, Inc. All Rights Reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
37 int hpt_iop_dbg_level = 0;
38 #define KdPrint(x) do { if (hpt_iop_dbg_level) printf x; } while (0)
39 #define HPT_ASSERT(x) assert(x)
45 #define HPT_SRB_MAX_REQ_SIZE 600
46 #define HPT_SRB_MAX_QUEUE_SIZE 0x100
49 #define HPT_SRB_FLAG_HIGH_MEM_ACESS 0x1
50 #define HPT_SRB_MAX_SIZE ((sizeof(struct hpt_iop_srb) + 0x1f) & ~0x1f)
52 #define offsetof(TYPE, MEM) ((size_t)&((TYPE*)0)->MEM)
56 #define MIN(a, b) ((a) < (b) ? (a) : (b))
59 #define HPT_IOCTL_MAGIC 0xA1B2C3D4
60 #define HPT_IOCTL_MAGIC32 0x1A2B3C4D
62 struct hpt_iopmu_itl {
63 u_int32_t resrved0[4];
64 u_int32_t inbound_msgaddr0;
65 u_int32_t inbound_msgaddr1;
66 u_int32_t outbound_msgaddr0;
67 u_int32_t outbound_msgaddr1;
68 u_int32_t inbound_doorbell;
69 u_int32_t inbound_intstatus;
70 u_int32_t inbound_intmask;
71 u_int32_t outbound_doorbell;
72 u_int32_t outbound_intstatus;
73 u_int32_t outbound_intmask;
74 u_int32_t reserved1[2];
75 u_int32_t inbound_queue;
76 u_int32_t outbound_queue;
79 #define IOPMU_QUEUE_EMPTY 0xffffffff
80 #define IOPMU_QUEUE_MASK_HOST_BITS 0xf0000000
81 #define IOPMU_QUEUE_ADDR_HOST_BIT 0x80000000
82 #define IOPMU_QUEUE_REQUEST_SIZE_BIT 0x40000000
83 #define IOPMU_QUEUE_REQUEST_RESULT_BIT 0x40000000
84 #define IOPMU_MAX_MEM_SUPPORT_MASK_64G 0xfffffff000000000ull
85 #define IOPMU_MAX_MEM_SUPPORT_MASK_32G 0xfffffff800000000ull
87 #define IOPMU_OUTBOUND_INT_MSG0 1
88 #define IOPMU_OUTBOUND_INT_MSG1 2
89 #define IOPMU_OUTBOUND_INT_DOORBELL 4
90 #define IOPMU_OUTBOUND_INT_POSTQUEUE 8
91 #define IOPMU_OUTBOUND_INT_PCI 0x10
93 #define IOPMU_INBOUND_INT_MSG0 1
94 #define IOPMU_INBOUND_INT_MSG1 2
95 #define IOPMU_INBOUND_INT_DOORBELL 4
96 #define IOPMU_INBOUND_INT_ERROR 8
97 #define IOPMU_INBOUND_INT_POSTQUEUE 0x10
99 #define MVIOP_QUEUE_LEN 512
100 struct hpt_iopmu_mv {
101 u_int32_t inbound_head;
102 u_int32_t inbound_tail;
103 u_int32_t outbound_head;
104 u_int32_t outbound_tail;
105 u_int32_t inbound_msg;
106 u_int32_t outbound_msg;
107 u_int32_t reserve[10];
108 u_int64_t inbound_q[MVIOP_QUEUE_LEN];
109 u_int64_t outbound_q[MVIOP_QUEUE_LEN];
112 struct hpt_iopmv_regs {
113 u_int32_t reserved[0x20400 / 4];
114 u_int32_t inbound_doorbell;
115 u_int32_t inbound_intmask;
116 u_int32_t outbound_doorbell;
117 u_int32_t outbound_intmask;
120 #define CL_POINTER_TOGGLE 0x00004000
121 #define CPU_TO_F0_DRBL_MSG_A_BIT 0x02000000
124 struct hpt_iopmu_mvfrey {
125 u_int32_t reserved[0x4000 / 4];
127 /* hpt_frey_com_reg */
128 u_int32_t inbound_base; /* 0x4000 : 0 */
129 u_int32_t inbound_base_high; /* 4 */
130 u_int32_t reserved2[(0x18 - 8)/ 4];
131 u_int32_t inbound_write_ptr; /* 0x18 */
132 u_int32_t inbound_read_ptr; /* 0x1c */
133 u_int32_t reserved3[(0x2c - 0x20) / 4];
134 u_int32_t inbound_conf_ctl; /* 0x2c */
135 u_int32_t reserved4[(0x50 - 0x30) / 4];
136 u_int32_t outbound_base; /* 0x50 */
137 u_int32_t outbound_base_high; /* 0x54 */
138 u_int32_t outbound_shadow_base; /* 0x58 */
139 u_int32_t outbound_shadow_base_high; /* 0x5c */
140 u_int32_t reserved5[(0x68 - 0x60) / 4];
141 u_int32_t outbound_write; /* 0x68 */
142 u_int32_t reserved6[(0x70 - 0x6c) / 4];
143 u_int32_t outbound_read; /* 0x70 */
144 u_int32_t reserved7[(0x88 - 0x74) / 4];
145 u_int32_t isr_cause; /* 0x88 */
146 u_int32_t isr_enable; /* 0x8c */
148 u_int32_t reserved8[(0x10200 - 0x4090) / 4];
150 /* hpt_frey_intr_ctl intr_ctl */
151 u_int32_t main_int_cuase; /* 0x10200: 0 */
152 u_int32_t main_irq_enable; /* 4 */
153 u_int32_t main_fiq_enable; /* 8 */
154 u_int32_t pcie_f0_int_enable; /* 0xc */
155 u_int32_t pcie_f1_int_enable; /* 0x10 */
156 u_int32_t pcie_f2_int_enable; /* 0x14 */
157 u_int32_t pcie_f3_int_enable; /* 0x18 */
159 u_int32_t reserved9[(0x10400 - 0x1021c) / 4];
161 /* hpt_frey_msg_drbl */
162 u_int32_t f0_to_cpu_msg_a; /* 0x10400: 0 */
163 u_int32_t reserved10[(0x20 - 4) / 4];
164 u_int32_t cpu_to_f0_msg_a; /* 0x20 */
165 u_int32_t reserved11[(0x80 - 0x24) / 4];
166 u_int32_t f0_doorbell; /* 0x80 */
167 u_int32_t f0_doorbell_enable; /* 0x84 */
170 struct mvfrey_inlist_entry {
172 u_int32_t intrfc_len;
176 struct mvfrey_outlist_entry {
182 #define MVIOP_IOCTLCFG_SIZE 0x800
183 #define MVIOP_MU_QUEUE_ADDR_HOST_MASK (~(0x1full))
184 #define MVIOP_MU_QUEUE_ADDR_HOST_BIT 4
186 #define MVIOP_MU_QUEUE_ADDR_IOP_HIGH32 0xffffffff
187 #define MVIOP_MU_QUEUE_REQUEST_RESULT_BIT 1
188 #define MVIOP_MU_QUEUE_REQUEST_RETURN_CONTEXT 2
190 #define MVIOP_MU_INBOUND_INT_MSG 1
191 #define MVIOP_MU_INBOUND_INT_POSTQUEUE 2
192 #define MVIOP_MU_OUTBOUND_INT_MSG 1
193 #define MVIOP_MU_OUTBOUND_INT_POSTQUEUE 2
195 #define MVIOP_CMD_TYPE_GET_CONFIG (1 << 5)
196 #define MVIOP_CMD_TYPE_SET_CONFIG (1 << 6)
197 #define MVIOP_CMD_TYPE_SCSI (1 << 7)
198 #define MVIOP_CMD_TYPE_IOCTL (1 << 8)
199 #define MVIOP_CMD_TYPE_BLOCK (1 << 9)
201 #define MVIOP_REQUEST_NUMBER_START_BIT 16
203 #define MVFREYIOPMU_QUEUE_REQUEST_RESULT_BIT 0x40000000
205 enum hpt_iopmu_message {
206 /* host-to-iop messages */
207 IOPMU_INBOUND_MSG0_NOP = 0,
208 IOPMU_INBOUND_MSG0_RESET,
209 IOPMU_INBOUND_MSG0_FLUSH,
210 IOPMU_INBOUND_MSG0_SHUTDOWN,
211 IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK,
212 IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK,
213 IOPMU_INBOUND_MSG0_RESET_COMM,
214 IOPMU_INBOUND_MSG0_MAX = 0xff,
215 /* iop-to-host messages */
216 IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_0 = 0x100,
217 IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_MAX = 0x1ff,
218 IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_0 = 0x200,
219 IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_MAX = 0x2ff,
220 IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_0 = 0x300,
221 IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_MAX = 0x3ff,
224 #define IOP_REQUEST_FLAG_SYNC_REQUEST 1
225 #define IOP_REQUEST_FLAG_BIST_REQUEST 2
226 #define IOP_REQUEST_FLAG_REMAPPED 4
227 #define IOP_REQUEST_FLAG_OUTPUT_CONTEXT 8
229 #define IOP_REQUEST_FLAG_ADDR_BITS 0x40 /* flags[31:16] is phy_addr[47:32] */
231 enum hpt_iop_request_type {
232 IOP_REQUEST_TYPE_GET_CONFIG = 0,
233 IOP_REQUEST_TYPE_SET_CONFIG,
234 IOP_REQUEST_TYPE_BLOCK_COMMAND,
235 IOP_REQUEST_TYPE_SCSI_COMMAND,
236 IOP_REQUEST_TYPE_IOCTL_COMMAND,
240 enum hpt_iop_result_type {
241 IOP_RESULT_PENDING = 0,
246 IOP_RESULT_INVALID_REQUEST,
247 IOP_RESULT_BAD_TARGET,
248 IOP_RESULT_CHECK_CONDITION,
252 struct hpt_iop_request_header {
257 u_int64_t context; /* host context */
260 struct hpt_iop_request_get_config {
261 struct hpt_iop_request_header header;
262 u_int32_t interface_version;
263 u_int32_t firmware_version;
264 u_int32_t max_requests;
265 u_int32_t request_size;
266 u_int32_t max_sg_count;
267 u_int32_t data_transfer_length;
268 u_int32_t alignment_mask;
269 u_int32_t max_devices;
270 u_int32_t sdram_size;
273 struct hpt_iop_request_set_config {
274 struct hpt_iop_request_header header;
277 u_int16_t max_host_request_size;
278 u_int32_t reserve[6];
283 u_int32_t eot; /* non-zero: end of table */
284 u_int64_t pci_address;
287 #define IOP_BLOCK_COMMAND_READ 1
288 #define IOP_BLOCK_COMMAND_WRITE 2
289 #define IOP_BLOCK_COMMAND_VERIFY 3
290 #define IOP_BLOCK_COMMAND_FLUSH 4
291 #define IOP_BLOCK_COMMAND_SHUTDOWN 5
292 struct hpt_iop_request_block_command {
293 struct hpt_iop_request_header header;
298 u_int16_t command; /* IOP_BLOCK_COMMAND_{READ,WRITE} */
301 struct hpt_iopsg sg_list[1];
304 struct hpt_iop_request_scsi_command {
305 struct hpt_iop_request_header header;
311 u_int32_t dataxfer_length;
312 struct hpt_iopsg sg_list[1];
315 struct hpt_iop_request_ioctl_command {
316 struct hpt_iop_request_header header;
317 u_int32_t ioctl_code;
318 u_int32_t inbuf_size;
319 u_int32_t outbuf_size;
320 u_int32_t bytes_returned;
322 /* out data should be put at buf[(inbuf_size+3)&~3] */
325 struct hpt_iop_ioctl_param {
326 u_int32_t Magic; /* used to check if it's a valid ioctl packet */
327 u_int32_t dwIoControlCode; /* operation control code */
328 unsigned long lpInBuffer; /* input data buffer */
329 u_int32_t nInBufferSize; /* size of input data buffer */
330 unsigned long lpOutBuffer; /* output data buffer */
331 u_int32_t nOutBufferSize; /* size of output data buffer */
332 unsigned long lpBytesReturned; /* count of HPT_U8s returned */
335 #define HPT_IOCTL_FLAG_OPEN 1
336 #define HPT_CTL_CODE_BSD_TO_IOP(x) ((x)-0xff00)
338 typedef struct cdev * ioctl_dev_t;
340 typedef struct thread * ioctl_thread_t;
343 struct hptiop_adapter_ops *ops;
346 struct hpt_iopmu_itl *mu;
349 struct hpt_iopmv_regs *regs;
350 struct hpt_iopmu_mv *mu;
353 struct hpt_iop_request_get_config *config;
354 struct hpt_iopmu_mvfrey *mu;
356 int internal_mem_size;
358 struct mvfrey_inlist_entry *inlist;
359 u_int64_t inlist_phy;
360 u_int32_t inlist_wptr;
361 struct mvfrey_outlist_entry *outlist;
362 u_int64_t outlist_phy;
363 u_int32_t *outlist_cptr; /* copy pointer shadow */
364 u_int64_t outlist_cptr_phy;
365 u_int32_t outlist_rptr;
369 struct hpt_iop_hba *next;
371 u_int32_t firmware_version;
372 u_int32_t interface_version;
373 u_int32_t max_devices;
374 u_int32_t max_requests;
375 u_int32_t max_request_size;
376 u_int32_t max_sg_count;
382 ioctl_dev_t ioctl_dev;
384 bus_dma_tag_t parent_dmat;
385 bus_dma_tag_t io_dmat;
386 bus_dma_tag_t srb_dmat;
387 bus_dma_tag_t ctlcfg_dmat;
389 bus_dmamap_t srb_dmamap;
390 bus_dmamap_t ctlcfg_dmamap;
392 struct resource *bar0_res;
393 bus_space_tag_t bar0t;
394 bus_space_handle_t bar0h;
397 struct resource *bar2_res;
398 bus_space_tag_t bar2t;
399 bus_space_handle_t bar2h;
403 u_int8_t *uncached_ptr;
405 /* for scsi request block */
406 struct hpt_iop_srb *srb_list;
408 struct resource *irq_res;
411 /* for ioctl and set/get config */
412 struct resource *ctlcfg_res;
414 u_int64_t ctlcfgcmd_phy;
415 u_int32_t config_done; /* can be negative value */
416 u_int32_t initialized:1;
418 /* other resources */
420 struct cam_path *path;
423 #define HPT_IOCTL_FLAG_OPEN 1
425 struct hpt_iop_srb* srb[HPT_SRB_MAX_QUEUE_SIZE];
433 UNKNOWN_BASED_IOP = 0xf
436 struct hptiop_adapter_ops {
437 enum hptiop_family family;
438 int (*iop_wait_ready)(struct hpt_iop_hba *hba, u_int32_t millisec);
439 int (*internal_memalloc)(struct hpt_iop_hba *hba);
440 int (*internal_memfree)(struct hpt_iop_hba *hba);
441 int (*alloc_pci_res)(struct hpt_iop_hba *hba);
442 void (*release_pci_res)(struct hpt_iop_hba *hba);
443 void (*enable_intr)(struct hpt_iop_hba *hba);
444 void (*disable_intr)(struct hpt_iop_hba *hba);
445 int (*get_config)(struct hpt_iop_hba *hba,
446 struct hpt_iop_request_get_config *config);
447 int (*set_config)(struct hpt_iop_hba *hba,
448 struct hpt_iop_request_set_config *config);
449 int (*iop_intr)(struct hpt_iop_hba *hba);
450 void (*post_msg)(struct hpt_iop_hba *hba, u_int32_t msg);
451 void (*post_req)(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb, bus_dma_segment_t *segs, int nsegs);
452 int (*do_ioctl)(struct hpt_iop_hba *hba, struct hpt_iop_ioctl_param * pParams);
453 int (*reset_comm)(struct hpt_iop_hba *hba);
457 u_int8_t req[HPT_SRB_MAX_REQ_SIZE];
458 struct hpt_iop_hba *hba;
460 struct hpt_iop_srb *next;
461 bus_dmamap_t dma_map;
465 struct callout timeout;
468 #define hptiop_lock_adapter(hba) mtx_lock(&(hba)->lock)
469 #define hptiop_unlock_adapter(hba) mtx_unlock(&(hba)->lock)
471 #define HPT_OSM_TIMEOUT (20*hz) /* timeout value for OS commands */
473 #define HPT_DO_IOCONTROL _IOW('H', 0, struct hpt_iop_ioctl_param)
474 #define HPT_SCAN_BUS _IO('H', 1)
476 static __inline int hptiop_sleep(struct hpt_iop_hba *hba, void *ident,
477 int priority, const char *wmesg, int timo)
482 retval = msleep(ident, &hba->lock, priority, wmesg, timo);
489 #define HPT_DEV_MAJOR 200