xref: /freebsd/sys/dev/hptiop/hptiop.h (revision 66fd12cf4896eb08ad8e7a2627537f84ead84dd3)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
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
8  * are met:
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.
14  *
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
25  * SUCH DAMAGE.
26  */
27 
28 #ifndef _HPTIOP_H
29 #define _HPTIOP_H
30 
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33 
34 #define DBG 0
35 
36 #ifdef DBG
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)
40 #else
41 #define KdPrint(x)
42 #define HPT_ASSERT(x)
43 #endif
44 
45 #define HPT_SRB_MAX_REQ_SIZE                600
46 #define HPT_SRB_MAX_QUEUE_SIZE              0x100
47 
48 /* beyond 64G mem */
49 #define HPT_SRB_FLAG_HIGH_MEM_ACESS         0x1
50 #define HPT_SRB_MAX_SIZE  ((sizeof(struct hpt_iop_srb) + 0x1f) & ~0x1f)
51 #ifndef offsetof
52 #define offsetof(TYPE, MEM) ((size_t)&((TYPE*)0)->MEM)
53 #endif
54 
55 #ifndef MIN
56 #define MIN(a, b)		((a) < (b) ? (a) : (b))
57 #endif
58 
59 #define HPT_IOCTL_MAGIC   0xA1B2C3D4
60 #define HPT_IOCTL_MAGIC32   0x1A2B3C4D
61 
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;
77 };
78 
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
86 
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
92 
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
98 
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];
110 };
111 
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;
118 };
119 
120 #define CL_POINTER_TOGGLE        0x00004000
121 #define CPU_TO_F0_DRBL_MSG_A_BIT 0x02000000
122 
123 #pragma pack(1)
124 struct hpt_iopmu_mvfrey {
125 	u_int32_t reserved[0x4000 / 4];
126 
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 */
147 
148 	u_int32_t reserved8[(0x10200 - 0x4090) / 4];
149 
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 */
158 
159 	u_int32_t reserved9[(0x10400 - 0x1021c) / 4];
160 
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 */
168 };
169 
170 struct mvfrey_inlist_entry {
171 	u_int64_t addr;
172 	u_int32_t intrfc_len;
173 	u_int32_t reserved;
174 };
175 
176 struct mvfrey_outlist_entry {
177 	u_int32_t val;
178 };
179 
180 #pragma pack()
181 
182 #define MVIOP_IOCTLCFG_SIZE	0x800
183 #define MVIOP_MU_QUEUE_ADDR_HOST_MASK   (~(0x1full))
184 #define MVIOP_MU_QUEUE_ADDR_HOST_BIT    4
185 
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
189 
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
194 
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)
200 
201 #define MVIOP_REQUEST_NUMBER_START_BIT 16
202 
203 #define MVFREYIOPMU_QUEUE_REQUEST_RESULT_BIT   0x40000000
204 
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,
222 };
223 
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
228 
229 #define IOP_REQUEST_FLAG_ADDR_BITS 0x40 /* flags[31:16] is phy_addr[47:32] */
230 
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,
237 	IOP_REQUEST_TYPE_MAX
238 };
239 
240 enum hpt_iop_result_type {
241 	IOP_RESULT_PENDING = 0,
242 	IOP_RESULT_SUCCESS,
243 	IOP_RESULT_FAIL,
244 	IOP_RESULT_BUSY,
245 	IOP_RESULT_RESET,
246 	IOP_RESULT_INVALID_REQUEST,
247 	IOP_RESULT_BAD_TARGET,
248 	IOP_RESULT_CHECK_CONDITION,
249 };
250 
251 #pragma pack(1)
252 struct hpt_iop_request_header {
253 	u_int32_t size;
254 	u_int32_t type;
255 	u_int32_t flags;
256 	u_int32_t result;
257 	u_int64_t context; /* host context */
258 };
259 
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;
271 };
272 
273 struct hpt_iop_request_set_config {
274 	struct hpt_iop_request_header header;
275 	u_int32_t iop_id;
276 	u_int16_t vbus_id;
277 	u_int16_t max_host_request_size;
278 	u_int32_t reserve[6];
279 };
280 
281 struct hpt_iopsg {
282 	u_int32_t size;
283 	u_int32_t eot; /* non-zero: end of table */
284 	u_int64_t pci_address;
285 };
286 
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;
294 	u_int8_t     channel;
295 	u_int8_t     target;
296 	u_int8_t     lun;
297 	u_int8_t     pad1;
298 	u_int16_t    command; /* IOP_BLOCK_COMMAND_{READ,WRITE} */
299 	u_int16_t    sectors;
300 	u_int64_t    lba;
301 	struct hpt_iopsg sg_list[1];
302 };
303 
304 struct hpt_iop_request_scsi_command {
305 	struct hpt_iop_request_header header;
306 	u_int8_t     channel;
307 	u_int8_t     target;
308 	u_int8_t     lun;
309 	u_int8_t     pad1;
310 	u_int8_t     cdb[16];
311 	u_int32_t    dataxfer_length;
312 	struct hpt_iopsg sg_list[1];
313 };
314 
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;
321 	u_int8_t     buf[1];
322 	/* out data should be put at buf[(inbuf_size+3)&~3] */
323 };
324 
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 */
333 } __packed;
334 
335 #define HPT_IOCTL_FLAG_OPEN 1
336 #define HPT_CTL_CODE_BSD_TO_IOP(x) ((x)-0xff00)
337 
338 typedef struct cdev * ioctl_dev_t;
339 
340 typedef struct thread * ioctl_thread_t;
341 
342 struct hpt_iop_hba {
343 	struct hptiop_adapter_ops *ops;
344 	union {
345 		struct {
346 			struct hpt_iopmu_itl *mu;
347 		} itl;
348 		struct {
349 			struct hpt_iopmv_regs *regs;
350 			struct hpt_iopmu_mv *mu;
351 		} mv;
352 		struct {
353 			struct hpt_iop_request_get_config *config;
354 			struct hpt_iopmu_mvfrey *mu;
355 
356 			int internal_mem_size;
357 			int list_count;
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;
366 		} mvfrey;
367 	} u;
368 
369 	struct hpt_iop_hba    *next;
370 
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;
377 
378 	u_int32_t             msg_done;
379 
380 	device_t              pcidev;
381 	u_int32_t             pciunit;
382 	ioctl_dev_t           ioctl_dev;
383 
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;
388 
389 	bus_dmamap_t          srb_dmamap;
390 	bus_dmamap_t          ctlcfg_dmamap;
391 
392 	struct resource       *bar0_res;
393 	bus_space_tag_t       bar0t;
394 	bus_space_handle_t    bar0h;
395 	int                   bar0_rid;
396 
397 	struct resource       *bar2_res;
398 	bus_space_tag_t	      bar2t;
399 	bus_space_handle_t    bar2h;
400 	int                   bar2_rid;
401 
402 	/* to release */
403 	u_int8_t              *uncached_ptr;
404 	void		      *ctlcfg_ptr;
405 	/* for scsi request block */
406 	struct hpt_iop_srb    *srb_list;
407 	/* for interrupt */
408 	struct resource       *irq_res;
409 	void                  *irq_handle;
410 
411 	/* for ioctl and set/get config */
412 	struct resource	      *ctlcfg_res;
413 	void		      *ctlcfg_handle;
414 	u_int64_t             ctlcfgcmd_phy;
415 	u_int32_t             config_done; /* can be negative value */
416 	u_int32_t             initialized:1;
417 
418 	/* other resources */
419 	struct cam_sim        *sim;
420 	struct cam_path       *path;
421 	void                  *req;
422 	struct mtx            lock;
423 #define HPT_IOCTL_FLAG_OPEN     1
424 	u_int32_t             flag;
425 	struct hpt_iop_srb* srb[HPT_SRB_MAX_QUEUE_SIZE];
426 };
427 #pragma pack()
428 
429 enum hptiop_family {
430 	INTEL_BASED_IOP = 0,
431 	MV_BASED_IOP,
432 	MVFREY_BASED_IOP,
433 	UNKNOWN_BASED_IOP = 0xf
434 };
435 
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);
454 };
455 
456 struct hpt_iop_srb {
457 	u_int8_t             req[HPT_SRB_MAX_REQ_SIZE];
458 	struct hpt_iop_hba   *hba;
459 	union ccb            *ccb;
460 	struct hpt_iop_srb   *next;
461 	bus_dmamap_t         dma_map;
462 	u_int64_t            phy_addr;
463 	u_int32_t            srb_flag;
464 	int                  index;
465 	struct callout	     timeout;
466 };
467 
468 #define hptiop_lock_adapter(hba)   mtx_lock(&(hba)->lock)
469 #define hptiop_unlock_adapter(hba) mtx_unlock(&(hba)->lock)
470 
471 #define HPT_OSM_TIMEOUT (20*hz)  /* timeout value for OS commands */
472 
473 #define HPT_DO_IOCONTROL    _IOW('H', 0, struct hpt_iop_ioctl_param)
474 #define HPT_SCAN_BUS        _IO('H', 1)
475 
476 static  __inline int hptiop_sleep(struct hpt_iop_hba *hba, void *ident,
477 				int priority, const char *wmesg, int timo)
478 {
479 
480 	int retval;
481 
482 	retval = msleep(ident, &hba->lock, priority, wmesg, timo);
483 
484 	return retval;
485 
486 }
487 
488 
489 #define HPT_DEV_MAJOR   200
490 
491 #endif
492 
493