Blame view

drivers/scsi/hptiop.c 45.4 KB
8e8e69d67   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
2
  /*
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
3
   * HighPoint RR3xxx/4xxx controller driver for Linux
a93429c30   linux   hptiop: Support H...
4
   * Copyright (C) 2006-2015 HighPoint Technologies, Inc. All Rights Reserved.
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
5
   *
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
6
7
8
9
   * Please report bugs/comments/suggestions to linux@highpoint-tech.com
   *
   * For more information, visit http://www.highpoint-tech.com
   */
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
10
11
12
13
14
15
16
17
18
19
  #include <linux/module.h>
  #include <linux/types.h>
  #include <linux/string.h>
  #include <linux/kernel.h>
  #include <linux/pci.h>
  #include <linux/interrupt.h>
  #include <linux/errno.h>
  #include <linux/delay.h>
  #include <linux/timer.h>
  #include <linux/spinlock.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
20
  #include <linux/gfp.h>
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
21
  #include <linux/uaccess.h>
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
22
23
24
25
26
27
28
29
30
31
32
  #include <asm/io.h>
  #include <asm/div64.h>
  #include <scsi/scsi_cmnd.h>
  #include <scsi/scsi_device.h>
  #include <scsi/scsi.h>
  #include <scsi/scsi_tcq.h>
  #include <scsi/scsi_host.h>
  
  #include "hptiop.h"
  
  MODULE_AUTHOR("HighPoint Technologies, Inc.");
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
33
  MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx/4xxx Controller Driver");
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
34
35
  
  static char driver_name[] = "hptiop";
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
36
  static const char driver_name_long[] = "RocketRAID 3xxx/4xxx Controller driver";
a93429c30   linux   hptiop: Support H...
37
  static const char driver_ver[] = "v1.10.0";
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
38
39
40
41
42
43
  
  static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec);
  static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag,
  				struct hpt_iop_request_scsi_command *req);
  static void hptiop_host_request_callback_itl(struct hptiop_hba *hba, u32 tag);
  static void hptiop_iop_request_callback_itl(struct hptiop_hba *hba, u32 tag);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
44
  static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
45
  static int iop_wait_ready_itl(struct hptiop_hba *hba, u32 millisec)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
46
47
48
49
50
  {
  	u32 req = 0;
  	int i;
  
  	for (i = 0; i < millisec; i++) {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
51
  		req = readl(&hba->u.itl.iop->inbound_queue);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
52
53
54
55
56
57
  		if (req != IOPMU_QUEUE_EMPTY)
  			break;
  		msleep(1);
  	}
  
  	if (req != IOPMU_QUEUE_EMPTY) {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
58
59
  		writel(req, &hba->u.itl.iop->outbound_queue);
  		readl(&hba->u.itl.iop->outbound_intstatus);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
60
61
62
63
64
  		return 0;
  	}
  
  	return -1;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
65
66
67
68
  static int iop_wait_ready_mv(struct hptiop_hba *hba, u32 millisec)
  {
  	return iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec);
  }
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
69
70
71
72
  static int iop_wait_ready_mvfrey(struct hptiop_hba *hba, u32 millisec)
  {
  	return iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec);
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
73
  static void hptiop_request_callback_itl(struct hptiop_hba *hba, u32 tag)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
