hptiop.c revision 203108
1169412Sscottl/* 2175942Sscottl * HighPoint RR3xxx/4xxx RAID Driver for FreeBSD 3175942Sscottl * Copyright (C) 2007-2008 HighPoint Technologies, Inc. All Rights Reserved. 4175942Sscottl * 5169412Sscottl * Redistribution and use in source and binary forms, with or without 6169412Sscottl * modification, are permitted provided that the following conditions 7169412Sscottl * are met: 8169412Sscottl * 1. Redistributions of source code must retain the above copyright 9169412Sscottl * notice, this list of conditions and the following disclaimer. 10169412Sscottl * 2. Redistributions in binary form must reproduce the above copyright 11169412Sscottl * notice, this list of conditions and the following disclaimer in the 12169412Sscottl * documentation and/or other materials provided with the distribution. 13169412Sscottl * 14169412Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15169412Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16169412Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17169412Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18169412Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19169412Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20169412Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21169412Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22169412Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23169412Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24169412Sscottl * SUCH DAMAGE. 25169412Sscottl */ 26175942Sscottl 27169412Sscottl#include <sys/cdefs.h> 28169412Sscottl__FBSDID("$FreeBSD: head/sys/dev/hptiop/hptiop.c 203108 2010-01-28 08:41:30Z mav $"); 29169412Sscottl 30169412Sscottl#include <sys/param.h> 31169412Sscottl#include <sys/types.h> 32169412Sscottl#include <sys/cons.h> 33169412Sscottl#if (__FreeBSD_version >= 500000) 34169412Sscottl#include <sys/time.h> 35169412Sscottl#include <sys/systm.h> 36169412Sscottl#else 37169412Sscottl#include <machine/clock.h> 38169412Sscottl#endif 39169412Sscottl 40169412Sscottl#include <sys/stat.h> 41169412Sscottl#include <sys/malloc.h> 42169412Sscottl#include <sys/conf.h> 43169412Sscottl#include <sys/libkern.h> 44169412Sscottl#include <sys/kernel.h> 45169412Sscottl 46169412Sscottl#if (__FreeBSD_version >= 500000) 47169412Sscottl#include <sys/kthread.h> 48169412Sscottl#include <sys/mutex.h> 49169412Sscottl#include <sys/module.h> 50169412Sscottl#endif 51169412Sscottl 52169412Sscottl#include <sys/eventhandler.h> 53169412Sscottl#include <sys/bus.h> 54169412Sscottl#include <sys/taskqueue.h> 55169412Sscottl#include <sys/ioccom.h> 56169412Sscottl 57169412Sscottl#include <machine/resource.h> 58169412Sscottl#include <machine/bus.h> 59169412Sscottl#include <machine/stdarg.h> 60169412Sscottl#include <sys/rman.h> 61169412Sscottl 62169412Sscottl#include <vm/vm.h> 63169412Sscottl#include <vm/pmap.h> 64169412Sscottl 65169412Sscottl#if (__FreeBSD_version >= 500000) 66169412Sscottl#include <dev/pci/pcireg.h> 67169412Sscottl#include <dev/pci/pcivar.h> 68169412Sscottl#else 69169412Sscottl#include <pci/pcivar.h> 70169412Sscottl#include <pci/pcireg.h> 71169412Sscottl#endif 72169412Sscottl 73169412Sscottl#if (__FreeBSD_version <= 500043) 74169412Sscottl#include <sys/devicestat.h> 75169412Sscottl#endif 76169412Sscottl 77169412Sscottl#include <cam/cam.h> 78169412Sscottl#include <cam/cam_ccb.h> 79169412Sscottl#include <cam/cam_sim.h> 80169412Sscottl#include <cam/cam_xpt_sim.h> 81169412Sscottl#include <cam/cam_debug.h> 82169412Sscottl#include <cam/cam_periph.h> 83169412Sscottl#include <cam/scsi/scsi_all.h> 84169412Sscottl#include <cam/scsi/scsi_message.h> 85169412Sscottl 86169412Sscottl#if (__FreeBSD_version < 500043) 87169412Sscottl#include <sys/bus_private.h> 88169412Sscottl#endif 89169412Sscottl 90169412Sscottl#include <dev/hptiop/hptiop.h> 91169412Sscottl 92169412Sscottlstatic char driver_name[] = "hptiop"; 93175942Sscottlstatic char driver_version[] = "v1.3 (010208)"; 94169412Sscottl 95169412Sscottlstatic devclass_t hptiop_devclass; 96169412Sscottl 97175942Sscottlstatic int hptiop_send_sync_msg(struct hpt_iop_hba *hba, 98175942Sscottl u_int32_t msg, u_int32_t millisec); 99175942Sscottlstatic void hptiop_request_callback_itl(struct hpt_iop_hba *hba, 100175942Sscottl u_int32_t req); 101175942Sscottlstatic void hptiop_request_callback_mv(struct hpt_iop_hba *hba, u_int64_t req); 102175942Sscottlstatic void hptiop_os_message_callback(struct hpt_iop_hba *hba, u_int32_t msg); 103175942Sscottlstatic int hptiop_do_ioctl_itl(struct hpt_iop_hba *hba, 104175942Sscottl struct hpt_iop_ioctl_param *pParams); 105175942Sscottlstatic int hptiop_do_ioctl_mv(struct hpt_iop_hba *hba, 106175942Sscottl struct hpt_iop_ioctl_param *pParams); 107175942Sscottlstatic int hptiop_rescan_bus(struct hpt_iop_hba *hba); 108175942Sscottlstatic int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba); 109175942Sscottlstatic int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba); 110175942Sscottlstatic int hptiop_get_config_itl(struct hpt_iop_hba *hba, 111175942Sscottl struct hpt_iop_request_get_config *config); 112175942Sscottlstatic int hptiop_get_config_mv(struct hpt_iop_hba *hba, 113175942Sscottl struct hpt_iop_request_get_config *config); 114175942Sscottlstatic int hptiop_set_config_itl(struct hpt_iop_hba *hba, 115175942Sscottl struct hpt_iop_request_set_config *config); 116175942Sscottlstatic int hptiop_set_config_mv(struct hpt_iop_hba *hba, 117175942Sscottl struct hpt_iop_request_set_config *config); 118175942Sscottlstatic int hptiop_internal_memalloc_mv(struct hpt_iop_hba *hba); 119175942Sscottlstatic int hptiop_internal_memfree_mv(struct hpt_iop_hba *hba); 120175942Sscottlstatic int hptiop_post_ioctl_command_itl(struct hpt_iop_hba *hba, 121175942Sscottl u_int32_t req32, struct hpt_iop_ioctl_param *pParams); 122175942Sscottlstatic int hptiop_post_ioctl_command_mv(struct hpt_iop_hba *hba, 123175942Sscottl struct hpt_iop_request_ioctl_command *req, 124175942Sscottl struct hpt_iop_ioctl_param *pParams); 125175942Sscottlstatic void hptiop_post_req_itl(struct hpt_iop_hba *hba, 126175942Sscottl struct hpt_iop_srb *srb, 127175942Sscottl bus_dma_segment_t *segs, int nsegs); 128175942Sscottlstatic void hptiop_post_req_mv(struct hpt_iop_hba *hba, 129175942Sscottl struct hpt_iop_srb *srb, 130175942Sscottl bus_dma_segment_t *segs, int nsegs); 131175942Sscottlstatic void hptiop_post_msg_itl(struct hpt_iop_hba *hba, u_int32_t msg); 132175942Sscottlstatic void hptiop_post_msg_mv(struct hpt_iop_hba *hba, u_int32_t msg); 133175942Sscottlstatic void hptiop_enable_intr_itl(struct hpt_iop_hba *hba); 134175942Sscottlstatic void hptiop_enable_intr_mv(struct hpt_iop_hba *hba); 135175942Sscottlstatic void hptiop_disable_intr_itl(struct hpt_iop_hba *hba); 136175942Sscottlstatic void hptiop_disable_intr_mv(struct hpt_iop_hba *hba); 137175942Sscottlstatic void hptiop_free_srb(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb); 138175942Sscottlstatic int hptiop_os_query_remove_device(struct hpt_iop_hba *hba, int tid); 139169412Sscottlstatic int hptiop_probe(device_t dev); 140169412Sscottlstatic int hptiop_attach(device_t dev); 141169412Sscottlstatic int hptiop_detach(device_t dev); 142169412Sscottlstatic int hptiop_shutdown(device_t dev); 143169412Sscottlstatic void hptiop_action(struct cam_sim *sim, union ccb *ccb); 144169412Sscottlstatic void hptiop_poll(struct cam_sim *sim); 145175942Sscottlstatic void hptiop_async(void *callback_arg, u_int32_t code, 146175942Sscottl struct cam_path *path, void *arg); 147169412Sscottlstatic void hptiop_pci_intr(void *arg); 148175942Sscottlstatic void hptiop_release_resource(struct hpt_iop_hba *hba); 149175942Sscottlstatic int hptiop_reset_adapter(struct hpt_iop_hba *hba); 150169412Sscottl 151169412Sscottlstatic d_open_t hptiop_open; 152169412Sscottlstatic d_close_t hptiop_close; 153169412Sscottlstatic d_ioctl_t hptiop_ioctl; 154169412Sscottl 155169412Sscottlstatic struct cdevsw hptiop_cdevsw = { 156169412Sscottl .d_open = hptiop_open, 157169412Sscottl .d_close = hptiop_close, 158169412Sscottl .d_ioctl = hptiop_ioctl, 159169412Sscottl .d_name = driver_name, 160169412Sscottl#if __FreeBSD_version>=503000 161169412Sscottl .d_version = D_VERSION, 162169412Sscottl#endif 163169412Sscottl#if (__FreeBSD_version>=503000 && __FreeBSD_version<600034) 164169412Sscottl .d_flags = D_NEEDGIANT, 165169412Sscottl#endif 166169412Sscottl#if __FreeBSD_version<600034 167169412Sscottl#if __FreeBSD_version>=501000 168169412Sscottl .d_maj = MAJOR_AUTO, 169169412Sscottl#else 170169412Sscottl .d_maj = HPT_DEV_MAJOR, 171169412Sscottl#endif 172169412Sscottl#endif 173169412Sscottl}; 174169412Sscottl 175169412Sscottl#if __FreeBSD_version < 503000 176169412Sscottl#define hba_from_dev(dev) ((struct hpt_iop_hba *)(dev)->si_drv1) 177169412Sscottl#else 178169412Sscottl#define hba_from_dev(dev) \ 179183397Sed ((struct hpt_iop_hba *)devclass_get_softc(hptiop_devclass, dev2unit(dev))) 180169412Sscottl#endif 181169412Sscottl 182175942Sscottl#define BUS_SPACE_WRT4_ITL(offset, value) bus_space_write_4(hba->bar0t,\ 183175942Sscottl hba->bar0h, offsetof(struct hpt_iopmu_itl, offset), (value)) 184175942Sscottl#define BUS_SPACE_RD4_ITL(offset) bus_space_read_4(hba->bar0t,\ 185175942Sscottl hba->bar0h, offsetof(struct hpt_iopmu_itl, offset)) 186175942Sscottl 187175942Sscottl#define BUS_SPACE_WRT4_MV0(offset, value) bus_space_write_4(hba->bar0t,\ 188175942Sscottl hba->bar0h, offsetof(struct hpt_iopmv_regs, offset), value) 189175942Sscottl#define BUS_SPACE_RD4_MV0(offset) bus_space_read_4(hba->bar0t,\ 190175942Sscottl hba->bar0h, offsetof(struct hpt_iopmv_regs, offset)) 191175942Sscottl#define BUS_SPACE_WRT4_MV2(offset, value) bus_space_write_4(hba->bar2t,\ 192175942Sscottl hba->bar2h, offsetof(struct hpt_iopmu_mv, offset), value) 193175942Sscottl#define BUS_SPACE_RD4_MV2(offset) bus_space_read_4(hba->bar2t,\ 194175942Sscottl hba->bar2h, offsetof(struct hpt_iopmu_mv, offset)) 195175942Sscottl 196169412Sscottlstatic int hptiop_open(ioctl_dev_t dev, int flags, 197169412Sscottl int devtype, ioctl_thread_t proc) 198169412Sscottl{ 199175942Sscottl struct hpt_iop_hba *hba = hba_from_dev(dev); 200169412Sscottl 201169412Sscottl if (hba==NULL) 202169412Sscottl return ENXIO; 203169412Sscottl if (hba->flag & HPT_IOCTL_FLAG_OPEN) 204169412Sscottl return EBUSY; 205169412Sscottl hba->flag |= HPT_IOCTL_FLAG_OPEN; 206169412Sscottl return 0; 207169412Sscottl} 208169412Sscottl 209169412Sscottlstatic int hptiop_close(ioctl_dev_t dev, int flags, 210169412Sscottl int devtype, ioctl_thread_t proc) 211169412Sscottl{ 212175942Sscottl struct hpt_iop_hba *hba = hba_from_dev(dev); 213169412Sscottl hba->flag &= ~(u_int32_t)HPT_IOCTL_FLAG_OPEN; 214169412Sscottl return 0; 215169412Sscottl} 216169412Sscottl 217169412Sscottlstatic int hptiop_ioctl(ioctl_dev_t dev, u_long cmd, caddr_t data, 218169412Sscottl int flags, ioctl_thread_t proc) 219169412Sscottl{ 220169412Sscottl int ret = EFAULT; 221175942Sscottl struct hpt_iop_hba *hba = hba_from_dev(dev); 222169412Sscottl 223169412Sscottl#if (__FreeBSD_version >= 500000) 224169412Sscottl mtx_lock(&Giant); 225169412Sscottl#endif 226169412Sscottl 227169412Sscottl switch (cmd) { 228169412Sscottl case HPT_DO_IOCONTROL: 229175942Sscottl ret = hba->ops->do_ioctl(hba, 230175942Sscottl (struct hpt_iop_ioctl_param *)data); 231169412Sscottl break; 232169412Sscottl case HPT_SCAN_BUS: 233169412Sscottl ret = hptiop_rescan_bus(hba); 234169412Sscottl break; 235169412Sscottl } 236169412Sscottl 237169412Sscottl#if (__FreeBSD_version >= 500000) 238169412Sscottl mtx_unlock(&Giant); 239169412Sscottl#endif 240169412Sscottl 241169412Sscottl return ret; 242169412Sscottl} 243169412Sscottl 244175942Sscottlstatic u_int64_t hptiop_mv_outbound_read(struct hpt_iop_hba *hba) 245169412Sscottl{ 246175942Sscottl u_int64_t p; 247175942Sscottl u_int32_t outbound_tail = BUS_SPACE_RD4_MV2(outbound_tail); 248175942Sscottl u_int32_t outbound_head = BUS_SPACE_RD4_MV2(outbound_head); 249175942Sscottl 250175942Sscottl if (outbound_tail != outbound_head) { 251175942Sscottl bus_space_read_region_4(hba->bar2t, hba->bar2h, 252175942Sscottl offsetof(struct hpt_iopmu_mv, 253175942Sscottl outbound_q[outbound_tail]), 254175942Sscottl (u_int32_t *)&p, 2); 255175942Sscottl 256175942Sscottl outbound_tail++; 257175942Sscottl 258175942Sscottl if (outbound_tail == MVIOP_QUEUE_LEN) 259175942Sscottl outbound_tail = 0; 260175942Sscottl 261175942Sscottl BUS_SPACE_WRT4_MV2(outbound_tail, outbound_tail); 262175942Sscottl return p; 263175942Sscottl } else 264175942Sscottl return 0; 265169412Sscottl} 266169412Sscottl 267175942Sscottlstatic void hptiop_mv_inbound_write(u_int64_t p, struct hpt_iop_hba *hba) 268169412Sscottl{ 269175942Sscottl u_int32_t inbound_head = BUS_SPACE_RD4_MV2(inbound_head); 270175942Sscottl u_int32_t head = inbound_head + 1; 271175942Sscottl 272175942Sscottl if (head == MVIOP_QUEUE_LEN) 273175942Sscottl head = 0; 274175942Sscottl 275175942Sscottl bus_space_write_region_4(hba->bar2t, hba->bar2h, 276175942Sscottl offsetof(struct hpt_iopmu_mv, inbound_q[inbound_head]), 277175942Sscottl (u_int32_t *)&p, 2); 278175942Sscottl BUS_SPACE_WRT4_MV2(inbound_head, head); 279175942Sscottl BUS_SPACE_WRT4_MV0(inbound_doorbell, MVIOP_MU_INBOUND_INT_POSTQUEUE); 280169412Sscottl} 281169412Sscottl 282175942Sscottlstatic void hptiop_post_msg_itl(struct hpt_iop_hba *hba, u_int32_t msg) 283169412Sscottl{ 284175942Sscottl BUS_SPACE_WRT4_ITL(inbound_msgaddr0, msg); 285175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 286169412Sscottl} 287169412Sscottl 288175942Sscottlstatic void hptiop_post_msg_mv(struct hpt_iop_hba *hba, u_int32_t msg) 289169412Sscottl{ 290175942Sscottl 291175942Sscottl BUS_SPACE_WRT4_MV2(inbound_msg, msg); 292175942Sscottl BUS_SPACE_WRT4_MV0(inbound_doorbell, MVIOP_MU_INBOUND_INT_MSG); 293175942Sscottl 294175942Sscottl BUS_SPACE_RD4_MV0(outbound_intmask); 295169412Sscottl} 296169412Sscottl 297175942Sscottlstatic int hptiop_wait_ready_itl(struct hpt_iop_hba * hba, u_int32_t millisec) 298169412Sscottl{ 299169412Sscottl u_int32_t req=0; 300169412Sscottl int i; 301169412Sscottl 302169412Sscottl for (i = 0; i < millisec; i++) { 303175942Sscottl req = BUS_SPACE_RD4_ITL(inbound_queue); 304169412Sscottl if (req != IOPMU_QUEUE_EMPTY) 305169412Sscottl break; 306169412Sscottl DELAY(1000); 307169412Sscottl } 308169412Sscottl 309169412Sscottl if (req!=IOPMU_QUEUE_EMPTY) { 310175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req); 311175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 312169412Sscottl return 0; 313169412Sscottl } 314169412Sscottl 315169412Sscottl return -1; 316169412Sscottl} 317169412Sscottl 318175942Sscottlstatic int hptiop_wait_ready_mv(struct hpt_iop_hba * hba, u_int32_t millisec) 319169412Sscottl{ 320175942Sscottl if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec)) 321175942Sscottl return -1; 322175942Sscottl 323175942Sscottl return 0; 324175942Sscottl} 325175942Sscottl 326175942Sscottlstatic void hptiop_request_callback_itl(struct hpt_iop_hba * hba, 327175942Sscottl u_int32_t index) 328175942Sscottl{ 329175942Sscottl struct hpt_iop_srb *srb; 330175942Sscottl struct hpt_iop_request_scsi_command *req=0; 331175942Sscottl union ccb *ccb; 332175942Sscottl u_int8_t *cdb; 333175942Sscottl u_int32_t result, temp, dxfer; 334175942Sscottl u_int64_t temp64; 335175942Sscottl 336175942Sscottl if (index & IOPMU_QUEUE_MASK_HOST_BITS) { /*host req*/ 337175942Sscottl if (hba->firmware_version > 0x01020000 || 338175942Sscottl hba->interface_version > 0x01020000) { 339175942Sscottl srb = hba->srb[index & ~(u_int32_t) 340175942Sscottl (IOPMU_QUEUE_ADDR_HOST_BIT 341175942Sscottl | IOPMU_QUEUE_REQUEST_RESULT_BIT)]; 342175942Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 343175942Sscottl if (index & IOPMU_QUEUE_REQUEST_RESULT_BIT) 344175942Sscottl result = IOP_RESULT_SUCCESS; 345175942Sscottl else 346175942Sscottl result = req->header.result; 347175942Sscottl } else { 348175942Sscottl srb = hba->srb[index & 349175942Sscottl ~(u_int32_t)IOPMU_QUEUE_ADDR_HOST_BIT]; 350175942Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 351175942Sscottl result = req->header.result; 352175942Sscottl } 353175942Sscottl dxfer = req->dataxfer_length; 354175942Sscottl goto srb_complete; 355175942Sscottl } 356175942Sscottl 357175942Sscottl /*iop req*/ 358175942Sscottl temp = bus_space_read_4(hba->bar0t, hba->bar0h, index + 359175942Sscottl offsetof(struct hpt_iop_request_header, type)); 360175942Sscottl result = bus_space_read_4(hba->bar0t, hba->bar0h, index + 361175942Sscottl offsetof(struct hpt_iop_request_header, result)); 362175942Sscottl switch(temp) { 363175942Sscottl case IOP_REQUEST_TYPE_IOCTL_COMMAND: 364175942Sscottl { 365175942Sscottl temp64 = 0; 366175942Sscottl bus_space_write_region_4(hba->bar0t, hba->bar0h, index + 367175942Sscottl offsetof(struct hpt_iop_request_header, context), 368175942Sscottl (u_int32_t *)&temp64, 2); 369175942Sscottl wakeup((void *)((unsigned long)hba->u.itl.mu + index)); 370175942Sscottl break; 371175942Sscottl } 372175942Sscottl 373175942Sscottl case IOP_REQUEST_TYPE_SCSI_COMMAND: 374175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h, index + 375175942Sscottl offsetof(struct hpt_iop_request_header, context), 376175942Sscottl (u_int32_t *)&temp64, 2); 377175942Sscottl srb = (struct hpt_iop_srb *)(unsigned long)temp64; 378175942Sscottl dxfer = bus_space_read_4(hba->bar0t, hba->bar0h, 379175942Sscottl index + offsetof(struct hpt_iop_request_scsi_command, 380175942Sscottl dataxfer_length)); 381175942Sscottlsrb_complete: 382175942Sscottl ccb = (union ccb *)srb->ccb; 383175942Sscottl if (ccb->ccb_h.flags & CAM_CDB_POINTER) 384175942Sscottl cdb = ccb->csio.cdb_io.cdb_ptr; 385175942Sscottl else 386175942Sscottl cdb = ccb->csio.cdb_io.cdb_bytes; 387175942Sscottl 388175942Sscottl if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */ 389175942Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 390175942Sscottl goto scsi_done; 391175942Sscottl } 392175942Sscottl 393175942Sscottl switch (result) { 394175942Sscottl case IOP_RESULT_SUCCESS: 395175942Sscottl switch (ccb->ccb_h.flags & CAM_DIR_MASK) { 396175942Sscottl case CAM_DIR_IN: 397175942Sscottl bus_dmamap_sync(hba->io_dmat, 398175942Sscottl srb->dma_map, BUS_DMASYNC_POSTREAD); 399175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 400175942Sscottl break; 401175942Sscottl case CAM_DIR_OUT: 402175942Sscottl bus_dmamap_sync(hba->io_dmat, 403175942Sscottl srb->dma_map, BUS_DMASYNC_POSTWRITE); 404175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 405175942Sscottl break; 406175942Sscottl } 407175942Sscottl 408175942Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 409175942Sscottl break; 410175942Sscottl 411175942Sscottl case IOP_RESULT_BAD_TARGET: 412175942Sscottl ccb->ccb_h.status = CAM_DEV_NOT_THERE; 413175942Sscottl break; 414175942Sscottl case IOP_RESULT_BUSY: 415175942Sscottl ccb->ccb_h.status = CAM_BUSY; 416175942Sscottl break; 417175942Sscottl case IOP_RESULT_INVALID_REQUEST: 418175942Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 419175942Sscottl break; 420175942Sscottl case IOP_RESULT_FAIL: 421175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 422175942Sscottl break; 423175942Sscottl case IOP_RESULT_RESET: 424175942Sscottl ccb->ccb_h.status = CAM_BUSY; 425175942Sscottl break; 426175942Sscottl case IOP_RESULT_CHECK_CONDITION: 427175942Sscottl if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) {/*iop*/ 428175942Sscottl bus_space_read_region_1(hba->bar0t, hba->bar0h, 429175942Sscottl index + offsetof(struct hpt_iop_request_scsi_command, 430175942Sscottl sg_list), (u_int8_t *)&ccb->csio.sense_data, 431175942Sscottl MIN(dxfer, sizeof(ccb->csio.sense_data))); 432175942Sscottl } else { 433175942Sscottl memcpy(&ccb->csio.sense_data, &req->sg_list, 434175942Sscottl MIN(dxfer, sizeof(ccb->csio.sense_data))); 435175942Sscottl } 436175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 437175942Sscottl ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 438175942Sscottl ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 439175942Sscottl break; 440175942Sscottl default: 441175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 442175942Sscottl break; 443175942Sscottl } 444175942Sscottlscsi_done: 445175942Sscottl if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) 446175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, index); 447175942Sscottl 448175942Sscottl ccb->csio.resid = ccb->csio.dxfer_len - dxfer; 449175942Sscottl 450175942Sscottl hptiop_free_srb(hba, srb); 451175942Sscottl xpt_done(ccb); 452175942Sscottl break; 453175942Sscottl } 454175942Sscottl} 455175942Sscottl 456175942Sscottlstatic void hptiop_drain_outbound_queue_itl(struct hpt_iop_hba *hba) 457175942Sscottl{ 458175942Sscottl u_int32_t req, temp; 459175942Sscottl 460175942Sscottl while ((req = BUS_SPACE_RD4_ITL(outbound_queue)) !=IOPMU_QUEUE_EMPTY) { 461175942Sscottl if (req & IOPMU_QUEUE_MASK_HOST_BITS) 462175942Sscottl hptiop_request_callback_itl(hba, req); 463175942Sscottl else { 464175942Sscottl struct hpt_iop_request_header *p; 465175942Sscottl 466175942Sscottl p = (struct hpt_iop_request_header *) 467175942Sscottl ((char *)hba->u.itl.mu + req); 468175942Sscottl temp = bus_space_read_4(hba->bar0t, 469175942Sscottl hba->bar0h,req + 470175942Sscottl offsetof(struct hpt_iop_request_header, 471175942Sscottl flags)); 472175942Sscottl if (temp & IOP_REQUEST_FLAG_SYNC_REQUEST) { 473175942Sscottl u_int64_t temp64; 474175942Sscottl bus_space_read_region_4(hba->bar0t, 475175942Sscottl hba->bar0h,req + 476175942Sscottl offsetof(struct hpt_iop_request_header, 477175942Sscottl context), 478175942Sscottl (u_int32_t *)&temp64, 2); 479175942Sscottl if (temp64) { 480175942Sscottl hptiop_request_callback_itl(hba, req); 481175942Sscottl } else { 482175942Sscottl temp64 = 1; 483175942Sscottl bus_space_write_region_4(hba->bar0t, 484175942Sscottl hba->bar0h,req + 485175942Sscottl offsetof(struct hpt_iop_request_header, 486175942Sscottl context), 487175942Sscottl (u_int32_t *)&temp64, 2); 488175942Sscottl } 489175942Sscottl } else 490175942Sscottl hptiop_request_callback_itl(hba, req); 491175942Sscottl } 492175942Sscottl } 493175942Sscottl} 494175942Sscottl 495175942Sscottlstatic int hptiop_intr_itl(struct hpt_iop_hba * hba) 496175942Sscottl{ 497169412Sscottl u_int32_t status; 498169412Sscottl int ret = 0; 499169412Sscottl 500175942Sscottl status = BUS_SPACE_RD4_ITL(outbound_intstatus); 501169412Sscottl 502169412Sscottl if (status & IOPMU_OUTBOUND_INT_MSG0) { 503175942Sscottl u_int32_t msg = BUS_SPACE_RD4_ITL(outbound_msgaddr0); 504175942Sscottl KdPrint(("hptiop: received outbound msg %x\n", msg)); 505175942Sscottl BUS_SPACE_WRT4_ITL(outbound_intstatus, IOPMU_OUTBOUND_INT_MSG0); 506175942Sscottl hptiop_os_message_callback(hba, msg); 507169412Sscottl ret = 1; 508169412Sscottl } 509169412Sscottl 510169412Sscottl if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) { 511175942Sscottl hptiop_drain_outbound_queue_itl(hba); 512175942Sscottl ret = 1; 513175942Sscottl } 514175942Sscottl 515175942Sscottl return ret; 516175942Sscottl} 517175942Sscottl 518175942Sscottlstatic void hptiop_request_callback_mv(struct hpt_iop_hba * hba, 519175942Sscottl u_int64_t _tag) 520175942Sscottl{ 521175942Sscottl u_int32_t context = (u_int32_t)_tag; 522175942Sscottl 523175942Sscottl if (context & MVIOP_CMD_TYPE_SCSI) { 524175942Sscottl struct hpt_iop_srb *srb; 525175942Sscottl struct hpt_iop_request_scsi_command *req; 526175942Sscottl union ccb *ccb; 527175942Sscottl u_int8_t *cdb; 528175942Sscottl 529175942Sscottl srb = hba->srb[context >> MVIOP_REQUEST_NUMBER_START_BIT]; 530175942Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 531175942Sscottl ccb = (union ccb *)srb->ccb; 532175942Sscottl if (ccb->ccb_h.flags & CAM_CDB_POINTER) 533175942Sscottl cdb = ccb->csio.cdb_io.cdb_ptr; 534175942Sscottl else 535175942Sscottl cdb = ccb->csio.cdb_io.cdb_bytes; 536175942Sscottl 537175942Sscottl if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */ 538175942Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 539175942Sscottl goto scsi_done; 540175942Sscottl } 541175942Sscottl if (context & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT) 542175942Sscottl req->header.result = IOP_RESULT_SUCCESS; 543175942Sscottl 544175942Sscottl switch (req->header.result) { 545175942Sscottl case IOP_RESULT_SUCCESS: 546175942Sscottl switch (ccb->ccb_h.flags & CAM_DIR_MASK) { 547175942Sscottl case CAM_DIR_IN: 548175942Sscottl bus_dmamap_sync(hba->io_dmat, 549175942Sscottl srb->dma_map, BUS_DMASYNC_POSTREAD); 550175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 551175942Sscottl break; 552175942Sscottl case CAM_DIR_OUT: 553175942Sscottl bus_dmamap_sync(hba->io_dmat, 554175942Sscottl srb->dma_map, BUS_DMASYNC_POSTWRITE); 555175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 556175942Sscottl break; 557169412Sscottl } 558175942Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 559175942Sscottl break; 560175942Sscottl case IOP_RESULT_BAD_TARGET: 561175942Sscottl ccb->ccb_h.status = CAM_DEV_NOT_THERE; 562175942Sscottl break; 563175942Sscottl case IOP_RESULT_BUSY: 564175942Sscottl ccb->ccb_h.status = CAM_BUSY; 565175942Sscottl break; 566175942Sscottl case IOP_RESULT_INVALID_REQUEST: 567175942Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 568175942Sscottl break; 569175942Sscottl case IOP_RESULT_FAIL: 570175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 571175942Sscottl break; 572175942Sscottl case IOP_RESULT_RESET: 573175942Sscottl ccb->ccb_h.status = CAM_BUSY; 574175942Sscottl break; 575175942Sscottl case IOP_RESULT_CHECK_CONDITION: 576175942Sscottl memcpy(&ccb->csio.sense_data, &req->sg_list, 577175942Sscottl MIN(req->dataxfer_length, sizeof(ccb->csio.sense_data))); 578175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 579175942Sscottl ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 580175942Sscottl ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 581175942Sscottl break; 582175942Sscottl default: 583175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 584175942Sscottl break; 585169412Sscottl } 586175942Sscottlscsi_done: 587175942Sscottl ccb->csio.resid = ccb->csio.dxfer_len - req->dataxfer_length; 588175942Sscottl 589175942Sscottl hptiop_free_srb(hba, srb); 590175942Sscottl xpt_done(ccb); 591175942Sscottl } else if (context & MVIOP_CMD_TYPE_IOCTL) { 592175942Sscottl struct hpt_iop_request_ioctl_command *req = hba->ctlcfg_ptr; 593175942Sscottl if (context & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT) 594175942Sscottl hba->config_done = 1; 595175942Sscottl else 596175942Sscottl hba->config_done = -1; 597175942Sscottl wakeup(req); 598175942Sscottl } else if (context & 599175942Sscottl (MVIOP_CMD_TYPE_SET_CONFIG | 600175942Sscottl MVIOP_CMD_TYPE_GET_CONFIG)) 601175942Sscottl hba->config_done = 1; 602175942Sscottl else { 603175942Sscottl device_printf(hba->pcidev, "wrong callback type\n"); 604175942Sscottl } 605175942Sscottl} 606175942Sscottl 607175942Sscottlstatic void hptiop_drain_outbound_queue_mv(struct hpt_iop_hba * hba) 608175942Sscottl{ 609175942Sscottl u_int64_t req; 610175942Sscottl 611175942Sscottl while ((req = hptiop_mv_outbound_read(hba))) { 612175942Sscottl if (req & MVIOP_MU_QUEUE_ADDR_HOST_BIT) { 613175942Sscottl if (req & MVIOP_MU_QUEUE_REQUEST_RETURN_CONTEXT) { 614175942Sscottl hptiop_request_callback_mv(hba, req); 615175942Sscottl } 616175942Sscottl } 617175942Sscottl } 618175942Sscottl} 619175942Sscottl 620175942Sscottlstatic int hptiop_intr_mv(struct hpt_iop_hba * hba) 621175942Sscottl{ 622175942Sscottl u_int32_t status; 623175942Sscottl int ret = 0; 624175942Sscottl 625175942Sscottl status = BUS_SPACE_RD4_MV0(outbound_doorbell); 626175942Sscottl 627175942Sscottl if (status) 628175942Sscottl BUS_SPACE_WRT4_MV0(outbound_doorbell, ~status); 629175942Sscottl 630175942Sscottl if (status & MVIOP_MU_OUTBOUND_INT_MSG) { 631175942Sscottl u_int32_t msg = BUS_SPACE_RD4_MV2(outbound_msg); 632175942Sscottl KdPrint(("hptiop: received outbound msg %x\n", msg)); 633175942Sscottl hptiop_os_message_callback(hba, msg); 634169412Sscottl ret = 1; 635169412Sscottl } 636175942Sscottl 637175942Sscottl if (status & MVIOP_MU_OUTBOUND_INT_POSTQUEUE) { 638175942Sscottl hptiop_drain_outbound_queue_mv(hba); 639175942Sscottl ret = 1; 640175942Sscottl } 641175942Sscottl 642169412Sscottl return ret; 643169412Sscottl} 644169412Sscottl 645175942Sscottlstatic int hptiop_send_sync_request_itl(struct hpt_iop_hba * hba, 646175942Sscottl u_int32_t req32, u_int32_t millisec) 647169412Sscottl{ 648169412Sscottl u_int32_t i; 649175942Sscottl u_int64_t temp64; 650169412Sscottl 651175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue, req32); 652175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 653169412Sscottl 654169412Sscottl for (i = 0; i < millisec; i++) { 655175942Sscottl hptiop_intr_itl(hba); 656175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h, req32 + 657175942Sscottl offsetof(struct hpt_iop_request_header, context), 658175942Sscottl (u_int32_t *)&temp64, 2); 659175942Sscottl if (temp64) 660169412Sscottl return 0; 661169412Sscottl DELAY(1000); 662169412Sscottl } 663169412Sscottl 664169412Sscottl return -1; 665169412Sscottl} 666169412Sscottl 667175942Sscottlstatic int hptiop_send_sync_request_mv(struct hpt_iop_hba *hba, 668175942Sscottl void *req, u_int32_t millisec) 669169412Sscottl{ 670169412Sscottl u_int32_t i; 671175942Sscottl u_int64_t phy_addr; 672175942Sscottl hba->config_done = 0; 673169412Sscottl 674175942Sscottl phy_addr = hba->ctlcfgcmd_phy | 675175942Sscottl (u_int64_t)MVIOP_MU_QUEUE_ADDR_HOST_BIT; 676175942Sscottl ((struct hpt_iop_request_get_config *)req)->header.flags |= 677175942Sscottl IOP_REQUEST_FLAG_SYNC_REQUEST | 678175942Sscottl IOP_REQUEST_FLAG_OUTPUT_CONTEXT; 679175942Sscottl hptiop_mv_inbound_write(phy_addr, hba); 680175942Sscottl BUS_SPACE_RD4_MV0(outbound_intmask); 681169412Sscottl 682175942Sscottl for (i = 0; i < millisec; i++) { 683175942Sscottl hptiop_intr_mv(hba); 684175942Sscottl if (hba->config_done) 685175942Sscottl return 0; 686175942Sscottl DELAY(1000); 687175942Sscottl } 688175942Sscottl return -1; 689175942Sscottl} 690169412Sscottl 691175942Sscottlstatic int hptiop_send_sync_msg(struct hpt_iop_hba *hba, 692175942Sscottl u_int32_t msg, u_int32_t millisec) 693175942Sscottl{ 694175942Sscottl u_int32_t i; 695169412Sscottl 696175942Sscottl hba->msg_done = 0; 697175942Sscottl hba->ops->post_msg(hba, msg); 698175942Sscottl 699175942Sscottl for (i=0; i<millisec; i++) { 700175942Sscottl hba->ops->iop_intr(hba); 701175942Sscottl if (hba->msg_done) 702169412Sscottl break; 703169412Sscottl DELAY(1000); 704169412Sscottl } 705169412Sscottl 706175942Sscottl return hba->msg_done? 0 : -1; 707169412Sscottl} 708169412Sscottl 709175942Sscottlstatic int hptiop_get_config_itl(struct hpt_iop_hba * hba, 710175942Sscottl struct hpt_iop_request_get_config * config) 711169412Sscottl{ 712175942Sscottl u_int32_t req32; 713169412Sscottl 714175942Sscottl config->header.size = sizeof(struct hpt_iop_request_get_config); 715175942Sscottl config->header.type = IOP_REQUEST_TYPE_GET_CONFIG; 716175942Sscottl config->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST; 717175942Sscottl config->header.result = IOP_RESULT_PENDING; 718175942Sscottl config->header.context = 0; 719175942Sscottl 720175942Sscottl req32 = BUS_SPACE_RD4_ITL(inbound_queue); 721175942Sscottl if (req32 == IOPMU_QUEUE_EMPTY) 722169412Sscottl return -1; 723169412Sscottl 724175942Sscottl bus_space_write_region_4(hba->bar0t, hba->bar0h, 725175942Sscottl req32, (u_int32_t *)config, 726175942Sscottl sizeof(struct hpt_iop_request_header) >> 2); 727175942Sscottl 728175942Sscottl if (hptiop_send_sync_request_itl(hba, req32, 20000)) { 729175942Sscottl KdPrint(("hptiop: get config send cmd failed")); 730175942Sscottl return -1; 731175942Sscottl } 732175942Sscottl 733175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h, 734175942Sscottl req32, (u_int32_t *)config, 735175942Sscottl sizeof(struct hpt_iop_request_get_config) >> 2); 736175942Sscottl 737175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req32); 738175942Sscottl 739175942Sscottl return 0; 740175942Sscottl} 741175942Sscottl 742175942Sscottlstatic int hptiop_get_config_mv(struct hpt_iop_hba * hba, 743175942Sscottl struct hpt_iop_request_get_config * config) 744175942Sscottl{ 745175942Sscottl struct hpt_iop_request_get_config *req; 746175942Sscottl 747175942Sscottl if (!(req = hba->ctlcfg_ptr)) 748175942Sscottl return -1; 749175942Sscottl 750169412Sscottl req->header.flags = 0; 751169412Sscottl req->header.type = IOP_REQUEST_TYPE_GET_CONFIG; 752169412Sscottl req->header.size = sizeof(struct hpt_iop_request_get_config); 753169412Sscottl req->header.result = IOP_RESULT_PENDING; 754175942Sscottl req->header.context = MVIOP_CMD_TYPE_GET_CONFIG; 755169412Sscottl 756175942Sscottl if (hptiop_send_sync_request_mv(hba, req, 20000)) { 757175942Sscottl KdPrint(("hptiop: get config send cmd failed")); 758169412Sscottl return -1; 759169412Sscottl } 760169412Sscottl 761169412Sscottl *config = *req; 762169412Sscottl return 0; 763169412Sscottl} 764169412Sscottl 765175942Sscottlstatic int hptiop_set_config_itl(struct hpt_iop_hba *hba, 766175942Sscottl struct hpt_iop_request_set_config *config) 767169412Sscottl{ 768169412Sscottl u_int32_t req32; 769169412Sscottl 770175942Sscottl req32 = BUS_SPACE_RD4_ITL(inbound_queue); 771175942Sscottl 772169412Sscottl if (req32 == IOPMU_QUEUE_EMPTY) 773169412Sscottl return -1; 774169412Sscottl 775175942Sscottl config->header.size = sizeof(struct hpt_iop_request_set_config); 776175942Sscottl config->header.type = IOP_REQUEST_TYPE_SET_CONFIG; 777175942Sscottl config->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST; 778175942Sscottl config->header.result = IOP_RESULT_PENDING; 779175942Sscottl config->header.context = 0; 780175942Sscottl 781175942Sscottl bus_space_write_region_4(hba->bar0t, hba->bar0h, req32, 782175942Sscottl (u_int32_t *)config, 783175942Sscottl sizeof(struct hpt_iop_request_set_config) >> 2); 784175942Sscottl 785175942Sscottl if (hptiop_send_sync_request_itl(hba, req32, 20000)) { 786175942Sscottl KdPrint(("hptiop: set config send cmd failed")); 787175942Sscottl return -1; 788175942Sscottl } 789175942Sscottl 790175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req32); 791175942Sscottl 792175942Sscottl return 0; 793175942Sscottl} 794175942Sscottl 795175942Sscottlstatic int hptiop_set_config_mv(struct hpt_iop_hba *hba, 796175942Sscottl struct hpt_iop_request_set_config *config) 797175942Sscottl{ 798175942Sscottl struct hpt_iop_request_set_config *req; 799175942Sscottl 800175942Sscottl if (!(req = hba->ctlcfg_ptr)) 801175942Sscottl return -1; 802175942Sscottl 803169412Sscottl memcpy((u_int8_t *)req + sizeof(struct hpt_iop_request_header), 804169412Sscottl (u_int8_t *)config + sizeof(struct hpt_iop_request_header), 805175942Sscottl sizeof(struct hpt_iop_request_set_config) - 806175942Sscottl sizeof(struct hpt_iop_request_header)); 807175942Sscottl 808169412Sscottl req->header.flags = 0; 809169412Sscottl req->header.type = IOP_REQUEST_TYPE_SET_CONFIG; 810169412Sscottl req->header.size = sizeof(struct hpt_iop_request_set_config); 811169412Sscottl req->header.result = IOP_RESULT_PENDING; 812175942Sscottl req->header.context = MVIOP_CMD_TYPE_SET_CONFIG; 813169412Sscottl 814175942Sscottl if (hptiop_send_sync_request_mv(hba, req, 20000)) { 815175942Sscottl KdPrint(("hptiop: set config send cmd failed")); 816169412Sscottl return -1; 817169412Sscottl } 818169412Sscottl 819169412Sscottl return 0; 820169412Sscottl} 821169412Sscottl 822175942Sscottlstatic int hptiop_post_ioctl_command_itl(struct hpt_iop_hba *hba, 823175942Sscottl u_int32_t req32, 824175942Sscottl struct hpt_iop_ioctl_param *pParams) 825169412Sscottl{ 826175942Sscottl u_int64_t temp64; 827175942Sscottl struct hpt_iop_request_ioctl_command req; 828169412Sscottl 829175942Sscottl if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) > 830175942Sscottl (hba->max_request_size - 831175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf))) { 832175942Sscottl device_printf(hba->pcidev, "request size beyond max value"); 833175942Sscottl return -1; 834175942Sscottl } 835175942Sscottl 836175942Sscottl req.header.size = offsetof(struct hpt_iop_request_ioctl_command, buf) 837175942Sscottl + pParams->nInBufferSize; 838175942Sscottl req.header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND; 839175942Sscottl req.header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST; 840175942Sscottl req.header.result = IOP_RESULT_PENDING; 841175942Sscottl req.header.context = req32 + (u_int64_t)(unsigned long)hba->u.itl.mu; 842175942Sscottl req.ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode); 843175942Sscottl req.inbuf_size = pParams->nInBufferSize; 844175942Sscottl req.outbuf_size = pParams->nOutBufferSize; 845175942Sscottl req.bytes_returned = 0; 846175942Sscottl 847175942Sscottl bus_space_write_region_4(hba->bar0t, hba->bar0h, req32, (u_int32_t *)&req, 848175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf)>>2); 849175942Sscottl 850175942Sscottl hptiop_lock_adapter(hba); 851175942Sscottl 852175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue, req32); 853175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 854175942Sscottl 855175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h, req32 + 856175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, header.context), 857175942Sscottl (u_int32_t *)&temp64, 2); 858175942Sscottl while (temp64) { 859175942Sscottl if (hptiop_sleep(hba, (void *)((unsigned long)hba->u.itl.mu + req32), 860175942Sscottl PPAUSE, "hptctl", HPT_OSM_TIMEOUT)==0) 861175942Sscottl break; 862175942Sscottl hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000); 863175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h,req32 + 864175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, 865175942Sscottl header.context), 866175942Sscottl (u_int32_t *)&temp64, 2); 867175942Sscottl } 868175942Sscottl 869175942Sscottl hptiop_unlock_adapter(hba); 870175942Sscottl return 0; 871175942Sscottl} 872175942Sscottl 873175942Sscottlstatic int hptiop_bus_space_copyin(struct hpt_iop_hba *hba, u_int32_t bus, void *user, int size) 874175942Sscottl{ 875175942Sscottl unsigned char byte; 876175942Sscottl int i; 877175942Sscottl 878175942Sscottl for (i=0; i<size; i++) { 879175942Sscottl if (copyin((u_int8_t *)user + i, &byte, 1)) 880175942Sscottl return -1; 881175942Sscottl bus_space_write_1(hba->bar0t, hba->bar0h, bus + i, byte); 882175942Sscottl } 883175942Sscottl 884175942Sscottl return 0; 885175942Sscottl} 886175942Sscottl 887175942Sscottlstatic int hptiop_bus_space_copyout(struct hpt_iop_hba *hba, u_int32_t bus, void *user, int size) 888175942Sscottl{ 889175942Sscottl unsigned char byte; 890175942Sscottl int i; 891175942Sscottl 892175942Sscottl for (i=0; i<size; i++) { 893175942Sscottl byte = bus_space_read_1(hba->bar0t, hba->bar0h, bus + i); 894175942Sscottl if (copyout(&byte, (u_int8_t *)user + i, 1)) 895175942Sscottl return -1; 896175942Sscottl } 897175942Sscottl 898175942Sscottl return 0; 899175942Sscottl} 900175942Sscottl 901175942Sscottlstatic int hptiop_do_ioctl_itl(struct hpt_iop_hba *hba, 902175942Sscottl struct hpt_iop_ioctl_param * pParams) 903175942Sscottl{ 904175942Sscottl u_int32_t req32; 905175942Sscottl u_int32_t result; 906175942Sscottl 907169412Sscottl if ((pParams->Magic != HPT_IOCTL_MAGIC) && 908169412Sscottl (pParams->Magic != HPT_IOCTL_MAGIC32)) 909169412Sscottl return EFAULT; 910175942Sscottl 911175942Sscottl req32 = BUS_SPACE_RD4_ITL(inbound_queue); 912175942Sscottl if (req32 == IOPMU_QUEUE_EMPTY) 913169412Sscottl return EFAULT; 914169412Sscottl 915169412Sscottl if (pParams->nInBufferSize) 916175942Sscottl if (hptiop_bus_space_copyin(hba, req32 + 917175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf), 918175942Sscottl (void *)pParams->lpInBuffer, pParams->nInBufferSize)) 919169412Sscottl goto invalid; 920169412Sscottl 921175942Sscottl if (hptiop_post_ioctl_command_itl(hba, req32, pParams)) 922169412Sscottl goto invalid; 923169412Sscottl 924175942Sscottl result = bus_space_read_4(hba->bar0t, hba->bar0h, req32 + 925175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, 926175942Sscottl header.result)); 927175942Sscottl 928175942Sscottl if (result == IOP_RESULT_SUCCESS) { 929169412Sscottl if (pParams->nOutBufferSize) 930175942Sscottl if (hptiop_bus_space_copyout(hba, req32 + 931175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf) + 932169412Sscottl ((pParams->nInBufferSize + 3) & ~3), 933175942Sscottl (void *)pParams->lpOutBuffer, pParams->nOutBufferSize)) 934169412Sscottl goto invalid; 935169412Sscottl 936175942Sscottl if (pParams->lpBytesReturned) { 937175942Sscottl if (hptiop_bus_space_copyout(hba, req32 + 938175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, bytes_returned), 939175942Sscottl (void *)pParams->lpBytesReturned, sizeof(unsigned long))) 940169412Sscottl goto invalid; 941175942Sscottl } 942175942Sscottl 943175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req32); 944175942Sscottl 945169412Sscottl return 0; 946169412Sscottl } else{ 947169412Sscottlinvalid: 948175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req32); 949175942Sscottl 950169412Sscottl return EFAULT; 951169412Sscottl } 952169412Sscottl} 953169412Sscottl 954175942Sscottlstatic int hptiop_post_ioctl_command_mv(struct hpt_iop_hba *hba, 955175942Sscottl struct hpt_iop_request_ioctl_command *req, 956175942Sscottl struct hpt_iop_ioctl_param *pParams) 957169412Sscottl{ 958175942Sscottl u_int64_t req_phy; 959175942Sscottl int size = 0; 960175942Sscottl 961175942Sscottl if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) > 962175942Sscottl (hba->max_request_size - 963175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf))) { 964175942Sscottl device_printf(hba->pcidev, "request size beyond max value"); 965169412Sscottl return -1; 966169412Sscottl } 967169412Sscottl 968169412Sscottl req->ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode); 969169412Sscottl req->inbuf_size = pParams->nInBufferSize; 970169412Sscottl req->outbuf_size = pParams->nOutBufferSize; 971175942Sscottl req->header.size = offsetof(struct hpt_iop_request_ioctl_command, buf) 972175942Sscottl + pParams->nInBufferSize; 973175942Sscottl req->header.context = (u_int64_t)MVIOP_CMD_TYPE_IOCTL; 974169412Sscottl req->header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND; 975169412Sscottl req->header.result = IOP_RESULT_PENDING; 976175942Sscottl req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT; 977175942Sscottl size = req->header.size >> 8; 978175942Sscottl size = size > 3 ? 3 : size; 979175942Sscottl req_phy = hba->ctlcfgcmd_phy | MVIOP_MU_QUEUE_ADDR_HOST_BIT | size; 980175942Sscottl hptiop_mv_inbound_write(req_phy, hba); 981169412Sscottl 982175942Sscottl BUS_SPACE_RD4_MV0(outbound_intmask); 983169412Sscottl 984175942Sscottl while (hba->config_done == 0) { 985175942Sscottl if (hptiop_sleep(hba, req, PPAUSE, 986175942Sscottl "hptctl", HPT_OSM_TIMEOUT)==0) 987175942Sscottl continue; 988175942Sscottl hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000); 989169412Sscottl } 990169412Sscottl return 0; 991169412Sscottl} 992169412Sscottl 993175942Sscottlstatic int hptiop_do_ioctl_mv(struct hpt_iop_hba *hba, 994175942Sscottl struct hpt_iop_ioctl_param *pParams) 995175942Sscottl{ 996175942Sscottl struct hpt_iop_request_ioctl_command *req; 997175942Sscottl 998175942Sscottl if ((pParams->Magic != HPT_IOCTL_MAGIC) && 999175942Sscottl (pParams->Magic != HPT_IOCTL_MAGIC32)) 1000175942Sscottl return EFAULT; 1001175942Sscottl 1002175942Sscottl req = (struct hpt_iop_request_ioctl_command *)(hba->ctlcfg_ptr); 1003175942Sscottl hba->config_done = 0; 1004175942Sscottl hptiop_lock_adapter(hba); 1005175942Sscottl if (pParams->nInBufferSize) 1006175942Sscottl if (copyin((void *)pParams->lpInBuffer, 1007175942Sscottl req->buf, pParams->nInBufferSize)) 1008175942Sscottl goto invalid; 1009175942Sscottl if (hptiop_post_ioctl_command_mv(hba, req, pParams)) 1010175942Sscottl goto invalid; 1011175942Sscottl 1012175942Sscottl if (hba->config_done == 1) { 1013175942Sscottl if (pParams->nOutBufferSize) 1014175942Sscottl if (copyout(req->buf + 1015175942Sscottl ((pParams->nInBufferSize + 3) & ~3), 1016175942Sscottl (void *)pParams->lpOutBuffer, 1017175942Sscottl pParams->nOutBufferSize)) 1018175942Sscottl goto invalid; 1019175942Sscottl 1020175942Sscottl if (pParams->lpBytesReturned) 1021175942Sscottl if (copyout(&req->bytes_returned, 1022175942Sscottl (void*)pParams->lpBytesReturned, 1023175942Sscottl sizeof(u_int32_t))) 1024175942Sscottl goto invalid; 1025175942Sscottl hptiop_unlock_adapter(hba); 1026175942Sscottl return 0; 1027175942Sscottl } else{ 1028175942Sscottlinvalid: 1029175942Sscottl hptiop_unlock_adapter(hba); 1030175942Sscottl return EFAULT; 1031175942Sscottl } 1032175942Sscottl} 1033175942Sscottl 1034169412Sscottlstatic int hptiop_rescan_bus(struct hpt_iop_hba * hba) 1035169412Sscottl{ 1036169412Sscottl union ccb *ccb; 1037203108Smav 1038203108Smav if ((ccb = xpt_alloc_ccb()) == NULL) 1039203108Smav return(ENOMEM); 1040203108Smav if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(hba->sim), 1041203108Smav CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 1042203108Smav xpt_free_ccb(ccb); 1043169412Sscottl return(EIO); 1044203108Smav } 1045203108Smav xpt_rescan(ccb); 1046169412Sscottl return(0); 1047169412Sscottl} 1048169412Sscottl 1049169412Sscottlstatic bus_dmamap_callback_t hptiop_map_srb; 1050169412Sscottlstatic bus_dmamap_callback_t hptiop_post_scsi_command; 1051175942Sscottlstatic bus_dmamap_callback_t hptiop_mv_map_ctlcfg; 1052169412Sscottl 1053175942Sscottlstatic int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba) 1054175942Sscottl{ 1055175942Sscottl hba->bar0_rid = 0x10; 1056175942Sscottl hba->bar0_res = bus_alloc_resource_any(hba->pcidev, 1057175942Sscottl SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE); 1058175942Sscottl 1059175942Sscottl if (hba->bar0_res == NULL) { 1060175942Sscottl device_printf(hba->pcidev, 1061175942Sscottl "failed to get iop base adrress.\n"); 1062175942Sscottl return -1; 1063175942Sscottl } 1064175942Sscottl hba->bar0t = rman_get_bustag(hba->bar0_res); 1065175942Sscottl hba->bar0h = rman_get_bushandle(hba->bar0_res); 1066175942Sscottl hba->u.itl.mu = (struct hpt_iopmu_itl *) 1067175942Sscottl rman_get_virtual(hba->bar0_res); 1068175942Sscottl 1069175942Sscottl if (!hba->u.itl.mu) { 1070175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1071175942Sscottl hba->bar0_rid, hba->bar0_res); 1072175942Sscottl device_printf(hba->pcidev, "alloc mem res failed\n"); 1073175942Sscottl return -1; 1074175942Sscottl } 1075175942Sscottl 1076175942Sscottl return 0; 1077175942Sscottl} 1078175942Sscottl 1079175942Sscottlstatic int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba) 1080175942Sscottl{ 1081175942Sscottl hba->bar0_rid = 0x10; 1082175942Sscottl hba->bar0_res = bus_alloc_resource_any(hba->pcidev, 1083175942Sscottl SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE); 1084175942Sscottl 1085175942Sscottl if (hba->bar0_res == NULL) { 1086175942Sscottl device_printf(hba->pcidev, "failed to get iop bar0.\n"); 1087175942Sscottl return -1; 1088175942Sscottl } 1089175942Sscottl hba->bar0t = rman_get_bustag(hba->bar0_res); 1090175942Sscottl hba->bar0h = rman_get_bushandle(hba->bar0_res); 1091175942Sscottl hba->u.mv.regs = (struct hpt_iopmv_regs *) 1092175942Sscottl rman_get_virtual(hba->bar0_res); 1093175942Sscottl 1094175942Sscottl if (!hba->u.mv.regs) { 1095175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1096175942Sscottl hba->bar0_rid, hba->bar0_res); 1097175942Sscottl device_printf(hba->pcidev, "alloc bar0 mem res failed\n"); 1098175942Sscottl return -1; 1099175942Sscottl } 1100175942Sscottl 1101175942Sscottl hba->bar2_rid = 0x18; 1102175942Sscottl hba->bar2_res = bus_alloc_resource_any(hba->pcidev, 1103175942Sscottl SYS_RES_MEMORY, &hba->bar2_rid, RF_ACTIVE); 1104175942Sscottl 1105175942Sscottl if (hba->bar2_res == NULL) { 1106175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1107175942Sscottl hba->bar0_rid, hba->bar0_res); 1108175942Sscottl device_printf(hba->pcidev, "failed to get iop bar2.\n"); 1109175942Sscottl return -1; 1110175942Sscottl } 1111175942Sscottl 1112175942Sscottl hba->bar2t = rman_get_bustag(hba->bar2_res); 1113175942Sscottl hba->bar2h = rman_get_bushandle(hba->bar2_res); 1114175942Sscottl hba->u.mv.mu = (struct hpt_iopmu_mv *)rman_get_virtual(hba->bar2_res); 1115175942Sscottl 1116175942Sscottl if (!hba->u.mv.mu) { 1117175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1118175942Sscottl hba->bar0_rid, hba->bar0_res); 1119175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1120175942Sscottl hba->bar2_rid, hba->bar2_res); 1121175942Sscottl device_printf(hba->pcidev, "alloc mem bar2 res failed\n"); 1122175942Sscottl return -1; 1123175942Sscottl } 1124175942Sscottl 1125175942Sscottl return 0; 1126175942Sscottl} 1127175942Sscottl 1128175942Sscottlstatic void hptiop_release_pci_res_itl(struct hpt_iop_hba *hba) 1129175942Sscottl{ 1130175942Sscottl if (hba->bar0_res) 1131175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1132175942Sscottl hba->bar0_rid, hba->bar0_res); 1133175942Sscottl} 1134175942Sscottl 1135175942Sscottlstatic void hptiop_release_pci_res_mv(struct hpt_iop_hba *hba) 1136175942Sscottl{ 1137175942Sscottl if (hba->bar0_res) 1138175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1139175942Sscottl hba->bar0_rid, hba->bar0_res); 1140175942Sscottl if (hba->bar2_res) 1141175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1142175942Sscottl hba->bar2_rid, hba->bar2_res); 1143175942Sscottl} 1144175942Sscottl 1145175942Sscottlstatic int hptiop_internal_memalloc_mv(struct hpt_iop_hba *hba) 1146175942Sscottl{ 1147175942Sscottl if (bus_dma_tag_create(hba->parent_dmat, 1148175942Sscottl 1, 1149175942Sscottl 0, 1150175942Sscottl BUS_SPACE_MAXADDR_32BIT, 1151175942Sscottl BUS_SPACE_MAXADDR, 1152175942Sscottl NULL, NULL, 1153175942Sscottl 0x800 - 0x8, 1154175942Sscottl 1, 1155175942Sscottl BUS_SPACE_MAXSIZE_32BIT, 1156175942Sscottl BUS_DMA_ALLOCNOW, 1157175942Sscottl#if __FreeBSD_version > 502000 1158175942Sscottl NULL, 1159175942Sscottl NULL, 1160175942Sscottl#endif 1161175942Sscottl &hba->ctlcfg_dmat)) { 1162175942Sscottl device_printf(hba->pcidev, "alloc ctlcfg_dmat failed\n"); 1163175942Sscottl return -1; 1164175942Sscottl } 1165175942Sscottl 1166175942Sscottl if (bus_dmamem_alloc(hba->ctlcfg_dmat, (void **)&hba->ctlcfg_ptr, 1167175942Sscottl#if __FreeBSD_version>501000 1168175942Sscottl BUS_DMA_WAITOK | BUS_DMA_COHERENT, 1169175942Sscottl#else 1170175942Sscottl BUS_DMA_WAITOK, 1171175942Sscottl#endif 1172175942Sscottl &hba->ctlcfg_dmamap) != 0) { 1173175942Sscottl device_printf(hba->pcidev, 1174175942Sscottl "bus_dmamem_alloc failed!\n"); 1175175942Sscottl bus_dma_tag_destroy(hba->ctlcfg_dmat); 1176175942Sscottl return -1; 1177175942Sscottl } 1178175942Sscottl 1179175942Sscottl if (bus_dmamap_load(hba->ctlcfg_dmat, 1180175942Sscottl hba->ctlcfg_dmamap, hba->ctlcfg_ptr, 1181175942Sscottl MVIOP_IOCTLCFG_SIZE, 1182175942Sscottl hptiop_mv_map_ctlcfg, hba, 0)) { 1183175942Sscottl device_printf(hba->pcidev, "bus_dmamap_load failed!\n"); 1184175942Sscottl if (hba->ctlcfg_dmat) 1185175942Sscottl bus_dmamem_free(hba->ctlcfg_dmat, 1186175942Sscottl hba->ctlcfg_ptr, hba->ctlcfg_dmamap); 1187175942Sscottl bus_dma_tag_destroy(hba->ctlcfg_dmat); 1188175942Sscottl return -1; 1189175942Sscottl } 1190175942Sscottl 1191175942Sscottl return 0; 1192175942Sscottl} 1193175942Sscottl 1194175942Sscottlstatic int hptiop_internal_memfree_mv(struct hpt_iop_hba *hba) 1195175942Sscottl{ 1196175942Sscottl if (hba->ctlcfg_dmat) { 1197175942Sscottl bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap); 1198175942Sscottl bus_dmamem_free(hba->ctlcfg_dmat, 1199175942Sscottl hba->ctlcfg_ptr, hba->ctlcfg_dmamap); 1200175942Sscottl bus_dma_tag_destroy(hba->ctlcfg_dmat); 1201175942Sscottl } 1202175942Sscottl 1203175942Sscottl return 0; 1204175942Sscottl} 1205175942Sscottl 1206169412Sscottl/* 1207169412Sscottl * CAM driver interface 1208169412Sscottl */ 1209169412Sscottlstatic device_method_t driver_methods[] = { 1210169412Sscottl /* Device interface */ 1211169412Sscottl DEVMETHOD(device_probe, hptiop_probe), 1212169412Sscottl DEVMETHOD(device_attach, hptiop_attach), 1213169412Sscottl DEVMETHOD(device_detach, hptiop_detach), 1214169412Sscottl DEVMETHOD(device_shutdown, hptiop_shutdown), 1215169412Sscottl { 0, 0 } 1216169412Sscottl}; 1217169412Sscottl 1218175942Sscottlstatic struct hptiop_adapter_ops hptiop_itl_ops = { 1219175942Sscottl .iop_wait_ready = hptiop_wait_ready_itl, 1220175942Sscottl .internal_memalloc = 0, 1221175942Sscottl .internal_memfree = 0, 1222175942Sscottl .alloc_pci_res = hptiop_alloc_pci_res_itl, 1223175942Sscottl .release_pci_res = hptiop_release_pci_res_itl, 1224175942Sscottl .enable_intr = hptiop_enable_intr_itl, 1225175942Sscottl .disable_intr = hptiop_disable_intr_itl, 1226175942Sscottl .get_config = hptiop_get_config_itl, 1227175942Sscottl .set_config = hptiop_set_config_itl, 1228175942Sscottl .iop_intr = hptiop_intr_itl, 1229175942Sscottl .post_msg = hptiop_post_msg_itl, 1230175942Sscottl .post_req = hptiop_post_req_itl, 1231175942Sscottl .do_ioctl = hptiop_do_ioctl_itl, 1232175942Sscottl}; 1233175942Sscottl 1234175942Sscottlstatic struct hptiop_adapter_ops hptiop_mv_ops = { 1235175942Sscottl .iop_wait_ready = hptiop_wait_ready_mv, 1236175942Sscottl .internal_memalloc = hptiop_internal_memalloc_mv, 1237175942Sscottl .internal_memfree = hptiop_internal_memfree_mv, 1238175942Sscottl .alloc_pci_res = hptiop_alloc_pci_res_mv, 1239175942Sscottl .release_pci_res = hptiop_release_pci_res_mv, 1240175942Sscottl .enable_intr = hptiop_enable_intr_mv, 1241175942Sscottl .disable_intr = hptiop_disable_intr_mv, 1242175942Sscottl .get_config = hptiop_get_config_mv, 1243175942Sscottl .set_config = hptiop_set_config_mv, 1244175942Sscottl .iop_intr = hptiop_intr_mv, 1245175942Sscottl .post_msg = hptiop_post_msg_mv, 1246175942Sscottl .post_req = hptiop_post_req_mv, 1247175942Sscottl .do_ioctl = hptiop_do_ioctl_mv, 1248175942Sscottl}; 1249175942Sscottl 1250169412Sscottlstatic driver_t hptiop_pci_driver = { 1251169412Sscottl driver_name, 1252169412Sscottl driver_methods, 1253169412Sscottl sizeof(struct hpt_iop_hba) 1254169412Sscottl}; 1255169412Sscottl 1256169412SscottlDRIVER_MODULE(hptiop, pci, hptiop_pci_driver, hptiop_devclass, 0, 0); 1257169412Sscottl 1258169412Sscottlstatic int hptiop_probe(device_t dev) 1259169412Sscottl{ 1260169412Sscottl struct hpt_iop_hba *hba; 1261175942Sscottl u_int32_t id; 1262175942Sscottl static char buf[256]; 1263175942Sscottl int sas = 0; 1264175942Sscottl struct hptiop_adapter_ops *ops; 1265169412Sscottl 1266175942Sscottl if (pci_get_vendor(dev) != 0x1103) 1267175942Sscottl return (ENXIO); 1268175942Sscottl 1269175942Sscottl id = pci_get_device(dev); 1270175942Sscottl 1271175942Sscottl switch (id) { 1272175942Sscottl case 0x4320: 1273175942Sscottl sas = 1; 1274175942Sscottl case 0x3220: 1275175942Sscottl case 0x3320: 1276175942Sscottl case 0x3410: 1277175942Sscottl case 0x3520: 1278175942Sscottl case 0x3510: 1279175942Sscottl case 0x3511: 1280175942Sscottl case 0x3521: 1281175942Sscottl case 0x3522: 1282175942Sscottl case 0x3540: 1283175942Sscottl ops = &hptiop_itl_ops; 1284175942Sscottl break; 1285175942Sscottl case 0x3120: 1286175942Sscottl case 0x3122: 1287175942Sscottl case 0x3020: 1288175942Sscottl ops = &hptiop_mv_ops; 1289175942Sscottl break; 1290175942Sscottl default: 1291175942Sscottl return (ENXIO); 1292169412Sscottl } 1293175942Sscottl 1294175942Sscottl device_printf(dev, "adapter at PCI %d:%d:%d, IRQ %d\n", 1295175942Sscottl pci_get_bus(dev), pci_get_slot(dev), 1296175942Sscottl pci_get_function(dev), pci_get_irq(dev)); 1297175942Sscottl 1298175942Sscottl sprintf(buf, "RocketRAID %x %s Controller\n", 1299175942Sscottl id, sas ? "SAS" : "SATA"); 1300175942Sscottl device_set_desc_copy(dev, buf); 1301175942Sscottl 1302175942Sscottl hba = (struct hpt_iop_hba *)device_get_softc(dev); 1303175942Sscottl bzero(hba, sizeof(struct hpt_iop_hba)); 1304175942Sscottl hba->ops = ops; 1305175942Sscottl 1306175942Sscottl KdPrint(("hba->ops=%p\n", hba->ops)); 1307175942Sscottl return 0; 1308169412Sscottl} 1309169412Sscottl 1310169412Sscottlstatic int hptiop_attach(device_t dev) 1311169412Sscottl{ 1312175942Sscottl struct hpt_iop_hba *hba = (struct hpt_iop_hba *)device_get_softc(dev); 1313169412Sscottl struct hpt_iop_request_get_config iop_config; 1314169412Sscottl struct hpt_iop_request_set_config set_config; 1315169412Sscottl int rid = 0; 1316169412Sscottl struct cam_devq *devq; 1317169412Sscottl struct ccb_setasync ccb; 1318169412Sscottl u_int32_t unit = device_get_unit(dev); 1319169412Sscottl 1320175942Sscottl device_printf(dev, "%d RocketRAID 3xxx/4xxx controller driver %s\n", 1321175942Sscottl unit, driver_version); 1322169412Sscottl 1323175942Sscottl KdPrint(("hptiop: attach(%d, %d/%d/%d) ops=%p\n", unit, 1324175942Sscottl pci_get_bus(dev), pci_get_slot(dev), 1325175942Sscottl pci_get_function(dev), hba->ops)); 1326175942Sscottl 1327169412Sscottl#if __FreeBSD_version >=440000 1328169412Sscottl pci_enable_busmaster(dev); 1329169412Sscottl#endif 1330169412Sscottl hba->pcidev = dev; 1331169412Sscottl hba->pciunit = unit; 1332169412Sscottl 1333175942Sscottl if (hba->ops->alloc_pci_res(hba)) 1334169412Sscottl return ENXIO; 1335169412Sscottl 1336175942Sscottl if (hba->ops->iop_wait_ready(hba, 2000)) { 1337175942Sscottl device_printf(dev, "adapter is not ready\n"); 1338175942Sscottl goto release_pci_res; 1339169412Sscottl } 1340169412Sscottl 1341169412Sscottl#if (__FreeBSD_version >= 500000) 1342169412Sscottl mtx_init(&hba->lock, "hptioplock", NULL, MTX_DEF); 1343169412Sscottl#endif 1344169412Sscottl 1345169412Sscottl if (bus_dma_tag_create(NULL,/* parent */ 1346169412Sscottl 1, /* alignment */ 1347169412Sscottl 0, /* boundary */ 1348169412Sscottl BUS_SPACE_MAXADDR, /* lowaddr */ 1349169412Sscottl BUS_SPACE_MAXADDR, /* highaddr */ 1350169412Sscottl NULL, NULL, /* filter, filterarg */ 1351169412Sscottl BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 1352169412Sscottl BUS_SPACE_UNRESTRICTED, /* nsegments */ 1353169412Sscottl BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 1354169412Sscottl 0, /* flags */ 1355169412Sscottl#if __FreeBSD_version>502000 1356169412Sscottl NULL, /* lockfunc */ 1357169412Sscottl NULL, /* lockfuncarg */ 1358169412Sscottl#endif 1359169412Sscottl &hba->parent_dmat /* tag */)) 1360169412Sscottl { 1361175942Sscottl device_printf(dev, "alloc parent_dmat failed\n"); 1362175942Sscottl goto release_pci_res; 1363169412Sscottl } 1364169412Sscottl 1365175942Sscottl if (hba->ops->internal_memalloc) { 1366175942Sscottl if (hba->ops->internal_memalloc(hba)) { 1367175942Sscottl device_printf(dev, "alloc srb_dmat failed\n"); 1368175942Sscottl goto destroy_parent_tag; 1369175942Sscottl } 1370175942Sscottl } 1371175942Sscottl 1372175942Sscottl if (hba->ops->get_config(hba, &iop_config)) { 1373175942Sscottl device_printf(dev, "get iop config failed.\n"); 1374175942Sscottl goto get_config_failed; 1375175942Sscottl } 1376175942Sscottl 1377175942Sscottl hba->firmware_version = iop_config.firmware_version; 1378175942Sscottl hba->interface_version = iop_config.interface_version; 1379175942Sscottl hba->max_requests = iop_config.max_requests; 1380175942Sscottl hba->max_devices = iop_config.max_devices; 1381175942Sscottl hba->max_request_size = iop_config.request_size; 1382175942Sscottl hba->max_sg_count = iop_config.max_sg_count; 1383175942Sscottl 1384169412Sscottl if (bus_dma_tag_create(hba->parent_dmat,/* parent */ 1385169412Sscottl 4, /* alignment */ 1386169412Sscottl BUS_SPACE_MAXADDR_32BIT+1, /* boundary */ 1387169412Sscottl BUS_SPACE_MAXADDR, /* lowaddr */ 1388169412Sscottl BUS_SPACE_MAXADDR, /* highaddr */ 1389169412Sscottl NULL, NULL, /* filter, filterarg */ 1390169412Sscottl PAGE_SIZE * (hba->max_sg_count-1), /* maxsize */ 1391169412Sscottl hba->max_sg_count, /* nsegments */ 1392169412Sscottl 0x20000, /* maxsegsize */ 1393169412Sscottl BUS_DMA_ALLOCNOW, /* flags */ 1394169412Sscottl#if __FreeBSD_version>502000 1395169412Sscottl busdma_lock_mutex, /* lockfunc */ 1396169412Sscottl &hba->lock, /* lockfuncarg */ 1397169412Sscottl#endif 1398169412Sscottl &hba->io_dmat /* tag */)) 1399169412Sscottl { 1400175942Sscottl device_printf(dev, "alloc io_dmat failed\n"); 1401175942Sscottl goto get_config_failed; 1402169412Sscottl } 1403169412Sscottl 1404169412Sscottl if (bus_dma_tag_create(hba->parent_dmat,/* parent */ 1405169412Sscottl 1, /* alignment */ 1406169412Sscottl 0, /* boundary */ 1407169412Sscottl BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 1408169412Sscottl BUS_SPACE_MAXADDR, /* highaddr */ 1409169412Sscottl NULL, NULL, /* filter, filterarg */ 1410169412Sscottl HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE + 0x20, 1411169412Sscottl 1, /* nsegments */ 1412169412Sscottl BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 1413169412Sscottl 0, /* flags */ 1414169412Sscottl#if __FreeBSD_version>502000 1415169412Sscottl NULL, /* lockfunc */ 1416169412Sscottl NULL, /* lockfuncarg */ 1417169412Sscottl#endif 1418169412Sscottl &hba->srb_dmat /* tag */)) 1419169412Sscottl { 1420175942Sscottl device_printf(dev, "alloc srb_dmat failed\n"); 1421175942Sscottl goto destroy_io_dmat; 1422169412Sscottl } 1423169412Sscottl 1424169412Sscottl if (bus_dmamem_alloc(hba->srb_dmat, (void **)&hba->uncached_ptr, 1425169412Sscottl#if __FreeBSD_version>501000 1426175942Sscottl BUS_DMA_WAITOK | BUS_DMA_COHERENT, 1427169412Sscottl#else 1428175942Sscottl BUS_DMA_WAITOK, 1429169412Sscottl#endif 1430175942Sscottl &hba->srb_dmamap) != 0) 1431169412Sscottl { 1432175942Sscottl device_printf(dev, "srb bus_dmamem_alloc failed!\n"); 1433175942Sscottl goto destroy_srb_dmat; 1434169412Sscottl } 1435169412Sscottl 1436169412Sscottl if (bus_dmamap_load(hba->srb_dmat, 1437169412Sscottl hba->srb_dmamap, hba->uncached_ptr, 1438169412Sscottl (HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE) + 0x20, 1439169412Sscottl hptiop_map_srb, hba, 0)) 1440169412Sscottl { 1441175942Sscottl device_printf(dev, "bus_dmamap_load failed!\n"); 1442175942Sscottl goto srb_dmamem_free; 1443169412Sscottl } 1444169412Sscottl 1445169412Sscottl if ((devq = cam_simq_alloc(hba->max_requests - 1 )) == NULL) { 1446175942Sscottl device_printf(dev, "cam_simq_alloc failed\n"); 1447175942Sscottl goto srb_dmamap_unload; 1448169412Sscottl } 1449175942Sscottl 1450175942Sscottl#if __FreeBSD_version <700000 1451169412Sscottl hba->sim = cam_sim_alloc(hptiop_action, hptiop_poll, driver_name, 1452175942Sscottl hba, unit, hba->max_requests - 1, 1, devq); 1453175942Sscottl#else 1454175942Sscottl hba->sim = cam_sim_alloc(hptiop_action, hptiop_poll, driver_name, 1455169412Sscottl hba, unit, &Giant, hba->max_requests - 1, 1, devq); 1456175942Sscottl#endif 1457169412Sscottl if (!hba->sim) { 1458175942Sscottl device_printf(dev, "cam_sim_alloc failed\n"); 1459169412Sscottl cam_simq_free(devq); 1460175942Sscottl goto srb_dmamap_unload; 1461169412Sscottl } 1462175942Sscottl#if __FreeBSD_version <700000 1463175942Sscottl if (xpt_bus_register(hba->sim, 0) != CAM_SUCCESS) 1464175942Sscottl#else 1465175942Sscottl if (xpt_bus_register(hba->sim, dev, 0) != CAM_SUCCESS) 1466175942Sscottl#endif 1467175942Sscottl { 1468175942Sscottl device_printf(dev, "xpt_bus_register failed\n"); 1469175942Sscottl goto free_cam_sim; 1470169412Sscottl } 1471169412Sscottl 1472169412Sscottl if (xpt_create_path(&hba->path, /*periph */ NULL, 1473169412Sscottl cam_sim_path(hba->sim), CAM_TARGET_WILDCARD, 1474175942Sscottl CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 1475175942Sscottl device_printf(dev, "xpt_create_path failed\n"); 1476175942Sscottl goto deregister_xpt_bus; 1477169412Sscottl } 1478169412Sscottl 1479169412Sscottl bzero(&set_config, sizeof(set_config)); 1480175942Sscottl set_config.iop_id = unit; 1481169412Sscottl set_config.vbus_id = cam_sim_path(hba->sim); 1482169412Sscottl set_config.max_host_request_size = HPT_SRB_MAX_REQ_SIZE; 1483169412Sscottl 1484175942Sscottl if (hba->ops->set_config(hba, &set_config)) { 1485175942Sscottl device_printf(dev, "set iop config failed.\n"); 1486175942Sscottl goto free_hba_path; 1487169412Sscottl } 1488169412Sscottl 1489169412Sscottl xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5); 1490169412Sscottl ccb.ccb_h.func_code = XPT_SASYNC_CB; 1491169412Sscottl ccb.event_enable = (AC_FOUND_DEVICE | AC_LOST_DEVICE); 1492169412Sscottl ccb.callback = hptiop_async; 1493169412Sscottl ccb.callback_arg = hba->sim; 1494169412Sscottl xpt_action((union ccb *)&ccb); 1495169412Sscottl 1496169412Sscottl rid = 0; 1497169412Sscottl if ((hba->irq_res = bus_alloc_resource(hba->pcidev, SYS_RES_IRQ, 1498169412Sscottl &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) { 1499175942Sscottl device_printf(dev, "allocate irq failed!\n"); 1500175942Sscottl goto free_hba_path; 1501169412Sscottl } 1502169412Sscottl 1503175942Sscottl#if __FreeBSD_version <700000 1504169412Sscottl if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM, 1505175942Sscottl hptiop_pci_intr, hba, &hba->irq_handle)) 1506175942Sscottl#else 1507175942Sscottl if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM, 1508175942Sscottl NULL, hptiop_pci_intr, hba, &hba->irq_handle)) 1509175942Sscottl#endif 1510175942Sscottl { 1511175942Sscottl device_printf(dev, "allocate intr function failed!\n"); 1512175942Sscottl goto free_irq_resource; 1513169412Sscottl } 1514169412Sscottl 1515175942Sscottl if (hptiop_send_sync_msg(hba, 1516175942Sscottl IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) { 1517175942Sscottl device_printf(dev, "fail to start background task\n"); 1518175942Sscottl goto teartown_irq_resource; 1519169412Sscottl } 1520169412Sscottl 1521175942Sscottl hba->ops->enable_intr(hba); 1522175942Sscottl 1523169412Sscottl hba->ioctl_dev = make_dev(&hptiop_cdevsw, unit, 1524169412Sscottl UID_ROOT, GID_WHEEL /*GID_OPERATOR*/, 1525169412Sscottl S_IRUSR | S_IWUSR, "%s%d", driver_name, unit); 1526169412Sscottl 1527169412Sscottl#if __FreeBSD_version < 503000 1528169412Sscottl hba->ioctl_dev->si_drv1 = hba; 1529169412Sscottl#endif 1530169412Sscottl 1531169412Sscottl return 0; 1532175942Sscottl 1533175942Sscottl 1534175942Sscottlteartown_irq_resource: 1535175942Sscottl bus_teardown_intr(dev, hba->irq_res, hba->irq_handle); 1536175942Sscottl 1537175942Sscottlfree_irq_resource: 1538175942Sscottl bus_release_resource(dev, SYS_RES_IRQ, 0, hba->irq_res); 1539175942Sscottl 1540175942Sscottlfree_hba_path: 1541175942Sscottl xpt_free_path(hba->path); 1542175942Sscottl 1543175942Sscottlderegister_xpt_bus: 1544175942Sscottl xpt_bus_deregister(cam_sim_path(hba->sim)); 1545175942Sscottl 1546175942Sscottlfree_cam_sim: 1547175942Sscottl cam_sim_free(hba->sim, /*free devq*/ TRUE); 1548175942Sscottl 1549175942Sscottlsrb_dmamap_unload: 1550175942Sscottl if (hba->uncached_ptr) 1551175942Sscottl bus_dmamap_unload(hba->srb_dmat, hba->srb_dmamap); 1552175942Sscottl 1553175942Sscottlsrb_dmamem_free: 1554175942Sscottl if (hba->uncached_ptr) 1555175942Sscottl bus_dmamem_free(hba->srb_dmat, 1556175942Sscottl hba->uncached_ptr, hba->srb_dmamap); 1557175942Sscottl 1558175942Sscottldestroy_srb_dmat: 1559175942Sscottl if (hba->srb_dmat) 1560175942Sscottl bus_dma_tag_destroy(hba->srb_dmat); 1561175942Sscottl 1562175942Sscottldestroy_io_dmat: 1563175942Sscottl if (hba->io_dmat) 1564175942Sscottl bus_dma_tag_destroy(hba->io_dmat); 1565175942Sscottl 1566175942Sscottlget_config_failed: 1567175942Sscottl if (hba->ops->internal_memfree) 1568175942Sscottl hba->ops->internal_memfree(hba); 1569175942Sscottl 1570175942Sscottldestroy_parent_tag: 1571175942Sscottl if (hba->parent_dmat) 1572175942Sscottl bus_dma_tag_destroy(hba->parent_dmat); 1573175942Sscottl 1574175942Sscottlrelease_pci_res: 1575175942Sscottl if (hba->ops->release_pci_res) 1576175942Sscottl hba->ops->release_pci_res(hba); 1577175942Sscottl 1578175942Sscottl return ENXIO; 1579169412Sscottl} 1580169412Sscottl 1581169412Sscottlstatic int hptiop_detach(device_t dev) 1582169412Sscottl{ 1583169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev); 1584169412Sscottl int i; 1585169412Sscottl int error = EBUSY; 1586169412Sscottl 1587169412Sscottl hptiop_lock_adapter(hba); 1588175942Sscottl for (i = 0; i < hba->max_devices; i++) 1589175942Sscottl if (hptiop_os_query_remove_device(hba, i)) { 1590175942Sscottl device_printf(dev, "%d file system is busy. id=%d", 1591169412Sscottl hba->pciunit, i); 1592169412Sscottl goto out; 1593169412Sscottl } 1594169412Sscottl 1595169412Sscottl if ((error = hptiop_shutdown(dev)) != 0) 1596169412Sscottl goto out; 1597175942Sscottl if (hptiop_send_sync_msg(hba, 1598175942Sscottl IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK, 60000)) 1599169412Sscottl goto out; 1600169412Sscottl 1601169412Sscottl hptiop_release_resource(hba); 1602169412Sscottl error = 0; 1603169412Sscottlout: 1604169412Sscottl hptiop_unlock_adapter(hba); 1605169412Sscottl return error; 1606169412Sscottl} 1607169412Sscottl 1608169412Sscottlstatic int hptiop_shutdown(device_t dev) 1609169412Sscottl{ 1610169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev); 1611169412Sscottl 1612169412Sscottl int error = 0; 1613169412Sscottl 1614169412Sscottl if (hba->flag & HPT_IOCTL_FLAG_OPEN) { 1615175942Sscottl device_printf(dev, "%d device is busy", hba->pciunit); 1616169412Sscottl return EBUSY; 1617169412Sscottl } 1618175942Sscottl 1619175942Sscottl hba->ops->disable_intr(hba); 1620175942Sscottl 1621175942Sscottl if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_SHUTDOWN, 60000)) 1622169412Sscottl error = EBUSY; 1623169412Sscottl 1624169412Sscottl return error; 1625169412Sscottl} 1626169412Sscottl 1627169412Sscottlstatic void hptiop_pci_intr(void *arg) 1628169412Sscottl{ 1629169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg; 1630169412Sscottl hptiop_lock_adapter(hba); 1631175942Sscottl hba->ops->iop_intr(hba); 1632169412Sscottl hptiop_unlock_adapter(hba); 1633169412Sscottl} 1634169412Sscottl 1635169412Sscottlstatic void hptiop_poll(struct cam_sim *sim) 1636169412Sscottl{ 1637169412Sscottl hptiop_pci_intr(cam_sim_softc(sim)); 1638169412Sscottl} 1639169412Sscottl 1640169412Sscottlstatic void hptiop_async(void * callback_arg, u_int32_t code, 1641169412Sscottl struct cam_path * path, void * arg) 1642169412Sscottl{ 1643169412Sscottl} 1644169412Sscottl 1645175942Sscottlstatic void hptiop_enable_intr_itl(struct hpt_iop_hba *hba) 1646169412Sscottl{ 1647175942Sscottl BUS_SPACE_WRT4_ITL(outbound_intmask, 1648169412Sscottl ~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0)); 1649169412Sscottl} 1650169412Sscottl 1651175942Sscottlstatic void hptiop_enable_intr_mv(struct hpt_iop_hba *hba) 1652169412Sscottl{ 1653169412Sscottl u_int32_t int_mask; 1654169412Sscottl 1655175942Sscottl int_mask = BUS_SPACE_RD4_MV0(outbound_intmask); 1656175942Sscottl 1657175942Sscottl int_mask |= MVIOP_MU_OUTBOUND_INT_POSTQUEUE 1658175942Sscottl | MVIOP_MU_OUTBOUND_INT_MSG; 1659175942Sscottl BUS_SPACE_WRT4_MV0(outbound_intmask,int_mask); 1660169412Sscottl} 1661169412Sscottl 1662175942Sscottlstatic void hptiop_disable_intr_itl(struct hpt_iop_hba *hba) 1663175942Sscottl{ 1664175942Sscottl u_int32_t int_mask; 1665175942Sscottl 1666175942Sscottl int_mask = BUS_SPACE_RD4_ITL(outbound_intmask); 1667175942Sscottl 1668175942Sscottl int_mask |= IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0; 1669175942Sscottl BUS_SPACE_WRT4_ITL(outbound_intmask, int_mask); 1670175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 1671175942Sscottl} 1672175942Sscottl 1673175942Sscottlstatic void hptiop_disable_intr_mv(struct hpt_iop_hba *hba) 1674175942Sscottl{ 1675175942Sscottl u_int32_t int_mask; 1676175942Sscottl int_mask = BUS_SPACE_RD4_MV0(outbound_intmask); 1677175942Sscottl 1678175942Sscottl int_mask &= ~(MVIOP_MU_OUTBOUND_INT_MSG 1679175942Sscottl | MVIOP_MU_OUTBOUND_INT_POSTQUEUE); 1680175942Sscottl BUS_SPACE_WRT4_MV0(outbound_intmask,int_mask); 1681175942Sscottl BUS_SPACE_RD4_MV0(outbound_intmask); 1682175942Sscottl} 1683175942Sscottl 1684169412Sscottlstatic int hptiop_reset_adapter(struct hpt_iop_hba * hba) 1685169412Sscottl{ 1686175942Sscottl return hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000); 1687169412Sscottl} 1688169412Sscottl 1689169412Sscottlstatic void *hptiop_get_srb(struct hpt_iop_hba * hba) 1690169412Sscottl{ 1691169412Sscottl struct hpt_iop_srb * srb; 1692169412Sscottl 1693169412Sscottl if (hba->srb_list) { 1694169412Sscottl srb = hba->srb_list; 1695169412Sscottl hba->srb_list = srb->next; 1696175942Sscottl return srb; 1697169412Sscottl } 1698169412Sscottl 1699175942Sscottl return NULL; 1700169412Sscottl} 1701169412Sscottl 1702175942Sscottlstatic void hptiop_free_srb(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb) 1703169412Sscottl{ 1704169412Sscottl srb->next = hba->srb_list; 1705169412Sscottl hba->srb_list = srb; 1706169412Sscottl} 1707169412Sscottl 1708169412Sscottlstatic void hptiop_action(struct cam_sim *sim, union ccb *ccb) 1709169412Sscottl{ 1710169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)cam_sim_softc(sim); 1711169412Sscottl struct hpt_iop_srb * srb; 1712169412Sscottl 1713169412Sscottl switch (ccb->ccb_h.func_code) { 1714169412Sscottl 1715169412Sscottl case XPT_SCSI_IO: 1716169412Sscottl hptiop_lock_adapter(hba); 1717169412Sscottl if (ccb->ccb_h.target_lun != 0 || 1718175942Sscottl ccb->ccb_h.target_id >= hba->max_devices || 1719169412Sscottl (ccb->ccb_h.flags & CAM_CDB_PHYS)) 1720169412Sscottl { 1721169412Sscottl ccb->ccb_h.status = CAM_TID_INVALID; 1722169412Sscottl xpt_done(ccb); 1723169412Sscottl goto scsi_done; 1724169412Sscottl } 1725169412Sscottl 1726169412Sscottl if ((srb = hptiop_get_srb(hba)) == NULL) { 1727175942Sscottl device_printf(hba->pcidev, "srb allocated failed"); 1728169412Sscottl ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1729169412Sscottl xpt_done(ccb); 1730169412Sscottl goto scsi_done; 1731169412Sscottl } 1732169412Sscottl 1733169412Sscottl srb->ccb = ccb; 1734169412Sscottl 1735169412Sscottl if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE) 1736169412Sscottl hptiop_post_scsi_command(srb, NULL, 0, 0); 1737169412Sscottl else if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { 1738169412Sscottl if ((ccb->ccb_h.flags & CAM_DATA_PHYS) == 0) { 1739169412Sscottl int error; 1740169412Sscottl 1741169412Sscottl error = bus_dmamap_load(hba->io_dmat, 1742175942Sscottl srb->dma_map, 1743175942Sscottl ccb->csio.data_ptr, 1744175942Sscottl ccb->csio.dxfer_len, 1745175942Sscottl hptiop_post_scsi_command, 1746175942Sscottl srb, 0); 1747169412Sscottl 1748169412Sscottl if (error && error != EINPROGRESS) { 1749175942Sscottl device_printf(hba->pcidev, 1750175942Sscottl "%d bus_dmamap_load error %d", 1751175942Sscottl hba->pciunit, error); 1752169412Sscottl xpt_freeze_simq(hba->sim, 1); 1753169412Sscottl ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1754169412Sscottlinvalid: 1755169412Sscottl hptiop_free_srb(hba, srb); 1756169412Sscottl xpt_done(ccb); 1757169412Sscottl goto scsi_done; 1758169412Sscottl } 1759169412Sscottl } 1760169412Sscottl else { 1761175942Sscottl device_printf(hba->pcidev, 1762175942Sscottl "CAM_DATA_PHYS not supported"); 1763169412Sscottl ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1764169412Sscottl goto invalid; 1765169412Sscottl } 1766169412Sscottl } 1767169412Sscottl else { 1768169412Sscottl struct bus_dma_segment *segs; 1769169412Sscottl 1770169412Sscottl if ((ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0 || 1771169412Sscottl (ccb->ccb_h.flags & CAM_DATA_PHYS) != 0) { 1772175942Sscottl device_printf(hba->pcidev, "SCSI cmd failed"); 1773169412Sscottl ccb->ccb_h.status=CAM_PROVIDE_FAIL; 1774169412Sscottl goto invalid; 1775169412Sscottl } 1776169412Sscottl 1777169412Sscottl segs = (struct bus_dma_segment *)ccb->csio.data_ptr; 1778169412Sscottl hptiop_post_scsi_command(srb, segs, 1779169412Sscottl ccb->csio.sglist_cnt, 0); 1780169412Sscottl } 1781169412Sscottl 1782169412Sscottlscsi_done: 1783169412Sscottl hptiop_unlock_adapter(hba); 1784169412Sscottl return; 1785169412Sscottl 1786169412Sscottl case XPT_RESET_BUS: 1787175942Sscottl device_printf(hba->pcidev, "reset adapter"); 1788169412Sscottl hptiop_lock_adapter(hba); 1789169412Sscottl hba->msg_done = 0; 1790169412Sscottl hptiop_reset_adapter(hba); 1791169412Sscottl hptiop_unlock_adapter(hba); 1792169412Sscottl break; 1793169412Sscottl 1794169412Sscottl case XPT_GET_TRAN_SETTINGS: 1795169412Sscottl case XPT_SET_TRAN_SETTINGS: 1796169412Sscottl ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 1797169412Sscottl break; 1798169412Sscottl 1799169412Sscottl case XPT_CALC_GEOMETRY: 1800169412Sscottl ccb->ccg.heads = 255; 1801169412Sscottl ccb->ccg.secs_per_track = 63; 1802169412Sscottl ccb->ccg.cylinders = ccb->ccg.volume_size / 1803169412Sscottl (ccb->ccg.heads * ccb->ccg.secs_per_track); 1804169412Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 1805169412Sscottl break; 1806169412Sscottl 1807169412Sscottl case XPT_PATH_INQ: 1808169412Sscottl { 1809169412Sscottl struct ccb_pathinq *cpi = &ccb->cpi; 1810169412Sscottl 1811169412Sscottl cpi->version_num = 1; 1812169412Sscottl cpi->hba_inquiry = PI_SDTR_ABLE; 1813169412Sscottl cpi->target_sprt = 0; 1814169412Sscottl cpi->hba_misc = PIM_NOBUSRESET; 1815169412Sscottl cpi->hba_eng_cnt = 0; 1816175942Sscottl cpi->max_target = hba->max_devices; 1817169412Sscottl cpi->max_lun = 0; 1818169412Sscottl cpi->unit_number = cam_sim_unit(sim); 1819169412Sscottl cpi->bus_id = cam_sim_bus(sim); 1820175942Sscottl cpi->initiator_id = hba->max_devices; 1821169412Sscottl cpi->base_transfer_speed = 3300; 1822169412Sscottl 1823169412Sscottl strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 1824169412Sscottl strncpy(cpi->hba_vid, "HPT ", HBA_IDLEN); 1825169412Sscottl strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 1826169412Sscottl cpi->ccb_h.status = CAM_REQ_CMP; 1827169412Sscottl break; 1828169412Sscottl } 1829169412Sscottl 1830169412Sscottl default: 1831169412Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 1832169412Sscottl break; 1833169412Sscottl } 1834169412Sscottl 1835169412Sscottl xpt_done(ccb); 1836169412Sscottl return; 1837169412Sscottl} 1838169412Sscottl 1839175942Sscottlstatic void hptiop_post_req_itl(struct hpt_iop_hba *hba, 1840175942Sscottl struct hpt_iop_srb *srb, 1841175942Sscottl bus_dma_segment_t *segs, int nsegs) 1842169412Sscottl{ 1843169412Sscottl int idx; 1844169412Sscottl union ccb *ccb = srb->ccb; 1845169412Sscottl u_int8_t *cdb; 1846169412Sscottl 1847175942Sscottl if (ccb->ccb_h.flags & CAM_CDB_POINTER) 1848175942Sscottl cdb = ccb->csio.cdb_io.cdb_ptr; 1849175942Sscottl else 1850175942Sscottl cdb = ccb->csio.cdb_io.cdb_bytes; 1851169412Sscottl 1852175942Sscottl KdPrint(("ccb=%p %x-%x-%x\n", 1853175942Sscottl ccb, *(u_int32_t *)cdb, *((u_int32_t *)cdb+1), *((u_int32_t *)cdb+2))); 1854169412Sscottl 1855169412Sscottl if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) { 1856175942Sscottl u_int32_t iop_req32; 1857175942Sscottl struct hpt_iop_request_scsi_command req; 1858169412Sscottl 1859175942Sscottl iop_req32 = BUS_SPACE_RD4_ITL(inbound_queue); 1860175942Sscottl 1861175942Sscottl if (iop_req32 == IOPMU_QUEUE_EMPTY) { 1862175942Sscottl device_printf(hba->pcidev, "invaild req offset\n"); 1863175942Sscottl ccb->ccb_h.status = CAM_BUSY; 1864175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 1865175942Sscottl hptiop_free_srb(hba, srb); 1866175942Sscottl xpt_done(ccb); 1867175942Sscottl return; 1868169412Sscottl } 1869175942Sscottl 1870175942Sscottl if (ccb->csio.dxfer_len && nsegs > 0) { 1871175942Sscottl struct hpt_iopsg *psg = req.sg_list; 1872175942Sscottl for (idx = 0; idx < nsegs; idx++, psg++) { 1873175942Sscottl psg->pci_address = (u_int64_t)segs[idx].ds_addr; 1874175942Sscottl psg->size = segs[idx].ds_len; 1875175942Sscottl psg->eot = 0; 1876175942Sscottl } 1877175942Sscottl psg[-1].eot = 1; 1878175942Sscottl } 1879175942Sscottl 1880175942Sscottl bcopy(cdb, req.cdb, ccb->csio.cdb_len); 1881175942Sscottl 1882175942Sscottl req.header.size = offsetof(struct hpt_iop_request_scsi_command, sg_list) 1883175942Sscottl + nsegs*sizeof(struct hpt_iopsg); 1884175942Sscottl req.header.type = IOP_REQUEST_TYPE_SCSI_COMMAND; 1885175942Sscottl req.header.flags = 0; 1886175942Sscottl req.header.result = IOP_RESULT_PENDING; 1887175942Sscottl req.header.context = (u_int64_t)(unsigned long)srb; 1888175942Sscottl req.dataxfer_length = ccb->csio.dxfer_len; 1889175942Sscottl req.channel = 0; 1890175942Sscottl req.target = ccb->ccb_h.target_id; 1891175942Sscottl req.lun = ccb->ccb_h.target_lun; 1892175942Sscottl 1893175942Sscottl bus_space_write_region_1(hba->bar0t, hba->bar0h, iop_req32, 1894175942Sscottl (u_int8_t *)&req, req.header.size); 1895175942Sscottl 1896175942Sscottl if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 1897175942Sscottl bus_dmamap_sync(hba->io_dmat, 1898175942Sscottl srb->dma_map, BUS_DMASYNC_PREREAD); 1899175942Sscottl } 1900175942Sscottl else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) 1901175942Sscottl bus_dmamap_sync(hba->io_dmat, 1902175942Sscottl srb->dma_map, BUS_DMASYNC_PREWRITE); 1903175942Sscottl 1904175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue,iop_req32); 1905175942Sscottl } else { 1906175942Sscottl struct hpt_iop_request_scsi_command *req; 1907175942Sscottl 1908169412Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 1909175942Sscottl if (ccb->csio.dxfer_len && nsegs > 0) { 1910175942Sscottl struct hpt_iopsg *psg = req->sg_list; 1911175942Sscottl for (idx = 0; idx < nsegs; idx++, psg++) { 1912175942Sscottl psg->pci_address = 1913175942Sscottl (u_int64_t)segs[idx].ds_addr; 1914175942Sscottl psg->size = segs[idx].ds_len; 1915175942Sscottl psg->eot = 0; 1916175942Sscottl } 1917175942Sscottl psg[-1].eot = 1; 1918175942Sscottl } 1919169412Sscottl 1920175942Sscottl bcopy(cdb, req->cdb, ccb->csio.cdb_len); 1921175942Sscottl 1922175942Sscottl req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND; 1923175942Sscottl req->header.result = IOP_RESULT_PENDING; 1924175942Sscottl req->dataxfer_length = ccb->csio.dxfer_len; 1925175942Sscottl req->channel = 0; 1926175942Sscottl req->target = ccb->ccb_h.target_id; 1927175942Sscottl req->lun = ccb->ccb_h.target_lun; 1928175942Sscottl req->header.size = offsetof(struct hpt_iop_request_scsi_command, sg_list) 1929175942Sscottl + nsegs*sizeof(struct hpt_iopsg); 1930175942Sscottl req->header.context = (u_int64_t)srb->index | 1931175942Sscottl IOPMU_QUEUE_ADDR_HOST_BIT; 1932175942Sscottl req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT; 1933175942Sscottl 1934175942Sscottl if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 1935175942Sscottl bus_dmamap_sync(hba->io_dmat, 1936175942Sscottl srb->dma_map, BUS_DMASYNC_PREREAD); 1937175942Sscottl }else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 1938175942Sscottl bus_dmamap_sync(hba->io_dmat, 1939175942Sscottl srb->dma_map, BUS_DMASYNC_PREWRITE); 1940175942Sscottl } 1941175942Sscottl 1942175942Sscottl if (hba->firmware_version > 0x01020000 1943175942Sscottl || hba->interface_version > 0x01020000) { 1944175942Sscottl u_int32_t size_bits; 1945175942Sscottl 1946175942Sscottl if (req->header.size < 256) 1947175942Sscottl size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT; 1948175942Sscottl else if (req->header.size < 512) 1949175942Sscottl size_bits = IOPMU_QUEUE_ADDR_HOST_BIT; 1950175942Sscottl else 1951175942Sscottl size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT 1952175942Sscottl | IOPMU_QUEUE_ADDR_HOST_BIT; 1953175942Sscottl 1954175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue, 1955175942Sscottl (u_int32_t)srb->phy_addr | size_bits); 1956175942Sscottl } else 1957175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue, (u_int32_t)srb->phy_addr 1958175942Sscottl |IOPMU_QUEUE_ADDR_HOST_BIT); 1959175942Sscottl } 1960175942Sscottl} 1961175942Sscottl 1962175942Sscottlstatic void hptiop_post_req_mv(struct hpt_iop_hba *hba, 1963175942Sscottl struct hpt_iop_srb *srb, 1964175942Sscottl bus_dma_segment_t *segs, int nsegs) 1965175942Sscottl{ 1966175942Sscottl int idx, size; 1967175942Sscottl union ccb *ccb = srb->ccb; 1968175942Sscottl u_int8_t *cdb; 1969175942Sscottl struct hpt_iop_request_scsi_command *req; 1970175942Sscottl u_int64_t req_phy; 1971175942Sscottl 1972175942Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 1973175942Sscottl req_phy = srb->phy_addr; 1974175942Sscottl 1975169412Sscottl if (ccb->csio.dxfer_len && nsegs > 0) { 1976169412Sscottl struct hpt_iopsg *psg = req->sg_list; 1977169412Sscottl for (idx = 0; idx < nsegs; idx++, psg++) { 1978169412Sscottl psg->pci_address = (u_int64_t)segs[idx].ds_addr; 1979169412Sscottl psg->size = segs[idx].ds_len; 1980169412Sscottl psg->eot = 0; 1981169412Sscottl } 1982169412Sscottl psg[-1].eot = 1; 1983169412Sscottl } 1984169412Sscottl if (ccb->ccb_h.flags & CAM_CDB_POINTER) 1985169412Sscottl cdb = ccb->csio.cdb_io.cdb_ptr; 1986169412Sscottl else 1987169412Sscottl cdb = ccb->csio.cdb_io.cdb_bytes; 1988169412Sscottl 1989169412Sscottl bcopy(cdb, req->cdb, ccb->csio.cdb_len); 1990169412Sscottl req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND; 1991169412Sscottl req->header.result = IOP_RESULT_PENDING; 1992169412Sscottl req->dataxfer_length = ccb->csio.dxfer_len; 1993175942Sscottl req->channel = 0; 1994169412Sscottl req->target = ccb->ccb_h.target_id; 1995169412Sscottl req->lun = ccb->ccb_h.target_lun; 1996169412Sscottl req->header.size = sizeof(struct hpt_iop_request_scsi_command) 1997175942Sscottl - sizeof(struct hpt_iopsg) 1998175942Sscottl + nsegs * sizeof(struct hpt_iopsg); 1999169412Sscottl if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 2000169412Sscottl bus_dmamap_sync(hba->io_dmat, 2001175942Sscottl srb->dma_map, BUS_DMASYNC_PREREAD); 2002169412Sscottl } 2003169412Sscottl else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) 2004169412Sscottl bus_dmamap_sync(hba->io_dmat, 2005175942Sscottl srb->dma_map, BUS_DMASYNC_PREWRITE); 2006175942Sscottl req->header.context = (u_int64_t)srb->index 2007175942Sscottl << MVIOP_REQUEST_NUMBER_START_BIT 2008175942Sscottl | MVIOP_CMD_TYPE_SCSI; 2009175942Sscottl req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT; 2010175942Sscottl size = req->header.size >> 8; 2011175942Sscottl hptiop_mv_inbound_write(req_phy 2012175942Sscottl | MVIOP_MU_QUEUE_ADDR_HOST_BIT 2013175942Sscottl | (size > 3 ? 3 : size), hba); 2014169412Sscottl} 2015169412Sscottl 2016175942Sscottlstatic void hptiop_post_scsi_command(void *arg, bus_dma_segment_t *segs, 2017175942Sscottl int nsegs, int error) 2018169412Sscottl{ 2019175942Sscottl struct hpt_iop_srb *srb = (struct hpt_iop_srb *)arg; 2020175942Sscottl union ccb *ccb = srb->ccb; 2021175942Sscottl struct hpt_iop_hba *hba = srb->hba; 2022169412Sscottl 2023175942Sscottl if (error || nsegs > hba->max_sg_count) { 2024175942Sscottl KdPrint(("hptiop: func_code=%x tid=%x lun=%x nsegs=%d\n", 2025175942Sscottl ccb->ccb_h.func_code, 2026175942Sscottl ccb->ccb_h.target_id, 2027175942Sscottl ccb->ccb_h.target_lun, nsegs)); 2028175942Sscottl ccb->ccb_h.status = CAM_BUSY; 2029175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 2030169412Sscottl hptiop_free_srb(hba, srb); 2031169412Sscottl xpt_done(ccb); 2032175942Sscottl return; 2033169412Sscottl } 2034175942Sscottl 2035175942Sscottl hba->ops->post_req(hba, srb, segs, nsegs); 2036169412Sscottl} 2037169412Sscottl 2038175942Sscottlstatic void hptiop_mv_map_ctlcfg(void *arg, bus_dma_segment_t *segs, 2039175942Sscottl int nsegs, int error) 2040175942Sscottl{ 2041175942Sscottl struct hpt_iop_hba *hba = (struct hpt_iop_hba *)arg; 2042175942Sscottl hba->ctlcfgcmd_phy = ((u_int64_t)segs->ds_addr + 0x1F) 2043175942Sscottl & ~(u_int64_t)0x1F; 2044175942Sscottl hba->ctlcfg_ptr = (u_int8_t *)(((unsigned long)hba->ctlcfg_ptr + 0x1F) 2045175942Sscottl & ~0x1F); 2046175942Sscottl} 2047175942Sscottl 2048169412Sscottlstatic void hptiop_map_srb(void *arg, bus_dma_segment_t *segs, 2049175942Sscottl int nsegs, int error) 2050169412Sscottl{ 2051169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg; 2052169412Sscottl bus_addr_t phy_addr = (segs->ds_addr + 0x1F) & ~(bus_addr_t)0x1F; 2053169412Sscottl struct hpt_iop_srb *srb, *tmp_srb; 2054169412Sscottl int i; 2055169412Sscottl 2056169412Sscottl if (error || nsegs == 0) { 2057175942Sscottl device_printf(hba->pcidev, "hptiop_map_srb error"); 2058169412Sscottl return; 2059169412Sscottl } 2060169412Sscottl 2061169412Sscottl /* map srb */ 2062169412Sscottl srb = (struct hpt_iop_srb *) 2063175942Sscottl (((unsigned long)hba->uncached_ptr + 0x1F) 2064175942Sscottl & ~(unsigned long)0x1F); 2065169412Sscottl 2066169412Sscottl for (i = 0; i < HPT_SRB_MAX_QUEUE_SIZE; i++) { 2067169412Sscottl tmp_srb = (struct hpt_iop_srb *) 2068169412Sscottl ((char *)srb + i * HPT_SRB_MAX_SIZE); 2069169412Sscottl if (((unsigned long)tmp_srb & 0x1F) == 0) { 2070169412Sscottl if (bus_dmamap_create(hba->io_dmat, 2071169412Sscottl 0, &tmp_srb->dma_map)) { 2072175942Sscottl device_printf(hba->pcidev, "dmamap create failed"); 2073169412Sscottl return; 2074169412Sscottl } 2075169412Sscottl 2076169412Sscottl bzero(tmp_srb, sizeof(struct hpt_iop_srb)); 2077169412Sscottl tmp_srb->hba = hba; 2078169412Sscottl tmp_srb->index = i; 2079175942Sscottl if (hba->ctlcfg_ptr == 0) {/*itl iop*/ 2080175942Sscottl tmp_srb->phy_addr = (u_int64_t)(u_int32_t) 2081175942Sscottl (phy_addr >> 5); 2082175942Sscottl if (phy_addr & IOPMU_MAX_MEM_SUPPORT_MASK_32G) 2083175942Sscottl tmp_srb->srb_flag = 2084175942Sscottl HPT_SRB_FLAG_HIGH_MEM_ACESS; 2085175942Sscottl } else { 2086175942Sscottl tmp_srb->phy_addr = phy_addr; 2087175942Sscottl } 2088175942Sscottl 2089169412Sscottl hptiop_free_srb(hba, tmp_srb); 2090169412Sscottl hba->srb[i] = tmp_srb; 2091169412Sscottl phy_addr += HPT_SRB_MAX_SIZE; 2092169412Sscottl } 2093169412Sscottl else { 2094175942Sscottl device_printf(hba->pcidev, "invalid alignment"); 2095169412Sscottl return; 2096169412Sscottl } 2097169412Sscottl } 2098169412Sscottl} 2099169412Sscottl 2100175942Sscottlstatic void hptiop_os_message_callback(struct hpt_iop_hba * hba, u_int32_t msg) 2101169412Sscottl{ 2102169412Sscottl hba->msg_done = 1; 2103169412Sscottl} 2104169412Sscottl 2105175942Sscottlstatic int hptiop_os_query_remove_device(struct hpt_iop_hba * hba, 2106175942Sscottl int target_id) 2107169412Sscottl{ 2108169412Sscottl struct cam_periph *periph = NULL; 2109169412Sscottl struct cam_path *path; 2110169412Sscottl int status, retval = 0; 2111169412Sscottl 2112169412Sscottl status = xpt_create_path(&path, NULL, hba->sim->path_id, target_id, 0); 2113169412Sscottl 2114169412Sscottl if (status == CAM_REQ_CMP) { 2115169412Sscottl if ((periph = cam_periph_find(path, "da")) != NULL) { 2116169412Sscottl if (periph->refcount >= 1) { 2117175942Sscottl device_printf(hba->pcidev, "%d ," 2118175942Sscottl "target_id=0x%x," 2119175942Sscottl "refcount=%d", 2120169412Sscottl hba->pciunit, target_id, periph->refcount); 2121169412Sscottl retval = -1; 2122169412Sscottl } 2123169412Sscottl } 2124169412Sscottl xpt_free_path(path); 2125169412Sscottl } 2126169412Sscottl return retval; 2127169412Sscottl} 2128169412Sscottl 2129169412Sscottlstatic void hptiop_release_resource(struct hpt_iop_hba *hba) 2130169412Sscottl{ 2131175942Sscottl int i; 2132175942Sscottl if (hba->path) { 2133175942Sscottl struct ccb_setasync ccb; 2134169412Sscottl 2135169412Sscottl xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5); 2136169412Sscottl ccb.ccb_h.func_code = XPT_SASYNC_CB; 2137169412Sscottl ccb.event_enable = 0; 2138169412Sscottl ccb.callback = hptiop_async; 2139169412Sscottl ccb.callback_arg = hba->sim; 2140169412Sscottl xpt_action((union ccb *)&ccb); 2141169412Sscottl xpt_free_path(hba->path); 2142169412Sscottl } 2143169412Sscottl 2144169412Sscottl if (hba->sim) { 2145169412Sscottl xpt_bus_deregister(cam_sim_path(hba->sim)); 2146169412Sscottl cam_sim_free(hba->sim, TRUE); 2147169412Sscottl } 2148169412Sscottl 2149175942Sscottl if (hba->ctlcfg_dmat) { 2150175942Sscottl bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap); 2151175942Sscottl bus_dmamem_free(hba->ctlcfg_dmat, 2152175942Sscottl hba->ctlcfg_ptr, hba->ctlcfg_dmamap); 2153175942Sscottl bus_dma_tag_destroy(hba->ctlcfg_dmat); 2154175942Sscottl } 2155175942Sscottl 2156175942Sscottl for (i = 0; i < HPT_SRB_MAX_QUEUE_SIZE; i++) { 2157175942Sscottl struct hpt_iop_srb *srb = hba->srb[i]; 2158175942Sscottl if (srb->dma_map) 2159175942Sscottl bus_dmamap_destroy(hba->io_dmat, srb->dma_map); 2160175942Sscottl } 2161175942Sscottl 2162169412Sscottl if (hba->srb_dmat) { 2163169412Sscottl bus_dmamap_unload(hba->srb_dmat, hba->srb_dmamap); 2164175942Sscottl bus_dmamap_destroy(hba->srb_dmat, hba->srb_dmamap); 2165169412Sscottl bus_dma_tag_destroy(hba->srb_dmat); 2166169412Sscottl } 2167169412Sscottl 2168169412Sscottl if (hba->io_dmat) 2169169412Sscottl bus_dma_tag_destroy(hba->io_dmat); 2170169412Sscottl 2171169412Sscottl if (hba->parent_dmat) 2172169412Sscottl bus_dma_tag_destroy(hba->parent_dmat); 2173169412Sscottl 2174169412Sscottl if (hba->irq_handle) 2175169412Sscottl bus_teardown_intr(hba->pcidev, hba->irq_res, hba->irq_handle); 2176169412Sscottl 2177169412Sscottl if (hba->irq_res) 2178175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_IRQ, 2179175942Sscottl 0, hba->irq_res); 2180169412Sscottl 2181169412Sscottl if (hba->bar0_res) 2182169412Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 2183169412Sscottl hba->bar0_rid, hba->bar0_res); 2184175942Sscottl if (hba->bar2_res) 2185175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 2186175942Sscottl hba->bar2_rid, hba->bar2_res); 2187169412Sscottl if (hba->ioctl_dev) 2188169412Sscottl destroy_dev(hba->ioctl_dev); 2189169412Sscottl} 2190