hptiop.c revision 227912
1169412Sscottl/* 2175942Sscottl * HighPoint RR3xxx/4xxx RAID Driver for FreeBSD 3175942Sscottl * Copyright (C) 2007-2008 HighPoint Technologies, Inc. All Rights Reserved. 4175942Sscottl * 5169412Sscottl * Redistribution and use in source and binary forms, with or without 6169412Sscottl * modification, are permitted provided that the following conditions 7169412Sscottl * are met: 8169412Sscottl * 1. Redistributions of source code must retain the above copyright 9169412Sscottl * notice, this list of conditions and the following disclaimer. 10169412Sscottl * 2. Redistributions in binary form must reproduce the above copyright 11169412Sscottl * notice, this list of conditions and the following disclaimer in the 12169412Sscottl * documentation and/or other materials provided with the distribution. 13169412Sscottl * 14169412Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15169412Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16169412Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17169412Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18169412Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19169412Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20169412Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21169412Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22169412Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23169412Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24169412Sscottl * SUCH DAMAGE. 25169412Sscottl */ 26175942Sscottl 27169412Sscottl#include <sys/cdefs.h> 28169412Sscottl__FBSDID("$FreeBSD: head/sys/dev/hptiop/hptiop.c 227912 2011-11-23 21:43:51Z marius $"); 29169412Sscottl 30169412Sscottl#include <sys/param.h> 31169412Sscottl#include <sys/types.h> 32169412Sscottl#include <sys/cons.h> 33169412Sscottl#if (__FreeBSD_version >= 500000) 34169412Sscottl#include <sys/time.h> 35169412Sscottl#include <sys/systm.h> 36169412Sscottl#else 37169412Sscottl#include <machine/clock.h> 38169412Sscottl#endif 39169412Sscottl 40169412Sscottl#include <sys/stat.h> 41169412Sscottl#include <sys/malloc.h> 42169412Sscottl#include <sys/conf.h> 43169412Sscottl#include <sys/libkern.h> 44169412Sscottl#include <sys/kernel.h> 45169412Sscottl 46169412Sscottl#if (__FreeBSD_version >= 500000) 47169412Sscottl#include <sys/kthread.h> 48169412Sscottl#include <sys/mutex.h> 49169412Sscottl#include <sys/module.h> 50169412Sscottl#endif 51169412Sscottl 52169412Sscottl#include <sys/eventhandler.h> 53169412Sscottl#include <sys/bus.h> 54169412Sscottl#include <sys/taskqueue.h> 55169412Sscottl#include <sys/ioccom.h> 56169412Sscottl 57169412Sscottl#include <machine/resource.h> 58169412Sscottl#include <machine/bus.h> 59169412Sscottl#include <machine/stdarg.h> 60169412Sscottl#include <sys/rman.h> 61169412Sscottl 62169412Sscottl#include <vm/vm.h> 63169412Sscottl#include <vm/pmap.h> 64169412Sscottl 65169412Sscottl#if (__FreeBSD_version >= 500000) 66169412Sscottl#include <dev/pci/pcireg.h> 67169412Sscottl#include <dev/pci/pcivar.h> 68169412Sscottl#else 69169412Sscottl#include <pci/pcivar.h> 70169412Sscottl#include <pci/pcireg.h> 71169412Sscottl#endif 72169412Sscottl 73169412Sscottl#if (__FreeBSD_version <= 500043) 74169412Sscottl#include <sys/devicestat.h> 75169412Sscottl#endif 76169412Sscottl 77169412Sscottl#include <cam/cam.h> 78169412Sscottl#include <cam/cam_ccb.h> 79169412Sscottl#include <cam/cam_sim.h> 80169412Sscottl#include <cam/cam_xpt_sim.h> 81169412Sscottl#include <cam/cam_debug.h> 82169412Sscottl#include <cam/cam_periph.h> 83169412Sscottl#include <cam/scsi/scsi_all.h> 84169412Sscottl#include <cam/scsi/scsi_message.h> 85169412Sscottl 86169412Sscottl#if (__FreeBSD_version < 500043) 87169412Sscottl#include <sys/bus_private.h> 88169412Sscottl#endif 89169412Sscottl 90169412Sscottl#include <dev/hptiop/hptiop.h> 91169412Sscottl 92169412Sscottlstatic char driver_name[] = "hptiop"; 93175942Sscottlstatic char driver_version[] = "v1.3 (010208)"; 94169412Sscottl 95169412Sscottlstatic devclass_t hptiop_devclass; 96169412Sscottl 97175942Sscottlstatic int hptiop_send_sync_msg(struct hpt_iop_hba *hba, 98175942Sscottl u_int32_t msg, u_int32_t millisec); 99175942Sscottlstatic void hptiop_request_callback_itl(struct hpt_iop_hba *hba, 100175942Sscottl u_int32_t req); 101175942Sscottlstatic void hptiop_request_callback_mv(struct hpt_iop_hba *hba, u_int64_t req); 102175942Sscottlstatic void hptiop_os_message_callback(struct hpt_iop_hba *hba, u_int32_t msg); 103175942Sscottlstatic int hptiop_do_ioctl_itl(struct hpt_iop_hba *hba, 104175942Sscottl struct hpt_iop_ioctl_param *pParams); 105175942Sscottlstatic int hptiop_do_ioctl_mv(struct hpt_iop_hba *hba, 106175942Sscottl struct hpt_iop_ioctl_param *pParams); 107175942Sscottlstatic int hptiop_rescan_bus(struct hpt_iop_hba *hba); 108175942Sscottlstatic int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba); 109175942Sscottlstatic int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba); 110175942Sscottlstatic int hptiop_get_config_itl(struct hpt_iop_hba *hba, 111175942Sscottl struct hpt_iop_request_get_config *config); 112175942Sscottlstatic int hptiop_get_config_mv(struct hpt_iop_hba *hba, 113175942Sscottl struct hpt_iop_request_get_config *config); 114175942Sscottlstatic int hptiop_set_config_itl(struct hpt_iop_hba *hba, 115175942Sscottl struct hpt_iop_request_set_config *config); 116175942Sscottlstatic int hptiop_set_config_mv(struct hpt_iop_hba *hba, 117175942Sscottl struct hpt_iop_request_set_config *config); 118175942Sscottlstatic int hptiop_internal_memalloc_mv(struct hpt_iop_hba *hba); 119175942Sscottlstatic int hptiop_internal_memfree_mv(struct hpt_iop_hba *hba); 120175942Sscottlstatic int hptiop_post_ioctl_command_itl(struct hpt_iop_hba *hba, 121175942Sscottl u_int32_t req32, struct hpt_iop_ioctl_param *pParams); 122175942Sscottlstatic int hptiop_post_ioctl_command_mv(struct hpt_iop_hba *hba, 123175942Sscottl struct hpt_iop_request_ioctl_command *req, 124175942Sscottl struct hpt_iop_ioctl_param *pParams); 125175942Sscottlstatic void hptiop_post_req_itl(struct hpt_iop_hba *hba, 126175942Sscottl struct hpt_iop_srb *srb, 127175942Sscottl bus_dma_segment_t *segs, int nsegs); 128175942Sscottlstatic void hptiop_post_req_mv(struct hpt_iop_hba *hba, 129175942Sscottl struct hpt_iop_srb *srb, 130175942Sscottl bus_dma_segment_t *segs, int nsegs); 131175942Sscottlstatic void hptiop_post_msg_itl(struct hpt_iop_hba *hba, u_int32_t msg); 132175942Sscottlstatic void hptiop_post_msg_mv(struct hpt_iop_hba *hba, u_int32_t msg); 133175942Sscottlstatic void hptiop_enable_intr_itl(struct hpt_iop_hba *hba); 134175942Sscottlstatic void hptiop_enable_intr_mv(struct hpt_iop_hba *hba); 135175942Sscottlstatic void hptiop_disable_intr_itl(struct hpt_iop_hba *hba); 136175942Sscottlstatic void hptiop_disable_intr_mv(struct hpt_iop_hba *hba); 137175942Sscottlstatic void hptiop_free_srb(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb); 138175942Sscottlstatic int hptiop_os_query_remove_device(struct hpt_iop_hba *hba, int tid); 139169412Sscottlstatic int hptiop_probe(device_t dev); 140169412Sscottlstatic int hptiop_attach(device_t dev); 141169412Sscottlstatic int hptiop_detach(device_t dev); 142169412Sscottlstatic int hptiop_shutdown(device_t dev); 143169412Sscottlstatic void hptiop_action(struct cam_sim *sim, union ccb *ccb); 144169412Sscottlstatic void hptiop_poll(struct cam_sim *sim); 145175942Sscottlstatic void hptiop_async(void *callback_arg, u_int32_t code, 146175942Sscottl struct cam_path *path, void *arg); 147169412Sscottlstatic void hptiop_pci_intr(void *arg); 148175942Sscottlstatic void hptiop_release_resource(struct hpt_iop_hba *hba); 149175942Sscottlstatic int hptiop_reset_adapter(struct hpt_iop_hba *hba); 150169412Sscottl 151169412Sscottlstatic d_open_t hptiop_open; 152169412Sscottlstatic d_close_t hptiop_close; 153169412Sscottlstatic d_ioctl_t hptiop_ioctl; 154169412Sscottl 155169412Sscottlstatic struct cdevsw hptiop_cdevsw = { 156169412Sscottl .d_open = hptiop_open, 157169412Sscottl .d_close = hptiop_close, 158169412Sscottl .d_ioctl = hptiop_ioctl, 159169412Sscottl .d_name = driver_name, 160169412Sscottl#if __FreeBSD_version>=503000 161169412Sscottl .d_version = D_VERSION, 162169412Sscottl#endif 163169412Sscottl#if (__FreeBSD_version>=503000 && __FreeBSD_version<600034) 164169412Sscottl .d_flags = D_NEEDGIANT, 165169412Sscottl#endif 166169412Sscottl#if __FreeBSD_version<600034 167169412Sscottl#if __FreeBSD_version>=501000 168169412Sscottl .d_maj = MAJOR_AUTO, 169169412Sscottl#else 170169412Sscottl .d_maj = HPT_DEV_MAJOR, 171169412Sscottl#endif 172169412Sscottl#endif 173169412Sscottl}; 174169412Sscottl 175169412Sscottl#if __FreeBSD_version < 503000 176169412Sscottl#define hba_from_dev(dev) ((struct hpt_iop_hba *)(dev)->si_drv1) 177169412Sscottl#else 178169412Sscottl#define hba_from_dev(dev) \ 179183397Sed ((struct hpt_iop_hba *)devclass_get_softc(hptiop_devclass, dev2unit(dev))) 180169412Sscottl#endif 181169412Sscottl 182175942Sscottl#define BUS_SPACE_WRT4_ITL(offset, value) bus_space_write_4(hba->bar0t,\ 183175942Sscottl hba->bar0h, offsetof(struct hpt_iopmu_itl, offset), (value)) 184175942Sscottl#define BUS_SPACE_RD4_ITL(offset) bus_space_read_4(hba->bar0t,\ 185175942Sscottl hba->bar0h, offsetof(struct hpt_iopmu_itl, offset)) 186175942Sscottl 187175942Sscottl#define BUS_SPACE_WRT4_MV0(offset, value) bus_space_write_4(hba->bar0t,\ 188175942Sscottl hba->bar0h, offsetof(struct hpt_iopmv_regs, offset), value) 189175942Sscottl#define BUS_SPACE_RD4_MV0(offset) bus_space_read_4(hba->bar0t,\ 190175942Sscottl hba->bar0h, offsetof(struct hpt_iopmv_regs, offset)) 191175942Sscottl#define BUS_SPACE_WRT4_MV2(offset, value) bus_space_write_4(hba->bar2t,\ 192175942Sscottl hba->bar2h, offsetof(struct hpt_iopmu_mv, offset), value) 193175942Sscottl#define BUS_SPACE_RD4_MV2(offset) bus_space_read_4(hba->bar2t,\ 194175942Sscottl hba->bar2h, offsetof(struct hpt_iopmu_mv, offset)) 195175942Sscottl 196169412Sscottlstatic int hptiop_open(ioctl_dev_t dev, int flags, 197169412Sscottl int devtype, ioctl_thread_t proc) 198169412Sscottl{ 199175942Sscottl struct hpt_iop_hba *hba = hba_from_dev(dev); 200169412Sscottl 201169412Sscottl if (hba==NULL) 202169412Sscottl return ENXIO; 203169412Sscottl if (hba->flag & HPT_IOCTL_FLAG_OPEN) 204169412Sscottl return EBUSY; 205169412Sscottl hba->flag |= HPT_IOCTL_FLAG_OPEN; 206169412Sscottl return 0; 207169412Sscottl} 208169412Sscottl 209169412Sscottlstatic int hptiop_close(ioctl_dev_t dev, int flags, 210169412Sscottl int devtype, ioctl_thread_t proc) 211169412Sscottl{ 212175942Sscottl struct hpt_iop_hba *hba = hba_from_dev(dev); 213169412Sscottl hba->flag &= ~(u_int32_t)HPT_IOCTL_FLAG_OPEN; 214169412Sscottl return 0; 215169412Sscottl} 216169412Sscottl 217169412Sscottlstatic int hptiop_ioctl(ioctl_dev_t dev, u_long cmd, caddr_t data, 218169412Sscottl int flags, ioctl_thread_t proc) 219169412Sscottl{ 220169412Sscottl int ret = EFAULT; 221175942Sscottl struct hpt_iop_hba *hba = hba_from_dev(dev); 222169412Sscottl 223169412Sscottl#if (__FreeBSD_version >= 500000) 224169412Sscottl mtx_lock(&Giant); 225169412Sscottl#endif 226169412Sscottl 227169412Sscottl switch (cmd) { 228169412Sscottl case HPT_DO_IOCONTROL: 229175942Sscottl ret = hba->ops->do_ioctl(hba, 230175942Sscottl (struct hpt_iop_ioctl_param *)data); 231169412Sscottl break; 232169412Sscottl case HPT_SCAN_BUS: 233169412Sscottl ret = hptiop_rescan_bus(hba); 234169412Sscottl break; 235169412Sscottl } 236169412Sscottl 237169412Sscottl#if (__FreeBSD_version >= 500000) 238169412Sscottl mtx_unlock(&Giant); 239169412Sscottl#endif 240169412Sscottl 241169412Sscottl return ret; 242169412Sscottl} 243169412Sscottl 244175942Sscottlstatic u_int64_t hptiop_mv_outbound_read(struct hpt_iop_hba *hba) 245169412Sscottl{ 246175942Sscottl u_int64_t p; 247175942Sscottl u_int32_t outbound_tail = BUS_SPACE_RD4_MV2(outbound_tail); 248175942Sscottl u_int32_t outbound_head = BUS_SPACE_RD4_MV2(outbound_head); 249175942Sscottl 250175942Sscottl if (outbound_tail != outbound_head) { 251175942Sscottl bus_space_read_region_4(hba->bar2t, hba->bar2h, 252175942Sscottl offsetof(struct hpt_iopmu_mv, 253175942Sscottl outbound_q[outbound_tail]), 254175942Sscottl (u_int32_t *)&p, 2); 255175942Sscottl 256175942Sscottl outbound_tail++; 257175942Sscottl 258175942Sscottl if (outbound_tail == MVIOP_QUEUE_LEN) 259175942Sscottl outbound_tail = 0; 260175942Sscottl 261175942Sscottl BUS_SPACE_WRT4_MV2(outbound_tail, outbound_tail); 262175942Sscottl return p; 263175942Sscottl } else 264175942Sscottl return 0; 265169412Sscottl} 266169412Sscottl 267175942Sscottlstatic void hptiop_mv_inbound_write(u_int64_t p, struct hpt_iop_hba *hba) 268169412Sscottl{ 269175942Sscottl u_int32_t inbound_head = BUS_SPACE_RD4_MV2(inbound_head); 270175942Sscottl u_int32_t head = inbound_head + 1; 271175942Sscottl 272175942Sscottl if (head == MVIOP_QUEUE_LEN) 273175942Sscottl head = 0; 274175942Sscottl 275175942Sscottl bus_space_write_region_4(hba->bar2t, hba->bar2h, 276175942Sscottl offsetof(struct hpt_iopmu_mv, inbound_q[inbound_head]), 277175942Sscottl (u_int32_t *)&p, 2); 278175942Sscottl BUS_SPACE_WRT4_MV2(inbound_head, head); 279175942Sscottl BUS_SPACE_WRT4_MV0(inbound_doorbell, MVIOP_MU_INBOUND_INT_POSTQUEUE); 280169412Sscottl} 281169412Sscottl 282175942Sscottlstatic void hptiop_post_msg_itl(struct hpt_iop_hba *hba, u_int32_t msg) 283169412Sscottl{ 284175942Sscottl BUS_SPACE_WRT4_ITL(inbound_msgaddr0, msg); 285175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 286169412Sscottl} 287169412Sscottl 288175942Sscottlstatic void hptiop_post_msg_mv(struct hpt_iop_hba *hba, u_int32_t msg) 289169412Sscottl{ 290175942Sscottl 291175942Sscottl BUS_SPACE_WRT4_MV2(inbound_msg, msg); 292175942Sscottl BUS_SPACE_WRT4_MV0(inbound_doorbell, MVIOP_MU_INBOUND_INT_MSG); 293175942Sscottl 294175942Sscottl BUS_SPACE_RD4_MV0(outbound_intmask); 295169412Sscottl} 296169412Sscottl 297175942Sscottlstatic int hptiop_wait_ready_itl(struct hpt_iop_hba * hba, u_int32_t millisec) 298169412Sscottl{ 299169412Sscottl u_int32_t req=0; 300169412Sscottl int i; 301169412Sscottl 302169412Sscottl for (i = 0; i < millisec; i++) { 303175942Sscottl req = BUS_SPACE_RD4_ITL(inbound_queue); 304169412Sscottl if (req != IOPMU_QUEUE_EMPTY) 305169412Sscottl break; 306169412Sscottl DELAY(1000); 307169412Sscottl } 308169412Sscottl 309169412Sscottl if (req!=IOPMU_QUEUE_EMPTY) { 310175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req); 311175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 312169412Sscottl return 0; 313169412Sscottl } 314169412Sscottl 315169412Sscottl return -1; 316169412Sscottl} 317169412Sscottl 318175942Sscottlstatic int hptiop_wait_ready_mv(struct hpt_iop_hba * hba, u_int32_t millisec) 319169412Sscottl{ 320175942Sscottl if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec)) 321175942Sscottl return -1; 322175942Sscottl 323175942Sscottl return 0; 324175942Sscottl} 325175942Sscottl 326175942Sscottlstatic void hptiop_request_callback_itl(struct hpt_iop_hba * hba, 327175942Sscottl u_int32_t index) 328175942Sscottl{ 329175942Sscottl struct hpt_iop_srb *srb; 330175942Sscottl struct hpt_iop_request_scsi_command *req=0; 331175942Sscottl union ccb *ccb; 332175942Sscottl u_int8_t *cdb; 333175942Sscottl u_int32_t result, temp, dxfer; 334175942Sscottl u_int64_t temp64; 335175942Sscottl 336175942Sscottl if (index & IOPMU_QUEUE_MASK_HOST_BITS) { /*host req*/ 337175942Sscottl if (hba->firmware_version > 0x01020000 || 338175942Sscottl hba->interface_version > 0x01020000) { 339175942Sscottl srb = hba->srb[index & ~(u_int32_t) 340175942Sscottl (IOPMU_QUEUE_ADDR_HOST_BIT 341175942Sscottl | IOPMU_QUEUE_REQUEST_RESULT_BIT)]; 342175942Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 343175942Sscottl if (index & IOPMU_QUEUE_REQUEST_RESULT_BIT) 344175942Sscottl result = IOP_RESULT_SUCCESS; 345175942Sscottl else 346175942Sscottl result = req->header.result; 347175942Sscottl } else { 348175942Sscottl srb = hba->srb[index & 349175942Sscottl ~(u_int32_t)IOPMU_QUEUE_ADDR_HOST_BIT]; 350175942Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 351175942Sscottl result = req->header.result; 352175942Sscottl } 353175942Sscottl dxfer = req->dataxfer_length; 354175942Sscottl goto srb_complete; 355175942Sscottl } 356175942Sscottl 357175942Sscottl /*iop req*/ 358175942Sscottl temp = bus_space_read_4(hba->bar0t, hba->bar0h, index + 359175942Sscottl offsetof(struct hpt_iop_request_header, type)); 360175942Sscottl result = bus_space_read_4(hba->bar0t, hba->bar0h, index + 361175942Sscottl offsetof(struct hpt_iop_request_header, result)); 362175942Sscottl switch(temp) { 363175942Sscottl case IOP_REQUEST_TYPE_IOCTL_COMMAND: 364175942Sscottl { 365175942Sscottl temp64 = 0; 366175942Sscottl bus_space_write_region_4(hba->bar0t, hba->bar0h, index + 367175942Sscottl offsetof(struct hpt_iop_request_header, context), 368175942Sscottl (u_int32_t *)&temp64, 2); 369175942Sscottl wakeup((void *)((unsigned long)hba->u.itl.mu + index)); 370175942Sscottl break; 371175942Sscottl } 372175942Sscottl 373175942Sscottl case IOP_REQUEST_TYPE_SCSI_COMMAND: 374175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h, index + 375175942Sscottl offsetof(struct hpt_iop_request_header, context), 376175942Sscottl (u_int32_t *)&temp64, 2); 377175942Sscottl srb = (struct hpt_iop_srb *)(unsigned long)temp64; 378175942Sscottl dxfer = bus_space_read_4(hba->bar0t, hba->bar0h, 379175942Sscottl index + offsetof(struct hpt_iop_request_scsi_command, 380175942Sscottl dataxfer_length)); 381175942Sscottlsrb_complete: 382175942Sscottl ccb = (union ccb *)srb->ccb; 383175942Sscottl if (ccb->ccb_h.flags & CAM_CDB_POINTER) 384175942Sscottl cdb = ccb->csio.cdb_io.cdb_ptr; 385175942Sscottl else 386175942Sscottl cdb = ccb->csio.cdb_io.cdb_bytes; 387175942Sscottl 388175942Sscottl if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */ 389175942Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 390175942Sscottl goto scsi_done; 391175942Sscottl } 392175942Sscottl 393175942Sscottl switch (result) { 394175942Sscottl case IOP_RESULT_SUCCESS: 395175942Sscottl switch (ccb->ccb_h.flags & CAM_DIR_MASK) { 396175942Sscottl case CAM_DIR_IN: 397175942Sscottl bus_dmamap_sync(hba->io_dmat, 398175942Sscottl srb->dma_map, BUS_DMASYNC_POSTREAD); 399175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 400175942Sscottl break; 401175942Sscottl case CAM_DIR_OUT: 402175942Sscottl bus_dmamap_sync(hba->io_dmat, 403175942Sscottl srb->dma_map, BUS_DMASYNC_POSTWRITE); 404175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 405175942Sscottl break; 406175942Sscottl } 407175942Sscottl 408175942Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 409175942Sscottl break; 410175942Sscottl 411175942Sscottl case IOP_RESULT_BAD_TARGET: 412175942Sscottl ccb->ccb_h.status = CAM_DEV_NOT_THERE; 413175942Sscottl break; 414175942Sscottl case IOP_RESULT_BUSY: 415175942Sscottl ccb->ccb_h.status = CAM_BUSY; 416175942Sscottl break; 417175942Sscottl case IOP_RESULT_INVALID_REQUEST: 418175942Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 419175942Sscottl break; 420175942Sscottl case IOP_RESULT_FAIL: 421175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 422175942Sscottl break; 423175942Sscottl case IOP_RESULT_RESET: 424175942Sscottl ccb->ccb_h.status = CAM_BUSY; 425175942Sscottl break; 426175942Sscottl case IOP_RESULT_CHECK_CONDITION: 427226350Smarius memset(&ccb->csio.sense_data, 0, 428226350Smarius sizeof(ccb->csio.sense_data)); 429226350Smarius if (dxfer < ccb->csio.sense_len) 430226350Smarius ccb->csio.sense_resid = ccb->csio.sense_len - 431226350Smarius dxfer; 432226350Smarius else 433226350Smarius ccb->csio.sense_resid = 0; 434175942Sscottl if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) {/*iop*/ 435175942Sscottl bus_space_read_region_1(hba->bar0t, hba->bar0h, 436175942Sscottl index + offsetof(struct hpt_iop_request_scsi_command, 437175942Sscottl sg_list), (u_int8_t *)&ccb->csio.sense_data, 438175942Sscottl MIN(dxfer, sizeof(ccb->csio.sense_data))); 439175942Sscottl } else { 440175942Sscottl memcpy(&ccb->csio.sense_data, &req->sg_list, 441175942Sscottl MIN(dxfer, sizeof(ccb->csio.sense_data))); 442175942Sscottl } 443175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 444175942Sscottl ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 445175942Sscottl ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 446175942Sscottl break; 447175942Sscottl default: 448175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 449175942Sscottl break; 450175942Sscottl } 451175942Sscottlscsi_done: 452175942Sscottl if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) 453175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, index); 454175942Sscottl 455175942Sscottl ccb->csio.resid = ccb->csio.dxfer_len - dxfer; 456175942Sscottl 457175942Sscottl hptiop_free_srb(hba, srb); 458175942Sscottl xpt_done(ccb); 459175942Sscottl break; 460175942Sscottl } 461175942Sscottl} 462175942Sscottl 463175942Sscottlstatic void hptiop_drain_outbound_queue_itl(struct hpt_iop_hba *hba) 464175942Sscottl{ 465175942Sscottl u_int32_t req, temp; 466175942Sscottl 467175942Sscottl while ((req = BUS_SPACE_RD4_ITL(outbound_queue)) !=IOPMU_QUEUE_EMPTY) { 468175942Sscottl if (req & IOPMU_QUEUE_MASK_HOST_BITS) 469175942Sscottl hptiop_request_callback_itl(hba, req); 470175942Sscottl else { 471175942Sscottl struct hpt_iop_request_header *p; 472175942Sscottl 473175942Sscottl p = (struct hpt_iop_request_header *) 474175942Sscottl ((char *)hba->u.itl.mu + req); 475175942Sscottl temp = bus_space_read_4(hba->bar0t, 476175942Sscottl hba->bar0h,req + 477175942Sscottl offsetof(struct hpt_iop_request_header, 478175942Sscottl flags)); 479175942Sscottl if (temp & IOP_REQUEST_FLAG_SYNC_REQUEST) { 480175942Sscottl u_int64_t temp64; 481175942Sscottl bus_space_read_region_4(hba->bar0t, 482175942Sscottl hba->bar0h,req + 483175942Sscottl offsetof(struct hpt_iop_request_header, 484175942Sscottl context), 485175942Sscottl (u_int32_t *)&temp64, 2); 486175942Sscottl if (temp64) { 487175942Sscottl hptiop_request_callback_itl(hba, req); 488175942Sscottl } else { 489175942Sscottl temp64 = 1; 490175942Sscottl bus_space_write_region_4(hba->bar0t, 491175942Sscottl hba->bar0h,req + 492175942Sscottl offsetof(struct hpt_iop_request_header, 493175942Sscottl context), 494175942Sscottl (u_int32_t *)&temp64, 2); 495175942Sscottl } 496175942Sscottl } else 497175942Sscottl hptiop_request_callback_itl(hba, req); 498175942Sscottl } 499175942Sscottl } 500175942Sscottl} 501175942Sscottl 502175942Sscottlstatic int hptiop_intr_itl(struct hpt_iop_hba * hba) 503175942Sscottl{ 504169412Sscottl u_int32_t status; 505169412Sscottl int ret = 0; 506169412Sscottl 507175942Sscottl status = BUS_SPACE_RD4_ITL(outbound_intstatus); 508169412Sscottl 509169412Sscottl if (status & IOPMU_OUTBOUND_INT_MSG0) { 510175942Sscottl u_int32_t msg = BUS_SPACE_RD4_ITL(outbound_msgaddr0); 511175942Sscottl KdPrint(("hptiop: received outbound msg %x\n", msg)); 512175942Sscottl BUS_SPACE_WRT4_ITL(outbound_intstatus, IOPMU_OUTBOUND_INT_MSG0); 513175942Sscottl hptiop_os_message_callback(hba, msg); 514169412Sscottl ret = 1; 515169412Sscottl } 516169412Sscottl 517169412Sscottl if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) { 518175942Sscottl hptiop_drain_outbound_queue_itl(hba); 519175942Sscottl ret = 1; 520175942Sscottl } 521175942Sscottl 522175942Sscottl return ret; 523175942Sscottl} 524175942Sscottl 525175942Sscottlstatic void hptiop_request_callback_mv(struct hpt_iop_hba * hba, 526175942Sscottl u_int64_t _tag) 527175942Sscottl{ 528175942Sscottl u_int32_t context = (u_int32_t)_tag; 529175942Sscottl 530175942Sscottl if (context & MVIOP_CMD_TYPE_SCSI) { 531175942Sscottl struct hpt_iop_srb *srb; 532175942Sscottl struct hpt_iop_request_scsi_command *req; 533175942Sscottl union ccb *ccb; 534175942Sscottl u_int8_t *cdb; 535175942Sscottl 536175942Sscottl srb = hba->srb[context >> MVIOP_REQUEST_NUMBER_START_BIT]; 537175942Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 538175942Sscottl ccb = (union ccb *)srb->ccb; 539175942Sscottl if (ccb->ccb_h.flags & CAM_CDB_POINTER) 540175942Sscottl cdb = ccb->csio.cdb_io.cdb_ptr; 541175942Sscottl else 542175942Sscottl cdb = ccb->csio.cdb_io.cdb_bytes; 543175942Sscottl 544175942Sscottl if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */ 545175942Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 546175942Sscottl goto scsi_done; 547175942Sscottl } 548175942Sscottl if (context & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT) 549175942Sscottl req->header.result = IOP_RESULT_SUCCESS; 550175942Sscottl 551175942Sscottl switch (req->header.result) { 552175942Sscottl case IOP_RESULT_SUCCESS: 553175942Sscottl switch (ccb->ccb_h.flags & CAM_DIR_MASK) { 554175942Sscottl case CAM_DIR_IN: 555175942Sscottl bus_dmamap_sync(hba->io_dmat, 556175942Sscottl srb->dma_map, BUS_DMASYNC_POSTREAD); 557175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 558175942Sscottl break; 559175942Sscottl case CAM_DIR_OUT: 560175942Sscottl bus_dmamap_sync(hba->io_dmat, 561175942Sscottl srb->dma_map, BUS_DMASYNC_POSTWRITE); 562175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 563175942Sscottl break; 564169412Sscottl } 565175942Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 566175942Sscottl break; 567175942Sscottl case IOP_RESULT_BAD_TARGET: 568175942Sscottl ccb->ccb_h.status = CAM_DEV_NOT_THERE; 569175942Sscottl break; 570175942Sscottl case IOP_RESULT_BUSY: 571175942Sscottl ccb->ccb_h.status = CAM_BUSY; 572175942Sscottl break; 573175942Sscottl case IOP_RESULT_INVALID_REQUEST: 574175942Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 575175942Sscottl break; 576175942Sscottl case IOP_RESULT_FAIL: 577175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 578175942Sscottl break; 579175942Sscottl case IOP_RESULT_RESET: 580175942Sscottl ccb->ccb_h.status = CAM_BUSY; 581175942Sscottl break; 582175942Sscottl case IOP_RESULT_CHECK_CONDITION: 583226350Smarius memset(&ccb->csio.sense_data, 0, 584226350Smarius sizeof(ccb->csio.sense_data)); 585226350Smarius if (req->dataxfer_length < ccb->csio.sense_len) 586226350Smarius ccb->csio.sense_resid = ccb->csio.sense_len - 587226350Smarius req->dataxfer_length; 588226350Smarius else 589226350Smarius ccb->csio.sense_resid = 0; 590175942Sscottl memcpy(&ccb->csio.sense_data, &req->sg_list, 591175942Sscottl MIN(req->dataxfer_length, sizeof(ccb->csio.sense_data))); 592175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 593175942Sscottl ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 594175942Sscottl ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 595175942Sscottl break; 596175942Sscottl default: 597175942Sscottl ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 598175942Sscottl break; 599169412Sscottl } 600175942Sscottlscsi_done: 601175942Sscottl ccb->csio.resid = ccb->csio.dxfer_len - req->dataxfer_length; 602175942Sscottl 603175942Sscottl hptiop_free_srb(hba, srb); 604175942Sscottl xpt_done(ccb); 605175942Sscottl } else if (context & MVIOP_CMD_TYPE_IOCTL) { 606175942Sscottl struct hpt_iop_request_ioctl_command *req = hba->ctlcfg_ptr; 607175942Sscottl if (context & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT) 608175942Sscottl hba->config_done = 1; 609175942Sscottl else 610175942Sscottl hba->config_done = -1; 611175942Sscottl wakeup(req); 612175942Sscottl } else if (context & 613175942Sscottl (MVIOP_CMD_TYPE_SET_CONFIG | 614175942Sscottl MVIOP_CMD_TYPE_GET_CONFIG)) 615175942Sscottl hba->config_done = 1; 616175942Sscottl else { 617175942Sscottl device_printf(hba->pcidev, "wrong callback type\n"); 618175942Sscottl } 619175942Sscottl} 620175942Sscottl 621175942Sscottlstatic void hptiop_drain_outbound_queue_mv(struct hpt_iop_hba * hba) 622175942Sscottl{ 623175942Sscottl u_int64_t req; 624175942Sscottl 625175942Sscottl while ((req = hptiop_mv_outbound_read(hba))) { 626175942Sscottl if (req & MVIOP_MU_QUEUE_ADDR_HOST_BIT) { 627175942Sscottl if (req & MVIOP_MU_QUEUE_REQUEST_RETURN_CONTEXT) { 628175942Sscottl hptiop_request_callback_mv(hba, req); 629175942Sscottl } 630175942Sscottl } 631175942Sscottl } 632175942Sscottl} 633175942Sscottl 634175942Sscottlstatic int hptiop_intr_mv(struct hpt_iop_hba * hba) 635175942Sscottl{ 636175942Sscottl u_int32_t status; 637175942Sscottl int ret = 0; 638175942Sscottl 639175942Sscottl status = BUS_SPACE_RD4_MV0(outbound_doorbell); 640175942Sscottl 641175942Sscottl if (status) 642175942Sscottl BUS_SPACE_WRT4_MV0(outbound_doorbell, ~status); 643175942Sscottl 644175942Sscottl if (status & MVIOP_MU_OUTBOUND_INT_MSG) { 645175942Sscottl u_int32_t msg = BUS_SPACE_RD4_MV2(outbound_msg); 646175942Sscottl KdPrint(("hptiop: received outbound msg %x\n", msg)); 647175942Sscottl hptiop_os_message_callback(hba, msg); 648169412Sscottl ret = 1; 649169412Sscottl } 650175942Sscottl 651175942Sscottl if (status & MVIOP_MU_OUTBOUND_INT_POSTQUEUE) { 652175942Sscottl hptiop_drain_outbound_queue_mv(hba); 653175942Sscottl ret = 1; 654175942Sscottl } 655175942Sscottl 656169412Sscottl return ret; 657169412Sscottl} 658169412Sscottl 659175942Sscottlstatic int hptiop_send_sync_request_itl(struct hpt_iop_hba * hba, 660175942Sscottl u_int32_t req32, u_int32_t millisec) 661169412Sscottl{ 662169412Sscottl u_int32_t i; 663175942Sscottl u_int64_t temp64; 664169412Sscottl 665175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue, req32); 666175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 667169412Sscottl 668169412Sscottl for (i = 0; i < millisec; i++) { 669175942Sscottl hptiop_intr_itl(hba); 670175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h, req32 + 671175942Sscottl offsetof(struct hpt_iop_request_header, context), 672175942Sscottl (u_int32_t *)&temp64, 2); 673175942Sscottl if (temp64) 674169412Sscottl return 0; 675169412Sscottl DELAY(1000); 676169412Sscottl } 677169412Sscottl 678169412Sscottl return -1; 679169412Sscottl} 680169412Sscottl 681175942Sscottlstatic int hptiop_send_sync_request_mv(struct hpt_iop_hba *hba, 682175942Sscottl void *req, u_int32_t millisec) 683169412Sscottl{ 684169412Sscottl u_int32_t i; 685175942Sscottl u_int64_t phy_addr; 686175942Sscottl hba->config_done = 0; 687169412Sscottl 688175942Sscottl phy_addr = hba->ctlcfgcmd_phy | 689175942Sscottl (u_int64_t)MVIOP_MU_QUEUE_ADDR_HOST_BIT; 690175942Sscottl ((struct hpt_iop_request_get_config *)req)->header.flags |= 691175942Sscottl IOP_REQUEST_FLAG_SYNC_REQUEST | 692175942Sscottl IOP_REQUEST_FLAG_OUTPUT_CONTEXT; 693175942Sscottl hptiop_mv_inbound_write(phy_addr, hba); 694175942Sscottl BUS_SPACE_RD4_MV0(outbound_intmask); 695169412Sscottl 696175942Sscottl for (i = 0; i < millisec; i++) { 697175942Sscottl hptiop_intr_mv(hba); 698175942Sscottl if (hba->config_done) 699175942Sscottl return 0; 700175942Sscottl DELAY(1000); 701175942Sscottl } 702175942Sscottl return -1; 703175942Sscottl} 704169412Sscottl 705175942Sscottlstatic int hptiop_send_sync_msg(struct hpt_iop_hba *hba, 706175942Sscottl u_int32_t msg, u_int32_t millisec) 707175942Sscottl{ 708175942Sscottl u_int32_t i; 709169412Sscottl 710175942Sscottl hba->msg_done = 0; 711175942Sscottl hba->ops->post_msg(hba, msg); 712175942Sscottl 713175942Sscottl for (i=0; i<millisec; i++) { 714175942Sscottl hba->ops->iop_intr(hba); 715175942Sscottl if (hba->msg_done) 716169412Sscottl break; 717169412Sscottl DELAY(1000); 718169412Sscottl } 719169412Sscottl 720175942Sscottl return hba->msg_done? 0 : -1; 721169412Sscottl} 722169412Sscottl 723175942Sscottlstatic int hptiop_get_config_itl(struct hpt_iop_hba * hba, 724175942Sscottl struct hpt_iop_request_get_config * config) 725169412Sscottl{ 726175942Sscottl u_int32_t req32; 727169412Sscottl 728175942Sscottl config->header.size = sizeof(struct hpt_iop_request_get_config); 729175942Sscottl config->header.type = IOP_REQUEST_TYPE_GET_CONFIG; 730175942Sscottl config->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST; 731175942Sscottl config->header.result = IOP_RESULT_PENDING; 732175942Sscottl config->header.context = 0; 733175942Sscottl 734175942Sscottl req32 = BUS_SPACE_RD4_ITL(inbound_queue); 735175942Sscottl if (req32 == IOPMU_QUEUE_EMPTY) 736169412Sscottl return -1; 737169412Sscottl 738175942Sscottl bus_space_write_region_4(hba->bar0t, hba->bar0h, 739175942Sscottl req32, (u_int32_t *)config, 740175942Sscottl sizeof(struct hpt_iop_request_header) >> 2); 741175942Sscottl 742175942Sscottl if (hptiop_send_sync_request_itl(hba, req32, 20000)) { 743175942Sscottl KdPrint(("hptiop: get config send cmd failed")); 744175942Sscottl return -1; 745175942Sscottl } 746175942Sscottl 747175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h, 748175942Sscottl req32, (u_int32_t *)config, 749175942Sscottl sizeof(struct hpt_iop_request_get_config) >> 2); 750175942Sscottl 751175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req32); 752175942Sscottl 753175942Sscottl return 0; 754175942Sscottl} 755175942Sscottl 756175942Sscottlstatic int hptiop_get_config_mv(struct hpt_iop_hba * hba, 757175942Sscottl struct hpt_iop_request_get_config * config) 758175942Sscottl{ 759175942Sscottl struct hpt_iop_request_get_config *req; 760175942Sscottl 761175942Sscottl if (!(req = hba->ctlcfg_ptr)) 762175942Sscottl return -1; 763175942Sscottl 764169412Sscottl req->header.flags = 0; 765169412Sscottl req->header.type = IOP_REQUEST_TYPE_GET_CONFIG; 766169412Sscottl req->header.size = sizeof(struct hpt_iop_request_get_config); 767169412Sscottl req->header.result = IOP_RESULT_PENDING; 768175942Sscottl req->header.context = MVIOP_CMD_TYPE_GET_CONFIG; 769169412Sscottl 770175942Sscottl if (hptiop_send_sync_request_mv(hba, req, 20000)) { 771175942Sscottl KdPrint(("hptiop: get config send cmd failed")); 772169412Sscottl return -1; 773169412Sscottl } 774169412Sscottl 775169412Sscottl *config = *req; 776169412Sscottl return 0; 777169412Sscottl} 778169412Sscottl 779175942Sscottlstatic int hptiop_set_config_itl(struct hpt_iop_hba *hba, 780175942Sscottl struct hpt_iop_request_set_config *config) 781169412Sscottl{ 782169412Sscottl u_int32_t req32; 783169412Sscottl 784175942Sscottl req32 = BUS_SPACE_RD4_ITL(inbound_queue); 785175942Sscottl 786169412Sscottl if (req32 == IOPMU_QUEUE_EMPTY) 787169412Sscottl return -1; 788169412Sscottl 789175942Sscottl config->header.size = sizeof(struct hpt_iop_request_set_config); 790175942Sscottl config->header.type = IOP_REQUEST_TYPE_SET_CONFIG; 791175942Sscottl config->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST; 792175942Sscottl config->header.result = IOP_RESULT_PENDING; 793175942Sscottl config->header.context = 0; 794175942Sscottl 795175942Sscottl bus_space_write_region_4(hba->bar0t, hba->bar0h, req32, 796175942Sscottl (u_int32_t *)config, 797175942Sscottl sizeof(struct hpt_iop_request_set_config) >> 2); 798175942Sscottl 799175942Sscottl if (hptiop_send_sync_request_itl(hba, req32, 20000)) { 800175942Sscottl KdPrint(("hptiop: set config send cmd failed")); 801175942Sscottl return -1; 802175942Sscottl } 803175942Sscottl 804175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req32); 805175942Sscottl 806175942Sscottl return 0; 807175942Sscottl} 808175942Sscottl 809175942Sscottlstatic int hptiop_set_config_mv(struct hpt_iop_hba *hba, 810175942Sscottl struct hpt_iop_request_set_config *config) 811175942Sscottl{ 812175942Sscottl struct hpt_iop_request_set_config *req; 813175942Sscottl 814175942Sscottl if (!(req = hba->ctlcfg_ptr)) 815175942Sscottl return -1; 816175942Sscottl 817169412Sscottl memcpy((u_int8_t *)req + sizeof(struct hpt_iop_request_header), 818169412Sscottl (u_int8_t *)config + sizeof(struct hpt_iop_request_header), 819175942Sscottl sizeof(struct hpt_iop_request_set_config) - 820175942Sscottl sizeof(struct hpt_iop_request_header)); 821175942Sscottl 822169412Sscottl req->header.flags = 0; 823169412Sscottl req->header.type = IOP_REQUEST_TYPE_SET_CONFIG; 824169412Sscottl req->header.size = sizeof(struct hpt_iop_request_set_config); 825169412Sscottl req->header.result = IOP_RESULT_PENDING; 826175942Sscottl req->header.context = MVIOP_CMD_TYPE_SET_CONFIG; 827169412Sscottl 828175942Sscottl if (hptiop_send_sync_request_mv(hba, req, 20000)) { 829175942Sscottl KdPrint(("hptiop: set config send cmd failed")); 830169412Sscottl return -1; 831169412Sscottl } 832169412Sscottl 833169412Sscottl return 0; 834169412Sscottl} 835169412Sscottl 836175942Sscottlstatic int hptiop_post_ioctl_command_itl(struct hpt_iop_hba *hba, 837175942Sscottl u_int32_t req32, 838175942Sscottl struct hpt_iop_ioctl_param *pParams) 839169412Sscottl{ 840175942Sscottl u_int64_t temp64; 841175942Sscottl struct hpt_iop_request_ioctl_command req; 842169412Sscottl 843175942Sscottl if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) > 844175942Sscottl (hba->max_request_size - 845175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf))) { 846175942Sscottl device_printf(hba->pcidev, "request size beyond max value"); 847175942Sscottl return -1; 848175942Sscottl } 849175942Sscottl 850175942Sscottl req.header.size = offsetof(struct hpt_iop_request_ioctl_command, buf) 851175942Sscottl + pParams->nInBufferSize; 852175942Sscottl req.header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND; 853175942Sscottl req.header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST; 854175942Sscottl req.header.result = IOP_RESULT_PENDING; 855175942Sscottl req.header.context = req32 + (u_int64_t)(unsigned long)hba->u.itl.mu; 856175942Sscottl req.ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode); 857175942Sscottl req.inbuf_size = pParams->nInBufferSize; 858175942Sscottl req.outbuf_size = pParams->nOutBufferSize; 859175942Sscottl req.bytes_returned = 0; 860175942Sscottl 861175942Sscottl bus_space_write_region_4(hba->bar0t, hba->bar0h, req32, (u_int32_t *)&req, 862175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf)>>2); 863175942Sscottl 864175942Sscottl hptiop_lock_adapter(hba); 865175942Sscottl 866175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue, req32); 867175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 868175942Sscottl 869175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h, req32 + 870175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, header.context), 871175942Sscottl (u_int32_t *)&temp64, 2); 872175942Sscottl while (temp64) { 873175942Sscottl if (hptiop_sleep(hba, (void *)((unsigned long)hba->u.itl.mu + req32), 874175942Sscottl PPAUSE, "hptctl", HPT_OSM_TIMEOUT)==0) 875175942Sscottl break; 876175942Sscottl hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000); 877175942Sscottl bus_space_read_region_4(hba->bar0t, hba->bar0h,req32 + 878175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, 879175942Sscottl header.context), 880175942Sscottl (u_int32_t *)&temp64, 2); 881175942Sscottl } 882175942Sscottl 883175942Sscottl hptiop_unlock_adapter(hba); 884175942Sscottl return 0; 885175942Sscottl} 886175942Sscottl 887175942Sscottlstatic int hptiop_bus_space_copyin(struct hpt_iop_hba *hba, u_int32_t bus, void *user, int size) 888175942Sscottl{ 889175942Sscottl unsigned char byte; 890175942Sscottl int i; 891175942Sscottl 892175942Sscottl for (i=0; i<size; i++) { 893175942Sscottl if (copyin((u_int8_t *)user + i, &byte, 1)) 894175942Sscottl return -1; 895175942Sscottl bus_space_write_1(hba->bar0t, hba->bar0h, bus + i, byte); 896175942Sscottl } 897175942Sscottl 898175942Sscottl return 0; 899175942Sscottl} 900175942Sscottl 901175942Sscottlstatic int hptiop_bus_space_copyout(struct hpt_iop_hba *hba, u_int32_t bus, void *user, int size) 902175942Sscottl{ 903175942Sscottl unsigned char byte; 904175942Sscottl int i; 905175942Sscottl 906175942Sscottl for (i=0; i<size; i++) { 907175942Sscottl byte = bus_space_read_1(hba->bar0t, hba->bar0h, bus + i); 908175942Sscottl if (copyout(&byte, (u_int8_t *)user + i, 1)) 909175942Sscottl return -1; 910175942Sscottl } 911175942Sscottl 912175942Sscottl return 0; 913175942Sscottl} 914175942Sscottl 915175942Sscottlstatic int hptiop_do_ioctl_itl(struct hpt_iop_hba *hba, 916175942Sscottl struct hpt_iop_ioctl_param * pParams) 917175942Sscottl{ 918175942Sscottl u_int32_t req32; 919175942Sscottl u_int32_t result; 920175942Sscottl 921169412Sscottl if ((pParams->Magic != HPT_IOCTL_MAGIC) && 922169412Sscottl (pParams->Magic != HPT_IOCTL_MAGIC32)) 923169412Sscottl return EFAULT; 924175942Sscottl 925175942Sscottl req32 = BUS_SPACE_RD4_ITL(inbound_queue); 926175942Sscottl if (req32 == IOPMU_QUEUE_EMPTY) 927169412Sscottl return EFAULT; 928169412Sscottl 929169412Sscottl if (pParams->nInBufferSize) 930175942Sscottl if (hptiop_bus_space_copyin(hba, req32 + 931175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf), 932175942Sscottl (void *)pParams->lpInBuffer, pParams->nInBufferSize)) 933169412Sscottl goto invalid; 934169412Sscottl 935175942Sscottl if (hptiop_post_ioctl_command_itl(hba, req32, pParams)) 936169412Sscottl goto invalid; 937169412Sscottl 938175942Sscottl result = bus_space_read_4(hba->bar0t, hba->bar0h, req32 + 939175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, 940175942Sscottl header.result)); 941175942Sscottl 942175942Sscottl if (result == IOP_RESULT_SUCCESS) { 943169412Sscottl if (pParams->nOutBufferSize) 944175942Sscottl if (hptiop_bus_space_copyout(hba, req32 + 945175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf) + 946169412Sscottl ((pParams->nInBufferSize + 3) & ~3), 947175942Sscottl (void *)pParams->lpOutBuffer, pParams->nOutBufferSize)) 948169412Sscottl goto invalid; 949169412Sscottl 950175942Sscottl if (pParams->lpBytesReturned) { 951175942Sscottl if (hptiop_bus_space_copyout(hba, req32 + 952175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, bytes_returned), 953175942Sscottl (void *)pParams->lpBytesReturned, sizeof(unsigned long))) 954169412Sscottl goto invalid; 955175942Sscottl } 956175942Sscottl 957175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req32); 958175942Sscottl 959169412Sscottl return 0; 960169412Sscottl } else{ 961169412Sscottlinvalid: 962175942Sscottl BUS_SPACE_WRT4_ITL(outbound_queue, req32); 963175942Sscottl 964169412Sscottl return EFAULT; 965169412Sscottl } 966169412Sscottl} 967169412Sscottl 968175942Sscottlstatic int hptiop_post_ioctl_command_mv(struct hpt_iop_hba *hba, 969175942Sscottl struct hpt_iop_request_ioctl_command *req, 970175942Sscottl struct hpt_iop_ioctl_param *pParams) 971169412Sscottl{ 972175942Sscottl u_int64_t req_phy; 973175942Sscottl int size = 0; 974175942Sscottl 975175942Sscottl if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) > 976175942Sscottl (hba->max_request_size - 977175942Sscottl offsetof(struct hpt_iop_request_ioctl_command, buf))) { 978175942Sscottl device_printf(hba->pcidev, "request size beyond max value"); 979169412Sscottl return -1; 980169412Sscottl } 981169412Sscottl 982169412Sscottl req->ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode); 983169412Sscottl req->inbuf_size = pParams->nInBufferSize; 984169412Sscottl req->outbuf_size = pParams->nOutBufferSize; 985175942Sscottl req->header.size = offsetof(struct hpt_iop_request_ioctl_command, buf) 986175942Sscottl + pParams->nInBufferSize; 987175942Sscottl req->header.context = (u_int64_t)MVIOP_CMD_TYPE_IOCTL; 988169412Sscottl req->header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND; 989169412Sscottl req->header.result = IOP_RESULT_PENDING; 990175942Sscottl req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT; 991175942Sscottl size = req->header.size >> 8; 992175942Sscottl size = size > 3 ? 3 : size; 993175942Sscottl req_phy = hba->ctlcfgcmd_phy | MVIOP_MU_QUEUE_ADDR_HOST_BIT | size; 994175942Sscottl hptiop_mv_inbound_write(req_phy, hba); 995169412Sscottl 996175942Sscottl BUS_SPACE_RD4_MV0(outbound_intmask); 997169412Sscottl 998175942Sscottl while (hba->config_done == 0) { 999175942Sscottl if (hptiop_sleep(hba, req, PPAUSE, 1000175942Sscottl "hptctl", HPT_OSM_TIMEOUT)==0) 1001175942Sscottl continue; 1002175942Sscottl hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000); 1003169412Sscottl } 1004169412Sscottl return 0; 1005169412Sscottl} 1006169412Sscottl 1007175942Sscottlstatic int hptiop_do_ioctl_mv(struct hpt_iop_hba *hba, 1008175942Sscottl struct hpt_iop_ioctl_param *pParams) 1009175942Sscottl{ 1010175942Sscottl struct hpt_iop_request_ioctl_command *req; 1011175942Sscottl 1012175942Sscottl if ((pParams->Magic != HPT_IOCTL_MAGIC) && 1013175942Sscottl (pParams->Magic != HPT_IOCTL_MAGIC32)) 1014175942Sscottl return EFAULT; 1015175942Sscottl 1016175942Sscottl req = (struct hpt_iop_request_ioctl_command *)(hba->ctlcfg_ptr); 1017175942Sscottl hba->config_done = 0; 1018175942Sscottl hptiop_lock_adapter(hba); 1019175942Sscottl if (pParams->nInBufferSize) 1020175942Sscottl if (copyin((void *)pParams->lpInBuffer, 1021175942Sscottl req->buf, pParams->nInBufferSize)) 1022175942Sscottl goto invalid; 1023175942Sscottl if (hptiop_post_ioctl_command_mv(hba, req, pParams)) 1024175942Sscottl goto invalid; 1025175942Sscottl 1026175942Sscottl if (hba->config_done == 1) { 1027175942Sscottl if (pParams->nOutBufferSize) 1028175942Sscottl if (copyout(req->buf + 1029175942Sscottl ((pParams->nInBufferSize + 3) & ~3), 1030175942Sscottl (void *)pParams->lpOutBuffer, 1031175942Sscottl pParams->nOutBufferSize)) 1032175942Sscottl goto invalid; 1033175942Sscottl 1034175942Sscottl if (pParams->lpBytesReturned) 1035175942Sscottl if (copyout(&req->bytes_returned, 1036175942Sscottl (void*)pParams->lpBytesReturned, 1037175942Sscottl sizeof(u_int32_t))) 1038175942Sscottl goto invalid; 1039175942Sscottl hptiop_unlock_adapter(hba); 1040175942Sscottl return 0; 1041175942Sscottl } else{ 1042175942Sscottlinvalid: 1043175942Sscottl hptiop_unlock_adapter(hba); 1044175942Sscottl return EFAULT; 1045175942Sscottl } 1046175942Sscottl} 1047175942Sscottl 1048169412Sscottlstatic int hptiop_rescan_bus(struct hpt_iop_hba * hba) 1049169412Sscottl{ 1050169412Sscottl union ccb *ccb; 1051203108Smav 1052203108Smav if ((ccb = xpt_alloc_ccb()) == NULL) 1053203108Smav return(ENOMEM); 1054203108Smav if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(hba->sim), 1055203108Smav CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 1056203108Smav xpt_free_ccb(ccb); 1057169412Sscottl return(EIO); 1058203108Smav } 1059203108Smav xpt_rescan(ccb); 1060169412Sscottl return(0); 1061169412Sscottl} 1062169412Sscottl 1063169412Sscottlstatic bus_dmamap_callback_t hptiop_map_srb; 1064169412Sscottlstatic bus_dmamap_callback_t hptiop_post_scsi_command; 1065175942Sscottlstatic bus_dmamap_callback_t hptiop_mv_map_ctlcfg; 1066169412Sscottl 1067175942Sscottlstatic int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba) 1068175942Sscottl{ 1069175942Sscottl hba->bar0_rid = 0x10; 1070175942Sscottl hba->bar0_res = bus_alloc_resource_any(hba->pcidev, 1071175942Sscottl SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE); 1072175942Sscottl 1073175942Sscottl if (hba->bar0_res == NULL) { 1074175942Sscottl device_printf(hba->pcidev, 1075175942Sscottl "failed to get iop base adrress.\n"); 1076175942Sscottl return -1; 1077175942Sscottl } 1078175942Sscottl hba->bar0t = rman_get_bustag(hba->bar0_res); 1079175942Sscottl hba->bar0h = rman_get_bushandle(hba->bar0_res); 1080175942Sscottl hba->u.itl.mu = (struct hpt_iopmu_itl *) 1081175942Sscottl rman_get_virtual(hba->bar0_res); 1082175942Sscottl 1083175942Sscottl if (!hba->u.itl.mu) { 1084175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1085175942Sscottl hba->bar0_rid, hba->bar0_res); 1086175942Sscottl device_printf(hba->pcidev, "alloc mem res failed\n"); 1087175942Sscottl return -1; 1088175942Sscottl } 1089175942Sscottl 1090175942Sscottl return 0; 1091175942Sscottl} 1092175942Sscottl 1093175942Sscottlstatic int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba) 1094175942Sscottl{ 1095175942Sscottl hba->bar0_rid = 0x10; 1096175942Sscottl hba->bar0_res = bus_alloc_resource_any(hba->pcidev, 1097175942Sscottl SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE); 1098175942Sscottl 1099175942Sscottl if (hba->bar0_res == NULL) { 1100175942Sscottl device_printf(hba->pcidev, "failed to get iop bar0.\n"); 1101175942Sscottl return -1; 1102175942Sscottl } 1103175942Sscottl hba->bar0t = rman_get_bustag(hba->bar0_res); 1104175942Sscottl hba->bar0h = rman_get_bushandle(hba->bar0_res); 1105175942Sscottl hba->u.mv.regs = (struct hpt_iopmv_regs *) 1106175942Sscottl rman_get_virtual(hba->bar0_res); 1107175942Sscottl 1108175942Sscottl if (!hba->u.mv.regs) { 1109175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1110175942Sscottl hba->bar0_rid, hba->bar0_res); 1111175942Sscottl device_printf(hba->pcidev, "alloc bar0 mem res failed\n"); 1112175942Sscottl return -1; 1113175942Sscottl } 1114175942Sscottl 1115175942Sscottl hba->bar2_rid = 0x18; 1116175942Sscottl hba->bar2_res = bus_alloc_resource_any(hba->pcidev, 1117175942Sscottl SYS_RES_MEMORY, &hba->bar2_rid, RF_ACTIVE); 1118175942Sscottl 1119175942Sscottl if (hba->bar2_res == NULL) { 1120175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1121175942Sscottl hba->bar0_rid, hba->bar0_res); 1122175942Sscottl device_printf(hba->pcidev, "failed to get iop bar2.\n"); 1123175942Sscottl return -1; 1124175942Sscottl } 1125175942Sscottl 1126175942Sscottl hba->bar2t = rman_get_bustag(hba->bar2_res); 1127175942Sscottl hba->bar2h = rman_get_bushandle(hba->bar2_res); 1128175942Sscottl hba->u.mv.mu = (struct hpt_iopmu_mv *)rman_get_virtual(hba->bar2_res); 1129175942Sscottl 1130175942Sscottl if (!hba->u.mv.mu) { 1131175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1132175942Sscottl hba->bar0_rid, hba->bar0_res); 1133175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1134175942Sscottl hba->bar2_rid, hba->bar2_res); 1135175942Sscottl device_printf(hba->pcidev, "alloc mem bar2 res failed\n"); 1136175942Sscottl return -1; 1137175942Sscottl } 1138175942Sscottl 1139175942Sscottl return 0; 1140175942Sscottl} 1141175942Sscottl 1142175942Sscottlstatic void hptiop_release_pci_res_itl(struct hpt_iop_hba *hba) 1143175942Sscottl{ 1144175942Sscottl if (hba->bar0_res) 1145175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1146175942Sscottl hba->bar0_rid, hba->bar0_res); 1147175942Sscottl} 1148175942Sscottl 1149175942Sscottlstatic void hptiop_release_pci_res_mv(struct hpt_iop_hba *hba) 1150175942Sscottl{ 1151175942Sscottl if (hba->bar0_res) 1152175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1153175942Sscottl hba->bar0_rid, hba->bar0_res); 1154175942Sscottl if (hba->bar2_res) 1155175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 1156175942Sscottl hba->bar2_rid, hba->bar2_res); 1157175942Sscottl} 1158175942Sscottl 1159175942Sscottlstatic int hptiop_internal_memalloc_mv(struct hpt_iop_hba *hba) 1160175942Sscottl{ 1161175942Sscottl if (bus_dma_tag_create(hba->parent_dmat, 1162175942Sscottl 1, 1163175942Sscottl 0, 1164175942Sscottl BUS_SPACE_MAXADDR_32BIT, 1165175942Sscottl BUS_SPACE_MAXADDR, 1166175942Sscottl NULL, NULL, 1167175942Sscottl 0x800 - 0x8, 1168175942Sscottl 1, 1169175942Sscottl BUS_SPACE_MAXSIZE_32BIT, 1170175942Sscottl BUS_DMA_ALLOCNOW, 1171175942Sscottl#if __FreeBSD_version > 502000 1172175942Sscottl NULL, 1173175942Sscottl NULL, 1174175942Sscottl#endif 1175175942Sscottl &hba->ctlcfg_dmat)) { 1176175942Sscottl device_printf(hba->pcidev, "alloc ctlcfg_dmat failed\n"); 1177175942Sscottl return -1; 1178175942Sscottl } 1179175942Sscottl 1180175942Sscottl if (bus_dmamem_alloc(hba->ctlcfg_dmat, (void **)&hba->ctlcfg_ptr, 1181175942Sscottl#if __FreeBSD_version>501000 1182175942Sscottl BUS_DMA_WAITOK | BUS_DMA_COHERENT, 1183175942Sscottl#else 1184175942Sscottl BUS_DMA_WAITOK, 1185175942Sscottl#endif 1186175942Sscottl &hba->ctlcfg_dmamap) != 0) { 1187175942Sscottl device_printf(hba->pcidev, 1188175942Sscottl "bus_dmamem_alloc failed!\n"); 1189175942Sscottl bus_dma_tag_destroy(hba->ctlcfg_dmat); 1190175942Sscottl return -1; 1191175942Sscottl } 1192175942Sscottl 1193175942Sscottl if (bus_dmamap_load(hba->ctlcfg_dmat, 1194175942Sscottl hba->ctlcfg_dmamap, hba->ctlcfg_ptr, 1195175942Sscottl MVIOP_IOCTLCFG_SIZE, 1196175942Sscottl hptiop_mv_map_ctlcfg, hba, 0)) { 1197175942Sscottl device_printf(hba->pcidev, "bus_dmamap_load failed!\n"); 1198175942Sscottl if (hba->ctlcfg_dmat) 1199175942Sscottl bus_dmamem_free(hba->ctlcfg_dmat, 1200175942Sscottl hba->ctlcfg_ptr, hba->ctlcfg_dmamap); 1201175942Sscottl bus_dma_tag_destroy(hba->ctlcfg_dmat); 1202175942Sscottl return -1; 1203175942Sscottl } 1204175942Sscottl 1205175942Sscottl return 0; 1206175942Sscottl} 1207175942Sscottl 1208175942Sscottlstatic int hptiop_internal_memfree_mv(struct hpt_iop_hba *hba) 1209175942Sscottl{ 1210175942Sscottl if (hba->ctlcfg_dmat) { 1211175942Sscottl bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap); 1212175942Sscottl bus_dmamem_free(hba->ctlcfg_dmat, 1213175942Sscottl hba->ctlcfg_ptr, hba->ctlcfg_dmamap); 1214175942Sscottl bus_dma_tag_destroy(hba->ctlcfg_dmat); 1215175942Sscottl } 1216175942Sscottl 1217175942Sscottl return 0; 1218175942Sscottl} 1219175942Sscottl 1220169412Sscottl/* 1221169412Sscottl * CAM driver interface 1222169412Sscottl */ 1223169412Sscottlstatic device_method_t driver_methods[] = { 1224169412Sscottl /* Device interface */ 1225169412Sscottl DEVMETHOD(device_probe, hptiop_probe), 1226169412Sscottl DEVMETHOD(device_attach, hptiop_attach), 1227169412Sscottl DEVMETHOD(device_detach, hptiop_detach), 1228169412Sscottl DEVMETHOD(device_shutdown, hptiop_shutdown), 1229169412Sscottl { 0, 0 } 1230169412Sscottl}; 1231169412Sscottl 1232175942Sscottlstatic struct hptiop_adapter_ops hptiop_itl_ops = { 1233175942Sscottl .iop_wait_ready = hptiop_wait_ready_itl, 1234175942Sscottl .internal_memalloc = 0, 1235175942Sscottl .internal_memfree = 0, 1236175942Sscottl .alloc_pci_res = hptiop_alloc_pci_res_itl, 1237175942Sscottl .release_pci_res = hptiop_release_pci_res_itl, 1238175942Sscottl .enable_intr = hptiop_enable_intr_itl, 1239175942Sscottl .disable_intr = hptiop_disable_intr_itl, 1240175942Sscottl .get_config = hptiop_get_config_itl, 1241175942Sscottl .set_config = hptiop_set_config_itl, 1242175942Sscottl .iop_intr = hptiop_intr_itl, 1243175942Sscottl .post_msg = hptiop_post_msg_itl, 1244175942Sscottl .post_req = hptiop_post_req_itl, 1245175942Sscottl .do_ioctl = hptiop_do_ioctl_itl, 1246175942Sscottl}; 1247175942Sscottl 1248175942Sscottlstatic struct hptiop_adapter_ops hptiop_mv_ops = { 1249175942Sscottl .iop_wait_ready = hptiop_wait_ready_mv, 1250175942Sscottl .internal_memalloc = hptiop_internal_memalloc_mv, 1251175942Sscottl .internal_memfree = hptiop_internal_memfree_mv, 1252175942Sscottl .alloc_pci_res = hptiop_alloc_pci_res_mv, 1253175942Sscottl .release_pci_res = hptiop_release_pci_res_mv, 1254175942Sscottl .enable_intr = hptiop_enable_intr_mv, 1255175942Sscottl .disable_intr = hptiop_disable_intr_mv, 1256175942Sscottl .get_config = hptiop_get_config_mv, 1257175942Sscottl .set_config = hptiop_set_config_mv, 1258175942Sscottl .iop_intr = hptiop_intr_mv, 1259175942Sscottl .post_msg = hptiop_post_msg_mv, 1260175942Sscottl .post_req = hptiop_post_req_mv, 1261175942Sscottl .do_ioctl = hptiop_do_ioctl_mv, 1262175942Sscottl}; 1263175942Sscottl 1264169412Sscottlstatic driver_t hptiop_pci_driver = { 1265169412Sscottl driver_name, 1266169412Sscottl driver_methods, 1267169412Sscottl sizeof(struct hpt_iop_hba) 1268169412Sscottl}; 1269169412Sscottl 1270169412SscottlDRIVER_MODULE(hptiop, pci, hptiop_pci_driver, hptiop_devclass, 0, 0); 1271169412Sscottl 1272169412Sscottlstatic int hptiop_probe(device_t dev) 1273169412Sscottl{ 1274169412Sscottl struct hpt_iop_hba *hba; 1275175942Sscottl u_int32_t id; 1276175942Sscottl static char buf[256]; 1277175942Sscottl int sas = 0; 1278175942Sscottl struct hptiop_adapter_ops *ops; 1279169412Sscottl 1280175942Sscottl if (pci_get_vendor(dev) != 0x1103) 1281175942Sscottl return (ENXIO); 1282175942Sscottl 1283175942Sscottl id = pci_get_device(dev); 1284175942Sscottl 1285175942Sscottl switch (id) { 1286224583Sdelphij case 0x4322: 1287224583Sdelphij case 0x4321: 1288175942Sscottl case 0x4320: 1289175942Sscottl sas = 1; 1290175942Sscottl case 0x3220: 1291175942Sscottl case 0x3320: 1292175942Sscottl case 0x3410: 1293175942Sscottl case 0x3520: 1294175942Sscottl case 0x3510: 1295175942Sscottl case 0x3511: 1296175942Sscottl case 0x3521: 1297175942Sscottl case 0x3522: 1298175942Sscottl case 0x3540: 1299175942Sscottl ops = &hptiop_itl_ops; 1300175942Sscottl break; 1301175942Sscottl case 0x3120: 1302175942Sscottl case 0x3122: 1303175942Sscottl case 0x3020: 1304175942Sscottl ops = &hptiop_mv_ops; 1305175942Sscottl break; 1306175942Sscottl default: 1307175942Sscottl return (ENXIO); 1308169412Sscottl } 1309175942Sscottl 1310175942Sscottl device_printf(dev, "adapter at PCI %d:%d:%d, IRQ %d\n", 1311175942Sscottl pci_get_bus(dev), pci_get_slot(dev), 1312175942Sscottl pci_get_function(dev), pci_get_irq(dev)); 1313175942Sscottl 1314175942Sscottl sprintf(buf, "RocketRAID %x %s Controller\n", 1315175942Sscottl id, sas ? "SAS" : "SATA"); 1316175942Sscottl device_set_desc_copy(dev, buf); 1317175942Sscottl 1318175942Sscottl hba = (struct hpt_iop_hba *)device_get_softc(dev); 1319175942Sscottl bzero(hba, sizeof(struct hpt_iop_hba)); 1320175942Sscottl hba->ops = ops; 1321175942Sscottl 1322175942Sscottl KdPrint(("hba->ops=%p\n", hba->ops)); 1323175942Sscottl return 0; 1324169412Sscottl} 1325169412Sscottl 1326169412Sscottlstatic int hptiop_attach(device_t dev) 1327169412Sscottl{ 1328175942Sscottl struct hpt_iop_hba *hba = (struct hpt_iop_hba *)device_get_softc(dev); 1329169412Sscottl struct hpt_iop_request_get_config iop_config; 1330169412Sscottl struct hpt_iop_request_set_config set_config; 1331169412Sscottl int rid = 0; 1332169412Sscottl struct cam_devq *devq; 1333169412Sscottl struct ccb_setasync ccb; 1334169412Sscottl u_int32_t unit = device_get_unit(dev); 1335169412Sscottl 1336175942Sscottl device_printf(dev, "%d RocketRAID 3xxx/4xxx controller driver %s\n", 1337175942Sscottl unit, driver_version); 1338169412Sscottl 1339175942Sscottl KdPrint(("hptiop: attach(%d, %d/%d/%d) ops=%p\n", unit, 1340175942Sscottl pci_get_bus(dev), pci_get_slot(dev), 1341175942Sscottl pci_get_function(dev), hba->ops)); 1342175942Sscottl 1343169412Sscottl#if __FreeBSD_version >=440000 1344169412Sscottl pci_enable_busmaster(dev); 1345169412Sscottl#endif 1346169412Sscottl hba->pcidev = dev; 1347169412Sscottl hba->pciunit = unit; 1348169412Sscottl 1349175942Sscottl if (hba->ops->alloc_pci_res(hba)) 1350169412Sscottl return ENXIO; 1351169412Sscottl 1352175942Sscottl if (hba->ops->iop_wait_ready(hba, 2000)) { 1353175942Sscottl device_printf(dev, "adapter is not ready\n"); 1354175942Sscottl goto release_pci_res; 1355169412Sscottl } 1356169412Sscottl 1357169412Sscottl#if (__FreeBSD_version >= 500000) 1358169412Sscottl mtx_init(&hba->lock, "hptioplock", NULL, MTX_DEF); 1359169412Sscottl#endif 1360169412Sscottl 1361169412Sscottl if (bus_dma_tag_create(NULL,/* parent */ 1362169412Sscottl 1, /* alignment */ 1363169412Sscottl 0, /* boundary */ 1364169412Sscottl BUS_SPACE_MAXADDR, /* lowaddr */ 1365169412Sscottl BUS_SPACE_MAXADDR, /* highaddr */ 1366169412Sscottl NULL, NULL, /* filter, filterarg */ 1367169412Sscottl BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 1368169412Sscottl BUS_SPACE_UNRESTRICTED, /* nsegments */ 1369169412Sscottl BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 1370169412Sscottl 0, /* flags */ 1371169412Sscottl#if __FreeBSD_version>502000 1372169412Sscottl NULL, /* lockfunc */ 1373169412Sscottl NULL, /* lockfuncarg */ 1374169412Sscottl#endif 1375169412Sscottl &hba->parent_dmat /* tag */)) 1376169412Sscottl { 1377175942Sscottl device_printf(dev, "alloc parent_dmat failed\n"); 1378175942Sscottl goto release_pci_res; 1379169412Sscottl } 1380169412Sscottl 1381175942Sscottl if (hba->ops->internal_memalloc) { 1382175942Sscottl if (hba->ops->internal_memalloc(hba)) { 1383175942Sscottl device_printf(dev, "alloc srb_dmat failed\n"); 1384175942Sscottl goto destroy_parent_tag; 1385175942Sscottl } 1386175942Sscottl } 1387175942Sscottl 1388175942Sscottl if (hba->ops->get_config(hba, &iop_config)) { 1389175942Sscottl device_printf(dev, "get iop config failed.\n"); 1390175942Sscottl goto get_config_failed; 1391175942Sscottl } 1392175942Sscottl 1393175942Sscottl hba->firmware_version = iop_config.firmware_version; 1394175942Sscottl hba->interface_version = iop_config.interface_version; 1395175942Sscottl hba->max_requests = iop_config.max_requests; 1396175942Sscottl hba->max_devices = iop_config.max_devices; 1397175942Sscottl hba->max_request_size = iop_config.request_size; 1398175942Sscottl hba->max_sg_count = iop_config.max_sg_count; 1399175942Sscottl 1400169412Sscottl if (bus_dma_tag_create(hba->parent_dmat,/* parent */ 1401169412Sscottl 4, /* alignment */ 1402169412Sscottl BUS_SPACE_MAXADDR_32BIT+1, /* boundary */ 1403169412Sscottl BUS_SPACE_MAXADDR, /* lowaddr */ 1404169412Sscottl BUS_SPACE_MAXADDR, /* highaddr */ 1405169412Sscottl NULL, NULL, /* filter, filterarg */ 1406169412Sscottl PAGE_SIZE * (hba->max_sg_count-1), /* maxsize */ 1407169412Sscottl hba->max_sg_count, /* nsegments */ 1408169412Sscottl 0x20000, /* maxsegsize */ 1409169412Sscottl BUS_DMA_ALLOCNOW, /* flags */ 1410169412Sscottl#if __FreeBSD_version>502000 1411169412Sscottl busdma_lock_mutex, /* lockfunc */ 1412169412Sscottl &hba->lock, /* lockfuncarg */ 1413169412Sscottl#endif 1414169412Sscottl &hba->io_dmat /* tag */)) 1415169412Sscottl { 1416175942Sscottl device_printf(dev, "alloc io_dmat failed\n"); 1417175942Sscottl goto get_config_failed; 1418169412Sscottl } 1419169412Sscottl 1420169412Sscottl if (bus_dma_tag_create(hba->parent_dmat,/* parent */ 1421169412Sscottl 1, /* alignment */ 1422169412Sscottl 0, /* boundary */ 1423169412Sscottl BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 1424169412Sscottl BUS_SPACE_MAXADDR, /* highaddr */ 1425169412Sscottl NULL, NULL, /* filter, filterarg */ 1426169412Sscottl HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE + 0x20, 1427169412Sscottl 1, /* nsegments */ 1428169412Sscottl BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 1429169412Sscottl 0, /* flags */ 1430169412Sscottl#if __FreeBSD_version>502000 1431169412Sscottl NULL, /* lockfunc */ 1432169412Sscottl NULL, /* lockfuncarg */ 1433169412Sscottl#endif 1434169412Sscottl &hba->srb_dmat /* tag */)) 1435169412Sscottl { 1436175942Sscottl device_printf(dev, "alloc srb_dmat failed\n"); 1437175942Sscottl goto destroy_io_dmat; 1438169412Sscottl } 1439169412Sscottl 1440169412Sscottl if (bus_dmamem_alloc(hba->srb_dmat, (void **)&hba->uncached_ptr, 1441169412Sscottl#if __FreeBSD_version>501000 1442175942Sscottl BUS_DMA_WAITOK | BUS_DMA_COHERENT, 1443169412Sscottl#else 1444175942Sscottl BUS_DMA_WAITOK, 1445169412Sscottl#endif 1446175942Sscottl &hba->srb_dmamap) != 0) 1447169412Sscottl { 1448175942Sscottl device_printf(dev, "srb bus_dmamem_alloc failed!\n"); 1449175942Sscottl goto destroy_srb_dmat; 1450169412Sscottl } 1451169412Sscottl 1452169412Sscottl if (bus_dmamap_load(hba->srb_dmat, 1453169412Sscottl hba->srb_dmamap, hba->uncached_ptr, 1454169412Sscottl (HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE) + 0x20, 1455169412Sscottl hptiop_map_srb, hba, 0)) 1456169412Sscottl { 1457175942Sscottl device_printf(dev, "bus_dmamap_load failed!\n"); 1458175942Sscottl goto srb_dmamem_free; 1459169412Sscottl } 1460169412Sscottl 1461169412Sscottl if ((devq = cam_simq_alloc(hba->max_requests - 1 )) == NULL) { 1462175942Sscottl device_printf(dev, "cam_simq_alloc failed\n"); 1463175942Sscottl goto srb_dmamap_unload; 1464169412Sscottl } 1465175942Sscottl 1466175942Sscottl#if __FreeBSD_version <700000 1467169412Sscottl hba->sim = cam_sim_alloc(hptiop_action, hptiop_poll, driver_name, 1468175942Sscottl hba, unit, hba->max_requests - 1, 1, devq); 1469175942Sscottl#else 1470175942Sscottl hba->sim = cam_sim_alloc(hptiop_action, hptiop_poll, driver_name, 1471169412Sscottl hba, unit, &Giant, hba->max_requests - 1, 1, devq); 1472175942Sscottl#endif 1473169412Sscottl if (!hba->sim) { 1474175942Sscottl device_printf(dev, "cam_sim_alloc failed\n"); 1475169412Sscottl cam_simq_free(devq); 1476175942Sscottl goto srb_dmamap_unload; 1477169412Sscottl } 1478175942Sscottl#if __FreeBSD_version <700000 1479175942Sscottl if (xpt_bus_register(hba->sim, 0) != CAM_SUCCESS) 1480175942Sscottl#else 1481175942Sscottl if (xpt_bus_register(hba->sim, dev, 0) != CAM_SUCCESS) 1482175942Sscottl#endif 1483175942Sscottl { 1484175942Sscottl device_printf(dev, "xpt_bus_register failed\n"); 1485175942Sscottl goto free_cam_sim; 1486169412Sscottl } 1487169412Sscottl 1488169412Sscottl if (xpt_create_path(&hba->path, /*periph */ NULL, 1489169412Sscottl cam_sim_path(hba->sim), CAM_TARGET_WILDCARD, 1490175942Sscottl CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 1491175942Sscottl device_printf(dev, "xpt_create_path failed\n"); 1492175942Sscottl goto deregister_xpt_bus; 1493169412Sscottl } 1494169412Sscottl 1495169412Sscottl bzero(&set_config, sizeof(set_config)); 1496175942Sscottl set_config.iop_id = unit; 1497169412Sscottl set_config.vbus_id = cam_sim_path(hba->sim); 1498169412Sscottl set_config.max_host_request_size = HPT_SRB_MAX_REQ_SIZE; 1499169412Sscottl 1500175942Sscottl if (hba->ops->set_config(hba, &set_config)) { 1501175942Sscottl device_printf(dev, "set iop config failed.\n"); 1502175942Sscottl goto free_hba_path; 1503169412Sscottl } 1504169412Sscottl 1505169412Sscottl xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5); 1506169412Sscottl ccb.ccb_h.func_code = XPT_SASYNC_CB; 1507169412Sscottl ccb.event_enable = (AC_FOUND_DEVICE | AC_LOST_DEVICE); 1508169412Sscottl ccb.callback = hptiop_async; 1509169412Sscottl ccb.callback_arg = hba->sim; 1510169412Sscottl xpt_action((union ccb *)&ccb); 1511169412Sscottl 1512169412Sscottl rid = 0; 1513169412Sscottl if ((hba->irq_res = bus_alloc_resource(hba->pcidev, SYS_RES_IRQ, 1514169412Sscottl &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) { 1515175942Sscottl device_printf(dev, "allocate irq failed!\n"); 1516175942Sscottl goto free_hba_path; 1517169412Sscottl } 1518169412Sscottl 1519175942Sscottl#if __FreeBSD_version <700000 1520169412Sscottl if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM, 1521175942Sscottl hptiop_pci_intr, hba, &hba->irq_handle)) 1522175942Sscottl#else 1523175942Sscottl if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM, 1524175942Sscottl NULL, hptiop_pci_intr, hba, &hba->irq_handle)) 1525175942Sscottl#endif 1526175942Sscottl { 1527175942Sscottl device_printf(dev, "allocate intr function failed!\n"); 1528175942Sscottl goto free_irq_resource; 1529169412Sscottl } 1530169412Sscottl 1531175942Sscottl if (hptiop_send_sync_msg(hba, 1532175942Sscottl IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) { 1533175942Sscottl device_printf(dev, "fail to start background task\n"); 1534175942Sscottl goto teartown_irq_resource; 1535169412Sscottl } 1536169412Sscottl 1537175942Sscottl hba->ops->enable_intr(hba); 1538175942Sscottl 1539169412Sscottl hba->ioctl_dev = make_dev(&hptiop_cdevsw, unit, 1540169412Sscottl UID_ROOT, GID_WHEEL /*GID_OPERATOR*/, 1541169412Sscottl S_IRUSR | S_IWUSR, "%s%d", driver_name, unit); 1542169412Sscottl 1543169412Sscottl#if __FreeBSD_version < 503000 1544169412Sscottl hba->ioctl_dev->si_drv1 = hba; 1545169412Sscottl#endif 1546169412Sscottl 1547169412Sscottl return 0; 1548175942Sscottl 1549175942Sscottl 1550175942Sscottlteartown_irq_resource: 1551175942Sscottl bus_teardown_intr(dev, hba->irq_res, hba->irq_handle); 1552175942Sscottl 1553175942Sscottlfree_irq_resource: 1554175942Sscottl bus_release_resource(dev, SYS_RES_IRQ, 0, hba->irq_res); 1555175942Sscottl 1556175942Sscottlfree_hba_path: 1557175942Sscottl xpt_free_path(hba->path); 1558175942Sscottl 1559175942Sscottlderegister_xpt_bus: 1560175942Sscottl xpt_bus_deregister(cam_sim_path(hba->sim)); 1561175942Sscottl 1562175942Sscottlfree_cam_sim: 1563175942Sscottl cam_sim_free(hba->sim, /*free devq*/ TRUE); 1564175942Sscottl 1565175942Sscottlsrb_dmamap_unload: 1566175942Sscottl if (hba->uncached_ptr) 1567175942Sscottl bus_dmamap_unload(hba->srb_dmat, hba->srb_dmamap); 1568175942Sscottl 1569175942Sscottlsrb_dmamem_free: 1570175942Sscottl if (hba->uncached_ptr) 1571175942Sscottl bus_dmamem_free(hba->srb_dmat, 1572175942Sscottl hba->uncached_ptr, hba->srb_dmamap); 1573175942Sscottl 1574175942Sscottldestroy_srb_dmat: 1575175942Sscottl if (hba->srb_dmat) 1576175942Sscottl bus_dma_tag_destroy(hba->srb_dmat); 1577175942Sscottl 1578175942Sscottldestroy_io_dmat: 1579175942Sscottl if (hba->io_dmat) 1580175942Sscottl bus_dma_tag_destroy(hba->io_dmat); 1581175942Sscottl 1582175942Sscottlget_config_failed: 1583175942Sscottl if (hba->ops->internal_memfree) 1584175942Sscottl hba->ops->internal_memfree(hba); 1585175942Sscottl 1586175942Sscottldestroy_parent_tag: 1587175942Sscottl if (hba->parent_dmat) 1588175942Sscottl bus_dma_tag_destroy(hba->parent_dmat); 1589175942Sscottl 1590175942Sscottlrelease_pci_res: 1591175942Sscottl if (hba->ops->release_pci_res) 1592175942Sscottl hba->ops->release_pci_res(hba); 1593175942Sscottl 1594175942Sscottl return ENXIO; 1595169412Sscottl} 1596169412Sscottl 1597169412Sscottlstatic int hptiop_detach(device_t dev) 1598169412Sscottl{ 1599169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev); 1600169412Sscottl int i; 1601169412Sscottl int error = EBUSY; 1602169412Sscottl 1603169412Sscottl hptiop_lock_adapter(hba); 1604175942Sscottl for (i = 0; i < hba->max_devices; i++) 1605175942Sscottl if (hptiop_os_query_remove_device(hba, i)) { 1606175942Sscottl device_printf(dev, "%d file system is busy. id=%d", 1607169412Sscottl hba->pciunit, i); 1608169412Sscottl goto out; 1609169412Sscottl } 1610169412Sscottl 1611169412Sscottl if ((error = hptiop_shutdown(dev)) != 0) 1612169412Sscottl goto out; 1613175942Sscottl if (hptiop_send_sync_msg(hba, 1614175942Sscottl IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK, 60000)) 1615169412Sscottl goto out; 1616169412Sscottl 1617169412Sscottl hptiop_release_resource(hba); 1618169412Sscottl error = 0; 1619169412Sscottlout: 1620169412Sscottl hptiop_unlock_adapter(hba); 1621169412Sscottl return error; 1622169412Sscottl} 1623169412Sscottl 1624169412Sscottlstatic int hptiop_shutdown(device_t dev) 1625169412Sscottl{ 1626169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev); 1627169412Sscottl 1628169412Sscottl int error = 0; 1629169412Sscottl 1630169412Sscottl if (hba->flag & HPT_IOCTL_FLAG_OPEN) { 1631175942Sscottl device_printf(dev, "%d device is busy", hba->pciunit); 1632169412Sscottl return EBUSY; 1633169412Sscottl } 1634175942Sscottl 1635175942Sscottl hba->ops->disable_intr(hba); 1636175942Sscottl 1637175942Sscottl if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_SHUTDOWN, 60000)) 1638169412Sscottl error = EBUSY; 1639169412Sscottl 1640169412Sscottl return error; 1641169412Sscottl} 1642169412Sscottl 1643169412Sscottlstatic void hptiop_pci_intr(void *arg) 1644169412Sscottl{ 1645169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg; 1646169412Sscottl hptiop_lock_adapter(hba); 1647175942Sscottl hba->ops->iop_intr(hba); 1648169412Sscottl hptiop_unlock_adapter(hba); 1649169412Sscottl} 1650169412Sscottl 1651169412Sscottlstatic void hptiop_poll(struct cam_sim *sim) 1652169412Sscottl{ 1653169412Sscottl hptiop_pci_intr(cam_sim_softc(sim)); 1654169412Sscottl} 1655169412Sscottl 1656169412Sscottlstatic void hptiop_async(void * callback_arg, u_int32_t code, 1657169412Sscottl struct cam_path * path, void * arg) 1658169412Sscottl{ 1659169412Sscottl} 1660169412Sscottl 1661175942Sscottlstatic void hptiop_enable_intr_itl(struct hpt_iop_hba *hba) 1662169412Sscottl{ 1663175942Sscottl BUS_SPACE_WRT4_ITL(outbound_intmask, 1664169412Sscottl ~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0)); 1665169412Sscottl} 1666169412Sscottl 1667175942Sscottlstatic void hptiop_enable_intr_mv(struct hpt_iop_hba *hba) 1668169412Sscottl{ 1669169412Sscottl u_int32_t int_mask; 1670169412Sscottl 1671175942Sscottl int_mask = BUS_SPACE_RD4_MV0(outbound_intmask); 1672175942Sscottl 1673175942Sscottl int_mask |= MVIOP_MU_OUTBOUND_INT_POSTQUEUE 1674175942Sscottl | MVIOP_MU_OUTBOUND_INT_MSG; 1675175942Sscottl BUS_SPACE_WRT4_MV0(outbound_intmask,int_mask); 1676169412Sscottl} 1677169412Sscottl 1678175942Sscottlstatic void hptiop_disable_intr_itl(struct hpt_iop_hba *hba) 1679175942Sscottl{ 1680175942Sscottl u_int32_t int_mask; 1681175942Sscottl 1682175942Sscottl int_mask = BUS_SPACE_RD4_ITL(outbound_intmask); 1683175942Sscottl 1684175942Sscottl int_mask |= IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0; 1685175942Sscottl BUS_SPACE_WRT4_ITL(outbound_intmask, int_mask); 1686175942Sscottl BUS_SPACE_RD4_ITL(outbound_intstatus); 1687175942Sscottl} 1688175942Sscottl 1689175942Sscottlstatic void hptiop_disable_intr_mv(struct hpt_iop_hba *hba) 1690175942Sscottl{ 1691175942Sscottl u_int32_t int_mask; 1692175942Sscottl int_mask = BUS_SPACE_RD4_MV0(outbound_intmask); 1693175942Sscottl 1694175942Sscottl int_mask &= ~(MVIOP_MU_OUTBOUND_INT_MSG 1695175942Sscottl | MVIOP_MU_OUTBOUND_INT_POSTQUEUE); 1696175942Sscottl BUS_SPACE_WRT4_MV0(outbound_intmask,int_mask); 1697175942Sscottl BUS_SPACE_RD4_MV0(outbound_intmask); 1698175942Sscottl} 1699175942Sscottl 1700169412Sscottlstatic int hptiop_reset_adapter(struct hpt_iop_hba * hba) 1701169412Sscottl{ 1702175942Sscottl return hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000); 1703169412Sscottl} 1704169412Sscottl 1705169412Sscottlstatic void *hptiop_get_srb(struct hpt_iop_hba * hba) 1706169412Sscottl{ 1707169412Sscottl struct hpt_iop_srb * srb; 1708169412Sscottl 1709169412Sscottl if (hba->srb_list) { 1710169412Sscottl srb = hba->srb_list; 1711169412Sscottl hba->srb_list = srb->next; 1712175942Sscottl return srb; 1713169412Sscottl } 1714169412Sscottl 1715175942Sscottl return NULL; 1716169412Sscottl} 1717169412Sscottl 1718175942Sscottlstatic void hptiop_free_srb(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb) 1719169412Sscottl{ 1720169412Sscottl srb->next = hba->srb_list; 1721169412Sscottl hba->srb_list = srb; 1722169412Sscottl} 1723169412Sscottl 1724169412Sscottlstatic void hptiop_action(struct cam_sim *sim, union ccb *ccb) 1725169412Sscottl{ 1726169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)cam_sim_softc(sim); 1727169412Sscottl struct hpt_iop_srb * srb; 1728169412Sscottl 1729169412Sscottl switch (ccb->ccb_h.func_code) { 1730169412Sscottl 1731169412Sscottl case XPT_SCSI_IO: 1732169412Sscottl hptiop_lock_adapter(hba); 1733169412Sscottl if (ccb->ccb_h.target_lun != 0 || 1734175942Sscottl ccb->ccb_h.target_id >= hba->max_devices || 1735169412Sscottl (ccb->ccb_h.flags & CAM_CDB_PHYS)) 1736169412Sscottl { 1737169412Sscottl ccb->ccb_h.status = CAM_TID_INVALID; 1738169412Sscottl xpt_done(ccb); 1739169412Sscottl goto scsi_done; 1740169412Sscottl } 1741169412Sscottl 1742169412Sscottl if ((srb = hptiop_get_srb(hba)) == NULL) { 1743175942Sscottl device_printf(hba->pcidev, "srb allocated failed"); 1744169412Sscottl ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1745169412Sscottl xpt_done(ccb); 1746169412Sscottl goto scsi_done; 1747169412Sscottl } 1748169412Sscottl 1749169412Sscottl srb->ccb = ccb; 1750169412Sscottl 1751169412Sscottl if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE) 1752169412Sscottl hptiop_post_scsi_command(srb, NULL, 0, 0); 1753169412Sscottl else if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { 1754169412Sscottl if ((ccb->ccb_h.flags & CAM_DATA_PHYS) == 0) { 1755169412Sscottl int error; 1756169412Sscottl 1757169412Sscottl error = bus_dmamap_load(hba->io_dmat, 1758175942Sscottl srb->dma_map, 1759175942Sscottl ccb->csio.data_ptr, 1760175942Sscottl ccb->csio.dxfer_len, 1761175942Sscottl hptiop_post_scsi_command, 1762175942Sscottl srb, 0); 1763169412Sscottl 1764169412Sscottl if (error && error != EINPROGRESS) { 1765175942Sscottl device_printf(hba->pcidev, 1766175942Sscottl "%d bus_dmamap_load error %d", 1767175942Sscottl hba->pciunit, error); 1768169412Sscottl xpt_freeze_simq(hba->sim, 1); 1769169412Sscottl ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1770169412Sscottlinvalid: 1771169412Sscottl hptiop_free_srb(hba, srb); 1772169412Sscottl xpt_done(ccb); 1773169412Sscottl goto scsi_done; 1774169412Sscottl } 1775169412Sscottl } 1776169412Sscottl else { 1777175942Sscottl device_printf(hba->pcidev, 1778175942Sscottl "CAM_DATA_PHYS not supported"); 1779169412Sscottl ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1780169412Sscottl goto invalid; 1781169412Sscottl } 1782169412Sscottl } 1783169412Sscottl else { 1784169412Sscottl struct bus_dma_segment *segs; 1785169412Sscottl 1786169412Sscottl if ((ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0 || 1787169412Sscottl (ccb->ccb_h.flags & CAM_DATA_PHYS) != 0) { 1788175942Sscottl device_printf(hba->pcidev, "SCSI cmd failed"); 1789169412Sscottl ccb->ccb_h.status=CAM_PROVIDE_FAIL; 1790169412Sscottl goto invalid; 1791169412Sscottl } 1792169412Sscottl 1793169412Sscottl segs = (struct bus_dma_segment *)ccb->csio.data_ptr; 1794169412Sscottl hptiop_post_scsi_command(srb, segs, 1795169412Sscottl ccb->csio.sglist_cnt, 0); 1796169412Sscottl } 1797169412Sscottl 1798169412Sscottlscsi_done: 1799169412Sscottl hptiop_unlock_adapter(hba); 1800169412Sscottl return; 1801169412Sscottl 1802169412Sscottl case XPT_RESET_BUS: 1803175942Sscottl device_printf(hba->pcidev, "reset adapter"); 1804169412Sscottl hptiop_lock_adapter(hba); 1805169412Sscottl hba->msg_done = 0; 1806169412Sscottl hptiop_reset_adapter(hba); 1807169412Sscottl hptiop_unlock_adapter(hba); 1808169412Sscottl break; 1809169412Sscottl 1810169412Sscottl case XPT_GET_TRAN_SETTINGS: 1811169412Sscottl case XPT_SET_TRAN_SETTINGS: 1812169412Sscottl ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 1813169412Sscottl break; 1814169412Sscottl 1815169412Sscottl case XPT_CALC_GEOMETRY: 1816227912Smarius#if __FreeBSD_version >= 500000 1817227912Smarius cam_calc_geometry(&ccb->ccg, 1); 1818227912Smarius#else 1819169412Sscottl ccb->ccg.heads = 255; 1820169412Sscottl ccb->ccg.secs_per_track = 63; 1821169412Sscottl ccb->ccg.cylinders = ccb->ccg.volume_size / 1822169412Sscottl (ccb->ccg.heads * ccb->ccg.secs_per_track); 1823169412Sscottl ccb->ccb_h.status = CAM_REQ_CMP; 1824227912Smarius#endif 1825169412Sscottl break; 1826169412Sscottl 1827169412Sscottl case XPT_PATH_INQ: 1828169412Sscottl { 1829169412Sscottl struct ccb_pathinq *cpi = &ccb->cpi; 1830169412Sscottl 1831169412Sscottl cpi->version_num = 1; 1832169412Sscottl cpi->hba_inquiry = PI_SDTR_ABLE; 1833169412Sscottl cpi->target_sprt = 0; 1834169412Sscottl cpi->hba_misc = PIM_NOBUSRESET; 1835169412Sscottl cpi->hba_eng_cnt = 0; 1836175942Sscottl cpi->max_target = hba->max_devices; 1837169412Sscottl cpi->max_lun = 0; 1838169412Sscottl cpi->unit_number = cam_sim_unit(sim); 1839169412Sscottl cpi->bus_id = cam_sim_bus(sim); 1840175942Sscottl cpi->initiator_id = hba->max_devices; 1841169412Sscottl cpi->base_transfer_speed = 3300; 1842169412Sscottl 1843169412Sscottl strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 1844169412Sscottl strncpy(cpi->hba_vid, "HPT ", HBA_IDLEN); 1845169412Sscottl strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 1846209340Smav cpi->transport = XPORT_SPI; 1847209340Smav cpi->transport_version = 2; 1848209340Smav cpi->protocol = PROTO_SCSI; 1849209340Smav cpi->protocol_version = SCSI_REV_2; 1850169412Sscottl cpi->ccb_h.status = CAM_REQ_CMP; 1851169412Sscottl break; 1852169412Sscottl } 1853169412Sscottl 1854169412Sscottl default: 1855169412Sscottl ccb->ccb_h.status = CAM_REQ_INVALID; 1856169412Sscottl break; 1857169412Sscottl } 1858169412Sscottl 1859169412Sscottl xpt_done(ccb); 1860169412Sscottl return; 1861169412Sscottl} 1862169412Sscottl 1863175942Sscottlstatic void hptiop_post_req_itl(struct hpt_iop_hba *hba, 1864175942Sscottl struct hpt_iop_srb *srb, 1865175942Sscottl bus_dma_segment_t *segs, int nsegs) 1866169412Sscottl{ 1867169412Sscottl int idx; 1868169412Sscottl union ccb *ccb = srb->ccb; 1869169412Sscottl u_int8_t *cdb; 1870169412Sscottl 1871175942Sscottl if (ccb->ccb_h.flags & CAM_CDB_POINTER) 1872175942Sscottl cdb = ccb->csio.cdb_io.cdb_ptr; 1873175942Sscottl else 1874175942Sscottl cdb = ccb->csio.cdb_io.cdb_bytes; 1875169412Sscottl 1876175942Sscottl KdPrint(("ccb=%p %x-%x-%x\n", 1877175942Sscottl ccb, *(u_int32_t *)cdb, *((u_int32_t *)cdb+1), *((u_int32_t *)cdb+2))); 1878169412Sscottl 1879169412Sscottl if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) { 1880175942Sscottl u_int32_t iop_req32; 1881175942Sscottl struct hpt_iop_request_scsi_command req; 1882169412Sscottl 1883175942Sscottl iop_req32 = BUS_SPACE_RD4_ITL(inbound_queue); 1884175942Sscottl 1885175942Sscottl if (iop_req32 == IOPMU_QUEUE_EMPTY) { 1886175942Sscottl device_printf(hba->pcidev, "invaild req offset\n"); 1887175942Sscottl ccb->ccb_h.status = CAM_BUSY; 1888175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 1889175942Sscottl hptiop_free_srb(hba, srb); 1890175942Sscottl xpt_done(ccb); 1891175942Sscottl return; 1892169412Sscottl } 1893175942Sscottl 1894175942Sscottl if (ccb->csio.dxfer_len && nsegs > 0) { 1895175942Sscottl struct hpt_iopsg *psg = req.sg_list; 1896175942Sscottl for (idx = 0; idx < nsegs; idx++, psg++) { 1897175942Sscottl psg->pci_address = (u_int64_t)segs[idx].ds_addr; 1898175942Sscottl psg->size = segs[idx].ds_len; 1899175942Sscottl psg->eot = 0; 1900175942Sscottl } 1901175942Sscottl psg[-1].eot = 1; 1902175942Sscottl } 1903175942Sscottl 1904175942Sscottl bcopy(cdb, req.cdb, ccb->csio.cdb_len); 1905175942Sscottl 1906175942Sscottl req.header.size = offsetof(struct hpt_iop_request_scsi_command, sg_list) 1907175942Sscottl + nsegs*sizeof(struct hpt_iopsg); 1908175942Sscottl req.header.type = IOP_REQUEST_TYPE_SCSI_COMMAND; 1909175942Sscottl req.header.flags = 0; 1910175942Sscottl req.header.result = IOP_RESULT_PENDING; 1911175942Sscottl req.header.context = (u_int64_t)(unsigned long)srb; 1912175942Sscottl req.dataxfer_length = ccb->csio.dxfer_len; 1913175942Sscottl req.channel = 0; 1914175942Sscottl req.target = ccb->ccb_h.target_id; 1915175942Sscottl req.lun = ccb->ccb_h.target_lun; 1916175942Sscottl 1917175942Sscottl bus_space_write_region_1(hba->bar0t, hba->bar0h, iop_req32, 1918175942Sscottl (u_int8_t *)&req, req.header.size); 1919175942Sscottl 1920175942Sscottl if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 1921175942Sscottl bus_dmamap_sync(hba->io_dmat, 1922175942Sscottl srb->dma_map, BUS_DMASYNC_PREREAD); 1923175942Sscottl } 1924175942Sscottl else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) 1925175942Sscottl bus_dmamap_sync(hba->io_dmat, 1926175942Sscottl srb->dma_map, BUS_DMASYNC_PREWRITE); 1927175942Sscottl 1928175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue,iop_req32); 1929175942Sscottl } else { 1930175942Sscottl struct hpt_iop_request_scsi_command *req; 1931175942Sscottl 1932169412Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 1933175942Sscottl if (ccb->csio.dxfer_len && nsegs > 0) { 1934175942Sscottl struct hpt_iopsg *psg = req->sg_list; 1935175942Sscottl for (idx = 0; idx < nsegs; idx++, psg++) { 1936175942Sscottl psg->pci_address = 1937175942Sscottl (u_int64_t)segs[idx].ds_addr; 1938175942Sscottl psg->size = segs[idx].ds_len; 1939175942Sscottl psg->eot = 0; 1940175942Sscottl } 1941175942Sscottl psg[-1].eot = 1; 1942175942Sscottl } 1943169412Sscottl 1944175942Sscottl bcopy(cdb, req->cdb, ccb->csio.cdb_len); 1945175942Sscottl 1946175942Sscottl req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND; 1947175942Sscottl req->header.result = IOP_RESULT_PENDING; 1948175942Sscottl req->dataxfer_length = ccb->csio.dxfer_len; 1949175942Sscottl req->channel = 0; 1950175942Sscottl req->target = ccb->ccb_h.target_id; 1951175942Sscottl req->lun = ccb->ccb_h.target_lun; 1952175942Sscottl req->header.size = offsetof(struct hpt_iop_request_scsi_command, sg_list) 1953175942Sscottl + nsegs*sizeof(struct hpt_iopsg); 1954175942Sscottl req->header.context = (u_int64_t)srb->index | 1955175942Sscottl IOPMU_QUEUE_ADDR_HOST_BIT; 1956175942Sscottl req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT; 1957175942Sscottl 1958175942Sscottl if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 1959175942Sscottl bus_dmamap_sync(hba->io_dmat, 1960175942Sscottl srb->dma_map, BUS_DMASYNC_PREREAD); 1961175942Sscottl }else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 1962175942Sscottl bus_dmamap_sync(hba->io_dmat, 1963175942Sscottl srb->dma_map, BUS_DMASYNC_PREWRITE); 1964175942Sscottl } 1965175942Sscottl 1966175942Sscottl if (hba->firmware_version > 0x01020000 1967175942Sscottl || hba->interface_version > 0x01020000) { 1968175942Sscottl u_int32_t size_bits; 1969175942Sscottl 1970175942Sscottl if (req->header.size < 256) 1971175942Sscottl size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT; 1972175942Sscottl else if (req->header.size < 512) 1973175942Sscottl size_bits = IOPMU_QUEUE_ADDR_HOST_BIT; 1974175942Sscottl else 1975175942Sscottl size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT 1976175942Sscottl | IOPMU_QUEUE_ADDR_HOST_BIT; 1977175942Sscottl 1978175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue, 1979175942Sscottl (u_int32_t)srb->phy_addr | size_bits); 1980175942Sscottl } else 1981175942Sscottl BUS_SPACE_WRT4_ITL(inbound_queue, (u_int32_t)srb->phy_addr 1982175942Sscottl |IOPMU_QUEUE_ADDR_HOST_BIT); 1983175942Sscottl } 1984175942Sscottl} 1985175942Sscottl 1986175942Sscottlstatic void hptiop_post_req_mv(struct hpt_iop_hba *hba, 1987175942Sscottl struct hpt_iop_srb *srb, 1988175942Sscottl bus_dma_segment_t *segs, int nsegs) 1989175942Sscottl{ 1990175942Sscottl int idx, size; 1991175942Sscottl union ccb *ccb = srb->ccb; 1992175942Sscottl u_int8_t *cdb; 1993175942Sscottl struct hpt_iop_request_scsi_command *req; 1994175942Sscottl u_int64_t req_phy; 1995175942Sscottl 1996175942Sscottl req = (struct hpt_iop_request_scsi_command *)srb; 1997175942Sscottl req_phy = srb->phy_addr; 1998175942Sscottl 1999169412Sscottl if (ccb->csio.dxfer_len && nsegs > 0) { 2000169412Sscottl struct hpt_iopsg *psg = req->sg_list; 2001169412Sscottl for (idx = 0; idx < nsegs; idx++, psg++) { 2002169412Sscottl psg->pci_address = (u_int64_t)segs[idx].ds_addr; 2003169412Sscottl psg->size = segs[idx].ds_len; 2004169412Sscottl psg->eot = 0; 2005169412Sscottl } 2006169412Sscottl psg[-1].eot = 1; 2007169412Sscottl } 2008169412Sscottl if (ccb->ccb_h.flags & CAM_CDB_POINTER) 2009169412Sscottl cdb = ccb->csio.cdb_io.cdb_ptr; 2010169412Sscottl else 2011169412Sscottl cdb = ccb->csio.cdb_io.cdb_bytes; 2012169412Sscottl 2013169412Sscottl bcopy(cdb, req->cdb, ccb->csio.cdb_len); 2014169412Sscottl req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND; 2015169412Sscottl req->header.result = IOP_RESULT_PENDING; 2016169412Sscottl req->dataxfer_length = ccb->csio.dxfer_len; 2017175942Sscottl req->channel = 0; 2018169412Sscottl req->target = ccb->ccb_h.target_id; 2019169412Sscottl req->lun = ccb->ccb_h.target_lun; 2020169412Sscottl req->header.size = sizeof(struct hpt_iop_request_scsi_command) 2021175942Sscottl - sizeof(struct hpt_iopsg) 2022175942Sscottl + nsegs * sizeof(struct hpt_iopsg); 2023169412Sscottl if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 2024169412Sscottl bus_dmamap_sync(hba->io_dmat, 2025175942Sscottl srb->dma_map, BUS_DMASYNC_PREREAD); 2026169412Sscottl } 2027169412Sscottl else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) 2028169412Sscottl bus_dmamap_sync(hba->io_dmat, 2029175942Sscottl srb->dma_map, BUS_DMASYNC_PREWRITE); 2030175942Sscottl req->header.context = (u_int64_t)srb->index 2031175942Sscottl << MVIOP_REQUEST_NUMBER_START_BIT 2032175942Sscottl | MVIOP_CMD_TYPE_SCSI; 2033175942Sscottl req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT; 2034175942Sscottl size = req->header.size >> 8; 2035175942Sscottl hptiop_mv_inbound_write(req_phy 2036175942Sscottl | MVIOP_MU_QUEUE_ADDR_HOST_BIT 2037175942Sscottl | (size > 3 ? 3 : size), hba); 2038169412Sscottl} 2039169412Sscottl 2040175942Sscottlstatic void hptiop_post_scsi_command(void *arg, bus_dma_segment_t *segs, 2041175942Sscottl int nsegs, int error) 2042169412Sscottl{ 2043175942Sscottl struct hpt_iop_srb *srb = (struct hpt_iop_srb *)arg; 2044175942Sscottl union ccb *ccb = srb->ccb; 2045175942Sscottl struct hpt_iop_hba *hba = srb->hba; 2046169412Sscottl 2047175942Sscottl if (error || nsegs > hba->max_sg_count) { 2048175942Sscottl KdPrint(("hptiop: func_code=%x tid=%x lun=%x nsegs=%d\n", 2049175942Sscottl ccb->ccb_h.func_code, 2050175942Sscottl ccb->ccb_h.target_id, 2051175942Sscottl ccb->ccb_h.target_lun, nsegs)); 2052175942Sscottl ccb->ccb_h.status = CAM_BUSY; 2053175942Sscottl bus_dmamap_unload(hba->io_dmat, srb->dma_map); 2054169412Sscottl hptiop_free_srb(hba, srb); 2055169412Sscottl xpt_done(ccb); 2056175942Sscottl return; 2057169412Sscottl } 2058175942Sscottl 2059175942Sscottl hba->ops->post_req(hba, srb, segs, nsegs); 2060169412Sscottl} 2061169412Sscottl 2062175942Sscottlstatic void hptiop_mv_map_ctlcfg(void *arg, bus_dma_segment_t *segs, 2063175942Sscottl int nsegs, int error) 2064175942Sscottl{ 2065175942Sscottl struct hpt_iop_hba *hba = (struct hpt_iop_hba *)arg; 2066175942Sscottl hba->ctlcfgcmd_phy = ((u_int64_t)segs->ds_addr + 0x1F) 2067175942Sscottl & ~(u_int64_t)0x1F; 2068175942Sscottl hba->ctlcfg_ptr = (u_int8_t *)(((unsigned long)hba->ctlcfg_ptr + 0x1F) 2069175942Sscottl & ~0x1F); 2070175942Sscottl} 2071175942Sscottl 2072169412Sscottlstatic void hptiop_map_srb(void *arg, bus_dma_segment_t *segs, 2073175942Sscottl int nsegs, int error) 2074169412Sscottl{ 2075169412Sscottl struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg; 2076169412Sscottl bus_addr_t phy_addr = (segs->ds_addr + 0x1F) & ~(bus_addr_t)0x1F; 2077169412Sscottl struct hpt_iop_srb *srb, *tmp_srb; 2078169412Sscottl int i; 2079169412Sscottl 2080169412Sscottl if (error || nsegs == 0) { 2081175942Sscottl device_printf(hba->pcidev, "hptiop_map_srb error"); 2082169412Sscottl return; 2083169412Sscottl } 2084169412Sscottl 2085169412Sscottl /* map srb */ 2086169412Sscottl srb = (struct hpt_iop_srb *) 2087175942Sscottl (((unsigned long)hba->uncached_ptr + 0x1F) 2088175942Sscottl & ~(unsigned long)0x1F); 2089169412Sscottl 2090169412Sscottl for (i = 0; i < HPT_SRB_MAX_QUEUE_SIZE; i++) { 2091169412Sscottl tmp_srb = (struct hpt_iop_srb *) 2092169412Sscottl ((char *)srb + i * HPT_SRB_MAX_SIZE); 2093169412Sscottl if (((unsigned long)tmp_srb & 0x1F) == 0) { 2094169412Sscottl if (bus_dmamap_create(hba->io_dmat, 2095169412Sscottl 0, &tmp_srb->dma_map)) { 2096175942Sscottl device_printf(hba->pcidev, "dmamap create failed"); 2097169412Sscottl return; 2098169412Sscottl } 2099169412Sscottl 2100169412Sscottl bzero(tmp_srb, sizeof(struct hpt_iop_srb)); 2101169412Sscottl tmp_srb->hba = hba; 2102169412Sscottl tmp_srb->index = i; 2103175942Sscottl if (hba->ctlcfg_ptr == 0) {/*itl iop*/ 2104175942Sscottl tmp_srb->phy_addr = (u_int64_t)(u_int32_t) 2105175942Sscottl (phy_addr >> 5); 2106175942Sscottl if (phy_addr & IOPMU_MAX_MEM_SUPPORT_MASK_32G) 2107175942Sscottl tmp_srb->srb_flag = 2108175942Sscottl HPT_SRB_FLAG_HIGH_MEM_ACESS; 2109175942Sscottl } else { 2110175942Sscottl tmp_srb->phy_addr = phy_addr; 2111175942Sscottl } 2112175942Sscottl 2113169412Sscottl hptiop_free_srb(hba, tmp_srb); 2114169412Sscottl hba->srb[i] = tmp_srb; 2115169412Sscottl phy_addr += HPT_SRB_MAX_SIZE; 2116169412Sscottl } 2117169412Sscottl else { 2118175942Sscottl device_printf(hba->pcidev, "invalid alignment"); 2119169412Sscottl return; 2120169412Sscottl } 2121169412Sscottl } 2122169412Sscottl} 2123169412Sscottl 2124175942Sscottlstatic void hptiop_os_message_callback(struct hpt_iop_hba * hba, u_int32_t msg) 2125169412Sscottl{ 2126169412Sscottl hba->msg_done = 1; 2127169412Sscottl} 2128169412Sscottl 2129175942Sscottlstatic int hptiop_os_query_remove_device(struct hpt_iop_hba * hba, 2130175942Sscottl int target_id) 2131169412Sscottl{ 2132169412Sscottl struct cam_periph *periph = NULL; 2133169412Sscottl struct cam_path *path; 2134169412Sscottl int status, retval = 0; 2135169412Sscottl 2136169412Sscottl status = xpt_create_path(&path, NULL, hba->sim->path_id, target_id, 0); 2137169412Sscottl 2138169412Sscottl if (status == CAM_REQ_CMP) { 2139169412Sscottl if ((periph = cam_periph_find(path, "da")) != NULL) { 2140169412Sscottl if (periph->refcount >= 1) { 2141175942Sscottl device_printf(hba->pcidev, "%d ," 2142175942Sscottl "target_id=0x%x," 2143175942Sscottl "refcount=%d", 2144169412Sscottl hba->pciunit, target_id, periph->refcount); 2145169412Sscottl retval = -1; 2146169412Sscottl } 2147169412Sscottl } 2148169412Sscottl xpt_free_path(path); 2149169412Sscottl } 2150169412Sscottl return retval; 2151169412Sscottl} 2152169412Sscottl 2153169412Sscottlstatic void hptiop_release_resource(struct hpt_iop_hba *hba) 2154169412Sscottl{ 2155175942Sscottl int i; 2156175942Sscottl if (hba->path) { 2157175942Sscottl struct ccb_setasync ccb; 2158169412Sscottl 2159169412Sscottl xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5); 2160169412Sscottl ccb.ccb_h.func_code = XPT_SASYNC_CB; 2161169412Sscottl ccb.event_enable = 0; 2162169412Sscottl ccb.callback = hptiop_async; 2163169412Sscottl ccb.callback_arg = hba->sim; 2164169412Sscottl xpt_action((union ccb *)&ccb); 2165169412Sscottl xpt_free_path(hba->path); 2166169412Sscottl } 2167169412Sscottl 2168169412Sscottl if (hba->sim) { 2169169412Sscottl xpt_bus_deregister(cam_sim_path(hba->sim)); 2170169412Sscottl cam_sim_free(hba->sim, TRUE); 2171169412Sscottl } 2172169412Sscottl 2173175942Sscottl if (hba->ctlcfg_dmat) { 2174175942Sscottl bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap); 2175175942Sscottl bus_dmamem_free(hba->ctlcfg_dmat, 2176175942Sscottl hba->ctlcfg_ptr, hba->ctlcfg_dmamap); 2177175942Sscottl bus_dma_tag_destroy(hba->ctlcfg_dmat); 2178175942Sscottl } 2179175942Sscottl 2180175942Sscottl for (i = 0; i < HPT_SRB_MAX_QUEUE_SIZE; i++) { 2181175942Sscottl struct hpt_iop_srb *srb = hba->srb[i]; 2182175942Sscottl if (srb->dma_map) 2183175942Sscottl bus_dmamap_destroy(hba->io_dmat, srb->dma_map); 2184175942Sscottl } 2185175942Sscottl 2186169412Sscottl if (hba->srb_dmat) { 2187169412Sscottl bus_dmamap_unload(hba->srb_dmat, hba->srb_dmamap); 2188175942Sscottl bus_dmamap_destroy(hba->srb_dmat, hba->srb_dmamap); 2189169412Sscottl bus_dma_tag_destroy(hba->srb_dmat); 2190169412Sscottl } 2191169412Sscottl 2192169412Sscottl if (hba->io_dmat) 2193169412Sscottl bus_dma_tag_destroy(hba->io_dmat); 2194169412Sscottl 2195169412Sscottl if (hba->parent_dmat) 2196169412Sscottl bus_dma_tag_destroy(hba->parent_dmat); 2197169412Sscottl 2198169412Sscottl if (hba->irq_handle) 2199169412Sscottl bus_teardown_intr(hba->pcidev, hba->irq_res, hba->irq_handle); 2200169412Sscottl 2201169412Sscottl if (hba->irq_res) 2202175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_IRQ, 2203175942Sscottl 0, hba->irq_res); 2204169412Sscottl 2205169412Sscottl if (hba->bar0_res) 2206169412Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 2207169412Sscottl hba->bar0_rid, hba->bar0_res); 2208175942Sscottl if (hba->bar2_res) 2209175942Sscottl bus_release_resource(hba->pcidev, SYS_RES_MEMORY, 2210175942Sscottl hba->bar2_rid, hba->bar2_res); 2211169412Sscottl if (hba->ioctl_dev) 2212169412Sscottl destroy_dev(hba->ioctl_dev); 2213169412Sscottl} 2214