74
  {
db9b6e89e   HighPoint Linux Team   [SCSI] hptiop: ad...
75
  	if (tag & IOPMU_QUEUE_ADDR_HOST_BIT)
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
76
  		hptiop_host_request_callback_itl(hba,
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
77
78
  				tag & ~IOPMU_QUEUE_ADDR_HOST_BIT);
  	else
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
79
  		hptiop_iop_request_callback_itl(hba, tag);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
80
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
81
  static void hptiop_drain_outbound_queue_itl(struct hptiop_hba *hba)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
82
83
  {
  	u32 req;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
84
85
  	while ((req = readl(&hba->u.itl.iop->outbound_queue)) !=
  						IOPMU_QUEUE_EMPTY) {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
86
87
  
  		if (req & IOPMU_QUEUE_MASK_HOST_BITS)
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
88
  			hptiop_request_callback_itl(hba, req);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
89
90
91
92
  		else {
  			struct hpt_iop_request_header __iomem * p;
  
  			p = (struct hpt_iop_request_header __iomem *)
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
93
  				((char __iomem *)hba->u.itl.iop + req);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
94
95
96
  
  			if (readl(&p->flags) & IOP_REQUEST_FLAG_SYNC_REQUEST) {
  				if (readl(&p->context))
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
97
  					hptiop_request_callback_itl(hba, req);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
98
99
100
101
  				else
  					writel(1, &p->context);
  			}
  			else
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
102
  				hptiop_request_callback_itl(hba, req);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
103
104
105
  		}
  	}
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
106
  static int iop_intr_itl(struct hptiop_hba *hba)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
107
  {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
108
  	struct hpt_iopmu_itl __iomem *iop = hba->u.itl.iop;
3bfc13c23   HighPoint Linux Team   [SCSI] hptiop: Ad...
109
  	void __iomem *plx = hba->u.itl.plx;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
110
111
  	u32 status;
  	int ret = 0;
3bfc13c23   HighPoint Linux Team   [SCSI] hptiop: Ad...
112
113
  	if (plx && readl(plx + 0x11C5C) & 0xf)
  		writel(1, plx + 0x11C60);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
114
115
116
117
  	status = readl(&iop->outbound_intstatus);
  
  	if (status & IOPMU_OUTBOUND_INT_MSG0) {
  		u32 msg = readl(&iop->outbound_msgaddr0);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
118

ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
119
120
121
122
123
124
125
126
  		dprintk("received outbound msg %x
  ", msg);
  		writel(IOPMU_OUTBOUND_INT_MSG0, &iop->outbound_intstatus);
  		hptiop_message_callback(hba, msg);
  		ret = 1;
  	}
  
  	if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
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
  		hptiop_drain_outbound_queue_itl(hba);
  		ret = 1;
  	}
  
  	return ret;
  }
  
  static u64 mv_outbound_read(struct hpt_iopmu_mv __iomem *mu)
  {
  	u32 outbound_tail = readl(&mu->outbound_tail);
  	u32 outbound_head = readl(&mu->outbound_head);
  
  	if (outbound_tail != outbound_head) {
  		u64 p;
  
  		memcpy_fromio(&p, &mu->outbound_q[mu->outbound_tail], 8);
  		outbound_tail++;
  
  		if (outbound_tail == MVIOP_QUEUE_LEN)
  			outbound_tail = 0;
  		writel(outbound_tail, &mu->outbound_tail);
  		return p;
  	} else
  		return 0;
  }
  
  static void mv_inbound_write(u64 p, struct hptiop_hba *hba)
  {
  	u32 inbound_head = readl(&hba->u.mv.mu->inbound_head);
  	u32 head = inbound_head + 1;
  
  	if (head == MVIOP_QUEUE_LEN)
  		head = 0;
  
  	memcpy_toio(&hba->u.mv.mu->inbound_q[inbound_head], &p, 8);
  	writel(head, &hba->u.mv.mu->inbound_head);
  	writel(MVIOP_MU_INBOUND_INT_POSTQUEUE,
  			&hba->u.mv.regs->inbound_doorbell);
  }
  
  static void hptiop_request_callback_mv(struct hptiop_hba *hba, u64 tag)
  {
  	u32 req_type = (tag >> 5) & 0x7;
  	struct hpt_iop_request_scsi_command *req;
  
  	dprintk("hptiop_request_callback_mv: tag=%llx
  ", tag);
  
  	BUG_ON((tag & MVIOP_MU_QUEUE_REQUEST_RETURN_CONTEXT) == 0);
  
  	switch (req_type) {
  	case IOP_REQUEST_TYPE_GET_CONFIG:
  	case IOP_REQUEST_TYPE_SET_CONFIG:
  		hba->msg_done = 1;
  		break;
  
  	case IOP_REQUEST_TYPE_SCSI_COMMAND:
  		req = hba->reqs[tag >> 8].req_virt;
  		if (likely(tag & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT))
  			req->header.result = cpu_to_le32(IOP_RESULT_SUCCESS);
  
  		hptiop_finish_scsi_req(hba, tag>>8, req);
  		break;
  
  	default:
  		break;
  	}
  }
  
  static int iop_intr_mv(struct hptiop_hba *hba)
  {
  	u32 status;
  	int ret = 0;
  
  	status = readl(&hba->u.mv.regs->outbound_doorbell);
  	writel(~status, &hba->u.mv.regs->outbound_doorbell);
  
  	if (status & MVIOP_MU_OUTBOUND_INT_MSG) {
  		u32 msg;
  		msg = readl(&hba->u.mv.mu->outbound_msg);
  		dprintk("received outbound msg %x
  ", msg);
  		hptiop_message_callback(hba, msg);
  		ret = 1;
  	}
  
  	if (status & MVIOP_MU_OUTBOUND_INT_POSTQUEUE) {
  		u64 tag;
  
  		while ((tag = mv_outbound_read(hba->u.mv.mu)))
  			hptiop_request_callback_mv(hba, tag);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
218
219
220
221
222
  		ret = 1;
  	}
  
  	return ret;
  }
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
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
  static void hptiop_request_callback_mvfrey(struct hptiop_hba *hba, u32 _tag)
  {
  	u32 req_type = _tag & 0xf;
  	struct hpt_iop_request_scsi_command *req;
  
  	switch (req_type) {
  	case IOP_REQUEST_TYPE_GET_CONFIG:
  	case IOP_REQUEST_TYPE_SET_CONFIG:
  		hba->msg_done = 1;
  		break;
  
  	case IOP_REQUEST_TYPE_SCSI_COMMAND:
  		req = hba->reqs[(_tag >> 4) & 0xff].req_virt;
  		if (likely(_tag & IOPMU_QUEUE_REQUEST_RESULT_BIT))
  			req->header.result = IOP_RESULT_SUCCESS;
  		hptiop_finish_scsi_req(hba, (_tag >> 4) & 0xff, req);
  		break;
  
  	default:
  		break;
  	}
  }
  
  static int iop_intr_mvfrey(struct hptiop_hba *hba)
  {
  	u32 _tag, status, cptr, cur_rptr;
  	int ret = 0;
  
  	if (hba->initialized)
  		writel(0, &(hba->u.mvfrey.mu->pcie_f0_int_enable));
  
  	status = readl(&(hba->u.mvfrey.mu->f0_doorbell));
  	if (status) {
  		writel(status, &(hba->u.mvfrey.mu->f0_doorbell));
  		if (status & CPU_TO_F0_DRBL_MSG_BIT) {
  			u32 msg = readl(&(hba->u.mvfrey.mu->cpu_to_f0_msg_a));
  			dprintk("received outbound msg %x
  ", msg);
  			hptiop_message_callback(hba, msg);
  		}
  		ret = 1;
  	}
  
  	status = readl(&(hba->u.mvfrey.mu->isr_cause));
  	if (status) {
  		writel(status, &(hba->u.mvfrey.mu->isr_cause));
  		do {
  			cptr = *hba->u.mvfrey.outlist_cptr & 0xff;
  			cur_rptr = hba->u.mvfrey.outlist_rptr;
  			while (cur_rptr != cptr) {
  				cur_rptr++;
  				if (cur_rptr ==	hba->u.mvfrey.list_count)
  					cur_rptr = 0;
  
  				_tag = hba->u.mvfrey.outlist[cur_rptr].val;
  				BUG_ON(!(_tag & IOPMU_QUEUE_MASK_HOST_BITS));
  				hptiop_request_callback_mvfrey(hba, _tag);
  				ret = 1;
  			}
  			hba->u.mvfrey.outlist_rptr = cur_rptr;
  		} while (cptr != (*hba->u.mvfrey.outlist_cptr & 0xff));
  	}
  
  	if (hba->initialized)
  		writel(0x1010, &(hba->u.mvfrey.mu->pcie_f0_int_enable));
  
  	return ret;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
291
  static int iop_send_sync_request_itl(struct hptiop_hba *hba,
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
292
293
294
295
  					void __iomem *_req, u32 millisec)
  {
  	struct hpt_iop_request_header __iomem *req = _req;
  	u32 i;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
296
  	writel(readl(&req->flags) | IOP_REQUEST_FLAG_SYNC_REQUEST, &req->flags);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
297
  	writel(0, &req->context);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
298
299
300
  	writel((unsigned long)req - (unsigned long)hba->u.itl.iop,
  			&hba->u.itl.iop->inbound_queue);
  	readl(&hba->u.itl.iop->outbound_intstatus);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
301
302
  
  	for (i = 0; i < millisec; i++) {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
303
  		iop_intr_itl(hba);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
304
305
306
307
308
309
310
  		if (readl(&req->context))
  			return 0;
  		msleep(1);
  	}
  
  	return -1;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
311
312
  static int iop_send_sync_request_mv(struct hptiop_hba *hba,
  					u32 size_bits, u32 millisec)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
313
  {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
314
  	struct hpt_iop_request_header *reqhdr = hba->u.mv.internal_req;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
315
316
317
  	u32 i;
  
  	hba->msg_done = 0;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
318
319
320
321
322
323
324
325
326
327
328
329
  	reqhdr->flags |= cpu_to_le32(IOP_REQUEST_FLAG_SYNC_REQUEST);
  	mv_inbound_write(hba->u.mv.internal_req_phy |
  			MVIOP_MU_QUEUE_ADDR_HOST_BIT | size_bits, hba);
  
  	for (i = 0; i < millisec; i++) {
  		iop_intr_mv(hba);
  		if (hba->msg_done)
  			return 0;
  		msleep(1);
  	}
  	return -1;
  }
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
  static int iop_send_sync_request_mvfrey(struct hptiop_hba *hba,
  					u32 size_bits, u32 millisec)
  {
  	struct hpt_iop_request_header *reqhdr =
  		hba->u.mvfrey.internal_req.req_virt;
  	u32 i;
  
  	hba->msg_done = 0;
  	reqhdr->flags |= cpu_to_le32(IOP_REQUEST_FLAG_SYNC_REQUEST);
  	hba->ops->post_req(hba, &(hba->u.mvfrey.internal_req));
  
  	for (i = 0; i < millisec; i++) {
  		iop_intr_mvfrey(hba);
  		if (hba->msg_done)
  			break;
  		msleep(1);
  	}
  	return hba->msg_done ? 0 : -1;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
349
350
351
352
353
354
355
356
357
358
359
360
  static void hptiop_post_msg_itl(struct hptiop_hba *hba, u32 msg)
  {
  	writel(msg, &hba->u.itl.iop->inbound_msgaddr0);
  	readl(&hba->u.itl.iop->outbound_intstatus);
  }
  
  static void hptiop_post_msg_mv(struct hptiop_hba *hba, u32 msg)
  {
  	writel(msg, &hba->u.mv.mu->inbound_msg);
  	writel(MVIOP_MU_INBOUND_INT_MSG, &hba->u.mv.regs->inbound_doorbell);
  	readl(&hba->u.mv.regs->inbound_doorbell);
  }
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
361

286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
362
363
364
365
366
  static void hptiop_post_msg_mvfrey(struct hptiop_hba *hba, u32 msg)
  {
  	writel(msg, &(hba->u.mvfrey.mu->f0_to_cpu_msg_a));
  	readl(&(hba->u.mvfrey.mu->f0_to_cpu_msg_a));
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
367
368
369
  static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec)
  {
  	u32 i;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
370

00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
371
  	hba->msg_done = 0;
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
372
  	hba->ops->disable_intr(hba);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
373
  	hba->ops->post_msg(hba, msg);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
374
375
376
  
  	for (i = 0; i < millisec; i++) {
  		spin_lock_irq(hba->host->host_lock);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
377
  		hba->ops->iop_intr(hba);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
378
379
380
381
382
  		spin_unlock_irq(hba->host->host_lock);
  		if (hba->msg_done)
  			break;
  		msleep(1);
  	}
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
383
  	hba->ops->enable_intr(hba);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
384
385
  	return hba->msg_done? 0 : -1;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
386
  static int iop_get_config_itl(struct hptiop_hba *hba,
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
387
388
389
390
  				struct hpt_iop_request_get_config *config)
  {
  	u32 req32;
  	struct hpt_iop_request_get_config __iomem *req;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
391
  	req32 = readl(&hba->u.itl.iop->inbound_queue);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
392
393
394
395
  	if (req32 == IOPMU_QUEUE_EMPTY)
  		return -1;
  
  	req = (struct hpt_iop_request_get_config __iomem *)
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
396
  			((unsigned long)hba->u.itl.iop + req32);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
397
398
399
400
401
  
  	writel(0, &req->header.flags);
  	writel(IOP_REQUEST_TYPE_GET_CONFIG, &req->header.type);
  	writel(sizeof(struct hpt_iop_request_get_config), &req->header.size);
  	writel(IOP_RESULT_PENDING, &req->header.result);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
402
  	if (iop_send_sync_request_itl(hba, req, 20000)) {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
403
404
405
406
407
408
  		dprintk("Get config send cmd failed
  ");
  		return -1;
  	}
  
  	memcpy_fromio(config, req, sizeof(*config));
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
409
410
411
412
413
414
415
416
417
418
419
420
421
422
  	writel(req32, &hba->u.itl.iop->outbound_queue);
  	return 0;
  }
  
  static int iop_get_config_mv(struct hptiop_hba *hba,
  				struct hpt_iop_request_get_config *config)
  {
  	struct hpt_iop_request_get_config *req = hba->u.mv.internal_req;
  
  	req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT);
  	req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_GET_CONFIG);
  	req->header.size =
  		cpu_to_le32(sizeof(struct hpt_iop_request_get_config));
  	req->header.result = cpu_to_le32(IOP_RESULT_PENDING);
f6b196a2f   James Bottomley   [SCSI] hptiop: fi...
423
424
  	req->header.context = cpu_to_le32(IOP_REQUEST_TYPE_GET_CONFIG<<5);
  	req->header.context_hi32 = 0;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
425
426
427
428
429
430
431
432
  
  	if (iop_send_sync_request_mv(hba, 0, 20000)) {
  		dprintk("Get config send cmd failed
  ");
  		return -1;
  	}
  
  	memcpy(config, req, sizeof(struct hpt_iop_request_get_config));
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
433
434
  	return 0;
  }
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
  static int iop_get_config_mvfrey(struct hptiop_hba *hba,
  				struct hpt_iop_request_get_config *config)
  {
  	struct hpt_iop_request_get_config *info = hba->u.mvfrey.config;
  
  	if (info->header.size != sizeof(struct hpt_iop_request_get_config) ||
  			info->header.type != IOP_REQUEST_TYPE_GET_CONFIG)
  		return -1;
  
  	config->interface_version = info->interface_version;
  	config->firmware_version = info->firmware_version;
  	config->max_requests = info->max_requests;
  	config->request_size = info->request_size;
  	config->max_sg_count = info->max_sg_count;
  	config->data_transfer_length = info->data_transfer_length;
  	config->alignment_mask = info->alignment_mask;
  	config->max_devices = info->max_devices;
  	config->sdram_size = info->sdram_size;
  
  	return 0;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
456
  static int iop_set_config_itl(struct hptiop_hba *hba,
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
457
458
459
460
  				struct hpt_iop_request_set_config *config)
  {
  	u32 req32;
  	struct hpt_iop_request_set_config __iomem *req;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
461
  	req32 = readl(&hba->u.itl.iop->inbound_queue);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
462
463
464
465
  	if (req32 == IOPMU_QUEUE_EMPTY)
  		return -1;
  
  	req = (struct hpt_iop_request_set_config __iomem *)
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
466
  			((unsigned long)hba->u.itl.iop + req32);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
467
468
469
470
471
472
473
474
475
476
  
  	memcpy_toio((u8 __iomem *)req + sizeof(struct hpt_iop_request_header),
  		(u8 *)config + sizeof(struct hpt_iop_request_header),
  		sizeof(struct hpt_iop_request_set_config) -
  			sizeof(struct hpt_iop_request_header));
  
  	writel(0, &req->header.flags);
  	writel(IOP_REQUEST_TYPE_SET_CONFIG, &req->header.type);
  	writel(sizeof(struct hpt_iop_request_set_config), &req->header.size);
  	writel(IOP_RESULT_PENDING, &req->header.result);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
477
  	if (iop_send_sync_request_itl(hba, req, 20000)) {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
478
479
480
481
  		dprintk("Set config send cmd failed
  ");
  		return -1;
  	}
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
482
  	writel(req32, &hba->u.itl.iop->outbound_queue);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
483
484
  	return 0;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
485
486
  static int iop_set_config_mv(struct hptiop_hba *hba,
  				struct hpt_iop_request_set_config *config)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
487
  {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
488
  	struct hpt_iop_request_set_config *req = hba->u.mv.internal_req;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
489

00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
490
491
492
493
494
495
  	memcpy(req, config, sizeof(struct hpt_iop_request_set_config));
  	req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT);
  	req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_SET_CONFIG);
  	req->header.size =
  		cpu_to_le32(sizeof(struct hpt_iop_request_set_config));
  	req->header.result = cpu_to_le32(IOP_RESULT_PENDING);
f6b196a2f   James Bottomley   [SCSI] hptiop: fi...
496
497
  	req->header.context = cpu_to_le32(IOP_REQUEST_TYPE_SET_CONFIG<<5);
  	req->header.context_hi32 = 0;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
498
499
500
501
502
503
504
505
506
  
  	if (iop_send_sync_request_mv(hba, 0, 20000)) {
  		dprintk("Set config send cmd failed
  ");
  		return -1;
  	}
  
  	return 0;
  }
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
  static int iop_set_config_mvfrey(struct hptiop_hba *hba,
  				struct hpt_iop_request_set_config *config)
  {
  	struct hpt_iop_request_set_config *req =
  		hba->u.mvfrey.internal_req.req_virt;
  
  	memcpy(req, config, sizeof(struct hpt_iop_request_set_config));
  	req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT);
  	req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_SET_CONFIG);
  	req->header.size =
  		cpu_to_le32(sizeof(struct hpt_iop_request_set_config));
  	req->header.result = cpu_to_le32(IOP_RESULT_PENDING);
  	req->header.context = cpu_to_le32(IOP_REQUEST_TYPE_SET_CONFIG<<5);
  	req->header.context_hi32 = 0;
  
  	if (iop_send_sync_request_mvfrey(hba, 0, 20000)) {
  		dprintk("Set config send cmd failed
  ");
  		return -1;
  	}
  
  	return 0;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
530
531
  static void hptiop_enable_intr_itl(struct hptiop_hba *hba)
  {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
532
  	writel(~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0),
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
533
534
535
536
537
538
539
540
  		&hba->u.itl.iop->outbound_intmask);
  }
  
  static void hptiop_enable_intr_mv(struct hptiop_hba *hba)
  {
  	writel(MVIOP_MU_OUTBOUND_INT_POSTQUEUE | MVIOP_MU_OUTBOUND_INT_MSG,
  		&hba->u.mv.regs->outbound_intmask);
  }
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
541
542
543
544
545
546
  static void hptiop_enable_intr_mvfrey(struct hptiop_hba *hba)
  {
  	writel(CPU_TO_F0_DRBL_MSG_BIT, &(hba->u.mvfrey.mu->f0_doorbell_enable));
  	writel(0x1, &(hba->u.mvfrey.mu->isr_enable));
  	writel(0x1010, &(hba->u.mvfrey.mu->pcie_f0_int_enable));
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
547
548
549
550
  static int hptiop_initialize_iop(struct hptiop_hba *hba)
  {
  	/* enable interrupts */
  	hba->ops->enable_intr(hba);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
551
552
553
554
555
556
557
558
559
560
561
562
563
  
  	hba->initialized = 1;
  
  	/* start background tasks */
  	if (iop_send_sync_msg(hba,
  			IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) {
  		printk(KERN_ERR "scsi%d: fail to start background task
  ",
  			hba->host->host_no);
  		return -1;
  	}
  	return 0;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
564
  static void __iomem *hptiop_map_pci_bar(struct hptiop_hba *hba, int index)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
565
566
567
  {
  	u32 mem_base_phy, length;
  	void __iomem *mem_base_virt;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
568

ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
569
  	struct pci_dev *pcidev = hba->pcidev;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
570
571
  
  	if (!(pci_resource_flags(pcidev, index) & IORESOURCE_MEM)) {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
572
573
574
  		printk(KERN_ERR "scsi%d: pci resource invalid
  ",
  				hba->host->host_no);
9bcf09108   Harvey Harrison   scsi: fix integer...
575
  		return NULL;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
576
  	}
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
577
578
  	mem_base_phy = pci_resource_start(pcidev, index);
  	length = pci_resource_len(pcidev, index);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
579
580
581
582
583
584
  	mem_base_virt = ioremap(mem_base_phy, length);
  
  	if (!mem_base_virt) {
  		printk(KERN_ERR "scsi%d: Fail to ioremap memory space
  ",
  				hba->host->host_no);
9bcf09108   Harvey Harrison   scsi: fix integer...
585
  		return NULL;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
586
587
588
589
590
591
  	}
  	return mem_base_virt;
  }
  
  static int hptiop_map_pci_bar_itl(struct hptiop_hba *hba)
  {
3bfc13c23   HighPoint Linux Team   [SCSI] hptiop: Ad...
592
  	struct pci_dev *pcidev = hba->pcidev;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
593
  	hba->u.itl.iop = hptiop_map_pci_bar(hba, 0);
3bfc13c23   HighPoint Linux Team   [SCSI] hptiop: Ad...
594
  	if (hba->u.itl.iop == NULL)
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
595
  		return -1;
3bfc13c23   HighPoint Linux Team   [SCSI] hptiop: Ad...
596
597
598
599
600
601
602
603
604
  	if ((pcidev->device & 0xff00) == 0x4400) {
  		hba->u.itl.plx = hba->u.itl.iop;
  		hba->u.itl.iop = hptiop_map_pci_bar(hba, 2);
  		if (hba->u.itl.iop == NULL) {
  			iounmap(hba->u.itl.plx);
  			return -1;
  		}
  	}
  	return 0;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
605
606
607
608
  }
  
  static void hptiop_unmap_pci_bar_itl(struct hptiop_hba *hba)
  {
3bfc13c23   HighPoint Linux Team   [SCSI] hptiop: Ad...
609
610
  	if (hba->u.itl.plx)
  		iounmap(hba->u.itl.plx);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
611
612
613
614
615
616
  	iounmap(hba->u.itl.iop);
  }
  
  static int hptiop_map_pci_bar_mv(struct hptiop_hba *hba)
  {
  	hba->u.mv.regs = hptiop_map_pci_bar(hba, 0);
9bcf09108   Harvey Harrison   scsi: fix integer...
617
  	if (hba->u.mv.regs == NULL)
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
618
619
620
  		return -1;
  
  	hba->u.mv.mu = hptiop_map_pci_bar(hba, 2);
9bcf09108   Harvey Harrison   scsi: fix integer...
621
  	if (hba->u.mv.mu == NULL) {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
622
  		iounmap(hba->u.mv.regs);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
623
624
  		return -1;
  	}
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
625
626
  	return 0;
  }
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
627
628
629
630
631
632
633
634
635
636
637
638
639
640
  static int hptiop_map_pci_bar_mvfrey(struct hptiop_hba *hba)
  {
  	hba->u.mvfrey.config = hptiop_map_pci_bar(hba, 0);
  	if (hba->u.mvfrey.config == NULL)
  		return -1;
  
  	hba->u.mvfrey.mu = hptiop_map_pci_bar(hba, 2);
  	if (hba->u.mvfrey.mu == NULL) {
  		iounmap(hba->u.mvfrey.config);
  		return -1;
  	}
  
  	return 0;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
641
642
643
644
645
  static void hptiop_unmap_pci_bar_mv(struct hptiop_hba *hba)
  {
  	iounmap(hba->u.mv.regs);
  	iounmap(hba->u.mv.mu);
  }
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
646
647
648
649
650
  static void hptiop_unmap_pci_bar_mvfrey(struct hptiop_hba *hba)
  {
  	iounmap(hba->u.mvfrey.config);
  	iounmap(hba->u.mvfrey.mu);
  }
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
651
652
653
654
  static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg)
  {
  	dprintk("iop message 0x%x
  ", msg);
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
655
656
  	if (msg == IOPMU_INBOUND_MSG0_NOP ||
  		msg == IOPMU_INBOUND_MSG0_RESET_COMM)
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
657
  		hba->msg_done = 1;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
658
659
660
661
662
663
664
665
666
667
  	if (!hba->initialized)
  		return;
  
  	if (msg == IOPMU_INBOUND_MSG0_RESET) {
  		atomic_set(&hba->resetting, 0);
  		wake_up(&hba->reset_wq);
  	}
  	else if (msg <= IOPMU_INBOUND_MSG0_MAX)
  		hba->msg_done = 1;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
668
  static struct hptiop_request *get_req(struct hptiop_hba *hba)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
669
670
671
672
673
674
675
676
677
678
679
680
  {
  	struct hptiop_request *ret;
  
  	dprintk("get_req : req=%p
  ", hba->req_list);
  
  	ret = hba->req_list;
  	if (ret)
  		hba->req_list = ret->next;
  
  	return ret;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
681
  static void free_req(struct hptiop_hba *hba, struct hptiop_request *req)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
682
683
684
685
686
687
  {
  	dprintk("free_req(%d, %p)
  ", req->index, req);
  	req->next = hba->req_list;
  	hba->req_list = req;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
688
689
  static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag,
  				struct hpt_iop_request_scsi_command *req)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
690
  {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
691
  	struct scsi_cmnd *scp;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
692
  	dprintk("hptiop_finish_scsi_req: req=%p, type=%d, "
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
693
694
695
696
697
698
699
700
701
  			"result=%d, context=0x%x tag=%d
  ",
  			req, req->header.type, req->header.result,
  			req->header.context, tag);
  
  	BUG_ON(!req->header.result);
  	BUG_ON(req->header.type != cpu_to_le32(IOP_REQUEST_TYPE_SCSI_COMMAND));
  
  	scp = hba->reqs[tag].scp;
f98754960   FUJITA Tomonori   [SCSI] hptiop: co...
702
703
  	if (HPT_SCP(scp)->mapped)
  		scsi_dma_unmap(scp);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
704
705
706
  
  	switch (le32_to_cpu(req->header.result)) {
  	case IOP_RESULT_SUCCESS:
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
707
708
  		scsi_set_resid(scp,
  			scsi_bufflen(scp) - le32_to_cpu(req->dataxfer_length));
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
  		scp->result = (DID_OK<<16);
  		break;
  	case IOP_RESULT_BAD_TARGET:
  		scp->result = (DID_BAD_TARGET<<16);
  		break;
  	case IOP_RESULT_BUSY:
  		scp->result = (DID_BUS_BUSY<<16);
  		break;
  	case IOP_RESULT_RESET:
  		scp->result = (DID_RESET<<16);
  		break;
  	case IOP_RESULT_FAIL:
  		scp->result = (DID_ERROR<<16);
  		break;
  	case IOP_RESULT_INVALID_REQUEST:
  		scp->result = (DID_ABORT<<16);
  		break;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
726
727
728
  	case IOP_RESULT_CHECK_CONDITION:
  		scsi_set_resid(scp,
  			scsi_bufflen(scp) - le32_to_cpu(req->dataxfer_length));
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
729
  		scp->result = SAM_STAT_CHECK_CONDITION;
a93429c30   linux   hptiop: Support H...
730
  		memcpy(scp->sense_buffer, &req->sg_list, SCSI_SENSE_BUFFERSIZE);
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
731
  		goto skip_resid;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
732
733
734
  		break;
  
  	default:
1c9fbafc8   Martin K. Petersen   [SCSI] Remove SUG...
735
  		scp->result = DRIVER_INVALID << 24 | DID_ABORT << 16;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
736
737
  		break;
  	}
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
738
739
740
741
  	scsi_set_resid(scp,
  		scsi_bufflen(scp) - le32_to_cpu(req->dataxfer_length));
  
  skip_resid:
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
742
743
744
745
746
  	dprintk("scsi_done(%p)
  ", scp);
  	scp->scsi_done(scp);
  	free_req(hba, &hba->reqs[tag]);
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
  static void hptiop_host_request_callback_itl(struct hptiop_hba *hba, u32 _tag)
  {
  	struct hpt_iop_request_scsi_command *req;
  	u32 tag;
  
  	if (hba->iopintf_v2) {
  		tag = _tag & ~IOPMU_QUEUE_REQUEST_RESULT_BIT;
  		req = hba->reqs[tag].req_virt;
  		if (likely(_tag & IOPMU_QUEUE_REQUEST_RESULT_BIT))
  			req->header.result = cpu_to_le32(IOP_RESULT_SUCCESS);
  	} else {
  		tag = _tag;
  		req = hba->reqs[tag].req_virt;
  	}
  
  	hptiop_finish_scsi_req(hba, tag, req);
  }
06d9eb4e7   Colin Ian King   scsi: hptiop: mak...
764
  static void hptiop_iop_request_callback_itl(struct hptiop_hba *hba, u32 tag)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
765
766
767
768
769
770
  {
  	struct hpt_iop_request_header __iomem *req;
  	struct hpt_iop_request_ioctl_command __iomem *p;
  	struct hpt_ioctl_k *arg;
  
  	req = (struct hpt_iop_request_header __iomem *)
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
771
772
  			((unsigned long)hba->u.itl.iop + tag);
  	dprintk("hptiop_iop_request_callback_itl: req=%p, type=%d, "
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
  			"result=%d, context=0x%x tag=%d
  ",
  			req, readl(&req->type), readl(&req->result),
  			readl(&req->context), tag);
  
  	BUG_ON(!readl(&req->result));
  	BUG_ON(readl(&req->type) != IOP_REQUEST_TYPE_IOCTL_COMMAND);
  
  	p = (struct hpt_iop_request_ioctl_command __iomem *)req;
  	arg = (struct hpt_ioctl_k *)(unsigned long)
  		(readl(&req->context) |
  			((u64)readl(&req->context_hi32)<<32));
  
  	if (readl(&req->result) == IOP_RESULT_SUCCESS) {
  		arg->result = HPT_IOCTL_RESULT_OK;
  
  		if (arg->outbuf_size)
  			memcpy_fromio(arg->outbuf,
  				&p->buf[(readl(&p->inbuf_size) + 3)& ~3],
  				arg->outbuf_size);
  
  		if (arg->bytes_returned)
  			*arg->bytes_returned = arg->outbuf_size;
  	}
  	else
  		arg->result = HPT_IOCTL_RESULT_FAILED;
  
  	arg->done(arg);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
801
  	writel(tag, &hba->u.itl.iop->outbound_queue);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
802
  }
7d12e780e   David Howells   IRQ: Maintain reg...
803
  static irqreturn_t hptiop_intr(int irq, void *dev_id)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
804
805
806
807
808
809
  {
  	struct hptiop_hba  *hba = dev_id;
  	int  handled;
  	unsigned long flags;
  
  	spin_lock_irqsave(hba->host->host_lock, flags);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
810
  	handled = hba->ops->iop_intr(hba);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
811
812
813
814
815
816
817
818
819
  	spin_unlock_irqrestore(hba->host->host_lock, flags);
  
  	return handled;
  }
  
  static int hptiop_buildsgl(struct scsi_cmnd *scp, struct hpt_iopsg *psg)
  {
  	struct Scsi_Host *host = scp->device->host;
  	struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
f98754960   FUJITA Tomonori   [SCSI] hptiop: co...
820
821
822
823
824
825
826
  	struct scatterlist *sg;
  	int idx, nseg;
  
  	nseg = scsi_dma_map(scp);
  	BUG_ON(nseg < 0);
  	if (!nseg)
  		return 0;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
827

f98754960   FUJITA Tomonori   [SCSI] hptiop: co...
828
829
830
831
832
833
  	HPT_SCP(scp)->sgcnt = nseg;
  	HPT_SCP(scp)->mapped = 1;
  
  	BUG_ON(HPT_SCP(scp)->sgcnt > hba->max_sg_descriptors);
  
  	scsi_for_each_sg(scp, sg, HPT_SCP(scp)->sgcnt, idx) {
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
834
835
  		psg[idx].pci_address = cpu_to_le64(sg_dma_address(sg)) |
  			hba->ops->host_phy_flag;
f98754960   FUJITA Tomonori   [SCSI] hptiop: co...
836
837
838
  		psg[idx].size = cpu_to_le32(sg_dma_len(sg));
  		psg[idx].eot = (idx == HPT_SCP(scp)->sgcnt - 1) ?
  			cpu_to_le32(1) : 0;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
839
  	}
f98754960   FUJITA Tomonori   [SCSI] hptiop: co...
840
  	return HPT_SCP(scp)->sgcnt;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
841
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
  static void hptiop_post_req_itl(struct hptiop_hba *hba,
  					struct hptiop_request *_req)
  {
  	struct hpt_iop_request_header *reqhdr = _req->req_virt;
  
  	reqhdr->context = cpu_to_le32(IOPMU_QUEUE_ADDR_HOST_BIT |
  							(u32)_req->index);
  	reqhdr->context_hi32 = 0;
  
  	if (hba->iopintf_v2) {
  		u32 size, size_bits;
  
  		size = le32_to_cpu(reqhdr->size);
  		if (size < 256)
  			size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT;
  		else if (size < 512)
  			size_bits = IOPMU_QUEUE_ADDR_HOST_BIT;
  		else
  			size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT |
  						IOPMU_QUEUE_ADDR_HOST_BIT;
  		writel(_req->req_shifted_phy | size_bits,
  			&hba->u.itl.iop->inbound_queue);
  	} else
  		writel(_req->req_shifted_phy | IOPMU_QUEUE_ADDR_HOST_BIT,
  					&hba->u.itl.iop->inbound_queue);
  }
  
  static void hptiop_post_req_mv(struct hptiop_hba *hba,
  					struct hptiop_request *_req)
  {
  	struct hpt_iop_request_header *reqhdr = _req->req_virt;
  	u32 size, size_bit;
  
  	reqhdr->context = cpu_to_le32(_req->index<<8 |
  					IOP_REQUEST_TYPE_SCSI_COMMAND<<5);
  	reqhdr->context_hi32 = 0;
  	size = le32_to_cpu(reqhdr->size);
  
  	if (size <= 256)
  		size_bit = 0;
  	else if (size <= 256*2)
  		size_bit = 1;
  	else if (size <= 256*3)
  		size_bit = 2;
  	else
  		size_bit = 3;
  
  	mv_inbound_write((_req->req_shifted_phy << 5) |
  		MVIOP_MU_QUEUE_ADDR_HOST_BIT | size_bit, hba);
  }
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
  static void hptiop_post_req_mvfrey(struct hptiop_hba *hba,
  					struct hptiop_request *_req)
  {
  	struct hpt_iop_request_header *reqhdr = _req->req_virt;
  	u32 index;
  
  	reqhdr->flags |= cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT |
  			IOP_REQUEST_FLAG_ADDR_BITS |
  			((_req->req_shifted_phy >> 11) & 0xffff0000));
  	reqhdr->context = cpu_to_le32(IOPMU_QUEUE_ADDR_HOST_BIT |
  			(_req->index << 4) | reqhdr->type);
  	reqhdr->context_hi32 = cpu_to_le32((_req->req_shifted_phy << 5) &
  			0xffffffff);
  
  	hba->u.mvfrey.inlist_wptr++;
  	index = hba->u.mvfrey.inlist_wptr & 0x3fff;
  
  	if (index == hba->u.mvfrey.list_count) {
  		index = 0;
  		hba->u.mvfrey.inlist_wptr &= ~0x3fff;
  		hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE;
  	}
  
  	hba->u.mvfrey.inlist[index].addr =
  			(dma_addr_t)_req->req_shifted_phy << 5;
  	hba->u.mvfrey.inlist[index].intrfc_len = (reqhdr->size + 3) / 4;
  	writel(hba->u.mvfrey.inlist_wptr,
  		&(hba->u.mvfrey.mu->inbound_write_ptr));
  	readl(&(hba->u.mvfrey.mu->inbound_write_ptr));
  }
  
  static int hptiop_reset_comm_itl(struct hptiop_hba *hba)
  {
  	return 0;
  }
  
  static int hptiop_reset_comm_mv(struct hptiop_hba *hba)
  {
  	return 0;
  }
  
  static int hptiop_reset_comm_mvfrey(struct hptiop_hba *hba)
  {
  	u32 list_count = hba->u.mvfrey.list_count;
  
  	if (iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET_COMM, 3000))
  		return -1;
  
  	/* wait 100ms for MCU ready */
  	msleep(100);
  
  	writel(cpu_to_le32(hba->u.mvfrey.inlist_phy & 0xffffffff),
  			&(hba->u.mvfrey.mu->inbound_base));
  	writel(cpu_to_le32((hba->u.mvfrey.inlist_phy >> 16) >> 16),
  			&(hba->u.mvfrey.mu->inbound_base_high));
  
  	writel(cpu_to_le32(hba->u.mvfrey.outlist_phy & 0xffffffff),
  			&(hba->u.mvfrey.mu->outbound_base));
  	writel(cpu_to_le32((hba->u.mvfrey.outlist_phy >> 16) >> 16),
  			&(hba->u.mvfrey.mu->outbound_base_high));
  
  	writel(cpu_to_le32(hba->u.mvfrey.outlist_cptr_phy & 0xffffffff),
  			&(hba->u.mvfrey.mu->outbound_shadow_base));
  	writel(cpu_to_le32((hba->u.mvfrey.outlist_cptr_phy >> 16) >> 16),
  			&(hba->u.mvfrey.mu->outbound_shadow_base_high));
  
  	hba->u.mvfrey.inlist_wptr = (list_count - 1) | CL_POINTER_TOGGLE;
  	*hba->u.mvfrey.outlist_cptr = (list_count - 1) | CL_POINTER_TOGGLE;
  	hba->u.mvfrey.outlist_rptr = list_count - 1;
  	return 0;
  }
f281233d3   Jeff Garzik   SCSI host lock pu...
963
  static int hptiop_queuecommand_lck(struct scsi_cmnd *scp,
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
964
965
966
967
968
969
970
971
972
973
  				void (*done)(struct scsi_cmnd *))
  {
  	struct Scsi_Host *host = scp->device->host;
  	struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
  	struct hpt_iop_request_scsi_command *req;
  	int sg_count = 0;
  	struct hptiop_request *_req;
  
  	BUG_ON(!done);
  	scp->scsi_done = done;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
974
975
976
977
  	_req = get_req(hba);
  	if (_req == NULL) {
  		dprintk("hptiop_queuecmd : no free req
  ");
4f2ddba39   HighPoint Linux Team   [SCSI] hptiop: Hi...
978
  		return SCSI_MLQUEUE_HOST_BUSY;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
979
980
981
  	}
  
  	_req->scp = scp;
9cb78c16f   Hannes Reinecke   scsi: use 64-bit ...
982
  	dprintk("hptiop_queuecmd(scp=%p) %d/%d/%d/%llu cdb=(%08x-%08x-%08x-%08x) "
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
983
984
985
986
987
  			"req_index=%d, req=%p
  ",
  			scp,
  			host->host_no, scp->device->channel,
  			scp->device->id, scp->device->lun,
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
988
989
990
991
  			cpu_to_be32(((u32 *)scp->cmnd)[0]),
  			cpu_to_be32(((u32 *)scp->cmnd)[1]),
  			cpu_to_be32(((u32 *)scp->cmnd)[2]),
  			cpu_to_be32(((u32 *)scp->cmnd)[3]),
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
992
993
994
  			_req->index, _req->req_virt);
  
  	scp->result = 0;
a93429c30   linux   hptiop: Support H...
995
996
997
  	if (scp->device->channel ||
  			(scp->device->id > hba->max_devices) ||
  			((scp->device->id == (hba->max_devices-1)) && scp->device->lun)) {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
998
999
1000
1001
  		scp->result = DID_BAD_TARGET << 16;
  		free_req(hba, _req);
  		goto cmd_done;
  	}
db9b6e89e   HighPoint Linux Team   [SCSI] hptiop: ad...
1002
  	req = _req->req_virt;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1003
1004
  
  	/* build S/G table */
f98754960   FUJITA Tomonori   [SCSI] hptiop: co...
1005
1006
  	sg_count = hptiop_buildsgl(scp, req->sg_list);
  	if (!sg_count)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1007
1008
1009
1010
1011
  		HPT_SCP(scp)->mapped = 0;
  
  	req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT);
  	req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_SCSI_COMMAND);
  	req->header.result = cpu_to_le32(IOP_RESULT_PENDING);
f98754960   FUJITA Tomonori   [SCSI] hptiop: co...
1012
  	req->dataxfer_length = cpu_to_le32(scsi_bufflen(scp));
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1013
1014
1015
1016
1017
1018
1019
1020
1021
  	req->channel = scp->device->channel;
  	req->target = scp->device->id;
  	req->lun = scp->device->lun;
  	req->header.size = cpu_to_le32(
  				sizeof(struct hpt_iop_request_scsi_command)
  				 - sizeof(struct hpt_iopsg)
  				 + sg_count * sizeof(struct hpt_iopsg));
  
  	memcpy(req->cdb, scp->cmnd, sizeof(req->cdb));
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1022
  	hba->ops->post_req(hba, _req);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1023
1024
1025
1026
1027
1028
1029
1030
  	return 0;
  
  cmd_done:
  	dprintk("scsi_done(scp=%p)
  ", scp);
  	scp->scsi_done(scp);
  	return 0;
  }
f281233d3   Jeff Garzik   SCSI host lock pu...
1031
  static DEF_SCSI_QCMD(hptiop_queuecommand)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1032
1033
1034
1035
1036
1037
1038
1039
1040
  static const char *hptiop_info(struct Scsi_Host *host)
  {
  	return driver_name_long;
  }
  
  static int hptiop_reset_hba(struct hptiop_hba *hba)
  {
  	if (atomic_xchg(&hba->resetting, 1) == 0) {
  		atomic_inc(&hba->reset_count);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1041
  		hba->ops->post_msg(hba, IOPMU_INBOUND_MSG0_RESET);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1042
1043
1044
1045
1046
1047
  	}
  
  	wait_event_timeout(hba->reset_wq,
  			atomic_read(&hba->resetting) == 0, 60 * HZ);
  
  	if (atomic_read(&hba->resetting)) {
af901ca18   André Goddard Rosa   tree-wide: fix as...
1048
  		/* IOP is in unknown state, abort reset */
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
  		printk(KERN_ERR "scsi%d: reset failed
  ", hba->host->host_no);
  		return -1;
  	}
  
  	if (iop_send_sync_msg(hba,
  		IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) {
  		dprintk("scsi%d: fail to start background task
  ",
  				hba->host->host_no);
  	}
  
  	return 0;
  }
  
  static int hptiop_reset(struct scsi_cmnd *scp)
  {
aceb29482   Hannes Reinecke   scsi: hptiop: Sim...
1066
  	struct hptiop_hba * hba = (struct hptiop_hba *)scp->device->host->hostdata;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1067

aceb29482   Hannes Reinecke   scsi: hptiop: Sim...
1068
1069
1070
  	printk(KERN_WARNING "hptiop_reset(%d/%d/%d)
  ",
  	       scp->device->host->host_no, -1, -1);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1071
1072
1073
1074
1075
  
  	return hptiop_reset_hba(hba)? FAILED : SUCCESS;
  }
  
  static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev,
db5ed4dfd   Christoph Hellwig   scsi: drop reason...
1076
  					  int queue_depth)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1077
  {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1078
1079
1080
1081
  	struct hptiop_hba *hba = (struct hptiop_hba *)sdev->host->hostdata;
  
  	if (queue_depth > hba->max_requests)
  		queue_depth = hba->max_requests;
db5ed4dfd   Christoph Hellwig   scsi: drop reason...
1082
  	return scsi_change_queue_depth(sdev, queue_depth);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1083
  }
ee959b00c   Tony Jones   SCSI: convert str...
1084
1085
  static ssize_t hptiop_show_version(struct device *dev,
  				   struct device_attribute *attr, char *buf)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1086
1087
1088
1089
  {
  	return snprintf(buf, PAGE_SIZE, "%s
  ", driver_ver);
  }
ee959b00c   Tony Jones   SCSI: convert str...
1090
1091
  static ssize_t hptiop_show_fw_version(struct device *dev,
  				      struct device_attribute *attr, char *buf)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1092
  {
ee959b00c   Tony Jones   SCSI: convert str...
1093
  	struct Scsi_Host *host = class_to_shost(dev);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1094
1095
1096
1097
1098
1099
1100
1101
1102
  	struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
  
  	return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d
  ",
  				hba->firmware_version >> 24,
  				(hba->firmware_version >> 16) & 0xff,
  				(hba->firmware_version >> 8) & 0xff,
  				hba->firmware_version & 0xff);
  }
ee959b00c   Tony Jones   SCSI: convert str...
1103
  static struct device_attribute hptiop_attr_version = {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1104
1105
1106
1107
1108
1109
  	.attr = {
  		.name = "driver-version",
  		.mode = S_IRUGO,
  	},
  	.show = hptiop_show_version,
  };
ee959b00c   Tony Jones   SCSI: convert str...
1110
  static struct device_attribute hptiop_attr_fw_version = {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1111
1112
1113
1114
1115
1116
  	.attr = {
  		.name = "firmware-version",
  		.mode = S_IRUGO,
  	},
  	.show = hptiop_show_fw_version,
  };
ee959b00c   Tony Jones   SCSI: convert str...
1117
  static struct device_attribute *hptiop_attrs[] = {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1118
1119
1120
1121
  	&hptiop_attr_version,
  	&hptiop_attr_fw_version,
  	NULL
  };
a93429c30   linux   hptiop: Support H...
1122
1123
1124
1125
1126
1127
1128
  static int hptiop_slave_config(struct scsi_device *sdev)
  {
  	if (sdev->type == TYPE_TAPE)
  		blk_queue_max_hw_sectors(sdev->request_queue, 8192);
  
  	return 0;
  }
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1129
1130
1131
1132
  static struct scsi_host_template driver_template = {
  	.module                     = THIS_MODULE,
  	.name                       = driver_name,
  	.queuecommand               = hptiop_queuecommand,
aceb29482   Hannes Reinecke   scsi: hptiop: Sim...
1133
  	.eh_host_reset_handler      = hptiop_reset,
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1134
  	.info                       = hptiop_info,
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1135
  	.emulated                   = 0,
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1136
1137
  	.proc_name                  = driver_name,
  	.shost_attrs                = hptiop_attrs,
a93429c30   linux   hptiop: Support H...
1138
  	.slave_configure            = hptiop_slave_config,
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1139
1140
1141
  	.this_id                    = -1,
  	.change_queue_depth         = hptiop_adjust_disk_queue_depth,
  };
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
1142
1143
1144
1145
  static int hptiop_internal_memalloc_itl(struct hptiop_hba *hba)
  {
  	return 0;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1146
1147
1148
1149
1150
1151
1152
1153
1154
  static int hptiop_internal_memalloc_mv(struct hptiop_hba *hba)
  {
  	hba->u.mv.internal_req = dma_alloc_coherent(&hba->pcidev->dev,
  			0x800, &hba->u.mv.internal_req_phy, GFP_KERNEL);
  	if (hba->u.mv.internal_req)
  		return 0;
  	else
  		return -1;
  }
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
  static int hptiop_internal_memalloc_mvfrey(struct hptiop_hba *hba)
  {
  	u32 list_count = readl(&hba->u.mvfrey.mu->inbound_conf_ctl);
  	char *p;
  	dma_addr_t phy;
  
  	BUG_ON(hba->max_request_size == 0);
  
  	if (list_count == 0) {
  		BUG_ON(1);
  		return -1;
  	}
  
  	list_count >>= 16;
  
  	hba->u.mvfrey.list_count = list_count;
  	hba->u.mvfrey.internal_mem_size = 0x800 +
  			list_count * sizeof(struct mvfrey_inlist_entry) +
  			list_count * sizeof(struct mvfrey_outlist_entry) +
  			sizeof(int);
  
  	p = dma_alloc_coherent(&hba->pcidev->dev,
  			hba->u.mvfrey.internal_mem_size, &phy, GFP_KERNEL);
  	if (!p)
  		return -1;
  
  	hba->u.mvfrey.internal_req.req_virt = p;
  	hba->u.mvfrey.internal_req.req_shifted_phy = phy >> 5;
  	hba->u.mvfrey.internal_req.scp = NULL;
  	hba->u.mvfrey.internal_req.next = NULL;
  
  	p += 0x800;
  	phy += 0x800;
  
  	hba->u.mvfrey.inlist = (struct mvfrey_inlist_entry *)p;
  	hba->u.mvfrey.inlist_phy = phy;
  
  	p += list_count * sizeof(struct mvfrey_inlist_entry);
  	phy += list_count * sizeof(struct mvfrey_inlist_entry);
  
  	hba->u.mvfrey.outlist = (struct mvfrey_outlist_entry *)p;
  	hba->u.mvfrey.outlist_phy = phy;
  
  	p += list_count * sizeof(struct mvfrey_outlist_entry);
  	phy += list_count * sizeof(struct mvfrey_outlist_entry);
  
  	hba->u.mvfrey.outlist_cptr = (__le32 *)p;
  	hba->u.mvfrey.outlist_cptr_phy = phy;
  
  	return 0;
  }
  
  static int hptiop_internal_memfree_itl(struct hptiop_hba *hba)
  {
  	return 0;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1211
1212
1213
1214
1215
1216
1217
1218
1219
  static int hptiop_internal_memfree_mv(struct hptiop_hba *hba)
  {
  	if (hba->u.mv.internal_req) {
  		dma_free_coherent(&hba->pcidev->dev, 0x800,
  			hba->u.mv.internal_req, hba->u.mv.internal_req_phy);
  		return 0;
  	} else
  		return -1;
  }
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
  static int hptiop_internal_memfree_mvfrey(struct hptiop_hba *hba)
  {
  	if (hba->u.mvfrey.internal_req.req_virt) {
  		dma_free_coherent(&hba->pcidev->dev,
  			hba->u.mvfrey.internal_mem_size,
  			hba->u.mvfrey.internal_req.req_virt,
  			(dma_addr_t)
  			hba->u.mvfrey.internal_req.req_shifted_phy << 5);
  		return 0;
  	} else
  		return -1;
  }
6f0397905   Greg Kroah-Hartman   Drivers: scsi: re...
1232
  static int hptiop_probe(struct pci_dev *pcidev, const struct pci_device_id *id)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1233
1234
1235
  {
  	struct Scsi_Host *host = NULL;
  	struct hptiop_hba *hba;
23f0bb47a   HighPoint Linux Team   [SCSI] hptiop: fi...
1236
  	struct hptiop_adapter_ops *iop_ops;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1237
1238
1239
1240
1241
  	struct hpt_iop_request_get_config iop_config;
  	struct hpt_iop_request_set_config set_config;
  	dma_addr_t start_phy;
  	void *start_virt;
  	u32 offset, i, req_size;
3e344b6ce   Hannes Reinecke   scsi: hptiop: fix...
1242
  	int rc;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
  
  	dprintk("hptiop_probe(%p)
  ", pcidev);
  
  	if (pci_enable_device(pcidev)) {
  		printk(KERN_ERR "hptiop: fail to enable pci device
  ");
  		return -ENODEV;
  	}
  
  	printk(KERN_INFO "adapter at PCI %d:%d:%d, IRQ %d
  ",
  		pcidev->bus->number, pcidev->devfn >> 3, pcidev->devfn & 7,
  		pcidev->irq);
  
  	pci_set_master(pcidev);
  
  	/* Enable 64bit DMA if possible */
23f0bb47a   HighPoint Linux Team   [SCSI] hptiop: fi...
1261
  	iop_ops = (struct hptiop_adapter_ops *)id->driver_data;
3e344b6ce   Hannes Reinecke   scsi: hptiop: fix...
1262
1263
1264
1265
1266
1267
  	rc = dma_set_mask(&pcidev->dev,
  			  DMA_BIT_MASK(iop_ops->hw_dma_bit_mask));
  	if (rc)
  		rc = dma_set_mask(&pcidev->dev, DMA_BIT_MASK(32));
  
  	if (rc) {
453cd3700   Christoph Hellwig   scsi: hptiop: use...
1268
1269
1270
  		printk(KERN_ERR "hptiop: fail to set dma_mask
  ");
  		goto disable_pci_device;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
  	}
  
  	if (pci_request_regions(pcidev, driver_name)) {
  		printk(KERN_ERR "hptiop: pci_request_regions failed
  ");
  		goto disable_pci_device;
  	}
  
  	host = scsi_host_alloc(&driver_template, sizeof(struct hptiop_hba));
  	if (!host) {
  		printk(KERN_ERR "hptiop: fail to alloc scsi host
  ");
  		goto free_pci_regions;
  	}
  
  	hba = (struct hptiop_hba *)host->hostdata;
a93429c30   linux   hptiop: Support H...
1287
  	memset(hba, 0, sizeof(struct hptiop_hba));
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1288

23f0bb47a   HighPoint Linux Team   [SCSI] hptiop: fi...
1289
  	hba->ops = iop_ops;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1290
1291
1292
  	hba->pcidev = pcidev;
  	hba->host = host;
  	hba->initialized = 0;
db9b6e89e   HighPoint Linux Team   [SCSI] hptiop: ad...
1293
  	hba->iopintf_v2 = 0;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1294
1295
1296
1297
1298
1299
  
  	atomic_set(&hba->resetting, 0);
  	atomic_set(&hba->reset_count, 0);
  
  	init_waitqueue_head(&hba->reset_wq);
  	init_waitqueue_head(&hba->ioctl_wq);
a93429c30   linux   hptiop: Support H...
1300
  	host->max_lun = 128;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1301
1302
1303
1304
  	host->max_channel = 0;
  	host->io_port = 0;
  	host->n_io_port = 0;
  	host->irq = pcidev->irq;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1305
  	if (hba->ops->map_pci_bar(hba))
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1306
  		goto free_scsi_host;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1307
  	if (hba->ops->iop_wait_ready(hba, 20000)) {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1308
1309
1310
1311
1312
  		printk(KERN_ERR "scsi%d: firmware not ready
  ",
  				hba->host->host_no);
  		goto unmap_pci_bar;
  	}
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
1313
  	if (hba->ops->family == MV_BASED_IOP) {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1314
1315
1316
1317
1318
1319
1320
1321
1322
  		if (hba->ops->internal_memalloc(hba)) {
  			printk(KERN_ERR "scsi%d: internal_memalloc failed
  ",
  				hba->host->host_no);
  			goto unmap_pci_bar;
  		}
  	}
  
  	if (hba->ops->get_config(hba, &iop_config)) {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
  		printk(KERN_ERR "scsi%d: get config failed
  ",
  				hba->host->host_no);
  		goto unmap_pci_bar;
  	}
  
  	hba->max_requests = min(le32_to_cpu(iop_config.max_requests),
  				HPTIOP_MAX_REQUESTS);
  	hba->max_devices = le32_to_cpu(iop_config.max_devices);
  	hba->max_request_size = le32_to_cpu(iop_config.request_size);
  	hba->max_sg_descriptors = le32_to_cpu(iop_config.max_sg_count);
  	hba->firmware_version = le32_to_cpu(iop_config.firmware_version);
db9b6e89e   HighPoint Linux Team   [SCSI] hptiop: ad...
1335
  	hba->interface_version = le32_to_cpu(iop_config.interface_version);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1336
  	hba->sdram_size = le32_to_cpu(iop_config.sdram_size);
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
  	if (hba->ops->family == MVFREY_BASED_IOP) {
  		if (hba->ops->internal_memalloc(hba)) {
  			printk(KERN_ERR "scsi%d: internal_memalloc failed
  ",
  				hba->host->host_no);
  			goto unmap_pci_bar;
  		}
  		if (hba->ops->reset_comm(hba)) {
  			printk(KERN_ERR "scsi%d: reset comm failed
  ",
  					hba->host->host_no);
  			goto unmap_pci_bar;
  		}
  	}
db9b6e89e   HighPoint Linux Team   [SCSI] hptiop: ad...
1351
1352
1353
  	if (hba->firmware_version > 0x01020000 ||
  			hba->interface_version > 0x01020000)
  		hba->iopintf_v2 = 1;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1354
1355
1356
1357
1358
1359
  	host->max_sectors = le32_to_cpu(iop_config.data_transfer_length) >> 9;
  	host->max_id = le32_to_cpu(iop_config.max_devices);
  	host->sg_tablesize = le32_to_cpu(iop_config.max_sg_count);
  	host->can_queue = le32_to_cpu(iop_config.max_requests);
  	host->cmd_per_lun = le32_to_cpu(iop_config.max_requests);
  	host->max_cmd_len = 16;
db9b6e89e   HighPoint Linux Team   [SCSI] hptiop: ad...
1360
1361
1362
1363
1364
1365
  	req_size = sizeof(struct hpt_iop_request_scsi_command)
  		+ sizeof(struct hpt_iopsg) * (hba->max_sg_descriptors - 1);
  	if ((req_size & 0x1f) != 0)
  		req_size = (req_size + 0x1f) & ~0x1f;
  
  	memset(&set_config, 0, sizeof(struct hpt_iop_request_set_config));
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1366
  	set_config.iop_id = cpu_to_le32(host->host_no);
db9b6e89e   HighPoint Linux Team   [SCSI] hptiop: ad...
1367
1368
  	set_config.vbus_id = cpu_to_le16(host->host_no);
  	set_config.max_host_request_size = cpu_to_le16(req_size);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1369

00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1370
  	if (hba->ops->set_config(hba, &set_config)) {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1371
1372
1373
1374
1375
  		printk(KERN_ERR "scsi%d: set config failed
  ",
  				hba->host->host_no);
  		goto unmap_pci_bar;
  	}
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1376
  	pci_set_drvdata(pcidev, host);
1d6f359a2   Thomas Gleixner   [PATCH] irq-flags...
1377
  	if (request_irq(pcidev->irq, hptiop_intr, IRQF_SHARED,
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1378
1379
1380
1381
  					driver_name, hba)) {
  		printk(KERN_ERR "scsi%d: request irq %d failed
  ",
  					hba->host->host_no, pcidev->irq);
3e74051bc   Christoph Hellwig   [SCSI] hptiop: ba...
1382
  		goto unmap_pci_bar;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1383
1384
1385
  	}
  
  	/* Allocate request mem */
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1386
1387
1388
1389
1390
  
  	dprintk("req_size=%d, max_requests=%d
  ", req_size, hba->max_requests);
  
  	hba->req_size = req_size;
a93429c30   linux   hptiop: Support H...
1391
  	hba->req_list = NULL;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1392

a93429c30   linux   hptiop: Support H...
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
  	for (i = 0; i < hba->max_requests; i++) {
  		start_virt = dma_alloc_coherent(&pcidev->dev,
  					hba->req_size + 0x20,
  					&start_phy, GFP_KERNEL);
  
  		if (!start_virt) {
  			printk(KERN_ERR "scsi%d: fail to alloc request mem
  ",
  						hba->host->host_no);
  			goto free_request_mem;
  		}
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1404

a93429c30   linux   hptiop: Support H...
1405
1406
  		hba->dma_coherent[i] = start_virt;
  		hba->dma_coherent_handle[i] = start_phy;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1407

a93429c30   linux   hptiop: Support H...
1408
1409
1410
1411
1412
  		if ((start_phy & 0x1f) != 0) {
  			offset = ((start_phy + 0x1f) & ~0x1f) - start_phy;
  			start_phy += offset;
  			start_virt += offset;
  		}
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1413

ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1414
1415
1416
1417
1418
  		hba->reqs[i].next = NULL;
  		hba->reqs[i].req_virt = start_virt;
  		hba->reqs[i].req_shifted_phy = start_phy >> 5;
  		hba->reqs[i].index = i;
  		free_req(hba, &hba->reqs[i]);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1419
1420
1421
1422
1423
  	}
  
  	/* Enable Interrupt and start background task */
  	if (hptiop_initialize_iop(hba))
  		goto free_request_mem;
3e74051bc   Christoph Hellwig   [SCSI] hptiop: ba...
1424
1425
1426
1427
1428
1429
  	if (scsi_add_host(host, &pcidev->dev)) {
  		printk(KERN_ERR "scsi%d: scsi_add_host failed
  ",
  					hba->host->host_no);
  		goto free_request_mem;
  	}
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1430
1431
1432
1433
1434
1435
1436
  	scsi_scan_host(host);
  
  	dprintk("scsi%d: hptiop_probe successfully
  ", hba->host->host_no);
  	return 0;
  
  free_request_mem:
a93429c30   linux   hptiop: Support H...
1437
1438
1439
1440
1441
1442
1443
1444
1445
  	for (i = 0; i < hba->max_requests; i++) {
  		if (hba->dma_coherent[i] && hba->dma_coherent_handle[i])
  			dma_free_coherent(&hba->pcidev->dev,
  					hba->req_size + 0x20,
  					hba->dma_coherent[i],
  					hba->dma_coherent_handle[i]);
  		else
  			break;
  	}
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1446

ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1447
  	free_irq(hba->pcidev->irq, hba);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1448
  unmap_pci_bar:
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
1449
  	hba->ops->internal_memfree(hba);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1450

00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1451
  	hba->ops->unmap_pci_bar(hba);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1452
1453
1454
  
  free_scsi_host:
  	scsi_host_put(host);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1455
1456
  free_pci_regions:
  	pci_release_regions(pcidev);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1457
1458
  disable_pci_device:
  	pci_disable_device(pcidev);
1db90ea23   Julia Lawall   [SCSI] hptiop: El...
1459
1460
  	dprintk("scsi%d: hptiop_probe fail
  ", host ? host->host_no : 0);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1461
1462
1463
1464
1465
1466
1467
  	return -ENODEV;
  }
  
  static void hptiop_shutdown(struct pci_dev *pcidev)
  {
  	struct Scsi_Host *host = pci_get_drvdata(pcidev);
  	struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
  
  	dprintk("hptiop_shutdown(%p)
  ", hba);
  
  	/* stop the iop */
  	if (iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_SHUTDOWN, 60000))
  		printk(KERN_ERR "scsi%d: shutdown the iop timeout
  ",
  					hba->host->host_no);
  
  	/* disable all outbound interrupts */
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1479
1480
1481
1482
1483
1484
1485
1486
  	hba->ops->disable_intr(hba);
  }
  
  static void hptiop_disable_intr_itl(struct hptiop_hba *hba)
  {
  	u32 int_mask;
  
  	int_mask = readl(&hba->u.itl.iop->outbound_intmask);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1487
1488
  	writel(int_mask |
  		IOPMU_OUTBOUND_INT_MSG0 | IOPMU_OUTBOUND_INT_POSTQUEUE,
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1489
1490
1491
1492
1493
1494
1495
1496
  		&hba->u.itl.iop->outbound_intmask);
  	readl(&hba->u.itl.iop->outbound_intmask);
  }
  
  static void hptiop_disable_intr_mv(struct hptiop_hba *hba)
  {
  	writel(0, &hba->u.mv.regs->outbound_intmask);
  	readl(&hba->u.mv.regs->outbound_intmask);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1497
  }
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
1498
1499
1500
1501
1502
1503
1504
1505
1506
  static void hptiop_disable_intr_mvfrey(struct hptiop_hba *hba)
  {
  	writel(0, &(hba->u.mvfrey.mu->f0_doorbell_enable));
  	readl(&(hba->u.mvfrey.mu->f0_doorbell_enable));
  	writel(0, &(hba->u.mvfrey.mu->isr_enable));
  	readl(&(hba->u.mvfrey.mu->isr_enable));
  	writel(0, &(hba->u.mvfrey.mu->pcie_f0_int_enable));
  	readl(&(hba->u.mvfrey.mu->pcie_f0_int_enable));
  }
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1507
1508
1509
1510
  static void hptiop_remove(struct pci_dev *pcidev)
  {
  	struct Scsi_Host *host = pci_get_drvdata(pcidev);
  	struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
a93429c30   linux   hptiop: Support H...
1511
  	u32 i;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1512
1513
1514
  
  	dprintk("scsi%d: hptiop_remove
  ", hba->host->host_no);
4f2ddba39   HighPoint Linux Team   [SCSI] hptiop: Hi...
1515
  	scsi_remove_host(host);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1516
1517
1518
  	hptiop_shutdown(pcidev);
  
  	free_irq(hba->pcidev->irq, hba);
a93429c30   linux   hptiop: Support H...
1519
1520
1521
1522
1523
1524
1525
1526
1527
  	for (i = 0; i < hba->max_requests; i++) {
  		if (hba->dma_coherent[i] && hba->dma_coherent_handle[i])
  			dma_free_coherent(&hba->pcidev->dev,
  					hba->req_size + 0x20,
  					hba->dma_coherent[i],
  					hba->dma_coherent_handle[i]);
  		else
  			break;
  	}
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1528

286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
1529
  	hba->ops->internal_memfree(hba);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1530
1531
  
  	hba->ops->unmap_pci_bar(hba);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1532
1533
1534
1535
  
  	pci_release_regions(hba->pcidev);
  	pci_set_drvdata(hba->pcidev, NULL);
  	pci_disable_device(hba->pcidev);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1536
1537
  	scsi_host_put(host);
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1538
  static struct hptiop_adapter_ops hptiop_itl_ops = {
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
1539
  	.family            = INTEL_BASED_IOP,
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1540
  	.iop_wait_ready    = iop_wait_ready_itl,
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
1541
1542
  	.internal_memalloc = hptiop_internal_memalloc_itl,
  	.internal_memfree  = hptiop_internal_memfree_itl,
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1543
1544
1545
1546
1547
1548
1549
1550
1551
  	.map_pci_bar       = hptiop_map_pci_bar_itl,
  	.unmap_pci_bar     = hptiop_unmap_pci_bar_itl,
  	.enable_intr       = hptiop_enable_intr_itl,
  	.disable_intr      = hptiop_disable_intr_itl,
  	.get_config        = iop_get_config_itl,
  	.set_config        = iop_set_config_itl,
  	.iop_intr          = iop_intr_itl,
  	.post_msg          = hptiop_post_msg_itl,
  	.post_req          = hptiop_post_req_itl,
23f0bb47a   HighPoint Linux Team   [SCSI] hptiop: fi...
1552
  	.hw_dma_bit_mask   = 64,
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
1553
1554
  	.reset_comm        = hptiop_reset_comm_itl,
  	.host_phy_flag     = cpu_to_le64(0),
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1555
1556
1557
  };
  
  static struct hptiop_adapter_ops hptiop_mv_ops = {
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
1558
  	.family            = MV_BASED_IOP,
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
  	.iop_wait_ready    = iop_wait_ready_mv,
  	.internal_memalloc = hptiop_internal_memalloc_mv,
  	.internal_memfree  = hptiop_internal_memfree_mv,
  	.map_pci_bar       = hptiop_map_pci_bar_mv,
  	.unmap_pci_bar     = hptiop_unmap_pci_bar_mv,
  	.enable_intr       = hptiop_enable_intr_mv,
  	.disable_intr      = hptiop_disable_intr_mv,
  	.get_config        = iop_get_config_mv,
  	.set_config        = iop_set_config_mv,
  	.iop_intr          = iop_intr_mv,
  	.post_msg          = hptiop_post_msg_mv,
  	.post_req          = hptiop_post_req_mv,
23f0bb47a   HighPoint Linux Team   [SCSI] hptiop: fi...
1571
  	.hw_dma_bit_mask   = 33,
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
  	.reset_comm        = hptiop_reset_comm_mv,
  	.host_phy_flag     = cpu_to_le64(0),
  };
  
  static struct hptiop_adapter_ops hptiop_mvfrey_ops = {
  	.family            = MVFREY_BASED_IOP,
  	.iop_wait_ready    = iop_wait_ready_mvfrey,
  	.internal_memalloc = hptiop_internal_memalloc_mvfrey,
  	.internal_memfree  = hptiop_internal_memfree_mvfrey,
  	.map_pci_bar       = hptiop_map_pci_bar_mvfrey,
  	.unmap_pci_bar     = hptiop_unmap_pci_bar_mvfrey,
  	.enable_intr       = hptiop_enable_intr_mvfrey,
  	.disable_intr      = hptiop_disable_intr_mvfrey,
  	.get_config        = iop_get_config_mvfrey,
  	.set_config        = iop_set_config_mvfrey,
  	.iop_intr          = iop_intr_mvfrey,
  	.post_msg          = hptiop_post_msg_mvfrey,
  	.post_req          = hptiop_post_req_mvfrey,
  	.hw_dma_bit_mask   = 64,
  	.reset_comm        = hptiop_reset_comm_mvfrey,
  	.host_phy_flag     = cpu_to_le64(1),
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1593
  };
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1594
  static struct pci_device_id hptiop_id_table[] = {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1595
1596
  	{ PCI_VDEVICE(TTI, 0x3220), (kernel_ulong_t)&hptiop_itl_ops },
  	{ PCI_VDEVICE(TTI, 0x3320), (kernel_ulong_t)&hptiop_itl_ops },
3bfc13c23   HighPoint Linux Team   [SCSI] hptiop: Ad...
1597
  	{ PCI_VDEVICE(TTI, 0x3410), (kernel_ulong_t)&hptiop_itl_ops },
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1598
1599
  	{ PCI_VDEVICE(TTI, 0x3510), (kernel_ulong_t)&hptiop_itl_ops },
  	{ PCI_VDEVICE(TTI, 0x3511), (kernel_ulong_t)&hptiop_itl_ops },
3bfc13c23   HighPoint Linux Team   [SCSI] hptiop: Ad...
1600
  	{ PCI_VDEVICE(TTI, 0x3520), (kernel_ulong_t)&hptiop_itl_ops },
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1601
1602
  	{ PCI_VDEVICE(TTI, 0x3521), (kernel_ulong_t)&hptiop_itl_ops },
  	{ PCI_VDEVICE(TTI, 0x3522), (kernel_ulong_t)&hptiop_itl_ops },
dd07428b4   HighPoint Linux Team   [SCSI] hptiop: ad...
1603
  	{ PCI_VDEVICE(TTI, 0x3530), (kernel_ulong_t)&hptiop_itl_ops },
3bfc13c23   HighPoint Linux Team   [SCSI] hptiop: Ad...
1604
  	{ PCI_VDEVICE(TTI, 0x3540), (kernel_ulong_t)&hptiop_itl_ops },
dd07428b4   HighPoint Linux Team   [SCSI] hptiop: ad...
1605
  	{ PCI_VDEVICE(TTI, 0x3560), (kernel_ulong_t)&hptiop_itl_ops },
dd07428b4   HighPoint Linux Team   [SCSI] hptiop: ad...
1606
1607
1608
1609
  	{ PCI_VDEVICE(TTI, 0x4210), (kernel_ulong_t)&hptiop_itl_ops },
  	{ PCI_VDEVICE(TTI, 0x4211), (kernel_ulong_t)&hptiop_itl_ops },
  	{ PCI_VDEVICE(TTI, 0x4310), (kernel_ulong_t)&hptiop_itl_ops },
  	{ PCI_VDEVICE(TTI, 0x4311), (kernel_ulong_t)&hptiop_itl_ops },
3bfc13c23   HighPoint Linux Team   [SCSI] hptiop: Ad...
1610
1611
1612
1613
  	{ PCI_VDEVICE(TTI, 0x4320), (kernel_ulong_t)&hptiop_itl_ops },
  	{ PCI_VDEVICE(TTI, 0x4321), (kernel_ulong_t)&hptiop_itl_ops },
  	{ PCI_VDEVICE(TTI, 0x4322), (kernel_ulong_t)&hptiop_itl_ops },
  	{ PCI_VDEVICE(TTI, 0x4400), (kernel_ulong_t)&hptiop_itl_ops },
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1614
1615
1616
  	{ PCI_VDEVICE(TTI, 0x3120), (kernel_ulong_t)&hptiop_mv_ops },
  	{ PCI_VDEVICE(TTI, 0x3122), (kernel_ulong_t)&hptiop_mv_ops },
  	{ PCI_VDEVICE(TTI, 0x3020), (kernel_ulong_t)&hptiop_mv_ops },
286aa0316   HighPoint Linux Team   [SCSI] hptiop: Su...
1617
1618
  	{ PCI_VDEVICE(TTI, 0x4520), (kernel_ulong_t)&hptiop_mvfrey_ops },
  	{ PCI_VDEVICE(TTI, 0x4522), (kernel_ulong_t)&hptiop_mvfrey_ops },
a93429c30   linux   hptiop: Support H...
1619
1620
1621
1622
1623
1624
1625
1626
  	{ PCI_VDEVICE(TTI, 0x3610), (kernel_ulong_t)&hptiop_mvfrey_ops },
  	{ PCI_VDEVICE(TTI, 0x3611), (kernel_ulong_t)&hptiop_mvfrey_ops },
  	{ PCI_VDEVICE(TTI, 0x3620), (kernel_ulong_t)&hptiop_mvfrey_ops },
  	{ PCI_VDEVICE(TTI, 0x3622), (kernel_ulong_t)&hptiop_mvfrey_ops },
  	{ PCI_VDEVICE(TTI, 0x3640), (kernel_ulong_t)&hptiop_mvfrey_ops },
  	{ PCI_VDEVICE(TTI, 0x3660), (kernel_ulong_t)&hptiop_mvfrey_ops },
  	{ PCI_VDEVICE(TTI, 0x3680), (kernel_ulong_t)&hptiop_mvfrey_ops },
  	{ PCI_VDEVICE(TTI, 0x3690), (kernel_ulong_t)&hptiop_mvfrey_ops },
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
  	{},
  };
  
  MODULE_DEVICE_TABLE(pci, hptiop_id_table);
  
  static struct pci_driver hptiop_pci_driver = {
  	.name       = driver_name,
  	.id_table   = hptiop_id_table,
  	.probe      = hptiop_probe,
  	.remove     = hptiop_remove,
  	.shutdown   = hptiop_shutdown,
  };
  
  static int __init hptiop_module_init(void)
  {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1642
1643
  	printk(KERN_INFO "%s %s
  ", driver_name_long, driver_ver);
3e74051bc   Christoph Hellwig   [SCSI] hptiop: ba...
1644
  	return pci_register_driver(&hptiop_pci_driver);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1645
1646
1647
1648
  }
  
  static void __exit hptiop_module_exit(void)
  {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1649
1650
1651
1652
1653
1654
1655
1656
  	pci_unregister_driver(&hptiop_pci_driver);
  }
  
  
  module_init(hptiop_module_init);
  module_exit(hptiop_module_exit);
  
  MODULE_LICENSE("GPL");
db9b6e89e   HighPoint Linux Team   [SCSI] hptiop: ad...
1657