1 /*
2 * HighPoint RR3xxx/4xxx RAID Driver for FreeBSD
3 * Copyright (C) 2007-2012 HighPoint Technologies, Inc. All Rights Reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD: stable/10/sys/dev/hptiop/hptiop.c 315813 2017-03-23 06:41:13Z mav $");
29
30 #include <sys/param.h>
31 #include <sys/types.h>
32 #include <sys/cons.h>
33 #include <sys/time.h>
34 #include <sys/systm.h>
35
36 #include <sys/stat.h>
37 #include <sys/malloc.h>
38 #include <sys/conf.h>
39 #include <sys/libkern.h>
40 #include <sys/kernel.h>
41
42 #include <sys/kthread.h>
43 #include <sys/mutex.h>
44 #include <sys/module.h>
45
46 #include <sys/eventhandler.h>
47 #include <sys/bus.h>
48 #include <sys/taskqueue.h>
49 #include <sys/ioccom.h>
50
51 #include <machine/resource.h>
52 #include <machine/bus.h>
53 #include <machine/stdarg.h>
54 #include <sys/rman.h>
55
56 #include <vm/vm.h>
57 #include <vm/pmap.h>
58
59 #include <dev/pci/pcireg.h>
60 #include <dev/pci/pcivar.h>
61
62
63 #include <cam/cam.h>
64 #include <cam/cam_ccb.h>
65 #include <cam/cam_sim.h>
66 #include <cam/cam_xpt_sim.h>
67 #include <cam/cam_debug.h>
68 #include <cam/cam_periph.h>
69 #include <cam/scsi/scsi_all.h>
70 #include <cam/scsi/scsi_message.h>
71
72
73 #include <dev/hptiop/hptiop.h>
74
75 static const char driver_name[] = "hptiop";
76 static const char driver_version[] = "v1.9";
77
78 static devclass_t hptiop_devclass;
79
80 static int hptiop_send_sync_msg(struct hpt_iop_hba *hba,
81 u_int32_t msg, u_int32_t millisec);
82 static void hptiop_request_callback_itl(struct hpt_iop_hba *hba,
83 u_int32_t req);
84 static void hptiop_request_callback_mv(struct hpt_iop_hba *hba, u_int64_t req);
85 static void hptiop_request_callback_mvfrey(struct hpt_iop_hba *hba,
86 u_int32_t req);
87 static void hptiop_os_message_callback(struct hpt_iop_hba *hba, u_int32_t msg);
88 static int hptiop_do_ioctl_itl(struct hpt_iop_hba *hba,
89 struct hpt_iop_ioctl_param *pParams);
90 static int hptiop_do_ioctl_mv(struct hpt_iop_hba *hba,
91 struct hpt_iop_ioctl_param *pParams);
92 static int hptiop_do_ioctl_mvfrey(struct hpt_iop_hba *hba,
93 struct hpt_iop_ioctl_param *pParams);
94 static int hptiop_rescan_bus(struct hpt_iop_hba *hba);
95 static int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba);
96 static int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba);
97 static int hptiop_alloc_pci_res_mvfrey(struct hpt_iop_hba *hba);
98 static int hptiop_get_config_itl(struct hpt_iop_hba *hba,
99 struct hpt_iop_request_get_config *config);
100 static int hptiop_get_config_mv(struct hpt_iop_hba *hba,
101 struct hpt_iop_request_get_config *config);
102 static int hptiop_get_config_mvfrey(struct hpt_iop_hba *hba,
103 struct hpt_iop_request_get_config *config);
104 static int hptiop_set_config_itl(struct hpt_iop_hba *hba,
105 struct hpt_iop_request_set_config *config);
106 static int hptiop_set_config_mv(struct hpt_iop_hba *hba,
107 struct hpt_iop_request_set_config *config);
108 static int hptiop_set_config_mvfrey(struct hpt_iop_hba *hba,
109 struct hpt_iop_request_set_config *config);
110 static int hptiop_internal_memalloc_mv(struct hpt_iop_hba *hba);
111 static int hptiop_internal_memalloc_mvfrey(struct hpt_iop_hba *hba);
112 static int hptiop_internal_memfree_itl(struct hpt_iop_hba *hba);
113 static int hptiop_internal_memfree_mv(struct hpt_iop_hba *hba);
114 static int hptiop_internal_memfree_mvfrey(struct hpt_iop_hba *hba);
115 static int hptiop_post_ioctl_command_itl(struct hpt_iop_hba *hba,
116 u_int32_t req32, struct hpt_iop_ioctl_param *pParams);
117 static int hptiop_post_ioctl_command_mv(struct hpt_iop_hba *hba,
118 struct hpt_iop_request_ioctl_command *req,
119 struct hpt_iop_ioctl_param *pParams);
120 static int hptiop_post_ioctl_command_mvfrey(struct hpt_iop_hba *hba,
121 struct hpt_iop_request_ioctl_command *req,
122 struct hpt_iop_ioctl_param *pParams);
123 static void hptiop_post_req_itl(struct hpt_iop_hba *hba,
124 struct hpt_iop_srb *srb,
125 bus_dma_segment_t *segs, int nsegs);
126 static void hptiop_post_req_mv(struct hpt_iop_hba *hba,
127 struct hpt_iop_srb *srb,
128 bus_dma_segment_t *segs, int nsegs);
129 static void hptiop_post_req_mvfrey(struct hpt_iop_hba *hba,
130 struct hpt_iop_srb *srb,
131 bus_dma_segment_t *segs, int nsegs);
132 static void hptiop_post_msg_itl(struct hpt_iop_hba *hba, u_int32_t msg);
133 static void hptiop_post_msg_mv(struct hpt_iop_hba *hba, u_int32_t msg);
134 static void hptiop_post_msg_mvfrey(struct hpt_iop_hba *hba, u_int32_t msg);
135 static void hptiop_enable_intr_itl(struct hpt_iop_hba *hba);
136 static void hptiop_enable_intr_mv(struct hpt_iop_hba *hba);
137 static void hptiop_enable_intr_mvfrey(struct hpt_iop_hba *hba);
138 static void hptiop_disable_intr_itl(struct hpt_iop_hba *hba);
139 static void hptiop_disable_intr_mv(struct hpt_iop_hba *hba);
140 static void hptiop_disable_intr_mvfrey(struct hpt_iop_hba *hba);
141 static void hptiop_free_srb(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb);
142 static int hptiop_os_query_remove_device(struct hpt_iop_hba *hba, int tid);
143 static int hptiop_probe(device_t dev);
144 static int hptiop_attach(device_t dev);
145 static int hptiop_detach(device_t dev);
146 static int hptiop_shutdown(device_t dev);
147 static void hptiop_action(struct cam_sim *sim, union ccb *ccb);
148 static void hptiop_poll(struct cam_sim *sim);
149 static void hptiop_async(void *callback_arg, u_int32_t code,
150 struct cam_path *path, void *arg);
151 static void hptiop_pci_intr(void *arg);
152 static void hptiop_release_resource(struct hpt_iop_hba *hba);
153 static void hptiop_reset_adapter(void *argv);
154 static d_open_t hptiop_open;
155 static d_close_t hptiop_close;
156 static d_ioctl_t hptiop_ioctl;
157
158 static struct cdevsw hptiop_cdevsw = {
159 .d_open = hptiop_open,
160 .d_close = hptiop_close,
161 .d_ioctl = hptiop_ioctl,
162 .d_name = driver_name,
163 .d_version = D_VERSION,
164 };
165
166 #define hba_from_dev(dev) \
167 ((struct hpt_iop_hba *)devclass_get_softc(hptiop_devclass, dev2unit(dev)))
168
169 #define BUS_SPACE_WRT4_ITL(offset, value) bus_space_write_4(hba->bar0t,\
170 hba->bar0h, offsetof(struct hpt_iopmu_itl, offset), (value))
171 #define BUS_SPACE_RD4_ITL(offset) bus_space_read_4(hba->bar0t,\
172 hba->bar0h, offsetof(struct hpt_iopmu_itl, offset))
173
174 #define BUS_SPACE_WRT4_MV0(offset, value) bus_space_write_4(hba->bar0t,\
175 hba->bar0h, offsetof(struct hpt_iopmv_regs, offset), value)
176 #define BUS_SPACE_RD4_MV0(offset) bus_space_read_4(hba->bar0t,\
177 hba->bar0h, offsetof(struct hpt_iopmv_regs, offset))
178 #define BUS_SPACE_WRT4_MV2(offset, value) bus_space_write_4(hba->bar2t,\
179 hba->bar2h, offsetof(struct hpt_iopmu_mv, offset), value)
180 #define BUS_SPACE_RD4_MV2(offset) bus_space_read_4(hba->bar2t,\
181 hba->bar2h, offsetof(struct hpt_iopmu_mv, offset))
182
183 #define BUS_SPACE_WRT4_MVFREY2(offset, value) bus_space_write_4(hba->bar2t,\
184 hba->bar2h, offsetof(struct hpt_iopmu_mvfrey, offset), value)
185 #define BUS_SPACE_RD4_MVFREY2(offset) bus_space_read_4(hba->bar2t,\
186 hba->bar2h, offsetof(struct hpt_iopmu_mvfrey, offset))
187
hptiop_open(ioctl_dev_t dev,int flags,int devtype,ioctl_thread_t proc)188 static int hptiop_open(ioctl_dev_t dev, int flags,
189 int devtype, ioctl_thread_t proc)
190 {
191 struct hpt_iop_hba *hba = hba_from_dev(dev);
192
193 if (hba==NULL)
194 return ENXIO;
195 if (hba->flag & HPT_IOCTL_FLAG_OPEN)
196 return EBUSY;
197 hba->flag |= HPT_IOCTL_FLAG_OPEN;
198 return 0;
199 }
200
hptiop_close(ioctl_dev_t dev,int flags,int devtype,ioctl_thread_t proc)201 static int hptiop_close(ioctl_dev_t dev, int flags,
202 int devtype, ioctl_thread_t proc)
203 {
204 struct hpt_iop_hba *hba = hba_from_dev(dev);
205 hba->flag &= ~(u_int32_t)HPT_IOCTL_FLAG_OPEN;
206 return 0;
207 }
208
hptiop_ioctl(ioctl_dev_t dev,u_long cmd,caddr_t data,int flags,ioctl_thread_t proc)209 static int hptiop_ioctl(ioctl_dev_t dev, u_long cmd, caddr_t data,
210 int flags, ioctl_thread_t proc)
211 {
212 int ret = EFAULT;
213 struct hpt_iop_hba *hba = hba_from_dev(dev);
214
215 mtx_lock(&Giant);
216
217 switch (cmd) {
218 case HPT_DO_IOCONTROL:
219 ret = hba->ops->do_ioctl(hba,
220 (struct hpt_iop_ioctl_param *)data);
221 break;
222 case HPT_SCAN_BUS:
223 ret = hptiop_rescan_bus(hba);
224 break;
225 }
226
227 mtx_unlock(&Giant);
228
229 return ret;
230 }
231
hptiop_mv_outbound_read(struct hpt_iop_hba * hba)232 static u_int64_t hptiop_mv_outbound_read(struct hpt_iop_hba *hba)
233 {
234 u_int64_t p;
235 u_int32_t outbound_tail = BUS_SPACE_RD4_MV2(outbound_tail);
236 u_int32_t outbound_head = BUS_SPACE_RD4_MV2(outbound_head);
237
238 if (outbound_tail != outbound_head) {
239 bus_space_read_region_4(hba->bar2t, hba->bar2h,
240 offsetof(struct hpt_iopmu_mv,
241 outbound_q[outbound_tail]),
242 (u_int32_t *)&p, 2);
243
244 outbound_tail++;
245
246 if (outbound_tail == MVIOP_QUEUE_LEN)
247 outbound_tail = 0;
248
249 BUS_SPACE_WRT4_MV2(outbound_tail, outbound_tail);
250 return p;
251 } else
252 return 0;
253 }
254
hptiop_mv_inbound_write(u_int64_t p,struct hpt_iop_hba * hba)255 static void hptiop_mv_inbound_write(u_int64_t p, struct hpt_iop_hba *hba)
256 {
257 u_int32_t inbound_head = BUS_SPACE_RD4_MV2(inbound_head);
258 u_int32_t head = inbound_head + 1;
259
260 if (head == MVIOP_QUEUE_LEN)
261 head = 0;
262
263 bus_space_write_region_4(hba->bar2t, hba->bar2h,
264 offsetof(struct hpt_iopmu_mv, inbound_q[inbound_head]),
265 (u_int32_t *)&p, 2);
266 BUS_SPACE_WRT4_MV2(inbound_head, head);
267 BUS_SPACE_WRT4_MV0(inbound_doorbell, MVIOP_MU_INBOUND_INT_POSTQUEUE);
268 }
269
hptiop_post_msg_itl(struct hpt_iop_hba * hba,u_int32_t msg)270 static void hptiop_post_msg_itl(struct hpt_iop_hba *hba, u_int32_t msg)
271 {
272 BUS_SPACE_WRT4_ITL(inbound_msgaddr0, msg);
273 BUS_SPACE_RD4_ITL(outbound_intstatus);
274 }
275
hptiop_post_msg_mv(struct hpt_iop_hba * hba,u_int32_t msg)276 static void hptiop_post_msg_mv(struct hpt_iop_hba *hba, u_int32_t msg)
277 {
278
279 BUS_SPACE_WRT4_MV2(inbound_msg, msg);
280 BUS_SPACE_WRT4_MV0(inbound_doorbell, MVIOP_MU_INBOUND_INT_MSG);
281
282 BUS_SPACE_RD4_MV0(outbound_intmask);
283 }
284
hptiop_post_msg_mvfrey(struct hpt_iop_hba * hba,u_int32_t msg)285 static void hptiop_post_msg_mvfrey(struct hpt_iop_hba *hba, u_int32_t msg)
286 {
287 BUS_SPACE_WRT4_MVFREY2(f0_to_cpu_msg_a, msg);
288 BUS_SPACE_RD4_MVFREY2(f0_to_cpu_msg_a);
289 }
290
hptiop_wait_ready_itl(struct hpt_iop_hba * hba,u_int32_t millisec)291 static int hptiop_wait_ready_itl(struct hpt_iop_hba * hba, u_int32_t millisec)
292 {
293 u_int32_t req=0;
294 int i;
295
296 for (i = 0; i < millisec; i++) {
297 req = BUS_SPACE_RD4_ITL(inbound_queue);
298 if (req != IOPMU_QUEUE_EMPTY)
299 break;
300 DELAY(1000);
301 }
302
303 if (req!=IOPMU_QUEUE_EMPTY) {
304 BUS_SPACE_WRT4_ITL(outbound_queue, req);
305 BUS_SPACE_RD4_ITL(outbound_intstatus);
306 return 0;
307 }
308
309 return -1;
310 }
311
hptiop_wait_ready_mv(struct hpt_iop_hba * hba,u_int32_t millisec)312 static int hptiop_wait_ready_mv(struct hpt_iop_hba * hba, u_int32_t millisec)
313 {
314 if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec))
315 return -1;
316
317 return 0;
318 }
319
hptiop_wait_ready_mvfrey(struct hpt_iop_hba * hba,u_int32_t millisec)320 static int hptiop_wait_ready_mvfrey(struct hpt_iop_hba * hba,
321 u_int32_t millisec)
322 {
323 if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec))
324 return -1;
325
326 return 0;
327 }
328
hptiop_request_callback_itl(struct hpt_iop_hba * hba,u_int32_t index)329 static void hptiop_request_callback_itl(struct hpt_iop_hba * hba,
330 u_int32_t index)
331 {
332 struct hpt_iop_srb *srb;
333 struct hpt_iop_request_scsi_command *req=0;
334 union ccb *ccb;
335 u_int8_t *cdb;
336 u_int32_t result, temp, dxfer;
337 u_int64_t temp64;
338
339 if (index & IOPMU_QUEUE_MASK_HOST_BITS) { /*host req*/
340 if (hba->firmware_version > 0x01020000 ||
341 hba->interface_version > 0x01020000) {
342 srb = hba->srb[index & ~(u_int32_t)
343 (IOPMU_QUEUE_ADDR_HOST_BIT
344 | IOPMU_QUEUE_REQUEST_RESULT_BIT)];
345 req = (struct hpt_iop_request_scsi_command *)srb;
346 if (index & IOPMU_QUEUE_REQUEST_RESULT_BIT)
347 result = IOP_RESULT_SUCCESS;
348 else
349 result = req->header.result;
350 } else {
351 srb = hba->srb[index &
352 ~(u_int32_t)IOPMU_QUEUE_ADDR_HOST_BIT];
353 req = (struct hpt_iop_request_scsi_command *)srb;
354 result = req->header.result;
355 }
356 dxfer = req->dataxfer_length;
357 goto srb_complete;
358 }
359
360 /*iop req*/
361 temp = bus_space_read_4(hba->bar0t, hba->bar0h, index +
362 offsetof(struct hpt_iop_request_header, type));
363 result = bus_space_read_4(hba->bar0t, hba->bar0h, index +
364 offsetof(struct hpt_iop_request_header, result));
365 switch(temp) {
366 case IOP_REQUEST_TYPE_IOCTL_COMMAND:
367 {
368 temp64 = 0;
369 bus_space_write_region_4(hba->bar0t, hba->bar0h, index +
370 offsetof(struct hpt_iop_request_header, context),
371 (u_int32_t *)&temp64, 2);
372 wakeup((void *)((unsigned long)hba->u.itl.mu + index));
373 break;
374 }
375
376 case IOP_REQUEST_TYPE_SCSI_COMMAND:
377 bus_space_read_region_4(hba->bar0t, hba->bar0h, index +
378 offsetof(struct hpt_iop_request_header, context),
379 (u_int32_t *)&temp64, 2);
380 srb = (struct hpt_iop_srb *)(unsigned long)temp64;
381 dxfer = bus_space_read_4(hba->bar0t, hba->bar0h,
382 index + offsetof(struct hpt_iop_request_scsi_command,
383 dataxfer_length));
384 srb_complete:
385 ccb = (union ccb *)srb->ccb;
386 if (ccb->ccb_h.flags & CAM_CDB_POINTER)
387 cdb = ccb->csio.cdb_io.cdb_ptr;
388 else
389 cdb = ccb->csio.cdb_io.cdb_bytes;
390
391 if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */
392 ccb->ccb_h.status = CAM_REQ_CMP;
393 goto scsi_done;
394 }
395
396 switch (result) {
397 case IOP_RESULT_SUCCESS:
398 switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
399 case CAM_DIR_IN:
400 bus_dmamap_sync(hba->io_dmat,
401 srb->dma_map, BUS_DMASYNC_POSTREAD);
402 bus_dmamap_unload(hba->io_dmat, srb->dma_map);
403 break;
404 case CAM_DIR_OUT:
405 bus_dmamap_sync(hba->io_dmat,
406 srb->dma_map, BUS_DMASYNC_POSTWRITE);
407 bus_dmamap_unload(hba->io_dmat, srb->dma_map);
408 break;
409 }
410
411 ccb->ccb_h.status = CAM_REQ_CMP;
412 break;
413
414 case IOP_RESULT_BAD_TARGET:
415 ccb->ccb_h.status = CAM_DEV_NOT_THERE;
416 break;
417 case IOP_RESULT_BUSY:
418 ccb->ccb_h.status = CAM_BUSY;
419 break;
420 case IOP_RESULT_INVALID_REQUEST:
421 ccb->ccb_h.status = CAM_REQ_INVALID;
422 break;
423 case IOP_RESULT_FAIL:
424 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
425 break;
426 case IOP_RESULT_RESET:
427 ccb->ccb_h.status = CAM_BUSY;
428 break;
429 case IOP_RESULT_CHECK_CONDITION:
430 memset(&ccb->csio.sense_data, 0,
431 sizeof(ccb->csio.sense_data));
432 if (dxfer < ccb->csio.sense_len)
433 ccb->csio.sense_resid = ccb->csio.sense_len -
434 dxfer;
435 else
436 ccb->csio.sense_resid = 0;
437 if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) {/*iop*/
438 bus_space_read_region_1(hba->bar0t, hba->bar0h,
439 index + offsetof(struct hpt_iop_request_scsi_command,
440 sg_list), (u_int8_t *)&ccb->csio.sense_data,
441 MIN(dxfer, sizeof(ccb->csio.sense_data)));
442 } else {
443 memcpy(&ccb->csio.sense_data, &req->sg_list,
444 MIN(dxfer, sizeof(ccb->csio.sense_data)));
445 }
446 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
447 ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
448 ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
449 break;
450 default:
451 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
452 break;
453 }
454 scsi_done:
455 if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS)
456 BUS_SPACE_WRT4_ITL(outbound_queue, index);
457
458 ccb->csio.resid = ccb->csio.dxfer_len - dxfer;
459
460 hptiop_free_srb(hba, srb);
461 xpt_done(ccb);
462 break;
463 }
464 }
465
hptiop_drain_outbound_queue_itl(struct hpt_iop_hba * hba)466 static void hptiop_drain_outbound_queue_itl(struct hpt_iop_hba *hba)
467 {
468 u_int32_t req, temp;
469
470 while ((req = BUS_SPACE_RD4_ITL(outbound_queue)) !=IOPMU_QUEUE_EMPTY) {
471 if (req & IOPMU_QUEUE_MASK_HOST_BITS)
472 hptiop_request_callback_itl(hba, req);
473 else {
474 struct hpt_iop_request_header *p;
475
476 p = (struct hpt_iop_request_header *)
477 ((char *)hba->u.itl.mu + req);
478 temp = bus_space_read_4(hba->bar0t,
479 hba->bar0h,req +
480 offsetof(struct hpt_iop_request_header,
481 flags));
482 if (temp & IOP_REQUEST_FLAG_SYNC_REQUEST) {
483 u_int64_t temp64;
484 bus_space_read_region_4(hba->bar0t,
485 hba->bar0h,req +
486 offsetof(struct hpt_iop_request_header,
487 context),
488 (u_int32_t *)&temp64, 2);
489 if (temp64) {
490 hptiop_request_callback_itl(hba, req);
491 } else {
492 temp64 = 1;
493 bus_space_write_region_4(hba->bar0t,
494 hba->bar0h,req +
495 offsetof(struct hpt_iop_request_header,
496 context),
497 (u_int32_t *)&temp64, 2);
498 }
499 } else
500 hptiop_request_callback_itl(hba, req);
501 }
502 }
503 }
504
hptiop_intr_itl(struct hpt_iop_hba * hba)505 static int hptiop_intr_itl(struct hpt_iop_hba * hba)
506 {
507 u_int32_t status;
508 int ret = 0;
509
510 status = BUS_SPACE_RD4_ITL(outbound_intstatus);
511
512 if (status & IOPMU_OUTBOUND_INT_MSG0) {
513 u_int32_t msg = BUS_SPACE_RD4_ITL(outbound_msgaddr0);
514 KdPrint(("hptiop: received outbound msg %x\n", msg));
515 BUS_SPACE_WRT4_ITL(outbound_intstatus, IOPMU_OUTBOUND_INT_MSG0);
516 hptiop_os_message_callback(hba, msg);
517 ret = 1;
518 }
519
520 if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) {
521 hptiop_drain_outbound_queue_itl(hba);
522 ret = 1;
523 }
524
525 return ret;
526 }
527
hptiop_request_callback_mv(struct hpt_iop_hba * hba,u_int64_t _tag)528 static void hptiop_request_callback_mv(struct hpt_iop_hba * hba,
529 u_int64_t _tag)
530 {
531 u_int32_t context = (u_int32_t)_tag;
532
533 if (context & MVIOP_CMD_TYPE_SCSI) {
534 struct hpt_iop_srb *srb;
535 struct hpt_iop_request_scsi_command *req;
536 union ccb *ccb;
537 u_int8_t *cdb;
538
539 srb = hba->srb[context >> MVIOP_REQUEST_NUMBER_START_BIT];
540 req = (struct hpt_iop_request_scsi_command *)srb;
541 ccb = (union ccb *)srb->ccb;
542 if (ccb->ccb_h.flags & CAM_CDB_POINTER)
543 cdb = ccb->csio.cdb_io.cdb_ptr;
544 else
545 cdb = ccb->csio.cdb_io.cdb_bytes;
546
547 if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */
548 ccb->ccb_h.status = CAM_REQ_CMP;
549 goto scsi_done;
550 }
551 if (context & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT)
552 req->header.result = IOP_RESULT_SUCCESS;
553
554 switch (req->header.result) {
555 case IOP_RESULT_SUCCESS:
556 switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
557 case CAM_DIR_IN:
558 bus_dmamap_sync(hba->io_dmat,
559 srb->dma_map, BUS_DMASYNC_POSTREAD);
560 bus_dmamap_unload(hba->io_dmat, srb->dma_map);
561 break;
562 case CAM_DIR_OUT:
563 bus_dmamap_sync(hba->io_dmat,
564 srb->dma_map, BUS_DMASYNC_POSTWRITE);
565 bus_dmamap_unload(hba->io_dmat, srb->dma_map);
566 break;
567 }
568 ccb->ccb_h.status = CAM_REQ_CMP;
569 break;
570 case IOP_RESULT_BAD_TARGET:
571 ccb->ccb_h.status = CAM_DEV_NOT_THERE;
572 break;
573 case IOP_RESULT_BUSY:
574 ccb->ccb_h.status = CAM_BUSY;
575 break;
576 case IOP_RESULT_INVALID_REQUEST:
577 ccb->ccb_h.status = CAM_REQ_INVALID;
578 break;
579 case IOP_RESULT_FAIL:
580 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
581 break;
582 case IOP_RESULT_RESET:
583 ccb->ccb_h.status = CAM_BUSY;
584 break;
585 case IOP_RESULT_CHECK_CONDITION:
586 memset(&ccb->csio.sense_data, 0,
587 sizeof(ccb->csio.sense_data));
588 if (req->dataxfer_length < ccb->csio.sense_len)
589 ccb->csio.sense_resid = ccb->csio.sense_len -
590 req->dataxfer_length;
591 else
592 ccb->csio.sense_resid = 0;
593 memcpy(&ccb->csio.sense_data, &req->sg_list,
594 MIN(req->dataxfer_length, sizeof(ccb->csio.sense_data)));
595 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
596 ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
597 ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
598 break;
599 default:
600 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
601 break;
602 }
603 scsi_done:
604 ccb->csio.resid = ccb->csio.dxfer_len - req->dataxfer_length;
605
606 hptiop_free_srb(hba, srb);
607 xpt_done(ccb);
608 } else if (context & MVIOP_CMD_TYPE_IOCTL) {
609 struct hpt_iop_request_ioctl_command *req = hba->ctlcfg_ptr;
610 if (context & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT)
611 hba->config_done = 1;
612 else
613 hba->config_done = -1;
614 wakeup(req);
615 } else if (context &
616 (MVIOP_CMD_TYPE_SET_CONFIG |
617 MVIOP_CMD_TYPE_GET_CONFIG))
618 hba->config_done = 1;
619 else {
620 device_printf(hba->pcidev, "wrong callback type\n");
621 }
622 }
623
hptiop_request_callback_mvfrey(struct hpt_iop_hba * hba,u_int32_t _tag)624 static void hptiop_request_callback_mvfrey(struct hpt_iop_hba * hba,
625 u_int32_t _tag)
626 {
627 u_int32_t req_type = _tag & 0xf;
628
629 struct hpt_iop_srb *srb;
630 struct hpt_iop_request_scsi_command *req;
631 union ccb *ccb;
632 u_int8_t *cdb;
633
634 switch (req_type) {
635 case IOP_REQUEST_TYPE_GET_CONFIG:
636 case IOP_REQUEST_TYPE_SET_CONFIG:
637 hba->config_done = 1;
638 break;
639
640 case IOP_REQUEST_TYPE_SCSI_COMMAND:
641 srb = hba->srb[(_tag >> 4) & 0xff];
642 req = (struct hpt_iop_request_scsi_command *)srb;
643
644 ccb = (union ccb *)srb->ccb;
645
646 untimeout(hptiop_reset_adapter, hba, srb->timeout_ch);
647
648 if (ccb->ccb_h.flags & CAM_CDB_POINTER)
649 cdb = ccb->csio.cdb_io.cdb_ptr;
650 else
651 cdb = ccb->csio.cdb_io.cdb_bytes;
652
653 if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */
654 ccb->ccb_h.status = CAM_REQ_CMP;
655 goto scsi_done;
656 }
657
658 if (_tag & MVFREYIOPMU_QUEUE_REQUEST_RESULT_BIT)
659 req->header.result = IOP_RESULT_SUCCESS;
660
661 switch (req->header.result) {
662 case IOP_RESULT_SUCCESS:
663 switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
664 case CAM_DIR_IN:
665 bus_dmamap_sync(hba->io_dmat,
666 srb->dma_map, BUS_DMASYNC_POSTREAD);
667 bus_dmamap_unload(hba->io_dmat, srb->dma_map);
668 break;
669 case CAM_DIR_OUT:
670 bus_dmamap_sync(hba->io_dmat,
671 srb->dma_map, BUS_DMASYNC_POSTWRITE);
672 bus_dmamap_unload(hba->io_dmat, srb->dma_map);
673 break;
674 }
675 ccb->ccb_h.status = CAM_REQ_CMP;
676 break;
677 case IOP_RESULT_BAD_TARGET:
678 ccb->ccb_h.status = CAM_DEV_NOT_THERE;
679 break;
680 case IOP_RESULT_BUSY:
681 ccb->ccb_h.status = CAM_BUSY;
682 break;
683 case IOP_RESULT_INVALID_REQUEST:
684 ccb->ccb_h.status = CAM_REQ_INVALID;
685 break;
686 case IOP_RESULT_FAIL:
687 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
688 break;
689 case IOP_RESULT_RESET:
690 ccb->ccb_h.status = CAM_BUSY;
691 break;
692 case IOP_RESULT_CHECK_CONDITION:
693 memset(&ccb->csio.sense_data, 0,
694 sizeof(ccb->csio.sense_data));
695 if (req->dataxfer_length < ccb->csio.sense_len)
696 ccb->csio.sense_resid = ccb->csio.sense_len -
697 req->dataxfer_length;
698 else
699 ccb->csio.sense_resid = 0;
700 memcpy(&ccb->csio.sense_data, &req->sg_list,
701 MIN(req->dataxfer_length, sizeof(ccb->csio.sense_data)));
702 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
703 ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
704 ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
705 break;
706 default:
707 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
708 break;
709 }
710 scsi_done:
711 ccb->csio.resid = ccb->csio.dxfer_len - req->dataxfer_length;
712
713 hptiop_free_srb(hba, srb);
714 xpt_done(ccb);
715 break;
716 case IOP_REQUEST_TYPE_IOCTL_COMMAND:
717 if (_tag & MVFREYIOPMU_QUEUE_REQUEST_RESULT_BIT)
718 hba->config_done = 1;
719 else
720 hba->config_done = -1;
721 wakeup((struct hpt_iop_request_ioctl_command *)hba->ctlcfg_ptr);
722 break;
723 default:
724 device_printf(hba->pcidev, "wrong callback type\n");
725 break;
726 }
727 }
728
hptiop_drain_outbound_queue_mv(struct hpt_iop_hba * hba)729 static void hptiop_drain_outbound_queue_mv(struct hpt_iop_hba * hba)
730 {
731 u_int64_t req;
732
733 while ((req = hptiop_mv_outbound_read(hba))) {
734 if (req & MVIOP_MU_QUEUE_ADDR_HOST_BIT) {
735 if (req & MVIOP_MU_QUEUE_REQUEST_RETURN_CONTEXT) {
736 hptiop_request_callback_mv(hba, req);
737 }
738 }
739 }
740 }
741
hptiop_intr_mv(struct hpt_iop_hba * hba)742 static int hptiop_intr_mv(struct hpt_iop_hba * hba)
743 {
744 u_int32_t status;
745 int ret = 0;
746
747 status = BUS_SPACE_RD4_MV0(outbound_doorbell);
748
749 if (status)
750 BUS_SPACE_WRT4_MV0(outbound_doorbell, ~status);
751
752 if (status & MVIOP_MU_OUTBOUND_INT_MSG) {
753 u_int32_t msg = BUS_SPACE_RD4_MV2(outbound_msg);
754 KdPrint(("hptiop: received outbound msg %x\n", msg));
755 hptiop_os_message_callback(hba, msg);
756 ret = 1;
757 }
758
759 if (status & MVIOP_MU_OUTBOUND_INT_POSTQUEUE) {
760 hptiop_drain_outbound_queue_mv(hba);
761 ret = 1;
762 }
763
764 return ret;
765 }
766
hptiop_intr_mvfrey(struct hpt_iop_hba * hba)767 static int hptiop_intr_mvfrey(struct hpt_iop_hba * hba)
768 {
769 u_int32_t status, _tag, cptr;
770 int ret = 0;
771
772 if (hba->initialized) {
773 BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0);
774 }
775
776 status = BUS_SPACE_RD4_MVFREY2(f0_doorbell);
777 if (status) {
778 BUS_SPACE_WRT4_MVFREY2(f0_doorbell, status);
779 if (status & CPU_TO_F0_DRBL_MSG_A_BIT) {
780 u_int32_t msg = BUS_SPACE_RD4_MVFREY2(cpu_to_f0_msg_a);
781 hptiop_os_message_callback(hba, msg);
782 }
783 ret = 1;
784 }
785
786 status = BUS_SPACE_RD4_MVFREY2(isr_cause);
787 if (status) {
788 BUS_SPACE_WRT4_MVFREY2(isr_cause, status);
789 do {
790 cptr = *hba->u.mvfrey.outlist_cptr & 0xff;
791 while (hba->u.mvfrey.outlist_rptr != cptr) {
792 hba->u.mvfrey.outlist_rptr++;
793 if (hba->u.mvfrey.outlist_rptr == hba->u.mvfrey.list_count) {
794 hba->u.mvfrey.outlist_rptr = 0;
795 }
796
797 _tag = hba->u.mvfrey.outlist[hba->u.mvfrey.outlist_rptr].val;
798 hptiop_request_callback_mvfrey(hba, _tag);
799 ret = 2;
800 }
801 } while (cptr != (*hba->u.mvfrey.outlist_cptr & 0xff));
802 }
803
804 if (hba->initialized) {
805 BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0x1010);
806 }
807
808 return ret;
809 }
810
hptiop_send_sync_request_itl(struct hpt_iop_hba * hba,u_int32_t req32,u_int32_t millisec)811 static int hptiop_send_sync_request_itl(struct hpt_iop_hba * hba,
812 u_int32_t req32, u_int32_t millisec)
813 {
814 u_int32_t i;
815 u_int64_t temp64;
816
817 BUS_SPACE_WRT4_ITL(inbound_queue, req32);
818 BUS_SPACE_RD4_ITL(outbound_intstatus);
819
820 for (i = 0; i < millisec; i++) {
821 hptiop_intr_itl(hba);
822 bus_space_read_region_4(hba->bar0t, hba->bar0h, req32 +
823 offsetof(struct hpt_iop_request_header, context),
824 (u_int32_t *)&temp64, 2);
825 if (temp64)
826 return 0;
827 DELAY(1000);
828 }
829
830 return -1;
831 }
832
hptiop_send_sync_request_mv(struct hpt_iop_hba * hba,void * req,u_int32_t millisec)833 static int hptiop_send_sync_request_mv(struct hpt_iop_hba *hba,
834 void *req, u_int32_t millisec)
835 {
836 u_int32_t i;
837 u_int64_t phy_addr;
838 hba->config_done = 0;
839
840 phy_addr = hba->ctlcfgcmd_phy |
841 (u_int64_t)MVIOP_MU_QUEUE_ADDR_HOST_BIT;
842 ((struct hpt_iop_request_get_config *)req)->header.flags |=
843 IOP_REQUEST_FLAG_SYNC_REQUEST |
844 IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
845 hptiop_mv_inbound_write(phy_addr, hba);
846 BUS_SPACE_RD4_MV0(outbound_intmask);
847
848 for (i = 0; i < millisec; i++) {
849 hptiop_intr_mv(hba);
850 if (hba->config_done)
851 return 0;
852 DELAY(1000);
853 }
854 return -1;
855 }
856
hptiop_send_sync_request_mvfrey(struct hpt_iop_hba * hba,void * req,u_int32_t millisec)857 static int hptiop_send_sync_request_mvfrey(struct hpt_iop_hba *hba,
858 void *req, u_int32_t millisec)
859 {
860 u_int32_t i, index;
861 u_int64_t phy_addr;
862 struct hpt_iop_request_header *reqhdr =
863 (struct hpt_iop_request_header *)req;
864
865 hba->config_done = 0;
866
867 phy_addr = hba->ctlcfgcmd_phy;
868 reqhdr->flags = IOP_REQUEST_FLAG_SYNC_REQUEST
869 | IOP_REQUEST_FLAG_OUTPUT_CONTEXT
870 | IOP_REQUEST_FLAG_ADDR_BITS
871 | ((phy_addr >> 16) & 0xffff0000);
872 reqhdr->context = ((phy_addr & 0xffffffff) << 32 )
873 | IOPMU_QUEUE_ADDR_HOST_BIT | reqhdr->type;
874
875 hba->u.mvfrey.inlist_wptr++;
876 index = hba->u.mvfrey.inlist_wptr & 0x3fff;
877
878 if (index == hba->u.mvfrey.list_count) {
879 index = 0;
880 hba->u.mvfrey.inlist_wptr &= ~0x3fff;
881 hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE;
882 }
883
884 hba->u.mvfrey.inlist[index].addr = phy_addr;
885 hba->u.mvfrey.inlist[index].intrfc_len = (reqhdr->size + 3) / 4;
886
887 BUS_SPACE_WRT4_MVFREY2(inbound_write_ptr, hba->u.mvfrey.inlist_wptr);
888 BUS_SPACE_RD4_MVFREY2(inbound_write_ptr);
889
890 for (i = 0; i < millisec; i++) {
891 hptiop_intr_mvfrey(hba);
892 if (hba->config_done)
893 return 0;
894 DELAY(1000);
895 }
896 return -1;
897 }
898
hptiop_send_sync_msg(struct hpt_iop_hba * hba,u_int32_t msg,u_int32_t millisec)899 static int hptiop_send_sync_msg(struct hpt_iop_hba *hba,
900 u_int32_t msg, u_int32_t millisec)
901 {
902 u_int32_t i;
903
904 hba->msg_done = 0;
905 hba->ops->post_msg(hba, msg);
906
907 for (i=0; i<millisec; i++) {
908 hba->ops->iop_intr(hba);
909 if (hba->msg_done)
910 break;
911 DELAY(1000);
912 }
913
914 return hba->msg_done? 0 : -1;
915 }
916
hptiop_get_config_itl(struct hpt_iop_hba * hba,struct hpt_iop_request_get_config * config)917 static int hptiop_get_config_itl(struct hpt_iop_hba * hba,
918 struct hpt_iop_request_get_config * config)
919 {
920 u_int32_t req32;
921
922 config->header.size = sizeof(struct hpt_iop_request_get_config);
923 config->header.type = IOP_REQUEST_TYPE_GET_CONFIG;
924 config->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST;
925 config->header.result = IOP_RESULT_PENDING;
926 config->header.context = 0;
927
928 req32 = BUS_SPACE_RD4_ITL(inbound_queue);
929 if (req32 == IOPMU_QUEUE_EMPTY)
930 return -1;
931
932 bus_space_write_region_4(hba->bar0t, hba->bar0h,
933 req32, (u_int32_t *)config,
934 sizeof(struct hpt_iop_request_header) >> 2);
935
936 if (hptiop_send_sync_request_itl(hba, req32, 20000)) {
937 KdPrint(("hptiop: get config send cmd failed"));
938 return -1;
939 }
940
941 bus_space_read_region_4(hba->bar0t, hba->bar0h,
942 req32, (u_int32_t *)config,
943 sizeof(struct hpt_iop_request_get_config) >> 2);
944
945 BUS_SPACE_WRT4_ITL(outbound_queue, req32);
946
947 return 0;
948 }
949
hptiop_get_config_mv(struct hpt_iop_hba * hba,struct hpt_iop_request_get_config * config)950 static int hptiop_get_config_mv(struct hpt_iop_hba * hba,
951 struct hpt_iop_request_get_config * config)
952 {
953 struct hpt_iop_request_get_config *req;
954
955 if (!(req = hba->ctlcfg_ptr))
956 return -1;
957
958 req->header.flags = 0;
959 req->header.type = IOP_REQUEST_TYPE_GET_CONFIG;
960 req->header.size = sizeof(struct hpt_iop_request_get_config);
961 req->header.result = IOP_RESULT_PENDING;
962 req->header.context = MVIOP_CMD_TYPE_GET_CONFIG;
963
964 if (hptiop_send_sync_request_mv(hba, req, 20000)) {
965 KdPrint(("hptiop: get config send cmd failed"));
966 return -1;
967 }
968
969 *config = *req;
970 return 0;
971 }
972
hptiop_get_config_mvfrey(struct hpt_iop_hba * hba,struct hpt_iop_request_get_config * config)973 static int hptiop_get_config_mvfrey(struct hpt_iop_hba * hba,
974 struct hpt_iop_request_get_config * config)
975 {
976 struct hpt_iop_request_get_config *info = hba->u.mvfrey.config;
977
978 if (info->header.size != sizeof(struct hpt_iop_request_get_config) ||
979 info->header.type != IOP_REQUEST_TYPE_GET_CONFIG) {
980 KdPrint(("hptiop: header size %x/%x type %x/%x",
981 info->header.size, (int)sizeof(struct hpt_iop_request_get_config),
982 info->header.type, IOP_REQUEST_TYPE_GET_CONFIG));
983 return -1;
984 }
985
986 config->interface_version = info->interface_version;
987 config->firmware_version = info->firmware_version;
988 config->max_requests = info->max_requests;
989 config->request_size = info->request_size;
990 config->max_sg_count = info->max_sg_count;
991 config->data_transfer_length = info->data_transfer_length;
992 config->alignment_mask = info->alignment_mask;
993 config->max_devices = info->max_devices;
994 config->sdram_size = info->sdram_size;
995
996 KdPrint(("hptiop: maxreq %x reqsz %x datalen %x maxdev %x sdram %x",
997 config->max_requests, config->request_size,
998 config->data_transfer_length, config->max_devices,
999 config->sdram_size));
1000
1001 return 0;
1002 }
1003
hptiop_set_config_itl(struct hpt_iop_hba * hba,struct hpt_iop_request_set_config * config)1004 static int hptiop_set_config_itl(struct hpt_iop_hba *hba,
1005 struct hpt_iop_request_set_config *config)
1006 {
1007 u_int32_t req32;
1008
1009 req32 = BUS_SPACE_RD4_ITL(inbound_queue);
1010
1011 if (req32 == IOPMU_QUEUE_EMPTY)
1012 return -1;
1013
1014 config->header.size = sizeof(struct hpt_iop_request_set_config);
1015 config->header.type = IOP_REQUEST_TYPE_SET_CONFIG;
1016 config->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST;
1017 config->header.result = IOP_RESULT_PENDING;
1018 config->header.context = 0;
1019
1020 bus_space_write_region_4(hba->bar0t, hba->bar0h, req32,
1021 (u_int32_t *)config,
1022 sizeof(struct hpt_iop_request_set_config) >> 2);
1023
1024 if (hptiop_send_sync_request_itl(hba, req32, 20000)) {
1025 KdPrint(("hptiop: set config send cmd failed"));
1026 return -1;
1027 }
1028
1029 BUS_SPACE_WRT4_ITL(outbound_queue, req32);
1030
1031 return 0;
1032 }
1033
hptiop_set_config_mv(struct hpt_iop_hba * hba,struct hpt_iop_request_set_config * config)1034 static int hptiop_set_config_mv(struct hpt_iop_hba *hba,
1035 struct hpt_iop_request_set_config *config)
1036 {
1037 struct hpt_iop_request_set_config *req;
1038
1039 if (!(req = hba->ctlcfg_ptr))
1040 return -1;
1041
1042 memcpy((u_int8_t *)req + sizeof(struct hpt_iop_request_header),
1043 (u_int8_t *)config + sizeof(struct hpt_iop_request_header),
1044 sizeof(struct hpt_iop_request_set_config) -
1045 sizeof(struct hpt_iop_request_header));
1046
1047 req->header.flags = 0;
1048 req->header.type = IOP_REQUEST_TYPE_SET_CONFIG;
1049 req->header.size = sizeof(struct hpt_iop_request_set_config);
1050 req->header.result = IOP_RESULT_PENDING;
1051 req->header.context = MVIOP_CMD_TYPE_SET_CONFIG;
1052
1053 if (hptiop_send_sync_request_mv(hba, req, 20000)) {
1054 KdPrint(("hptiop: set config send cmd failed"));
1055 return -1;
1056 }
1057
1058 return 0;
1059 }
1060
hptiop_set_config_mvfrey(struct hpt_iop_hba * hba,struct hpt_iop_request_set_config * config)1061 static int hptiop_set_config_mvfrey(struct hpt_iop_hba *hba,
1062 struct hpt_iop_request_set_config *config)
1063 {
1064 struct hpt_iop_request_set_config *req;
1065
1066 if (!(req = hba->ctlcfg_ptr))
1067 return -1;
1068
1069 memcpy((u_int8_t *)req + sizeof(struct hpt_iop_request_header),
1070 (u_int8_t *)config + sizeof(struct hpt_iop_request_header),
1071 sizeof(struct hpt_iop_request_set_config) -
1072 sizeof(struct hpt_iop_request_header));
1073
1074 req->header.type = IOP_REQUEST_TYPE_SET_CONFIG;
1075 req->header.size = sizeof(struct hpt_iop_request_set_config);
1076 req->header.result = IOP_RESULT_PENDING;
1077
1078 if (hptiop_send_sync_request_mvfrey(hba, req, 20000)) {
1079 KdPrint(("hptiop: set config send cmd failed"));
1080 return -1;
1081 }
1082
1083 return 0;
1084 }
1085
hptiop_post_ioctl_command_itl(struct hpt_iop_hba * hba,u_int32_t req32,struct hpt_iop_ioctl_param * pParams)1086 static int hptiop_post_ioctl_command_itl(struct hpt_iop_hba *hba,
1087 u_int32_t req32,
1088 struct hpt_iop_ioctl_param *pParams)
1089 {
1090 u_int64_t temp64;
1091 struct hpt_iop_request_ioctl_command req;
1092
1093 if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) >
1094 (hba->max_request_size -
1095 offsetof(struct hpt_iop_request_ioctl_command, buf))) {
1096 device_printf(hba->pcidev, "request size beyond max value");
1097 return -1;
1098 }
1099
1100 req.header.size = offsetof(struct hpt_iop_request_ioctl_command, buf)
1101 + pParams->nInBufferSize;
1102 req.header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND;
1103 req.header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST;
1104 req.header.result = IOP_RESULT_PENDING;
1105 req.header.context = req32 + (u_int64_t)(unsigned long)hba->u.itl.mu;
1106 req.ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode);
1107 req.inbuf_size = pParams->nInBufferSize;
1108 req.outbuf_size = pParams->nOutBufferSize;
1109 req.bytes_returned = 0;
1110
1111 bus_space_write_region_4(hba->bar0t, hba->bar0h, req32, (u_int32_t *)&req,
1112 offsetof(struct hpt_iop_request_ioctl_command, buf)>>2);
1113
1114 hptiop_lock_adapter(hba);
1115
1116 BUS_SPACE_WRT4_ITL(inbound_queue, req32);
1117 BUS_SPACE_RD4_ITL(outbound_intstatus);
1118
1119 bus_space_read_region_4(hba->bar0t, hba->bar0h, req32 +
1120 offsetof(struct hpt_iop_request_ioctl_command, header.context),
1121 (u_int32_t *)&temp64, 2);
1122 while (temp64) {
1123 if (hptiop_sleep(hba, (void *)((unsigned long)hba->u.itl.mu + req32),
1124 PPAUSE, "hptctl", HPT_OSM_TIMEOUT)==0)
1125 break;
1126 hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000);
1127 bus_space_read_region_4(hba->bar0t, hba->bar0h,req32 +
1128 offsetof(struct hpt_iop_request_ioctl_command,
1129 header.context),
1130 (u_int32_t *)&temp64, 2);
1131 }
1132
1133 hptiop_unlock_adapter(hba);
1134 return 0;
1135 }
1136
hptiop_bus_space_copyin(struct hpt_iop_hba * hba,u_int32_t bus,void * user,int size)1137 static int hptiop_bus_space_copyin(struct hpt_iop_hba *hba, u_int32_t bus,
1138 void *user, int size)
1139 {
1140 unsigned char byte;
1141 int i;
1142
1143 for (i=0; i<size; i++) {
1144 if (copyin((u_int8_t *)user + i, &byte, 1))
1145 return -1;
1146 bus_space_write_1(hba->bar0t, hba->bar0h, bus + i, byte);
1147 }
1148
1149 return 0;
1150 }
1151
hptiop_bus_space_copyout(struct hpt_iop_hba * hba,u_int32_t bus,void * user,int size)1152 static int hptiop_bus_space_copyout(struct hpt_iop_hba *hba, u_int32_t bus,
1153 void *user, int size)
1154 {
1155 unsigned char byte;
1156 int i;
1157
1158 for (i=0; i<size; i++) {
1159 byte = bus_space_read_1(hba->bar0t, hba->bar0h, bus + i);
1160 if (copyout(&byte, (u_int8_t *)user + i, 1))
1161 return -1;
1162 }
1163
1164 return 0;
1165 }
1166
hptiop_do_ioctl_itl(struct hpt_iop_hba * hba,struct hpt_iop_ioctl_param * pParams)1167 static int hptiop_do_ioctl_itl(struct hpt_iop_hba *hba,
1168 struct hpt_iop_ioctl_param * pParams)
1169 {
1170 u_int32_t req32;
1171 u_int32_t result;
1172
1173 if ((pParams->Magic != HPT_IOCTL_MAGIC) &&
1174 (pParams->Magic != HPT_IOCTL_MAGIC32))
1175 return EFAULT;
1176
1177 req32 = BUS_SPACE_RD4_ITL(inbound_queue);
1178 if (req32 == IOPMU_QUEUE_EMPTY)
1179 return EFAULT;
1180
1181 if (pParams->nInBufferSize)
1182 if (hptiop_bus_space_copyin(hba, req32 +
1183 offsetof(struct hpt_iop_request_ioctl_command, buf),
1184 (void *)pParams->lpInBuffer, pParams->nInBufferSize))
1185 goto invalid;
1186
1187 if (hptiop_post_ioctl_command_itl(hba, req32, pParams))
1188 goto invalid;
1189
1190 result = bus_space_read_4(hba->bar0t, hba->bar0h, req32 +
1191 offsetof(struct hpt_iop_request_ioctl_command,
1192 header.result));
1193
1194 if (result == IOP_RESULT_SUCCESS) {
1195 if (pParams->nOutBufferSize)
1196 if (hptiop_bus_space_copyout(hba, req32 +
1197 offsetof(struct hpt_iop_request_ioctl_command, buf) +
1198 ((pParams->nInBufferSize + 3) & ~3),
1199 (void *)pParams->lpOutBuffer, pParams->nOutBufferSize))
1200 goto invalid;
1201
1202 if (pParams->lpBytesReturned) {
1203 if (hptiop_bus_space_copyout(hba, req32 +
1204 offsetof(struct hpt_iop_request_ioctl_command, bytes_returned),
1205 (void *)pParams->lpBytesReturned, sizeof(unsigned long)))
1206 goto invalid;
1207 }
1208
1209 BUS_SPACE_WRT4_ITL(outbound_queue, req32);
1210
1211 return 0;
1212 } else{
1213 invalid:
1214 BUS_SPACE_WRT4_ITL(outbound_queue, req32);
1215
1216 return EFAULT;
1217 }
1218 }
1219
hptiop_post_ioctl_command_mv(struct hpt_iop_hba * hba,struct hpt_iop_request_ioctl_command * req,struct hpt_iop_ioctl_param * pParams)1220 static int hptiop_post_ioctl_command_mv(struct hpt_iop_hba *hba,
1221 struct hpt_iop_request_ioctl_command *req,
1222 struct hpt_iop_ioctl_param *pParams)
1223 {
1224 u_int64_t req_phy;
1225 int size = 0;
1226
1227 if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) >
1228 (hba->max_request_size -
1229 offsetof(struct hpt_iop_request_ioctl_command, buf))) {
1230 device_printf(hba->pcidev, "request size beyond max value");
1231 return -1;
1232 }
1233
1234 req->ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode);
1235 req->inbuf_size = pParams->nInBufferSize;
1236 req->outbuf_size = pParams->nOutBufferSize;
1237 req->header.size = offsetof(struct hpt_iop_request_ioctl_command, buf)
1238 + pParams->nInBufferSize;
1239 req->header.context = (u_int64_t)MVIOP_CMD_TYPE_IOCTL;
1240 req->header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND;
1241 req->header.result = IOP_RESULT_PENDING;
1242 req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
1243 size = req->header.size >> 8;
1244 size = size > 3 ? 3 : size;
1245 req_phy = hba->ctlcfgcmd_phy | MVIOP_MU_QUEUE_ADDR_HOST_BIT | size;
1246 hptiop_mv_inbound_write(req_phy, hba);
1247
1248 BUS_SPACE_RD4_MV0(outbound_intmask);
1249
1250 while (hba->config_done == 0) {
1251 if (hptiop_sleep(hba, req, PPAUSE,
1252 "hptctl", HPT_OSM_TIMEOUT)==0)
1253 continue;
1254 hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000);
1255 }
1256 return 0;
1257 }
1258
hptiop_do_ioctl_mv(struct hpt_iop_hba * hba,struct hpt_iop_ioctl_param * pParams)1259 static int hptiop_do_ioctl_mv(struct hpt_iop_hba *hba,
1260 struct hpt_iop_ioctl_param *pParams)
1261 {
1262 struct hpt_iop_request_ioctl_command *req;
1263
1264 if ((pParams->Magic != HPT_IOCTL_MAGIC) &&
1265 (pParams->Magic != HPT_IOCTL_MAGIC32))
1266 return EFAULT;
1267
1268 req = (struct hpt_iop_request_ioctl_command *)(hba->ctlcfg_ptr);
1269 hba->config_done = 0;
1270 hptiop_lock_adapter(hba);
1271 if (pParams->nInBufferSize)
1272 if (copyin((void *)pParams->lpInBuffer,
1273 req->buf, pParams->nInBufferSize))
1274 goto invalid;
1275 if (hptiop_post_ioctl_command_mv(hba, req, pParams))
1276 goto invalid;
1277
1278 if (hba->config_done == 1) {
1279 if (pParams->nOutBufferSize)
1280 if (copyout(req->buf +
1281 ((pParams->nInBufferSize + 3) & ~3),
1282 (void *)pParams->lpOutBuffer,
1283 pParams->nOutBufferSize))
1284 goto invalid;
1285
1286 if (pParams->lpBytesReturned)
1287 if (copyout(&req->bytes_returned,
1288 (void*)pParams->lpBytesReturned,
1289 sizeof(u_int32_t)))
1290 goto invalid;
1291 hptiop_unlock_adapter(hba);
1292 return 0;
1293 } else{
1294 invalid:
1295 hptiop_unlock_adapter(hba);
1296 return EFAULT;
1297 }
1298 }
1299
hptiop_post_ioctl_command_mvfrey(struct hpt_iop_hba * hba,struct hpt_iop_request_ioctl_command * req,struct hpt_iop_ioctl_param * pParams)1300 static int hptiop_post_ioctl_command_mvfrey(struct hpt_iop_hba *hba,
1301 struct hpt_iop_request_ioctl_command *req,
1302 struct hpt_iop_ioctl_param *pParams)
1303 {
1304 u_int64_t phy_addr;
1305 u_int32_t index;
1306
1307 phy_addr = hba->ctlcfgcmd_phy;
1308
1309 if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) >
1310 (hba->max_request_size -
1311 offsetof(struct hpt_iop_request_ioctl_command, buf))) {
1312 device_printf(hba->pcidev, "request size beyond max value");
1313 return -1;
1314 }
1315
1316 req->ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode);
1317 req->inbuf_size = pParams->nInBufferSize;
1318 req->outbuf_size = pParams->nOutBufferSize;
1319 req->header.size = offsetof(struct hpt_iop_request_ioctl_command, buf)
1320 + pParams->nInBufferSize;
1321
1322 req->header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND;
1323 req->header.result = IOP_RESULT_PENDING;
1324
1325 req->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST
1326 | IOP_REQUEST_FLAG_OUTPUT_CONTEXT
1327 | IOP_REQUEST_FLAG_ADDR_BITS
1328 | ((phy_addr >> 16) & 0xffff0000);
1329 req->header.context = ((phy_addr & 0xffffffff) << 32 )
1330 | IOPMU_QUEUE_ADDR_HOST_BIT | req->header.type;
1331
1332 hba->u.mvfrey.inlist_wptr++;
1333 index = hba->u.mvfrey.inlist_wptr & 0x3fff;
1334
1335 if (index == hba->u.mvfrey.list_count) {
1336 index = 0;
1337 hba->u.mvfrey.inlist_wptr &= ~0x3fff;
1338 hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE;
1339 }
1340
1341 hba->u.mvfrey.inlist[index].addr = phy_addr;
1342 hba->u.mvfrey.inlist[index].intrfc_len = (req->header.size + 3) / 4;
1343
1344 BUS_SPACE_WRT4_MVFREY2(inbound_write_ptr, hba->u.mvfrey.inlist_wptr);
1345 BUS_SPACE_RD4_MVFREY2(inbound_write_ptr);
1346
1347 while (hba->config_done == 0) {
1348 if (hptiop_sleep(hba, req, PPAUSE,
1349 "hptctl", HPT_OSM_TIMEOUT)==0)
1350 continue;
1351 hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000);
1352 }
1353 return 0;
1354 }
1355
hptiop_do_ioctl_mvfrey(struct hpt_iop_hba * hba,struct hpt_iop_ioctl_param * pParams)1356 static int hptiop_do_ioctl_mvfrey(struct hpt_iop_hba *hba,
1357 struct hpt_iop_ioctl_param *pParams)
1358 {
1359 struct hpt_iop_request_ioctl_command *req;
1360
1361 if ((pParams->Magic != HPT_IOCTL_MAGIC) &&
1362 (pParams->Magic != HPT_IOCTL_MAGIC32))
1363 return EFAULT;
1364
1365 req = (struct hpt_iop_request_ioctl_command *)(hba->ctlcfg_ptr);
1366 hba->config_done = 0;
1367 hptiop_lock_adapter(hba);
1368 if (pParams->nInBufferSize)
1369 if (copyin((void *)pParams->lpInBuffer,
1370 req->buf, pParams->nInBufferSize))
1371 goto invalid;
1372 if (hptiop_post_ioctl_command_mvfrey(hba, req, pParams))
1373 goto invalid;
1374
1375 if (hba->config_done == 1) {
1376 if (pParams->nOutBufferSize)
1377 if (copyout(req->buf +
1378 ((pParams->nInBufferSize + 3) & ~3),
1379 (void *)pParams->lpOutBuffer,
1380 pParams->nOutBufferSize))
1381 goto invalid;
1382
1383 if (pParams->lpBytesReturned)
1384 if (copyout(&req->bytes_returned,
1385 (void*)pParams->lpBytesReturned,
1386 sizeof(u_int32_t)))
1387 goto invalid;
1388 hptiop_unlock_adapter(hba);
1389 return 0;
1390 } else{
1391 invalid:
1392 hptiop_unlock_adapter(hba);
1393 return EFAULT;
1394 }
1395 }
1396
hptiop_rescan_bus(struct hpt_iop_hba * hba)1397 static int hptiop_rescan_bus(struct hpt_iop_hba * hba)
1398 {
1399 union ccb *ccb;
1400
1401 if ((ccb = xpt_alloc_ccb()) == NULL)
1402 return(ENOMEM);
1403 if (xpt_create_path(&ccb->ccb_h.path, NULL, cam_sim_path(hba->sim),
1404 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1405 xpt_free_ccb(ccb);
1406 return(EIO);
1407 }
1408 xpt_rescan(ccb);
1409 return(0);
1410 }
1411
1412 static bus_dmamap_callback_t hptiop_map_srb;
1413 static bus_dmamap_callback_t hptiop_post_scsi_command;
1414 static bus_dmamap_callback_t hptiop_mv_map_ctlcfg;
1415 static bus_dmamap_callback_t hptiop_mvfrey_map_ctlcfg;
1416
hptiop_alloc_pci_res_itl(struct hpt_iop_hba * hba)1417 static int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba)
1418 {
1419 hba->bar0_rid = 0x10;
1420 hba->bar0_res = bus_alloc_resource_any(hba->pcidev,
1421 SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE);
1422
1423 if (hba->bar0_res == NULL) {
1424 device_printf(hba->pcidev,
1425 "failed to get iop base adrress.\n");
1426 return -1;
1427 }
1428 hba->bar0t = rman_get_bustag(hba->bar0_res);
1429 hba->bar0h = rman_get_bushandle(hba->bar0_res);
1430 hba->u.itl.mu = (struct hpt_iopmu_itl *)
1431 rman_get_virtual(hba->bar0_res);
1432
1433 if (!hba->u.itl.mu) {
1434 bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1435 hba->bar0_rid, hba->bar0_res);
1436 device_printf(hba->pcidev, "alloc mem res failed\n");
1437 return -1;
1438 }
1439
1440 return 0;
1441 }
1442
hptiop_alloc_pci_res_mv(struct hpt_iop_hba * hba)1443 static int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba)
1444 {
1445 hba->bar0_rid = 0x10;
1446 hba->bar0_res = bus_alloc_resource_any(hba->pcidev,
1447 SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE);
1448
1449 if (hba->bar0_res == NULL) {
1450 device_printf(hba->pcidev, "failed to get iop bar0.\n");
1451 return -1;
1452 }
1453 hba->bar0t = rman_get_bustag(hba->bar0_res);
1454 hba->bar0h = rman_get_bushandle(hba->bar0_res);
1455 hba->u.mv.regs = (struct hpt_iopmv_regs *)
1456 rman_get_virtual(hba->bar0_res);
1457
1458 if (!hba->u.mv.regs) {
1459 bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1460 hba->bar0_rid, hba->bar0_res);
1461 device_printf(hba->pcidev, "alloc bar0 mem res failed\n");
1462 return -1;
1463 }
1464
1465 hba->bar2_rid = 0x18;
1466 hba->bar2_res = bus_alloc_resource_any(hba->pcidev,
1467 SYS_RES_MEMORY, &hba->bar2_rid, RF_ACTIVE);
1468
1469 if (hba->bar2_res == NULL) {
1470 bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1471 hba->bar0_rid, hba->bar0_res);
1472 device_printf(hba->pcidev, "failed to get iop bar2.\n");
1473 return -1;
1474 }
1475
1476 hba->bar2t = rman_get_bustag(hba->bar2_res);
1477 hba->bar2h = rman_get_bushandle(hba->bar2_res);
1478 hba->u.mv.mu = (struct hpt_iopmu_mv *)rman_get_virtual(hba->bar2_res);
1479
1480 if (!hba->u.mv.mu) {
1481 bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1482 hba->bar0_rid, hba->bar0_res);
1483 bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1484 hba->bar2_rid, hba->bar2_res);
1485 device_printf(hba->pcidev, "alloc mem bar2 res failed\n");
1486 return -1;
1487 }
1488
1489 return 0;
1490 }
1491
hptiop_alloc_pci_res_mvfrey(struct hpt_iop_hba * hba)1492 static int hptiop_alloc_pci_res_mvfrey(struct hpt_iop_hba *hba)
1493 {
1494 hba->bar0_rid = 0x10;
1495 hba->bar0_res = bus_alloc_resource_any(hba->pcidev,
1496 SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE);
1497
1498 if (hba->bar0_res == NULL) {
1499 device_printf(hba->pcidev, "failed to get iop bar0.\n");
1500 return -1;
1501 }
1502 hba->bar0t = rman_get_bustag(hba->bar0_res);
1503 hba->bar0h = rman_get_bushandle(hba->bar0_res);
1504 hba->u.mvfrey.config = (struct hpt_iop_request_get_config *)
1505 rman_get_virtual(hba->bar0_res);
1506
1507 if (!hba->u.mvfrey.config) {
1508 bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1509 hba->bar0_rid, hba->bar0_res);
1510 device_printf(hba->pcidev, "alloc bar0 mem res failed\n");
1511 return -1;
1512 }
1513
1514 hba->bar2_rid = 0x18;
1515 hba->bar2_res = bus_alloc_resource_any(hba->pcidev,
1516 SYS_RES_MEMORY, &hba->bar2_rid, RF_ACTIVE);
1517
1518 if (hba->bar2_res == NULL) {
1519 bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1520 hba->bar0_rid, hba->bar0_res);
1521 device_printf(hba->pcidev, "failed to get iop bar2.\n");
1522 return -1;
1523 }
1524
1525 hba->bar2t = rman_get_bustag(hba->bar2_res);
1526 hba->bar2h = rman_get_bushandle(hba->bar2_res);
1527 hba->u.mvfrey.mu =
1528 (struct hpt_iopmu_mvfrey *)rman_get_virtual(hba->bar2_res);
1529
1530 if (!hba->u.mvfrey.mu) {
1531 bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1532 hba->bar0_rid, hba->bar0_res);
1533 bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1534 hba->bar2_rid, hba->bar2_res);
1535 device_printf(hba->pcidev, "alloc mem bar2 res failed\n");
1536 return -1;
1537 }
1538
1539 return 0;
1540 }
1541
hptiop_release_pci_res_itl(struct hpt_iop_hba * hba)1542 static void hptiop_release_pci_res_itl(struct hpt_iop_hba *hba)
1543 {
1544 if (hba->bar0_res)
1545 bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1546 hba->bar0_rid, hba->bar0_res);
1547 }
1548
hptiop_release_pci_res_mv(struct hpt_iop_hba * hba)1549 static void hptiop_release_pci_res_mv(struct hpt_iop_hba *hba)
1550 {
1551 if (hba->bar0_res)
1552 bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1553 hba->bar0_rid, hba->bar0_res);
1554 if (hba->bar2_res)
1555 bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1556 hba->bar2_rid, hba->bar2_res);
1557 }
1558
hptiop_release_pci_res_mvfrey(struct hpt_iop_hba * hba)1559 static void hptiop_release_pci_res_mvfrey(struct hpt_iop_hba *hba)
1560 {
1561 if (hba->bar0_res)
1562 bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1563 hba->bar0_rid, hba->bar0_res);
1564 if (hba->bar2_res)
1565 bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1566 hba->bar2_rid, hba->bar2_res);
1567 }
1568
hptiop_internal_memalloc_mv(struct hpt_iop_hba * hba)1569 static int hptiop_internal_memalloc_mv(struct hpt_iop_hba *hba)
1570 {
1571 if (bus_dma_tag_create(hba->parent_dmat,
1572 1,
1573 0,
1574 BUS_SPACE_MAXADDR_32BIT,
1575 BUS_SPACE_MAXADDR,
1576 NULL, NULL,
1577 0x800 - 0x8,
1578 1,
1579 BUS_SPACE_MAXSIZE_32BIT,
1580 BUS_DMA_ALLOCNOW,
1581 NULL,
1582 NULL,
1583 &hba->ctlcfg_dmat)) {
1584 device_printf(hba->pcidev, "alloc ctlcfg_dmat failed\n");
1585 return -1;
1586 }
1587
1588 if (bus_dmamem_alloc(hba->ctlcfg_dmat, (void **)&hba->ctlcfg_ptr,
1589 BUS_DMA_WAITOK | BUS_DMA_COHERENT,
1590 &hba->ctlcfg_dmamap) != 0) {
1591 device_printf(hba->pcidev,
1592 "bus_dmamem_alloc failed!\n");
1593 bus_dma_tag_destroy(hba->ctlcfg_dmat);
1594 return -1;
1595 }
1596
1597 if (bus_dmamap_load(hba->ctlcfg_dmat,
1598 hba->ctlcfg_dmamap, hba->ctlcfg_ptr,
1599 MVIOP_IOCTLCFG_SIZE,
1600 hptiop_mv_map_ctlcfg, hba, 0)) {
1601 device_printf(hba->pcidev, "bus_dmamap_load failed!\n");
1602 if (hba->ctlcfg_dmat) {
1603 bus_dmamem_free(hba->ctlcfg_dmat,
1604 hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
1605 bus_dma_tag_destroy(hba->ctlcfg_dmat);
1606 }
1607 return -1;
1608 }
1609
1610 return 0;
1611 }
1612
hptiop_internal_memalloc_mvfrey(struct hpt_iop_hba * hba)1613 static int hptiop_internal_memalloc_mvfrey(struct hpt_iop_hba *hba)
1614 {
1615 u_int32_t list_count = BUS_SPACE_RD4_MVFREY2(inbound_conf_ctl);
1616
1617 list_count >>= 16;
1618
1619 if (list_count == 0) {
1620 return -1;
1621 }
1622
1623 hba->u.mvfrey.list_count = list_count;
1624 hba->u.mvfrey.internal_mem_size = 0x800
1625 + list_count * sizeof(struct mvfrey_inlist_entry)
1626 + list_count * sizeof(struct mvfrey_outlist_entry)
1627 + sizeof(int);
1628 if (bus_dma_tag_create(hba->parent_dmat,
1629 1,
1630 0,
1631 BUS_SPACE_MAXADDR_32BIT,
1632 BUS_SPACE_MAXADDR,
1633 NULL, NULL,
1634 hba->u.mvfrey.internal_mem_size,
1635 1,
1636 BUS_SPACE_MAXSIZE_32BIT,
1637 BUS_DMA_ALLOCNOW,
1638 NULL,
1639 NULL,
1640 &hba->ctlcfg_dmat)) {
1641 device_printf(hba->pcidev, "alloc ctlcfg_dmat failed\n");
1642 return -1;
1643 }
1644
1645 if (bus_dmamem_alloc(hba->ctlcfg_dmat, (void **)&hba->ctlcfg_ptr,
1646 BUS_DMA_WAITOK | BUS_DMA_COHERENT,
1647 &hba->ctlcfg_dmamap) != 0) {
1648 device_printf(hba->pcidev,
1649 "bus_dmamem_alloc failed!\n");
1650 bus_dma_tag_destroy(hba->ctlcfg_dmat);
1651 return -1;
1652 }
1653
1654 if (bus_dmamap_load(hba->ctlcfg_dmat,
1655 hba->ctlcfg_dmamap, hba->ctlcfg_ptr,
1656 hba->u.mvfrey.internal_mem_size,
1657 hptiop_mvfrey_map_ctlcfg, hba, 0)) {
1658 device_printf(hba->pcidev, "bus_dmamap_load failed!\n");
1659 if (hba->ctlcfg_dmat) {
1660 bus_dmamem_free(hba->ctlcfg_dmat,
1661 hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
1662 bus_dma_tag_destroy(hba->ctlcfg_dmat);
1663 }
1664 return -1;
1665 }
1666
1667 return 0;
1668 }
1669
hptiop_internal_memfree_itl(struct hpt_iop_hba * hba)1670 static int hptiop_internal_memfree_itl(struct hpt_iop_hba *hba) {
1671 return 0;
1672 }
1673
hptiop_internal_memfree_mv(struct hpt_iop_hba * hba)1674 static int hptiop_internal_memfree_mv(struct hpt_iop_hba *hba)
1675 {
1676 if (hba->ctlcfg_dmat) {
1677 bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap);
1678 bus_dmamem_free(hba->ctlcfg_dmat,
1679 hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
1680 bus_dma_tag_destroy(hba->ctlcfg_dmat);
1681 }
1682
1683 return 0;
1684 }
1685
hptiop_internal_memfree_mvfrey(struct hpt_iop_hba * hba)1686 static int hptiop_internal_memfree_mvfrey(struct hpt_iop_hba *hba)
1687 {
1688 if (hba->ctlcfg_dmat) {
1689 bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap);
1690 bus_dmamem_free(hba->ctlcfg_dmat,
1691 hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
1692 bus_dma_tag_destroy(hba->ctlcfg_dmat);
1693 }
1694
1695 return 0;
1696 }
1697
hptiop_reset_comm_mvfrey(struct hpt_iop_hba * hba)1698 static int hptiop_reset_comm_mvfrey(struct hpt_iop_hba *hba)
1699 {
1700 u_int32_t i = 100;
1701
1702 if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET_COMM, 3000))
1703 return -1;
1704
1705 /* wait 100ms for MCU ready */
1706 while(i--) {
1707 DELAY(1000);
1708 }
1709
1710 BUS_SPACE_WRT4_MVFREY2(inbound_base,
1711 hba->u.mvfrey.inlist_phy & 0xffffffff);
1712 BUS_SPACE_WRT4_MVFREY2(inbound_base_high,
1713 (hba->u.mvfrey.inlist_phy >> 16) >> 16);
1714
1715 BUS_SPACE_WRT4_MVFREY2(outbound_base,
1716 hba->u.mvfrey.outlist_phy & 0xffffffff);
1717 BUS_SPACE_WRT4_MVFREY2(outbound_base_high,
1718 (hba->u.mvfrey.outlist_phy >> 16) >> 16);
1719
1720 BUS_SPACE_WRT4_MVFREY2(outbound_shadow_base,
1721 hba->u.mvfrey.outlist_cptr_phy & 0xffffffff);
1722 BUS_SPACE_WRT4_MVFREY2(outbound_shadow_base_high,
1723 (hba->u.mvfrey.outlist_cptr_phy >> 16) >> 16);
1724
1725 hba->u.mvfrey.inlist_wptr = (hba->u.mvfrey.list_count - 1)
1726 | CL_POINTER_TOGGLE;
1727 *hba->u.mvfrey.outlist_cptr = (hba->u.mvfrey.list_count - 1)
1728 | CL_POINTER_TOGGLE;
1729 hba->u.mvfrey.outlist_rptr = hba->u.mvfrey.list_count - 1;
1730
1731 return 0;
1732 }
1733
1734 /*
1735 * CAM driver interface
1736 */
1737 static device_method_t driver_methods[] = {
1738 /* Device interface */
1739 DEVMETHOD(device_probe, hptiop_probe),
1740 DEVMETHOD(device_attach, hptiop_attach),
1741 DEVMETHOD(device_detach, hptiop_detach),
1742 DEVMETHOD(device_shutdown, hptiop_shutdown),
1743 { 0, 0 }
1744 };
1745
1746 static struct hptiop_adapter_ops hptiop_itl_ops = {
1747 .family = INTEL_BASED_IOP,
1748 .iop_wait_ready = hptiop_wait_ready_itl,
1749 .internal_memalloc = 0,
1750 .internal_memfree = hptiop_internal_memfree_itl,
1751 .alloc_pci_res = hptiop_alloc_pci_res_itl,
1752 .release_pci_res = hptiop_release_pci_res_itl,
1753 .enable_intr = hptiop_enable_intr_itl,
1754 .disable_intr = hptiop_disable_intr_itl,
1755 .get_config = hptiop_get_config_itl,
1756 .set_config = hptiop_set_config_itl,
1757 .iop_intr = hptiop_intr_itl,
1758 .post_msg = hptiop_post_msg_itl,
1759 .post_req = hptiop_post_req_itl,
1760 .do_ioctl = hptiop_do_ioctl_itl,
1761 .reset_comm = 0,
1762 };
1763
1764 static struct hptiop_adapter_ops hptiop_mv_ops = {
1765 .family = MV_BASED_IOP,
1766 .iop_wait_ready = hptiop_wait_ready_mv,
1767 .internal_memalloc = hptiop_internal_memalloc_mv,
1768 .internal_memfree = hptiop_internal_memfree_mv,
1769 .alloc_pci_res = hptiop_alloc_pci_res_mv,
1770 .release_pci_res = hptiop_release_pci_res_mv,
1771 .enable_intr = hptiop_enable_intr_mv,
1772 .disable_intr = hptiop_disable_intr_mv,
1773 .get_config = hptiop_get_config_mv,
1774 .set_config = hptiop_set_config_mv,
1775 .iop_intr = hptiop_intr_mv,
1776 .post_msg = hptiop_post_msg_mv,
1777 .post_req = hptiop_post_req_mv,
1778 .do_ioctl = hptiop_do_ioctl_mv,
1779 .reset_comm = 0,
1780 };
1781
1782 static struct hptiop_adapter_ops hptiop_mvfrey_ops = {
1783 .family = MVFREY_BASED_IOP,
1784 .iop_wait_ready = hptiop_wait_ready_mvfrey,
1785 .internal_memalloc = hptiop_internal_memalloc_mvfrey,
1786 .internal_memfree = hptiop_internal_memfree_mvfrey,
1787 .alloc_pci_res = hptiop_alloc_pci_res_mvfrey,
1788 .release_pci_res = hptiop_release_pci_res_mvfrey,
1789 .enable_intr = hptiop_enable_intr_mvfrey,
1790 .disable_intr = hptiop_disable_intr_mvfrey,
1791 .get_config = hptiop_get_config_mvfrey,
1792 .set_config = hptiop_set_config_mvfrey,
1793 .iop_intr = hptiop_intr_mvfrey,
1794 .post_msg = hptiop_post_msg_mvfrey,
1795 .post_req = hptiop_post_req_mvfrey,
1796 .do_ioctl = hptiop_do_ioctl_mvfrey,
1797 .reset_comm = hptiop_reset_comm_mvfrey,
1798 };
1799
1800 static driver_t hptiop_pci_driver = {
1801 driver_name,
1802 driver_methods,
1803 sizeof(struct hpt_iop_hba)
1804 };
1805
1806 DRIVER_MODULE(hptiop, pci, hptiop_pci_driver, hptiop_devclass, 0, 0);
1807 MODULE_DEPEND(hptiop, cam, 1, 1, 1);
1808
hptiop_probe(device_t dev)1809 static int hptiop_probe(device_t dev)
1810 {
1811 struct hpt_iop_hba *hba;
1812 u_int32_t id;
1813 static char buf[256];
1814 int sas = 0;
1815 struct hptiop_adapter_ops *ops;
1816
1817 if (pci_get_vendor(dev) != 0x1103)
1818 return (ENXIO);
1819
1820 id = pci_get_device(dev);
1821
1822 switch (id) {
1823 case 0x4520:
1824 case 0x4521:
1825 case 0x4522:
1826 sas = 1;
1827 case 0x3620:
1828 case 0x3622:
1829 case 0x3640:
1830 ops = &hptiop_mvfrey_ops;
1831 break;
1832 case 0x4210:
1833 case 0x4211:
1834 case 0x4310:
1835 case 0x4311:
1836 case 0x4320:
1837 case 0x4321:
1838 case 0x4322:
1839 sas = 1;
1840 case 0x3220:
1841 case 0x3320:
1842 case 0x3410:
1843 case 0x3520:
1844 case 0x3510:
1845 case 0x3511:
1846 case 0x3521:
1847 case 0x3522:
1848 case 0x3530:
1849 case 0x3540:
1850 case 0x3560:
1851 ops = &hptiop_itl_ops;
1852 break;
1853 case 0x3020:
1854 case 0x3120:
1855 case 0x3122:
1856 ops = &hptiop_mv_ops;
1857 break;
1858 default:
1859 return (ENXIO);
1860 }
1861
1862 device_printf(dev, "adapter at PCI %d:%d:%d, IRQ %d\n",
1863 pci_get_bus(dev), pci_get_slot(dev),
1864 pci_get_function(dev), pci_get_irq(dev));
1865
1866 sprintf(buf, "RocketRAID %x %s Controller\n",
1867 id, sas ? "SAS" : "SATA");
1868 device_set_desc_copy(dev, buf);
1869
1870 hba = (struct hpt_iop_hba *)device_get_softc(dev);
1871 bzero(hba, sizeof(struct hpt_iop_hba));
1872 hba->ops = ops;
1873
1874 KdPrint(("hba->ops=%p\n", hba->ops));
1875 return 0;
1876 }
1877
hptiop_attach(device_t dev)1878 static int hptiop_attach(device_t dev)
1879 {
1880 struct hpt_iop_hba *hba = (struct hpt_iop_hba *)device_get_softc(dev);
1881 struct hpt_iop_request_get_config iop_config;
1882 struct hpt_iop_request_set_config set_config;
1883 int rid = 0;
1884 struct cam_devq *devq;
1885 struct ccb_setasync ccb;
1886 u_int32_t unit = device_get_unit(dev);
1887
1888 device_printf(dev, "%d RocketRAID 3xxx/4xxx controller driver %s\n",
1889 unit, driver_version);
1890
1891 KdPrint(("hptiop: attach(%d, %d/%d/%d) ops=%p\n", unit,
1892 pci_get_bus(dev), pci_get_slot(dev),
1893 pci_get_function(dev), hba->ops));
1894
1895 pci_enable_busmaster(dev);
1896 hba->pcidev = dev;
1897 hba->pciunit = unit;
1898
1899 if (hba->ops->alloc_pci_res(hba))
1900 return ENXIO;
1901
1902 if (hba->ops->iop_wait_ready(hba, 2000)) {
1903 device_printf(dev, "adapter is not ready\n");
1904 goto release_pci_res;
1905 }
1906
1907 mtx_init(&hba->lock, "hptioplock", NULL, MTX_DEF);
1908
1909 if (bus_dma_tag_create(bus_get_dma_tag(dev),/* PCI parent */
1910 1, /* alignment */
1911 0, /* boundary */
1912 BUS_SPACE_MAXADDR, /* lowaddr */
1913 BUS_SPACE_MAXADDR, /* highaddr */
1914 NULL, NULL, /* filter, filterarg */
1915 BUS_SPACE_MAXSIZE_32BIT, /* maxsize */
1916 BUS_SPACE_UNRESTRICTED, /* nsegments */
1917 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
1918 0, /* flags */
1919 NULL, /* lockfunc */
1920 NULL, /* lockfuncarg */
1921 &hba->parent_dmat /* tag */))
1922 {
1923 device_printf(dev, "alloc parent_dmat failed\n");
1924 goto release_pci_res;
1925 }
1926
1927 if (hba->ops->family == MV_BASED_IOP) {
1928 if (hba->ops->internal_memalloc(hba)) {
1929 device_printf(dev, "alloc srb_dmat failed\n");
1930 goto destroy_parent_tag;
1931 }
1932 }
1933
1934 if (hba->ops->get_config(hba, &iop_config)) {
1935 device_printf(dev, "get iop config failed.\n");
1936 goto get_config_failed;
1937 }
1938
1939 hba->firmware_version = iop_config.firmware_version;
1940 hba->interface_version = iop_config.interface_version;
1941 hba->max_requests = iop_config.max_requests;
1942 hba->max_devices = iop_config.max_devices;
1943 hba->max_request_size = iop_config.request_size;
1944 hba->max_sg_count = iop_config.max_sg_count;
1945
1946 if (hba->ops->family == MVFREY_BASED_IOP) {
1947 if (hba->ops->internal_memalloc(hba)) {
1948 device_printf(dev, "alloc srb_dmat failed\n");
1949 goto destroy_parent_tag;
1950 }
1951 if (hba->ops->reset_comm(hba)) {
1952 device_printf(dev, "reset comm failed\n");
1953 goto get_config_failed;
1954 }
1955 }
1956
1957 if (bus_dma_tag_create(hba->parent_dmat,/* parent */
1958 4, /* alignment */
1959 BUS_SPACE_MAXADDR_32BIT+1, /* boundary */
1960 BUS_SPACE_MAXADDR, /* lowaddr */
1961 BUS_SPACE_MAXADDR, /* highaddr */
1962 NULL, NULL, /* filter, filterarg */
1963 PAGE_SIZE * (hba->max_sg_count-1), /* maxsize */
1964 hba->max_sg_count, /* nsegments */
1965 0x20000, /* maxsegsize */
1966 BUS_DMA_ALLOCNOW, /* flags */
1967 busdma_lock_mutex, /* lockfunc */
1968 &hba->lock, /* lockfuncarg */
1969 &hba->io_dmat /* tag */))
1970 {
1971 device_printf(dev, "alloc io_dmat failed\n");
1972 goto get_config_failed;
1973 }
1974
1975 if (bus_dma_tag_create(hba->parent_dmat,/* parent */
1976 1, /* alignment */
1977 0, /* boundary */
1978 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
1979 BUS_SPACE_MAXADDR, /* highaddr */
1980 NULL, NULL, /* filter, filterarg */
1981 HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE + 0x20,
1982 1, /* nsegments */
1983 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
1984 0, /* flags */
1985 NULL, /* lockfunc */
1986 NULL, /* lockfuncarg */
1987 &hba->srb_dmat /* tag */))
1988 {
1989 device_printf(dev, "alloc srb_dmat failed\n");
1990 goto destroy_io_dmat;
1991 }
1992
1993 if (bus_dmamem_alloc(hba->srb_dmat, (void **)&hba->uncached_ptr,
1994 BUS_DMA_WAITOK | BUS_DMA_COHERENT,
1995 &hba->srb_dmamap) != 0)
1996 {
1997 device_printf(dev, "srb bus_dmamem_alloc failed!\n");
1998 goto destroy_srb_dmat;
1999 }
2000
2001 if (bus_dmamap_load(hba->srb_dmat,
2002 hba->srb_dmamap, hba->uncached_ptr,
2003 (HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE) + 0x20,
2004 hptiop_map_srb, hba, 0))
2005 {
2006 device_printf(dev, "bus_dmamap_load failed!\n");
2007 goto srb_dmamem_free;
2008 }
2009
2010 if ((devq = cam_simq_alloc(hba->max_requests - 1 )) == NULL) {
2011 device_printf(dev, "cam_simq_alloc failed\n");
2012 goto srb_dmamap_unload;
2013 }
2014
2015 hba->sim = cam_sim_alloc(hptiop_action, hptiop_poll, driver_name,
2016 hba, unit, &Giant, hba->max_requests - 1, 1, devq);
2017 if (!hba->sim) {
2018 device_printf(dev, "cam_sim_alloc failed\n");
2019 cam_simq_free(devq);
2020 goto srb_dmamap_unload;
2021 }
2022 if (xpt_bus_register(hba->sim, dev, 0) != CAM_SUCCESS)
2023 {
2024 device_printf(dev, "xpt_bus_register failed\n");
2025 goto free_cam_sim;
2026 }
2027
2028 if (xpt_create_path(&hba->path, /*periph */ NULL,
2029 cam_sim_path(hba->sim), CAM_TARGET_WILDCARD,
2030 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
2031 device_printf(dev, "xpt_create_path failed\n");
2032 goto deregister_xpt_bus;
2033 }
2034
2035 bzero(&set_config, sizeof(set_config));
2036 set_config.iop_id = unit;
2037 set_config.vbus_id = cam_sim_path(hba->sim);
2038 set_config.max_host_request_size = HPT_SRB_MAX_REQ_SIZE;
2039
2040 if (hba->ops->set_config(hba, &set_config)) {
2041 device_printf(dev, "set iop config failed.\n");
2042 goto free_hba_path;
2043 }
2044
2045 xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5);
2046 ccb.ccb_h.func_code = XPT_SASYNC_CB;
2047 ccb.event_enable = (AC_FOUND_DEVICE | AC_LOST_DEVICE);
2048 ccb.callback = hptiop_async;
2049 ccb.callback_arg = hba->sim;
2050 xpt_action((union ccb *)&ccb);
2051
2052 rid = 0;
2053 if ((hba->irq_res = bus_alloc_resource(hba->pcidev, SYS_RES_IRQ,
2054 &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
2055 device_printf(dev, "allocate irq failed!\n");
2056 goto free_hba_path;
2057 }
2058
2059 if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM,
2060 NULL, hptiop_pci_intr, hba, &hba->irq_handle))
2061 {
2062 device_printf(dev, "allocate intr function failed!\n");
2063 goto free_irq_resource;
2064 }
2065
2066 if (hptiop_send_sync_msg(hba,
2067 IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) {
2068 device_printf(dev, "fail to start background task\n");
2069 goto teartown_irq_resource;
2070 }
2071
2072 hba->ops->enable_intr(hba);
2073 hba->initialized = 1;
2074
2075 hba->ioctl_dev = make_dev(&hptiop_cdevsw, unit,
2076 UID_ROOT, GID_WHEEL /*GID_OPERATOR*/,
2077 S_IRUSR | S_IWUSR, "%s%d", driver_name, unit);
2078
2079
2080 return 0;
2081
2082
2083 teartown_irq_resource:
2084 bus_teardown_intr(dev, hba->irq_res, hba->irq_handle);
2085
2086 free_irq_resource:
2087 bus_release_resource(dev, SYS_RES_IRQ, 0, hba->irq_res);
2088
2089 free_hba_path:
2090 xpt_free_path(hba->path);
2091
2092 deregister_xpt_bus:
2093 xpt_bus_deregister(cam_sim_path(hba->sim));
2094
2095 free_cam_sim:
2096 cam_sim_free(hba->sim, /*free devq*/ TRUE);
2097
2098 srb_dmamap_unload:
2099 if (hba->uncached_ptr)
2100 bus_dmamap_unload(hba->srb_dmat, hba->srb_dmamap);
2101
2102 srb_dmamem_free:
2103 if (hba->uncached_ptr)
2104 bus_dmamem_free(hba->srb_dmat,
2105 hba->uncached_ptr, hba->srb_dmamap);
2106
2107 destroy_srb_dmat:
2108 if (hba->srb_dmat)
2109 bus_dma_tag_destroy(hba->srb_dmat);
2110
2111 destroy_io_dmat:
2112 if (hba->io_dmat)
2113 bus_dma_tag_destroy(hba->io_dmat);
2114
2115 get_config_failed:
2116 hba->ops->internal_memfree(hba);
2117
2118 destroy_parent_tag:
2119 if (hba->parent_dmat)
2120 bus_dma_tag_destroy(hba->parent_dmat);
2121
2122 release_pci_res:
2123 if (hba->ops->release_pci_res)
2124 hba->ops->release_pci_res(hba);
2125
2126 return ENXIO;
2127 }
2128
hptiop_detach(device_t dev)2129 static int hptiop_detach(device_t dev)
2130 {
2131 struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev);
2132 int i;
2133 int error = EBUSY;
2134
2135 hptiop_lock_adapter(hba);
2136 for (i = 0; i < hba->max_devices; i++)
2137 if (hptiop_os_query_remove_device(hba, i)) {
2138 device_printf(dev, "%d file system is busy. id=%d",
2139 hba->pciunit, i);
2140 goto out;
2141 }
2142
2143 if ((error = hptiop_shutdown(dev)) != 0)
2144 goto out;
2145 if (hptiop_send_sync_msg(hba,
2146 IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK, 60000))
2147 goto out;
2148
2149 hptiop_release_resource(hba);
2150 error = 0;
2151 out:
2152 hptiop_unlock_adapter(hba);
2153 return error;
2154 }
2155
hptiop_shutdown(device_t dev)2156 static int hptiop_shutdown(device_t dev)
2157 {
2158 struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev);
2159
2160 int error = 0;
2161
2162 if (hba->flag & HPT_IOCTL_FLAG_OPEN) {
2163 device_printf(dev, "%d device is busy", hba->pciunit);
2164 return EBUSY;
2165 }
2166
2167 hba->ops->disable_intr(hba);
2168
2169 if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_SHUTDOWN, 60000))
2170 error = EBUSY;
2171
2172 return error;
2173 }
2174
hptiop_pci_intr(void * arg)2175 static void hptiop_pci_intr(void *arg)
2176 {
2177 struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg;
2178 hptiop_lock_adapter(hba);
2179 hba->ops->iop_intr(hba);
2180 hptiop_unlock_adapter(hba);
2181 }
2182
hptiop_poll(struct cam_sim * sim)2183 static void hptiop_poll(struct cam_sim *sim)
2184 {
2185 hptiop_pci_intr(cam_sim_softc(sim));
2186 }
2187
hptiop_async(void * callback_arg,u_int32_t code,struct cam_path * path,void * arg)2188 static void hptiop_async(void * callback_arg, u_int32_t code,
2189 struct cam_path * path, void * arg)
2190 {
2191 }
2192
hptiop_enable_intr_itl(struct hpt_iop_hba * hba)2193 static void hptiop_enable_intr_itl(struct hpt_iop_hba *hba)
2194 {
2195 BUS_SPACE_WRT4_ITL(outbound_intmask,
2196 ~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0));
2197 }
2198
hptiop_enable_intr_mv(struct hpt_iop_hba * hba)2199 static void hptiop_enable_intr_mv(struct hpt_iop_hba *hba)
2200 {
2201 u_int32_t int_mask;
2202
2203 int_mask = BUS_SPACE_RD4_MV0(outbound_intmask);
2204
2205 int_mask |= MVIOP_MU_OUTBOUND_INT_POSTQUEUE
2206 | MVIOP_MU_OUTBOUND_INT_MSG;
2207 BUS_SPACE_WRT4_MV0(outbound_intmask,int_mask);
2208 }
2209
hptiop_enable_intr_mvfrey(struct hpt_iop_hba * hba)2210 static void hptiop_enable_intr_mvfrey(struct hpt_iop_hba *hba)
2211 {
2212 BUS_SPACE_WRT4_MVFREY2(f0_doorbell_enable, CPU_TO_F0_DRBL_MSG_A_BIT);
2213 BUS_SPACE_RD4_MVFREY2(f0_doorbell_enable);
2214
2215 BUS_SPACE_WRT4_MVFREY2(isr_enable, 0x1);
2216 BUS_SPACE_RD4_MVFREY2(isr_enable);
2217
2218 BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0x1010);
2219 BUS_SPACE_RD4_MVFREY2(pcie_f0_int_enable);
2220 }
2221
hptiop_disable_intr_itl(struct hpt_iop_hba * hba)2222 static void hptiop_disable_intr_itl(struct hpt_iop_hba *hba)
2223 {
2224 u_int32_t int_mask;
2225
2226 int_mask = BUS_SPACE_RD4_ITL(outbound_intmask);
2227
2228 int_mask |= IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0;
2229 BUS_SPACE_WRT4_ITL(outbound_intmask, int_mask);
2230 BUS_SPACE_RD4_ITL(outbound_intstatus);
2231 }
2232
hptiop_disable_intr_mv(struct hpt_iop_hba * hba)2233 static void hptiop_disable_intr_mv(struct hpt_iop_hba *hba)
2234 {
2235 u_int32_t int_mask;
2236 int_mask = BUS_SPACE_RD4_MV0(outbound_intmask);
2237
2238 int_mask &= ~(MVIOP_MU_OUTBOUND_INT_MSG
2239 | MVIOP_MU_OUTBOUND_INT_POSTQUEUE);
2240 BUS_SPACE_WRT4_MV0(outbound_intmask,int_mask);
2241 BUS_SPACE_RD4_MV0(outbound_intmask);
2242 }
2243
hptiop_disable_intr_mvfrey(struct hpt_iop_hba * hba)2244 static void hptiop_disable_intr_mvfrey(struct hpt_iop_hba *hba)
2245 {
2246 BUS_SPACE_WRT4_MVFREY2(f0_doorbell_enable, 0);
2247 BUS_SPACE_RD4_MVFREY2(f0_doorbell_enable);
2248
2249 BUS_SPACE_WRT4_MVFREY2(isr_enable, 0);
2250 BUS_SPACE_RD4_MVFREY2(isr_enable);
2251
2252 BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0);
2253 BUS_SPACE_RD4_MVFREY2(pcie_f0_int_enable);
2254 }
2255
hptiop_reset_adapter(void * argv)2256 static void hptiop_reset_adapter(void *argv)
2257 {
2258 struct hpt_iop_hba * hba = (struct hpt_iop_hba *)argv;
2259 if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000))
2260 return;
2261 hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000);
2262 }
2263
hptiop_get_srb(struct hpt_iop_hba * hba)2264 static void *hptiop_get_srb(struct hpt_iop_hba * hba)
2265 {
2266 struct hpt_iop_srb * srb;
2267
2268 if (hba->srb_list) {
2269 srb = hba->srb_list;
2270 hba->srb_list = srb->next;
2271 return srb;
2272 }
2273
2274 return NULL;
2275 }
2276
hptiop_free_srb(struct hpt_iop_hba * hba,struct hpt_iop_srb * srb)2277 static void hptiop_free_srb(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb)
2278 {
2279 srb->next = hba->srb_list;
2280 hba->srb_list = srb;
2281 }
2282
hptiop_action(struct cam_sim * sim,union ccb * ccb)2283 static void hptiop_action(struct cam_sim *sim, union ccb *ccb)
2284 {
2285 struct hpt_iop_hba * hba = (struct hpt_iop_hba *)cam_sim_softc(sim);
2286 struct hpt_iop_srb * srb;
2287 int error;
2288
2289 switch (ccb->ccb_h.func_code) {
2290
2291 case XPT_SCSI_IO:
2292 hptiop_lock_adapter(hba);
2293 if (ccb->ccb_h.target_lun != 0 ||
2294 ccb->ccb_h.target_id >= hba->max_devices ||
2295 (ccb->ccb_h.flags & CAM_CDB_PHYS))
2296 {
2297 ccb->ccb_h.status = CAM_TID_INVALID;
2298 xpt_done(ccb);
2299 goto scsi_done;
2300 }
2301
2302 if ((srb = hptiop_get_srb(hba)) == NULL) {
2303 device_printf(hba->pcidev, "srb allocated failed");
2304 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
2305 xpt_done(ccb);
2306 goto scsi_done;
2307 }
2308
2309 srb->ccb = ccb;
2310 error = bus_dmamap_load_ccb(hba->io_dmat,
2311 srb->dma_map,
2312 ccb,
2313 hptiop_post_scsi_command,
2314 srb,
2315 0);
2316
2317 if (error && error != EINPROGRESS) {
2318 device_printf(hba->pcidev,
2319 "%d bus_dmamap_load error %d",
2320 hba->pciunit, error);
2321 xpt_freeze_simq(hba->sim, 1);
2322 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
2323 hptiop_free_srb(hba, srb);
2324 xpt_done(ccb);
2325 goto scsi_done;
2326 }
2327
2328 scsi_done:
2329 hptiop_unlock_adapter(hba);
2330 return;
2331
2332 case XPT_RESET_BUS:
2333 device_printf(hba->pcidev, "reset adapter");
2334 hptiop_lock_adapter(hba);
2335 hba->msg_done = 0;
2336 hptiop_reset_adapter(hba);
2337 hptiop_unlock_adapter(hba);
2338 break;
2339
2340 case XPT_GET_TRAN_SETTINGS:
2341 case XPT_SET_TRAN_SETTINGS:
2342 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
2343 break;
2344
2345 case XPT_CALC_GEOMETRY:
2346 cam_calc_geometry(&ccb->ccg, 1);
2347 break;
2348
2349 case XPT_PATH_INQ:
2350 {
2351 struct ccb_pathinq *cpi = &ccb->cpi;
2352
2353 cpi->version_num = 1;
2354 cpi->hba_inquiry = PI_SDTR_ABLE;
2355 cpi->target_sprt = 0;
2356 cpi->hba_misc = PIM_NOBUSRESET;
2357 cpi->hba_eng_cnt = 0;
2358 cpi->max_target = hba->max_devices;
2359 cpi->max_lun = 0;
2360 cpi->unit_number = cam_sim_unit(sim);
2361 cpi->bus_id = cam_sim_bus(sim);
2362 cpi->initiator_id = hba->max_devices;
2363 cpi->base_transfer_speed = 3300;
2364
2365 strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
2366 strlcpy(cpi->hba_vid, "HPT ", HBA_IDLEN);
2367 strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
2368 cpi->transport = XPORT_SPI;
2369 cpi->transport_version = 2;
2370 cpi->protocol = PROTO_SCSI;
2371 cpi->protocol_version = SCSI_REV_2;
2372 cpi->ccb_h.status = CAM_REQ_CMP;
2373 break;
2374 }
2375
2376 default:
2377 ccb->ccb_h.status = CAM_REQ_INVALID;
2378 break;
2379 }
2380
2381 xpt_done(ccb);
2382 return;
2383 }
2384
hptiop_post_req_itl(struct hpt_iop_hba * hba,struct hpt_iop_srb * srb,bus_dma_segment_t * segs,int nsegs)2385 static void hptiop_post_req_itl(struct hpt_iop_hba *hba,
2386 struct hpt_iop_srb *srb,
2387 bus_dma_segment_t *segs, int nsegs)
2388 {
2389 int idx;
2390 union ccb *ccb = srb->ccb;
2391 u_int8_t *cdb;
2392
2393 if (ccb->ccb_h.flags & CAM_CDB_POINTER)
2394 cdb = ccb->csio.cdb_io.cdb_ptr;
2395 else
2396 cdb = ccb->csio.cdb_io.cdb_bytes;
2397
2398 KdPrint(("ccb=%p %x-%x-%x\n",
2399 ccb, *(u_int32_t *)cdb, *((u_int32_t *)cdb+1), *((u_int32_t *)cdb+2)));
2400
2401 if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) {
2402 u_int32_t iop_req32;
2403 struct hpt_iop_request_scsi_command req;
2404
2405 iop_req32 = BUS_SPACE_RD4_ITL(inbound_queue);
2406
2407 if (iop_req32 == IOPMU_QUEUE_EMPTY) {
2408 device_printf(hba->pcidev, "invalid req offset\n");
2409 ccb->ccb_h.status = CAM_BUSY;
2410 bus_dmamap_unload(hba->io_dmat, srb->dma_map);
2411 hptiop_free_srb(hba, srb);
2412 xpt_done(ccb);
2413 return;
2414 }
2415
2416 if (ccb->csio.dxfer_len && nsegs > 0) {
2417 struct hpt_iopsg *psg = req.sg_list;
2418 for (idx = 0; idx < nsegs; idx++, psg++) {
2419 psg->pci_address = (u_int64_t)segs[idx].ds_addr;
2420 psg->size = segs[idx].ds_len;
2421 psg->eot = 0;
2422 }
2423 psg[-1].eot = 1;
2424 }
2425
2426 bcopy(cdb, req.cdb, ccb->csio.cdb_len);
2427
2428 req.header.size =
2429 offsetof(struct hpt_iop_request_scsi_command, sg_list)
2430 + nsegs*sizeof(struct hpt_iopsg);
2431 req.header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
2432 req.header.flags = 0;
2433 req.header.result = IOP_RESULT_PENDING;
2434 req.header.context = (u_int64_t)(unsigned long)srb;
2435 req.dataxfer_length = ccb->csio.dxfer_len;
2436 req.channel = 0;
2437 req.target = ccb->ccb_h.target_id;
2438 req.lun = ccb->ccb_h.target_lun;
2439
2440 bus_space_write_region_1(hba->bar0t, hba->bar0h, iop_req32,
2441 (u_int8_t *)&req, req.header.size);
2442
2443 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
2444 bus_dmamap_sync(hba->io_dmat,
2445 srb->dma_map, BUS_DMASYNC_PREREAD);
2446 }
2447 else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
2448 bus_dmamap_sync(hba->io_dmat,
2449 srb->dma_map, BUS_DMASYNC_PREWRITE);
2450
2451 BUS_SPACE_WRT4_ITL(inbound_queue,iop_req32);
2452 } else {
2453 struct hpt_iop_request_scsi_command *req;
2454
2455 req = (struct hpt_iop_request_scsi_command *)srb;
2456 if (ccb->csio.dxfer_len && nsegs > 0) {
2457 struct hpt_iopsg *psg = req->sg_list;
2458 for (idx = 0; idx < nsegs; idx++, psg++) {
2459 psg->pci_address =
2460 (u_int64_t)segs[idx].ds_addr;
2461 psg->size = segs[idx].ds_len;
2462 psg->eot = 0;
2463 }
2464 psg[-1].eot = 1;
2465 }
2466
2467 bcopy(cdb, req->cdb, ccb->csio.cdb_len);
2468
2469 req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
2470 req->header.result = IOP_RESULT_PENDING;
2471 req->dataxfer_length = ccb->csio.dxfer_len;
2472 req->channel = 0;
2473 req->target = ccb->ccb_h.target_id;
2474 req->lun = ccb->ccb_h.target_lun;
2475 req->header.size =
2476 offsetof(struct hpt_iop_request_scsi_command, sg_list)
2477 + nsegs*sizeof(struct hpt_iopsg);
2478 req->header.context = (u_int64_t)srb->index |
2479 IOPMU_QUEUE_ADDR_HOST_BIT;
2480 req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
2481
2482 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
2483 bus_dmamap_sync(hba->io_dmat,
2484 srb->dma_map, BUS_DMASYNC_PREREAD);
2485 }else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
2486 bus_dmamap_sync(hba->io_dmat,
2487 srb->dma_map, BUS_DMASYNC_PREWRITE);
2488 }
2489
2490 if (hba->firmware_version > 0x01020000
2491 || hba->interface_version > 0x01020000) {
2492 u_int32_t size_bits;
2493
2494 if (req->header.size < 256)
2495 size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT;
2496 else if (req->header.size < 512)
2497 size_bits = IOPMU_QUEUE_ADDR_HOST_BIT;
2498 else
2499 size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT
2500 | IOPMU_QUEUE_ADDR_HOST_BIT;
2501
2502 BUS_SPACE_WRT4_ITL(inbound_queue,
2503 (u_int32_t)srb->phy_addr | size_bits);
2504 } else
2505 BUS_SPACE_WRT4_ITL(inbound_queue, (u_int32_t)srb->phy_addr
2506 |IOPMU_QUEUE_ADDR_HOST_BIT);
2507 }
2508 }
2509
hptiop_post_req_mv(struct hpt_iop_hba * hba,struct hpt_iop_srb * srb,bus_dma_segment_t * segs,int nsegs)2510 static void hptiop_post_req_mv(struct hpt_iop_hba *hba,
2511 struct hpt_iop_srb *srb,
2512 bus_dma_segment_t *segs, int nsegs)
2513 {
2514 int idx, size;
2515 union ccb *ccb = srb->ccb;
2516 u_int8_t *cdb;
2517 struct hpt_iop_request_scsi_command *req;
2518 u_int64_t req_phy;
2519
2520 req = (struct hpt_iop_request_scsi_command *)srb;
2521 req_phy = srb->phy_addr;
2522
2523 if (ccb->csio.dxfer_len && nsegs > 0) {
2524 struct hpt_iopsg *psg = req->sg_list;
2525 for (idx = 0; idx < nsegs; idx++, psg++) {
2526 psg->pci_address = (u_int64_t)segs[idx].ds_addr;
2527 psg->size = segs[idx].ds_len;
2528 psg->eot = 0;
2529 }
2530 psg[-1].eot = 1;
2531 }
2532 if (ccb->ccb_h.flags & CAM_CDB_POINTER)
2533 cdb = ccb->csio.cdb_io.cdb_ptr;
2534 else
2535 cdb = ccb->csio.cdb_io.cdb_bytes;
2536
2537 bcopy(cdb, req->cdb, ccb->csio.cdb_len);
2538 req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
2539 req->header.result = IOP_RESULT_PENDING;
2540 req->dataxfer_length = ccb->csio.dxfer_len;
2541 req->channel = 0;
2542 req->target = ccb->ccb_h.target_id;
2543 req->lun = ccb->ccb_h.target_lun;
2544 req->header.size = sizeof(struct hpt_iop_request_scsi_command)
2545 - sizeof(struct hpt_iopsg)
2546 + nsegs * sizeof(struct hpt_iopsg);
2547 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
2548 bus_dmamap_sync(hba->io_dmat,
2549 srb->dma_map, BUS_DMASYNC_PREREAD);
2550 }
2551 else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
2552 bus_dmamap_sync(hba->io_dmat,
2553 srb->dma_map, BUS_DMASYNC_PREWRITE);
2554 req->header.context = (u_int64_t)srb->index
2555 << MVIOP_REQUEST_NUMBER_START_BIT
2556 | MVIOP_CMD_TYPE_SCSI;
2557 req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
2558 size = req->header.size >> 8;
2559 hptiop_mv_inbound_write(req_phy
2560 | MVIOP_MU_QUEUE_ADDR_HOST_BIT
2561 | (size > 3 ? 3 : size), hba);
2562 }
2563
hptiop_post_req_mvfrey(struct hpt_iop_hba * hba,struct hpt_iop_srb * srb,bus_dma_segment_t * segs,int nsegs)2564 static void hptiop_post_req_mvfrey(struct hpt_iop_hba *hba,
2565 struct hpt_iop_srb *srb,
2566 bus_dma_segment_t *segs, int nsegs)
2567 {
2568 int idx, index;
2569 union ccb *ccb = srb->ccb;
2570 u_int8_t *cdb;
2571 struct hpt_iop_request_scsi_command *req;
2572 u_int64_t req_phy;
2573
2574 req = (struct hpt_iop_request_scsi_command *)srb;
2575 req_phy = srb->phy_addr;
2576
2577 if (ccb->csio.dxfer_len && nsegs > 0) {
2578 struct hpt_iopsg *psg = req->sg_list;
2579 for (idx = 0; idx < nsegs; idx++, psg++) {
2580 psg->pci_address = (u_int64_t)segs[idx].ds_addr | 1;
2581 psg->size = segs[idx].ds_len;
2582 psg->eot = 0;
2583 }
2584 psg[-1].eot = 1;
2585 }
2586 if (ccb->ccb_h.flags & CAM_CDB_POINTER)
2587 cdb = ccb->csio.cdb_io.cdb_ptr;
2588 else
2589 cdb = ccb->csio.cdb_io.cdb_bytes;
2590
2591 bcopy(cdb, req->cdb, ccb->csio.cdb_len);
2592 req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
2593 req->header.result = IOP_RESULT_PENDING;
2594 req->dataxfer_length = ccb->csio.dxfer_len;
2595 req->channel = 0;
2596 req->target = ccb->ccb_h.target_id;
2597 req->lun = ccb->ccb_h.target_lun;
2598 req->header.size = sizeof(struct hpt_iop_request_scsi_command)
2599 - sizeof(struct hpt_iopsg)
2600 + nsegs * sizeof(struct hpt_iopsg);
2601 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
2602 bus_dmamap_sync(hba->io_dmat,
2603 srb->dma_map, BUS_DMASYNC_PREREAD);
2604 }
2605 else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
2606 bus_dmamap_sync(hba->io_dmat,
2607 srb->dma_map, BUS_DMASYNC_PREWRITE);
2608
2609 req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT
2610 | IOP_REQUEST_FLAG_ADDR_BITS
2611 | ((req_phy >> 16) & 0xffff0000);
2612 req->header.context = ((req_phy & 0xffffffff) << 32 )
2613 | srb->index << 4
2614 | IOPMU_QUEUE_ADDR_HOST_BIT | req->header.type;
2615
2616 hba->u.mvfrey.inlist_wptr++;
2617 index = hba->u.mvfrey.inlist_wptr & 0x3fff;
2618
2619 if (index == hba->u.mvfrey.list_count) {
2620 index = 0;
2621 hba->u.mvfrey.inlist_wptr &= ~0x3fff;
2622 hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE;
2623 }
2624
2625 hba->u.mvfrey.inlist[index].addr = req_phy;
2626 hba->u.mvfrey.inlist[index].intrfc_len = (req->header.size + 3) / 4;
2627
2628 BUS_SPACE_WRT4_MVFREY2(inbound_write_ptr, hba->u.mvfrey.inlist_wptr);
2629 BUS_SPACE_RD4_MVFREY2(inbound_write_ptr);
2630
2631 if (req->header.type == IOP_REQUEST_TYPE_SCSI_COMMAND) {
2632 srb->timeout_ch = timeout(hptiop_reset_adapter, hba, 20*hz);
2633 }
2634 }
2635
hptiop_post_scsi_command(void * arg,bus_dma_segment_t * segs,int nsegs,int error)2636 static void hptiop_post_scsi_command(void *arg, bus_dma_segment_t *segs,
2637 int nsegs, int error)
2638 {
2639 struct hpt_iop_srb *srb = (struct hpt_iop_srb *)arg;
2640 union ccb *ccb = srb->ccb;
2641 struct hpt_iop_hba *hba = srb->hba;
2642
2643 if (error || nsegs > hba->max_sg_count) {
2644 KdPrint(("hptiop: func_code=%x tid=%x lun=%x nsegs=%d\n",
2645 ccb->ccb_h.func_code,
2646 ccb->ccb_h.target_id,
2647 ccb->ccb_h.target_lun, nsegs));
2648 ccb->ccb_h.status = CAM_BUSY;
2649 bus_dmamap_unload(hba->io_dmat, srb->dma_map);
2650 hptiop_free_srb(hba, srb);
2651 xpt_done(ccb);
2652 return;
2653 }
2654
2655 hba->ops->post_req(hba, srb, segs, nsegs);
2656 }
2657
hptiop_mv_map_ctlcfg(void * arg,bus_dma_segment_t * segs,int nsegs,int error)2658 static void hptiop_mv_map_ctlcfg(void *arg, bus_dma_segment_t *segs,
2659 int nsegs, int error)
2660 {
2661 struct hpt_iop_hba *hba = (struct hpt_iop_hba *)arg;
2662 hba->ctlcfgcmd_phy = ((u_int64_t)segs->ds_addr + 0x1F)
2663 & ~(u_int64_t)0x1F;
2664 hba->ctlcfg_ptr = (u_int8_t *)(((unsigned long)hba->ctlcfg_ptr + 0x1F)
2665 & ~0x1F);
2666 }
2667
hptiop_mvfrey_map_ctlcfg(void * arg,bus_dma_segment_t * segs,int nsegs,int error)2668 static void hptiop_mvfrey_map_ctlcfg(void *arg, bus_dma_segment_t *segs,
2669 int nsegs, int error)
2670 {
2671 struct hpt_iop_hba *hba = (struct hpt_iop_hba *)arg;
2672 char *p;
2673 u_int64_t phy;
2674 u_int32_t list_count = hba->u.mvfrey.list_count;
2675
2676 phy = ((u_int64_t)segs->ds_addr + 0x1F)
2677 & ~(u_int64_t)0x1F;
2678 p = (u_int8_t *)(((unsigned long)hba->ctlcfg_ptr + 0x1F)
2679 & ~0x1F);
2680
2681 hba->ctlcfgcmd_phy = phy;
2682 hba->ctlcfg_ptr = p;
2683
2684 p += 0x800;
2685 phy += 0x800;
2686
2687 hba->u.mvfrey.inlist = (struct mvfrey_inlist_entry *)p;
2688 hba->u.mvfrey.inlist_phy = phy;
2689
2690 p += list_count * sizeof(struct mvfrey_inlist_entry);
2691 phy += list_count * sizeof(struct mvfrey_inlist_entry);
2692
2693 hba->u.mvfrey.outlist = (struct mvfrey_outlist_entry *)p;
2694 hba->u.mvfrey.outlist_phy = phy;
2695
2696 p += list_count * sizeof(struct mvfrey_outlist_entry);
2697 phy += list_count * sizeof(struct mvfrey_outlist_entry);
2698
2699 hba->u.mvfrey.outlist_cptr = (u_int32_t *)p;
2700 hba->u.mvfrey.outlist_cptr_phy = phy;
2701 }
2702
hptiop_map_srb(void * arg,bus_dma_segment_t * segs,int nsegs,int error)2703 static void hptiop_map_srb(void *arg, bus_dma_segment_t *segs,
2704 int nsegs, int error)
2705 {
2706 struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg;
2707 bus_addr_t phy_addr = (segs->ds_addr + 0x1F) & ~(bus_addr_t)0x1F;
2708 struct hpt_iop_srb *srb, *tmp_srb;
2709 int i;
2710
2711 if (error || nsegs == 0) {
2712 device_printf(hba->pcidev, "hptiop_map_srb error");
2713 return;
2714 }
2715
2716 /* map srb */
2717 srb = (struct hpt_iop_srb *)
2718 (((unsigned long)hba->uncached_ptr + 0x1F)
2719 & ~(unsigned long)0x1F);
2720
2721 for (i = 0; i < HPT_SRB_MAX_QUEUE_SIZE; i++) {
2722 tmp_srb = (struct hpt_iop_srb *)
2723 ((char *)srb + i * HPT_SRB_MAX_SIZE);
2724 if (((unsigned long)tmp_srb & 0x1F) == 0) {
2725 if (bus_dmamap_create(hba->io_dmat,
2726 0, &tmp_srb->dma_map)) {
2727 device_printf(hba->pcidev, "dmamap create failed");
2728 return;
2729 }
2730
2731 bzero(tmp_srb, sizeof(struct hpt_iop_srb));
2732 tmp_srb->hba = hba;
2733 tmp_srb->index = i;
2734 if (hba->ctlcfg_ptr == 0) {/*itl iop*/
2735 tmp_srb->phy_addr = (u_int64_t)(u_int32_t)
2736 (phy_addr >> 5);
2737 if (phy_addr & IOPMU_MAX_MEM_SUPPORT_MASK_32G)
2738 tmp_srb->srb_flag =
2739 HPT_SRB_FLAG_HIGH_MEM_ACESS;
2740 } else {
2741 tmp_srb->phy_addr = phy_addr;
2742 }
2743
2744 callout_handle_init(&tmp_srb->timeout_ch);
2745 hptiop_free_srb(hba, tmp_srb);
2746 hba->srb[i] = tmp_srb;
2747 phy_addr += HPT_SRB_MAX_SIZE;
2748 }
2749 else {
2750 device_printf(hba->pcidev, "invalid alignment");
2751 return;
2752 }
2753 }
2754 }
2755
hptiop_os_message_callback(struct hpt_iop_hba * hba,u_int32_t msg)2756 static void hptiop_os_message_callback(struct hpt_iop_hba * hba, u_int32_t msg)
2757 {
2758 hba->msg_done = 1;
2759 }
2760
hptiop_os_query_remove_device(struct hpt_iop_hba * hba,int target_id)2761 static int hptiop_os_query_remove_device(struct hpt_iop_hba * hba,
2762 int target_id)
2763 {
2764 struct cam_periph *periph = NULL;
2765 struct cam_path *path;
2766 int status, retval = 0;
2767
2768 status = xpt_create_path(&path, NULL, hba->sim->path_id, target_id, 0);
2769
2770 if (status == CAM_REQ_CMP) {
2771 if ((periph = cam_periph_find(path, "da")) != NULL) {
2772 if (periph->refcount >= 1) {
2773 device_printf(hba->pcidev, "%d ,"
2774 "target_id=0x%x,"
2775 "refcount=%d",
2776 hba->pciunit, target_id, periph->refcount);
2777 retval = -1;
2778 }
2779 }
2780 xpt_free_path(path);
2781 }
2782 return retval;
2783 }
2784
hptiop_release_resource(struct hpt_iop_hba * hba)2785 static void hptiop_release_resource(struct hpt_iop_hba *hba)
2786 {
2787 int i;
2788 if (hba->path) {
2789 struct ccb_setasync ccb;
2790
2791 xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5);
2792 ccb.ccb_h.func_code = XPT_SASYNC_CB;
2793 ccb.event_enable = 0;
2794 ccb.callback = hptiop_async;
2795 ccb.callback_arg = hba->sim;
2796 xpt_action((union ccb *)&ccb);
2797 xpt_free_path(hba->path);
2798 }
2799
2800 if (hba->sim) {
2801 xpt_bus_deregister(cam_sim_path(hba->sim));
2802 cam_sim_free(hba->sim, TRUE);
2803 }
2804
2805 if (hba->ctlcfg_dmat) {
2806 bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap);
2807 bus_dmamem_free(hba->ctlcfg_dmat,
2808 hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
2809 bus_dma_tag_destroy(hba->ctlcfg_dmat);
2810 }
2811
2812 for (i = 0; i < HPT_SRB_MAX_QUEUE_SIZE; i++) {
2813 struct hpt_iop_srb *srb = hba->srb[i];
2814 if (srb->dma_map)
2815 bus_dmamap_destroy(hba->io_dmat, srb->dma_map);
2816 }
2817
2818 if (hba->srb_dmat) {
2819 bus_dmamap_unload(hba->srb_dmat, hba->srb_dmamap);
2820 bus_dmamap_destroy(hba->srb_dmat, hba->srb_dmamap);
2821 bus_dma_tag_destroy(hba->srb_dmat);
2822 }
2823
2824 if (hba->io_dmat)
2825 bus_dma_tag_destroy(hba->io_dmat);
2826
2827 if (hba->parent_dmat)
2828 bus_dma_tag_destroy(hba->parent_dmat);
2829
2830 if (hba->irq_handle)
2831 bus_teardown_intr(hba->pcidev, hba->irq_res, hba->irq_handle);
2832
2833 if (hba->irq_res)
2834 bus_release_resource(hba->pcidev, SYS_RES_IRQ,
2835 0, hba->irq_res);
2836
2837 if (hba->bar0_res)
2838 bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
2839 hba->bar0_rid, hba->bar0_res);
2840 if (hba->bar2_res)
2841 bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
2842 hba->bar2_rid, hba->bar2_res);
2843 if (hba->ioctl_dev)
2844 destroy_dev(hba->ioctl_dev);
2845 }
2846