Blame view

drivers/scsi/hptiop.c 34.4 KB
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1
  /*
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
2
   * HighPoint RR3xxx/4xxx controller driver for Linux
3bfc13c23   HighPoint Linux Team   [SCSI] hptiop: Ad...
3
   * Copyright (C) 2006-2009 HighPoint Technologies, Inc. All Rights Reserved.
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
4
5
6
7
8
9
10
11
12
13
14
15
16
17
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; version 2 of the License.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * 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...
18
19
20
21
22
23
24
25
26
27
  #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: ...
28
  #include <linux/gfp.h>
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
29
30
31
32
33
34
35
36
37
38
39
40
  #include <asm/uaccess.h>
  #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...
41
  MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx/4xxx Controller Driver");
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
42
43
  
  static char driver_name[] = "hptiop";
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
44
  static const char driver_name_long[] = "RocketRAID 3xxx/4xxx Controller driver";
3bfc13c23   HighPoint Linux Team   [SCSI] hptiop: Ad...
45
  static const char driver_ver[] = "v1.6 (090910)";
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
46
47
48
49
50
51
  
  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...
52
  static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
53
  static int iop_wait_ready_itl(struct hptiop_hba *hba, u32 millisec)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
54
55
56
57
58
  {
  	u32 req = 0;
  	int i;
  
  	for (i = 0; i < millisec; i++) {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
59
  		req = readl(&hba->u.itl.iop->inbound_queue);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
60
61
62
63
64
65
  		if (req != IOPMU_QUEUE_EMPTY)
  			break;
  		msleep(1);
  	}
  
  	if (req != IOPMU_QUEUE_EMPTY) {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
66
67
  		writel(req, &hba->u.itl.iop->outbound_queue);
  		readl(&hba->u.itl.iop->outbound_intstatus);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
68
69
70
71
72
  		return 0;
  	}
  
  	return -1;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
73
74
75
76
77
78
  static int iop_wait_ready_mv(struct hptiop_hba *hba, u32 millisec)
  {
  	return iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec);
  }
  
  static void hptiop_request_callback_itl(struct hptiop_hba *hba, u32 tag)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
79
  {
db9b6e89e   HighPoint Linux Team   [SCSI] hptiop: ad...
80
  	if (tag & IOPMU_QUEUE_ADDR_HOST_BIT)
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
81
  		hptiop_host_request_callback_itl(hba,
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
82
83
  				tag & ~IOPMU_QUEUE_ADDR_HOST_BIT);
  	else
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
84
  		hptiop_iop_request_callback_itl(hba, tag);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
85
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
86
  static void hptiop_drain_outbound_queue_itl(struct hptiop_hba *hba)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
87
88
  {
  	u32 req;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
89
90
  	while ((req = readl(&hba->u.itl.iop->outbound_queue)) !=
  						IOPMU_QUEUE_EMPTY) {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
91
92
  
  		if (req & IOPMU_QUEUE_MASK_HOST_BITS)
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
93
  			hptiop_request_callback_itl(hba, req);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
94
95
96
97
  		else {
  			struct hpt_iop_request_header __iomem * p;
  
  			p = (struct hpt_iop_request_header __iomem *)
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
98
  				((char __iomem *)hba->u.itl.iop + req);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
99
100
101
  
  			if (readl(&p->flags) & IOP_REQUEST_FLAG_SYNC_REQUEST) {
  				if (readl(&p->context))
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
102
  					hptiop_request_callback_itl(hba, req);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
103
104
105
106
  				else
  					writel(1, &p->context);
  			}
  			else
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
107
  				hptiop_request_callback_itl(hba, req);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
108
109
110
  		}
  	}
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
111
  static int iop_intr_itl(struct hptiop_hba *hba)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
112
  {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
113
  	struct hpt_iopmu_itl __iomem *iop = hba->u.itl.iop;
3bfc13c23   HighPoint Linux Team   [SCSI] hptiop: Ad...
114
  	void __iomem *plx = hba->u.itl.plx;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
115
116
  	u32 status;
  	int ret = 0;
3bfc13c23   HighPoint Linux Team   [SCSI] hptiop: Ad...
117
118
  	if (plx && readl(plx + 0x11C5C) & 0xf)
  		writel(1, plx + 0x11C60);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
119
120
121
122
  	status = readl(&iop->outbound_intstatus);
  
  	if (status & IOPMU_OUTBOUND_INT_MSG0) {
  		u32 msg = readl(&iop->outbound_msgaddr0);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
123

ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
124
125
126
127
128
129
130
131
  		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...
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
  		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...
223
224
225
226
227
  		ret = 1;
  	}
  
  	return ret;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
228
  static int iop_send_sync_request_itl(struct hptiop_hba *hba,
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
229
230
231
232
  					void __iomem *_req, u32 millisec)
  {
  	struct hpt_iop_request_header __iomem *req = _req;
  	u32 i;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
233
  	writel(readl(&req->flags) | IOP_REQUEST_FLAG_SYNC_REQUEST, &req->flags);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
234
  	writel(0, &req->context);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
235
236
237
  	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...
238
239
  
  	for (i = 0; i < millisec; i++) {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
240
  		iop_intr_itl(hba);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
241
242
243
244
245
246
247
  		if (readl(&req->context))
  			return 0;
  		msleep(1);
  	}
  
  	return -1;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
248
249
  static int iop_send_sync_request_mv(struct hptiop_hba *hba,
  					u32 size_bits, u32 millisec)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
250
  {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
251
  	struct hpt_iop_request_header *reqhdr = hba->u.mv.internal_req;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
252
253
254
  	u32 i;
  
  	hba->msg_done = 0;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
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
  	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;
  }
  
  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...
280

00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
281
282
283
  static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec)
  {
  	u32 i;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
284

00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
285
286
  	hba->msg_done = 0;
  	hba->ops->post_msg(hba, msg);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
287
288
289
  
  	for (i = 0; i < millisec; i++) {
  		spin_lock_irq(hba->host->host_lock);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
290
  		hba->ops->iop_intr(hba);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
291
292
293
294
295
296
297
298
  		spin_unlock_irq(hba->host->host_lock);
  		if (hba->msg_done)
  			break;
  		msleep(1);
  	}
  
  	return hba->msg_done? 0 : -1;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
299
  static int iop_get_config_itl(struct hptiop_hba *hba,
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
300
301
302
303
  				struct hpt_iop_request_get_config *config)
  {
  	u32 req32;
  	struct hpt_iop_request_get_config __iomem *req;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
304
  	req32 = readl(&hba->u.itl.iop->inbound_queue);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
305
306
307
308
  	if (req32 == IOPMU_QUEUE_EMPTY)
  		return -1;
  
  	req = (struct hpt_iop_request_get_config __iomem *)
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
309
  			((unsigned long)hba->u.itl.iop + req32);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
310
311
312
313
314
  
  	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...
315
  	if (iop_send_sync_request_itl(hba, req, 20000)) {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
316
317
318
319
320
321
  		dprintk("Get config send cmd failed
  ");
  		return -1;
  	}
  
  	memcpy_fromio(config, req, sizeof(*config));
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
322
323
324
325
326
327
328
329
330
331
332
333
334
335
  	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...
336
337
  	req->header.context = cpu_to_le32(IOP_REQUEST_TYPE_GET_CONFIG<<5);
  	req->header.context_hi32 = 0;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
338
339
340
341
342
343
344
345
  
  	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...
346
347
  	return 0;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
348
  static int iop_set_config_itl(struct hptiop_hba *hba,
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
349
350
351
352
  				struct hpt_iop_request_set_config *config)
  {
  	u32 req32;
  	struct hpt_iop_request_set_config __iomem *req;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
353
  	req32 = readl(&hba->u.itl.iop->inbound_queue);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
354
355
356
357
  	if (req32 == IOPMU_QUEUE_EMPTY)
  		return -1;
  
  	req = (struct hpt_iop_request_set_config __iomem *)
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
358
  			((unsigned long)hba->u.itl.iop + req32);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
359
360
361
362
363
364
365
366
367
368
  
  	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...
369
  	if (iop_send_sync_request_itl(hba, req, 20000)) {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
370
371
372
373
  		dprintk("Set config send cmd failed
  ");
  		return -1;
  	}
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
374
  	writel(req32, &hba->u.itl.iop->outbound_queue);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
375
376
  	return 0;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
377
378
  static int iop_set_config_mv(struct hptiop_hba *hba,
  				struct hpt_iop_request_set_config *config)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
379
  {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
380
  	struct hpt_iop_request_set_config *req = hba->u.mv.internal_req;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
381

00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
382
383
384
385
386
387
  	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...
388
389
  	req->header.context = cpu_to_le32(IOP_REQUEST_TYPE_SET_CONFIG<<5);
  	req->header.context_hi32 = 0;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
390
391
392
393
394
395
396
397
398
399
400
401
  
  	if (iop_send_sync_request_mv(hba, 0, 20000)) {
  		dprintk("Set config send cmd failed
  ");
  		return -1;
  	}
  
  	return 0;
  }
  
  static void hptiop_enable_intr_itl(struct hptiop_hba *hba)
  {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
402
  	writel(~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0),
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
403
404
405
406
407
408
409
410
411
412
413
414
415
  		&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);
  }
  
  static int hptiop_initialize_iop(struct hptiop_hba *hba)
  {
  	/* enable interrupts */
  	hba->ops->enable_intr(hba);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
