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