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