summaryrefslogtreecommitdiffstats
path: root/sys/dev/hptiop/hptiop.h
blob: fc332e590aa71643856ffd7e75b72942f3371481 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
/*
 * HighPoint RR3xxx RAID Driver for FreeBSD
 * Copyright (C) 2005-2007 HighPoint Technologies, Inc. All Rights Reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef _HPTIOP_H
#define _HPTIOP_H

#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");

#ifdef DBG
int hpt_dbg_level = 0;
#define KdPrint(x)  do { if (hpt_dbg_level) printf x; } while (0)
#define HPT_ASSERT(x) assert(x)
#else
#define KdPrint(x)
#define HPT_ASSERT(x)
#endif

#define HPT_SRB_MAX_REQ_SIZE                600
#define HPT_SRB_MAX_QUEUE_SIZE              0x100

/* beyond 64G mem */
#define HPT_SRB_FLAG_HIGH_MEM_ACESS         0x1
#define HPT_SRB_MAX_SIZE  ((sizeof(struct hpt_iop_srb) + 0x1f) & ~0x1f)

#define HPT_IOCTL_MAGIC   0xA1B2C3D4
#define HPT_IOCTL_MAGIC32 0x1A2B3C4D


struct hpt_iopmu
{
	u_int32_t resrved0[4];
	u_int32_t inbound_msgaddr0;
	u_int32_t inbound_msgaddr1;
	u_int32_t outbound_msgaddr0;
	u_int32_t outbound_msgaddr1;
	u_int32_t inbound_doorbell;
	u_int32_t inbound_intstatus;
	u_int32_t inbound_intmask;
	u_int32_t outbound_doorbell;
	u_int32_t outbound_intstatus;
	u_int32_t outbound_intmask;
	u_int32_t reserved1[2];
	u_int32_t inbound_queue;
	u_int32_t outbound_queue;
};

struct hpt_iop_ioctl_param {
	u_int32_t        Magic;                 /* used to check if it's a valid ioctl packet */
	u_int32_t        dwIoControlCode;       /* operation control code */
	unsigned long   lpInBuffer;            /* input data buffer */
	u_int32_t        nInBufferSize;         /* size of input data buffer */
	unsigned long   lpOutBuffer;           /* output data buffer */
	u_int32_t        nOutBufferSize;        /* size of output data buffer */
	unsigned long   lpBytesReturned;       /* count of HPT_U8s returned */
} __attribute__((packed));


struct hpt_iop_srb {
	u_int8_t           req[HPT_SRB_MAX_REQ_SIZE];
	struct hpt_iop_hba     *hba;
	union ccb        *ccb;
	struct hpt_iop_srb *    next;
	bus_dmamap_t     dma_map;
	u_int32_t          phy_addr;
	u_int32_t          srb_flag;
	int              index;
};

#define IOPMU_QUEUE_EMPTY            0xffffffff
#define IOPMU_QUEUE_MASK_HOST_BITS   0xf0000000
#define IOPMU_QUEUE_ADDR_HOST_BIT    0x80000000
#define IOPMU_QUEUE_REQUEST_SIZE_BIT    0x40000000
#define IOPMU_QUEUE_REQUEST_RESULT_BIT   0x40000000
#define IOPMU_MAX_MEM_SUPPORT_MASK_64G 0xfffffff000000000ull
#define IOPMU_MAX_MEM_SUPPORT_MASK_32G 0xfffffff800000000ull

#define IOPMU_OUTBOUND_INT_MSG0      1
#define IOPMU_OUTBOUND_INT_MSG1      2
#define IOPMU_OUTBOUND_INT_DOORBELL  4
#define IOPMU_OUTBOUND_INT_POSTQUEUE 8
#define IOPMU_OUTBOUND_INT_PCI       0x10

