1169412Sscottl/* 2175942Sscottl * HighPoint RR3xxx/4xxx RAID Driver for FreeBSD 3242214Sdelphij * Copyright (C) 2007-2012 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$"); 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 92242214Sdelphijstatic const char driver_name[] = "hptiop"; 93252884Sdelphijstatic const char driver_version[] = "v1.9"; 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); 102242214Sdelphijstatic void hptiop_request_callback_mvfrey(struct hpt_iop_hba *hba, 103242214Sdelphij u_int32_t req); 104175942Sscottlstatic void hptiop_os_message_callback(struct hpt_iop_hba *hba, u_int32_t msg); 105175942Sscottlstatic int hptiop_do_ioctl_itl(struct hpt_iop_hba *hba, 106175942Sscottl struct hpt_iop_ioctl_param *pParams); 107175942Sscottlstatic int hptiop_do_ioctl_mv(struct hpt_iop_hba *hba, 108175942Sscottl struct hpt_iop_ioctl_param *pParams); 109242214Sdelphijstatic int hptiop_do_ioctl_mvfrey(struct hpt_iop_hba *hba, 110242214Sdelphij struct hpt_iop_ioctl_param *pParams); 111175942Sscottlstatic int hptiop_rescan_bus(struct hpt_iop_hba *hba); 112175942Sscottlstatic int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba); 113175942Sscottlstatic int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba); 114242214Sdelphijstatic int hptiop_alloc_pci_res_mvfrey(struct hpt_iop_hba *hba); 115175942Sscottlstatic int hptiop_get_config_itl(struct hpt_iop_hba *hba, 116175942Sscottl struct hpt_iop_request_get_config *config); 117175942Sscottlstatic int hptiop_get_config_mv(struct hpt_iop_hba *hba, 118175942Sscottl struct hpt_iop_request_get_config *config); 119242214Sdelphijstatic int hptiop_get_config_mvfrey(struct hpt_iop_hba *hba, 120242214Sdelphij struct hpt_iop_request_get_config *config); 121175942Sscottlstatic int hptiop_set_config_itl(struct hpt_iop_hba *hba, 122175942Sscottl struct hpt_iop_request_set_config *config); 123175942Sscottlstatic int hptiop_set_config_mv(struct hpt_iop_hba *hba, 124175942Sscottl struct hpt_iop_request_set_config *config); 125242214Sdelphijstatic int hptiop_set_config_mvfrey(struct hpt_iop_hba *hba, 126242214Sdelphij struct hpt_iop_request_set_config *config); 127175942Sscottlstatic int hptiop_internal_memalloc_mv(struct hpt_iop_hba *hba); 128242214Sdelphijstatic int hptiop_internal_memalloc_mvfrey(struct hpt_iop_hba *hba); 129242214Sdelphijstatic int hptiop_internal_memfree_itl(struct hpt_iop_hba *hba); 130175942Sscottlstatic int hptiop_internal_memfree_mv(struct hpt_iop_hba *hba); 131242214Sdelphijstatic int hptiop_internal_memfree_mvfrey(struct hpt_iop_hba *hba); 132175942Sscottlstatic int hptiop_post_ioctl_command_itl(struct hpt_iop_hba *hba, 133175942Sscottl u_int32_t req32, struct hpt_iop_ioctl_param *pParams); 134175942Sscottlstatic int hptiop_post_ioctl_command_mv(struct hpt_iop_hba *hba, 135175942Sscottl struct hpt_iop_request_ioctl_command *req, 136175942Sscottl struct hpt_iop_ioctl_param *pParams); 137242214Sdelphijstatic int hptiop_post_ioctl_command_mvfrey(struct hpt_iop_hba *hba, 138242214Sdelphij struct hpt_iop_request_ioctl_command *req, 139242214Sdelphij struct hpt_iop_ioctl_param *pParams); 140175942Sscottlstatic void hptiop_post_req_itl(struct hpt_iop_hba *hba, 141175942Sscottl struct hpt_iop_srb *srb, 142175942Sscottl bus_dma_segment_t *segs, int nsegs); 143175942Sscottlstatic void hptiop_post_req_mv(struct hpt_iop_hba *hba, 144175942Sscottl struct hpt_iop_srb *srb, 145175942Sscottl bus_dma_segment_t *segs, int nsegs); 146242214Sdelphijstatic void hptiop_post_req_mvfrey(struct hpt_iop_hba *hba, 147242214Sdelphij struct hpt_iop_srb *srb, 148242214Sdelphij bus_dma_segment_t *segs, int nsegs); 149175942Sscottlstatic void hptiop_post_msg_itl(struct hpt_iop_hba *hba, u_int32_t msg); 150175942Sscottlstatic void hptiop_post_msg_mv(struct hpt_iop_hba *hba, u_int32_t msg); 151242214Sdelphijstatic void hptiop_post_msg_mvfrey(struct hpt_iop_hba *hba, u_int32_t msg); 152175942Sscottlstatic void hptiop_enable_intr_itl(struct hpt_iop_hba *hba); 153175942Sscottlstatic void hptiop_enable_intr_mv(struct hpt_iop_hba *hba); 154242214Sdelphijstatic void hptiop_enable_intr_mvfrey(struct hpt_iop_hba *hba); 155175942Sscottlstatic void hptiop_disable_intr_itl(struct hpt_iop_hba *hba); 156175942Sscottlstatic void hptiop_disable_intr_mv(struct hpt_iop_hba *hba); 157242214Sdelphijstatic void hptiop_disable_intr_mvfrey(struct hpt_iop_hba *hba); 158175942Sscottlstatic void hptiop_free_srb(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb); 159175942Sscottlstatic int hptiop_os_query_remove_device(struct hpt_iop_hba *hba, int tid); 160169412Sscottlstatic int hptiop_probe(device_t dev); 161169412Sscottlstatic int hptiop_attach(device_t dev); 162169412Sscottlstatic int hptiop_detach(device_t dev); 163169412Sscottlstatic int hptiop_shutdown(device_t dev); 164169412Sscottlstatic void hptiop_action(struct cam_sim *sim, union ccb *ccb); 165169412Sscottlstatic void hptiop_poll(struct cam_sim *sim); 166175942Sscottlstatic void hptiop_async(void *callback_arg, u_int32_t code, 167175942Sscottl struct cam_path *path, void *arg); 168169412Sscottlstatic void hptiop_pci_intr(void *arg); 169175942Sscottlstatic void hptiop_release_resource(struct hpt_iop_hba *hba); 170242214Sdelphijstatic void hptiop_reset_adapter(void *argv); 171169412Sscottlstatic d_open_t hptiop_open; 172169412Sscottlstatic d_close_t hptiop_close; 173169412Sscottlstatic d_ioctl_t hptiop_ioctl; 174169412Sscottl 175169412Sscottlstatic struct cdevsw hptiop_cdevsw = { 176169412Sscottl .d_open = hptiop_open, 177169412Sscottl .d_close = hptiop_close, 178169412Sscottl .d_ioctl = hptiop_ioctl, 179169412Sscottl .d_name = driver_name, 180169412Sscottl#if __FreeBSD_version>=503000 181169412Sscottl .d_version = D_VERSION, 182169412Sscottl#endif 183169412Sscottl#if (__FreeBSD_version>=503000 && __FreeBSD_version<600034) 184169412Sscottl .d_flags = D_NEEDGIANT, 185169412Sscottl#endif 186169412Sscottl#if __FreeBSD_version<600034 187169412Sscottl#if __FreeBSD_version>=501000 188169412Sscottl .d_maj = MAJOR_AUTO, 189169412Sscottl#else 190169412Sscottl .d_maj = HPT_DEV_MAJOR, 191169412Sscottl#endif 192169412Sscottl#endif 193169412Sscottl}; 194169412Sscottl 195169412Sscottl#if __FreeBSD_version < 503000 196169412Sscottl#define hba_from_dev(dev) ((struct hpt_iop_hba *)(dev)->si_drv1) 197169412Sscottl#else 198169412Sscottl#define hba_from_dev(dev) \ 199183397Sed ((struct hpt_iop_hba *)devclass_get_softc(hptiop_devclass, dev2unit(dev))) 200169412Sscottl#endif 201169412Sscottl 202175942Sscottl#define BUS_SPACE_WRT4_ITL(offset, value) bus_space_write_4(hba->bar0t,\ 203175942Sscottl hba->bar0h, offsetof(struct hpt_iopmu_itl, offset), (value)) 204175942Sscottl#define BUS_SPACE_RD4_ITL(offset) bus_space_read_4(hba->bar0t,\ 205175942Sscottl hba->bar0h, offsetof(struct hpt_iopmu_itl, offset)) 206175942Sscottl 207175942Sscottl#define BUS_SPACE_WRT4_MV0(offset, value) bus_space_write_4(hba->bar0t,\ 208175942Sscottl hba->bar0h, offsetof(struct hpt_iopmv_regs, offset), value) 209175942Sscottl#define BUS_SPACE_RD4_MV0(offset) bus_space_read_4(hba->bar0t,\ 210175942Sscottl hba->bar0h, offsetof(struct hpt_iopmv_regs, offset)) 211175942Sscottl#define BUS_SPACE_WRT4_MV2(offset, value) bus_space_write_4(hba->bar2t,\ 212175942Sscottl hba->bar2h, offsetof(struct hpt_iopmu_mv, offset), value) 213175942Sscottl#define BUS_SPACE_RD4_MV2(offset) bus_space_read_4(hba->bar2t,\ 214175942Sscottl hba->bar2h, offsetof(struct hpt_iopmu_mv, offset)) 215175942Sscottl 216242214Sdelphij#define BUS_SPACE_WRT4_MVFREY2(offset, value) bus_space_write_4(hba->bar2t,\ 217242214Sdelphij hba->bar2h, offsetof(struct hpt_iopmu_mvfrey, offset), value) 218242214Sdelphij#define BUS_SPACE_RD4_MVFREY2(offset) bus_space_read_4(hba->bar2t,\ 219242214Sdelphij hba->bar2h, offsetof(struct hpt_iopmu_mvfrey, offset)) 220242214Sdelphij 221169412Sscottlstatic int hptiop_open(ioctl_dev_t dev, int flags, 222169412Sscottl int devtype, ioctl_thread_t proc) 223169412Sscottl{ 224175942Sscottl struct hpt_iop_hba *hba = hba_from_dev(dev); 225169412Sscottl 226169412Sscottl if (hba==NULL) 227169412Sscottl return ENXIO; 228169412Sscottl if (hba->flag & HPT_IOCTL_FLAG_OPEN) 229169412Sscottl return EBUSY; 230169412Sscottl hba->flag |= HPT_IOCTL_FLAG_OPEN; 231169412Sscottl return 0; 232169412Sscottl} 233169412Sscottl 234169412Sscottlstatic int hptiop_close(ioctl_dev_t dev, int flags, 235169412Sscottl int devtype, ioctl_thread_t proc) 236169412Sscottl{ 237175942Sscottl struct hpt_iop_hba *hba = hba_from_dev(dev); 238169412Sscottl hba->flag &= ~(u_int32_t)HPT_IOCTL_FLAG_OPEN; 239169412Sscottl return 0; 240169412Sscottl} 241169412Sscottl 242169412Sscottlstatic int hptiop_ioctl(ioctl_dev_t dev, u_long cmd, caddr_t data, 243169412Sscottl int flags, ioctl_thread_t proc) 244169412Sscottl{ 245169412Sscottl int ret = EFAULT; 246175942Sscottl struct hpt_iop_hba *hba = hba_from_dev(dev); 247169412Sscottl 248169412Sscottl#if (__FreeBSD_version >= 500000) 249169412Sscottl mtx_lock(&Giant); 250169412Sscottl#endif 251169412Sscottl 252169412Sscottl switch (cmd) { 253169412Sscottl case HPT_DO_IOCONTROL: 254175942Sscottl ret = hba->ops->do_ioctl(hba, 255175942Sscottl (struct hpt_iop_ioctl_param *)data); 256169412Sscottl break; 257169412Sscottl case HPT_SCAN_BUS: 258169412Sscottl ret = hptiop_rescan_bus(hba); 259169412Sscottl break; 260169412Sscottl } 261169412Sscottl 262169412Sscottl#if (__FreeBSD_version >= 500000) 263169412Sscottl mtx_unlock(&Giant); 264169412Sscottl#endif 265169412Sscottl 266169412Sscottl return ret; 267169412Sscottl} 268169412Sscottl 269175942Sscottlstatic u_int64_t hptiop_mv_outbound_read(struct hpt_iop_hba *hba) 270169412Sscottl{ 271175942Sscottl u_int64_t p; 272175942Sscottl u_int32_t outbound_tail = BUS_SPACE_RD4_MV2(outbound_tail); 273175942Sscottl u_int32_t outbound_head = BUS_SPACE_RD4_MV2(outbound_head); 274175942Sscottl 275175942Sscottl if (outbound_tail != outbound_head) { 276175942Sscottl bus_space_read_region_4(hba->bar2t, hba->bar2h, 277175942Sscottl offsetof(struct hpt_iopmu_mv, 278175942Sscottl outbound_q[outbound_tail]), 279175942Sscottl (u_int32_t *)&p, 2); 280175942Sscottl 281175942Sscottl outbound_tail++; 282175942Sscottl 283175942Sscottl if (outbound_tail == MVIOP_QUEUE_LEN) 284175942Sscottl outbound_tail = 0; 285175942Sscottl 286175942Sscottl BUS_SPACE_WRT4_MV2(outbound_tail, outbound_tail); 287175942Sscottl return p; 288175942Sscottl } else 289175942Sscottl return 0; 290169412Sscottl} 291169412Sscottl 292175942Sscottlstatic void hptiop_mv_inbound_write(u_int64_t p, struct hpt_iop_hba *hba) 293169412Sscottl{ 294175942Sscottl u_int32_t inbound_head = BUS_SPACE_RD4_MV2(inbound_head); 295175942Sscottl u_int32_t head = inbound_head + 1; 296175942Sscottl 297175942Sscottl if (head == MVIOP_QUEUE_LEN) 298175942Sscottl head = 0; 299175942Sscottl 300175942Sscottl bus_space_write_region_4(hba->bar2t, hba->bar2h, 301175942Sscottl offsetof(struct hpt_iopmu_mv, inbound_q[inbound_head]), 302175942Sscottl (u_int32_t *)&p, 2); 303175942Sscottl BUS_SPACE_WRT4_MV2(inbound_head, head); 304175942Sscottl BUS_SPACE_WRT4_MV0(inbound_doorbell, MVIOP_MU_INBOUND_INT_POSTQUEUE); 305169412Sscottl} 306169412Sscottl 307175942Sscottlstatic void hptiop_post_msg_itl(struct hpt_iop_hba *hba, u_int32_t msg) 308169412Sscottl{ 309175942Sscottl BUS_SPACE_WRT4_ITL(inbound_msgaddr0, msg); 310175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 311169412Sscottl} 312169412Sscottl 313175942Sscottlstatic void hptiop_post_msg_mv(struct hpt_iop_hba *hba, u_int32_t msg) 314169412Sscottl{ 315175942Sscottl 316175942Sscottl BUS_SPACE_WRT4_MV2(inbound_msg, msg); 317175942Sscottl BUS_SPACE_WRT4_MV0(inbound_doorbell, MVIOP_MU_INBOUND_INT_MSG); 318175942Sscottl 319175942Sscottl BUS_SPACE_RD4_MV0(outbound_intmask); 320169412Sscottl} 321169412Sscottl 322242214Sdelphijstatic void hptiop_post_msg_mvfrey(struct hpt_iop_hba *hba, u_int32_t msg) 323242214Sdelphij{ 324242214Sdelphij BUS_SPACE_WRT4_MVFREY2(f0_to_cpu_msg_a, msg); 325242214Sdelphij BUS_SPACE_RD4_MVFREY2(f0_to_cpu_msg_a); 326242214Sdelphij} 327242214Sdelphij 328175942Sscottlstatic int hptiop_wait_ready_itl(struct hpt_iop_hba * hba, u_int32_t millisec) 329169412Sscottl{ 330169412Sscottl u_int32_t req=0; 331169412Sscottl int i; 332169412Sscottl 333169412Sscottl for (i = 0; i < millisec; i++) { 334175942Sscottl req = BUS_SPACE_RD4_ITL(inbound_queue); 335169412Sscottl if (req != IOPMU_QUEUE_EMPTY) 336169412Sscottl break; 337169412Sscottl DELAY(1000); 338169412Sscottl } 339169412Sscottl 340169412Sscottl if (req!=IOPMU_QUEUE_EMPTY) { 341175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req); 342175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 343169412Sscottl return 0; 344169412Sscottl } 345169412Sscottl 346169412Sscottl return -1; 347169412Sscottl} 348169412Sscottl 349175942Sscottlstatic int hptiop_wait_ready_mv(struct hpt_iop_hba * hba, u_int32_t millisec) 350169412Sscottl{ 351175942Sscottl if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec)) 352175942Sscottl return -1; 353175942Sscottl 354175942Sscottl return 0; 355175942Sscottl} 356175942Sscottl 357242214Sdelphijstatic int hptiop_wait_ready_mvfrey(struct hpt_iop_hba * hba, 358242214Sdelphij u_int32_t millisec) 359242214Sdelphij{ 360242214Sdelphij if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec)) 361242214Sdelphij return -1; 362242214Sdelphij 363242214Sdelphij return 0; 364242214Sdelphij} 365242214Sdelphij 366175942Sscottlstatic void hptiop_request_callback_itl(struct hpt_iop_hba * hba, 367175942Sscottl u_int32_t index) 368175942Sscottl{ 369175942Sscottl struct hpt_iop_srb *srb; 370175942Sscottl struct hpt_iop_request_scsi_command *req=0; 371175942Sscottl union ccb *ccb; 372175942Sscottl u_int8_t *cdb; 373175942Sscottl u_int32_t result, temp, dxfer; 374175942Sscottl u_int64_t temp64; 375175942Sscottl 376175942Sscottl if (index & IOPMU_QUEUE_MASK_HOST_BITS) { /*host req*/ 377175942Sscottl if (hba->firmware_version > 0x01020000 || 378175942Sscottl hba->interface_version > 0x01020000) { 379175942Sscottl srb = hba->srb[index & ~(u_int32_t) 380175942Sscottl (IOPMU_QUEUE_ADDR_HOST_BIT 381175942Sscottl | IOPMU_QUEUE_REQUEST_RESULT_BIT)]; 382175942Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 383175942Sscottl if (index & IOPMU_QUEUE_REQUEST_RESULT_BIT) 384175942Sscottl result = IOP_RESULT_SUCCESS; 385175942Sscottl else 386175942Sscottl result = req->header.result; 387175942Sscottl } else { 388175942Sscottl srb = hba->srb[index & 389175942Sscottl ~(u_int32_t)IOPMU_QUEUE_ADDR_HOST_BIT]; 390175942Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 391175942Sscottl result = req->header.result; 392175942Sscottl } 393175942Sscottl dxfer = req->dataxfer_length; 394175942Sscottl goto srb_complete; 395175942Sscottl } 396175942Sscottl 397175942Sscottl /*iop req*/ 398175942Sscottl temp = bus_space_read_4(hba->bar0t, hba->bar0h, index + 399175942Sscottl offsetof(struct hpt_iop_request_header, type)); 400175942Sscottl result = bus_space_read_4(hba->bar0t, hba->bar0h, index + 401175942Sscottl offsetof(struct hpt_iop_request_header, result)); 402175942Sscottl switch(temp) { 403175942Sscottl case IOP_REQUEST_TYPE_IOCTL_COMMAND: 404175942Sscottl { 405175942Sscottl temp64 = 0; 406175942Sscottl bus_space_write_region_4(hba->bar0t, hba->bar0h, index + 407175942Sscottl offsetof(struct hpt_iop_request_header, context), 408175942Sscottl (u_int32_t *)&temp64, 2); 409175942Sscottl wakeup((void *)((unsigned long)hba->u.itl.mu + index)); 410175942Sscottl break; 411175942Sscottl } 412175942Sscottl 413175942Sscottl case IOP_REQUEST_TYPE_SCSI_COMMAND: 414175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h, index + 415175942Sscottl offsetof(struct hpt_iop_request_header, context), 416175942Sscottl (u_int32_t *)&temp64, 2); 417175942Sscottl srb = (struct hpt_iop_srb *)(unsigned long)temp64; 418175942Sscottl dxfer = bus_space_read_4(hba->bar0t, hba->bar0h, 419175942Sscottl index + offsetof(struct hpt_iop_request_scsi_command, 420175942Sscottl dataxfer_length)); 421175942Sscottlsrb_complete: 422175942Sscottl ccb = (union ccb *)srb->ccb; 423175942Sscottl if (ccb->ccb_h.flags & CAM_CDB_POINTER) 424175942Sscottl cdb = ccb->csio.cdb_io.cdb_ptr; 425175942Sscottl else 426175942Sscottl cdb = ccb->csio.cdb_io.cdb_bytes; 427175942Sscottl 428175942Sscottl if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */ 429175942Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 430175942Sscottl goto scsi_done; 431175942Sscottl } 432175942Sscottl 433175942Sscottl switch (result) { 434175942Sscottl case IOP_RESULT_SUCCESS: 435175942Sscottl switch (ccb->ccb_h.flags & CAM_DIR_MASK) { 436175942Sscottl case CAM_DIR_IN: 437175942Sscottl bus_dmamap_sync(hba->io_dmat, 438175942Sscottl srb->dma_map, BUS_DMASYNC_POSTREAD); 439175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 440175942Sscottl break; 441175942Sscottl case CAM_DIR_OUT: 442175942Sscottl bus_dmamap_sync(hba->io_dmat, 443175942Sscottl srb->dma_map, BUS_DMASYNC_POSTWRITE); 444175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 445175942Sscottl break; 446175942Sscottl } 447175942Sscottl 448175942Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 449175942Sscottl break; 450175942Sscottl 451175942Sscottl case IOP_RESULT_BAD_TARGET: 452175942Sscottl ccb->ccb_h.status = CAM_DEV_NOT_THERE; 453175942Sscottl break; 454175942Sscottl case IOP_RESULT_BUSY: 455175942Sscottl ccb->ccb_h.status = CAM_BUSY; 456175942Sscottl break; 457175942Sscottl case IOP_RESULT_INVALID_REQUEST: 458175942Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 459175942Sscottl break; 460175942Sscottl case IOP_RESULT_FAIL: 461175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 462175942Sscottl break; 463175942Sscottl case IOP_RESULT_RESET: 464175942Sscottl ccb->ccb_h.status = CAM_BUSY; 465175942Sscottl break; 466175942Sscottl case IOP_RESULT_CHECK_CONDITION: 467226910Smarius memset(&ccb->csio.sense_data, 0, 468226910Smarius sizeof(ccb->csio.sense_data)); 469226910Smarius if (dxfer < ccb->csio.sense_len) 470226910Smarius ccb->csio.sense_resid = ccb->csio.sense_len - 471226910Smarius dxfer; 472226910Smarius else 473226910Smarius ccb->csio.sense_resid = 0; 474175942Sscottl if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) {/*iop*/ 475175942Sscottl bus_space_read_region_1(hba->bar0t, hba->bar0h, 476175942Sscottl index + offsetof(struct hpt_iop_request_scsi_command, 477175942Sscottl sg_list), (u_int8_t *)&ccb->csio.sense_data, 478175942Sscottl MIN(dxfer, sizeof(ccb->csio.sense_data))); 479175942Sscottl } else { 480175942Sscottl memcpy(&ccb->csio.sense_data, &req->sg_list, 481175942Sscottl MIN(dxfer, sizeof(ccb->csio.sense_data))); 482175942Sscottl } 483175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 484175942Sscottl ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 485175942Sscottl ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 486175942Sscottl break; 487175942Sscottl default: 488175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 489175942Sscottl break; 490175942Sscottl } 491175942Sscottlscsi_done: 492175942Sscottl if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) 493175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, index); 494175942Sscottl 495175942Sscottl ccb->csio.resid = ccb->csio.dxfer_len - dxfer; 496175942Sscottl 497175942Sscottl hptiop_free_srb(hba, srb); 498175942Sscottl xpt_done(ccb); 499175942Sscottl break; 500175942Sscottl } 501175942Sscottl} 502175942Sscottl 503175942Sscottlstatic void hptiop_drain_outbound_queue_itl(struct hpt_iop_hba *hba) 504175942Sscottl{ 505175942Sscottl u_int32_t req, temp; 506175942Sscottl 507175942Sscottl while ((req = BUS_SPACE_RD4_ITL(outbound_queue)) !=IOPMU_QUEUE_EMPTY) { 508175942Sscottl if (req & IOPMU_QUEUE_MASK_HOST_BITS) 509175942Sscottl hptiop_request_callback_itl(hba, req); 510175942Sscottl else { 511175942Sscottl struct hpt_iop_request_header *p; 512175942Sscottl 513175942Sscottl p = (struct hpt_iop_request_header *) 514175942Sscottl ((char *)hba->u.itl.mu + req); 515175942Sscottl temp = bus_space_read_4(hba->bar0t, 516175942Sscottl hba->bar0h,req + 517175942Sscottl offsetof(struct hpt_iop_request_header, 518175942Sscottl flags)); 519175942Sscottl if (temp & IOP_REQUEST_FLAG_SYNC_REQUEST) { 520175942Sscottl u_int64_t temp64; 521175942Sscottl bus_space_read_region_4(hba->bar0t, 522175942Sscottl hba->bar0h,req + 523175942Sscottl offsetof(struct hpt_iop_request_header, 524175942Sscottl context), 525175942Sscottl (u_int32_t *)&temp64, 2); 526175942Sscottl if (temp64) { 527175942Sscottl hptiop_request_callback_itl(hba, req); 528175942Sscottl } else { 529175942Sscottl temp64 = 1; 530175942Sscottl bus_space_write_region_4(hba->bar0t, 531175942Sscottl hba->bar0h,req + 532175942Sscottl offsetof(struct hpt_iop_request_header, 533175942Sscottl context), 534175942Sscottl (u_int32_t *)&temp64, 2); 535175942Sscottl } 536175942Sscottl } else 537175942Sscottl hptiop_request_callback_itl(hba, req); 538175942Sscottl } 539175942Sscottl } 540175942Sscottl} 541175942Sscottl 542175942Sscottlstatic int hptiop_intr_itl(struct hpt_iop_hba * hba) 543175942Sscottl{ 544169412Sscottl u_int32_t status; 545169412Sscottl int ret = 0; 546169412Sscottl 547175942Sscottl status = BUS_SPACE_RD4_ITL(outbound_intstatus); 548169412Sscottl 549169412Sscottl if (status & IOPMU_OUTBOUND_INT_MSG0) { 550175942Sscottl u_int32_t msg = BUS_SPACE_RD4_ITL(outbound_msgaddr0); 551175942Sscottl KdPrint(("hptiop: received outbound msg %x\n", msg)); 552175942Sscottl BUS_SPACE_WRT4_ITL(outbound_intstatus, IOPMU_OUTBOUND_INT_MSG0); 553175942Sscottl hptiop_os_message_callback(hba, msg); 554169412Sscottl ret = 1; 555169412Sscottl } 556169412Sscottl 557169412Sscottl if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) { 558175942Sscottl hptiop_drain_outbound_queue_itl(hba); 559175942Sscottl ret = 1; 560175942Sscottl } 561175942Sscottl 562175942Sscottl return ret; 563175942Sscottl} 564175942Sscottl 565175942Sscottlstatic void hptiop_request_callback_mv(struct hpt_iop_hba * hba, 566175942Sscottl u_int64_t _tag) 567175942Sscottl{ 568175942Sscottl u_int32_t context = (u_int32_t)_tag; 569175942Sscottl 570175942Sscottl if (context & MVIOP_CMD_TYPE_SCSI) { 571175942Sscottl struct hpt_iop_srb *srb; 572175942Sscottl struct hpt_iop_request_scsi_command *req; 573175942Sscottl union ccb *ccb; 574175942Sscottl u_int8_t *cdb; 575175942Sscottl 576175942Sscottl srb = hba->srb[context >> MVIOP_REQUEST_NUMBER_START_BIT]; 577175942Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 578175942Sscottl ccb = (union ccb *)srb->ccb; 579175942Sscottl if (ccb->ccb_h.flags & CAM_CDB_POINTER) 580175942Sscottl cdb = ccb->csio.cdb_io.cdb_ptr; 581175942Sscottl else 582175942Sscottl cdb = ccb->csio.cdb_io.cdb_bytes; 583175942Sscottl 584175942Sscottl if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */ 585175942Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 586175942Sscottl goto scsi_done; 587175942Sscottl } 588175942Sscottl if (context & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT) 589175942Sscottl req->header.result = IOP_RESULT_SUCCESS; 590175942Sscottl 591175942Sscottl switch (req->header.result) { 592175942Sscottl case IOP_RESULT_SUCCESS: 593175942Sscottl switch (ccb->ccb_h.flags & CAM_DIR_MASK) { 594175942Sscottl case CAM_DIR_IN: 595175942Sscottl bus_dmamap_sync(hba->io_dmat, 596175942Sscottl srb->dma_map, BUS_DMASYNC_POSTREAD); 597175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 598175942Sscottl break; 599175942Sscottl case CAM_DIR_OUT: 600175942Sscottl bus_dmamap_sync(hba->io_dmat, 601175942Sscottl srb->dma_map, BUS_DMASYNC_POSTWRITE); 602175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 603175942Sscottl break; 604169412Sscottl } 605175942Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 606175942Sscottl break; 607175942Sscottl case IOP_RESULT_BAD_TARGET: 608175942Sscottl ccb->ccb_h.status = CAM_DEV_NOT_THERE; 609175942Sscottl break; 610175942Sscottl case IOP_RESULT_BUSY: 611175942Sscottl ccb->ccb_h.status = CAM_BUSY; 612175942Sscottl break; 613175942Sscottl case IOP_RESULT_INVALID_REQUEST: 614175942Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 615175942Sscottl break; 616175942Sscottl case IOP_RESULT_FAIL: 617175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 618175942Sscottl break; 619175942Sscottl case IOP_RESULT_RESET: 620175942Sscottl ccb->ccb_h.status = CAM_BUSY; 621175942Sscottl break; 622175942Sscottl case IOP_RESULT_CHECK_CONDITION: 623226910Smarius memset(&ccb->csio.sense_data, 0, 624226910Smarius sizeof(ccb->csio.sense_data)); 625226910Smarius if (req->dataxfer_length < ccb->csio.sense_len) 626226910Smarius ccb->csio.sense_resid = ccb->csio.sense_len - 627226910Smarius req->dataxfer_length; 628226910Smarius else 629226910Smarius ccb->csio.sense_resid = 0; 630175942Sscottl memcpy(&ccb->csio.sense_data, &req->sg_list, 631175942Sscottl MIN(req->dataxfer_length, sizeof(ccb->csio.sense_data))); 632175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 633175942Sscottl ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 634175942Sscottl ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 635175942Sscottl break; 636175942Sscottl default: 637175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 638175942Sscottl break; 639169412Sscottl } 640175942Sscottlscsi_done: 641175942Sscottl ccb->csio.resid = ccb->csio.dxfer_len - req->dataxfer_length; 642175942Sscottl 643175942Sscottl hptiop_free_srb(hba, srb); 644175942Sscottl xpt_done(ccb); 645175942Sscottl } else if (context & MVIOP_CMD_TYPE_IOCTL) { 646175942Sscottl struct hpt_iop_request_ioctl_command *req = hba->ctlcfg_ptr; 647175942Sscottl if (context & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT) 648175942Sscottl hba->config_done = 1; 649175942Sscottl else 650175942Sscottl hba->config_done = -1; 651175942Sscottl wakeup(req); 652175942Sscottl } else if (context & 653175942Sscottl (MVIOP_CMD_TYPE_SET_CONFIG | 654175942Sscottl MVIOP_CMD_TYPE_GET_CONFIG)) 655175942Sscottl hba->config_done = 1; 656175942Sscottl else { 657175942Sscottl device_printf(hba->pcidev, "wrong callback type\n"); 658175942Sscottl } 659175942Sscottl} 660175942Sscottl 661242214Sdelphijstatic void hptiop_request_callback_mvfrey(struct hpt_iop_hba * hba, 662242214Sdelphij u_int32_t _tag) 663242214Sdelphij{ 664242214Sdelphij u_int32_t req_type = _tag & 0xf; 665242214Sdelphij 666242214Sdelphij struct hpt_iop_srb *srb; 667242214Sdelphij struct hpt_iop_request_scsi_command *req; 668242214Sdelphij union ccb *ccb; 669242214Sdelphij u_int8_t *cdb; 670242214Sdelphij 671242214Sdelphij switch (req_type) { 672242214Sdelphij case IOP_REQUEST_TYPE_GET_CONFIG: 673242214Sdelphij case IOP_REQUEST_TYPE_SET_CONFIG: 674242214Sdelphij hba->config_done = 1; 675242214Sdelphij break; 676242214Sdelphij 677242214Sdelphij case IOP_REQUEST_TYPE_SCSI_COMMAND: 678242214Sdelphij srb = hba->srb[(_tag >> 4) & 0xff]; 679242214Sdelphij req = (struct hpt_iop_request_scsi_command *)srb; 680242214Sdelphij 681242214Sdelphij ccb = (union ccb *)srb->ccb; 682242214Sdelphij 683242214Sdelphij untimeout(hptiop_reset_adapter, hba, ccb->ccb_h.timeout_ch); 684242214Sdelphij 685242214Sdelphij if (ccb->ccb_h.flags & CAM_CDB_POINTER) 686242214Sdelphij cdb = ccb->csio.cdb_io.cdb_ptr; 687242214Sdelphij else 688242214Sdelphij cdb = ccb->csio.cdb_io.cdb_bytes; 689242214Sdelphij 690242214Sdelphij if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */ 691242214Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 692242214Sdelphij goto scsi_done; 693242214Sdelphij } 694242214Sdelphij 695242214Sdelphij if (_tag & MVFREYIOPMU_QUEUE_REQUEST_RESULT_BIT) 696242214Sdelphij req->header.result = IOP_RESULT_SUCCESS; 697242214Sdelphij 698242214Sdelphij switch (req->header.result) { 699242214Sdelphij case IOP_RESULT_SUCCESS: 700242214Sdelphij switch (ccb->ccb_h.flags & CAM_DIR_MASK) { 701242214Sdelphij case CAM_DIR_IN: 702242214Sdelphij bus_dmamap_sync(hba->io_dmat, 703242214Sdelphij srb->dma_map, BUS_DMASYNC_POSTREAD); 704242214Sdelphij bus_dmamap_unload(hba->io_dmat, srb->dma_map); 705242214Sdelphij break; 706242214Sdelphij case CAM_DIR_OUT: 707242214Sdelphij bus_dmamap_sync(hba->io_dmat, 708242214Sdelphij srb->dma_map, BUS_DMASYNC_POSTWRITE); 709242214Sdelphij bus_dmamap_unload(hba->io_dmat, srb->dma_map); 710242214Sdelphij break; 711242214Sdelphij } 712242214Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 713242214Sdelphij break; 714242214Sdelphij case IOP_RESULT_BAD_TARGET: 715242214Sdelphij ccb->ccb_h.status = CAM_DEV_NOT_THERE; 716242214Sdelphij break; 717242214Sdelphij case IOP_RESULT_BUSY: 718242214Sdelphij ccb->ccb_h.status = CAM_BUSY; 719242214Sdelphij break; 720242214Sdelphij case IOP_RESULT_INVALID_REQUEST: 721242214Sdelphij ccb->ccb_h.status = CAM_REQ_INVALID; 722242214Sdelphij break; 723242214Sdelphij case IOP_RESULT_FAIL: 724242214Sdelphij ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 725242214Sdelphij break; 726242214Sdelphij case IOP_RESULT_RESET: 727242214Sdelphij ccb->ccb_h.status = CAM_BUSY; 728242214Sdelphij break; 729242214Sdelphij case IOP_RESULT_CHECK_CONDITION: 730242214Sdelphij memset(&ccb->csio.sense_data, 0, 731242214Sdelphij sizeof(ccb->csio.sense_data)); 732242214Sdelphij if (req->dataxfer_length < ccb->csio.sense_len) 733242214Sdelphij ccb->csio.sense_resid = ccb->csio.sense_len - 734242214Sdelphij req->dataxfer_length; 735242214Sdelphij else 736242214Sdelphij ccb->csio.sense_resid = 0; 737242214Sdelphij memcpy(&ccb->csio.sense_data, &req->sg_list, 738242214Sdelphij MIN(req->dataxfer_length, sizeof(ccb->csio.sense_data))); 739242214Sdelphij ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 740242214Sdelphij ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 741242214Sdelphij ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 742242214Sdelphij break; 743242214Sdelphij default: 744242214Sdelphij ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 745242214Sdelphij break; 746242214Sdelphij } 747242214Sdelphijscsi_done: 748242214Sdelphij ccb->csio.resid = ccb->csio.dxfer_len - req->dataxfer_length; 749242214Sdelphij 750242214Sdelphij hptiop_free_srb(hba, srb); 751242214Sdelphij xpt_done(ccb); 752242214Sdelphij break; 753242214Sdelphij case IOP_REQUEST_TYPE_IOCTL_COMMAND: 754242214Sdelphij if (_tag & MVFREYIOPMU_QUEUE_REQUEST_RESULT_BIT) 755242214Sdelphij hba->config_done = 1; 756242214Sdelphij else 757242214Sdelphij hba->config_done = -1; 758242214Sdelphij wakeup((struct hpt_iop_request_ioctl_command *)hba->ctlcfg_ptr); 759242214Sdelphij break; 760242214Sdelphij default: 761242214Sdelphij device_printf(hba->pcidev, "wrong callback type\n"); 762242214Sdelphij break; 763242214Sdelphij } 764242214Sdelphij} 765242214Sdelphij 766175942Sscottlstatic void hptiop_drain_outbound_queue_mv(struct hpt_iop_hba * hba) 767175942Sscottl{ 768175942Sscottl u_int64_t req; 769175942Sscottl 770175942Sscottl while ((req = hptiop_mv_outbound_read(hba))) { 771175942Sscottl if (req & MVIOP_MU_QUEUE_ADDR_HOST_BIT) { 772175942Sscottl if (req & MVIOP_MU_QUEUE_REQUEST_RETURN_CONTEXT) { 773175942Sscottl hptiop_request_callback_mv(hba, req); 774175942Sscottl } 775175942Sscottl } 776175942Sscottl } 777175942Sscottl} 778175942Sscottl 779175942Sscottlstatic int hptiop_intr_mv(struct hpt_iop_hba * hba) 780175942Sscottl{ 781175942Sscottl u_int32_t status; 782175942Sscottl int ret = 0; 783175942Sscottl 784175942Sscottl status = BUS_SPACE_RD4_MV0(outbound_doorbell); 785175942Sscottl 786175942Sscottl if (status) 787175942Sscottl BUS_SPACE_WRT4_MV0(outbound_doorbell, ~status); 788175942Sscottl 789175942Sscottl if (status & MVIOP_MU_OUTBOUND_INT_MSG) { 790175942Sscottl u_int32_t msg = BUS_SPACE_RD4_MV2(outbound_msg); 791175942Sscottl KdPrint(("hptiop: received outbound msg %x\n", msg)); 792175942Sscottl hptiop_os_message_callback(hba, msg); 793169412Sscottl ret = 1; 794169412Sscottl } 795175942Sscottl 796175942Sscottl if (status & MVIOP_MU_OUTBOUND_INT_POSTQUEUE) { 797175942Sscottl hptiop_drain_outbound_queue_mv(hba); 798175942Sscottl ret = 1; 799175942Sscottl } 800175942Sscottl 801169412Sscottl return ret; 802169412Sscottl} 803169412Sscottl 804242214Sdelphijstatic int hptiop_intr_mvfrey(struct hpt_iop_hba * hba) 805242214Sdelphij{ 806242214Sdelphij u_int32_t status, _tag, cptr; 807242214Sdelphij int ret = 0; 808242214Sdelphij 809242214Sdelphij if (hba->initialized) { 810242214Sdelphij BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0); 811242214Sdelphij } 812242214Sdelphij 813242214Sdelphij status = BUS_SPACE_RD4_MVFREY2(f0_doorbell); 814242214Sdelphij if (status) { 815242214Sdelphij BUS_SPACE_WRT4_MVFREY2(f0_doorbell, status); 816242214Sdelphij if (status & CPU_TO_F0_DRBL_MSG_A_BIT) { 817242214Sdelphij u_int32_t msg = BUS_SPACE_RD4_MVFREY2(cpu_to_f0_msg_a); 818242214Sdelphij hptiop_os_message_callback(hba, msg); 819242214Sdelphij } 820242214Sdelphij ret = 1; 821242214Sdelphij } 822242214Sdelphij 823242214Sdelphij status = BUS_SPACE_RD4_MVFREY2(isr_cause); 824242214Sdelphij if (status) { 825242214Sdelphij BUS_SPACE_WRT4_MVFREY2(isr_cause, status); 826242214Sdelphij do { 827242214Sdelphij cptr = *hba->u.mvfrey.outlist_cptr & 0xff; 828242214Sdelphij while (hba->u.mvfrey.outlist_rptr != cptr) { 829242214Sdelphij hba->u.mvfrey.outlist_rptr++; 830242214Sdelphij if (hba->u.mvfrey.outlist_rptr == hba->u.mvfrey.list_count) { 831242214Sdelphij hba->u.mvfrey.outlist_rptr = 0; 832242214Sdelphij } 833242214Sdelphij 834242214Sdelphij _tag = hba->u.mvfrey.outlist[hba->u.mvfrey.outlist_rptr].val; 835242214Sdelphij hptiop_request_callback_mvfrey(hba, _tag); 836242214Sdelphij ret = 2; 837242214Sdelphij } 838242214Sdelphij } while (cptr != (*hba->u.mvfrey.outlist_cptr & 0xff)); 839242214Sdelphij } 840242214Sdelphij 841242214Sdelphij if (hba->initialized) { 842242214Sdelphij BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0x1010); 843242214Sdelphij } 844242214Sdelphij 845242214Sdelphij return ret; 846242214Sdelphij} 847242214Sdelphij 848175942Sscottlstatic int hptiop_send_sync_request_itl(struct hpt_iop_hba * hba, 849175942Sscottl u_int32_t req32, u_int32_t millisec) 850169412Sscottl{ 851169412Sscottl u_int32_t i; 852175942Sscottl u_int64_t temp64; 853169412Sscottl 854175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue, req32); 855175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 856169412Sscottl 857169412Sscottl for (i = 0; i < millisec; i++) { 858175942Sscottl hptiop_intr_itl(hba); 859175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h, req32 + 860175942Sscottl offsetof(struct hpt_iop_request_header, context), 861175942Sscottl (u_int32_t *)&temp64, 2); 862175942Sscottl if (temp64) 863169412Sscottl return 0; 864169412Sscottl DELAY(1000); 865169412Sscottl } 866169412Sscottl 867169412Sscottl return -1; 868169412Sscottl} 869169412Sscottl 870175942Sscottlstatic int hptiop_send_sync_request_mv(struct hpt_iop_hba *hba, 871175942Sscottl void *req, u_int32_t millisec) 872169412Sscottl{ 873169412Sscottl u_int32_t i; 874175942Sscottl u_int64_t phy_addr; 875175942Sscottl hba->config_done = 0; 876169412Sscottl 877175942Sscottl phy_addr = hba->ctlcfgcmd_phy | 878175942Sscottl (u_int64_t)MVIOP_MU_QUEUE_ADDR_HOST_BIT; 879175942Sscottl ((struct hpt_iop_request_get_config *)req)->header.flags |= 880175942Sscottl IOP_REQUEST_FLAG_SYNC_REQUEST | 881175942Sscottl IOP_REQUEST_FLAG_OUTPUT_CONTEXT; 882175942Sscottl hptiop_mv_inbound_write(phy_addr, hba); 883175942Sscottl BUS_SPACE_RD4_MV0(outbound_intmask); 884169412Sscottl 885175942Sscottl for (i = 0; i < millisec; i++) { 886175942Sscottl hptiop_intr_mv(hba); 887175942Sscottl if (hba->config_done) 888175942Sscottl return 0; 889175942Sscottl DELAY(1000); 890175942Sscottl } 891175942Sscottl return -1; 892175942Sscottl} 893169412Sscottl 894242214Sdelphijstatic int hptiop_send_sync_request_mvfrey(struct hpt_iop_hba *hba, 895242214Sdelphij void *req, u_int32_t millisec) 896242214Sdelphij{ 897242214Sdelphij u_int32_t i, index; 898242214Sdelphij u_int64_t phy_addr; 899242214Sdelphij struct hpt_iop_request_header *reqhdr = 900242214Sdelphij (struct hpt_iop_request_header *)req; 901242214Sdelphij 902242214Sdelphij hba->config_done = 0; 903242214Sdelphij 904242214Sdelphij phy_addr = hba->ctlcfgcmd_phy; 905242214Sdelphij reqhdr->flags = IOP_REQUEST_FLAG_SYNC_REQUEST 906242214Sdelphij | IOP_REQUEST_FLAG_OUTPUT_CONTEXT 907242214Sdelphij | IOP_REQUEST_FLAG_ADDR_BITS 908242214Sdelphij | ((phy_addr >> 16) & 0xffff0000); 909242214Sdelphij reqhdr->context = ((phy_addr & 0xffffffff) << 32 ) 910242214Sdelphij | IOPMU_QUEUE_ADDR_HOST_BIT | reqhdr->type; 911242214Sdelphij 912242214Sdelphij hba->u.mvfrey.inlist_wptr++; 913242214Sdelphij index = hba->u.mvfrey.inlist_wptr & 0x3fff; 914242214Sdelphij 915242214Sdelphij if (index == hba->u.mvfrey.list_count) { 916242214Sdelphij index = 0; 917242214Sdelphij hba->u.mvfrey.inlist_wptr &= ~0x3fff; 918242214Sdelphij hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE; 919242214Sdelphij } 920242214Sdelphij 921242214Sdelphij hba->u.mvfrey.inlist[index].addr = phy_addr; 922242214Sdelphij hba->u.mvfrey.inlist[index].intrfc_len = (reqhdr->size + 3) / 4; 923242214Sdelphij 924242214Sdelphij BUS_SPACE_WRT4_MVFREY2(inbound_write_ptr, hba->u.mvfrey.inlist_wptr); 925242214Sdelphij BUS_SPACE_RD4_MVFREY2(inbound_write_ptr); 926242214Sdelphij 927242214Sdelphij for (i = 0; i < millisec; i++) { 928242214Sdelphij hptiop_intr_mvfrey(hba); 929242214Sdelphij if (hba->config_done) 930242214Sdelphij return 0; 931242214Sdelphij DELAY(1000); 932242214Sdelphij } 933242214Sdelphij return -1; 934242214Sdelphij} 935242214Sdelphij 936175942Sscottlstatic int hptiop_send_sync_msg(struct hpt_iop_hba *hba, 937175942Sscottl u_int32_t msg, u_int32_t millisec) 938175942Sscottl{ 939175942Sscottl u_int32_t i; 940169412Sscottl 941175942Sscottl hba->msg_done = 0; 942175942Sscottl hba->ops->post_msg(hba, msg); 943175942Sscottl 944175942Sscottl for (i=0; i<millisec; i++) { 945175942Sscottl hba->ops->iop_intr(hba); 946175942Sscottl if (hba->msg_done) 947169412Sscottl break; 948169412Sscottl DELAY(1000); 949169412Sscottl } 950169412Sscottl 951175942Sscottl return hba->msg_done? 0 : -1; 952169412Sscottl} 953169412Sscottl 954175942Sscottlstatic int hptiop_get_config_itl(struct hpt_iop_hba * hba, 955175942Sscottl struct hpt_iop_request_get_config * config) 956169412Sscottl{ 957175942Sscottl u_int32_t req32; 958169412Sscottl 959175942Sscottl config->header.size = sizeof(struct hpt_iop_request_get_config); 960175942Sscottl config->header.type = IOP_REQUEST_TYPE_GET_CONFIG; 961175942Sscottl config->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST; 962175942Sscottl config->header.result = IOP_RESULT_PENDING; 963175942Sscottl config->header.context = 0; 964175942Sscottl 965175942Sscottl req32 = BUS_SPACE_RD4_ITL(inbound_queue); 966175942Sscottl if (req32 == IOPMU_QUEUE_EMPTY) 967169412Sscottl return -1; 968169412Sscottl 969175942Sscottl bus_space_write_region_4(hba->bar0t, hba->bar0h, 970175942Sscottl req32, (u_int32_t *)config, 971175942Sscottl sizeof(struct hpt_iop_request_header) >> 2); 972175942Sscottl 973175942Sscottl if (hptiop_send_sync_request_itl(hba, req32, 20000)) { 974175942Sscottl KdPrint(("hptiop: get config send cmd failed")); 975175942Sscottl return -1; 976175942Sscottl } 977175942Sscottl 978175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h, 979175942Sscottl req32, (u_int32_t *)config, 980175942Sscottl sizeof(struct hpt_iop_request_get_config) >> 2); 981175942Sscottl 982175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req32); 983175942Sscottl 984175942Sscottl return 0; 985175942Sscottl} 986175942Sscottl 987175942Sscottlstatic int hptiop_get_config_mv(struct hpt_iop_hba * hba, 988175942Sscottl struct hpt_iop_request_get_config * config) 989175942Sscottl{ 990175942Sscottl struct hpt_iop_request_get_config *req; 991175942Sscottl 992175942Sscottl if (!(req = hba->ctlcfg_ptr)) 993175942Sscottl return -1; 994175942Sscottl 995169412Sscottl req->header.flags = 0; 996169412Sscottl req->header.type = IOP_REQUEST_TYPE_GET_CONFIG; 997169412Sscottl req->header.size = sizeof(struct hpt_iop_request_get_config); 998169412Sscottl req->header.result = IOP_RESULT_PENDING; 999175942Sscottl req->header.context = MVIOP_CMD_TYPE_GET_CONFIG; 1000169412Sscottl 1001175942Sscottl if (hptiop_send_sync_request_mv(hba, req, 20000)) { 1002175942Sscottl KdPrint(("hptiop: get config send cmd failed")); 1003169412Sscottl return -1; 1004169412Sscottl } 1005169412Sscottl 1006169412Sscottl *config = *req; 1007169412Sscottl return 0; 1008169412Sscottl} 1009169412Sscottl 1010242214Sdelphijstatic int hptiop_get_config_mvfrey(struct hpt_iop_hba * hba, 1011242214Sdelphij struct hpt_iop_request_get_config * config) 1012242214Sdelphij{ 1013242214Sdelphij struct hpt_iop_request_get_config *info = hba->u.mvfrey.config; 1014242214Sdelphij 1015242214Sdelphij if (info->header.size != sizeof(struct hpt_iop_request_get_config) || 1016242214Sdelphij info->header.type != IOP_REQUEST_TYPE_GET_CONFIG) { 1017242214Sdelphij KdPrint(("hptiop: header size %x/%x type %x/%x", 1018242214Sdelphij info->header.size, (int)sizeof(struct hpt_iop_request_get_config), 1019242214Sdelphij info->header.type, IOP_REQUEST_TYPE_GET_CONFIG)); 1020242214Sdelphij return -1; 1021242214Sdelphij } 1022242214Sdelphij 1023242214Sdelphij config->interface_version = info->interface_version; 1024242214Sdelphij config->firmware_version = info->firmware_version; 1025242214Sdelphij config->max_requests = info->max_requests; 1026242214Sdelphij config->request_size = info->request_size; 1027242214Sdelphij config->max_sg_count = info->max_sg_count; 1028242214Sdelphij config->data_transfer_length = info->data_transfer_length; 1029242214Sdelphij config->alignment_mask = info->alignment_mask; 1030242214Sdelphij config->max_devices = info->max_devices; 1031242214Sdelphij config->sdram_size = info->sdram_size; 1032242214Sdelphij 1033242214Sdelphij KdPrint(("hptiop: maxreq %x reqsz %x datalen %x maxdev %x sdram %x", 1034242214Sdelphij config->max_requests, config->request_size, 1035242214Sdelphij config->data_transfer_length, config->max_devices, 1036242214Sdelphij config->sdram_size)); 1037242214Sdelphij 1038242214Sdelphij return 0; 1039242214Sdelphij} 1040242214Sdelphij 1041175942Sscottlstatic int hptiop_set_config_itl(struct hpt_iop_hba *hba, 1042175942Sscottl struct hpt_iop_request_set_config *config) 1043169412Sscottl{ 1044169412Sscottl u_int32_t req32; 1045169412Sscottl 1046175942Sscottl req32 = BUS_SPACE_RD4_ITL(inbound_queue); 1047175942Sscottl 1048169412Sscottl if (req32 == IOPMU_QUEUE_EMPTY) 1049169412Sscottl return -1; 1050169412Sscottl 1051175942Sscottl config->header.size = sizeof(struct hpt_iop_request_set_config); 1052175942Sscottl config->header.type = IOP_REQUEST_TYPE_SET_CONFIG; 1053175942Sscottl config->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST; 1054175942Sscottl config->header.result = IOP_RESULT_PENDING; 1055175942Sscottl config->header.context = 0; 1056175942Sscottl 1057175942Sscottl bus_space_write_region_4(hba->bar0t, hba->bar0h, req32, 1058175942Sscottl (u_int32_t *)config, 1059175942Sscottl sizeof(struct hpt_iop_request_set_config) >> 2); 1060175942Sscottl 1061175942Sscottl if (hptiop_send_sync_request_itl(hba, req32, 20000)) { 1062175942Sscottl KdPrint(("hptiop: set config send cmd failed")); 1063175942Sscottl return -1; 1064175942Sscottl } 1065175942Sscottl 1066175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req32); 1067175942Sscottl 1068175942Sscottl return 0; 1069175942Sscottl} 1070175942Sscottl 1071175942Sscottlstatic int hptiop_set_config_mv(struct hpt_iop_hba *hba, 1072175942Sscottl struct hpt_iop_request_set_config *config) 1073175942Sscottl{ 1074175942Sscottl struct hpt_iop_request_set_config *req; 1075175942Sscottl 1076175942Sscottl if (!(req = hba->ctlcfg_ptr)) 1077175942Sscottl return -1; 1078175942Sscottl 1079169412Sscottl memcpy((u_int8_t *)req + sizeof(struct hpt_iop_request_header), 1080169412Sscottl (u_int8_t *)config + sizeof(struct hpt_iop_request_header), 1081175942Sscottl sizeof(struct hpt_iop_request_set_config) - 1082175942Sscottl sizeof(struct hpt_iop_request_header)); 1083175942Sscottl 1084169412Sscottl req->header.flags = 0; 1085169412Sscottl req->header.type = IOP_REQUEST_TYPE_SET_CONFIG; 1086169412Sscottl req->header.size = sizeof(struct hpt_iop_request_set_config); 1087169412Sscottl req->header.result = IOP_RESULT_PENDING; 1088175942Sscottl req->header.context = MVIOP_CMD_TYPE_SET_CONFIG; 1089169412Sscottl 1090175942Sscottl if (hptiop_send_sync_request_mv(hba, req, 20000)) { 1091175942Sscottl KdPrint(("hptiop: set config send cmd failed")); 1092169412Sscottl return -1; 1093169412Sscottl } 1094169412Sscottl 1095169412Sscottl return 0; 1096169412Sscottl} 1097169412Sscottl 1098242214Sdelphijstatic int hptiop_set_config_mvfrey(struct hpt_iop_hba *hba, 1099242214Sdelphij struct hpt_iop_request_set_config *config) 1100242214Sdelphij{ 1101242214Sdelphij struct hpt_iop_request_set_config *req; 1102242214Sdelphij 1103242214Sdelphij if (!(req = hba->ctlcfg_ptr)) 1104242214Sdelphij return -1; 1105242214Sdelphij 1106242214Sdelphij memcpy((u_int8_t *)req + sizeof(struct hpt_iop_request_header), 1107242214Sdelphij (u_int8_t *)config + sizeof(struct hpt_iop_request_header), 1108242214Sdelphij sizeof(struct hpt_iop_request_set_config) - 1109242214Sdelphij sizeof(struct hpt_iop_request_header)); 1110242214Sdelphij 1111242214Sdelphij req->header.type = IOP_REQUEST_TYPE_SET_CONFIG; 1112242214Sdelphij req->header.size = sizeof(struct hpt_iop_request_set_config); 1113242214Sdelphij req->header.result = IOP_RESULT_PENDING; 1114242214Sdelphij 1115242214Sdelphij if (hptiop_send_sync_request_mvfrey(hba, req, 20000)) { 1116242214Sdelphij KdPrint(("hptiop: set config send cmd failed")); 1117242214Sdelphij return -1; 1118242214Sdelphij } 1119242214Sdelphij 1120242214Sdelphij return 0; 1121242214Sdelphij} 1122242214Sdelphij 1123175942Sscottlstatic int hptiop_post_ioctl_command_itl(struct hpt_iop_hba *hba, 1124175942Sscottl u_int32_t req32, 1125175942Sscottl struct hpt_iop_ioctl_param *pParams) 1126169412Sscottl{ 1127175942Sscottl u_int64_t temp64; 1128175942Sscottl struct hpt_iop_request_ioctl_command req; 1129169412Sscottl 1130175942Sscottl if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) > 1131175942Sscottl (hba->max_request_size - 1132175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf))) { 1133175942Sscottl device_printf(hba->pcidev, "request size beyond max value"); 1134175942Sscottl return -1; 1135175942Sscottl } 1136175942Sscottl 1137175942Sscottl req.header.size = offsetof(struct hpt_iop_request_ioctl_command, buf) 1138175942Sscottl + pParams->nInBufferSize; 1139175942Sscottl req.header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND; 1140175942Sscottl req.header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST; 1141175942Sscottl req.header.result = IOP_RESULT_PENDING; 1142175942Sscottl req.header.context = req32 + (u_int64_t)(unsigned long)hba->u.itl.mu; 1143175942Sscottl req.ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode); 1144175942Sscottl req.inbuf_size = pParams->nInBufferSize; 1145175942Sscottl req.outbuf_size = pParams->nOutBufferSize; 1146175942Sscottl req.bytes_returned = 0; 1147175942Sscottl 1148175942Sscottl bus_space_write_region_4(hba->bar0t, hba->bar0h, req32, (u_int32_t *)&req, 1149175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf)>>2); 1150175942Sscottl 1151175942Sscottl hptiop_lock_adapter(hba); 1152175942Sscottl 1153175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue, req32); 1154175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 1155175942Sscottl 1156175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h, req32 + 1157175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, header.context), 1158175942Sscottl (u_int32_t *)&temp64, 2); 1159175942Sscottl while (temp64) { 1160175942Sscottl if (hptiop_sleep(hba, (void *)((unsigned long)hba->u.itl.mu + req32), 1161175942Sscottl PPAUSE, "hptctl", HPT_OSM_TIMEOUT)==0) 1162175942Sscottl break; 1163175942Sscottl hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000); 1164175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h,req32 + 1165175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, 1166175942Sscottl header.context), 1167175942Sscottl (u_int32_t *)&temp64, 2); 1168175942Sscottl } 1169175942Sscottl 1170175942Sscottl hptiop_unlock_adapter(hba); 1171175942Sscottl return 0; 1172175942Sscottl} 1173175942Sscottl 1174242214Sdelphijstatic int hptiop_bus_space_copyin(struct hpt_iop_hba *hba, u_int32_t bus, 1175242214Sdelphij void *user, int size) 1176175942Sscottl{ 1177175942Sscottl unsigned char byte; 1178175942Sscottl int i; 1179175942Sscottl 1180175942Sscottl for (i=0; i<size; i++) { 1181175942Sscottl if (copyin((u_int8_t *)user + i, &byte, 1)) 1182175942Sscottl return -1; 1183175942Sscottl bus_space_write_1(hba->bar0t, hba->bar0h, bus + i, byte); 1184175942Sscottl } 1185175942Sscottl 1186175942Sscottl return 0; 1187175942Sscottl} 1188175942Sscottl 1189242214Sdelphijstatic int hptiop_bus_space_copyout(struct hpt_iop_hba *hba, u_int32_t bus, 1190242214Sdelphij void *user, int size) 1191175942Sscottl{ 1192175942Sscottl unsigned char byte; 1193175942Sscottl int i; 1194175942Sscottl 1195175942Sscottl for (i=0; i<size; i++) { 1196175942Sscottl byte = bus_space_read_1(hba->bar0t, hba->bar0h, bus + i); 1197175942Sscottl if (copyout(&byte, (u_int8_t *)user + i, 1)) 1198175942Sscottl return -1; 1199175942Sscottl } 1200175942Sscottl 1201175942Sscottl return 0; 1202175942Sscottl} 1203175942Sscottl 1204175942Sscottlstatic int hptiop_do_ioctl_itl(struct hpt_iop_hba *hba, 1205175942Sscottl struct hpt_iop_ioctl_param * pParams) 1206175942Sscottl{ 1207175942Sscottl u_int32_t req32; 1208175942Sscottl u_int32_t result; 1209175942Sscottl 1210169412Sscottl if ((pParams->Magic != HPT_IOCTL_MAGIC) && 1211169412Sscottl (pParams->Magic != HPT_IOCTL_MAGIC32)) 1212169412Sscottl return EFAULT; 1213175942Sscottl 1214175942Sscottl req32 = BUS_SPACE_RD4_ITL(inbound_queue); 1215175942Sscottl if (req32 == IOPMU_QUEUE_EMPTY) 1216169412Sscottl return EFAULT; 1217169412Sscottl 1218169412Sscottl if (pParams->nInBufferSize) 1219175942Sscottl if (hptiop_bus_space_copyin(hba, req32 + 1220175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf), 1221175942Sscottl (void *)pParams->lpInBuffer, pParams->nInBufferSize)) 1222169412Sscottl goto invalid; 1223169412Sscottl 1224175942Sscottl if (hptiop_post_ioctl_command_itl(hba, req32, pParams)) 1225169412Sscottl goto invalid; 1226169412Sscottl 1227175942Sscottl result = bus_space_read_4(hba->bar0t, hba->bar0h, req32 + 1228175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, 1229175942Sscottl header.result)); 1230175942Sscottl 1231175942Sscottl if (result == IOP_RESULT_SUCCESS) { 1232169412Sscottl if (pParams->nOutBufferSize) 1233175942Sscottl if (hptiop_bus_space_copyout(hba, req32 + 1234175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf) + 1235169412Sscottl ((pParams->nInBufferSize + 3) & ~3), 1236175942Sscottl (void *)pParams->lpOutBuffer, pParams->nOutBufferSize)) 1237169412Sscottl goto invalid; 1238169412Sscottl 1239175942Sscottl if (pParams->lpBytesReturned) { 1240175942Sscottl if (hptiop_bus_space_copyout(hba, req32 + 1241175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, bytes_returned), 1242175942Sscottl (void *)pParams->lpBytesReturned, sizeof(unsigned long))) 1243169412Sscottl goto invalid; 1244175942Sscottl } 1245175942Sscottl 1246175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req32); 1247175942Sscottl 1248169412Sscottl return 0; 1249169412Sscottl } else{ 1250169412Sscottlinvalid: 1251175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req32); 1252175942Sscottl 1253169412Sscottl return EFAULT; 1254169412Sscottl } 1255169412Sscottl} 1256169412Sscottl 1257175942Sscottlstatic int hptiop_post_ioctl_command_mv(struct hpt_iop_hba *hba, 1258175942Sscottl struct hpt_iop_request_ioctl_command *req, 1259175942Sscottl struct hpt_iop_ioctl_param *pParams) 1260169412Sscottl{ 1261175942Sscottl u_int64_t req_phy; 1262175942Sscottl int size = 0; 1263175942Sscottl 1264175942Sscottl if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) > 1265175942Sscottl (hba->max_request_size - 1266175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf))) { 1267175942Sscottl device_printf(hba->pcidev, "request size beyond max value"); 1268169412Sscottl return -1; 1269169412Sscottl } 1270169412Sscottl 1271169412Sscottl req->ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode); 1272169412Sscottl req->inbuf_size = pParams->nInBufferSize; 1273169412Sscottl req->outbuf_size = pParams->nOutBufferSize; 1274175942Sscottl req->header.size = offsetof(struct hpt_iop_request_ioctl_command, buf) 1275175942Sscottl + pParams->nInBufferSize; 1276175942Sscottl req->header.context = (u_int64_t)MVIOP_CMD_TYPE_IOCTL; 1277169412Sscottl req->header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND; 1278169412Sscottl req->header.result = IOP_RESULT_PENDING; 1279175942Sscottl req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT; 1280175942Sscottl size = req->header.size >> 8; 1281175942Sscottl size = size > 3 ? 3 : size; 1282175942Sscottl req_phy = hba->ctlcfgcmd_phy | MVIOP_MU_QUEUE_ADDR_HOST_BIT | size; 1283175942Sscottl hptiop_mv_inbound_write(req_phy, hba); 1284169412Sscottl 1285175942Sscottl BUS_SPACE_RD4_MV0(outbound_intmask); 1286169412Sscottl 1287175942Sscottl while (hba->config_done == 0) { 1288175942Sscottl if (hptiop_sleep(hba, req, PPAUSE, 1289175942Sscottl "hptctl", HPT_OSM_TIMEOUT)==0) 1290175942Sscottl continue; 1291175942Sscottl hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000); 1292169412Sscottl } 1293169412Sscottl return 0; 1294169412Sscottl} 1295169412Sscottl 1296175942Sscottlstatic int hptiop_do_ioctl_mv(struct hpt_iop_hba *hba, 1297175942Sscottl struct hpt_iop_ioctl_param *pParams) 1298175942Sscottl{ 1299175942Sscottl struct hpt_iop_request_ioctl_command *req; 1300175942Sscottl 1301175942Sscottl if ((pParams->Magic != HPT_IOCTL_MAGIC) && 1302175942Sscottl (pParams->Magic != HPT_IOCTL_MAGIC32)) 1303175942Sscottl return EFAULT; 1304175942Sscottl 1305175942Sscottl req = (struct hpt_iop_request_ioctl_command *)(hba->ctlcfg_ptr); 1306175942Sscottl hba->config_done = 0; 1307175942Sscottl hptiop_lock_adapter(hba); 1308175942Sscottl if (pParams->nInBufferSize) 1309175942Sscottl if (copyin((void *)pParams->lpInBuffer, 1310175942Sscottl req->buf, pParams->nInBufferSize)) 1311175942Sscottl goto invalid; 1312175942Sscottl if (hptiop_post_ioctl_command_mv(hba, req, pParams)) 1313175942Sscottl goto invalid; 1314175942Sscottl 1315175942Sscottl if (hba->config_done == 1) { 1316175942Sscottl if (pParams->nOutBufferSize) 1317175942Sscottl if (copyout(req->buf + 1318175942Sscottl ((pParams->nInBufferSize + 3) & ~3), 1319175942Sscottl (void *)pParams->lpOutBuffer, 1320175942Sscottl pParams->nOutBufferSize)) 1321175942Sscottl goto invalid; 1322175942Sscottl 1323175942Sscottl if (pParams->lpBytesReturned) 1324175942Sscottl if (copyout(&req->bytes_returned, 1325175942Sscottl (void*)pParams->lpBytesReturned, 1326175942Sscottl sizeof(u_int32_t))) 1327175942Sscottl goto invalid; 1328175942Sscottl hptiop_unlock_adapter(hba); 1329175942Sscottl return 0; 1330175942Sscottl } else{ 1331175942Sscottlinvalid: 1332175942Sscottl hptiop_unlock_adapter(hba); 1333175942Sscottl return EFAULT; 1334175942Sscottl } 1335175942Sscottl} 1336175942Sscottl 1337242214Sdelphijstatic int hptiop_post_ioctl_command_mvfrey(struct hpt_iop_hba *hba, 1338242214Sdelphij struct hpt_iop_request_ioctl_command *req, 1339242214Sdelphij struct hpt_iop_ioctl_param *pParams) 1340242214Sdelphij{ 1341242214Sdelphij u_int64_t phy_addr; 1342242214Sdelphij u_int32_t index; 1343242214Sdelphij 1344242214Sdelphij phy_addr = hba->ctlcfgcmd_phy; 1345242214Sdelphij 1346242214Sdelphij if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) > 1347242214Sdelphij (hba->max_request_size - 1348242214Sdelphij offsetof(struct hpt_iop_request_ioctl_command, buf))) { 1349242214Sdelphij device_printf(hba->pcidev, "request size beyond max value"); 1350242214Sdelphij return -1; 1351242214Sdelphij } 1352242214Sdelphij 1353242214Sdelphij req->ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode); 1354242214Sdelphij req->inbuf_size = pParams->nInBufferSize; 1355242214Sdelphij req->outbuf_size = pParams->nOutBufferSize; 1356242214Sdelphij req->header.size = offsetof(struct hpt_iop_request_ioctl_command, buf) 1357242214Sdelphij + pParams->nInBufferSize; 1358242214Sdelphij 1359242214Sdelphij req->header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND; 1360242214Sdelphij req->header.result = IOP_RESULT_PENDING; 1361242214Sdelphij 1362242214Sdelphij req->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST 1363242214Sdelphij | IOP_REQUEST_FLAG_OUTPUT_CONTEXT 1364242214Sdelphij | IOP_REQUEST_FLAG_ADDR_BITS 1365242214Sdelphij | ((phy_addr >> 16) & 0xffff0000); 1366242214Sdelphij req->header.context = ((phy_addr & 0xffffffff) << 32 ) 1367242214Sdelphij | IOPMU_QUEUE_ADDR_HOST_BIT | req->header.type; 1368242214Sdelphij 1369242214Sdelphij hba->u.mvfrey.inlist_wptr++; 1370242214Sdelphij index = hba->u.mvfrey.inlist_wptr & 0x3fff; 1371242214Sdelphij 1372242214Sdelphij if (index == hba->u.mvfrey.list_count) { 1373242214Sdelphij index = 0; 1374242214Sdelphij hba->u.mvfrey.inlist_wptr &= ~0x3fff; 1375242214Sdelphij hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE; 1376242214Sdelphij } 1377242214Sdelphij 1378242214Sdelphij hba->u.mvfrey.inlist[index].addr = phy_addr; 1379242214Sdelphij hba->u.mvfrey.inlist[index].intrfc_len = (req->header.size + 3) / 4; 1380242214Sdelphij 1381242214Sdelphij BUS_SPACE_WRT4_MVFREY2(inbound_write_ptr, hba->u.mvfrey.inlist_wptr); 1382242214Sdelphij BUS_SPACE_RD4_MVFREY2(inbound_write_ptr); 1383242214Sdelphij 1384242214Sdelphij while (hba->config_done == 0) { 1385242214Sdelphij if (hptiop_sleep(hba, req, PPAUSE, 1386242214Sdelphij "hptctl", HPT_OSM_TIMEOUT)==0) 1387242214Sdelphij continue; 1388242214Sdelphij hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000); 1389242214Sdelphij } 1390242214Sdelphij return 0; 1391242214Sdelphij} 1392242214Sdelphij 1393242214Sdelphijstatic int hptiop_do_ioctl_mvfrey(struct hpt_iop_hba *hba, 1394242214Sdelphij struct hpt_iop_ioctl_param *pParams) 1395242214Sdelphij{ 1396242214Sdelphij struct hpt_iop_request_ioctl_command *req; 1397242214Sdelphij 1398242214Sdelphij if ((pParams->Magic != HPT_IOCTL_MAGIC) && 1399242214Sdelphij (pParams->Magic != HPT_IOCTL_MAGIC32)) 1400242214Sdelphij return EFAULT; 1401242214Sdelphij 1402242214Sdelphij req = (struct hpt_iop_request_ioctl_command *)(hba->ctlcfg_ptr); 1403242214Sdelphij hba->config_done = 0; 1404242214Sdelphij hptiop_lock_adapter(hba); 1405242214Sdelphij if (pParams->nInBufferSize) 1406242214Sdelphij if (copyin((void *)pParams->lpInBuffer, 1407242214Sdelphij req->buf, pParams->nInBufferSize)) 1408242214Sdelphij goto invalid; 1409242214Sdelphij if (hptiop_post_ioctl_command_mvfrey(hba, req, pParams)) 1410242214Sdelphij goto invalid; 1411242214Sdelphij 1412242214Sdelphij if (hba->config_done == 1) { 1413242214Sdelphij if (pParams->nOutBufferSize) 1414242214Sdelphij if (copyout(req->buf + 1415242214Sdelphij ((pParams->nInBufferSize + 3) & ~3), 1416242214Sdelphij (void *)pParams->lpOutBuffer, 1417242214Sdelphij pParams->nOutBufferSize)) 1418242214Sdelphij goto invalid; 1419242214Sdelphij 1420242214Sdelphij if (pParams->lpBytesReturned) 1421242214Sdelphij if (copyout(&req->bytes_returned, 1422242214Sdelphij (void*)pParams->lpBytesReturned, 1423242214Sdelphij sizeof(u_int32_t))) 1424242214Sdelphij goto invalid; 1425242214Sdelphij hptiop_unlock_adapter(hba); 1426242214Sdelphij return 0; 1427242214Sdelphij } else{ 1428242214Sdelphijinvalid: 1429242214Sdelphij hptiop_unlock_adapter(hba); 1430242214Sdelphij return EFAULT; 1431242214Sdelphij } 1432242214Sdelphij} 1433242214Sdelphij 1434169412Sscottlstatic int hptiop_rescan_bus(struct hpt_iop_hba * hba) 1435169412Sscottl{ 1436169412Sscottl union ccb *ccb; 1437203108Smav 1438203108Smav if ((ccb = xpt_alloc_ccb()) == NULL) 1439203108Smav return(ENOMEM); 1440253037Smav if (xpt_create_path(&ccb->ccb_h.path, NULL, cam_sim_path(hba->sim), 1441203108Smav CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 1442203108Smav xpt_free_ccb(ccb); 1443169412Sscottl return(EIO); 1444203108Smav } 1445203108Smav xpt_rescan(ccb); 1446169412Sscottl return(0); 1447169412Sscottl} 1448169412Sscottl 1449169412Sscottlstatic bus_dmamap_callback_t hptiop_map_srb; 1450169412Sscottlstatic bus_dmamap_callback_t hptiop_post_scsi_command; 1451175942Sscottlstatic bus_dmamap_callback_t hptiop_mv_map_ctlcfg; 1452242214Sdelphijstatic bus_dmamap_callback_t hptiop_mvfrey_map_ctlcfg; 1453169412Sscottl 1454175942Sscottlstatic int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba) 1455175942Sscottl{ 1456175942Sscottl hba->bar0_rid = 0x10; 1457175942Sscottl hba->bar0_res = bus_alloc_resource_any(hba->pcidev, 1458175942Sscottl SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE); 1459175942Sscottl 1460175942Sscottl if (hba->bar0_res == NULL) { 1461175942Sscottl device_printf(hba->pcidev, 1462175942Sscottl "failed to get iop base adrress.\n"); 1463175942Sscottl return -1; 1464175942Sscottl } 1465175942Sscottl hba->bar0t = rman_get_bustag(hba->bar0_res); 1466175942Sscottl hba->bar0h = rman_get_bushandle(hba->bar0_res); 1467175942Sscottl hba->u.itl.mu = (struct hpt_iopmu_itl *) 1468175942Sscottl rman_get_virtual(hba->bar0_res); 1469175942Sscottl 1470175942Sscottl if (!hba->u.itl.mu) { 1471175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1472175942Sscottl hba->bar0_rid, hba->bar0_res); 1473175942Sscottl device_printf(hba->pcidev, "alloc mem res failed\n"); 1474175942Sscottl return -1; 1475175942Sscottl } 1476175942Sscottl 1477175942Sscottl return 0; 1478175942Sscottl} 1479175942Sscottl 1480175942Sscottlstatic int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba) 1481175942Sscottl{ 1482175942Sscottl hba->bar0_rid = 0x10; 1483175942Sscottl hba->bar0_res = bus_alloc_resource_any(hba->pcidev, 1484175942Sscottl SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE); 1485175942Sscottl 1486175942Sscottl if (hba->bar0_res == NULL) { 1487175942Sscottl device_printf(hba->pcidev, "failed to get iop bar0.\n"); 1488175942Sscottl return -1; 1489175942Sscottl } 1490175942Sscottl hba->bar0t = rman_get_bustag(hba->bar0_res); 1491175942Sscottl hba->bar0h = rman_get_bushandle(hba->bar0_res); 1492175942Sscottl hba->u.mv.regs = (struct hpt_iopmv_regs *) 1493175942Sscottl rman_get_virtual(hba->bar0_res); 1494175942Sscottl 1495175942Sscottl if (!hba->u.mv.regs) { 1496175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1497175942Sscottl hba->bar0_rid, hba->bar0_res); 1498175942Sscottl device_printf(hba->pcidev, "alloc bar0 mem res failed\n"); 1499175942Sscottl return -1; 1500175942Sscottl } 1501175942Sscottl 1502175942Sscottl hba->bar2_rid = 0x18; 1503175942Sscottl hba->bar2_res = bus_alloc_resource_any(hba->pcidev, 1504175942Sscottl SYS_RES_MEMORY, &hba->bar2_rid, RF_ACTIVE); 1505175942Sscottl 1506175942Sscottl if (hba->bar2_res == NULL) { 1507175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1508175942Sscottl hba->bar0_rid, hba->bar0_res); 1509175942Sscottl device_printf(hba->pcidev, "failed to get iop bar2.\n"); 1510175942Sscottl return -1; 1511175942Sscottl } 1512175942Sscottl 1513175942Sscottl hba->bar2t = rman_get_bustag(hba->bar2_res); 1514175942Sscottl hba->bar2h = rman_get_bushandle(hba->bar2_res); 1515175942Sscottl hba->u.mv.mu = (struct hpt_iopmu_mv *)rman_get_virtual(hba->bar2_res); 1516175942Sscottl 1517175942Sscottl if (!hba->u.mv.mu) { 1518175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1519175942Sscottl hba->bar0_rid, hba->bar0_res); 1520175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1521175942Sscottl hba->bar2_rid, hba->bar2_res); 1522175942Sscottl device_printf(hba->pcidev, "alloc mem bar2 res failed\n"); 1523175942Sscottl return -1; 1524175942Sscottl } 1525175942Sscottl 1526175942Sscottl return 0; 1527175942Sscottl} 1528175942Sscottl 1529242214Sdelphijstatic int hptiop_alloc_pci_res_mvfrey(struct hpt_iop_hba *hba) 1530242214Sdelphij{ 1531242214Sdelphij hba->bar0_rid = 0x10; 1532242214Sdelphij hba->bar0_res = bus_alloc_resource_any(hba->pcidev, 1533242214Sdelphij SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE); 1534242214Sdelphij 1535242214Sdelphij if (hba->bar0_res == NULL) { 1536242214Sdelphij device_printf(hba->pcidev, "failed to get iop bar0.\n"); 1537242214Sdelphij return -1; 1538242214Sdelphij } 1539242214Sdelphij hba->bar0t = rman_get_bustag(hba->bar0_res); 1540242214Sdelphij hba->bar0h = rman_get_bushandle(hba->bar0_res); 1541242214Sdelphij hba->u.mvfrey.config = (struct hpt_iop_request_get_config *) 1542242214Sdelphij rman_get_virtual(hba->bar0_res); 1543242214Sdelphij 1544242214Sdelphij if (!hba->u.mvfrey.config) { 1545242214Sdelphij bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1546242214Sdelphij hba->bar0_rid, hba->bar0_res); 1547242214Sdelphij device_printf(hba->pcidev, "alloc bar0 mem res failed\n"); 1548242214Sdelphij return -1; 1549242214Sdelphij } 1550242214Sdelphij 1551242214Sdelphij hba->bar2_rid = 0x18; 1552242214Sdelphij hba->bar2_res = bus_alloc_resource_any(hba->pcidev, 1553242214Sdelphij SYS_RES_MEMORY, &hba->bar2_rid, RF_ACTIVE); 1554242214Sdelphij 1555242214Sdelphij if (hba->bar2_res == NULL) { 1556242214Sdelphij bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1557242214Sdelphij hba->bar0_rid, hba->bar0_res); 1558242214Sdelphij device_printf(hba->pcidev, "failed to get iop bar2.\n"); 1559242214Sdelphij return -1; 1560242214Sdelphij } 1561242214Sdelphij 1562242214Sdelphij hba->bar2t = rman_get_bustag(hba->bar2_res); 1563242214Sdelphij hba->bar2h = rman_get_bushandle(hba->bar2_res); 1564242214Sdelphij hba->u.mvfrey.mu = 1565242214Sdelphij (struct hpt_iopmu_mvfrey *)rman_get_virtual(hba->bar2_res); 1566242214Sdelphij 1567242214Sdelphij if (!hba->u.mvfrey.mu) { 1568242214Sdelphij bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1569242214Sdelphij hba->bar0_rid, hba->bar0_res); 1570242214Sdelphij bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1571242214Sdelphij hba->bar2_rid, hba->bar2_res); 1572242214Sdelphij device_printf(hba->pcidev, "alloc mem bar2 res failed\n"); 1573242214Sdelphij return -1; 1574242214Sdelphij } 1575242214Sdelphij 1576242214Sdelphij return 0; 1577242214Sdelphij} 1578242214Sdelphij 1579175942Sscottlstatic void hptiop_release_pci_res_itl(struct hpt_iop_hba *hba) 1580175942Sscottl{ 1581175942Sscottl if (hba->bar0_res) 1582175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1583175942Sscottl hba->bar0_rid, hba->bar0_res); 1584175942Sscottl} 1585175942Sscottl 1586175942Sscottlstatic void hptiop_release_pci_res_mv(struct hpt_iop_hba *hba) 1587175942Sscottl{ 1588175942Sscottl if (hba->bar0_res) 1589175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1590175942Sscottl hba->bar0_rid, hba->bar0_res); 1591175942Sscottl if (hba->bar2_res) 1592175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1593175942Sscottl hba->bar2_rid, hba->bar2_res); 1594175942Sscottl} 1595175942Sscottl 1596242214Sdelphijstatic void hptiop_release_pci_res_mvfrey(struct hpt_iop_hba *hba) 1597242214Sdelphij{ 1598242214Sdelphij if (hba->bar0_res) 1599242214Sdelphij bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1600242214Sdelphij hba->bar0_rid, hba->bar0_res); 1601242214Sdelphij if (hba->bar2_res) 1602242214Sdelphij bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1603242214Sdelphij hba->bar2_rid, hba->bar2_res); 1604242214Sdelphij} 1605242214Sdelphij 1606175942Sscottlstatic int hptiop_internal_memalloc_mv(struct hpt_iop_hba *hba) 1607175942Sscottl{ 1608175942Sscottl if (bus_dma_tag_create(hba->parent_dmat, 1609175942Sscottl 1, 1610175942Sscottl 0, 1611175942Sscottl BUS_SPACE_MAXADDR_32BIT, 1612175942Sscottl BUS_SPACE_MAXADDR, 1613175942Sscottl NULL, NULL, 1614175942Sscottl 0x800 - 0x8, 1615175942Sscottl 1, 1616175942Sscottl BUS_SPACE_MAXSIZE_32BIT, 1617175942Sscottl BUS_DMA_ALLOCNOW, 1618175942Sscottl#if __FreeBSD_version > 502000 1619175942Sscottl NULL, 1620175942Sscottl NULL, 1621175942Sscottl#endif 1622242214Sdelphij &hba->ctlcfg_dmat)) { 1623175942Sscottl device_printf(hba->pcidev, "alloc ctlcfg_dmat failed\n"); 1624175942Sscottl return -1; 1625175942Sscottl } 1626175942Sscottl 1627175942Sscottl if (bus_dmamem_alloc(hba->ctlcfg_dmat, (void **)&hba->ctlcfg_ptr, 1628175942Sscottl#if __FreeBSD_version>501000 1629175942Sscottl BUS_DMA_WAITOK | BUS_DMA_COHERENT, 1630175942Sscottl#else 1631175942Sscottl BUS_DMA_WAITOK, 1632175942Sscottl#endif 1633175942Sscottl &hba->ctlcfg_dmamap) != 0) { 1634175942Sscottl device_printf(hba->pcidev, 1635175942Sscottl "bus_dmamem_alloc failed!\n"); 1636175942Sscottl bus_dma_tag_destroy(hba->ctlcfg_dmat); 1637175942Sscottl return -1; 1638175942Sscottl } 1639175942Sscottl 1640175942Sscottl if (bus_dmamap_load(hba->ctlcfg_dmat, 1641175942Sscottl hba->ctlcfg_dmamap, hba->ctlcfg_ptr, 1642175942Sscottl MVIOP_IOCTLCFG_SIZE, 1643175942Sscottl hptiop_mv_map_ctlcfg, hba, 0)) { 1644175942Sscottl device_printf(hba->pcidev, "bus_dmamap_load failed!\n"); 1645175942Sscottl if (hba->ctlcfg_dmat) 1646175942Sscottl bus_dmamem_free(hba->ctlcfg_dmat, 1647175942Sscottl hba->ctlcfg_ptr, hba->ctlcfg_dmamap); 1648175942Sscottl bus_dma_tag_destroy(hba->ctlcfg_dmat); 1649175942Sscottl return -1; 1650175942Sscottl } 1651175942Sscottl 1652175942Sscottl return 0; 1653175942Sscottl} 1654175942Sscottl 1655242214Sdelphijstatic int hptiop_internal_memalloc_mvfrey(struct hpt_iop_hba *hba) 1656242214Sdelphij{ 1657242214Sdelphij u_int32_t list_count = BUS_SPACE_RD4_MVFREY2(inbound_conf_ctl); 1658242214Sdelphij 1659242214Sdelphij list_count >>= 16; 1660242214Sdelphij 1661242214Sdelphij if (list_count == 0) { 1662242214Sdelphij return -1; 1663242214Sdelphij } 1664242214Sdelphij 1665242214Sdelphij hba->u.mvfrey.list_count = list_count; 1666242214Sdelphij hba->u.mvfrey.internal_mem_size = 0x800 1667242214Sdelphij + list_count * sizeof(struct mvfrey_inlist_entry) 1668242214Sdelphij + list_count * sizeof(struct mvfrey_outlist_entry) 1669242214Sdelphij + sizeof(int); 1670242214Sdelphij if (bus_dma_tag_create(hba->parent_dmat, 1671242214Sdelphij 1, 1672242214Sdelphij 0, 1673242214Sdelphij BUS_SPACE_MAXADDR_32BIT, 1674242214Sdelphij BUS_SPACE_MAXADDR, 1675242214Sdelphij NULL, NULL, 1676242214Sdelphij hba->u.mvfrey.internal_mem_size, 1677242214Sdelphij 1, 1678242214Sdelphij BUS_SPACE_MAXSIZE_32BIT, 1679242214Sdelphij BUS_DMA_ALLOCNOW, 1680242214Sdelphij#if __FreeBSD_version > 502000 1681242214Sdelphij NULL, 1682242214Sdelphij NULL, 1683242214Sdelphij#endif 1684242214Sdelphij &hba->ctlcfg_dmat)) { 1685242214Sdelphij device_printf(hba->pcidev, "alloc ctlcfg_dmat failed\n"); 1686242214Sdelphij return -1; 1687242214Sdelphij } 1688242214Sdelphij 1689242214Sdelphij if (bus_dmamem_alloc(hba->ctlcfg_dmat, (void **)&hba->ctlcfg_ptr, 1690242214Sdelphij#if __FreeBSD_version>501000 1691242214Sdelphij BUS_DMA_WAITOK | BUS_DMA_COHERENT, 1692242214Sdelphij#else 1693242214Sdelphij BUS_DMA_WAITOK, 1694242214Sdelphij#endif 1695242214Sdelphij &hba->ctlcfg_dmamap) != 0) { 1696242214Sdelphij device_printf(hba->pcidev, 1697242214Sdelphij "bus_dmamem_alloc failed!\n"); 1698242214Sdelphij bus_dma_tag_destroy(hba->ctlcfg_dmat); 1699242214Sdelphij return -1; 1700242214Sdelphij } 1701242214Sdelphij 1702242214Sdelphij if (bus_dmamap_load(hba->ctlcfg_dmat, 1703242214Sdelphij hba->ctlcfg_dmamap, hba->ctlcfg_ptr, 1704242214Sdelphij hba->u.mvfrey.internal_mem_size, 1705242214Sdelphij hptiop_mvfrey_map_ctlcfg, hba, 0)) { 1706242214Sdelphij device_printf(hba->pcidev, "bus_dmamap_load failed!\n"); 1707251162Sdelphij if (hba->ctlcfg_dmat) { 1708242214Sdelphij bus_dmamem_free(hba->ctlcfg_dmat, 1709242214Sdelphij hba->ctlcfg_ptr, hba->ctlcfg_dmamap); 1710242214Sdelphij bus_dma_tag_destroy(hba->ctlcfg_dmat); 1711251162Sdelphij } 1712242214Sdelphij return -1; 1713242214Sdelphij } 1714242214Sdelphij 1715242214Sdelphij return 0; 1716242214Sdelphij} 1717242214Sdelphij 1718242214Sdelphijstatic int hptiop_internal_memfree_itl(struct hpt_iop_hba *hba) { 1719242214Sdelphij return 0; 1720242214Sdelphij} 1721242214Sdelphij 1722175942Sscottlstatic int hptiop_internal_memfree_mv(struct hpt_iop_hba *hba) 1723175942Sscottl{ 1724175942Sscottl if (hba->ctlcfg_dmat) { 1725175942Sscottl bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap); 1726175942Sscottl bus_dmamem_free(hba->ctlcfg_dmat, 1727175942Sscottl hba->ctlcfg_ptr, hba->ctlcfg_dmamap); 1728175942Sscottl bus_dma_tag_destroy(hba->ctlcfg_dmat); 1729175942Sscottl } 1730175942Sscottl 1731175942Sscottl return 0; 1732175942Sscottl} 1733175942Sscottl 1734242214Sdelphijstatic int hptiop_internal_memfree_mvfrey(struct hpt_iop_hba *hba) 1735242214Sdelphij{ 1736242214Sdelphij if (hba->ctlcfg_dmat) { 1737242214Sdelphij bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap); 1738242214Sdelphij bus_dmamem_free(hba->ctlcfg_dmat, 1739242214Sdelphij hba->ctlcfg_ptr, hba->ctlcfg_dmamap); 1740242214Sdelphij bus_dma_tag_destroy(hba->ctlcfg_dmat); 1741242214Sdelphij } 1742242214Sdelphij 1743242214Sdelphij return 0; 1744242214Sdelphij} 1745242214Sdelphij 1746242214Sdelphijstatic int hptiop_reset_comm_mvfrey(struct hpt_iop_hba *hba) 1747242214Sdelphij{ 1748242214Sdelphij u_int32_t i = 100; 1749242214Sdelphij 1750242214Sdelphij if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET_COMM, 3000)) 1751242214Sdelphij return -1; 1752242214Sdelphij 1753242214Sdelphij /* wait 100ms for MCU ready */ 1754242214Sdelphij while(i--) { 1755242214Sdelphij DELAY(1000); 1756242214Sdelphij } 1757242214Sdelphij 1758242214Sdelphij BUS_SPACE_WRT4_MVFREY2(inbound_base, 1759242214Sdelphij hba->u.mvfrey.inlist_phy & 0xffffffff); 1760242214Sdelphij BUS_SPACE_WRT4_MVFREY2(inbound_base_high, 1761242214Sdelphij (hba->u.mvfrey.inlist_phy >> 16) >> 16); 1762242214Sdelphij 1763242214Sdelphij BUS_SPACE_WRT4_MVFREY2(outbound_base, 1764242214Sdelphij hba->u.mvfrey.outlist_phy & 0xffffffff); 1765242214Sdelphij BUS_SPACE_WRT4_MVFREY2(outbound_base_high, 1766242214Sdelphij (hba->u.mvfrey.outlist_phy >> 16) >> 16); 1767242214Sdelphij 1768242214Sdelphij BUS_SPACE_WRT4_MVFREY2(outbound_shadow_base, 1769242214Sdelphij hba->u.mvfrey.outlist_cptr_phy & 0xffffffff); 1770242214Sdelphij BUS_SPACE_WRT4_MVFREY2(outbound_shadow_base_high, 1771242214Sdelphij (hba->u.mvfrey.outlist_cptr_phy >> 16) >> 16); 1772242214Sdelphij 1773242214Sdelphij hba->u.mvfrey.inlist_wptr = (hba->u.mvfrey.list_count - 1) 1774242214Sdelphij | CL_POINTER_TOGGLE; 1775242214Sdelphij *hba->u.mvfrey.outlist_cptr = (hba->u.mvfrey.list_count - 1) 1776242214Sdelphij | CL_POINTER_TOGGLE; 1777242214Sdelphij hba->u.mvfrey.outlist_rptr = hba->u.mvfrey.list_count - 1; 1778242214Sdelphij 1779242214Sdelphij return 0; 1780242214Sdelphij} 1781242214Sdelphij 1782169412Sscottl/* 1783169412Sscottl * CAM driver interface 1784169412Sscottl */ 1785169412Sscottlstatic device_method_t driver_methods[] = { 1786169412Sscottl /* Device interface */ 1787169412Sscottl DEVMETHOD(device_probe, hptiop_probe), 1788169412Sscottl DEVMETHOD(device_attach, hptiop_attach), 1789169412Sscottl DEVMETHOD(device_detach, hptiop_detach), 1790169412Sscottl DEVMETHOD(device_shutdown, hptiop_shutdown), 1791169412Sscottl { 0, 0 } 1792169412Sscottl}; 1793169412Sscottl 1794175942Sscottlstatic struct hptiop_adapter_ops hptiop_itl_ops = { 1795242214Sdelphij .family = INTEL_BASED_IOP, 1796175942Sscottl .iop_wait_ready = hptiop_wait_ready_itl, 1797175942Sscottl .internal_memalloc = 0, 1798242214Sdelphij .internal_memfree = hptiop_internal_memfree_itl, 1799175942Sscottl .alloc_pci_res = hptiop_alloc_pci_res_itl, 1800175942Sscottl .release_pci_res = hptiop_release_pci_res_itl, 1801175942Sscottl .enable_intr = hptiop_enable_intr_itl, 1802175942Sscottl .disable_intr = hptiop_disable_intr_itl, 1803175942Sscottl .get_config = hptiop_get_config_itl, 1804175942Sscottl .set_config = hptiop_set_config_itl, 1805175942Sscottl .iop_intr = hptiop_intr_itl, 1806175942Sscottl .post_msg = hptiop_post_msg_itl, 1807175942Sscottl .post_req = hptiop_post_req_itl, 1808175942Sscottl .do_ioctl = hptiop_do_ioctl_itl, 1809242214Sdelphij .reset_comm = 0, 1810175942Sscottl}; 1811175942Sscottl 1812175942Sscottlstatic struct hptiop_adapter_ops hptiop_mv_ops = { 1813242214Sdelphij .family = MV_BASED_IOP, 1814175942Sscottl .iop_wait_ready = hptiop_wait_ready_mv, 1815175942Sscottl .internal_memalloc = hptiop_internal_memalloc_mv, 1816175942Sscottl .internal_memfree = hptiop_internal_memfree_mv, 1817175942Sscottl .alloc_pci_res = hptiop_alloc_pci_res_mv, 1818175942Sscottl .release_pci_res = hptiop_release_pci_res_mv, 1819175942Sscottl .enable_intr = hptiop_enable_intr_mv, 1820175942Sscottl .disable_intr = hptiop_disable_intr_mv, 1821175942Sscottl .get_config = hptiop_get_config_mv, 1822175942Sscottl .set_config = hptiop_set_config_mv, 1823175942Sscottl .iop_intr = hptiop_intr_mv, 1824175942Sscottl .post_msg = hptiop_post_msg_mv, 1825175942Sscottl .post_req = hptiop_post_req_mv, 1826175942Sscottl .do_ioctl = hptiop_do_ioctl_mv, 1827242214Sdelphij .reset_comm = 0, 1828175942Sscottl}; 1829175942Sscottl 1830242214Sdelphijstatic struct hptiop_adapter_ops hptiop_mvfrey_ops = { 1831242214Sdelphij .family = MVFREY_BASED_IOP, 1832242214Sdelphij .iop_wait_ready = hptiop_wait_ready_mvfrey, 1833242214Sdelphij .internal_memalloc = hptiop_internal_memalloc_mvfrey, 1834242214Sdelphij .internal_memfree = hptiop_internal_memfree_mvfrey, 1835242214Sdelphij .alloc_pci_res = hptiop_alloc_pci_res_mvfrey, 1836242214Sdelphij .release_pci_res = hptiop_release_pci_res_mvfrey, 1837242214Sdelphij .enable_intr = hptiop_enable_intr_mvfrey, 1838242214Sdelphij .disable_intr = hptiop_disable_intr_mvfrey, 1839242214Sdelphij .get_config = hptiop_get_config_mvfrey, 1840242214Sdelphij .set_config = hptiop_set_config_mvfrey, 1841242214Sdelphij .iop_intr = hptiop_intr_mvfrey, 1842242214Sdelphij .post_msg = hptiop_post_msg_mvfrey, 1843242214Sdelphij .post_req = hptiop_post_req_mvfrey, 1844242214Sdelphij .do_ioctl = hptiop_do_ioctl_mvfrey, 1845242214Sdelphij .reset_comm = hptiop_reset_comm_mvfrey, 1846242214Sdelphij}; 1847242214Sdelphij 1848169412Sscottlstatic driver_t hptiop_pci_driver = { 1849169412Sscottl driver_name, 1850169412Sscottl driver_methods, 1851169412Sscottl sizeof(struct hpt_iop_hba) 1852169412Sscottl}; 1853169412Sscottl 1854169412SscottlDRIVER_MODULE(hptiop, pci, hptiop_pci_driver, hptiop_devclass, 0, 0); 1855236655SeadlerMODULE_DEPEND(hptiop, cam, 1, 1, 1); 1856169412Sscottl 1857169412Sscottlstatic int hptiop_probe(device_t dev) 1858169412Sscottl{ 1859169412Sscottl struct hpt_iop_hba *hba; 1860175942Sscottl u_int32_t id; 1861175942Sscottl static char buf[256]; 1862175942Sscottl int sas = 0; 1863175942Sscottl struct hptiop_adapter_ops *ops; 1864169412Sscottl 1865175942Sscottl if (pci_get_vendor(dev) != 0x1103) 1866175942Sscottl return (ENXIO); 1867175942Sscottl 1868175942Sscottl id = pci_get_device(dev); 1869175942Sscottl 1870175942Sscottl switch (id) { 1871242214Sdelphij case 0x4520: 1872252884Sdelphij case 0x4521: 1873242214Sdelphij case 0x4522: 1874242214Sdelphij sas = 1; 1875252884Sdelphij case 0x3620: 1876252884Sdelphij case 0x3622: 1877252884Sdelphij case 0x3640: 1878242214Sdelphij ops = &hptiop_mvfrey_ops; 1879242214Sdelphij break; 1880239458Sdelphij case 0x4210: 1881239458Sdelphij case 0x4211: 1882239458Sdelphij case 0x4310: 1883239458Sdelphij case 0x4311: 1884239458Sdelphij case 0x4320: 1885224583Sdelphij case 0x4321: 1886239458Sdelphij case 0x4322: 1887175942Sscottl sas = 1; 1888175942Sscottl case 0x3220: 1889175942Sscottl case 0x3320: 1890175942Sscottl case 0x3410: 1891175942Sscottl case 0x3520: 1892175942Sscottl case 0x3510: 1893175942Sscottl case 0x3511: 1894175942Sscottl case 0x3521: 1895175942Sscottl case 0x3522: 1896239458Sdelphij case 0x3530: 1897175942Sscottl case 0x3540: 1898239458Sdelphij case 0x3560: 1899175942Sscottl ops = &hptiop_itl_ops; 1900175942Sscottl break; 1901239458Sdelphij case 0x3020: 1902175942Sscottl case 0x3120: 1903175942Sscottl case 0x3122: 1904175942Sscottl ops = &hptiop_mv_ops; 1905175942Sscottl break; 1906175942Sscottl default: 1907175942Sscottl return (ENXIO); 1908169412Sscottl } 1909175942Sscottl 1910175942Sscottl device_printf(dev, "adapter at PCI %d:%d:%d, IRQ %d\n", 1911175942Sscottl pci_get_bus(dev), pci_get_slot(dev), 1912175942Sscottl pci_get_function(dev), pci_get_irq(dev)); 1913175942Sscottl 1914175942Sscottl sprintf(buf, "RocketRAID %x %s Controller\n", 1915175942Sscottl id, sas ? "SAS" : "SATA"); 1916175942Sscottl device_set_desc_copy(dev, buf); 1917175942Sscottl 1918175942Sscottl hba = (struct hpt_iop_hba *)device_get_softc(dev); 1919175942Sscottl bzero(hba, sizeof(struct hpt_iop_hba)); 1920175942Sscottl hba->ops = ops; 1921175942Sscottl 1922175942Sscottl KdPrint(("hba->ops=%p\n", hba->ops)); 1923175942Sscottl return 0; 1924169412Sscottl} 1925169412Sscottl 1926169412Sscottlstatic int hptiop_attach(device_t dev) 1927169412Sscottl{ 1928175942Sscottl struct hpt_iop_hba *hba = (struct hpt_iop_hba *)device_get_softc(dev); 1929169412Sscottl struct hpt_iop_request_get_config iop_config; 1930169412Sscottl struct hpt_iop_request_set_config set_config; 1931169412Sscottl int rid = 0; 1932169412Sscottl struct cam_devq *devq; 1933169412Sscottl struct ccb_setasync ccb; 1934169412Sscottl u_int32_t unit = device_get_unit(dev); 1935169412Sscottl 1936175942Sscottl device_printf(dev, "%d RocketRAID 3xxx/4xxx controller driver %s\n", 1937175942Sscottl unit, driver_version); 1938169412Sscottl 1939175942Sscottl KdPrint(("hptiop: attach(%d, %d/%d/%d) ops=%p\n", unit, 1940175942Sscottl pci_get_bus(dev), pci_get_slot(dev), 1941175942Sscottl pci_get_function(dev), hba->ops)); 1942175942Sscottl 1943169412Sscottl#if __FreeBSD_version >=440000 1944169412Sscottl pci_enable_busmaster(dev); 1945169412Sscottl#endif 1946169412Sscottl hba->pcidev = dev; 1947169412Sscottl hba->pciunit = unit; 1948169412Sscottl 1949175942Sscottl if (hba->ops->alloc_pci_res(hba)) 1950169412Sscottl return ENXIO; 1951169412Sscottl 1952175942Sscottl if (hba->ops->iop_wait_ready(hba, 2000)) { 1953175942Sscottl device_printf(dev, "adapter is not ready\n"); 1954175942Sscottl goto release_pci_res; 1955169412Sscottl } 1956169412Sscottl 1957169412Sscottl#if (__FreeBSD_version >= 500000) 1958169412Sscottl mtx_init(&hba->lock, "hptioplock", NULL, MTX_DEF); 1959169412Sscottl#endif 1960169412Sscottl 1961233024Sscottl if (bus_dma_tag_create(bus_get_dma_tag(dev),/* PCI parent */ 1962169412Sscottl 1, /* alignment */ 1963169412Sscottl 0, /* boundary */ 1964169412Sscottl BUS_SPACE_MAXADDR, /* lowaddr */ 1965169412Sscottl BUS_SPACE_MAXADDR, /* highaddr */ 1966169412Sscottl NULL, NULL, /* filter, filterarg */ 1967169412Sscottl BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 1968169412Sscottl BUS_SPACE_UNRESTRICTED, /* nsegments */ 1969169412Sscottl BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 1970169412Sscottl 0, /* flags */ 1971169412Sscottl#if __FreeBSD_version>502000 1972169412Sscottl NULL, /* lockfunc */ 1973169412Sscottl NULL, /* lockfuncarg */ 1974169412Sscottl#endif 1975169412Sscottl &hba->parent_dmat /* tag */)) 1976169412Sscottl { 1977175942Sscottl device_printf(dev, "alloc parent_dmat failed\n"); 1978175942Sscottl goto release_pci_res; 1979169412Sscottl } 1980169412Sscottl 1981242214Sdelphij if (hba->ops->family == MV_BASED_IOP) { 1982175942Sscottl if (hba->ops->internal_memalloc(hba)) { 1983175942Sscottl device_printf(dev, "alloc srb_dmat failed\n"); 1984175942Sscottl goto destroy_parent_tag; 1985175942Sscottl } 1986175942Sscottl } 1987175942Sscottl 1988175942Sscottl if (hba->ops->get_config(hba, &iop_config)) { 1989175942Sscottl device_printf(dev, "get iop config failed.\n"); 1990175942Sscottl goto get_config_failed; 1991175942Sscottl } 1992175942Sscottl 1993175942Sscottl hba->firmware_version = iop_config.firmware_version; 1994175942Sscottl hba->interface_version = iop_config.interface_version; 1995175942Sscottl hba->max_requests = iop_config.max_requests; 1996175942Sscottl hba->max_devices = iop_config.max_devices; 1997175942Sscottl hba->max_request_size = iop_config.request_size; 1998175942Sscottl hba->max_sg_count = iop_config.max_sg_count; 1999175942Sscottl 2000242214Sdelphij if (hba->ops->family == MVFREY_BASED_IOP) { 2001242214Sdelphij if (hba->ops->internal_memalloc(hba)) { 2002242214Sdelphij device_printf(dev, "alloc srb_dmat failed\n"); 2003242214Sdelphij goto destroy_parent_tag; 2004242214Sdelphij } 2005242214Sdelphij if (hba->ops->reset_comm(hba)) { 2006242214Sdelphij device_printf(dev, "reset comm failed\n"); 2007242214Sdelphij goto get_config_failed; 2008242214Sdelphij } 2009242214Sdelphij } 2010242214Sdelphij 2011169412Sscottl if (bus_dma_tag_create(hba->parent_dmat,/* parent */ 2012169412Sscottl 4, /* alignment */ 2013169412Sscottl BUS_SPACE_MAXADDR_32BIT+1, /* boundary */ 2014169412Sscottl BUS_SPACE_MAXADDR, /* lowaddr */ 2015169412Sscottl BUS_SPACE_MAXADDR, /* highaddr */ 2016169412Sscottl NULL, NULL, /* filter, filterarg */ 2017169412Sscottl PAGE_SIZE * (hba->max_sg_count-1), /* maxsize */ 2018169412Sscottl hba->max_sg_count, /* nsegments */ 2019169412Sscottl 0x20000, /* maxsegsize */ 2020169412Sscottl BUS_DMA_ALLOCNOW, /* flags */ 2021169412Sscottl#if __FreeBSD_version>502000 2022169412Sscottl busdma_lock_mutex, /* lockfunc */ 2023169412Sscottl &hba->lock, /* lockfuncarg */ 2024169412Sscottl#endif 2025169412Sscottl &hba->io_dmat /* tag */)) 2026169412Sscottl { 2027175942Sscottl device_printf(dev, "alloc io_dmat failed\n"); 2028175942Sscottl goto get_config_failed; 2029169412Sscottl } 2030169412Sscottl 2031169412Sscottl if (bus_dma_tag_create(hba->parent_dmat,/* parent */ 2032169412Sscottl 1, /* alignment */ 2033169412Sscottl 0, /* boundary */ 2034169412Sscottl BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 2035169412Sscottl BUS_SPACE_MAXADDR, /* highaddr */ 2036169412Sscottl NULL, NULL, /* filter, filterarg */ 2037169412Sscottl HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE + 0x20, 2038169412Sscottl 1, /* nsegments */ 2039169412Sscottl BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 2040169412Sscottl 0, /* flags */ 2041169412Sscottl#if __FreeBSD_version>502000 2042169412Sscottl NULL, /* lockfunc */ 2043169412Sscottl NULL, /* lockfuncarg */ 2044169412Sscottl#endif 2045169412Sscottl &hba->srb_dmat /* tag */)) 2046169412Sscottl { 2047175942Sscottl device_printf(dev, "alloc srb_dmat failed\n"); 2048175942Sscottl goto destroy_io_dmat; 2049169412Sscottl } 2050169412Sscottl 2051169412Sscottl if (bus_dmamem_alloc(hba->srb_dmat, (void **)&hba->uncached_ptr, 2052169412Sscottl#if __FreeBSD_version>501000 2053175942Sscottl BUS_DMA_WAITOK | BUS_DMA_COHERENT, 2054169412Sscottl#else 2055175942Sscottl BUS_DMA_WAITOK, 2056169412Sscottl#endif 2057175942Sscottl &hba->srb_dmamap) != 0) 2058169412Sscottl { 2059175942Sscottl device_printf(dev, "srb bus_dmamem_alloc failed!\n"); 2060175942Sscottl goto destroy_srb_dmat; 2061169412Sscottl } 2062169412Sscottl 2063169412Sscottl if (bus_dmamap_load(hba->srb_dmat, 2064169412Sscottl hba->srb_dmamap, hba->uncached_ptr, 2065169412Sscottl (HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE) + 0x20, 2066169412Sscottl hptiop_map_srb, hba, 0)) 2067169412Sscottl { 2068175942Sscottl device_printf(dev, "bus_dmamap_load failed!\n"); 2069175942Sscottl goto srb_dmamem_free; 2070169412Sscottl } 2071169412Sscottl 2072169412Sscottl if ((devq = cam_simq_alloc(hba->max_requests - 1 )) == NULL) { 2073175942Sscottl device_printf(dev, "cam_simq_alloc failed\n"); 2074175942Sscottl goto srb_dmamap_unload; 2075169412Sscottl } 2076175942Sscottl 2077175942Sscottl#if __FreeBSD_version <700000 2078169412Sscottl hba->sim = cam_sim_alloc(hptiop_action, hptiop_poll, driver_name, 2079175942Sscottl hba, unit, hba->max_requests - 1, 1, devq); 2080175942Sscottl#else 2081175942Sscottl hba->sim = cam_sim_alloc(hptiop_action, hptiop_poll, driver_name, 2082169412Sscottl hba, unit, &Giant, hba->max_requests - 1, 1, devq); 2083175942Sscottl#endif 2084169412Sscottl if (!hba->sim) { 2085175942Sscottl device_printf(dev, "cam_sim_alloc failed\n"); 2086169412Sscottl cam_simq_free(devq); 2087175942Sscottl goto srb_dmamap_unload; 2088169412Sscottl } 2089175942Sscottl#if __FreeBSD_version <700000 2090175942Sscottl if (xpt_bus_register(hba->sim, 0) != CAM_SUCCESS) 2091175942Sscottl#else 2092175942Sscottl if (xpt_bus_register(hba->sim, dev, 0) != CAM_SUCCESS) 2093175942Sscottl#endif 2094175942Sscottl { 2095175942Sscottl device_printf(dev, "xpt_bus_register failed\n"); 2096175942Sscottl goto free_cam_sim; 2097169412Sscottl } 2098169412Sscottl 2099169412Sscottl if (xpt_create_path(&hba->path, /*periph */ NULL, 2100169412Sscottl cam_sim_path(hba->sim), CAM_TARGET_WILDCARD, 2101175942Sscottl CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 2102175942Sscottl device_printf(dev, "xpt_create_path failed\n"); 2103175942Sscottl goto deregister_xpt_bus; 2104169412Sscottl } 2105169412Sscottl 2106169412Sscottl bzero(&set_config, sizeof(set_config)); 2107175942Sscottl set_config.iop_id = unit; 2108169412Sscottl set_config.vbus_id = cam_sim_path(hba->sim); 2109169412Sscottl set_config.max_host_request_size = HPT_SRB_MAX_REQ_SIZE; 2110169412Sscottl 2111175942Sscottl if (hba->ops->set_config(hba, &set_config)) { 2112175942Sscottl device_printf(dev, "set iop config failed.\n"); 2113175942Sscottl goto free_hba_path; 2114169412Sscottl } 2115169412Sscottl 2116169412Sscottl xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5); 2117169412Sscottl ccb.ccb_h.func_code = XPT_SASYNC_CB; 2118169412Sscottl ccb.event_enable = (AC_FOUND_DEVICE | AC_LOST_DEVICE); 2119169412Sscottl ccb.callback = hptiop_async; 2120169412Sscottl ccb.callback_arg = hba->sim; 2121169412Sscottl xpt_action((union ccb *)&ccb); 2122169412Sscottl 2123169412Sscottl rid = 0; 2124169412Sscottl if ((hba->irq_res = bus_alloc_resource(hba->pcidev, SYS_RES_IRQ, 2125169412Sscottl &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) { 2126175942Sscottl device_printf(dev, "allocate irq failed!\n"); 2127175942Sscottl goto free_hba_path; 2128169412Sscottl } 2129169412Sscottl 2130175942Sscottl#if __FreeBSD_version <700000 2131169412Sscottl if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM, 2132175942Sscottl hptiop_pci_intr, hba, &hba->irq_handle)) 2133175942Sscottl#else 2134175942Sscottl if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM, 2135175942Sscottl NULL, hptiop_pci_intr, hba, &hba->irq_handle)) 2136175942Sscottl#endif 2137175942Sscottl { 2138175942Sscottl device_printf(dev, "allocate intr function failed!\n"); 2139175942Sscottl goto free_irq_resource; 2140169412Sscottl } 2141169412Sscottl 2142175942Sscottl if (hptiop_send_sync_msg(hba, 2143175942Sscottl IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) { 2144175942Sscottl device_printf(dev, "fail to start background task\n"); 2145175942Sscottl goto teartown_irq_resource; 2146169412Sscottl } 2147169412Sscottl 2148175942Sscottl hba->ops->enable_intr(hba); 2149242214Sdelphij hba->initialized = 1; 2150175942Sscottl 2151169412Sscottl hba->ioctl_dev = make_dev(&hptiop_cdevsw, unit, 2152169412Sscottl UID_ROOT, GID_WHEEL /*GID_OPERATOR*/, 2153169412Sscottl S_IRUSR | S_IWUSR, "%s%d", driver_name, unit); 2154169412Sscottl 2155169412Sscottl#if __FreeBSD_version < 503000 2156169412Sscottl hba->ioctl_dev->si_drv1 = hba; 2157169412Sscottl#endif 2158169412Sscottl 2159169412Sscottl return 0; 2160175942Sscottl 2161175942Sscottl 2162175942Sscottlteartown_irq_resource: 2163175942Sscottl bus_teardown_intr(dev, hba->irq_res, hba->irq_handle); 2164175942Sscottl 2165175942Sscottlfree_irq_resource: 2166175942Sscottl bus_release_resource(dev, SYS_RES_IRQ, 0, hba->irq_res); 2167175942Sscottl 2168175942Sscottlfree_hba_path: 2169175942Sscottl xpt_free_path(hba->path); 2170175942Sscottl 2171175942Sscottlderegister_xpt_bus: 2172175942Sscottl xpt_bus_deregister(cam_sim_path(hba->sim)); 2173175942Sscottl 2174175942Sscottlfree_cam_sim: 2175175942Sscottl cam_sim_free(hba->sim, /*free devq*/ TRUE); 2176175942Sscottl 2177175942Sscottlsrb_dmamap_unload: 2178175942Sscottl if (hba->uncached_ptr) 2179175942Sscottl bus_dmamap_unload(hba->srb_dmat, hba->srb_dmamap); 2180175942Sscottl 2181175942Sscottlsrb_dmamem_free: 2182175942Sscottl if (hba->uncached_ptr) 2183175942Sscottl bus_dmamem_free(hba->srb_dmat, 2184175942Sscottl hba->uncached_ptr, hba->srb_dmamap); 2185175942Sscottl 2186175942Sscottldestroy_srb_dmat: 2187175942Sscottl if (hba->srb_dmat) 2188175942Sscottl bus_dma_tag_destroy(hba->srb_dmat); 2189175942Sscottl 2190175942Sscottldestroy_io_dmat: 2191175942Sscottl if (hba->io_dmat) 2192175942Sscottl bus_dma_tag_destroy(hba->io_dmat); 2193175942Sscottl 2194175942Sscottlget_config_failed: 2195242214Sdelphij hba->ops->internal_memfree(hba); 2196175942Sscottl 2197175942Sscottldestroy_parent_tag: 2198175942Sscottl if (hba->parent_dmat) 2199175942Sscottl bus_dma_tag_destroy(hba->parent_dmat); 2200175942Sscottl 2201175942Sscottlrelease_pci_res: 2202175942Sscottl if (hba->ops->release_pci_res) 2203175942Sscottl hba->ops->release_pci_res(hba); 2204175942Sscottl 2205175942Sscottl return ENXIO; 2206169412Sscottl} 2207169412Sscottl 2208169412Sscottlstatic int hptiop_detach(device_t dev) 2209169412Sscottl{ 2210169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev); 2211169412Sscottl int i; 2212169412Sscottl int error = EBUSY; 2213169412Sscottl 2214169412Sscottl hptiop_lock_adapter(hba); 2215175942Sscottl for (i = 0; i < hba->max_devices; i++) 2216175942Sscottl if (hptiop_os_query_remove_device(hba, i)) { 2217175942Sscottl device_printf(dev, "%d file system is busy. id=%d", 2218169412Sscottl hba->pciunit, i); 2219169412Sscottl goto out; 2220169412Sscottl } 2221169412Sscottl 2222169412Sscottl if ((error = hptiop_shutdown(dev)) != 0) 2223169412Sscottl goto out; 2224175942Sscottl if (hptiop_send_sync_msg(hba, 2225175942Sscottl IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK, 60000)) 2226169412Sscottl goto out; 2227169412Sscottl 2228169412Sscottl hptiop_release_resource(hba); 2229169412Sscottl error = 0; 2230169412Sscottlout: 2231169412Sscottl hptiop_unlock_adapter(hba); 2232169412Sscottl return error; 2233169412Sscottl} 2234169412Sscottl 2235169412Sscottlstatic int hptiop_shutdown(device_t dev) 2236169412Sscottl{ 2237169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev); 2238169412Sscottl 2239169412Sscottl int error = 0; 2240169412Sscottl 2241169412Sscottl if (hba->flag & HPT_IOCTL_FLAG_OPEN) { 2242175942Sscottl device_printf(dev, "%d device is busy", hba->pciunit); 2243169412Sscottl return EBUSY; 2244169412Sscottl } 2245175942Sscottl 2246175942Sscottl hba->ops->disable_intr(hba); 2247175942Sscottl 2248175942Sscottl if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_SHUTDOWN, 60000)) 2249169412Sscottl error = EBUSY; 2250169412Sscottl 2251169412Sscottl return error; 2252169412Sscottl} 2253169412Sscottl 2254169412Sscottlstatic void hptiop_pci_intr(void *arg) 2255169412Sscottl{ 2256169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg; 2257169412Sscottl hptiop_lock_adapter(hba); 2258175942Sscottl hba->ops->iop_intr(hba); 2259169412Sscottl hptiop_unlock_adapter(hba); 2260169412Sscottl} 2261169412Sscottl 2262169412Sscottlstatic void hptiop_poll(struct cam_sim *sim) 2263169412Sscottl{ 2264169412Sscottl hptiop_pci_intr(cam_sim_softc(sim)); 2265169412Sscottl} 2266169412Sscottl 2267169412Sscottlstatic void hptiop_async(void * callback_arg, u_int32_t code, 2268169412Sscottl struct cam_path * path, void * arg) 2269169412Sscottl{ 2270169412Sscottl} 2271169412Sscottl 2272175942Sscottlstatic void hptiop_enable_intr_itl(struct hpt_iop_hba *hba) 2273169412Sscottl{ 2274175942Sscottl BUS_SPACE_WRT4_ITL(outbound_intmask, 2275169412Sscottl ~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0)); 2276169412Sscottl} 2277169412Sscottl 2278175942Sscottlstatic void hptiop_enable_intr_mv(struct hpt_iop_hba *hba) 2279169412Sscottl{ 2280169412Sscottl u_int32_t int_mask; 2281169412Sscottl 2282175942Sscottl int_mask = BUS_SPACE_RD4_MV0(outbound_intmask); 2283175942Sscottl 2284175942Sscottl int_mask |= MVIOP_MU_OUTBOUND_INT_POSTQUEUE 2285175942Sscottl | MVIOP_MU_OUTBOUND_INT_MSG; 2286175942Sscottl BUS_SPACE_WRT4_MV0(outbound_intmask,int_mask); 2287169412Sscottl} 2288169412Sscottl 2289242214Sdelphijstatic void hptiop_enable_intr_mvfrey(struct hpt_iop_hba *hba) 2290242214Sdelphij{ 2291242214Sdelphij BUS_SPACE_WRT4_MVFREY2(f0_doorbell_enable, CPU_TO_F0_DRBL_MSG_A_BIT); 2292242214Sdelphij BUS_SPACE_RD4_MVFREY2(f0_doorbell_enable); 2293242214Sdelphij 2294242214Sdelphij BUS_SPACE_WRT4_MVFREY2(isr_enable, 0x1); 2295242214Sdelphij BUS_SPACE_RD4_MVFREY2(isr_enable); 2296242214Sdelphij 2297242214Sdelphij BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0x1010); 2298242214Sdelphij BUS_SPACE_RD4_MVFREY2(pcie_f0_int_enable); 2299242214Sdelphij} 2300242214Sdelphij 2301175942Sscottlstatic void hptiop_disable_intr_itl(struct hpt_iop_hba *hba) 2302175942Sscottl{ 2303175942Sscottl u_int32_t int_mask; 2304175942Sscottl 2305175942Sscottl int_mask = BUS_SPACE_RD4_ITL(outbound_intmask); 2306175942Sscottl 2307175942Sscottl int_mask |= IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0; 2308175942Sscottl BUS_SPACE_WRT4_ITL(outbound_intmask, int_mask); 2309175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 2310175942Sscottl} 2311175942Sscottl 2312175942Sscottlstatic void hptiop_disable_intr_mv(struct hpt_iop_hba *hba) 2313175942Sscottl{ 2314175942Sscottl u_int32_t int_mask; 2315175942Sscottl int_mask = BUS_SPACE_RD4_MV0(outbound_intmask); 2316175942Sscottl 2317175942Sscottl int_mask &= ~(MVIOP_MU_OUTBOUND_INT_MSG 2318175942Sscottl | MVIOP_MU_OUTBOUND_INT_POSTQUEUE); 2319175942Sscottl BUS_SPACE_WRT4_MV0(outbound_intmask,int_mask); 2320175942Sscottl BUS_SPACE_RD4_MV0(outbound_intmask); 2321175942Sscottl} 2322175942Sscottl 2323242214Sdelphijstatic void hptiop_disable_intr_mvfrey(struct hpt_iop_hba *hba) 2324169412Sscottl{ 2325242214Sdelphij BUS_SPACE_WRT4_MVFREY2(f0_doorbell_enable, 0); 2326242214Sdelphij BUS_SPACE_RD4_MVFREY2(f0_doorbell_enable); 2327242214Sdelphij 2328242214Sdelphij BUS_SPACE_WRT4_MVFREY2(isr_enable, 0); 2329242214Sdelphij BUS_SPACE_RD4_MVFREY2(isr_enable); 2330242214Sdelphij 2331242214Sdelphij BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0); 2332242214Sdelphij BUS_SPACE_RD4_MVFREY2(pcie_f0_int_enable); 2333169412Sscottl} 2334169412Sscottl 2335242214Sdelphijstatic void hptiop_reset_adapter(void *argv) 2336242214Sdelphij{ 2337242214Sdelphij struct hpt_iop_hba * hba = (struct hpt_iop_hba *)argv; 2338242214Sdelphij if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000)) 2339242214Sdelphij return; 2340242214Sdelphij hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000); 2341242214Sdelphij} 2342242214Sdelphij 2343169412Sscottlstatic void *hptiop_get_srb(struct hpt_iop_hba * hba) 2344169412Sscottl{ 2345169412Sscottl struct hpt_iop_srb * srb; 2346169412Sscottl 2347169412Sscottl if (hba->srb_list) { 2348169412Sscottl srb = hba->srb_list; 2349169412Sscottl hba->srb_list = srb->next; 2350175942Sscottl return srb; 2351169412Sscottl } 2352169412Sscottl 2353175942Sscottl return NULL; 2354169412Sscottl} 2355169412Sscottl 2356175942Sscottlstatic void hptiop_free_srb(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb) 2357169412Sscottl{ 2358169412Sscottl srb->next = hba->srb_list; 2359169412Sscottl hba->srb_list = srb; 2360169412Sscottl} 2361169412Sscottl 2362169412Sscottlstatic void hptiop_action(struct cam_sim *sim, union ccb *ccb) 2363169412Sscottl{ 2364169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)cam_sim_softc(sim); 2365169412Sscottl struct hpt_iop_srb * srb; 2366251874Sscottl int error; 2367169412Sscottl 2368169412Sscottl switch (ccb->ccb_h.func_code) { 2369169412Sscottl 2370169412Sscottl case XPT_SCSI_IO: 2371169412Sscottl hptiop_lock_adapter(hba); 2372169412Sscottl if (ccb->ccb_h.target_lun != 0 || 2373175942Sscottl ccb->ccb_h.target_id >= hba->max_devices || 2374169412Sscottl (ccb->ccb_h.flags & CAM_CDB_PHYS)) 2375169412Sscottl { 2376169412Sscottl ccb->ccb_h.status = CAM_TID_INVALID; 2377169412Sscottl xpt_done(ccb); 2378169412Sscottl goto scsi_done; 2379169412Sscottl } 2380169412Sscottl 2381169412Sscottl if ((srb = hptiop_get_srb(hba)) == NULL) { 2382175942Sscottl device_printf(hba->pcidev, "srb allocated failed"); 2383169412Sscottl ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2384169412Sscottl xpt_done(ccb); 2385169412Sscottl goto scsi_done; 2386169412Sscottl } 2387169412Sscottl 2388169412Sscottl srb->ccb = ccb; 2389251874Sscottl error = bus_dmamap_load_ccb(hba->io_dmat, 2390251874Sscottl srb->dma_map, 2391251874Sscottl ccb, 2392251874Sscottl hptiop_post_scsi_command, 2393251874Sscottl srb, 2394251874Sscottl 0); 2395169412Sscottl 2396251874Sscottl if (error && error != EINPROGRESS) { 2397251874Sscottl device_printf(hba->pcidev, 2398251874Sscottl "%d bus_dmamap_load error %d", 2399251874Sscottl hba->pciunit, error); 2400251874Sscottl xpt_freeze_simq(hba->sim, 1); 2401251874Sscottl ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2402251874Sscottl hptiop_free_srb(hba, srb); 2403251874Sscottl xpt_done(ccb); 2404251874Sscottl goto scsi_done; 2405169412Sscottl } 2406169412Sscottl 2407169412Sscottlscsi_done: 2408169412Sscottl hptiop_unlock_adapter(hba); 2409169412Sscottl return; 2410169412Sscottl 2411169412Sscottl case XPT_RESET_BUS: 2412175942Sscottl device_printf(hba->pcidev, "reset adapter"); 2413169412Sscottl hptiop_lock_adapter(hba); 2414169412Sscottl hba->msg_done = 0; 2415169412Sscottl hptiop_reset_adapter(hba); 2416169412Sscottl hptiop_unlock_adapter(hba); 2417169412Sscottl break; 2418169412Sscottl 2419169412Sscottl case XPT_GET_TRAN_SETTINGS: 2420169412Sscottl case XPT_SET_TRAN_SETTINGS: 2421169412Sscottl ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 2422169412Sscottl break; 2423169412Sscottl 2424169412Sscottl case XPT_CALC_GEOMETRY: 2425230719Smarius#if __FreeBSD_version >= 500000 2426230719Smarius cam_calc_geometry(&ccb->ccg, 1); 2427230719Smarius#else 2428169412Sscottl ccb->ccg.heads = 255; 2429169412Sscottl ccb->ccg.secs_per_track = 63; 2430169412Sscottl ccb->ccg.cylinders = ccb->ccg.volume_size / 2431169412Sscottl (ccb->ccg.heads * ccb->ccg.secs_per_track); 2432169412Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 2433230719Smarius#endif 2434169412Sscottl break; 2435169412Sscottl 2436169412Sscottl case XPT_PATH_INQ: 2437169412Sscottl { 2438169412Sscottl struct ccb_pathinq *cpi = &ccb->cpi; 2439169412Sscottl 2440169412Sscottl cpi->version_num = 1; 2441169412Sscottl cpi->hba_inquiry = PI_SDTR_ABLE; 2442169412Sscottl cpi->target_sprt = 0; 2443169412Sscottl cpi->hba_misc = PIM_NOBUSRESET; 2444169412Sscottl cpi->hba_eng_cnt = 0; 2445175942Sscottl cpi->max_target = hba->max_devices; 2446169412Sscottl cpi->max_lun = 0; 2447169412Sscottl cpi->unit_number = cam_sim_unit(sim); 2448169412Sscottl cpi->bus_id = cam_sim_bus(sim); 2449175942Sscottl cpi->initiator_id = hba->max_devices; 2450169412Sscottl cpi->base_transfer_speed = 3300; 2451169412Sscottl 2452169412Sscottl strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2453169412Sscottl strncpy(cpi->hba_vid, "HPT ", HBA_IDLEN); 2454169412Sscottl strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 2455209340Smav cpi->transport = XPORT_SPI; 2456209340Smav cpi->transport_version = 2; 2457209340Smav cpi->protocol = PROTO_SCSI; 2458209340Smav cpi->protocol_version = SCSI_REV_2; 2459169412Sscottl cpi->ccb_h.status = CAM_REQ_CMP; 2460169412Sscottl break; 2461169412Sscottl } 2462169412Sscottl 2463169412Sscottl default: 2464169412Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 2465169412Sscottl break; 2466169412Sscottl } 2467169412Sscottl 2468169412Sscottl xpt_done(ccb); 2469169412Sscottl return; 2470169412Sscottl} 2471169412Sscottl 2472175942Sscottlstatic void hptiop_post_req_itl(struct hpt_iop_hba *hba, 2473175942Sscottl struct hpt_iop_srb *srb, 2474175942Sscottl bus_dma_segment_t *segs, int nsegs) 2475169412Sscottl{ 2476169412Sscottl int idx; 2477169412Sscottl union ccb *ccb = srb->ccb; 2478169412Sscottl u_int8_t *cdb; 2479169412Sscottl 2480175942Sscottl if (ccb->ccb_h.flags & CAM_CDB_POINTER) 2481175942Sscottl cdb = ccb->csio.cdb_io.cdb_ptr; 2482175942Sscottl else 2483175942Sscottl cdb = ccb->csio.cdb_io.cdb_bytes; 2484169412Sscottl 2485175942Sscottl KdPrint(("ccb=%p %x-%x-%x\n", 2486175942Sscottl ccb, *(u_int32_t *)cdb, *((u_int32_t *)cdb+1), *((u_int32_t *)cdb+2))); 2487169412Sscottl 2488169412Sscottl if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) { 2489175942Sscottl u_int32_t iop_req32; 2490175942Sscottl struct hpt_iop_request_scsi_command req; 2491169412Sscottl 2492175942Sscottl iop_req32 = BUS_SPACE_RD4_ITL(inbound_queue); 2493175942Sscottl 2494175942Sscottl if (iop_req32 == IOPMU_QUEUE_EMPTY) { 2495175942Sscottl device_printf(hba->pcidev, "invaild req offset\n"); 2496175942Sscottl ccb->ccb_h.status = CAM_BUSY; 2497175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 2498175942Sscottl hptiop_free_srb(hba, srb); 2499175942Sscottl xpt_done(ccb); 2500175942Sscottl return; 2501169412Sscottl } 2502175942Sscottl 2503175942Sscottl if (ccb->csio.dxfer_len && nsegs > 0) { 2504175942Sscottl struct hpt_iopsg *psg = req.sg_list; 2505175942Sscottl for (idx = 0; idx < nsegs; idx++, psg++) { 2506175942Sscottl psg->pci_address = (u_int64_t)segs[idx].ds_addr; 2507175942Sscottl psg->size = segs[idx].ds_len; 2508175942Sscottl psg->eot = 0; 2509175942Sscottl } 2510175942Sscottl psg[-1].eot = 1; 2511175942Sscottl } 2512175942Sscottl 2513175942Sscottl bcopy(cdb, req.cdb, ccb->csio.cdb_len); 2514175942Sscottl 2515242214Sdelphij req.header.size = 2516242214Sdelphij offsetof(struct hpt_iop_request_scsi_command, sg_list) 2517175942Sscottl + nsegs*sizeof(struct hpt_iopsg); 2518175942Sscottl req.header.type = IOP_REQUEST_TYPE_SCSI_COMMAND; 2519175942Sscottl req.header.flags = 0; 2520175942Sscottl req.header.result = IOP_RESULT_PENDING; 2521175942Sscottl req.header.context = (u_int64_t)(unsigned long)srb; 2522175942Sscottl req.dataxfer_length = ccb->csio.dxfer_len; 2523175942Sscottl req.channel = 0; 2524175942Sscottl req.target = ccb->ccb_h.target_id; 2525175942Sscottl req.lun = ccb->ccb_h.target_lun; 2526175942Sscottl 2527175942Sscottl bus_space_write_region_1(hba->bar0t, hba->bar0h, iop_req32, 2528175942Sscottl (u_int8_t *)&req, req.header.size); 2529175942Sscottl 2530175942Sscottl if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 2531175942Sscottl bus_dmamap_sync(hba->io_dmat, 2532175942Sscottl srb->dma_map, BUS_DMASYNC_PREREAD); 2533175942Sscottl } 2534175942Sscottl else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) 2535175942Sscottl bus_dmamap_sync(hba->io_dmat, 2536175942Sscottl srb->dma_map, BUS_DMASYNC_PREWRITE); 2537175942Sscottl 2538175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue,iop_req32); 2539175942Sscottl } else { 2540175942Sscottl struct hpt_iop_request_scsi_command *req; 2541175942Sscottl 2542169412Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 2543175942Sscottl if (ccb->csio.dxfer_len && nsegs > 0) { 2544175942Sscottl struct hpt_iopsg *psg = req->sg_list; 2545175942Sscottl for (idx = 0; idx < nsegs; idx++, psg++) { 2546175942Sscottl psg->pci_address = 2547175942Sscottl (u_int64_t)segs[idx].ds_addr; 2548175942Sscottl psg->size = segs[idx].ds_len; 2549175942Sscottl psg->eot = 0; 2550175942Sscottl } 2551175942Sscottl psg[-1].eot = 1; 2552175942Sscottl } 2553169412Sscottl 2554175942Sscottl bcopy(cdb, req->cdb, ccb->csio.cdb_len); 2555175942Sscottl 2556175942Sscottl req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND; 2557175942Sscottl req->header.result = IOP_RESULT_PENDING; 2558175942Sscottl req->dataxfer_length = ccb->csio.dxfer_len; 2559175942Sscottl req->channel = 0; 2560175942Sscottl req->target = ccb->ccb_h.target_id; 2561175942Sscottl req->lun = ccb->ccb_h.target_lun; 2562242214Sdelphij req->header.size = 2563242214Sdelphij offsetof(struct hpt_iop_request_scsi_command, sg_list) 2564175942Sscottl + nsegs*sizeof(struct hpt_iopsg); 2565175942Sscottl req->header.context = (u_int64_t)srb->index | 2566175942Sscottl IOPMU_QUEUE_ADDR_HOST_BIT; 2567175942Sscottl req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT; 2568175942Sscottl 2569175942Sscottl if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 2570175942Sscottl bus_dmamap_sync(hba->io_dmat, 2571175942Sscottl srb->dma_map, BUS_DMASYNC_PREREAD); 2572175942Sscottl }else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 2573175942Sscottl bus_dmamap_sync(hba->io_dmat, 2574175942Sscottl srb->dma_map, BUS_DMASYNC_PREWRITE); 2575175942Sscottl } 2576175942Sscottl 2577175942Sscottl if (hba->firmware_version > 0x01020000 2578175942Sscottl || hba->interface_version > 0x01020000) { 2579175942Sscottl u_int32_t size_bits; 2580175942Sscottl 2581175942Sscottl if (req->header.size < 256) 2582175942Sscottl size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT; 2583175942Sscottl else if (req->header.size < 512) 2584175942Sscottl size_bits = IOPMU_QUEUE_ADDR_HOST_BIT; 2585175942Sscottl else 2586175942Sscottl size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT 2587175942Sscottl | IOPMU_QUEUE_ADDR_HOST_BIT; 2588175942Sscottl 2589175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue, 2590175942Sscottl (u_int32_t)srb->phy_addr | size_bits); 2591175942Sscottl } else 2592175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue, (u_int32_t)srb->phy_addr 2593175942Sscottl |IOPMU_QUEUE_ADDR_HOST_BIT); 2594175942Sscottl } 2595175942Sscottl} 2596175942Sscottl 2597175942Sscottlstatic void hptiop_post_req_mv(struct hpt_iop_hba *hba, 2598175942Sscottl struct hpt_iop_srb *srb, 2599175942Sscottl bus_dma_segment_t *segs, int nsegs) 2600175942Sscottl{ 2601175942Sscottl int idx, size; 2602175942Sscottl union ccb *ccb = srb->ccb; 2603175942Sscottl u_int8_t *cdb; 2604175942Sscottl struct hpt_iop_request_scsi_command *req; 2605175942Sscottl u_int64_t req_phy; 2606175942Sscottl 2607175942Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 2608175942Sscottl req_phy = srb->phy_addr; 2609175942Sscottl 2610169412Sscottl if (ccb->csio.dxfer_len && nsegs > 0) { 2611169412Sscottl struct hpt_iopsg *psg = req->sg_list; 2612169412Sscottl for (idx = 0; idx < nsegs; idx++, psg++) { 2613169412Sscottl psg->pci_address = (u_int64_t)segs[idx].ds_addr; 2614169412Sscottl psg->size = segs[idx].ds_len; 2615169412Sscottl psg->eot = 0; 2616169412Sscottl } 2617169412Sscottl psg[-1].eot = 1; 2618169412Sscottl } 2619169412Sscottl if (ccb->ccb_h.flags & CAM_CDB_POINTER) 2620169412Sscottl cdb = ccb->csio.cdb_io.cdb_ptr; 2621169412Sscottl else 2622169412Sscottl cdb = ccb->csio.cdb_io.cdb_bytes; 2623169412Sscottl 2624169412Sscottl bcopy(cdb, req->cdb, ccb->csio.cdb_len); 2625169412Sscottl req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND; 2626169412Sscottl req->header.result = IOP_RESULT_PENDING; 2627169412Sscottl req->dataxfer_length = ccb->csio.dxfer_len; 2628175942Sscottl req->channel = 0; 2629169412Sscottl req->target = ccb->ccb_h.target_id; 2630169412Sscottl req->lun = ccb->ccb_h.target_lun; 2631169412Sscottl req->header.size = sizeof(struct hpt_iop_request_scsi_command) 2632175942Sscottl - sizeof(struct hpt_iopsg) 2633175942Sscottl + nsegs * sizeof(struct hpt_iopsg); 2634169412Sscottl if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 2635169412Sscottl bus_dmamap_sync(hba->io_dmat, 2636175942Sscottl srb->dma_map, BUS_DMASYNC_PREREAD); 2637169412Sscottl } 2638169412Sscottl else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) 2639169412Sscottl bus_dmamap_sync(hba->io_dmat, 2640175942Sscottl srb->dma_map, BUS_DMASYNC_PREWRITE); 2641175942Sscottl req->header.context = (u_int64_t)srb->index 2642175942Sscottl << MVIOP_REQUEST_NUMBER_START_BIT 2643175942Sscottl | MVIOP_CMD_TYPE_SCSI; 2644175942Sscottl req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT; 2645175942Sscottl size = req->header.size >> 8; 2646175942Sscottl hptiop_mv_inbound_write(req_phy 2647175942Sscottl | MVIOP_MU_QUEUE_ADDR_HOST_BIT 2648175942Sscottl | (size > 3 ? 3 : size), hba); 2649169412Sscottl} 2650169412Sscottl 2651242214Sdelphijstatic void hptiop_post_req_mvfrey(struct hpt_iop_hba *hba, 2652242214Sdelphij struct hpt_iop_srb *srb, 2653242214Sdelphij bus_dma_segment_t *segs, int nsegs) 2654242214Sdelphij{ 2655242214Sdelphij int idx, index; 2656242214Sdelphij union ccb *ccb = srb->ccb; 2657242214Sdelphij u_int8_t *cdb; 2658242214Sdelphij struct hpt_iop_request_scsi_command *req; 2659242214Sdelphij u_int64_t req_phy; 2660242214Sdelphij 2661242214Sdelphij req = (struct hpt_iop_request_scsi_command *)srb; 2662242214Sdelphij req_phy = srb->phy_addr; 2663242214Sdelphij 2664242214Sdelphij if (ccb->csio.dxfer_len && nsegs > 0) { 2665242214Sdelphij struct hpt_iopsg *psg = req->sg_list; 2666242214Sdelphij for (idx = 0; idx < nsegs; idx++, psg++) { 2667242214Sdelphij psg->pci_address = (u_int64_t)segs[idx].ds_addr | 1; 2668242214Sdelphij psg->size = segs[idx].ds_len; 2669242214Sdelphij psg->eot = 0; 2670242214Sdelphij } 2671242214Sdelphij psg[-1].eot = 1; 2672242214Sdelphij } 2673242214Sdelphij if (ccb->ccb_h.flags & CAM_CDB_POINTER) 2674242214Sdelphij cdb = ccb->csio.cdb_io.cdb_ptr; 2675242214Sdelphij else 2676242214Sdelphij cdb = ccb->csio.cdb_io.cdb_bytes; 2677242214Sdelphij 2678242214Sdelphij bcopy(cdb, req->cdb, ccb->csio.cdb_len); 2679242214Sdelphij req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND; 2680242214Sdelphij req->header.result = IOP_RESULT_PENDING; 2681242214Sdelphij req->dataxfer_length = ccb->csio.dxfer_len; 2682242214Sdelphij req->channel = 0; 2683242214Sdelphij req->target = ccb->ccb_h.target_id; 2684242214Sdelphij req->lun = ccb->ccb_h.target_lun; 2685242214Sdelphij req->header.size = sizeof(struct hpt_iop_request_scsi_command) 2686242214Sdelphij - sizeof(struct hpt_iopsg) 2687242214Sdelphij + nsegs * sizeof(struct hpt_iopsg); 2688242214Sdelphij if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 2689242214Sdelphij bus_dmamap_sync(hba->io_dmat, 2690242214Sdelphij srb->dma_map, BUS_DMASYNC_PREREAD); 2691242214Sdelphij } 2692242214Sdelphij else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) 2693242214Sdelphij bus_dmamap_sync(hba->io_dmat, 2694242214Sdelphij srb->dma_map, BUS_DMASYNC_PREWRITE); 2695242214Sdelphij 2696242214Sdelphij req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT 2697242214Sdelphij | IOP_REQUEST_FLAG_ADDR_BITS 2698242214Sdelphij | ((req_phy >> 16) & 0xffff0000); 2699242214Sdelphij req->header.context = ((req_phy & 0xffffffff) << 32 ) 2700242214Sdelphij | srb->index << 4 2701242214Sdelphij | IOPMU_QUEUE_ADDR_HOST_BIT | req->header.type; 2702242214Sdelphij 2703242214Sdelphij hba->u.mvfrey.inlist_wptr++; 2704242214Sdelphij index = hba->u.mvfrey.inlist_wptr & 0x3fff; 2705242214Sdelphij 2706242214Sdelphij if (index == hba->u.mvfrey.list_count) { 2707242214Sdelphij index = 0; 2708242214Sdelphij hba->u.mvfrey.inlist_wptr &= ~0x3fff; 2709242214Sdelphij hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE; 2710242214Sdelphij } 2711242214Sdelphij 2712242214Sdelphij hba->u.mvfrey.inlist[index].addr = req_phy; 2713242214Sdelphij hba->u.mvfrey.inlist[index].intrfc_len = (req->header.size + 3) / 4; 2714242214Sdelphij 2715242214Sdelphij BUS_SPACE_WRT4_MVFREY2(inbound_write_ptr, hba->u.mvfrey.inlist_wptr); 2716242214Sdelphij BUS_SPACE_RD4_MVFREY2(inbound_write_ptr); 2717242214Sdelphij 2718242214Sdelphij if (req->header.type == IOP_REQUEST_TYPE_SCSI_COMMAND) { 2719242214Sdelphij ccb->ccb_h.timeout_ch = timeout(hptiop_reset_adapter, hba, 20*hz); 2720242214Sdelphij } 2721242214Sdelphij} 2722242214Sdelphij 2723175942Sscottlstatic void hptiop_post_scsi_command(void *arg, bus_dma_segment_t *segs, 2724175942Sscottl int nsegs, int error) 2725169412Sscottl{ 2726175942Sscottl struct hpt_iop_srb *srb = (struct hpt_iop_srb *)arg; 2727175942Sscottl union ccb *ccb = srb->ccb; 2728175942Sscottl struct hpt_iop_hba *hba = srb->hba; 2729169412Sscottl 2730175942Sscottl if (error || nsegs > hba->max_sg_count) { 2731175942Sscottl KdPrint(("hptiop: func_code=%x tid=%x lun=%x nsegs=%d\n", 2732175942Sscottl ccb->ccb_h.func_code, 2733175942Sscottl ccb->ccb_h.target_id, 2734175942Sscottl ccb->ccb_h.target_lun, nsegs)); 2735175942Sscottl ccb->ccb_h.status = CAM_BUSY; 2736175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 2737169412Sscottl hptiop_free_srb(hba, srb); 2738169412Sscottl xpt_done(ccb); 2739175942Sscottl return; 2740169412Sscottl } 2741175942Sscottl 2742175942Sscottl hba->ops->post_req(hba, srb, segs, nsegs); 2743169412Sscottl} 2744169412Sscottl 2745175942Sscottlstatic void hptiop_mv_map_ctlcfg(void *arg, bus_dma_segment_t *segs, 2746175942Sscottl int nsegs, int error) 2747175942Sscottl{ 2748175942Sscottl struct hpt_iop_hba *hba = (struct hpt_iop_hba *)arg; 2749175942Sscottl hba->ctlcfgcmd_phy = ((u_int64_t)segs->ds_addr + 0x1F) 2750175942Sscottl & ~(u_int64_t)0x1F; 2751175942Sscottl hba->ctlcfg_ptr = (u_int8_t *)(((unsigned long)hba->ctlcfg_ptr + 0x1F) 2752175942Sscottl & ~0x1F); 2753175942Sscottl} 2754175942Sscottl 2755242214Sdelphijstatic void hptiop_mvfrey_map_ctlcfg(void *arg, bus_dma_segment_t *segs, 2756242214Sdelphij int nsegs, int error) 2757242214Sdelphij{ 2758242214Sdelphij struct hpt_iop_hba *hba = (struct hpt_iop_hba *)arg; 2759242214Sdelphij char *p; 2760242214Sdelphij u_int64_t phy; 2761242214Sdelphij u_int32_t list_count = hba->u.mvfrey.list_count; 2762242214Sdelphij 2763242214Sdelphij phy = ((u_int64_t)segs->ds_addr + 0x1F) 2764242214Sdelphij & ~(u_int64_t)0x1F; 2765242214Sdelphij p = (u_int8_t *)(((unsigned long)hba->ctlcfg_ptr + 0x1F) 2766242214Sdelphij & ~0x1F); 2767242214Sdelphij 2768242214Sdelphij hba->ctlcfgcmd_phy = phy; 2769242214Sdelphij hba->ctlcfg_ptr = p; 2770242214Sdelphij 2771242214Sdelphij p += 0x800; 2772242214Sdelphij phy += 0x800; 2773242214Sdelphij 2774242214Sdelphij hba->u.mvfrey.inlist = (struct mvfrey_inlist_entry *)p; 2775242214Sdelphij hba->u.mvfrey.inlist_phy = phy; 2776242214Sdelphij 2777242214Sdelphij p += list_count * sizeof(struct mvfrey_inlist_entry); 2778242214Sdelphij phy += list_count * sizeof(struct mvfrey_inlist_entry); 2779242214Sdelphij 2780242214Sdelphij hba->u.mvfrey.outlist = (struct mvfrey_outlist_entry *)p; 2781242214Sdelphij hba->u.mvfrey.outlist_phy = phy; 2782242214Sdelphij 2783242214Sdelphij p += list_count * sizeof(struct mvfrey_outlist_entry); 2784242214Sdelphij phy += list_count * sizeof(struct mvfrey_outlist_entry); 2785242214Sdelphij 2786242214Sdelphij hba->u.mvfrey.outlist_cptr = (u_int32_t *)p; 2787242214Sdelphij hba->u.mvfrey.outlist_cptr_phy = phy; 2788242214Sdelphij} 2789242214Sdelphij 2790169412Sscottlstatic void hptiop_map_srb(void *arg, bus_dma_segment_t *segs, 2791175942Sscottl int nsegs, int error) 2792169412Sscottl{ 2793169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg; 2794169412Sscottl bus_addr_t phy_addr = (segs->ds_addr + 0x1F) & ~(bus_addr_t)0x1F; 2795169412Sscottl struct hpt_iop_srb *srb, *tmp_srb; 2796169412Sscottl int i; 2797169412Sscottl 2798169412Sscottl if (error || nsegs == 0) { 2799175942Sscottl device_printf(hba->pcidev, "hptiop_map_srb error"); 2800169412Sscottl return; 2801169412Sscottl } 2802169412Sscottl 2803169412Sscottl /* map srb */ 2804169412Sscottl srb = (struct hpt_iop_srb *) 2805175942Sscottl (((unsigned long)hba->uncached_ptr + 0x1F) 2806175942Sscottl & ~(unsigned long)0x1F); 2807169412Sscottl 2808169412Sscottl for (i = 0; i < HPT_SRB_MAX_QUEUE_SIZE; i++) { 2809169412Sscottl tmp_srb = (struct hpt_iop_srb *) 2810169412Sscottl ((char *)srb + i * HPT_SRB_MAX_SIZE); 2811169412Sscottl if (((unsigned long)tmp_srb & 0x1F) == 0) { 2812169412Sscottl if (bus_dmamap_create(hba->io_dmat, 2813169412Sscottl 0, &tmp_srb->dma_map)) { 2814175942Sscottl device_printf(hba->pcidev, "dmamap create failed"); 2815169412Sscottl return; 2816169412Sscottl } 2817169412Sscottl 2818169412Sscottl bzero(tmp_srb, sizeof(struct hpt_iop_srb)); 2819169412Sscottl tmp_srb->hba = hba; 2820169412Sscottl tmp_srb->index = i; 2821175942Sscottl if (hba->ctlcfg_ptr == 0) {/*itl iop*/ 2822175942Sscottl tmp_srb->phy_addr = (u_int64_t)(u_int32_t) 2823175942Sscottl (phy_addr >> 5); 2824175942Sscottl if (phy_addr & IOPMU_MAX_MEM_SUPPORT_MASK_32G) 2825175942Sscottl tmp_srb->srb_flag = 2826175942Sscottl HPT_SRB_FLAG_HIGH_MEM_ACESS; 2827175942Sscottl } else { 2828175942Sscottl tmp_srb->phy_addr = phy_addr; 2829175942Sscottl } 2830175942Sscottl 2831169412Sscottl hptiop_free_srb(hba, tmp_srb); 2832169412Sscottl hba->srb[i] = tmp_srb; 2833169412Sscottl phy_addr += HPT_SRB_MAX_SIZE; 2834169412Sscottl } 2835169412Sscottl else { 2836175942Sscottl device_printf(hba->pcidev, "invalid alignment"); 2837169412Sscottl return; 2838169412Sscottl } 2839169412Sscottl } 2840169412Sscottl} 2841169412Sscottl 2842175942Sscottlstatic void hptiop_os_message_callback(struct hpt_iop_hba * hba, u_int32_t msg) 2843169412Sscottl{ 2844242214Sdelphij hba->msg_done = 1; 2845169412Sscottl} 2846169412Sscottl 2847175942Sscottlstatic int hptiop_os_query_remove_device(struct hpt_iop_hba * hba, 2848175942Sscottl int target_id) 2849169412Sscottl{ 2850169412Sscottl struct cam_periph *periph = NULL; 2851169412Sscottl struct cam_path *path; 2852169412Sscottl int status, retval = 0; 2853169412Sscottl 2854169412Sscottl status = xpt_create_path(&path, NULL, hba->sim->path_id, target_id, 0); 2855169412Sscottl 2856169412Sscottl if (status == CAM_REQ_CMP) { 2857169412Sscottl if ((periph = cam_periph_find(path, "da")) != NULL) { 2858169412Sscottl if (periph->refcount >= 1) { 2859175942Sscottl device_printf(hba->pcidev, "%d ," 2860175942Sscottl "target_id=0x%x," 2861175942Sscottl "refcount=%d", 2862169412Sscottl hba->pciunit, target_id, periph->refcount); 2863169412Sscottl retval = -1; 2864169412Sscottl } 2865169412Sscottl } 2866169412Sscottl xpt_free_path(path); 2867169412Sscottl } 2868169412Sscottl return retval; 2869169412Sscottl} 2870169412Sscottl 2871169412Sscottlstatic void hptiop_release_resource(struct hpt_iop_hba *hba) 2872169412Sscottl{ 2873175942Sscottl int i; 2874175942Sscottl if (hba->path) { 2875175942Sscottl struct ccb_setasync ccb; 2876169412Sscottl 2877169412Sscottl xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5); 2878169412Sscottl ccb.ccb_h.func_code = XPT_SASYNC_CB; 2879169412Sscottl ccb.event_enable = 0; 2880169412Sscottl ccb.callback = hptiop_async; 2881169412Sscottl ccb.callback_arg = hba->sim; 2882169412Sscottl xpt_action((union ccb *)&ccb); 2883169412Sscottl xpt_free_path(hba->path); 2884169412Sscottl } 2885169412Sscottl 2886169412Sscottl if (hba->sim) { 2887169412Sscottl xpt_bus_deregister(cam_sim_path(hba->sim)); 2888169412Sscottl cam_sim_free(hba->sim, TRUE); 2889169412Sscottl } 2890169412Sscottl 2891175942Sscottl if (hba->ctlcfg_dmat) { 2892175942Sscottl bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap); 2893175942Sscottl bus_dmamem_free(hba->ctlcfg_dmat, 2894175942Sscottl hba->ctlcfg_ptr, hba->ctlcfg_dmamap); 2895175942Sscottl bus_dma_tag_destroy(hba->ctlcfg_dmat); 2896175942Sscottl } 2897175942Sscottl 2898175942Sscottl for (i = 0; i < HPT_SRB_MAX_QUEUE_SIZE; i++) { 2899175942Sscottl struct hpt_iop_srb *srb = hba->srb[i]; 2900175942Sscottl if (srb->dma_map) 2901175942Sscottl bus_dmamap_destroy(hba->io_dmat, srb->dma_map); 2902175942Sscottl } 2903175942Sscottl 2904169412Sscottl if (hba->srb_dmat) { 2905169412Sscottl bus_dmamap_unload(hba->srb_dmat, hba->srb_dmamap); 2906175942Sscottl bus_dmamap_destroy(hba->srb_dmat, hba->srb_dmamap); 2907169412Sscottl bus_dma_tag_destroy(hba->srb_dmat); 2908169412Sscottl } 2909169412Sscottl 2910169412Sscottl if (hba->io_dmat) 2911169412Sscottl bus_dma_tag_destroy(hba->io_dmat); 2912169412Sscottl 2913169412Sscottl if (hba->parent_dmat) 2914169412Sscottl bus_dma_tag_destroy(hba->parent_dmat); 2915169412Sscottl 2916169412Sscottl if (hba->irq_handle) 2917169412Sscottl bus_teardown_intr(hba->pcidev, hba->irq_res, hba->irq_handle); 2918169412Sscottl 2919169412Sscottl if (hba->irq_res) 2920175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_IRQ, 2921175942Sscottl 0, hba->irq_res); 2922169412Sscottl 2923169412Sscottl if (hba->bar0_res) 2924169412Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 2925169412Sscottl hba->bar0_rid, hba->bar0_res); 2926175942Sscottl if (hba->bar2_res) 2927175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 2928175942Sscottl hba->bar2_rid, hba->bar2_res); 2929169412Sscottl if (hba->ioctl_dev) 2930169412Sscottl destroy_dev(hba->ioctl_dev); 2931169412Sscottl} 2932