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