#define IOPMU_INBOUND_INT_MSG0       1
#define IOPMU_INBOUND_INT_MSG1       2
#define IOPMU_INBOUND_INT_DOORBELL   4
#define IOPMU_INBOUND_INT_ERROR      8
#define IOPMU_INBOUND_INT_POSTQUEUE  0x10

enum hpt_iopmu_message {
	/* host-to-iop messages */
	IOPMU_INBOUND_MSG0_NOP = 0,
	IOPMU_INBOUND_MSG0_RESET,
	IOPMU_INBOUND_MSG0_FLUSH,
	IOPMU_INBOUND_MSG0_SHUTDOWN,
	IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK,
	IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK,
	IOPMU_INBOUND_MSG0_MAX = 0xff,
	/* iop-to-host messages */
	IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_0 = 0x100,
	IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_MAX = 0x1ff,
	IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_0 = 0x200,
	IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_MAX = 0x2ff,
	IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_0 = 0x300,
	IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_MAX = 0x3ff,
};

struct hpt_iop_request_header
{
	u_int32_t size;
	u_int32_t type;
	u_int32_t flags;
	u_int32_t result;
	u_int32_t context; /* host context */
	u_int32_t context_hi32;
};

#define IOP_REQUEST_FLAG_SYNC_REQUEST 1
#define IOP_REQUEST_FLAG_BIST_REQUEST 2
#define IOP_REQUEST_FLAG_REMAPPED     4
#define IOP_REQUEST_FLAG_OUTPUT_CONTEXT 8

enum hpt_iop_request_type {
	IOP_REQUEST_TYPE_GET_CONFIG = 0,
	IOP_REQUEST_TYPE_SET_CONFIG,
	IOP_REQUEST_TYPE_BLOCK_COMMAND,
	IOP_REQUEST_TYPE_SCSI_COMMAND,
	IOP_REQUEST_TYPE_IOCTL_COMMAND,
	IOP_REQUEST_TYPE_MAX
};

enum hpt_iop_result_type {
	IOP_RESULT_PENDING = 0,
	IOP_RESULT_SUCCESS,
	IOP_RESULT_FAIL,
	IOP_RESULT_BUSY,
	IOP_RESULT_RESET,
	IOP_RESULT_INVALID_REQUEST,
	IOP_RESULT_BAD_TARGET,
	IOP_RESULT_MODE_SENSE_CHECK_CONDITION,
};

struct hpt_iop_request_get_config
{
	struct hpt_iop_request_header header;
	u_int32_t interface_version;
	u_int32_t firmware_version;
	u_int32_t max_requests;
	u_int32_t request_size;
	u_int32_t max_sg_count;
	u_int32_t data_transfer_length;
	u_int32_t alignment_mask;
	u_int32_t max_devices;
	u_int32_t sdram_size;
};

struct hpt_iop_request_set_config
{
	struct hpt_iop_request_header header;
	u_int32_t iop_id;
	u_int16_t vbus_id;
	u_int16_t max_host_request_size;	
	u_int32_t reserve[6];
};

struct hpt_iopsg
{
	u_int32_t size;
	u_int32_t eot; /* non-zero: end of table */
	u_int64_t pci_address;
};

struct hpt_iop_request_block_command
{
	struct hpt_iop_request_header header;
	u_int8_t     channel;
	u_int8_t     target;
	u_int8_t     lun;
	u_int8_t     pad1;
	u_int16_t   command; /* IOP_BLOCK_COMMAND_{READ,WRITE} */
	u_int16_t   sectors;
	u_int64_t   lba;
	struct hpt_iopsg sg_list[1];
};

#define IOP_BLOCK_COMMAND_READ     1
#define IOP_BLOCK_COMMAND_WRITE    2
#define IOP_BLOCK_COMMAND_VERIFY   3
#define IOP_BLOCK_COMMAND_FLUSH    4
#define IOP_BLOCK_COMMAND_SHUTDOWN 5

