1331722Seadler/* 2175942Sscottl * HighPoint RR3xxx/4xxx RAID Driver for FreeBSD 3242086Sdelphij * 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: stable/11/sys/dev/hptiop/hptiop.c 315812 2017-03-23 06:40:20Z mav $"); 29169412Sscottl 30169412Sscottl#include <sys/param.h> 31169412Sscottl#include <sys/types.h> 32169412Sscottl#include <sys/cons.h> 33169412Sscottl#include <sys/time.h> 34169412Sscottl#include <sys/systm.h> 35169412Sscottl 36169412Sscottl#include <sys/stat.h> 37169412Sscottl#include <sys/malloc.h> 38169412Sscottl#include <sys/conf.h> 39169412Sscottl#include <sys/libkern.h> 40169412Sscottl#include <sys/kernel.h> 41169412Sscottl 42169412Sscottl#include <sys/kthread.h> 43169412Sscottl#include <sys/mutex.h> 44169412Sscottl#include <sys/module.h> 45169412Sscottl 46169412Sscottl#include <sys/eventhandler.h> 47169412Sscottl#include <sys/bus.h> 48169412Sscottl#include <sys/taskqueue.h> 49169412Sscottl#include <sys/ioccom.h> 50169412Sscottl 51169412Sscottl#include <machine/resource.h> 52169412Sscottl#include <machine/bus.h> 53169412Sscottl#include <machine/stdarg.h> 54169412Sscottl#include <sys/rman.h> 55169412Sscottl 56169412Sscottl#include <vm/vm.h> 57169412Sscottl#include <vm/pmap.h> 58169412Sscottl 59169412Sscottl#include <dev/pci/pcireg.h> 60169412Sscottl#include <dev/pci/pcivar.h> 61169412Sscottl 62169412Sscottl 63169412Sscottl#include <cam/cam.h> 64169412Sscottl#include <cam/cam_ccb.h> 65169412Sscottl#include <cam/cam_sim.h> 66169412Sscottl#include <cam/cam_xpt_sim.h> 67169412Sscottl#include <cam/cam_debug.h> 68169412Sscottl#include <cam/cam_periph.h> 69169412Sscottl#include <cam/scsi/scsi_all.h> 70169412Sscottl#include <cam/scsi/scsi_message.h> 71169412Sscottl 72169412Sscottl 73169412Sscottl#include <dev/hptiop/hptiop.h> 74169412Sscottl 75242086Sdelphijstatic const char driver_name[] = "hptiop"; 76252851Sdelphijstatic const char driver_version[] = "v1.9"; 77169412Sscottl 78169412Sscottlstatic devclass_t hptiop_devclass; 79169412Sscottl 80175942Sscottlstatic int hptiop_send_sync_msg(struct hpt_iop_hba *hba, 81175942Sscottl u_int32_t msg, u_int32_t millisec); 82175942Sscottlstatic void hptiop_request_callback_itl(struct hpt_iop_hba *hba, 83175942Sscottl u_int32_t req); 84175942Sscottlstatic void hptiop_request_callback_mv(struct hpt_iop_hba *hba, u_int64_t req); 85242086Sdelphijstatic void hptiop_request_callback_mvfrey(struct hpt_iop_hba *hba, 86242086Sdelphij u_int32_t req); 87175942Sscottlstatic void hptiop_os_message_callback(struct hpt_iop_hba *hba, u_int32_t msg); 88175942Sscottlstatic int hptiop_do_ioctl_itl(struct hpt_iop_hba *hba, 89175942Sscottl struct hpt_iop_ioctl_param *pParams); 90175942Sscottlstatic int hptiop_do_ioctl_mv(struct hpt_iop_hba *hba, 91175942Sscottl struct hpt_iop_ioctl_param *pParams); 92242086Sdelphijstatic int hptiop_do_ioctl_mvfrey(struct hpt_iop_hba *hba, 93242086Sdelphij struct hpt_iop_ioctl_param *pParams); 94175942Sscottlstatic int hptiop_rescan_bus(struct hpt_iop_hba *hba); 95175942Sscottlstatic int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba); 96175942Sscottlstatic int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba); 97242086Sdelphijstatic int hptiop_alloc_pci_res_mvfrey(struct hpt_iop_hba *hba); 98175942Sscottlstatic int hptiop_get_config_itl(struct hpt_iop_hba *hba, 99175942Sscottl struct hpt_iop_request_get_config *config); 100175942Sscottlstatic int hptiop_get_config_mv(struct hpt_iop_hba *hba, 101175942Sscottl struct hpt_iop_request_get_config *config); 102242086Sdelphijstatic int hptiop_get_config_mvfrey(struct hpt_iop_hba *hba, 103242086Sdelphij struct hpt_iop_request_get_config *config); 104175942Sscottlstatic int hptiop_set_config_itl(struct hpt_iop_hba *hba, 105175942Sscottl struct hpt_iop_request_set_config *config); 106175942Sscottlstatic int hptiop_set_config_mv(struct hpt_iop_hba *hba, 107175942Sscottl struct hpt_iop_request_set_config *config); 108242086Sdelphijstatic int hptiop_set_config_mvfrey(struct hpt_iop_hba *hba, 109242086Sdelphij struct hpt_iop_request_set_config *config); 110175942Sscottlstatic int hptiop_internal_memalloc_mv(struct hpt_iop_hba *hba); 111242086Sdelphijstatic int hptiop_internal_memalloc_mvfrey(struct hpt_iop_hba *hba); 112242086Sdelphijstatic int hptiop_internal_memfree_itl(struct hpt_iop_hba *hba); 113175942Sscottlstatic int hptiop_internal_memfree_mv(struct hpt_iop_hba *hba); 114242086Sdelphijstatic int hptiop_internal_memfree_mvfrey(struct hpt_iop_hba *hba); 115175942Sscottlstatic int hptiop_post_ioctl_command_itl(struct hpt_iop_hba *hba, 116175942Sscottl u_int32_t req32, struct hpt_iop_ioctl_param *pParams); 117175942Sscottlstatic int hptiop_post_ioctl_command_mv(struct hpt_iop_hba *hba, 118175942Sscottl struct hpt_iop_request_ioctl_command *req, 119175942Sscottl struct hpt_iop_ioctl_param *pParams); 120242086Sdelphijstatic int hptiop_post_ioctl_command_mvfrey(struct hpt_iop_hba *hba, 121242086Sdelphij struct hpt_iop_request_ioctl_command *req, 122242086Sdelphij struct hpt_iop_ioctl_param *pParams); 123175942Sscottlstatic void hptiop_post_req_itl(struct hpt_iop_hba *hba, 124175942Sscottl struct hpt_iop_srb *srb, 125175942Sscottl bus_dma_segment_t *segs, int nsegs); 126175942Sscottlstatic void hptiop_post_req_mv(struct hpt_iop_hba *hba, 127175942Sscottl struct hpt_iop_srb *srb, 128175942Sscottl bus_dma_segment_t *segs, int nsegs); 129242086Sdelphijstatic void hptiop_post_req_mvfrey(struct hpt_iop_hba *hba, 130242086Sdelphij struct hpt_iop_srb *srb, 131242086Sdelphij bus_dma_segment_t *segs, int nsegs); 132175942Sscottlstatic void hptiop_post_msg_itl(struct hpt_iop_hba *hba, u_int32_t msg); 133175942Sscottlstatic void hptiop_post_msg_mv(struct hpt_iop_hba *hba, u_int32_t msg); 134242086Sdelphijstatic void hptiop_post_msg_mvfrey(struct hpt_iop_hba *hba, u_int32_t msg); 135175942Sscottlstatic void hptiop_enable_intr_itl(struct hpt_iop_hba *hba); 136175942Sscottlstatic void hptiop_enable_intr_mv(struct hpt_iop_hba *hba); 137242086Sdelphijstatic void hptiop_enable_intr_mvfrey(struct hpt_iop_hba *hba); 138175942Sscottlstatic void hptiop_disable_intr_itl(struct hpt_iop_hba *hba); 139175942Sscottlstatic void hptiop_disable_intr_mv(struct hpt_iop_hba *hba); 140242086Sdelphijstatic void hptiop_disable_intr_mvfrey(struct hpt_iop_hba *hba); 141175942Sscottlstatic void hptiop_free_srb(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb); 142175942Sscottlstatic int hptiop_os_query_remove_device(struct hpt_iop_hba *hba, int tid); 143169412Sscottlstatic int hptiop_probe(device_t dev); 144169412Sscottlstatic int hptiop_attach(device_t dev); 145169412Sscottlstatic int hptiop_detach(device_t dev); 146169412Sscottlstatic int hptiop_shutdown(device_t dev); 147169412Sscottlstatic void hptiop_action(struct cam_sim *sim, union ccb *ccb); 148169412Sscottlstatic void hptiop_poll(struct cam_sim *sim); 149175942Sscottlstatic void hptiop_async(void *callback_arg, u_int32_t code, 150175942Sscottl struct cam_path *path, void *arg); 151169412Sscottlstatic void hptiop_pci_intr(void *arg); 152175942Sscottlstatic void hptiop_release_resource(struct hpt_iop_hba *hba); 153242086Sdelphijstatic void hptiop_reset_adapter(void *argv); 154169412Sscottlstatic d_open_t hptiop_open; 155169412Sscottlstatic d_close_t hptiop_close; 156169412Sscottlstatic d_ioctl_t hptiop_ioctl; 157169412Sscottl 158169412Sscottlstatic struct cdevsw hptiop_cdevsw = { 159169412Sscottl .d_open = hptiop_open, 160169412Sscottl .d_close = hptiop_close, 161169412Sscottl .d_ioctl = hptiop_ioctl, 162169412Sscottl .d_name = driver_name, 163169412Sscottl .d_version = D_VERSION, 164169412Sscottl}; 165169412Sscottl 166169412Sscottl#define hba_from_dev(dev) \ 167183397Sed ((struct hpt_iop_hba *)devclass_get_softc(hptiop_devclass, dev2unit(dev))) 168169412Sscottl 169175942Sscottl#define BUS_SPACE_WRT4_ITL(offset, value) bus_space_write_4(hba->bar0t,\ 170175942Sscottl hba->bar0h, offsetof(struct hpt_iopmu_itl, offset), (value)) 171175942Sscottl#define BUS_SPACE_RD4_ITL(offset) bus_space_read_4(hba->bar0t,\ 172175942Sscottl hba->bar0h, offsetof(struct hpt_iopmu_itl, offset)) 173175942Sscottl 174175942Sscottl#define BUS_SPACE_WRT4_MV0(offset, value) bus_space_write_4(hba->bar0t,\ 175175942Sscottl hba->bar0h, offsetof(struct hpt_iopmv_regs, offset), value) 176175942Sscottl#define BUS_SPACE_RD4_MV0(offset) bus_space_read_4(hba->bar0t,\ 177175942Sscottl hba->bar0h, offsetof(struct hpt_iopmv_regs, offset)) 178175942Sscottl#define BUS_SPACE_WRT4_MV2(offset, value) bus_space_write_4(hba->bar2t,\ 179175942Sscottl hba->bar2h, offsetof(struct hpt_iopmu_mv, offset), value) 180175942Sscottl#define BUS_SPACE_RD4_MV2(offset) bus_space_read_4(hba->bar2t,\ 181175942Sscottl hba->bar2h, offsetof(struct hpt_iopmu_mv, offset)) 182175942Sscottl 183242086Sdelphij#define BUS_SPACE_WRT4_MVFREY2(offset, value) bus_space_write_4(hba->bar2t,\ 184242086Sdelphij hba->bar2h, offsetof(struct hpt_iopmu_mvfrey, offset), value) 185242086Sdelphij#define BUS_SPACE_RD4_MVFREY2(offset) bus_space_read_4(hba->bar2t,\ 186242086Sdelphij hba->bar2h, offsetof(struct hpt_iopmu_mvfrey, offset)) 187242086Sdelphij 188169412Sscottlstatic int hptiop_open(ioctl_dev_t dev, int flags, 189169412Sscottl int devtype, ioctl_thread_t proc) 190169412Sscottl{ 191175942Sscottl struct hpt_iop_hba *hba = hba_from_dev(dev); 192169412Sscottl 193169412Sscottl if (hba==NULL) 194169412Sscottl return ENXIO; 195169412Sscottl if (hba->flag & HPT_IOCTL_FLAG_OPEN) 196169412Sscottl return EBUSY; 197169412Sscottl hba->flag |= HPT_IOCTL_FLAG_OPEN; 198169412Sscottl return 0; 199169412Sscottl} 200169412Sscottl 201169412Sscottlstatic int hptiop_close(ioctl_dev_t dev, int flags, 202169412Sscottl int devtype, ioctl_thread_t proc) 203169412Sscottl{ 204175942Sscottl struct hpt_iop_hba *hba = hba_from_dev(dev); 205169412Sscottl hba->flag &= ~(u_int32_t)HPT_IOCTL_FLAG_OPEN; 206169412Sscottl return 0; 207169412Sscottl} 208169412Sscottl 209169412Sscottlstatic int hptiop_ioctl(ioctl_dev_t dev, u_long cmd, caddr_t data, 210169412Sscottl int flags, ioctl_thread_t proc) 211169412Sscottl{ 212169412Sscottl int ret = EFAULT; 213175942Sscottl struct hpt_iop_hba *hba = hba_from_dev(dev); 214169412Sscottl 215169412Sscottl mtx_lock(&Giant); 216169412Sscottl 217169412Sscottl switch (cmd) { 218169412Sscottl case HPT_DO_IOCONTROL: 219175942Sscottl ret = hba->ops->do_ioctl(hba, 220175942Sscottl (struct hpt_iop_ioctl_param *)data); 221169412Sscottl break; 222169412Sscottl case HPT_SCAN_BUS: 223169412Sscottl ret = hptiop_rescan_bus(hba); 224169412Sscottl break; 225169412Sscottl } 226169412Sscottl 227169412Sscottl mtx_unlock(&Giant); 228169412Sscottl 229169412Sscottl return ret; 230169412Sscottl} 231169412Sscottl 232175942Sscottlstatic u_int64_t hptiop_mv_outbound_read(struct hpt_iop_hba *hba) 233169412Sscottl{ 234175942Sscottl u_int64_t p; 235175942Sscottl u_int32_t outbound_tail = BUS_SPACE_RD4_MV2(outbound_tail); 236175942Sscottl u_int32_t outbound_head = BUS_SPACE_RD4_MV2(outbound_head); 237175942Sscottl 238175942Sscottl if (outbound_tail != outbound_head) { 239175942Sscottl bus_space_read_region_4(hba->bar2t, hba->bar2h, 240175942Sscottl offsetof(struct hpt_iopmu_mv, 241175942Sscottl outbound_q[outbound_tail]), 242175942Sscottl (u_int32_t *)&p, 2); 243175942Sscottl 244175942Sscottl outbound_tail++; 245175942Sscottl 246175942Sscottl if (outbound_tail == MVIOP_QUEUE_LEN) 247175942Sscottl outbound_tail = 0; 248175942Sscottl 249175942Sscottl BUS_SPACE_WRT4_MV2(outbound_tail, outbound_tail); 250175942Sscottl return p; 251175942Sscottl } else 252175942Sscottl return 0; 253169412Sscottl} 254169412Sscottl 255175942Sscottlstatic void hptiop_mv_inbound_write(u_int64_t p, struct hpt_iop_hba *hba) 256169412Sscottl{ 257175942Sscottl u_int32_t inbound_head = BUS_SPACE_RD4_MV2(inbound_head); 258175942Sscottl u_int32_t head = inbound_head + 1; 259175942Sscottl 260175942Sscottl if (head == MVIOP_QUEUE_LEN) 261175942Sscottl head = 0; 262175942Sscottl 263175942Sscottl bus_space_write_region_4(hba->bar2t, hba->bar2h, 264175942Sscottl offsetof(struct hpt_iopmu_mv, inbound_q[inbound_head]), 265175942Sscottl (u_int32_t *)&p, 2); 266175942Sscottl BUS_SPACE_WRT4_MV2(inbound_head, head); 267175942Sscottl BUS_SPACE_WRT4_MV0(inbound_doorbell, MVIOP_MU_INBOUND_INT_POSTQUEUE); 268169412Sscottl} 269169412Sscottl 270175942Sscottlstatic void hptiop_post_msg_itl(struct hpt_iop_hba *hba, u_int32_t msg) 271169412Sscottl{ 272175942Sscottl BUS_SPACE_WRT4_ITL(inbound_msgaddr0, msg); 273175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 274169412Sscottl} 275169412Sscottl 276175942Sscottlstatic void hptiop_post_msg_mv(struct hpt_iop_hba *hba, u_int32_t msg) 277169412Sscottl{ 278175942Sscottl 279175942Sscottl BUS_SPACE_WRT4_MV2(inbound_msg, msg); 280175942Sscottl BUS_SPACE_WRT4_MV0(inbound_doorbell, MVIOP_MU_INBOUND_INT_MSG); 281175942Sscottl 282175942Sscottl BUS_SPACE_RD4_MV0(outbound_intmask); 283169412Sscottl} 284169412Sscottl 285242086Sdelphijstatic void hptiop_post_msg_mvfrey(struct hpt_iop_hba *hba, u_int32_t msg) 286242086Sdelphij{ 287242086Sdelphij BUS_SPACE_WRT4_MVFREY2(f0_to_cpu_msg_a, msg); 288242086Sdelphij BUS_SPACE_RD4_MVFREY2(f0_to_cpu_msg_a); 289242086Sdelphij} 290242086Sdelphij 291175942Sscottlstatic int hptiop_wait_ready_itl(struct hpt_iop_hba * hba, u_int32_t millisec) 292169412Sscottl{ 293169412Sscottl u_int32_t req=0; 294169412Sscottl int i; 295169412Sscottl 296169412Sscottl for (i = 0; i < millisec; i++) { 297175942Sscottl req = BUS_SPACE_RD4_ITL(inbound_queue); 298169412Sscottl if (req != IOPMU_QUEUE_EMPTY) 299169412Sscottl break; 300169412Sscottl DELAY(1000); 301169412Sscottl } 302169412Sscottl 303169412Sscottl if (req!=IOPMU_QUEUE_EMPTY) { 304175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req); 305175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 306169412Sscottl return 0; 307169412Sscottl } 308169412Sscottl 309169412Sscottl return -1; 310169412Sscottl} 311169412Sscottl 312175942Sscottlstatic int hptiop_wait_ready_mv(struct hpt_iop_hba * hba, u_int32_t millisec) 313169412Sscottl{ 314175942Sscottl if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec)) 315175942Sscottl return -1; 316175942Sscottl 317175942Sscottl return 0; 318175942Sscottl} 319175942Sscottl 320242086Sdelphijstatic int hptiop_wait_ready_mvfrey(struct hpt_iop_hba * hba, 321242086Sdelphij u_int32_t millisec) 322242086Sdelphij{ 323242086Sdelphij if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec)) 324242086Sdelphij return -1; 325242086Sdelphij 326242086Sdelphij return 0; 327242086Sdelphij} 328242086Sdelphij 329175942Sscottlstatic void hptiop_request_callback_itl(struct hpt_iop_hba * hba, 330175942Sscottl u_int32_t index) 331175942Sscottl{ 332175942Sscottl struct hpt_iop_srb *srb; 333315221Spfg struct hpt_iop_request_scsi_command *req=NULL; 334175942Sscottl union ccb *ccb; 335175942Sscottl u_int8_t *cdb; 336175942Sscottl u_int32_t result, temp, dxfer; 337175942Sscottl u_int64_t temp64; 338175942Sscottl 339175942Sscottl if (index & IOPMU_QUEUE_MASK_HOST_BITS) { /*host req*/ 340175942Sscottl if (hba->firmware_version > 0x01020000 || 341175942Sscottl hba->interface_version > 0x01020000) { 342175942Sscottl srb = hba->srb[index & ~(u_int32_t) 343175942Sscottl (IOPMU_QUEUE_ADDR_HOST_BIT 344175942Sscottl | IOPMU_QUEUE_REQUEST_RESULT_BIT)]; 345175942Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 346175942Sscottl if (index & IOPMU_QUEUE_REQUEST_RESULT_BIT) 347175942Sscottl result = IOP_RESULT_SUCCESS; 348175942Sscottl else 349175942Sscottl result = req->header.result; 350175942Sscottl } else { 351175942Sscottl srb = hba->srb[index & 352175942Sscottl ~(u_int32_t)IOPMU_QUEUE_ADDR_HOST_BIT]; 353175942Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 354175942Sscottl result = req->header.result; 355175942Sscottl } 356175942Sscottl dxfer = req->dataxfer_length; 357175942Sscottl goto srb_complete; 358175942Sscottl } 359175942Sscottl 360175942Sscottl /*iop req*/ 361175942Sscottl temp = bus_space_read_4(hba->bar0t, hba->bar0h, index + 362175942Sscottl offsetof(struct hpt_iop_request_header, type)); 363175942Sscottl result = bus_space_read_4(hba->bar0t, hba->bar0h, index + 364175942Sscottl offsetof(struct hpt_iop_request_header, result)); 365175942Sscottl switch(temp) { 366175942Sscottl case IOP_REQUEST_TYPE_IOCTL_COMMAND: 367175942Sscottl { 368175942Sscottl temp64 = 0; 369175942Sscottl bus_space_write_region_4(hba->bar0t, hba->bar0h, index + 370175942Sscottl offsetof(struct hpt_iop_request_header, context), 371175942Sscottl (u_int32_t *)&temp64, 2); 372175942Sscottl wakeup((void *)((unsigned long)hba->u.itl.mu + index)); 373175942Sscottl break; 374175942Sscottl } 375175942Sscottl 376175942Sscottl case IOP_REQUEST_TYPE_SCSI_COMMAND: 377175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h, index + 378175942Sscottl offsetof(struct hpt_iop_request_header, context), 379175942Sscottl (u_int32_t *)&temp64, 2); 380175942Sscottl srb = (struct hpt_iop_srb *)(unsigned long)temp64; 381175942Sscottl dxfer = bus_space_read_4(hba->bar0t, hba->bar0h, 382175942Sscottl index + offsetof(struct hpt_iop_request_scsi_command, 383175942Sscottl dataxfer_length)); 384175942Sscottlsrb_complete: 385175942Sscottl ccb = (union ccb *)srb->ccb; 386175942Sscottl if (ccb->ccb_h.flags & CAM_CDB_POINTER) 387175942Sscottl cdb = ccb->csio.cdb_io.cdb_ptr; 388175942Sscottl else 389175942Sscottl cdb = ccb->csio.cdb_io.cdb_bytes; 390175942Sscottl 391175942Sscottl if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */ 392175942Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 393175942Sscottl goto scsi_done; 394175942Sscottl } 395175942Sscottl 396175942Sscottl switch (result) { 397175942Sscottl case IOP_RESULT_SUCCESS: 398175942Sscottl switch (ccb->ccb_h.flags & CAM_DIR_MASK) { 399175942Sscottl case CAM_DIR_IN: 400175942Sscottl bus_dmamap_sync(hba->io_dmat, 401175942Sscottl srb->dma_map, BUS_DMASYNC_POSTREAD); 402175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 403175942Sscottl break; 404175942Sscottl case CAM_DIR_OUT: 405175942Sscottl bus_dmamap_sync(hba->io_dmat, 406175942Sscottl srb->dma_map, BUS_DMASYNC_POSTWRITE); 407175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 408175942Sscottl break; 409175942Sscottl } 410175942Sscottl 411175942Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 412175942Sscottl break; 413175942Sscottl 414175942Sscottl case IOP_RESULT_BAD_TARGET: 415175942Sscottl ccb->ccb_h.status = CAM_DEV_NOT_THERE; 416175942Sscottl break; 417175942Sscottl case IOP_RESULT_BUSY: 418175942Sscottl ccb->ccb_h.status = CAM_BUSY; 419175942Sscottl break; 420175942Sscottl case IOP_RESULT_INVALID_REQUEST: 421175942Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 422175942Sscottl break; 423175942Sscottl case IOP_RESULT_FAIL: 424175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 425175942Sscottl break; 426175942Sscottl case IOP_RESULT_RESET: 427175942Sscottl ccb->ccb_h.status = CAM_BUSY; 428175942Sscottl break; 429175942Sscottl case IOP_RESULT_CHECK_CONDITION: 430226350Smarius memset(&ccb->csio.sense_data, 0, 431226350Smarius sizeof(ccb->csio.sense_data)); 432226350Smarius if (dxfer < ccb->csio.sense_len) 433226350Smarius ccb->csio.sense_resid = ccb->csio.sense_len - 434226350Smarius dxfer; 435226350Smarius else 436226350Smarius ccb->csio.sense_resid = 0; 437175942Sscottl if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) {/*iop*/ 438175942Sscottl bus_space_read_region_1(hba->bar0t, hba->bar0h, 439175942Sscottl index + offsetof(struct hpt_iop_request_scsi_command, 440175942Sscottl sg_list), (u_int8_t *)&ccb->csio.sense_data, 441175942Sscottl MIN(dxfer, sizeof(ccb->csio.sense_data))); 442175942Sscottl } else { 443175942Sscottl memcpy(&ccb->csio.sense_data, &req->sg_list, 444175942Sscottl MIN(dxfer, sizeof(ccb->csio.sense_data))); 445175942Sscottl } 446175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 447175942Sscottl ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 448175942Sscottl ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 449175942Sscottl break; 450175942Sscottl default: 451175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 452175942Sscottl break; 453175942Sscottl } 454175942Sscottlscsi_done: 455175942Sscottl if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) 456175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, index); 457175942Sscottl 458175942Sscottl ccb->csio.resid = ccb->csio.dxfer_len - dxfer; 459175942Sscottl 460175942Sscottl hptiop_free_srb(hba, srb); 461175942Sscottl xpt_done(ccb); 462175942Sscottl break; 463175942Sscottl } 464175942Sscottl} 465175942Sscottl 466175942Sscottlstatic void hptiop_drain_outbound_queue_itl(struct hpt_iop_hba *hba) 467175942Sscottl{ 468175942Sscottl u_int32_t req, temp; 469175942Sscottl 470175942Sscottl while ((req = BUS_SPACE_RD4_ITL(outbound_queue)) !=IOPMU_QUEUE_EMPTY) { 471175942Sscottl if (req & IOPMU_QUEUE_MASK_HOST_BITS) 472175942Sscottl hptiop_request_callback_itl(hba, req); 473175942Sscottl else { 474175942Sscottl struct hpt_iop_request_header *p; 475175942Sscottl 476175942Sscottl p = (struct hpt_iop_request_header *) 477175942Sscottl ((char *)hba->u.itl.mu + req); 478175942Sscottl temp = bus_space_read_4(hba->bar0t, 479175942Sscottl hba->bar0h,req + 480175942Sscottl offsetof(struct hpt_iop_request_header, 481175942Sscottl flags)); 482175942Sscottl if (temp & IOP_REQUEST_FLAG_SYNC_REQUEST) { 483175942Sscottl u_int64_t temp64; 484175942Sscottl bus_space_read_region_4(hba->bar0t, 485175942Sscottl hba->bar0h,req + 486175942Sscottl offsetof(struct hpt_iop_request_header, 487175942Sscottl context), 488175942Sscottl (u_int32_t *)&temp64, 2); 489175942Sscottl if (temp64) { 490175942Sscottl hptiop_request_callback_itl(hba, req); 491175942Sscottl } else { 492175942Sscottl temp64 = 1; 493175942Sscottl bus_space_write_region_4(hba->bar0t, 494175942Sscottl hba->bar0h,req + 495175942Sscottl offsetof(struct hpt_iop_request_header, 496175942Sscottl context), 497175942Sscottl (u_int32_t *)&temp64, 2); 498175942Sscottl } 499175942Sscottl } else 500175942Sscottl hptiop_request_callback_itl(hba, req); 501175942Sscottl } 502175942Sscottl } 503175942Sscottl} 504175942Sscottl 505175942Sscottlstatic int hptiop_intr_itl(struct hpt_iop_hba * hba) 506175942Sscottl{ 507169412Sscottl u_int32_t status; 508169412Sscottl int ret = 0; 509169412Sscottl 510175942Sscottl status = BUS_SPACE_RD4_ITL(outbound_intstatus); 511169412Sscottl 512169412Sscottl if (status & IOPMU_OUTBOUND_INT_MSG0) { 513175942Sscottl u_int32_t msg = BUS_SPACE_RD4_ITL(outbound_msgaddr0); 514175942Sscottl KdPrint(("hptiop: received outbound msg %x\n", msg)); 515175942Sscottl BUS_SPACE_WRT4_ITL(outbound_intstatus, IOPMU_OUTBOUND_INT_MSG0); 516175942Sscottl hptiop_os_message_callback(hba, msg); 517169412Sscottl ret = 1; 518169412Sscottl } 519169412Sscottl 520169412Sscottl if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) { 521175942Sscottl hptiop_drain_outbound_queue_itl(hba); 522175942Sscottl ret = 1; 523175942Sscottl } 524175942Sscottl 525175942Sscottl return ret; 526175942Sscottl} 527175942Sscottl 528175942Sscottlstatic void hptiop_request_callback_mv(struct hpt_iop_hba * hba, 529175942Sscottl u_int64_t _tag) 530175942Sscottl{ 531175942Sscottl u_int32_t context = (u_int32_t)_tag; 532175942Sscottl 533175942Sscottl if (context & MVIOP_CMD_TYPE_SCSI) { 534175942Sscottl struct hpt_iop_srb *srb; 535175942Sscottl struct hpt_iop_request_scsi_command *req; 536175942Sscottl union ccb *ccb; 537175942Sscottl u_int8_t *cdb; 538175942Sscottl 539175942Sscottl srb = hba->srb[context >> MVIOP_REQUEST_NUMBER_START_BIT]; 540175942Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 541175942Sscottl ccb = (union ccb *)srb->ccb; 542175942Sscottl if (ccb->ccb_h.flags & CAM_CDB_POINTER) 543175942Sscottl cdb = ccb->csio.cdb_io.cdb_ptr; 544175942Sscottl else 545175942Sscottl cdb = ccb->csio.cdb_io.cdb_bytes; 546175942Sscottl 547175942Sscottl if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */ 548175942Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 549175942Sscottl goto scsi_done; 550175942Sscottl } 551175942Sscottl if (context & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT) 552175942Sscottl req->header.result = IOP_RESULT_SUCCESS; 553175942Sscottl 554175942Sscottl switch (req->header.result) { 555175942Sscottl case IOP_RESULT_SUCCESS: 556175942Sscottl switch (ccb->ccb_h.flags & CAM_DIR_MASK) { 557175942Sscottl case CAM_DIR_IN: 558175942Sscottl bus_dmamap_sync(hba->io_dmat, 559175942Sscottl srb->dma_map, BUS_DMASYNC_POSTREAD); 560175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 561175942Sscottl break; 562175942Sscottl case CAM_DIR_OUT: 563175942Sscottl bus_dmamap_sync(hba->io_dmat, 564175942Sscottl srb->dma_map, BUS_DMASYNC_POSTWRITE); 565175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 566175942Sscottl break; 567169412Sscottl } 568175942Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 569175942Sscottl break; 570175942Sscottl case IOP_RESULT_BAD_TARGET: 571175942Sscottl ccb->ccb_h.status = CAM_DEV_NOT_THERE; 572175942Sscottl break; 573175942Sscottl case IOP_RESULT_BUSY: 574175942Sscottl ccb->ccb_h.status = CAM_BUSY; 575175942Sscottl break; 576175942Sscottl case IOP_RESULT_INVALID_REQUEST: 577175942Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 578175942Sscottl break; 579175942Sscottl case IOP_RESULT_FAIL: 580175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 581175942Sscottl break; 582175942Sscottl case IOP_RESULT_RESET: 583175942Sscottl ccb->ccb_h.status = CAM_BUSY; 584175942Sscottl break; 585175942Sscottl case IOP_RESULT_CHECK_CONDITION: 586226350Smarius memset(&ccb->csio.sense_data, 0, 587226350Smarius sizeof(ccb->csio.sense_data)); 588226350Smarius if (req->dataxfer_length < ccb->csio.sense_len) 589226350Smarius ccb->csio.sense_resid = ccb->csio.sense_len - 590226350Smarius req->dataxfer_length; 591226350Smarius else 592226350Smarius ccb->csio.sense_resid = 0; 593175942Sscottl memcpy(&ccb->csio.sense_data, &req->sg_list, 594175942Sscottl MIN(req->dataxfer_length, sizeof(ccb->csio.sense_data))); 595175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 596175942Sscottl ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 597175942Sscottl ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 598175942Sscottl break; 599175942Sscottl default: 600175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 601175942Sscottl break; 602169412Sscottl } 603175942Sscottlscsi_done: 604175942Sscottl ccb->csio.resid = ccb->csio.dxfer_len - req->dataxfer_length; 605175942Sscottl 606175942Sscottl hptiop_free_srb(hba, srb); 607175942Sscottl xpt_done(ccb); 608175942Sscottl } else if (context & MVIOP_CMD_TYPE_IOCTL) { 609175942Sscottl struct hpt_iop_request_ioctl_command *req = hba->ctlcfg_ptr; 610175942Sscottl if (context & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT) 611175942Sscottl hba->config_done = 1; 612175942Sscottl else 613175942Sscottl hba->config_done = -1; 614175942Sscottl wakeup(req); 615175942Sscottl } else if (context & 616175942Sscottl (MVIOP_CMD_TYPE_SET_CONFIG | 617175942Sscottl MVIOP_CMD_TYPE_GET_CONFIG)) 618175942Sscottl hba->config_done = 1; 619175942Sscottl else { 620175942Sscottl device_printf(hba->pcidev, "wrong callback type\n"); 621175942Sscottl } 622175942Sscottl} 623175942Sscottl 624242086Sdelphijstatic void hptiop_request_callback_mvfrey(struct hpt_iop_hba * hba, 625242086Sdelphij u_int32_t _tag) 626242086Sdelphij{ 627242086Sdelphij u_int32_t req_type = _tag & 0xf; 628242086Sdelphij 629242086Sdelphij struct hpt_iop_srb *srb; 630242086Sdelphij struct hpt_iop_request_scsi_command *req; 631242086Sdelphij union ccb *ccb; 632242086Sdelphij u_int8_t *cdb; 633242086Sdelphij 634242086Sdelphij switch (req_type) { 635242086Sdelphij case IOP_REQUEST_TYPE_GET_CONFIG: 636242086Sdelphij case IOP_REQUEST_TYPE_SET_CONFIG: 637242086Sdelphij hba->config_done = 1; 638242086Sdelphij break; 639242086Sdelphij 640242086Sdelphij case IOP_REQUEST_TYPE_SCSI_COMMAND: 641242086Sdelphij srb = hba->srb[(_tag >> 4) & 0xff]; 642242086Sdelphij req = (struct hpt_iop_request_scsi_command *)srb; 643242086Sdelphij 644242086Sdelphij ccb = (union ccb *)srb->ccb; 645242086Sdelphij 646269612Sjhb callout_stop(&srb->timeout); 647242086Sdelphij 648242086Sdelphij if (ccb->ccb_h.flags & CAM_CDB_POINTER) 649242086Sdelphij cdb = ccb->csio.cdb_io.cdb_ptr; 650242086Sdelphij else 651242086Sdelphij cdb = ccb->csio.cdb_io.cdb_bytes; 652242086Sdelphij 653242086Sdelphij if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */ 654242086Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 655242086Sdelphij goto scsi_done; 656242086Sdelphij } 657242086Sdelphij 658242086Sdelphij if (_tag & MVFREYIOPMU_QUEUE_REQUEST_RESULT_BIT) 659242086Sdelphij req->header.result = IOP_RESULT_SUCCESS; 660242086Sdelphij 661242086Sdelphij switch (req->header.result) { 662242086Sdelphij case IOP_RESULT_SUCCESS: 663242086Sdelphij switch (ccb->ccb_h.flags & CAM_DIR_MASK) { 664242086Sdelphij case CAM_DIR_IN: 665242086Sdelphij bus_dmamap_sync(hba->io_dmat, 666242086Sdelphij srb->dma_map, BUS_DMASYNC_POSTREAD); 667242086Sdelphij bus_dmamap_unload(hba->io_dmat, srb->dma_map); 668242086Sdelphij break; 669242086Sdelphij case CAM_DIR_OUT: 670242086Sdelphij bus_dmamap_sync(hba->io_dmat, 671242086Sdelphij srb->dma_map, BUS_DMASYNC_POSTWRITE); 672242086Sdelphij bus_dmamap_unload(hba->io_dmat, srb->dma_map); 673242086Sdelphij break; 674242086Sdelphij } 675242086Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 676242086Sdelphij break; 677242086Sdelphij case IOP_RESULT_BAD_TARGET: 678242086Sdelphij ccb->ccb_h.status = CAM_DEV_NOT_THERE; 679242086Sdelphij break; 680242086Sdelphij case IOP_RESULT_BUSY: 681242086Sdelphij ccb->ccb_h.status = CAM_BUSY; 682242086Sdelphij break; 683242086Sdelphij case IOP_RESULT_INVALID_REQUEST: 684242086Sdelphij ccb->ccb_h.status = CAM_REQ_INVALID; 685242086Sdelphij break; 686242086Sdelphij case IOP_RESULT_FAIL: 687242086Sdelphij ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 688242086Sdelphij break; 689242086Sdelphij case IOP_RESULT_RESET: 690242086Sdelphij ccb->ccb_h.status = CAM_BUSY; 691242086Sdelphij break; 692242086Sdelphij case IOP_RESULT_CHECK_CONDITION: 693242086Sdelphij memset(&ccb->csio.sense_data, 0, 694242086Sdelphij sizeof(ccb->csio.sense_data)); 695242086Sdelphij if (req->dataxfer_length < ccb->csio.sense_len) 696242086Sdelphij ccb->csio.sense_resid = ccb->csio.sense_len - 697242086Sdelphij req->dataxfer_length; 698242086Sdelphij else 699242086Sdelphij ccb->csio.sense_resid = 0; 700242086Sdelphij memcpy(&ccb->csio.sense_data, &req->sg_list, 701242086Sdelphij MIN(req->dataxfer_length, sizeof(ccb->csio.sense_data))); 702242086Sdelphij ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 703242086Sdelphij ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 704242086Sdelphij ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 705242086Sdelphij break; 706242086Sdelphij default: 707242086Sdelphij ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 708242086Sdelphij break; 709242086Sdelphij } 710242086Sdelphijscsi_done: 711242086Sdelphij ccb->csio.resid = ccb->csio.dxfer_len - req->dataxfer_length; 712242086Sdelphij 713242086Sdelphij hptiop_free_srb(hba, srb); 714242086Sdelphij xpt_done(ccb); 715242086Sdelphij break; 716242086Sdelphij case IOP_REQUEST_TYPE_IOCTL_COMMAND: 717242086Sdelphij if (_tag & MVFREYIOPMU_QUEUE_REQUEST_RESULT_BIT) 718242086Sdelphij hba->config_done = 1; 719242086Sdelphij else 720242086Sdelphij hba->config_done = -1; 721242086Sdelphij wakeup((struct hpt_iop_request_ioctl_command *)hba->ctlcfg_ptr); 722242086Sdelphij break; 723242086Sdelphij default: 724242086Sdelphij device_printf(hba->pcidev, "wrong callback type\n"); 725242086Sdelphij break; 726242086Sdelphij } 727242086Sdelphij} 728242086Sdelphij 729175942Sscottlstatic void hptiop_drain_outbound_queue_mv(struct hpt_iop_hba * hba) 730175942Sscottl{ 731175942Sscottl u_int64_t req; 732175942Sscottl 733175942Sscottl while ((req = hptiop_mv_outbound_read(hba))) { 734175942Sscottl if (req & MVIOP_MU_QUEUE_ADDR_HOST_BIT) { 735175942Sscottl if (req & MVIOP_MU_QUEUE_REQUEST_RETURN_CONTEXT) { 736175942Sscottl hptiop_request_callback_mv(hba, req); 737175942Sscottl } 738175942Sscottl } 739175942Sscottl } 740175942Sscottl} 741175942Sscottl 742175942Sscottlstatic int hptiop_intr_mv(struct hpt_iop_hba * hba) 743175942Sscottl{ 744175942Sscottl u_int32_t status; 745175942Sscottl int ret = 0; 746175942Sscottl 747175942Sscottl status = BUS_SPACE_RD4_MV0(outbound_doorbell); 748175942Sscottl 749175942Sscottl if (status) 750175942Sscottl BUS_SPACE_WRT4_MV0(outbound_doorbell, ~status); 751175942Sscottl 752175942Sscottl if (status & MVIOP_MU_OUTBOUND_INT_MSG) { 753175942Sscottl u_int32_t msg = BUS_SPACE_RD4_MV2(outbound_msg); 754175942Sscottl KdPrint(("hptiop: received outbound msg %x\n", msg)); 755175942Sscottl hptiop_os_message_callback(hba, msg); 756169412Sscottl ret = 1; 757169412Sscottl } 758175942Sscottl 759175942Sscottl if (status & MVIOP_MU_OUTBOUND_INT_POSTQUEUE) { 760175942Sscottl hptiop_drain_outbound_queue_mv(hba); 761175942Sscottl ret = 1; 762175942Sscottl } 763175942Sscottl 764169412Sscottl return ret; 765169412Sscottl} 766169412Sscottl 767242086Sdelphijstatic int hptiop_intr_mvfrey(struct hpt_iop_hba * hba) 768242086Sdelphij{ 769242086Sdelphij u_int32_t status, _tag, cptr; 770242086Sdelphij int ret = 0; 771242086Sdelphij 772242086Sdelphij if (hba->initialized) { 773242086Sdelphij BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0); 774242086Sdelphij } 775242086Sdelphij 776242086Sdelphij status = BUS_SPACE_RD4_MVFREY2(f0_doorbell); 777242086Sdelphij if (status) { 778242086Sdelphij BUS_SPACE_WRT4_MVFREY2(f0_doorbell, status); 779242086Sdelphij if (status & CPU_TO_F0_DRBL_MSG_A_BIT) { 780242086Sdelphij u_int32_t msg = BUS_SPACE_RD4_MVFREY2(cpu_to_f0_msg_a); 781242086Sdelphij hptiop_os_message_callback(hba, msg); 782242086Sdelphij } 783242086Sdelphij ret = 1; 784242086Sdelphij } 785242086Sdelphij 786242086Sdelphij status = BUS_SPACE_RD4_MVFREY2(isr_cause); 787242086Sdelphij if (status) { 788242086Sdelphij BUS_SPACE_WRT4_MVFREY2(isr_cause, status); 789242086Sdelphij do { 790242086Sdelphij cptr = *hba->u.mvfrey.outlist_cptr & 0xff; 791242086Sdelphij while (hba->u.mvfrey.outlist_rptr != cptr) { 792242086Sdelphij hba->u.mvfrey.outlist_rptr++; 793242086Sdelphij if (hba->u.mvfrey.outlist_rptr == hba->u.mvfrey.list_count) { 794242086Sdelphij hba->u.mvfrey.outlist_rptr = 0; 795242086Sdelphij } 796242086Sdelphij 797242086Sdelphij _tag = hba->u.mvfrey.outlist[hba->u.mvfrey.outlist_rptr].val; 798242086Sdelphij hptiop_request_callback_mvfrey(hba, _tag); 799242086Sdelphij ret = 2; 800242086Sdelphij } 801242086Sdelphij } while (cptr != (*hba->u.mvfrey.outlist_cptr & 0xff)); 802242086Sdelphij } 803242086Sdelphij 804242086Sdelphij if (hba->initialized) { 805242086Sdelphij BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0x1010); 806242086Sdelphij } 807242086Sdelphij 808242086Sdelphij return ret; 809242086Sdelphij} 810242086Sdelphij 811175942Sscottlstatic int hptiop_send_sync_request_itl(struct hpt_iop_hba * hba, 812175942Sscottl u_int32_t req32, u_int32_t millisec) 813169412Sscottl{ 814169412Sscottl u_int32_t i; 815175942Sscottl u_int64_t temp64; 816169412Sscottl 817175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue, req32); 818175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 819169412Sscottl 820169412Sscottl for (i = 0; i < millisec; i++) { 821175942Sscottl hptiop_intr_itl(hba); 822175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h, req32 + 823175942Sscottl offsetof(struct hpt_iop_request_header, context), 824175942Sscottl (u_int32_t *)&temp64, 2); 825175942Sscottl if (temp64) 826169412Sscottl return 0; 827169412Sscottl DELAY(1000); 828169412Sscottl } 829169412Sscottl 830169412Sscottl return -1; 831169412Sscottl} 832169412Sscottl 833175942Sscottlstatic int hptiop_send_sync_request_mv(struct hpt_iop_hba *hba, 834175942Sscottl void *req, u_int32_t millisec) 835169412Sscottl{ 836169412Sscottl u_int32_t i; 837175942Sscottl u_int64_t phy_addr; 838175942Sscottl hba->config_done = 0; 839169412Sscottl 840175942Sscottl phy_addr = hba->ctlcfgcmd_phy | 841175942Sscottl (u_int64_t)MVIOP_MU_QUEUE_ADDR_HOST_BIT; 842175942Sscottl ((struct hpt_iop_request_get_config *)req)->header.flags |= 843175942Sscottl IOP_REQUEST_FLAG_SYNC_REQUEST | 844175942Sscottl IOP_REQUEST_FLAG_OUTPUT_CONTEXT; 845175942Sscottl hptiop_mv_inbound_write(phy_addr, hba); 846175942Sscottl BUS_SPACE_RD4_MV0(outbound_intmask); 847169412Sscottl 848175942Sscottl for (i = 0; i < millisec; i++) { 849175942Sscottl hptiop_intr_mv(hba); 850175942Sscottl if (hba->config_done) 851175942Sscottl return 0; 852175942Sscottl DELAY(1000); 853175942Sscottl } 854175942Sscottl return -1; 855175942Sscottl} 856169412Sscottl 857242086Sdelphijstatic int hptiop_send_sync_request_mvfrey(struct hpt_iop_hba *hba, 858242086Sdelphij void *req, u_int32_t millisec) 859242086Sdelphij{ 860242086Sdelphij u_int32_t i, index; 861242086Sdelphij u_int64_t phy_addr; 862242086Sdelphij struct hpt_iop_request_header *reqhdr = 863242086Sdelphij (struct hpt_iop_request_header *)req; 864242086Sdelphij 865242086Sdelphij hba->config_done = 0; 866242086Sdelphij 867242086Sdelphij phy_addr = hba->ctlcfgcmd_phy; 868242086Sdelphij reqhdr->flags = IOP_REQUEST_FLAG_SYNC_REQUEST 869242086Sdelphij | IOP_REQUEST_FLAG_OUTPUT_CONTEXT 870242086Sdelphij | IOP_REQUEST_FLAG_ADDR_BITS 871242086Sdelphij | ((phy_addr >> 16) & 0xffff0000); 872242086Sdelphij reqhdr->context = ((phy_addr & 0xffffffff) << 32 ) 873242086Sdelphij | IOPMU_QUEUE_ADDR_HOST_BIT | reqhdr->type; 874242086Sdelphij 875242086Sdelphij hba->u.mvfrey.inlist_wptr++; 876242086Sdelphij index = hba->u.mvfrey.inlist_wptr & 0x3fff; 877242086Sdelphij 878242086Sdelphij if (index == hba->u.mvfrey.list_count) { 879242086Sdelphij index = 0; 880242086Sdelphij hba->u.mvfrey.inlist_wptr &= ~0x3fff; 881242086Sdelphij hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE; 882242086Sdelphij } 883242086Sdelphij 884242086Sdelphij hba->u.mvfrey.inlist[index].addr = phy_addr; 885242086Sdelphij hba->u.mvfrey.inlist[index].intrfc_len = (reqhdr->size + 3) / 4; 886242086Sdelphij 887242086Sdelphij BUS_SPACE_WRT4_MVFREY2(inbound_write_ptr, hba->u.mvfrey.inlist_wptr); 888242086Sdelphij BUS_SPACE_RD4_MVFREY2(inbound_write_ptr); 889242086Sdelphij 890242086Sdelphij for (i = 0; i < millisec; i++) { 891242086Sdelphij hptiop_intr_mvfrey(hba); 892242086Sdelphij if (hba->config_done) 893242086Sdelphij return 0; 894242086Sdelphij DELAY(1000); 895242086Sdelphij } 896242086Sdelphij return -1; 897242086Sdelphij} 898242086Sdelphij 899175942Sscottlstatic int hptiop_send_sync_msg(struct hpt_iop_hba *hba, 900175942Sscottl u_int32_t msg, u_int32_t millisec) 901175942Sscottl{ 902175942Sscottl u_int32_t i; 903169412Sscottl 904175942Sscottl hba->msg_done = 0; 905175942Sscottl hba->ops->post_msg(hba, msg); 906175942Sscottl 907175942Sscottl for (i=0; i<millisec; i++) { 908175942Sscottl hba->ops->iop_intr(hba); 909175942Sscottl if (hba->msg_done) 910169412Sscottl break; 911169412Sscottl DELAY(1000); 912169412Sscottl } 913169412Sscottl 914175942Sscottl return hba->msg_done? 0 : -1; 915169412Sscottl} 916169412Sscottl 917175942Sscottlstatic int hptiop_get_config_itl(struct hpt_iop_hba * hba, 918175942Sscottl struct hpt_iop_request_get_config * config) 919169412Sscottl{ 920175942Sscottl u_int32_t req32; 921169412Sscottl 922175942Sscottl config->header.size = sizeof(struct hpt_iop_request_get_config); 923175942Sscottl config->header.type = IOP_REQUEST_TYPE_GET_CONFIG; 924175942Sscottl config->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST; 925175942Sscottl config->header.result = IOP_RESULT_PENDING; 926175942Sscottl config->header.context = 0; 927175942Sscottl 928175942Sscottl req32 = BUS_SPACE_RD4_ITL(inbound_queue); 929175942Sscottl if (req32 == IOPMU_QUEUE_EMPTY) 930169412Sscottl return -1; 931169412Sscottl 932175942Sscottl bus_space_write_region_4(hba->bar0t, hba->bar0h, 933175942Sscottl req32, (u_int32_t *)config, 934175942Sscottl sizeof(struct hpt_iop_request_header) >> 2); 935175942Sscottl 936175942Sscottl if (hptiop_send_sync_request_itl(hba, req32, 20000)) { 937175942Sscottl KdPrint(("hptiop: get config send cmd failed")); 938175942Sscottl return -1; 939175942Sscottl } 940175942Sscottl 941175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h, 942175942Sscottl req32, (u_int32_t *)config, 943175942Sscottl sizeof(struct hpt_iop_request_get_config) >> 2); 944175942Sscottl 945175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req32); 946175942Sscottl 947175942Sscottl return 0; 948175942Sscottl} 949175942Sscottl 950175942Sscottlstatic int hptiop_get_config_mv(struct hpt_iop_hba * hba, 951175942Sscottl struct hpt_iop_request_get_config * config) 952175942Sscottl{ 953175942Sscottl struct hpt_iop_request_get_config *req; 954175942Sscottl 955175942Sscottl if (!(req = hba->ctlcfg_ptr)) 956175942Sscottl return -1; 957175942Sscottl 958169412Sscottl req->header.flags = 0; 959169412Sscottl req->header.type = IOP_REQUEST_TYPE_GET_CONFIG; 960169412Sscottl req->header.size = sizeof(struct hpt_iop_request_get_config); 961169412Sscottl req->header.result = IOP_RESULT_PENDING; 962175942Sscottl req->header.context = MVIOP_CMD_TYPE_GET_CONFIG; 963169412Sscottl 964175942Sscottl if (hptiop_send_sync_request_mv(hba, req, 20000)) { 965175942Sscottl KdPrint(("hptiop: get config send cmd failed")); 966169412Sscottl return -1; 967169412Sscottl } 968169412Sscottl 969169412Sscottl *config = *req; 970169412Sscottl return 0; 971169412Sscottl} 972169412Sscottl 973242086Sdelphijstatic int hptiop_get_config_mvfrey(struct hpt_iop_hba * hba, 974242086Sdelphij struct hpt_iop_request_get_config * config) 975242086Sdelphij{ 976242086Sdelphij struct hpt_iop_request_get_config *info = hba->u.mvfrey.config; 977242086Sdelphij 978242086Sdelphij if (info->header.size != sizeof(struct hpt_iop_request_get_config) || 979242086Sdelphij info->header.type != IOP_REQUEST_TYPE_GET_CONFIG) { 980242086Sdelphij KdPrint(("hptiop: header size %x/%x type %x/%x", 981242086Sdelphij info->header.size, (int)sizeof(struct hpt_iop_request_get_config), 982242086Sdelphij info->header.type, IOP_REQUEST_TYPE_GET_CONFIG)); 983242086Sdelphij return -1; 984242086Sdelphij } 985242086Sdelphij 986242086Sdelphij config->interface_version = info->interface_version; 987242086Sdelphij config->firmware_version = info->firmware_version; 988242086Sdelphij config->max_requests = info->max_requests; 989242086Sdelphij config->request_size = info->request_size; 990242086Sdelphij config->max_sg_count = info->max_sg_count; 991242086Sdelphij config->data_transfer_length = info->data_transfer_length; 992242086Sdelphij config->alignment_mask = info->alignment_mask; 993242086Sdelphij config->max_devices = info->max_devices; 994242086Sdelphij config->sdram_size = info->sdram_size; 995242086Sdelphij 996242086Sdelphij KdPrint(("hptiop: maxreq %x reqsz %x datalen %x maxdev %x sdram %x", 997242086Sdelphij config->max_requests, config->request_size, 998242086Sdelphij config->data_transfer_length, config->max_devices, 999242086Sdelphij config->sdram_size)); 1000242086Sdelphij 1001242086Sdelphij return 0; 1002242086Sdelphij} 1003242086Sdelphij 1004175942Sscottlstatic int hptiop_set_config_itl(struct hpt_iop_hba *hba, 1005175942Sscottl struct hpt_iop_request_set_config *config) 1006169412Sscottl{ 1007169412Sscottl u_int32_t req32; 1008169412Sscottl 1009175942Sscottl req32 = BUS_SPACE_RD4_ITL(inbound_queue); 1010175942Sscottl 1011169412Sscottl if (req32 == IOPMU_QUEUE_EMPTY) 1012169412Sscottl return -1; 1013169412Sscottl 1014175942Sscottl config->header.size = sizeof(struct hpt_iop_request_set_config); 1015175942Sscottl config->header.type = IOP_REQUEST_TYPE_SET_CONFIG; 1016175942Sscottl config->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST; 1017175942Sscottl config->header.result = IOP_RESULT_PENDING; 1018175942Sscottl config->header.context = 0; 1019175942Sscottl 1020175942Sscottl bus_space_write_region_4(hba->bar0t, hba->bar0h, req32, 1021175942Sscottl (u_int32_t *)config, 1022175942Sscottl sizeof(struct hpt_iop_request_set_config) >> 2); 1023175942Sscottl 1024175942Sscottl if (hptiop_send_sync_request_itl(hba, req32, 20000)) { 1025175942Sscottl KdPrint(("hptiop: set config send cmd failed")); 1026175942Sscottl return -1; 1027175942Sscottl } 1028175942Sscottl 1029175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req32); 1030175942Sscottl 1031175942Sscottl return 0; 1032175942Sscottl} 1033175942Sscottl 1034175942Sscottlstatic int hptiop_set_config_mv(struct hpt_iop_hba *hba, 1035175942Sscottl struct hpt_iop_request_set_config *config) 1036175942Sscottl{ 1037175942Sscottl struct hpt_iop_request_set_config *req; 1038175942Sscottl 1039175942Sscottl if (!(req = hba->ctlcfg_ptr)) 1040175942Sscottl return -1; 1041175942Sscottl 1042169412Sscottl memcpy((u_int8_t *)req + sizeof(struct hpt_iop_request_header), 1043169412Sscottl (u_int8_t *)config + sizeof(struct hpt_iop_request_header), 1044175942Sscottl sizeof(struct hpt_iop_request_set_config) - 1045175942Sscottl sizeof(struct hpt_iop_request_header)); 1046175942Sscottl 1047169412Sscottl req->header.flags = 0; 1048169412Sscottl req->header.type = IOP_REQUEST_TYPE_SET_CONFIG; 1049169412Sscottl req->header.size = sizeof(struct hpt_iop_request_set_config); 1050169412Sscottl req->header.result = IOP_RESULT_PENDING; 1051175942Sscottl req->header.context = MVIOP_CMD_TYPE_SET_CONFIG; 1052169412Sscottl 1053175942Sscottl if (hptiop_send_sync_request_mv(hba, req, 20000)) { 1054175942Sscottl KdPrint(("hptiop: set config send cmd failed")); 1055169412Sscottl return -1; 1056169412Sscottl } 1057169412Sscottl 1058169412Sscottl return 0; 1059169412Sscottl} 1060169412Sscottl 1061242086Sdelphijstatic int hptiop_set_config_mvfrey(struct hpt_iop_hba *hba, 1062242086Sdelphij struct hpt_iop_request_set_config *config) 1063242086Sdelphij{ 1064242086Sdelphij struct hpt_iop_request_set_config *req; 1065242086Sdelphij 1066242086Sdelphij if (!(req = hba->ctlcfg_ptr)) 1067242086Sdelphij return -1; 1068242086Sdelphij 1069242086Sdelphij memcpy((u_int8_t *)req + sizeof(struct hpt_iop_request_header), 1070242086Sdelphij (u_int8_t *)config + sizeof(struct hpt_iop_request_header), 1071242086Sdelphij sizeof(struct hpt_iop_request_set_config) - 1072242086Sdelphij sizeof(struct hpt_iop_request_header)); 1073242086Sdelphij 1074242086Sdelphij req->header.type = IOP_REQUEST_TYPE_SET_CONFIG; 1075242086Sdelphij req->header.size = sizeof(struct hpt_iop_request_set_config); 1076242086Sdelphij req->header.result = IOP_RESULT_PENDING; 1077242086Sdelphij 1078242086Sdelphij if (hptiop_send_sync_request_mvfrey(hba, req, 20000)) { 1079242086Sdelphij KdPrint(("hptiop: set config send cmd failed")); 1080242086Sdelphij return -1; 1081242086Sdelphij } 1082242086Sdelphij 1083242086Sdelphij return 0; 1084242086Sdelphij} 1085242086Sdelphij 1086175942Sscottlstatic int hptiop_post_ioctl_command_itl(struct hpt_iop_hba *hba, 1087175942Sscottl u_int32_t req32, 1088175942Sscottl struct hpt_iop_ioctl_param *pParams) 1089169412Sscottl{ 1090175942Sscottl u_int64_t temp64; 1091175942Sscottl struct hpt_iop_request_ioctl_command req; 1092169412Sscottl 1093175942Sscottl if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) > 1094175942Sscottl (hba->max_request_size - 1095175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf))) { 1096175942Sscottl device_printf(hba->pcidev, "request size beyond max value"); 1097175942Sscottl return -1; 1098175942Sscottl } 1099175942Sscottl 1100175942Sscottl req.header.size = offsetof(struct hpt_iop_request_ioctl_command, buf) 1101175942Sscottl + pParams->nInBufferSize; 1102175942Sscottl req.header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND; 1103175942Sscottl req.header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST; 1104175942Sscottl req.header.result = IOP_RESULT_PENDING; 1105175942Sscottl req.header.context = req32 + (u_int64_t)(unsigned long)hba->u.itl.mu; 1106175942Sscottl req.ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode); 1107175942Sscottl req.inbuf_size = pParams->nInBufferSize; 1108175942Sscottl req.outbuf_size = pParams->nOutBufferSize; 1109175942Sscottl req.bytes_returned = 0; 1110175942Sscottl 1111175942Sscottl bus_space_write_region_4(hba->bar0t, hba->bar0h, req32, (u_int32_t *)&req, 1112175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf)>>2); 1113175942Sscottl 1114175942Sscottl hptiop_lock_adapter(hba); 1115175942Sscottl 1116175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue, req32); 1117175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 1118175942Sscottl 1119175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h, req32 + 1120175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, header.context), 1121175942Sscottl (u_int32_t *)&temp64, 2); 1122175942Sscottl while (temp64) { 1123175942Sscottl if (hptiop_sleep(hba, (void *)((unsigned long)hba->u.itl.mu + req32), 1124175942Sscottl PPAUSE, "hptctl", HPT_OSM_TIMEOUT)==0) 1125175942Sscottl break; 1126175942Sscottl hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000); 1127175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h,req32 + 1128175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, 1129175942Sscottl header.context), 1130175942Sscottl (u_int32_t *)&temp64, 2); 1131175942Sscottl } 1132175942Sscottl 1133175942Sscottl hptiop_unlock_adapter(hba); 1134175942Sscottl return 0; 1135175942Sscottl} 1136175942Sscottl 1137242086Sdelphijstatic int hptiop_bus_space_copyin(struct hpt_iop_hba *hba, u_int32_t bus, 1138242086Sdelphij void *user, int size) 1139175942Sscottl{ 1140175942Sscottl unsigned char byte; 1141175942Sscottl int i; 1142175942Sscottl 1143175942Sscottl for (i=0; i<size; i++) { 1144175942Sscottl if (copyin((u_int8_t *)user + i, &byte, 1)) 1145175942Sscottl return -1; 1146175942Sscottl bus_space_write_1(hba->bar0t, hba->bar0h, bus + i, byte); 1147175942Sscottl } 1148175942Sscottl 1149175942Sscottl return 0; 1150175942Sscottl} 1151175942Sscottl 1152242086Sdelphijstatic int hptiop_bus_space_copyout(struct hpt_iop_hba *hba, u_int32_t bus, 1153242086Sdelphij void *user, int size) 1154175942Sscottl{ 1155175942Sscottl unsigned char byte; 1156175942Sscottl int i; 1157175942Sscottl 1158175942Sscottl for (i=0; i<size; i++) { 1159175942Sscottl byte = bus_space_read_1(hba->bar0t, hba->bar0h, bus + i); 1160175942Sscottl if (copyout(&byte, (u_int8_t *)user + i, 1)) 1161175942Sscottl return -1; 1162175942Sscottl } 1163175942Sscottl 1164175942Sscottl return 0; 1165175942Sscottl} 1166175942Sscottl 1167175942Sscottlstatic int hptiop_do_ioctl_itl(struct hpt_iop_hba *hba, 1168175942Sscottl struct hpt_iop_ioctl_param * pParams) 1169175942Sscottl{ 1170175942Sscottl u_int32_t req32; 1171175942Sscottl u_int32_t result; 1172175942Sscottl 1173169412Sscottl if ((pParams->Magic != HPT_IOCTL_MAGIC) && 1174169412Sscottl (pParams->Magic != HPT_IOCTL_MAGIC32)) 1175169412Sscottl return EFAULT; 1176175942Sscottl 1177175942Sscottl req32 = BUS_SPACE_RD4_ITL(inbound_queue); 1178175942Sscottl if (req32 == IOPMU_QUEUE_EMPTY) 1179169412Sscottl return EFAULT; 1180169412Sscottl 1181169412Sscottl if (pParams->nInBufferSize) 1182175942Sscottl if (hptiop_bus_space_copyin(hba, req32 + 1183175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf), 1184175942Sscottl (void *)pParams->lpInBuffer, pParams->nInBufferSize)) 1185169412Sscottl goto invalid; 1186169412Sscottl 1187175942Sscottl if (hptiop_post_ioctl_command_itl(hba, req32, pParams)) 1188169412Sscottl goto invalid; 1189169412Sscottl 1190175942Sscottl result = bus_space_read_4(hba->bar0t, hba->bar0h, req32 + 1191175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, 1192175942Sscottl header.result)); 1193175942Sscottl 1194175942Sscottl if (result == IOP_RESULT_SUCCESS) { 1195169412Sscottl if (pParams->nOutBufferSize) 1196175942Sscottl if (hptiop_bus_space_copyout(hba, req32 + 1197175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf) + 1198169412Sscottl ((pParams->nInBufferSize + 3) & ~3), 1199175942Sscottl (void *)pParams->lpOutBuffer, pParams->nOutBufferSize)) 1200169412Sscottl goto invalid; 1201169412Sscottl 1202175942Sscottl if (pParams->lpBytesReturned) { 1203175942Sscottl if (hptiop_bus_space_copyout(hba, req32 + 1204175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, bytes_returned), 1205175942Sscottl (void *)pParams->lpBytesReturned, sizeof(unsigned long))) 1206169412Sscottl goto invalid; 1207175942Sscottl } 1208175942Sscottl 1209175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req32); 1210175942Sscottl 1211169412Sscottl return 0; 1212169412Sscottl } else{ 1213169412Sscottlinvalid: 1214175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req32); 1215175942Sscottl 1216169412Sscottl return EFAULT; 1217169412Sscottl } 1218169412Sscottl} 1219169412Sscottl 1220175942Sscottlstatic int hptiop_post_ioctl_command_mv(struct hpt_iop_hba *hba, 1221175942Sscottl struct hpt_iop_request_ioctl_command *req, 1222175942Sscottl struct hpt_iop_ioctl_param *pParams) 1223169412Sscottl{ 1224175942Sscottl u_int64_t req_phy; 1225175942Sscottl int size = 0; 1226175942Sscottl 1227175942Sscottl if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) > 1228175942Sscottl (hba->max_request_size - 1229175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf))) { 1230175942Sscottl device_printf(hba->pcidev, "request size beyond max value"); 1231169412Sscottl return -1; 1232169412Sscottl } 1233169412Sscottl 1234169412Sscottl req->ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode); 1235169412Sscottl req->inbuf_size = pParams->nInBufferSize; 1236169412Sscottl req->outbuf_size = pParams->nOutBufferSize; 1237175942Sscottl req->header.size = offsetof(struct hpt_iop_request_ioctl_command, buf) 1238175942Sscottl + pParams->nInBufferSize; 1239175942Sscottl req->header.context = (u_int64_t)MVIOP_CMD_TYPE_IOCTL; 1240169412Sscottl req->header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND; 1241169412Sscottl req->header.result = IOP_RESULT_PENDING; 1242175942Sscottl req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT; 1243175942Sscottl size = req->header.size >> 8; 1244299033Saraujo size = imin(3, size); 1245175942Sscottl req_phy = hba->ctlcfgcmd_phy | MVIOP_MU_QUEUE_ADDR_HOST_BIT | size; 1246175942Sscottl hptiop_mv_inbound_write(req_phy, hba); 1247169412Sscottl 1248175942Sscottl BUS_SPACE_RD4_MV0(outbound_intmask); 1249169412Sscottl 1250175942Sscottl while (hba->config_done == 0) { 1251175942Sscottl if (hptiop_sleep(hba, req, PPAUSE, 1252175942Sscottl "hptctl", HPT_OSM_TIMEOUT)==0) 1253175942Sscottl continue; 1254175942Sscottl hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000); 1255169412Sscottl } 1256169412Sscottl return 0; 1257169412Sscottl} 1258169412Sscottl 1259175942Sscottlstatic int hptiop_do_ioctl_mv(struct hpt_iop_hba *hba, 1260175942Sscottl struct hpt_iop_ioctl_param *pParams) 1261175942Sscottl{ 1262175942Sscottl struct hpt_iop_request_ioctl_command *req; 1263175942Sscottl 1264175942Sscottl if ((pParams->Magic != HPT_IOCTL_MAGIC) && 1265175942Sscottl (pParams->Magic != HPT_IOCTL_MAGIC32)) 1266175942Sscottl return EFAULT; 1267175942Sscottl 1268175942Sscottl req = (struct hpt_iop_request_ioctl_command *)(hba->ctlcfg_ptr); 1269175942Sscottl hba->config_done = 0; 1270175942Sscottl hptiop_lock_adapter(hba); 1271175942Sscottl if (pParams->nInBufferSize) 1272175942Sscottl if (copyin((void *)pParams->lpInBuffer, 1273175942Sscottl req->buf, pParams->nInBufferSize)) 1274175942Sscottl goto invalid; 1275175942Sscottl if (hptiop_post_ioctl_command_mv(hba, req, pParams)) 1276175942Sscottl goto invalid; 1277175942Sscottl 1278175942Sscottl if (hba->config_done == 1) { 1279175942Sscottl if (pParams->nOutBufferSize) 1280175942Sscottl if (copyout(req->buf + 1281175942Sscottl ((pParams->nInBufferSize + 3) & ~3), 1282175942Sscottl (void *)pParams->lpOutBuffer, 1283175942Sscottl pParams->nOutBufferSize)) 1284175942Sscottl goto invalid; 1285175942Sscottl 1286175942Sscottl if (pParams->lpBytesReturned) 1287175942Sscottl if (copyout(&req->bytes_returned, 1288175942Sscottl (void*)pParams->lpBytesReturned, 1289175942Sscottl sizeof(u_int32_t))) 1290175942Sscottl goto invalid; 1291175942Sscottl hptiop_unlock_adapter(hba); 1292175942Sscottl return 0; 1293175942Sscottl } else{ 1294175942Sscottlinvalid: 1295175942Sscottl hptiop_unlock_adapter(hba); 1296175942Sscottl return EFAULT; 1297175942Sscottl } 1298175942Sscottl} 1299175942Sscottl 1300242086Sdelphijstatic int hptiop_post_ioctl_command_mvfrey(struct hpt_iop_hba *hba, 1301242086Sdelphij struct hpt_iop_request_ioctl_command *req, 1302242086Sdelphij struct hpt_iop_ioctl_param *pParams) 1303242086Sdelphij{ 1304242086Sdelphij u_int64_t phy_addr; 1305242086Sdelphij u_int32_t index; 1306242086Sdelphij 1307242086Sdelphij phy_addr = hba->ctlcfgcmd_phy; 1308242086Sdelphij 1309242086Sdelphij if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) > 1310242086Sdelphij (hba->max_request_size - 1311242086Sdelphij offsetof(struct hpt_iop_request_ioctl_command, buf))) { 1312242086Sdelphij device_printf(hba->pcidev, "request size beyond max value"); 1313242086Sdelphij return -1; 1314242086Sdelphij } 1315242086Sdelphij 1316242086Sdelphij req->ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode); 1317242086Sdelphij req->inbuf_size = pParams->nInBufferSize; 1318242086Sdelphij req->outbuf_size = pParams->nOutBufferSize; 1319242086Sdelphij req->header.size = offsetof(struct hpt_iop_request_ioctl_command, buf) 1320242086Sdelphij + pParams->nInBufferSize; 1321242086Sdelphij 1322242086Sdelphij req->header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND; 1323242086Sdelphij req->header.result = IOP_RESULT_PENDING; 1324242086Sdelphij 1325242086Sdelphij req->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST 1326242086Sdelphij | IOP_REQUEST_FLAG_OUTPUT_CONTEXT 1327242086Sdelphij | IOP_REQUEST_FLAG_ADDR_BITS 1328242086Sdelphij | ((phy_addr >> 16) & 0xffff0000); 1329242086Sdelphij req->header.context = ((phy_addr & 0xffffffff) << 32 ) 1330242086Sdelphij | IOPMU_QUEUE_ADDR_HOST_BIT | req->header.type; 1331242086Sdelphij 1332242086Sdelphij hba->u.mvfrey.inlist_wptr++; 1333242086Sdelphij index = hba->u.mvfrey.inlist_wptr & 0x3fff; 1334242086Sdelphij 1335242086Sdelphij if (index == hba->u.mvfrey.list_count) { 1336242086Sdelphij index = 0; 1337242086Sdelphij hba->u.mvfrey.inlist_wptr &= ~0x3fff; 1338242086Sdelphij hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE; 1339242086Sdelphij } 1340242086Sdelphij 1341242086Sdelphij hba->u.mvfrey.inlist[index].addr = phy_addr; 1342242086Sdelphij hba->u.mvfrey.inlist[index].intrfc_len = (req->header.size + 3) / 4; 1343242086Sdelphij 1344242086Sdelphij BUS_SPACE_WRT4_MVFREY2(inbound_write_ptr, hba->u.mvfrey.inlist_wptr); 1345242086Sdelphij BUS_SPACE_RD4_MVFREY2(inbound_write_ptr); 1346242086Sdelphij 1347242086Sdelphij while (hba->config_done == 0) { 1348242086Sdelphij if (hptiop_sleep(hba, req, PPAUSE, 1349242086Sdelphij "hptctl", HPT_OSM_TIMEOUT)==0) 1350242086Sdelphij continue; 1351242086Sdelphij hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000); 1352242086Sdelphij } 1353242086Sdelphij return 0; 1354242086Sdelphij} 1355242086Sdelphij 1356242086Sdelphijstatic int hptiop_do_ioctl_mvfrey(struct hpt_iop_hba *hba, 1357242086Sdelphij struct hpt_iop_ioctl_param *pParams) 1358242086Sdelphij{ 1359242086Sdelphij struct hpt_iop_request_ioctl_command *req; 1360242086Sdelphij 1361242086Sdelphij if ((pParams->Magic != HPT_IOCTL_MAGIC) && 1362242086Sdelphij (pParams->Magic != HPT_IOCTL_MAGIC32)) 1363242086Sdelphij return EFAULT; 1364242086Sdelphij 1365242086Sdelphij req = (struct hpt_iop_request_ioctl_command *)(hba->ctlcfg_ptr); 1366242086Sdelphij hba->config_done = 0; 1367242086Sdelphij hptiop_lock_adapter(hba); 1368242086Sdelphij if (pParams->nInBufferSize) 1369242086Sdelphij if (copyin((void *)pParams->lpInBuffer, 1370242086Sdelphij req->buf, pParams->nInBufferSize)) 1371242086Sdelphij goto invalid; 1372242086Sdelphij if (hptiop_post_ioctl_command_mvfrey(hba, req, pParams)) 1373242086Sdelphij goto invalid; 1374242086Sdelphij 1375242086Sdelphij if (hba->config_done == 1) { 1376242086Sdelphij if (pParams->nOutBufferSize) 1377242086Sdelphij if (copyout(req->buf + 1378242086Sdelphij ((pParams->nInBufferSize + 3) & ~3), 1379242086Sdelphij (void *)pParams->lpOutBuffer, 1380242086Sdelphij pParams->nOutBufferSize)) 1381242086Sdelphij goto invalid; 1382242086Sdelphij 1383242086Sdelphij if (pParams->lpBytesReturned) 1384242086Sdelphij if (copyout(&req->bytes_returned, 1385242086Sdelphij (void*)pParams->lpBytesReturned, 1386242086Sdelphij sizeof(u_int32_t))) 1387242086Sdelphij goto invalid; 1388242086Sdelphij hptiop_unlock_adapter(hba); 1389242086Sdelphij return 0; 1390242086Sdelphij } else{ 1391242086Sdelphijinvalid: 1392242086Sdelphij hptiop_unlock_adapter(hba); 1393242086Sdelphij return EFAULT; 1394242086Sdelphij } 1395242086Sdelphij} 1396242086Sdelphij 1397169412Sscottlstatic int hptiop_rescan_bus(struct hpt_iop_hba * hba) 1398169412Sscottl{ 1399169412Sscottl union ccb *ccb; 1400203108Smav 1401203108Smav if ((ccb = xpt_alloc_ccb()) == NULL) 1402203108Smav return(ENOMEM); 1403249468Smav if (xpt_create_path(&ccb->ccb_h.path, NULL, cam_sim_path(hba->sim), 1404203108Smav CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 1405203108Smav xpt_free_ccb(ccb); 1406169412Sscottl return(EIO); 1407203108Smav } 1408203108Smav xpt_rescan(ccb); 1409169412Sscottl return(0); 1410169412Sscottl} 1411169412Sscottl 1412169412Sscottlstatic bus_dmamap_callback_t hptiop_map_srb; 1413169412Sscottlstatic bus_dmamap_callback_t hptiop_post_scsi_command; 1414175942Sscottlstatic bus_dmamap_callback_t hptiop_mv_map_ctlcfg; 1415242086Sdelphijstatic bus_dmamap_callback_t hptiop_mvfrey_map_ctlcfg; 1416169412Sscottl 1417175942Sscottlstatic int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba) 1418175942Sscottl{ 1419175942Sscottl hba->bar0_rid = 0x10; 1420175942Sscottl hba->bar0_res = bus_alloc_resource_any(hba->pcidev, 1421175942Sscottl SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE); 1422175942Sscottl 1423175942Sscottl if (hba->bar0_res == NULL) { 1424175942Sscottl device_printf(hba->pcidev, 1425175942Sscottl "failed to get iop base adrress.\n"); 1426175942Sscottl return -1; 1427175942Sscottl } 1428175942Sscottl hba->bar0t = rman_get_bustag(hba->bar0_res); 1429175942Sscottl hba->bar0h = rman_get_bushandle(hba->bar0_res); 1430175942Sscottl hba->u.itl.mu = (struct hpt_iopmu_itl *) 1431175942Sscottl rman_get_virtual(hba->bar0_res); 1432175942Sscottl 1433175942Sscottl if (!hba->u.itl.mu) { 1434175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1435175942Sscottl hba->bar0_rid, hba->bar0_res); 1436175942Sscottl device_printf(hba->pcidev, "alloc mem res failed\n"); 1437175942Sscottl return -1; 1438175942Sscottl } 1439175942Sscottl 1440175942Sscottl return 0; 1441175942Sscottl} 1442175942Sscottl 1443175942Sscottlstatic int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba) 1444175942Sscottl{ 1445175942Sscottl hba->bar0_rid = 0x10; 1446175942Sscottl hba->bar0_res = bus_alloc_resource_any(hba->pcidev, 1447175942Sscottl SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE); 1448175942Sscottl 1449175942Sscottl if (hba->bar0_res == NULL) { 1450175942Sscottl device_printf(hba->pcidev, "failed to get iop bar0.\n"); 1451175942Sscottl return -1; 1452175942Sscottl } 1453175942Sscottl hba->bar0t = rman_get_bustag(hba->bar0_res); 1454175942Sscottl hba->bar0h = rman_get_bushandle(hba->bar0_res); 1455175942Sscottl hba->u.mv.regs = (struct hpt_iopmv_regs *) 1456175942Sscottl rman_get_virtual(hba->bar0_res); 1457175942Sscottl 1458175942Sscottl if (!hba->u.mv.regs) { 1459175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1460175942Sscottl hba->bar0_rid, hba->bar0_res); 1461175942Sscottl device_printf(hba->pcidev, "alloc bar0 mem res failed\n"); 1462175942Sscottl return -1; 1463175942Sscottl } 1464175942Sscottl 1465175942Sscottl hba->bar2_rid = 0x18; 1466175942Sscottl hba->bar2_res = bus_alloc_resource_any(hba->pcidev, 1467175942Sscottl SYS_RES_MEMORY, &hba->bar2_rid, RF_ACTIVE); 1468175942Sscottl 1469175942Sscottl if (hba->bar2_res == NULL) { 1470175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1471175942Sscottl hba->bar0_rid, hba->bar0_res); 1472175942Sscottl device_printf(hba->pcidev, "failed to get iop bar2.\n"); 1473175942Sscottl return -1; 1474175942Sscottl } 1475175942Sscottl 1476175942Sscottl hba->bar2t = rman_get_bustag(hba->bar2_res); 1477175942Sscottl hba->bar2h = rman_get_bushandle(hba->bar2_res); 1478175942Sscottl hba->u.mv.mu = (struct hpt_iopmu_mv *)rman_get_virtual(hba->bar2_res); 1479175942Sscottl 1480175942Sscottl if (!hba->u.mv.mu) { 1481175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1482175942Sscottl hba->bar0_rid, hba->bar0_res); 1483175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1484175942Sscottl hba->bar2_rid, hba->bar2_res); 1485175942Sscottl device_printf(hba->pcidev, "alloc mem bar2 res failed\n"); 1486175942Sscottl return -1; 1487175942Sscottl } 1488175942Sscottl 1489175942Sscottl return 0; 1490175942Sscottl} 1491175942Sscottl 1492242086Sdelphijstatic int hptiop_alloc_pci_res_mvfrey(struct hpt_iop_hba *hba) 1493242086Sdelphij{ 1494242086Sdelphij hba->bar0_rid = 0x10; 1495242086Sdelphij hba->bar0_res = bus_alloc_resource_any(hba->pcidev, 1496242086Sdelphij SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE); 1497242086Sdelphij 1498242086Sdelphij if (hba->bar0_res == NULL) { 1499242086Sdelphij device_printf(hba->pcidev, "failed to get iop bar0.\n"); 1500242086Sdelphij return -1; 1501242086Sdelphij } 1502242086Sdelphij hba->bar0t = rman_get_bustag(hba->bar0_res); 1503242086Sdelphij hba->bar0h = rman_get_bushandle(hba->bar0_res); 1504242086Sdelphij hba->u.mvfrey.config = (struct hpt_iop_request_get_config *) 1505242086Sdelphij rman_get_virtual(hba->bar0_res); 1506242086Sdelphij 1507242086Sdelphij if (!hba->u.mvfrey.config) { 1508242086Sdelphij bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1509242086Sdelphij hba->bar0_rid, hba->bar0_res); 1510242086Sdelphij device_printf(hba->pcidev, "alloc bar0 mem res failed\n"); 1511242086Sdelphij return -1; 1512242086Sdelphij } 1513242086Sdelphij 1514242086Sdelphij hba->bar2_rid = 0x18; 1515242086Sdelphij hba->bar2_res = bus_alloc_resource_any(hba->pcidev, 1516242086Sdelphij SYS_RES_MEMORY, &hba->bar2_rid, RF_ACTIVE); 1517242086Sdelphij 1518242086Sdelphij if (hba->bar2_res == NULL) { 1519242086Sdelphij bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1520242086Sdelphij hba->bar0_rid, hba->bar0_res); 1521242086Sdelphij device_printf(hba->pcidev, "failed to get iop bar2.\n"); 1522242086Sdelphij return -1; 1523242086Sdelphij } 1524242086Sdelphij 1525242086Sdelphij hba->bar2t = rman_get_bustag(hba->bar2_res); 1526242086Sdelphij hba->bar2h = rman_get_bushandle(hba->bar2_res); 1527242086Sdelphij hba->u.mvfrey.mu = 1528242086Sdelphij (struct hpt_iopmu_mvfrey *)rman_get_virtual(hba->bar2_res); 1529242086Sdelphij 1530242086Sdelphij if (!hba->u.mvfrey.mu) { 1531242086Sdelphij bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1532242086Sdelphij hba->bar0_rid, hba->bar0_res); 1533242086Sdelphij bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1534242086Sdelphij hba->bar2_rid, hba->bar2_res); 1535242086Sdelphij device_printf(hba->pcidev, "alloc mem bar2 res failed\n"); 1536242086Sdelphij return -1; 1537242086Sdelphij } 1538242086Sdelphij 1539242086Sdelphij return 0; 1540242086Sdelphij} 1541242086Sdelphij 1542175942Sscottlstatic void hptiop_release_pci_res_itl(struct hpt_iop_hba *hba) 1543175942Sscottl{ 1544175942Sscottl if (hba->bar0_res) 1545175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1546175942Sscottl hba->bar0_rid, hba->bar0_res); 1547175942Sscottl} 1548175942Sscottl 1549175942Sscottlstatic void hptiop_release_pci_res_mv(struct hpt_iop_hba *hba) 1550175942Sscottl{ 1551175942Sscottl if (hba->bar0_res) 1552175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1553175942Sscottl hba->bar0_rid, hba->bar0_res); 1554175942Sscottl if (hba->bar2_res) 1555175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1556175942Sscottl hba->bar2_rid, hba->bar2_res); 1557175942Sscottl} 1558175942Sscottl 1559242086Sdelphijstatic void hptiop_release_pci_res_mvfrey(struct hpt_iop_hba *hba) 1560242086Sdelphij{ 1561242086Sdelphij if (hba->bar0_res) 1562242086Sdelphij bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1563242086Sdelphij hba->bar0_rid, hba->bar0_res); 1564242086Sdelphij if (hba->bar2_res) 1565242086Sdelphij bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1566242086Sdelphij hba->bar2_rid, hba->bar2_res); 1567242086Sdelphij} 1568242086Sdelphij 1569175942Sscottlstatic int hptiop_internal_memalloc_mv(struct hpt_iop_hba *hba) 1570175942Sscottl{ 1571175942Sscottl if (bus_dma_tag_create(hba->parent_dmat, 1572175942Sscottl 1, 1573175942Sscottl 0, 1574175942Sscottl BUS_SPACE_MAXADDR_32BIT, 1575175942Sscottl BUS_SPACE_MAXADDR, 1576175942Sscottl NULL, NULL, 1577175942Sscottl 0x800 - 0x8, 1578175942Sscottl 1, 1579175942Sscottl BUS_SPACE_MAXSIZE_32BIT, 1580175942Sscottl BUS_DMA_ALLOCNOW, 1581175942Sscottl NULL, 1582175942Sscottl NULL, 1583242086Sdelphij &hba->ctlcfg_dmat)) { 1584175942Sscottl device_printf(hba->pcidev, "alloc ctlcfg_dmat failed\n"); 1585175942Sscottl return -1; 1586175942Sscottl } 1587175942Sscottl 1588175942Sscottl if (bus_dmamem_alloc(hba->ctlcfg_dmat, (void **)&hba->ctlcfg_ptr, 1589175942Sscottl BUS_DMA_WAITOK | BUS_DMA_COHERENT, 1590175942Sscottl &hba->ctlcfg_dmamap) != 0) { 1591175942Sscottl device_printf(hba->pcidev, 1592175942Sscottl "bus_dmamem_alloc failed!\n"); 1593175942Sscottl bus_dma_tag_destroy(hba->ctlcfg_dmat); 1594175942Sscottl return -1; 1595175942Sscottl } 1596175942Sscottl 1597175942Sscottl if (bus_dmamap_load(hba->ctlcfg_dmat, 1598175942Sscottl hba->ctlcfg_dmamap, hba->ctlcfg_ptr, 1599175942Sscottl MVIOP_IOCTLCFG_SIZE, 1600175942Sscottl hptiop_mv_map_ctlcfg, hba, 0)) { 1601175942Sscottl device_printf(hba->pcidev, "bus_dmamap_load failed!\n"); 1602250123Seadler if (hba->ctlcfg_dmat) { 1603175942Sscottl bus_dmamem_free(hba->ctlcfg_dmat, 1604175942Sscottl hba->ctlcfg_ptr, hba->ctlcfg_dmamap); 1605175942Sscottl bus_dma_tag_destroy(hba->ctlcfg_dmat); 1606250123Seadler } 1607175942Sscottl return -1; 1608175942Sscottl } 1609175942Sscottl 1610175942Sscottl return 0; 1611175942Sscottl} 1612175942Sscottl 1613242086Sdelphijstatic int hptiop_internal_memalloc_mvfrey(struct hpt_iop_hba *hba) 1614242086Sdelphij{ 1615242086Sdelphij u_int32_t list_count = BUS_SPACE_RD4_MVFREY2(inbound_conf_ctl); 1616242086Sdelphij 1617242086Sdelphij list_count >>= 16; 1618242086Sdelphij 1619242086Sdelphij if (list_count == 0) { 1620242086Sdelphij return -1; 1621242086Sdelphij } 1622242086Sdelphij 1623242086Sdelphij hba->u.mvfrey.list_count = list_count; 1624242086Sdelphij hba->u.mvfrey.internal_mem_size = 0x800 1625242086Sdelphij + list_count * sizeof(struct mvfrey_inlist_entry) 1626242086Sdelphij + list_count * sizeof(struct mvfrey_outlist_entry) 1627242086Sdelphij + sizeof(int); 1628242086Sdelphij if (bus_dma_tag_create(hba->parent_dmat, 1629242086Sdelphij 1, 1630242086Sdelphij 0, 1631242086Sdelphij BUS_SPACE_MAXADDR_32BIT, 1632242086Sdelphij BUS_SPACE_MAXADDR, 1633242086Sdelphij NULL, NULL, 1634242086Sdelphij hba->u.mvfrey.internal_mem_size, 1635242086Sdelphij 1, 1636242086Sdelphij BUS_SPACE_MAXSIZE_32BIT, 1637242086Sdelphij BUS_DMA_ALLOCNOW, 1638242086Sdelphij NULL, 1639242086Sdelphij NULL, 1640242086Sdelphij &hba->ctlcfg_dmat)) { 1641242086Sdelphij device_printf(hba->pcidev, "alloc ctlcfg_dmat failed\n"); 1642242086Sdelphij return -1; 1643242086Sdelphij } 1644242086Sdelphij 1645242086Sdelphij if (bus_dmamem_alloc(hba->ctlcfg_dmat, (void **)&hba->ctlcfg_ptr, 1646242086Sdelphij BUS_DMA_WAITOK | BUS_DMA_COHERENT, 1647242086Sdelphij &hba->ctlcfg_dmamap) != 0) { 1648242086Sdelphij device_printf(hba->pcidev, 1649242086Sdelphij "bus_dmamem_alloc failed!\n"); 1650242086Sdelphij bus_dma_tag_destroy(hba->ctlcfg_dmat); 1651242086Sdelphij return -1; 1652242086Sdelphij } 1653242086Sdelphij 1654242086Sdelphij if (bus_dmamap_load(hba->ctlcfg_dmat, 1655242086Sdelphij hba->ctlcfg_dmamap, hba->ctlcfg_ptr, 1656242086Sdelphij hba->u.mvfrey.internal_mem_size, 1657242086Sdelphij hptiop_mvfrey_map_ctlcfg, hba, 0)) { 1658242086Sdelphij device_printf(hba->pcidev, "bus_dmamap_load failed!\n"); 1659250050Sdelphij if (hba->ctlcfg_dmat) { 1660242086Sdelphij bus_dmamem_free(hba->ctlcfg_dmat, 1661242086Sdelphij hba->ctlcfg_ptr, hba->ctlcfg_dmamap); 1662242086Sdelphij bus_dma_tag_destroy(hba->ctlcfg_dmat); 1663250050Sdelphij } 1664242086Sdelphij return -1; 1665242086Sdelphij } 1666242086Sdelphij 1667242086Sdelphij return 0; 1668242086Sdelphij} 1669242086Sdelphij 1670242086Sdelphijstatic int hptiop_internal_memfree_itl(struct hpt_iop_hba *hba) { 1671242086Sdelphij return 0; 1672242086Sdelphij} 1673242086Sdelphij 1674175942Sscottlstatic int hptiop_internal_memfree_mv(struct hpt_iop_hba *hba) 1675175942Sscottl{ 1676175942Sscottl if (hba->ctlcfg_dmat) { 1677175942Sscottl bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap); 1678175942Sscottl bus_dmamem_free(hba->ctlcfg_dmat, 1679175942Sscottl hba->ctlcfg_ptr, hba->ctlcfg_dmamap); 1680175942Sscottl bus_dma_tag_destroy(hba->ctlcfg_dmat); 1681175942Sscottl } 1682175942Sscottl 1683175942Sscottl return 0; 1684175942Sscottl} 1685175942Sscottl 1686242086Sdelphijstatic int hptiop_internal_memfree_mvfrey(struct hpt_iop_hba *hba) 1687242086Sdelphij{ 1688242086Sdelphij if (hba->ctlcfg_dmat) { 1689242086Sdelphij bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap); 1690242086Sdelphij bus_dmamem_free(hba->ctlcfg_dmat, 1691242086Sdelphij hba->ctlcfg_ptr, hba->ctlcfg_dmamap); 1692242086Sdelphij bus_dma_tag_destroy(hba->ctlcfg_dmat); 1693242086Sdelphij } 1694242086Sdelphij 1695242086Sdelphij return 0; 1696242086Sdelphij} 1697242086Sdelphij 1698242086Sdelphijstatic int hptiop_reset_comm_mvfrey(struct hpt_iop_hba *hba) 1699242086Sdelphij{ 1700242086Sdelphij u_int32_t i = 100; 1701242086Sdelphij 1702242086Sdelphij if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET_COMM, 3000)) 1703242086Sdelphij return -1; 1704242086Sdelphij 1705242086Sdelphij /* wait 100ms for MCU ready */ 1706242086Sdelphij while(i--) { 1707242086Sdelphij DELAY(1000); 1708242086Sdelphij } 1709242086Sdelphij 1710242086Sdelphij BUS_SPACE_WRT4_MVFREY2(inbound_base, 1711242086Sdelphij hba->u.mvfrey.inlist_phy & 0xffffffff); 1712242086Sdelphij BUS_SPACE_WRT4_MVFREY2(inbound_base_high, 1713242086Sdelphij (hba->u.mvfrey.inlist_phy >> 16) >> 16); 1714242086Sdelphij 1715242086Sdelphij BUS_SPACE_WRT4_MVFREY2(outbound_base, 1716242086Sdelphij hba->u.mvfrey.outlist_phy & 0xffffffff); 1717242086Sdelphij BUS_SPACE_WRT4_MVFREY2(outbound_base_high, 1718242086Sdelphij (hba->u.mvfrey.outlist_phy >> 16) >> 16); 1719242086Sdelphij 1720242086Sdelphij BUS_SPACE_WRT4_MVFREY2(outbound_shadow_base, 1721242086Sdelphij hba->u.mvfrey.outlist_cptr_phy & 0xffffffff); 1722242086Sdelphij BUS_SPACE_WRT4_MVFREY2(outbound_shadow_base_high, 1723242086Sdelphij (hba->u.mvfrey.outlist_cptr_phy >> 16) >> 16); 1724242086Sdelphij 1725242086Sdelphij hba->u.mvfrey.inlist_wptr = (hba->u.mvfrey.list_count - 1) 1726242086Sdelphij | CL_POINTER_TOGGLE; 1727242086Sdelphij *hba->u.mvfrey.outlist_cptr = (hba->u.mvfrey.list_count - 1) 1728242086Sdelphij | CL_POINTER_TOGGLE; 1729242086Sdelphij hba->u.mvfrey.outlist_rptr = hba->u.mvfrey.list_count - 1; 1730242086Sdelphij 1731242086Sdelphij return 0; 1732242086Sdelphij} 1733242086Sdelphij 1734169412Sscottl/* 1735169412Sscottl * CAM driver interface 1736169412Sscottl */ 1737169412Sscottlstatic device_method_t driver_methods[] = { 1738169412Sscottl /* Device interface */ 1739169412Sscottl DEVMETHOD(device_probe, hptiop_probe), 1740169412Sscottl DEVMETHOD(device_attach, hptiop_attach), 1741169412Sscottl DEVMETHOD(device_detach, hptiop_detach), 1742169412Sscottl DEVMETHOD(device_shutdown, hptiop_shutdown), 1743169412Sscottl { 0, 0 } 1744169412Sscottl}; 1745169412Sscottl 1746175942Sscottlstatic struct hptiop_adapter_ops hptiop_itl_ops = { 1747242086Sdelphij .family = INTEL_BASED_IOP, 1748175942Sscottl .iop_wait_ready = hptiop_wait_ready_itl, 1749175942Sscottl .internal_memalloc = 0, 1750242086Sdelphij .internal_memfree = hptiop_internal_memfree_itl, 1751175942Sscottl .alloc_pci_res = hptiop_alloc_pci_res_itl, 1752175942Sscottl .release_pci_res = hptiop_release_pci_res_itl, 1753175942Sscottl .enable_intr = hptiop_enable_intr_itl, 1754175942Sscottl .disable_intr = hptiop_disable_intr_itl, 1755175942Sscottl .get_config = hptiop_get_config_itl, 1756175942Sscottl .set_config = hptiop_set_config_itl, 1757175942Sscottl .iop_intr = hptiop_intr_itl, 1758175942Sscottl .post_msg = hptiop_post_msg_itl, 1759175942Sscottl .post_req = hptiop_post_req_itl, 1760175942Sscottl .do_ioctl = hptiop_do_ioctl_itl, 1761242086Sdelphij .reset_comm = 0, 1762175942Sscottl}; 1763175942Sscottl 1764175942Sscottlstatic struct hptiop_adapter_ops hptiop_mv_ops = { 1765242086Sdelphij .family = MV_BASED_IOP, 1766175942Sscottl .iop_wait_ready = hptiop_wait_ready_mv, 1767175942Sscottl .internal_memalloc = hptiop_internal_memalloc_mv, 1768175942Sscottl .internal_memfree = hptiop_internal_memfree_mv, 1769175942Sscottl .alloc_pci_res = hptiop_alloc_pci_res_mv, 1770175942Sscottl .release_pci_res = hptiop_release_pci_res_mv, 1771175942Sscottl .enable_intr = hptiop_enable_intr_mv, 1772175942Sscottl .disable_intr = hptiop_disable_intr_mv, 1773175942Sscottl .get_config = hptiop_get_config_mv, 1774175942Sscottl .set_config = hptiop_set_config_mv, 1775175942Sscottl .iop_intr = hptiop_intr_mv, 1776175942Sscottl .post_msg = hptiop_post_msg_mv, 1777175942Sscottl .post_req = hptiop_post_req_mv, 1778175942Sscottl .do_ioctl = hptiop_do_ioctl_mv, 1779242086Sdelphij .reset_comm = 0, 1780175942Sscottl}; 1781175942Sscottl 1782242086Sdelphijstatic struct hptiop_adapter_ops hptiop_mvfrey_ops = { 1783242086Sdelphij .family = MVFREY_BASED_IOP, 1784242086Sdelphij .iop_wait_ready = hptiop_wait_ready_mvfrey, 1785242086Sdelphij .internal_memalloc = hptiop_internal_memalloc_mvfrey, 1786242086Sdelphij .internal_memfree = hptiop_internal_memfree_mvfrey, 1787242086Sdelphij .alloc_pci_res = hptiop_alloc_pci_res_mvfrey, 1788242086Sdelphij .release_pci_res = hptiop_release_pci_res_mvfrey, 1789242086Sdelphij .enable_intr = hptiop_enable_intr_mvfrey, 1790242086Sdelphij .disable_intr = hptiop_disable_intr_mvfrey, 1791242086Sdelphij .get_config = hptiop_get_config_mvfrey, 1792242086Sdelphij .set_config = hptiop_set_config_mvfrey, 1793242086Sdelphij .iop_intr = hptiop_intr_mvfrey, 1794242086Sdelphij .post_msg = hptiop_post_msg_mvfrey, 1795242086Sdelphij .post_req = hptiop_post_req_mvfrey, 1796242086Sdelphij .do_ioctl = hptiop_do_ioctl_mvfrey, 1797242086Sdelphij .reset_comm = hptiop_reset_comm_mvfrey, 1798242086Sdelphij}; 1799242086Sdelphij 1800169412Sscottlstatic driver_t hptiop_pci_driver = { 1801169412Sscottl driver_name, 1802169412Sscottl driver_methods, 1803169412Sscottl sizeof(struct hpt_iop_hba) 1804169412Sscottl}; 1805169412Sscottl 1806169412SscottlDRIVER_MODULE(hptiop, pci, hptiop_pci_driver, hptiop_devclass, 0, 0); 1807236379SeadlerMODULE_DEPEND(hptiop, cam, 1, 1, 1); 1808169412Sscottl 1809169412Sscottlstatic int hptiop_probe(device_t dev) 1810169412Sscottl{ 1811169412Sscottl struct hpt_iop_hba *hba; 1812175942Sscottl u_int32_t id; 1813175942Sscottl static char buf[256]; 1814175942Sscottl int sas = 0; 1815175942Sscottl struct hptiop_adapter_ops *ops; 1816169412Sscottl 1817175942Sscottl if (pci_get_vendor(dev) != 0x1103) 1818175942Sscottl return (ENXIO); 1819175942Sscottl 1820175942Sscottl id = pci_get_device(dev); 1821175942Sscottl 1822175942Sscottl switch (id) { 1823242086Sdelphij case 0x4520: 1824252851Sdelphij case 0x4521: 1825242086Sdelphij case 0x4522: 1826242086Sdelphij sas = 1; 1827252851Sdelphij case 0x3620: 1828252851Sdelphij case 0x3622: 1829252851Sdelphij case 0x3640: 1830242086Sdelphij ops = &hptiop_mvfrey_ops; 1831242086Sdelphij break; 1832239084Sdelphij case 0x4210: 1833239084Sdelphij case 0x4211: 1834239084Sdelphij case 0x4310: 1835239084Sdelphij case 0x4311: 1836239084Sdelphij case 0x4320: 1837224583Sdelphij case 0x4321: 1838239084Sdelphij case 0x4322: 1839175942Sscottl sas = 1; 1840175942Sscottl case 0x3220: 1841175942Sscottl case 0x3320: 1842175942Sscottl case 0x3410: 1843175942Sscottl case 0x3520: 1844175942Sscottl case 0x3510: 1845175942Sscottl case 0x3511: 1846175942Sscottl case 0x3521: 1847175942Sscottl case 0x3522: 1848239084Sdelphij case 0x3530: 1849175942Sscottl case 0x3540: 1850239084Sdelphij case 0x3560: 1851175942Sscottl ops = &hptiop_itl_ops; 1852175942Sscottl break; 1853239084Sdelphij case 0x3020: 1854175942Sscottl case 0x3120: 1855175942Sscottl case 0x3122: 1856175942Sscottl ops = &hptiop_mv_ops; 1857175942Sscottl break; 1858175942Sscottl default: 1859175942Sscottl return (ENXIO); 1860169412Sscottl } 1861175942Sscottl 1862175942Sscottl device_printf(dev, "adapter at PCI %d:%d:%d, IRQ %d\n", 1863175942Sscottl pci_get_bus(dev), pci_get_slot(dev), 1864175942Sscottl pci_get_function(dev), pci_get_irq(dev)); 1865175942Sscottl 1866175942Sscottl sprintf(buf, "RocketRAID %x %s Controller\n", 1867175942Sscottl id, sas ? "SAS" : "SATA"); 1868175942Sscottl device_set_desc_copy(dev, buf); 1869175942Sscottl 1870175942Sscottl hba = (struct hpt_iop_hba *)device_get_softc(dev); 1871175942Sscottl bzero(hba, sizeof(struct hpt_iop_hba)); 1872175942Sscottl hba->ops = ops; 1873175942Sscottl 1874175942Sscottl KdPrint(("hba->ops=%p\n", hba->ops)); 1875175942Sscottl return 0; 1876169412Sscottl} 1877169412Sscottl 1878169412Sscottlstatic int hptiop_attach(device_t dev) 1879169412Sscottl{ 1880175942Sscottl struct hpt_iop_hba *hba = (struct hpt_iop_hba *)device_get_softc(dev); 1881169412Sscottl struct hpt_iop_request_get_config iop_config; 1882169412Sscottl struct hpt_iop_request_set_config set_config; 1883169412Sscottl int rid = 0; 1884169412Sscottl struct cam_devq *devq; 1885169412Sscottl struct ccb_setasync ccb; 1886169412Sscottl u_int32_t unit = device_get_unit(dev); 1887169412Sscottl 1888175942Sscottl device_printf(dev, "%d RocketRAID 3xxx/4xxx controller driver %s\n", 1889175942Sscottl unit, driver_version); 1890169412Sscottl 1891175942Sscottl KdPrint(("hptiop: attach(%d, %d/%d/%d) ops=%p\n", unit, 1892175942Sscottl pci_get_bus(dev), pci_get_slot(dev), 1893175942Sscottl pci_get_function(dev), hba->ops)); 1894175942Sscottl 1895169412Sscottl pci_enable_busmaster(dev); 1896169412Sscottl hba->pcidev = dev; 1897169412Sscottl hba->pciunit = unit; 1898169412Sscottl 1899175942Sscottl if (hba->ops->alloc_pci_res(hba)) 1900169412Sscottl return ENXIO; 1901169412Sscottl 1902175942Sscottl if (hba->ops->iop_wait_ready(hba, 2000)) { 1903175942Sscottl device_printf(dev, "adapter is not ready\n"); 1904175942Sscottl goto release_pci_res; 1905169412Sscottl } 1906169412Sscottl 1907169412Sscottl mtx_init(&hba->lock, "hptioplock", NULL, MTX_DEF); 1908169412Sscottl 1909232854Sscottl if (bus_dma_tag_create(bus_get_dma_tag(dev),/* PCI parent */ 1910169412Sscottl 1, /* alignment */ 1911169412Sscottl 0, /* boundary */ 1912169412Sscottl BUS_SPACE_MAXADDR, /* lowaddr */ 1913169412Sscottl BUS_SPACE_MAXADDR, /* highaddr */ 1914169412Sscottl NULL, NULL, /* filter, filterarg */ 1915169412Sscottl BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 1916169412Sscottl BUS_SPACE_UNRESTRICTED, /* nsegments */ 1917169412Sscottl BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 1918169412Sscottl 0, /* flags */ 1919169412Sscottl NULL, /* lockfunc */ 1920169412Sscottl NULL, /* lockfuncarg */ 1921169412Sscottl &hba->parent_dmat /* tag */)) 1922169412Sscottl { 1923175942Sscottl device_printf(dev, "alloc parent_dmat failed\n"); 1924175942Sscottl goto release_pci_res; 1925169412Sscottl } 1926169412Sscottl 1927242086Sdelphij if (hba->ops->family == MV_BASED_IOP) { 1928175942Sscottl if (hba->ops->internal_memalloc(hba)) { 1929175942Sscottl device_printf(dev, "alloc srb_dmat failed\n"); 1930175942Sscottl goto destroy_parent_tag; 1931175942Sscottl } 1932175942Sscottl } 1933175942Sscottl 1934175942Sscottl if (hba->ops->get_config(hba, &iop_config)) { 1935175942Sscottl device_printf(dev, "get iop config failed.\n"); 1936175942Sscottl goto get_config_failed; 1937175942Sscottl } 1938175942Sscottl 1939175942Sscottl hba->firmware_version = iop_config.firmware_version; 1940175942Sscottl hba->interface_version = iop_config.interface_version; 1941175942Sscottl hba->max_requests = iop_config.max_requests; 1942175942Sscottl hba->max_devices = iop_config.max_devices; 1943175942Sscottl hba->max_request_size = iop_config.request_size; 1944175942Sscottl hba->max_sg_count = iop_config.max_sg_count; 1945175942Sscottl 1946242086Sdelphij if (hba->ops->family == MVFREY_BASED_IOP) { 1947242086Sdelphij if (hba->ops->internal_memalloc(hba)) { 1948242086Sdelphij device_printf(dev, "alloc srb_dmat failed\n"); 1949242086Sdelphij goto destroy_parent_tag; 1950242086Sdelphij } 1951242086Sdelphij if (hba->ops->reset_comm(hba)) { 1952242086Sdelphij device_printf(dev, "reset comm failed\n"); 1953242086Sdelphij goto get_config_failed; 1954242086Sdelphij } 1955242086Sdelphij } 1956242086Sdelphij 1957169412Sscottl if (bus_dma_tag_create(hba->parent_dmat,/* parent */ 1958169412Sscottl 4, /* alignment */ 1959169412Sscottl BUS_SPACE_MAXADDR_32BIT+1, /* boundary */ 1960169412Sscottl BUS_SPACE_MAXADDR, /* lowaddr */ 1961169412Sscottl BUS_SPACE_MAXADDR, /* highaddr */ 1962169412Sscottl NULL, NULL, /* filter, filterarg */ 1963169412Sscottl PAGE_SIZE * (hba->max_sg_count-1), /* maxsize */ 1964169412Sscottl hba->max_sg_count, /* nsegments */ 1965169412Sscottl 0x20000, /* maxsegsize */ 1966169412Sscottl BUS_DMA_ALLOCNOW, /* flags */ 1967169412Sscottl busdma_lock_mutex, /* lockfunc */ 1968169412Sscottl &hba->lock, /* lockfuncarg */ 1969169412Sscottl &hba->io_dmat /* tag */)) 1970169412Sscottl { 1971175942Sscottl device_printf(dev, "alloc io_dmat failed\n"); 1972175942Sscottl goto get_config_failed; 1973169412Sscottl } 1974169412Sscottl 1975169412Sscottl if (bus_dma_tag_create(hba->parent_dmat,/* parent */ 1976169412Sscottl 1, /* alignment */ 1977169412Sscottl 0, /* boundary */ 1978169412Sscottl BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 1979169412Sscottl BUS_SPACE_MAXADDR, /* highaddr */ 1980169412Sscottl NULL, NULL, /* filter, filterarg */ 1981169412Sscottl HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE + 0x20, 1982169412Sscottl 1, /* nsegments */ 1983169412Sscottl BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 1984169412Sscottl 0, /* flags */ 1985169412Sscottl NULL, /* lockfunc */ 1986169412Sscottl NULL, /* lockfuncarg */ 1987169412Sscottl &hba->srb_dmat /* tag */)) 1988169412Sscottl { 1989175942Sscottl device_printf(dev, "alloc srb_dmat failed\n"); 1990175942Sscottl goto destroy_io_dmat; 1991169412Sscottl } 1992169412Sscottl 1993169412Sscottl if (bus_dmamem_alloc(hba->srb_dmat, (void **)&hba->uncached_ptr, 1994175942Sscottl BUS_DMA_WAITOK | BUS_DMA_COHERENT, 1995175942Sscottl &hba->srb_dmamap) != 0) 1996169412Sscottl { 1997175942Sscottl device_printf(dev, "srb bus_dmamem_alloc failed!\n"); 1998175942Sscottl goto destroy_srb_dmat; 1999169412Sscottl } 2000169412Sscottl 2001169412Sscottl if (bus_dmamap_load(hba->srb_dmat, 2002169412Sscottl hba->srb_dmamap, hba->uncached_ptr, 2003169412Sscottl (HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE) + 0x20, 2004169412Sscottl hptiop_map_srb, hba, 0)) 2005169412Sscottl { 2006175942Sscottl device_printf(dev, "bus_dmamap_load failed!\n"); 2007175942Sscottl goto srb_dmamem_free; 2008169412Sscottl } 2009169412Sscottl 2010169412Sscottl if ((devq = cam_simq_alloc(hba->max_requests - 1 )) == NULL) { 2011175942Sscottl device_printf(dev, "cam_simq_alloc failed\n"); 2012175942Sscottl goto srb_dmamap_unload; 2013169412Sscottl } 2014175942Sscottl 2015169412Sscottl hba->sim = cam_sim_alloc(hptiop_action, hptiop_poll, driver_name, 2016269612Sjhb hba, unit, &hba->lock, hba->max_requests - 1, 1, devq); 2017169412Sscottl if (!hba->sim) { 2018175942Sscottl device_printf(dev, "cam_sim_alloc failed\n"); 2019169412Sscottl cam_simq_free(devq); 2020175942Sscottl goto srb_dmamap_unload; 2021169412Sscottl } 2022269612Sjhb hptiop_lock_adapter(hba); 2023175942Sscottl if (xpt_bus_register(hba->sim, dev, 0) != CAM_SUCCESS) 2024175942Sscottl { 2025175942Sscottl device_printf(dev, "xpt_bus_register failed\n"); 2026175942Sscottl goto free_cam_sim; 2027169412Sscottl } 2028169412Sscottl 2029169412Sscottl if (xpt_create_path(&hba->path, /*periph */ NULL, 2030169412Sscottl cam_sim_path(hba->sim), CAM_TARGET_WILDCARD, 2031175942Sscottl CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 2032175942Sscottl device_printf(dev, "xpt_create_path failed\n"); 2033175942Sscottl goto deregister_xpt_bus; 2034169412Sscottl } 2035269612Sjhb hptiop_unlock_adapter(hba); 2036169412Sscottl 2037169412Sscottl bzero(&set_config, sizeof(set_config)); 2038175942Sscottl set_config.iop_id = unit; 2039169412Sscottl set_config.vbus_id = cam_sim_path(hba->sim); 2040169412Sscottl set_config.max_host_request_size = HPT_SRB_MAX_REQ_SIZE; 2041169412Sscottl 2042175942Sscottl if (hba->ops->set_config(hba, &set_config)) { 2043175942Sscottl device_printf(dev, "set iop config failed.\n"); 2044175942Sscottl goto free_hba_path; 2045169412Sscottl } 2046169412Sscottl 2047169412Sscottl xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5); 2048169412Sscottl ccb.ccb_h.func_code = XPT_SASYNC_CB; 2049169412Sscottl ccb.event_enable = (AC_FOUND_DEVICE | AC_LOST_DEVICE); 2050169412Sscottl ccb.callback = hptiop_async; 2051169412Sscottl ccb.callback_arg = hba->sim; 2052169412Sscottl xpt_action((union ccb *)&ccb); 2053169412Sscottl 2054169412Sscottl rid = 0; 2055295790Sjhibbits if ((hba->irq_res = bus_alloc_resource_any(hba->pcidev, SYS_RES_IRQ, 2056295790Sjhibbits &rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { 2057175942Sscottl device_printf(dev, "allocate irq failed!\n"); 2058175942Sscottl goto free_hba_path; 2059169412Sscottl } 2060169412Sscottl 2061269612Sjhb if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM | INTR_MPSAFE, 2062175942Sscottl NULL, hptiop_pci_intr, hba, &hba->irq_handle)) 2063175942Sscottl { 2064175942Sscottl device_printf(dev, "allocate intr function failed!\n"); 2065175942Sscottl goto free_irq_resource; 2066169412Sscottl } 2067169412Sscottl 2068175942Sscottl if (hptiop_send_sync_msg(hba, 2069175942Sscottl IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) { 2070175942Sscottl device_printf(dev, "fail to start background task\n"); 2071175942Sscottl goto teartown_irq_resource; 2072169412Sscottl } 2073169412Sscottl 2074175942Sscottl hba->ops->enable_intr(hba); 2075242086Sdelphij hba->initialized = 1; 2076175942Sscottl 2077169412Sscottl hba->ioctl_dev = make_dev(&hptiop_cdevsw, unit, 2078169412Sscottl UID_ROOT, GID_WHEEL /*GID_OPERATOR*/, 2079169412Sscottl S_IRUSR | S_IWUSR, "%s%d", driver_name, unit); 2080169412Sscottl 2081169412Sscottl 2082169412Sscottl return 0; 2083175942Sscottl 2084175942Sscottl 2085175942Sscottlteartown_irq_resource: 2086175942Sscottl bus_teardown_intr(dev, hba->irq_res, hba->irq_handle); 2087175942Sscottl 2088175942Sscottlfree_irq_resource: 2089175942Sscottl bus_release_resource(dev, SYS_RES_IRQ, 0, hba->irq_res); 2090175942Sscottl 2091269612Sjhb hptiop_lock_adapter(hba); 2092175942Sscottlfree_hba_path: 2093175942Sscottl xpt_free_path(hba->path); 2094175942Sscottl 2095175942Sscottlderegister_xpt_bus: 2096175942Sscottl xpt_bus_deregister(cam_sim_path(hba->sim)); 2097175942Sscottl 2098175942Sscottlfree_cam_sim: 2099175942Sscottl cam_sim_free(hba->sim, /*free devq*/ TRUE); 2100269612Sjhb hptiop_unlock_adapter(hba); 2101175942Sscottl 2102175942Sscottlsrb_dmamap_unload: 2103175942Sscottl if (hba->uncached_ptr) 2104175942Sscottl bus_dmamap_unload(hba->srb_dmat, hba->srb_dmamap); 2105175942Sscottl 2106175942Sscottlsrb_dmamem_free: 2107175942Sscottl if (hba->uncached_ptr) 2108175942Sscottl bus_dmamem_free(hba->srb_dmat, 2109175942Sscottl hba->uncached_ptr, hba->srb_dmamap); 2110175942Sscottl 2111175942Sscottldestroy_srb_dmat: 2112175942Sscottl if (hba->srb_dmat) 2113175942Sscottl bus_dma_tag_destroy(hba->srb_dmat); 2114175942Sscottl 2115175942Sscottldestroy_io_dmat: 2116175942Sscottl if (hba->io_dmat) 2117175942Sscottl bus_dma_tag_destroy(hba->io_dmat); 2118175942Sscottl 2119175942Sscottlget_config_failed: 2120242086Sdelphij hba->ops->internal_memfree(hba); 2121175942Sscottl 2122175942Sscottldestroy_parent_tag: 2123175942Sscottl if (hba->parent_dmat) 2124175942Sscottl bus_dma_tag_destroy(hba->parent_dmat); 2125175942Sscottl 2126175942Sscottlrelease_pci_res: 2127175942Sscottl if (hba->ops->release_pci_res) 2128175942Sscottl hba->ops->release_pci_res(hba); 2129175942Sscottl 2130175942Sscottl return ENXIO; 2131169412Sscottl} 2132169412Sscottl 2133169412Sscottlstatic int hptiop_detach(device_t dev) 2134169412Sscottl{ 2135169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev); 2136169412Sscottl int i; 2137169412Sscottl int error = EBUSY; 2138169412Sscottl 2139169412Sscottl hptiop_lock_adapter(hba); 2140175942Sscottl for (i = 0; i < hba->max_devices; i++) 2141175942Sscottl if (hptiop_os_query_remove_device(hba, i)) { 2142175942Sscottl device_printf(dev, "%d file system is busy. id=%d", 2143169412Sscottl hba->pciunit, i); 2144169412Sscottl goto out; 2145169412Sscottl } 2146169412Sscottl 2147169412Sscottl if ((error = hptiop_shutdown(dev)) != 0) 2148169412Sscottl goto out; 2149175942Sscottl if (hptiop_send_sync_msg(hba, 2150175942Sscottl IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK, 60000)) 2151169412Sscottl goto out; 2152269612Sjhb hptiop_unlock_adapter(hba); 2153169412Sscottl 2154169412Sscottl hptiop_release_resource(hba); 2155269612Sjhb return (0); 2156169412Sscottlout: 2157169412Sscottl hptiop_unlock_adapter(hba); 2158169412Sscottl return error; 2159169412Sscottl} 2160169412Sscottl 2161169412Sscottlstatic int hptiop_shutdown(device_t dev) 2162169412Sscottl{ 2163169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev); 2164169412Sscottl 2165169412Sscottl int error = 0; 2166169412Sscottl 2167169412Sscottl if (hba->flag & HPT_IOCTL_FLAG_OPEN) { 2168175942Sscottl device_printf(dev, "%d device is busy", hba->pciunit); 2169169412Sscottl return EBUSY; 2170169412Sscottl } 2171175942Sscottl 2172175942Sscottl hba->ops->disable_intr(hba); 2173175942Sscottl 2174175942Sscottl if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_SHUTDOWN, 60000)) 2175169412Sscottl error = EBUSY; 2176169412Sscottl 2177169412Sscottl return error; 2178169412Sscottl} 2179169412Sscottl 2180169412Sscottlstatic void hptiop_pci_intr(void *arg) 2181169412Sscottl{ 2182169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg; 2183169412Sscottl hptiop_lock_adapter(hba); 2184175942Sscottl hba->ops->iop_intr(hba); 2185169412Sscottl hptiop_unlock_adapter(hba); 2186169412Sscottl} 2187169412Sscottl 2188169412Sscottlstatic void hptiop_poll(struct cam_sim *sim) 2189169412Sscottl{ 2190269612Sjhb struct hpt_iop_hba *hba; 2191269612Sjhb 2192269612Sjhb hba = cam_sim_softc(sim); 2193269612Sjhb hba->ops->iop_intr(hba); 2194169412Sscottl} 2195169412Sscottl 2196169412Sscottlstatic void hptiop_async(void * callback_arg, u_int32_t code, 2197169412Sscottl struct cam_path * path, void * arg) 2198169412Sscottl{ 2199169412Sscottl} 2200169412Sscottl 2201175942Sscottlstatic void hptiop_enable_intr_itl(struct hpt_iop_hba *hba) 2202169412Sscottl{ 2203175942Sscottl BUS_SPACE_WRT4_ITL(outbound_intmask, 2204169412Sscottl ~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0)); 2205169412Sscottl} 2206169412Sscottl 2207175942Sscottlstatic void hptiop_enable_intr_mv(struct hpt_iop_hba *hba) 2208169412Sscottl{ 2209169412Sscottl u_int32_t int_mask; 2210169412Sscottl 2211175942Sscottl int_mask = BUS_SPACE_RD4_MV0(outbound_intmask); 2212175942Sscottl 2213175942Sscottl int_mask |= MVIOP_MU_OUTBOUND_INT_POSTQUEUE 2214175942Sscottl | MVIOP_MU_OUTBOUND_INT_MSG; 2215175942Sscottl BUS_SPACE_WRT4_MV0(outbound_intmask,int_mask); 2216169412Sscottl} 2217169412Sscottl 2218242086Sdelphijstatic void hptiop_enable_intr_mvfrey(struct hpt_iop_hba *hba) 2219242086Sdelphij{ 2220242086Sdelphij BUS_SPACE_WRT4_MVFREY2(f0_doorbell_enable, CPU_TO_F0_DRBL_MSG_A_BIT); 2221242086Sdelphij BUS_SPACE_RD4_MVFREY2(f0_doorbell_enable); 2222242086Sdelphij 2223242086Sdelphij BUS_SPACE_WRT4_MVFREY2(isr_enable, 0x1); 2224242086Sdelphij BUS_SPACE_RD4_MVFREY2(isr_enable); 2225242086Sdelphij 2226242086Sdelphij BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0x1010); 2227242086Sdelphij BUS_SPACE_RD4_MVFREY2(pcie_f0_int_enable); 2228242086Sdelphij} 2229242086Sdelphij 2230175942Sscottlstatic void hptiop_disable_intr_itl(struct hpt_iop_hba *hba) 2231175942Sscottl{ 2232175942Sscottl u_int32_t int_mask; 2233175942Sscottl 2234175942Sscottl int_mask = BUS_SPACE_RD4_ITL(outbound_intmask); 2235175942Sscottl 2236175942Sscottl int_mask |= IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0; 2237175942Sscottl BUS_SPACE_WRT4_ITL(outbound_intmask, int_mask); 2238175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 2239175942Sscottl} 2240175942Sscottl 2241175942Sscottlstatic void hptiop_disable_intr_mv(struct hpt_iop_hba *hba) 2242175942Sscottl{ 2243175942Sscottl u_int32_t int_mask; 2244175942Sscottl int_mask = BUS_SPACE_RD4_MV0(outbound_intmask); 2245175942Sscottl 2246175942Sscottl int_mask &= ~(MVIOP_MU_OUTBOUND_INT_MSG 2247175942Sscottl | MVIOP_MU_OUTBOUND_INT_POSTQUEUE); 2248175942Sscottl BUS_SPACE_WRT4_MV0(outbound_intmask,int_mask); 2249175942Sscottl BUS_SPACE_RD4_MV0(outbound_intmask); 2250175942Sscottl} 2251175942Sscottl 2252242086Sdelphijstatic void hptiop_disable_intr_mvfrey(struct hpt_iop_hba *hba) 2253169412Sscottl{ 2254242086Sdelphij BUS_SPACE_WRT4_MVFREY2(f0_doorbell_enable, 0); 2255242086Sdelphij BUS_SPACE_RD4_MVFREY2(f0_doorbell_enable); 2256242086Sdelphij 2257242086Sdelphij BUS_SPACE_WRT4_MVFREY2(isr_enable, 0); 2258242086Sdelphij BUS_SPACE_RD4_MVFREY2(isr_enable); 2259242086Sdelphij 2260242086Sdelphij BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0); 2261242086Sdelphij BUS_SPACE_RD4_MVFREY2(pcie_f0_int_enable); 2262169412Sscottl} 2263169412Sscottl 2264242086Sdelphijstatic void hptiop_reset_adapter(void *argv) 2265242086Sdelphij{ 2266242086Sdelphij struct hpt_iop_hba * hba = (struct hpt_iop_hba *)argv; 2267242086Sdelphij if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000)) 2268242086Sdelphij return; 2269242086Sdelphij hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000); 2270242086Sdelphij} 2271242086Sdelphij 2272169412Sscottlstatic void *hptiop_get_srb(struct hpt_iop_hba * hba) 2273169412Sscottl{ 2274169412Sscottl struct hpt_iop_srb * srb; 2275169412Sscottl 2276169412Sscottl if (hba->srb_list) { 2277169412Sscottl srb = hba->srb_list; 2278169412Sscottl hba->srb_list = srb->next; 2279175942Sscottl return srb; 2280169412Sscottl } 2281169412Sscottl 2282175942Sscottl return NULL; 2283169412Sscottl} 2284169412Sscottl 2285175942Sscottlstatic void hptiop_free_srb(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb) 2286169412Sscottl{ 2287169412Sscottl srb->next = hba->srb_list; 2288169412Sscottl hba->srb_list = srb; 2289169412Sscottl} 2290169412Sscottl 2291169412Sscottlstatic void hptiop_action(struct cam_sim *sim, union ccb *ccb) 2292169412Sscottl{ 2293169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)cam_sim_softc(sim); 2294169412Sscottl struct hpt_iop_srb * srb; 2295246713Skib int error; 2296169412Sscottl 2297169412Sscottl switch (ccb->ccb_h.func_code) { 2298169412Sscottl 2299169412Sscottl case XPT_SCSI_IO: 2300169412Sscottl if (ccb->ccb_h.target_lun != 0 || 2301175942Sscottl ccb->ccb_h.target_id >= hba->max_devices || 2302169412Sscottl (ccb->ccb_h.flags & CAM_CDB_PHYS)) 2303169412Sscottl { 2304169412Sscottl ccb->ccb_h.status = CAM_TID_INVALID; 2305169412Sscottl xpt_done(ccb); 2306269612Sjhb return; 2307169412Sscottl } 2308169412Sscottl 2309169412Sscottl if ((srb = hptiop_get_srb(hba)) == NULL) { 2310175942Sscottl device_printf(hba->pcidev, "srb allocated failed"); 2311169412Sscottl ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2312169412Sscottl xpt_done(ccb); 2313269612Sjhb return; 2314169412Sscottl } 2315169412Sscottl 2316169412Sscottl srb->ccb = ccb; 2317246713Skib error = bus_dmamap_load_ccb(hba->io_dmat, 2318246713Skib srb->dma_map, 2319246713Skib ccb, 2320246713Skib hptiop_post_scsi_command, 2321246713Skib srb, 2322246713Skib 0); 2323169412Sscottl 2324246713Skib if (error && error != EINPROGRESS) { 2325246713Skib device_printf(hba->pcidev, 2326246713Skib "%d bus_dmamap_load error %d", 2327246713Skib hba->pciunit, error); 2328246713Skib xpt_freeze_simq(hba->sim, 1); 2329246713Skib ccb->ccb_h.status = CAM_REQ_CMP_ERR; 2330246713Skib hptiop_free_srb(hba, srb); 2331246713Skib xpt_done(ccb); 2332269612Sjhb return; 2333169412Sscottl } 2334169412Sscottl 2335169412Sscottl return; 2336169412Sscottl 2337169412Sscottl case XPT_RESET_BUS: 2338175942Sscottl device_printf(hba->pcidev, "reset adapter"); 2339169412Sscottl hba->msg_done = 0; 2340169412Sscottl hptiop_reset_adapter(hba); 2341169412Sscottl break; 2342169412Sscottl 2343169412Sscottl case XPT_GET_TRAN_SETTINGS: 2344169412Sscottl case XPT_SET_TRAN_SETTINGS: 2345169412Sscottl ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 2346169412Sscottl break; 2347169412Sscottl 2348169412Sscottl case XPT_CALC_GEOMETRY: 2349227912Smarius cam_calc_geometry(&ccb->ccg, 1); 2350169412Sscottl break; 2351169412Sscottl 2352169412Sscottl case XPT_PATH_INQ: 2353169412Sscottl { 2354169412Sscottl struct ccb_pathinq *cpi = &ccb->cpi; 2355169412Sscottl 2356169412Sscottl cpi->version_num = 1; 2357169412Sscottl cpi->hba_inquiry = PI_SDTR_ABLE; 2358169412Sscottl cpi->target_sprt = 0; 2359169412Sscottl cpi->hba_misc = PIM_NOBUSRESET; 2360169412Sscottl cpi->hba_eng_cnt = 0; 2361175942Sscottl cpi->max_target = hba->max_devices; 2362169412Sscottl cpi->max_lun = 0; 2363169412Sscottl cpi->unit_number = cam_sim_unit(sim); 2364169412Sscottl cpi->bus_id = cam_sim_bus(sim); 2365175942Sscottl cpi->initiator_id = hba->max_devices; 2366169412Sscottl cpi->base_transfer_speed = 3300; 2367169412Sscottl 2368315812Smav strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2369315812Smav strlcpy(cpi->hba_vid, "HPT ", HBA_IDLEN); 2370315812Smav strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 2371209340Smav cpi->transport = XPORT_SPI; 2372209340Smav cpi->transport_version = 2; 2373209340Smav cpi->protocol = PROTO_SCSI; 2374209340Smav cpi->protocol_version = SCSI_REV_2; 2375169412Sscottl cpi->ccb_h.status = CAM_REQ_CMP; 2376169412Sscottl break; 2377169412Sscottl } 2378169412Sscottl 2379169412Sscottl default: 2380169412Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 2381169412Sscottl break; 2382169412Sscottl } 2383169412Sscottl 2384169412Sscottl xpt_done(ccb); 2385169412Sscottl return; 2386169412Sscottl} 2387169412Sscottl 2388175942Sscottlstatic void hptiop_post_req_itl(struct hpt_iop_hba *hba, 2389175942Sscottl struct hpt_iop_srb *srb, 2390175942Sscottl bus_dma_segment_t *segs, int nsegs) 2391169412Sscottl{ 2392169412Sscottl int idx; 2393169412Sscottl union ccb *ccb = srb->ccb; 2394169412Sscottl u_int8_t *cdb; 2395169412Sscottl 2396175942Sscottl if (ccb->ccb_h.flags & CAM_CDB_POINTER) 2397175942Sscottl cdb = ccb->csio.cdb_io.cdb_ptr; 2398175942Sscottl else 2399175942Sscottl cdb = ccb->csio.cdb_io.cdb_bytes; 2400169412Sscottl 2401175942Sscottl KdPrint(("ccb=%p %x-%x-%x\n", 2402175942Sscottl ccb, *(u_int32_t *)cdb, *((u_int32_t *)cdb+1), *((u_int32_t *)cdb+2))); 2403169412Sscottl 2404169412Sscottl if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) { 2405175942Sscottl u_int32_t iop_req32; 2406175942Sscottl struct hpt_iop_request_scsi_command req; 2407169412Sscottl 2408175942Sscottl iop_req32 = BUS_SPACE_RD4_ITL(inbound_queue); 2409175942Sscottl 2410175942Sscottl if (iop_req32 == IOPMU_QUEUE_EMPTY) { 2411298931Spfg device_printf(hba->pcidev, "invalid req offset\n"); 2412175942Sscottl ccb->ccb_h.status = CAM_BUSY; 2413175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 2414175942Sscottl hptiop_free_srb(hba, srb); 2415175942Sscottl xpt_done(ccb); 2416175942Sscottl return; 2417169412Sscottl } 2418175942Sscottl 2419175942Sscottl if (ccb->csio.dxfer_len && nsegs > 0) { 2420175942Sscottl struct hpt_iopsg *psg = req.sg_list; 2421175942Sscottl for (idx = 0; idx < nsegs; idx++, psg++) { 2422175942Sscottl psg->pci_address = (u_int64_t)segs[idx].ds_addr; 2423175942Sscottl psg->size = segs[idx].ds_len; 2424175942Sscottl psg->eot = 0; 2425175942Sscottl } 2426175942Sscottl psg[-1].eot = 1; 2427175942Sscottl } 2428175942Sscottl 2429175942Sscottl bcopy(cdb, req.cdb, ccb->csio.cdb_len); 2430175942Sscottl 2431242086Sdelphij req.header.size = 2432242086Sdelphij offsetof(struct hpt_iop_request_scsi_command, sg_list) 2433175942Sscottl + nsegs*sizeof(struct hpt_iopsg); 2434175942Sscottl req.header.type = IOP_REQUEST_TYPE_SCSI_COMMAND; 2435175942Sscottl req.header.flags = 0; 2436175942Sscottl req.header.result = IOP_RESULT_PENDING; 2437175942Sscottl req.header.context = (u_int64_t)(unsigned long)srb; 2438175942Sscottl req.dataxfer_length = ccb->csio.dxfer_len; 2439175942Sscottl req.channel = 0; 2440175942Sscottl req.target = ccb->ccb_h.target_id; 2441175942Sscottl req.lun = ccb->ccb_h.target_lun; 2442175942Sscottl 2443175942Sscottl bus_space_write_region_1(hba->bar0t, hba->bar0h, iop_req32, 2444175942Sscottl (u_int8_t *)&req, req.header.size); 2445175942Sscottl 2446175942Sscottl if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 2447175942Sscottl bus_dmamap_sync(hba->io_dmat, 2448175942Sscottl srb->dma_map, BUS_DMASYNC_PREREAD); 2449175942Sscottl } 2450175942Sscottl else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) 2451175942Sscottl bus_dmamap_sync(hba->io_dmat, 2452175942Sscottl srb->dma_map, BUS_DMASYNC_PREWRITE); 2453175942Sscottl 2454175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue,iop_req32); 2455175942Sscottl } else { 2456175942Sscottl struct hpt_iop_request_scsi_command *req; 2457175942Sscottl 2458169412Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 2459175942Sscottl if (ccb->csio.dxfer_len && nsegs > 0) { 2460175942Sscottl struct hpt_iopsg *psg = req->sg_list; 2461175942Sscottl for (idx = 0; idx < nsegs; idx++, psg++) { 2462175942Sscottl psg->pci_address = 2463175942Sscottl (u_int64_t)segs[idx].ds_addr; 2464175942Sscottl psg->size = segs[idx].ds_len; 2465175942Sscottl psg->eot = 0; 2466175942Sscottl } 2467175942Sscottl psg[-1].eot = 1; 2468175942Sscottl } 2469169412Sscottl 2470175942Sscottl bcopy(cdb, req->cdb, ccb->csio.cdb_len); 2471175942Sscottl 2472175942Sscottl req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND; 2473175942Sscottl req->header.result = IOP_RESULT_PENDING; 2474175942Sscottl req->dataxfer_length = ccb->csio.dxfer_len; 2475175942Sscottl req->channel = 0; 2476175942Sscottl req->target = ccb->ccb_h.target_id; 2477175942Sscottl req->lun = ccb->ccb_h.target_lun; 2478242086Sdelphij req->header.size = 2479242086Sdelphij offsetof(struct hpt_iop_request_scsi_command, sg_list) 2480175942Sscottl + nsegs*sizeof(struct hpt_iopsg); 2481175942Sscottl req->header.context = (u_int64_t)srb->index | 2482175942Sscottl IOPMU_QUEUE_ADDR_HOST_BIT; 2483175942Sscottl req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT; 2484175942Sscottl 2485175942Sscottl if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 2486175942Sscottl bus_dmamap_sync(hba->io_dmat, 2487175942Sscottl srb->dma_map, BUS_DMASYNC_PREREAD); 2488175942Sscottl }else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 2489175942Sscottl bus_dmamap_sync(hba->io_dmat, 2490175942Sscottl srb->dma_map, BUS_DMASYNC_PREWRITE); 2491175942Sscottl } 2492175942Sscottl 2493175942Sscottl if (hba->firmware_version > 0x01020000 2494175942Sscottl || hba->interface_version > 0x01020000) { 2495175942Sscottl u_int32_t size_bits; 2496175942Sscottl 2497175942Sscottl if (req->header.size < 256) 2498175942Sscottl size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT; 2499175942Sscottl else if (req->header.size < 512) 2500175942Sscottl size_bits = IOPMU_QUEUE_ADDR_HOST_BIT; 2501175942Sscottl else 2502175942Sscottl size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT 2503175942Sscottl | IOPMU_QUEUE_ADDR_HOST_BIT; 2504175942Sscottl 2505175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue, 2506175942Sscottl (u_int32_t)srb->phy_addr | size_bits); 2507175942Sscottl } else 2508175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue, (u_int32_t)srb->phy_addr 2509175942Sscottl |IOPMU_QUEUE_ADDR_HOST_BIT); 2510175942Sscottl } 2511175942Sscottl} 2512175942Sscottl 2513175942Sscottlstatic void hptiop_post_req_mv(struct hpt_iop_hba *hba, 2514175942Sscottl struct hpt_iop_srb *srb, 2515175942Sscottl bus_dma_segment_t *segs, int nsegs) 2516175942Sscottl{ 2517175942Sscottl int idx, size; 2518175942Sscottl union ccb *ccb = srb->ccb; 2519175942Sscottl u_int8_t *cdb; 2520175942Sscottl struct hpt_iop_request_scsi_command *req; 2521175942Sscottl u_int64_t req_phy; 2522175942Sscottl 2523175942Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 2524175942Sscottl req_phy = srb->phy_addr; 2525175942Sscottl 2526169412Sscottl if (ccb->csio.dxfer_len && nsegs > 0) { 2527169412Sscottl struct hpt_iopsg *psg = req->sg_list; 2528169412Sscottl for (idx = 0; idx < nsegs; idx++, psg++) { 2529169412Sscottl psg->pci_address = (u_int64_t)segs[idx].ds_addr; 2530169412Sscottl psg->size = segs[idx].ds_len; 2531169412Sscottl psg->eot = 0; 2532169412Sscottl } 2533169412Sscottl psg[-1].eot = 1; 2534169412Sscottl } 2535169412Sscottl if (ccb->ccb_h.flags & CAM_CDB_POINTER) 2536169412Sscottl cdb = ccb->csio.cdb_io.cdb_ptr; 2537169412Sscottl else 2538169412Sscottl cdb = ccb->csio.cdb_io.cdb_bytes; 2539169412Sscottl 2540169412Sscottl bcopy(cdb, req->cdb, ccb->csio.cdb_len); 2541169412Sscottl req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND; 2542169412Sscottl req->header.result = IOP_RESULT_PENDING; 2543169412Sscottl req->dataxfer_length = ccb->csio.dxfer_len; 2544175942Sscottl req->channel = 0; 2545169412Sscottl req->target = ccb->ccb_h.target_id; 2546169412Sscottl req->lun = ccb->ccb_h.target_lun; 2547169412Sscottl req->header.size = sizeof(struct hpt_iop_request_scsi_command) 2548175942Sscottl - sizeof(struct hpt_iopsg) 2549175942Sscottl + nsegs * sizeof(struct hpt_iopsg); 2550169412Sscottl if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 2551169412Sscottl bus_dmamap_sync(hba->io_dmat, 2552175942Sscottl srb->dma_map, BUS_DMASYNC_PREREAD); 2553169412Sscottl } 2554169412Sscottl else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) 2555169412Sscottl bus_dmamap_sync(hba->io_dmat, 2556175942Sscottl srb->dma_map, BUS_DMASYNC_PREWRITE); 2557175942Sscottl req->header.context = (u_int64_t)srb->index 2558175942Sscottl << MVIOP_REQUEST_NUMBER_START_BIT 2559175942Sscottl | MVIOP_CMD_TYPE_SCSI; 2560175942Sscottl req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT; 2561175942Sscottl size = req->header.size >> 8; 2562175942Sscottl hptiop_mv_inbound_write(req_phy 2563175942Sscottl | MVIOP_MU_QUEUE_ADDR_HOST_BIT 2564299033Saraujo | imin(3, size), hba); 2565169412Sscottl} 2566169412Sscottl 2567242086Sdelphijstatic void hptiop_post_req_mvfrey(struct hpt_iop_hba *hba, 2568242086Sdelphij struct hpt_iop_srb *srb, 2569242086Sdelphij bus_dma_segment_t *segs, int nsegs) 2570242086Sdelphij{ 2571242086Sdelphij int idx, index; 2572242086Sdelphij union ccb *ccb = srb->ccb; 2573242086Sdelphij u_int8_t *cdb; 2574242086Sdelphij struct hpt_iop_request_scsi_command *req; 2575242086Sdelphij u_int64_t req_phy; 2576242086Sdelphij 2577242086Sdelphij req = (struct hpt_iop_request_scsi_command *)srb; 2578242086Sdelphij req_phy = srb->phy_addr; 2579242086Sdelphij 2580242086Sdelphij if (ccb->csio.dxfer_len && nsegs > 0) { 2581242086Sdelphij struct hpt_iopsg *psg = req->sg_list; 2582242086Sdelphij for (idx = 0; idx < nsegs; idx++, psg++) { 2583242086Sdelphij psg->pci_address = (u_int64_t)segs[idx].ds_addr | 1; 2584242086Sdelphij psg->size = segs[idx].ds_len; 2585242086Sdelphij psg->eot = 0; 2586242086Sdelphij } 2587242086Sdelphij psg[-1].eot = 1; 2588242086Sdelphij } 2589242086Sdelphij if (ccb->ccb_h.flags & CAM_CDB_POINTER) 2590242086Sdelphij cdb = ccb->csio.cdb_io.cdb_ptr; 2591242086Sdelphij else 2592242086Sdelphij cdb = ccb->csio.cdb_io.cdb_bytes; 2593242086Sdelphij 2594242086Sdelphij bcopy(cdb, req->cdb, ccb->csio.cdb_len); 2595242086Sdelphij req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND; 2596242086Sdelphij req->header.result = IOP_RESULT_PENDING; 2597242086Sdelphij req->dataxfer_length = ccb->csio.dxfer_len; 2598242086Sdelphij req->channel = 0; 2599242086Sdelphij req->target = ccb->ccb_h.target_id; 2600242086Sdelphij req->lun = ccb->ccb_h.target_lun; 2601242086Sdelphij req->header.size = sizeof(struct hpt_iop_request_scsi_command) 2602242086Sdelphij - sizeof(struct hpt_iopsg) 2603242086Sdelphij + nsegs * sizeof(struct hpt_iopsg); 2604242086Sdelphij if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 2605242086Sdelphij bus_dmamap_sync(hba->io_dmat, 2606242086Sdelphij srb->dma_map, BUS_DMASYNC_PREREAD); 2607242086Sdelphij } 2608242086Sdelphij else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) 2609242086Sdelphij bus_dmamap_sync(hba->io_dmat, 2610242086Sdelphij srb->dma_map, BUS_DMASYNC_PREWRITE); 2611242086Sdelphij 2612242086Sdelphij req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT 2613242086Sdelphij | IOP_REQUEST_FLAG_ADDR_BITS 2614242086Sdelphij | ((req_phy >> 16) & 0xffff0000); 2615242086Sdelphij req->header.context = ((req_phy & 0xffffffff) << 32 ) 2616242086Sdelphij | srb->index << 4 2617242086Sdelphij | IOPMU_QUEUE_ADDR_HOST_BIT | req->header.type; 2618242086Sdelphij 2619242086Sdelphij hba->u.mvfrey.inlist_wptr++; 2620242086Sdelphij index = hba->u.mvfrey.inlist_wptr & 0x3fff; 2621242086Sdelphij 2622242086Sdelphij if (index == hba->u.mvfrey.list_count) { 2623242086Sdelphij index = 0; 2624242086Sdelphij hba->u.mvfrey.inlist_wptr &= ~0x3fff; 2625242086Sdelphij hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE; 2626242086Sdelphij } 2627242086Sdelphij 2628242086Sdelphij hba->u.mvfrey.inlist[index].addr = req_phy; 2629242086Sdelphij hba->u.mvfrey.inlist[index].intrfc_len = (req->header.size + 3) / 4; 2630242086Sdelphij 2631242086Sdelphij BUS_SPACE_WRT4_MVFREY2(inbound_write_ptr, hba->u.mvfrey.inlist_wptr); 2632242086Sdelphij BUS_SPACE_RD4_MVFREY2(inbound_write_ptr); 2633242086Sdelphij 2634242086Sdelphij if (req->header.type == IOP_REQUEST_TYPE_SCSI_COMMAND) { 2635269612Sjhb callout_reset(&srb->timeout, 20 * hz, hptiop_reset_adapter, hba); 2636242086Sdelphij } 2637242086Sdelphij} 2638242086Sdelphij 2639175942Sscottlstatic void hptiop_post_scsi_command(void *arg, bus_dma_segment_t *segs, 2640175942Sscottl int nsegs, int error) 2641169412Sscottl{ 2642175942Sscottl struct hpt_iop_srb *srb = (struct hpt_iop_srb *)arg; 2643175942Sscottl union ccb *ccb = srb->ccb; 2644175942Sscottl struct hpt_iop_hba *hba = srb->hba; 2645169412Sscottl 2646175942Sscottl if (error || nsegs > hba->max_sg_count) { 2647257381Snwhitehorn KdPrint(("hptiop: func_code=%x tid=%x lun=%jx nsegs=%d\n", 2648175942Sscottl ccb->ccb_h.func_code, 2649175942Sscottl ccb->ccb_h.target_id, 2650257381Snwhitehorn (uintmax_t)ccb->ccb_h.target_lun, nsegs)); 2651175942Sscottl ccb->ccb_h.status = CAM_BUSY; 2652175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 2653169412Sscottl hptiop_free_srb(hba, srb); 2654169412Sscottl xpt_done(ccb); 2655175942Sscottl return; 2656169412Sscottl } 2657175942Sscottl 2658175942Sscottl hba->ops->post_req(hba, srb, segs, nsegs); 2659169412Sscottl} 2660169412Sscottl 2661175942Sscottlstatic void hptiop_mv_map_ctlcfg(void *arg, bus_dma_segment_t *segs, 2662175942Sscottl int nsegs, int error) 2663175942Sscottl{ 2664175942Sscottl struct hpt_iop_hba *hba = (struct hpt_iop_hba *)arg; 2665175942Sscottl hba->ctlcfgcmd_phy = ((u_int64_t)segs->ds_addr + 0x1F) 2666175942Sscottl & ~(u_int64_t)0x1F; 2667175942Sscottl hba->ctlcfg_ptr = (u_int8_t *)(((unsigned long)hba->ctlcfg_ptr + 0x1F) 2668175942Sscottl & ~0x1F); 2669175942Sscottl} 2670175942Sscottl 2671242086Sdelphijstatic void hptiop_mvfrey_map_ctlcfg(void *arg, bus_dma_segment_t *segs, 2672242086Sdelphij int nsegs, int error) 2673242086Sdelphij{ 2674242086Sdelphij struct hpt_iop_hba *hba = (struct hpt_iop_hba *)arg; 2675242086Sdelphij char *p; 2676242086Sdelphij u_int64_t phy; 2677242086Sdelphij u_int32_t list_count = hba->u.mvfrey.list_count; 2678242086Sdelphij 2679242086Sdelphij phy = ((u_int64_t)segs->ds_addr + 0x1F) 2680242086Sdelphij & ~(u_int64_t)0x1F; 2681242086Sdelphij p = (u_int8_t *)(((unsigned long)hba->ctlcfg_ptr + 0x1F) 2682242086Sdelphij & ~0x1F); 2683242086Sdelphij 2684242086Sdelphij hba->ctlcfgcmd_phy = phy; 2685242086Sdelphij hba->ctlcfg_ptr = p; 2686242086Sdelphij 2687242086Sdelphij p += 0x800; 2688242086Sdelphij phy += 0x800; 2689242086Sdelphij 2690242086Sdelphij hba->u.mvfrey.inlist = (struct mvfrey_inlist_entry *)p; 2691242086Sdelphij hba->u.mvfrey.inlist_phy = phy; 2692242086Sdelphij 2693242086Sdelphij p += list_count * sizeof(struct mvfrey_inlist_entry); 2694242086Sdelphij phy += list_count * sizeof(struct mvfrey_inlist_entry); 2695242086Sdelphij 2696242086Sdelphij hba->u.mvfrey.outlist = (struct mvfrey_outlist_entry *)p; 2697242086Sdelphij hba->u.mvfrey.outlist_phy = phy; 2698242086Sdelphij 2699242086Sdelphij p += list_count * sizeof(struct mvfrey_outlist_entry); 2700242086Sdelphij phy += list_count * sizeof(struct mvfrey_outlist_entry); 2701242086Sdelphij 2702242086Sdelphij hba->u.mvfrey.outlist_cptr = (u_int32_t *)p; 2703242086Sdelphij hba->u.mvfrey.outlist_cptr_phy = phy; 2704242086Sdelphij} 2705242086Sdelphij 2706169412Sscottlstatic void hptiop_map_srb(void *arg, bus_dma_segment_t *segs, 2707175942Sscottl int nsegs, int error) 2708169412Sscottl{ 2709169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg; 2710169412Sscottl bus_addr_t phy_addr = (segs->ds_addr + 0x1F) & ~(bus_addr_t)0x1F; 2711169412Sscottl struct hpt_iop_srb *srb, *tmp_srb; 2712169412Sscottl int i; 2713169412Sscottl 2714169412Sscottl if (error || nsegs == 0) { 2715175942Sscottl device_printf(hba->pcidev, "hptiop_map_srb error"); 2716169412Sscottl return; 2717169412Sscottl } 2718169412Sscottl 2719169412Sscottl /* map srb */ 2720169412Sscottl srb = (struct hpt_iop_srb *) 2721175942Sscottl (((unsigned long)hba->uncached_ptr + 0x1F) 2722175942Sscottl & ~(unsigned long)0x1F); 2723169412Sscottl 2724169412Sscottl for (i = 0; i < HPT_SRB_MAX_QUEUE_SIZE; i++) { 2725169412Sscottl tmp_srb = (struct hpt_iop_srb *) 2726169412Sscottl ((char *)srb + i * HPT_SRB_MAX_SIZE); 2727169412Sscottl if (((unsigned long)tmp_srb & 0x1F) == 0) { 2728169412Sscottl if (bus_dmamap_create(hba->io_dmat, 2729169412Sscottl 0, &tmp_srb->dma_map)) { 2730175942Sscottl device_printf(hba->pcidev, "dmamap create failed"); 2731169412Sscottl return; 2732169412Sscottl } 2733169412Sscottl 2734169412Sscottl bzero(tmp_srb, sizeof(struct hpt_iop_srb)); 2735169412Sscottl tmp_srb->hba = hba; 2736169412Sscottl tmp_srb->index = i; 2737175942Sscottl if (hba->ctlcfg_ptr == 0) {/*itl iop*/ 2738175942Sscottl tmp_srb->phy_addr = (u_int64_t)(u_int32_t) 2739175942Sscottl (phy_addr >> 5); 2740175942Sscottl if (phy_addr & IOPMU_MAX_MEM_SUPPORT_MASK_32G) 2741175942Sscottl tmp_srb->srb_flag = 2742175942Sscottl HPT_SRB_FLAG_HIGH_MEM_ACESS; 2743175942Sscottl } else { 2744175942Sscottl tmp_srb->phy_addr = phy_addr; 2745175942Sscottl } 2746175942Sscottl 2747269612Sjhb callout_init_mtx(&tmp_srb->timeout, &hba->lock, 0); 2748169412Sscottl hptiop_free_srb(hba, tmp_srb); 2749169412Sscottl hba->srb[i] = tmp_srb; 2750169412Sscottl phy_addr += HPT_SRB_MAX_SIZE; 2751169412Sscottl } 2752169412Sscottl else { 2753175942Sscottl device_printf(hba->pcidev, "invalid alignment"); 2754169412Sscottl return; 2755169412Sscottl } 2756169412Sscottl } 2757169412Sscottl} 2758169412Sscottl 2759175942Sscottlstatic void hptiop_os_message_callback(struct hpt_iop_hba * hba, u_int32_t msg) 2760169412Sscottl{ 2761242086Sdelphij hba->msg_done = 1; 2762169412Sscottl} 2763169412Sscottl 2764175942Sscottlstatic int hptiop_os_query_remove_device(struct hpt_iop_hba * hba, 2765175942Sscottl int target_id) 2766169412Sscottl{ 2767169412Sscottl struct cam_periph *periph = NULL; 2768169412Sscottl struct cam_path *path; 2769169412Sscottl int status, retval = 0; 2770169412Sscottl 2771169412Sscottl status = xpt_create_path(&path, NULL, hba->sim->path_id, target_id, 0); 2772169412Sscottl 2773169412Sscottl if (status == CAM_REQ_CMP) { 2774169412Sscottl if ((periph = cam_periph_find(path, "da")) != NULL) { 2775169412Sscottl if (periph->refcount >= 1) { 2776175942Sscottl device_printf(hba->pcidev, "%d ," 2777175942Sscottl "target_id=0x%x," 2778175942Sscottl "refcount=%d", 2779169412Sscottl hba->pciunit, target_id, periph->refcount); 2780169412Sscottl retval = -1; 2781169412Sscottl } 2782169412Sscottl } 2783169412Sscottl xpt_free_path(path); 2784169412Sscottl } 2785169412Sscottl return retval; 2786169412Sscottl} 2787169412Sscottl 2788169412Sscottlstatic void hptiop_release_resource(struct hpt_iop_hba *hba) 2789169412Sscottl{ 2790175942Sscottl int i; 2791269612Sjhb 2792269612Sjhb if (hba->ioctl_dev) 2793269612Sjhb destroy_dev(hba->ioctl_dev); 2794269612Sjhb 2795175942Sscottl if (hba->path) { 2796175942Sscottl struct ccb_setasync ccb; 2797169412Sscottl 2798169412Sscottl xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5); 2799169412Sscottl ccb.ccb_h.func_code = XPT_SASYNC_CB; 2800169412Sscottl ccb.event_enable = 0; 2801169412Sscottl ccb.callback = hptiop_async; 2802169412Sscottl ccb.callback_arg = hba->sim; 2803169412Sscottl xpt_action((union ccb *)&ccb); 2804169412Sscottl xpt_free_path(hba->path); 2805169412Sscottl } 2806169412Sscottl 2807269612Sjhb if (hba->irq_handle) 2808269612Sjhb bus_teardown_intr(hba->pcidev, hba->irq_res, hba->irq_handle); 2809269612Sjhb 2810169412Sscottl if (hba->sim) { 2811269612Sjhb hptiop_lock_adapter(hba); 2812169412Sscottl xpt_bus_deregister(cam_sim_path(hba->sim)); 2813169412Sscottl cam_sim_free(hba->sim, TRUE); 2814269612Sjhb hptiop_unlock_adapter(hba); 2815169412Sscottl } 2816169412Sscottl 2817175942Sscottl if (hba->ctlcfg_dmat) { 2818175942Sscottl bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap); 2819175942Sscottl bus_dmamem_free(hba->ctlcfg_dmat, 2820175942Sscottl hba->ctlcfg_ptr, hba->ctlcfg_dmamap); 2821175942Sscottl bus_dma_tag_destroy(hba->ctlcfg_dmat); 2822175942Sscottl } 2823175942Sscottl 2824175942Sscottl for (i = 0; i < HPT_SRB_MAX_QUEUE_SIZE; i++) { 2825175942Sscottl struct hpt_iop_srb *srb = hba->srb[i]; 2826175942Sscottl if (srb->dma_map) 2827175942Sscottl bus_dmamap_destroy(hba->io_dmat, srb->dma_map); 2828269612Sjhb callout_drain(&srb->timeout); 2829175942Sscottl } 2830175942Sscottl 2831169412Sscottl if (hba->srb_dmat) { 2832169412Sscottl bus_dmamap_unload(hba->srb_dmat, hba->srb_dmamap); 2833175942Sscottl bus_dmamap_destroy(hba->srb_dmat, hba->srb_dmamap); 2834169412Sscottl bus_dma_tag_destroy(hba->srb_dmat); 2835169412Sscottl } 2836169412Sscottl 2837169412Sscottl if (hba->io_dmat) 2838169412Sscottl bus_dma_tag_destroy(hba->io_dmat); 2839169412Sscottl 2840169412Sscottl if (hba->parent_dmat) 2841169412Sscottl bus_dma_tag_destroy(hba->parent_dmat); 2842169412Sscottl 2843169412Sscottl if (hba->irq_res) 2844175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_IRQ, 2845175942Sscottl 0, hba->irq_res); 2846169412Sscottl 2847169412Sscottl if (hba->bar0_res) 2848169412Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 2849169412Sscottl hba->bar0_rid, hba->bar0_res); 2850175942Sscottl if (hba->bar2_res) 2851175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 2852175942Sscottl hba->bar2_rid, hba->bar2_res); 2853269612Sjhb mtx_destroy(&hba->lock); 2854169412Sscottl} 2855