hptiop.h revision 190398
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: head/sys/dev/hptiop/hptiop.h 190398 2009-03-25 00:57:09Z delphij $");
31
32#define DBG 0
33
34#ifdef DBG
35int hpt_iop_dbg_level = 0;
36#define KdPrint(x)  do { if (hpt_iop_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
60struct 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
98struct 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
110struct 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
139enum 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
162enum 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
171enum 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
182struct 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
190struct 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
203struct 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
211struct 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
222struct 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
234struct 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
245struct 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
255struct 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} __attribute__((packed));
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
269typedef struct cdev * ioctl_dev_t;
270#else
271typedef dev_t ioctl_dev_t;
272#endif
273
274#if __FreeBSD_version >= 500000
275typedef struct thread * ioctl_thread_t;
276#else
277typedef struct proc * ioctl_thread_t;
278#endif
279
280struct 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
354struct 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
372struct 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
387static __inline void hptiop_lock_adapter(struct hpt_iop_hba *hba)
388{
389	hba->hpt_splx = splcam();
390}
391static __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
402static  __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