struct hpt_iop_request_scsi_command
{
	struct hpt_iop_request_header header;
	u_int8_t     channel;
	u_int8_t     target;
	u_int8_t     lun;
	u_int8_t     pad1;
	u_int8_t     cdb[16];
	u_int32_t   dataxfer_length;
	struct hpt_iopsg sg_list[1];
};

struct hpt_iop_request_ioctl_command
{
	struct hpt_iop_request_header header;
	u_int32_t    ioctl_code;
	u_int32_t    inbuf_size;
	u_int32_t    outbuf_size;
	u_int32_t    bytes_returned;
	u_int8_t     buf[1];
	/* out data should be put at buf[(inbuf_size+3)&~3] */
};

#define HPT_CTL_CODE_BSD_TO_IOP(x) ((x)-0xff00)

#if __FreeBSD_version>503000
typedef struct cdev * ioctl_dev_t;
#else
typedef dev_t ioctl_dev_t;
#endif

#if __FreeBSD_version >= 500000
typedef struct thread * ioctl_thread_t;
#else
typedef struct proc * ioctl_thread_t;
#endif

struct hpt_iop_hba {
	struct hpt_iopmu    *iop;
	struct hpt_iop_hba *next;
	
	u_int32_t             firmware_version;
	u_int32_t             interface_version;	
	u_int32_t             max_devices;
	u_int32_t             max_requests;
	u_int32_t             max_request_size;
	u_int32_t             max_sg_count;

	int                 msg_done;

	device_t            pcidev;
	u_int32_t           pciunit;
	ioctl_dev_t         ioctl_dev;

	struct resource    *bar0_res;
	int                 bar0_rid;

	bus_dma_tag_t       parent_dmat;
	bus_dma_tag_t       io_dmat;
	bus_dma_tag_t       srb_dmat;
	bus_dmamap_t        srb_dmamap;
	/* to release */
	u_int8_t              *uncached_ptr;
	/* for scsi request block */
	struct hpt_iop_srb   *srb_list;
	/* for interrupt */
	struct resource     *irq_res;
	void                *irq_handle;
	/* other resources */
	struct cam_sim      *sim;
	struct cam_path     *path;
	void                *req;
#if (__FreeBSD_version >= 500000)
	struct mtx          lock;
#else
	int                 hpt_splx;
#endif
#define HPT_IOCTL_FLAG_OPEN     1
	u_int32_t             flag;
	struct hpt_iop_srb* srb[HPT_SRB_MAX_QUEUE_SIZE];
};

#if __FreeBSD_version >= 500000
#define hptiop_lock_adapter(hba)   mtx_lock(&(hba)->lock)
#define hptiop_unlock_adapter(hba) mtx_unlock(&(hba)->lock)
#else
static __inline void hptiop_lock_adapter(struct hpt_iop_hba *hba)
{
	hba->hpt_splx = splcam();
}
static __inline void hptiop_unlock_adapter(struct hpt_iop_hba *hba)
{
	splx(hba->hpt_splx);
}
#endif

#define HPT_OSM_TIMEOUT (20*hz)  /* timeout value for OS commands */

#define HPT_DO_IOCONTROL    _IOW('H', 0, struct hpt_iop_ioctl_param)
#define HPT_SCAN_BUS        _IO('H', 1)

static  __inline int hptiop_sleep(struct hpt_iop_hba *hba, void *ident,
				int priority, const char *wmesg, int timo)
{

	int retval;

#if __FreeBSD_version >= 500000
	retval = msleep(ident, &hba->lock, priority, wmesg, timo);
#else
	asleep(ident, priority, wmesg, timo);
	hptiop_unlock_adapter(hba);
	retval = await(priority, timo);
	hptiop_lock_adapter(hba);
#endif

	return retval;

}

#if __FreeBSD_version < 501000
#define READ_16             0x88
#define WRITE_16            0x8a
#define SERVICE_ACTION_IN   0x9e
#endif

#define HPT_DEV_MAJOR   200

#endif

OpenPOWER on IntegriCloud