416
417
418
419
420
421
422
423
424
425
426
427
428
  
  	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...
429
  static void __iomem *hptiop_map_pci_bar(struct hptiop_hba *hba, int index)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
430
431
432
  {
  	u32 mem_base_phy, length;
  	void __iomem *mem_base_virt;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
433

ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
434
  	struct pci_dev *pcidev = hba->pcidev;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
435
436
  
  	if (!(pci_resource_flags(pcidev, index) & IORESOURCE_MEM)) {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
437
438
439
  		printk(KERN_ERR "scsi%d: pci resource invalid
  ",
  				hba->host->host_no);
9bcf09108   Harvey Harrison   scsi: fix integer...
440
  		return NULL;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
441
  	}
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
442
443
  	mem_base_phy = pci_resource_start(pcidev, index);
  	length = pci_resource_len(pcidev, index);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
444
445
446
447
448
449
  	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...
450
  		return NULL;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
451
452
453
454
455
456
  	}
  	return mem_base_virt;
  }
  
  static int hptiop_map_pci_bar_itl(struct hptiop_hba *hba)
  {
3bfc13c23   HighPoint Linux Team   [SCSI] hptiop: Ad...
457
  	struct pci_dev *pcidev = hba->pcidev;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
458
  	hba->u.itl.iop = hptiop_map_pci_bar(hba, 0);
3bfc13c23   HighPoint Linux Team   [SCSI] hptiop: Ad...
459
  	if (hba->u.itl.iop == NULL)
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
460
  		return -1;
3bfc13c23   HighPoint Linux Team   [SCSI] hptiop: Ad...
461
462
463
464
465
466
467
468
469
  	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...
470
471
472
473
  }
  
  static void hptiop_unmap_pci_bar_itl(struct hptiop_hba *hba)
  {
3bfc13c23   HighPoint Linux Team   [SCSI] hptiop: Ad...
474
475
  	if (hba->u.itl.plx)
  		iounmap(hba->u.itl.plx);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
476
477
478
479
480
481
  	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...
482
  	if (hba->u.mv.regs == NULL)
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
483
484
485
  		return -1;
  
  	hba->u.mv.mu = hptiop_map_pci_bar(hba, 2);
9bcf09108   Harvey Harrison   scsi: fix integer...
486
  	if (hba->u.mv.mu == NULL) {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
487
  		iounmap(hba->u.mv.regs);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
488
489
  		return -1;
  	}
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
490
491
  	return 0;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
492
493
494
495
496
  static void hptiop_unmap_pci_bar_mv(struct hptiop_hba *hba)
  {
  	iounmap(hba->u.mv.regs);
  	iounmap(hba->u.mv.mu);
  }
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
497
498
499
500
  static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg)
  {
  	dprintk("iop message 0x%x
  ", msg);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
501
502
  	if (msg == IOPMU_INBOUND_MSG0_NOP)
  		hba->msg_done = 1;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
503
504
505
506
507
508
509
510
511
512
  	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...
513
  static struct hptiop_request *get_req(struct hptiop_hba *hba)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
514
515
516
517
518
519
520
521
522
523
524
525
  {
  	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...
526
  static void free_req(struct hptiop_hba *hba, struct hptiop_request *req)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
527
528
529
530
531
532
  {
  	dprintk("free_req(%d, %p)
  ", req->index, req);
  	req->next = hba->req_list;
  	hba->req_list = req;
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
533
534
  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...
535
  {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
536
  	struct scsi_cmnd *scp;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
537
  	dprintk("hptiop_finish_scsi_req: req=%p, type=%d, "
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
538
539
540
541
542
543
544
545
546
  			"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...
547
548
  	if (HPT_SCP(scp)->mapped)
  		scsi_dma_unmap(scp);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
549
550
551
  
  	switch (le32_to_cpu(req->header.result)) {
  	case IOP_RESULT_SUCCESS:
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
552
553
  		scsi_set_resid(scp,
  			scsi_bufflen(scp) - le32_to_cpu(req->dataxfer_length));
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
  		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...
571
572
573
  	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...
574
  		scp->result = SAM_STAT_CHECK_CONDITION;
c372f4a82   FUJITA Tomonori   [SCSI] hptiop: fi...
575
  		memcpy(scp->sense_buffer, &req->sg_list,
b80ca4f7e   FUJITA Tomonori   [SCSI] replace si...
576
  				min_t(size_t, SCSI_SENSE_BUFFERSIZE,
0fec02c93   HighPoint Linux Team   [SCSI] hptiop: av...
577
  					le32_to_cpu(req->dataxfer_length)));
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
578
579
580
  		break;
  
  	default:
1c9fbafc8   Martin K. Petersen   [SCSI] Remove SUG...
581
  		scp->result = DRIVER_INVALID << 24 | DID_ABORT << 16;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
582
583
584
585
586
587
588
589
  		break;
  	}
  
  	dprintk("scsi_done(%p)
  ", scp);
  	scp->scsi_done(scp);
  	free_req(hba, &hba->reqs[tag]);
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
  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);
  }
  
  void hptiop_iop_request_callback_itl(struct hptiop_hba *hba, u32 tag)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
609
610
611
612
613
614
  {
  	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...
615
616
  			((unsigned long)hba->u.itl.iop + tag);
  	dprintk("hptiop_iop_request_callback_itl: req=%p, type=%d, "
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
  			"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...
645
  	writel(tag, &hba->u.itl.iop->outbound_queue);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
646
  }
7d12e780e   David Howells   IRQ: Maintain reg...
647
  static irqreturn_t hptiop_intr(int irq, void *dev_id)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
648
649
650
651
652
653
  {
  	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...
654
  	handled = hba->ops->iop_intr(hba);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
655
656
657
658
659
660
661
662
663
  	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...
664
665
666
667
668
669
670
  	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...
671

f98754960   FUJITA Tomonori   [SCSI] hptiop: co...
672
673
674
675
676
677
678
679
680
681
  	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) {
  		psg[idx].pci_address = cpu_to_le64(sg_dma_address(sg));
  		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...
682
  	}
f98754960   FUJITA Tomonori   [SCSI] hptiop: co...
683
  	return HPT_SCP(scp)->sgcnt;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
684
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
  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);
  }
f281233d3   Jeff Garzik   SCSI host lock pu...
735
  static int hptiop_queuecommand_lck(struct scsi_cmnd *scp,
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
736
737
738
739
740
741
742
743
744
745
  				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...
746
747
748
749
  	_req = get_req(hba);
  	if (_req == NULL) {
  		dprintk("hptiop_queuecmd : no free req
  ");
4f2ddba39   HighPoint Linux Team   [SCSI] hptiop: Hi...
750
  		return SCSI_MLQUEUE_HOST_BUSY;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
751
752
753
754
755
756
757
758
759
760
  	}
  
  	_req->scp = scp;
  
  	dprintk("hptiop_queuecmd(scp=%p) %d/%d/%d/%d cdb=(%x-%x-%x) "
  			"req_index=%d, req=%p
  ",
  			scp,
  			host->host_no, scp->device->channel,
  			scp->device->id, scp->device->lun,
64a87b244   Boaz Harrosh   [SCSI] Let scsi_c...
761
762
763
  			((u32 *)scp->cmnd)[0],
  			((u32 *)scp->cmnd)[1],
  			((u32 *)scp->cmnd)[2],
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
764
765
766
767
768
769
770
771
772
773
  			_req->index, _req->req_virt);
  
  	scp->result = 0;
  
  	if (scp->device->channel || scp->device->lun ||
  			scp->device->id > hba->max_devices) {
  		scp->result = DID_BAD_TARGET << 16;
  		free_req(hba, _req);
  		goto cmd_done;
  	}
db9b6e89e   HighPoint Linux Team   [SCSI] hptiop: ad...
774
  	req = _req->req_virt;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
775
776
  
  	/* build S/G table */
f98754960   FUJITA Tomonori   [SCSI] hptiop: co...
777
778
  	sg_count = hptiop_buildsgl(scp, req->sg_list);
  	if (!sg_count)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
779
780
781
782
783
  		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...
784
  	req->dataxfer_length = cpu_to_le32(scsi_bufflen(scp));
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
785
786
787
788
789
790
791
792
793
  	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...
794
  	hba->ops->post_req(hba, _req);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
795
796
797
798
799
800
801
802
  	return 0;
  
  cmd_done:
  	dprintk("scsi_done(scp=%p)
  ", scp);
  	scp->scsi_done(scp);
  	return 0;
  }
f281233d3   Jeff Garzik   SCSI host lock pu...
803
  static DEF_SCSI_QCMD(hptiop_queuecommand)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
804
805
806
807
808
809
810
811
812
  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...
813
  		hba->ops->post_msg(hba, IOPMU_INBOUND_MSG0_RESET);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
814
815
816
817
818
819
  	}
  
  	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...
820
  		/* IOP is in unknown state, abort reset */
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
  		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)
  {
  	struct Scsi_Host * host = scp->device->host;
  	struct hptiop_hba * hba = (struct hptiop_hba *)host->hostdata;
  
  	printk(KERN_WARNING "hptiop_reset(%d/%d/%d) scp=%p
  ",
  			scp->device->host->host_no, scp->device->channel,
  			scp->device->id, scp);
  
  	return hptiop_reset_hba(hba)? FAILED : SUCCESS;
  }
  
  static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev,
e881a172d   Mike Christie   [SCSI] modify cha...
850
  					  int queue_depth, int reason)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
851
  {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
852
  	struct hptiop_hba *hba = (struct hptiop_hba *)sdev->host->hostdata;
e881a172d   Mike Christie   [SCSI] modify cha...
853
854
  	if (reason != SCSI_QDEPTH_DEFAULT)
  		return -EOPNOTSUPP;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
855
856
  	if (queue_depth > hba->max_requests)
  		queue_depth = hba->max_requests;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
857
858
859
  	scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
  	return queue_depth;
  }
ee959b00c   Tony Jones   SCSI: convert str...
860
861
  static ssize_t hptiop_show_version(struct device *dev,
  				   struct device_attribute *attr, char *buf)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
862
863
864
865
  {
  	return snprintf(buf, PAGE_SIZE, "%s
  ", driver_ver);
  }
ee959b00c   Tony Jones   SCSI: convert str...
866
867
  static ssize_t hptiop_show_fw_version(struct device *dev,
  				      struct device_attribute *attr, char *buf)
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
868
  {
ee959b00c   Tony Jones   SCSI: convert str...
869
  	struct Scsi_Host *host = class_to_shost(dev);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
870
871
872
873
874
875
876
877
878
  	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...
879
  static struct device_attribute hptiop_attr_version = {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
880
881
882
883
884
885
  	.attr = {
  		.name = "driver-version",
  		.mode = S_IRUGO,
  	},
  	.show = hptiop_show_version,
  };
ee959b00c   Tony Jones   SCSI: convert str...
886
  static struct device_attribute hptiop_attr_fw_version = {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
887
888
889
890
891
892
  	.attr = {
  		.name = "firmware-version",
  		.mode = S_IRUGO,
  	},
  	.show = hptiop_show_fw_version,
  };
ee959b00c   Tony Jones   SCSI: convert str...
893
  static struct device_attribute *hptiop_attrs[] = {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
894
895
896
897
898
899
900
901
902
903
904
905
  	&hptiop_attr_version,
  	&hptiop_attr_fw_version,
  	NULL
  };
  
  static struct scsi_host_template driver_template = {
  	.module                     = THIS_MODULE,
  	.name                       = driver_name,
  	.queuecommand               = hptiop_queuecommand,
  	.eh_device_reset_handler    = hptiop_reset,
  	.eh_bus_reset_handler       = hptiop_reset,
  	.info                       = hptiop_info,
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
906
907
908
909
910
911
912
  	.emulated                   = 0,
  	.use_clustering             = ENABLE_CLUSTERING,
  	.proc_name                  = driver_name,
  	.shost_attrs                = hptiop_attrs,
  	.this_id                    = -1,
  	.change_queue_depth         = hptiop_adjust_disk_queue_depth,
  };
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
  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;
  }
  
  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;
  }
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
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
  static int __devinit hptiop_probe(struct pci_dev *pcidev,
  					const struct pci_device_id *id)
  {
  	struct Scsi_Host *host = NULL;
  	struct hptiop_hba *hba;
  	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;
  
  	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 */
6a35528a8   Yang Hongyang   dma-mapping: repl...
960
  	if (pci_set_dma_mask(pcidev, DMA_BIT_MASK(64))) {
284901a90   Yang Hongyang   dma-mapping: repl...
961
  		if (pci_set_dma_mask(pcidev, DMA_BIT_MASK(32))) {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
  			printk(KERN_ERR "hptiop: fail to set dma_mask
  ");
  			goto disable_pci_device;
  		}
  	}
  
  	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;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
982
  	hba->ops = (struct hptiop_adapter_ops *)id->driver_data;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
983
984
985
  	hba->pcidev = pcidev;
  	hba->host = host;
  	hba->initialized = 0;
db9b6e89e   HighPoint Linux Team   [SCSI] hptiop: ad...
986
  	hba->iopintf_v2 = 0;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
987
988
989
990
991
992
993
994
995
996
997
998
  
  	atomic_set(&hba->resetting, 0);
  	atomic_set(&hba->reset_count, 0);
  
  	init_waitqueue_head(&hba->reset_wq);
  	init_waitqueue_head(&hba->ioctl_wq);
  
  	host->max_lun = 1;
  	host->max_channel = 0;
  	host->io_port = 0;
  	host->n_io_port = 0;
  	host->irq = pcidev->irq;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
999
  	if (hba->ops->map_pci_bar(hba))
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1000
  		goto free_scsi_host;
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1001
  	if (hba->ops->iop_wait_ready(hba, 20000)) {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1002
1003
1004
1005
1006
  		printk(KERN_ERR "scsi%d: firmware not ready
  ",
  				hba->host->host_no);
  		goto unmap_pci_bar;
  	}
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
  	if (hba->ops->internal_memalloc) {
  		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...
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
  		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...
1029
  	hba->interface_version = le32_to_cpu(iop_config.interface_version);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1030
  	hba->sdram_size = le32_to_cpu(iop_config.sdram_size);
db9b6e89e   HighPoint Linux Team   [SCSI] hptiop: ad...
1031
1032
1033
  	if (hba->firmware_version > 0x01020000 ||
  			hba->interface_version > 0x01020000)
  		hba->iopintf_v2 = 1;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1034
1035
1036
1037
1038
1039
  	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...
1040
1041
1042
1043
1044
1045
  	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...
1046
  	set_config.iop_id = cpu_to_le32(host->host_no);
db9b6e89e   HighPoint Linux Team   [SCSI] hptiop: ad...
1047
1048
  	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...
1049

00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1050
  	if (hba->ops->set_config(hba, &set_config)) {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1051
1052
1053
1054
1055
  		printk(KERN_ERR "scsi%d: set config failed
  ",
  				hba->host->host_no);
  		goto unmap_pci_bar;
  	}
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1056
  	pci_set_drvdata(pcidev, host);
1d6f359a2   Thomas Gleixner   [PATCH] irq-flags...
1057
  	if (request_irq(pcidev->irq, hptiop_intr, IRQF_SHARED,
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1058
1059
1060
1061
  					driver_name, hba)) {
  		printk(KERN_ERR "scsi%d: request irq %d failed
  ",
  					hba->host->host_no, pcidev->irq);
3e74051bc   Christoph Hellwig   [SCSI] hptiop: ba...
1062
  		goto unmap_pci_bar;
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1063
1064
1065
  	}
  
  	/* Allocate request mem */
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
  
  	dprintk("req_size=%d, max_requests=%d
  ", req_size, hba->max_requests);
  
  	hba->req_size = req_size;
  	start_virt = dma_alloc_coherent(&pcidev->dev,
  				hba->req_size*hba->max_requests + 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_irq;
  	}
  
  	hba->dma_coherent = start_virt;
  	hba->dma_coherent_handle = start_phy;
  
  	if ((start_phy & 0x1f) != 0)
  	{
  		offset = ((start_phy + 0x1f) & ~0x1f) - start_phy;
  		start_phy += offset;
  		start_virt += offset;
  	}
  
  	hba->req_list = start_virt;
  	for (i = 0; i < hba->max_requests; i++) {
  		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]);
  		start_virt = (char *)start_virt + hba->req_size;
  		start_phy = start_phy + hba->req_size;
  	}
  
  	/* Enable Interrupt and start background task */
  	if (hptiop_initialize_iop(hba))
  		goto free_request_mem;
3e74051bc   Christoph Hellwig   [SCSI] hptiop: ba...
1106
1107
1108
1109
1110
1111
  	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...
1112
1113
1114
1115
1116
1117
1118
1119
1120
  
  	scsi_scan_host(host);
  
  	dprintk("scsi%d: hptiop_probe successfully
  ", hba->host->host_no);
  	return 0;
  
  free_request_mem:
  	dma_free_coherent(&hba->pcidev->dev,
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1121
  			hba->req_size * hba->max_requests + 0x20,
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1122
1123
1124
1125
  			hba->dma_coherent, hba->dma_coherent_handle);
  
  free_request_irq:
  	free_irq(hba->pcidev->irq, hba);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1126
  unmap_pci_bar:
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1127
1128
  	if (hba->ops->internal_memfree)
  		hba->ops->internal_memfree(hba);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1129

00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1130
  	hba->ops->unmap_pci_bar(hba);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1131
1132
1133
  
  free_scsi_host:
  	scsi_host_put(host);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1134
1135
  free_pci_regions:
  	pci_release_regions(pcidev);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1136
1137
  disable_pci_device:
  	pci_disable_device(pcidev);
1db90ea23   Julia Lawall   [SCSI] hptiop: El...
1138
1139
  	dprintk("scsi%d: hptiop_probe fail
  ", host ? host->host_no : 0);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1140
1141
1142
1143
1144
1145
1146
  	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...
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
  
  	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...
1158
1159
1160
1161
1162
1163
1164
1165
  	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...
1166
1167
  	writel(int_mask |
  		IOPMU_OUTBOUND_INT_MSG0 | IOPMU_OUTBOUND_INT_POSTQUEUE,
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1168
1169
1170
1171
1172
1173
1174
1175
  		&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...
1176
1177
1178
1179
1180
1181
1182
1183
1184
  }
  
  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;
  
  	dprintk("scsi%d: hptiop_remove
  ", hba->host->host_no);
4f2ddba39   HighPoint Linux Team   [SCSI] hptiop: Hi...
1185
  	scsi_remove_host(host);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1186
1187
1188
1189
1190
1191
1192
1193
  	hptiop_shutdown(pcidev);
  
  	free_irq(hba->pcidev->irq, hba);
  
  	dma_free_coherent(&hba->pcidev->dev,
  			hba->req_size * hba->max_requests + 0x20,
  			hba->dma_coherent,
  			hba->dma_coherent_handle);
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1194
1195
1196
1197
  	if (hba->ops->internal_memfree)
  		hba->ops->internal_memfree(hba);
  
  	hba->ops->unmap_pci_bar(hba);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1198
1199
1200
1201
  
  	pci_release_regions(hba->pcidev);
  	pci_set_drvdata(hba->pcidev, NULL);
  	pci_disable_device(hba->pcidev);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1202
1203
  	scsi_host_put(host);
  }
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1204
1205
  static struct hptiop_adapter_ops hptiop_itl_ops = {
  	.iop_wait_ready    = iop_wait_ready_itl,
9bcf09108   Harvey Harrison   scsi: fix integer...
1206
1207
  	.internal_memalloc = NULL,
  	.internal_memfree  = NULL,
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
  	.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,
  };
  
  static struct hptiop_adapter_ops hptiop_mv_ops = {
  	.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,
  };
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1233
  static struct pci_device_id hptiop_id_table[] = {
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1234
1235
  	{ 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...
1236
  	{ PCI_VDEVICE(TTI, 0x3410), (kernel_ulong_t)&hptiop_itl_ops },
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1237
1238
  	{ 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...
1239
  	{ PCI_VDEVICE(TTI, 0x3520), (kernel_ulong_t)&hptiop_itl_ops },
00f597019   HighPoint Linux Team   [SCSI] hptiop: ad...
1240
1241
  	{ 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...
1242
  	{ PCI_VDEVICE(TTI, 0x3530), (kernel_ulong_t)&hptiop_itl_ops },
3bfc13c23   HighPoint Linux Team   [SCSI] hptiop: Ad...
1243
  	{ PCI_VDEVICE(TTI, 0x3540), (kernel_ulong_t)&hptiop_itl_ops },
dd07428b4   HighPoint Linux Team   [SCSI] hptiop: ad...
1244
  	{ PCI_VDEVICE(TTI, 0x3560), (kernel_ulong_t)&hptiop_itl_ops },
dd07428b4   HighPoint Linux Team   [SCSI] hptiop: ad...
1245
1246
1247
1248
  	{ 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...
1249
1250
1251
1252
  	{ 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...
1253
1254
1255
  	{ 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 },
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
  	{},
  };
  
  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...
1271
1272
  	printk(KERN_INFO "%s %s
  ", driver_name_long, driver_ver);
3e74051bc   Christoph Hellwig   [SCSI] hptiop: ba...
1273
  	return pci_register_driver(&hptiop_pci_driver);
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1274
1275
1276
1277
  }
  
  static void __exit hptiop_module_exit(void)
  {
ede1e6f8b   HighPoint Linux Team   [SCSI] hptiop: Hi...
1278
1279
1280
1281
1282
1283
1284
1285
  	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...
1286